Fix bug in vm_stack

This commit is contained in:
CismonX 2020-05-17 02:48:04 +08:00
parent a4d7098b3c
commit 5268372d8b
No known key found for this signature in database
GPG Key ID: 315D6652268C5007
2 changed files with 21 additions and 5 deletions

View File

@ -12,10 +12,10 @@ Load and execute Unlambda bytecode from the given \fIbytecode\-file\fR, or \fBST
.SH OPTIONS
.TP
\fB\-s\fR, \fB\-\-stack\-segment\-size\=\fIelem\-count\fR
Specify size of each stack segment of Unlambda VM to \fIelem\-count\fR.
Specify size of each stack segment of Unlambda VM to \fIelem\-count\fR. Default: 256.
.TP
\fB\-p\fR, \fB\-\-pool\-size\fR=\fIelem\-count\fR
Specify size of object pool of Unlambda VM to \fIelem\-count\fR.
Specify size of object pool of Unlambda VM to \fIelem\-count\fR. Deafult: 1048576.
.TP
\fB\-i\fR, \fB\-\-info\fR
Print info (version, segment size, etc.) corresponding to the \fIbytecode\-file\fR, then exit.

View File

@ -47,7 +47,7 @@ vm_stack_create(struct vm_stack* prev, uint32_t top) {
}
vs->prev = prev;
vs->top = top;
vs->refcnt = 1;
vs->refcnt = 0;
return vs;
}
@ -60,7 +60,7 @@ vm_stack_dup(struct vm_stack* vs) {
return NULL;
}
memcpy(dup_stack, vs, sizeof(struct vm_stack) + (vs->top + 1) * sizeof(struct u6a_vm_var_fn));
dup_stack->refcnt = 1;
dup_stack->refcnt = 0;
for (uint32_t idx = vs->top; idx < UINT32_MAX; --idx) {
struct u6a_vm_var_fn elem = vs->elems[idx];
if (elem.token.fn & U6A_VM_FN_REF) {
@ -199,7 +199,7 @@ u6a_vm_stack_push4(struct u6a_vm_var_fn v0, struct u6a_vm_var_fn v1, struct u6a_
U6A_HOT bool
u6a_vm_stack_pop() {
struct vm_stack* vs = active_stack;
if (LIKELY(vs->top-- < UINT32_MAX)) {
if (LIKELY(vs->top-- != UINT32_MAX)) {
return true;
}
active_stack = vs->prev;
@ -223,6 +223,22 @@ 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];
vs->elems[vs->top - 1] = v0;
return elem;