Berry fix reference when exeception is raised

This commit is contained in:
Stephan Hadinger 2022-07-25 22:32:26 +02:00
parent a0d6670a5a
commit 197e25132c
3 changed files with 37 additions and 0 deletions

View File

@ -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) {

View File

@ -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);

View File

@ -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