diff --git a/lib/heap.c b/lib/heap.c index 98f9a0c..8cc9c74 100644 --- a/lib/heap.c +++ b/lib/heap.c @@ -12,17 +12,19 @@ #include "./heap.h" +#include + +#include #include #include -page_t *page_create(size_t max, page_t *next) +page_t *page_create(size_t max) { if (max == 0) max = PAGE_DEFAULT_SIZE; page_t *page = calloc(1, sizeof(*page) + max); page->available = max; - page->next = next; return page; } @@ -38,13 +40,8 @@ void heap_create(heap_t *heap) page_t *heap_allocate(heap_t *heap, size_t requested) { - page_t *cur = page_create(requested, NULL); - if (heap->end) - heap->end->next = cur; - else - heap->beg = cur; - heap->end = cur; - heap->pages++; + page_t *cur = page_create(requested); + darr_append_bytes(&heap->page_vec, (byte_t *)cur, sizeof(cur)); return cur; } @@ -53,52 +50,30 @@ bool heap_free(heap_t *heap, page_t *page) if (!page || !heap) return false; - if (page == heap->beg) + for (size_t i = 0; i < (heap->page_vec.used / sizeof(page)); ++i) { - heap->beg = heap->beg->next; - page_delete(page); - --heap->pages; - if (heap->pages == 0) - heap->end = NULL; - return true; - } - - page_t *prev = NULL, *next = NULL, *cur = NULL; - for (cur = heap->beg; cur; cur = cur->next) - { - next = cur->next; + page_t *cur = DARR_AT(page_t *, heap->page_vec.data, i); if (cur == page) - break; - prev = cur; + { + page_delete(cur); + // TODO: When does this fragmentation become a performance + // issue? + DARR_AT(page_t *, heap->page_vec.data, i) = NULL; + return true; + } } - if (!cur) - // Couldn't find the page - return false; - // Page was found - prev->next = next; - if (!next) - // This means page == heap->end - heap->end = prev; - page_delete(page); - --heap->pages; - if (heap->pages == 0) - heap->beg = NULL; - - return true; + return false; } void heap_stop(heap_t *heap) { - page_t *ptr = heap->beg; - for (size_t i = 0; i < heap->pages; ++i) + for (size_t i = 0; i < (heap->page_vec.used / sizeof(page_t *)); i++) { - page_t *cur = ptr; - page_t *next = ptr->next; - page_delete(cur); - ptr = next; + page_t *ptr = DARR_AT(page_t *, heap->page_vec.data, i); + if (ptr) + page_delete(ptr); } - heap->beg = NULL; - heap->end = NULL; - heap->pages = 0; + free(heap->page_vec.data); + heap->page_vec = (darr_t){0}; } diff --git a/lib/heap.h b/lib/heap.h index 186eedd..a19ae6e 100644 --- a/lib/heap.h +++ b/lib/heap.h @@ -14,19 +14,17 @@ #define HEAP_H #include "./base.h" +#include "./darr.h" #include -#include #define PAGE_DEFAULT_SIZE 256 /** - @brief Some fixed portion of bytes allocated on the heap in a - linked list. + @brief Some fixed portion of bytes allocated on the heap. - @details A fixed allocation of bytes, with size and a link to the - next page. Cannot be resized nor can it be stack allocated the - usual way due to flexible array attached. + @details A fixed allocation of bytes. Cannot be resized nor can it + be stack allocated (the usual way) due to flexible array attached. @prop[next] Next page in the linked list @prop[available] Available number of bytes in page @@ -34,7 +32,6 @@ */ typedef struct Page { - struct Page *next; size_t available; byte_t data[]; } page_t; @@ -47,16 +44,15 @@ typedef struct Page default. @param[max] Maximum available memory in page - @param[next] Next page to link this page to */ -page_t *page_create(size_t max, page_t *next); +page_t *page_create(size_t max); /** @brief Delete a page, freeing its memory @details Free's the memory associated with the page via free(). - NOTE: any pointer's to the page's memory are considered invalid - once this is called. + NOTE: any pointers to the page's memory are considered invalid once + this is called. @param[page] Page to delete */ @@ -66,17 +62,14 @@ void page_delete(page_t *page); @brief A collection of pages through which generic allocations can occur. - @details Structure which maintains a linked list of pages (with a - reference to the beginning and end of it). + @details Collection of pages maintained through a vector of + pointers to pages. - @prop[beg] Beginning of linked list of pages - @prop[end] End of linked list of pages - @prop[pages] Number of pages allocated in heap + @prop[page_vec] Vector of pages */ typedef struct { - page_t *beg, *end; - size_t pages; + darr_t page_vec; } heap_t; /** diff --git a/vm/struct.c b/vm/struct.c index 6ba429d..e1f7207 100644 --- a/vm/struct.c +++ b/vm/struct.c @@ -14,6 +14,7 @@ #include #include "./struct.h" +#include "lib/darr.h" void vm_load_stack(vm_t *vm, byte_t *bytes, size_t size) { @@ -180,17 +181,18 @@ void vm_print_program(vm_t *vm, FILE *fp) void vm_print_heap(vm_t *vm, FILE *fp) { - heap_t heap = vm->heap; - fprintf(fp, "Heap.pages = %lu\nHeap.data = [", heap.pages); - if (heap.pages == 0) + heap_t heap = vm->heap; + const size_t heap_pages = heap.page_vec.used / sizeof(page_t *); + fprintf(fp, "Heap.pages = %lu\nHeap.data = [", heap_pages); + if (heap_pages == 0) { fprintf(fp, "]\n"); return; } - page_t *cur = heap.beg; fprintf(fp, "\n"); - for (size_t i = 0; i < heap.pages; ++i) + for (size_t i = 0; i < heap_pages; ++i) { + page_t *cur = DARR_AT(page_t *, heap.page_vec.data, i); fprintf(fp, "\t[%lu]@%p: ", i, (void *)cur); if (!cur) fprintf(fp, "\n"); @@ -206,7 +208,6 @@ void vm_print_heap(vm_t *vm, FILE *fp) fprintf(fp, ",\t"); } fprintf(fp, "\n\t}\n"); - cur = cur->next; } } fprintf(fp, "]\n");