mirror of
https://github.com/janet-lang/janet
synced 2024-12-26 08:20:27 +00:00
More cleanup in vm.c
This commit is contained in:
parent
001917f8d9
commit
5afb00859a
127
src/core/vm.c
127
src/core/vm.c
@ -137,12 +137,20 @@ static void *op_lookup[255] = {
|
|||||||
#define vm_next() opcode = *pc & 0xFF; continue
|
#define vm_next() opcode = *pc & 0xFF; continue
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Commit and restore VM state before possible longjmp */
|
||||||
|
#define vm_commit() do { janet_stack_frame(stack)->pc = pc; } while (0)
|
||||||
|
#define vm_restore() do { \
|
||||||
|
stack = fiber->data + fiber->frame; \
|
||||||
|
pc = janet_stack_frame(stack)->pc; \
|
||||||
|
func = janet_stack_frame(stack)->func; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/* Next instruction variations */
|
/* Next instruction variations */
|
||||||
#define janet_maybe_collect() do {\
|
#define maybe_collect() do {\
|
||||||
if (janet_vm_next_collection >= janet_vm_gc_interval) janet_collect(); } while (0)
|
if (janet_vm_next_collection >= janet_vm_gc_interval) janet_collect(); } while (0)
|
||||||
#define vm_checkgc_next() janet_maybe_collect(); vm_next()
|
#define vm_checkgc_next() maybe_collect(); vm_next()
|
||||||
#define vm_pcnext() pc++; vm_next()
|
#define vm_pcnext() pc++; vm_next()
|
||||||
#define vm_checkgc_pcnext() janet_maybe_collect(); vm_pcnext()
|
#define vm_checkgc_pcnext() maybe_collect(); vm_pcnext()
|
||||||
|
|
||||||
/* Handle certain errors in main vm loop */
|
/* Handle certain errors in main vm loop */
|
||||||
#define vm_throw(e) do { retreg = janet_cstringv(e); goto vm_error; } while (0)
|
#define vm_throw(e) do { retreg = janet_cstringv(e); goto vm_error; } while (0)
|
||||||
@ -211,10 +219,11 @@ static void *op_lookup[255] = {
|
|||||||
/* Interpreter main loop */
|
/* Interpreter main loop */
|
||||||
static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
||||||
|
|
||||||
/* interpreter state */
|
/* Interpreter state */
|
||||||
register Janet *stack;
|
register Janet *stack;
|
||||||
register uint32_t *pc;
|
register uint32_t *pc;
|
||||||
register JanetFunction *func;
|
register JanetFunction *func;
|
||||||
|
vm_restore();
|
||||||
|
|
||||||
/* Keep in mind the garbage collector cannot see this value.
|
/* Keep in mind the garbage collector cannot see this value.
|
||||||
* Values stored here should be used immediately */
|
* Values stored here should be used immediately */
|
||||||
@ -226,23 +235,12 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
/* Signal to return when done */
|
/* Signal to return when done */
|
||||||
JanetSignal signal = JANET_SIGNAL_OK;
|
JanetSignal signal = JANET_SIGNAL_OK;
|
||||||
|
|
||||||
/* Setup fiber state */
|
/* Only should be hit if the fiber is either waiting for a child, or
|
||||||
stack = fiber->data + fiber->frame;
|
* waiting to be resumed. In those cases, use input and increment pc. We
|
||||||
pc = janet_stack_frame(stack)->pc;
|
* DO NOT use input when resuming a fiber that has been interrupted at a
|
||||||
func = janet_stack_frame(stack)->func;
|
* breakpoint. */
|
||||||
|
|
||||||
if (fiber->child) {
|
|
||||||
/* Check for child fiber. If there is a child, run child before self.
|
|
||||||
* This should only be hit when the current fiber is pending on a RESUME
|
|
||||||
* instruction. */
|
|
||||||
retreg = in;
|
|
||||||
goto vm_resume_child;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (janet_fiber_status(fiber) != JANET_STATUS_NEW &&
|
if (janet_fiber_status(fiber) != JANET_STATUS_NEW &&
|
||||||
((*pc & 0xFF) == JOP_SIGNAL)) {
|
((*pc & 0xFF) == JOP_SIGNAL || (*pc & 0xFF) == JOP_RESUME)) {
|
||||||
/* Only should be hit if child is waiting on a SIGNAL instruction */
|
|
||||||
/* If waiting for response to signal, use input and increment pc */
|
|
||||||
stack[A] = in;
|
stack[A] = in;
|
||||||
pc++;
|
pc++;
|
||||||
}
|
}
|
||||||
@ -568,7 +566,11 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
signal = JANET_SIGNAL_ERROR;
|
signal = JANET_SIGNAL_ERROR;
|
||||||
goto vm_exit;
|
goto vm_exit;
|
||||||
}
|
}
|
||||||
goto vm_return_cfunc;
|
janet_fiber_popframe(fiber);
|
||||||
|
if (fiber->frame == 0) goto vm_exit;
|
||||||
|
stack = fiber->data + fiber->frame;
|
||||||
|
stack[A] = retreg;
|
||||||
|
vm_checkgc_pcnext();
|
||||||
} else {
|
} else {
|
||||||
int status;
|
int status;
|
||||||
int32_t argn = fiber->stacktop - fiber->stackstart;
|
int32_t argn = fiber->stacktop - fiber->stackstart;
|
||||||
@ -624,7 +626,10 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
signal = JANET_SIGNAL_ERROR;
|
signal = JANET_SIGNAL_ERROR;
|
||||||
goto vm_exit;
|
goto vm_exit;
|
||||||
}
|
}
|
||||||
goto vm_return_cfunc_tail;
|
janet_fiber_popframe(fiber);
|
||||||
|
janet_fiber_popframe(fiber);
|
||||||
|
if (fiber->frame == 0) goto vm_exit;
|
||||||
|
goto vm_reset;
|
||||||
} else {
|
} else {
|
||||||
int status;
|
int status;
|
||||||
int32_t argn = fiber->stacktop - fiber->stackstart;
|
int32_t argn = fiber->stacktop - fiber->stackstart;
|
||||||
@ -663,11 +668,17 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
|
|
||||||
VM_OP(JOP_RESUME)
|
VM_OP(JOP_RESUME)
|
||||||
{
|
{
|
||||||
Janet fiberval = stack[B];
|
vm_assert_type(stack[B], JANET_FIBER);
|
||||||
vm_assert_type(fiberval, JANET_FIBER);
|
JanetFiber *child = janet_unwrap_fiber(stack[B]);
|
||||||
retreg = stack[C];
|
fiber->child = child;
|
||||||
fiber->child = janet_unwrap_fiber(fiberval);
|
JanetSignal sig = janet_continue(child, stack[C], &retreg);
|
||||||
goto vm_resume_child;
|
if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig))) {
|
||||||
|
signal = sig;
|
||||||
|
goto vm_exit;
|
||||||
|
}
|
||||||
|
fiber->child = NULL;
|
||||||
|
stack[A] = retreg;
|
||||||
|
vm_checkgc_pcnext();
|
||||||
}
|
}
|
||||||
|
|
||||||
VM_OP(JOP_SIGNAL)
|
VM_OP(JOP_SIGNAL)
|
||||||
@ -826,25 +837,6 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
vm_checkgc_pcnext();
|
vm_checkgc_pcnext();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return from c function. Simpler than returning from janet function */
|
|
||||||
vm_return_cfunc:
|
|
||||||
{
|
|
||||||
janet_fiber_popframe(fiber);
|
|
||||||
if (fiber->frame == 0) goto vm_exit;
|
|
||||||
stack = fiber->data + fiber->frame;
|
|
||||||
stack[A] = retreg;
|
|
||||||
vm_checkgc_pcnext();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return from a cfunction that is in tail position (pop 2 stack frames) */
|
|
||||||
vm_return_cfunc_tail:
|
|
||||||
{
|
|
||||||
janet_fiber_popframe(fiber);
|
|
||||||
janet_fiber_popframe(fiber);
|
|
||||||
if (fiber->frame == 0) goto vm_exit;
|
|
||||||
goto vm_reset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle returning from stack frame. Expect return value in retreg */
|
/* Handle returning from stack frame. Expect return value in retreg */
|
||||||
vm_return:
|
vm_return:
|
||||||
{
|
{
|
||||||
@ -878,31 +870,6 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
goto vm_exit;
|
goto vm_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resume a child fiber */
|
|
||||||
vm_resume_child:
|
|
||||||
{
|
|
||||||
JanetFiber *child = fiber->child;
|
|
||||||
JanetFiberStatus status = janet_fiber_status(child);
|
|
||||||
if (status == JANET_STATUS_ALIVE) vm_throw("cannot resume live fiber");
|
|
||||||
if (status == JANET_STATUS_DEAD) vm_throw("cannot resume dead fiber");
|
|
||||||
if (status == JANET_STATUS_ERROR) vm_throw("cannot resume errored fiber");
|
|
||||||
signal = janet_continue(child, retreg, &retreg);
|
|
||||||
if (signal != JANET_SIGNAL_OK) {
|
|
||||||
if (child->flags & (1 << signal)) {
|
|
||||||
/* Intercept signal */
|
|
||||||
signal = JANET_SIGNAL_OK;
|
|
||||||
fiber->child = NULL;
|
|
||||||
} else {
|
|
||||||
/* Propogate signal */
|
|
||||||
goto vm_exit;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fiber->child = NULL;
|
|
||||||
}
|
|
||||||
stack[A] = retreg;
|
|
||||||
vm_checkgc_pcnext();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle type errors. The found type is the type of retreg,
|
/* Handle type errors. The found type is the type of retreg,
|
||||||
* the expected types are in the expected_types field. */
|
* the expected types are in the expected_types field. */
|
||||||
vm_type_error:
|
vm_type_error:
|
||||||
@ -938,9 +905,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
/* Reset state of machine */
|
/* Reset state of machine */
|
||||||
vm_reset:
|
vm_reset:
|
||||||
{
|
{
|
||||||
stack = fiber->data + fiber->frame;
|
vm_restore();
|
||||||
func = janet_stack_frame(stack)->func;
|
|
||||||
pc = janet_stack_frame(stack)->pc;
|
|
||||||
stack[A] = retreg;
|
stack[A] = retreg;
|
||||||
vm_checkgc_pcnext();
|
vm_checkgc_pcnext();
|
||||||
}
|
}
|
||||||
@ -950,6 +915,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
|
|
||||||
/* Enter the main vm loop */
|
/* Enter the main vm loop */
|
||||||
JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out) {
|
JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out) {
|
||||||
|
|
||||||
/* Check conditions */
|
/* Check conditions */
|
||||||
if (janet_vm_stackn >= JANET_RECURSION_GUARD) {
|
if (janet_vm_stackn >= JANET_RECURSION_GUARD) {
|
||||||
janet_fiber_set_status(fiber, JANET_STATUS_ERROR);
|
janet_fiber_set_status(fiber, JANET_STATUS_ERROR);
|
||||||
@ -964,6 +930,19 @@ JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out) {
|
|||||||
return JANET_SIGNAL_ERROR;
|
return JANET_SIGNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Continue child fiber if it exists */
|
||||||
|
if (fiber->child) {
|
||||||
|
JanetFiber *child = fiber->child;
|
||||||
|
janet_vm_stackn++;
|
||||||
|
JanetSignal sig = janet_continue(child, in, &in);
|
||||||
|
janet_vm_stackn--;
|
||||||
|
if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig))) {
|
||||||
|
*out = in;
|
||||||
|
return sig;
|
||||||
|
}
|
||||||
|
fiber->child = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Prepare state */
|
/* Prepare state */
|
||||||
janet_vm_stackn++;
|
janet_vm_stackn++;
|
||||||
janet_gcroot(janet_wrap_fiber(fiber));
|
janet_gcroot(janet_wrap_fiber(fiber));
|
||||||
|
Loading…
Reference in New Issue
Block a user