mirror of
https://github.com/python/cpython.git
synced 2025-08-04 17:08:35 +00:00
gh-121459: Deferred LOAD_GLOBAL (GH-123128)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Co-authored-by: Sam Gross <655866+colesbury@users.noreply.github.com>
This commit is contained in:
parent
74330d992b
commit
8810e286fa
8 changed files with 108 additions and 29 deletions
|
@ -1496,6 +1496,45 @@ read_failed:
|
|||
return ix;
|
||||
}
|
||||
|
||||
Py_ssize_t
|
||||
_Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t hash, _PyStackRef *value_addr)
|
||||
{
|
||||
PyDictKeysObject *dk = _Py_atomic_load_ptr(&mp->ma_keys);
|
||||
if (dk->dk_kind == DICT_KEYS_UNICODE && PyUnicode_CheckExact(key)) {
|
||||
Py_ssize_t ix = unicodekeys_lookup_unicode_threadsafe(dk, key, hash);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
*value_addr = PyStackRef_NULL;
|
||||
return ix;
|
||||
}
|
||||
else if (ix >= 0) {
|
||||
PyObject **addr_of_value = &DK_UNICODE_ENTRIES(dk)[ix].me_value;
|
||||
PyObject *value = _Py_atomic_load_ptr(addr_of_value);
|
||||
if (value == NULL) {
|
||||
*value_addr = PyStackRef_NULL;
|
||||
return DKIX_EMPTY;
|
||||
}
|
||||
if (_Py_IsImmortal(value) || _PyObject_HasDeferredRefcount(value)) {
|
||||
*value_addr = (_PyStackRef){ .bits = (uintptr_t)value | Py_TAG_DEFERRED };
|
||||
return ix;
|
||||
}
|
||||
if (_Py_TryIncrefCompare(addr_of_value, value)) {
|
||||
*value_addr = PyStackRef_FromPyObjectSteal(value);
|
||||
return ix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *obj;
|
||||
Py_ssize_t ix = _Py_dict_lookup_threadsafe(mp, key, hash, &obj);
|
||||
if (ix >= 0 && obj != NULL) {
|
||||
*value_addr = PyStackRef_FromPyObjectSteal(obj);
|
||||
}
|
||||
else {
|
||||
*value_addr = PyStackRef_NULL;
|
||||
}
|
||||
return ix;
|
||||
}
|
||||
|
||||
#else // Py_GIL_DISABLED
|
||||
|
||||
Py_ssize_t
|
||||
|
@ -1506,6 +1545,15 @@ _Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyOb
|
|||
return ix;
|
||||
}
|
||||
|
||||
Py_ssize_t
|
||||
_Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t hash, _PyStackRef *value_addr)
|
||||
{
|
||||
PyObject *val;
|
||||
Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &val);
|
||||
*value_addr = val == NULL ? PyStackRef_NULL : PyStackRef_FromPyObjectNew(val);
|
||||
return ix;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -2420,6 +2468,32 @@ _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)
|
|||
return value;
|
||||
}
|
||||
|
||||
void
|
||||
_PyDict_LoadGlobalStackRef(PyDictObject *globals, PyDictObject *builtins, PyObject *key, _PyStackRef *res)
|
||||
{
|
||||
Py_ssize_t ix;
|
||||
Py_hash_t hash;
|
||||
|
||||
hash = _PyObject_HashFast(key);
|
||||
if (hash == -1) {
|
||||
*res = PyStackRef_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* namespace 1: globals */
|
||||
ix = _Py_dict_lookup_threadsafe_stackref(globals, key, hash, res);
|
||||
if (ix == DKIX_ERROR) {
|
||||
*res = PyStackRef_NULL;
|
||||
}
|
||||
if (ix != DKIX_EMPTY && !PyStackRef_IsNull(*res)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* namespace 2: builtins */
|
||||
ix = _Py_dict_lookup_threadsafe_stackref(builtins, key, hash, res);
|
||||
assert(ix >= 0 || PyStackRef_IsNull(*res));
|
||||
}
|
||||
|
||||
/* Consumes references to key and value */
|
||||
static int
|
||||
setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue