Skip to content

Commit 6ebe947

Browse files
authored
Update Regressions.hs
1 parent 208e450 commit 6ebe947

File tree

1 file changed

+20
-23
lines changed

1 file changed

+20
-23
lines changed

tests/Regressions.hs

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
{-# LANGUAGE ScopedTypeVariables #-}
2+
{-# LANGUAGE MagicHash #-}
3+
{-# LANGUAGE UnboxedTuples #-}
14
module Main where
25

36
import Control.Applicative ((<$>))
@@ -8,8 +11,11 @@ import qualified Data.HashMap.Strict as HM
811
import qualified Data.HashMap.Lazy as HML
912
import Data.List (delete)
1013
import Data.Maybe
14+
import GHC.Exts (touch#)
15+
import GHC.IO (IO (..))
1116
import System.Mem (performGC)
1217
import System.Mem.Weak (mkWeakPtr, deRefWeak)
18+
import System.Random (randomIO)
1319
import Test.HUnit (Assertion, assert)
1420
import Test.Framework (Test, defaultMain)
1521
import Test.Framework.Providers.HUnit (testCase)
@@ -85,46 +91,37 @@ newtype KC = KC Int
8591
instance Hashable KC where
8692
hashWithSalt salt _ = salt
8793

88-
issue254Lazy :: Assertion
89-
issue254Lazy = issue254LazyLambda 2
94+
touch :: a -> IO ()
95+
touch a = IO (\s -> (# touch# a s, () #))
9096

9197
-- We want to make sure that old values in the HashMap are evicted when new values are inserted,
9298
-- even if they aren't evaluated. To do that, we use the WeakPtr trick described at
9399
-- http://simonmar.github.io/posts/2018-06-20-Finding-fixing-space-leaks.html.
94100
-- We insert a value named oldV into the HashMap, then insert over it, checking oldV is no longer reachable.
95101
--
96-
-- To make the test robust, it's important that oldV isn't hoisted up to the top or shared. To do that,
97-
-- we use NOINLINE, make oldV dependent on an unseen argument, and insert _ <- return () to ensure oldV
98-
-- is under a lambda.
99-
{-# NOINLINE issue254LazyLambda #-}
100-
issue254LazyLambda :: Int -> Assertion
101-
issue254LazyLambda i = do
102-
_ <- return () -- put oldV under a lambda
102+
-- To make the test robust, it's important that oldV isn't hoisted up to the top or shared.
103+
-- To do that, we generate it randomly.
104+
issue254Lazy :: Assertion
105+
issue254Lazy = do
106+
i :: Int <- randomIO
103107
let oldV = error $ "Should not be evaluated: " ++ show i
104-
weakV <- mkWeakPtr oldV Nothing -- test whether oldV is alive
105-
let mp = HML.insert (KC 1) (error "Should not be evaluated") $ HML.fromList [(KC 0, "1"), (KC 1, oldV)]
106-
_ <- evaluate mp -- force the insert to happen
108+
weakV <- mkWeakPtr oldV Nothing -- add the ability to test whether oldV is alive
109+
mp <- evaluate $ HML.insert (KC 1) (error "Should not be evaluated") $ HML.fromList [(KC 0, "1"), (KC 1, oldV)]
107110
performGC
108111
res <- deRefWeak weakV -- gives Just if oldV is still alive
109-
_ <- evaluate mp -- makes sure that we didn't GC away the whole HashMap, just oldV
112+
touch mp -- makes sure that we didn't GC away the whole HashMap, just oldV
110113
assert $ isNothing res
111114

112115
-- Like issue254Lazy, but using strict HashMap
113116
issue254Strict :: Assertion
114-
issue254Strict = issue254StrictLambda 2
115-
116-
-- Important that oldV is not hoisted out by optimisation, so use NOINLINE
117-
{-# NOINLINE issue254StrictLambda #-}
118-
issue254StrictLambda :: Int -> Assertion
119-
issue254StrictLambda i = do
120-
_ <- return ()
117+
issue254Strict = do
118+
i :: Int <- randomIO
121119
let oldV = show i
122120
weakV <- mkWeakPtr oldV Nothing
123-
let mp = HM.insert (KC 1) "3" $ HM.fromList [(KC 0, "1"), (KC 1, oldV)]
124-
_ <- evaluate mp
121+
mp <- evaluate $ HM.insert (KC 1) "3" $ HM.fromList [(KC 0, "1"), (KC 1, oldV)]
125122
performGC
126123
res <- deRefWeak weakV
127-
_ <- evaluate mp
124+
touch mp
128125
assert $ isNothing res
129126

130127
------------------------------------------------------------------------

0 commit comments

Comments
 (0)