This commit is contained in:
CismonX 2020-02-05 02:47:45 +08:00
parent 9bbf4a3ec0
commit f0d9df747a
No known key found for this signature in database
GPG Key ID: 315D6652268C5007
5 changed files with 67 additions and 16 deletions

View File

@ -83,9 +83,6 @@ static const char* info_runtime = "runtime";
#define POOL_GET1(offset) \
u6a_vm_pool_get1(offset).fn; \
u6a_vm_pool_free(offset)
#define POOL_GET2(offset) \
u6a_vm_pool_get2(offset); \
u6a_vm_pool_free(offset)
static inline bool
read_bc_header(struct u6a_bc_header* restrict header, FILE* restrict input_stream) {
@ -108,6 +105,13 @@ read_bc_header(struct u6a_bc_header* restrict header, FILE* restrict input_strea
return true;
}
static inline void
vm_var_fn_addref(struct u6a_vm_var_fn var) {
if (var.token.fn & U6A_VM_FN_REF) {
u6a_vm_pool_addref(var.ref);
}
}
static inline void
vm_var_fn_free(struct u6a_vm_var_fn var) {
if (var.token.fn & U6A_VM_FN_REF) {
@ -221,16 +225,15 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) {
case u6a_vf_s1:
ACC_FN_REF(u6a_vf_s2, u6a_vm_pool_fill2(func.ref, arg));
break;
ACC_FN_REF(u6a_vf_d1_c, u6a_vm_pool_alloc1(arg));
case u6a_vf_s2:
if (ins++ - text == 0x03) {
STACK_PUSH3(arg, u6a_vm_pool_get2(func.ref));
} else {
STACK_PUSH4(U6A_VM_VAR_FN_REF(u6a_vf_j, ins - text), arg, u6a_vm_pool_get2(func.ref));
}
u6a_vm_pool_free(func.ref);
vm_var_fn_addref(arg);
ins = text;
goto do_apply;
continue;
case u6a_vf_k:
ACC_FN_REF(u6a_vf_k1, u6a_vm_pool_alloc1(arg));
break;
@ -271,8 +274,9 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) {
ACC_FN_REF(u6a_vf_d1_c, u6a_vm_pool_alloc1(arg));
break;
case u6a_vf_c1:
tuple = POOL_GET2(func.ref);
tuple = u6a_vm_pool_get2_separate(func.ref);
u6a_vm_stack_resume(tuple.v1.ptr);
u6a_vm_pool_free(func.ref);
ins = tuple.v2.ptr;
acc = arg;
break;
@ -280,7 +284,8 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) {
func = POOL_GET1(func.ref);
goto do_apply;
case u6a_vf_d1_s:
tuple = POOL_GET2(func.ref);
tuple = u6a_vm_pool_get2(func.ref);
u6a_vm_pool_free(func.ref);
STACK_PUSH1(tuple.v1.fn);
acc = tuple.v2.fn;
ins = text + 0x03;
@ -310,7 +315,7 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) {
case u6a_vf_pipe:
func = arg;
if (UNLIKELY(current_char == EOF)) {
arg.token.fn = u6a_vf_v;acc = u6a_vm_stack_xch(acc);
arg.token.fn = u6a_vf_v;
} else {
arg.token = U6A_TOKEN(u6a_vf_out, current_char);
}
@ -339,7 +344,7 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) {
break;
case u6a_vo_del:
delay:
STACK_PUSH1(U6A_VM_VAR_FN_REF(u6a_vf_d1_d, ins + 1 - text));
acc = U6A_VM_VAR_FN_REF(u6a_vf_d1_d, ins + 1 - text);
ins = text + text_subst_len + ins->operand.offset;
continue;
case u6a_vo_lc:

View File

@ -85,7 +85,7 @@ free_stack_pop() {
if (fstack_top == UINT32_MAX) {
return NULL;
}
return fstack[--fstack_top];
return fstack[fstack_top--];
}
bool
@ -176,6 +176,22 @@ u6a_vm_pool_get2(uint32_t offset) {
return (active_pool->elems + offset)->values;
}
U6A_HOT struct u6a_vm_var_tuple
u6a_vm_pool_get2_separate(uint32_t offset) {
struct vm_pool_elem* elem = active_pool->elems + offset;
struct u6a_vm_var_tuple values = elem->values;
if (elem->refcnt > 1) {
// Continuation having more than 1 reference should be separated before reinstatement
values.v1.ptr = u6a_vm_stack_dup(values.v1.ptr);
}
return values;
}
U6A_HOT void
u6a_vm_pool_addref(uint32_t offset) {
++active_pool->elems[offset].refcnt;
}
U6A_HOT void
u6a_vm_pool_free(uint32_t offset) {
struct vm_pool_elem* elem = active_pool->elems;

View File

@ -47,6 +47,12 @@ u6a_vm_pool_get1(uint32_t offset);
struct u6a_vm_var_tuple
u6a_vm_pool_get2(uint32_t offset);
struct u6a_vm_var_tuple
u6a_vm_pool_get2_separate(uint32_t offset);
void
u6a_vm_pool_addref(uint32_t offset);
void
u6a_vm_pool_free(uint32_t offset);

View File

@ -18,6 +18,7 @@
*/
#include "vm_stack.h"
#include "vm_pool.h"
#include <stddef.h>
#include <stdlib.h>
@ -47,8 +48,7 @@ vm_stack_create(struct vm_stack* prev, uint32_t top) {
}
static inline struct vm_stack*
vm_stack_dup() {
struct vm_stack* vs = active_stack;
vm_stack_dup(struct vm_stack* vs) {
const uint32_t size = sizeof(struct vm_stack) + stack_seg_len * sizeof(struct u6a_vm_var_fn);
struct vm_stack* dup_stack = malloc(size);
if (UNLIKELY(dup_stack == NULL)) {
@ -56,6 +56,15 @@ vm_stack_dup() {
}
memcpy(dup_stack, vs, sizeof(struct vm_stack) + (vs->top + 1) * sizeof(struct u6a_vm_var_fn));
dup_stack->refcnt = 1;
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) {
u6a_vm_pool_addref(elem.ref);
}
}
if (vs->prev) {
++vs->prev->refcnt;
}
return dup_stack;
}
@ -65,11 +74,18 @@ vm_stack_free(struct vm_stack* vs) {
do {
prev = vs->prev;
if (--vs->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) {
u6a_vm_pool_free(elem.ref);
}
}
free(vs);
vs = prev;
} else {
break;
}
} while (prev);
} while (vs);
}
bool
@ -186,7 +202,7 @@ u6a_vm_stack_pop() {
return false;
}
if (active_stack->refcnt-- > 1) {
active_stack = vm_stack_dup();
active_stack = vm_stack_dup(active_stack);
}
if (UNLIKELY(active_stack == NULL)) {
active_stack = vs;
@ -206,7 +222,12 @@ u6a_vm_stack_xch(struct u6a_vm_var_fn v0) {
void*
u6a_vm_stack_save() {
return vm_stack_dup();
return vm_stack_dup(active_stack);
}
void*
u6a_vm_stack_dup(void* ptr) {
return vm_stack_dup(ptr);
}
void

View File

@ -55,6 +55,9 @@ u6a_vm_stack_xch(struct u6a_vm_var_fn v1);
void*
u6a_vm_stack_save();
void*
u6a_vm_stack_dup(void* ptr);
void
u6a_vm_stack_resume(void* ptr);