guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 03/03: Speed up returns in JIT


From: Andy Wingo
Subject: [Guile-commits] 03/03: Speed up returns in JIT
Date: Tue, 18 Jun 2019 15:51:56 -0400 (EDT)

wingo pushed a commit to branch master
in repository guile.

commit af72d01de8c64776f550205c540f9678c5dda2e5
Author: Andy Wingo <address@hidden>
Date:   Tue Jun 18 21:40:55 2019 +0200

    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.
---
 libguile/jit.c       | 50 +++++++++++++++++++++++++++++++++++++++-----------
 libguile/jit.h       |  5 ++++-
 libguile/vm-engine.c |  2 +-
 libguile/vm.c        | 19 +++++--------------
 4 files changed, 49 insertions(+), 27 deletions(-)

diff --git a/libguile/jit.c b/libguile/jit.c
index 8e0781d..a90b9b4 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)
 {
diff --git a/libguile/jit.h b/libguile/jit.h
index 365be07..455f9c7 100644
--- a/libguile/jit.h
+++ b/libguile/jit.h
@@ -1,7 +1,7 @@
 #ifndef SCM_JIT_H
 #define SCM_JIT_H
 
-/* Copyright 2018
+/* Copyright 2018-2019
      Free Software Foundation, Inc.
 
    This file is part of Guile.
@@ -62,6 +62,9 @@ SCM_INTERNAL void scm_jit_enter_mcode (scm_thread *thread,
                                        const uint8_t *mcode);
 SCM_INTERNAL void scm_jit_state_free (struct scm_jit_state *j);
 
+SCM_INTERNAL void *scm_jit_return_to_interpreter_trampoline;
+SCM_INTERNAL void scm_jit_clear_mcode_return_addresses (scm_thread *thread);
+
 SCM_INTERNAL void scm_init_jit (void);
 
 #endif  /* SCM_JIT_H */
diff --git a/libguile/vm-engine.c b/libguile/vm-engine.c
index 5596dab..469a31c 100644
--- a/libguile/vm-engine.c
+++ b/libguile/vm-engine.c
@@ -551,7 +551,7 @@ VM_NAME (scm_thread *thread)
       if (!VP->disable_mcode)
         {
           mcode = SCM_FRAME_MACHINE_RETURN_ADDRESS (old_fp);
-          if (mcode)
+          if (mcode && mcode != scm_jit_return_to_interpreter_trampoline)
             {
               scm_jit_enter_mcode (thread, mcode);
               CACHE_REGISTER ();
diff --git a/libguile/vm.c b/libguile/vm.c
index 82cdae9..d7b1788 100644
--- a/libguile/vm.c
+++ b/libguile/vm.c
@@ -199,18 +199,6 @@ scm_i_capture_current_stack (void)
                         0);
 }
 
-/* Call to force a thread to go back to the interpreter, for example
-   when single-stepping is enabled.  */
-static void
-vm_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, NULL);
-}
-
 #define FOR_EACH_HOOK(M) \
   M(apply) \
   M(return) \
@@ -242,7 +230,7 @@ vm_recompute_disable_mcode (scm_thread *thread)
 #undef DISABLE_MCODE_IF_HOOK_ENABLED
 
   if (thread->vm.disable_mcode && !was_disabled)
-    vm_clear_mcode_return_addresses (thread);
+    scm_jit_clear_mcode_return_addresses (thread);
 }
 
 static int
@@ -1163,11 +1151,14 @@ static SCM
 capture_continuation (scm_thread *thread)
 {
   struct scm_vm *vp = &thread->vm;
+  void *mra = SCM_FRAME_MACHINE_RETURN_ADDRESS (vp->fp);
+  if (mra == scm_jit_return_to_interpreter_trampoline)
+    mra = NULL;
   SCM vm_cont = capture_stack (vp->stack_top,
                                SCM_FRAME_DYNAMIC_LINK (vp->fp),
                                SCM_FRAME_PREVIOUS_SP (vp->fp),
                                SCM_FRAME_VIRTUAL_RETURN_ADDRESS (vp->fp),
-                               SCM_FRAME_MACHINE_RETURN_ADDRESS (vp->fp),
+                               mra,
                                scm_dynstack_capture_all (&thread->dynstack),
                                0);
   return scm_i_make_continuation (thread, vm_cont);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]