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) \ #define POOL_GET1(offset) \
u6a_vm_pool_get1(offset).fn; \ u6a_vm_pool_get1(offset).fn; \
u6a_vm_pool_free(offset) u6a_vm_pool_free(offset)
#define POOL_GET2(offset) \
u6a_vm_pool_get2(offset); \
u6a_vm_pool_free(offset)
static inline bool static inline bool
read_bc_header(struct u6a_bc_header* restrict header, FILE* restrict input_stream) { 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; 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 static inline void
vm_var_fn_free(struct u6a_vm_var_fn var) { vm_var_fn_free(struct u6a_vm_var_fn var) {
if (var.token.fn & U6A_VM_FN_REF) { 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: case u6a_vf_s1:
ACC_FN_REF(u6a_vf_s2, u6a_vm_pool_fill2(func.ref, arg)); ACC_FN_REF(u6a_vf_s2, u6a_vm_pool_fill2(func.ref, arg));
break; break;
ACC_FN_REF(u6a_vf_d1_c, u6a_vm_pool_alloc1(arg));
case u6a_vf_s2: case u6a_vf_s2:
if (ins++ - text == 0x03) { if (ins++ - text == 0x03) {
STACK_PUSH3(arg, u6a_vm_pool_get2(func.ref)); STACK_PUSH3(arg, u6a_vm_pool_get2(func.ref));
} else { } else {
STACK_PUSH4(U6A_VM_VAR_FN_REF(u6a_vf_j, ins - text), arg, u6a_vm_pool_get2(func.ref)); 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; ins = text;
goto do_apply; continue;
case u6a_vf_k: case u6a_vf_k:
ACC_FN_REF(u6a_vf_k1, u6a_vm_pool_alloc1(arg)); ACC_FN_REF(u6a_vf_k1, u6a_vm_pool_alloc1(arg));
break; 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)); ACC_FN_REF(u6a_vf_d1_c, u6a_vm_pool_alloc1(arg));
break; break;
case u6a_vf_c1: 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_stack_resume(tuple.v1.ptr);
u6a_vm_pool_free(func.ref);
ins = tuple.v2.ptr; ins = tuple.v2.ptr;
acc = arg; acc = arg;
break; break;
@ -280,7 +284,8 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) {
func = POOL_GET1(func.ref); func = POOL_GET1(func.ref);
goto do_apply; goto do_apply;
case u6a_vf_d1_s: 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); STACK_PUSH1(tuple.v1.fn);
acc = tuple.v2.fn; acc = tuple.v2.fn;
ins = text + 0x03; ins = text + 0x03;
@ -310,7 +315,7 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) {
case u6a_vf_pipe: case u6a_vf_pipe:
func = arg; func = arg;
if (UNLIKELY(current_char == EOF)) { if (UNLIKELY(current_char == EOF)) {
arg.token.fn = u6a_vf_v;acc = u6a_vm_stack_xch(acc); arg.token.fn = u6a_vf_v;
} else { } else {
arg.token = U6A_TOKEN(u6a_vf_out, current_char); arg.token = U6A_TOKEN(u6a_vf_out, current_char);
} }
@ -339,7 +344,7 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) {
break; break;
case u6a_vo_del: case u6a_vo_del:
delay: 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; ins = text + text_subst_len + ins->operand.offset;
continue; continue;
case u6a_vo_lc: case u6a_vo_lc:

View File

@ -85,7 +85,7 @@ free_stack_pop() {
if (fstack_top == UINT32_MAX) { if (fstack_top == UINT32_MAX) {
return NULL; return NULL;
} }
return fstack[--fstack_top]; return fstack[fstack_top--];
} }
bool bool
@ -176,6 +176,22 @@ u6a_vm_pool_get2(uint32_t offset) {
return (active_pool->elems + offset)->values; 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_HOT void
u6a_vm_pool_free(uint32_t offset) { u6a_vm_pool_free(uint32_t offset) {
struct vm_pool_elem* elem = active_pool->elems; 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 struct u6a_vm_var_tuple
u6a_vm_pool_get2(uint32_t offset); 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 void
u6a_vm_pool_free(uint32_t offset); u6a_vm_pool_free(uint32_t offset);

View File

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

View File

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