guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] GNU Guile branch, master, updated. v2.1.0-256-gd691ac2


From: Andy Wingo
Subject: [Guile-commits] GNU Guile branch, master, updated. v2.1.0-256-gd691ac2
Date: Fri, 18 Oct 2013 16:42:43 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Guile".

http://git.savannah.gnu.org/cgit/guile.git/commit/?id=d691ac206906d2539cb94667fd10854aafc8955a

The branch, master has been updated
       via  d691ac206906d2539cb94667fd10854aafc8955a (commit)
       via  8bd261baaa96eba005517eef5fb8d5d08f22720a (commit)
       via  b0ca878cae82ebb2028783aff6e27352b70810d8 (commit)
      from  d724a36562357c86f2b4c21b46992abf9598b4d1 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit d691ac206906d2539cb94667fd10854aafc8955a
Author: Andy Wingo <address@hidden>
Date:   Fri Oct 18 18:44:11 2013 +0200

    Continuations are RTL stubs
    
    * libguile/continuations.h:
    * libguile/continuations.c: Reimplement continuations and the call_cc
      stub as RTL programs.
    
    * libguile/programs.c (scm_i_rtl_program_minimum_arity): Add a case for
      continuations.
    
    * libguile/vm-engine.c (rtl_vm_debug_engine): Always call the abort
      continuation hook with the number of non-procedure locals.  Fix
      compose-continuation argument count.  Enable call/cc.

commit 8bd261baaa96eba005517eef5fb8d5d08f22720a
Author: Andy Wingo <address@hidden>
Date:   Fri Oct 18 18:41:59 2013 +0200

    (language tree-il analyze) works better with RTL programs
    
    * module/system/vm/program.scm (program-arguments-alists): Export this
      interface.  Fall back to grovelling through procedure-minimum-arity if
      the program has no arities, as might be the case for continuations.
    
    * module/language/tree-il/analyze.scm (validate-arity): Use
      program-arguments-alists instead of the program-arities interface, to
      cover both stack VM and RTL programs.

commit b0ca878cae82ebb2028783aff6e27352b70810d8
Author: Andy Wingo <address@hidden>
Date:   Fri Oct 18 17:41:33 2013 +0200

    Foreign procedures are RTL programs
    
    * libguile/foreign.c: Convert to using RTL stubs.  Because RTL code has
      different GC characteristics than objcode -- it's mostly assumed that
      RTL code will never go away -- we go ahead and pre-generate code for
      100 arguments.  This is actually less memory than the stack VM code,
      and doesn't require any relocations at load-time: bonus!  We'll cross
      the >=100 args bridge if we ever come to it.
      (get_foreign_stub_code) New function.
      (scm_i_foreign_arity): New helper, like scm_i_primitive_arity.
      (cif_to_procedure): Rework to make RTL programs.
    
    * libguile/foreign.h: Declare scm_pointer_to_scm and
      scm_scm_to_pointer.  Declare new internal helpers.
    
    * libguile/gsubr.c (create_subr): Refactor to set the flags when the
      object is allocated.
    
    * libguile/instructions.h: Define SCM_PACK_RTL_12_12.
    
    * libguile/programs.c (scm_i_rtl_program_minimum_arity): Dispatch to
      scm_i_foreign_arity if the procedure has the FOREIGN flag.
    * libguile/programs.h (SCM_F_PROGRAM_IS_FOREIGN)
      (SCM_PROGRAM_IS_FOREIGN): New interfaces.
    
    * test-suite/tests/foreign.test ("procedure->pointer"): Add a test for
      foreign arities.

-----------------------------------------------------------------------

Summary of changes:
 libguile/continuations.c            |  120 ++++-----------------
 libguile/continuations.h            |    4 +-
 libguile/foreign.c                  |  202 ++++++++---------------------------
 libguile/foreign.h                  |    6 +-
 libguile/gsubr.c                    |    4 +-
 libguile/instructions.h             |    3 +-
 libguile/programs.c                 |   10 ++
 libguile/programs.h                 |    2 +
 libguile/vm-engine.c                |   47 +++++---
 module/language/tree-il/analyze.scm |   12 ++-
 module/system/vm/program.scm        |   16 ++-
 test-suite/tests/foreign.test       |    5 +
 12 files changed, 143 insertions(+), 288 deletions(-)

diff --git a/libguile/continuations.c b/libguile/continuations.c
index fe7618f..58a1936 100644
--- a/libguile/continuations.c
+++ b/libguile/continuations.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1998,2000,2001,2004, 2006, 2008, 2009, 2010, 2011, 
2012 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,2000,2001,2004, 2006, 2008, 2009, 2010, 2011, 
2012, 2013 Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -58,107 +58,35 @@ static scm_t_bits tc16_continuation;
 
 
 
-/* scm_i_make_continuation will return a procedure whose objcode contains an
-   instruction to reinstate the continuation. Here, as in gsubr.c and smob.c, 
we
-   define the form of that trampoline function.
+/* scm_i_make_continuation will return a procedure whose code will
+   reinstate the continuation. Here, as in gsubr.c, we define the form
+   of that trampoline function.
  */
 
-#ifdef WORDS_BIGENDIAN
-#define OBJCODE_HEADER(main,meta) 0, 0, 0, main, 0, 0, 0, meta+8
-#define META_HEADER(meta)         0, 0, 0, meta, 0, 0, 0, 0
-#else
-#define OBJCODE_HEADER(main,meta) main, 0, 0, 0, meta+8, 0, 0, 0
-#define META_HEADER(meta)         meta, 0, 0, 0, 0,      0, 0, 0
-#endif
-
-#define OBJCODE_TAG SCM_MAKE_OBJCODE_TAG (SCM_OBJCODE_TYPE_STATIC, 0)
-
-#if defined (SCM_ALIGNED) && 0
-#define SCM_DECLARE_STATIC_ALIGNED_ARRAY(type, sym)     \
-static const type sym[]
-#define SCM_STATIC_ALIGNED_ARRAY(alignment, type, sym)  \
-static SCM_ALIGNED (alignment) const type sym[]
-#define SCM_STATIC_OBJCODE(sym)                                         \
-  SCM_DECLARE_STATIC_ALIGNED_ARRAY (scm_t_uint8, sym##__bytecode);      \
-  SCM_STATIC_ALIGNED_ARRAY (8, scm_t_cell, sym##__cells) = {            \
-    { SCM_PACK (OBJCODE_TAG), SCM_PACK (sym##__bytecode) },             \
-    { SCM_BOOL_F, SCM_PACK (0) }                                        \
-  };                                                                    \
-  static const SCM sym = SCM_PACK (sym##__cells);                       \
-  SCM_STATIC_ALIGNED_ARRAY (8, scm_t_uint8, sym##__bytecode)
-#else
-#define SCM_STATIC_OBJCODE(sym)                                         \
-static SCM sym;                                                         \
-static scm_t_uint8 *sym##_bytecode;                                     \
-SCM_SNARF_INIT(sym##_bytecode = scm_gc_malloc_pointerless 
(sizeof(sym##_bytecode__unaligned), "partial continuation stub"); \
-               memcpy (sym##_bytecode, sym##_bytecode__unaligned, 
sizeof(sym##_bytecode__unaligned));) \
-SCM_SNARF_INIT(sym = scm_double_cell (OBJCODE_TAG,                      \
-                                      (scm_t_bits)sym##_bytecode,       \
-                                      SCM_UNPACK (SCM_BOOL_F),          \
-                                      0);)                              \
-static const scm_t_uint8 sym##_bytecode__unaligned[]
-#endif
+static const scm_t_uint32 continuation_stub_code[] =
+  {
+    SCM_PACK_RTL_24 (scm_rtl_op_continuation_call, 0)
+  };
 
+/* Before Scheme's call/cc is compiled, eval.c will use this hand-coded
+   call/cc. */
 
-SCM_STATIC_OBJCODE (cont_objcode) = {
-  /* This code is the same as in gsubr.c, except we use continuation_call
-     instead of subr_call. */
-  OBJCODE_HEADER (8, 19),
-  /* leave args on the stack */
-  /* 0 */ scm_op_object_ref, 0, /* push scm_t_contregs smob */
-  /* 2 */ scm_op_continuation_call, /* and longjmp (whee) */
-  /* 3 */ scm_op_nop, /* pad to 8 bytes */
-  /* 4 */ scm_op_nop, scm_op_nop, scm_op_nop, scm_op_nop,
-  /* 8 */
-
-  /* We could put some meta-info to say that this proc is a continuation. Not 
sure
-     how to do that, though. */
-  META_HEADER (19),
-  /* 0 */ scm_op_make_eol, /* bindings */
-  /* 1 */ scm_op_make_eol, /* sources */
-  /* 2 */ scm_op_make_int8, 0, scm_op_make_int8, 3, /* arity: from ip 0 to ip 
3 */
-  /* 6 */ scm_op_make_int8_0, /* the arity is 0 required args */
-  /* 7 */ scm_op_make_int8_0, /* 0 optionals */
-  /* 8 */ scm_op_make_true, /* and a rest arg */
-  /* 9 */ scm_op_list, 0, 5, /* make a list of those 5 vals */
-  /* 12 */ scm_op_list, 0, 1, /* and the arities will be a list of that one 
list */
-  /* 15 */ scm_op_list, 0, 3, /* pack bindings, sources, and arities into list 
*/
-  /* 18 */ scm_op_return /* and return */
-  /* 19 */
-};
-
-
-SCM_STATIC_OBJCODE (call_cc_objcode) = {
-  /* Before Scheme's call/cc is compiled, eval.c will use this hand-coded
-     call/cc. */
-  OBJCODE_HEADER (8, 17),
-  /* 0 */ scm_op_assert_nargs_ee, 0, 1, /* assert that nargs==1 */
-  /* 3 */ scm_op_local_ref, 0, /* push the proc */
-  /* 5 */ scm_op_tail_call_cc, /* and call/cc */
-  /* 6 */ scm_op_nop, scm_op_nop, /* pad to 8 bytes */
-  /* 8 */
-
-  META_HEADER (17),
-  /* 0 */ scm_op_make_eol, /* bindings */
-  /* 1 */ scm_op_make_eol, /* sources */
-  /* 2 */ scm_op_make_int8, 3, scm_op_make_int8, 6, /* arity: from ip 0 to ip 
6 */
-  /* 6 */ scm_op_make_int8_1, /* the arity is 0 required args */
-  /* 7 */ scm_op_list, 0, 3, /* make a list of those 5 vals */
-  /* 10 */ scm_op_list, 0, 1, /* and the arities will be a list of that one 
list */
-  /* 13 */ scm_op_list, 0, 3, /* pack bindings, sources, and arities into list 
*/
-  /* 16 */ scm_op_return /* and return */
-  /* 17 */
-};
-
+static const scm_t_uint32 call_cc_code[] =
+  {
+    SCM_PACK_RTL_24 (scm_rtl_op_assert_nargs_ee, 2),
+    SCM_PACK_RTL_24 (scm_rtl_op_call_cc, 0)
+  };
 
 static SCM
 make_continuation_trampoline (SCM contregs)
 {
-  SCM ret = scm_make_program (cont_objcode,
-                              scm_c_make_vector (1, contregs),
-                              SCM_BOOL_F);
-  SCM_SET_CELL_WORD_0 (ret,
-                       SCM_CELL_WORD_0 (ret) | SCM_F_PROGRAM_IS_CONTINUATION);
+  SCM ret;
+  scm_t_bits nfree = 1;
+  scm_t_bits flags = SCM_F_PROGRAM_IS_CONTINUATION;
+
+  ret = scm_words (scm_tc7_rtl_program | (nfree << 16) | flags, nfree + 2);
+  SCM_SET_CELL_WORD_1 (ret, continuation_stub_code);
+  SCM_RTL_PROGRAM_FREE_VARIABLE_SET (ret, 0, contregs);
 
   return ret;
 }
@@ -252,7 +180,7 @@ scm_i_call_with_current_continuation (SCM proc)
   static SCM call_cc = SCM_BOOL_F;
 
   if (scm_is_false (call_cc))
-    call_cc = scm_make_program (call_cc_objcode, SCM_BOOL_F, SCM_BOOL_F);
+    call_cc = scm_i_make_rtl_program (call_cc_code);
   
   return scm_call_1 (call_cc, proc);
 }
@@ -263,7 +191,7 @@ scm_i_continuation_to_frame (SCM continuation)
   SCM contregs;
   scm_t_contregs *cont;
 
-  contregs = scm_c_vector_ref (scm_program_objects (continuation), 0);
+  contregs = SCM_RTL_PROGRAM_FREE_VARIABLE_REF (continuation, 0);
   cont = SCM_CONTREGS (contregs);
 
   if (scm_is_true (cont->vm_cont))
diff --git a/libguile/continuations.h b/libguile/continuations.h
index 29ea1c1..e7fa16d 100644
--- a/libguile/continuations.h
+++ b/libguile/continuations.h
@@ -3,7 +3,7 @@
 #ifndef SCM_CONTINUATIONS_H
 #define SCM_CONTINUATIONS_H
 
-/* Copyright (C) 1995,1996,2000,2001, 2006, 2008, 2009, 2010, 2012 Free 
Software Foundation, Inc.
+/* Copyright (C) 1995,1996,2000,2001, 2006, 2008, 2009, 2010, 2012, 2013 Free 
Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -32,7 +32,7 @@
 
 
 #define SCM_CONTINUATIONP(x) \
-  (SCM_PROGRAM_P (x) && SCM_PROGRAM_IS_CONTINUATION (x))
+  (SCM_RTL_PROGRAM_P (x) && SCM_PROGRAM_IS_CONTINUATION (x))
 
 /* a continuation SCM is a non-immediate pointing to a heap cell with:
    word 0: bits 0-15: smob type tag: scm_tc16_continuation.
diff --git a/libguile/foreign.c b/libguile/foreign.c
index 76e43f3..ac7cf8c 100644
--- a/libguile/foreign.c
+++ b/libguile/foreign.c
@@ -763,182 +763,68 @@ SCM_DEFINE (scm_pointer_to_procedure, 
"pointer->procedure", 3, 0, 0,
 
 
 
-/* Pre-generate trampolines for less than 10 arguments. */
+/* We support calling foreign functions with up to 100 arguments. */
 
-#ifdef WORDS_BIGENDIAN
-#define OBJCODE_HEADER(M) M (0), M (0), M (0), M (8), M (0), M (0), M (0), M 
(40)
-#define META_HEADER(M)    M (0), M (0), M (0), M (32), M (0), M (0), M (0), M 
(0)
-#else
-#define OBJCODE_HEADER(M) M (8), M (0), M (0), M (0), M (40), M (0), M (0), M 
(0)
-#define META_HEADER(M)    M (32), M (0), M (0), M (0), M (0), M (0), M (0), M 
(0)
-#endif
+#define CODE(nreq)                                                  \
+  SCM_PACK_RTL_24 (scm_rtl_op_assert_nargs_ee, nreq + 1),           \
+  SCM_PACK_RTL_12_12 (scm_rtl_op_foreign_call, 0, 1)
 
-#define GEN_CODE(M, nreq)                                               \
-  OBJCODE_HEADER (M),                                                   \
-  /* 0 */ M (scm_op_assert_nargs_ee), M (0), M (nreq), /* assert number of 
args */ \
-  /* 3 */ M (scm_op_object_ref), M (0), /* push the pair with the cif and the 
function pointer */ \
-  /* 5 */ M (scm_op_foreign_call), M (nreq), /* and call (will return value as 
well) */ \
-  /* 7 */ M (scm_op_nop),                                               \
-  /* 8 */ META (M, 3, 7, nreq)
-
-#define META(M, start, end, nreq)                                       \
-  META_HEADER (M),                                                      \
-  /* 0 */ M (scm_op_make_eol), /* bindings */                           \
-  /* 1 */ M (scm_op_make_eol), /* sources */                            \
-  /* 2 */ M (scm_op_make_int8), M (start), M (scm_op_make_int8), M (end), /* 
arity: from ip N to ip N */ \
-  /* 6 */ M (scm_op_make_int8), M (nreq), /* the arity is N required args */ \
-  /* 8 */ M (scm_op_list), M (0), M (3), /* make a list of those 3 vals */ \
-  /* 11 */ M (scm_op_list), M (0), M (1), /* and the arities will be a list of 
that one list */ \
-  /* 14 */ M (scm_op_load_symbol), M (0), M (0), M (4), M ('n'), M ('a'), M 
('M'), M ('e'), /* `name' */ \
-  /* 22 */ M (scm_op_object_ref), M (1), /* the name from the object table */ \
-  /* 24 */ M (scm_op_cons), /* make a pair for the properties */        \
-  /* 25 */ M (scm_op_list), M (0), M (4), /* pack bindings, sources, and 
arities into list */ \
-  /* 28 */ M (scm_op_return), /* and return */                          \
-  /* 29 */ M (scm_op_nop), M (scm_op_nop), M (scm_op_nop)               \
-  /* 32 */
-
-#define M_STATIC(x) (x)
-#define CODE(nreq) GEN_CODE (M_STATIC, nreq)
-
-static const struct
-{
-  scm_t_uint64 dummy; /* ensure 8-byte alignment; perhaps there's a better way 
*/
-  const scm_t_uint8 bytes[10 * (sizeof (struct scm_objcode) + 8
-                                + sizeof (struct scm_objcode) + 32)];
-} raw_bytecode = {
-  0,
-  {
-    CODE (0), CODE (1), CODE (2), CODE (3), CODE (4),
-    CODE (5), CODE (6), CODE (7), CODE (8), CODE (9)
-  }
-};
+#define CODE_10(n)                                               \
+  CODE (n + 0), CODE (n + 1), CODE (n + 2), CODE (n + 3), CODE (n + 4), \
+  CODE (n + 5), CODE (n + 6), CODE (n + 7), CODE (n + 8), CODE (n + 9)
 
-static SCM
-make_objcode_trampoline (unsigned int nargs)
-{
-  const int size = sizeof (struct scm_objcode) + 8
-    + sizeof (struct scm_objcode) + 32;
-  SCM bytecode = scm_c_make_bytevector (size);
-  scm_t_uint8 *bytes = (scm_t_uint8 *) SCM_BYTEVECTOR_CONTENTS (bytecode);
-  int i = 0;
-
-#define M_DYNAMIC(x) (bytes[i++] = (x))
-  GEN_CODE (M_DYNAMIC, nargs);
-#undef M_DYNAMIC
-
-  if (i != size)
-    scm_syserror ("make_objcode_trampoline");
-  return scm_bytecode_to_objcode (bytecode, SCM_UNDEFINED);
-}
+static const scm_t_uint32 foreign_stub_code[] =
+  {
+    CODE_10 (0), CODE_10 (10), CODE_10 (20), CODE_10 (30), CODE_10 (40),
+    CODE_10 (50), CODE_10 (60), CODE_10 (70), CODE_10 (80), CODE_10 (90)
+  };
 
-#undef GEN_CODE
-#undef META
-#undef M_STATIC
 #undef CODE
-#undef OBJCODE_HEADER
-#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)))))
-*/
-#define STATIC_OBJCODE_TAG                                      \
-  SCM_PACK (SCM_MAKE_OBJCODE_TAG (SCM_OBJCODE_TYPE_STATIC, 0))
+#undef CODE_10
 
-static const struct
+static const scm_t_uint32 *
+get_foreign_stub_code (unsigned int nargs)
 {
-  scm_t_uint64 dummy; /* alignment */
-  scm_t_cell cells[10 * 2]; /* 10 double cells */
-} 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) },
-    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 56) },
-    { SCM_BOOL_F, SCM_PACK (0) },
-    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 112) },
-    { SCM_BOOL_F, SCM_PACK (0) },
-    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 168) },
-    { SCM_BOOL_F, SCM_PACK (0) },
-    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 224) },
-    { SCM_BOOL_F, SCM_PACK (0) },
-    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 280) },
-    { SCM_BOOL_F, SCM_PACK (0) },
-    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 336) },
-    { SCM_BOOL_F, SCM_PACK (0) },
-    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 392) },
-    { SCM_BOOL_F, SCM_PACK (0) },
-    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 448) },
-    { SCM_BOOL_F, SCM_PACK (0) },
-    { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 504) },
-    { SCM_BOOL_F, SCM_PACK (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+6),
-  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),
-  SCM_PACK (objcode_cells.cells+18),
-};
-
-static SCM large_objcode_trampolines = SCM_UNDEFINED;
-static scm_i_pthread_mutex_t large_objcode_trampolines_mutex =
-  SCM_I_PTHREAD_MUTEX_INITIALIZER;
+  if (nargs >= 100)
+    scm_misc_error ("make-foreign-function", "args >= 100 currently 
unimplemented",
+                    SCM_EOL);
 
-static SCM
-get_objcode_trampoline (unsigned int nargs)
+  return &foreign_stub_code[nargs * 2];
+}
+
+/* Given a foreign procedure, determine its minimum arity. */
+int
+scm_i_foreign_arity (SCM foreign, int *req, int *opt, int *rest)
 {
-  SCM objcode;
+  const scm_t_uint32 *code = SCM_RTL_PROGRAM_CODE (foreign);
 
-  if (nargs < 10)
-    objcode = objcode_trampolines[nargs];
-  else if (nargs < 128)
-    {
-      scm_i_scm_pthread_mutex_lock (&large_objcode_trampolines_mutex);
-      if (SCM_UNBNDP (large_objcode_trampolines))
-        large_objcode_trampolines = scm_c_make_vector (128, SCM_UNDEFINED);
-      objcode = scm_c_vector_ref (large_objcode_trampolines, nargs);
-      if (SCM_UNBNDP (objcode))
-        scm_c_vector_set_x (large_objcode_trampolines, nargs,
-                            objcode = make_objcode_trampoline (nargs));
-      scm_i_pthread_mutex_unlock (&large_objcode_trampolines_mutex);
-    }
-  else
-    scm_misc_error ("make-foreign-function", "args >= 128 currently 
unimplemented",
-                    SCM_EOL);
+  if (code < foreign_stub_code)
+    return 0;
+  if (code > (foreign_stub_code
+              + (sizeof(foreign_stub_code) / sizeof(scm_t_uint32))))
+    return 0;
+
+  *req = (code - foreign_stub_code) / 2;
+  *opt = 0;
+  *rest = 0;
 
-  return objcode;
+  return 1;
 }
 
 static SCM
 cif_to_procedure (SCM cif, SCM func_ptr)
 {
   ffi_cif *c_cif;
-  SCM objcode, table, ret;
+  SCM ret;
+  scm_t_bits nfree = 2;
+  scm_t_bits flags = SCM_F_PROGRAM_IS_FOREIGN;
 
   c_cif = (ffi_cif *) SCM_POINTER_VALUE (cif);
-  objcode = get_objcode_trampoline (c_cif->nargs);
-  
-  table = scm_c_make_vector (2, SCM_UNDEFINED);
-  SCM_SIMPLE_VECTOR_SET (table, 0, scm_cons (cif, func_ptr));
-  SCM_SIMPLE_VECTOR_SET (table, 1, SCM_BOOL_F); /* name */
-  ret = scm_make_program (objcode, table, SCM_BOOL_F);
+
+  ret = scm_words (scm_tc7_rtl_program | (nfree << 16) | flags, nfree + 2);
+  SCM_SET_CELL_WORD_1 (ret, get_foreign_stub_code (c_cif->nargs));
+  SCM_RTL_PROGRAM_FREE_VARIABLE_SET (ret, 0, cif);
+  SCM_RTL_PROGRAM_FREE_VARIABLE_SET (ret, 1, func_ptr);
   
   return ret;
 }
diff --git a/libguile/foreign.h b/libguile/foreign.h
index 172fa24..fbb9764 100644
--- a/libguile/foreign.h
+++ b/libguile/foreign.h
@@ -1,7 +1,7 @@
 #ifndef SCM_FOREIGN_H
 #define SCM_FOREIGN_H
 
-/* Copyright (C) 2010, 2011, 2012  Free Software Foundation, Inc.
+/* Copyright (C) 2010, 2011, 2012, 2013  Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -60,6 +60,8 @@ SCM_API SCM scm_from_pointer (void *, 
scm_t_pointer_finalizer);
 SCM_API SCM scm_alignof (SCM type);
 SCM_API SCM scm_sizeof (SCM type);
 SCM_API SCM scm_pointer_address (SCM pointer);
+SCM_API SCM scm_pointer_to_scm (SCM pointer);
+SCM_API SCM scm_scm_to_pointer (SCM scm);
 SCM_API SCM scm_pointer_to_bytevector (SCM pointer, SCM type,
                                        SCM offset, SCM len);
 SCM_API SCM scm_set_pointer_finalizer_x (SCM pointer, SCM finalizer);
@@ -96,6 +98,8 @@ SCM_API SCM scm_pointer_to_procedure (SCM return_type, SCM 
func_ptr,
 SCM_API SCM scm_procedure_to_pointer (SCM return_type, SCM func_ptr,
                                      SCM arg_types);
 SCM_INTERNAL SCM scm_i_foreign_call (SCM foreign, const SCM *argv);
+SCM_INTERNAL int scm_i_foreign_arity (SCM foreign,
+                                      int *req, int *opt, int *rest);
 
 
 
diff --git a/libguile/gsubr.c b/libguile/gsubr.c
index 4e061e3..5dd767d 100644
--- a/libguile/gsubr.c
+++ b/libguile/gsubr.c
@@ -236,10 +236,10 @@ create_subr (int define, const char *name,
 
   sname = scm_from_utf8_symbol (name);
 
-  ret = scm_words (scm_tc7_rtl_program | (nfree << 16), nfree + 2);
   flags = SCM_F_PROGRAM_IS_PRIMITIVE;
   flags |= generic_loc ? SCM_F_PROGRAM_IS_PRIMITIVE_GENERIC : 0;
-  SCM_SET_CELL_WORD_0 (ret, SCM_CELL_WORD_0 (ret) | flags);
+
+  ret = scm_words (scm_tc7_rtl_program | (nfree << 16) | flags, nfree + 2);
   SCM_SET_CELL_WORD_1 (ret, get_subr_stub_code (nreq, nopt, rest));
   SCM_RTL_PROGRAM_FREE_VARIABLE_SET (ret, 0, scm_from_pointer (fcn, NULL));
   SCM_RTL_PROGRAM_FREE_VARIABLE_SET (ret, 1, sname);
diff --git a/libguile/instructions.h b/libguile/instructions.h
index 81e7572..63bff7a 100644
--- a/libguile/instructions.h
+++ b/libguile/instructions.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2009, 2012 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2009, 2012, 2013 Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -32,6 +32,7 @@ enum scm_rtl_opcode
 #define SCM_PACK_RTL_8_8_8(op,a,b,c) ((op) | ((a) << 8) | ((b) << 16) | ((c) 
<< 24))
 #define SCM_PACK_RTL_8_16(op,a,b) ((op) | ((a) << 8) | ((b) << 16))
 #define SCM_PACK_RTL_16_8(op,a,b) ((op) | ((a) << 8) | ((b) << 24))
+#define SCM_PACK_RTL_12_12(op,a,b) ((op) | ((a) << 8) | ((b) << 20))
 #define SCM_PACK_RTL_24(op,a) ((op) | ((a) << 8))
 
 #define SCM_UNPACK_RTL_8_8_8(op,a,b,c)    \
diff --git a/libguile/programs.c b/libguile/programs.c
index c10dede..a0decdd 100644
--- a/libguile/programs.c
+++ b/libguile/programs.c
@@ -524,6 +524,16 @@ scm_i_rtl_program_minimum_arity (SCM program, int *req, 
int *opt, int *rest)
   if (SCM_PRIMITIVE_P (program))
     return scm_i_primitive_arity (program, req, opt, rest);
 
+  if (SCM_PROGRAM_IS_FOREIGN (program))
+    return scm_i_foreign_arity (program, req, opt, rest);
+
+  if (SCM_PROGRAM_IS_CONTINUATION (program))
+    {
+      *req = *opt = 0;
+      *rest = 1;
+      return 1;
+    }
+
   if (scm_is_false (rtl_program_minimum_arity) && scm_module_system_booted_p)
     rtl_program_minimum_arity =
         scm_c_private_variable ("system vm program",
diff --git a/libguile/programs.h b/libguile/programs.h
index 1ecc35d..f2518ca 100644
--- a/libguile/programs.h
+++ b/libguile/programs.h
@@ -60,6 +60,7 @@ SCM_INTERNAL SCM scm_i_rtl_program_properties (SCM program);
 #define SCM_F_PROGRAM_IS_PRIMITIVE_GENERIC 0x400
 #define SCM_F_PROGRAM_IS_CONTINUATION 0x800
 #define SCM_F_PROGRAM_IS_PARTIAL_CONTINUATION 0x1000
+#define SCM_F_PROGRAM_IS_FOREIGN 0x2000
 
 #define SCM_PROGRAM_P(x)       (SCM_HAS_TYP7 (x, scm_tc7_program))
 #define SCM_PROGRAM_OBJCODE(x) (SCM_CELL_OBJECT_1 (x))
@@ -75,6 +76,7 @@ SCM_INTERNAL SCM scm_i_rtl_program_properties (SCM program);
 #define SCM_PROGRAM_IS_PRIMITIVE_GENERIC(x) (SCM_CELL_WORD_0 (x) & 
SCM_F_PROGRAM_IS_PRIMITIVE_GENERIC)
 #define SCM_PROGRAM_IS_CONTINUATION(x) (SCM_CELL_WORD_0 (x) & 
SCM_F_PROGRAM_IS_CONTINUATION)
 #define SCM_PROGRAM_IS_PARTIAL_CONTINUATION(x) (SCM_CELL_WORD_0 (x) & 
SCM_F_PROGRAM_IS_PARTIAL_CONTINUATION)
+#define SCM_PROGRAM_IS_FOREIGN(x) (SCM_CELL_WORD_0 (x) & 
SCM_F_PROGRAM_IS_FOREIGN)
 
 SCM_API SCM scm_make_program (SCM objcode, SCM objtable, SCM free_variables);
 
diff --git a/libguile/vm-engine.c b/libguile/vm-engine.c
index 095f0bc..e2f8745 100644
--- a/libguile/vm-engine.c
+++ b/libguile/vm-engine.c
@@ -849,7 +849,7 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_)
          to pull all our state back from the ip/fp/sp.
       */
       CACHE_REGISTER ();
-      ABORT_CONTINUATION_HOOK (fp, FRAME_LOCALS_COUNT());
+      ABORT_CONTINUATION_HOOK (fp, FRAME_LOCALS_COUNT () - 1);
       NEXT (0);
     }
 
@@ -1252,7 +1252,7 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t 
nargs_)
       scm_i_check_continuation (contregs);
       vm_return_to_continuation (scm_i_contregs_vm (contregs),
                                  scm_i_contregs_vm_cont (contregs),
-                                 FRAME_LOCALS_COUNT (), fp);
+                                 FRAME_LOCALS_COUNT () - 1, fp);
       scm_i_reinstate_continuation (contregs);
 
       /* no NEXT */
@@ -1278,7 +1278,7 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t 
nargs_)
       SYNC_IP ();
       VM_ASSERT (SCM_VM_CONT_REWINDABLE_P (vmcont),
                  vm_error_continuation_not_rewindable (vmcont));
-      vm_reinstate_partial_continuation (vm, vmcont, FRAME_LOCALS_COUNT (), fp,
+      vm_reinstate_partial_continuation (vm, vmcont, FRAME_LOCALS_COUNT () - 
1, fp,
                                          &current_thread->dynstack,
                                          &registers);
       CACHE_REGISTER ();
@@ -1333,14 +1333,14 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t 
nargs_)
   /* call/cc _:24
    *
    * Capture the current continuation, and tail-apply the procedure in
-   * local slot 0 to it.  This instruction is part of the implementation
+   * local slot 1 to it.  This instruction is part of the implementation
    * of `call/cc', and is not generated by the compiler.
    */
   VM_DEFINE_OP (12, call_cc, "call/cc", OP1 (U8_X24))
-#if 0
     {
       SCM vm_cont, cont;
       scm_t_dynstack *dynstack;
+      int first;
 
       VM_HANDLE_INTERRUPTS;
 
@@ -1353,23 +1353,34 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t 
nargs_)
                                         SCM_FRAME_MV_RETURN_ADDRESS (fp),
                                         dynstack,
                                         0);
-      cont = scm_i_make_continuation (&registers, vm, vm_cont);
-
-      fp[-1] = fp[0];
-      fp[0] = cont;
-      RESET_FRAME (2);
+      /* FIXME: Seems silly to capture the registers here, when they are
+         already captured in the registers local, which here we are
+         copying out to the heap; and likewise, the setjmp(&registers)
+         code already has the non-local return handler.  But oh
+         well!  */
+      cont = scm_i_make_continuation (&first, vm, vm_cont);
+
+      if (first)
+        {
+          LOCAL_SET (0, LOCAL_REF (1));
+          LOCAL_SET (1, cont);
+          RESET_FRAME (2);
 
-      APPLY_HOOK ();
+          APPLY_HOOK ();
 
-      if (SCM_UNLIKELY (!SCM_RTL_PROGRAM_P (SCM_FRAME_PROGRAM (fp))))
-        goto apply;
+          if (SCM_UNLIKELY (!SCM_RTL_PROGRAM_P (SCM_FRAME_PROGRAM (fp))))
+            goto apply;
 
-      ip = SCM_RTL_PROGRAM_CODE (SCM_FRAME_PROGRAM (fp));
-      NEXT (0);
+          ip = SCM_RTL_PROGRAM_CODE (SCM_FRAME_PROGRAM (fp));
+          NEXT (0);
+        }
+      else
+        {
+          CACHE_REGISTER ();
+          ABORT_CONTINUATION_HOOK (fp, FRAME_LOCALS_COUNT () - 1);
+          NEXT (0);
+        }
     }
-#else
-  abort();
-#endif
 
 
   
diff --git a/module/language/tree-il/analyze.scm 
b/module/language/tree-il/analyze.scm
index 2f6e369..22287f6 100644
--- a/module/language/tree-il/analyze.scm
+++ b/module/language/tree-il/analyze.scm
@@ -950,13 +950,15 @@ given `tree-il' element."
       (or (and (or (null? x) (pair? x))
                (length x))
           0))
-    (cond ((program? proc)
+    (cond ((or (program? proc) (rtl-program? proc))
            (values (procedure-name proc)
                    (map (lambda (a)
-                          (list (arity:nreq a) (arity:nopt a) (arity:rest? a)
-                                (map car (arity:kw a))
-                                (arity:allow-other-keys? a)))
-                        (program-arities proc))))
+                          (list (length (or (assq-ref a 'required) '()))
+                                (length (or (assq-ref a 'optional) '()))
+                                (and (assq-ref a 'rest) #t)
+                                (map car (or (assq-ref a 'keyword) '()))
+                                (assq-ref a 'allow-other-keys?)))
+                        (program-arguments-alists proc))))
           ((procedure? proc)
            (if (struct? proc)
                ;; An applicable struct.
diff --git a/module/system/vm/program.scm b/module/system/vm/program.scm
index 4466504..2c8cd75 100644
--- a/module/system/vm/program.scm
+++ b/module/system/vm/program.scm
@@ -41,7 +41,8 @@
 
             arity:nreq arity:nopt arity:rest? arity:kw arity:allow-other-keys?
 
-            program-arguments-alist program-lambda-list
+            program-arguments-alist program-arguments-alists
+            program-lambda-list
 
             program-meta
             program-objcode program? program-objects
@@ -340,8 +341,9 @@
             0)))
 
 (define (program-arguments-alists prog)
-  (cond
-   ((primitive? prog)
+  "Returns all arities of the given procedure, as a list of association
+lists."
+  (define (fallback)
     (match (procedure-minimum-arity prog)
       (#f '())
       ((nreq nopt rest?)
@@ -349,9 +351,13 @@
         (arity->arguments-alist
          prog
          (list 0 0 nreq nopt rest? '(#f . ())))))))
+  (cond
+   ((primitive? prog) (fallback))
    ((rtl-program? prog)
-    (map arity-arguments-alist
-         (or (find-program-arities (rtl-program-code prog)) '())))
+    (let ((arities (find-program-arities (rtl-program-code prog))))
+      (if arities
+          (map arity-arguments-alist arities)
+          (fallback))))
    ((program? prog)
     (map (lambda (arity) (arity->arguments-alist prog arity))
          (or (program-arities prog) '())))
diff --git a/test-suite/tests/foreign.test b/test-suite/tests/foreign.test
index 8ba989e..c53c044 100644
--- a/test-suite/tests/foreign.test
+++ b/test-suite/tests/foreign.test
@@ -333,6 +333,11 @@
           (gc) (gc) (gc)
           (every (cut = <> 9)
                  (map (lambda (f) (f 2)) procs)))
+        (throw 'unresolved)))
+
+  (pass-if "arity"
+    (if (and qsort (defined? 'procedure->pointer))
+        (equal? '(4 0 #f) (procedure-minimum-arity qsort))
         (throw 'unresolved))))
 
 


hooks/post-receive
-- 
GNU Guile



reply via email to

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