summaryrefslogtreecommitdiffstats
path: root/bytecode/heap.c
diff options
context:
space:
mode:
Diffstat (limited to 'bytecode/heap.c')
-rw-r--r--bytecode/heap.c43
1 files changed, 27 insertions, 16 deletions
diff --git a/bytecode/heap.c b/bytecode/heap.c
index 863bf0c..1ba5faf 100644
--- a/bytecode/heap.c
+++ b/bytecode/heap.c
@@ -6,8 +6,9 @@
#include "heap.h"
#include "panic.h"
#include "value.h"
+#include "value_slice.h"
-struct heap new_heap(struct val_slice gc_roots)
+struct heap new_heap(value_slice gc_roots)
{
return (struct heap) {
.buf = NULL,
@@ -56,14 +57,16 @@ static value process_gc_value(struct heap *h, value val)
// Allocate space in the new buffer.
value *q = simple_alloc(h, size);
+ // Write forwarding pointer.
+ value first_value = p[0];
+ p[0] = from_pointer(q);
+
// Copy values, recursively modifying pointers.
- for (size_t i = 0; i < size; i++) {
+ q[0] = process_gc_value(h, first_value);
+ for (size_t i = 1; i < size; i++) {
q[i] = process_gc_value(h, p[i]);
}
- // Write forwarding pointer.
- p[0] = from_pointer(q);
-
return from_pointer(q);
}
@@ -74,7 +77,7 @@ static void collect_garbage(struct heap *h)
}
// Swap the heaps.
- struct val_slice temp = h->active;
+ value_slice temp = h->active;
h->active = h->standby;
h->standby = temp;
@@ -85,19 +88,25 @@ static void collect_garbage(struct heap *h)
}
}
-static void more_space(struct heap *h, int64_t size_hint)
+static value_slice xcalloc(size_t size)
{
- size_t new_size = h->active.size * 2 + size_hint;
- value *new_buf = calloc(2 * new_size, sizeof(value));
- if (!new_buf) {
+ value *p = calloc(size, sizeof(value));
+ if (!p) {
panicf("Out of memory!\n");
}
- memcpy(new_buf, h->active.buf, h->active.size * sizeof(value));
- free(h->buf);
+ return (value_slice) { .size = size, .buf = p };
+}
+
+static void more_space(struct heap *h, int64_t size_hint)
+{
+ size_t new_size = h->active.size * 2 + size_hint;
+ value_slice new_buf = xcalloc(2 * new_size);
+ memcpy(new_buf.buf, h->active.buf, h->active.size * sizeof(value));
- h->buf = new_buf;
- h->active = (struct val_slice) { .size = new_size, .buf = new_buf };
- h->standby = (struct val_slice) { .size = new_size, .buf = new_buf + new_size };
+ free(h->buf);
+ h->buf = new_buf.buf;
+ h->active = value_slice2(new_buf, 0, new_size);
+ h->standby = value_slice1(new_buf, new_size);
}
value *alloc(struct heap *h, int64_t size)
@@ -110,5 +119,7 @@ value *alloc(struct heap *h, int64_t size)
if (h->free_ptr + size >= h->active.size) {
more_space(h, size);
}
- return simple_alloc(h, size);
+ value *p = simple_alloc(h, size);
+ memset(p, 0, size * sizeof(value));
+ return p;
}