- commit
- 62230c5
- parent
- 60f2e3f
- author
- Evgenii Akentev
- date
- 2024-09-12 16:42:26 +0400 +04
Add mark sweep in hs
1 files changed,
+116,
-0
+116,
-0
1@@ -0,0 +1,116 @@
2+module MarkSweep where
3+
4+import Debug.Trace
5+
6+-- run as ghci MarkSweep.hs -package unordered-containers
7+
8+data Value = IntVal Int
9+ deriving (Eq, Show)
10+
11+data Object = Object {
12+ val :: Value,
13+ fields :: [ObjectPtr],
14+ marked :: Bool
15+} deriving (Eq, Show)
16+
17+data ObjectPtr = ObjectPtr Int | NullPtr
18+ deriving (Eq, Show)
19+
20+increment :: ObjectPtr -> ObjectPtr
21+increment (ObjectPtr p) = ObjectPtr $ p + 1
22+increment NullPtr = NullPtr
23+
24+newtype Heap = Heap { heapObjects :: [Maybe Object] }
25+ deriving (Eq, Show)
26+
27+newHeap :: Heap
28+newHeap = Heap [Nothing | x <- [1..8]]
29+
30+isMarked :: ObjectPtr -> Heap -> Bool
31+isMarked NullPtr _ = False
32+isMarked (ObjectPtr p) h = Just True == (marked <$> (heapObjects h !! p))
33+
34+setMarked :: ObjectPtr -> Heap -> Heap
35+setMarked NullPtr h = h
36+setMarked (ObjectPtr p) (Heap hs) = Heap $ reverse $ foldl step [] $ zip [0..] hs
37+ where
38+ step res (idx, Nothing) = Nothing : res
39+ step res (idx, Just obj)
40+ | p == idx = (Just $ obj { marked = True }) : res
41+ | otherwise = (Just obj) : res
42+
43+newtype Roots = Roots { rootsObjects :: [ObjectPtr]}
44+ deriving (Eq, Show)
45+
46+data MarkSweepGC = MarkSweepGC {
47+ roots :: Roots,
48+ heap :: Heap
49+} deriving (Eq, Show)
50+
51+allocate :: Value -> Heap -> Either String (ObjectPtr, Heap)
52+allocate v (Heap objs) = case foldl step (False, -1, []) objs of
53+ (True, idx, res) -> Right $ (ObjectPtr idx, Heap $ reverse res)
54+ _ -> Left "Out of memory"
55+ where
56+ step (True, idx, res) obj = (True, idx, obj : res)
57+ step (_, idx, res) Nothing = (True, idx + 1, (Just $ Object v [] False) : res)
58+ step (ok, idx, res) obj = (ok, idx + 1, obj : res)
59+
60+mark :: [ObjectPtr] -> Heap -> Heap
61+mark [] h = h
62+mark ((ObjectPtr p):rest) h = case heapObjects h !! p of
63+ Just obj ->
64+ let
65+ step acc NullPtr = acc
66+ step (wl, heap) child
67+ | not (isMarked child h) = (child : wl, setMarked child heap)
68+ step acc _ = acc
69+
70+ (workList, newH) = foldl step ([], h) $ fields obj
71+ in mark (workList ++ rest) newH
72+ Nothing -> mark rest h
73+
74+markFromRoots :: Heap -> Roots -> (Heap, Roots)
75+markFromRoots h rs =
76+ let newHeap = foldl step h $ rootsObjects rs
77+ in (newHeap, rs)
78+ where
79+ step heap ptr
80+ | not (isMarked ptr heap) =
81+ let newH = setMarked ptr heap
82+ in mark [ptr] newH
83+ step heap ptr = heap
84+
85+collect :: Heap -> Roots -> (Heap, Roots)
86+collect h r =
87+ let (h', r') = markFromRoots h r
88+ in (sweep h', r')
89+
90+sweep :: Heap -> Heap
91+sweep (Heap hs) = Heap $ map step hs
92+ where
93+ step Nothing = Nothing
94+ step (Just o) = if marked o then Just (o { marked = False }) else Nothing
95+
96+newObject :: Value -> MarkSweepGC -> Either String (ObjectPtr, MarkSweepGC)
97+newObject v (MarkSweepGC roots heap) =
98+ case allocate v heap of
99+ Right (ptr, heap') -> Right (ptr, MarkSweepGC roots heap')
100+ Left s ->
101+ let (heap', roots') = collect heap roots
102+ in case allocate v heap' of
103+ Right (ptr, heap'') -> Right (ptr, MarkSweepGC roots' heap'')
104+ Left s -> Left s
105+
106+main :: IO ()
107+main = do
108+ let gc = MarkSweepGC (Roots []) newHeap
109+ let
110+ res = do
111+ (ptr, gc') <- newObject (IntVal 3) gc
112+ (ptr2, MarkSweepGC (Roots roots) h) <- newObject (IntVal 5) gc'
113+
114+ let (r'', h'') = collect h (Roots $ ptr2 : roots)
115+ let newGc = MarkSweepGC h'' r''
116+ return ([ptr, ptr2], newGc)
117+ print res