module GHC.HeapView.Debug where
import GHC.HeapView
import Text.Printf
import System.IO
import Control.Monad
import System.Mem
import Data.Maybe
import Data.Char
import Data.IORef
import Control.Applicative ((<$>))
walkHeap
:: Bool
-> Bool
-> Box
-> IO ()
walkHeap slow check x = do
seenRef <- newIORef []
go seenRef [] x
where
go seenRef prefix b = do
_ <- printf "At %s:\n" (show prefix)
seen <- readIORef seenRef
previous <- if check then findM (areBoxesEqual b . fst) seen else return Nothing
case previous of
Just (_,p') -> printf "Seen at %s.\n" (show p')
Nothing -> do
hFlush stdout
c <- getBoxedClosureData b
putStrLn (ppClosure (\_ box -> show box) 0 c)
when slow performGC
isCC <- isCharCons c
unless isCC $ do
modifyIORef seenRef ((b,prefix):)
forM_ (zip [(0::Int)..] (allClosures c)) $ \(n,box) ->
go seenRef (prefix ++ [n]) box
walkPrefix :: [Int] -> a -> IO Box
walkPrefix is v = go is (asBox v)
where
go [] a = return a
go (x:xs) a = do
c <- getBoxedClosureData a
walkPrefix xs (allClosures c !! x)
findM :: (a -> IO Bool) -> [a] -> IO (Maybe a)
findM _p [] = return Nothing
findM p (x:xs) = do
b <- p x
if b then return (Just x) else findM p xs
isCharCons :: GenClosure Box -> IO Bool
isCharCons c | Just (h,_) <- isCons c = (isJust . isChar) <$> getBoxedClosureData h
isCharCons _ = return False
isCons :: GenClosure b -> Maybe (b, b)
isCons (ConstrClosure { name = ":", dataArgs = [], ptrArgs = [h,t]}) = Just (h,t)
isCons _ = Nothing
isChar :: GenClosure b -> Maybe Char
isChar (ConstrClosure { name = "C#", dataArgs = [ch], ptrArgs = []}) = Just (chr (fromIntegral ch))
isChar _ = Nothing