23
23
24
24
#define MAX_EXECUTORS_SIZE 256
25
25
26
+ #ifdef Py_DEBUG
27
+ static int
28
+ base_opcode (PyCodeObject * code , int offset )
29
+ {
30
+ int opcode = _Py_GetBaseOpcode (code , offset );
31
+ if (opcode == ENTER_EXECUTOR ) {
32
+ int oparg = _PyCode_CODE (code )[offset ].op .arg ;
33
+ _PyExecutorObject * ex = code -> co_executors -> executors [oparg ];
34
+ return ex -> vm_data .opcode ;
35
+ }
36
+ return opcode ;
37
+ }
38
+ #endif
26
39
27
40
static bool
28
41
has_space_for_executor (PyCodeObject * code , _Py_CODEUNIT * instr )
@@ -445,6 +458,14 @@ _PyUOp_Replacements[MAX_UOP_ID + 1] = {
445
458
[_FOR_ITER ] = _FOR_ITER_TIER_TWO ,
446
459
};
447
460
461
+ static const uint8_t
462
+ is_for_iter_test [MAX_UOP_ID + 1 ] = {
463
+ [_GUARD_NOT_EXHAUSTED_RANGE ] = 1 ,
464
+ [_GUARD_NOT_EXHAUSTED_LIST ] = 1 ,
465
+ [_GUARD_NOT_EXHAUSTED_TUPLE ] = 1 ,
466
+ [_FOR_ITER_TIER_TWO ] = 1 ,
467
+ };
468
+
448
469
static const uint16_t
449
470
BRANCH_TO_GUARD [4 ][2 ] = {
450
471
[POP_JUMP_IF_FALSE - POP_JUMP_IF_FALSE ][0 ] = _GUARD_IS_TRUE_POP ,
@@ -594,7 +615,6 @@ translate_bytecode_to_trace(
594
615
595
616
uint32_t opcode = instr -> op .code ;
596
617
uint32_t oparg = instr -> op .arg ;
597
- uint32_t extended = 0 ;
598
618
599
619
DPRINTF (2 , "%d: %s(%d)\n" , target , _PyOpcode_OpName [opcode ], oparg );
600
620
@@ -608,7 +628,6 @@ translate_bytecode_to_trace(
608
628
609
629
if (opcode == EXTENDED_ARG ) {
610
630
instr ++ ;
611
- extended = 1 ;
612
631
opcode = instr -> op .code ;
613
632
oparg = (oparg << 8 ) | instr -> op .arg ;
614
633
if (opcode == EXTENDED_ARG ) {
@@ -772,12 +791,15 @@ translate_bytecode_to_trace(
772
791
case OPARG_REPLACED :
773
792
uop = _PyUOp_Replacements [uop ];
774
793
assert (uop != 0 );
775
- if (uop == _FOR_ITER_TIER_TWO ) {
776
- target += 1 + INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 2 + extended ;
777
- assert (_PyCode_CODE (code )[target - 2 ].op .code == END_FOR ||
778
- _PyCode_CODE (code )[target - 2 ].op .code == INSTRUMENTED_END_FOR );
779
- assert (_PyCode_CODE (code )[target - 1 ].op .code == POP_TOP );
794
+ #ifdef Py_DEBUG
795
+ {
796
+ uint32_t next_inst = target + 1 + INLINE_CACHE_ENTRIES_FOR_ITER + (oparg > 255 );
797
+ uint32_t jump_target = next_inst + oparg ;
798
+ assert (base_opcode (code , jump_target ) == END_FOR ||
799
+ base_opcode (code , jump_target ) == INSTRUMENTED_END_FOR );
800
+ assert (base_opcode (code , jump_target + 1 ) == POP_TOP );
780
801
}
802
+ #endif
781
803
break ;
782
804
default :
783
805
fprintf (stderr ,
@@ -1000,10 +1022,18 @@ prepare_for_execution(_PyUOpInstruction *buffer, int length)
1000
1022
if (_PyUop_Flags [opcode ] & (HAS_EXIT_FLAG | HAS_DEOPT_FLAG )) {
1001
1023
uint16_t exit_op = (_PyUop_Flags [opcode ] & HAS_EXIT_FLAG ) ?
1002
1024
_SIDE_EXIT : _DEOPT ;
1003
- if (target != current_jump_target || current_exit_op != exit_op ) {
1004
- make_exit (& buffer [next_spare ], exit_op , target );
1025
+ int32_t jump_target = target ;
1026
+ if (is_for_iter_test [opcode ]) {
1027
+ /* Target the POP_TOP immediately after the END_FOR,
1028
+ * leaving only the iterator on the stack. */
1029
+ int extended_arg = inst -> oparg > 255 ;
1030
+ int32_t next_inst = target + 1 + INLINE_CACHE_ENTRIES_FOR_ITER + extended_arg ;
1031
+ jump_target = next_inst + inst -> oparg + 1 ;
1032
+ }
1033
+ if (jump_target != current_jump_target || current_exit_op != exit_op ) {
1034
+ make_exit (& buffer [next_spare ], exit_op , jump_target );
1005
1035
current_exit_op = exit_op ;
1006
- current_jump_target = target ;
1036
+ current_jump_target = jump_target ;
1007
1037
current_jump = next_spare ;
1008
1038
next_spare ++ ;
1009
1039
}
0 commit comments