diff options
author | Ben Gamari <ben@smart-cactus.org> | 2019-03-13 19:42:47 -0400 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2019-03-17 05:05:10 -0400 |
commit | cb61371e3260e07be724a04b72a935133f66b514 (patch) | |
tree | 456e4f3fa84ab7f8fa94ed66f717f6ea949899f8 /libraries/ghc-heap | |
parent | 3f2291e47b8e00f1312c9be31484ceddd1289212 (diff) | |
download | haskell-cb61371e3260e07be724a04b72a935133f66b514.tar.gz |
ghc-heap: Introduce closureSize
This function allows the user to compute the (non-transitive) size of a
heap object in words. The "closure" in the name is admittedly confusing
but we are stuck with this nomenclature at this point.
Diffstat (limited to 'libraries/ghc-heap')
-rw-r--r-- | libraries/ghc-heap/GHC/Exts/Heap/Closures.hs | 14 | ||||
-rw-r--r-- | libraries/ghc-heap/tests/all.T | 3 | ||||
-rw-r--r-- | libraries/ghc-heap/tests/closure_size.hs | 34 | ||||
-rw-r--r-- | libraries/ghc-heap/tests/closure_size.stdout | 0 |
4 files changed, 51 insertions, 0 deletions
diff --git a/libraries/ghc-heap/GHC/Exts/Heap/Closures.hs b/libraries/ghc-heap/GHC/Exts/Heap/Closures.hs index e624a17b78..2465014e48 100644 --- a/libraries/ghc-heap/GHC/Exts/Heap/Closures.hs +++ b/libraries/ghc-heap/GHC/Exts/Heap/Closures.hs @@ -13,6 +13,12 @@ module GHC.Exts.Heap.Closures ( , GenClosure(..) , PrimType(..) , allClosures +#if __GLASGOW_HASKELL__ >= 809 + -- The closureSize# primop is unsupported on earlier GHC releases but we + -- build ghc-heap as a boot library so it must be buildable. Drop this once + -- we are guaranteed to bootstsrap with GHC >= 8.9. + , closureSize +#endif -- * Boxes , Box(..) @@ -321,3 +327,11 @@ allClosures (FunClosure {..}) = ptrArgs allClosures (BlockingQueueClosure {..}) = [link, blackHole, owner, queue] allClosures (OtherClosure {..}) = hvalues allClosures _ = [] + +#if __GLASGOW_HASKELL__ >= 809 +-- | Get the size of a closure in words. +-- +-- @since 8.10.1 +closureSize :: Box -> Int +closureSize (Box x) = I# (closureSize# x) +#endif diff --git a/libraries/ghc-heap/tests/all.T b/libraries/ghc-heap/tests/all.T index a676b4971a..595bd000d4 100644 --- a/libraries/ghc-heap/tests/all.T +++ b/libraries/ghc-heap/tests/all.T @@ -6,3 +6,6 @@ test('heap_all', omit_ways(['ghci', 'hpc']) ], compile_and_run, ['']) +test('closure_size', + omit_ways(['ghci', 'hpc', 'prof']), + compile_and_run, ['']) diff --git a/libraries/ghc-heap/tests/closure_size.hs b/libraries/ghc-heap/tests/closure_size.hs new file mode 100644 index 0000000000..d77060779e --- /dev/null +++ b/libraries/ghc-heap/tests/closure_size.hs @@ -0,0 +1,34 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE ScopedTypeVariables #-} + +import Control.Monad +import Type.Reflection +import GHC.Stack + +import GHC.Exts.Heap.Closures + +assertSize :: forall a. (HasCallStack, Typeable a) + => a -> Int -> IO () +assertSize !x expected = do + let !size = closureSize (asBox x) + when (size /= expected) $ do + putStrLn $ "closureSize ("++show (typeRep @a)++") == "++show size++", expected "++show expected + putStrLn $ prettyCallStack callStack +{-# NOINLINE assertSize #-} + +pap :: Int -> Char -> Int +pap x _ = x +{-# NOINLINE pap #-} + +main :: IO () +main = do + assertSize 'a' 2 + assertSize (Just ()) 2 + assertSize (Nothing :: Maybe ()) 2 + assertSize ((1,2) :: (Int,Int)) 3 + assertSize ((1,2,3) :: (Int,Int,Int)) 4 + assertSize (id :: Int -> Int) 1 + assertSize (fst :: (Int,Int) -> Int) 1 + assertSize (pap 1) 2 + diff --git a/libraries/ghc-heap/tests/closure_size.stdout b/libraries/ghc-heap/tests/closure_size.stdout new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/libraries/ghc-heap/tests/closure_size.stdout |