From 18239d9ca3844cf63393842959fdc80b438b1be1 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 10 Apr 2022 22:28:22 +0200 Subject: [PATCH] Berry stack resize debug mode --- lib/libesp32/berry/default/berry_conf.h | 8 ++++++++ lib/libesp32/berry/src/be_exec.c | 16 +++++++++++++++- lib/libesp32/berry/src/be_vm.c | 9 +++++---- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/libesp32/berry/default/berry_conf.h b/lib/libesp32/berry/default/berry_conf.h index 43994b22d..84255936b 100644 --- a/lib/libesp32/berry/default/berry_conf.h +++ b/lib/libesp32/berry/default/berry_conf.h @@ -175,6 +175,14 @@ **/ #define BE_USE_DEBUG_GC 0 +/* Macro: BE_USE_DEBUG_STACK + * Enable Stack Resize debug mode. At each function call + * the stack is reallocated at a different memory location + * and the previous location is cleared with toxic data. + * Default: 0 + **/ +#define BE_USE_DEBUG_STACK 0 + /* Macro: BE_USE_MEM_ALIGNED * Some embedded processors have special memory areas * with read/write constraints of being aligned to 32 bits boundaries. diff --git a/lib/libesp32/berry/src/be_exec.c b/lib/libesp32/berry/src/be_exec.c index bdbeb0234..2278ab2fa 100644 --- a/lib/libesp32/berry/src/be_exec.c +++ b/lib/libesp32/berry/src/be_exec.c @@ -15,6 +15,7 @@ #include "be_bytecode.h" #include "be_decoder.h" #include +#include #if !BE_USE_SCRIPT_COMPILER && !BE_USE_BYTECODE_LOADER #error no compiler or bytecode loader enabled. @@ -337,9 +338,13 @@ void be_stackpush(bvm *vm) /* check that the stack is able to store `count` items, and increase stack if needed */ BERRY_API void be_stack_require(bvm *vm, int count) { +#if BE_USE_DEBUG_STACK == 0 if (vm->top + count >= vm->stacktop) { be_stack_expansion(vm, count); } +#else + be_stack_expansion(vm, vm->top - vm->stacktop + count); /* force exact resize each time */ +#endif } /* Scan the entire callstack and adjust all pointer by `offset` */ @@ -372,7 +377,16 @@ static void stack_resize(bvm *vm, size_t size) intptr_t offset; bvalue *old = vm->stack; /* save original pointer of stack before resize */ size_t os = (vm->stacktop - old) * sizeof(bvalue); /* size of current stack allocated in bytes */ +#if BE_USE_DEBUG_STACK == 0 vm->stack = be_realloc(vm, old, os, sizeof(bvalue) * size); /* reallocate with the new size */ +#else /* force a reallocation */ + size_t ns = sizeof(bvalue) * size; + vm->stack = be_malloc(vm, ns); + size_t transf = (os < ns) ? os : ns; /* min size */ + memmove(vm->stack, old, transf); /* copy to new location */ + memset(old, 0xFF, os); /* fill the structure with invalid pointers */ + be_free(vm, old, os); +#endif vm->stacktop = vm->stack + size; /* compute new stacktop */ offset = ptr_offset(vm->stack, old); /* compute the address difference between old and ne stack addresses */ /* update callframes */ @@ -386,7 +400,7 @@ static void stack_resize(bvm *vm, size_t size) /* Check if we are above the max allowed stack */ void be_stack_expansion(bvm *vm, int n) { - size_t size = vm->stacktop - vm->stack; + int size = vm->stacktop - vm->stack; /* with debug enabled, stack increase may be negative */ /* check new stack size */ if (size + n > BE_STACK_TOTAL_MAX) { /* ensure the stack is enough when generating error messages. */ diff --git a/lib/libesp32/berry/src/be_vm.c b/lib/libesp32/berry/src/be_vm.c index 1f6fe4586..c60d88c01 100644 --- a/lib/libesp32/berry/src/be_vm.c +++ b/lib/libesp32/berry/src/be_vm.c @@ -1207,11 +1207,12 @@ static void prep_closure(bvm *vm, int pos, int argc, int mode) for (v = vm->reg + argc; v <= end; ++v) { var_setnil(v); } + int v_offset = v - vm->stack; /* offset from stack base, stack may be reallocated */ if (proto->varg & BE_VA_VARARG) { /* there are vararg at the last argument, build the list */ /* code below uses mostly low-level calls for performance */ - be_stack_require(vm, argc + 2); /* make sure we don't overflow the stack */ - bvalue *top_save = vm->top; /* save original stack, we need fresh slots to create the 'list' instance */ - vm->top = v; /* move top of stack right after last argument */ + be_stack_require(vm, argc + 4); /* make sure we don't overflow the stack */ + int top_save_offset = vm->top - vm->stack; /* save original stack, we need fresh slots to create the 'list' instance */ + vm->top = vm->stack + v_offset; /* move top of stack right after last argument */ be_newobject(vm, "list"); /* this creates 2 objects on stack: list instance, BE_LIST object */ blist *list = var_toobj(vm->top-1); /* get low-level BE_LIST structure */ v = vm->reg + proto->argc - 1; /* last argument */ @@ -1219,7 +1220,7 @@ static void prep_closure(bvm *vm, int pos, int argc, int mode) be_list_push(vm, list, v); /* push all varargs into list */ } *(vm->reg + proto->argc - 1) = *(vm->top-2); /* change the vararg argument to now contain the list instance */ - vm->top = top_save; /* restore top of stack pointer */ + vm->top = vm->stack + top_save_offset; /* restore top of stack pointer */ } }