summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c78
1 files changed, 76 insertions, 2 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index d3bd8b5..a396e81 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -15,6 +15,7 @@
#include "dictobject.h"
#include "frameobject.h"
#include "opcode.h"
+#include "pydtrace.h"
#include "setobject.h"
#include "structmember.h"
@@ -50,6 +51,9 @@ static void call_exc_trace(Py_tracefunc, PyObject *,
PyThreadState *, PyFrameObject *);
static int maybe_call_line_trace(Py_tracefunc, PyObject *,
PyThreadState *, PyFrameObject *, int *, int *, int *);
+static void maybe_dtrace_line(PyFrameObject *, int *, int *, int *);
+static void dtrace_function_entry(PyFrameObject *);
+static void dtrace_function_return(PyFrameObject *);
static PyObject * cmp_outcome(int, PyObject *, PyObject *);
static PyObject * import_name(PyFrameObject *, PyObject *, PyObject *, PyObject *);
@@ -822,7 +826,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
#ifdef LLTRACE
#define FAST_DISPATCH() \
{ \
- if (!lltrace && !_Py_TracingPossible) { \
+ if (!lltrace && !_Py_TracingPossible && !PyDTrace_LINE_ENABLED()) { \
f->f_lasti = INSTR_OFFSET(); \
NEXTOPARG(); \
goto *opcode_targets[opcode]; \
@@ -832,7 +836,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
#else
#define FAST_DISPATCH() \
{ \
- if (!_Py_TracingPossible) { \
+ if (!_Py_TracingPossible && !PyDTrace_LINE_ENABLED()) { \
f->f_lasti = INSTR_OFFSET(); \
NEXTOPARG(); \
goto *opcode_targets[opcode]; \
@@ -1042,6 +1046,9 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
}
}
+ if (PyDTrace_FUNCTION_ENTRY_ENABLED())
+ dtrace_function_entry(f);
+
co = f->f_code;
names = co->co_names;
consts = co->co_consts;
@@ -1162,6 +1169,9 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
fast_next_opcode:
f->f_lasti = INSTR_OFFSET();
+ if (PyDTrace_LINE_ENABLED())
+ maybe_dtrace_line(f, &instr_lb, &instr_ub, &instr_prev);
+
/* line-by-line tracing support */
if (_Py_TracingPossible &&
@@ -3620,6 +3630,8 @@ fast_yield:
/* pop frame */
exit_eval_frame:
+ if (PyDTrace_FUNCTION_RETURN_ENABLED())
+ dtrace_function_return(f);
Py_LeaveRecursiveCall();
f->f_executing = 0;
tstate->frame = f->f_back;
@@ -5415,3 +5427,65 @@ _PyEval_RequestCodeExtraIndex(freefunc free)
tstate->co_extra_freefuncs[new_index] = free;
return new_index;
}
+
+static void
+dtrace_function_entry(PyFrameObject *f)
+{
+ char* filename;
+ char* funcname;
+ int lineno;
+
+ filename = PyUnicode_AsUTF8(f->f_code->co_filename);
+ funcname = PyUnicode_AsUTF8(f->f_code->co_name);
+ lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
+
+ PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
+}
+
+static void
+dtrace_function_return(PyFrameObject *f)
+{
+ char* filename;
+ char* funcname;
+ int lineno;
+
+ filename = PyUnicode_AsUTF8(f->f_code->co_filename);
+ funcname = PyUnicode_AsUTF8(f->f_code->co_name);
+ lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
+
+ PyDTrace_FUNCTION_RETURN(filename, funcname, lineno);
+}
+
+/* DTrace equivalent of maybe_call_line_trace. */
+static void
+maybe_dtrace_line(PyFrameObject *frame,
+ int *instr_lb, int *instr_ub, int *instr_prev)
+{
+ int line = frame->f_lineno;
+ char *co_filename, *co_name;
+
+ /* If the last instruction executed isn't in the current
+ instruction window, reset the window.
+ */
+ if (frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub) {
+ PyAddrPair bounds;
+ line = _PyCode_CheckLineNumber(frame->f_code, frame->f_lasti,
+ &bounds);
+ *instr_lb = bounds.ap_lower;
+ *instr_ub = bounds.ap_upper;
+ }
+ /* If the last instruction falls at the start of a line or if
+ it represents a jump backwards, update the frame's line
+ number and call the trace function. */
+ if (frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev) {
+ frame->f_lineno = line;
+ co_filename = PyUnicode_AsUTF8(frame->f_code->co_filename);
+ if (!co_filename)
+ co_filename = "?";
+ co_name = PyUnicode_AsUTF8(frame->f_code->co_name);
+ if (!co_name)
+ co_name = "?";
+ PyDTrace_LINE(co_filename, co_name, line);
+ }
+ *instr_prev = frame->f_lasti;
+}