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