@@ -877,31 +877,41 @@ insertNewKey !h0 !k0 x0 !m0 = go h0 k0 x0 0 m0
877877--
878878-- It is only valid to call this when the key exists in the map and you know the
879879-- 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
881881-- (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.
885882insertKeyExists :: 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
887884 where
888- go ! _collPos ! h ! k x ! _s (Leaf _hy _kx)
885+ go ! _collPos ! _shiftedHash ! k x (Leaf h _kx)
889886 = Leaf h (L k x)
890- go collPos h k x s (BitmapIndexed b ary) =
887+ go collPos shiftedHash k x (BitmapIndexed b ary) =
891888 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
893890 in BitmapIndexed b (A. update ary i st')
894- where m = mask h s
891+ where m = mask' shiftedHash
895892 i = sparseIndex b m
896- go collPos h k x s (Full ary) =
893+ go collPos shiftedHash k x (Full ary) =
897894 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
899896 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)
902899 | collPos >= 0 = Collision h (setAtPosition collPos k x v)
903900 | 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 #-}
905915
906916{-# NOINLINE insertKeyExists #-}
907917
@@ -1159,18 +1169,15 @@ delete' h0 k0 m0 = go h0 k0 0 m0
11591169--
11601170-- It is only valid to call this when the key exists in the map and you know the
11611171-- 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.
11661173deleteKeyExists :: 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
11681175 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) =
11721179 let ! st = A. index ary i
1173- ! st' = go collPos h k (nextShift s) st
1180+ ! st' = go collPos (shiftHash shiftedHash) k st
11741181 in case st' of
11751182 Empty | A. length ary == 1 -> Empty
11761183 | A. length ary == 2 ->
@@ -1183,25 +1190,39 @@ deleteKeyExists !collPos0 !h0 !k0 !m0 = go collPos0 h0 k0 0 m0
11831190 bIndexed = BitmapIndexed (b .&. complement m) (A. delete ary i)
11841191 l | isLeafOrCollision l && A. length ary == 1 -> l
11851192 _ -> BitmapIndexed b (A. update ary i st')
1186- where m = mask h s
1193+ where m = mask' shiftedHash
11871194 i = sparseIndex b m
1188- go collPos h k s (Full ary) =
1195+ go collPos shiftedHash k (Full ary) =
11891196 let ! st = A. index ary i
1190- ! st' = go collPos h k (nextShift s) st
1197+ ! st' = go collPos (shiftHash shiftedHash) k st
11911198 in case st' of
11921199 Empty ->
11931200 let ary' = A. delete ary i
11941201 bm = fullBitmap .&. complement (1 `unsafeShiftL` i)
11951202 in BitmapIndexed bm ary'
11961203 _ -> 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)
11991206 | A. length v == 2
12001207 = if collPos == 0
12011208 then Leaf h (A. index v 1 )
12021209 else Leaf h (A. index v 0 )
12031210 | 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+
12051226{-# NOINLINE deleteKeyExists #-}
12061227
12071228-- | \(O(\log n)\) Adjust the value tied to a given key in this map only
0 commit comments