@@ -444,6 +444,7 @@ translate_bytecode_to_trace(
444
444
code -> co_firstlineno ,
445
445
2 * INSTR_IP (initial_instr , code ));
446
446
447
+ top : // Jump here after _PUSH_FRAME
447
448
for (;;) {
448
449
RESERVE_RAW (2 , "epilogue" ); // Always need space for SAVE_IP and EXIT_TRACE
449
450
ADD_TO_TRACE (SAVE_IP , INSTR_IP (instr , code ), 0 );
@@ -617,6 +618,34 @@ translate_bytecode_to_trace(
617
618
ADD_TO_TRACE (expansion -> uops [i ].uop , oparg , operand );
618
619
if (expansion -> uops [i ].uop == _PUSH_FRAME ) {
619
620
assert (i + 1 == nuops );
621
+ int func_version_offset =
622
+ offsetof(_PyCallCache , func_version )/sizeof (_Py_CODEUNIT )
623
+ // Add one to account for the actual opcode/oparg pair:
624
+ + 1 ;
625
+ uint32_t func_version = read_u32 (& instr [func_version_offset ].cache );
626
+ PyFunctionObject * func = _PyFunction_LookupByVersion (func_version );
627
+ DPRINTF (3 , "Function object: %p\n" , func );
628
+ if (func != NULL ) {
629
+ PyCodeObject * new_code = (PyCodeObject * )PyFunction_GET_CODE (func );
630
+ if (new_code == code ) {
631
+ // Recursive call, bail (we could be here forever).
632
+ DPRINTF (2 , "Bailing on recursive call to %s (%s:%d)\n" ,
633
+ PyUnicode_AsUTF8 (new_code -> co_qualname ),
634
+ PyUnicode_AsUTF8 (new_code -> co_filename ),
635
+ new_code -> co_firstlineno );
636
+ ADD_TO_TRACE (SAVE_IP , 0 , 0 );
637
+ goto done ;
638
+ }
639
+ code = new_code ;
640
+ initial_instr = instr = _PyCode_CODE (code );
641
+ DPRINTF (2 ,
642
+ "Continuing in %s (%s:%d) at byte offset %d\n" ,
643
+ PyUnicode_AsUTF8 (code -> co_qualname ),
644
+ PyUnicode_AsUTF8 (code -> co_filename ),
645
+ code -> co_firstlineno ,
646
+ 2 * INSTR_IP (initial_instr , code ));
647
+ goto top ;
648
+ }
620
649
ADD_TO_TRACE (SAVE_IP , 0 , 0 );
621
650
goto done ;
622
651
}
0 commit comments