summaryrefslogtreecommitdiff
path: root/src/gc/gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gc/gc.c')
-rw-r--r--src/gc/gc.c99
1 files changed, 76 insertions, 23 deletions
diff --git a/src/gc/gc.c b/src/gc/gc.c
index f53fd79..1c0daec 100644
--- a/src/gc/gc.c
+++ b/src/gc/gc.c
@@ -1,18 +1,12 @@
+#include "../gc.h"
+#include "../platform.h"
#include "../util.h"
#include <stdbool.h>
#include <stddef.h>
-#include <stdio.h>
+#include <stdint.h>
#include <stdlib.h>
/**
- * These cache-size details are from
- * https://www.copetti.org/writings/consoles/nintendo-3ds/. We call the second
- * level of cache (only available on N3DS) L3, since this GC design only cares
- * about L1D and L3.
- */
-static const size_t L1D_SIZE = 16 * 1024, L3_SIZE = 2 * 1024 * 1024;
-
-/**
* Constants that should probably be learned.
*/
static const size_t NURSERY_L1D_SIZE_FACTOR = 1;
@@ -43,19 +37,19 @@ enum object_kind {
OBJECT_UNTRACED,
/**
+ * A wrapper for a pointer to a code address. When this object gets collected,
+ * calls `free_code` on its first untraced slot.
+ */
+ OBJECT_COMPILED_FUNCTION,
+
+ /**
* A hashtable keyed by the addresses. This behaves like a normal object, but
* the first untraced slot gets set to the `uintptr_t` 1 whenever a collection
* traces the hashtable.
*
* The hashtable uses this information to rehash after each collection.
*/
- OBJECT_EQ_HASHTABLE,
-
- /**
- * A wrapper for a pointer to a code address. When this object gets collected,
- * calls `free_code` on its first untraced slot.
- */
- OBJECT_COMPILED_FUNCTION,
+ OBJECT_HASHTABLE_EQ,
};
/**
@@ -72,11 +66,11 @@ struct object_size {
/**
* Returns the number of slots for values the object has.
*/
-static size_t object_value_slots(struct object_size size) {
+static size_t object_size_value_slots(struct object_size size) {
switch (size.kind) {
case OBJECT_NORMAL:
- case OBJECT_EQ_HASHTABLE:
case OBJECT_COMPILED_FUNCTION:
+ case OBJECT_HASHTABLE_EQ:
return size.bits >> ((4 * sizeof(size_t)) - 3);
case OBJECT_UNTRACED:
return 0;
@@ -86,11 +80,11 @@ static size_t object_value_slots(struct object_size size) {
/**
* Returns the number of untraced slots the object has.
*/
-static size_t object_untraced_slots(struct object_size size) {
+static size_t object_size_untraced_slots(struct object_size size) {
switch (size.kind) {
case OBJECT_NORMAL:
- case OBJECT_EQ_HASHTABLE:
case OBJECT_COMPILED_FUNCTION:
+ case OBJECT_HASHTABLE_EQ:
return size.bits & ((1 << ((4 * sizeof(size_t)) - 3)) - 1);
case OBJECT_UNTRACED:
return size.bits;
@@ -106,6 +100,20 @@ struct object {
};
/**
+ * Returns the number of slots for values the object has.
+ */
+static size_t object_value_slots(const struct object *obj) {
+ return object_size_value_slots(((struct object_size *)obj)[-1]);
+}
+
+/**
+ * Returns the number of untraced slots the object has.
+ */
+static size_t object_untraced_slots(const struct object *obj) {
+ return object_size_untraced_slots(((struct object_size *)obj)[-1]);
+}
+
+/**
* This is the layout of an object in the nursery.
*/
struct nursery_object {
@@ -120,8 +128,8 @@ struct nursery_object {
* with one.
*/
struct young_heap_object {
- struct object_size size;
size_t fwd;
+ struct object_size size;
uintptr_t slots[];
};
@@ -199,10 +207,10 @@ static struct old_heap_block old_heap_sentinels[SIZE_CLASS_COUNT];
void gc_init(void) {
// Allocate the nursery and young-heap.
nursery_bottom = nursery_next =
- (uintptr_t)malloc(L1D_SIZE * NURSERY_L1D_SIZE_FACTOR);
+ (uintptr_t)malloc(get_l1d_size() * NURSERY_L1D_SIZE_FACTOR);
assume(nursery_bottom);
young_heap_bottom = young_heap_next =
- (uintptr_t)malloc(L3_SIZE * YOUNG_HEAP_L3_SIZE_FACTOR);
+ (uintptr_t)malloc(get_l3_size() * YOUNG_HEAP_L3_SIZE_FACTOR);
assume(young_heap_bottom);
// Self-link the old-heap.
@@ -211,3 +219,48 @@ void gc_init(void) {
&old_heap_sentinels[i];
}
}
+
+struct object *gc_alloc(size_t value_slot_count, size_t untraced_slot_count) {
+ todo("gc_alloc");
+}
+
+struct object *gc_alloc_compiled_function(size_t value_slot_count,
+ size_t untraced_slot_count) {
+ todo("gc_alloc_compiled_function");
+}
+
+struct object *gc_alloc_hashtable_eq(size_t value_slot_count,
+ size_t untraced_slot_count) {
+ todo("gc_alloc_hashtable_eq");
+}
+
+struct value gc_read_value_slot(const struct object *obj, size_t slot_index) {
+ assume(slot_index < object_value_slots(obj));
+ todo("gc_read_value_slot");
+}
+
+uintptr_t gc_read_untraced_slot(const struct object *obj, size_t slot_index) {
+ assume(slot_index < object_untraced_slots(obj));
+ todo("gc_read_untraced_slot");
+}
+
+uint8_t gc_read_untraced_byte(const struct object *obj, size_t byte_index) {
+ todo("gc_read_untraced_byte");
+}
+
+void gc_write_value_slot(struct object *obj, size_t slot_index,
+ struct value value) {
+ assume(slot_index < object_value_slots(obj));
+ todo("gc_write_value_slot");
+}
+
+void gc_write_untraced_slot(struct object *obj, size_t slot_index,
+ uintptr_t value) {
+ assume(slot_index < object_untraced_slots(obj));
+ todo("gc_write_untraced_slot");
+}
+
+void gc_write_untraced_byte(struct object *obj, size_t byte_index,
+ uint8_t byte) {
+ todo("gc_write_untraced_byte");
+}