7272
7373/* Pseudo-instructions used in the compiler,
7474 * but turned into NOPs by the assembler. */
75- #define SETUP_FINALLY 255
76- #define SETUP_CLEANUP 254
77- #define SETUP_WITH 253
78- #define POP_BLOCK 252
79- #define JUMP 251
75+ #define SETUP_FINALLY -1
76+ #define SETUP_CLEANUP -2
77+ #define SETUP_WITH -3
78+ #define POP_BLOCK -4
79+ #define JUMP -5
80+
81+ #define MIN_VIRTUAL_OPCODE -5
82+ #define MAX_ALLOWED_OPCODE 254
83+
84+ #define IS_WITHIN_OPCODE_RANGE (opcode ) \
85+ ((opcode) >= MIN_VIRTUAL_OPCODE && (opcode) <= MAX_ALLOWED_OPCODE)
86+
87+ #define IS_VIRTUAL_OPCODE (opcode ) ((opcode) < 0)
8088
8189#define IS_TOP_LEVEL_AWAIT (c ) ( \
8290 (c->c_flags->cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \
8391 && (c->u->u_ste->ste_type == ModuleBlock))
8492
8593struct instr {
86- unsigned char i_opcode ;
94+ int i_opcode ;
8795 int i_oparg ;
8896 /* target block (if jump instruction) */
8997 struct basicblock_ * i_target ;
@@ -115,8 +123,13 @@ is_bit_set_in_table(const uint32_t *table, int bitindex) {
115123 * Word is indexed by (bitindex>>ln(size of int in bits)).
116124 * Bit within word is the low bits of bitindex.
117125 */
118- uint32_t word = table [bitindex >> LOG_BITS_PER_INT ];
119- return (word >> (bitindex & MASK_LOW_LOG_BITS )) & 1 ;
126+ if (bitindex >= 0 && bitindex < 256 ) {
127+ uint32_t word = table [bitindex >> LOG_BITS_PER_INT ];
128+ return (word >> (bitindex & MASK_LOW_LOG_BITS )) & 1 ;
129+ }
130+ else {
131+ return 0 ;
132+ }
120133}
121134
122135static inline int
@@ -125,18 +138,25 @@ is_relative_jump(struct instr *i)
125138 return is_bit_set_in_table (_PyOpcode_RelativeJump , i -> i_opcode );
126139}
127140
141+ static inline int
142+ is_block_push (struct instr * instr )
143+ {
144+ int opcode = instr -> i_opcode ;
145+ return opcode == SETUP_FINALLY || opcode == SETUP_WITH || opcode == SETUP_CLEANUP ;
146+ }
147+
128148static inline int
129149is_jump (struct instr * i )
130150{
131- return i -> i_opcode >= SETUP_WITH ||
132- i -> i_opcode == JUMP ||
151+ return i -> i_opcode == JUMP ||
133152 is_bit_set_in_table (_PyOpcode_Jump , i -> i_opcode );
134153}
135154
136155static int
137156instr_size (struct instr * instruction )
138157{
139158 int opcode = instruction -> i_opcode ;
159+ assert (!IS_VIRTUAL_OPCODE (opcode ));
140160 int oparg = HAS_ARG (opcode ) ? instruction -> i_oparg : 0 ;
141161 int extended_args = (0xFFFFFF < oparg ) + (0xFFFF < oparg ) + (0xFF < oparg );
142162 int caches = _PyOpcode_Caches [opcode ];
@@ -147,6 +167,7 @@ static void
147167write_instr (_Py_CODEUNIT * codestr , struct instr * instruction , int ilen )
148168{
149169 int opcode = instruction -> i_opcode ;
170+ assert (!IS_VIRTUAL_OPCODE (opcode ));
150171 int oparg = HAS_ARG (opcode ) ? instruction -> i_oparg : 0 ;
151172 int caches = _PyOpcode_Caches [opcode ];
152173 switch (ilen - caches ) {
@@ -1177,6 +1198,7 @@ static int
11771198compiler_addop_line (struct compiler * c , int opcode , int line ,
11781199 int end_line , int col_offset , int end_col_offset )
11791200{
1201+ assert (IS_WITHIN_OPCODE_RANGE (opcode ));
11801202 assert (!HAS_ARG (opcode ) || IS_ARTIFICIAL (opcode ));
11811203
11821204 if (compiler_use_new_implicit_block_if_needed (c ) < 0 ) {
@@ -1419,6 +1441,7 @@ compiler_addop_i_line(struct compiler *c, int opcode, Py_ssize_t oparg,
14191441 The argument of a concrete bytecode instruction is limited to 8-bit.
14201442 EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */
14211443
1444+ assert (IS_WITHIN_OPCODE_RANGE (opcode ));
14221445 assert (HAS_ARG (opcode ));
14231446 assert (0 <= oparg && oparg <= 2147483647 );
14241447
@@ -1462,7 +1485,8 @@ static int add_jump_to_block(struct compiler *c, int opcode,
14621485 int col_offset , int end_col_offset ,
14631486 basicblock * target )
14641487{
1465- assert (HAS_ARG (opcode ));
1488+ assert (IS_WITHIN_OPCODE_RANGE (opcode ));
1489+ assert (HAS_ARG (opcode ) || IS_VIRTUAL_OPCODE (opcode ));
14661490 assert (target != NULL );
14671491
14681492 if (compiler_use_new_implicit_block_if_needed (c ) < 0 ) {
@@ -7040,7 +7064,7 @@ stackdepth(struct compiler *c)
70407064 maxdepth = new_depth ;
70417065 }
70427066 assert (depth >= 0 ); /* invalid code or bug in stackdepth() */
7043- if (is_jump (instr )) {
7067+ if (is_jump (instr ) || is_block_push ( instr ) ) {
70447068 effect = stack_effect (instr -> i_opcode , instr -> i_oparg , 1 );
70457069 assert (effect != PY_INVALID_STACK_EFFECT );
70467070 int target_depth = depth + effect ;
@@ -7159,13 +7183,6 @@ assemble_emit_table_pair(struct assembler* a, PyObject** table, int* offset,
71597183 return 1 ;
71607184}
71617185
7162- static int
7163- is_block_push (struct instr * instr )
7164- {
7165- int opcode = instr -> i_opcode ;
7166- return opcode == SETUP_FINALLY || opcode == SETUP_WITH || opcode == SETUP_CLEANUP ;
7167- }
7168-
71697186static basicblock *
71707187push_except_block (ExceptStack * stack , struct instr * setup ) {
71717188 assert (is_block_push (setup ));
@@ -8600,6 +8617,7 @@ apply_static_swaps(basicblock *block, int i)
86008617static bool
86018618jump_thread (struct instr * inst , struct instr * target , int opcode )
86028619{
8620+ assert (!IS_VIRTUAL_OPCODE (opcode ) || opcode == JUMP );
86038621 assert (is_jump (inst ));
86048622 assert (is_jump (target ));
86058623 // bpo-45773: If inst->i_target == target->i_target, then nothing actually
@@ -8629,7 +8647,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
86298647 struct instr * inst = & bb -> b_instr [i ];
86308648 int oparg = inst -> i_oparg ;
86318649 int nextop = i + 1 < bb -> b_iused ? bb -> b_instr [i + 1 ].i_opcode : 0 ;
8632- if (is_jump (inst )) {
8650+ if (is_jump (inst ) || is_block_push ( inst ) ) {
86338651 /* Skip over empty basic blocks. */
86348652 while (inst -> i_target -> b_iused == 0 ) {
86358653 inst -> i_target = inst -> i_target -> b_next ;
@@ -8996,8 +9014,9 @@ mark_reachable(struct assembler *a) {
89969014 }
89979015 for (int i = 0 ; i < b -> b_iused ; i ++ ) {
89989016 basicblock * target ;
8999- if (is_jump (& b -> b_instr [i ])) {
9000- target = b -> b_instr [i ].i_target ;
9017+ struct instr * instr = & b -> b_instr [i ];
9018+ if (is_jump (instr ) || is_block_push (instr )) {
9019+ target = instr -> i_target ;
90019020 if (target -> b_predecessors == 0 ) {
90029021 * sp ++ = target ;
90039022 }
@@ -9073,13 +9092,6 @@ propagate_line_numbers(struct assembler *a) {
90739092 }
90749093 }
90759094 if (is_jump (& b -> b_instr [b -> b_iused - 1 ])) {
9076- switch (b -> b_instr [b -> b_iused - 1 ].i_opcode ) {
9077- /* Note: Only actual jumps, not exception handlers */
9078- case SETUP_WITH :
9079- case SETUP_FINALLY :
9080- case SETUP_CLEANUP :
9081- continue ;
9082- }
90839095 basicblock * target = b -> b_instr [b -> b_iused - 1 ].i_target ;
90849096 if (target -> b_predecessors == 1 ) {
90859097 if (target -> b_instr [0 ].i_lineno < 0 ) {
@@ -9205,13 +9217,6 @@ duplicate_exits_without_lineno(struct compiler *c)
92059217 */
92069218 for (basicblock * b = c -> u -> u_blocks ; b != NULL ; b = b -> b_list ) {
92079219 if (b -> b_iused > 0 && is_jump (& b -> b_instr [b -> b_iused - 1 ])) {
9208- switch (b -> b_instr [b -> b_iused - 1 ].i_opcode ) {
9209- /* Note: Only actual jumps, not exception handlers */
9210- case SETUP_WITH :
9211- case SETUP_FINALLY :
9212- case SETUP_CLEANUP :
9213- continue ;
9214- }
92159220 basicblock * target = b -> b_instr [b -> b_iused - 1 ].i_target ;
92169221 if (is_exit_without_lineno (target ) && target -> b_predecessors > 1 ) {
92179222 basicblock * new_target = compiler_copy_block (c , target );
0 commit comments