diff options
| author | Mark Shannon <mark@hotpy.org> | 2020-08-04 17:30:11 +0100 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-04 17:30:11 +0100 | 
| commit | 582aaf19e8b94a70c1f96792197770d604ba0fdf (patch) | |
| tree | 5f7934d5792806ac1f21c023734eebfb031b0117 /Python/compile.c | |
| parent | c7decc27d529c04a4e6b2922e3f3f9419b920f63 (diff) | |
| download | cpython-git-582aaf19e8b94a70c1f96792197770d604ba0fdf.tar.gz | |
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'
Diffstat (limited to 'Python/compile.c')
| -rw-r--r-- | Python/compile.c | 132 | 
1 files changed, 73 insertions, 59 deletions
| diff --git a/Python/compile.c b/Python/compile.c index 42b09fd96d..5dbd9f221f 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; | 
