summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2009-12-07 20:57:15 +0100
committerJohannes Weiner <hannes@cmpxchg.org>2009-12-07 20:57:15 +0100
commit00546601746744521fb34ba67277225d08b897d0 (patch)
treeab39008d0ede399e76b0b6786186ab84644b5930
parentff84a7153e567fac1a6d5d88e4794758fce15391 (diff)
gc: move garbage collector from object.c
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
-rw-r--r--include/sheep/gc.h21
-rw-r--r--include/sheep/object.h10
-rw-r--r--sheep/Makefile2
-rw-r--r--sheep/compile.c1
-rw-r--r--sheep/core.c1
-rw-r--r--sheep/eval.c1
-rw-r--r--sheep/function.c1
-rw-r--r--sheep/gc.c221
-rw-r--r--sheep/list.c1
-rw-r--r--sheep/object.c215
-rw-r--r--sheep/read.c1
-rw-r--r--sheep/string.c1
-rw-r--r--sheep/vm.c3
13 files changed, 254 insertions, 225 deletions
diff --git a/include/sheep/gc.h b/include/sheep/gc.h
new file mode 100644
index 0000000..fa9e562
--- /dev/null
+++ b/include/sheep/gc.h
@@ -0,0 +1,21 @@
+/*
+ * include/sheep/gc.h
+ *
+ * Copyright (c) 2009 Johannes Weiner <hannes@cmpxchg.org>
+ */
+#ifndef _SHEEP_GC_H
+#define _SHEEP_GC_H
+
+#include <sheep/object_types.h>
+
+struct sheep_vm;
+
+struct sheep_object *sheep_gc_alloc(struct sheep_vm *);
+
+void sheep_mark(sheep_t);
+void sheep_protect(struct sheep_vm *, sheep_t);
+void sheep_unprotect(struct sheep_vm *, sheep_t);
+
+void sheep_gc_exit(struct sheep_vm *);
+
+#endif /* _SHEEP_GC_H */
diff --git a/include/sheep/object.h b/include/sheep/object.h
index 1b32524..667fcf6 100644
--- a/include/sheep/object.h
+++ b/include/sheep/object.h
@@ -31,14 +31,4 @@ static inline void sheep_set_data(sheep_t sheep, void *data)
int sheep_test(sheep_t);
int sheep_equal(sheep_t, sheep_t);
-void sheep_mark(sheep_t);
-
-void sheep_protect(struct sheep_vm *, sheep_t);
-void sheep_unprotect(struct sheep_vm *, sheep_t);
-
-void sheep_gc_disable(struct sheep_vm *);
-void sheep_gc_enable(struct sheep_vm *);
-
-void sheep_objects_exit(struct sheep_vm *);
-
#endif /* _SHEEP_OBJECT_H */
diff --git a/sheep/Makefile b/sheep/Makefile
index e9c1c3e..e939626 100644
--- a/sheep/Makefile
+++ b/sheep/Makefile
@@ -1,4 +1,4 @@
-sheep-obj := util.o vector.o map.o code.o
+sheep-obj := util.o vector.o map.o code.o gc.o
sheep-obj += object.o bool.o string.o name.o number.o list.o \
sequence.o function.o alien.o
sheep-obj += unpack.o vm.o module.o read.o compile.o eval.o core.o
diff --git a/sheep/compile.c b/sheep/compile.c
index e3708a5..011d223 100644
--- a/sheep/compile.c
+++ b/sheep/compile.c
@@ -11,6 +11,7 @@
#include <sheep/name.h>
#include <sheep/util.h>
#include <sheep/map.h>
+#include <sheep/gc.h>
#include <sheep/vm.h>
#include <string.h>
#include <stdio.h>
diff --git a/sheep/core.c b/sheep/core.c
index 6e4306a..2556247 100644
--- a/sheep/core.c
+++ b/sheep/core.c
@@ -12,6 +12,7 @@
#include <sheep/name.h>
#include <sheep/util.h>
#include <sheep/map.h>
+#include <sheep/gc.h>
#include <sheep/vm.h>
#include <stdarg.h>
#include <string.h>
diff --git a/sheep/eval.c b/sheep/eval.c
index dc81165..01d95b7 100644
--- a/sheep/eval.c
+++ b/sheep/eval.c
@@ -10,6 +10,7 @@
#include <sheep/code.h>
#include <sheep/util.h>
#include <sheep/map.h>
+#include <sheep/gc.h>
#include <sheep/vm.h>
#include <stdarg.h>
#include <stdlib.h>
diff --git a/sheep/function.c b/sheep/function.c
index 167b7eb..9266956 100644
--- a/sheep/function.c
+++ b/sheep/function.c
@@ -8,6 +8,7 @@
#include <sheep/bool.h>
#include <sheep/code.h>
#include <sheep/util.h>
+#include <sheep/gc.h>
#include <sheep/vm.h>
#include <stdio.h>
diff --git a/sheep/gc.c b/sheep/gc.c
new file mode 100644
index 0000000..6f0f376
--- /dev/null
+++ b/sheep/gc.c
@@ -0,0 +1,221 @@
+/*
+ * sheep/gc.c
+ *
+ * Copyright (c) 2009 Johannes Weiner <hannes@cmpxchg.org>
+ */
+#include <sheep/object_types.h>
+#include <sheep/vector.h>
+#include <sheep/util.h>
+#include <sheep/vm.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include <sheep/gc.h>
+
+#define PAGE_SIZE sysconf(_SC_PAGE_SIZE)
+#define POOL_SIZE (PAGE_SIZE / sizeof(struct sheep_object))
+
+struct sheep_objects {
+ struct sheep_object *mem;
+ struct sheep_object *free;
+ unsigned int nr_used;
+ struct sheep_objects *next;
+};
+
+static struct sheep_objects *alloc_pool(void)
+{
+ struct sheep_objects *pool;
+ unsigned int i;
+
+ pool = sheep_malloc(sizeof(struct sheep_objects));
+ pool->mem = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ pool->free = pool->mem;
+ for (i = 0; i < POOL_SIZE - 1; i++)
+ pool->mem[i].data = (unsigned long)&pool->mem[i + 1];
+ pool->nr_used = 0;
+ pool->next = NULL;
+ return pool;
+}
+
+static void free_pool(struct sheep_objects *pool)
+{
+ munmap(pool->mem, PAGE_SIZE);
+ sheep_free(pool);
+}
+
+static void unmark_pools(struct sheep_objects *pool)
+{
+ while (pool) {
+ unsigned int i;
+
+ for (i = 0; i < POOL_SIZE; i++) {
+ struct sheep_object *sheep = &pool->mem[i];
+
+ if (sheep->type)
+ sheep->data &= ~1;
+ }
+ pool = pool->next;
+ }
+}
+
+static void unmark(struct sheep_vm *vm)
+{
+ unmark_pools(vm->parts);
+ unmark_pools(vm->fulls);
+}
+
+static void mark_protected(struct sheep_vector *protected)
+{
+ unsigned long i;
+
+ for (i = 0; i < protected->nr_items; i++)
+ sheep_mark(protected->items[i]);
+}
+
+static unsigned int collect_pool(struct sheep_vm *vm,
+ struct sheep_objects *pool)
+{
+ unsigned int i, moved;
+
+ for (i = moved = 0; i < POOL_SIZE; i++) {
+ struct sheep_object *sheep = &pool->mem[i];
+
+ if (sheep->data & 1) {
+ sheep->data &= ~1;
+ continue;
+ }
+
+ if (sheep->type->free)
+ sheep->type->free(vm, sheep);
+
+ sheep->data = (unsigned long)pool->free;
+ sheep->type = NULL;
+ pool->free = &pool->mem[i];
+ pool->nr_used--;
+ moved++;
+ }
+ return moved;
+}
+
+static void collect(struct sheep_vm *vm)
+{
+ struct sheep_objects *pool, *next,
+ *cache_part = NULL, *last_full = NULL;
+
+ if (vm->gc_disabled)
+ goto alloc;
+
+ unmark(vm);
+ sheep_vm_mark(vm);
+ mark_protected(&vm->protected);
+
+ for (pool = vm->fulls; pool; pool = next) {
+ unsigned int moved;
+
+ moved = collect_pool(vm, pool);
+ next = pool->next;
+
+ if (!moved) {
+ last_full = pool;
+ continue;
+ }
+
+ if (last_full)
+ last_full->next = pool->next;
+ else
+ vm->fulls = pool->next;
+
+ if (moved < POOL_SIZE || !cache_part) {
+ pool->next = vm->parts;
+ vm->parts = cache_part = pool;
+ } else
+ free_pool(pool);
+ }
+
+alloc:
+ if (!vm->parts)
+ vm->parts = alloc_pool();
+}
+
+static sheep_t alloc(struct sheep_vm *vm)
+{
+ struct sheep_object *sheep = vm->parts->free;
+
+ if (++vm->parts->nr_used < POOL_SIZE)
+ vm->parts->free = (struct sheep_object *)sheep->data;
+ else {
+ struct sheep_objects *pool;
+
+ pool = vm->parts;
+ vm->parts = vm->parts->next;
+ pool->next = vm->fulls;
+ vm->fulls = pool;
+ }
+ return sheep;
+}
+
+struct sheep_object *sheep_gc_alloc(struct sheep_vm *vm)
+{
+ if (!vm->parts)
+ collect(vm);
+
+ return alloc(vm);
+}
+
+void sheep_mark(sheep_t sheep)
+{
+ if (sheep_is_fixnum(sheep))
+ return;
+ if (sheep->data & 1)
+ return;
+ sheep->data |= 1;
+ if (sheep_type(sheep)->mark)
+ sheep_type(sheep)->mark(sheep);
+}
+
+void sheep_protect(struct sheep_vm *vm, sheep_t sheep)
+{
+ sheep_vector_push(&vm->protected, sheep);
+}
+
+void sheep_unprotect(struct sheep_vm *vm, sheep_t sheep)
+{
+ sheep_t prot;
+
+ prot = sheep_vector_pop(&vm->protected);
+ sheep_bug_on(prot != sheep);
+}
+
+static void drain_pool(struct sheep_vm *vm, struct sheep_objects *pool)
+{
+ unsigned int i;
+
+ for (i = 0; i < POOL_SIZE; i++) {
+ struct sheep_object *sheep = &pool->mem[i];
+
+ if (sheep->type && sheep->type->free)
+ sheep->type->free(vm, sheep);
+ }
+}
+
+void sheep_gc_exit(struct sheep_vm *vm)
+{
+ struct sheep_objects *next;
+
+ sheep_free(vm->protected.items);
+ while (vm->parts) {
+ next = vm->parts->next;
+ drain_pool(vm, vm->parts);
+ free_pool(vm->parts);
+ vm->parts = next;
+ }
+ while (vm->fulls) {
+ next = vm->fulls->next;
+ drain_pool(vm, vm->fulls);
+ free_pool(vm->fulls);
+ vm->fulls = next;
+ }
+}
diff --git a/sheep/list.c b/sheep/list.c
index e7b2d13..867b895 100644
--- a/sheep/list.c
+++ b/sheep/list.c
@@ -9,6 +9,7 @@
#include <sheep/unpack.h>
#include <sheep/eval.h>
#include <sheep/util.h>
+#include <sheep/gc.h>
#include <sheep/vm.h>
#include <stdio.h>
diff --git a/sheep/object.c b/sheep/object.c
index f26cdb5..a59029c 100644
--- a/sheep/object.c
+++ b/sheep/object.c
@@ -5,6 +5,7 @@
*/
#include <sheep/vector.h>
#include <sheep/util.h>
+#include <sheep/gc.h>
#include <sheep/vm.h>
#include <sys/mman.h>
#include <unistd.h>
@@ -12,159 +13,12 @@
#include <sheep/object.h>
-#define PAGE_SIZE sysconf(_SC_PAGE_SIZE)
-#define POOL_SIZE (PAGE_SIZE / sizeof(struct sheep_object))
-
-struct sheep_objects {
- struct sheep_object *mem;
- struct sheep_object *free;
- unsigned int nr_used;
- struct sheep_objects *next;
-};
-
-static struct sheep_objects *alloc_pool(void)
-{
- struct sheep_objects *pool;
- unsigned int i;
-
- pool = sheep_malloc(sizeof(struct sheep_objects));
- pool->mem = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-
- pool->free = pool->mem;
- for (i = 0; i < POOL_SIZE - 1; i++)
- pool->mem[i].data = (unsigned long)&pool->mem[i + 1];
- pool->nr_used = 0;
- pool->next = NULL;
- return pool;
-}
-
-static void free_pool(struct sheep_objects *pool)
-{
- munmap(pool->mem, PAGE_SIZE);
- sheep_free(pool);
-}
-
-static void unmark_pools(struct sheep_objects *pool)
-{
- while (pool) {
- unsigned int i;
-
- for (i = 0; i < POOL_SIZE; i++) {
- struct sheep_object *sheep = &pool->mem[i];
-
- if (sheep->type)
- sheep->data &= ~1;
- }
- pool = pool->next;
- }
-}
-
-static void unmark(struct sheep_vm *vm)
-{
- unmark_pools(vm->parts);
- unmark_pools(vm->fulls);
-}
-
-static void mark_protected(struct sheep_vector *protected)
-{
- unsigned long i;
-
- for (i = 0; i < protected->nr_items; i++)
- sheep_mark(protected->items[i]);
-}
-
-static unsigned int collect_pool(struct sheep_vm *vm,
- struct sheep_objects *pool)
-{
- unsigned int i, moved;
-
- for (i = moved = 0; i < POOL_SIZE; i++) {
- struct sheep_object *sheep = &pool->mem[i];
-
- if (sheep->data & 1) {
- sheep->data &= ~1;
- continue;
- }
-
- if (sheep->type->free)
- sheep->type->free(vm, sheep);
-
- sheep->data = (unsigned long)pool->free;
- sheep->type = NULL;
- pool->free = &pool->mem[i];
- pool->nr_used--;
- moved++;
- }
- return moved;
-}
-
-static void collect(struct sheep_vm *vm)
-{
- struct sheep_objects *pool, *next,
- *cache_part = NULL, *last_full = NULL;
-
- if (vm->gc_disabled)
- goto alloc;
-
- unmark(vm);
- sheep_vm_mark(vm);
- mark_protected(&vm->protected);
-
- for (pool = vm->fulls; pool; pool = next) {
- unsigned int moved;
-
- moved = collect_pool(vm, pool);
- next = pool->next;
-
- if (!moved) {
- last_full = pool;
- continue;
- }
-
- if (last_full)
- last_full->next = pool->next;
- else
- vm->fulls = pool->next;
-
- if (moved < POOL_SIZE || !cache_part) {
- pool->next = vm->parts;
- vm->parts = cache_part = pool;
- } else
- free_pool(pool);
- }
-
-alloc:
- if (!vm->parts)
- vm->parts = alloc_pool();
-}
-
-static sheep_t alloc(struct sheep_vm *vm)
-{
- struct sheep_object *sheep = vm->parts->free;
-
- if (++vm->parts->nr_used < POOL_SIZE)
- vm->parts->free = (struct sheep_object *)sheep->data;
- else {
- struct sheep_objects *pool;
-
- pool = vm->parts;
- vm->parts = vm->parts->next;
- pool->next = vm->fulls;
- vm->fulls = pool;
- }
- return sheep;
-}
-
sheep_t sheep_make_object(struct sheep_vm *vm, const struct sheep_type *type,
void *data)
{
struct sheep_object *sheep;
- if (!vm->parts)
- collect(vm);
-
- sheep = alloc(vm);
+ sheep = sheep_gc_alloc(vm);
sheep->type = type;
sheep->data = (unsigned long)data;
return sheep;
@@ -187,68 +41,3 @@ int sheep_equal(sheep_t a, sheep_t b)
return sheep_type(a)->equal(a, b);
return 0;
}
-
-void sheep_mark(sheep_t sheep)
-{
- if (sheep_is_fixnum(sheep))
- return;
- if (sheep->data & 1)
- return;
- sheep->data |= 1;
- if (sheep_type(sheep)->mark)
- sheep_type(sheep)->mark(sheep);
-}
-
-void sheep_protect(struct sheep_vm *vm, sheep_t sheep)
-{
- sheep_vector_push(&vm->protected, sheep);
-}
-
-void sheep_unprotect(struct sheep_vm *vm, sheep_t sheep)
-{
- sheep_t prot;
-
- prot = sheep_vector_pop(&vm->protected);
- sheep_bug_on(prot != sheep);
-}
-
-void sheep_gc_disable(struct sheep_vm *vm)
-{
- vm->gc_disabled = 1;
-}
-
-void sheep_gc_enable(struct sheep_vm *vm)
-{
- vm->gc_disabled = 0;
-}
-
-static void drain_pool(struct sheep_vm *vm, struct sheep_objects *pool)
-{
- unsigned int i;
-
- for (i = 0; i < POOL_SIZE; i++) {
- struct sheep_object *sheep = &pool->mem[i];
-
- if (sheep->type && sheep->type->free)
- sheep->type->free(vm, sheep);
- }
-}
-
-void sheep_objects_exit(struct sheep_vm *vm)
-{
- struct sheep_objects *next;
-
- sheep_free(vm->protected.items);
- while (vm->parts) {
- next = vm->parts->next;
- drain_pool(vm, vm->parts);
- free_pool(vm->parts);
- vm->parts = next;
- }
- while (vm->fulls) {
- next = vm->fulls->next;
- drain_pool(vm, vm->fulls);
- free_pool(vm->fulls);
- vm->fulls = next;
- }
-}
diff --git a/sheep/read.c b/sheep/read.c
index ad8a5e0..6a81cb6 100644
--- a/sheep/read.c
+++ b/sheep/read.c
@@ -8,6 +8,7 @@
#include <sheep/string.h>
#include <sheep/list.h>
#include <sheep/name.h>
+#include <sheep/gc.h>
#include <sheep/vm.h>
#include <ctype.h>
#include <stdio.h>
diff --git a/sheep/string.c b/sheep/string.c
index d8d0aae..5370e18 100644
--- a/sheep/string.c
+++ b/sheep/string.c
@@ -7,6 +7,7 @@
#include <sheep/object.h>
#include <sheep/unpack.h>
#include <sheep/util.h>
+#include <sheep/gc.h>
#include <sheep/vm.h>
#include <string.h>
#include <stdio.h>
diff --git a/sheep/vm.c b/sheep/vm.c
index be3056f..fc0900c 100644
--- a/sheep/vm.c
+++ b/sheep/vm.c
@@ -14,6 +14,7 @@
#include <sheep/eval.h>
#include <sheep/list.h>
#include <sheep/util.h>
+#include <sheep/gc.h>
#include <string.h>
#include <sheep/vm.h>
@@ -74,5 +75,5 @@ void sheep_vm_exit(struct sheep_vm *vm)
sheep_core_exit(vm);
sheep_evaluator_exit(vm);
sheep_free(vm->globals.items);
- sheep_objects_exit(vm);
+ sheep_gc_exit(vm);
}