From 197e25132cafb63db52b9f8871e548b3b0d4f7eb Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 25 Jul 2022 22:32:26 +0200 Subject: [PATCH] Berry fix reference when exeception is raised --- lib/libesp32/berry/src/be_exec.c | 5 +++++ lib/libesp32/berry/src/be_exec.h | 1 + lib/libesp32/berry/tests/reference.be | 31 +++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 lib/libesp32/berry/tests/reference.be diff --git a/lib/libesp32/berry/src/be_exec.c b/lib/libesp32/berry/src/be_exec.c index 2278ab2fa..9be2793d7 100644 --- a/lib/libesp32/berry/src/be_exec.c +++ b/lib/libesp32/berry/src/be_exec.c @@ -61,6 +61,7 @@ struct pcall { struct vmstate { int top, reg, depth; + int refcount; }; struct strbuf { @@ -125,6 +126,7 @@ static void vm_state_save(bvm *vm, struct vmstate *state) state->depth = be_stack_count(&vm->callstack); state->top = cast_int(vm->top - vm->stack); state->reg = cast_int(vm->reg - vm->stack); + state->refcount = vm->refstack.count; } static void copy_exception(bvm *vm, int res, int dstindex) @@ -143,6 +145,7 @@ static void copy_exception(bvm *vm, int res, int dstindex) static void vm_state_restore(bvm *vm, const struct vmstate *state, int res) { vm->reg = vm->stack + state->reg; + be_vector_resize(vm, &vm->refstack, state->refcount); /* copy exception information to top */ copy_exception(vm, res, state->top); be_assert(be_stack_count(&vm->callstack) >= state->depth); @@ -444,6 +447,7 @@ void be_except_block_setup(bvm *vm) /* set longjmp() jump point */ frame->errjmp.status = 0; frame->errjmp.prev = vm->errjmp; /* save long jump list */ + frame->refcount = vm->refstack.count; /* save reference pointer */ vm->errjmp = &frame->errjmp; fixup_exceptstack(vm, lbase); } @@ -455,6 +459,7 @@ void be_except_block_resume(bvm *vm) struct bexecptframe *frame = be_stack_top(&vm->exceptstack); if (errorcode == BE_EXCEPTION) { vm->errjmp = vm->errjmp->prev; + be_vector_resize(vm, &vm->refstack, frame->refcount); /* jump to except instruction */ vm->ip = frame->ip + IGET_sBx(frame->ip[-1]); if (be_stack_count(&vm->callstack) > frame->depth) { diff --git a/lib/libesp32/berry/src/be_exec.h b/lib/libesp32/berry/src/be_exec.h index ffb85fa87..af10bf255 100644 --- a/lib/libesp32/berry/src/be_exec.h +++ b/lib/libesp32/berry/src/be_exec.h @@ -45,6 +45,7 @@ struct bexecptframe { struct blongjmp errjmp; /* long jump information */ int depth; /* function call stack depth */ binstruction *ip; /* instruction pointer */ + int refcount; /* save object reference stack */ }; void be_throw(bvm *vm, int errorcode); diff --git a/lib/libesp32/berry/tests/reference.be b/lib/libesp32/berry/tests/reference.be new file mode 100644 index 000000000..f63bab459 --- /dev/null +++ b/lib/libesp32/berry/tests/reference.be @@ -0,0 +1,31 @@ +# try to exercise bug in reference + +class failable + var fail # if 'true', tostring() raises an exception + + def tostring() + if self.fail + raise "internal_error", "FAIL" + return "FAIL" + else + return "SUCCESS" + end + end +end +f = failable() + +l1 = [1, 2, f] +l2 = ["foo", l1] +l1.push(l1) + +assert(str(l2) == "['foo', [1, 2, SUCCESS, [...]]]") +assert(str(l1) == "[1, 2, SUCCESS, [...]]") + +f.fail = true +try + print(str(l1)) +except .. +end + +f.fail = false +assert(str(l1) == "[1, 2, SUCCESS, [...]]") # FAILS