bpo-41463: Generate information about jumps from 'opcode.py' rather than duplicating it in 'compile.c' (GH-21714)

Generate information about jumps from 'opcode.py' rather than duplicate it in 'compile.c'
This commit is contained in:
Mark Shannon 2020-08-04 17:30:11 +01:00 committed by GitHub
parent c7decc27d5
commit 582aaf19e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 114 additions and 59 deletions

22
Include/opcode.h generated
View File

@ -127,6 +127,28 @@ extern "C" {
#define SET_UPDATE 163 #define SET_UPDATE 163
#define DICT_MERGE 164 #define DICT_MERGE 164
#define DICT_UPDATE 165 #define DICT_UPDATE 165
#ifdef NEED_OPCODE_JUMP_TABLES
static uint32_t _PyOpcode_RelativeJump[8] = {
0U,
0U,
536870912U,
67125248U,
67141632U,
0U,
0U,
0U,
};
static uint32_t _PyOpcode_Jump[8] = {
0U,
0U,
536870912U,
101695488U,
67141632U,
0U,
0U,
0U,
};
#endif /* OPCODE_TABLES */
/* EXCEPT_HANDLER is a special, implicit block type which is created when /* EXCEPT_HANDLER is a special, implicit block type which is created when
entering an except handler. It is not an opcode but we define it here entering an except handler. It is not an opcode but we define it here

View File

@ -27,6 +27,7 @@
#include "ast.h" #include "ast.h"
#include "code.h" #include "code.h"
#include "symtable.h" #include "symtable.h"
#define NEED_OPCODE_JUMP_TABLES
#include "opcode.h" #include "opcode.h"
#include "wordcode_helpers.h" #include "wordcode_helpers.h"
@ -45,14 +46,38 @@
&& (c->u->u_ste->ste_type == ModuleBlock)) && (c->u->u_ste->ste_type == ModuleBlock))
struct instr { struct instr {
unsigned i_jabs : 1;
unsigned i_jrel : 1;
unsigned char i_opcode; unsigned char i_opcode;
int i_oparg; int i_oparg;
struct basicblock_ *i_target; /* target block (if jump instruction) */ struct basicblock_ *i_target; /* target block (if jump instruction) */
int i_lineno; int i_lineno;
}; };
#define LOG_BITS_PER_INT 5
#define MASK_LOW_LOG_BITS 31
static inline int
is_bit_set_in_table(uint32_t *table, int bitindex) {
/* Is the relevant bit set in the relevant word? */
/* 256 bits fit into 8 32-bits words.
* Word is indexed by (bitindex>>ln(size of int in bits)).
* Bit within word is the low bits of bitindex.
*/
uint32_t word = table[bitindex >> LOG_BITS_PER_INT];
return (word >> (bitindex & MASK_LOW_LOG_BITS)) & 1;
}
static inline int
is_relative_jump(struct instr *i)
{
return is_bit_set_in_table(_PyOpcode_RelativeJump, i->i_opcode);
}
static inline int
is_jump(struct instr *i)
{
return is_bit_set_in_table(_PyOpcode_Jump, i->i_opcode);
}
typedef struct basicblock_ { typedef struct basicblock_ {
/* Each basicblock in a compilation unit is linked via b_list in the /* Each basicblock in a compilation unit is linked via b_list in the
reverse order that the block are allocated. b_list points to the next reverse order that the block are allocated. b_list points to the next
@ -182,7 +207,7 @@ static basicblock *compiler_new_block(struct compiler *);
static int compiler_next_instr(basicblock *); static int compiler_next_instr(basicblock *);
static int compiler_addop(struct compiler *, int); static int compiler_addop(struct compiler *, int);
static int compiler_addop_i(struct compiler *, int, Py_ssize_t); static int compiler_addop_i(struct compiler *, int, Py_ssize_t);
static int compiler_addop_j(struct compiler *, int, basicblock *, int); static int compiler_addop_j(struct compiler *, int, basicblock *);
static int compiler_error(struct compiler *, const char *); static int compiler_error(struct compiler *, const char *);
static int compiler_warn(struct compiler *, const char *, ...); static int compiler_warn(struct compiler *, const char *, ...);
static int compiler_nameop(struct compiler *, identifier, expr_context_ty); static int compiler_nameop(struct compiler *, identifier, expr_context_ty);
@ -1381,7 +1406,7 @@ compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg)
} }
static int static int
compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) compiler_addop_j(struct compiler *c, int opcode, basicblock *b)
{ {
struct instr *i; struct instr *i;
int off; int off;
@ -1398,10 +1423,6 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
i = &c->u->u_curblock->b_instr[off]; i = &c->u->u_curblock->b_instr[off];
i->i_opcode = opcode; i->i_opcode = opcode;
i->i_target = b; i->i_target = b;
if (absolute)
i->i_jabs = 1;
else
i->i_jrel = 1;
i->i_lineno = c->u->u_lineno; i->i_lineno = c->u->u_lineno;
return 1; return 1;
} }
@ -1471,17 +1492,11 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
return 0; \ return 0; \
} }
#define ADDOP_JABS(C, OP, O) { \ #define ADDOP_JUMP(C, OP, O) { \
if (!compiler_addop_j((C), (OP), (O), 1)) \ if (!compiler_addop_j((C), (OP), (O))) \
return 0; \ return 0; \
} }
#define ADDOP_JREL(C, OP, O) { \
if (!compiler_addop_j((C), (OP), (O), 0)) \
return 0; \
}
#define ADDOP_COMPARE(C, CMP) { \ #define ADDOP_COMPARE(C, CMP) { \
if (!compiler_addcompare((C), (cmpop_ty)(CMP))) \ if (!compiler_addcompare((C), (cmpop_ty)(CMP))) \
return 0; \ return 0; \
@ -2545,7 +2560,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
return 0; return 0;
if (!compiler_jump_if(c, e->v.IfExp.body, next, cond)) if (!compiler_jump_if(c, e->v.IfExp.body, next, cond))
return 0; return 0;
ADDOP_JREL(c, JUMP_FORWARD, end); ADDOP_JUMP(c, JUMP_FORWARD, end);
compiler_use_next_block(c, next2); compiler_use_next_block(c, next2);
if (!compiler_jump_if(c, e->v.IfExp.orelse, next, cond)) if (!compiler_jump_if(c, e->v.IfExp.orelse, next, cond))
return 0; return 0;
@ -2568,20 +2583,20 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
ADDOP(c, DUP_TOP); ADDOP(c, DUP_TOP);
ADDOP(c, ROT_THREE); ADDOP(c, ROT_THREE);
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i)); ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
ADDOP_JABS(c, POP_JUMP_IF_FALSE, cleanup); ADDOP_JUMP(c, POP_JUMP_IF_FALSE, cleanup);
NEXT_BLOCK(c); NEXT_BLOCK(c);
} }
VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n)); VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, n)); ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, n));
ADDOP_JABS(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next); ADDOP_JUMP(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
basicblock *end = compiler_new_block(c); basicblock *end = compiler_new_block(c);
if (end == NULL) if (end == NULL)
return 0; return 0;
ADDOP_JREL(c, JUMP_FORWARD, end); ADDOP_JUMP(c, JUMP_FORWARD, end);
compiler_use_next_block(c, cleanup); compiler_use_next_block(c, cleanup);
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
if (!cond) { if (!cond) {
ADDOP_JREL(c, JUMP_FORWARD, next); ADDOP_JUMP(c, JUMP_FORWARD, next);
} }
compiler_use_next_block(c, end); compiler_use_next_block(c, end);
return 1; return 1;
@ -2596,7 +2611,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
/* general implementation */ /* general implementation */
VISIT(c, expr, e); VISIT(c, expr, e);
ADDOP_JABS(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next); ADDOP_JUMP(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
return 1; return 1;
} }
@ -2615,7 +2630,7 @@ compiler_ifexp(struct compiler *c, expr_ty e)
if (!compiler_jump_if(c, e->v.IfExp.test, next, 0)) if (!compiler_jump_if(c, e->v.IfExp.test, next, 0))
return 0; return 0;
VISIT(c, expr, e->v.IfExp.body); VISIT(c, expr, e->v.IfExp.body);
ADDOP_JREL(c, JUMP_FORWARD, end); ADDOP_JUMP(c, JUMP_FORWARD, end);
compiler_use_next_block(c, next); compiler_use_next_block(c, next);
VISIT(c, expr, e->v.IfExp.orelse); VISIT(c, expr, e->v.IfExp.orelse);
compiler_use_next_block(c, end); compiler_use_next_block(c, end);
@ -2721,7 +2736,7 @@ compiler_if(struct compiler *c, stmt_ty s)
} }
VISIT_SEQ(c, stmt, s->v.If.body); VISIT_SEQ(c, stmt, s->v.If.body);
if (asdl_seq_LEN(s->v.If.orelse)) { if (asdl_seq_LEN(s->v.If.orelse)) {
ADDOP_JREL(c, JUMP_FORWARD, end); ADDOP_JUMP(c, JUMP_FORWARD, end);
compiler_use_next_block(c, next); compiler_use_next_block(c, next);
VISIT_SEQ(c, stmt, s->v.If.orelse); VISIT_SEQ(c, stmt, s->v.If.orelse);
} }
@ -2747,10 +2762,10 @@ compiler_for(struct compiler *c, stmt_ty s)
VISIT(c, expr, s->v.For.iter); VISIT(c, expr, s->v.For.iter);
ADDOP(c, GET_ITER); ADDOP(c, GET_ITER);
compiler_use_next_block(c, start); compiler_use_next_block(c, start);
ADDOP_JREL(c, FOR_ITER, cleanup); ADDOP_JUMP(c, FOR_ITER, cleanup);
VISIT(c, expr, s->v.For.target); VISIT(c, expr, s->v.For.target);
VISIT_SEQ(c, stmt, s->v.For.body); VISIT_SEQ(c, stmt, s->v.For.body);
ADDOP_JABS(c, JUMP_ABSOLUTE, start); ADDOP_JUMP(c, JUMP_ABSOLUTE, start);
compiler_use_next_block(c, cleanup); compiler_use_next_block(c, cleanup);
compiler_pop_fblock(c, FOR_LOOP, start); compiler_pop_fblock(c, FOR_LOOP, start);
@ -2786,7 +2801,7 @@ compiler_async_for(struct compiler *c, stmt_ty s)
return 0; return 0;
} }
/* SETUP_FINALLY to guard the __anext__ call */ /* SETUP_FINALLY to guard the __anext__ call */
ADDOP_JREL(c, SETUP_FINALLY, except); ADDOP_JUMP(c, SETUP_FINALLY, except);
ADDOP(c, GET_ANEXT); ADDOP(c, GET_ANEXT);
ADDOP_LOAD_CONST(c, Py_None); ADDOP_LOAD_CONST(c, Py_None);
ADDOP(c, YIELD_FROM); ADDOP(c, YIELD_FROM);
@ -2795,7 +2810,7 @@ compiler_async_for(struct compiler *c, stmt_ty s)
/* Success block for __anext__ */ /* Success block for __anext__ */
VISIT(c, expr, s->v.AsyncFor.target); VISIT(c, expr, s->v.AsyncFor.target);
VISIT_SEQ(c, stmt, s->v.AsyncFor.body); VISIT_SEQ(c, stmt, s->v.AsyncFor.body);
ADDOP_JABS(c, JUMP_ABSOLUTE, start); ADDOP_JUMP(c, JUMP_ABSOLUTE, start);
compiler_pop_fblock(c, FOR_LOOP, start); compiler_pop_fblock(c, FOR_LOOP, start);
@ -2859,7 +2874,7 @@ compiler_while(struct compiler *c, stmt_ty s)
return 0; return 0;
} }
VISIT_SEQ(c, stmt, s->v.While.body); VISIT_SEQ(c, stmt, s->v.While.body);
ADDOP_JABS(c, JUMP_ABSOLUTE, loop); ADDOP_JUMP(c, JUMP_ABSOLUTE, loop);
/* XXX should the two POP instructions be in a separate block /* XXX should the two POP instructions be in a separate block
if there is no else clause ? if there is no else clause ?
@ -2918,7 +2933,7 @@ compiler_break(struct compiler *c)
if (!compiler_unwind_fblock(c, loop, 0)) { if (!compiler_unwind_fblock(c, loop, 0)) {
return 0; return 0;
} }
ADDOP_JABS(c, JUMP_ABSOLUTE, loop->fb_exit); ADDOP_JUMP(c, JUMP_ABSOLUTE, loop->fb_exit);
return 1; return 1;
} }
@ -2932,7 +2947,7 @@ compiler_continue(struct compiler *c)
if (loop == NULL) { if (loop == NULL) {
return compiler_error(c, "'continue' not properly in loop"); return compiler_error(c, "'continue' not properly in loop");
} }
ADDOP_JABS(c, JUMP_ABSOLUTE, loop->fb_block); ADDOP_JUMP(c, JUMP_ABSOLUTE, loop->fb_block);
return 1; return 1;
} }
@ -2978,7 +2993,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
return 0; return 0;
/* `try` block */ /* `try` block */
ADDOP_JREL(c, SETUP_FINALLY, end); ADDOP_JUMP(c, SETUP_FINALLY, end);
compiler_use_next_block(c, body); compiler_use_next_block(c, body);
if (!compiler_push_fblock(c, FINALLY_TRY, body, end, s->v.Try.finalbody)) if (!compiler_push_fblock(c, FINALLY_TRY, body, end, s->v.Try.finalbody))
return 0; return 0;
@ -2992,7 +3007,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
ADDOP(c, POP_BLOCK); ADDOP(c, POP_BLOCK);
compiler_pop_fblock(c, FINALLY_TRY, body); compiler_pop_fblock(c, FINALLY_TRY, body);
VISIT_SEQ(c, stmt, s->v.Try.finalbody); VISIT_SEQ(c, stmt, s->v.Try.finalbody);
ADDOP_JREL(c, JUMP_FORWARD, exit); ADDOP_JUMP(c, JUMP_FORWARD, exit);
/* `finally` block */ /* `finally` block */
compiler_use_next_block(c, end); compiler_use_next_block(c, end);
if (!compiler_push_fblock(c, FINALLY_END, end, NULL, NULL)) if (!compiler_push_fblock(c, FINALLY_END, end, NULL, NULL))
@ -3046,14 +3061,14 @@ compiler_try_except(struct compiler *c, stmt_ty s)
end = compiler_new_block(c); end = compiler_new_block(c);
if (body == NULL || except == NULL || orelse == NULL || end == NULL) if (body == NULL || except == NULL || orelse == NULL || end == NULL)
return 0; return 0;
ADDOP_JREL(c, SETUP_FINALLY, except); ADDOP_JUMP(c, SETUP_FINALLY, except);
compiler_use_next_block(c, body); compiler_use_next_block(c, body);
if (!compiler_push_fblock(c, EXCEPT, body, NULL, NULL)) if (!compiler_push_fblock(c, EXCEPT, body, NULL, NULL))
return 0; return 0;
VISIT_SEQ(c, stmt, s->v.Try.body); VISIT_SEQ(c, stmt, s->v.Try.body);
ADDOP(c, POP_BLOCK); ADDOP(c, POP_BLOCK);
compiler_pop_fblock(c, EXCEPT, body); compiler_pop_fblock(c, EXCEPT, body);
ADDOP_JREL(c, JUMP_FORWARD, orelse); ADDOP_JUMP(c, JUMP_FORWARD, orelse);
n = asdl_seq_LEN(s->v.Try.handlers); n = asdl_seq_LEN(s->v.Try.handlers);
compiler_use_next_block(c, except); compiler_use_next_block(c, except);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
@ -3068,7 +3083,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
if (handler->v.ExceptHandler.type) { if (handler->v.ExceptHandler.type) {
ADDOP(c, DUP_TOP); ADDOP(c, DUP_TOP);
VISIT(c, expr, handler->v.ExceptHandler.type); VISIT(c, expr, handler->v.ExceptHandler.type);
ADDOP_JABS(c, JUMP_IF_NOT_EXC_MATCH, except); ADDOP_JUMP(c, JUMP_IF_NOT_EXC_MATCH, except);
} }
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
if (handler->v.ExceptHandler.name) { if (handler->v.ExceptHandler.name) {
@ -3095,7 +3110,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
*/ */
/* second try: */ /* second try: */
ADDOP_JREL(c, SETUP_FINALLY, cleanup_end); ADDOP_JUMP(c, SETUP_FINALLY, cleanup_end);
compiler_use_next_block(c, cleanup_body); compiler_use_next_block(c, cleanup_body);
if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, handler->v.ExceptHandler.name)) if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, handler->v.ExceptHandler.name))
return 0; return 0;
@ -3109,7 +3124,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
ADDOP_LOAD_CONST(c, Py_None); ADDOP_LOAD_CONST(c, Py_None);
compiler_nameop(c, handler->v.ExceptHandler.name, Store); compiler_nameop(c, handler->v.ExceptHandler.name, Store);
compiler_nameop(c, handler->v.ExceptHandler.name, Del); compiler_nameop(c, handler->v.ExceptHandler.name, Del);
ADDOP_JREL(c, JUMP_FORWARD, end); ADDOP_JUMP(c, JUMP_FORWARD, end);
/* except: */ /* except: */
compiler_use_next_block(c, cleanup_end); compiler_use_next_block(c, cleanup_end);
@ -3136,7 +3151,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body);
compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body); compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body);
ADDOP(c, POP_EXCEPT); ADDOP(c, POP_EXCEPT);
ADDOP_JREL(c, JUMP_FORWARD, end); ADDOP_JUMP(c, JUMP_FORWARD, end);
} }
compiler_use_next_block(c, except); compiler_use_next_block(c, except);
} }
@ -3645,7 +3660,7 @@ compiler_boolop(struct compiler *c, expr_ty e)
assert(n >= 0); assert(n >= 0);
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i)); VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i));
ADDOP_JABS(c, jumpi, end); ADDOP_JUMP(c, jumpi, end);
basicblock *next = compiler_new_block(c); basicblock *next = compiler_new_block(c);
if (next == NULL) { if (next == NULL) {
return 0; return 0;
@ -3933,7 +3948,7 @@ compiler_compare(struct compiler *c, expr_ty e)
ADDOP(c, DUP_TOP); ADDOP(c, DUP_TOP);
ADDOP(c, ROT_THREE); ADDOP(c, ROT_THREE);
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i)); ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
ADDOP_JABS(c, JUMP_IF_FALSE_OR_POP, cleanup); ADDOP_JUMP(c, JUMP_IF_FALSE_OR_POP, cleanup);
NEXT_BLOCK(c); NEXT_BLOCK(c);
} }
VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n)); VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));
@ -3941,7 +3956,7 @@ compiler_compare(struct compiler *c, expr_ty e)
basicblock *end = compiler_new_block(c); basicblock *end = compiler_new_block(c);
if (end == NULL) if (end == NULL)
return 0; return 0;
ADDOP_JREL(c, JUMP_FORWARD, end); ADDOP_JUMP(c, JUMP_FORWARD, end);
compiler_use_next_block(c, cleanup); compiler_use_next_block(c, cleanup);
ADDOP(c, ROT_TWO); ADDOP(c, ROT_TWO);
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
@ -4435,7 +4450,7 @@ compiler_sync_comprehension_generator(struct compiler *c,
if (start) { if (start) {
depth++; depth++;
compiler_use_next_block(c, start); compiler_use_next_block(c, start);
ADDOP_JREL(c, FOR_ITER, anchor); ADDOP_JUMP(c, FOR_ITER, anchor);
NEXT_BLOCK(c); NEXT_BLOCK(c);
} }
VISIT(c, expr, gen->target); VISIT(c, expr, gen->target);
@ -4487,7 +4502,7 @@ compiler_sync_comprehension_generator(struct compiler *c,
} }
compiler_use_next_block(c, if_cleanup); compiler_use_next_block(c, if_cleanup);
if (start) { if (start) {
ADDOP_JABS(c, JUMP_ABSOLUTE, start); ADDOP_JUMP(c, JUMP_ABSOLUTE, start);
compiler_use_next_block(c, anchor); compiler_use_next_block(c, anchor);
} }
@ -4526,7 +4541,7 @@ compiler_async_comprehension_generator(struct compiler *c,
compiler_use_next_block(c, start); compiler_use_next_block(c, start);
ADDOP_JREL(c, SETUP_FINALLY, except); ADDOP_JUMP(c, SETUP_FINALLY, except);
ADDOP(c, GET_ANEXT); ADDOP(c, GET_ANEXT);
ADDOP_LOAD_CONST(c, Py_None); ADDOP_LOAD_CONST(c, Py_None);
ADDOP(c, YIELD_FROM); ADDOP(c, YIELD_FROM);
@ -4577,7 +4592,7 @@ compiler_async_comprehension_generator(struct compiler *c,
} }
} }
compiler_use_next_block(c, if_cleanup); compiler_use_next_block(c, if_cleanup);
ADDOP_JABS(c, JUMP_ABSOLUTE, start); ADDOP_JUMP(c, JUMP_ABSOLUTE, start);
compiler_use_next_block(c, except); compiler_use_next_block(c, except);
ADDOP(c, END_ASYNC_FOR); ADDOP(c, END_ASYNC_FOR);
@ -4773,7 +4788,7 @@ compiler_with_except_finish(struct compiler *c) {
exit = compiler_new_block(c); exit = compiler_new_block(c);
if (exit == NULL) if (exit == NULL)
return 0; return 0;
ADDOP_JABS(c, POP_JUMP_IF_TRUE, exit); ADDOP_JUMP(c, POP_JUMP_IF_TRUE, exit);
ADDOP(c, RERAISE); ADDOP(c, RERAISE);
compiler_use_next_block(c, exit); compiler_use_next_block(c, exit);
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
@ -4835,7 +4850,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
ADDOP_LOAD_CONST(c, Py_None); ADDOP_LOAD_CONST(c, Py_None);
ADDOP(c, YIELD_FROM); ADDOP(c, YIELD_FROM);
ADDOP_JREL(c, SETUP_ASYNC_WITH, final); ADDOP_JUMP(c, SETUP_ASYNC_WITH, final);
/* SETUP_ASYNC_WITH pushes a finally block. */ /* SETUP_ASYNC_WITH pushes a finally block. */
compiler_use_next_block(c, block); compiler_use_next_block(c, block);
@ -4873,7 +4888,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
ADDOP_JABS(c, JUMP_ABSOLUTE, exit); ADDOP_JUMP(c, JUMP_ABSOLUTE, exit);
/* For exceptional outcome: */ /* For exceptional outcome: */
compiler_use_next_block(c, final); compiler_use_next_block(c, final);
@ -4927,7 +4942,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
/* Evaluate EXPR */ /* Evaluate EXPR */
VISIT(c, expr, item->context_expr); VISIT(c, expr, item->context_expr);
/* Will push bound __exit__ */ /* Will push bound __exit__ */
ADDOP_JREL(c, SETUP_WITH, final); ADDOP_JUMP(c, SETUP_WITH, final);
/* SETUP_WITH pushes a finally block. */ /* SETUP_WITH pushes a finally block. */
compiler_use_next_block(c, block); compiler_use_next_block(c, block);
@ -4961,7 +4976,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
if (!compiler_call_exit_with_nones(c)) if (!compiler_call_exit_with_nones(c))
return 0; return 0;
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
ADDOP_JREL(c, JUMP_FORWARD, exit); ADDOP_JUMP(c, JUMP_FORWARD, exit);
/* For exceptional outcome: */ /* For exceptional outcome: */
compiler_use_next_block(c, final); compiler_use_next_block(c, final);
@ -5492,7 +5507,7 @@ stackdepth(struct compiler *c)
maxdepth = new_depth; maxdepth = new_depth;
} }
assert(depth >= 0); /* invalid code or bug in stackdepth() */ assert(depth >= 0); /* invalid code or bug in stackdepth() */
if (instr->i_jrel || instr->i_jabs) { if (is_jump(instr)) {
effect = stack_effect(instr->i_opcode, instr->i_oparg, 1); effect = stack_effect(instr->i_opcode, instr->i_oparg, 1);
assert(effect != PY_INVALID_STACK_EFFECT); assert(effect != PY_INVALID_STACK_EFFECT);
int target_depth = depth + effect; int target_depth = depth + effect;
@ -5730,9 +5745,9 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
the jump instruction. the jump instruction.
*/ */
bsize += isize; bsize += isize;
if (instr->i_jabs || instr->i_jrel) { if (is_jump(instr)) {
instr->i_oparg = instr->i_target->b_offset; instr->i_oparg = instr->i_target->b_offset;
if (instr->i_jrel) { if (is_relative_jump(instr)) {
instr->i_oparg -= bsize; instr->i_oparg -= bsize;
} }
instr->i_oparg *= sizeof(_Py_CODEUNIT); instr->i_oparg *= sizeof(_Py_CODEUNIT);
@ -5946,8 +5961,8 @@ makecode(struct compiler *c, struct assembler *a, PyObject *consts)
static void static void
dump_instr(const struct instr *i) dump_instr(const struct instr *i)
{ {
const char *jrel = i->i_jrel ? "jrel " : ""; const char *jrel = (is_relative_jump(instr)) ? "jrel " : "";
const char *jabs = i->i_jabs ? "jabs " : ""; const char *jabs = (is_jump(instr) && !is_relative_jump(instr))? "jabs " : "";
char arg[128]; char arg[128];
*arg = '\0'; *arg = '\0';
@ -6122,7 +6137,7 @@ optimize_basic_block(basicblock *bb, PyObject *consts)
struct instr *inst = &bb->b_instr[i]; struct instr *inst = &bb->b_instr[i];
int oparg = inst->i_oparg; int oparg = inst->i_oparg;
int nextop = i+1 < bb->b_iused ? bb->b_instr[i+1].i_opcode : 0; int nextop = i+1 < bb->b_iused ? bb->b_instr[i+1].i_opcode : 0;
if (inst->i_jabs || inst->i_jrel) { if (is_jump(inst)) {
/* Skip over empty basic blocks. */ /* Skip over empty basic blocks. */
while (inst->i_target->b_iused == 0) { while (inst->i_target->b_iused == 0) {
inst->i_target = inst->i_target->b_next; inst->i_target = inst->i_target->b_next;
@ -6148,7 +6163,6 @@ optimize_basic_block(basicblock *bb, PyObject *consts)
if (is_true == 1) { if (is_true == 1) {
inst->i_opcode = NOP; inst->i_opcode = NOP;
bb->b_instr[i+1].i_opcode = NOP; bb->b_instr[i+1].i_opcode = NOP;
bb->b_instr[i+1].i_jabs = 0;
} }
break; break;
@ -6318,7 +6332,7 @@ mark_reachable(struct assembler *a) {
} }
for (int i = 0; i < b->b_iused; i++) { for (int i = 0; i < b->b_iused; i++) {
basicblock *target; basicblock *target;
if (b->b_instr[i].i_jrel || b->b_instr[i].i_jabs) { if (is_jump(&b->b_instr[i])) {
target = b->b_instr[i].i_target; target = b->b_instr[i].i_target;
if (target->b_reachable == 0) { if (target->b_reachable == 0) {
target->b_reachable = 1; target->b_reachable = 1;

View File

@ -30,6 +30,18 @@ footer = """
#endif /* !Py_OPCODE_H */ #endif /* !Py_OPCODE_H */
""" """
UINT32_MASK = (1<<32)-1
def write_int_array_from_ops(name, ops, out):
bits = 0
for op in ops:
bits |= 1<<op
out.write(f"static uint32_t {name}[8] = {{\n")
for i in range(8):
out.write(f" {bits & UINT32_MASK}U,\n")
bits >>= 32
assert bits == 0
out.write(f"}};\n")
def main(opcode_py, outfile='Include/opcode.h'): def main(opcode_py, outfile='Include/opcode.h'):
opcode = {} opcode = {}
@ -41,6 +53,8 @@ def main(opcode_py, outfile='Include/opcode.h'):
code = fp.read() code = fp.read()
exec(code, opcode) exec(code, opcode)
opmap = opcode['opmap'] opmap = opcode['opmap']
hasjrel = opcode['hasjrel']
hasjabs = opcode['hasjabs']
with open(outfile, 'w') as fobj: with open(outfile, 'w') as fobj:
fobj.write(header) fobj.write(header)
for name in opcode['opname']: for name in opcode['opname']:
@ -49,8 +63,13 @@ def main(opcode_py, outfile='Include/opcode.h'):
if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT
fobj.write("#define %-23s %3d\n" % fobj.write("#define %-23s %3d\n" %
('HAVE_ARGUMENT', opcode['HAVE_ARGUMENT'])) ('HAVE_ARGUMENT', opcode['HAVE_ARGUMENT']))
fobj.write("#ifdef NEED_OPCODE_JUMP_TABLES\n")
write_int_array_from_ops("_PyOpcode_RelativeJump", opcode['hasjrel'], fobj)
write_int_array_from_ops("_PyOpcode_Jump", opcode['hasjrel'] + opcode['hasjabs'], fobj)
fobj.write("#endif /* OPCODE_TABLES */\n")
fobj.write(footer) fobj.write(footer)
print("%s regenerated from %s" % (outfile, opcode_py)) print("%s regenerated from %s" % (outfile, opcode_py))