Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 019a78e

Browse files
author
Michael W. Hudson
committed
Assorted patches from Armin Rigo:
[ 617309 ] getframe hook (Psyco #1) [ 617311 ] Tiny profiling info (Psyco #2) [ 617312 ] debugger-controlled jumps (Psyco #3) These are forward ports from 2.2.2.
1 parent 1f04610 commit 019a78e

4 files changed

Lines changed: 65 additions & 43 deletions

File tree

Include/pystate.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ typedef struct _ts {
6767

6868
PyObject *dict;
6969

70+
int tick_counter;
71+
7072
/* XXX signal handlers should also be here */
7173

7274
} PyThreadState;
@@ -105,6 +107,9 @@ PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Next(PyInterpreterState *);
105107
PyAPI_FUNC(PyThreadState *) PyInterpreterState_ThreadHead(PyInterpreterState *);
106108
PyAPI_FUNC(PyThreadState *) PyThreadState_Next(PyThreadState *);
107109

110+
/* hook for PyEval_GetFrame(), requested for Psyco */
111+
PyAPI_DATA(unaryfunc) _PyThreadState_GetFrame;
112+
108113
#ifdef __cplusplus
109114
}
110115
#endif

Modules/pyexpat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ call_with_frame(PyCodeObject *c, PyObject* func, PyObject* args)
304304
f = PyFrame_New(
305305
tstate, /*back*/
306306
c, /*code*/
307-
tstate->frame->f_globals, /*globals*/
307+
PyEval_GetGlobals(), /*globals*/
308308
NULL /*locals*/
309309
);
310310
if (f == NULL)

Python/ceval.c

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *,
5151
static void call_trace_protected(Py_tracefunc, PyObject *,
5252
PyFrameObject *, int);
5353
static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *);
54-
static void maybe_call_line_trace(int, Py_tracefunc, PyObject *,
54+
static void maybe_call_line_trace(Py_tracefunc, PyObject *,
5555
PyFrameObject *, int *, int *);
5656

5757
static PyObject *apply_slice(PyObject *, PyObject *, PyObject *);
@@ -599,24 +599,6 @@ eval_frame(PyFrameObject *f)
599599
}
600600

601601
tstate->frame = f;
602-
co = f->f_code;
603-
names = co->co_names;
604-
consts = co->co_consts;
605-
fastlocals = f->f_localsplus;
606-
freevars = f->f_localsplus + f->f_nlocals;
607-
_PyCode_GETCODEPTR(co, &first_instr);
608-
/* An explanation is in order for the next line.
609-
610-
f->f_lasti now refers to the index of the last instruction
611-
executed. You might think this was obvious from the name, but
612-
this wasn't always true before 2.3! PyFrame_New now sets
613-
f->f_lasti to -1 (i.e. the index *before* the first instruction)
614-
and YIELD_VALUE doesn't fiddle with f_lasti any more. So this
615-
does work. Promise. */
616-
next_instr = first_instr + f->f_lasti + 1;
617-
stack_pointer = f->f_stacktop;
618-
assert(stack_pointer != NULL);
619-
f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */
620602

621603
if (tstate->use_tracing) {
622604
if (tstate->c_tracefunc != NULL) {
@@ -655,6 +637,25 @@ eval_frame(PyFrameObject *f)
655637
}
656638
}
657639

640+
co = f->f_code;
641+
names = co->co_names;
642+
consts = co->co_consts;
643+
fastlocals = f->f_localsplus;
644+
freevars = f->f_localsplus + f->f_nlocals;
645+
_PyCode_GETCODEPTR(co, &first_instr);
646+
/* An explanation is in order for the next line.
647+
648+
f->f_lasti now refers to the index of the last instruction
649+
executed. You might think this was obvious from the name, but
650+
this wasn't always true before 2.3! PyFrame_New now sets
651+
f->f_lasti to -1 (i.e. the index *before* the first instruction)
652+
and YIELD_VALUE doesn't fiddle with f_lasti any more. So this
653+
does work. Promise. */
654+
next_instr = first_instr + f->f_lasti + 1;
655+
stack_pointer = f->f_stacktop;
656+
assert(stack_pointer != NULL);
657+
f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */
658+
658659
#ifdef LLTRACE
659660
lltrace = PyDict_GetItemString(f->f_globals,"__lltrace__") != NULL;
660661
#endif
@@ -681,6 +682,7 @@ eval_frame(PyFrameObject *f)
681682

682683
if (--_Py_Ticker < 0) {
683684
_Py_Ticker = _Py_CheckInterval;
685+
tstate->tick_counter++;
684686
if (things_to_do) {
685687
if (Py_MakePendingCalls() < 0) {
686688
why = WHY_EXCEPTION;
@@ -716,10 +718,26 @@ eval_frame(PyFrameObject *f)
716718
}
717719

718720
fast_next_opcode:
719-
/* Extract opcode and argument */
720-
721721
f->f_lasti = INSTR_OFFSET();
722722

723+
/* line-by-line tracing support */
724+
725+
if (tstate->c_tracefunc != NULL && !tstate->tracing) {
726+
/* see maybe_call_line_trace
727+
for expository comments */
728+
f->f_stacktop = stack_pointer;
729+
maybe_call_line_trace(tstate->c_tracefunc,
730+
tstate->c_traceobj,
731+
f, &instr_lb, &instr_ub);
732+
/* Reload possibly changed frame fields */
733+
JUMPTO(f->f_lasti);
734+
stack_pointer = f->f_stacktop;
735+
assert(stack_pointer != NULL);
736+
f->f_stacktop = NULL;
737+
}
738+
739+
/* Extract opcode and argument */
740+
723741
opcode = NEXTOP();
724742
if (HAS_ARG(opcode))
725743
oparg = NEXTARG();
@@ -747,17 +765,6 @@ eval_frame(PyFrameObject *f)
747765
}
748766
#endif
749767

750-
/* line-by-line tracing support */
751-
752-
if (tstate->c_tracefunc != NULL && !tstate->tracing) {
753-
/* see maybe_call_line_trace
754-
for expository comments */
755-
maybe_call_line_trace(opcode,
756-
tstate->c_tracefunc,
757-
tstate->c_traceobj,
758-
f, &instr_lb, &instr_ub);
759-
}
760-
761768
/* Main switch on opcode */
762769

763770
switch (opcode) {
@@ -2866,7 +2873,7 @@ call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
28662873
}
28672874

28682875
static void
2869-
maybe_call_line_trace(int opcode, Py_tracefunc func, PyObject *obj,
2876+
maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
28702877
PyFrameObject *frame, int *instr_lb, int *instr_ub)
28712878
{
28722879
/* The theory of SET_LINENO-less tracing.
@@ -3025,18 +3032,17 @@ PyEval_SetTrace(Py_tracefunc func, PyObject *arg)
30253032
PyObject *
30263033
PyEval_GetBuiltins(void)
30273034
{
3028-
PyThreadState *tstate = PyThreadState_Get();
3029-
PyFrameObject *current_frame = tstate->frame;
3035+
PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
30303036
if (current_frame == NULL)
3031-
return tstate->interp->builtins;
3037+
return PyThreadState_Get()->interp->builtins;
30323038
else
30333039
return current_frame->f_builtins;
30343040
}
30353041

30363042
PyObject *
30373043
PyEval_GetLocals(void)
30383044
{
3039-
PyFrameObject *current_frame = PyThreadState_Get()->frame;
3045+
PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
30403046
if (current_frame == NULL)
30413047
return NULL;
30423048
PyFrame_FastToLocals(current_frame);
@@ -3046,7 +3052,7 @@ PyEval_GetLocals(void)
30463052
PyObject *
30473053
PyEval_GetGlobals(void)
30483054
{
3049-
PyFrameObject *current_frame = PyThreadState_Get()->frame;
3055+
PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
30503056
if (current_frame == NULL)
30513057
return NULL;
30523058
else
@@ -3056,21 +3062,21 @@ PyEval_GetGlobals(void)
30563062
PyObject *
30573063
PyEval_GetFrame(void)
30583064
{
3059-
PyFrameObject *current_frame = PyThreadState_Get()->frame;
3060-
return (PyObject *)current_frame;
3065+
PyThreadState *tstate = PyThreadState_Get();
3066+
return _PyThreadState_GetFrame((PyObject *)tstate);
30613067
}
30623068

30633069
int
30643070
PyEval_GetRestricted(void)
30653071
{
3066-
PyFrameObject *current_frame = PyThreadState_Get()->frame;
3072+
PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
30673073
return current_frame == NULL ? 0 : current_frame->f_restricted;
30683074
}
30693075

30703076
int
30713077
PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
30723078
{
3073-
PyFrameObject *current_frame = PyThreadState_Get()->frame;
3079+
PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
30743080
int result = 0;
30753081

30763082
if (current_frame != NULL) {

Python/pystate.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
3535
static PyInterpreterState *interp_head = NULL;
3636

3737
PyThreadState *_PyThreadState_Current = NULL;
38+
unaryfunc _PyThreadState_GetFrame = NULL;
3839

3940

4041
PyInterpreterState *
@@ -113,10 +114,19 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
113114
}
114115

115116

117+
/* Default implementation for _PyThreadState_GetFrame */
118+
static struct _frame *
119+
threadstate_getframe(PyThreadState *self)
120+
{
121+
return self->frame;
122+
}
123+
116124
PyThreadState *
117125
PyThreadState_New(PyInterpreterState *interp)
118126
{
119127
PyThreadState *tstate = PyMem_NEW(PyThreadState, 1);
128+
if (_PyThreadState_GetFrame == NULL)
129+
_PyThreadState_GetFrame = (unaryfunc)threadstate_getframe;
120130

121131
if (tstate != NULL) {
122132
tstate->interp = interp;
@@ -125,6 +135,7 @@ PyThreadState_New(PyInterpreterState *interp)
125135
tstate->recursion_depth = 0;
126136
tstate->tracing = 0;
127137
tstate->use_tracing = 0;
138+
tstate->tick_counter = 0;
128139

129140
tstate->dict = NULL;
130141

0 commit comments

Comments
 (0)