From 904aa7bb00e7cbcde9a8d7f449c2094155395d49 Mon Sep 17 00:00:00 2001 From: Fred Drake Date: Fri, 8 Jun 2001 04:33:09 +0000 Subject: call_trace(): Add an additional parameter -- pointer to a PyObject* that should be used to cache an interned version of the event string passed to the profile/trace function. call_trace() will create interned strings and cache them in using the storage specified by this additional parameter, avoiding a lot of string object creation at runtime when using the profiling or tracing functions. All call sites are modified to pass the additional parameter, and four static PyObject* variables are allocated to cache the interned string objects. This closes SF patch #431257. --- Python/ceval.c | 49 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index 902d529..ceecdb1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -62,7 +62,7 @@ static int prtrace(PyObject *, char *); #endif static void call_exc_trace(PyObject **, PyObject**, PyFrameObject *); static int call_trace(PyObject **, PyObject **, - PyFrameObject *, char *, PyObject *); + PyFrameObject *, char *, PyObject **, PyObject *); static PyObject *loop_subscript(PyObject *, PyObject *); static PyObject *apply_slice(PyObject *, PyObject *, PyObject *); static int assign_slice(PyObject *, PyObject *, @@ -97,6 +97,15 @@ static long dxp[256]; #endif #endif +/* Cached interned string objects used for calling the profile and + * trace functions. + */ +static PyObject *str_call = NULL; +static PyObject *str_exception = NULL; +static PyObject *str_line = NULL; +static PyObject *str_return = NULL; + + #ifdef WITH_THREAD #ifndef DONT_HAVE_ERRNO_H @@ -645,7 +654,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, (sys.trace) is also called whenever an exception is detected. */ if (call_trace(&tstate->sys_tracefunc, - &f->f_trace, f, "call", + &f->f_trace, f, "call", &str_call, Py_None/*XXX how to compute arguments now?*/)) { /* Trace function raised an error */ goto fail; @@ -656,7 +665,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, /* Similar for sys_profilefunc, except it needn't return itself and isn't called for "line" events */ if (call_trace(&tstate->sys_profilefunc, - (PyObject**)0, f, "call", + (PyObject**)0, f, "call", &str_call, Py_None/*XXX*/)) { goto fail; } @@ -1952,7 +1961,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, /* Trace each line of code reached */ f->f_lasti = INSTR_OFFSET(); err = call_trace(&f->f_trace, &f->f_trace, - f, "line", Py_None); + f, "line", &str_line, Py_None); break; case CALL_FUNCTION: @@ -2297,7 +2306,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, if (f->f_trace) { if (why == WHY_RETURN) { if (call_trace(&f->f_trace, &f->f_trace, f, - "return", retval)) { + "return", &str_return, retval)) { Py_XDECREF(retval); retval = NULL; why = WHY_EXCEPTION; @@ -2307,7 +2316,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, if (tstate->sys_profilefunc && why == WHY_RETURN) { if (call_trace(&tstate->sys_profilefunc, (PyObject**)0, - f, "return", retval)) { + f, "return", &str_return, retval)) { Py_XDECREF(retval); retval = NULL; why = WHY_EXCEPTION; @@ -2575,7 +2584,8 @@ call_exc_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f) PyErr_Restore(type, value, traceback); return; } - err = call_trace(p_trace, p_newtrace, f, "exception", arg); + err = call_trace(p_trace, p_newtrace, f, + "exception", &str_exception, arg); Py_DECREF(arg); if (err == 0) PyErr_Restore(type, value, traceback); @@ -2588,13 +2598,18 @@ call_exc_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f) /* PyObject **p_trace: in/out; may not be NULL; may not point to NULL variable initially - PyObject **p_newtrace: in/out; may be NULL; + PyObject **p_newtrace: in/out; may be NULL; may point to NULL variable; - may be same variable as p_newtrace */ + may be same variable as p_newtrace + PyObject **p_omsg: in/out; may not be NULL; + if non-null & *p_omsg == NULL, will be + initialized with an interned string + corresponding to msg. +*/ static int call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, - char *msg, PyObject *arg) + char *msg, PyObject **p_omsg, PyObject *arg) { PyThreadState *tstate = f->f_tstate; PyObject *args, *what; @@ -2612,9 +2627,17 @@ call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, args = PyTuple_New(3); if (args == NULL) goto cleanup; - what = PyString_FromString(msg); - if (what == NULL) - goto cleanup; + if (*p_omsg != NULL) { + what = *p_omsg; + Py_INCREF(what); + } + else { + what = PyString_InternFromString(msg); + if (what == NULL) + goto cleanup; + *p_omsg = what; + Py_INCREF(what); + } Py_INCREF(f); PyTuple_SET_ITEM(args, 0, (PyObject *)f); PyTuple_SET_ITEM(args, 1, what); -- cgit v0.12