Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bdb941b

Browse files
authored
bpo-42217: compiler: merge same co_code and co_linetable objects (GH-23056)
1 parent dbb2281 commit bdb941b

File tree

5 files changed

+3847
-3847
lines changed

5 files changed

+3847
-3847
lines changed

Lib/test/test_compile.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,17 @@ def check_same_constant(const):
632632
self.check_constant(f1, frozenset({0}))
633633
self.assertTrue(f1(0))
634634

635+
# Merging equal co_linetable and co_code is not a strict requirement
636+
# for the Python semantics, it's a more an implementation detail.
637+
@support.cpython_only
638+
def test_merge_code_attrs(self):
639+
# See https://bugs.python.org/issue42217
640+
f1 = lambda x: x.y.z
641+
f2 = lambda a: a.b.c
642+
643+
self.assertIs(f1.__code__.co_linetable, f2.__code__.co_linetable)
644+
self.assertIs(f1.__code__.co_code, f2.__code__.co_code)
645+
635646
# This is a regression test for a CPython specific peephole optimizer
636647
# implementation bug present in a few releases. It's assertion verifies
637648
# that peephole optimization was actually done though that isn't an
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Make the compiler merges same co_code and co_linetable objects in a module like already did for co_consts.

Python/compile.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5806,14 +5806,12 @@ compute_code_flags(struct compiler *c)
58065806
return flags;
58075807
}
58085808

5809-
// Merge *tuple* with constant cache.
5809+
// Merge *obj* with constant cache.
58105810
// Unlike merge_consts_recursive(), this function doesn't work recursively.
58115811
static int
5812-
merge_const_tuple(struct compiler *c, PyObject **tuple)
5812+
merge_const_one(struct compiler *c, PyObject **obj)
58135813
{
5814-
assert(PyTuple_CheckExact(*tuple));
5815-
5816-
PyObject *key = _PyCode_ConstantKey(*tuple);
5814+
PyObject *key = _PyCode_ConstantKey(*obj);
58175815
if (key == NULL) {
58185816
return 0;
58195817
}
@@ -5824,14 +5822,18 @@ merge_const_tuple(struct compiler *c, PyObject **tuple)
58245822
if (t == NULL) {
58255823
return 0;
58265824
}
5827-
if (t == key) { // tuple is new constant.
5825+
if (t == key) { // obj is new constant.
58285826
return 1;
58295827
}
58305828

5831-
PyObject *u = PyTuple_GET_ITEM(t, 1);
5832-
Py_INCREF(u);
5833-
Py_DECREF(*tuple);
5834-
*tuple = u;
5829+
if (PyTuple_CheckExact(t)) {
5830+
// t is still borrowed reference
5831+
t = PyTuple_GET_ITEM(t, 1);
5832+
}
5833+
5834+
Py_INCREF(t);
5835+
Py_DECREF(*obj);
5836+
*obj = t;
58355837
return 1;
58365838
}
58375839

@@ -5861,10 +5863,10 @@ makecode(struct compiler *c, struct assembler *a, PyObject *consts)
58615863
if (!freevars)
58625864
goto error;
58635865

5864-
if (!merge_const_tuple(c, &names) ||
5865-
!merge_const_tuple(c, &varnames) ||
5866-
!merge_const_tuple(c, &cellvars) ||
5867-
!merge_const_tuple(c, &freevars))
5866+
if (!merge_const_one(c, &names) ||
5867+
!merge_const_one(c, &varnames) ||
5868+
!merge_const_one(c, &cellvars) ||
5869+
!merge_const_one(c, &freevars))
58685870
{
58695871
goto error;
58705872
}
@@ -5881,7 +5883,7 @@ makecode(struct compiler *c, struct assembler *a, PyObject *consts)
58815883
if (consts == NULL) {
58825884
goto error;
58835885
}
5884-
if (!merge_const_tuple(c, &consts)) {
5886+
if (!merge_const_one(c, &consts)) {
58855887
Py_DECREF(consts);
58865888
goto error;
58875889
}
@@ -6028,10 +6030,18 @@ assemble(struct compiler *c, int addNone)
60286030
goto error;
60296031
}
60306032

6031-
if (_PyBytes_Resize(&a.a_lnotab, a.a_lnotab_off) < 0)
6033+
if (_PyBytes_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) {
60326034
goto error;
6033-
if (_PyBytes_Resize(&a.a_bytecode, a.a_offset * sizeof(_Py_CODEUNIT)) < 0)
6035+
}
6036+
if (!merge_const_one(c, &a.a_lnotab)) {
60346037
goto error;
6038+
}
6039+
if (_PyBytes_Resize(&a.a_bytecode, a.a_offset * sizeof(_Py_CODEUNIT)) < 0) {
6040+
goto error;
6041+
}
6042+
if (!merge_const_one(c, &a.a_bytecode)) {
6043+
goto error;
6044+
}
60356045

60366046
co = makecode(c, &a, consts);
60376047
error:

0 commit comments

Comments
 (0)