From cfc66b3b567538b76c6170e3a86f0cabdd867b91 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Sun, 29 Sep 2019 14:07:04 -0400 Subject: made allocator; will switch to it soon --- abbrevs.txt | 2 ++ allocator.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ archive/arr.c | 61 +++++++++++++++++++++++++++++++++++++ main.c | 5 +++ toc.c | 1 + 5 files changed, 166 insertions(+) create mode 100644 allocator.c create mode 100644 archive/arr.c diff --git a/abbrevs.txt b/abbrevs.txt index cdf5bb1..d5a3a68 100644 --- a/abbrevs.txt +++ b/abbrevs.txt @@ -1,9 +1,11 @@ +allocr - allocator arg - argument decl - declaration del - delete deref - dereference direct - directive eof - end of file +err - error expr - expression fn - function ident - identifier diff --git a/allocator.c b/allocator.c new file mode 100644 index 0000000..7d1c6a7 --- /dev/null +++ b/allocator.c @@ -0,0 +1,97 @@ +typedef struct Page { + struct Page *next; + size_t used; + max_align_t data[]; +} Page; + +typedef struct { + Page *first; + Page *last; +} Allocator; + +/* number of bytes a page hold, not including the header */ +#define PAGE_SIZE (16384 - sizeof(Page)) + +static void allocr_create(Allocator *a) { + a->first = a->last = NULL; +} + +static void *allocr_malloc(Allocator *a, size_t bytes) { + /* position in this page to return */ + size_t pos = PAGE_SIZE; + if (a->last) + pos = (a->last->used + sizeof(max_align_t) - 1) / sizeof(max_align_t); + + if (pos * sizeof(max_align_t) + bytes > PAGE_SIZE) { + /* make a new page for this data */ + Page *page = err_malloc(sizeof *page + (bytes > PAGE_SIZE ? bytes : PAGE_SIZE)); + page->next = NULL; + page->used = bytes; + if (a->last) + a->last->next = page; + else + a->first = page; + a->last = page; + return page->data; + } else { + a->last->used += bytes; + return &a->last->data[pos]; + } +} + +static void *allocr_calloc(Allocator *a, size_t bytes) { + void *data = allocr_malloc(a, bytes); + memset(data, 0, bytes); + return data; +} + +/* IMPORTANT: this can only be called with data which was originally allocated with allocr_realloc(a, NULL, x) */ +static void *allocr_realloc(Allocator *a, void *data, size_t new_size) { + if (!data) { + Page *page = err_malloc(sizeof *page + new_size); + page->used = PAGE_SIZE; /* pretend we used all of this page */ + page->next = NULL; + if (a->last) + a->last->next = page; + else + a->first = page; + a->last = page; + return page->data; + } else { + Page *page = (Page *)((char *)data - offsetof(Page, data)); + page = err_realloc(page, sizeof *page + new_size); + return page->data; + } +} + +static void allocr_free_all(Allocator *a) { + for (Page *page = a->first; page;) { + Page *next = page->next; + free(page); + page = next; + } +} + +static void allocr_test(void) { + Allocator a; + allocr_create(&a); + for (int x = 1000; x <= 8000; x += 1000) { + size_t nfoos = x; + int *foos = allocr_malloc(&a, nfoos * sizeof(int)); + + for (size_t i = 0; i < nfoos; i++) + foos[i] = (int)i; + for (size_t i = 0; i < nfoos; i++) + assert(foos[i] == (int)i); + size_t nbars = x; + int *bars = allocr_calloc(&a, nbars * sizeof(int)); + for (size_t i = 0; i < nbars; i++) + assert(bars[i] == 0); + for (size_t i = 0; i < nbars; i++) + bars[i] = (int)i; + for (size_t i = 0; i < nbars; i++) + assert(bars[i] == (int)i); + } + + allocr_free_all(&a); +} diff --git a/archive/arr.c b/archive/arr.c new file mode 100644 index 0000000..2555d72 --- /dev/null +++ b/archive/arr.c @@ -0,0 +1,61 @@ +typedef struct { + void *data; + size_t len; + size_t cap; + size_t item_sz; +} Array; + +static void arr_create(Array *arr, size_t item_sz) { + arr->len = arr->cap = 0; + arr->item_sz = item_sz; + arr->data = NULL; +} + +static inline void arr_reserve(Array *arr, size_t n) { + arr->cap = n; + arr->data = err_realloc(arr->data, arr->item_sz * arr->cap); +} + +/* like arr_reserve, but sets the length of the array too */ +static inline void arr_set_len(Array *arr, size_t n) { + arr->len = arr->cap = n; + arr->data = err_realloc(arr->data, arr->item_sz * arr->cap); +} + +static inline void *arr_last(Array *arr) { + if (arr->data) + return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); + else + return NULL; +} + +static void *arr_add(Array *arr) { + if (arr->len >= arr->cap) { + arr_reserve(arr, (arr->cap + 1) * 2); + } + arr->len++; + return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); +} + +static void arr_clear(Array *arr) { + free(arr->data); + arr->len = arr->cap = 0; + arr->data = NULL; +} + +static void arr_remove_last(Array *arr) { + /* OPTIM (memory): Shorten array. */ + arr->len--; + if (!arr->len) { + arr_clear(arr); + } + +} + +static void arr_free(Array *arr) { + free(arr->data); +} + +/* NOTE: this will not work if type is a pointer! */ +#define arr_foreach(arr, type, var) for (type *var = (arr)->data, *var##_foreach_last = arr_last(arr); var; var == var##_foreach_last ? var = NULL : var++) +#define arr_foreach_reverse(arr, type, var) for (type *var = arr_last(arr); var; var == (arr)->data ? var = NULL : var--) diff --git a/main.c b/main.c index 596f3de..5c2f1f1 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,8 @@ /* TODO: +allocator +casting errors +call fns at compile time finish evaluator fix void fn type re-do cgen @@ -8,6 +11,8 @@ any odd number of "s for a string #include "toc.c" int main(int argc, char **argv) { + allocr_test(); + return 0; if (argc < 2) { fprintf(stderr, "Please specify an input file.\n"); return EXIT_FAILURE; diff --git a/toc.c b/toc.c index 2fd7e86..ac5db05 100644 --- a/toc.c +++ b/toc.c @@ -19,6 +19,7 @@ typedef long double Floating; /* OPTIM: Switch to double */ #include "location.c" #include "err.c" +#include "allocator.c" #include "arr.c" #include "blockarr.c" #include "str.c" -- cgit v1.2.3