summaryrefslogtreecommitdiffstats
path: root/Python/bytecodes.c
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2025-02-28 18:00:38 (GMT)
committerGitHub <noreply@github.com>2025-02-28 18:00:38 (GMT)
commit54965f3fb25b381995a73b09d928c344bd2b86bd (patch)
treecf2f71ac2775a4cfec347a70fd123d176c353948 /Python/bytecodes.c
parentab11c097052757b79060c75dd4835c2431e752b7 (diff)
downloadcpython-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.c128
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