unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* Storing JIT Code
@ 2010-07-19  2:01 Noah Lavine
  2010-08-19  5:58 ` Andy Wingo
  0 siblings, 1 reply; 3+ messages in thread
From: Noah Lavine @ 2010-07-19  2:01 UTC (permalink / raw)
  To: guile-devel

[-- Attachment #1: Type: text/plain, Size: 2189 bytes --]

Hello,

Attached are some patches I made for storing JIT code associated with
objcode objects. These are based on some threads a few weeks ago in
which we discussed how to handle JIT code, with the eventual goal of
adding a JIT compiler to Guile (I'm working on it).

The goal is to have a piece of JIT code associated with each objcode
object. Another possibility would be to associate them with procedure
objects, but that was rejected because it would make the procedure
object 5 words long, which might mess up caching.

I've tried two ways to do this so far: putting the JIT code in a
struct scm_objcode and putting it in the SCM object that always wraps
one of those structs. I tried the first way first, but I hit problems
because strings of bytecode are expected to be valid C structs, and
adding a pointer would require leaving more space there, which would
leak abstractions. Therefore, these patches implement the second way.
(A possible third way would be to put the JIT code in a property.)

The first patch adds the extra slot to the SCM object and initializes
it to C's NULL. This required changing a few functions in objcode.c to
make the SCMs differently. Unfortunately, I also had to change all of
the statically-generated objcode objects in continuations.c,
control.c, gsubr.c, foreign.c, and smob.c, so the patch is quite long.

The second patch adds some infrastructure to the VM to call a dummy
JIT compiler, cache its results, and run the resulting code if any is
generated. I set up a return convention so that the JIT compiler can
fail to compile things and the VM will run as usual, which I think
will be useful while there is a partially-complete compiler. (Although
I'm not convinced I've chosen the best values for it. Currently a NULL
jitcode means we've never tried to compile, and an SCM_BOOL_F means we
tried and failed, and therefore won't try again. Are there better
choices?)

I'm afraid these patches will require the set of small fixes I just
emailed, because one of the diffs modifies a comment that was added in
one of those patches. I believe the first patch is complete, but the
second patch is quite rough still. What do you think of them?

Noah

[-- Attachment #2: 0001-Add-JIT-pointers.patch --]
[-- Type: application/octet-stream, Size: 40413 bytes --]

From fde14a0a21c688978093c789899bd831f7ceb2da Mon Sep 17 00:00:00 2001
From: Noah Lavine <nlavine@haverford.edu>
Date: Sun, 18 Jul 2010 13:30:53 -0400
Subject: [PATCH] Add JIT pointers

Add a fifth machine word to the SCM objects that hold struct scm_objcodes to
store JIT code corresponding to that object code, and initialize them to
NULL.
---
 libguile/continuations.c |    3 +-
 libguile/control.c       |    3 +-
 libguile/foreign.c       |   52 ++++---
 libguile/gsubr.c         |  374 ++++++++++++++++++++++++++++++---------------
 libguile/objcodes.c      |   37 ++++--
 libguile/objcodes.h      |    2 +
 libguile/smob.c          |   47 ++++--
 7 files changed, 345 insertions(+), 173 deletions(-)

diff --git a/libguile/continuations.c b/libguile/continuations.c
index ed476a8..e9974e1 100644
--- a/libguile/continuations.c
+++ b/libguile/continuations.c
@@ -98,7 +98,8 @@ static const type sym##__unaligned[]
   SCM_DECLARE_STATIC_ALIGNED_ARRAY (scm_t_uint8, sym##__bytecode);      \
   SCM_STATIC_ALIGNED_ARRAY (8, scm_t_cell, sym##__cells) = {            \
     { STATIC_OBJCODE_TAG, SCM_PACK (sym##__bytecode) },                 \
-    { SCM_BOOL_F, SCM_PACK (0) }                                        \
+    { SCM_BOOL_F, SCM_PACK (0) },                                       \
+    { NULL }                                                            \
   };                                                                    \
   static const SCM sym = SCM_PACK (sym##__cells);                       \
   SCM_STATIC_ALIGNED_ARRAY (8, scm_t_uint8, sym##__bytecode)
diff --git a/libguile/control.c b/libguile/control.c
index caf79eb..fca39ab 100644
--- a/libguile/control.c
+++ b/libguile/control.c
@@ -105,7 +105,8 @@ static const type sym##__unaligned[]
   SCM_DECLARE_STATIC_ALIGNED_ARRAY (scm_t_uint8, sym##__bytecode);      \
   SCM_STATIC_ALIGNED_ARRAY (8, scm_t_cell, sym##__cells) = {            \
     { STATIC_OBJCODE_TAG, SCM_PACK (sym##__bytecode) },                 \
-    { SCM_BOOL_F, SCM_PACK (0) }                                        \
+    { SCM_BOOL_F, SCM_PACK (0) },                                       \
+    { NULL }                                                            \
   };                                                                    \
   static const SCM sym = SCM_PACK (sym##__cells);                       \
   SCM_STATIC_ALIGNED_ARRAY (8, scm_t_uint8, sym##__bytecode)
diff --git a/libguile/foreign.c b/libguile/foreign.c
index c541d13..6f68cba 100644
--- a/libguile/foreign.c
+++ b/libguile/foreign.c
@@ -788,20 +788,22 @@ static const struct
 
 #undef CODE
 #undef META
-#undef OBJCODE_HEADER
+/* don't undef OBJCODE_HEADER because the init function will use
+ * it to verify that it's the right size. */
 #undef META_HEADER
 
 /*
- (defun generate-objcode-cells (n)
-   "Generate objcode cells for up to N arguments"
-   (interactive "p")
-   (let ((i 0))
-     (while (< i n)
-       (insert
-        (format "    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + %d) },\n"
-                (* (+ 4 4 8 4 4 32) i)))
-       (insert "    { SCM_BOOL_F, SCM_PACK (0) },\n")
-       (setq i (1+ i)))))
+(defun generate-objcode-cells (n)
+  "Generate objcode cells for up to N arguments"
+  (interactive "p")
+  (let ((i 0))
+    (while (< i n)
+      (insert
+       (format "    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + %d) },\n"
+               (* (+ 4 4 8 4 4 32) i)))
+      (insert "    { SCM_BOOL_F, SCM_PACK (0) },\n")
+      (insert "    { NULL, 0 },\n")
+      (setq i (1+ i)))))
 */
 #define STATIC_OBJCODE_TAG                                      \
   SCM_PACK (scm_tc7_objcode | (SCM_F_OBJCODE_IS_STATIC << 8))
@@ -809,45 +811,55 @@ static const struct
 static const struct
 {
   scm_t_uint64 dummy; /* alignment */
-  scm_t_cell cells[10 * 2]; /* 10 double cells */
+  scm_t_cell cells[10 * 3]; /* 10 six-word cells (last word unused) */
 } objcode_cells = {
   0,
   /* C-u 1 0 M-x generate-objcode-cells RET */
-  {
+  { 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 0) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 56) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 112) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 168) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 224) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 280) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 336) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 392) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 448) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 504) },
-    { SCM_BOOL_F, SCM_PACK (0) }
+    { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
   }
 };
 
 static const SCM objcode_trampolines[10] = {
   SCM_PACK (objcode_cells.cells+0),
-  SCM_PACK (objcode_cells.cells+2),
-  SCM_PACK (objcode_cells.cells+4),
+  SCM_PACK (objcode_cells.cells+3),
   SCM_PACK (objcode_cells.cells+6),
-  SCM_PACK (objcode_cells.cells+8),
-  SCM_PACK (objcode_cells.cells+10),
+  SCM_PACK (objcode_cells.cells+9),
   SCM_PACK (objcode_cells.cells+12),
-  SCM_PACK (objcode_cells.cells+14),
-  SCM_PACK (objcode_cells.cells+16),
+  SCM_PACK (objcode_cells.cells+15),
   SCM_PACK (objcode_cells.cells+18),
+  SCM_PACK (objcode_cells.cells+21),
+  SCM_PACK (objcode_cells.cells+24),
+  SCM_PACK (objcode_cells.cells+27),
 };
 
 static SCM
diff --git a/libguile/gsubr.c b/libguile/gsubr.c
index af1c031..ceaddc6 100644
--- a/libguile/gsubr.c
+++ b/libguile/gsubr.c
@@ -274,36 +274,39 @@ static const struct
 #undef AC
 #undef BC
 #undef ABC
-#undef OBJCODE_HEADER
+/* don't undef OBJCODE_HEADER because scm_init_gsubr will use it to verify
+ * that its size is correct. */
 #undef META_HEADER
 #undef META
 
 /*
  ;; (nargs * nargs) + nopt + rest * (nargs + 1)
- (defun generate-objcode-cells-helper (n)
-   "Generate objcode cells for N arguments"
-   (interactive "p")
-   (insert (format "    /\* %d arguments *\/\n" n))
-   (let ((nreq n))
-     (while (<= 0 nreq)
-       (let ((nopt (- n nreq)))
-         (insert
-          (format "    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + %d) },\n"
-                  (* (+ 4 4 16 4 4 32)
-                     (+ (* n n) nopt))))
-         (insert "    { SCM_BOOL_F, SCM_PACK (0) },\n")
-         (setq nreq (1- nreq))))
-     (insert "\n")
-     (setq nreq (1- n))
-     (while (<= 0 nreq)
-       (let ((nopt (- n nreq 1)))
-         (insert
-          (format "    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + %d) },\n"
-                  (* (+ 4 4 16 4 4 32)
-                     (+ (* n n) nopt n 1))))
-         (insert "    { SCM_BOOL_F, SCM_PACK (0) },\n")
-         (setq nreq (1- nreq))))
-     (insert "\n")))
+(defun generate-objcode-cells-helper (n)
+  "Generate objcode cells for N arguments"
+  (interactive "p")
+  (insert (format "    /\* %d arguments *\/\n" n))
+  (let ((nreq n))
+    (while (<= 0 nreq)
+      (let ((nopt (- n nreq)))
+        (insert
+         (format "    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + %d) },\n"
+                 (* (+ 4 4 16 4 4 32)
+                    (+ (* n n) nopt))))
+        (insert "    { SCM_BOOL_F, SCM_PACK (0) },\n")
+        (insert "    { NULL, 0 },\n")
+        (setq nreq (1- nreq))))
+    (insert "\n")
+    (setq nreq (1- n))
+    (while (<= 0 nreq)
+      (let ((nopt (- n nreq 1)))
+        (insert
+         (format "    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + %d) },\n"
+                 (* (+ 4 4 16 4 4 32)
+                    (+ (* n n) nopt n 1))))
+        (insert "    { SCM_BOOL_F, SCM_PACK (0) },\n")
+        (insert "    { NULL, 0 },\n")
+        (setq nreq (1- nreq))))
+    (insert "\n")))
 
  (defun generate-objcode-cells (n)
    "Generate objcode cells for up to N arguments"
@@ -320,7 +323,7 @@ static const struct
 static const struct
 {
   scm_t_uint64 dummy; /* alignment */
-  scm_t_cell cells[121 * 2]; /* 11*11 double cells */
+  scm_t_cell cells[121 * 3]; /* 11*11 triple cells (last word unused) */
 } objcode_cells = {
   0,
   /* C-u 1 0 M-x generate-objcode-cells RET */
@@ -328,277 +331,398 @@ static const struct
     /* 0 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 0) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
 
     /* 1 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 64) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 128) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 192) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     /* 2 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 256) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 320) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 384) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 448) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 512) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     /* 3 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 576) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 640) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 704) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 768) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 832) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 896) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 960) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     /* 4 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1024) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1088) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1152) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1216) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1280) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1344) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1408) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1472) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1536) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     /* 5 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1600) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1664) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1728) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1792) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1856) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1920) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 1984) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2048) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2112) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2176) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2240) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     /* 6 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2304) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2368) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2432) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2496) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2560) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2624) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2688) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2752) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2816) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2880) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 2944) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3008) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3072) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     /* 7 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3136) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3200) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3264) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3328) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3392) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3456) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3520) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3584) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3648) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3712) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3776) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3840) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3904) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 3968) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4032) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     /* 8 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4096) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4160) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4224) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4288) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4352) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4416) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4480) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4544) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4608) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4672) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4736) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4800) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4864) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4928) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 4992) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5056) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5120) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     /* 9 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5184) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5248) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5312) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5376) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5440) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5504) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5568) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5632) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5696) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5760) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5824) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5888) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 5952) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6016) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6080) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6144) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6208) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6272) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6336) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     /* 10 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6400) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6464) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6528) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6592) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6656) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6720) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6784) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6848) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6912) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 6976) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 7040) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 7104) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 7168) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 7232) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 7296) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 7360) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 7424) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 7488) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 7552) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 7616) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 7680) },
-    { SCM_BOOL_F, SCM_PACK (0) }
+    { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
   }
 };
   
@@ -609,7 +733,7 @@ static const struct
    (insert (format "  /\* %d arguments *\/\n" n))
    (let ((i (* n n)))
      (while (< i (* (1+ n) (1+ n)))
-       (insert (format "  SCM_PACK (objcode_cells.cells+%d),\n" (* i 2)))
+       (insert (format "  SCM_PACK (objcode_cells.cells+%d),\n" (* i 3)))
        (setq i (1+ i)))
      (insert "\n")))
 
@@ -627,144 +751,144 @@ static const SCM scm_subr_objcode_trampolines[121] = {
   SCM_PACK (objcode_cells.cells+0),
 
   /* 1 arguments */
-  SCM_PACK (objcode_cells.cells+2),
-  SCM_PACK (objcode_cells.cells+4),
+  SCM_PACK (objcode_cells.cells+3),
   SCM_PACK (objcode_cells.cells+6),
+  SCM_PACK (objcode_cells.cells+9),
 
   /* 2 arguments */
-  SCM_PACK (objcode_cells.cells+8),
-  SCM_PACK (objcode_cells.cells+10),
   SCM_PACK (objcode_cells.cells+12),
-  SCM_PACK (objcode_cells.cells+14),
-  SCM_PACK (objcode_cells.cells+16),
-
-  /* 3 arguments */
+  SCM_PACK (objcode_cells.cells+15),
   SCM_PACK (objcode_cells.cells+18),
-  SCM_PACK (objcode_cells.cells+20),
-  SCM_PACK (objcode_cells.cells+22),
+  SCM_PACK (objcode_cells.cells+21),
   SCM_PACK (objcode_cells.cells+24),
-  SCM_PACK (objcode_cells.cells+26),
-  SCM_PACK (objcode_cells.cells+28),
-  SCM_PACK (objcode_cells.cells+30),
 
-  /* 4 arguments */
-  SCM_PACK (objcode_cells.cells+32),
-  SCM_PACK (objcode_cells.cells+34),
+  /* 3 arguments */
+  SCM_PACK (objcode_cells.cells+27),
+  SCM_PACK (objcode_cells.cells+30),
+  SCM_PACK (objcode_cells.cells+33),
   SCM_PACK (objcode_cells.cells+36),
-  SCM_PACK (objcode_cells.cells+38),
-  SCM_PACK (objcode_cells.cells+40),
+  SCM_PACK (objcode_cells.cells+39),
   SCM_PACK (objcode_cells.cells+42),
-  SCM_PACK (objcode_cells.cells+44),
-  SCM_PACK (objcode_cells.cells+46),
-  SCM_PACK (objcode_cells.cells+48),
+  SCM_PACK (objcode_cells.cells+45),
 
-  /* 5 arguments */
-  SCM_PACK (objcode_cells.cells+50),
-  SCM_PACK (objcode_cells.cells+52),
+  /* 4 arguments */
+  SCM_PACK (objcode_cells.cells+48),
+  SCM_PACK (objcode_cells.cells+51),
   SCM_PACK (objcode_cells.cells+54),
-  SCM_PACK (objcode_cells.cells+56),
-  SCM_PACK (objcode_cells.cells+58),
+  SCM_PACK (objcode_cells.cells+57),
   SCM_PACK (objcode_cells.cells+60),
-  SCM_PACK (objcode_cells.cells+62),
-  SCM_PACK (objcode_cells.cells+64),
+  SCM_PACK (objcode_cells.cells+63),
   SCM_PACK (objcode_cells.cells+66),
-  SCM_PACK (objcode_cells.cells+68),
-  SCM_PACK (objcode_cells.cells+70),
-
-  /* 6 arguments */
+  SCM_PACK (objcode_cells.cells+69),
   SCM_PACK (objcode_cells.cells+72),
-  SCM_PACK (objcode_cells.cells+74),
-  SCM_PACK (objcode_cells.cells+76),
+
+  /* 5 arguments */
+  SCM_PACK (objcode_cells.cells+75),
   SCM_PACK (objcode_cells.cells+78),
-  SCM_PACK (objcode_cells.cells+80),
-  SCM_PACK (objcode_cells.cells+82),
+  SCM_PACK (objcode_cells.cells+81),
   SCM_PACK (objcode_cells.cells+84),
-  SCM_PACK (objcode_cells.cells+86),
-  SCM_PACK (objcode_cells.cells+88),
+  SCM_PACK (objcode_cells.cells+87),
   SCM_PACK (objcode_cells.cells+90),
-  SCM_PACK (objcode_cells.cells+92),
-  SCM_PACK (objcode_cells.cells+94),
+  SCM_PACK (objcode_cells.cells+93),
   SCM_PACK (objcode_cells.cells+96),
-
-  /* 7 arguments */
-  SCM_PACK (objcode_cells.cells+98),
-  SCM_PACK (objcode_cells.cells+100),
+  SCM_PACK (objcode_cells.cells+99),
   SCM_PACK (objcode_cells.cells+102),
-  SCM_PACK (objcode_cells.cells+104),
-  SCM_PACK (objcode_cells.cells+106),
+  SCM_PACK (objcode_cells.cells+105),
+
+  /* 6 arguments */
   SCM_PACK (objcode_cells.cells+108),
-  SCM_PACK (objcode_cells.cells+110),
-  SCM_PACK (objcode_cells.cells+112),
+  SCM_PACK (objcode_cells.cells+111),
   SCM_PACK (objcode_cells.cells+114),
-  SCM_PACK (objcode_cells.cells+116),
-  SCM_PACK (objcode_cells.cells+118),
+  SCM_PACK (objcode_cells.cells+117),
   SCM_PACK (objcode_cells.cells+120),
-  SCM_PACK (objcode_cells.cells+122),
-  SCM_PACK (objcode_cells.cells+124),
+  SCM_PACK (objcode_cells.cells+123),
   SCM_PACK (objcode_cells.cells+126),
-
-  /* 8 arguments */
-  SCM_PACK (objcode_cells.cells+128),
-  SCM_PACK (objcode_cells.cells+130),
+  SCM_PACK (objcode_cells.cells+129),
   SCM_PACK (objcode_cells.cells+132),
-  SCM_PACK (objcode_cells.cells+134),
-  SCM_PACK (objcode_cells.cells+136),
+  SCM_PACK (objcode_cells.cells+135),
   SCM_PACK (objcode_cells.cells+138),
-  SCM_PACK (objcode_cells.cells+140),
-  SCM_PACK (objcode_cells.cells+142),
+  SCM_PACK (objcode_cells.cells+141),
   SCM_PACK (objcode_cells.cells+144),
-  SCM_PACK (objcode_cells.cells+146),
-  SCM_PACK (objcode_cells.cells+148),
+
+  /* 7 arguments */
+  SCM_PACK (objcode_cells.cells+147),
   SCM_PACK (objcode_cells.cells+150),
-  SCM_PACK (objcode_cells.cells+152),
-  SCM_PACK (objcode_cells.cells+154),
+  SCM_PACK (objcode_cells.cells+153),
   SCM_PACK (objcode_cells.cells+156),
-  SCM_PACK (objcode_cells.cells+158),
-  SCM_PACK (objcode_cells.cells+160),
-
-  /* 9 arguments */
+  SCM_PACK (objcode_cells.cells+159),
   SCM_PACK (objcode_cells.cells+162),
-  SCM_PACK (objcode_cells.cells+164),
-  SCM_PACK (objcode_cells.cells+166),
+  SCM_PACK (objcode_cells.cells+165),
   SCM_PACK (objcode_cells.cells+168),
-  SCM_PACK (objcode_cells.cells+170),
-  SCM_PACK (objcode_cells.cells+172),
+  SCM_PACK (objcode_cells.cells+171),
   SCM_PACK (objcode_cells.cells+174),
-  SCM_PACK (objcode_cells.cells+176),
-  SCM_PACK (objcode_cells.cells+178),
+  SCM_PACK (objcode_cells.cells+177),
   SCM_PACK (objcode_cells.cells+180),
-  SCM_PACK (objcode_cells.cells+182),
-  SCM_PACK (objcode_cells.cells+184),
+  SCM_PACK (objcode_cells.cells+183),
   SCM_PACK (objcode_cells.cells+186),
-  SCM_PACK (objcode_cells.cells+188),
-  SCM_PACK (objcode_cells.cells+190),
+  SCM_PACK (objcode_cells.cells+189),
+
+  /* 8 arguments */
   SCM_PACK (objcode_cells.cells+192),
-  SCM_PACK (objcode_cells.cells+194),
-  SCM_PACK (objcode_cells.cells+196),
+  SCM_PACK (objcode_cells.cells+195),
   SCM_PACK (objcode_cells.cells+198),
-
-  /* 10 arguments */
-  SCM_PACK (objcode_cells.cells+200),
-  SCM_PACK (objcode_cells.cells+202),
+  SCM_PACK (objcode_cells.cells+201),
   SCM_PACK (objcode_cells.cells+204),
-  SCM_PACK (objcode_cells.cells+206),
-  SCM_PACK (objcode_cells.cells+208),
+  SCM_PACK (objcode_cells.cells+207),
   SCM_PACK (objcode_cells.cells+210),
-  SCM_PACK (objcode_cells.cells+212),
-  SCM_PACK (objcode_cells.cells+214),
+  SCM_PACK (objcode_cells.cells+213),
   SCM_PACK (objcode_cells.cells+216),
-  SCM_PACK (objcode_cells.cells+218),
-  SCM_PACK (objcode_cells.cells+220),
+  SCM_PACK (objcode_cells.cells+219),
   SCM_PACK (objcode_cells.cells+222),
-  SCM_PACK (objcode_cells.cells+224),
-  SCM_PACK (objcode_cells.cells+226),
+  SCM_PACK (objcode_cells.cells+225),
   SCM_PACK (objcode_cells.cells+228),
-  SCM_PACK (objcode_cells.cells+230),
-  SCM_PACK (objcode_cells.cells+232),
+  SCM_PACK (objcode_cells.cells+231),
   SCM_PACK (objcode_cells.cells+234),
-  SCM_PACK (objcode_cells.cells+236),
-  SCM_PACK (objcode_cells.cells+238),
-  SCM_PACK (objcode_cells.cells+240)
+  SCM_PACK (objcode_cells.cells+237),
+  SCM_PACK (objcode_cells.cells+240),
+
+  /* 9 arguments */
+  SCM_PACK (objcode_cells.cells+243),
+  SCM_PACK (objcode_cells.cells+246),
+  SCM_PACK (objcode_cells.cells+249),
+  SCM_PACK (objcode_cells.cells+252),
+  SCM_PACK (objcode_cells.cells+255),
+  SCM_PACK (objcode_cells.cells+258),
+  SCM_PACK (objcode_cells.cells+261),
+  SCM_PACK (objcode_cells.cells+264),
+  SCM_PACK (objcode_cells.cells+267),
+  SCM_PACK (objcode_cells.cells+270),
+  SCM_PACK (objcode_cells.cells+273),
+  SCM_PACK (objcode_cells.cells+276),
+  SCM_PACK (objcode_cells.cells+279),
+  SCM_PACK (objcode_cells.cells+282),
+  SCM_PACK (objcode_cells.cells+285),
+  SCM_PACK (objcode_cells.cells+288),
+  SCM_PACK (objcode_cells.cells+291),
+  SCM_PACK (objcode_cells.cells+294),
+  SCM_PACK (objcode_cells.cells+297),
+
+  /* 10 arguments */
+  SCM_PACK (objcode_cells.cells+300),
+  SCM_PACK (objcode_cells.cells+303),
+  SCM_PACK (objcode_cells.cells+306),
+  SCM_PACK (objcode_cells.cells+309),
+  SCM_PACK (objcode_cells.cells+312),
+  SCM_PACK (objcode_cells.cells+315),
+  SCM_PACK (objcode_cells.cells+318),
+  SCM_PACK (objcode_cells.cells+321),
+  SCM_PACK (objcode_cells.cells+324),
+  SCM_PACK (objcode_cells.cells+327),
+  SCM_PACK (objcode_cells.cells+330),
+  SCM_PACK (objcode_cells.cells+333),
+  SCM_PACK (objcode_cells.cells+336),
+  SCM_PACK (objcode_cells.cells+339),
+  SCM_PACK (objcode_cells.cells+342),
+  SCM_PACK (objcode_cells.cells+345),
+  SCM_PACK (objcode_cells.cells+348),
+  SCM_PACK (objcode_cells.cells+351),
+  SCM_PACK (objcode_cells.cells+354),
+  SCM_PACK (objcode_cells.cells+357),
+  SCM_PACK (objcode_cells.cells+360),
 };
 
 /* (nargs * nargs) + nopt + rest * (nargs + 1) */
diff --git a/libguile/objcodes.c b/libguile/objcodes.c
index 41a5990..767c0ac 100644
--- a/libguile/objcodes.c
+++ b/libguile/objcodes.c
@@ -44,11 +44,13 @@ verify (((sizeof (SCM_OBJCODE_COOKIE) - 1) & 7) == 0);
  * Objcode type
  */
 
-/* an objcode SCM object is a four-word object containing
+/* an objcode SCM object is a five-word object containing
    - scm_tc7_objcode | the flags for this objcode
    - the struct scm_objcode C object
    - the parent of this objcode, if this is a slice, or #f if none
    - the file descriptor this objcode came from if this was mmaped, or 0 if none
+   - the JIT code for this object, NULL if we've never tried to JIT this,
+     and #f if we tried and failed.
 */
 
 static SCM
@@ -97,10 +99,12 @@ make_objcode_by_mmap (int fd)
 						   + data->metalen)));
     }
 
-  sret = scm_double_cell (scm_tc7_objcode | (SCM_F_OBJCODE_IS_MMAP<<8),
-                          (scm_t_bits)(addr + strlen (SCM_OBJCODE_COOKIE)),
-                          SCM_UNPACK (SCM_BOOL_F),
-                          (scm_t_bits)fd);
+  sret = scm_words (scm_tc7_objcode | (SCM_F_OBJCODE_IS_MMAP<<8), 5);
+  SCM_GC_SET_CELL_WORD (sret, 1,
+                       (scm_t_bits)(addr + strlen(SCM_OBJCODE_COOKIE)));
+  SCM_GC_SET_CELL_WORD (sret, 2, SCM_UNPACK (SCM_BOOL_F));
+  SCM_GC_SET_CELL_WORD (sret, 3, (scm_t_bits)fd);
+  SCM_GC_SET_CELL_WORD (sret, 4, (scm_t_bits)NULL);
 
   /* FIXME: we leak ourselves and the file descriptor. but then again so does
      dlopen(). */
@@ -114,6 +118,7 @@ scm_c_make_objcode_slice (SCM parent, const scm_t_uint8 *ptr)
 {
   const struct scm_objcode *data, *parent_data;
   const scm_t_uint8 *parent_base;
+  SCM ret;
 
   SCM_VALIDATE_OBJCODE (1, parent);
   parent_data = SCM_OBJCODE_DATA (parent);
@@ -137,8 +142,12 @@ scm_c_make_objcode_slice (SCM parent, const scm_t_uint8 *ptr)
   assert (SCM_C_OBJCODE_BASE (data) + data->len + data->metalen
 	  <= parent_base + parent_data->len + parent_data->metalen);
 
-  return scm_double_cell (scm_tc7_objcode | (SCM_F_OBJCODE_IS_SLICE<<8),
-                          (scm_t_bits)data, SCM_UNPACK (parent), 0);
+  ret = scm_words (scm_tc7_objcode, 5);
+  SCM_GC_SET_CELL_WORD (ret, 1, (scm_t_bits)data);
+  SCM_GC_SET_CELL_WORD (ret, 2, SCM_UNPACK (parent));
+  SCM_GC_SET_CELL_WORD (ret, 3, 0);
+  SCM_GC_SET_CELL_WORD (ret, 4, NULL);
+  return ret;
 }
 #undef FUNC_NAME
 
@@ -179,7 +188,8 @@ SCM_DEFINE (scm_bytecode_to_objcode, "bytecode->objcode", 1, 0, 0,
   size_t size;
   const scm_t_uint8 *c_bytecode;
   struct scm_objcode *data;
-
+  SCM ret;
+  
   if (!scm_is_bytevector (bytecode))
     scm_wrong_type_arg (FUNC_NAME, 1, bytecode);
 
@@ -187,17 +197,22 @@ SCM_DEFINE (scm_bytecode_to_objcode, "bytecode->objcode", 1, 0, 0,
   c_bytecode = (const scm_t_uint8*)SCM_BYTEVECTOR_CONTENTS (bytecode);
   
   SCM_ASSERT_RANGE (0, bytecode, size >= sizeof(struct scm_objcode));
+
   data = (struct scm_objcode*)c_bytecode;
 
   if (data->len + data->metalen != (size - sizeof (*data)))
     scm_misc_error (FUNC_NAME, "bad bytevector size (~a != ~a)",
 		    scm_list_2 (scm_from_size_t (size),
 				scm_from_uint32 (sizeof (*data) + data->len + data->metalen)));
-
+  
   /* foolishly, we assume that as long as bytecode is around, that c_bytecode
      will be of the same length; perhaps a bad assumption? */
-  return scm_double_cell (scm_tc7_objcode | (SCM_F_OBJCODE_IS_BYTEVECTOR<<8),
-                          (scm_t_bits)data, SCM_UNPACK (bytecode), 0);
+  ret = scm_words (scm_tc7_objcode | (SCM_F_OBJCODE_IS_BYTEVECTOR<<8), 5);
+  SCM_GC_SET_CELL_WORD (ret, 1, (scm_t_bits)data);
+  SCM_GC_SET_CELL_WORD (ret, 2, SCM_UNPACK (bytecode));
+  SCM_GC_SET_CELL_WORD (ret, 3, 0);
+  SCM_GC_SET_CELL_WORD (ret, 4, NULL);
+  return ret;
 }
 #undef FUNC_NAME
 
diff --git a/libguile/objcodes.h b/libguile/objcodes.h
index 2bff9aa..b92e8ef 100644
--- a/libguile/objcodes.h
+++ b/libguile/objcodes.h
@@ -54,6 +54,8 @@ struct scm_objcode
 #define SCM_OBJCODE_IS_BYTEVECTOR(x) (SCM_OBJCODE_FLAGS (x) & SCM_F_OBJCODE_IS_BYTEVECTOR)
 #define SCM_OBJCODE_IS_SLICE(x) (SCM_OBJCODE_FLAGS (x) & SCM_F_OBJCODE_IS_SLICE)
 
+#define SCM_OBJCODE_JITCODE(x) (SCM_CELL_WORD ((x), 4))
+
 SCM scm_c_make_objcode_slice (SCM parent, const scm_t_uint8 *ptr);
 SCM_API SCM scm_load_objcode (SCM file);
 SCM_API SCM scm_objcode_p (SCM obj);
diff --git a/libguile/smob.c b/libguile/smob.c
index 6582612..7d8abb2 100644
--- a/libguile/smob.c
+++ b/libguile/smob.c
@@ -261,7 +261,7 @@ static const struct
 static const struct
 {
   scm_t_uint64 dummy; /* alignment */
-  scm_t_cell cells[16 * 2]; /* 4*4 double cells */
+  scm_t_cell cells[16 * 3]; /* 4*4 triple cells (last cell unused) */
 } objcode_cells = {
   0,
   /* C-u 3 M-x generate-objcode-cells RET */
@@ -269,45 +269,62 @@ static const struct
     /* 0 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 0) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
+
 
     /* 1 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 64) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 128) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 192) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     /* 2 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 256) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 320) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 384) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 448) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 512) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     /* 3 arguments */
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 576) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 640) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 704) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 768) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
 
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 832) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 896) },
     { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
     { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 960) },
-    { SCM_BOOL_F, SCM_PACK (0) }
+    { SCM_BOOL_F, SCM_PACK (0) },
+    { NULL, 0 },
   }
 };
   
@@ -317,25 +334,25 @@ static const SCM scm_smob_objcode_trampolines[16] = {
   SCM_PACK (objcode_cells.cells+0),
 
   /* 1 arguments */
-  SCM_PACK (objcode_cells.cells+2),
-  SCM_PACK (objcode_cells.cells+4),
+  SCM_PACK (objcode_cells.cells+3),
   SCM_PACK (objcode_cells.cells+6),
+  SCM_PACK (objcode_cells.cells+9),
 
   /* 2 arguments */
-  SCM_PACK (objcode_cells.cells+8),
-  SCM_PACK (objcode_cells.cells+10),
   SCM_PACK (objcode_cells.cells+12),
-  SCM_PACK (objcode_cells.cells+14),
-  SCM_PACK (objcode_cells.cells+16),
-
-  /* 3 arguments */
+  SCM_PACK (objcode_cells.cells+15),
   SCM_PACK (objcode_cells.cells+18),
-  SCM_PACK (objcode_cells.cells+20),
-  SCM_PACK (objcode_cells.cells+22),
+  SCM_PACK (objcode_cells.cells+21),
   SCM_PACK (objcode_cells.cells+24),
-  SCM_PACK (objcode_cells.cells+26),
-  SCM_PACK (objcode_cells.cells+28),
-  SCM_PACK (objcode_cells.cells+30)
+
+  /* 3 arguments */
+  SCM_PACK (objcode_cells.cells+27),
+  SCM_PACK (objcode_cells.cells+30),
+  SCM_PACK (objcode_cells.cells+33),
+  SCM_PACK (objcode_cells.cells+36),
+  SCM_PACK (objcode_cells.cells+39),
+  SCM_PACK (objcode_cells.cells+42),
+  SCM_PACK (objcode_cells.cells+45),
 };
 
 /* (nargs * nargs) + nopt + rest * (nargs + 1) */
-- 
1.7.1


[-- Attachment #3: 0002-Add-JIT-Infrastructure.patch --]
[-- Type: application/octet-stream, Size: 8670 bytes --]

From 10d47c5561917eb0b9b7fc5a3ef0154ff38925fc Mon Sep 17 00:00:00 2001
From: Noah Lavine <nlavine@haverford.edu>
Date: Sun, 18 Jul 2010 13:35:27 -0400
Subject: [PATCH] Add JIT Infrastructure

Add a dummy JIT compiler, and the infrastructure to invoke it on object code,
run the JIT code if it's generated, and cache the JIT code for future use.
---
 libguile/Makefile.am   |    2 +
 libguile/init.c        |    4 ++-
 libguile/vm-engine.c   |   22 ++++++++++++++++-
 libguile/vm-engine.h   |    2 +
 libguile/vm-i-system.c |   17 +++++++++++++
 libguile/vm-jit.c      |   60 ++++++++++++++++++++++++++++++++++++++++++++++++
 libguile/vm-jit.h      |   39 +++++++++++++++++++++++++++++++
 7 files changed, 144 insertions(+), 2 deletions(-)
 create mode 100644 libguile/vm-jit.c
 create mode 100644 libguile/vm-jit.h

diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index 5eea8dc..3da0009 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -210,6 +210,7 @@ libguile_@GUILE_EFFECTIVE_VERSION@_la_SOURCES =				\
 	vectors.c				\
 	version.c				\
 	vm.c					\
+	vm-jit.c				\
 	vports.c				\
 	weaks.c
 
@@ -583,6 +584,7 @@ modinclude_HEADERS =				\
 	vectors.h				\
 	vm-engine.h				\
 	vm-expand.h				\
+	vm-jit.h				\
 	vm.h					\
 	vports.h				\
 	weaks.h
diff --git a/libguile/init.c b/libguile/init.c
index 4843910..7c88a4a 100644
--- a/libguile/init.c
+++ b/libguile/init.c
@@ -128,6 +128,7 @@
 #include "libguile/vectors.h"
 #include "libguile/version.h"
 #include "libguile/vm.h"
+#include "libguile/vm-jit.h"
 #include "libguile/vports.h"
 #include "libguile/weaks.h"
 #include "libguile/guardians.h"
@@ -546,7 +547,8 @@ scm_i_init_guile (SCM_STACKITEM *base)
   scm_init_weaks ();
   scm_init_guardians (); /* requires smob_prehistory */
   scm_init_vports ();
-  scm_init_standard_ports ();  /* Requires fports */
+  scm_init_jit ();
+  scm_init_standard_ports ();  /* Requires fports, jit */
   scm_init_expand ();   /* Requires structs */
   scm_init_memoize ();  /* Requires smob_prehistory */
   scm_init_eval ();     /* Requires smob_prehistory */
diff --git a/libguile/vm-engine.c b/libguile/vm-engine.c
index 7f4641a..a567a85 100644
--- a/libguile/vm-engine.c
+++ b/libguile/vm-engine.c
@@ -31,7 +31,7 @@
 #endif
 
 #include "vm-engine.h"
-
+#include "tags.h" /* for SCM_BOOL_F */
 
 static SCM
 VM_NAME (SCM vm, SCM program, SCM *argv, int nargs)
@@ -47,6 +47,7 @@ VM_NAME (SCM vm, SCM program, SCM *argv, int nargs)
   SCM *objects = NULL;			/* constant objects */
   size_t object_count = 0;              /* length of OBJECTS */
   SCM *stack_limit = vp->stack_limit;	/* stack limit address */
+  jitf *jitcode = NULL;  /* JIT code, if any */
 
   SCM dynstate = SCM_I_CURRENT_THREAD->dynamic_state;
   scm_t_int64 vm_cookie = vp->cookie++;
@@ -80,6 +81,10 @@ VM_NAME (SCM vm, SCM program, SCM *argv, int nargs)
   {
     SCM prog = program;
 
+    /* program could also be a smob. maybe other things? */
+    if (SCM_PROGRAM_P(program))
+      jitcode = (jitf *)SCM_OBJCODE_JITCODE(SCM_PROGRAM_OBJCODE(program));
+
     /* Boot program */
     program = vm_make_boot_program (nargs);
 
@@ -105,6 +110,21 @@ VM_NAME (SCM vm, SCM program, SCM *argv, int nargs)
 
   /* Let's go! */
   BOOT_HOOK ();
+
+  if (jitcode == NULL) {
+    jitcode = jit_objcode(bp);
+    SCM_OBJCODE_JITCODE(SCM_PROGRAM_OBJCODE(program)) = jitcode;
+  }
+  if (jitcode != SCM_BOOL_F) {
+    scm_t_uint8 *sip = ip;
+    SCM *ssp = sp;
+    SCM *sfp = fp;
+    SCM_JITCODE_ENTER(jitcode, sip, ssp, sfp);
+    ip = sip;
+    sp = ssp;
+    fp = sfp;
+  }
+  /* if the jitcode runs, we'll still want to do NEXT afterwards */
   NEXT;
 
 #ifndef HAVE_LABELS_AS_VALUES
diff --git a/libguile/vm-engine.h b/libguile/vm-engine.h
index 836648c..b90e481 100644
--- a/libguile/vm-engine.h
+++ b/libguile/vm-engine.h
@@ -90,6 +90,8 @@
 #define FP_REG
 #endif
 
+#include "vm-jit.h"
+
 \f
 /*
  * Cache/Sync
diff --git a/libguile/vm-i-system.c b/libguile/vm-i-system.c
index 11f8ae0..5499bcf 100644
--- a/libguile/vm-i-system.c
+++ b/libguile/vm-i-system.c
@@ -744,6 +744,7 @@ VM_DEFINE_INSTRUCTION (53, new_frame, "new-frame", 0, 0, 3)
 
 VM_DEFINE_INSTRUCTION (54, call, "call", 1, -1, 1)
 {
+  (jitf *)jitcode = NULL;
   nargs = FETCH ();
 
  vm_call:
@@ -778,6 +779,22 @@ VM_DEFINE_INSTRUCTION (54, call, "call", 1, -1, 1)
   ip = SCM_C_OBJCODE_BASE (bp);
   ENTER_HOOK ();
   APPLY_HOOK ();
+
+  jitcode = SCM_OBJCODE_JITCODE(SCM_PROGRAM_OBJCODE(program));
+  if (jitcode == NULL) {
+    jitcode = jit_objcode(bp);
+    SCM_OBJCODE_JITCODE(SCM_PROGRAM_OBJCODE(program)) = jitcode;
+  }
+  if (jitcode != SCM_BOOL_F) {
+    scm_t_uint8 *sip = ip;
+    SCM *ssp = sp;
+    SCM *sfp = fp;
+    SCM_JITCODE_ENTER(jitcode, sip, ssp, sfp);
+    ip = sip;
+    sp = ssp;
+    fp = sfp;
+  }
+  /* if the jitcode runs, we'll still want to do NEXT afterwards */
   NEXT;
 }
 
diff --git a/libguile/vm-jit.c b/libguile/vm-jit.c
new file mode 100644
index 0000000..d9a4a08
--- /dev/null
+++ b/libguile/vm-jit.c
@@ -0,0 +1,60 @@
+#include <stdio.h>
+
+#include "libguile/instructions.h"
+#include "libguile/snarf.h"
+#include "libguile/objcodes.h"
+#include "libguile/symbols.h"
+#include "libguile/list.h"
+#include "libguile/tags.h"
+#include "libguile/strings.h" /* for scm_from_locale_string, for the init function */
+#include "libguile/struct.h"
+#include "libguile/numbers.h"
+
+#include "libguile/vm-jit.h" /* defines struct scm_jit_code */
+#include "lightning.h"
+
+/* SCM jitcode_vtable = NULL; */
+
+/* jit_objcode: this procedure either JITs the given object code, and returns a
+ * pointer to an scm_jit_code object with the results, or SCM_BOOL_F if it
+ * couldn't jit the code. this will most likely occur if the jitter hits an
+ * object code that it doesn't know how to translate. */
+jitf *jit_objcode(struct scm_objcode *objcode)
+{
+  /* SCM code; */
+  jitf *code;
+  jit_insn *buffer, *end;
+
+  buffer = scm_gc_calloc(32 * sizeof (jit_insn), "JIT instruction buffer");
+  if (buffer == NULL)
+    return (jitf *)SCM_BOOL_F;
+
+  /* Make a test function */
+  jit_set_ip(buffer);
+  jit_prolog(3);
+  jit_movi_p(JIT_R0, "JIT code called!\n");
+  jit_prepare(1);
+  jit_pusharg_p(JIT_R0);
+  jit_finish(printf);
+  jit_ret();
+
+  end = (jit_insn *)jit_get_ip().ptr;
+  jit_flush_code(buffer, end);
+
+  /* Make the struct */
+  /* code = scm_c_make_structv(jitcode_vtable, 1, 1, (scm_t_bits *)buffer); */
+  code = scm_gc_malloc (sizeof (jitf *), "a table of pointers to machine code");
+  if (code == NULL)
+    return (jitf *)SCM_BOOL_F;
+  
+  *code = (jitf *)buffer;
+
+  return code;
+}
+
+void scm_init_jit (void)
+{
+  /* jitcode_vtable = scm_make_vtable (scm_from_locale_string("pO"), SCM_UNDEFINED); */
+  
+  return;
+}
diff --git a/libguile/vm-jit.h b/libguile/vm-jit.h
new file mode 100644
index 0000000..8251fef
--- /dev/null
+++ b/libguile/vm-jit.h
@@ -0,0 +1,39 @@
+#ifndef _SCM_VM_JIT_H_
+#define _SCM_VM_JIT_H_
+
+#include "_scm.h"
+#include "libguile/struct.h"
+
+/* jitted code for a procedure will be stored as an array of pointers to the
+ * blocks of the machine code. the generated machine code will expect this array
+ * to be available (how?) when it is called, and all machine code branches will
+ * indirect through this array. this is done to make the code relocatable: as
+ * long as the block array points to the correct blocks, then the code can be
+ * loaded anywhere in memory. this is important because it will allow us to
+ * store the code to a .go file and mmap() it back into memory and have it still
+ * work, which will allow fast startups. if we're storing code for a procedure,
+ * the first pointer in the block array will point to the procedure entry point.
+ *
+ * a block is a basic block of the object code. it's not really a basic block
+ * from the JIT perspective, because all of the instructions are implemented as
+ * calls to C functions.
+ *
+ * (one could also implement position-independent code by only using relative
+ * branches, but it's not clear that GNU Lightning supports this, so I'll use
+ * the table method.) */
+
+typedef void (*jitf)(void *block_pointers, scm_t_uint8 **ip,
+                     SCM **sp, SCM **fp);
+
+/* the first block is number 1. */
+#define SCM_C_JITCODE_BLOCK(block_pointers, n)                           \
+  (*((block_pointers) + (n) - 1))
+  /*  SCM_STRUCT_SLOT_REF(obj, n - 1) */
+#define SCM_JITCODE_ENTER(obj, ip, sp, fp)                    \
+  ((jitf)(SCM_C_JITCODE_BLOCK(obj, 1)))(SCM_C_JITCODE_BLOCK(obj, 1), &ip, &sp, &fp)
+
+jitf *jit_objcode(struct scm_objcode *objcode);
+
+void scm_init_jit (void);
+
+#endif /* not _SCM_VM_JIT_H_ */
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-08-19 12:40 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-19  2:01 Storing JIT Code Noah Lavine
2010-08-19  5:58 ` Andy Wingo
2010-08-19 12:40   ` Noah Lavine

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).