This commit is contained in:
crumbtoo
2023-11-25 04:17:15 -07:00
parent 2153861927
commit 57d08046de
2 changed files with 35 additions and 36 deletions

View File

@@ -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

View File

@@ -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)