diff --git a/TODO.md b/TODO.md index be18c9c..3b3ff62 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,6 @@ +tmp: + - fix realloc + - Benchmarks - Tests - Rework assign/call to work better diff --git a/src/exec_common.c b/src/exec_common.c index 27b9a70..981d7ed 100644 --- a/src/exec_common.c +++ b/src/exec_common.c @@ -36,6 +36,8 @@ typedef struct { } AllocBlock; +#define EXT_BLOCK 4096 + void *internal_buf; AllocBlock *blocks; u32 *usage; // bitmap for usage, by 8byte chunks @@ -70,48 +72,14 @@ int evaluate(Value val){ } } -int alloc_init(){ - internal_buf = malloc(4096); - blocks = malloc(sizeof(AllocBlock)); - block_count = 0; - usage = malloc(sizeof(u32)*4096/32/8); - if(!internal_buf || !blocks || !usage) +int alloc_extend(u32 size){ + size = (size/EXT_BLOCK+1)*EXT_BLOCK; + internal_buf = realloc(internal_buf, internal_size+size); + usage = realloc(usage, sizeof(u32)*(internal_size+size)/32/8); + if(!internal_buf || !usage) return 1; - memset(usage, 0, sizeof(u32)*4096/32/8); - return 0; -} - -u32 flisp_alloc(size_t size){ - u32 pos = 32; - u32 curr_free = 0; - while(pos < internal_size){ - if(usage[pos/32/8]){ - for(int i = 0; i < 32; i++){ - if((usage[pos/32/8]>>i) & 1) - curr_free = 0; - else - curr_free+=8; - } - } - else { - curr_free += 32*8; - } - if(curr_free >= size){ - blocks = realloc(blocks, sizeof(AllocBlock)*(block_count+1)); - if(!blocks) - return 0; - AllocBlock *block = &blocks[block_count++]; - block->pos = pos - curr_free; - block->size = size; - for(u32 i = block->pos; i < block->pos+size; i++){ - usage[i/32/8] |= 1<<(i%(32*8)); - } - // Unvirtualize the memory - memset(get_addr(block->pos),0xB00B5069,size); - return block->pos; - } - pos++; - } + memset(usage+(internal_size/32/8), 0, sizeof(u32)*size/32/8); + internal_size += size; return 0; } @@ -121,10 +89,86 @@ int block_cmpfunc(const void *_a, const void *_b){ return b->pos - a->pos; } -void flisp_free(u32 pos){ +AllocBlock *get_block(u32 pos){ AllocBlock tmp = {.pos = pos}; AllocBlock *ret = bsearch(&tmp, blocks, block_count, sizeof(AllocBlock), block_cmpfunc); + return ret; +} + +int alloc_init(){ + blocks = malloc(sizeof(AllocBlock)); + block_count = 0; + internal_buf = NULL; + internal_size = 0; + usage = NULL; + if(!blocks || alloc_extend(EXT_BLOCK)) + return 1; + return 0; +} + +void alloc_clean(){ + free(internal_buf); + free(blocks); + free(usage); +} + +u32 flisp_alloc(u32 size){ + u32 pos = 32; + u32 curr_free = 0; + while(pos < internal_size){ + if(usage[pos/32/8]){ + for(int i = 0; i < 32; i++){ + if((usage[pos/32/8]>>i) & 1) + curr_free = 0; + else + curr_free+=8; + pos+=8; + if(curr_free >= size) + break; + } + } + else { + curr_free += 32*8; + pos+=32*8; + } + if(curr_free >= size){ + blocks = realloc(blocks, sizeof(AllocBlock)*(block_count+1)); + if(!blocks) + return 0; + AllocBlock *block = &blocks[block_count++]; + block->pos = pos-curr_free; + block->size = size; + for(u32 i = block->pos; i < block->pos+size; i+=8){ + usage[i/32/8] |= 1<<(i%32); + } + // Unvirtualize the memory + memset(get_addr(block->pos),0xB00B5069,size); + return block->pos; + } + } + if(alloc_extend(size)) + return 0; + + // Try again after extending the buffer + return flisp_alloc(size); +} + +// TODO : make it efficient +u32 flisp_realloc(u32 pos, u32 size){ + if(!pos) + return flisp_alloc(size); + u32 new = flisp_alloc(size); + if(!new) + return 0; + AllocBlock *block = get_block(pos); + memcpy(get_addr(new),get_addr(pos),block->size); + flisp_free(pos); + return new; +} + +void flisp_free(u32 pos){ + AllocBlock *ret = get_block(pos); if(!ret) return; i32 bpos = (size_t)(ret-blocks)/sizeof(AllocBlock); diff --git a/src/exec_common.h b/src/exec_common.h index fe63d65..f3b35bb 100644 --- a/src/exec_common.h +++ b/src/exec_common.h @@ -27,17 +27,21 @@ void runtime_err(char *s); int evaluate(Value val); + int alloc_init(); -// All internal allocator memory is guaranteed to be free range and 32bit -u32 flisp_alloc(size_t size); +void alloc_clean(); + +// All internal allocator memory is guaranteed to be free range +u32 flisp_alloc(u32 size); + +u32 flisp_realloc(u32 pos, u32 size); void flisp_free(u32 pos); -void *flisp_realloc(u32 pos, size_t size); - void *get_addr(u32 pos); + Value is(Tag tag, Value b); Value cast(Tag tag, Value b); diff --git a/src/parser.y b/src/parser.y index fc0be05..2fb6ba2 100644 --- a/src/parser.y +++ b/src/parser.y @@ -144,8 +144,6 @@ void yyerror(char *s){ extern FILE *yyin; int main(int argc, char *argv[]){ - alloc_init(); - i32 fpos = 1; if(argc > 1){ @@ -167,6 +165,8 @@ int main(int argc, char *argv[]){ yyin = stdin; } + alloc_init(); + make_stack(); yyparse(); free_stack(); diff --git a/src/tests.c b/src/tests.c index 8d8e438..a72b484 100644 --- a/src/tests.c +++ b/src/tests.c @@ -19,12 +19,14 @@ #include #include +#include #include #include "types.h" #include "parser.h" #include "code_defs.h" #include "byte_defs.h" +#include "exec_common.h" typedef int (test_fun_t)(void); @@ -66,6 +68,50 @@ int t_free_hashmap(){ return 0; } +int t_alloc_init(){ + return alloc_init(); +} + +int t_flisp_alloc(){ + int err = 0; + u32 pos0 = flisp_alloc(sizeof(u64)); + u32 pos1 = flisp_alloc(sizeof(u64)); + err += !pos0 || !pos1; + if(err) + return 1; + err += pos0 == pos1; + u64 *ptr0 = get_addr(pos0); + u64 *ptr1 = get_addr(pos1); + *ptr1 = 0; + *ptr0 = 0xFFFFFFFFFFFFFFFF; + err += !!*ptr1; + flisp_free(pos0); + flisp_free(pos1); + + return err; +} + +int t_flisp_realloc(){ + int err = 0; + u8 ref[10] = {1,2,3,4,5,6,7,8,9,10}; + u32 pos0 = flisp_alloc(5); + if(!pos0) + return 1; + u8 *ptr0 = get_addr(pos0); + memcpy(ptr0, ref, 5); + pos0 = flisp_realloc(pos0, 10); + if(!pos0) + return 1; + ptr0 = get_addr(pos0); + err += memcmp(ptr0, ref, 5); + return err; +} + +int t_alloc_clean(){ + alloc_clean(); + return 0; +} + int t_get_type(){ int err = 0; Tag ttag = get_type("int"); @@ -118,6 +164,10 @@ test_fun_t *tests[] = { t_hashmap_insert_get, t_hashmap_remove, t_free_hashmap, + t_alloc_init, + t_flisp_alloc, + t_flisp_realloc, + t_alloc_clean, t_get_type, t_make_stack, t_make_iconst, @@ -132,6 +182,10 @@ char *names[] = { "hashmap_insert_get", "hashmap_remove", "free_hashmap", + "alloc_init", + "flisp_alloc", + "flisp_realloc", + "alloc_clean", "get_type", "make_stack", "make_iconst",