mirror of
https://github.com/janet-lang/janet
synced 2025-11-18 08:15:13 +00:00
When marshalling a closure, try to detach funcenvs
If possible, this will reduce the need to marshal fibers in many cases. Also add this logic to the GC so holding a closure that originally came from a fiber that crashed does not cause that fiber to hang around forever.
This commit is contained in:
@@ -230,6 +230,24 @@ static void janet_env_detach(JanetFuncEnv *env) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Detach a fiber from the env if the target fiber has stopped mutating */
|
||||||
|
void janet_env_maybe_detach(JanetFuncEnv *env) {
|
||||||
|
/* Check for detachable closure envs */
|
||||||
|
if (env->offset) {
|
||||||
|
JanetFiberStatus s = janet_fiber_status(env->as.fiber);
|
||||||
|
int isFinished = s == JANET_STATUS_DEAD ||
|
||||||
|
s == JANET_STATUS_ERROR ||
|
||||||
|
s == JANET_STATUS_USER0 ||
|
||||||
|
s == JANET_STATUS_USER1 ||
|
||||||
|
s == JANET_STATUS_USER2 ||
|
||||||
|
s == JANET_STATUS_USER3 ||
|
||||||
|
s == JANET_STATUS_USER4;
|
||||||
|
if (isFinished) {
|
||||||
|
janet_env_detach(env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a tail frame for a function */
|
/* Create a tail frame for a function */
|
||||||
int janet_fiber_funcframe_tail(JanetFiber *fiber, JanetFunction *func) {
|
int janet_fiber_funcframe_tail(JanetFiber *fiber, JanetFunction *func) {
|
||||||
int32_t i;
|
int32_t i;
|
||||||
|
|||||||
@@ -73,5 +73,6 @@ int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func);
|
|||||||
int janet_fiber_funcframe_tail(JanetFiber *fiber, JanetFunction *func);
|
int janet_fiber_funcframe_tail(JanetFiber *fiber, JanetFunction *func);
|
||||||
void janet_fiber_cframe(JanetFiber *fiber, JanetCFunction cfun);
|
void janet_fiber_cframe(JanetFiber *fiber, JanetCFunction cfun);
|
||||||
void janet_fiber_popframe(JanetFiber *fiber);
|
void janet_fiber_popframe(JanetFiber *fiber);
|
||||||
|
void janet_env_maybe_detach(JanetFuncEnv *env);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "symcache.h"
|
#include "symcache.h"
|
||||||
#include "gc.h"
|
#include "gc.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "fiber.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct JanetScratch {
|
struct JanetScratch {
|
||||||
@@ -189,6 +190,9 @@ static void janet_mark_funcenv(JanetFuncEnv *env) {
|
|||||||
if (janet_gc_reachable(env))
|
if (janet_gc_reachable(env))
|
||||||
return;
|
return;
|
||||||
janet_gc_mark(env);
|
janet_gc_mark(env);
|
||||||
|
/* If closure env references a dead fiber, we can just copy out the stack frame we need so
|
||||||
|
* we don't need to keep around the whole dead fiber. */
|
||||||
|
janet_env_maybe_detach(env);
|
||||||
if (env->offset) {
|
if (env->offset) {
|
||||||
/* On stack */
|
/* On stack */
|
||||||
janet_mark_fiber(env->as.fiber);
|
janet_mark_fiber(env->as.fiber);
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ static void marshal_one_env(MarshalState *st, JanetFuncEnv *env, int flags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
janet_v_push(st->seen_envs, env);
|
janet_v_push(st->seen_envs, env);
|
||||||
|
janet_env_maybe_detach(env);
|
||||||
pushint(st, env->offset);
|
pushint(st, env->offset);
|
||||||
pushint(st, env->length);
|
pushint(st, env->length);
|
||||||
if (env->offset) {
|
if (env->offset) {
|
||||||
|
|||||||
Reference in New Issue
Block a user