mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
bpo-45056: Remove trailing unused constants from co_consts (GH-28109)
This commit is contained in:
parent
19ba2122ac
commit
55c4a92fc1
7 changed files with 6369 additions and 6331 deletions
|
@ -650,6 +650,17 @@ if 1:
|
||||||
self.assertIs(f1.__code__.co_linetable, f2.__code__.co_linetable)
|
self.assertIs(f1.__code__.co_linetable, f2.__code__.co_linetable)
|
||||||
self.assertIs(f1.__code__.co_code, f2.__code__.co_code)
|
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
|
# This is a regression test for a CPython specific peephole optimizer
|
||||||
# implementation bug present in a few releases. It's assertion verifies
|
# implementation bug present in a few releases. It's assertion verifies
|
||||||
# that peephole optimization was actually done though that isn't an
|
# that peephole optimization was actually done though that isn't an
|
||||||
|
|
|
@ -702,10 +702,7 @@ class DisWithFileTests(DisTests):
|
||||||
if sys.flags.optimize:
|
if sys.flags.optimize:
|
||||||
code_info_consts = "0: None"
|
code_info_consts = "0: None"
|
||||||
else:
|
else:
|
||||||
code_info_consts = (
|
code_info_consts = "0: 'Formatted details of methods, functions, or code.'"
|
||||||
"""0: 'Formatted details of methods, functions, or code.'
|
|
||||||
1: None"""
|
|
||||||
)
|
|
||||||
|
|
||||||
code_info_code_info = f"""\
|
code_info_code_info = f"""\
|
||||||
Name: code_info
|
Name: code_info
|
||||||
|
@ -828,7 +825,6 @@ Flags: 0x0
|
||||||
Constants:
|
Constants:
|
||||||
0: 0
|
0: 0
|
||||||
1: 1
|
1: 1
|
||||||
2: None
|
|
||||||
Names:
|
Names:
|
||||||
0: x"""
|
0: x"""
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Compiler now removes trailing unused constants from co_consts.
|
|
@ -7573,6 +7573,9 @@ normalize_basic_block(basicblock *bb);
|
||||||
static int
|
static int
|
||||||
optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts);
|
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 */
|
/* Duplicates exit BBs, so that line numbers can be propagated to them */
|
||||||
static int
|
static int
|
||||||
duplicate_exits_without_lineno(struct compiler *c);
|
duplicate_exits_without_lineno(struct compiler *c);
|
||||||
|
@ -7870,6 +7873,9 @@ assemble(struct compiler *c, int addNone)
|
||||||
if (duplicate_exits_without_lineno(c)) {
|
if (duplicate_exits_without_lineno(c)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (trim_unused_consts(c, &a, consts)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
propagate_line_numbers(&a);
|
propagate_line_numbers(&a);
|
||||||
guarantee_lineno_for_exits(&a, c->u->u_firstlineno);
|
guarantee_lineno_for_exits(&a, c->u->u_firstlineno);
|
||||||
int maxdepth = stackdepth(c);
|
int maxdepth = stackdepth(c);
|
||||||
|
@ -8599,6 +8605,33 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts)
|
||||||
return 0;
|
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
|
static inline int
|
||||||
is_exit_without_lineno(basicblock *b) {
|
is_exit_without_lineno(basicblock *b) {
|
||||||
return b->b_exit && b->b_instr[0].i_lineno < 0;
|
return b->b_exit && b->b_instr[0].i_lineno < 0;
|
||||||
|
|
4101
Python/frozen_modules/importlib__bootstrap.h
generated
4101
Python/frozen_modules/importlib__bootstrap.h
generated
File diff suppressed because it is too large
Load diff
6242
Python/frozen_modules/importlib__bootstrap_external.h
generated
6242
Python/frozen_modules/importlib__bootstrap_external.h
generated
File diff suppressed because it is too large
Load diff
2306
Python/frozen_modules/zipimport.h
generated
2306
Python/frozen_modules/zipimport.h
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue