Skip to content

Commit 644baae

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 644baae

20 files changed

Lines changed: 416 additions & 56 deletions

Include/internal/pycore_call.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ extern PyObject* _PyObject_Call_Prepend(
3939
PyObject *args,
4040
PyObject *kwargs);
4141

42+
PyAPI_FUNC(int) _PyObject_CallSetItemDunder(
43+
PyThreadState *tstate,
44+
PyObject *func,
45+
PyObject *self,
46+
PyObject *key,
47+
PyObject *value);
48+
4249
extern PyObject* _PyObject_VectorcallDictTstate(
4350
PyThreadState *tstate,
4451
PyObject *callable,

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];
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)