diff options
Diffstat (limited to 'Python/compile.c')
-rw-r--r-- | Python/compile.c | 476 |
1 files changed, 346 insertions, 130 deletions
diff --git a/Python/compile.c b/Python/compile.c index 0c4a6c8..485fdd7 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -29,6 +29,7 @@ #include "code.h" #include "symtable.h" #include "opcode.h" +#include "wordcode_helpers.h" #define DEFAULT_BLOCK_SIZE 16 #define DEFAULT_BLOCKS 8 @@ -43,7 +44,6 @@ struct instr { unsigned i_jabs : 1; unsigned i_jrel : 1; - unsigned i_hasarg : 1; unsigned char i_opcode; int i_oparg; struct basicblock_ *i_target; /* target block (if jump instruction) */ @@ -171,7 +171,6 @@ static int compiler_addop(struct compiler *, int); static int compiler_addop_o(struct compiler *, int, PyObject *, PyObject *); static int compiler_addop_i(struct compiler *, int, Py_ssize_t); static int compiler_addop_j(struct compiler *, int, basicblock *, int); -static basicblock *compiler_use_new_block(struct compiler *); static int compiler_error(struct compiler *, const char *); static int compiler_nameop(struct compiler *, identifier, expr_context_ty); @@ -196,7 +195,7 @@ static int expr_constant(struct compiler *, expr_ty); static int compiler_with(struct compiler *, stmt_ty, int); static int compiler_async_with(struct compiler *, stmt_ty, int); static int compiler_async_for(struct compiler *, stmt_ty); -static int compiler_call_helper(struct compiler *c, Py_ssize_t n, +static int compiler_call_helper(struct compiler *c, int n, asdl_seq *args, asdl_seq *keywords); static int compiler_try_except(struct compiler *, stmt_ty); @@ -477,9 +476,9 @@ compiler_unit_check(struct compiler_unit *u) { basicblock *block; for (block = u->u_blocks; block != NULL; block = block->b_list) { - assert((void *)block != (void *)0xcbcbcbcb); - assert((void *)block != (void *)0xfbfbfbfb); - assert((void *)block != (void *)0xdbdbdbdb); + assert((Py_uintptr_t)block != 0xcbcbcbcbU); + assert((Py_uintptr_t)block != 0xfbfbfbfbU); + assert((Py_uintptr_t)block != 0xdbdbdbdbU); if (block->b_instr != NULL) { assert(block->b_ialloc > 0); assert(block->b_iused > 0); @@ -523,6 +522,7 @@ compiler_enter_scope(struct compiler *c, identifier name, int scope_type, void *key, int lineno) { struct compiler_unit *u; + basicblock *block; u = (struct compiler_unit *)PyObject_Malloc(sizeof( struct compiler_unit)); @@ -620,8 +620,11 @@ compiler_enter_scope(struct compiler *c, identifier name, c->u = u; c->c_nestlevel++; - if (compiler_use_new_block(c) == NULL) + + block = compiler_new_block(c); + if (block == NULL) return 0; + c->u->u_curblock = block; if (u->u_scope_type != COMPILER_SCOPE_MODULE) { if (!compiler_set_qualname(c)) @@ -731,6 +734,7 @@ compiler_set_qualname(struct compiler *c) return 1; } + /* Allocate a new block and return a pointer to it. Returns NULL on error. */ @@ -755,16 +759,6 @@ compiler_new_block(struct compiler *c) } static basicblock * -compiler_use_new_block(struct compiler *c) -{ - basicblock *block = compiler_new_block(c); - if (block == NULL) - return NULL; - c->u->u_curblock = block; - return block; -} - -static basicblock * compiler_next_block(struct compiler *c) { basicblock *block = compiler_new_block(c); @@ -986,6 +980,8 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) return 1 - (oparg & 0xFF); case BUILD_MAP: return 1 - 2*oparg; + case BUILD_CONST_KEY_MAP: + return -oparg; case LOAD_ATTR: return 0; case COMPARE_OP: @@ -1066,6 +1062,10 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) return 1; case GET_YIELD_FROM_ITER: return 0; + case FORMAT_VALUE: + /* If there's a fmt_spec on the stack, we go from 2->1, + else 1->1. */ + return (oparg & FVS_MASK) == FVS_HAVE_SPEC ? -1 : 0; default: return PY_INVALID_STACK_EFFECT; } @@ -1082,13 +1082,14 @@ compiler_addop(struct compiler *c, int opcode) basicblock *b; struct instr *i; int off; + assert(!HAS_ARG(opcode)); off = compiler_next_instr(c, c->u->u_curblock); if (off < 0) return 0; b = c->u->u_curblock; i = &b->b_instr[off]; i->i_opcode = opcode; - i->i_hasarg = 0; + i->i_oparg = 0; if (opcode == RETURN_VALUE) b->b_return = 1; compiler_set_lineno(c, off); @@ -1165,10 +1166,15 @@ compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg) struct instr *i; int off; - /* Integer arguments are limit to 16-bit. There is an extension for 32-bit - integer arguments. */ - assert((-2147483647-1) <= oparg); - assert(oparg <= 2147483647); + /* oparg value is unsigned, but a signed C int is usually used to store + it in the C code (like Python/ceval.c). + + Limit to 32-bit signed C int (rather than INT_MAX) for portability. + + The argument of a concrete bytecode instruction is limited to 8-bit. + EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */ + assert(HAS_ARG(opcode)); + assert(0 <= oparg && oparg <= 2147483647); off = compiler_next_instr(c, c->u->u_curblock); if (off < 0) @@ -1176,7 +1182,6 @@ compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg) i = &c->u->u_curblock->b_instr[off]; i->i_opcode = opcode; i->i_oparg = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int); - i->i_hasarg = 1; compiler_set_lineno(c, off); return 1; } @@ -1187,6 +1192,7 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) struct instr *i; int off; + assert(HAS_ARG(opcode)); assert(b != NULL); off = compiler_next_instr(c, c->u->u_curblock); if (off < 0) @@ -1194,7 +1200,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; - i->i_hasarg = 1; if (absolute) i->i_jabs = 1; else @@ -1203,22 +1208,12 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) return 1; } -/* The distinction between NEW_BLOCK and NEXT_BLOCK is subtle. (I'd - like to find better names.) NEW_BLOCK() creates a new block and sets - it as the current block. NEXT_BLOCK() also creates an implicit jump - from the current block to the new block. -*/ +/* NEXT_BLOCK() creates an implicit jump from the current block + to the new block. -/* The returns inside these macros make it impossible to decref objects - created in the local function. Local objects should use the arena. + The returns inside this macro make it impossible to decref objects + created in the local function. Local objects should use the arena. */ - - -#define NEW_BLOCK(C) { \ - if (compiler_use_new_block((C)) == NULL) \ - return 0; \ -} - #define NEXT_BLOCK(C) { \ if (compiler_next_block((C)) == NULL) \ return 0; \ @@ -1241,6 +1236,15 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) return 0; \ } +/* Same as ADDOP_O, but steals a reference. */ +#define ADDOP_N(C, OP, O, TYPE) { \ + if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) { \ + Py_DECREF((O)); \ + return 0; \ + } \ + Py_DECREF((O)); \ +} + #define ADDOP_NAME(C, OP, O, TYPE) { \ if (!compiler_addop_name((C), (OP), (C)->u->u_ ## TYPE, (O))) \ return 0; \ @@ -1309,7 +1313,49 @@ compiler_isdocstring(stmt_ty s) { if (s->kind != Expr_kind) return 0; - return s->v.Expr.value->kind == Str_kind; + if (s->v.Expr.value->kind == Str_kind) + return 1; + if (s->v.Expr.value->kind == Constant_kind) + return PyUnicode_CheckExact(s->v.Expr.value->v.Constant.value); + return 0; +} + +static int +is_const(expr_ty e) +{ + switch (e->kind) { + case Constant_kind: + case Num_kind: + case Str_kind: + case Bytes_kind: + case Ellipsis_kind: + case NameConstant_kind: + return 1; + default: + return 0; + } +} + +static PyObject * +get_const_value(expr_ty e) +{ + switch (e->kind) { + case Constant_kind: + return e->v.Constant.value; + case Num_kind: + return e->v.Num.n; + case Str_kind: + return e->v.Str.s; + case Bytes_kind: + return e->v.Bytes.s; + case Ellipsis_kind: + return Py_Ellipsis; + case NameConstant_kind: + return e->v.NameConstant.value; + default: + assert(!is_const(e)); + return NULL; + } } /* Compile a sequence of statements, checking for a docstring. */ @@ -1683,8 +1729,12 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) st = (stmt_ty)asdl_seq_GET(body, 0); docstring = compiler_isdocstring(st); - if (docstring && c->c_optimize < 2) - first_const = st->v.Expr.value->v.Str.s; + if (docstring && c->c_optimize < 2) { + if (st->v.Expr.value->kind == Constant_kind) + first_const = st->v.Expr.value->v.Constant.value; + else + first_const = st->v.Expr.value->v.Str.s; + } if (compiler_add_o(c, c->u->u_consts, first_const) < 0) { compiler_exit_scope(c); return 0; @@ -2595,6 +2645,25 @@ compiler_assert(struct compiler *c, stmt_ty s) } static int +compiler_visit_stmt_expr(struct compiler *c, expr_ty value) +{ + if (c->c_interactive && c->c_nestlevel <= 1) { + VISIT(c, expr, value); + ADDOP(c, PRINT_EXPR); + return 1; + } + + if (is_const(value)) { + /* ignore constant statement */ + return 1; + } + + VISIT(c, expr, value); + ADDOP(c, POP_TOP); + return 1; +} + +static int compiler_visit_stmt(struct compiler *c, stmt_ty s) { Py_ssize_t i, n; @@ -2664,16 +2733,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) case Nonlocal_kind: break; case Expr_kind: - if (c->c_interactive && c->c_nestlevel <= 1) { - VISIT(c, expr, s->v.Expr.value); - ADDOP(c, PRINT_EXPR); - } - else if (s->v.Expr.value->kind != Str_kind && - s->v.Expr.value->kind != Num_kind) { - VISIT(c, expr, s->v.Expr.value); - ADDOP(c, POP_TOP); - } - break; + return compiler_visit_stmt_expr(c, s->v.Expr.value); case Pass_kind: break; case Break_kind: @@ -3075,9 +3135,53 @@ compiler_set(struct compiler *c, expr_ty e) } static int +are_all_items_const(asdl_seq *seq, Py_ssize_t begin, Py_ssize_t end) +{ + Py_ssize_t i; + for (i = begin; i < end; i++) { + expr_ty key = (expr_ty)asdl_seq_GET(seq, i); + if (key == NULL || !is_const(key)) + return 0; + } + return 1; +} + +static int +compiler_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end) +{ + Py_ssize_t i, n = end - begin; + PyObject *keys, *key; + if (n > 1 && are_all_items_const(e->v.Dict.keys, begin, end)) { + for (i = begin; i < end; i++) { + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); + } + keys = PyTuple_New(n); + if (keys == NULL) { + return 0; + } + for (i = begin; i < end; i++) { + key = get_const_value((expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); + Py_INCREF(key); + PyTuple_SET_ITEM(keys, i - begin, key); + } + ADDOP_N(c, LOAD_CONST, keys, consts); + ADDOP_I(c, BUILD_CONST_KEY_MAP, n); + } + else { + for (i = begin; i < end; i++) { + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); + } + ADDOP_I(c, BUILD_MAP, n); + } + return 1; +} + +static int compiler_dict(struct compiler *c, expr_ty e) { - Py_ssize_t i, n, containers, elements; + Py_ssize_t i, n, elements; + int containers; int is_unpacking = 0; n = asdl_seq_LEN(e->v.Dict.values); containers = 0; @@ -3085,7 +3189,8 @@ compiler_dict(struct compiler *c, expr_ty e) for (i = 0; i < n; i++) { is_unpacking = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i) == NULL; if (elements == 0xFFFF || (elements && is_unpacking)) { - ADDOP_I(c, BUILD_MAP, elements); + if (!compiler_subdict(c, e, i - elements, i)) + return 0; containers++; elements = 0; } @@ -3094,13 +3199,12 @@ compiler_dict(struct compiler *c, expr_ty e) containers++; } else { - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); elements++; } } if (elements || containers == 0) { - ADDOP_I(c, BUILD_MAP, elements); + if (!compiler_subdict(c, e, n - elements, n)) + return 0; containers++; } /* If there is more than one dict, they need to be merged into a new @@ -3169,15 +3273,127 @@ compiler_call(struct compiler *c, expr_ty e) e->v.Call.keywords); } +static int +compiler_joined_str(struct compiler *c, expr_ty e) +{ + /* Concatenate parts of a string using ''.join(parts). There are + probably better ways of doing this. + + This is used for constructs like "'x=' f'{42}'", which have to + be evaluated at compile time. */ + + static PyObject *empty_string; + static PyObject *join_string; + + if (!empty_string) { + empty_string = PyUnicode_FromString(""); + if (!empty_string) + return 0; + } + if (!join_string) { + join_string = PyUnicode_FromString("join"); + if (!join_string) + return 0; + } + + ADDOP_O(c, LOAD_CONST, empty_string, consts); + ADDOP_NAME(c, LOAD_ATTR, join_string, names); + VISIT_SEQ(c, expr, e->v.JoinedStr.values); + ADDOP_I(c, BUILD_LIST, asdl_seq_LEN(e->v.JoinedStr.values)); + ADDOP_I(c, CALL_FUNCTION, 1); + return 1; +} + +/* Used to implement f-strings. Format a single value. */ +static int +compiler_formatted_value(struct compiler *c, expr_ty e) +{ + /* Our oparg encodes 2 pieces of information: the conversion + character, and whether or not a format_spec was provided. + + Convert the conversion char to 2 bits: + None: 000 0x0 FVC_NONE + !s : 001 0x1 FVC_STR + !r : 010 0x2 FVC_REPR + !a : 011 0x3 FVC_ASCII + + next bit is whether or not we have a format spec: + yes : 100 0x4 + no : 000 0x0 + */ + + int oparg; + + /* Evaluate the expression to be formatted. */ + VISIT(c, expr, e->v.FormattedValue.value); + + switch (e->v.FormattedValue.conversion) { + case 's': oparg = FVC_STR; break; + case 'r': oparg = FVC_REPR; break; + case 'a': oparg = FVC_ASCII; break; + case -1: oparg = FVC_NONE; break; + default: + PyErr_SetString(PyExc_SystemError, + "Unrecognized conversion character"); + return 0; + } + if (e->v.FormattedValue.format_spec) { + /* Evaluate the format spec, and update our opcode arg. */ + VISIT(c, expr, e->v.FormattedValue.format_spec); + oparg |= FVS_HAVE_SPEC; + } + + /* And push our opcode and oparg */ + ADDOP_I(c, FORMAT_VALUE, oparg); + return 1; +} + +static int +compiler_subkwargs(struct compiler *c, asdl_seq *keywords, Py_ssize_t begin, Py_ssize_t end) +{ + Py_ssize_t i, n = end - begin; + keyword_ty kw; + PyObject *keys, *key; + assert(n > 0); + if (n > 1) { + for (i = begin; i < end; i++) { + kw = asdl_seq_GET(keywords, i); + VISIT(c, expr, kw->value); + } + keys = PyTuple_New(n); + if (keys == NULL) { + return 0; + } + for (i = begin; i < end; i++) { + key = ((keyword_ty) asdl_seq_GET(keywords, i))->arg; + Py_INCREF(key); + PyTuple_SET_ITEM(keys, i - begin, key); + } + ADDOP_N(c, LOAD_CONST, keys, consts); + ADDOP_I(c, BUILD_CONST_KEY_MAP, n); + } + else { + /* a for loop only executes once */ + for (i = begin; i < end; i++) { + kw = asdl_seq_GET(keywords, i); + ADDOP_O(c, LOAD_CONST, kw->arg, consts); + VISIT(c, expr, kw->value); + } + ADDOP_I(c, BUILD_MAP, n); + } + return 1; +} + /* shared code between compiler_call and compiler_class */ static int compiler_call_helper(struct compiler *c, - Py_ssize_t n, /* Args already pushed */ + int n, /* Args already pushed */ asdl_seq *args, asdl_seq *keywords) { int code = 0; - Py_ssize_t nelts, i, nseen, nkw; + Py_ssize_t nelts, i, nseen; + int nkw; /* the number of tuples and dictionaries on the stack */ Py_ssize_t nsubargs = 0, nsubkwargs = 0; @@ -3234,29 +3450,38 @@ compiler_call_helper(struct compiler *c, if (kw->arg == NULL) { /* A keyword argument unpacking. */ if (nseen) { - ADDOP_I(c, BUILD_MAP, nseen); + if (nsubkwargs) { + if (!compiler_subkwargs(c, keywords, i - nseen, i)) + return 0; + nsubkwargs++; + } + else { + Py_ssize_t j; + for (j = 0; j < nseen; j++) { + VISIT(c, keyword, asdl_seq_GET(keywords, j)); + } + nkw = nseen; + } nseen = 0; - nsubkwargs++; } VISIT(c, expr, kw->value); nsubkwargs++; } - else if (nsubkwargs) { - /* A keyword argument and we already have a dict. */ - ADDOP_O(c, LOAD_CONST, kw->arg, consts); - VISIT(c, expr, kw->value); - nseen++; - } else { - /* keyword argument */ - VISIT(c, keyword, kw) - nkw++; + nseen++; } } if (nseen) { - /* Pack up any trailing keyword arguments. */ - ADDOP_I(c, BUILD_MAP, nseen); - nsubkwargs++; + if (nsubkwargs) { + /* Pack up any trailing keyword arguments. */ + if (!compiler_subkwargs(c, keywords, nelts - nseen, nelts)) + return 0; + nsubkwargs++; + } + else { + VISIT_SEQ(c, keyword, keywords); + nkw = nseen; + } } if (nsubkwargs) { code |= 2; @@ -3545,6 +3770,8 @@ expr_constant(struct compiler *c, expr_ty e) switch (e->kind) { case Ellipsis_kind: return 1; + case Constant_kind: + return PyObject_IsTrue(e->v.Constant.value); case Num_kind: return PyObject_IsTrue(e->v.Num.n); case Str_kind: @@ -3588,9 +3815,9 @@ expr_constant(struct compiler *c, expr_ty e) BLOCK finally: if an exception was raised: - exc = copy of (exception, instance, traceback) + exc = copy of (exception, instance, traceback) else: - exc = (None, None, None) + exc = (None, None, None) if not (await exit(*exc)): raise */ @@ -3832,12 +4059,19 @@ compiler_visit_expr(struct compiler *c, expr_ty e) return compiler_compare(c, e); case Call_kind: return compiler_call(c, e); + case Constant_kind: + ADDOP_O(c, LOAD_CONST, e->v.Constant.value, consts); + break; case Num_kind: ADDOP_O(c, LOAD_CONST, e->v.Num.n, consts); break; case Str_kind: ADDOP_O(c, LOAD_CONST, e->v.Str.s, consts); break; + case JoinedStr_kind: + return compiler_joined_str(c, e); + case FormattedValue_kind: + return compiler_formatted_value(c, e); case Bytes_kind: ADDOP_O(c, LOAD_CONST, e->v.Bytes.s, consts); break; @@ -4291,18 +4525,6 @@ assemble_free(struct assembler *a) PyObject_Free(a->a_postorder); } -/* Return the size of a basic block in bytes. */ - -static int -instrsize(struct instr *instr) -{ - if (!instr->i_hasarg) - return 1; /* 1 byte for the opcode*/ - if (instr->i_oparg > 0xffff) - return 6; /* 1 (opcode) + 1 (EXTENDED_ARG opcode) + 2 (oparg) + 2(oparg extended) */ - return 3; /* 1 (opcode) + 2 (oparg) */ -} - static int blocksize(basicblock *b) { @@ -4310,7 +4532,7 @@ blocksize(basicblock *b) int size = 0; for (i = 0; i < b->b_iused; i++) - size += instrsize(&b->b_instr[i]); + size += instrsize(b->b_instr[i].i_oparg); return size; } @@ -4329,7 +4551,6 @@ assemble_lnotab(struct assembler *a, struct instr *i) d_lineno = i->i_lineno - a->a_lineno; assert(d_bytecode >= 0); - assert(d_lineno >= 0); if(d_bytecode == 0 && d_lineno == 0) return 1; @@ -4359,9 +4580,21 @@ assemble_lnotab(struct assembler *a, struct instr *i) d_bytecode -= ncodes * 255; a->a_lnotab_off += ncodes * 2; } - assert(d_bytecode <= 255); - if (d_lineno > 255) { - int j, nbytes, ncodes = d_lineno / 255; + assert(0 <= d_bytecode && d_bytecode <= 255); + + if (d_lineno < -128 || 127 < d_lineno) { + int j, nbytes, ncodes, k; + if (d_lineno < 0) { + k = -128; + /* use division on positive numbers */ + ncodes = (-d_lineno) / 128; + } + else { + k = 127; + ncodes = d_lineno / 127; + } + d_lineno -= ncodes * k; + assert(ncodes >= 1); nbytes = a->a_lnotab_off + 2 * ncodes; len = PyBytes_GET_SIZE(a->a_lnotab); if (nbytes >= len) { @@ -4379,15 +4612,15 @@ assemble_lnotab(struct assembler *a, struct instr *i) lnotab = (unsigned char *) PyBytes_AS_STRING(a->a_lnotab) + a->a_lnotab_off; *lnotab++ = d_bytecode; - *lnotab++ = 255; + *lnotab++ = k; d_bytecode = 0; for (j = 1; j < ncodes; j++) { *lnotab++ = 0; - *lnotab++ = 255; + *lnotab++ = k; } - d_lineno -= ncodes * 255; a->a_lnotab_off += ncodes * 2; } + assert(-128 <= d_lineno && d_lineno <= 127); len = PyBytes_GET_SIZE(a->a_lnotab); if (a->a_lnotab_off + 2 >= len) { @@ -4419,15 +4652,12 @@ assemble_lnotab(struct assembler *a, struct instr *i) static int assemble_emit(struct assembler *a, struct instr *i) { - int size, arg = 0, ext = 0; + int size, arg = 0; Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode); char *code; - size = instrsize(i); - if (i->i_hasarg) { - arg = i->i_oparg; - ext = arg >> 16; - } + arg = i->i_oparg; + size = instrsize(arg); if (i->i_lineno && !assemble_lnotab(a, i)) return 0; if (a->a_offset + size >= len) { @@ -4438,19 +4668,7 @@ assemble_emit(struct assembler *a, struct instr *i) } code = PyBytes_AS_STRING(a->a_bytecode) + a->a_offset; a->a_offset += size; - if (size == 6) { - assert(i->i_hasarg); - *code++ = (char)EXTENDED_ARG; - *code++ = ext & 0xff; - *code++ = ext >> 8; - arg &= 0xffff; - } - *code++ = i->i_opcode; - if (i->i_hasarg) { - assert(size == 3 || size == 6); - *code++ = arg & 0xff; - *code++ = arg >> 8; - } + write_op_arg((unsigned char*)code, i->i_opcode, arg, size); return 1; } @@ -4458,7 +4676,7 @@ static void assemble_jump_offsets(struct assembler *a, struct compiler *c) { basicblock *b; - int bsize, totsize, extended_arg_count = 0, last_extended_arg_count; + int bsize, totsize, extended_arg_recompile; int i; /* Compute the size of each block and fixup jump args. @@ -4471,27 +4689,26 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c) b->b_offset = totsize; totsize += bsize; } - last_extended_arg_count = extended_arg_count; - extended_arg_count = 0; + extended_arg_recompile = 0; for (b = c->u->u_blocks; b != NULL; b = b->b_list) { bsize = b->b_offset; for (i = 0; i < b->b_iused; i++) { struct instr *instr = &b->b_instr[i]; + int isize = instrsize(instr->i_oparg); /* Relative jumps are computed relative to the instruction pointer after fetching the jump instruction. */ - bsize += instrsize(instr); - if (instr->i_jabs) + bsize += isize; + if (instr->i_jabs || instr->i_jrel) { instr->i_oparg = instr->i_target->b_offset; - else if (instr->i_jrel) { - int delta = instr->i_target->b_offset - bsize; - instr->i_oparg = delta; + if (instr->i_jrel) { + instr->i_oparg -= bsize; + } + if (instrsize(instr->i_oparg) != isize) { + extended_arg_recompile = 1; + } } - else - continue; - if (instr->i_oparg > 0xffff) - extended_arg_count++; } } @@ -4501,7 +4718,7 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c) The issue is that in the first loop blocksize() is called which calls instrsize() which requires i_oparg be set - appropriately. There is a bootstrap problem because + appropriately. There is a bootstrap problem because i_oparg is calculated in the second loop above. So we loop until we stop seeing new EXTENDED_ARGs. @@ -4509,7 +4726,7 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c) ones in jump instructions. So this should converge fairly quickly. */ - } while (last_extended_arg_count != extended_arg_count); + } while (extended_arg_recompile); } static PyObject * @@ -4655,9 +4872,9 @@ dump_instr(const struct instr *i) char arg[128]; *arg = '\0'; - if (i->i_hasarg) + if (HAS_ARG(i->i_opcode)) { sprintf(arg, "arg: %d ", i->i_oparg); - + } fprintf(stderr, "line: %d, opcode: %d %s%s%s\n", i->i_lineno, i->i_opcode, arg, jabs, jrel); } @@ -4745,4 +4962,3 @@ PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, { return PyAST_CompileEx(mod, filename, flags, -1, arena); } - |