1
0
mirror of https://github.com/janet-lang/janet synced 2025-07-14 16:02:59 +00:00

Update func env representation to not store envs in function

objects.
This commit is contained in:
Calvin Rose 2018-02-12 16:43:59 -05:00
parent e124029ae3
commit a614816a04
10 changed files with 93 additions and 96 deletions

View File

@ -187,17 +187,19 @@ static int32_t dst_asm_addenv(DstAssembler *a, Dst envname) {
int32_t envindex; int32_t envindex;
int32_t res; int32_t res;
if (dst_equals(a->name, envname)) { if (dst_equals(a->name, envname)) {
return 0; return -1;
} }
/* Check for memoized value */ /* Check for memoized value */
check = dst_table_get(&a->envs, envname); check = dst_table_get(&a->envs, envname);
if (dst_checktype(check, DST_INTEGER)) return dst_unwrap_integer(check); if (dst_checktype(check, DST_INTEGER)) {
if (NULL == a->parent) return -1; return dst_unwrap_integer(check);
}
if (NULL == a->parent) return -2;
res = dst_asm_addenv(a->parent, envname); res = dst_asm_addenv(a->parent, envname);
if (res < 0) if (res < -1) {
return res; return res;
}
envindex = def->environments_length; envindex = def->environments_length;
if (envindex == 0) envindex = 1;
dst_table_put(&a->envs, envname, dst_wrap_integer(envindex)); dst_table_put(&a->envs, envname, dst_wrap_integer(envindex));
if (envindex >= a->environments_capacity) { if (envindex >= a->environments_capacity) {
int32_t newcap = 2 * envindex; int32_t newcap = 2 * envindex;
@ -291,7 +293,7 @@ static int32_t doarg_1(
if (argtype == DST_OAT_ENVIRONMENT && ret == -1) { if (argtype == DST_OAT_ENVIRONMENT && ret == -1) {
/* Add a new env */ /* Add a new env */
ret = dst_asm_addenv(a, x); ret = dst_asm_addenv(a, x);
if (ret < 0) { if (ret < -1) {
dst_asm_errorv(a, dst_formatc("unknown environment %q", x)); dst_asm_errorv(a, dst_formatc("unknown environment %q", x));
} }
} }
@ -788,7 +790,6 @@ Dst dst_disasm(DstFuncDef *def) {
DstArray *bcode = dst_array(def->bytecode_length); DstArray *bcode = dst_array(def->bytecode_length);
DstArray *constants; DstArray *constants;
DstTable *ret = dst_table(10); DstTable *ret = dst_table(10);
if (def->arity)
dst_table_put(ret, dst_csymbolv("arity"), dst_wrap_integer(def->arity)); dst_table_put(ret, dst_csymbolv("arity"), dst_wrap_integer(def->arity));
dst_table_put(ret, dst_csymbolv("bytecode"), dst_wrap_array(bcode)); dst_table_put(ret, dst_csymbolv("bytecode"), dst_wrap_array(bcode));
if (NULL != def->sourcepath) { if (NULL != def->sourcepath) {
@ -871,7 +872,7 @@ int dst_asm_cfun(DstArgs args) {
if (args.n < 1) return dst_throw(args, "expected assembly source"); if (args.n < 1) return dst_throw(args, "expected assembly source");
res = dst_asm(args.v[0], 0); res = dst_asm(args.v[0], 0);
if (res.status == DST_ASSEMBLE_OK) { if (res.status == DST_ASSEMBLE_OK) {
return dst_return(args, dst_wrap_function(dst_function(res.funcdef, NULL))); return dst_return(args, dst_wrap_function(dst_thunk(res.funcdef)));
} else { } else {
return dst_throwv(args, dst_wrap_string(res.error)); return dst_throwv(args, dst_wrap_string(res.error));
} }

View File

@ -132,7 +132,7 @@ int32_t dstc_lslotn(DstCompiler *c, int32_t max, int32_t nth) {
/* Free a slot */ /* Free a slot */
void dstc_freeslot(DstCompiler *c, DstSlot s) { void dstc_freeslot(DstCompiler *c, DstSlot s) {
if (s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF | DST_SLOT_NAMED)) return; if (s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF | DST_SLOT_NAMED)) return;
if (s.envindex > 0) return; if (s.envindex >= 0) return;
dstc_sfreei(c, s.index); dstc_sfreei(c, s.index);
} }
@ -208,7 +208,7 @@ void dstc_popscope(DstCompiler *c) {
/* Leave a scope but keep a slot allocated. */ /* Leave a scope but keep a slot allocated. */
void dstc_popscope_keepslot(DstCompiler *c, DstSlot retslot) { void dstc_popscope_keepslot(DstCompiler *c, DstSlot retslot) {
dstc_popscope(c); dstc_popscope(c);
if (retslot.envindex == 0 && retslot.index >= 0) { if (retslot.envindex < 0 && retslot.index >= 0) {
slotalloci(c, retslot.index); slotalloci(c, retslot.index);
} }
} }
@ -219,7 +219,7 @@ DstSlot dstc_cslot(Dst x) {
ret.flags = (1 << dst_type(x)) | DST_SLOT_CONSTANT; ret.flags = (1 << dst_type(x)) | DST_SLOT_CONSTANT;
ret.index = -1; ret.index = -1;
ret.constant = x; ret.constant = x;
ret.envindex = 0; ret.envindex = -1;
return ret; return ret;
} }
@ -285,7 +285,7 @@ DstSlot dstc_resolve(
/* Unused references and locals shouldn't add captured envs. */ /* Unused references and locals shouldn't add captured envs. */
if (unused || foundlocal) { if (unused || foundlocal) {
ret.envindex = 0; ret.envindex = -1;
return ret; return ret;
} }
@ -294,18 +294,17 @@ DstSlot dstc_resolve(
while (scope >= c->scopes && !(scope->flags & DST_SCOPE_FUNCTION)) scope--; while (scope >= c->scopes && !(scope->flags & DST_SCOPE_FUNCTION)) scope--;
dst_assert(scope >= c->scopes, "invalid scopes"); dst_assert(scope >= c->scopes, "invalid scopes");
scope->flags |= DST_SCOPE_ENV; scope->flags |= DST_SCOPE_ENV;
if (!dst_v_count(scope->envs)) dst_v_push(scope->envs, 0);
scope++; scope++;
/* Propogate env up to current scope */ /* Propogate env up to current scope */
int32_t envindex = 0; int32_t envindex = -1;
while (scope <= top) { while (scope <= top) {
if (scope->flags & DST_SCOPE_FUNCTION) { if (scope->flags & DST_SCOPE_FUNCTION) {
int32_t j, len; int32_t j, len;
int scopefound = 0; int scopefound = 0;
/* Check if scope already has env. If so, break */ /* Check if scope already has env. If so, break */
len = dst_v_count(scope->envs); len = dst_v_count(scope->envs);
for (j = 1; j < len; j++) { for (j = 0; j < len; j++) {
if (scope->envs[j] == envindex) { if (scope->envs[j] == envindex) {
scopefound = 1; scopefound = 1;
envindex = j; envindex = j;
@ -314,7 +313,6 @@ DstSlot dstc_resolve(
} }
/* Add the environment if it is not already referenced */ /* Add the environment if it is not already referenced */
if (!scopefound) { if (!scopefound) {
if (!dst_v_count(scope->envs)) dst_v_push(scope->envs, 0);
len = dst_v_count(scope->envs); len = dst_v_count(scope->envs);
dst_v_push(scope->envs, envindex); dst_v_push(scope->envs, envindex);
envindex = len; envindex = len;
@ -418,7 +416,7 @@ int32_t dstc_preread(
(ret << 8) | (ret << 8) |
DOP_GET_INDEX); DOP_GET_INDEX);
} }
} else if (s.envindex > 0 || s.index > max) { } else if (s.envindex >= 0 || s.index > max) {
ret = dstc_lslotn(c, max, nth); ret = dstc_lslotn(c, max, nth);
dstc_emit(c, ast, dstc_emit(c, ast,
((uint32_t)(s.index) << 24) | ((uint32_t)(s.index) << 24) |
@ -440,7 +438,7 @@ int32_t dstc_preread(
/* Call this to release a read handle after emitting the instruction. */ /* Call this to release a read handle after emitting the instruction. */
void dstc_postread(DstCompiler *c, DstSlot s, int32_t index) { void dstc_postread(DstCompiler *c, DstSlot s, int32_t index) {
if (index != s.index || s.envindex > 0 || s.flags & DST_SLOT_CONSTANT) { if (index != s.index || s.envindex >= 0 || s.flags & DST_SLOT_CONSTANT) {
/* We need to free the temporary slot */ /* We need to free the temporary slot */
dstc_sfreei(c, index); dstc_sfreei(c, index);
} }
@ -495,7 +493,7 @@ void dstc_copy(
/* far index */ /* far index */
/* If dest is a near index, do some optimization */ /* If dest is a near index, do some optimization */
if (dest.envindex == 0 && dest.index >= 0 && dest.index <= 0xFF) { if (dest.envindex < 0 && dest.index >= 0 && dest.index <= 0xFF) {
if (src.flags & DST_SLOT_CONSTANT) { if (src.flags & DST_SLOT_CONSTANT) {
dstc_loadconst(c, ast, src.constant, dest.index); dstc_loadconst(c, ast, src.constant, dest.index);
} else if (src.flags & DST_SLOT_REF) { } else if (src.flags & DST_SLOT_REF) {
@ -504,7 +502,7 @@ void dstc_copy(
(dest.index << 16) | (dest.index << 16) |
(dest.index << 8) | (dest.index << 8) |
DOP_GET_INDEX); DOP_GET_INDEX);
} else if (src.envindex > 0) { } else if (src.envindex >= 0) {
dstc_emit(c, ast, dstc_emit(c, ast,
(src.index << 24) | (src.index << 24) |
(src.envindex << 16) | (src.envindex << 16) |
@ -533,7 +531,7 @@ void dstc_copy(
(dstc_const(c, ast, dest.constant) << 16) | (dstc_const(c, ast, dest.constant) << 16) |
(reflocal << 8) | (reflocal << 8) |
DOP_LOAD_CONSTANT); DOP_LOAD_CONSTANT);
} else if (dest.envindex > 0) { } else if (dest.envindex >= 0) {
writeback = 2; writeback = 2;
destlocal = srclocal; destlocal = srclocal;
} else if (dest.index > 0xFF) { } else if (dest.index > 0xFF) {
@ -597,11 +595,11 @@ DstSlot dstc_return(DstCompiler *c, DstAst *ast, DstSlot s) {
DstSlot dstc_gettarget(DstFopts opts) { DstSlot dstc_gettarget(DstFopts opts) {
DstSlot slot; DstSlot slot;
if ((opts.flags & DST_FOPTS_HINT) && if ((opts.flags & DST_FOPTS_HINT) &&
(opts.hint.envindex == 0) && (opts.hint.envindex < 0) &&
(opts.hint.index >= 0 && opts.hint.index <= 0xFF)) { (opts.hint.index >= 0 && opts.hint.index <= 0xFF)) {
slot = opts.hint; slot = opts.hint;
} else { } else {
slot.envindex = 0; slot.envindex = -1;
slot.constant = dst_wrap_nil(); slot.constant = dst_wrap_nil();
slot.flags = 0; slot.flags = 0;
slot.index = dstc_lslotn(opts.compiler, 0xFF, 4); slot.index = dstc_lslotn(opts.compiler, 0xFF, 4);
@ -883,7 +881,7 @@ DstFuncDef *dstc_pop_funcdef(DstCompiler *c) {
/* Copy envs */ /* Copy envs */
def->environments_length = dst_v_count(scope.envs); def->environments_length = dst_v_count(scope.envs);
if (def->environments_length > 1) def->environments = dst_v_flatten(scope.envs); def->environments = dst_v_flatten(scope.envs);
def->constants_length = dst_v_count(scope.consts); def->constants_length = dst_v_count(scope.consts);
def->constants = dst_v_flatten(scope.consts); def->constants = dst_v_flatten(scope.consts);
@ -926,9 +924,6 @@ DstFuncDef *dstc_pop_funcdef(DstCompiler *c) {
def->flags = 0; def->flags = 0;
if (scope.flags & DST_SCOPE_ENV) { if (scope.flags & DST_SCOPE_ENV) {
def->flags |= DST_FUNCDEF_FLAG_NEEDSENV; def->flags |= DST_FUNCDEF_FLAG_NEEDSENV;
if (def->environments_length == 0) {
def->environments_length = 1;
}
} }
/* Pop the scope */ /* Pop the scope */
@ -1001,7 +996,7 @@ int dst_compile_cfun(DstArgs args) {
env = dst_unwrap_table(args.v[1]); env = dst_unwrap_table(args.v[1]);
res = dst_compile(args.v[0], env, 0); res = dst_compile(args.v[0], env, 0);
if (res.status == DST_COMPILE_OK) { if (res.status == DST_COMPILE_OK) {
DstFunction *fun = dst_function(res.funcdef, NULL); DstFunction *fun = dst_thunk(res.funcdef);
return dst_return(args, dst_wrap_function(fun)); return dst_return(args, dst_wrap_function(fun));
} else { } else {
t = dst_table(2); t = dst_table(2);

View File

@ -40,7 +40,7 @@ int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len) {
Dst form = dst_parser_produce(&parser); Dst form = dst_parser_produce(&parser);
DstCompileResult cres = dst_compile(form, env, 0); DstCompileResult cres = dst_compile(form, env, 0);
if (cres.status == DST_COMPILE_OK) { if (cres.status == DST_COMPILE_OK) {
DstFunction *f = dst_function(cres.funcdef, NULL); DstFunction *f = dst_thunk(cres.funcdef);
Dst ret; Dst ret;
if (dst_run(dst_wrap_function(f), &ret)) { if (dst_run(dst_wrap_function(f), &ret)) {
printf("internal runtime error: %s\n", (const char *) dst_to_string(ret)); printf("internal runtime error: %s\n", (const char *) dst_to_string(ret));

View File

@ -90,7 +90,7 @@ static void destructure(DstCompiler *c, Dst left, DstSlot right,
dstc_postread(c, islot, locali); dstc_postread(c, islot, locali);
} }
newright.index = localsub; newright.index = localsub;
newright.envindex = 0; newright.envindex = -1;
newright.constant = dst_wrap_nil(); newright.constant = dst_wrap_nil();
newright.flags = DST_SLOTTYPE_ANY; newright.flags = DST_SLOTTYPE_ANY;
/* Traverse into the structure */ /* Traverse into the structure */
@ -120,7 +120,7 @@ static void destructure(DstCompiler *c, Dst left, DstSlot right,
DOP_GET); DOP_GET);
dstc_postread(c, kslot, localk); dstc_postread(c, kslot, localk);
newright.index = localsub; newright.index = localsub;
newright.envindex = 0; newright.envindex = -1;
newright.constant = dst_wrap_nil(); newright.constant = dst_wrap_nil();
newright.flags = DST_SLOTTYPE_ANY; newright.flags = DST_SLOTTYPE_ANY;
/* Traverse into the structure */ /* Traverse into the structure */
@ -197,7 +197,7 @@ static DstSlot dohead(DstCompiler *c, DstFopts opts, DstAst *ast, Dst *head, int
static DstSlot namelocal(DstCompiler *c, DstAst *ast, Dst head, int32_t flags, DstSlot ret) { static DstSlot namelocal(DstCompiler *c, DstAst *ast, Dst head, int32_t flags, DstSlot ret) {
/* Non root scope, bring to local slot */ /* Non root scope, bring to local slot */
if (ret.flags & DST_SLOT_NAMED || if (ret.flags & DST_SLOT_NAMED ||
ret.envindex != 0 || ret.envindex >= 0 ||
ret.index < 0 || ret.index < 0 ||
ret.index > 0xFF) { ret.index > 0xFF) {
/* Slot is not able to be named */ /* Slot is not able to be named */
@ -205,7 +205,7 @@ static DstSlot namelocal(DstCompiler *c, DstAst *ast, Dst head, int32_t flags, D
localslot.index = dstc_lsloti(c); localslot.index = dstc_lsloti(c);
/* infer type? */ /* infer type? */
localslot.flags = flags; localslot.flags = flags;
localslot.envindex = 0; localslot.envindex = -1;
localslot.constant = dst_wrap_nil(); localslot.constant = dst_wrap_nil();
dstc_copy(c, ast, localslot, ret); dstc_copy(c, ast, localslot, ret);
ret = localslot; ret = localslot;
@ -546,7 +546,7 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
continue; continue;
} }
slot.flags = DST_SLOT_NAMED; slot.flags = DST_SLOT_NAMED;
slot.envindex = 0; slot.envindex = -1;
slot.constant = dst_wrap_nil(); slot.constant = dst_wrap_nil();
slot.index = dstc_lsloti(c); slot.index = dstc_lsloti(c);
dstc_nameslot(c, dst_unwrap_symbol(param), slot); dstc_nameslot(c, dst_unwrap_symbol(param), slot);
@ -564,7 +564,7 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
/* Check for self ref */ /* Check for self ref */
if (selfref) { if (selfref) {
DstSlot slot; DstSlot slot;
slot.envindex = 0; slot.envindex = -1;
slot.flags = DST_SLOT_NAMED | DST_FUNCTION; slot.flags = DST_SLOT_NAMED | DST_FUNCTION;
slot.constant = dst_wrap_nil(); slot.constant = dst_wrap_nil();
slot.index = dstc_lsloti(c); slot.index = dstc_lsloti(c);

View File

@ -221,26 +221,11 @@ DstFuncDef *dst_funcdef_alloc() {
return def; return def;
} }
/* Create a closure from a funcdef and a parent function */ /* Create a simple closure from a funcdef */
DstFunction *dst_function(DstFuncDef *def, DstFunction *parent) { DstFunction *dst_thunk(DstFuncDef *def) {
int32_t i;
DstFunction *func = dst_gcalloc(DST_MEMORY_FUNCTION, sizeof(DstFunction)); DstFunction *func = dst_gcalloc(DST_MEMORY_FUNCTION, sizeof(DstFunction));
int32_t elen = def->environments_length;
func->def = def; func->def = def;
if (elen) {
func->envs = malloc(sizeof(DstFuncEnv *) * elen);
if (elen > 1 && !parent) return NULL;
if (NULL == func->envs) {
DST_OUT_OF_MEMORY;
}
func->envs[0] = NULL;
} else {
func->envs = NULL; func->envs = NULL;
}
for (i = 1; i < def->environments_length; ++i) {
int32_t inherit = def->environments[i];
func->envs[i] = parent->envs[inherit];
}
return func; return func;
} }
@ -256,5 +241,5 @@ DstFunction *dst_quick_asm(int32_t arity, int varargs, int32_t slots, const uint
DST_OUT_OF_MEMORY; DST_OUT_OF_MEMORY;
} }
memcpy(def->bytecode, bytecode, bytecode_size); memcpy(def->bytecode, bytecode, bytecode_size);
return dst_function(def, NULL); return dst_thunk(def);
} }

View File

@ -101,19 +101,6 @@ void dst_fiber_pushn(DstFiber *fiber, const Dst *arr, int32_t n) {
fiber->stacktop = newtop; fiber->stacktop = newtop;
} }
/* Help set up function */
static void funcframe_env(DstFiber *fiber, DstFunction *func) {
/* Check closure env */
if (func->def->flags & DST_FUNCDEF_FLAG_NEEDSENV) {
/* Delayed capture of current stack frame */
DstFuncEnv *env = dst_gcalloc(DST_MEMORY_FUNCENV, sizeof(DstFuncEnv));
env->offset = fiber->frame;
env->as.fiber = fiber;
env->length = func->def->slotcount;
func->envs[0] = env;
}
}
/* Push a stack frame to a fiber */ /* Push a stack frame to a fiber */
void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func) { void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func) {
DstStackFrame *newframe; DstStackFrame *newframe;
@ -140,6 +127,7 @@ void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func) {
newframe->prevframe = oldframe; newframe->prevframe = oldframe;
newframe->pc = func->def->bytecode; newframe->pc = func->def->bytecode;
newframe->func = func; newframe->func = func;
newframe->env = NULL;
/* Check varargs */ /* Check varargs */
if (func->def->flags & DST_FUNCDEF_FLAG_VARARG) { if (func->def->flags & DST_FUNCDEF_FLAG_VARARG) {
@ -152,17 +140,13 @@ void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func) {
oldtop - tuplehead)); oldtop - tuplehead));
} }
} }
/* Check env */
funcframe_env(fiber, func) ;
} }
/* If a frame has a closure environment, detach it from /* If a frame has a closure environment, detach it from
* the stack and have it keep its own values */ * the stack and have it keep its own values */
static void dst_function_detach(DstFunction *func) { static void dst_env_detach(DstFuncEnv *env) {
/* Check for closure environment */ /* Check for closure environment */
if (NULL != func->envs && NULL != func->envs[0]) { if (env) {
DstFuncEnv *env = func->envs[0];
size_t s = sizeof(Dst) * env->length; size_t s = sizeof(Dst) * env->length;
Dst *vmem = malloc(s); Dst *vmem = malloc(s);
if (NULL == vmem) { if (NULL == vmem) {
@ -190,7 +174,8 @@ void dst_fiber_funcframe_tail(DstFiber *fiber, DstFunction *func) {
/* Detatch old function */ /* Detatch old function */
if (NULL != dst_fiber_frame(fiber)->func) if (NULL != dst_fiber_frame(fiber)->func)
dst_function_detach(dst_fiber_frame(fiber)->func); dst_env_detach(dst_fiber_frame(fiber)->env);
dst_fiber_frame(fiber)->env = NULL;
/* Check varargs */ /* Check varargs */
if (func->def->flags & DST_FUNCDEF_FLAG_VARARG) { if (func->def->flags & DST_FUNCDEF_FLAG_VARARG) {
@ -218,9 +203,6 @@ void dst_fiber_funcframe_tail(DstFiber *fiber, DstFunction *func) {
/* Set stack stuff */ /* Set stack stuff */
fiber->stacktop = fiber->stackstart = nextstacktop; fiber->stacktop = fiber->stackstart = nextstacktop;
/* Varargs and func envs */
funcframe_env(fiber, func);
/* Set frame stuff */ /* Set frame stuff */
dst_fiber_frame(fiber)->func = func; dst_fiber_frame(fiber)->func = func;
dst_fiber_frame(fiber)->pc = func->def->bytecode; dst_fiber_frame(fiber)->pc = func->def->bytecode;
@ -257,7 +239,7 @@ void dst_fiber_popframe(DstFiber *fiber) {
/* Clean up the frame (detach environments) */ /* Clean up the frame (detach environments) */
if (NULL != frame->func) if (NULL != frame->func)
dst_function_detach(frame->func); dst_env_detach(frame->env);
/* Shrink stack */ /* Shrink stack */
fiber->stacktop = fiber->stackstart = fiber->frame; fiber->stacktop = fiber->stackstart = fiber->frame;

View File

@ -186,6 +186,8 @@ static void dst_mark_fiber(DstFiber *fiber) {
frame = (DstStackFrame *)(fiber->data + i - DST_FRAME_SIZE); frame = (DstStackFrame *)(fiber->data + i - DST_FRAME_SIZE);
if (NULL != frame->func) if (NULL != frame->func)
dst_mark_function(frame->func); dst_mark_function(frame->func);
if (NULL != frame->env)
dst_mark_funcenv(frame->env);
/* Mark all values in the stack frame */ /* Mark all values in the stack frame */
dst_mark_many(fiber->data + i, j - i); dst_mark_many(fiber->data + i, j - i);
j = i - DST_FRAME_SIZE; j = i - DST_FRAME_SIZE;

View File

@ -494,9 +494,40 @@ static void *op_lookup[255] = {
VM_OP(DOP_CLOSURE) VM_OP(DOP_CLOSURE)
{ {
DstFuncDef *fd; DstFuncDef *fd;
DstFunction *fn;
vm_assert((int32_t)oparg(2, 0xFFFF) < func->def->defs_length, "invalid funcdef"); vm_assert((int32_t)oparg(2, 0xFFFF) < func->def->defs_length, "invalid funcdef");
fd = func->def->defs[(int32_t)oparg(2, 0xFFFF)]; fd = func->def->defs[(int32_t)oparg(2, 0xFFFF)];
stack[oparg(1, 0xFF)] = dst_wrap_function(dst_function(fd, func)); fn = dst_thunk(fd);
{
int32_t elen = fd->environments_length;
if (elen) {
int32_t i;
fn->envs = malloc(sizeof(DstFuncEnv *) * elen);
if (NULL == fn->envs) {
DST_OUT_OF_MEMORY;
}
for (i = 0; i < elen; ++i) {
int32_t inherit = fd->environments[i];
if (inherit == -1) {
DstStackFrame *frame = (DstStackFrame *)stack - 1;
if (!frame->env) {
/* Lazy capture of current stack frame */
DstFuncEnv *env = dst_gcalloc(DST_MEMORY_FUNCENV, sizeof(DstFuncEnv));
env->offset = dst_vm_fiber->frame;
env->as.fiber = dst_vm_fiber;
env->length = func->def->slotcount;
frame->env = env;
}
fn->envs[i] = frame->env;
} else {
fn->envs[i] = func->envs[inherit];
}
}
} else {
fn->envs = NULL;
}
}
stack[oparg(1, 0xFF)] = dst_wrap_function(fn);
pc++; pc++;
vm_checkgc_next(); vm_checkgc_next();
} }
@ -743,10 +774,10 @@ static void *op_lookup[255] = {
/* Run the vm with a given function. This function is /* Run the vm with a given function. This function is
* called to start the vm. */ * called to start the vm. */
int dst_run(Dst callee, Dst *returnreg) { int dst_run(Dst callee, Dst *returnreg) {
if (NULL == dst_vm_fiber) { if (dst_vm_fiber) {
dst_vm_fiber = dst_fiber(0);
} else {
dst_fiber_reset(dst_vm_fiber); dst_fiber_reset(dst_vm_fiber);
} else {
dst_vm_fiber = dst_fiber(64);
} }
if (dst_checktype(callee, DST_CFUNCTION)) { if (dst_checktype(callee, DST_CFUNCTION)) {
DstArgs args; DstArgs args;
@ -772,7 +803,7 @@ int dst_call(Dst callee, Dst *returnreg, int32_t argn, const Dst *argv) {
int lock; int lock;
DstFiber *oldfiber = dst_vm_fiber; DstFiber *oldfiber = dst_vm_fiber;
lock = dst_vm_gc_suspend++; lock = dst_vm_gc_suspend++;
dst_vm_fiber = dst_fiber(0); dst_vm_fiber = dst_fiber(64);
dst_fiber_pushn(dst_vm_fiber, argv, argn); dst_fiber_pushn(dst_vm_fiber, argv, argn);
if (dst_checktype(callee, DST_CFUNCTION)) { if (dst_checktype(callee, DST_CFUNCTION)) {
DstArgs args; DstArgs args;

View File

@ -172,7 +172,7 @@ int dst_gcunrootall(Dst root);
/* Functions */ /* Functions */
DstFuncDef *dst_funcdef_alloc(void); DstFuncDef *dst_funcdef_alloc(void);
DstFunction *dst_function(DstFuncDef *def, DstFunction *parent); DstFunction *dst_thunk(DstFuncDef *def);
int dst_verify(DstFuncDef *def); int dst_verify(DstFuncDef *def);
DstFunction *dst_quick_asm(int32_t arity, int varargs, int32_t slots, const uint32_t *bytecode, size_t bytecode_size); DstFunction *dst_quick_asm(int32_t arity, int varargs, int32_t slots, const uint32_t *bytecode, size_t bytecode_size);

View File

@ -328,6 +328,7 @@ struct DstStackFrame {
DstFunction *func; DstFunction *func;
uint32_t *pc; uint32_t *pc;
int32_t prevframe; int32_t prevframe;
DstFuncEnv *env;
}; };
/* Number of Dsts a frame takes up in the stack */ /* Number of Dsts a frame takes up in the stack */