@@ -339,6 +339,8 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
339339 co -> _co_code = NULL ;
340340
341341 co -> co_warmup = QUICKENING_INITIAL_WARMUP_VALUE ;
342+ co -> _co_linearray_entry_size = 0 ;
343+ co -> _co_linearray = NULL ;
342344 memcpy (_PyCode_CODE (co ), PyBytes_AS_STRING (con -> code ),
343345 PyBytes_GET_SIZE (con -> code ));
344346 int entry_point = 0 ;
@@ -703,13 +705,60 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
703705 lnotab_notes.txt for the details of the lnotab representation.
704706*/
705707
708+ int
709+ _PyCode_CreateLineArray (PyCodeObject * co )
710+ {
711+ assert (co -> _co_linearray == NULL );
712+ PyCodeAddressRange bounds ;
713+ int size ;
714+ int max_line = 0 ;
715+ _PyCode_InitAddressRange (co , & bounds );
716+ while (_PyLineTable_NextAddressRange (& bounds )) {
717+ if (bounds .ar_line > max_line ) {
718+ max_line = bounds .ar_line ;
719+ }
720+ }
721+ if (max_line < (1 << 15 )) {
722+ size = 2 ;
723+ }
724+ else {
725+ size = 4 ;
726+ }
727+ co -> _co_linearray = PyMem_Malloc (Py_SIZE (co )* size );
728+ if (co -> _co_linearray == NULL ) {
729+ PyErr_NoMemory ();
730+ return -1 ;
731+ }
732+ co -> _co_linearray_entry_size = size ;
733+ _PyCode_InitAddressRange (co , & bounds );
734+ while (_PyLineTable_NextAddressRange (& bounds )) {
735+ int start = bounds .ar_start / sizeof (_Py_CODEUNIT );
736+ int end = bounds .ar_end / sizeof (_Py_CODEUNIT );
737+ for (int index = start ; index < end ; index ++ ) {
738+ assert (index < (int )Py_SIZE (co ));
739+ if (size == 2 ) {
740+ assert (((int16_t )bounds .ar_line ) == bounds .ar_line );
741+ ((int16_t * )co -> _co_linearray )[index ] = bounds .ar_line ;
742+ }
743+ else {
744+ assert (size == 4 );
745+ ((int32_t * )co -> _co_linearray )[index ] = bounds .ar_line ;
746+ }
747+ }
748+ }
749+ return 0 ;
750+ }
751+
706752int
707753PyCode_Addr2Line (PyCodeObject * co , int addrq )
708754{
709755 if (addrq < 0 ) {
710756 return co -> co_firstlineno ;
711757 }
712758 assert (addrq >= 0 && addrq < _PyCode_NBYTES (co ));
759+ if (co -> _co_linearray ) {
760+ return _PyCode_LineNumberFromArray (co , addrq / sizeof (_Py_CODEUNIT ));
761+ }
713762 PyCodeAddressRange bounds ;
714763 _PyCode_InitAddressRange (co , & bounds );
715764 return _PyCode_CheckLineNumber (addrq , & bounds );
@@ -1549,6 +1598,9 @@ code_dealloc(PyCodeObject *co)
15491598 if (co -> co_weakreflist != NULL ) {
15501599 PyObject_ClearWeakRefs ((PyObject * )co );
15511600 }
1601+ if (co -> _co_linearray ) {
1602+ PyMem_Free (co -> _co_linearray );
1603+ }
15521604 if (co -> co_warmup == 0 ) {
15531605 _Py_QuickenedCount -- ;
15541606 }
@@ -2106,6 +2158,10 @@ _PyStaticCode_Dealloc(PyCodeObject *co)
21062158 PyObject_ClearWeakRefs ((PyObject * )co );
21072159 co -> co_weakreflist = NULL ;
21082160 }
2161+ if (co -> _co_linearray ) {
2162+ PyMem_Free (co -> _co_linearray );
2163+ co -> _co_linearray = NULL ;
2164+ }
21092165}
21102166
21112167int
0 commit comments