mirror of
https://github.com/python/cpython.git
synced 2026-03-30 00:21:21 +00:00
Issue #6042:
lnotab-based tracing is very complicated and isn't documented very well. There were at least 3 comment blocks purporting to document co_lnotab, and none did a very good job. This patch unifies them into Objects/lnotab_notes.txt which tries to completely capture the current state of affairs. I also discovered that we've attached 2 layers of patches to the basic tracing scheme. The first layer avoids jumping to instructions that don't start a line, to avoid problems in if statements and while loops. The second layer discovered that jumps backward do need to trace at instructions that don't start a line, so it added extra lnotab entries for 'while' and 'for' loops, and added a special case for backward jumps within the same line. I replaced these patches by just treating forward and backward jumps differently.
This commit is contained in:
parent
3724d6c392
commit
655d835415
6 changed files with 157 additions and 209 deletions
|
|
@ -3591,33 +3591,30 @@ _PyEval_CallTracing(PyObject *func, PyObject *args)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* See Objects/lnotab_notes.txt for a description of how tracing works. */
|
||||
static int
|
||||
maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
|
||||
PyFrameObject *frame, int *instr_lb, int *instr_ub,
|
||||
int *instr_prev)
|
||||
{
|
||||
int result = 0;
|
||||
int line = frame->f_lineno;
|
||||
|
||||
/* If the last instruction executed isn't in the current
|
||||
instruction window, reset the window. If the last
|
||||
instruction happens to fall at the start of a line or if it
|
||||
represents a jump backwards, call the trace function.
|
||||
instruction window, reset the window.
|
||||
*/
|
||||
if ((frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub)) {
|
||||
int line;
|
||||
if (frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub) {
|
||||
PyAddrPair bounds;
|
||||
|
||||
line = PyCode_CheckLineNumber(frame->f_code, frame->f_lasti,
|
||||
&bounds);
|
||||
if (line >= 0) {
|
||||
frame->f_lineno = line;
|
||||
result = call_trace(func, obj, frame,
|
||||
PyTrace_LINE, Py_None);
|
||||
}
|
||||
line = _PyCode_CheckLineNumber(frame->f_code, frame->f_lasti,
|
||||
&bounds);
|
||||
*instr_lb = bounds.ap_lower;
|
||||
*instr_ub = bounds.ap_upper;
|
||||
}
|
||||
else if (frame->f_lasti <= *instr_prev) {
|
||||
/* 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;
|
||||
result = call_trace(func, obj, frame, PyTrace_LINE, Py_None);
|
||||
}
|
||||
*instr_prev = frame->f_lasti;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue