repos / gcs.git


commit
60f2e3f
parent
60f2e3f
author
Evgenii Akentev
date
2024-09-10 12:55:53 +0400 +04
Add basic mark-sweep
2 files changed,  +173, -0
A .gitignore
+1, -0
1@@ -0,0 +1 @@
2+a.out
A mark-sweep/basic.c
+172, -0
  1@@ -0,0 +1,172 @@
  2+#include <stdio.h>
  3+#include <stdlib.h>
  4+
  5+// To simplify things sizes are statically defined
  6+#define FIELDS_SIZE 4
  7+#define HEAP_SIZE 8
  8+#define ROOTS_SIZE 4
  9+#define WORKLIST_SIZE 100
 10+
 11+struct Object;
 12+
 13+typedef struct Object {
 14+  int val;
 15+  int field_size;
 16+  int isMarked;
 17+  struct Object* fields[FIELDS_SIZE];
 18+} Object;
 19+
 20+typedef struct {
 21+  int size;
 22+  Object** objects;
 23+} Heap;
 24+
 25+typedef struct {
 26+  int size;
 27+  Object* objects[ROOTS_SIZE];
 28+} Roots;
 29+
 30+typedef struct {
 31+  int current;
 32+  Object* objects[WORKLIST_SIZE];
 33+} Worklist;
 34+
 35+void push(Worklist* w, Object* o) {
 36+  w->current += 1;
 37+  w->objects[w->current] = o;
 38+}
 39+
 40+int isEmpty(Worklist *w) {
 41+  if (w->current == -1) return 1;
 42+
 43+  return 0;
 44+}
 45+
 46+Object* pop(Worklist *w) {
 47+  Object* item = w->objects[w->current];
 48+  w->current -= 1;
 49+  return item;
 50+}
 51+
 52+Heap* mkHeap () {
 53+  Heap* h = malloc(sizeof(Heap));
 54+  h->size = HEAP_SIZE;
 55+  h->objects = calloc(h->size, sizeof(Object*));
 56+  return h;
 57+}
 58+
 59+int heapObjectsNumber(Heap* h) {
 60+  int c = 0;
 61+  for (int i = 0; i < h->size; i++) {
 62+    if (h->objects[i] != NULL) c++;
 63+  }
 64+  return c;
 65+}
 66+
 67+void freeHeap (Heap* h) {
 68+  for (int i = 0; i < h->size; i++) {
 69+    if (h->objects[i] != NULL) {
 70+      free(h->objects[i]);
 71+    }
 72+  }
 73+  free(h->objects);
 74+  free(h);
 75+}
 76+
 77+Object* allocate(int val, Heap* h) {
 78+  Object* p = NULL;
 79+  for (int i = 0; i < h->size; i++) {
 80+    if (h->objects[i] == NULL && p == NULL) {
 81+      p = malloc(sizeof(Object));
 82+      *p = (Object){val, FIELDS_SIZE, 0, NULL};
 83+      h->objects[i] = p;
 84+    }
 85+  }
 86+  return p;
 87+}
 88+
 89+void mark(Heap* h, Roots* roots, Worklist* w) {
 90+  while (isEmpty(w) == 0) {
 91+    Object *ref = pop(w);
 92+    for (int i = 0; i < ref->field_size; i++) {
 93+       Object* child = ref->fields[i];
 94+      if (child != NULL && child->isMarked != 1) {
 95+        child->isMarked = 1;
 96+        push(w, child);
 97+      }
 98+    }
 99+  }
100+}
101+
102+void markFromRoots(Heap* h, Roots* roots) {
103+  Worklist worklist;
104+  worklist.current = -1;
105+
106+  for (int i = 0; i < roots->size; i++) {
107+    Object* ref = roots->objects[i];
108+    if (ref != NULL && ref->isMarked != 1) {
109+      ref->isMarked = 1;
110+      push(&worklist, ref);
111+      mark(h, roots, &worklist);
112+    }
113+  }
114+}
115+
116+void sweep(Heap *h) {
117+  for (int i = 0; i < h->size; i++) {
118+    if (h->objects[i] != NULL) {
119+      if (h->objects[i]->isMarked == 1) {
120+        h->objects[i]->isMarked = 0; 
121+      } else {
122+        free(h->objects[i]);
123+        h->objects[i] = NULL;
124+      }
125+    }
126+  }
127+}
128+
129+void collect(Heap* h, Roots* roots) {
130+  markFromRoots(h, roots);
131+  sweep(h);
132+}
133+
134+Object* new(int val, Heap* h, Roots* roots) {
135+  Object* ref = allocate(val, h);
136+  if (ref == NULL) {
137+    printf("Running collect");
138+    collect(h, roots);
139+    ref = allocate(val, h);
140+    if (ref == NULL) {
141+      printf("Out of memory\n");
142+      exit(0);
143+    }
144+  }
145+  return ref;
146+}
147+
148+int main() {
149+  Heap* h = mkHeap();
150+  Roots roots;
151+  roots.size = ROOTS_SIZE;
152+  for (int i = 0; i < roots.size; i++) {
153+    roots.objects[i] = NULL;
154+  }
155+
156+  // mutator
157+  roots.objects[0] = new(7, h, &roots);
158+  roots.objects[0] = new(5, h, &roots);
159+
160+  roots.objects[0]->fields[0] = new(8, h, &roots);
161+
162+  printf("heap size before collect: %d\n", heapObjectsNumber(h));
163+  printf("heap third obj value: %d\n", h->objects[2]->val);
164+
165+  collect(h, &roots);
166+
167+  printf("heap second obj value: %d\n", h->objects[1]->val);
168+
169+  printf("heap size after collect: %d\n", heapObjectsNumber(h));
170+
171+  freeHeap(h);
172+  return 0;
173+}