Fix bug in vm_stack

This commit is contained in:
CismonX 2020-05-17 03:23:47 +08:00
parent 5268372d8b
commit d6febd352a
No known key found for this signature in database
GPG Key ID: 315D6652268C5007
1 changed files with 23 additions and 13 deletions

View File

@ -214,7 +214,7 @@ u6a_vm_stack_pop() {
if (UNLIKELY(active_stack == NULL)) {
active_stack = vs;
return false;
};
}
free(vs);
--active_stack->top;
return true;
@ -223,24 +223,34 @@ u6a_vm_stack_pop() {
struct u6a_vm_var_fn
u6a_vm_stack_xch(struct u6a_vm_var_fn v0) {
struct vm_stack* vs = active_stack;
if (UNLIKELY(vs->top == UINT32_MAX)) {
active_stack = vs->prev;
if (UNLIKELY(active_stack == NULL)) {
active_stack = vs;
return (struct u6a_vm_var_fn) { 0 };
}
if (--active_stack->refcnt > 0) {
active_stack = vm_stack_dup(active_stack);
}
if (UNLIKELY(active_stack == NULL)) {
active_stack = vs;
return (struct u6a_vm_var_fn) { 0 };
};
free(vs);
vs = active_stack;
}
struct u6a_vm_var_fn elem = vs->elems[vs->top - 1];
struct u6a_vm_var_fn elem;
// XCH on segmented stacks is inefficient, perhaps there's a better solution?
if (LIKELY(vs->top != 0 && vs->top != UINT32_MAX)) {
elem = vs->elems[vs->top - 1];
vs->elems[vs->top - 1] = v0;
} else {
struct vm_stack* prev = vs->prev;
if (UNLIKELY(prev == NULL)) {
return (struct u6a_vm_var_fn) { 0 };
}
if (--prev->refcnt > 0) {
prev = vm_stack_dup(active_stack);
}
if (UNLIKELY(active_stack == NULL)) {
return (struct u6a_vm_var_fn) { 0 };
}
if (vs->top == 0) {
++prev->refcnt;
vs->prev = prev;
elem = prev->elems[prev->top];
prev->elems[prev->top] = v0;
} else {
free(vs);
active_stack = prev;
elem = prev->elems[prev->top - 1];
prev->elems[prev->top - 1] = v0;
}
}
return elem;
}