15
15
{-# OPTIONS_GHC -fno-full-laziness -funbox-strict-fields #-}
16
16
{-# OPTIONS_HADDOCK not-home #-}
17
17
18
+ #include "MachDeps.h"
19
+
18
20
-- | = WARNING
19
21
--
20
22
-- This module is considered __internal__.
@@ -125,9 +127,9 @@ module Data.HashMap.Internal
125
127
, sparseIndex
126
128
, two
127
129
, unionArrayBy
128
- , update32
129
- , update32M
130
- , update32With '
130
+ , updateFullArray
131
+ , updateFullArrayM
132
+ , updateFullArrayWith '
131
133
, updateOrConcatWithKey
132
134
, filterMapAux
133
135
, equalKeys
@@ -830,7 +832,7 @@ insert' h0 k0 v0 m0 = go h0 k0 v0 0 m0
830
832
! st' = go h k x (nextShift s) st
831
833
in if st' `ptrEq` st
832
834
then t
833
- else Full (update32 ary i st')
835
+ else Full (updateFullArray ary i st')
834
836
where i = index h s
835
837
go h k x s t@ (Collision hy v)
836
838
| 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
864
866
go h k x s (Full ary) =
865
867
let ! st = A. index ary i
866
868
! st' = go h k x (nextShift s) st
867
- in Full (update32 ary i st')
869
+ in Full (updateFullArray ary i st')
868
870
where i = index h s
869
871
go h k x s t@ (Collision hy v)
870
872
| 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
893
895
go collPos shiftedHash k x (Full ary) =
894
896
let ! st = A. index ary i
895
897
! st' = go collPos (shiftHash shiftedHash) k x st
896
- in Full (update32 ary i st')
898
+ in Full (updateFullArray ary i st')
897
899
where i = index' shiftedHash
898
900
go collPos _shiftedHash k x (Collision h v)
899
901
| collPos >= 0 = Collision h (setAtPosition collPos k x v)
@@ -1041,7 +1043,7 @@ insertModifying x f k0 m0 = go h0 k0 0 m0
1041
1043
go h k s t@ (Full ary) =
1042
1044
let ! st = A. index ary i
1043
1045
! st' = go h k (nextShift s) st
1044
- ary' = update32 ary i $! st'
1046
+ ary' = updateFullArray ary i $! st'
1045
1047
in if ptrEq st st'
1046
1048
then t
1047
1049
else Full ary'
@@ -1270,7 +1272,7 @@ adjust# f k0 m0 = go h0 k0 0 m0
1270
1272
let i = index h s
1271
1273
! st = A. index ary i
1272
1274
! st' = go h k (nextShift s) st
1273
- ary' = update32 ary i $! st'
1275
+ ary' = updateFullArray ary i $! st'
1274
1276
in if ptrEq st st'
1275
1277
then t
1276
1278
else Full ary'
@@ -1554,6 +1556,9 @@ submapBitmapIndexed comp !b1 !ary1 !b2 !ary2 = subsetBitmaps && go 0 0 (b1Orb2 .
1554
1556
where
1555
1557
go :: Int -> Int -> Bitmap -> Bool
1556
1558
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'
1557
1562
| m > b1Orb2 = True
1558
1563
1559
1564
-- In case a key is both in ary1 and ary2, check ary1[i] <= ary2[j] and
@@ -1660,12 +1665,12 @@ unionWithKey f = go 0
1660
1665
go s (Full ary1) t2 =
1661
1666
let h2 = leafHashCode t2
1662
1667
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
1664
1669
in Full ary'
1665
1670
go s t1 (Full ary2) =
1666
1671
let h1 = leafHashCode t1
1667
1672
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
1669
1674
in Full ary'
1670
1675
1671
1676
leafHashCode (Leaf h _) = h
@@ -2406,24 +2411,24 @@ subsetArray cmpV ary1 ary2 = A.length ary1 <= A.length ary2 && A.all inAry2 ary1
2406
2411
-- Manually unrolled loops
2407
2412
2408
2413
-- | \(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 #-}
2412
2417
2413
2418
-- | \(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
2416
2421
mary <- clone ary
2417
2422
A. write mary idx b
2418
2423
A. unsafeFreeze mary
2419
- {-# INLINE update32M #-}
2424
+ {-# INLINE updateFullArrayM #-}
2420
2425
2421
2426
-- | \(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
2424
2429
| (# x # ) <- A. index# ary idx
2425
- = update32 ary idx $! f x
2426
- {-# INLINE update32With ' #-}
2430
+ = updateFullArray ary idx $! f x
2431
+ {-# INLINE updateFullArrayWith ' #-}
2427
2432
2428
2433
-- | Unsafely clone an array of (2^bitsPerSubkey) elements. The length of the input
2429
2434
-- array is not checked.
@@ -2440,8 +2445,16 @@ clone ary =
2440
2445
-- | Number of bits that are inspected at each level of the hash tree.
2441
2446
--
2442
2447
-- 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.
2443
2452
bitsPerSubkey :: Int
2453
+ #if WORD_SIZE_IN_BITS < 64
2454
+ bitsPerSubkey = 4
2455
+ #else
2444
2456
bitsPerSubkey = 5
2457
+ #endif
2445
2458
2446
2459
-- | The size of a 'Full' node, i.e. @2 ^ 'bitsPerSubkey'@.
2447
2460
maxChildren :: Int
0 commit comments