From 956dde00a3c90cf3813211bb754e6dcd411bbd76 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Sun, 18 May 2025 12:02:34 +0300 Subject: [PATCH] byterun gc integration fix: move __gc_stack_top by 1 --- byterun/include/stack.h | 92 ++++++++++++++++++---------------- byterun/src/interpreter.c | 6 +-- byterun/src/module_manager.cpp | 5 +- byterun/src/types.c | 4 +- runtime/gc.h | 2 +- 5 files changed, 57 insertions(+), 52 deletions(-) diff --git a/byterun/include/stack.h b/byterun/include/stack.h index 16f21268d..e1fadb634 100644 --- a/byterun/include/stack.h +++ b/byterun/include/stack.h @@ -16,9 +16,26 @@ static inline void **s_top() { return (void **)__gc_stack_bottom - s.bf->global_area_size; } +static inline void **s_peek_unsafe() { + return (void **)(__gc_stack_top + sizeof(void *)); +} + +static inline void **s_peek() { + void **peek = s_peek_unsafe(); +#ifndef WITH_CHECK + if (peek == s_top()) { + s_failure(&s, "peek: empty stack"); + } + if (s.fp != NULL && peek == f_locals(s.fp)) { + s_failure(&s, "peek: empty function stack"); + } +#endif + return peek; +} + static inline bool s_is_empty() { - if ((void **)__gc_stack_top == s_top() || - (s.fp != NULL && (void **)__gc_stack_top == f_locals(s.fp))) { + if (s_peek_unsafe() == s_top() || + (s.fp != NULL && s_peek_unsafe() == f_locals(s.fp))) { return true; } return false; @@ -26,41 +43,29 @@ static inline bool s_is_empty() { static inline void **s_nth(size_t n) { #ifndef WITH_CHECK - if ((void **)__gc_stack_top + n >= s_top()) { + if (s_peek_unsafe() + n >= s_top()) { s_failure(&s, "not enough elements in stack"); } - if (s.fp != NULL && (void **)__gc_stack_top + n >= f_locals(s.fp)) { + if (s.fp != NULL && s_peek_unsafe() + n >= f_locals(s.fp)) { s_failure(&s, "not enough elements in function stack"); } #endif - return (void **)__gc_stack_top + n; + return s_peek_unsafe() + n; } static inline aint *s_nth_i(size_t n) { return (aint *)s_nth(n); } -static inline void **s_peek() { -#ifndef WITH_CHECK - if ((void **)__gc_stack_top == s_top()) { - s_failure(&s, "peek: empty stack"); - } - if (s.fp != NULL && (void **)__gc_stack_top == f_locals(s.fp)) { - s_failure(&s, "peek: empty function stack"); - } -#endif - return (void **)__gc_stack_top; -} - static inline aint *s_peek_i() { return (aint *)s_peek(); } static inline void s_push(void *val) { #ifndef WITH_CHECK - if ((void **)__gc_stack_top == s.stack) { + if (s_peek_unsafe() == s.stack) { s_failure(&s, "stack overflow"); } #endif - __gc_stack_top -= sizeof(void *); *(void **)__gc_stack_top = val; + __gc_stack_top -= sizeof(void *); } static inline void s_push_i(aint val) { s_push((void *)val); } @@ -69,27 +74,27 @@ static inline void s_push_nil() { s_push(NULL); } static inline void s_pushn_nil(size_t n) { #ifndef WITH_CHECK - if ((void **)__gc_stack_top + (aint)n - 1 <= s.stack) { + if (s_peek_unsafe() + (aint)n - 1 <= s.stack) { s_failure(&s, "pushn: stack overflow"); } #endif for (size_t i = 0; i < n; ++i) { - __gc_stack_top -= sizeof(void *); *(void **)__gc_stack_top = NULL; + __gc_stack_top -= sizeof(void *); } } static inline void *s_pop() { #ifndef WITH_CHECK - if ((void **)__gc_stack_top == s_top()) { + if (s_peek_unsafe() == s_top()) { s_failure(&s, "pop: empty stack"); } if (s.fp != NULL && (void **)__gc_stack_top == f_locals(s.fp)) { s_failure(&s, "pop: empty function stack"); } #endif - void *value = *(void **)__gc_stack_top; __gc_stack_top += sizeof(void *); + void *value = *(void **)__gc_stack_top; return value; } @@ -97,10 +102,10 @@ static inline aint s_pop_i() { return (aint)s_pop(); } static inline void s_popn(size_t n) { #ifndef WITH_CHECK - if ((void **)__gc_stack_top + (aint)n - 1 >= s_top()) { + if (s_peek_unsafe() + (aint)n - 1 >= s_top()) { s_failure(&s, "popn: empty stack"); } - if (s.fp != NULL && (void **)__gc_stack_top + (aint)n - 1 >= f_locals(s.fp)) { + if (s.fp != NULL && s_peek_unsafe() + (aint)n - 1 >= f_locals(s.fp)) { s_failure(&s, "popn: empty function stack"); } #endif @@ -122,35 +127,35 @@ static inline void s_swap_tops() { static inline void s_put_nth(size_t n, void *val) { s_push_nil(); #ifndef WITH_CHECK - if ((void **)__gc_stack_top + n >= s_top()) { + if (s_peek_unsafe() + n >= s_top()) { s_failure(&s, "not enough elements in stack"); } - if (s.fp != NULL && (void **)__gc_stack_top + n >= f_locals(s.fp)) { + if (s.fp != NULL && s_peek_unsafe() + n >= f_locals(s.fp)) { s_failure(&s, "not enough elements in function stack"); } #endif for (size_t i = 0; i < n; ++i) { - ((void **)__gc_stack_top)[i] = ((void **)__gc_stack_top)[i + 1]; + s_peek_unsafe()[i] = s_peek_unsafe()[i + 1]; } - ((void **)__gc_stack_top)[n] = val; + s_peek_unsafe()[n] = val; } static inline void s_rotate_n(size_t n) { #ifndef WITH_CHECK - if ((void **)__gc_stack_top + (aint)n - 1 >= s_top()) { + if (s_peek_unsafe() + (aint)n - 1 >= s_top()) { s_failure(&s, "not enough elements in stack"); } - if (s.fp != NULL && (void **)__gc_stack_top + (aint)n - 1 >= f_locals(s.fp)) { + if (s.fp != NULL && s_peek_unsafe() + (aint)n - 1 >= f_locals(s.fp)) { s_failure(&s, "not enough elements in function stack"); } #endif void *buf = NULL; for (size_t i = 0; 2 * i + 1 < n; ++i) { - buf = ((void **)__gc_stack_top)[n - i - 1]; - ((void **)__gc_stack_top)[n - i - 1] = ((void **)__gc_stack_top)[i]; - ((void **)__gc_stack_top)[i] = buf; + buf = s_peek_unsafe()[n - i - 1]; + s_peek_unsafe()[n - i - 1] = s_peek_unsafe()[i]; + s_peek_unsafe()[i] = buf; } } @@ -165,12 +170,11 @@ static inline void s_rotate_n(size_t n) { static inline void s_enter_f(char *rp, bool is_closure_call, auint args_sz, auint locals_sz) { // check that params count is valid - if ((void **)__gc_stack_top + (aint)args_sz - (is_closure_call ? 0 : 1) >= - s_top()) { + if (s_peek_unsafe() + (aint)args_sz - (is_closure_call ? 0 : 1) >= s_top()) { s_failure(&s, "not enough parameters in stack"); } if (s.fp != NULL && - (void **)__gc_stack_top + (aint)args_sz - (is_closure_call ? 0 : 1) >= + s_peek_unsafe() + (aint)args_sz - (is_closure_call ? 0 : 1) >= f_locals(s.fp)) { s_failure(&s, "not enough parameters in function stack"); } @@ -193,7 +197,7 @@ static inline void s_enter_f(char *rp, bool is_closure_call, auint args_sz, }; // put frame on stack - s.fp = (struct Frame *)__gc_stack_top; + s.fp = (struct Frame *)s_peek_unsafe(); (*s.fp) = frame; s_pushn_nil(locals_sz); @@ -209,7 +213,7 @@ static inline void s_exit_f() { struct Frame frame = *s.fp; // drop stack entities, locals, frame - size_t to_pop = f_args(s.fp) - (void **)__gc_stack_top; + size_t to_pop = f_args(s.fp) - s_peek_unsafe(); s.fp = (struct Frame *)f_prev_fp(&frame); s_popn(to_pop); @@ -229,11 +233,11 @@ static inline void s_exit_f() { } static inline void print_stack(struct State *state) { - printf("stack (%li) is\n[", - state->stack + STACK_SIZE - (void **)__gc_stack_top); - for (void **x = state->stack + STACK_SIZE - 1; x >= (void **)__gc_stack_top; - --x) { - printf("%li ", (long)UNBOX(*x)); + void **peek = s_peek_unsafe(); + printf("stack (%li) is\n[", state->stack + STACK_SIZE - peek); + for (void **x = state->stack + STACK_SIZE - 1; x > peek; --x) { + printf("(%li, ", (long)UNBOX(*x)); + printf("%p) ", *x); } printf("]\n"); } diff --git a/byterun/src/interpreter.c b/byterun/src/interpreter.c index 2375c20cf..4a091ffbd 100644 --- a/byterun/src/interpreter.c +++ b/byterun/src/interpreter.c @@ -327,7 +327,7 @@ void run_main(Bytefile* bf, int argc, char **argv) { s_enter_f(s.call_ip /*ip from call*/, s.is_closure_call, args_sz, locals_sz); #ifndef WITH_CHECK - if ((void **)__gc_stack_top + (aint)max_additional_stack_sz - 1 <= s.stack) { + if (s_peek_unsafe() + (aint)max_additional_stack_sz - 1 <= s.stack) { s_failure(&s, "stack overflow"); } #endif @@ -351,7 +351,7 @@ void run_main(Bytefile* bf, int argc, char **argv) { s_enter_f(s.call_ip /*ip from call*/, s.is_closure_call, args_sz, locals_sz); #ifndef WITH_CHECK - if ((void **)__gc_stack_top + (aint)max_additional_stack_sz - 1 <= s.stack) { + if (s_peek_unsafe() + (aint)max_additional_stack_sz - 1 <= s.stack) { s_failure(&s, "stack overflow"); } #endif @@ -383,7 +383,7 @@ void run_main(Bytefile* bf, int argc, char **argv) { s_rotate_n(args_count); s_push_i(BOX(call_offset)); - void *closure = Bclosure((aint *)__gc_stack_top, BOX(args_count)); + void *closure = Bclosure((aint *)s_peek(), BOX(args_count)); // printf("args is %li, count is %li\n", args_count, get_len(TO_DATA(closure))); s_popn(args_count + 1); diff --git a/byterun/src/module_manager.cpp b/byterun/src/module_manager.cpp index 8abbe8da6..37408627a 100644 --- a/byterun/src/module_manager.cpp +++ b/byterun/src/module_manager.cpp @@ -1,7 +1,6 @@ -#include extern "C" { -#include "interpreter.h" #include "module_manager.h" +#include "interpreter.h" #include "runtime_externs.h" #include "stack.h" #include "utils.h" @@ -10,7 +9,9 @@ extern "C" { #include "analyzer.hpp" #include "parser.hpp" +#include #include +#include #include #include #include diff --git a/byterun/src/types.c b/byterun/src/types.c index e2381ac11..4dbd38aa6 100644 --- a/byterun/src/types.c +++ b/byterun/src/types.c @@ -12,7 +12,7 @@ extern size_t __gc_stack_top, __gc_stack_bottom; // --- State --- void init_state(struct State* s, void** stack) { - __init(); // FIXME, disable gc + __init(); s->stack = stack; s->fp = NULL; @@ -28,7 +28,7 @@ void init_state(struct State* s, void** stack) { } __gc_stack_bottom = (size_t)(s->stack + STACK_SIZE); - __gc_stack_top = __gc_stack_bottom; + __gc_stack_top = __gc_stack_bottom - sizeof(void*); #ifdef DEBUG_VERSION printf("- state init done\n"); diff --git a/runtime/gc.h b/runtime/gc.h index 932a91609..2d47be8f7 100644 --- a/runtime/gc.h +++ b/runtime/gc.h @@ -37,7 +37,7 @@ #define SET_FORWARD_ADDRESS(x, addr) (x = ((x & 3) | ((ptrt)(addr)))) // if heap is full after gc shows in how many times it has to be extended #define EXTRA_ROOM_HEAP_COEFFICIENT 2 -#define MINIMUM_HEAP_CAPACITY (640000) +#define MINIMUM_HEAP_CAPACITY (16) #include #include