Commit 904aa7bb authored by Fred Drake's avatar Fred Drake

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.
parent edb5ffb2
...@@ -62,7 +62,7 @@ static int prtrace(PyObject *, char *); ...@@ -62,7 +62,7 @@ static int prtrace(PyObject *, char *);
#endif #endif
static void call_exc_trace(PyObject **, PyObject**, PyFrameObject *); static void call_exc_trace(PyObject **, PyObject**, PyFrameObject *);
static int call_trace(PyObject **, PyObject **, static int call_trace(PyObject **, PyObject **,
PyFrameObject *, char *, PyObject *); PyFrameObject *, char *, PyObject **, PyObject *);
static PyObject *loop_subscript(PyObject *, PyObject *); static PyObject *loop_subscript(PyObject *, PyObject *);
static PyObject *apply_slice(PyObject *, PyObject *, PyObject *); static PyObject *apply_slice(PyObject *, PyObject *, PyObject *);
static int assign_slice(PyObject *, PyObject *, static int assign_slice(PyObject *, PyObject *,
...@@ -97,6 +97,15 @@ static long dxp[256]; ...@@ -97,6 +97,15 @@ static long dxp[256];
#endif #endif
#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 #ifdef WITH_THREAD
#ifndef DONT_HAVE_ERRNO_H #ifndef DONT_HAVE_ERRNO_H
...@@ -645,7 +654,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -645,7 +654,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
(sys.trace) is also called whenever an exception (sys.trace) is also called whenever an exception
is detected. */ is detected. */
if (call_trace(&tstate->sys_tracefunc, 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?*/)) { Py_None/*XXX how to compute arguments now?*/)) {
/* Trace function raised an error */ /* Trace function raised an error */
goto fail; goto fail;
...@@ -656,7 +665,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -656,7 +665,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
/* Similar for sys_profilefunc, except it needn't return /* Similar for sys_profilefunc, except it needn't return
itself and isn't called for "line" events */ itself and isn't called for "line" events */
if (call_trace(&tstate->sys_profilefunc, if (call_trace(&tstate->sys_profilefunc,
(PyObject**)0, f, "call", (PyObject**)0, f, "call", &str_call,
Py_None/*XXX*/)) { Py_None/*XXX*/)) {
goto fail; goto fail;
} }
...@@ -1952,7 +1961,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -1952,7 +1961,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
/* Trace each line of code reached */ /* Trace each line of code reached */
f->f_lasti = INSTR_OFFSET(); f->f_lasti = INSTR_OFFSET();
err = call_trace(&f->f_trace, &f->f_trace, err = call_trace(&f->f_trace, &f->f_trace,
f, "line", Py_None); f, "line", &str_line, Py_None);
break; break;
case CALL_FUNCTION: case CALL_FUNCTION:
...@@ -2297,7 +2306,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -2297,7 +2306,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
if (f->f_trace) { if (f->f_trace) {
if (why == WHY_RETURN) { if (why == WHY_RETURN) {
if (call_trace(&f->f_trace, &f->f_trace, f, if (call_trace(&f->f_trace, &f->f_trace, f,
"return", retval)) { "return", &str_return, retval)) {
Py_XDECREF(retval); Py_XDECREF(retval);
retval = NULL; retval = NULL;
why = WHY_EXCEPTION; why = WHY_EXCEPTION;
...@@ -2307,7 +2316,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -2307,7 +2316,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
if (tstate->sys_profilefunc && why == WHY_RETURN) { if (tstate->sys_profilefunc && why == WHY_RETURN) {
if (call_trace(&tstate->sys_profilefunc, (PyObject**)0, if (call_trace(&tstate->sys_profilefunc, (PyObject**)0,
f, "return", retval)) { f, "return", &str_return, retval)) {
Py_XDECREF(retval); Py_XDECREF(retval);
retval = NULL; retval = NULL;
why = WHY_EXCEPTION; why = WHY_EXCEPTION;
...@@ -2575,7 +2584,8 @@ call_exc_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f) ...@@ -2575,7 +2584,8 @@ call_exc_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f)
PyErr_Restore(type, value, traceback); PyErr_Restore(type, value, traceback);
return; 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); Py_DECREF(arg);
if (err == 0) if (err == 0)
PyErr_Restore(type, value, traceback); PyErr_Restore(type, value, traceback);
...@@ -2588,13 +2598,18 @@ call_exc_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f) ...@@ -2588,13 +2598,18 @@ call_exc_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f)
/* PyObject **p_trace: in/out; may not be NULL; /* PyObject **p_trace: in/out; may not be NULL;
may not point to NULL variable initially 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 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 static int
call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, 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; PyThreadState *tstate = f->f_tstate;
PyObject *args, *what; PyObject *args, *what;
...@@ -2612,9 +2627,17 @@ call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, ...@@ -2612,9 +2627,17 @@ call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f,
args = PyTuple_New(3); args = PyTuple_New(3);
if (args == NULL) if (args == NULL)
goto cleanup; goto cleanup;
what = PyString_FromString(msg); if (*p_omsg != NULL) {
if (what == NULL) what = *p_omsg;
goto cleanup; Py_INCREF(what);
}
else {
what = PyString_InternFromString(msg);
if (what == NULL)
goto cleanup;
*p_omsg = what;
Py_INCREF(what);
}
Py_INCREF(f); Py_INCREF(f);
PyTuple_SET_ITEM(args, 0, (PyObject *)f); PyTuple_SET_ITEM(args, 0, (PyObject *)f);
PyTuple_SET_ITEM(args, 1, what); PyTuple_SET_ITEM(args, 1, what);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment