From 94bf898d1143cf095cd26d35c24d2dc7c78abb70 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 1 May 2024 11:28:42 +0100 Subject: [PATCH 1/2] Use __static_attributes__ to initialize shared keys --- Include/internal/pycore_dict.h | 2 +- Objects/dictobject.c | 17 ++++++++++++++++- Objects/typeobject.c | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index f33026dbd6be58..1ec575fb5b36b6 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -81,7 +81,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. diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 1f21f70f149c80..1f24422c2117f6 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -6586,9 +6586,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) { @@ -6600,6 +6601,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; 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; } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index ec19a3d461f623..42c34b27c82114 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -7883,7 +7883,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; From d54afaf925ddfe838e40971a9f6d5324dc9602b6 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 1 May 2024 21:45:37 +0100 Subject: [PATCH 2/2] Initialize value --- Objects/dictobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 1f24422c2117f6..11219cbcefe20e 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -6604,7 +6604,7 @@ _PyDict_NewKeysForClass(PyHeapTypeObject *cls) 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; i < PyTuple_GET_SIZE(attrs); i++) { + 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) {