summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1992-03-23 18:19:28 (GMT)
committerGuido van Rossum <guido@python.org>1992-03-23 18:19:28 (GMT)
commit9c8d70de457118c25ee2d30ac506cba65f6583ef (patch)
tree071ab6112c3ac0619cd79d41248234270e6f3c23 /Python/ceval.c
parentcb9d66da5992a6c5b01ad4be8d17948107723118 (diff)
downloadcpython-9c8d70de457118c25ee2d30ac506cba65f6583ef.zip
cpython-9c8d70de457118c25ee2d30ac506cba65f6583ef.tar.gz
cpython-9c8d70de457118c25ee2d30ac506cba65f6583ef.tar.bz2
New trace implementation; and profile (in a similat vein).
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c193
1 files changed, 109 insertions, 84 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 3e0c76a..2b60e57 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -71,7 +71,9 @@ static int testbool();
static int assign_subscript PROTO((object *, object *, object *));
static int assign_slice PROTO((object *, object *, object *, object *));
static int import_from PROTO((object *, object *, object *));
-static object *call_trace PROTO((object *, frameobject *, char *, object *));
+static void call_exc_trace PROTO((object **, object**, frameobject *));
+static int call_trace
+ PROTO((object **, object **, frameobject *, char *, object *));
static frameobject *current_frame;
@@ -109,7 +111,7 @@ eval_code(co, globals, locals, arg)
register object *u;
register object *t;
register frameobject *f; /* Current frame */
- object *trace; /* Trace function or NULL */
+ object *trace = NULL; /* Trace function or NULL */
object *retval; /* Return value iff why == WHY_RETURN */
char *name; /* Name used by some instructions */
FILE *fp; /* Used by print operations */
@@ -157,13 +159,8 @@ eval_code(co, globals, locals, arg)
current_frame = f;
- trace = sysget("trace");
- if (trace != NULL) {
- if (trace == None) {
- trace = NULL;
- }
- else {
- /* sys.trace, if defined, is a function that will
+ if (sys_trace != NULL) {
+ /* sys_trace, if defined, is a function that will
be called on *every* entry to a code block.
Its return value, if not None, is a function that
will be called at the start of each executed line
@@ -175,20 +172,22 @@ eval_code(co, globals, locals, arg)
depends on the situation. The global trace function
(sys.trace) is also called whenever an exception
is detected. */
- trace = call_trace(trace, f, "call", arg);
- if (trace == NULL) {
+ if (call_trace(&sys_trace, &trace, f, "call", arg)) {
/* Trace function raised an error */
- sysset("trace", (object *)NULL);
current_frame = f->f_back;
DECREF(f);
return NULL;
}
- if (trace == None) {
- /* No need to trace this code block */
- DECREF(trace);
- trace = NULL;
+ }
+
+ if (sys_profile != NULL) {
+ /* Similar for sys_profile, except it needn't return
+ itself and isn't called for "line" events */
+ if (call_trace(&sys_profile, (object**)0, f, "call", arg)) {
+ current_frame = f->f_back;
+ DECREF(f);
+ return NULL;
}
- }
}
next_instr = GETUSTRINGVALUE(f->f_code->co_code);
@@ -1005,16 +1004,8 @@ eval_code(co, globals, locals, arg)
if (trace != NULL) {
/* Trace each line of code reached */
f->f_lasti = INSTR_OFFSET();
- x = call_trace(trace, f, "line", None);
- /* The trace function must return itself
- in order to continue tracing */
- DECREF(trace);
- if (x == None) {
- DECREF(x);
- trace = NULL;
- }
- else
- trace = x;
+ err = call_trace(&trace, &trace,
+ f, "line", None);
}
break;
@@ -1066,40 +1057,10 @@ eval_code(co, globals, locals, arg)
f->f_lasti -= 2;
tb_here(f);
- if (trace) {
- object *type, *value, *traceback, *arg;
- err_get(&type, &value);
- traceback = tb_fetch();
- arg = newtupleobject(3);
- if (arg == NULL)
- err_clear();
- else {
- settupleitem(arg, 0, type);
- settupleitem(arg, 1, value);
- settupleitem(arg, 2, traceback);
- }
- v = call_trace(trace, f, "exception", arg);
- if (v == NULL) {
- /* Trace function raised error */
- tb_here(f);
- sysset("trace", (object *)NULL);
- XDECREF(trace);
- trace = NULL;
- }
- else {
- /* Restore original exception */
- err_setval(type, value);
- tb_store(traceback);
- if (v == None)
- DECREF(v);
- else {
- /* Set trace function */
- XDECREF(trace);
- trace = v;
- }
- }
- XDECREF(arg);
- }
+ if (trace)
+ call_exc_trace(&trace, &trace, f);
+ if (sys_profile)
+ call_exc_trace(&sys_profile, (object**)0, f);
}
/* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */
@@ -1177,15 +1138,22 @@ eval_code(co, globals, locals, arg)
if (trace) {
if (why == WHY_RETURN) {
- x = call_trace(trace, f, "return", retval);
- if (x == NULL) {
+ if (call_trace(&trace, &trace, f, "return", retval)) {
XDECREF(retval);
retval = NULL;
+ why = WHY_EXCEPTION;
}
- else
- DECREF(x);
}
- DECREF(trace);
+ XDECREF(trace);
+ }
+
+ if (sys_profile && why == WHY_RETURN) {
+ if (call_trace(&sys_profile, (object**)0,
+ f, "return", retval)) {
+ XDECREF(retval);
+ retval = NULL;
+ why = WHY_EXCEPTION;
+ }
}
/* Restore previous frame and release the current one */
@@ -1209,44 +1177,101 @@ prtrace(v, str)
}
#endif
-static object *
-call_trace(trace, f, msg, arg)
- object *trace;
+static void
+call_exc_trace(p_trace, p_newtrace, f)
+ object **p_trace, **p_newtrace;
+ frameobject *f;
+{
+ object *type, *value, *traceback, *arg;
+ int err;
+ err_get(&type, &value);
+ traceback = tb_fetch();
+ arg = newtupleobject(3);
+ if (arg == NULL) {
+ err = -1;
+ goto cleanup;
+ }
+ settupleitem(arg, 0, type);
+ settupleitem(arg, 1, value);
+ settupleitem(arg, 2, traceback);
+ err = call_trace(p_trace, p_newtrace, f, "exception", arg);
+ XDECREF(arg);
+ cleanup:
+ if (!err) {
+ /* Restore original exception */
+ err_setval(type, value);
+ tb_store(traceback);
+ }
+}
+
+static int
+call_trace(p_trace, p_newtrace, f, msg, arg)
+ object **p_trace; /* in/out; may not be NULL;
+ may not point to NULL variable initially */
+ object **p_newtrace; /* in/out; may be NULL;
+ may point to NULL variable;
+ may be same variable as p_newtrace */
frameobject *f;
char *msg;
object *arg;
{
- object *arglist, *what, *res;
+ object *arglist, *what;
+ object *res = NULL;
static int tracing = 0;
if (tracing) {
- /* Don't trace the trace code! */
- INCREF(None);
- return None;
+ /* Don't do recursive traces */
+ if (p_newtrace) {
+ XDECREF(*p_newtrace);
+ *p_newtrace = NULL;
+ }
+ return 0;
}
arglist = newtupleobject(3);
if (arglist == NULL)
- return NULL;
+ goto cleanup;
what = newstringobject(msg);
- if (what == NULL) {
- DECREF(arglist);
- return NULL;
- }
+ if (what == NULL)
+ goto cleanup;
INCREF(f);
+ settupleitem(arglist, 0, (object *)f);
+ settupleitem(arglist, 1, what);
if (arg == NULL)
arg = None;
INCREF(arg);
- settupleitem(arglist, 0, (object *)f);
- settupleitem(arglist, 1, what);
settupleitem(arglist, 2, arg);
tracing++;
- res = call_object(trace, arglist);
+ res = call_object(*p_trace, arglist);
tracing--;
- if (res == NULL)
+ cleanup:
+ XDECREF(arglist);
+ if (res == NULL) {
+ /* The trace proc raised an exception */
tb_here(f);
- DECREF(arglist);
- return res;
+ XDECREF(*p_trace);
+ *p_trace = NULL;
+ if (p_newtrace) {
+ XDECREF(*p_newtrace);
+ *p_newtrace = NULL;
+ }
+ }
+ else {
+ if (p_newtrace) {
+ XDECREF(*p_newtrace);
+ if (res == None)
+ *p_newtrace = NULL;
+ else {
+ INCREF(res);
+ *p_newtrace = res;
+ }
+ }
+ DECREF(res);
+ }
+ if (res == NULL)
+ return -1;
+ else
+ return 0;
}
object *