From b97b33c4712f5afc1bfd94a54be10a5fe240e7e5 Mon Sep 17 00:00:00 2001 From: Ludovic 'Archivist' Lagouardette Date: Tue, 21 May 2024 21:06:20 +0200 Subject: [PATCH] Garbage collector and arrays work! --- lib.c | 146 ++++++++++++++++++++++++++++++++++++++----------- test/test01.nk | 2 +- test/test02.nk | 2 - test/test05.nk | 13 +++++ 4 files changed, 128 insertions(+), 35 deletions(-) create mode 100644 test/test05.nk diff --git a/lib.c b/lib.c index c5c5835..039b9ea 100644 --- a/lib.c +++ b/lib.c @@ -876,7 +876,7 @@ struct elem ink_make_native(struct context* ctx, int type, void* ptr) { ctx->types[type_id].elements = ctx->inner_malloc(sizeof(struct element_slab) * 8); ctx->types[type_id].elements_top = 0; ctx->types[type_id].elements_capacity = 8; - memset(ctx->types[type_id].elements + ctx->types[type_id].elements_top, 0, ctx->types[type_id].elements_capacity - ctx->types[type_id].elements_top); + memset(ctx->types[type_id].elements + ctx->types[type_id].elements_top, 0, sizeof(struct element_slab)*(ctx->types[type_id].elements_capacity - ctx->types[type_id].elements_top)); } else if(ctx->types[type_id].elements_top == ctx->types[type_id].elements_capacity) { int new_count = (ctx->types[type_id].elements_capacity + ctx->types[type_id].elements_capacity/2); void* renewed = ctx->inner_realloc(ctx->types[type_id].elements, sizeof(struct element_slab) * new_count); @@ -888,7 +888,7 @@ struct elem ink_make_native(struct context* ctx, int type, void* ptr) { } else { ctx->types[type_id].elements = renewed; ctx->types[type_id].elements_capacity = new_count; - memset(ctx->types[type_id].elements + ctx->types[type_id].elements_top, 0, ctx->types[type_id].elements_capacity - ctx->types[type_id].elements_top); + memset(ctx->types[type_id].elements + ctx->types[type_id].elements_top, 0, sizeof(struct element_slab)*(ctx->types[type_id].elements_capacity - ctx->types[type_id].elements_top)); } } int g = ctx->types[type_id].elements_capacity; @@ -908,9 +908,9 @@ struct elem ink_make_native(struct context* ctx, int type, void* ptr) { return ret; } memcpy(new_ptr, ptr, ctx->types[type_id].element_size); - ctx->types[type_id].elements[i].data = ptr; + ctx->types[type_id].elements[i].data = new_ptr; } - ctx->types[type_id].elements_top = max(ctx->types[type_id].elements_top+1, i+1); + ctx->types[type_id].elements_top = max(ctx->types[type_id].elements_top, i+1); struct elem ret; ret.type = type; ret.value = i; @@ -930,27 +930,37 @@ void ink_gc(struct context* ctx) { ctx->types[i].elements[j].uses = 0; } } + + for(i = 0; i < ctx->routines_top; ++i) { + for(j = 0; j < ctx->routines[i].top; ++j) { + struct element_slab* v = ink_get_value_link(ctx, ctx->routines[i].stack[j]); + if(v != NULL) ++v->uses; + } + } + + int marked; + do { + marked = 0; + for (i = 0; i < ctx->types_top; ++i) { + for (j = 0; j < ctx->types[i].elements_top; ++j) { + if (ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].uses) { + struct ink_collection_list c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data); + for (k = 0; k < c.count; ++k) { + struct element_slab *v = ink_get_value_link(ctx, c.elements[k]); + if (v != NULL && !v->uses) { + ++v->uses; + marked = 1; + } + } + if (c.elements != NULL) ctx->inner_free(c.elements); + } + } + } + } while(marked); for(i = 0; i < ctx->types_top; ++i) { for(j = 0; j < ctx->types[i].elements_top; ++j) { - struct ink_collection_list c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data); - for(k = 0; k < c.count; ++k) { - struct element_slab* v = ink_get_value_link(ctx, c.elements[k]); - if(v != NULL) ++v->uses; - } - if(c.elements != NULL) ctx->inner_free(c.elements); - } - } - for(i = 0; i < ctx->routines_top; ++i) { - for(j = 0; j < ctx->routines[i].top; ++j) { - struct element_slab* v = ink_get_value_link(ctx, ctx->routines[i].stack[j]); - if(v != NULL) ++v->uses; - } - } - - for(i = 0; i < ctx->types_top; ++i) { - for(j = 0; j < ctx->types[i].elements_top; ++j) { - if(ctx->types[i].elements[j].uses == 0) { + if(ctx->types[i].elements[j].uses == 0 && ctx->types[i].elements[j].in_use) { ctx->collections++; ctx->types[i].collect(ctx, ctx->types[i].elements[j].data); if(ctx->types[i].element_size > 0) { @@ -1260,7 +1270,7 @@ static int get_type_by_name(struct context* ctx, const char* name) { static void collect_array(struct context* ctx, void* array) { struct ink_array* ary = array; - ctx->free(ary->elements); + if(ary->elements != NULL) ctx->free(ary->elements); } static struct ink_collection_list gc_array(struct context* ctx, void* array) { @@ -1273,23 +1283,95 @@ static struct ink_collection_list gc_array(struct context* ctx, void* array) { } static void new_array(struct context* ctx) { - int tid = get_type_by_name(ctx, "array"); - struct ink_array ary; - ary.elements = NULL; - ary.top = 0; - ary.capacity = 0; - struct elem e = ink_make_native(ctx, tid, &ary); - ink_push(ctx, e); + int tid = get_type_by_name(ctx, "array"); + struct ink_array ary; + ary.elements = NULL; + ary.top = 0; + ary.capacity = 0; + struct elem e = ink_make_native(ctx, tid, &ary); + ink_push(ctx, e); +} + +static void push_array(struct context* ctx) { + int tid = get_type_by_name(ctx, "array"); + struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current; + if(currentRoutine->top < 2 || currentRoutine->stack[currentRoutine->top-1].type != tid) { + currentRoutine->panic = 1; + return; + } + struct elem a; + a = currentRoutine->stack[currentRoutine->top-1]; + struct ink_array* ary= ink_get_value(ctx, a); + if(ary == NULL) { + currentRoutine->panic = 1; + return; + } + ink_pop(ctx); + + if(ary->elements == NULL) { + ary->elements = ctx->malloc(sizeof(struct elem) * 8); + ary->top = 0; + ary->capacity = 8; + } else if(ary->top == ary->capacity) { + int new_count = (ary->capacity + ary->capacity/2); + void* renewed = ctx->realloc(ary->elements, sizeof(struct elem) * new_count); + if(renewed == NULL) { + currentRoutine->panic = 1; + return; + } else { + ary->elements = renewed; + ary->capacity = new_count; + } + } + ary->elements[ary->top] = currentRoutine->stack[currentRoutine->top-1]; + ary->top++; + ink_pop(ctx); +} + + + +static void index_array(struct context* ctx) { + int tid = get_type_by_name(ctx, "array"); + struct ink_routine *currentRoutine = ctx->routines + ctx->routine_current; + if (currentRoutine->top < 2 || currentRoutine->stack[currentRoutine->top - 1].type != tid || currentRoutine->stack[currentRoutine->top - 2].type != INK_INTEGER) { + currentRoutine->panic = 1; + return; + } + struct elem a; + a = currentRoutine->stack[currentRoutine->top - 1]; + struct ink_array *ary = ink_get_value(ctx, a); + if (ary == NULL) { + currentRoutine->panic = 1; + return; + } + ink_pop(ctx); + + struct elem idx; + idx = currentRoutine->stack[currentRoutine->top - 1]; + ink_pop(ctx); + + if(ary->top <= idx.value) { + currentRoutine->panic = 1; + return; + } + + ink_push(ctx, ary->elements[idx.value]); } +static void run_gc(struct context* ctx) { + ink_gc(ctx); +} int ink_std_library(struct context* ctx) { int v; v = 0; int array_t = ink_new_type(ctx, "array", sizeof(struct ink_array), collect_array, gc_array); - v += ink_add_native(ctx, "array", new_array); - v += ink_add_native(ctx, "trace", print_stacktrace); + v += ink_add_native(ctx, "array.new", new_array); + v += ink_add_native(ctx, "array.push", push_array); + v += ink_add_native(ctx, "array.index", index_array); + v += ink_add_native(ctx, "sys.trace", print_stacktrace); + v += ink_add_native(ctx, "sys.gc", run_gc); v += ink_add_native(ctx, "print_int", print_int); v += ink_add_native(ctx, "print_utf8", print_as_utf8); v += ink_add_native(ctx, "+", add_int); diff --git a/test/test01.nk b/test/test01.nk index 082b334..2bde0a3 100644 --- a/test/test01.nk +++ b/test/test01.nk @@ -1,5 +1,5 @@ fn potato do - trace return + sys.trace return end fn print_n_utf8_impl do diff --git a/test/test02.nk b/test/test02.nk index 5dea0ed..3fc8712 100644 --- a/test/test02.nk +++ b/test/test02.nk @@ -1,5 +1,3 @@ fn print_n_utf8 do print_n_utf8_impl drop end - -array drop array drop \ No newline at end of file diff --git a/test/test05.nk b/test/test05.nk new file mode 100644 index 0000000..7f560a1 --- /dev/null +++ b/test/test05.nk @@ -0,0 +1,13 @@ + +array.new drop +array.new drop +array.new drop +array.new drop + +sys.gc + +array.new dup 1 swap array.push dup 0 swap array.index print_int dup 2 swap array.push dup 1 swap array.index print_int drop + +sys.gc + +array.new dup array.push \ No newline at end of file