@@ -877,31 +877,41 @@ insertNewKey !h0 !k0 x0 !m0 = go h0 k0 x0 0 m0
877
877
--
878
878
-- It is only valid to call this when the key exists in the map and you know the
879
879
-- hash collision position if there was one. This information can be obtained
880
- -- from 'lookupRecordCollision'. If there is no collision pass (-1) as collPos
880
+ -- from 'lookupRecordCollision'. If there is no collision, pass (-1) as collPos
881
881
-- (first argument).
882
- --
883
- -- We can skip the key equality check on a Leaf because we know the leaf must be
884
- -- for this key.
885
882
insertKeyExists :: Int -> Hash -> k -> v -> HashMap k v -> HashMap k v
886
- insertKeyExists ! collPos0 ! h0 ! k0 x0 ! m0 = go collPos0 h0 k0 x0 0 m0
883
+ insertKeyExists ! collPos0 ! h0 ! k0 x0 ! m0 = go collPos0 h0 k0 x0 m0
887
884
where
888
- go ! _collPos ! h ! k x ! _s (Leaf _hy _kx)
885
+ go ! _collPos ! _shiftedHash ! k x (Leaf h _kx)
889
886
= Leaf h (L k x)
890
- go collPos h k x s (BitmapIndexed b ary) =
887
+ go collPos shiftedHash k x (BitmapIndexed b ary) =
891
888
let ! st = A. index ary i
892
- ! st' = go collPos h k x (nextShift s) st
889
+ ! st' = go collPos (shiftHash shiftedHash) k x st
893
890
in BitmapIndexed b (A. update ary i st')
894
- where m = mask h s
891
+ where m = mask' shiftedHash
895
892
i = sparseIndex b m
896
- go collPos h k x s (Full ary) =
893
+ go collPos shiftedHash k x (Full ary) =
897
894
let ! st = A. index ary i
898
- ! st' = go collPos h k x (nextShift s) st
895
+ ! st' = go collPos (shiftHash shiftedHash) k x st
899
896
in Full (update32 ary i st')
900
- where i = index h s
901
- go collPos h k x _s (Collision _hy v)
897
+ where i = index' shiftedHash
898
+ go collPos _shiftedHash k x (Collision h v)
902
899
| collPos >= 0 = Collision h (setAtPosition collPos k x v)
903
900
| otherwise = Empty -- error "Internal error: go {collPos negative}"
904
- go _ _ _ _ _ Empty = Empty -- error "Internal error: go Empty"
901
+ go _ _ _ _ Empty = Empty -- error "Internal error: go Empty"
902
+
903
+ -- Customized version of 'index' that doesn't require a 'Shift'.
904
+ index' :: Hash -> Int
905
+ index' w = fromIntegral $ w .&. subkeyMask
906
+ {-# INLINE index' #-}
907
+
908
+ -- Customized version of 'mask' that doesn't require a 'Shift'.
909
+ mask' :: Word -> Bitmap
910
+ mask' w = 1 `unsafeShiftL` index' w
911
+ {-# INLINE mask' #-}
912
+
913
+ shiftHash h = h `unsafeShiftR` bitsPerSubkey
914
+ {-# INLINE shiftHash #-}
905
915
906
916
{-# NOINLINE insertKeyExists #-}
907
917
@@ -1159,18 +1169,15 @@ delete' h0 k0 m0 = go h0 k0 0 m0
1159
1169
--
1160
1170
-- It is only valid to call this when the key exists in the map and you know the
1161
1171
-- hash collision position if there was one. This information can be obtained
1162
- -- from 'lookupRecordCollision'. If there is no collision pass (-1) as collPos.
1163
- --
1164
- -- We can skip:
1165
- -- - the key equality check on the leaf, if we reach a leaf it must be the key
1172
+ -- from 'lookupRecordCollision'. If there is no collision, pass (-1) as collPos.
1166
1173
deleteKeyExists :: Int -> Hash -> k -> HashMap k v -> HashMap k v
1167
- deleteKeyExists ! collPos0 ! h0 ! k0 ! m0 = go collPos0 h0 k0 0 m0
1174
+ deleteKeyExists ! collPos0 ! h0 ! k0 ! m0 = go collPos0 h0 k0 m0
1168
1175
where
1169
- go :: Int -> Hash -> k -> Int -> HashMap k v -> HashMap k v
1170
- go ! _collPos ! _h ! _k ! _s (Leaf _ _) = Empty
1171
- go collPos h k s (BitmapIndexed b ary) =
1176
+ go :: Int -> Word -> k -> HashMap k v -> HashMap k v
1177
+ go ! _collPos ! _shiftedHash ! _k (Leaf _ _) = Empty
1178
+ go collPos shiftedHash k (BitmapIndexed b ary) =
1172
1179
let ! st = A. index ary i
1173
- ! st' = go collPos h k (nextShift s) st
1180
+ ! st' = go collPos (shiftHash shiftedHash) k st
1174
1181
in case st' of
1175
1182
Empty | A. length ary == 1 -> Empty
1176
1183
| A. length ary == 2 ->
@@ -1183,25 +1190,39 @@ deleteKeyExists !collPos0 !h0 !k0 !m0 = go collPos0 h0 k0 0 m0
1183
1190
bIndexed = BitmapIndexed (b .&. complement m) (A. delete ary i)
1184
1191
l | isLeafOrCollision l && A. length ary == 1 -> l
1185
1192
_ -> BitmapIndexed b (A. update ary i st')
1186
- where m = mask h s
1193
+ where m = mask' shiftedHash
1187
1194
i = sparseIndex b m
1188
- go collPos h k s (Full ary) =
1195
+ go collPos shiftedHash k (Full ary) =
1189
1196
let ! st = A. index ary i
1190
- ! st' = go collPos h k (nextShift s) st
1197
+ ! st' = go collPos (shiftHash shiftedHash) k st
1191
1198
in case st' of
1192
1199
Empty ->
1193
1200
let ary' = A. delete ary i
1194
1201
bm = fullBitmap .&. complement (1 `unsafeShiftL` i)
1195
1202
in BitmapIndexed bm ary'
1196
1203
_ -> Full (A. update ary i st')
1197
- where i = index h s
1198
- go collPos h _ _ (Collision _hy v)
1204
+ where i = index' shiftedHash
1205
+ go collPos _shiftedHash _k (Collision h v)
1199
1206
| A. length v == 2
1200
1207
= if collPos == 0
1201
1208
then Leaf h (A. index v 1 )
1202
1209
else Leaf h (A. index v 0 )
1203
1210
| otherwise = Collision h (A. delete v collPos)
1204
- go ! _ ! _ ! _ ! _ Empty = Empty -- error "Internal error: deleteKeyExists empty"
1211
+ go ! _ ! _ ! _ Empty = Empty -- error "Internal error: deleteKeyExists empty"
1212
+
1213
+ -- Customized version of 'index' that doesn't require a 'Shift'.
1214
+ index' :: Hash -> Int
1215
+ index' w = fromIntegral $ w .&. subkeyMask
1216
+ {-# INLINE index' #-}
1217
+
1218
+ -- Customized version of 'mask' that doesn't require a 'Shift'.
1219
+ mask' :: Word -> Bitmap
1220
+ mask' w = 1 `unsafeShiftL` index' w
1221
+ {-# INLINE mask' #-}
1222
+
1223
+ shiftHash h = h `unsafeShiftR` bitsPerSubkey
1224
+ {-# INLINE shiftHash #-}
1225
+
1205
1226
{-# NOINLINE deleteKeyExists #-}
1206
1227
1207
1228
-- | \(O(\log n)\) Adjust the value tied to a given key in this map only
0 commit comments