diff options
author | Andy Wingo <wingo@pobox.com> | 2019-06-18 21:40:55 +0200 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2019-06-18 21:45:29 +0200 |
commit | af72d01de8c64776f550205c540f9678c5dda2e5 (patch) | |
tree | 9362039fb392c36e6e18ec8359bba769bb30a7b9 /libguile/jit.c | |
parent | e8203a3f8c34b0505fa0f914503348c1b85c74d3 (diff) | |
download | guile-af72d01de8c64776f550205c540f9678c5dda2e5.tar.gz |
Speed up returns in JIT
This patch is a bit unfortunate, in the sense that it exposes some of
the JIT guts to the rest of the VM. Code needs to treat "machine return
addresses" as valid if non-NULL (as before) and also not equal to a
tier-down trampoline. This is because tier-down at a return needs the
old frame pointer to load the "virtual return address", and the way this
patch works is that it passes the vra in a well-known register. It's a
custom calling convention for a certain kind of return.
* libguile/jit.h (scm_jit_return_to_interpreter_trampoline): New
internal global.
* libguile/jit.c: (scm_jit_clear_mcode_return_addresses): Move here,
from vm.c. Instead of zeroing return addresses, set them to the
return-to-interpreter trampoline.
* libguile/vm-engine.c (return-values): Don't enter mcode if the mra is
scm_jit_return_to_interpreter_trampoline.
* libguile/vm.c (capture_continuation): Treat the tier-down trampoline
as NULL.
Diffstat (limited to 'libguile/jit.c')
-rw-r--r-- | libguile/jit.c | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/libguile/jit.c b/libguile/jit.c index 8e0781d22..a90b9b444 100644 --- a/libguile/jit.c +++ b/libguile/jit.c @@ -152,6 +152,10 @@ static void *exit_mcode; instruction, compiled as a stub on the side to reduce code size. */ static void *handle_interrupts_trampoline; +/* Return to interpreter trampoline: trampoline to load IP from the VRA + and tier down. */ +void *scm_jit_return_to_interpreter_trampoline; + /* Thread-local buffer into which to write code. */ struct code_arena { @@ -1590,28 +1594,32 @@ compile_shuffle_down (scm_jit_state *j, uint16_t from, uint16_t to) j->frame_size_max -= (from - to); } +static const jit_gpr_t old_fp_for_return_trampoline = T0; + static void compile_return_values (scm_jit_state *j) { - jit_gpr_t old_fp = T0, ra = T1; - jit_reloc_t interp; + jit_gpr_t ra = T1; - emit_pop_fp (j, old_fp); - - emit_load_mra (j, ra, old_fp); - interp = jit_beqi (j->jit, ra, 0); + emit_pop_fp (j, old_fp_for_return_trampoline); + emit_load_mra (j, ra, old_fp_for_return_trampoline); jit_jmpr (j->jit, ra); - jit_patch_here (j->jit, interp); - emit_load_vra (j, ra, old_fp); - emit_store_ip (j, ra); - emit_exit (j); - j->frame_size_min = 0; j->frame_size_max = INT32_MAX; } static void +emit_return_to_interpreter_trampoline (scm_jit_state *j) +{ + jit_gpr_t ra = T1; + + emit_load_vra (j, ra, old_fp_for_return_trampoline); + emit_store_ip (j, ra); + emit_exit (j); +} + +static void compile_subr_call (scm_jit_state *j, uint32_t idx) { jit_gpr_t t = T0, ret = T1; @@ -4688,6 +4696,10 @@ initialize_jit (void) handle_interrupts_trampoline = emit_code (j, emit_handle_interrupts_trampoline); ASSERT (handle_interrupts_trampoline); + + scm_jit_return_to_interpreter_trampoline = + emit_code (j, emit_return_to_interpreter_trampoline); + ASSERT (scm_jit_return_to_interpreter_trampoline); } static uint8_t * @@ -4804,10 +4816,26 @@ void scm_jit_enter_mcode (scm_thread *thread, const uint8_t *mcode) { LOG ("entering mcode: %p\n", mcode); + if (!SCM_FRAME_MACHINE_RETURN_ADDRESS (thread->vm.fp)) + SCM_FRAME_SET_MACHINE_RETURN_ADDRESS + (thread->vm.fp, scm_jit_return_to_interpreter_trampoline); enter_mcode (thread, mcode); LOG ("exited mcode\n"); } +/* Call to force a thread to go back to the interpreter, for example + when single-stepping is enabled. */ +void +scm_jit_clear_mcode_return_addresses (scm_thread *thread) +{ + union scm_vm_stack_element *fp; + struct scm_vm *vp = &thread->vm; + + for (fp = vp->fp; fp < vp->stack_top; fp = SCM_FRAME_DYNAMIC_LINK (fp)) + SCM_FRAME_SET_MACHINE_RETURN_ADDRESS + (fp, scm_jit_return_to_interpreter_trampoline); +} + void scm_jit_state_free (scm_jit_state *j) { |