]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Instead of initializing & interning the strings passed to the profile
authorFred Drake <fdrake@acm.org>
Sat, 16 Jun 2001 21:02:31 +0000 (21:02 +0000)
committerFred Drake <fdrake@acm.org>
Sat, 16 Jun 2001 21:02:31 +0000 (21:02 +0000)
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
Python/sysmodule.c

index 7f668fca9cd225a96bb91946f0dae46c53426a5c..f9d03253eb8fbff3b9eb62ba333c621a48b7f297 100644 (file)
@@ -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)
 {
index 52fbbc89d32db6c10c81ff3813ac6809aa615bd3..62e08414d8c9d93f3ce2977032ab89d87d27ffbb 100644 (file)
@@ -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