Skip to content

Commit 21d960a

Browse files
committed
Introduce size-aware 'insertInternal' function
1 parent 1b48d0c commit 21d960a

File tree

1 file changed

+45
-1
lines changed

1 file changed

+45
-1
lines changed

Data/HashMap/Base.hs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ data HashMap k v
157157

158158
type role HashMap nominal representational
159159

160+
-- | WIP. This will become the user-facing 'HashMap' after this PR is
161+
-- finalized.
162+
data HashMapW = HashMapW {-# UNPACK #-} !Int !HashMap
163+
160164
instance (NFData k, NFData v) => NFData (HashMap k v) where
161165
rnf Empty = ()
162166
rnf (BitmapIndexed _ ary) = rnf ary
@@ -523,6 +527,46 @@ insert k0 v0 m0 = go h0 k0 v0 0 m0
523527
| otherwise = go h k x s $ BitmapIndexed (mask hy s) (A.singleton t)
524528
{-# INLINABLE insert #-}
525529

530+
insertInternal :: (Eq k, Hashable k) => k -> v -> HashMap k v -> (Int, HashMap k v)
531+
insertInternal k0 v0 m0 = go h0 k0 v0 0 m0
532+
where
533+
h0 = hash k0
534+
go !h !k x !_ Empty = (1, Leaf h (L k x))
535+
go h k x s t@(Leaf hy l@(L ky y))
536+
| hy == h = if ky == k
537+
then if x `ptrEq` y
538+
then (0, t)
539+
else (0, Leaf h (L k x))
540+
else (1, collision h l (L k x))
541+
| otherwise = (1, runST (two s h k x hy ky y))
542+
go h k x s t@(BitmapIndexed b ary)
543+
| b .&. m == 0 =
544+
let !ary' = A.insert ary i $! Leaf h (L k x)
545+
in (1, bitmapIndexedOrFull (b .|. m) ary')
546+
| otherwise =
547+
let !st = A.index ary i
548+
(!sz, !st') = go h k x (s+bitsPerSubkey) st
549+
in if st' `ptrEq` st
550+
then (sz, t)
551+
else (sz, BitmapIndexed b (A.update ary i st'))
552+
where m = mask h s
553+
i = sparseIndex b m
554+
go h k x s t@(Full ary) =
555+
let !st = A.index ary i
556+
(!sz, !st') = go h k x (s+bitsPerSubkey) st
557+
in if st' `ptrEq` st
558+
then (sz, t)
559+
else (sz, Full (update16 ary i st'))
560+
where i = index h s
561+
go h k x s t@(Collision hy v)
562+
| h == hy =
563+
let !start = A.length v
564+
!newV = updateOrSnocWith const k x v
565+
!end = A.length newV
566+
in (end - start, Collision h newV)
567+
| otherwise = go h k x s $ BitmapIndexed (mask hy s) (A.singleton t)
568+
{-# INLINABLE insertInternal #-}
569+
526570
-- | In-place update version of insert
527571
unsafeInsert :: (Eq k, Hashable k) => k -> v -> HashMap k v -> HashMap k v
528572
unsafeInsert k0 v0 m0 = runST (go h0 k0 v0 0 m0)
@@ -1342,7 +1386,7 @@ fullNodeMask :: Bitmap
13421386
fullNodeMask = complement (complement 0 `unsafeShiftL` maxChildren)
13431387
{-# INLINE fullNodeMask #-}
13441388

1345-
-- | Check if two the two arguments are the same value. N.B. This
1389+
-- | Check if the two arguments are the same value. N.B. This
13461390
-- function might give false negatives (due to GC moving objects.)
13471391
ptrEq :: a -> a -> Bool
13481392
ptrEq x y = isTrue# (reallyUnsafePtrEquality# x y ==# 1#)

0 commit comments

Comments
 (0)