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

Mark Shannon webhook-mailer at python.org
Tue Aug 4 12:30:21 EDT 2020


https://github.com/python/cpython/commit/582aaf19e8b94a70c1f96792197770d604ba0fdf
commit: 582aaf19e8b94a70c1f96792197770d604ba0fdf
branch: master
author: Mark Shannon <mark at hotpy.org>
committer: GitHub <noreply at github.com>
date: 2020-08-04T17:30:11+01:00
summary:

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'

files:
M Include/opcode.h
M Python/compile.c
M Tools/scripts/generate_opcode_h.py

diff --git a/Include/opcode.h b/Include/opcode.h
index 19944fac0b9f2..420c87aa0f24f 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -127,6 +127,28 @@ extern "C" {
 #define SET_UPDATE              163
 #define DICT_MERGE              164
 #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
    entering an except handler. It is not an opcode but we define it here
diff --git a/Python/compile.c b/Python/compile.c
index 42b09fd96dfbb..5dbd9f221fdf1 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -27,6 +27,7 @@
 #include "ast.h"
 #include "code.h"
 #include "symtable.h"
+#define NEED_OPCODE_JUMP_TABLES
 #include "opcode.h"
 #include "wordcode_helpers.h"
 
@@ -45,14 +46,38 @@
         && (c->u->u_ste->ste_type == ModuleBlock))
 
 struct instr {
-    unsigned i_jabs : 1;
-    unsigned i_jrel : 1;
     unsigned char i_opcode;
     int i_oparg;
     struct basicblock_ *i_target; /* target block (if jump instruction) */
     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_ {
     /* 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
@@ -182,7 +207,7 @@ static basicblock *compiler_new_block(struct compiler *);
 static int compiler_next_instr(basicblock *);
 static int compiler_addop(struct compiler *, int);
 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_warn(struct compiler *, const char *, ...);
 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
-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;
     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->i_opcode = opcode;
     i->i_target = b;
-    if (absolute)
-        i->i_jabs = 1;
-    else
-        i->i_jrel = 1;
     i->i_lineno = c->u->u_lineno;
     return 1;
 }
@@ -1471,17 +1492,11 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
         return 0; \
 }
 
-#define ADDOP_JABS(C, OP, O) { \
-    if (!compiler_addop_j((C), (OP), (O), 1)) \
+#define ADDOP_JUMP(C, OP, O) { \
+    if (!compiler_addop_j((C), (OP), (O))) \
         return 0; \
 }
 
-#define ADDOP_JREL(C, OP, O) { \
-    if (!compiler_addop_j((C), (OP), (O), 0)) \
-        return 0; \
-}
-
-
 #define ADDOP_COMPARE(C, CMP) { \
     if (!compiler_addcompare((C), (cmpop_ty)(CMP))) \
         return 0; \
@@ -2545,7 +2560,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
             return 0;
         if (!compiler_jump_if(c, e->v.IfExp.body, next, cond))
             return 0;
-        ADDOP_JREL(c, JUMP_FORWARD, end);
+        ADDOP_JUMP(c, JUMP_FORWARD, end);
         compiler_use_next_block(c, next2);
         if (!compiler_jump_if(c, e->v.IfExp.orelse, next, cond))
             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, ROT_THREE);
                 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);
             }
             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_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);
             if (end == NULL)
                 return 0;
-            ADDOP_JREL(c, JUMP_FORWARD, end);
+            ADDOP_JUMP(c, JUMP_FORWARD, end);
             compiler_use_next_block(c, cleanup);
             ADDOP(c, POP_TOP);
             if (!cond) {
-                ADDOP_JREL(c, JUMP_FORWARD, next);
+                ADDOP_JUMP(c, JUMP_FORWARD, next);
             }
             compiler_use_next_block(c, end);
             return 1;
@@ -2596,7 +2611,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
 
     /* general implementation */
     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;
 }
 
@@ -2615,7 +2630,7 @@ compiler_ifexp(struct compiler *c, expr_ty e)
     if (!compiler_jump_if(c, e->v.IfExp.test, next, 0))
         return 0;
     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);
     VISIT(c, expr, e->v.IfExp.orelse);
     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);
         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);
             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);
     ADDOP(c, GET_ITER);
     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_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_pop_fblock(c, FOR_LOOP, start);
@@ -2786,7 +2801,7 @@ compiler_async_for(struct compiler *c, stmt_ty s)
         return 0;
     }
     /* SETUP_FINALLY to guard the __anext__ call */
-    ADDOP_JREL(c, SETUP_FINALLY, except);
+    ADDOP_JUMP(c, SETUP_FINALLY, except);
     ADDOP(c, GET_ANEXT);
     ADDOP_LOAD_CONST(c, Py_None);
     ADDOP(c, YIELD_FROM);
@@ -2795,7 +2810,7 @@ compiler_async_for(struct compiler *c, stmt_ty s)
     /* Success block for __anext__ */
     VISIT(c, expr, s->v.AsyncFor.target);
     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);
 
@@ -2859,7 +2874,7 @@ compiler_while(struct compiler *c, stmt_ty s)
             return 0;
     }
     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
        if there is no else clause ?
@@ -2918,7 +2933,7 @@ compiler_break(struct compiler *c)
     if (!compiler_unwind_fblock(c, loop, 0)) {
         return 0;
     }
-    ADDOP_JABS(c, JUMP_ABSOLUTE, loop->fb_exit);
+    ADDOP_JUMP(c, JUMP_ABSOLUTE, loop->fb_exit);
     return 1;
 }
 
@@ -2932,7 +2947,7 @@ compiler_continue(struct compiler *c)
     if (loop == NULL) {
         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;
 }
 
@@ -2978,7 +2993,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
         return 0;
 
     /* `try` block */
-    ADDOP_JREL(c, SETUP_FINALLY, end);
+    ADDOP_JUMP(c, SETUP_FINALLY, end);
     compiler_use_next_block(c, body);
     if (!compiler_push_fblock(c, FINALLY_TRY, body, end, s->v.Try.finalbody))
         return 0;
@@ -2992,7 +3007,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
     ADDOP(c, POP_BLOCK);
     compiler_pop_fblock(c, FINALLY_TRY, body);
     VISIT_SEQ(c, stmt, s->v.Try.finalbody);
-    ADDOP_JREL(c, JUMP_FORWARD, exit);
+    ADDOP_JUMP(c, JUMP_FORWARD, exit);
     /* `finally` block */
     compiler_use_next_block(c, end);
     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);
     if (body == NULL || except == NULL || orelse == NULL || end == NULL)
         return 0;
-    ADDOP_JREL(c, SETUP_FINALLY, except);
+    ADDOP_JUMP(c, SETUP_FINALLY, except);
     compiler_use_next_block(c, body);
     if (!compiler_push_fblock(c, EXCEPT, body, NULL, NULL))
         return 0;
     VISIT_SEQ(c, stmt, s->v.Try.body);
     ADDOP(c, POP_BLOCK);
     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);
     compiler_use_next_block(c, except);
     for (i = 0; i < n; i++) {
@@ -3068,7 +3083,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
         if (handler->v.ExceptHandler.type) {
             ADDOP(c, DUP_TOP);
             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);
         if (handler->v.ExceptHandler.name) {
@@ -3095,7 +3110,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
             */
 
             /* second try: */
-            ADDOP_JREL(c, SETUP_FINALLY, cleanup_end);
+            ADDOP_JUMP(c, SETUP_FINALLY, cleanup_end);
             compiler_use_next_block(c, cleanup_body);
             if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, handler->v.ExceptHandler.name))
                 return 0;
@@ -3109,7 +3124,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
             ADDOP_LOAD_CONST(c, Py_None);
             compiler_nameop(c, handler->v.ExceptHandler.name, Store);
             compiler_nameop(c, handler->v.ExceptHandler.name, Del);
-            ADDOP_JREL(c, JUMP_FORWARD, end);
+            ADDOP_JUMP(c, JUMP_FORWARD, end);
 
             /* except: */
             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);
             compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body);
             ADDOP(c, POP_EXCEPT);
-            ADDOP_JREL(c, JUMP_FORWARD, end);
+            ADDOP_JUMP(c, JUMP_FORWARD, end);
         }
         compiler_use_next_block(c, except);
     }
@@ -3645,7 +3660,7 @@ compiler_boolop(struct compiler *c, expr_ty e)
     assert(n >= 0);
     for (i = 0; i < n; ++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);
         if (next == NULL) {
             return 0;
@@ -3933,7 +3948,7 @@ compiler_compare(struct compiler *c, expr_ty e)
             ADDOP(c, DUP_TOP);
             ADDOP(c, ROT_THREE);
             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);
         }
         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);
         if (end == NULL)
             return 0;
-        ADDOP_JREL(c, JUMP_FORWARD, end);
+        ADDOP_JUMP(c, JUMP_FORWARD, end);
         compiler_use_next_block(c, cleanup);
         ADDOP(c, ROT_TWO);
         ADDOP(c, POP_TOP);
@@ -4435,7 +4450,7 @@ compiler_sync_comprehension_generator(struct compiler *c,
     if (start) {
         depth++;
         compiler_use_next_block(c, start);
-        ADDOP_JREL(c, FOR_ITER, anchor);
+        ADDOP_JUMP(c, FOR_ITER, anchor);
         NEXT_BLOCK(c);
     }
     VISIT(c, expr, gen->target);
@@ -4487,7 +4502,7 @@ compiler_sync_comprehension_generator(struct compiler *c,
     }
     compiler_use_next_block(c, if_cleanup);
     if (start) {
-        ADDOP_JABS(c, JUMP_ABSOLUTE, start);
+        ADDOP_JUMP(c, JUMP_ABSOLUTE, start);
         compiler_use_next_block(c, anchor);
     }
 
@@ -4526,7 +4541,7 @@ compiler_async_comprehension_generator(struct compiler *c,
 
     compiler_use_next_block(c, start);
 
-    ADDOP_JREL(c, SETUP_FINALLY, except);
+    ADDOP_JUMP(c, SETUP_FINALLY, except);
     ADDOP(c, GET_ANEXT);
     ADDOP_LOAD_CONST(c, Py_None);
     ADDOP(c, YIELD_FROM);
@@ -4577,7 +4592,7 @@ compiler_async_comprehension_generator(struct compiler *c,
         }
     }
     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);
     ADDOP(c, END_ASYNC_FOR);
@@ -4773,7 +4788,7 @@ compiler_with_except_finish(struct compiler *c) {
     exit = compiler_new_block(c);
     if (exit == NULL)
         return 0;
-    ADDOP_JABS(c, POP_JUMP_IF_TRUE, exit);
+    ADDOP_JUMP(c, POP_JUMP_IF_TRUE, exit);
     ADDOP(c, RERAISE);
     compiler_use_next_block(c, exit);
     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(c, YIELD_FROM);
 
-    ADDOP_JREL(c, SETUP_ASYNC_WITH, final);
+    ADDOP_JUMP(c, SETUP_ASYNC_WITH, final);
 
     /* SETUP_ASYNC_WITH pushes a finally 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_JABS(c, JUMP_ABSOLUTE, exit);
+    ADDOP_JUMP(c, JUMP_ABSOLUTE, exit);
 
     /* For exceptional outcome: */
     compiler_use_next_block(c, final);
@@ -4927,7 +4942,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
     /* Evaluate EXPR */
     VISIT(c, expr, item->context_expr);
     /* Will push bound __exit__ */
-    ADDOP_JREL(c, SETUP_WITH, final);
+    ADDOP_JUMP(c, SETUP_WITH, final);
 
     /* SETUP_WITH pushes a finally 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))
         return 0;
     ADDOP(c, POP_TOP);
-    ADDOP_JREL(c, JUMP_FORWARD, exit);
+    ADDOP_JUMP(c, JUMP_FORWARD, exit);
 
     /* For exceptional outcome: */
     compiler_use_next_block(c, final);
@@ -5492,7 +5507,7 @@ stackdepth(struct compiler *c)
                 maxdepth = new_depth;
             }
             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);
                 assert(effect != PY_INVALID_STACK_EFFECT);
                 int target_depth = depth + effect;
@@ -5730,9 +5745,9 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
                    the jump instruction.
                 */
                 bsize += isize;
-                if (instr->i_jabs || instr->i_jrel) {
+                if (is_jump(instr)) {
                     instr->i_oparg = instr->i_target->b_offset;
-                    if (instr->i_jrel) {
+                    if (is_relative_jump(instr)) {
                         instr->i_oparg -= bsize;
                     }
                     instr->i_oparg *= sizeof(_Py_CODEUNIT);
@@ -5946,8 +5961,8 @@ makecode(struct compiler *c, struct assembler *a, PyObject *consts)
 static void
 dump_instr(const struct instr *i)
 {
-    const char *jrel = i->i_jrel ? "jrel " : "";
-    const char *jabs = i->i_jabs ? "jabs " : "";
+    const char *jrel = (is_relative_jump(instr)) ? "jrel " : "";
+    const char *jabs = (is_jump(instr) && !is_relative_jump(instr))? "jabs " : "";
     char arg[128];
 
     *arg = '\0';
@@ -6122,7 +6137,7 @@ optimize_basic_block(basicblock *bb, PyObject *consts)
         struct instr *inst = &bb->b_instr[i];
         int oparg = inst->i_oparg;
         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. */
             while (inst->i_target->b_iused == 0) {
                 inst->i_target = inst->i_target->b_next;
@@ -6148,7 +6163,6 @@ optimize_basic_block(basicblock *bb, PyObject *consts)
                 if (is_true == 1) {
                     inst->i_opcode = NOP;
                     bb->b_instr[i+1].i_opcode = NOP;
-                    bb->b_instr[i+1].i_jabs = 0;
                 }
                 break;
 
@@ -6318,7 +6332,7 @@ mark_reachable(struct assembler *a) {
         }
         for (int i = 0; i < b->b_iused; i++) {
             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;
                 if (target->b_reachable == 0) {
                     target->b_reachable = 1;
diff --git a/Tools/scripts/generate_opcode_h.py b/Tools/scripts/generate_opcode_h.py
index 873f82156e217..cba13b2421390 100644
--- a/Tools/scripts/generate_opcode_h.py
+++ b/Tools/scripts/generate_opcode_h.py
@@ -30,6 +30,18 @@
 #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'):
     opcode = {}
@@ -41,6 +53,8 @@ def main(opcode_py, outfile='Include/opcode.h'):
         code = fp.read()
     exec(code, opcode)
     opmap = opcode['opmap']
+    hasjrel = opcode['hasjrel']
+    hasjabs = opcode['hasjabs']
     with open(outfile, 'w') as fobj:
         fobj.write(header)
         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
                 fobj.write("#define %-23s %3d\n" %
                             ('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)
 
+
     print("%s regenerated from %s" % (outfile, opcode_py))
 
 



More information about the Python-checkins mailing list