diff options
author | Ken Jin <kenjin@python.org> | 2024-09-13 16:23:51 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-13 16:23:51 (GMT) |
commit | 8810e286fa48876422d1b230208911decbead294 (patch) | |
tree | 0d171d70418884104b8681e0e7492d136b8b6778 /Objects | |
parent | 74330d992be26829dba65ab83d698d42b2f2a2ee (diff) | |
download | cpython-8810e286fa48876422d1b230208911decbead294.zip cpython-8810e286fa48876422d1b230208911decbead294.tar.gz cpython-8810e286fa48876422d1b230208911decbead294.tar.bz2 |
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>
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/dictobject.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index b81ed18..006bc59 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -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) |