diff --git a/include/gc_alloc.h b/include/gc_alloc.h index cbb23b8..44858df 100644 --- a/include/gc_alloc.h +++ b/include/gc_alloc.h @@ -6,9 +6,9 @@ // Metadata for allocated memory - Headers are stored in a linked list to keep // track of alloc's and free's struct gcHeader { - size_t size; - int free; - struct gcHeader *next; + size_t size; + int free; + struct gcHeader *next; }; // Iterates over the galloc linked list attempting to find free space diff --git a/include/vm.h b/include/vm.h index 5bfde17..8731464 100644 --- a/include/vm.h +++ b/include/vm.h @@ -6,38 +6,38 @@ // Primitive types for garbage collection enum garbageData { - GARBAGE_INT, - GARBAGE_PAIR, + GARBAGE_INT, + GARBAGE_PAIR, }; // Holds type and value data for the virtual machine struct garbageObject { - enum garbageData type; - struct garbageObject *next; - unsigned char mark; + enum garbageData type; + struct garbageObject *next; + unsigned char mark; - union { - int value; + union { + int value; - struct { - struct garbageObject *head; - struct garbageObject *tail; - }; - }; + struct { + struct garbageObject *head; + struct garbageObject *tail; + }; + }; }; // Virtual machine hold the stack to trace references struct virtualMachine { - int stackSize; - unsigned refCount; - unsigned refMax; - struct garbageObject *head; - struct garbageObject *stack[STACK_MAX]; + int stackSize; + unsigned refCount; + unsigned refMax; + struct garbageObject *head; + struct garbageObject *stack[STACK_MAX]; }; // Create a new garbageObject struct garbageObject *initGarbage(struct virtualMachine *vm, - enum garbageData type); + enum garbageData type); // Create a new VM struct virtualMachine *initVM(void); diff --git a/src/gc.c b/src/gc.c index 99d5337..6d2268c 100644 --- a/src/gc.c +++ b/src/gc.c @@ -4,44 +4,45 @@ void mark(struct garbageObject *obj) { - if (obj->mark) - return; + if (obj->mark) + return; - ++obj->mark; + ++obj->mark; - if (obj->type == GARBAGE_PAIR) { - mark(obj->head); - mark(obj->tail); - } + 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]); - } + for (int i = 0; i < vm->stackSize; ++i) { + mark(vm->stack[i]); + } } void sweep(struct virtualMachine *vm) { - struct garbageObject **obj = &vm->head; + 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; - } - } + 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; + markAll(vm); + sweep(vm); + vm->refMax = vm->refCount * 2 <= STACK_MAX ? vm->refCount * 2 : + STACK_MAX; } diff --git a/src/gc_alloc.c b/src/gc_alloc.c index 11a823e..640ceb4 100644 --- a/src/gc_alloc.c +++ b/src/gc_alloc.c @@ -5,45 +5,47 @@ static void *allocHead = NULL; -struct gcHeader *findFree(struct gcHeader **prev, size_t size) { - struct gcHeader *curr = allocHead; +struct gcHeader *findFree(struct gcHeader **prev, size_t size) +{ + struct gcHeader *curr = allocHead; - while (curr && !(curr->free && curr->size >= size)) { - *prev = curr; - curr = curr->next; - } + while (curr && !(curr->free && curr->size >= size)) { + *prev = curr; + curr = curr->next; + } - return curr; + return curr; } -struct gcHeader *requestMem(struct gcHeader *prev, size_t size) { - struct gcHeader *block; - void *request; +struct gcHeader *requestMem(struct gcHeader *prev, size_t size) +{ + struct gcHeader *block; + void *request; - block = sbrk(0); - if (block == (void *)-1) { - perror("sbrk block"); - return NULL; - } + block = sbrk(0); + if (block == (void *)-1) { + perror("sbrk block"); + return NULL; + } - request = sbrk(size + sizeof(struct gcHeader)); - if (request == (void *)-1) { - perror("sbrk request"); - return NULL; - } + request = sbrk(size + sizeof(struct gcHeader)); + if (request == (void *)-1) { + perror("sbrk request"); + return NULL; + } - if ((void *)block != request) { - fprintf(stderr, "gcHeader: block != request"); - return NULL; - } + if ((void *)block != request) { + fprintf(stderr, "gcHeader: block != request"); + return NULL; + } - if (prev) { - prev->next = block; - } + if (prev) { + prev->next = block; + } - block->size = size; - block->next = NULL; - block->free = 0; + block->size = size; + block->next = NULL; + block->free = 0; - return block; + return block; } diff --git a/src/main.c b/src/main.c index 25199a6..26050be 100644 --- a/src/main.c +++ b/src/main.c @@ -7,108 +7,107 @@ 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); + 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); + 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); + 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); + 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); + 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(); + struct virtualMachine *vm = initVM(); - for (size_t i = 0; i < 505; ++i) { - pushInt(vm, 1); - } + 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 < 5; ++i) { + pop(vm); + } - for (size_t i = 0; i < 50; ++i) { - pushInt(vm, 2); - } + 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); + 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(); + test_int_alloc(); + test_pair_alloc(); + test_obj_count(); + test_nested_pair(); + test_unreachable(); + test_auto_gc(); - return 0; + return 0; } diff --git a/src/vm.c b/src/vm.c index 8c60405..90a3431 100644 --- a/src/vm.c +++ b/src/vm.c @@ -6,84 +6,85 @@ 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; + 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); + 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; + 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; - } + if (vm->stackSize < 0) { + fprintf(stderr, "ERROR: pop(): Stack size cannot be negative!"); + return NULL; + } - return vm->stack[--vm->stackSize]; + return vm->stack[--vm->stackSize]; } struct garbageObject *initGarbage(struct virtualMachine *vm, - enum garbageData type) + enum garbageData type) { - if (vm->refCount >= vm->refMax) { - collect(vm); - } + if (vm->refCount >= vm->refMax) { + collect(vm); + } - struct garbageObject *obj = malloc(sizeof(struct garbageObject)); - if (obj == NULL) { - fprintf(stderr, "initGarbage(): Allocation failure!"); - return obj; - } + 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; + 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?"); - } + 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); + 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?"); - } + 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); + obj->tail = pop(vm); + obj->head = pop(vm); - push(vm, obj); - return obj; + push(vm, obj); + return obj; }