Skip to content

Commit 42ed55b

Browse files
committed
fix
1 parent 23d5d49 commit 42ed55b

File tree

3 files changed

+16
-11
lines changed

3 files changed

+16
-11
lines changed

Lib/test/test_opcache.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ def assert_races_do_not_crash(
609609
for writer in writers:
610610
writer.join()
611611

612-
@requires_specialization_ft
612+
@requires_specialization
613613
def test_binary_subscr_getitem(self):
614614
def get_items():
615615
class C:
@@ -1245,6 +1245,14 @@ def f(o, n):
12451245
f(test_obj, 1)
12461246
self.assertEqual(test_obj.b, 0)
12471247

1248+
# gh-115999: BINARY_SUBSCR_GETITEM will only cache __getitem__ methods that
1249+
# are deferred. We only defer functions defined at the top-level.
1250+
class CGetItem:
1251+
def __init__(self, val):
1252+
self.val = val
1253+
def __getitem__(self, item):
1254+
return self.val
1255+
12481256

12491257
class TestSpecializer(TestBase):
12501258

@@ -1521,12 +1529,7 @@ def binary_subscr_str_int():
15211529
self.assert_no_opcode(binary_subscr_str_int, "BINARY_SUBSCR")
15221530

15231531
def binary_subscr_getitems():
1524-
class C:
1525-
def __init__(self, val):
1526-
self.val = val
1527-
def __getitem__(self, item):
1528-
return self.val
1529-
items = [C(i) for i in range(100)]
1532+
items = [CGetItem(i) for i in range(100)]
15301533
for i in range(100):
15311534
self.assertEqual(items[i][i], i)
15321535

Objects/typeobject.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5693,17 +5693,19 @@ _PyType_CacheInitForSpecialization(PyHeapTypeObject *type, PyObject *init,
56935693
}
56945694

56955695
int
5696-
_PyType_CacheGetItemForSpecialization(PyHeapTypeObject *ht, PyObject *descriptor, uint32_t version)
5696+
_PyType_CacheGetItemForSpecialization(PyHeapTypeObject *ht, PyObject *descriptor, uint32_t tp_version)
56975697
{
5698-
if (!descriptor || !version) {
5698+
if (!descriptor || !tp_version) {
56995699
return 0;
57005700
}
57015701
int can_cache;
57025702
BEGIN_TYPE_LOCK();
5703+
can_cache = ((PyTypeObject*)ht)->tp_version_tag == tp_version;
57035704
// This pointer is invalidated by PyType_Modified (see the comment on
57045705
// struct _specialization_cache):
57055706
PyFunctionObject *func = (PyFunctionObject *)descriptor;
5706-
can_cache = _PyFunction_GetVersionForCurrentState(func) == version;
5707+
uint32_t version = _PyFunction_GetVersionForCurrentState(func);
5708+
can_cache = _PyFunction_IsVersionValid(version);
57075709
#ifdef Py_GIL_DISABLED
57085710
can_cache = can_cache && _PyObject_HasDeferredRefcount(descriptor);
57095711
#endif

Python/specialize.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1797,8 +1797,8 @@ _Py_Specialize_BinarySubscr(
17971797
Py_DECREF(descriptor);
17981798
goto success;
17991799
}
1800-
Py_DECREF(descriptor);
18011800
}
1801+
Py_XDECREF(descriptor);
18021802
SPECIALIZATION_FAIL(BINARY_SUBSCR,
18031803
binary_subscr_fail_kind(container_type, sub));
18041804
fail:

0 commit comments

Comments
 (0)