bpo-42217: compiler: merge same co_code and co_linetable objects (GH-23056)

This commit is contained in:
Inada Naoki 2021-02-10 09:20:42 +09:00 committed by GitHub
parent dbb228189b
commit bdb941be42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 3849 additions and 3849 deletions

View File

@ -632,6 +632,17 @@ if 1:
self.check_constant(f1, frozenset({0})) self.check_constant(f1, frozenset({0}))
self.assertTrue(f1(0)) self.assertTrue(f1(0))
# Merging equal co_linetable and co_code is not a strict requirement
# for the Python semantics, it's a more an implementation detail.
@support.cpython_only
def test_merge_code_attrs(self):
# See https://bugs.python.org/issue42217
f1 = lambda x: x.y.z
f2 = lambda a: a.b.c
self.assertIs(f1.__code__.co_linetable, f2.__code__.co_linetable)
self.assertIs(f1.__code__.co_code, f2.__code__.co_code)
# 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

View File

@ -0,0 +1 @@
Make the compiler merges same co_code and co_linetable objects in a module like already did for co_consts.

View File

@ -5806,14 +5806,12 @@ compute_code_flags(struct compiler *c)
return flags; return flags;
} }
// Merge *tuple* with constant cache. // Merge *obj* with constant cache.
// Unlike merge_consts_recursive(), this function doesn't work recursively. // Unlike merge_consts_recursive(), this function doesn't work recursively.
static int static int
merge_const_tuple(struct compiler *c, PyObject **tuple) merge_const_one(struct compiler *c, PyObject **obj)
{ {
assert(PyTuple_CheckExact(*tuple)); PyObject *key = _PyCode_ConstantKey(*obj);
PyObject *key = _PyCode_ConstantKey(*tuple);
if (key == NULL) { if (key == NULL) {
return 0; return 0;
} }
@ -5824,14 +5822,18 @@ merge_const_tuple(struct compiler *c, PyObject **tuple)
if (t == NULL) { if (t == NULL) {
return 0; return 0;
} }
if (t == key) { // tuple is new constant. if (t == key) { // obj is new constant.
return 1; return 1;
} }
PyObject *u = PyTuple_GET_ITEM(t, 1); if (PyTuple_CheckExact(t)) {
Py_INCREF(u); // t is still borrowed reference
Py_DECREF(*tuple); t = PyTuple_GET_ITEM(t, 1);
*tuple = u; }
Py_INCREF(t);
Py_DECREF(*obj);
*obj = t;
return 1; return 1;
} }
@ -5861,10 +5863,10 @@ makecode(struct compiler *c, struct assembler *a, PyObject *consts)
if (!freevars) if (!freevars)
goto error; goto error;
if (!merge_const_tuple(c, &names) || if (!merge_const_one(c, &names) ||
!merge_const_tuple(c, &varnames) || !merge_const_one(c, &varnames) ||
!merge_const_tuple(c, &cellvars) || !merge_const_one(c, &cellvars) ||
!merge_const_tuple(c, &freevars)) !merge_const_one(c, &freevars))
{ {
goto error; goto error;
} }
@ -5881,7 +5883,7 @@ makecode(struct compiler *c, struct assembler *a, PyObject *consts)
if (consts == NULL) { if (consts == NULL) {
goto error; goto error;
} }
if (!merge_const_tuple(c, &consts)) { if (!merge_const_one(c, &consts)) {
Py_DECREF(consts); Py_DECREF(consts);
goto error; goto error;
} }
@ -6028,10 +6030,18 @@ assemble(struct compiler *c, int addNone)
goto error; goto error;
} }
if (_PyBytes_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) if (_PyBytes_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) {
goto error; goto error;
if (_PyBytes_Resize(&a.a_bytecode, a.a_offset * sizeof(_Py_CODEUNIT)) < 0) }
if (!merge_const_one(c, &a.a_lnotab)) {
goto error; goto error;
}
if (_PyBytes_Resize(&a.a_bytecode, a.a_offset * sizeof(_Py_CODEUNIT)) < 0) {
goto error;
}
if (!merge_const_one(c, &a.a_bytecode)) {
goto error;
}
co = makecode(c, &a, consts); co = makecode(c, &a, consts);
error: error:

3144
Python/importlib.h generated

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff