Make sure that frame.f_lineno is correct regardless of whether frame.f_trace is set.

This commit is contained in:
Mark Shannon 2021-01-04 18:04:06 +00:00
parent 60b5a03328
commit 2634396732
5 changed files with 24 additions and 26 deletions

View File

@ -42,12 +42,7 @@ struct _frame {
PyObject *f_gen;
int f_lasti; /* Last instruction if called */
/* Call PyFrame_GetLineNumber() instead of reading this field
directly. As of 2.3 f_lineno is only valid when tracing is
active (i.e. when f_trace is set). At other times we use
PyCode_Addr2Line to calculate the line from the current
bytecode index. */
int f_lineno; /* Current line number */
int f_lineno; /* Current line number. Only valid if non-zero */
int f_iblock; /* index in f_blockstack */
PyFrameState f_state; /* What state the frame is in */
PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */

View File

@ -1261,7 +1261,8 @@ PyLineTable_InitAddressRange(char *linetable, int firstlineno, PyCodeAddressRang
range->lo_next = linetable;
range->ar_start = -1;
range->ar_end = 0;
range->ar_computed_line = range->ar_line = firstlineno;
range->ar_computed_line = firstlineno;
range->ar_line = -1;
}
int

View File

@ -44,7 +44,7 @@ int
PyFrame_GetLineNumber(PyFrameObject *f)
{
assert(f != NULL);
if (f->f_trace) {
if (f->f_lineno != 0) {
return f->f_lineno;
}
else {
@ -476,8 +476,8 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
start_block_stack = pop_block(start_block_stack);
}
/* Finally set the new f_lineno and f_lasti and return OK. */
f->f_lineno = new_lineno;
/* Finally set the new f_lasti and return OK. */
f->f_lineno = 0;
f->f_lasti = best_addr;
return 0;
}
@ -498,11 +498,9 @@ frame_gettrace(PyFrameObject *f, void *closure)
static int
frame_settrace(PyFrameObject *f, PyObject* v, void *closure)
{
/* We rely on f_lineno being accurate when f_trace is set. */
f->f_lineno = PyFrame_GetLineNumber(f);
if (v == Py_None)
if (v == Py_None) {
v = NULL;
}
Py_XINCREF(v);
Py_XSETREF(f->f_trace, v);

View File

@ -4993,27 +4993,25 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
PyCodeAddressRange *bounds, 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.
*/
line = _PyCode_CheckLineNumber(frame->f_lasti, bounds);
/* 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.
represents a jump backwards, update the frame's line number and
then call the trace function if we're tracing source lines.
*/
if ((line != frame->f_lineno || frame->f_lasti < *instr_prev)) {
if (line != -1) {
int lastline = bounds->ar_line;
int line = _PyCode_CheckLineNumber(frame->f_lasti, bounds);
if (frame->f_lasti < *instr_prev || (line != lastline && frame->f_lasti == bounds->ar_start)) {
if (line != -1 && frame->f_trace_lines) {
frame->f_lineno = line;
if (frame->f_trace_lines) {
result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None);
}
result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None);
frame->f_lineno = 0;
}
}
/* Always emit an opcode event if we're tracing all opcodes. */
if (frame->f_trace_opcodes) {
frame->f_lineno = _PyCode_CheckLineNumber(frame->f_lasti, bounds);
result = call_trace(func, obj, tstate, frame, PyTrace_OPCODE, Py_None);
frame->f_lineno = 0;
}
*instr_prev = frame->f_lasti;
return result;

View File

@ -6558,6 +6558,12 @@ ensure_exits_have_lineno(struct compiler *c)
if (is_exit_without_lineno(entry)) {
entry->b_instr[0].i_lineno = c->u->u_firstlineno;
}
/* Eliminate empty blocks */
for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) {
while (b->b_next && b->b_next->b_iused == 0) {
b->b_next = b->b_next->b_next;
}
}
/* Any remaining reachable exit blocks without line number can only be reached by
* fall through, and thus can only have a single predecessor */
for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) {