summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorKen Jin <kenjin@python.org>2024-09-13 16:23:51 (GMT)
committerGitHub <noreply@github.com>2024-09-13 16:23:51 (GMT)
commit8810e286fa48876422d1b230208911decbead294 (patch)
tree0d171d70418884104b8681e0e7492d136b8b6778 /Objects
parent74330d992be26829dba65ab83d698d42b2f2a2ee (diff)
downloadcpython-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.c74
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)