Skip to content

Commit 6d0e011

Browse files
committed
Specialize __setitem__ dunder method for STORE_SUBSCR
This is precursuor for JIT improvements but also results in standard improvements due to specializing the bytecode
1 parent af49df9 commit 6d0e011

18 files changed

Lines changed: 408 additions & 56 deletions

Include/internal/pycore_code.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ typedef struct {
131131

132132
typedef struct {
133133
_Py_BackoffCounter counter;
134+
uint16_t version[2]; /* gh-143732: container type version for STORE_SUBSCR_PY_DUNDER */
134135
} _PyStoreSubscrCache;
135136

136137
#define INLINE_CACHE_ENTRIES_STORE_SUBSCR CACHE_ENTRIES(_PyStoreSubscrCache)

Include/internal/pycore_opcode_metadata.h

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

Include/internal/pycore_uop_ids.h

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

Include/internal/pycore_uop_metadata.h

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

Include/opcode_ids.h

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

Lib/_opcode_metadata.py

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

Lib/test/test_dis.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,8 @@ def wrap_func_w_kwargs():
410410
LOAD_SMALL_INT 0
411411
CALL 1
412412
STORE_SUBSCR
413+
CACHE
414+
CACHE
413415
LOAD_COMMON_CONSTANT 7 (None)
414416
RETURN_VALUE
415417
"""

Lib/test/test_opcache.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,36 @@ def write(items):
691691
opname = "BINARY_OP_SUBSCR_GETITEM"
692692
self.assert_races_do_not_crash(opname, get_items, read, write)
693693

694+
@requires_specialization
695+
def test_store_subscr_py_dunder(self):
696+
def get_items():
697+
class C:
698+
__setitem__ = lambda self, item, value: None
699+
700+
items = []
701+
for _ in range(self.ITEMS):
702+
item = C()
703+
items.append(item)
704+
return items
705+
706+
def read(items):
707+
for item in items:
708+
try:
709+
item[None] = None
710+
except TypeError:
711+
pass
712+
713+
def write(items):
714+
for item in items:
715+
try:
716+
del item.__setitem__
717+
except AttributeError:
718+
pass
719+
type(item).__setitem__ = lambda self, item, value: None
720+
721+
opname = "STORE_SUBSCR_PY_DUNDER"
722+
self.assert_races_do_not_crash(opname, get_items, read, write)
723+
694724
@requires_specialization
695725
def test_binary_subscr_list_int(self):
696726
def get_items():
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Specialize :opcode:`STORE_SUBSCR` for container objects whose type defines
2+
``__setitem__`` as a simple Python function. The new ``STORE_SUBSCR_PY_DUNDER``
3+
specialization guards on the container's type version and calls the dunder
4+
directly, skipping the generic ``PyObject_SetItem`` slot dispatch.

0 commit comments

Comments
 (0)