Skip to content

Commit

Permalink
GH-127953: Make line number lookup O(1) regardless of the size of the…
Browse files Browse the repository at this point in the history
… code object (GH-128350)
  • Loading branch information
markshannon authored Jan 21, 2025
1 parent f7cc7d2 commit 7239da7
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 163 deletions.
9 changes: 5 additions & 4 deletions Include/cpython/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ typedef struct {
} _PyCoCached;

/* Ancillary data structure used for instrumentation.
Line instrumentation creates an array of
these. One entry per code unit.*/
Line instrumentation creates this with sufficient
space for one entry per code unit. The total size
of the data will be `bytes_per_entry * Py_SIZE(code)` */
typedef struct {
uint8_t original_opcode;
int8_t line_delta;
uint8_t bytes_per_entry;
uint8_t data[1];
} _PyCoLineInstrumentationData;


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The time to handle a ``LINE`` event in sys.monitoring (and sys.settrace) is
now independent of the number of lines in the code object.
3 changes: 3 additions & 0 deletions Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,9 @@ PyCode_Addr2Line(PyCodeObject *co, int addrq)
if (addrq < 0) {
return co->co_firstlineno;
}
if (co->_co_monitoring && co->_co_monitoring->lines) {
return _Py_Instrumentation_GetLine(co, addrq/sizeof(_Py_CODEUNIT));
}
assert(addrq >= 0 && addrq < _PyCode_NBYTES(co));
PyCodeAddressRange bounds;
_PyCode_InitAddressRange(co, &bounds);
Expand Down
3 changes: 2 additions & 1 deletion Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -4816,7 +4816,8 @@ dummy_func(
int original_opcode = 0;
if (tstate->tracing) {
PyCodeObject *code = _PyFrame_GetCode(frame);
original_opcode = code->_co_monitoring->lines[(int)(this_instr - _PyFrame_GetBytecode(frame))].original_opcode;
int index = (int)(this_instr - _PyFrame_GetBytecode(frame));
original_opcode = code->_co_monitoring->lines->data[index*code->_co_monitoring->lines->bytes_per_entry];
next_instr = this_instr;
} else {
original_opcode = _Py_call_instrumentation_line(
Expand Down
3 changes: 2 additions & 1 deletion Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 7239da7

Please sign in to comment.