summaryrefslogtreecommitdiff
path: root/libguile/jit.c
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2019-06-18 21:40:55 +0200
committerAndy Wingo <wingo@pobox.com>2019-06-18 21:45:29 +0200
commitaf72d01de8c64776f550205c540f9678c5dda2e5 (patch)
tree9362039fb392c36e6e18ec8359bba769bb30a7b9 /libguile/jit.c
parente8203a3f8c34b0505fa0f914503348c1b85c74d3 (diff)
downloadguile-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.c50
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)
{