bpo-31344: Per-frame control of trace events (GH-3417)

f_trace_lines: enable/disable line trace events
f_trace_opcodes: enable/disable opcode trace events

These are intended primarily for testing of the interpreter
itself, as they make it much easier to emulate signals
arriving at unfortunate times.
This commit is contained in:
Nick Coghlan 2017-09-08 10:14:16 +10:00 committed by GitHub
parent 2eb0cb4787
commit 5a8516701f
11 changed files with 126 additions and 17 deletions

View file

@ -4458,12 +4458,19 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
*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) {
/* Always emit an opcode event if we're tracing all opcodes. */
if (frame->f_trace_opcodes) {
result = call_trace(func, obj, tstate, frame, PyTrace_OPCODE, Py_None);
}
/* 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
then call the trace function if we're tracing source lines.
*/
if ((frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev)) {
frame->f_lineno = line;
result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None);
if (frame->f_trace_lines) {
result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None);
}
}
*instr_prev = frame->f_lasti;
return result;

View file

@ -349,18 +349,19 @@ same value.");
* Cached interned string objects used for calling the profile and
* trace functions. Initialized by trace_init().
*/
static PyObject *whatstrings[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
static PyObject *whatstrings[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
static int
trace_init(void)
{
static const char * const whatnames[7] = {
static const char * const whatnames[8] = {
"call", "exception", "line", "return",
"c_call", "c_exception", "c_return"
"c_call", "c_exception", "c_return",
"opcode"
};
PyObject *name;
int i;
for (i = 0; i < 7; ++i) {
for (i = 0; i < 8; ++i) {
if (whatstrings[i] == NULL) {
name = PyUnicode_InternFromString(whatnames[i]);
if (name == NULL)