Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork34k
Open
Description
Consider
classC:def__init__(self,a,b,c):self.a=aself.b=bself.c=cC(1,2,3)
This produces a trace looking something like this:
..._CHECK_AND_ALLOCATE_OBJECT_CREATE_INIT_FRAME_PUSH_FRAME# Some guards_LOAD_FAST_BORROW_1_LOAD_FAST_BORROW_0# Some more guards_STORE_ATTR_INSTANCE_VALUE# Some more guards_LOAD_FAST_BORROW_2_LOAD_FAST_BORROW_0# Some more guards_STORE_ATTR_INSTANCE_VALUE# Some more guards_LOAD_FAST_BORROW_3_LOAD_FAST_BORROW_0# Some more guards_STORE_ATTR_INSTANCE_VALUE...Each of those_STORE_ATTR_INSTANCE_VALUE reads the old value out of memory and then conditionally decrefs it.
But in this case we know that the old value wasNULL so we can just overwrite it.
So we can replace this:
PyObject**value_ptr= (PyObject**)(((char*)owner_o)+offset);PyObject*old_value=*value_ptr;FT_ATOMIC_STORE_PTR_RELEASE(*value_ptr,PyStackRef_AsPyObjectSteal(value));if (old_value==NULL) {PyDictValues*values=_PyObject_InlineValues(owner_o);Py_ssize_tindex=value_ptr-values->values;_PyDictValues_AddToInsertionOrder(values,index); }Py_XDECREF(old_value);
with this:
PyObject**value_ptr= (PyObject**)(((char*)owner_o)+offset);FT_ATOMIC_STORE_PTR_RELEASE(*value_ptr,PyStackRef_AsPyObjectSteal(value));PyDictValues*values=_PyObject_InlineValues(owner_o);Py_ssize_tindex=value_ptr-values->values;_PyDictValues_AddToInsertionOrder(values,index);
On Aarch64, this reduces the number of machine instructions from 48 to 26.
The same reasoning also applies to_STORE_ATTR_SLOT where it reduces the number of machine instructions from 32 to 14.
See also#134584
We can probably remove some of those guards as well, but that's a separate issue.