diff options
Diffstat (limited to 'Python/compile.c')
-rw-r--r-- | Python/compile.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/Python/compile.c b/Python/compile.c index baea494..b007859 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -6986,6 +6986,9 @@ normalize_basic_block(basicblock *bb); static int optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts); +static int +trim_unused_consts(struct compiler *c, struct assembler *a, PyObject *consts); + /* Duplicates exit BBs, so that line numbers can be propagated to them */ static int duplicate_exits_without_lineno(struct compiler *c); @@ -7127,6 +7130,9 @@ assemble(struct compiler *c, int addNone) if (duplicate_exits_without_lineno(c)) { return NULL; } + if (trim_unused_consts(c, &a, consts)) { + goto error; + } propagate_line_numbers(&a); guarantee_lineno_for_exits(&a, c->u->u_firstlineno); /* Can't modify the bytecode after computing jump offsets. */ @@ -7809,6 +7815,33 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts) return 0; } +// Remove trailing unused constants. +static int +trim_unused_consts(struct compiler *c, struct assembler *a, PyObject *consts) +{ + assert(PyList_CheckExact(consts)); + + // The first constant may be docstring; keep it always. + int max_const_index = 0; + for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) { + for (int i = 0; i < b->b_iused; i++) { + if (b->b_instr[i].i_opcode == LOAD_CONST && + b->b_instr[i].i_oparg > max_const_index) { + max_const_index = b->b_instr[i].i_oparg; + } + } + } + if (max_const_index+1 < PyList_GET_SIZE(consts)) { + //fprintf(stderr, "removing trailing consts: max=%d, size=%d\n", + // max_const_index, (int)PyList_GET_SIZE(consts)); + if (PyList_SetSlice(consts, max_const_index+1, + PyList_GET_SIZE(consts), NULL) < 0) { + return 1; + } + } + return 0; +} + static inline int is_exit_without_lineno(basicblock *b) { return b->b_exit && b->b_instr[0].i_lineno < 0; |