gh-141367: Use CALL_LIST_APPEND instruction only for lists, not for l… · python/cpython@1281be1 · GitHub
Skip to content

Commit 1281be1

Browse files
gh-141367: Use CALL_LIST_APPEND instruction only for lists, not for list subclasses (GH-141398)
Co-authored-by: Ken Jin <kenjin4096@gmail.com>
1 parent f26ed45 commit 1281be1

7 files changed

Lines changed: 44 additions & 20 deletions

File tree

Include/internal/pycore_code.h

Lines changed: 2 additions & 2 deletions

Lib/test/test_opcache.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,6 +1872,33 @@ def for_iter_generator():
18721872
self.assert_specialized(for_iter_generator, "FOR_ITER_GEN")
18731873
self.assert_no_opcode(for_iter_generator, "FOR_ITER")
18741874

1875+
@cpython_only
1876+
@requires_specialization_ft
1877+
def test_call_list_append(self):
1878+
# gh-141367: only exact lists should use
1879+
# CALL_LIST_APPEND instruction after specialization.
1880+
1881+
r = range(_testinternalcapi.SPECIALIZATION_THRESHOLD)
1882+
1883+
def list_append(l):
1884+
for _ in r:
1885+
l.append(1)
1886+
1887+
list_append([])
1888+
self.assert_specialized(list_append, "CALL_LIST_APPEND")
1889+
self.assert_no_opcode(list_append, "CALL_METHOD_DESCRIPTOR_O")
1890+
self.assert_no_opcode(list_append, "CALL")
1891+
1892+
def my_list_append(l):
1893+
for _ in r:
1894+
l.append(1)
1895+
1896+
class MyList(list): pass
1897+
my_list_append(MyList())
1898+
self.assert_specialized(my_list_append, "CALL_METHOD_DESCRIPTOR_O")
1899+
self.assert_no_opcode(my_list_append, "CALL_LIST_APPEND")
1900+
self.assert_no_opcode(my_list_append, "CALL")
1901+
18751902

18761903
if __name__ == "__main__":
18771904
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Specialize ``CALL_LIST_APPEND`` instruction only for lists, not for list
2+
subclasses, to avoid unnecessary deopt. Patch by Mikhail Efimov.

Python/bytecodes.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3689,7 +3689,7 @@ dummy_func(
36893689
#if ENABLE_SPECIALIZATION_FT
36903690
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
36913691
next_instr = this_instr;
3692-
_Py_Specialize_Call(callable, next_instr, oparg + !PyStackRef_IsNull(self_or_null));
3692+
_Py_Specialize_Call(callable, self_or_null, next_instr, oparg + !PyStackRef_IsNull(self_or_null));
36933693
DISPATCH_SAME_OPARG();
36943694
}
36953695
OPCODE_DEFERRED_INC(CALL);
@@ -4395,7 +4395,6 @@ dummy_func(
43954395
assert(oparg == 1);
43964396
PyObject *self_o = PyStackRef_AsPyObjectBorrow(self);
43974397

4398-
DEOPT_IF(!PyList_CheckExact(self_o));
43994398
DEOPT_IF(!LOCK_OBJECT(self_o));
44004399
STAT_INC(CALL, hit);
44014400
int err = _PyList_AppendTakeRef((PyListObject *)self_o, PyStackRef_AsPyObjectSteal(arg));

Python/executor_cases.c.h

Lines changed: 0 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 1 addition & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/specialize.c

Lines changed: 11 additions & 6 deletions

0 commit comments

Comments
 (0)