mirror of
https://github.com/janet-lang/janet
synced 2024-11-25 01:37:19 +00:00
Work on marshaling fiber.
This commit is contained in:
parent
f5b4bc4fdf
commit
b8a6cd84c0
@ -186,7 +186,8 @@ recur:
|
|||||||
return;
|
return;
|
||||||
dst_gc_mark(fiber);
|
dst_gc_mark(fiber);
|
||||||
|
|
||||||
dst_mark_function(fiber->root);
|
if (fiber->root)
|
||||||
|
dst_mark_function(fiber->root);
|
||||||
|
|
||||||
i = fiber->frame;
|
i = fiber->frame;
|
||||||
j = fiber->stackstart - DST_FRAME_SIZE;
|
j = fiber->stackstart - DST_FRAME_SIZE;
|
||||||
|
149
src/core/marsh.c
149
src/core/marsh.c
@ -446,20 +446,22 @@ enum {
|
|||||||
UMR_EXPECTED_FIBER,
|
UMR_EXPECTED_FIBER,
|
||||||
UMR_EXPECTED_STRING,
|
UMR_EXPECTED_STRING,
|
||||||
UMR_INVALID_REFERENCE,
|
UMR_INVALID_REFERENCE,
|
||||||
UMR_INVALID_BYTECODE
|
UMR_INVALID_BYTECODE,
|
||||||
|
UMR_INVALID_FIBER
|
||||||
} UnmarshalResult;
|
} UnmarshalResult;
|
||||||
|
|
||||||
const char *umr_strings[] = {
|
const char *umr_strings[] = {
|
||||||
"",
|
"",
|
||||||
"stack overflow",
|
"stack overflow",
|
||||||
"unexpected end of source",
|
"unexpected end of source",
|
||||||
"unknown byte",
|
"unmarshal error",
|
||||||
"expected integer",
|
"expected integer",
|
||||||
"expected table",
|
"expected table",
|
||||||
"expected fiber",
|
"expected fiber",
|
||||||
"expected string",
|
"expected string",
|
||||||
"invalid reference",
|
"invalid reference",
|
||||||
"invalid bytecode"
|
"invalid bytecode",
|
||||||
|
"invalid fiber"
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Helper to read a 32 bit integer from an unmarshal state */
|
/* Helper to read a 32 bit integer from an unmarshal state */
|
||||||
@ -506,26 +508,31 @@ static const uint8_t *unmarshal_one_env(
|
|||||||
*out = st->lookup_envs[index];
|
*out = st->lookup_envs[index];
|
||||||
} else {
|
} else {
|
||||||
DstFuncEnv *env = dst_gcalloc(DST_MEMORY_FUNCENV, sizeof(DstFuncEnv));
|
DstFuncEnv *env = dst_gcalloc(DST_MEMORY_FUNCENV, sizeof(DstFuncEnv));
|
||||||
|
env->length = 0;
|
||||||
|
env->offset = 0;
|
||||||
dst_v_push(st->lookup_envs, env);
|
dst_v_push(st->lookup_envs, env);
|
||||||
env->offset = readint(st, &data);
|
int32_t offset = readint(st, &data);
|
||||||
env->length = readint(st, &data);
|
int32_t length = readint(st, &data);
|
||||||
if (env->offset) {
|
if (offset) {
|
||||||
/* On stack variant */
|
/* On stack variant */
|
||||||
Dst fiberv;
|
Dst fiberv;
|
||||||
data = unmarshal_one(st, data, &fiberv, flags);
|
data = unmarshal_one(st, data, &fiberv, flags);
|
||||||
if (!dst_checktype(fiberv, DST_FIBER)) longjmp(st->err, UMR_EXPECTED_FIBER);
|
if (!dst_checktype(fiberv, DST_FIBER)) longjmp(st->err, UMR_EXPECTED_FIBER);
|
||||||
env->as.fiber = dst_unwrap_fiber(fiberv);
|
env->as.fiber = dst_unwrap_fiber(fiberv);
|
||||||
|
/* Unmarshaling fiber may set values */
|
||||||
|
if (env->offset != 0 && env->offset != offset) longjmp(st->err, UMR_UNKNOWN);
|
||||||
|
if (env->length != 0 && env->length != length) longjmp(st->err, UMR_UNKNOWN);
|
||||||
} else {
|
} else {
|
||||||
/* Off stack variant */
|
/* Off stack variant */
|
||||||
env->as.values = malloc(sizeof(Dst) * env->length);
|
env->as.values = malloc(sizeof(Dst) * length);
|
||||||
if (!env->as.values) {
|
if (!env->as.values) {
|
||||||
DST_OUT_OF_MEMORY;
|
DST_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
for (int32_t i = 0; i < env->length; i++) {
|
for (int32_t i = 0; i < env->length; i++)
|
||||||
data = unmarshal_one(st, data, env->as.values + i, flags);
|
data = unmarshal_one(st, data, env->as.values + i, flags);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Set out */
|
env->offset = offset;
|
||||||
|
env->length = length;
|
||||||
*out = env;
|
*out = env;
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
@ -670,15 +677,129 @@ static const uint8_t *unmarshal_one_def(
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unmarshal a fiber */
|
||||||
static const uint8_t *unmarshal_one_fiber(
|
static const uint8_t *unmarshal_one_fiber(
|
||||||
UnmarshalState *st,
|
UnmarshalState *st,
|
||||||
const uint8_t *data,
|
const uint8_t *data,
|
||||||
DstFiber **out,
|
DstFiber **out,
|
||||||
int flags) {
|
int flags) {
|
||||||
longjmp(st->err, UMR_UNKNOWN);
|
|
||||||
(void) out;
|
/* Initialize a new fiber */
|
||||||
(void) flags;
|
DstFiber *fiber = dst_gcalloc(DST_MEMORY_FIBER, sizeof(DstFiber));
|
||||||
return data + 1;
|
fiber->flags = 0;
|
||||||
|
fiber->frame = 0;
|
||||||
|
fiber->stackstart = 0;
|
||||||
|
fiber->stacktop = 0;
|
||||||
|
fiber->capacity = 0;
|
||||||
|
fiber->root = NULL;
|
||||||
|
fiber->child = NULL;
|
||||||
|
|
||||||
|
/* Set frame later so fiber can be GCed at anytime if unmarshaling fails */
|
||||||
|
int32_t frame = 0;
|
||||||
|
int32_t stack = 0;
|
||||||
|
int32_t stacktop = 0;
|
||||||
|
|
||||||
|
/* Read ints */
|
||||||
|
fiber->flags = readint(st, &data);
|
||||||
|
frame = readint(st, &data);
|
||||||
|
fiber->stackstart = readint(st, &data);
|
||||||
|
fiber->stacktop = readint(st, &data);
|
||||||
|
fiber->maxstack = readint(st, &data);
|
||||||
|
|
||||||
|
/* Check for bad flags and ints */
|
||||||
|
if (frame + DST_FRAME_SIZE > fiber->stackstart ||
|
||||||
|
fiber->stackstart > fiber->stacktop ||
|
||||||
|
fiber->stacktop > fiber->capacity ||
|
||||||
|
fiber->stacktop > fiber->maxstack) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get root fuction */
|
||||||
|
Dst funcv;
|
||||||
|
data = dst_unmarshal_one(st, data, &funcv, flags + 1);
|
||||||
|
if (!dst_checktype(funcv, DST_FUNCTION)) goto error;
|
||||||
|
fiber->root = dst_unwrap_function(funcv);
|
||||||
|
|
||||||
|
/* Allocate stack memory */
|
||||||
|
fiber->capacity = fiber->stacktop + 10;
|
||||||
|
fiber->data = malloc(sizeof(Dst) * fiber->capacity);
|
||||||
|
if (!fiber->data) {
|
||||||
|
DST_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get frames */
|
||||||
|
stack = frame;
|
||||||
|
stacktop = fiber->stackstart - DST_FRAME_SIZE;
|
||||||
|
while (stack > 0) {
|
||||||
|
DstFunction *func;
|
||||||
|
DstFuncDef *def;
|
||||||
|
DstFuncEnv *env;
|
||||||
|
int32_t frameflags = readint(st, &data);
|
||||||
|
int32_t prevframe = readint(st, &data);
|
||||||
|
int32_t pcdiff = readint(st, &data);
|
||||||
|
|
||||||
|
/* Get frame items */
|
||||||
|
Dst *framestack = fiber->data + stack;
|
||||||
|
DstStackFrame *framep = (DstStackFrame *)framestack - 1;
|
||||||
|
|
||||||
|
/* Get function */
|
||||||
|
Dst funcv;
|
||||||
|
data = unmarshal_one(st, data, &funcv, flags + 1);
|
||||||
|
if (!dst_checktype(framefunc, DST_FUNCTION))
|
||||||
|
goto error;
|
||||||
|
func = dst_unwrap_function(funcv);
|
||||||
|
def = func->def;
|
||||||
|
|
||||||
|
/* Check env */
|
||||||
|
if (frameflags & DST_STACKFRAME_HASENV) {
|
||||||
|
frameflags &= ~DST_STACKFRAME_HASENV;
|
||||||
|
int32_t offset = stack;
|
||||||
|
int32_t length = stacktop - stack;
|
||||||
|
data = unmarshal_one_env(st, data, &env, flags + 1);
|
||||||
|
if (env->offset != 0 && env->offset != offset) goto error;
|
||||||
|
if (env->length != 0 && env->length != offset) goto error;
|
||||||
|
env->offset = offset;
|
||||||
|
env->length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error checking */
|
||||||
|
int32_t expected_framesize = def->arity + !!(def->flags & DST_FUNCDEF_FLAG_VARARG);
|
||||||
|
if (expected_framesize != stacktop - stack) goto error;
|
||||||
|
if (pcdiff < 0 || pcdiff >= def->bytecode_length) goto error;
|
||||||
|
if (prevframe + DST_FRAME_SIZE > stack) goto error;
|
||||||
|
|
||||||
|
/* Get stack items */
|
||||||
|
for (int32_t i = stack; i < stacktop; i++) {
|
||||||
|
data = dst_unmarshal_one(st, data, fiber->data + i, flags + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set frame */
|
||||||
|
framep->env = env;
|
||||||
|
framep->pc = def->bytecode + pcdiff;
|
||||||
|
framep->prevframe = prevframe;
|
||||||
|
framep->flags = frameflags;
|
||||||
|
framep->func = func;
|
||||||
|
|
||||||
|
/* Goto previous frame */
|
||||||
|
stacktop = stack - DST_FRAME_SIZE;
|
||||||
|
stack = prevframe;
|
||||||
|
}
|
||||||
|
if (stack < 0) goto error;
|
||||||
|
|
||||||
|
/* Check for child fiber */
|
||||||
|
if (fiber->flags & DST_FIBER_HAS_CHILD) {
|
||||||
|
fiber->flags &= ~DST_FIBER_FLAG_HASCHILD;
|
||||||
|
data = unmarshal_one_fiber(st, data, &(fiber->child), flags + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return data */
|
||||||
|
fiber->frame = frame;
|
||||||
|
*out = dst_wrap_fiber(fiber);
|
||||||
|
return data;
|
||||||
|
|
||||||
|
error:
|
||||||
|
longjmp(st->err, UMR_INVALID_FIBER);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t *unmarshal_one(
|
static const uint8_t *unmarshal_one(
|
||||||
|
Loading…
Reference in New Issue
Block a user