From d083839fb4f44ff66792d80f7a71863600ca4638 Mon Sep 17 00:00:00 2001 From: Fred Drake Date: Sat, 16 Jun 2001 21:02:31 +0000 Subject: [PATCH] Instead of initializing & interning the strings passed to the profile and trace functions lazily, which incurs extra argument pushing and checks in the C overhead for profiling/tracing, create the strings semi-lazily when the Python code first registers a profile or trace function. This simplifies the trampoline into the profile/trace functions. --- Python/ceval.c | 68 ++++++++++++++++++++++++++++------------------ Python/sysmodule.c | 6 ++++ 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index 7f668fca9cd..f9d03253eb8 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 **, PyObject *); + PyFrameObject *, PyObject *, PyObject *); static PyObject *loop_subscript(PyObject *, PyObject *); static PyObject *apply_slice(PyObject *, PyObject *, PyObject *); static int assign_slice(PyObject *, PyObject *, @@ -654,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", &str_call, + &f->f_trace, f, str_call, Py_None/*XXX how to compute arguments now?*/)) { /* Trace function raised an error */ goto fail; @@ -665,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", &str_call, + (PyObject**)0, f, str_call, Py_None/*XXX*/)) { goto fail; } @@ -1961,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", &str_line, Py_None); + f, str_line, Py_None); break; case CALL_FUNCTION: @@ -2306,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", &str_return, retval)) { + str_return, retval)) { Py_XDECREF(retval); retval = NULL; why = WHY_EXCEPTION; @@ -2316,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", &str_return, retval)) { + f, str_return, retval)) { Py_XDECREF(retval); retval = NULL; why = WHY_EXCEPTION; @@ -2584,8 +2584,7 @@ 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", &str_exception, arg); + err = call_trace(p_trace, p_newtrace, f, str_exception, arg); Py_DECREF(arg); if (err == 0) PyErr_Restore(type, value, traceback); @@ -2601,18 +2600,15 @@ call_exc_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f) PyObject **p_newtrace: in/out; may be NULL; may point to NULL variable; 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. + PyObject *msg: in; must not be NULL */ static int call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, - char *msg, PyObject **p_omsg, PyObject *arg) + PyObject *msg, PyObject *arg) { PyThreadState *tstate = f->f_tstate; - PyObject *args, *what; + PyObject *args; PyObject *res = NULL; if (tstate->tracing) { @@ -2627,20 +2623,10 @@ call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, args = PyTuple_New(3); if (args == 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(msg); Py_INCREF(f); PyTuple_SET_ITEM(args, 0, (PyObject *)f); - PyTuple_SET_ITEM(args, 1, what); + PyTuple_SET_ITEM(args, 1, msg); if (arg == NULL) arg = Py_None; Py_INCREF(arg); @@ -2686,6 +2672,36 @@ call_trace(PyObject **p_trace, PyObject **p_newtrace, PyFrameObject *f, } } +/* Initialize the strings that get passed to the profile and trace functions; + * this avoids doing this while we're actually profiling/tracing. + */ +int +_PyTrace_Init(void) +{ + if (str_call == NULL) { + str_call = PyString_InternFromString("call"); + if (str_call == NULL) + return -1; + } + if (str_exception == NULL) { + str_exception = PyString_InternFromString("exception"); + if (str_exception == NULL) + return -1; + } + if (str_line == NULL) { + str_line = PyString_InternFromString("line"); + if (str_line == NULL) + return -1; + } + if (str_return == NULL) { + str_return = PyString_InternFromString("return"); + if (str_return == NULL) + return -1; + } + return 0; +} + + PyObject * PyEval_GetBuiltins(void) { diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 52fbbc89d32..62e08414d8c 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -196,10 +196,14 @@ static char setdefaultencoding_doc[] = \n\ Set the current default string encoding used by the Unicode implementation."; +extern int _PyTrace_Init(void); + static PyObject * sys_settrace(PyObject *self, PyObject *args) { PyThreadState *tstate = PyThreadState_Get(); + if (_PyTrace_Init() == -1) + return NULL; if (args == Py_None) args = NULL; else @@ -220,6 +224,8 @@ static PyObject * sys_setprofile(PyObject *self, PyObject *args) { PyThreadState *tstate = PyThreadState_Get(); + if (_PyTrace_Init() == -1) + return NULL; if (args == Py_None) args = NULL; else