Skip to content

Commit d1b0297

Browse files
authored
gh-105481: add HAS_JUMP flag to opcode metadata (#105791)
1 parent 5ab13c5 commit d1b0297

File tree

8 files changed

+189
-168
lines changed

8 files changed

+189
-168
lines changed

Include/internal/pycore_opcode_utils.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ extern "C" {
2626
(opcode) == SETUP_CLEANUP)
2727

2828
#define HAS_TARGET(opcode) \
29-
(IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode))
29+
(OPCODE_HAS_JUMP(opcode) || IS_BLOCK_PUSH_OPCODE(opcode))
3030

3131
/* opcodes that must be last in the basicblock */
3232
#define IS_TERMINATOR_OPCODE(opcode) \
33-
(IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode))
33+
(OPCODE_HAS_JUMP(opcode) || IS_SCOPE_EXIT_OPCODE(opcode))
3434

3535
/* opcodes which are not emitted in codegen stage, only by the assembler */
3636
#define IS_ASSEMBLER_OPCODE(opcode) \

Python/bytecodes.c

+19-15
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ dummy_func(
430430
_Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
431431
ERROR_IF(*target_local == NULL, error);
432432
// The STORE_FAST is already done.
433-
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP + 1);
433+
SKIP_OVER(INLINE_CACHE_ENTRIES_BINARY_OP + 1);
434434
}
435435

436436
macro(BINARY_OP_INPLACE_ADD_UNICODE) =
@@ -557,7 +557,7 @@ dummy_func(
557557
STACK_SHRINK(2);
558558
new_frame->localsplus[0] = container;
559559
new_frame->localsplus[1] = sub;
560-
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
560+
SKIP_OVER(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
561561
frame->return_offset = 0;
562562
DISPATCH_INLINED(new_frame);
563563
}
@@ -879,7 +879,7 @@ dummy_func(
879879
gen->gi_frame_state = FRAME_EXECUTING;
880880
gen->gi_exc_state.previous_item = tstate->exc_info;
881881
tstate->exc_info = &gen->gi_exc_state;
882-
JUMPBY(INLINE_CACHE_ENTRIES_SEND);
882+
SKIP_OVER(INLINE_CACHE_ENTRIES_SEND);
883883
DISPATCH_INLINED(gen_frame);
884884
}
885885
if (Py_IsNone(v) && PyIter_Check(receiver)) {
@@ -918,7 +918,7 @@ dummy_func(
918918
gen->gi_frame_state = FRAME_EXECUTING;
919919
gen->gi_exc_state.previous_item = tstate->exc_info;
920920
tstate->exc_info = &gen->gi_exc_state;
921-
JUMPBY(INLINE_CACHE_ENTRIES_SEND);
921+
SKIP_OVER(INLINE_CACHE_ENTRIES_SEND);
922922
DISPATCH_INLINED(gen_frame);
923923
}
924924

@@ -1905,7 +1905,7 @@ dummy_func(
19051905
int shrink_stack = !(oparg & 1);
19061906
STACK_SHRINK(shrink_stack);
19071907
new_frame->localsplus[0] = owner;
1908-
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
1908+
SKIP_OVER(INLINE_CACHE_ENTRIES_LOAD_ATTR);
19091909
frame->return_offset = 0;
19101910
DISPATCH_INLINED(new_frame);
19111911
}
@@ -1933,7 +1933,7 @@ dummy_func(
19331933
STACK_SHRINK(shrink_stack);
19341934
new_frame->localsplus[0] = owner;
19351935
new_frame->localsplus[1] = Py_NewRef(name);
1936-
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
1936+
SKIP_OVER(INLINE_CACHE_ENTRIES_LOAD_ATTR);
19371937
frame->return_offset = 0;
19381938
DISPATCH_INLINED(new_frame);
19391939
}
@@ -2356,8 +2356,9 @@ dummy_func(
23562356
next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == INSTRUMENTED_END_FOR);
23572357
Py_DECREF(iter);
23582358
STACK_SHRINK(1);
2359+
SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
23592360
/* Jump forward oparg, then skip following END_FOR instruction */
2360-
JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
2361+
JUMPBY(oparg + 1);
23612362
DISPATCH();
23622363
}
23632364
// Common case: no jump, leave it to the code generator
@@ -2406,8 +2407,9 @@ dummy_func(
24062407
}
24072408
Py_DECREF(iter);
24082409
STACK_SHRINK(1);
2410+
SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
24092411
/* Jump forward oparg, then skip following END_FOR instruction */
2410-
JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
2412+
JUMPBY(oparg + 1);
24112413
DISPATCH();
24122414
end_for_iter_list:
24132415
// Common case: no jump, leave it to the code generator
@@ -2428,8 +2430,9 @@ dummy_func(
24282430
}
24292431
Py_DECREF(iter);
24302432
STACK_SHRINK(1);
2433+
SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
24312434
/* Jump forward oparg, then skip following END_FOR instruction */
2432-
JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
2435+
JUMPBY(oparg + 1);
24332436
DISPATCH();
24342437
end_for_iter_tuple:
24352438
// Common case: no jump, leave it to the code generator
@@ -2442,8 +2445,9 @@ dummy_func(
24422445
if (r->len <= 0) {
24432446
STACK_SHRINK(1);
24442447
Py_DECREF(r);
2448+
SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
24452449
// Jump over END_FOR instruction.
2446-
JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
2450+
JUMPBY(oparg + 1);
24472451
DISPATCH();
24482452
}
24492453
long value = r->start;
@@ -2467,7 +2471,7 @@ dummy_func(
24672471
gen->gi_frame_state = FRAME_EXECUTING;
24682472
gen->gi_exc_state.previous_item = tstate->exc_info;
24692473
tstate->exc_info = &gen->gi_exc_state;
2470-
JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER);
2474+
SKIP_OVER(INLINE_CACHE_ENTRIES_FOR_ITER);
24712475
assert(next_instr[oparg].op.code == END_FOR ||
24722476
next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
24732477
DISPATCH_INLINED(gen_frame);
@@ -2738,7 +2742,7 @@ dummy_func(
27382742
if (new_frame == NULL) {
27392743
goto error;
27402744
}
2741-
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
2745+
SKIP_OVER(INLINE_CACHE_ENTRIES_CALL);
27422746
frame->return_offset = 0;
27432747
DISPATCH_INLINED(new_frame);
27442748
}
@@ -2812,7 +2816,7 @@ dummy_func(
28122816
}
28132817
// Manipulate stack directly since we leave using DISPATCH_INLINED().
28142818
STACK_SHRINK(oparg + 2);
2815-
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
2819+
SKIP_OVER(INLINE_CACHE_ENTRIES_CALL);
28162820
frame->return_offset = 0;
28172821
DISPATCH_INLINED(new_frame);
28182822
}
@@ -2850,7 +2854,7 @@ dummy_func(
28502854
}
28512855
// Manipulate stack and cache directly since we leave using DISPATCH_INLINED().
28522856
STACK_SHRINK(oparg + 2);
2853-
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
2857+
SKIP_OVER(INLINE_CACHE_ENTRIES_CALL);
28542858
frame->return_offset = 0;
28552859
DISPATCH_INLINED(new_frame);
28562860
}
@@ -3093,7 +3097,7 @@ dummy_func(
30933097
Py_DECREF(method);
30943098
STACK_SHRINK(3);
30953099
// CALL + POP_TOP
3096-
JUMPBY(INLINE_CACHE_ENTRIES_CALL + 1);
3100+
SKIP_OVER(INLINE_CACHE_ENTRIES_CALL + 1);
30973101
assert(next_instr[-1].op.code == POP_TOP);
30983102
DISPATCH();
30993103
}

Python/ceval_macros.h

+6
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,13 @@ GETITEM(PyObject *v, Py_ssize_t i) {
145145
oparg = word.op.arg; \
146146
} while (0)
147147
#define JUMPTO(x) (next_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + (x))
148+
149+
/* JUMPBY makes the generator identify the instruction as a jump. SKIP_OVER is
150+
* for advancing to the next instruction, taking into account cache entries
151+
* and skipped instructions.
152+
*/
148153
#define JUMPBY(x) (next_instr += (x))
154+
#define SKIP_OVER(x) (next_instr += (x))
149155

150156
/* OpCode prediction macros
151157
Some opcodes tend to come in pairs thus making it possible to

Python/compile.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,11 @@ instr_sequence_use_label(instr_sequence *seq, int lbl) {
248248
static int
249249
instr_sequence_addop(instr_sequence *seq, int opcode, int oparg, location loc)
250250
{
251+
/* compare old and new opcode macros - use ! to compare as bools. */
251252
assert(!HAS_ARG(opcode) == !OPCODE_HAS_ARG(opcode));
252253
assert(!HAS_CONST(opcode) == !OPCODE_HAS_CONST(opcode));
254+
assert(!OPCODE_HAS_JUMP(opcode) == !OPCODE_HAS_JUMP(opcode));
255+
253256
assert(0 <= opcode && opcode <= MAX_OPCODE);
254257
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
255258
assert(IS_WITHIN_OPCODE_RANGE(opcode));
@@ -1114,7 +1117,7 @@ codegen_addop_j(instr_sequence *seq, location loc,
11141117
int opcode, jump_target_label target)
11151118
{
11161119
assert(IS_LABEL(target));
1117-
assert(IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode));
1120+
assert(OPCODE_HAS_JUMP(opcode) || IS_BLOCK_PUSH_OPCODE(opcode));
11181121
assert(!IS_ASSEMBLER_OPCODE(opcode));
11191122
return instr_sequence_addop(seq, opcode, target.id, loc);
11201123
}

Python/flowgraph.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ is_block_push(cfg_instr *i)
4545
static inline int
4646
is_jump(cfg_instr *i)
4747
{
48-
return IS_JUMP_OPCODE(i->i_opcode);
48+
assert(!OPCODE_HAS_JUMP(i->i_opcode) == !IS_JUMP_OPCODE(i->i_opcode));
49+
return OPCODE_HAS_JUMP(i->i_opcode);
4950
}
5051

5152
/* One arg*/

0 commit comments

Comments
 (0)