good gc
This commit is contained in:
@@ -20,8 +20,10 @@ module Data.Heap
|
|||||||
where
|
where
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
import Data.Map (Map, (!?))
|
import Data.Map (Map, (!?))
|
||||||
|
import Debug.Trace
|
||||||
import Data.Map qualified as M
|
import Data.Map qualified as M
|
||||||
import Data.List (intersect)
|
import Data.List (intersect)
|
||||||
|
import GHC.Stack (HasCallStack)
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
data Heap a = Heap [Addr] (Map Addr a)
|
data Heap a = Heap [Addr] (Map Addr a)
|
||||||
@@ -62,15 +64,16 @@ adjust :: Addr -> (a -> a) -> Heap a -> Heap a
|
|||||||
adjust k f (Heap u m) = Heap u (M.adjust f k m)
|
adjust k f (Heap u m) = Heap u (M.adjust f k m)
|
||||||
|
|
||||||
free :: Addr -> Heap a -> Heap a
|
free :: Addr -> Heap a -> Heap a
|
||||||
free k (Heap u m) = Heap (k:u) (M.delete k m)
|
free k (Heap u m) = Heap (k:u) (M.delete k' m)
|
||||||
|
where k' = k -- trace ("free " <> show k) k
|
||||||
|
|
||||||
hLookup :: Addr -> Heap a -> Maybe a
|
hLookup :: Addr -> Heap a -> Maybe a
|
||||||
hLookup k (Heap _ m) = m !? k
|
hLookup k (Heap _ m) = m !? k
|
||||||
|
|
||||||
hLookupUnsafe :: Addr -> Heap a -> a
|
hLookupUnsafe :: (HasCallStack) => Addr -> Heap a -> a
|
||||||
hLookupUnsafe k (Heap _ m) = case m !? k of
|
hLookupUnsafe k (Heap _ m) = case m !? k of
|
||||||
Just a -> a
|
Just v -> v
|
||||||
Nothing -> error "erm... segfault much?"
|
Nothing -> error $ "erm... segfault much? addr: " <> show k
|
||||||
|
|
||||||
addresses :: Heap a -> [Addr]
|
addresses :: Heap a -> [Addr]
|
||||||
addresses (Heap _ m) = M.keys m
|
addresses (Heap _ m) = M.keys m
|
||||||
|
|||||||
60
src/TIM.hs
60
src/TIM.hs
@@ -16,6 +16,7 @@ import System.IO (Handle, hPutStr)
|
|||||||
import Text.Printf (printf, hPrintf)
|
import Text.Printf (printf, hPrintf)
|
||||||
import Data.Proxy (Proxy(..))
|
import Data.Proxy (Proxy(..))
|
||||||
import Data.Monoid (Endo(..))
|
import Data.Monoid (Endo(..))
|
||||||
|
import Debug.Trace (trace)
|
||||||
import Lens.Micro
|
import Lens.Micro
|
||||||
import Lens.Micro.TH
|
import Lens.Micro.TH
|
||||||
import Data.Pretty
|
import Data.Pretty
|
||||||
@@ -39,6 +40,7 @@ data Node = NAp Addr Addr
|
|||||||
| NNum Int
|
| NNum Int
|
||||||
| NInd Addr
|
| NInd Addr
|
||||||
| NData Int [Addr] -- NData Tag [Component]
|
| NData Int [Addr] -- NData Tag [Component]
|
||||||
|
| NMarked Node
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
type Dump = [Stack]
|
type Dump = [Stack]
|
||||||
@@ -464,6 +466,7 @@ isDataNode _ = False
|
|||||||
needsEval :: Node -> Bool
|
needsEval :: Node -> Bool
|
||||||
needsEval = not . isDataNode
|
needsEval = not . isDataNode
|
||||||
|
|
||||||
|
-- TODO: count allocations
|
||||||
doAdmin :: TiState -> TiState
|
doAdmin :: TiState -> TiState
|
||||||
doAdmin = doStats
|
doAdmin = doStats
|
||||||
. doGC
|
. doGC
|
||||||
@@ -478,10 +481,6 @@ isHeapLarge :: TiState -> Bool
|
|||||||
isHeapLarge st = hSize (st ^. tiHeap) >= triggerSize
|
isHeapLarge st = hSize (st ^. tiHeap) >= triggerSize
|
||||||
where triggerSize = 50
|
where triggerSize = 50
|
||||||
|
|
||||||
whenE :: Bool -> (a -> a) -> a -> a
|
|
||||||
whenE True f = f
|
|
||||||
whenE False _ = id
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
dbgProg :: Program -> IO (Node, Stats)
|
dbgProg :: Program -> IO (Node, Stats)
|
||||||
@@ -560,6 +559,8 @@ instance Pretty TiState where
|
|||||||
& intersperse " "
|
& intersperse " "
|
||||||
& mconcat
|
& mconcat
|
||||||
|
|
||||||
|
pnode (NMarked n) p = bracketPrec 0 p $ "NMarked (" <> pnode n 0 <> ")"
|
||||||
|
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
findRoots :: TiState -> [Addr]
|
findRoots :: TiState -> [Addr]
|
||||||
@@ -574,39 +575,34 @@ findRoots (TiState s d _ g _) = stackRoots s <> dumpRoots d <> globalsRoots g
|
|||||||
globalsRoots :: Env -> [Addr]
|
globalsRoots :: Env -> [Addr]
|
||||||
globalsRoots = fmap snd
|
globalsRoots = fmap snd
|
||||||
|
|
||||||
prepMarks :: TiHeap -> Heap (Node, Bool)
|
markFrom :: Addr -> TiHeap -> TiHeap
|
||||||
prepMarks = fmap (,False)
|
|
||||||
|
|
||||||
unprepMarks :: Heap (Node, Bool) -> TiHeap
|
|
||||||
unprepMarks = fmap fst
|
|
||||||
|
|
||||||
markFrom :: Addr -> Heap (Node, Bool) -> Heap (Node, Bool)
|
|
||||||
markFrom a h = case hLookup a h of
|
markFrom a h = case hLookup a h of
|
||||||
Just (NAp l r,_) -> h & mark & markFrom l & markFrom r
|
Just (NMarked _) -> h
|
||||||
Just (NInd x,_) -> h & mark & markFrom x
|
Just n@(NAp l r) -> h & update a (NMarked n)
|
||||||
Just (NData _ as,_) -> h & mark
|
& markFrom l
|
||||||
& appEndo (foldMap Endo $ fmap markFrom as)
|
& markFrom r
|
||||||
Just (x,_) -> h & mark
|
-- note that we don't mark the indirection node itself.
|
||||||
where mark = adjust a (_2 .~ True)
|
Just n@(NInd p) -> h & update a (NMarked n)
|
||||||
|
& markFrom p
|
||||||
|
Just n@(NData _ as) -> h & update a (NMarked n)
|
||||||
|
& appEndo (foldMap Endo $ markFrom <$> as)
|
||||||
|
Just n -> h & update a (NMarked n)
|
||||||
|
|
||||||
-- TODO: unmedicated code: rewrite
|
-- we silently ignore dangling pointers without a ruckus as findRoots may
|
||||||
scanHeap :: Heap (Node, Bool) -> TiHeap
|
-- scout the same address multiple times
|
||||||
scanHeap h = unmark $ appEndo (scan h) h
|
Nothing -> h
|
||||||
|
|
||||||
|
scanHeap :: TiHeap -> TiHeap
|
||||||
|
scanHeap h = appEndo (foldMap f $ addresses h) h
|
||||||
where
|
where
|
||||||
unmark = fmap fst
|
f a = case hLookupUnsafe a h of
|
||||||
scanAddr :: Addr -> (Node, Bool)
|
NMarked n -> Endo $ update a n
|
||||||
-> Endo (Heap (Node, Bool))
|
_ -> Endo $ free a
|
||||||
scanAddr k (_,True) = Endo $ id
|
|
||||||
scanAddr k (_,False) = Endo $ free k
|
|
||||||
|
|
||||||
scan :: Heap (Node, Bool) -> Endo (Heap (Node, Bool))
|
|
||||||
scan = foldMapWithAddress scanAddr
|
|
||||||
|
|
||||||
gc :: TiState -> TiState
|
gc :: TiState -> TiState
|
||||||
gc st@(TiState s d h g sts) = TiState s d h' g sts
|
gc st@(TiState s d h g sts) = TiState s d h' g sts
|
||||||
where
|
where
|
||||||
h' = prepMarks h
|
as = findRoots st
|
||||||
& appEndo (foldMap Endo marked)
|
marked = h & appEndo (foldMap Endo $ markFrom <$> as)
|
||||||
& unprepMarks
|
h' = scanHeap marked
|
||||||
marked = fmap markFrom (findRoots st)
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user