@@ -1185,6 +1185,37 @@ dictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, P
1185
1185
return do_lookup (mp , dk , key , hash , compare_generic );
1186
1186
}
1187
1187
1188
+ #ifdef Py_GIL_DISABLED
1189
+
1190
+ static Py_ssize_t
1191
+ unicodekeys_lookup_unicode_threadsafe (PyDictKeysObject * dk , PyObject * key ,
1192
+ Py_hash_t hash );
1193
+
1194
+ #endif
1195
+
1196
+ static Py_ssize_t
1197
+ unicodekeys_lookup_split (PyDictKeysObject * dk , PyObject * key , Py_hash_t hash )
1198
+ {
1199
+ Py_ssize_t ix ;
1200
+ assert (dk -> dk_kind == DICT_KEYS_SPLIT );
1201
+ assert (PyUnicode_CheckExact (key ));
1202
+
1203
+ #ifdef Py_GIL_DISABLED
1204
+ // A split dictionaries keys can be mutated by other dictionaries
1205
+ // but if we have a unicode key we can avoid locking the shared
1206
+ // keys.
1207
+ ix = unicodekeys_lookup_unicode_threadsafe (dk , key , hash );
1208
+ if (ix == DKIX_KEY_CHANGED ) {
1209
+ LOCK_KEYS (dk );
1210
+ ix = unicodekeys_lookup_unicode (dk , key , hash );
1211
+ UNLOCK_KEYS (dk );
1212
+ }
1213
+ #else
1214
+ ix = unicodekeys_lookup_unicode (dk , key , hash );
1215
+ #endif
1216
+ return ix ;
1217
+ }
1218
+
1188
1219
/* Lookup a string in a (all unicode) dict keys.
1189
1220
* Returns DKIX_ERROR if key is not a string,
1190
1221
* or if the dict keys is not all strings.
@@ -1209,13 +1240,24 @@ _PyDictKeys_StringLookup(PyDictKeysObject* dk, PyObject *key)
1209
1240
return unicodekeys_lookup_unicode (dk , key , hash );
1210
1241
}
1211
1242
1212
- #ifdef Py_GIL_DISABLED
1213
-
1214
- static Py_ssize_t
1215
- unicodekeys_lookup_unicode_threadsafe (PyDictKeysObject * dk , PyObject * key ,
1216
- Py_hash_t hash );
1217
-
1218
- #endif
1243
+ /* Like _PyDictKeys_StringLookup() but only works on split keys. Note
1244
+ * that in free-threaded builds this locks the keys object as required.
1245
+ */
1246
+ Py_ssize_t
1247
+ _PyDictKeys_StringLookupSplit (PyDictKeysObject * dk , PyObject * key )
1248
+ {
1249
+ assert (dk -> dk_kind == DICT_KEYS_SPLIT );
1250
+ assert (PyUnicode_CheckExact (key ));
1251
+ Py_hash_t hash = unicode_get_hash (key );
1252
+ if (hash == -1 ) {
1253
+ hash = PyUnicode_Type .tp_hash (key );
1254
+ if (hash == -1 ) {
1255
+ PyErr_Clear ();
1256
+ return DKIX_ERROR ;
1257
+ }
1258
+ }
1259
+ return unicodekeys_lookup_split (dk , key , hash );
1260
+ }
1219
1261
1220
1262
/*
1221
1263
The basic lookup function used by all operations.
@@ -6976,7 +7018,7 @@ _PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name, PyObject **attr
6976
7018
6977
7019
PyDictKeysObject * keys = CACHED_KEYS (Py_TYPE (obj ));
6978
7020
assert (keys != NULL );
6979
- Py_ssize_t ix = _PyDictKeys_StringLookup (keys , name );
7021
+ Py_ssize_t ix = _PyDictKeys_StringLookupSplit (keys , name );
6980
7022
if (ix == DKIX_EMPTY ) {
6981
7023
* attr = NULL ;
6982
7024
return true;
0 commit comments