1
0
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:
Calvin Rose 2019-02-01 11:56:25 -05:00
parent 19e59705b9
commit 8a3f512746
5 changed files with 56 additions and 32 deletions

View File

@ -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);

View File

@ -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;
} }

View File

@ -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;

View File

@ -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);
@ -839,12 +854,13 @@ JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out) {
janet_gcunroot(janet_wrap_fiber(fiber)); janet_gcunroot(janet_wrap_fiber(fiber));
/* Restore global state */ /* Restore global state */
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;
} }

View File

@ -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;