@@ -874,69 +874,37 @@ lookdict_index(PyDictKeysObject *k, Py_hash_t hash, Py_ssize_t index)
874
874
Py_UNREACHABLE ();
875
875
}
876
876
877
- // Search non-Unicode key from Unicode table
878
- static Py_ssize_t
879
- unicodekeys_lookup_generic (PyDictObject * mp , PyDictKeysObject * dk , PyObject * key , Py_hash_t hash )
877
+ typedef void * (* generic_entries_func )(PyDictKeysObject * dk );
878
+
879
+ static inline Py_ALWAYS_INLINE Py_ssize_t
880
+ do_lookup (PyDictObject * mp , PyDictKeysObject * dk , PyObject * key , Py_hash_t hash ,
881
+ generic_entries_func entries ,
882
+ Py_ssize_t (* check_lookup )(PyDictObject * , PyDictKeysObject * , void * , Py_ssize_t ix , PyObject * key , Py_hash_t ))
880
883
{
881
- PyDictUnicodeEntry * ep0 = DK_UNICODE_ENTRIES (dk );
884
+ void * ep0 = entries (dk );
882
885
size_t mask = DK_MASK (dk );
883
886
size_t perturb = hash ;
884
887
size_t i = (size_t )hash & mask ;
885
888
Py_ssize_t ix ;
886
889
for (;;) {
887
890
ix = dictkeys_get_index (dk , i );
888
891
if (ix >= 0 ) {
889
- PyDictUnicodeEntry * ep = & ep0 [ix ];
890
- assert (ep -> me_key != NULL );
891
- assert (PyUnicode_CheckExact (ep -> me_key ));
892
- if (ep -> me_key == key ) {
892
+ ix = check_lookup (mp , dk , ep0 , ix , key , hash );
893
+ if (ix != DKIX_DUMMY ) {
893
894
return ix ;
894
895
}
895
- if (unicode_get_hash (ep -> me_key ) == hash ) {
896
- PyObject * startkey = ep -> me_key ;
897
- Py_INCREF (startkey );
898
- int cmp = PyObject_RichCompareBool (startkey , key , Py_EQ );
899
- Py_DECREF (startkey );
900
- if (cmp < 0 ) {
901
- return DKIX_ERROR ;
902
- }
903
- if (dk == mp -> ma_keys && ep -> me_key == startkey ) {
904
- if (cmp > 0 ) {
905
- return ix ;
906
- }
907
- }
908
- else {
909
- /* The dict was mutated, restart */
910
- return DKIX_KEY_CHANGED ;
911
- }
912
- }
913
896
}
914
897
else if (ix == DKIX_EMPTY ) {
915
898
return DKIX_EMPTY ;
916
899
}
917
900
perturb >>= PERTURB_SHIFT ;
918
901
i = mask & (i * 5 + perturb + 1 );
919
- }
920
- Py_UNREACHABLE ();
921
- }
922
902
923
- // Search Unicode key from Unicode table.
924
- static Py_ssize_t _Py_HOT_FUNCTION
925
- unicodekeys_lookup_unicode (PyDictKeysObject * dk , PyObject * key , Py_hash_t hash )
926
- {
927
- PyDictUnicodeEntry * ep0 = DK_UNICODE_ENTRIES (dk );
928
- size_t mask = DK_MASK (dk );
929
- size_t perturb = hash ;
930
- size_t i = (size_t )hash & mask ;
931
- Py_ssize_t ix ;
932
- for (;;) {
903
+ // Manual loop unrolling
933
904
ix = dictkeys_get_index (dk , i );
934
905
if (ix >= 0 ) {
935
- PyDictUnicodeEntry * ep = & ep0 [ix ];
936
- assert (ep -> me_key != NULL );
937
- assert (PyUnicode_CheckExact (ep -> me_key ));
938
- if (ep -> me_key == key ||
939
- (unicode_get_hash (ep -> me_key ) == hash && unicode_eq (ep -> me_key , key ))) {
906
+ ix = check_lookup (mp , dk , ep0 , ix , key , hash );
907
+ if (ix != DKIX_DUMMY ) {
940
908
return ix ;
941
909
}
942
910
}
@@ -945,69 +913,102 @@ unicodekeys_lookup_unicode(PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
945
913
}
946
914
perturb >>= PERTURB_SHIFT ;
947
915
i = mask & (i * 5 + perturb + 1 );
948
- // Manual loop unrolling
949
- ix = dictkeys_get_index (dk , i );
950
- if (ix >= 0 ) {
951
- PyDictUnicodeEntry * ep = & ep0 [ix ];
952
- assert (ep -> me_key != NULL );
953
- assert (PyUnicode_CheckExact (ep -> me_key ));
954
- if (ep -> me_key == key ||
955
- (unicode_get_hash (ep -> me_key ) == hash && unicode_eq (ep -> me_key , key ))) {
916
+ }
917
+ Py_UNREACHABLE ();
918
+ }
919
+
920
+ static inline Py_ALWAYS_INLINE
921
+ Py_ssize_t compare_unicode_generic (PyDictObject * mp , PyDictKeysObject * dk ,
922
+ void * ep0 , Py_ssize_t ix , PyObject * key , Py_hash_t hash )
923
+ {
924
+ PyDictUnicodeEntry * ep = & ((PyDictUnicodeEntry * )ep0 )[ix ];
925
+ assert (ep -> me_key != NULL );
926
+ assert (PyUnicode_CheckExact (ep -> me_key ));
927
+ assert (!PyUnicode_CheckExact (key ));
928
+ // TODO: Thread safety
929
+
930
+ if (unicode_get_hash (ep -> me_key ) == hash ) {
931
+ PyObject * startkey = ep -> me_key ;
932
+ Py_INCREF (startkey );
933
+ int cmp = PyObject_RichCompareBool (startkey , key , Py_EQ );
934
+ Py_DECREF (startkey );
935
+ if (cmp < 0 ) {
936
+ return DKIX_ERROR ;
937
+ }
938
+ if (dk == mp -> ma_keys && ep -> me_key == startkey ) {
939
+ if (cmp > 0 ) {
956
940
return ix ;
957
941
}
958
942
}
959
- else if (ix == DKIX_EMPTY ) {
960
- return DKIX_EMPTY ;
943
+ else {
944
+ /* The dict was mutated, restart */
945
+ return DKIX_KEY_CHANGED ;
961
946
}
962
- perturb >>= PERTURB_SHIFT ;
963
- i = mask & (i * 5 + perturb + 1 );
964
947
}
965
- Py_UNREACHABLE () ;
948
+ return DKIX_DUMMY ;
966
949
}
967
950
968
- // Search key from Generic table.
951
+ // Search non-Unicode key from Unicode table
969
952
static Py_ssize_t
970
- dictkeys_generic_lookup (PyDictObject * mp , PyDictKeysObject * dk , PyObject * key , Py_hash_t hash )
953
+ unicodekeys_lookup_generic (PyDictObject * mp , PyDictKeysObject * dk , PyObject * key , Py_hash_t hash )
971
954
{
972
- PyDictKeyEntry * ep0 = DK_ENTRIES (dk );
973
- size_t mask = DK_MASK (dk );
974
- size_t perturb = hash ;
975
- size_t i = (size_t )hash & mask ;
976
- Py_ssize_t ix ;
977
- for (;;) {
978
- ix = dictkeys_get_index (dk , i );
979
- if (ix >= 0 ) {
980
- PyDictKeyEntry * ep = & ep0 [ix ];
981
- assert (ep -> me_key != NULL );
982
- if (ep -> me_key == key ) {
955
+ return do_lookup (mp , dk , key , hash , (generic_entries_func )DK_UNICODE_ENTRIES , compare_unicode_generic );
956
+ }
957
+
958
+ static inline Py_ALWAYS_INLINE
959
+ Py_ssize_t compare_unicode_unicode (PyDictObject * mp , PyDictKeysObject * dk ,
960
+ void * ep0 , Py_ssize_t ix , PyObject * key , Py_hash_t hash )
961
+ {
962
+ PyDictUnicodeEntry * ep = & ((PyDictUnicodeEntry * )ep0 )[ix ];
963
+ assert (ep -> me_key != NULL );
964
+ assert (PyUnicode_CheckExact (ep -> me_key ));
965
+ if (ep -> me_key == key ||
966
+ (unicode_get_hash (ep -> me_key ) == hash && unicode_eq (ep -> me_key , key ))) {
967
+ return ix ;
968
+ }
969
+ return DKIX_DUMMY ;
970
+ }
971
+
972
+ static Py_ssize_t _Py_HOT_FUNCTION
973
+ unicodekeys_lookup_unicode (PyDictKeysObject * dk , PyObject * key , Py_hash_t hash )
974
+ {
975
+ return do_lookup (NULL , dk , key , hash , (generic_entries_func )DK_UNICODE_ENTRIES , compare_unicode_unicode );
976
+ }
977
+
978
+ static inline Py_ALWAYS_INLINE
979
+ Py_ssize_t compare_generic (PyDictObject * mp , PyDictKeysObject * dk ,
980
+ void * ep0 , Py_ssize_t ix , PyObject * key , Py_hash_t hash )
981
+ {
982
+ PyDictKeyEntry * ep = & ((PyDictKeyEntry * )ep0 )[ix ];
983
+ assert (ep -> me_key != NULL );
984
+ if (ep -> me_key == key ) {
985
+ return ix ;
986
+ }
987
+ if (ep -> me_hash == hash ) {
988
+ PyObject * startkey = ep -> me_key ;
989
+ Py_INCREF (startkey );
990
+ int cmp = PyObject_RichCompareBool (startkey , key , Py_EQ );
991
+ Py_DECREF (startkey );
992
+ if (cmp < 0 ) {
993
+ return DKIX_ERROR ;
994
+ }
995
+ if (dk == mp -> ma_keys && ep -> me_key == startkey ) {
996
+ if (cmp > 0 ) {
983
997
return ix ;
984
998
}
985
- if (ep -> me_hash == hash ) {
986
- PyObject * startkey = ep -> me_key ;
987
- Py_INCREF (startkey );
988
- int cmp = PyObject_RichCompareBool (startkey , key , Py_EQ );
989
- Py_DECREF (startkey );
990
- if (cmp < 0 ) {
991
- return DKIX_ERROR ;
992
- }
993
- if (dk == mp -> ma_keys && ep -> me_key == startkey ) {
994
- if (cmp > 0 ) {
995
- return ix ;
996
- }
997
- }
998
- else {
999
- /* The dict was mutated, restart */
1000
- return DKIX_KEY_CHANGED ;
1001
- }
1002
- }
1003
999
}
1004
- else if (ix == DKIX_EMPTY ) {
1005
- return DKIX_EMPTY ;
1000
+ else {
1001
+ /* The dict was mutated, restart */
1002
+ return DKIX_KEY_CHANGED ;
1006
1003
}
1007
- perturb >>= PERTURB_SHIFT ;
1008
- i = mask & (i * 5 + perturb + 1 );
1009
1004
}
1010
- Py_UNREACHABLE ();
1005
+ return DKIX_DUMMY ;
1006
+ }
1007
+
1008
+ static Py_ssize_t
1009
+ dictkeys_generic_lookup (PyDictObject * mp , PyDictKeysObject * dk , PyObject * key , Py_hash_t hash )
1010
+ {
1011
+ return do_lookup (mp , dk , key , hash , (generic_entries_func )DK_ENTRIES , compare_generic );
1011
1012
}
1012
1013
1013
1014
/* Lookup a string in a (all unicode) dict keys.
0 commit comments