summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/pystate.h5
-rw-r--r--Modules/pyexpat.c2
-rw-r--r--Python/ceval.c90
-rw-r--r--Python/pystate.c11
4 files changed, 65 insertions, 43 deletions
diff --git a/Include/pystate.h b/Include/pystate.h
index 9b61ad7..d4233bf 100644
--- a/Include/pystate.h
+++ b/Include/pystate.h
@@ -67,6 +67,8 @@ typedef struct _ts {
PyObject *dict;
+ int tick_counter;
+
/* XXX signal handlers should also be here */
} PyThreadState;
@@ -105,6 +107,9 @@ PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Next(PyInterpreterState *);
PyAPI_FUNC(PyThreadState *) PyInterpreterState_ThreadHead(PyInterpreterState *);
PyAPI_FUNC(PyThreadState *) PyThreadState_Next(PyThreadState *);
+/* hook for PyEval_GetFrame(), requested for Psyco */
+PyAPI_DATA(unaryfunc) _PyThreadState_GetFrame;
+
#ifdef __cplusplus
}
#endif
diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c
index 2009b22..f74751b 100644
--- a/Modules/pyexpat.c
+++ b/Modules/pyexpat.c
@@ -304,7 +304,7 @@ call_with_frame(PyCodeObject *c, PyObject* func, PyObject* args)
f = PyFrame_New(
tstate, /*back*/
c, /*code*/
- tstate->frame->f_globals, /*globals*/
+ PyEval_GetGlobals(), /*globals*/
NULL /*locals*/
);
if (f == NULL)
diff --git a/Python/ceval.c b/Python/ceval.c
index 09b88a6..1c95cb9 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -51,7 +51,7 @@ static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *,
static void call_trace_protected(Py_tracefunc, PyObject *,
PyFrameObject *, int);
static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *);
-static void maybe_call_line_trace(int, Py_tracefunc, PyObject *,
+static void maybe_call_line_trace(Py_tracefunc, PyObject *,
PyFrameObject *, int *, int *);
static PyObject *apply_slice(PyObject *, PyObject *, PyObject *);
@@ -599,24 +599,6 @@ eval_frame(PyFrameObject *f)
}
tstate->frame = f;
- co = f->f_code;
- names = co->co_names;
- consts = co->co_consts;
- fastlocals = f->f_localsplus;
- freevars = f->f_localsplus + f->f_nlocals;
- _PyCode_GETCODEPTR(co, &first_instr);
- /* An explanation is in order for the next line.
-
- f->f_lasti now refers to the index of the last instruction
- executed. You might think this was obvious from the name, but
- this wasn't always true before 2.3! PyFrame_New now sets
- f->f_lasti to -1 (i.e. the index *before* the first instruction)
- and YIELD_VALUE doesn't fiddle with f_lasti any more. So this
- does work. Promise. */
- next_instr = first_instr + f->f_lasti + 1;
- stack_pointer = f->f_stacktop;
- assert(stack_pointer != NULL);
- f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */
if (tstate->use_tracing) {
if (tstate->c_tracefunc != NULL) {
@@ -655,6 +637,25 @@ eval_frame(PyFrameObject *f)
}
}
+ co = f->f_code;
+ names = co->co_names;
+ consts = co->co_consts;
+ fastlocals = f->f_localsplus;
+ freevars = f->f_localsplus + f->f_nlocals;
+ _PyCode_GETCODEPTR(co, &first_instr);
+ /* An explanation is in order for the next line.
+
+ f->f_lasti now refers to the index of the last instruction
+ executed. You might think this was obvious from the name, but
+ this wasn't always true before 2.3! PyFrame_New now sets
+ f->f_lasti to -1 (i.e. the index *before* the first instruction)
+ and YIELD_VALUE doesn't fiddle with f_lasti any more. So this
+ does work. Promise. */
+ next_instr = first_instr + f->f_lasti + 1;
+ stack_pointer = f->f_stacktop;
+ assert(stack_pointer != NULL);
+ f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */
+
#ifdef LLTRACE
lltrace = PyDict_GetItemString(f->f_globals,"__lltrace__") != NULL;
#endif
@@ -681,6 +682,7 @@ eval_frame(PyFrameObject *f)
if (--_Py_Ticker < 0) {
_Py_Ticker = _Py_CheckInterval;
+ tstate->tick_counter++;
if (things_to_do) {
if (Py_MakePendingCalls() < 0) {
why = WHY_EXCEPTION;
@@ -716,10 +718,26 @@ eval_frame(PyFrameObject *f)
}
fast_next_opcode:
- /* Extract opcode and argument */
-
f->f_lasti = INSTR_OFFSET();
+ /* line-by-line tracing support */
+
+ if (tstate->c_tracefunc != NULL && !tstate->tracing) {
+ /* see maybe_call_line_trace
+ for expository comments */
+ f->f_stacktop = stack_pointer;
+ maybe_call_line_trace(tstate->c_tracefunc,
+ tstate->c_traceobj,
+ f, &instr_lb, &instr_ub);
+ /* Reload possibly changed frame fields */
+ JUMPTO(f->f_lasti);
+ stack_pointer = f->f_stacktop;
+ assert(stack_pointer != NULL);
+ f->f_stacktop = NULL;
+ }
+
+ /* Extract opcode and argument */
+
opcode = NEXTOP();
if (HAS_ARG(opcode))
oparg = NEXTARG();
@@ -747,17 +765,6 @@ eval_frame(PyFrameObject *f)
}
#endif
- /* line-by-line tracing support */
-
- if (tstate->c_tracefunc != NULL && !tstate->tracing) {
- /* see maybe_call_line_trace
- for expository comments */
- maybe_call_line_trace(opcode,
- tstate->c_tracefunc,
- tstate->c_traceobj,
- f, &instr_lb, &instr_ub);
- }
-
/* Main switch on opcode */
switch (opcode) {
@@ -2866,7 +2873,7 @@ call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
}
static void
-maybe_call_line_trace(int opcode, Py_tracefunc func, PyObject *obj,
+maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
PyFrameObject *frame, int *instr_lb, int *instr_ub)
{
/* The theory of SET_LINENO-less tracing.
@@ -3025,10 +3032,9 @@ PyEval_SetTrace(Py_tracefunc func, PyObject *arg)
PyObject *
PyEval_GetBuiltins(void)
{
- PyThreadState *tstate = PyThreadState_Get();
- PyFrameObject *current_frame = tstate->frame;
+ PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
if (current_frame == NULL)
- return tstate->interp->builtins;
+ return PyThreadState_Get()->interp->builtins;
else
return current_frame->f_builtins;
}
@@ -3036,7 +3042,7 @@ PyEval_GetBuiltins(void)
PyObject *
PyEval_GetLocals(void)
{
- PyFrameObject *current_frame = PyThreadState_Get()->frame;
+ PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
if (current_frame == NULL)
return NULL;
PyFrame_FastToLocals(current_frame);
@@ -3046,7 +3052,7 @@ PyEval_GetLocals(void)
PyObject *
PyEval_GetGlobals(void)
{
- PyFrameObject *current_frame = PyThreadState_Get()->frame;
+ PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
if (current_frame == NULL)
return NULL;
else
@@ -3056,21 +3062,21 @@ PyEval_GetGlobals(void)
PyObject *
PyEval_GetFrame(void)
{
- PyFrameObject *current_frame = PyThreadState_Get()->frame;
- return (PyObject *)current_frame;
+ PyThreadState *tstate = PyThreadState_Get();
+ return _PyThreadState_GetFrame((PyObject *)tstate);
}
int
PyEval_GetRestricted(void)
{
- PyFrameObject *current_frame = PyThreadState_Get()->frame;
+ PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
return current_frame == NULL ? 0 : current_frame->f_restricted;
}
int
PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
{
- PyFrameObject *current_frame = PyThreadState_Get()->frame;
+ PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
int result = 0;
if (current_frame != NULL) {
diff --git a/Python/pystate.c b/Python/pystate.c
index ad92dde..707e43e 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -35,6 +35,7 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
static PyInterpreterState *interp_head = NULL;
PyThreadState *_PyThreadState_Current = NULL;
+unaryfunc _PyThreadState_GetFrame = NULL;
PyInterpreterState *
@@ -113,10 +114,19 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
}
+/* Default implementation for _PyThreadState_GetFrame */
+static struct _frame *
+threadstate_getframe(PyThreadState *self)
+{
+ return self->frame;
+}
+
PyThreadState *
PyThreadState_New(PyInterpreterState *interp)
{
PyThreadState *tstate = PyMem_NEW(PyThreadState, 1);
+ if (_PyThreadState_GetFrame == NULL)
+ _PyThreadState_GetFrame = (unaryfunc)threadstate_getframe;
if (tstate != NULL) {
tstate->interp = interp;
@@ -125,6 +135,7 @@ PyThreadState_New(PyInterpreterState *interp)
tstate->recursion_depth = 0;
tstate->tracing = 0;
tstate->use_tracing = 0;
+ tstate->tick_counter = 0;
tstate->dict = NULL;