mirror of
https://github.com/python/cpython.git
synced 2025-08-04 17:08:35 +00:00
[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:
parent
7538fe34d7
commit
d41abe8970
7 changed files with 4672 additions and 4634 deletions
|
@ -648,6 +648,17 @@ if 1:
|
|||
self.assertIs(f1.__code__.co_linetable, f2.__code__.co_linetable)
|
||||
self.assertIs(f1.__code__.co_code, f2.__code__.co_code)
|
||||
|
||||
# Stripping unused constants is not a strict requirement for the
|
||||
# Python semantics, it's a more an implementation detail.
|
||||
@support.cpython_only
|
||||
def test_strip_unused_consts(self):
|
||||
# Python 3.10rc1 appended None to co_consts when None is not used
|
||||
# at all. See bpo-45056.
|
||||
def f1():
|
||||
"docstring"
|
||||
return 42
|
||||
self.assertEqual(f1.__code__.co_consts, ("docstring", 42))
|
||||
|
||||
# This is a regression test for a CPython specific peephole optimizer
|
||||
# implementation bug present in a few releases. It's assertion verifies
|
||||
# that peephole optimization was actually done though that isn't an
|
||||
|
|
|
@ -689,10 +689,7 @@ class DisWithFileTests(DisTests):
|
|||
if sys.flags.optimize:
|
||||
code_info_consts = "0: None"
|
||||
else:
|
||||
code_info_consts = (
|
||||
"""0: 'Formatted details of methods, functions, or code.'
|
||||
1: None"""
|
||||
)
|
||||
code_info_consts = "0: 'Formatted details of methods, functions, or code.'"
|
||||
|
||||
code_info_code_info = f"""\
|
||||
Name: code_info
|
||||
|
@ -816,7 +813,6 @@ Flags: NOFREE
|
|||
Constants:
|
||||
0: 0
|
||||
1: 1
|
||||
2: None
|
||||
Names:
|
||||
0: x"""
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Compiler now removes trailing unused constants from co_consts.
|
|
@ -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;
|
||||
|
|
2941
Python/importlib.h
generated
2941
Python/importlib.h
generated
File diff suppressed because it is too large
Load diff
4744
Python/importlib_external.h
generated
4744
Python/importlib_external.h
generated
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue