diff --git a/man/u6a.1 b/man/u6a.1 index 7c0ec2c..3b497de 100644 --- a/man/u6a.1 +++ b/man/u6a.1 @@ -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. diff --git a/src/vm_stack.c b/src/vm_stack.c index 224375d..6dbb9fd 100644 --- a/src/vm_stack.c +++ b/src/vm_stack.c @@ -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;