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:
parent
e124029ae3
commit
a614816a04
@ -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,8 +790,7 @@ 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) {
|
||||||
dst_table_put(ret, dst_csymbolv("sourcepath"),
|
dst_table_put(ret, dst_csymbolv("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));
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
|
@ -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 = NULL;
|
||||||
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;
|
|
||||||
}
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -494,32 +494,63 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
VM_OP(DOP_PUSH)
|
VM_OP(DOP_PUSH)
|
||||||
dst_fiber_push(dst_vm_fiber, stack[oparg(1, 0xFFFFFF)]);
|
dst_fiber_push(dst_vm_fiber, stack[oparg(1, 0xFFFFFF)]);
|
||||||
pc++;
|
pc++;
|
||||||
stack = dst_vm_fiber->data + dst_vm_fiber->frame;
|
stack = dst_vm_fiber->data + dst_vm_fiber->frame;
|
||||||
vm_checkgc_next();
|
vm_checkgc_next();
|
||||||
|
|
||||||
VM_OP(DOP_PUSH_2)
|
VM_OP(DOP_PUSH_2)
|
||||||
dst_fiber_push2(dst_vm_fiber,
|
dst_fiber_push2(dst_vm_fiber,
|
||||||
stack[oparg(1, 0xFF)],
|
stack[oparg(1, 0xFF)],
|
||||||
stack[oparg(2, 0xFFFF)]);
|
stack[oparg(2, 0xFFFF)]);
|
||||||
pc++;
|
pc++;
|
||||||
stack = dst_vm_fiber->data + dst_vm_fiber->frame;
|
stack = dst_vm_fiber->data + dst_vm_fiber->frame;
|
||||||
vm_checkgc_next();
|
vm_checkgc_next();
|
||||||
|
|
||||||
VM_OP(DOP_PUSH_3)
|
VM_OP(DOP_PUSH_3)
|
||||||
dst_fiber_push3(dst_vm_fiber,
|
dst_fiber_push3(dst_vm_fiber,
|
||||||
stack[oparg(1, 0xFF)],
|
stack[oparg(1, 0xFF)],
|
||||||
stack[oparg(2, 0xFF)],
|
stack[oparg(2, 0xFF)],
|
||||||
stack[oparg(3, 0xFF)]);
|
stack[oparg(3, 0xFF)]);
|
||||||
pc++;
|
pc++;
|
||||||
stack = dst_vm_fiber->data + dst_vm_fiber->frame;
|
stack = dst_vm_fiber->data + dst_vm_fiber->frame;
|
||||||
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);
|
dst_fiber_reset(dst_vm_fiber);
|
||||||
} else {
|
} else {
|
||||||
dst_fiber_reset(dst_vm_fiber);
|
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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user