@@ -1129,6 +1129,38 @@ dictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, P
1129
1129
return do_lookup (mp , dk , key , hash , compare_generic );
1130
1130
}
1131
1131
1132
+ #ifdef Py_GIL_DISABLED
1133
+ static Py_ssize_t
1134
+ unicodekeys_lookup_unicode_threadsafe (PyDictKeysObject * dk , PyObject * key ,
1135
+ Py_hash_t hash );
1136
+ #endif
1137
+
1138
+ static Py_ssize_t
1139
+ unicodekeys_lookup_split (PyDictKeysObject * dk , PyObject * key , Py_hash_t hash )
1140
+ {
1141
+ Py_ssize_t ix ;
1142
+ assert (dk -> dk_kind == DICT_KEYS_SPLIT );
1143
+ assert (PyUnicode_CheckExact (key ));
1144
+
1145
+ #ifdef Py_GIL_DISABLED
1146
+ // A split dictionaries keys can be mutated by other dictionaries
1147
+ // but if we have a unicode key we can avoid locking the shared
1148
+ // keys.
1149
+ ix = unicodekeys_lookup_unicode_threadsafe (dk , key , hash );
1150
+ if (ix == DKIX_KEY_CHANGED ) {
1151
+ LOCK_KEYS (dk );
1152
+ ix = unicodekeys_lookup_unicode (dk , key , hash );
1153
+ UNLOCK_KEYS (dk );
1154
+ }
1155
+ else {
1156
+ ix = unicodekeys_lookup_unicode (dk , key , hash );
1157
+ }
1158
+ #else
1159
+ ix = unicodekeys_lookup_unicode (dk , key , hash );
1160
+ #endif
1161
+ return ix ;
1162
+ }
1163
+
1132
1164
/* Lookup a string in a (all unicode) dict keys.
1133
1165
* Returns DKIX_ERROR if key is not a string,
1134
1166
* or if the dict keys is not all strings.
@@ -1153,13 +1185,24 @@ _PyDictKeys_StringLookup(PyDictKeysObject* dk, PyObject *key)
1153
1185
return unicodekeys_lookup_unicode (dk , key , hash );
1154
1186
}
1155
1187
1156
- #ifdef Py_GIL_DISABLED
1157
-
1158
- static Py_ssize_t
1159
- unicodekeys_lookup_unicode_threadsafe (PyDictKeysObject * dk , PyObject * key ,
1160
- Py_hash_t hash );
1161
-
1162
- #endif
1188
+ /* Like _PyDictKeys_StringLookup() but only works on split keys. Note
1189
+ * that in free-threaded builds this locks the keys object as required.
1190
+ */
1191
+ Py_ssize_t
1192
+ _PyDictKeys_StringLookupSplit (PyDictKeysObject * dk , PyObject * key )
1193
+ {
1194
+ assert (dk -> dk_kind == DICT_KEYS_SPLIT );
1195
+ assert (PyUnicode_CheckExact (key ));
1196
+ Py_hash_t hash = unicode_get_hash (key );
1197
+ if (hash == -1 ) {
1198
+ hash = PyUnicode_Type .tp_hash (key );
1199
+ if (hash == -1 ) {
1200
+ PyErr_Clear ();
1201
+ return DKIX_ERROR ;
1202
+ }
1203
+ }
1204
+ return unicodekeys_lookup_split (dk , key , hash );
1205
+ }
1163
1206
1164
1207
/*
1165
1208
The basic lookup function used by all operations.
@@ -1192,15 +1235,7 @@ _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **valu
1192
1235
if (PyUnicode_CheckExact (key )) {
1193
1236
#ifdef Py_GIL_DISABLED
1194
1237
if (kind == DICT_KEYS_SPLIT ) {
1195
- // A split dictionaries keys can be mutated by other
1196
- // dictionaries but if we have a unicode key we can avoid
1197
- // locking the shared keys.
1198
- ix = unicodekeys_lookup_unicode_threadsafe (dk , key , hash );
1199
- if (ix == DKIX_KEY_CHANGED ) {
1200
- LOCK_KEYS (dk );
1201
- ix = unicodekeys_lookup_unicode (dk , key , hash );
1202
- UNLOCK_KEYS (dk );
1203
- }
1238
+ ix = unicodekeys_lookup_split (dk , key , hash );
1204
1239
}
1205
1240
else {
1206
1241
ix = unicodekeys_lookup_unicode (dk , key , hash );
@@ -6967,7 +7002,12 @@ _PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name, PyObject **attr
6967
7002
6968
7003
PyDictKeysObject * keys = CACHED_KEYS (Py_TYPE (obj ));
6969
7004
assert (keys != NULL );
6970
- Py_ssize_t ix = _PyDictKeys_StringLookup (keys , name );
7005
+ Py_ssize_t ix ;
7006
+ if (keys -> dk_kind == DICT_KEYS_SPLIT ) {
7007
+ ix = _PyDictKeys_StringLookupSplit (keys , name );
7008
+ } else {
7009
+ ix = _PyDictKeys_StringLookup (keys , name );
7010
+ }
6971
7011
if (ix == DKIX_EMPTY ) {
6972
7012
* attr = NULL ;
6973
7013
return true;
0 commit comments