mirror of
https://github.com/python/cpython.git
synced 2025-08-24 02:35:59 +00:00
GH-130296: Avoid stack transients in four instructions. (GH-130310)
* Combine _GUARD_GLOBALS_VERSION_PUSH_KEYS and _LOAD_GLOBAL_MODULE_FROM_KEYS into _LOAD_GLOBAL_MODULE * Combine _GUARD_BUILTINS_VERSION_PUSH_KEYS and _LOAD_GLOBAL_BUILTINS_FROM_KEYS into _LOAD_GLOBAL_BUILTINS * Combine _CHECK_ATTR_MODULE_PUSH_KEYS and _LOAD_ATTR_MODULE_FROM_KEYS into _LOAD_ATTR_MODULE * Remove stack transient in LOAD_ATTR_WITH_HINT
This commit is contained in:
parent
ab11c09705
commit
54965f3fb2
15 changed files with 615 additions and 1005 deletions
|
@ -1689,70 +1689,55 @@ dummy_func(
|
|||
assert(DK_IS_UNICODE(keys));
|
||||
}
|
||||
|
||||
op(_GUARD_GLOBALS_VERSION_PUSH_KEYS, (version / 1 -- globals_keys: PyDictKeysObject *))
|
||||
op(_LOAD_GLOBAL_MODULE, (version/1, unused/1, index/1 -- res))
|
||||
{
|
||||
PyDictObject *dict = (PyDictObject *)GLOBALS();
|
||||
DEOPT_IF(!PyDict_CheckExact(dict));
|
||||
PyDictKeysObject *keys = FT_ATOMIC_LOAD_PTR_ACQUIRE(dict->ma_keys);
|
||||
DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != version);
|
||||
globals_keys = keys;
|
||||
assert(DK_IS_UNICODE(globals_keys));
|
||||
assert(DK_IS_UNICODE(keys));
|
||||
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys);
|
||||
assert(index < DK_SIZE(keys));
|
||||
PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value);
|
||||
DEOPT_IF(res_o == NULL);
|
||||
#if Py_GIL_DISABLED
|
||||
int increfed = _Py_TryIncrefCompareStackRef(&entries[index].me_value, res_o, &res);
|
||||
DEOPT_IF(!increfed);
|
||||
#else
|
||||
res = PyStackRef_FromPyObjectNew(res_o);
|
||||
#endif
|
||||
STAT_INC(LOAD_GLOBAL, hit);
|
||||
}
|
||||
|
||||
op(_GUARD_BUILTINS_VERSION_PUSH_KEYS, (version / 1 -- builtins_keys: PyDictKeysObject *))
|
||||
op(_LOAD_GLOBAL_BUILTINS, (version/1, index/1 -- res))
|
||||
{
|
||||
PyDictObject *dict = (PyDictObject *)BUILTINS();
|
||||
DEOPT_IF(!PyDict_CheckExact(dict));
|
||||
PyDictKeysObject *keys = FT_ATOMIC_LOAD_PTR_ACQUIRE(dict->ma_keys);
|
||||
DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != version);
|
||||
builtins_keys = keys;
|
||||
assert(DK_IS_UNICODE(builtins_keys));
|
||||
}
|
||||
|
||||
op(_LOAD_GLOBAL_MODULE_FROM_KEYS, (index/1, globals_keys: PyDictKeysObject* -- res)) {
|
||||
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(globals_keys);
|
||||
assert(DK_IS_UNICODE(keys));
|
||||
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys);
|
||||
PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value);
|
||||
DEAD(globals_keys);
|
||||
SYNC_SP();
|
||||
DEOPT_IF(res_o == NULL);
|
||||
#if Py_GIL_DISABLED
|
||||
int increfed = _Py_TryIncrefCompareStackRef(&entries[index].me_value, res_o, &res);
|
||||
DEOPT_IF(!increfed);
|
||||
#else
|
||||
Py_INCREF(res_o);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
#endif
|
||||
STAT_INC(LOAD_GLOBAL, hit);
|
||||
}
|
||||
|
||||
op(_LOAD_GLOBAL_BUILTINS_FROM_KEYS, (index/1, builtins_keys: PyDictKeysObject* -- res)) {
|
||||
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(builtins_keys);
|
||||
PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value);
|
||||
DEAD(builtins_keys);
|
||||
SYNC_SP();
|
||||
DEOPT_IF(res_o == NULL);
|
||||
#if Py_GIL_DISABLED
|
||||
int increfed = _Py_TryIncrefCompareStackRef(&entries[index].me_value, res_o, &res);
|
||||
DEOPT_IF(!increfed);
|
||||
#else
|
||||
Py_INCREF(res_o);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
res = PyStackRef_FromPyObjectNew(res_o);
|
||||
#endif
|
||||
STAT_INC(LOAD_GLOBAL, hit);
|
||||
}
|
||||
|
||||
macro(LOAD_GLOBAL_MODULE) =
|
||||
unused/1 + // Skip over the counter
|
||||
_GUARD_GLOBALS_VERSION_PUSH_KEYS +
|
||||
unused/1 + // Skip over the builtins version
|
||||
_LOAD_GLOBAL_MODULE_FROM_KEYS +
|
||||
NOP + // For guard insertion in the JIT optimizer
|
||||
_LOAD_GLOBAL_MODULE +
|
||||
_PUSH_NULL_CONDITIONAL;
|
||||
|
||||
macro(LOAD_GLOBAL_BUILTIN) =
|
||||
unused/1 + // Skip over the counter
|
||||
_GUARD_GLOBALS_VERSION +
|
||||
_GUARD_BUILTINS_VERSION_PUSH_KEYS +
|
||||
_LOAD_GLOBAL_BUILTINS_FROM_KEYS +
|
||||
_LOAD_GLOBAL_BUILTINS +
|
||||
_PUSH_NULL_CONDITIONAL;
|
||||
|
||||
inst(DELETE_FAST, (--)) {
|
||||
|
@ -2247,23 +2232,17 @@ dummy_func(
|
|||
unused/5 +
|
||||
_PUSH_NULL_CONDITIONAL;
|
||||
|
||||
op(_CHECK_ATTR_MODULE_PUSH_KEYS, (dict_version/2, owner -- owner, mod_keys: PyDictKeysObject *)) {
|
||||
op(_LOAD_ATTR_MODULE, (dict_version/2, index/1, owner -- attr)) {
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
DEOPT_IF(Py_TYPE(owner_o)->tp_getattro != PyModule_Type.tp_getattro);
|
||||
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner_o)->md_dict;
|
||||
assert(dict != NULL);
|
||||
PyDictKeysObject *keys = FT_ATOMIC_LOAD_PTR_ACQUIRE(dict->ma_keys);
|
||||
DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != dict_version);
|
||||
mod_keys = keys;
|
||||
}
|
||||
|
||||
op(_LOAD_ATTR_MODULE_FROM_KEYS, (index/1, owner, mod_keys: PyDictKeysObject * -- attr)) {
|
||||
assert(mod_keys->dk_kind == DICT_KEYS_UNICODE);
|
||||
assert(index < FT_ATOMIC_LOAD_SSIZE_RELAXED(mod_keys->dk_nentries));
|
||||
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(mod_keys) + index;
|
||||
assert(keys->dk_kind == DICT_KEYS_UNICODE);
|
||||
assert(index < FT_ATOMIC_LOAD_SSIZE_RELAXED(keys->dk_nentries));
|
||||
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(keys) + index;
|
||||
PyObject *attr_o = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_value);
|
||||
// Clear mod_keys from stack in case we need to deopt
|
||||
POP_INPUT(mod_keys);
|
||||
DEOPT_IF(attr_o == NULL);
|
||||
#ifdef Py_GIL_DISABLED
|
||||
int increfed = _Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr);
|
||||
|
@ -2271,8 +2250,7 @@ dummy_func(
|
|||
DEOPT_IF(true);
|
||||
}
|
||||
#else
|
||||
Py_INCREF(attr_o);
|
||||
attr = PyStackRef_FromPyObjectSteal(attr_o);
|
||||
attr = PyStackRef_FromPyObjectNew(attr_o);
|
||||
#endif
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
PyStackRef_CLOSE(owner);
|
||||
|
@ -2280,62 +2258,49 @@ dummy_func(
|
|||
|
||||
macro(LOAD_ATTR_MODULE) =
|
||||
unused/1 +
|
||||
_CHECK_ATTR_MODULE_PUSH_KEYS +
|
||||
_LOAD_ATTR_MODULE_FROM_KEYS +
|
||||
_LOAD_ATTR_MODULE +
|
||||
unused/5 +
|
||||
_PUSH_NULL_CONDITIONAL;
|
||||
|
||||
op(_CHECK_ATTR_WITH_HINT, (owner -- owner, dict: PyDictObject *)) {
|
||||
op(_LOAD_ATTR_WITH_HINT, (hint/1, owner -- attr)) {
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
|
||||
assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictObject *dict_o = _PyObject_GetManagedDict(owner_o);
|
||||
EXIT_IF(dict_o == NULL);
|
||||
assert(PyDict_CheckExact((PyObject *)dict_o));
|
||||
dict = dict_o;
|
||||
}
|
||||
|
||||
op(_LOAD_ATTR_WITH_HINT, (hint/1, owner, dict: PyDictObject * -- attr)) {
|
||||
PyDictObject *dict = _PyObject_GetManagedDict(owner_o);
|
||||
DEOPT_IF(dict == NULL);
|
||||
assert(PyDict_CheckExact((PyObject *)dict));
|
||||
PyObject *attr_o;
|
||||
if (!LOCK_OBJECT(dict)) {
|
||||
POP_INPUT(dict);
|
||||
DEOPT_IF(true);
|
||||
}
|
||||
|
||||
if (hint >= (size_t)dict->ma_keys->dk_nentries) {
|
||||
UNLOCK_OBJECT(dict);
|
||||
POP_INPUT(dict);
|
||||
DEOPT_IF(true);
|
||||
}
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
||||
if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
|
||||
UNLOCK_OBJECT(dict);
|
||||
POP_INPUT(dict);
|
||||
DEOPT_IF(true);
|
||||
}
|
||||
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
|
||||
if (ep->me_key != name) {
|
||||
UNLOCK_OBJECT(dict);
|
||||
POP_INPUT(dict);
|
||||
DEOPT_IF(true);
|
||||
}
|
||||
attr_o = ep->me_value;
|
||||
if (attr_o == NULL) {
|
||||
UNLOCK_OBJECT(dict);
|
||||
POP_INPUT(dict);
|
||||
DEOPT_IF(true);
|
||||
}
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
attr = PyStackRef_FromPyObjectNew(attr_o);
|
||||
UNLOCK_OBJECT(dict);
|
||||
DEAD(dict);
|
||||
DECREF_INPUTS();
|
||||
PyStackRef_CLOSE(owner);
|
||||
}
|
||||
|
||||
macro(LOAD_ATTR_WITH_HINT) =
|
||||
unused/1 +
|
||||
_GUARD_TYPE_VERSION +
|
||||
_CHECK_ATTR_WITH_HINT +
|
||||
_LOAD_ATTR_WITH_HINT +
|
||||
unused/5 +
|
||||
_PUSH_NULL_CONDITIONAL;
|
||||
|
@ -5045,6 +5010,11 @@ dummy_func(
|
|||
value = PyStackRef_FromPyObjectNew(ptr);
|
||||
}
|
||||
|
||||
tier2 pure op (_POP_TOP_LOAD_CONST_INLINE, (ptr/4, pop -- value)) {
|
||||
PyStackRef_CLOSE(pop);
|
||||
value = PyStackRef_FromPyObjectNew(ptr);
|
||||
}
|
||||
|
||||
tier2 pure op(_LOAD_CONST_INLINE_BORROW, (ptr/4 -- value)) {
|
||||
value = PyStackRef_FromPyObjectImmortal(ptr);
|
||||
}
|
||||
|
@ -5060,38 +5030,6 @@ dummy_func(
|
|||
DEOPT_IF(func->func_version != func_version);
|
||||
}
|
||||
|
||||
tier2 op(_LOAD_GLOBAL_MODULE, (index/1 -- res)) {
|
||||
PyDictObject *dict = (PyDictObject *)GLOBALS();
|
||||
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
|
||||
PyObject *res_o = entries[index].me_value;
|
||||
DEOPT_IF(res_o == NULL);
|
||||
Py_INCREF(res_o);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
}
|
||||
|
||||
tier2 op(_LOAD_GLOBAL_BUILTINS, (index/1 -- res)) {
|
||||
PyDictObject *dict = (PyDictObject *)BUILTINS();
|
||||
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
|
||||
PyObject *res_o = entries[index].me_value;
|
||||
DEOPT_IF(res_o == NULL);
|
||||
Py_INCREF(res_o);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
}
|
||||
|
||||
tier2 op(_LOAD_ATTR_MODULE, (index/1, owner -- attr)) {
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner_o)->md_dict;
|
||||
assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);
|
||||
assert(index < dict->ma_keys->dk_nentries);
|
||||
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index;
|
||||
PyObject *attr_o = ep->me_value;
|
||||
DEOPT_IF(attr_o == NULL);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(attr_o);
|
||||
attr = PyStackRef_FromPyObjectSteal(attr_o);
|
||||
DECREF_INPUTS();
|
||||
}
|
||||
|
||||
tier2 op(_START_EXECUTOR, (executor/4 --)) {
|
||||
Py_CLEAR(tstate->previous_executor);
|
||||
#ifndef _Py_JIT
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue