[3.10] bpo-45056: Remove trailing unused constants from co_consts (GH-28109) (GH-28125)
(cherry picked from commit 55c4a92fc1abfe388335071f1d64b3addfa5793f)
Co-authored-by: Inada Naoki <songofacandy@gmail.com>
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;