From 02d017af64dba52460b5e5a8e999b1b07ec23f25 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Sat, 24 Aug 2024 17:33:57 -0400 Subject: [PATCH] Move all source and header files to subdirectories --- .gitignore | 6 +- gc.c | 44 ------------ gc.h => include/gc.h | 0 gc_alloc.h => include/gc_alloc.h | 6 +- test_gc.h => include/test_gc.h | 0 vm.h => include/vm.h | 0 main.c | 107 ----------------------------- src/gc.c | 47 +++++++++++++ gc_alloc.c => src/gc_alloc.c | 0 src/main.c | 114 +++++++++++++++++++++++++++++++ src/vm.c | 89 ++++++++++++++++++++++++ vm.c | 82 ---------------------- 12 files changed, 257 insertions(+), 238 deletions(-) delete mode 100644 gc.c rename gc.h => include/gc.h (100%) rename gc_alloc.h => include/gc_alloc.h (90%) rename test_gc.h => include/test_gc.h (100%) rename vm.h => include/vm.h (100%) delete mode 100644 main.c create mode 100644 src/gc.c rename gc_alloc.c => src/gc_alloc.c (100%) create mode 100644 src/main.c create mode 100644 src/vm.c delete mode 100644 vm.c diff --git a/.gitignore b/.gitignore index 93a8f2b..167de1e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ * !.gitignore -!*.c -!*.h !*.md !LICENSE !Makefile +!/src +!/src/*.c +!/include +!/include/*.h diff --git a/gc.c b/gc.c deleted file mode 100644 index 0e5fb74..0000000 --- a/gc.c +++ /dev/null @@ -1,44 +0,0 @@ -#include - -#include "gc.h" -#include "vm.h" - -void mark(struct garbageObject *obj) { - if (obj->mark) - return; - - ++obj->mark; - - if (obj->type == GARBAGE_PAIR) { - mark(obj->head); - mark(obj->tail); - } -} - -void markAll(struct virtualMachine *vm) { - for (int i = 0; i < vm->stackSize; ++i) { - mark(vm->stack[i]); - } -} - -void sweep(struct virtualMachine *vm) { - struct garbageObject **obj = &vm->head; - - while (*obj) { - if (!(*obj)->mark) { - struct garbageObject *unreachable = *obj; - *obj = unreachable->next; - free(unreachable); - vm->refCount--; - } else { - (*obj)->mark = 0; - obj = &(*obj)->next; - } - } -} - -void collect(struct virtualMachine *vm) { - markAll(vm); - sweep(vm); - vm->refMax = vm->refCount * 2 <= STACK_MAX ? vm->refCount * 2 : STACK_MAX; -} diff --git a/gc.h b/include/gc.h similarity index 100% rename from gc.h rename to include/gc.h diff --git a/gc_alloc.h b/include/gc_alloc.h similarity index 90% rename from gc_alloc.h rename to include/gc_alloc.h index 652bddc..cbb23b8 100644 --- a/gc_alloc.h +++ b/include/gc_alloc.h @@ -1,5 +1,5 @@ -#ifndef GALLOC_H -#define GALLOC_H +#ifndef GC_ALLOC_H +#define GC_ALLOC_H #include @@ -23,4 +23,4 @@ void *galloc(size_t size); // Frees memory allocated with galloc() void gfree(void *ptr); -#endif /* GALLOC_H */ +#endif /* GC_ALLOC_H */ diff --git a/test_gc.h b/include/test_gc.h similarity index 100% rename from test_gc.h rename to include/test_gc.h diff --git a/vm.h b/include/vm.h similarity index 100% rename from vm.h rename to include/vm.h diff --git a/main.c b/main.c deleted file mode 100644 index c347a75..0000000 --- a/main.c +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include - -#include "gc.h" -#include "test_gc.h" -#include "vm.h" - -void test_int_alloc(void) { - struct virtualMachine *vm = initVM(); - pushInt(vm, 100); - pushInt(vm, 1000); - pushInt(vm, 10000); - pushInt(vm, -100000); - assert(vm->refCount == 4 && - "test_int_alloc: GARBAGE_INT allocation failure\n"); - printf("test_int_alloc: PASS\n"); - deinitVM(vm); -} - -void test_pair_alloc(void) { - struct virtualMachine *vm = initVM(); - pushInt(vm, 100); - pushInt(vm, 1000); - pushInt(vm, 10000); - pushInt(vm, -100000); - pushPair(vm); - pushPair(vm); - assert(vm->refCount == 6 && - "test_pair_alloc: FAILED: GARBAGE_PAIR allocation failure\n"); - printf("test_pair_alloc: PASS\n"); - deinitVM(vm); -} - -void test_obj_count(void) { - struct virtualMachine *vm = initVM(); - pushInt(vm, 100); - pushInt(vm, 1000); - pushInt(vm, 10000); - pushInt(vm, -100000); - collect(vm); - assert(vm->refCount == 4 && - "test_obj_count: FAILED: GC occurred when it shouldn't have\n"); - printf("test_obj_count: PASS\n"); - deinitVM(vm); -} - -void test_nested_pair(void) { - struct virtualMachine *vm = initVM(); - pushInt(vm, 100); - pushInt(vm, 1000); - pushPair(vm); - pushInt(vm, 10000); - pushInt(vm, -100000); - pushPair(vm); - pushPair(vm); - collect(vm); - assert(vm->refCount == 7 && - "test_nested_pair: FAILED: GARBAGE_PAIR allocation failure\n"); - printf("test_pair_alloc: PASS\n"); - deinitVM(vm); -} - -void test_unreachable(void) { - struct virtualMachine *vm = initVM(); - pushInt(vm, 100); - pushInt(vm, 1000); - pop(vm); - pop(vm); - collect(vm); - assert(vm->refCount == 0 && - "test_unreachable: FAILED: 2 GARBAGE_INT should have been freed\n"); - printf("test_unreachable: PASS\n"); - deinitVM(vm); -} - -void test_auto_gc(void) { - struct virtualMachine *vm = initVM(); - - for (size_t i = 0; i < 505; ++i) { - pushInt(vm, 1); - } - - for (size_t i = 0; i < 5; ++i) { - pop(vm); - } - - for (size_t i = 0; i < 50; ++i) { - pushInt(vm, 2); - } - - assert(vm->refCount == 550 && - "test_auto_gc: FAILED: 5 references should have been freed\n"); - printf("test_auto_gc: PASS\n"); - deinitVM(vm); -} - -int main(void) { - - test_int_alloc(); - test_pair_alloc(); - test_obj_count(); - test_nested_pair(); - test_unreachable(); - test_auto_gc(); - - return 0; -} diff --git a/src/gc.c b/src/gc.c new file mode 100644 index 0000000..99d5337 --- /dev/null +++ b/src/gc.c @@ -0,0 +1,47 @@ +#include + +#include "gc.h" + +void mark(struct garbageObject *obj) +{ + if (obj->mark) + return; + + ++obj->mark; + + if (obj->type == GARBAGE_PAIR) { + mark(obj->head); + mark(obj->tail); + } +} + +void markAll(struct virtualMachine *vm) +{ + for (int i = 0; i < vm->stackSize; ++i) { + mark(vm->stack[i]); + } +} + +void sweep(struct virtualMachine *vm) +{ + struct garbageObject **obj = &vm->head; + + while (*obj) { + if (!(*obj)->mark) { + struct garbageObject *unreachable = *obj; + *obj = unreachable->next; + free(unreachable); + vm->refCount--; + } else { + (*obj)->mark = 0; + obj = &(*obj)->next; + } + } +} + +void collect(struct virtualMachine *vm) +{ + markAll(vm); + sweep(vm); + vm->refMax = vm->refCount * 2 <= STACK_MAX ? vm->refCount * 2 : STACK_MAX; +} diff --git a/gc_alloc.c b/src/gc_alloc.c similarity index 100% rename from gc_alloc.c rename to src/gc_alloc.c diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..25199a6 --- /dev/null +++ b/src/main.c @@ -0,0 +1,114 @@ +#include +#include + +#include "gc.h" +#include "test_gc.h" +#include "vm.h" + +void test_int_alloc(void) +{ + struct virtualMachine *vm = initVM(); + pushInt(vm, 100); + pushInt(vm, 1000); + pushInt(vm, 10000); + pushInt(vm, -100000); + assert(vm->refCount == 4 + && "test_int_alloc: GARBAGE_INT allocation failure\n"); + printf("test_int_alloc: PASS\n"); + deinitVM(vm); +} + +void test_pair_alloc(void) +{ + struct virtualMachine *vm = initVM(); + pushInt(vm, 100); + pushInt(vm, 1000); + pushInt(vm, 10000); + pushInt(vm, -100000); + pushPair(vm); + pushPair(vm); + assert(vm->refCount == 6 + && "test_pair_alloc: FAILED: GARBAGE_PAIR allocation failure\n"); + printf("test_pair_alloc: PASS\n"); + deinitVM(vm); +} + +void test_obj_count(void) +{ + struct virtualMachine *vm = initVM(); + pushInt(vm, 100); + pushInt(vm, 1000); + pushInt(vm, 10000); + pushInt(vm, -100000); + collect(vm); + assert(vm->refCount == 4 + && "test_obj_count: FAILED: GC occurred when it shouldn't have\n"); + printf("test_obj_count: PASS\n"); + deinitVM(vm); +} + +void test_nested_pair(void) +{ + struct virtualMachine *vm = initVM(); + pushInt(vm, 100); + pushInt(vm, 1000); + pushPair(vm); + pushInt(vm, 10000); + pushInt(vm, -100000); + pushPair(vm); + pushPair(vm); + collect(vm); + assert(vm->refCount == 7 + && "test_nested_pair: FAILED: GARBAGE_PAIR allocation failure\n"); + printf("test_pair_alloc: PASS\n"); + deinitVM(vm); +} + +void test_unreachable(void) +{ + struct virtualMachine *vm = initVM(); + pushInt(vm, 100); + pushInt(vm, 1000); + pop(vm); + pop(vm); + collect(vm); + assert( + vm->refCount == 0 + && "test_unreachable: FAILED: 2 GARBAGE_INT should have been freed\n"); + printf("test_unreachable: PASS\n"); + deinitVM(vm); +} + +void test_auto_gc(void) +{ + struct virtualMachine *vm = initVM(); + + for (size_t i = 0; i < 505; ++i) { + pushInt(vm, 1); + } + + for (size_t i = 0; i < 5; ++i) { + pop(vm); + } + + for (size_t i = 0; i < 50; ++i) { + pushInt(vm, 2); + } + + assert(vm->refCount == 550 + && "test_auto_gc: FAILED: 5 references should have been freed\n"); + printf("test_auto_gc: PASS\n"); + deinitVM(vm); +} + +int main(void) +{ + test_int_alloc(); + test_pair_alloc(); + test_obj_count(); + test_nested_pair(); + test_unreachable(); + test_auto_gc(); + + return 0; +} diff --git a/src/vm.c b/src/vm.c new file mode 100644 index 0000000..8c60405 --- /dev/null +++ b/src/vm.c @@ -0,0 +1,89 @@ +#include +#include + +#include "gc.h" +#include "vm.h" + +struct virtualMachine *initVM(void) +{ + struct virtualMachine *vm = malloc(sizeof(struct virtualMachine)); + vm->stackSize = 0; + vm->refCount = 0; + vm->refMax = GC_THRESHOLD; + vm->head = NULL; + return vm; +} + +void deinitVM(struct virtualMachine *vm) +{ + vm->stackSize = 0; + collect(vm); + free(vm); +} + +void push(struct virtualMachine *vm, struct garbageObject *value) +{ + if (vm->stackSize >= STACK_MAX) { + fprintf(stderr, "ERROR: push(): refusing to overflow the stack!\n"); + return; + } + vm->stack[vm->stackSize++] = value; +} + +struct garbageObject *pop(struct virtualMachine *vm) +{ + if (vm->stackSize < 0) { + fprintf(stderr, "ERROR: pop(): Stack size cannot be negative!"); + return NULL; + } + + return vm->stack[--vm->stackSize]; +} + +struct garbageObject *initGarbage(struct virtualMachine *vm, + enum garbageData type) +{ + if (vm->refCount >= vm->refMax) { + collect(vm); + } + + struct garbageObject *obj = malloc(sizeof(struct garbageObject)); + if (obj == NULL) { + fprintf(stderr, "initGarbage(): Allocation failure!"); + return obj; + } + + obj->type = type; + obj->mark = 0; + obj->next = vm->head; + vm->head = obj; + vm->refCount++; + return obj; +} + +void pushInt(struct virtualMachine *vm, int value) +{ + struct garbageObject *obj = initGarbage(vm, GARBAGE_INT); + if (obj == NULL) { + fprintf(stderr, + "pushInt(): Unable to create GARBAGE_INT - out of memory?"); + } + + obj->value = value; + push(vm, obj); +} + +struct garbageObject *pushPair(struct virtualMachine *vm) +{ + struct garbageObject *obj = initGarbage(vm, GARBAGE_PAIR); + if (obj == NULL) { + fprintf(stderr, + "pushPair(): Unable to create GARBAGE_PAIR - out of memory?"); + } + + obj->tail = pop(vm); + obj->head = pop(vm); + + push(vm, obj); + return obj; +} diff --git a/vm.c b/vm.c deleted file mode 100644 index 0125e07..0000000 --- a/vm.c +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include - -#include "gc.h" -#include "vm.h" - -struct virtualMachine *initVM(void) { - struct virtualMachine *vm = malloc(sizeof(struct virtualMachine)); - vm->stackSize = 0; - vm->refCount = 0; - vm->refMax = GC_THRESHOLD; - vm->head = NULL; - return vm; -} - -void deinitVM(struct virtualMachine *vm) { - vm->stackSize = 0; - collect(vm); - free(vm); -} - -void push(struct virtualMachine *vm, struct garbageObject *value) { - if (vm->stackSize >= STACK_MAX) { - fprintf(stderr, "ERROR: push(): refusing to overflow the stack!\n"); - return; - } - vm->stack[vm->stackSize++] = value; -} - -struct garbageObject *pop(struct virtualMachine *vm) { - if (vm->stackSize < 0) { - fprintf(stderr, "ERROR: pop(): Stack size cannot be negative!"); - return NULL; - } - - return vm->stack[--vm->stackSize]; -} - -struct garbageObject *initGarbage(struct virtualMachine *vm, - enum garbageData type) { - - if (vm->refCount >= vm->refMax) { - collect(vm); - } - - struct garbageObject *obj = malloc(sizeof(struct garbageObject)); - if (obj == NULL) { - fprintf(stderr, "initGarbage(): Allocation failure!"); - return obj; - } - - obj->type = type; - obj->mark = 0; - obj->next = vm->head; - vm->head = obj; - vm->refCount++; - return obj; -} - -void pushInt(struct virtualMachine *vm, int value) { - struct garbageObject *obj = initGarbage(vm, GARBAGE_INT); - if (obj == NULL) { - fprintf(stderr, "pushInt(): Unable to create GARBAGE_INT - out of memory?"); - } - - obj->value = value; - push(vm, obj); -} - -struct garbageObject *pushPair(struct virtualMachine *vm) { - struct garbageObject *obj = initGarbage(vm, GARBAGE_PAIR); - if (obj == NULL) { - fprintf(stderr, - "pushPair(): Unable to create GARBAGE_PAIR - out of memory?"); - } - - obj->tail = pop(vm); - obj->head = pop(vm); - - push(vm, obj); - return obj; -}