mirror of https://github.com/python/cpython
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:
parent
1f04610b49
commit
019a78e76d
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue