Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Include/internal/pycore_call.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ extern PyObject* _PyObject_Call_Prepend(
PyObject *args,
PyObject *kwargs);

PyAPI_FUNC(int) _PyObject_CallSetItemDunder(
PyThreadState *tstate,
PyObject *func,
PyObject *self,
PyObject *key,
PyObject *value);

extern PyObject* _PyObject_VectorcallDictTstate(
PyThreadState *tstate,
PyObject *callable,
Expand Down
1 change: 1 addition & 0 deletions Include/internal/pycore_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ typedef struct {

typedef struct {
_Py_BackoffCounter counter;
uint16_t version[2];
} _PyStoreSubscrCache;

#define INLINE_CACHE_ENTRIES_STORE_SUBSCR CACHE_ENTRIES(_PyStoreSubscrCache)
Expand Down
3 changes: 2 additions & 1 deletion Include/internal/pycore_magic_number.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ Known values:
Python 3.16a1 3703 (Replace DELETE_GLOBAL with PUSH_NULL; STORE_GLOBAL)
Python 3.16a1 3704 (Replace DELETE_ATTR with PUSH_NULL; STORE_ATTR)
Python 3.16a1 3705 (Add INTRINSIC_ADD_CONDITIONAL_ANNOTATION)
Python 3.16a1 3706 (Add STORE_SUBSCR_PY_DUNDER)

Python 3.17 will start with 3750

Expand All @@ -312,7 +313,7 @@ Known values:

*/

#define PYC_MAGIC_NUMBER 3705
#define PYC_MAGIC_NUMBER 3706
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
(little-endian) and then appending b'\r\n'. */
#define PYC_MAGIC_NUMBER_TOKEN \
Expand Down
24 changes: 15 additions & 9 deletions Include/internal/pycore_opcode_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions Include/internal/pycore_uop_ids.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions Include/internal/pycore_uop_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 10 additions & 9 deletions Include/opcode_ids.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 11 additions & 9 deletions Lib/_opcode_metadata.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
),
STORE_SUBSCR=frozendict(
counter=1,
version=2,
),
SEND=frozendict(
counter=1,
Expand Down
30 changes: 30 additions & 0 deletions Lib/test/test_opcache.py
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,36 @@ def write(items):
opname = "BINARY_OP_SUBSCR_GETITEM"
self.assert_races_do_not_crash(opname, get_items, read, write)

@requires_specialization
def test_store_subscr_py_dunder(self):
def get_items():
class C:
__setitem__ = lambda self, item, value: None

items = []
for _ in range(self.ITEMS):
item = C()
items.append(item)
return items

def read(items):
for item in items:
try:
item[None] = None
except TypeError:
pass

def write(items):
for item in items:
try:
del item.__setitem__
except AttributeError:
pass
type(item).__setitem__ = lambda self, item, value: None

opname = "STORE_SUBSCR_PY_DUNDER"
self.assert_races_do_not_crash(opname, get_items, read, write)

@requires_specialization
def test_binary_subscr_list_int(self):
def get_items():
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Specialize :opcode:`STORE_SUBSCR` for container objects whose type defines
``__setitem__`` as a simple Python function. The new ``STORE_SUBSCR_PY_DUNDER``
specialization guards on the container's type version and calls the dunder
directly, skipping the generic ``PyObject_SetItem`` slot dispatch.
Loading
Loading