1515{-# OPTIONS_GHC -fno-full-laziness -funbox-strict-fields #-}
1616{-# OPTIONS_HADDOCK not-home #-}
1717
18+ #include "MachDeps.h"
19+
1820-- | = WARNING
1921--
2022-- This module is considered __internal__.
@@ -125,9 +127,9 @@ module Data.HashMap.Internal
125127 , sparseIndex
126128 , two
127129 , unionArrayBy
128- , update32
129- , update32M
130- , update32With '
130+ , updateFullArray
131+ , updateFullArrayM
132+ , updateFullArrayWith '
131133 , updateOrConcatWithKey
132134 , filterMapAux
133135 , equalKeys
@@ -830,7 +832,7 @@ insert' h0 k0 v0 m0 = go h0 k0 v0 0 m0
830832 ! st' = go h k x (nextShift s) st
831833 in if st' `ptrEq` st
832834 then t
833- else Full (update32 ary i st')
835+ else Full (updateFullArray ary i st')
834836 where i = index h s
835837 go h k x s t@ (Collision hy v)
836838 | h == hy = Collision h (updateOrSnocWith (\ a _ -> (# a # )) k x v)
@@ -864,7 +866,7 @@ insertNewKey !h0 !k0 x0 !m0 = go h0 k0 x0 0 m0
864866 go h k x s (Full ary) =
865867 let ! st = A. index ary i
866868 ! st' = go h k x (nextShift s) st
867- in Full (update32 ary i st')
869+ in Full (updateFullArray ary i st')
868870 where i = index h s
869871 go h k x s t@ (Collision hy v)
870872 | h == hy = Collision h (A. snoc v (L k x))
@@ -893,7 +895,7 @@ insertKeyExists !collPos0 !h0 !k0 x0 !m0 = go collPos0 h0 k0 x0 m0
893895 go collPos shiftedHash k x (Full ary) =
894896 let ! st = A. index ary i
895897 ! st' = go collPos (shiftHash shiftedHash) k x st
896- in Full (update32 ary i st')
898+ in Full (updateFullArray ary i st')
897899 where i = index' shiftedHash
898900 go collPos _shiftedHash k x (Collision h v)
899901 | collPos >= 0 = Collision h (setAtPosition collPos k x v)
@@ -1041,7 +1043,7 @@ insertModifying x f k0 m0 = go h0 k0 0 m0
10411043 go h k s t@ (Full ary) =
10421044 let ! st = A. index ary i
10431045 ! st' = go h k (nextShift s) st
1044- ary' = update32 ary i $! st'
1046+ ary' = updateFullArray ary i $! st'
10451047 in if ptrEq st st'
10461048 then t
10471049 else Full ary'
@@ -1270,7 +1272,7 @@ adjust# f k0 m0 = go h0 k0 0 m0
12701272 let i = index h s
12711273 ! st = A. index ary i
12721274 ! st' = go h k (nextShift s) st
1273- ary' = update32 ary i $! st'
1275+ ary' = updateFullArray ary i $! st'
12741276 in if ptrEq st st'
12751277 then t
12761278 else Full ary'
@@ -1554,6 +1556,9 @@ submapBitmapIndexed comp !b1 !ary1 !b2 !ary2 = subsetBitmaps && go 0 0 (b1Orb2 .
15541556 where
15551557 go :: Int -> Int -> Bitmap -> Bool
15561558 go ! i ! j ! m
1559+
1560+ -- Note: m can overflow to 0 when maxChildren == WORD_SIZE_IN_BITS. See
1561+ -- #491. In that case there needs to be a check '| m == 0 = True'
15571562 | m > b1Orb2 = True
15581563
15591564 -- In case a key is both in ary1 and ary2, check ary1[i] <= ary2[j] and
@@ -1660,12 +1665,12 @@ unionWithKey f = go 0
16601665 go s (Full ary1) t2 =
16611666 let h2 = leafHashCode t2
16621667 i = index h2 s
1663- ary' = update32With ' ary1 i $ \ st1 -> go (nextShift s) st1 t2
1668+ ary' = updateFullArrayWith ' ary1 i $ \ st1 -> go (nextShift s) st1 t2
16641669 in Full ary'
16651670 go s t1 (Full ary2) =
16661671 let h1 = leafHashCode t1
16671672 i = index h1 s
1668- ary' = update32With ' ary2 i $ \ st2 -> go (nextShift s) t1 st2
1673+ ary' = updateFullArrayWith ' ary2 i $ \ st2 -> go (nextShift s) t1 st2
16691674 in Full ary'
16701675
16711676 leafHashCode (Leaf h _) = h
@@ -2406,24 +2411,24 @@ subsetArray cmpV ary1 ary2 = A.length ary1 <= A.length ary2 && A.all inAry2 ary1
24062411-- Manually unrolled loops
24072412
24082413-- | \(O(n)\) Update the element at the given position in this array.
2409- update32 :: A. Array e -> Int -> e -> A. Array e
2410- update32 ary idx b = runST (update32M ary idx b)
2411- {-# INLINE update32 #-}
2414+ updateFullArray :: A. Array e -> Int -> e -> A. Array e
2415+ updateFullArray ary idx b = runST (updateFullArrayM ary idx b)
2416+ {-# INLINE updateFullArray #-}
24122417
24132418-- | \(O(n)\) Update the element at the given position in this array.
2414- update32M :: A. Array e -> Int -> e -> ST s (A. Array e )
2415- update32M ary idx b = do
2419+ updateFullArrayM :: A. Array e -> Int -> e -> ST s (A. Array e )
2420+ updateFullArrayM ary idx b = do
24162421 mary <- clone ary
24172422 A. write mary idx b
24182423 A. unsafeFreeze mary
2419- {-# INLINE update32M #-}
2424+ {-# INLINE updateFullArrayM #-}
24202425
24212426-- | \(O(n)\) Update the element at the given position in this array, by applying a function to it.
2422- update32With ' :: A. Array e -> Int -> (e -> e ) -> A. Array e
2423- update32With ' ary idx f
2427+ updateFullArrayWith ' :: A. Array e -> Int -> (e -> e ) -> A. Array e
2428+ updateFullArrayWith ' ary idx f
24242429 | (# x # ) <- A. index# ary idx
2425- = update32 ary idx $! f x
2426- {-# INLINE update32With ' #-}
2430+ = updateFullArray ary idx $! f x
2431+ {-# INLINE updateFullArrayWith ' #-}
24272432
24282433-- | Unsafely clone an array of (2^bitsPerSubkey) elements. The length of the input
24292434-- array is not checked.
@@ -2440,8 +2445,16 @@ clone ary =
24402445-- | Number of bits that are inspected at each level of the hash tree.
24412446--
24422447-- This constant is named /t/ in the original /Ideal Hash Trees/ paper.
2448+ --
2449+ -- Note that this constant is platform-dependent. On 32-bit platforms we use
2450+ -- '4', because bitmaps using '2^5' bits turned out to be prone to integer
2451+ -- overflow bugs. See #491 for instance.
24432452bitsPerSubkey :: Int
2453+ #if WORD_SIZE_IN_BITS < 64
2454+ bitsPerSubkey = 4
2455+ #else
24442456bitsPerSubkey = 5
2457+ #endif
24452458
24462459-- | The size of a 'Full' node, i.e. @2 ^ 'bitsPerSubkey'@.
24472460maxChildren :: Int
0 commit comments