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