@@ -503,8 +503,7 @@ add_to_trace(
503
503
if (trace_stack_depth >= TRACE_STACK_SIZE) { \
504
504
DPRINTF(2, "Trace stack overflow\n"); \
505
505
OPT_STAT_INC(trace_stack_overflow); \
506
- trace_length = 0; \
507
- goto done; \
506
+ return 0; \
508
507
} \
509
508
assert(func == NULL || func->func_code == (PyObject *)code); \
510
509
trace_stack[trace_stack_depth].func = func; \
@@ -550,6 +549,7 @@ translate_bytecode_to_trace(
550
549
} trace_stack [TRACE_STACK_SIZE ];
551
550
int trace_stack_depth = 0 ;
552
551
int confidence = CONFIDENCE_RANGE ; // Adjusted by branch instructions
552
+ bool jump_seen = false;
553
553
554
554
#ifdef Py_DEBUG
555
555
char * python_lltrace = Py_GETENV ("PYTHON_LLTRACE" );
@@ -568,7 +568,6 @@ translate_bytecode_to_trace(
568
568
ADD_TO_TRACE (_START_EXECUTOR , 0 , (uintptr_t )instr , INSTR_IP (instr , code ));
569
569
uint32_t target = 0 ;
570
570
571
- top : // Jump here after _PUSH_FRAME or likely branches
572
571
for (;;) {
573
572
target = INSTR_IP (instr , code );
574
573
// Need space for _DEOPT
@@ -577,6 +576,13 @@ translate_bytecode_to_trace(
577
576
uint32_t opcode = instr -> op .code ;
578
577
uint32_t oparg = instr -> op .arg ;
579
578
579
+ if (!progress_needed && instr == initial_instr ) {
580
+ // We have looped around to the start:
581
+ RESERVE (1 );
582
+ ADD_TO_TRACE (_JUMP_TO_TOP , 0 , 0 , 0 );
583
+ goto done ;
584
+ }
585
+
580
586
DPRINTF (2 , "%d: %s(%d)\n" , target , _PyOpcode_OpName [opcode ], oparg );
581
587
582
588
if (opcode == ENTER_EXECUTOR ) {
@@ -603,30 +609,21 @@ translate_bytecode_to_trace(
603
609
/* Special case the first instruction,
604
610
* so that we can guarantee forward progress */
605
611
if (progress_needed ) {
606
- progress_needed = false;
607
- if (opcode == JUMP_BACKWARD || opcode == JUMP_BACKWARD_NO_INTERRUPT ) {
608
- instr += 1 + _PyOpcode_Caches [opcode ] - (int32_t )oparg ;
609
- initial_instr = instr ;
610
- if (opcode == JUMP_BACKWARD ) {
611
- ADD_TO_TRACE (_TIER2_RESUME_CHECK , 0 , 0 , target );
612
- }
613
- continue ;
614
- }
615
- else {
616
- if (OPCODE_HAS_EXIT (opcode ) || OPCODE_HAS_DEOPT (opcode )) {
617
- opcode = _PyOpcode_Deopt [opcode ];
618
- }
619
- assert (!OPCODE_HAS_EXIT (opcode ));
620
- assert (!OPCODE_HAS_DEOPT (opcode ));
612
+ if (OPCODE_HAS_EXIT (opcode ) || OPCODE_HAS_DEOPT (opcode )) {
613
+ opcode = _PyOpcode_Deopt [opcode ];
621
614
}
615
+ assert (!OPCODE_HAS_EXIT (opcode ));
616
+ assert (!OPCODE_HAS_DEOPT (opcode ));
622
617
}
623
618
624
619
if (OPCODE_HAS_EXIT (opcode )) {
625
- // Make space for exit code
620
+ // Make space for side exit and final _EXIT_TRACE:
621
+ RESERVE_RAW (2 , "_EXIT_TRACE" );
626
622
max_length -- ;
627
623
}
628
624
if (OPCODE_HAS_ERROR (opcode )) {
629
- // Make space for error code
625
+ // Make space for error stub and final _EXIT_TRACE:
626
+ RESERVE_RAW (2 , "_ERROR_POP_N" );
630
627
max_length -- ;
631
628
}
632
629
switch (opcode ) {
@@ -672,19 +669,18 @@ translate_bytecode_to_trace(
672
669
}
673
670
674
671
case JUMP_BACKWARD :
672
+ ADD_TO_TRACE (_CHECK_PERIODIC , 0 , 0 , target );
673
+ _Py_FALLTHROUGH ;
675
674
case JUMP_BACKWARD_NO_INTERRUPT :
676
675
{
677
- _Py_CODEUNIT * target = instr + 1 + _PyOpcode_Caches [opcode ] - (int )oparg ;
678
- if (target == initial_instr ) {
679
- /* We have looped round to the start */
680
- RESERVE (1 );
681
- ADD_TO_TRACE (_JUMP_TO_TOP , 0 , 0 , 0 );
682
- }
683
- else {
676
+ instr += 1 + _PyOpcode_Caches [_PyOpcode_Deopt [opcode ]] - (int )oparg ;
677
+ if (jump_seen ) {
684
678
OPT_STAT_INC (inner_loop );
685
679
DPRINTF (2 , "JUMP_BACKWARD not to top ends trace\n" );
680
+ goto done ;
686
681
}
687
- goto done ;
682
+ jump_seen = true;
683
+ goto top ;
688
684
}
689
685
690
686
case JUMP_FORWARD :
@@ -904,23 +900,25 @@ translate_bytecode_to_trace(
904
900
assert (instr -> op .code == POP_TOP );
905
901
instr ++ ;
906
902
}
903
+ top :
904
+ // Jump here after _PUSH_FRAME or likely branches.
905
+ progress_needed = false;
907
906
} // End for (;;)
908
907
909
908
done :
910
909
while (trace_stack_depth > 0 ) {
911
910
TRACE_STACK_POP ();
912
911
}
913
912
assert (code == initial_code );
914
- // Skip short traces like _SET_IP, LOAD_FAST, _SET_IP, _EXIT_TRACE
915
- if (progress_needed || trace_length < 5 ) {
913
+ // Skip short traces where we can't even translate a single instruction:
914
+ if (progress_needed ) {
916
915
OPT_STAT_INC (trace_too_short );
917
916
DPRINTF (2 ,
918
- "No trace for %s (%s:%d) at byte offset %d (%s )\n" ,
917
+ "No trace for %s (%s:%d) at byte offset %d (no progress )\n" ,
919
918
PyUnicode_AsUTF8 (code -> co_qualname ),
920
919
PyUnicode_AsUTF8 (code -> co_filename ),
921
920
code -> co_firstlineno ,
922
- 2 * INSTR_IP (initial_instr , code ),
923
- progress_needed ? "no progress" : "too short" );
921
+ 2 * INSTR_IP (initial_instr , code ));
924
922
return 0 ;
925
923
}
926
924
if (trace [trace_length - 1 ].opcode != _JUMP_TO_TOP ) {
0 commit comments