diff options
author | Mark Shannon <mark@hotpy.org> | 2025-02-28 18:00:38 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-28 18:00:38 (GMT) |
commit | 54965f3fb25b381995a73b09d928c344bd2b86bd (patch) | |
tree | cf2f71ac2775a4cfec347a70fd123d176c353948 /Python/bytecodes.c | |
parent | ab11c097052757b79060c75dd4835c2431e752b7 (diff) | |
download | cpython-54965f3fb25b381995a73b09d928c344bd2b86bd.zip cpython-54965f3fb25b381995a73b09d928c344bd2b86bd.tar.gz cpython-54965f3fb25b381995a73b09d928c344bd2b86bd.tar.bz2 |
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
Diffstat (limited to 'Python/bytecodes.c')
-rw-r--r-- | Python/bytecodes.c | 128 |
1 files changed, 33 insertions, 95 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 1b9b651..24aa7bb 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -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)); - } - - op(_GUARD_BUILTINS_VERSION_PUSH_KEYS, (version / 1 -- builtins_keys: PyDictKeysObject *)) - { - 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); + assert(index < DK_SIZE(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); + res = PyStackRef_FromPyObjectNew(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); + 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); + assert(DK_IS_UNICODE(keys)); + PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(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 |