GH-93516: Speedup line number checks when tracing. (GH-93763)

* Use a lookup table to reduce overhead of getting line numbers during tracing.
This commit is contained in:
Mark Shannon 2022-06-20 13:00:42 +01:00 committed by GitHub
parent 45e62a2bc1
commit ab0e601016
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 8 deletions

View file

@ -339,6 +339,8 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
co->_co_code = NULL;
co->co_warmup = QUICKENING_INITIAL_WARMUP_VALUE;
co->_co_linearray_entry_size = 0;
co->_co_linearray = NULL;
memcpy(_PyCode_CODE(co), PyBytes_AS_STRING(con->code),
PyBytes_GET_SIZE(con->code));
int entry_point = 0;
@ -703,6 +705,50 @@ failed:
lnotab_notes.txt for the details of the lnotab representation.
*/
int
_PyCode_CreateLineArray(PyCodeObject *co)
{
assert(co->_co_linearray == NULL);
PyCodeAddressRange bounds;
int size;
int max_line = 0;
_PyCode_InitAddressRange(co, &bounds);
while(_PyLineTable_NextAddressRange(&bounds)) {
if (bounds.ar_line > max_line) {
max_line = bounds.ar_line;
}
}
if (max_line < (1 << 15)) {
size = 2;
}
else {
size = 4;
}
co->_co_linearray = PyMem_Malloc(Py_SIZE(co)*size);
if (co->_co_linearray == NULL) {
PyErr_NoMemory();
return -1;
}
co->_co_linearray_entry_size = size;
_PyCode_InitAddressRange(co, &bounds);
while(_PyLineTable_NextAddressRange(&bounds)) {
int start = bounds.ar_start / sizeof(_Py_CODEUNIT);
int end = bounds.ar_end / sizeof(_Py_CODEUNIT);
for (int index = start; index < end; index++) {
assert(index < (int)Py_SIZE(co));
if (size == 2) {
assert(((int16_t)bounds.ar_line) == bounds.ar_line);
((int16_t *)co->_co_linearray)[index] = bounds.ar_line;
}
else {
assert(size == 4);
((int32_t *)co->_co_linearray)[index] = bounds.ar_line;
}
}
}
return 0;
}
int
PyCode_Addr2Line(PyCodeObject *co, int addrq)
{
@ -710,6 +756,9 @@ PyCode_Addr2Line(PyCodeObject *co, int addrq)
return co->co_firstlineno;
}
assert(addrq >= 0 && addrq < _PyCode_NBYTES(co));
if (co->_co_linearray) {
return _PyCode_LineNumberFromArray(co, addrq / sizeof(_Py_CODEUNIT));
}
PyCodeAddressRange bounds;
_PyCode_InitAddressRange(co, &bounds);
return _PyCode_CheckLineNumber(addrq, &bounds);
@ -1549,6 +1598,9 @@ code_dealloc(PyCodeObject *co)
if (co->co_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject*)co);
}
if (co->_co_linearray) {
PyMem_Free(co->_co_linearray);
}
if (co->co_warmup == 0) {
_Py_QuickenedCount--;
}
@ -2106,6 +2158,10 @@ _PyStaticCode_Dealloc(PyCodeObject *co)
PyObject_ClearWeakRefs((PyObject *)co);
co->co_weakreflist = NULL;
}
if (co->_co_linearray) {
PyMem_Free(co->_co_linearray);
co->_co_linearray = NULL;
}
}
int