@@ -734,6 +734,73 @@ lookdict_index(PyDictKeysObject *k, Py_hash_t hash, Py_ssize_t index)
734
734
Py_UNREACHABLE ();
735
735
}
736
736
737
+ static Py_ssize_t
738
+ dictkeys_stringlookup (PyDictKeysObject * dk , PyObject * key , Py_hash_t hash )
739
+ {
740
+ PyDictKeyEntry * ep0 = DK_ENTRIES (dk );
741
+ size_t mask = DK_MASK (dk );
742
+ size_t perturb = hash ;
743
+ size_t i = (size_t )hash & mask ;
744
+ Py_ssize_t ix ;
745
+ for (;;) {
746
+ ix = dictkeys_get_index (dk , i );
747
+ if (ix >= 0 ) {
748
+ PyDictKeyEntry * ep = & ep0 [ix ];
749
+ assert (ep -> me_key != NULL );
750
+ assert (PyUnicode_CheckExact (ep -> me_key ));
751
+ if (ep -> me_key == key ||
752
+ (ep -> me_hash == hash && unicode_eq (ep -> me_key , key ))) {
753
+ return ix ;
754
+ }
755
+ }
756
+ else if (ix == DKIX_EMPTY ) {
757
+ return DKIX_EMPTY ;
758
+ }
759
+ perturb >>= PERTURB_SHIFT ;
760
+ i = mask & (i * 5 + perturb + 1 );
761
+ ix = dictkeys_get_index (dk , i );
762
+ if (ix >= 0 ) {
763
+ PyDictKeyEntry * ep = & ep0 [ix ];
764
+ assert (ep -> me_key != NULL );
765
+ assert (PyUnicode_CheckExact (ep -> me_key ));
766
+ if (ep -> me_key == key ||
767
+ (ep -> me_hash == hash && unicode_eq (ep -> me_key , key ))) {
768
+ return ix ;
769
+ }
770
+ }
771
+ else if (ix == DKIX_EMPTY ) {
772
+ return DKIX_EMPTY ;
773
+ }
774
+ perturb >>= PERTURB_SHIFT ;
775
+ i = mask & (i * 5 + perturb + 1 );
776
+ }
777
+ Py_UNREACHABLE ();
778
+ }
779
+
780
+ /* Lookup a string in a (all unicode) dict keys.
781
+ * Returns DKIX_ERROR if key is not a string,
782
+ * or if the dict keys is not all strings.
783
+ * If the keys is present then return the index of key.
784
+ * If the key is not present then return DKIX_EMPTY.
785
+ */
786
+ Py_ssize_t
787
+ _PyDictKeys_StringLookup (PyDictKeysObject * dk , PyObject * key )
788
+ {
789
+ DictKeysKind kind = dk -> dk_kind ;
790
+ if (!PyUnicode_CheckExact (key ) || kind == DICT_KEYS_GENERAL ) {
791
+ return DKIX_ERROR ;
792
+ }
793
+ Py_hash_t hash = ((PyASCIIObject * )key )-> hash ;
794
+ if (hash == -1 ) {
795
+ hash = PyUnicode_Type .tp_hash (key );
796
+ if (hash == -1 ) {
797
+ PyErr_Clear ();
798
+ return DKIX_ERROR ;
799
+ }
800
+ }
801
+ return dictkeys_stringlookup (dk , key , hash );
802
+ }
803
+
737
804
/*
738
805
The basic lookup function used by all operations.
739
806
This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
@@ -756,49 +823,24 @@ _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **valu
756
823
start :
757
824
dk = mp -> ma_keys ;
758
825
DictKeysKind kind = dk -> dk_kind ;
826
+ if (PyUnicode_CheckExact (key ) && kind != DICT_KEYS_GENERAL ) {
827
+ Py_ssize_t ix = dictkeys_stringlookup (dk , key , hash );
828
+ if (ix == DKIX_EMPTY ) {
829
+ * value_addr = NULL ;
830
+ }
831
+ else if (kind == DICT_KEYS_SPLIT ) {
832
+ * value_addr = mp -> ma_values [ix ];
833
+ }
834
+ else {
835
+ * value_addr = DK_ENTRIES (dk )[ix ].me_value ;
836
+ }
837
+ return ix ;
838
+ }
759
839
PyDictKeyEntry * ep0 = DK_ENTRIES (dk );
760
840
size_t mask = DK_MASK (dk );
761
841
size_t perturb = hash ;
762
842
size_t i = (size_t )hash & mask ;
763
843
Py_ssize_t ix ;
764
- if (PyUnicode_CheckExact (key ) && kind != DICT_KEYS_GENERAL ) {
765
- /* Strings only */
766
- for (;;) {
767
- ix = dictkeys_get_index (mp -> ma_keys , i );
768
- if (ix >= 0 ) {
769
- PyDictKeyEntry * ep = & ep0 [ix ];
770
- assert (ep -> me_key != NULL );
771
- assert (PyUnicode_CheckExact (ep -> me_key ));
772
- if (ep -> me_key == key ||
773
- (ep -> me_hash == hash && unicode_eq (ep -> me_key , key ))) {
774
- goto found ;
775
- }
776
- }
777
- else if (ix == DKIX_EMPTY ) {
778
- * value_addr = NULL ;
779
- return DKIX_EMPTY ;
780
- }
781
- perturb >>= PERTURB_SHIFT ;
782
- i = mask & (i * 5 + perturb + 1 );
783
- ix = dictkeys_get_index (mp -> ma_keys , i );
784
- if (ix >= 0 ) {
785
- PyDictKeyEntry * ep = & ep0 [ix ];
786
- assert (ep -> me_key != NULL );
787
- assert (PyUnicode_CheckExact (ep -> me_key ));
788
- if (ep -> me_key == key ||
789
- (ep -> me_hash == hash && unicode_eq (ep -> me_key , key ))) {
790
- goto found ;
791
- }
792
- }
793
- else if (ix == DKIX_EMPTY ) {
794
- * value_addr = NULL ;
795
- return DKIX_EMPTY ;
796
- }
797
- perturb >>= PERTURB_SHIFT ;
798
- i = mask & (i * 5 + perturb + 1 );
799
- }
800
- Py_UNREACHABLE ();
801
- }
802
844
for (;;) {
803
845
ix = dictkeys_get_index (dk , i );
804
846
if (ix == DKIX_EMPTY ) {
@@ -4997,15 +5039,15 @@ _PyDictKeys_DecRef(PyDictKeysObject *keys)
4997
5039
4998
5040
static uint32_t next_dict_keys_version = 2 ;
4999
5041
5000
- uint32_t _PyDictKeys_GetVersionForCurrentState (PyDictObject * dict )
5042
+ uint32_t _PyDictKeys_GetVersionForCurrentState (PyDictKeysObject * dictkeys )
5001
5043
{
5002
- if (dict -> ma_keys -> dk_version != 0 ) {
5003
- return dict -> ma_keys -> dk_version ;
5044
+ if (dictkeys -> dk_version != 0 ) {
5045
+ return dictkeys -> dk_version ;
5004
5046
}
5005
5047
if (next_dict_keys_version == 0 ) {
5006
5048
return 0 ;
5007
5049
}
5008
5050
uint32_t v = next_dict_keys_version ++ ;
5009
- dict -> ma_keys -> dk_version = v ;
5051
+ dictkeys -> dk_version = v ;
5010
5052
return v ;
5011
5053
}
0 commit comments