]> granicus.if.org Git - python/commitdiff
call_trace(): Add an additional parameter -- pointer to a PyObject*
authorFred Drake <fdrake@acm.org>
Fri, 8 Jun 2001 04:33:09 +0000 (04:33 +0000)
committerFred Drake <fdrake@acm.org>
Fri, 8 Jun 2001 04:33:09 +0000 (04:33 +0000)
    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

index 902d52918bdecdacce352d63531afe22e7653b0a..ceecdb15efa7582b26d3c45c7322ea7dd7cdf63d 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 *);
+                     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);