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