mirror of
https://github.com/janet-lang/janet
synced 2024-11-28 11:09:54 +00:00
Experimental changes to janet_call to make it faster.
Remove setjmp and fiber creationg from janet_call. This adds the constraint to janet_call can only be called when there is already a current fiber.
This commit is contained in:
parent
19e59705b9
commit
8a3f512746
@ -27,9 +27,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void janet_panicv(Janet message) {
|
void janet_panicv(Janet message) {
|
||||||
if (janet_vm_fiber != NULL) {
|
if (janet_vm_return_reg != NULL) {
|
||||||
janet_fiber_push(janet_vm_fiber, message);
|
*janet_vm_return_reg = message;
|
||||||
longjmp(janet_vm_fiber->buf, 1);
|
longjmp(*janet_vm_jmp_buf, 1);
|
||||||
} else {
|
} else {
|
||||||
fputs((const char *)janet_formatc("janet top level panic - %v\n", message), stdout);
|
fputs((const char *)janet_formatc("janet top level panic - %v\n", message), stdout);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -66,6 +66,7 @@ JanetFiber *janet_fiber_reset(JanetFiber *fiber, JanetFunction *callee, int32_t
|
|||||||
fiber->stacktop = newstacktop;
|
fiber->stacktop = newstacktop;
|
||||||
}
|
}
|
||||||
if (janet_fiber_funcframe(fiber, callee)) return NULL;
|
if (janet_fiber_funcframe(fiber, callee)) return NULL;
|
||||||
|
janet_fiber_frame(fiber)->flags |= JANET_STACKFRAME_ENTRANCE;
|
||||||
return fiber;
|
return fiber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,11 @@ extern JANET_THREAD_LOCAL int janet_vm_stackn;
|
|||||||
* Set and unset by janet_run. */
|
* Set and unset by janet_run. */
|
||||||
extern JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber;
|
extern JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber;
|
||||||
|
|
||||||
|
/* The current pointer to the inner most jmp_buf. The current
|
||||||
|
* return point for panics. */
|
||||||
|
extern JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf;
|
||||||
|
extern JANET_THREAD_LOCAL Janet *janet_vm_return_reg;
|
||||||
|
|
||||||
/* The global registry for c functions. Used to store meta-data
|
/* The global registry for c functions. Used to store meta-data
|
||||||
* along with otherwise bare c function pointers. */
|
* along with otherwise bare c function pointers. */
|
||||||
extern JANET_THREAD_LOCAL JanetTable *janet_vm_registry;
|
extern JANET_THREAD_LOCAL JanetTable *janet_vm_registry;
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
JANET_THREAD_LOCAL JanetTable *janet_vm_registry;
|
JANET_THREAD_LOCAL JanetTable *janet_vm_registry;
|
||||||
JANET_THREAD_LOCAL int janet_vm_stackn = 0;
|
JANET_THREAD_LOCAL int janet_vm_stackn = 0;
|
||||||
JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber = NULL;
|
JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber = NULL;
|
||||||
|
JANET_THREAD_LOCAL Janet *janet_vm_return_reg = NULL;
|
||||||
|
JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
|
||||||
|
|
||||||
/* Virtual registers
|
/* Virtual registers
|
||||||
*
|
*
|
||||||
@ -148,7 +150,7 @@ static void *op_lookup[255] = {
|
|||||||
} while (0)
|
} while (0)
|
||||||
#define vm_return(sig, val) do { \
|
#define vm_return(sig, val) do { \
|
||||||
vm_commit(); \
|
vm_commit(); \
|
||||||
janet_fiber_push(fiber, (val)); \
|
janet_vm_return_reg[0] = (val); \
|
||||||
return (sig); \
|
return (sig); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -283,8 +285,9 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
|||||||
VM_OP(JOP_RETURN)
|
VM_OP(JOP_RETURN)
|
||||||
{
|
{
|
||||||
Janet retval = stack[D];
|
Janet retval = stack[D];
|
||||||
|
int entrance_frame = janet_stack_frame(stack)->flags & JANET_STACKFRAME_ENTRANCE;
|
||||||
janet_fiber_popframe(fiber);
|
janet_fiber_popframe(fiber);
|
||||||
if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, retval);
|
if (entrance_frame) vm_return(JANET_SIGNAL_OK, retval);
|
||||||
vm_restore();
|
vm_restore();
|
||||||
stack[A] = retval;
|
stack[A] = retval;
|
||||||
vm_checkgc_pcnext();
|
vm_checkgc_pcnext();
|
||||||
@ -293,8 +296,9 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
|||||||
VM_OP(JOP_RETURN_NIL)
|
VM_OP(JOP_RETURN_NIL)
|
||||||
{
|
{
|
||||||
Janet retval = janet_wrap_nil();
|
Janet retval = janet_wrap_nil();
|
||||||
|
int entrance_frame = janet_stack_frame(stack)->flags & JANET_STACKFRAME_ENTRANCE;
|
||||||
janet_fiber_popframe(fiber);
|
janet_fiber_popframe(fiber);
|
||||||
if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, retval);
|
if (entrance_frame) vm_return(JANET_SIGNAL_OK, retval);
|
||||||
vm_restore();
|
vm_restore();
|
||||||
stack[A] = retval;
|
stack[A] = retval;
|
||||||
vm_checkgc_pcnext();
|
vm_checkgc_pcnext();
|
||||||
@ -581,7 +585,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
|||||||
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
|
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
|
||||||
Janet ret = janet_unwrap_cfunction(callee)(argc, fiber->data + fiber->frame);
|
Janet ret = janet_unwrap_cfunction(callee)(argc, fiber->data + fiber->frame);
|
||||||
janet_fiber_popframe(fiber);
|
janet_fiber_popframe(fiber);
|
||||||
if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, ret);
|
/*if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, ret);*/
|
||||||
stack = fiber->data + fiber->frame;
|
stack = fiber->data + fiber->frame;
|
||||||
stack[A] = ret;
|
stack[A] = ret;
|
||||||
vm_checkgc_pcnext();
|
vm_checkgc_pcnext();
|
||||||
@ -614,6 +618,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
|||||||
vm_checkgc_next();
|
vm_checkgc_next();
|
||||||
} else {
|
} else {
|
||||||
Janet retreg;
|
Janet retreg;
|
||||||
|
int entrance_frame = janet_stack_frame(stack)->flags & JANET_STACKFRAME_ENTRANCE;
|
||||||
vm_commit();
|
vm_commit();
|
||||||
if (janet_checktype(callee, JANET_CFUNCTION)) {
|
if (janet_checktype(callee, JANET_CFUNCTION)) {
|
||||||
int32_t argc = fiber->stacktop - fiber->stackstart;
|
int32_t argc = fiber->stacktop - fiber->stackstart;
|
||||||
@ -624,7 +629,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
|||||||
retreg = call_nonfn(fiber, callee);
|
retreg = call_nonfn(fiber, callee);
|
||||||
}
|
}
|
||||||
janet_fiber_popframe(fiber);
|
janet_fiber_popframe(fiber);
|
||||||
if (fiber->frame == 0)
|
if (entrance_frame)
|
||||||
vm_return(JANET_SIGNAL_OK, retreg);
|
vm_return(JANET_SIGNAL_OK, retreg);
|
||||||
vm_restore();
|
vm_restore();
|
||||||
stack[A] = retreg;
|
stack[A] = retreg;
|
||||||
@ -755,39 +760,45 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
|
Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
|
||||||
|
Janet ret;
|
||||||
|
Janet *old_return_reg = janet_vm_return_reg;
|
||||||
|
|
||||||
|
/* Check entry conditions */
|
||||||
|
if (!janet_vm_fiber)
|
||||||
|
janet_panic("janet_call failed because there is no current fiber");
|
||||||
if (janet_vm_stackn >= JANET_RECURSION_GUARD)
|
if (janet_vm_stackn >= JANET_RECURSION_GUARD)
|
||||||
janet_panic("C stack recursed too deeply");
|
janet_panic("C stack recursed too deeply");
|
||||||
JanetFiber *fiber = janet_fiber(fun, 64, argc, argv);
|
|
||||||
if (!fiber)
|
/* Push frame */
|
||||||
janet_panic("arity mismatch");
|
janet_fiber_pushn(janet_vm_fiber, argv, argc);
|
||||||
JanetFiber *old_fiber = janet_vm_fiber;
|
if (janet_fiber_funcframe(janet_vm_fiber, fun)) {
|
||||||
janet_vm_fiber = fiber;
|
janet_panicf("arity mismatch in %v", fun);
|
||||||
janet_gcroot(janet_wrap_fiber(fiber));
|
}
|
||||||
|
janet_fiber_frame(janet_vm_fiber)->flags |= JANET_STACKFRAME_ENTRANCE;
|
||||||
|
|
||||||
|
/* Set up */
|
||||||
int32_t oldn = janet_vm_stackn++;
|
int32_t oldn = janet_vm_stackn++;
|
||||||
int handle = janet_gclock();
|
int handle = janet_gclock();
|
||||||
|
janet_vm_return_reg = &ret;
|
||||||
|
|
||||||
JanetSignal signal;
|
/* Run vm */
|
||||||
if (setjmp(fiber->buf)) {
|
JanetSignal signal = run_vm(janet_vm_fiber,
|
||||||
signal = JANET_SIGNAL_ERROR;
|
janet_wrap_nil(),
|
||||||
} else {
|
JANET_STATUS_ALIVE);
|
||||||
signal = run_vm(fiber, janet_wrap_nil(), JANET_STATUS_NEW);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Teardown */
|
||||||
|
janet_vm_return_reg = old_return_reg;
|
||||||
janet_vm_stackn = oldn;
|
janet_vm_stackn = oldn;
|
||||||
janet_vm_fiber = old_fiber;
|
|
||||||
Janet ret = fiber->data[fiber->stacktop - 1];
|
|
||||||
janet_gcunroot(janet_wrap_fiber(fiber));
|
|
||||||
janet_gcunlock(handle);
|
janet_gcunlock(handle);
|
||||||
if (signal == JANET_SIGNAL_ERROR) {
|
|
||||||
old_fiber->child = fiber;
|
if (signal != JANET_SIGNAL_OK) janet_panicv(ret);
|
||||||
janet_fiber_set_status(fiber, signal);
|
|
||||||
janet_panicv(ret);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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) {
|
||||||
|
jmp_buf buf;
|
||||||
|
|
||||||
/* Check conditions */
|
/* Check conditions */
|
||||||
JanetFiberStatus old_status = janet_fiber_status(fiber);
|
JanetFiberStatus old_status = janet_fiber_status(fiber);
|
||||||
@ -820,15 +831,19 @@ JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out) {
|
|||||||
int32_t oldn = janet_vm_stackn++;
|
int32_t oldn = janet_vm_stackn++;
|
||||||
int handle = janet_vm_gc_suspend;
|
int handle = janet_vm_gc_suspend;
|
||||||
JanetFiber *old_vm_fiber = janet_vm_fiber;
|
JanetFiber *old_vm_fiber = janet_vm_fiber;
|
||||||
|
jmp_buf *old_vm_jmp_buf = janet_vm_jmp_buf;
|
||||||
|
Janet *old_vm_return_reg = janet_vm_return_reg;
|
||||||
|
|
||||||
/* Setup fiber */
|
/* Setup fiber */
|
||||||
janet_vm_fiber = fiber;
|
janet_vm_fiber = fiber;
|
||||||
janet_gcroot(janet_wrap_fiber(fiber));
|
janet_gcroot(janet_wrap_fiber(fiber));
|
||||||
janet_fiber_set_status(fiber, JANET_STATUS_ALIVE);
|
janet_fiber_set_status(fiber, JANET_STATUS_ALIVE);
|
||||||
|
janet_vm_return_reg = out;
|
||||||
|
janet_vm_jmp_buf = &buf;
|
||||||
|
|
||||||
/* Run loop */
|
/* Run loop */
|
||||||
JanetSignal signal;
|
JanetSignal signal;
|
||||||
if (setjmp(fiber->buf)) {
|
if (setjmp(buf)) {
|
||||||
signal = JANET_SIGNAL_ERROR;
|
signal = JANET_SIGNAL_ERROR;
|
||||||
} else {
|
} else {
|
||||||
signal = run_vm(fiber, in, old_status);
|
signal = run_vm(fiber, in, old_status);
|
||||||
@ -842,9 +857,10 @@ JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out) {
|
|||||||
janet_vm_gc_suspend = handle;
|
janet_vm_gc_suspend = handle;
|
||||||
janet_vm_fiber = old_vm_fiber;
|
janet_vm_fiber = old_vm_fiber;
|
||||||
janet_vm_stackn = oldn;
|
janet_vm_stackn = oldn;
|
||||||
|
janet_vm_return_reg = old_vm_return_reg;
|
||||||
|
janet_vm_jmp_buf = old_vm_jmp_buf;
|
||||||
|
|
||||||
/* Pop error or return value from fiber stack */
|
/* Pop error or return value from fiber stack */
|
||||||
*out = fiber->data[--fiber->stacktop];
|
|
||||||
|
|
||||||
return signal;
|
return signal;
|
||||||
}
|
}
|
||||||
|
@ -603,12 +603,14 @@ struct JanetFiber {
|
|||||||
int32_t capacity;
|
int32_t capacity;
|
||||||
int32_t maxstack; /* Arbitrary defined limit for stack overflow */
|
int32_t maxstack; /* Arbitrary defined limit for stack overflow */
|
||||||
int32_t flags; /* Various flags */
|
int32_t flags; /* Various flags */
|
||||||
jmp_buf buf; /* Handle errors */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Mark if a stack frame is a tail call for debugging */
|
/* Mark if a stack frame is a tail call for debugging */
|
||||||
#define JANET_STACKFRAME_TAILCALL 1
|
#define JANET_STACKFRAME_TAILCALL 1
|
||||||
|
|
||||||
|
/* Mark if a stack frame is an entrance frame */
|
||||||
|
#define JANET_STACKFRAME_ENTRANCE 2
|
||||||
|
|
||||||
/* A stack frame on the fiber. Is stored along with the stack values. */
|
/* A stack frame on the fiber. Is stored along with the stack values. */
|
||||||
struct JanetStackFrame {
|
struct JanetStackFrame {
|
||||||
JanetFunction *func;
|
JanetFunction *func;
|
||||||
|
Loading…
Reference in New Issue
Block a user