[3.10] bpo-45056: Remove trailing unused constants from co_consts (GH-28109) (GH-28125)

(cherry picked from commit 55c4a92fc1)

Co-authored-by: Inada Naoki <songofacandy@gmail.com>
This commit is contained in:
Łukasz Langa 2021-09-08 18:25:09 +02:00 committed by GitHub
parent 7538fe34d7
commit d41abe8970
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 4672 additions and 4634 deletions

View file

@ -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;