]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-115775: Use `__static_attributes__` to initialize shared keys (GH-118468)
authorMark Shannon <mark@hotpy.org>
Tue, 27 Aug 2024 09:34:46 +0000 (10:34 +0100)
committerGitHub <noreply@github.com>
Tue, 27 Aug 2024 09:34:46 +0000 (10:34 +0100)
Include/internal/pycore_dict.h
Objects/dictobject.c
Objects/typeobject.c

index a84246ee34efff4a897e811bbe52d311a026a218..100250928d206433fb47230fe698bf500180ffee 100644 (file)
@@ -83,7 +83,7 @@ typedef struct {
     PyObject *me_value; /* This field is only meaningful for combined tables */
 } PyDictUnicodeEntry;
 
-extern PyDictKeysObject *_PyDict_NewKeysForClass(void);
+extern PyDictKeysObject *_PyDict_NewKeysForClass(PyHeapTypeObject *);
 extern PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *);
 
 /* Gets a version number unique to the current state of the keys of dict, if possible.
index a30b3e37319ccf8a38adbf99985a5eecfa929f27..b81ed189456ec12ad3f0e4ae580f48f3372a93e2 100644 (file)
@@ -6559,9 +6559,10 @@ dictvalues_reversed(PyObject *self, PyObject *Py_UNUSED(ignored))
 /* Returns NULL if cannot allocate a new PyDictKeysObject,
    but does not set an error */
 PyDictKeysObject *
-_PyDict_NewKeysForClass(void)
+_PyDict_NewKeysForClass(PyHeapTypeObject *cls)
 {
     PyInterpreterState *interp = _PyInterpreterState_GET();
+
     PyDictKeysObject *keys = new_keys_object(
             interp, NEXT_LOG2_SHARED_KEYS_MAX_SIZE, 1);
     if (keys == NULL) {
@@ -6573,6 +6574,20 @@ _PyDict_NewKeysForClass(void)
         keys->dk_usable = SHARED_KEYS_MAX_SIZE;
         keys->dk_kind = DICT_KEYS_SPLIT;
     }
+    if (cls->ht_type.tp_dict) {
+        PyObject *attrs = PyDict_GetItem(cls->ht_type.tp_dict, &_Py_ID(__static_attributes__));
+        if (attrs != NULL && PyTuple_Check(attrs)) {
+            for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(attrs); i++) {
+                PyObject *key = PyTuple_GET_ITEM(attrs, i);
+                Py_hash_t hash;
+                if (PyUnicode_CheckExact(key) && (hash = unicode_get_hash(key)) != -1) {
+                    if (insert_split_key(keys, key, hash) == DKIX_EMPTY) {
+                        break;
+                    }
+                }
+            }
+        }
+    }
     return keys;
 }
 
index f74d51222b7a65b8a1b1f413bd8436794306be07..c3a8fb5567932badc8d261571bc81a64aaca2685 100644 (file)
@@ -8334,7 +8334,7 @@ type_ready_managed_dict(PyTypeObject *type)
     }
     PyHeapTypeObject* et = (PyHeapTypeObject*)type;
     if (et->ht_cached_keys == NULL) {
-        et->ht_cached_keys = _PyDict_NewKeysForClass();
+        et->ht_cached_keys = _PyDict_NewKeysForClass(et);
         if (et->ht_cached_keys == NULL) {
             PyErr_NoMemory();
             return -1;