diff options
author | Mark Shannon <mark@hotpy.org> | 2022-06-20 12:00:42 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-20 12:00:42 (GMT) |
commit | ab0e60101637b7cf47f3cc95813996791e7118c4 (patch) | |
tree | c0590854ab9e9137c872f0789763d7bb07151fb0 /Objects | |
parent | 45e62a2bc1c0000e2e9b613fff6bebf2c26fcb93 (diff) | |
download | cpython-ab0e60101637b7cf47f3cc95813996791e7118c4.zip cpython-ab0e60101637b7cf47f3cc95813996791e7118c4.tar.gz cpython-ab0e60101637b7cf47f3cc95813996791e7118c4.tar.bz2 |
GH-93516: Speedup line number checks when tracing. (GH-93763)
* Use a lookup table to reduce overhead of getting line numbers during tracing.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/codeobject.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 556d3a3..c1f696d 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -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; @@ -704,12 +706,59 @@ failed: */ 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) { if (addrq < 0) { 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 |