guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] 02/02: Explicit interrupt handling in VM


From: Andy Wingo
Subject: [Guile-commits] 02/02: Explicit interrupt handling in VM
Date: Thu, 17 Nov 2016 21:20:10 +0000 (UTC)

wingo pushed a commit to branch master
in repository guile.

commit 4985ef13e68c83adf3e83f2c981205806ed9b621
Author: Andy Wingo <address@hidden>
Date:   Thu Nov 17 22:13:53 2016 +0100

    Explicit interrupt handling in VM
    
    * libguile/foreign.c (CODE, get_foreign_stub_code): Add explicit
      handle-interrupts and return-values calls, as foreign-call will fall
      through.
    * libguile/gsubr.c (A, B, C, AB, AC, BC, ABC, SUBR_STUB_CODE)
      (scm_i_primitive_call_ip): Same.
    * libguile/vm-engine.c (VM_HANDLE_INTERRUPTS): Inline into
      handle-interrupts.
      (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Inline into callers, and fall
      through instead of returning.
      (BR_BINARY, BR_UNARY, BR_ARITHMETIC, BR_U64_ARITHMETIC): Remove
      conditional VM_HANDLE_INTERRUPTS, as the compiler already inserted the
      handle-interrupts calls if needed.
      (vm_engine): Remove VM_HANDLE_INTERRUPTS invocations except in the
      handle-interrupts instruction.
---
 libguile/foreign.c   |    6 ++-
 libguile/gsubr.c     |   26 ++++++++--
 libguile/vm-engine.c |  133 +++++++++++++++++---------------------------------
 3 files changed, 70 insertions(+), 95 deletions(-)

diff --git a/libguile/foreign.c b/libguile/foreign.c
index 0992ef4..17a3eed 100644
--- a/libguile/foreign.c
+++ b/libguile/foreign.c
@@ -767,7 +767,9 @@ SCM_DEFINE (scm_pointer_to_procedure, "pointer->procedure", 
3, 0, 0,
 
 #define CODE(nreq)                                                  \
   SCM_PACK_OP_24 (assert_nargs_ee, nreq + 1),                       \
-  SCM_PACK_OP_12_12 (foreign_call, 0, 1)
+  SCM_PACK_OP_12_12 (foreign_call, 0, 1),                           \
+  SCM_PACK_OP_24 (handle_interrupts, 0),                            \
+  SCM_PACK_OP_24 (return_values, 0)
 
 #define CODE_10(n)                                                      \
   CODE (n + 0), CODE (n + 1), CODE (n + 2), CODE (n + 3), CODE (n + 4), \
@@ -789,7 +791,7 @@ get_foreign_stub_code (unsigned int nargs)
     scm_misc_error ("make-foreign-function", "args >= 100 currently 
unimplemented",
                     SCM_EOL);
 
-  return &foreign_stub_code[nargs * 2];
+  return &foreign_stub_code[nargs * 4];
 }
 
 static SCM
diff --git a/libguile/gsubr.c b/libguile/gsubr.c
index b456b22..e22d163 100644
--- a/libguile/gsubr.c
+++ b/libguile/gsubr.c
@@ -75,6 +75,8 @@
 #define A(nreq)                                                         \
   SCM_PACK_OP_24 (assert_nargs_ee, nreq + 1),                           \
   SCM_PACK_OP_24 (subr_call, 0),                                        \
+  SCM_PACK_OP_24 (handle_interrupts, 0),                                \
+  SCM_PACK_OP_24 (return_values, 0),                                    \
   0,                                                                    \
   0
 
@@ -82,11 +84,15 @@
   SCM_PACK_OP_24 (assert_nargs_le, nopt + 1),                           \
   SCM_PACK_OP_24 (alloc_frame, nopt + 1),                               \
   SCM_PACK_OP_24 (subr_call, 0),                                        \
+  SCM_PACK_OP_24 (handle_interrupts, 0),                                \
+  SCM_PACK_OP_24 (return_values, 0),                                    \
   0
 
 #define C()                                                             \
   SCM_PACK_OP_24 (bind_rest, 1),                                        \
   SCM_PACK_OP_24 (subr_call, 0),                                        \
+  SCM_PACK_OP_24 (handle_interrupts, 0),                                \
+  SCM_PACK_OP_24 (return_values, 0),                                    \
   0,                                                                    \
   0
 
@@ -94,17 +100,23 @@
   SCM_PACK_OP_24 (assert_nargs_ge, nreq + 1),                           \
   SCM_PACK_OP_24 (assert_nargs_le, nreq + nopt + 1),                    \
   SCM_PACK_OP_24 (alloc_frame, nreq + nopt + 1),                        \
-  SCM_PACK_OP_24 (subr_call, 0)
+  SCM_PACK_OP_24 (subr_call, 0),                                        \
+  SCM_PACK_OP_24 (handle_interrupts, 0),                                \
+  SCM_PACK_OP_24 (return_values, 0)
 
 #define AC(nreq)                                                        \
   SCM_PACK_OP_24 (assert_nargs_ge, nreq + 1),                           \
   SCM_PACK_OP_24 (bind_rest, nreq + 1),                                 \
   SCM_PACK_OP_24 (subr_call, 0),                                        \
+  SCM_PACK_OP_24 (handle_interrupts, 0),                                \
+  SCM_PACK_OP_24 (return_values, 0),                                    \
   0
 
 #define BC(nopt)                                                        \
   SCM_PACK_OP_24 (bind_rest, nopt + 1),                                 \
   SCM_PACK_OP_24 (subr_call, 0),                                        \
+  SCM_PACK_OP_24 (handle_interrupts, 0),                                \
+  SCM_PACK_OP_24 (return_values, 0),                                    \
   0,                                                                    \
   0
 
@@ -112,6 +124,8 @@
   SCM_PACK_OP_24 (assert_nargs_ge, nreq + 1),                           \
   SCM_PACK_OP_24 (bind_rest, nreq + nopt + 1),                          \
   SCM_PACK_OP_24 (subr_call, 0),                                        \
+  SCM_PACK_OP_24 (handle_interrupts, 0),                                \
+  SCM_PACK_OP_24 (return_values, 0),                                    \
   0
 
 
@@ -212,7 +226,7 @@ static const scm_t_uint32 subr_stub_code[] = {
 /* (nargs * nargs) + nopt + rest * (nargs + 1) */
 #define SUBR_STUB_CODE(nreq,nopt,rest)                                \
   &subr_stub_code[((nreq + nopt + rest) * (nreq + nopt + rest)        \
-                   + nopt + rest * (nreq + nopt + rest + 1)) * 4]
+                   + nopt + rest * (nreq + nopt + rest + 1)) * 6]
 
 static const scm_t_uint32*
 get_subr_stub_code (unsigned int nreq, unsigned int nopt, unsigned int rest)
@@ -265,12 +279,16 @@ scm_i_primitive_code_p (const scm_t_uint32 *code)
 scm_t_uintptr
 scm_i_primitive_call_ip (SCM subr)
 {
+  size_t i;
   const scm_t_uint32 *code = SCM_PROGRAM_CODE (subr);
 
-  /* A stub is 4 32-bit words long, or 16 bytes.  The call will be one
+  /* A stub is 6 32-bit words long, or 24 bytes.  The call will be one
      instruction, in either the fourth, third, or second word.  Return a
      byte offset from the entry.  */
-  return (scm_t_uintptr)(code + (code[3] ? 3 : code[2] ? 2 : 1));
+  for (i = 1; i < 4; i++)
+    if ((code[i] & 0xff) == scm_op_subr_call)
+      return (scm_t_uintptr) (code + i);
+  abort ();
 }
 
 SCM
diff --git a/libguile/vm-engine.c b/libguile/vm-engine.c
index 4de1971..ac8f32e 100644
--- a/libguile/vm-engine.c
+++ b/libguile/vm-engine.c
@@ -127,22 +127,6 @@
 #define ABORT_CONTINUATION_HOOK()               \
   RUN_HOOK0 (abort)
 
-/* TODO: Invoke asyncs without trampolining out to C.  That will let us
-   preempt computations via an asynchronous interrupt.  */
-#define VM_HANDLE_INTERRUPTS                                            \
-  do                                                                    \
-    if (SCM_LIKELY (thread->block_asyncs == 0))                         \
-      {                                                                 \
-        SCM asyncs = scm_atomic_ref_scm (&thread->pending_asyncs);      \
-        if (SCM_UNLIKELY (!scm_is_null (asyncs)))                       \
-          {                                                             \
-            SYNC_IP ();                                                 \
-            scm_async_tick ();                                          \
-            CACHE_SP ();                                                \
-          }                                                             \
-      }                                                                 \
-  while (0)
-
 
 
 
@@ -282,38 +266,6 @@
 #define VARIABLE_SET(v,o)      SCM_VARIABLE_SET (v, o)
 #define VARIABLE_BOUNDP(v)      (!scm_is_eq (VARIABLE_REF (v), SCM_UNDEFINED))
 
-#define RETURN_ONE_VALUE(ret)                           \
-  do {                                                  \
-    SCM val = ret;                                      \
-    union scm_vm_stack_element *old_fp;                 \
-    VM_HANDLE_INTERRUPTS;                               \
-    ALLOC_FRAME (2);                                   \
-    old_fp = vp->fp;                                    \
-    ip = SCM_FRAME_RETURN_ADDRESS (old_fp);             \
-    vp->fp = SCM_FRAME_DYNAMIC_LINK (old_fp);           \
-    /* Clear frame. */                                  \
-    old_fp[0].as_scm = SCM_BOOL_F;                      \
-    old_fp[1].as_scm = SCM_BOOL_F;                      \
-    /* Leave proc. */                                   \
-    SP_SET (0, val);                                    \
-    POP_CONTINUATION_HOOK (old_fp);                     \
-    NEXT (0);                                           \
-  } while (0)
-
-/* While we could generate the list-unrolling code here, it's fine for
-   now to just tail-call (apply values vals).  */
-#define RETURN_VALUE_LIST(vals_)                        \
-  do {                                                  \
-    SCM vals = vals_;                                   \
-    VM_HANDLE_INTERRUPTS;                               \
-    ALLOC_FRAME (3);                                    \
-    SP_SET (2, vm_builtin_apply);                       \
-    SP_SET (1, vm_builtin_values);                      \
-    SP_SET (0, vals);                                   \
-    ip = (scm_t_uint32 *) vm_builtin_apply_code;        \
-    goto op_tail_apply;                                 \
-  } while (0)
-
 #define BR_NARGS(rel)                           \
   scm_t_uint32 expected;                        \
   UNPACK_24 (op, expected);                     \
@@ -334,8 +286,6 @@
     {                                           \
       scm_t_int32 offset = ip[1];               \
       offset >>= 8; /* Sign-extending shift. */ \
-      if (offset <= 0)                          \
-        VM_HANDLE_INTERRUPTS;                   \
       NEXT (offset);                            \
     }                                           \
   NEXT (2)
@@ -351,8 +301,6 @@
     {                                           \
       scm_t_int32 offset = ip[2];               \
       offset >>= 8; /* Sign-extending shift. */ \
-      if (offset <= 0)                          \
-        VM_HANDLE_INTERRUPTS;                   \
       NEXT (offset);                            \
     }                                           \
   NEXT (3)
@@ -373,8 +321,6 @@
           {                                                             \
             scm_t_int32 offset = ip[2];                                 \
             offset >>= 8; /* Sign-extending shift. */                   \
-            if (offset <= 0)                                            \
-              VM_HANDLE_INTERRUPTS;                                     \
             NEXT (offset);                                              \
           }                                                             \
         NEXT (3);                                                       \
@@ -389,8 +335,6 @@
           {                                                             \
             scm_t_int32 offset = ip[2];                                 \
             offset >>= 8; /* Sign-extending shift. */                   \
-            if (offset <= 0)                                            \
-              VM_HANDLE_INTERRUPTS;                                     \
             NEXT (offset);                                              \
           }                                                             \
         NEXT (3);                                                       \
@@ -409,8 +353,6 @@
       {                                                                 \
         scm_t_int32 offset = ip[2];                                     \
         offset >>= 8; /* Sign-extending shift. */                       \
-        if (offset <= 0)                                                \
-          VM_HANDLE_INTERRUPTS;                                         \
         NEXT (offset);                                                  \
       }                                                                 \
     NEXT (3);                                                           \
@@ -587,8 +529,6 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
       UNPACK_24 (op, proc);
       UNPACK_24 (ip[1], nlocals);
 
-      VM_HANDLE_INTERRUPTS;
-
       PUSH_CONTINUATION_HOOK ();
 
       old_fp = vp->fp;
@@ -628,8 +568,6 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
       UNPACK_24 (ip[1], nlocals);
       label = ip[2];
 
-      VM_HANDLE_INTERRUPTS;
-
       PUSH_CONTINUATION_HOOK ();
 
       old_fp = vp->fp;
@@ -658,8 +596,6 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
       
       UNPACK_24 (op, nlocals);
 
-      VM_HANDLE_INTERRUPTS;
-
       RESET_FRAME (nlocals);
 
       if (SCM_LIKELY (SCM_PROGRAM_P (FP_REF (0))))
@@ -685,8 +621,6 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
       UNPACK_24 (op, nlocals);
       label = ip[1];
 
-      VM_HANDLE_INTERRUPTS;
-
       RESET_FRAME (nlocals);
 
       ip += label;
@@ -709,8 +643,6 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
 
       UNPACK_24 (op, from);
 
-      VM_HANDLE_INTERRUPTS;
-
       VM_ASSERT (from > 0, abort ());
       nlocals = FRAME_LOCALS_COUNT ();
 
@@ -789,8 +721,6 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
       union scm_vm_stack_element *old_fp;
       scm_t_uint32 nlocals;
 
-      VM_HANDLE_INTERRUPTS;
-
       UNPACK_24 (op, nlocals);
       if (nlocals)
         RESET_FRAME (nlocals);
@@ -831,10 +761,23 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
       CACHE_SP ();
 
       if (SCM_UNLIKELY (SCM_VALUESP (ret)))
-        /* multiple values returned to continuation */
-        RETURN_VALUE_LIST (scm_struct_ref (ret, SCM_INUM0));
+        {
+          SCM vals = scm_struct_ref (ret, SCM_INUM0);
+          long len = scm_ilength (vals);
+          ALLOC_FRAME (1 + len);
+          while (len--)
+            {
+              SP_SET (len, SCM_CAR (vals));
+              vals = SCM_CDR (vals);
+            }
+          NEXT (1);
+        }
       else
-        RETURN_ONE_VALUE (ret);
+        {
+          ALLOC_FRAME (2);
+          SP_SET (0, ret);
+          NEXT (1);
+        }
     }
 
   /* foreign-call cif-idx:12 ptr-idx:12
@@ -864,10 +807,23 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
       CACHE_SP ();
 
       if (SCM_UNLIKELY (SCM_VALUESP (ret)))
-        /* multiple values returned to continuation */
-        RETURN_VALUE_LIST (scm_struct_ref (ret, SCM_INUM0));
+        {
+          SCM vals = scm_struct_ref (ret, SCM_INUM0);
+          long len = scm_ilength (vals);
+          ALLOC_FRAME (1 + len);
+          while (len--)
+            {
+              SP_SET (len, SCM_CAR (vals));
+              vals = SCM_CDR (vals);
+            }
+          NEXT (1);
+        }
       else
-        RETURN_ONE_VALUE (ret);
+        {
+          ALLOC_FRAME (2);
+          SP_SET (0, ret);
+          NEXT (1);
+        }
     }
 
   /* continuation-call contregs:24
@@ -936,8 +892,6 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
       int i, list_idx, list_len, nlocals;
       SCM list;
 
-      VM_HANDLE_INTERRUPTS;
-
       nlocals = FRAME_LOCALS_COUNT ();
       // At a minimum, there should be apply, f, and the list.
       VM_ASSERT (nlocals >= 3, abort ());
@@ -983,8 +937,6 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
       scm_t_dynstack *dynstack;
       int first;
 
-      VM_HANDLE_INTERRUPTS;
-
       SYNC_IP ();
       dynstack = scm_dynstack_capture_all (&thread->dynstack);
       vm_cont = scm_i_vm_capture_stack (vp->stack_top,
@@ -1407,8 +1359,6 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
     {
       scm_t_int32 offset = op;
       offset >>= 8; /* Sign-extending shift. */
-      if (offset <= 0)
-        VM_HANDLE_INTERRUPTS;
       NEXT (offset);
     }
 
@@ -3704,8 +3654,6 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
           {                                                             \
             scm_t_int32 offset = ip[2];                                 \
             offset >>= 8; /* Sign-extending shift. */                   \
-            if (offset <= 0)                                            \
-              VM_HANDLE_INTERRUPTS;                                     \
             NEXT (offset);                                              \
           }                                                             \
         NEXT (3);                                                       \
@@ -3720,8 +3668,6 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
           {                                                             \
             scm_t_int32 offset = ip[2];                                 \
             offset >>= 8; /* Sign-extending shift. */                   \
-            if (offset <= 0)                                            \
-              VM_HANDLE_INTERRUPTS;                                     \
             NEXT (offset);                                              \
           }                                                             \
         NEXT (3);                                                       \
@@ -3926,7 +3872,18 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
    */
   VM_DEFINE_OP (183, handle_interrupts, "handle-interrupts", OP1 (X32))
     {
-      VM_HANDLE_INTERRUPTS;
+      /* TODO: Invoke asyncs without trampolining out to C.  That will
+         let us preempt computations via an asynchronous interrupt.  */
+      if (SCM_LIKELY (thread->block_asyncs == 0))
+        {
+          SCM asyncs = scm_atomic_ref_scm (&thread->pending_asyncs);
+          if (SCM_UNLIKELY (!scm_is_null (asyncs)))
+            {
+              SYNC_IP ();
+              scm_async_tick ();
+              CACHE_SP ();
+            }
+        }
       NEXT (1);
     }
 
@@ -4045,8 +4002,6 @@ VM_NAME (scm_i_thread *thread, struct scm_vm *vp,
 #undef POP_CONTINUATION_HOOK
 #undef PUSH_CONTINUATION_HOOK
 #undef RETURN
-#undef RETURN_ONE_VALUE
-#undef RETURN_VALUE_LIST
 #undef RUN_HOOK
 #undef RUN_HOOK0
 #undef RUN_HOOK1



reply via email to

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