diff options
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 100 |
1 files changed, 49 insertions, 51 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 104dbe44ecf..6bfbf683241 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1392,6 +1392,45 @@ eval_frame_handle_pending(PyThreadState *tstate) #define BUILTINS() frame->f_builtins #define LOCALS() frame->f_locals +static int +trace_function_entry(PyThreadState *tstate, InterpreterFrame *frame) +{ + if (tstate->c_tracefunc != NULL) { + /* tstate->c_tracefunc, if defined, is a + function that will be called on *every* entry + to a code block. Its return value, if not + None, is a function that will be called at + the start of each executed line of code. + (Actually, the function must return itself + in order to continue tracing.) The trace + functions are called with three arguments: + a pointer to the current frame, a string + indicating why the function is called, and + an argument which depends on the situation. + The global trace function is also called + whenever an exception is detected. */ + if (call_trace_protected(tstate->c_tracefunc, + tstate->c_traceobj, + tstate, frame, + PyTrace_CALL, Py_None)) { + /* Trace function raised an error */ + return -1; + } + } + if (tstate->c_profilefunc != NULL) { + /* Similar for c_profilefunc, except it needn't + return itself and isn't called for "line" events */ + if (call_trace_protected(tstate->c_profilefunc, + tstate->c_profileobj, + tstate, frame, + PyTrace_CALL, Py_None)) { + /* Profile function raised an error */ + return -1; + } + } + return 0; +} + PyObject* _Py_HOT_FUNCTION _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int throwflag) { @@ -1405,22 +1444,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr #ifdef DXPAIRS int lastopcode = 0; #endif - PyObject **stack_pointer; /* Next free slot in value stack */ - _Py_CODEUNIT *next_instr; int opcode; /* Current opcode */ int oparg; /* Current opcode argument, if any */ - PyObject **localsplus; PyObject *retval = NULL; /* Return value */ _Py_atomic_int * const eval_breaker = &tstate->interp->ceval.eval_breaker; - PyCodeObject *co; - - _Py_CODEUNIT *first_instr; - PyObject *names; - PyObject *consts; - -#ifdef LLTRACE - _Py_IDENTIFIER(__ltrace__); -#endif if (_Py_EnterRecursiveCall(tstate, "")) { return NULL; @@ -1439,47 +1466,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr /* push frame */ tstate->frame = frame; - co = frame->f_code; if (cframe.use_tracing) { - if (tstate->c_tracefunc != NULL) { - /* tstate->c_tracefunc, if defined, is a - function that will be called on *every* entry - to a code block. Its return value, if not - None, is a function that will be called at - the start of each executed line of code. - (Actually, the function must return itself - in order to continue tracing.) The trace - functions are called with three arguments: - a pointer to the current frame, a string - indicating why the function is called, and - an argument which depends on the situation. - The global trace function is also called - whenever an exception is detected. */ - if (call_trace_protected(tstate->c_tracefunc, - tstate->c_traceobj, - tstate, frame, - PyTrace_CALL, Py_None)) { - /* Trace function raised an error */ - goto exit_eval_frame; - } - } - if (tstate->c_profilefunc != NULL) { - /* Similar for c_profilefunc, except it needn't - return itself and isn't called for "line" events */ - if (call_trace_protected(tstate->c_profilefunc, - tstate->c_profileobj, - tstate, frame, - PyTrace_CALL, Py_None)) { - /* Profile function raised an error */ - goto exit_eval_frame; - } + if (trace_function_entry(tstate, frame)) { + goto exit_eval_frame; } } if (PyDTrace_FUNCTION_ENTRY_ENABLED()) dtrace_function_entry(frame); + PyCodeObject *co = frame->f_code; /* Increment the warmup counter and quicken if warm enough * _Py_Quicken is idempotent so we don't worry about overflow */ if (!PyCodeObject_IsWarmedUp(co)) { @@ -1492,10 +1489,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } - names = co->co_names; - consts = co->co_consts; - localsplus = _PyFrame_GetLocalsArray(frame); - first_instr = co->co_firstinstr; + PyObject *names = co->co_names; + PyObject *consts = co->co_consts; + PyObject **localsplus = _PyFrame_GetLocalsArray(frame); + _Py_CODEUNIT *first_instr = co->co_firstinstr; /* frame->f_lasti refers to the index of the last instruction, unless it's -1 in which case next_instr should be first_instr. @@ -1512,8 +1509,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr to the beginning of the combined pair.) */ assert(frame->f_lasti >= -1); - next_instr = first_instr + frame->f_lasti + 1; - stack_pointer = frame->stack + frame->stackdepth; + _Py_CODEUNIT *next_instr = first_instr + frame->f_lasti + 1; + PyObject **stack_pointer = frame->stack + frame->stackdepth; /* Set stackdepth to -1. * Update when returning or calling trace function. Having f_stackdepth <= 0 ensures that invalid @@ -1524,6 +1521,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr frame->f_state = FRAME_EXECUTING; #ifdef LLTRACE + _Py_IDENTIFIER(__ltrace__); { int r = _PyDict_ContainsId(GLOBALS(), &PyId___ltrace__); if (r < 0) { |