aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/generated_cases.c.h
diff options
context:
space:
mode:
authormpage <mpage@meta.com>2024-12-13 10:17:16 -0800
committerGitHub <noreply@github.com>2024-12-13 10:17:16 -0800
commit2de048ce79e621f5ae0574095b9600fe8595f607 (patch)
treede3116284fc2016192787297de7a67ba348e5825 /Python/generated_cases.c.h
parent292067fbc9db81896c16ff12d51c21d2b0f233e2 (diff)
downloadcpython-2de048ce79e621f5ae0574095b9600fe8595f607.tar.gz
cpython-2de048ce79e621f5ae0574095b9600fe8595f607.zip
gh-115999: Specialize loading attributes from modules in free-threaded builds (#127711)
We use the same approach that was used for specialization of LOAD_GLOBAL in free-threaded builds: _CHECK_ATTR_MODULE is renamed to _CHECK_ATTR_MODULE_PUSH_KEYS; it pushes the keys object for the following _LOAD_ATTR_MODULE_FROM_KEYS (nee _LOAD_ATTR_MODULE). This arrangement avoids having to recheck the keys version. _LOAD_ATTR_MODULE is renamed to _LOAD_ATTR_MODULE_FROM_KEYS; it loads the value from the keys object pushed by the preceding _CHECK_ATTR_MODULE_PUSH_KEYS at the cached index.
Diffstat (limited to 'Python/generated_cases.c.h')
-rw-r--r--Python/generated_cases.c.h33
1 files changed, 21 insertions, 12 deletions
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 51227c9868b..94343f95322 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -5200,7 +5200,7 @@
owner = stack_pointer[-1];
uint16_t counter = read_u16(&this_instr[1].cache);
(void)counter;
- #if ENABLE_SPECIALIZATION
+ #if ENABLE_SPECIALIZATION_FT
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
next_instr = this_instr;
@@ -5211,7 +5211,7 @@
}
OPCODE_DEFERRED_INC(LOAD_ATTR);
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
- #endif /* ENABLE_SPECIALIZATION */
+ #endif /* ENABLE_SPECIALIZATION_FT */
}
/* Skip 8 cache entries */
// _LOAD_ATTR
@@ -5553,10 +5553,11 @@
INSTRUCTION_STATS(LOAD_ATTR_MODULE);
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
_PyStackRef owner;
+ PyDictKeysObject *mod_keys;
_PyStackRef attr;
_PyStackRef null = PyStackRef_NULL;
/* Skip 1 cache entry */
- // _CHECK_ATTR_MODULE
+ // _CHECK_ATTR_MODULE_PUSH_KEYS
{
owner = stack_pointer[-1];
uint32_t dict_version = read_u32(&this_instr[2].cache);
@@ -5564,21 +5565,29 @@
DEOPT_IF(Py_TYPE(owner_o)->tp_getattro != PyModule_Type.tp_getattro, LOAD_ATTR);
PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner_o)->md_dict;
assert(dict != NULL);
- DEOPT_IF(dict->ma_keys->dk_version != dict_version, LOAD_ATTR);
+ PyDictKeysObject *keys = FT_ATOMIC_LOAD_PTR_ACQUIRE(dict->ma_keys);
+ DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != dict_version, LOAD_ATTR);
+ mod_keys = keys;
}
- // _LOAD_ATTR_MODULE
+ // _LOAD_ATTR_MODULE_FROM_KEYS
{
uint16_t index = read_u16(&this_instr[4].cache);
- 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;
+ 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;
+ PyObject *attr_o = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_value);
+ // Clear mod_keys from stack in case we need to deopt
DEOPT_IF(attr_o == NULL, LOAD_ATTR);
- STAT_INC(LOAD_ATTR, hit);
+ #ifdef Py_GIL_DISABLED
+ int increfed = _Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr);
+ if (!increfed) {
+ DEOPT_IF(true, LOAD_ATTR);
+ }
+ #else
Py_INCREF(attr_o);
attr = PyStackRef_FromPyObjectSteal(attr_o);
+ #endif
+ STAT_INC(LOAD_ATTR, hit);
null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
}