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.
This commit is contained in:
Michael W. Hudson 2002-11-08 12:53:11 +00:00
parent 1f04610b49
commit 019a78e76d
4 changed files with 65 additions and 43 deletions

View File

@ -67,6 +67,8 @@ typedef struct _ts {
PyObject *dict; PyObject *dict;
int tick_counter;
/* XXX signal handlers should also be here */ /* XXX signal handlers should also be here */
} PyThreadState; } PyThreadState;
@ -105,6 +107,9 @@ PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Next(PyInterpreterState *);
PyAPI_FUNC(PyThreadState *) PyInterpreterState_ThreadHead(PyInterpreterState *); PyAPI_FUNC(PyThreadState *) PyInterpreterState_ThreadHead(PyInterpreterState *);
PyAPI_FUNC(PyThreadState *) PyThreadState_Next(PyThreadState *); PyAPI_FUNC(PyThreadState *) PyThreadState_Next(PyThreadState *);
/* hook for PyEval_GetFrame(), requested for Psyco */
PyAPI_DATA(unaryfunc) _PyThreadState_GetFrame;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -304,7 +304,7 @@ call_with_frame(PyCodeObject *c, PyObject* func, PyObject* args)
f = PyFrame_New( f = PyFrame_New(
tstate, /*back*/ tstate, /*back*/
c, /*code*/ c, /*code*/
tstate->frame->f_globals, /*globals*/ PyEval_GetGlobals(), /*globals*/
NULL /*locals*/ NULL /*locals*/
); );
if (f == NULL) if (f == NULL)

View File

@ -51,7 +51,7 @@ static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *,
static void call_trace_protected(Py_tracefunc, PyObject *, static void call_trace_protected(Py_tracefunc, PyObject *,
PyFrameObject *, int); PyFrameObject *, int);
static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *); 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 *); PyFrameObject *, int *, int *);
static PyObject *apply_slice(PyObject *, PyObject *, PyObject *); static PyObject *apply_slice(PyObject *, PyObject *, PyObject *);
@ -599,24 +599,6 @@ eval_frame(PyFrameObject *f)
} }
tstate->frame = 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->use_tracing) {
if (tstate->c_tracefunc != NULL) { 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 #ifdef LLTRACE
lltrace = PyDict_GetItemString(f->f_globals,"__lltrace__") != NULL; lltrace = PyDict_GetItemString(f->f_globals,"__lltrace__") != NULL;
#endif #endif
@ -681,6 +682,7 @@ eval_frame(PyFrameObject *f)
if (--_Py_Ticker < 0) { if (--_Py_Ticker < 0) {
_Py_Ticker = _Py_CheckInterval; _Py_Ticker = _Py_CheckInterval;
tstate->tick_counter++;
if (things_to_do) { if (things_to_do) {
if (Py_MakePendingCalls() < 0) { if (Py_MakePendingCalls() < 0) {
why = WHY_EXCEPTION; why = WHY_EXCEPTION;
@ -716,10 +718,26 @@ eval_frame(PyFrameObject *f)
} }
fast_next_opcode: fast_next_opcode:
/* Extract opcode and argument */
f->f_lasti = INSTR_OFFSET(); 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(); opcode = NEXTOP();
if (HAS_ARG(opcode)) if (HAS_ARG(opcode))
oparg = NEXTARG(); oparg = NEXTARG();
@ -747,17 +765,6 @@ eval_frame(PyFrameObject *f)
} }
#endif #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 */ /* Main switch on opcode */
switch (opcode) { switch (opcode) {
@ -2866,7 +2873,7 @@ call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
} }
static void 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) PyFrameObject *frame, int *instr_lb, int *instr_ub)
{ {
/* The theory of SET_LINENO-less tracing. /* The theory of SET_LINENO-less tracing.
@ -3025,10 +3032,9 @@ PyEval_SetTrace(Py_tracefunc func, PyObject *arg)
PyObject * PyObject *
PyEval_GetBuiltins(void) PyEval_GetBuiltins(void)
{ {
PyThreadState *tstate = PyThreadState_Get(); PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
PyFrameObject *current_frame = tstate->frame;
if (current_frame == NULL) if (current_frame == NULL)
return tstate->interp->builtins; return PyThreadState_Get()->interp->builtins;
else else
return current_frame->f_builtins; return current_frame->f_builtins;
} }
@ -3036,7 +3042,7 @@ PyEval_GetBuiltins(void)
PyObject * PyObject *
PyEval_GetLocals(void) PyEval_GetLocals(void)
{ {
PyFrameObject *current_frame = PyThreadState_Get()->frame; PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
if (current_frame == NULL) if (current_frame == NULL)
return NULL; return NULL;
PyFrame_FastToLocals(current_frame); PyFrame_FastToLocals(current_frame);
@ -3046,7 +3052,7 @@ PyEval_GetLocals(void)
PyObject * PyObject *
PyEval_GetGlobals(void) PyEval_GetGlobals(void)
{ {
PyFrameObject *current_frame = PyThreadState_Get()->frame; PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
if (current_frame == NULL) if (current_frame == NULL)
return NULL; return NULL;
else else
@ -3056,21 +3062,21 @@ PyEval_GetGlobals(void)
PyObject * PyObject *
PyEval_GetFrame(void) PyEval_GetFrame(void)
{ {
PyFrameObject *current_frame = PyThreadState_Get()->frame; PyThreadState *tstate = PyThreadState_Get();
return (PyObject *)current_frame; return _PyThreadState_GetFrame((PyObject *)tstate);
} }
int int
PyEval_GetRestricted(void) PyEval_GetRestricted(void)
{ {
PyFrameObject *current_frame = PyThreadState_Get()->frame; PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
return current_frame == NULL ? 0 : current_frame->f_restricted; return current_frame == NULL ? 0 : current_frame->f_restricted;
} }
int int
PyEval_MergeCompilerFlags(PyCompilerFlags *cf) PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
{ {
PyFrameObject *current_frame = PyThreadState_Get()->frame; PyFrameObject *current_frame = (PyFrameObject *)PyEval_GetFrame();
int result = 0; int result = 0;
if (current_frame != NULL) { if (current_frame != NULL) {

View File

@ -35,6 +35,7 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
static PyInterpreterState *interp_head = NULL; static PyInterpreterState *interp_head = NULL;
PyThreadState *_PyThreadState_Current = NULL; PyThreadState *_PyThreadState_Current = NULL;
unaryfunc _PyThreadState_GetFrame = NULL;
PyInterpreterState * 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 *
PyThreadState_New(PyInterpreterState *interp) PyThreadState_New(PyInterpreterState *interp)
{ {
PyThreadState *tstate = PyMem_NEW(PyThreadState, 1); PyThreadState *tstate = PyMem_NEW(PyThreadState, 1);
if (_PyThreadState_GetFrame == NULL)
_PyThreadState_GetFrame = (unaryfunc)threadstate_getframe;
if (tstate != NULL) { if (tstate != NULL) {
tstate->interp = interp; tstate->interp = interp;
@ -125,6 +135,7 @@ PyThreadState_New(PyInterpreterState *interp)
tstate->recursion_depth = 0; tstate->recursion_depth = 0;
tstate->tracing = 0; tstate->tracing = 0;
tstate->use_tracing = 0; tstate->use_tracing = 0;
tstate->tick_counter = 0;
tstate->dict = NULL; tstate->dict = NULL;