diff options
author | Fred Drake <fdrake@acm.org> | 2001-07-03 23:39:52 (GMT) |
---|---|---|
committer | Fred Drake <fdrake@acm.org> | 2001-07-03 23:39:52 (GMT) |
commit | 9e3ad7844425d96baf856d3da1975756504b2aa5 (patch) | |
tree | 60b7fd58e8c450f80f827e04240aba389b0421c6 /Python/ceval.c | |
parent | d89a2e7731f1c8e1dd39a2f93201fa8d93fdf0fb (diff) | |
download | cpython-9e3ad7844425d96baf856d3da1975756504b2aa5.zip cpython-9e3ad7844425d96baf856d3da1975756504b2aa5.tar.gz cpython-9e3ad7844425d96baf856d3da1975756504b2aa5.tar.bz2 |
This change adjusts the profiling/tracing support so that the common
path (with no profile/trace function) through eval_code2() and
eval_frame() avoids several checks.
In the common cases of calls, returns, and exception propogation,
eval_code2() and eval_frame() used to test two values in the
thread-state: the profiling function and the tracing function. With
this change, a flag is set in the thread-state if either of these is
active, allowing a single check to suffice when both are NULL. This
also simplifies the code needed when either function is in use but is
already active (to avoid profiling/tracing the profiler/tracer); the
flag is set to 0 when the profile/trace code is entered, allowing the
same check to suffice for "already in the tracer" for call/return/
exception events.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 112 |
1 files changed, 65 insertions, 47 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 702380d..79eb0ad 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1890,8 +1890,11 @@ eval_frame(PyFrameObject *f) f->f_lasti = INSTR_OFFSET(); /* Inline call_trace() for performance: */ tstate->tracing++; + tstate->use_tracing = 0; err = (tstate->c_tracefunc)(tstate->c_traceobj, f, PyTrace_LINE, Py_None); + tstate->use_tracing = (tstate->c_tracefunc + || tstate->c_profilefunc); tstate->tracing--; break; @@ -2142,12 +2145,14 @@ eval_frame(PyFrameObject *f) f->f_lasti -= 2; PyTraceBack_Here(f); - if (tstate->c_tracefunc) - call_exc_trace(tstate->c_tracefunc, - tstate->c_traceobj, f); - if (tstate->c_profilefunc) - call_exc_trace(tstate->c_profilefunc, - tstate->c_profileobj, f); + if (tstate->use_tracing) { + if (tstate->c_tracefunc) + call_exc_trace(tstate->c_tracefunc, + tstate->c_traceobj, f); + if (tstate->c_profilefunc) + call_exc_trace(tstate->c_profilefunc, + tstate->c_profileobj,f); + } } /* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */ @@ -2228,24 +2233,26 @@ eval_frame(PyFrameObject *f) if (why != WHY_RETURN && why != WHY_YIELD) retval = NULL; - if (tstate->c_tracefunc && !tstate->tracing) { - if (why == WHY_RETURN || why == WHY_YIELD) { - if (call_trace(tstate->c_tracefunc, tstate->c_traceobj, - f, PyTrace_RETURN, retval)) { + if (tstate->use_tracing) { + if (tstate->c_tracefunc + && (why == WHY_RETURN || why == WHY_YIELD)) { + if (call_trace(tstate->c_tracefunc, + tstate->c_traceobj, f, + PyTrace_RETURN, retval)) { Py_XDECREF(retval); retval = NULL; why = WHY_EXCEPTION; } } - } - - if (tstate->c_profilefunc && !tstate->tracing - && (why == WHY_RETURN || why == WHY_YIELD)) { - if (call_trace(tstate->c_profilefunc, tstate->c_profileobj, - f, PyTrace_RETURN, retval)) { - Py_XDECREF(retval); - retval = NULL; - why = WHY_EXCEPTION; + if (tstate->c_profilefunc + && (why == WHY_RETURN || why == WHY_YIELD)) { + if (call_trace(tstate->c_profilefunc, + tstate->c_profileobj, f, + PyTrace_RETURN, retval)) { + Py_XDECREF(retval); + retval = NULL; + why = WHY_EXCEPTION; + } } } @@ -2471,35 +2478,38 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, } } - if (tstate->c_tracefunc != NULL && !tstate->tracing) { - /* tstate->sys_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 - (sys.trace) is also called whenever an exception - is detected. */ - if (call_trace(tstate->c_tracefunc, tstate->c_traceobj, - f, PyTrace_CALL, Py_None)) { - /* XXX Need way to compute arguments?? */ - /* Trace function raised an error */ - goto fail; + if (tstate->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(tstate->c_tracefunc, tstate->c_traceobj, + f, PyTrace_CALL, Py_None)) { + /* XXX Need way to compute arguments?? */ + /* Trace function raised an error */ + goto fail; + } } - } - - if (tstate->c_profilefunc != NULL) { - /* Similar for sys_profilefunc, except it needn't return - itself and isn't called for "line" events */ - if (call_trace(tstate->c_profilefunc, tstate->c_profileobj, - f, PyTrace_CALL, Py_None)) { - /* XXX Need way to compute arguments?? */ - /* Profile function raised an error */ - goto fail; + 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(tstate->c_profilefunc, + tstate->c_profileobj, + f, PyTrace_CALL, Py_None)) { + /* XXX Need way to compute arguments?? */ + /* Profile function raised an error */ + goto fail; + } } } @@ -2803,7 +2813,10 @@ call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame, if (tstate->tracing) return 0; tstate->tracing++; + tstate->use_tracing = 0; result = func(obj, frame, what, arg); + tstate->use_tracing = ((tstate->c_tracefunc != NULL) + || (tstate->c_profilefunc != NULL)); tstate->tracing--; return result; } @@ -2816,9 +2829,11 @@ PyEval_SetProfile(Py_tracefunc func, PyObject *arg) Py_XINCREF(arg); tstate->c_profilefunc = NULL; tstate->c_profileobj = NULL; + tstate->use_tracing = tstate->c_tracefunc != NULL; Py_XDECREF(temp); tstate->c_profilefunc = func; tstate->c_profileobj = arg; + tstate->use_tracing = (func != NULL) || (tstate->c_tracefunc != NULL); } void @@ -2829,9 +2844,12 @@ PyEval_SetTrace(Py_tracefunc func, PyObject *arg) Py_XINCREF(arg); tstate->c_tracefunc = NULL; tstate->c_traceobj = NULL; + tstate->use_tracing = tstate->c_profilefunc != NULL; Py_XDECREF(temp); tstate->c_tracefunc = func; tstate->c_traceobj = arg; + tstate->use_tracing = ((func != NULL) + || (tstate->c_profilefunc != NULL)); } PyObject * |