Skip to content

Commit fbb6def

Browse files
authored
[3.11] GH-104405: Add missing PEP 523 checks (GH-104441)
1 parent 4ade7c3 commit fbb6def

File tree

4 files changed

+36
-18
lines changed

4 files changed

+36
-18
lines changed

Lib/test/test_capi/test_misc.py

+29-18
Original file line numberDiff line numberDiff line change
@@ -1378,28 +1378,39 @@ def dummy():
13781378

13791379
class Test_Pep523API(unittest.TestCase):
13801380

1381-
def do_test(self, func):
1382-
calls = []
1381+
def do_test(self, func, names):
1382+
actual_calls = []
13831383
start = SUFFICIENT_TO_DEOPT_AND_SPECIALIZE
13841384
count = start + SUFFICIENT_TO_DEOPT_AND_SPECIALIZE
1385-
for i in range(count):
1386-
if i == start:
1387-
_testinternalcapi.set_eval_frame_record(calls)
1388-
func()
1389-
_testinternalcapi.set_eval_frame_default()
1390-
self.assertEqual(len(calls), SUFFICIENT_TO_DEOPT_AND_SPECIALIZE)
1391-
for name in calls:
1392-
self.assertEqual(name, func.__name__)
1393-
1394-
def test_pep523_with_specialization_simple(self):
1395-
def func1():
1396-
pass
1397-
self.do_test(func1)
1385+
try:
1386+
for i in range(count):
1387+
if i == start:
1388+
_testinternalcapi.set_eval_frame_record(actual_calls)
1389+
func()
1390+
finally:
1391+
_testinternalcapi.set_eval_frame_default()
1392+
expected_calls = names * SUFFICIENT_TO_DEOPT_AND_SPECIALIZE
1393+
self.assertEqual(len(expected_calls), len(actual_calls))
1394+
for expected, actual in zip(expected_calls, actual_calls, strict=True):
1395+
self.assertEqual(expected, actual)
1396+
1397+
def test_inlined_binary_subscr(self):
1398+
class C:
1399+
def __getitem__(self, other):
1400+
return None
1401+
def func():
1402+
C()[42]
1403+
names = ["func", "__getitem__"]
1404+
self.do_test(func, names)
13981405

1399-
def test_pep523_with_specialization_with_default(self):
1400-
def func2(x=None):
1406+
def test_inlined_call(self):
1407+
def inner(x=42):
14011408
pass
1402-
self.do_test(func2)
1409+
def func():
1410+
inner()
1411+
inner(42)
1412+
names = ["func", "inner", "inner"]
1413+
self.do_test(func, names)
14031414

14041415

14051416
if __name__ == "__main__":
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix an issue where some :term:`bytecode` instructions could ignore
2+
:pep:`523` when "inlining" calls.

Python/ceval.c

+1
Original file line numberDiff line numberDiff line change
@@ -2233,6 +2233,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
22332233
}
22342234

22352235
TARGET(BINARY_SUBSCR_GETITEM) {
2236+
DEOPT_IF(tstate->interp->eval_frame, BINARY_SUBSCR);
22362237
PyObject *sub = TOP();
22372238
PyObject *container = SECOND();
22382239
_PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr;

Python/specialize.c

+4
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,10 @@ _Py_Specialize_BinarySubscr(
12381238
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_VERSIONS);
12391239
goto fail;
12401240
}
1241+
if (_PyInterpreterState_GET()->eval_frame) {
1242+
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OTHER);
1243+
goto fail;
1244+
}
12411245
cache->func_version = version;
12421246
((PyHeapTypeObject *)container_type)->_spec_cache.getitem = descriptor;
12431247
_Py_SET_OPCODE(*instr, BINARY_SUBSCR_GETITEM);

0 commit comments

Comments
 (0)