guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] GNU Guile branch, stable-2.0, updated. v2.0.5-86-gf74044


From: Andy Wingo
Subject: [Guile-commits] GNU Guile branch, stable-2.0, updated. v2.0.5-86-gf740445
Date: Thu, 08 Mar 2012 14:25:36 +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=f740445a9b5bf0a5e5090f0a2ddaffb2b803bab7

The branch, stable-2.0 has been updated
       via  f740445a9b5bf0a5e5090f0a2ddaffb2b803bab7 (commit)
       via  75ba64d6797f5857cc9885eb753126119a8c8b68 (commit)
       via  7b327550e20967b0a8f89182bcf9a04543db3a0f (commit)
       via  c46fee438cf9f4a3449e8d04e7a54805517fd092 (commit)
       via  42d691ee16c7f6fd102d93f9e76d436f14198f2c (commit)
       via  46163e52e5513cf882dafe2bbd05ffbd2b03a755 (commit)
      from  be79627c21ba0848af3ac7bea25293170fec6480 (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 f740445a9b5bf0a5e5090f0a2ddaffb2b803bab7
Author: Andy Wingo <address@hidden>
Date:   Fri Feb 24 13:18:48 2012 +0100

    run finalizers asynchronously in asyncs
    
    * libguile/finalizers.c: New excitement!  We'll be running finalizers
      asynchronously, from asyncs.  This will make it safer to allocate
      while holding a mutex.
      (GC_set_finalizer_notifier): Add back-compat shim.
    
    * libguile/init.c (scm_i_init_guile): Init the async finalizer mechanism
      during boot.
    
    * libguile/gc.c (scm_storage_prehistory): Tell libgc we'll be finalizing
      on demand.
      (scm_gc): Explicitly run finalizers here.
    
    * libguile/threads.c (guilify_self_2): Run finalizers here if
      queue_finalizer_async happened to run during guilify_self_1.
    
    * configure.ac: Add check for GC_set_finalizer_notifier.

commit 75ba64d6797f5857cc9885eb753126119a8c8b68
Author: Andy Wingo <address@hidden>
Date:   Sun Feb 19 12:23:29 2012 +0100

    use the new finalizer helpers
    
    * libguile/foreign.c (scm_set_pointer_finalizer_x)
    * libguile/ports.c (finalize_port)
    * libguile/smob.c (scm_i_new_smob, scm_i_new_double_smob)
    * libguile/struct.c (scm_i_alloc_struct)
    * libguile/numbers.c (make_bignum): Use the new API.

commit 7b327550e20967b0a8f89182bcf9a04543db3a0f
Author: Andy Wingo <address@hidden>
Date:   Sun Feb 19 12:22:12 2012 +0100

    add scm_i_set_finalizer, scm_i_add_finalizer, scm_i_add_resuscitator
    
    * libguile/finalizers.h:
    * libguile/finalizers.c: New files.
    
    * libguile.h:
    * libguile/Makefile.am: Add to build.

commit c46fee438cf9f4a3449e8d04e7a54805517fd092
Author: Andy Wingo <address@hidden>
Date:   Thu May 26 16:49:47 2011 +0200

    scm_new_smob, scm_new_double_smob inline functions
    
    * libguile/smob.h (scm_new_smob, scm_new_double_smob): New constructors,
      which do what SCM_NEWSMOB / SCM_NEWSMOB3 had done, but with inline
      functions instead of macros.  They also bail to scm_i_new_smob /
      scm_i_new_double_smob in either the mark or the free case, so that the
      inline definition doesn't reference other internal details like libgc
      stuff.
      (SCM_SMOB_TYPE_MASK et al): Move definitions up so the new_smob see
      them as already being declared.
      (SCM_NEWSMOB, SCM_RETURN_NEWSMOB, SCM_NEWSMOB2, SCM_RETURN_NEWSMOB2):
      (SCM_NEWSMOB3, SCM_RETURN_NEWSMOB3): Reimplement in terms of the new
      inline functions.
    
      Remove now-unneeded bdw-gc include.
    
    * libguile/smob.c (finalize_smob): Rename from scm_i_finalize_smob, and
      make static.
      (scm_i_new_smob, scm_i_new_double_smob): Slow-path allocators.
      (scm_i_finalize_smob, scm_i_new_smob_with_mark_proc): Add
      back-compatibility shims to preserve ABI.
    
    * libguile/inline.c: Include smob.h, so as to reify scm_new_smob and
      scm_new_double_smob.

commit 42d691ee16c7f6fd102d93f9e76d436f14198f2c
Author: Andy Wingo <address@hidden>
Date:   Thu May 26 16:08:02 2011 +0200

    scm_cell, scm_double_cell, scm_words back to gc.h
    
    * libguile/inline.h:
    * libguile/gc.h (scm_cell, scm_double_cell, scm_words): Move
      declarations and definitions back here, from inline.h.  It's more
      natural.
    
    * libguile/inline.c: Include gc.h as well.

commit 46163e52e5513cf882dafe2bbd05ffbd2b03a755
Author: Andy Wingo <address@hidden>
Date:   Thu May 26 15:53:02 2011 +0200

    simplify inline function infrastructure
    
    * libguile/__scm.h (SCM_C_EXTERN_INLINE): Move this definition here,
      from inline.h.  We'd like to support inline function definitions in
      more header files: not just inline.h.
      (SCM_CAN_INLINE, SCM_INLINE, SCM_INLINE_IMPLEMENTATION): New
      definitions.
    
    * libguile/gc.h (SCM_GC_MALLOC, SCM_GC_MALLOC_POINTERLESS): Define these
      wrappers, which redirect to the GC_MALLOC macros when building Guile,
      and the scm_gc_malloc functions otherwise.  A step towards getting
      BDW-GC out of Guile's API.
    
    * libguile/inline.h: Simplify, using SCM_INLINE,
      SCM_INLINE_IMPLEMENTATION, and SCM_IMPLEMENT_INLINES.  Also use the
      new SCM_GC_MALLOC macros.

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

Summary of changes:
 configure.ac                              |    2 +-
 libguile.h                                |    3 +-
 libguile/Makefile.am                      |    4 +-
 libguile/__scm.h                          |   58 ++++++++
 libguile/finalizers.c                     |  182 ++++++++++++++++++++++++
 libguile/{debug-malloc.h => finalizers.h} |   30 ++---
 libguile/foreign.c                        |   25 +---
 libguile/gc.c                             |    6 +-
 libguile/gc.h                             |  108 ++++++++++++++
 libguile/init.c                           |    2 +
 libguile/inline.c                         |    7 +-
 libguile/inline.h                         |  216 +++-------------------------
 libguile/numbers.c                        |    8 +-
 libguile/ports.c                          |    7 +-
 libguile/smob.c                           |  101 +++++++++++---
 libguile/smob.h                           |  170 +++++++++++------------
 libguile/struct.c                         |   14 +--
 libguile/threads.c                        |    3 +
 18 files changed, 573 insertions(+), 373 deletions(-)
 create mode 100644 libguile/finalizers.c
 copy libguile/{debug-malloc.h => finalizers.h} (55%)

diff --git a/configure.ac b/configure.ac
index 66d735e..c9a443b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1232,7 +1232,7 @@ save_LIBS="$LIBS"
 LIBS="$BDW_GC_LIBS $LIBS"
 CFLAGS="$BDW_GC_CFLAGS $CFLAGS"
 
-AC_CHECK_FUNCS([GC_do_blocking GC_call_with_gc_active GC_pthread_exit 
GC_pthread_cancel GC_allow_register_threads GC_pthread_sigmask 
GC_set_start_callback GC_get_heap_usage_safe GC_get_free_space_divisor 
GC_gcollect_and_unmap GC_get_unmapped_bytes])
+AC_CHECK_FUNCS([GC_do_blocking GC_call_with_gc_active GC_pthread_exit 
GC_pthread_cancel GC_allow_register_threads GC_pthread_sigmask 
GC_set_start_callback GC_get_heap_usage_safe GC_get_free_space_divisor 
GC_gcollect_and_unmap GC_get_unmapped_bytes GC_set_finalizer_notifier])
 
 # Though the `GC_do_blocking ()' symbol is present in GC 7.1, it is not
 # declared, and has a different type (returning void instead of
diff --git a/libguile.h b/libguile.h
index 2c10d05..fefca43 100644
--- a/libguile.h
+++ b/libguile.h
@@ -1,7 +1,7 @@
 #ifndef SCM_LIBGUILE_H
 #define SCM_LIBGUILE_H
 
-/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2002, 2003, 2004, 2006, 2008, 
2009, 2010, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2002, 2003, 2004, 2006, 2008, 
2009, 2010, 2011, 2012 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
@@ -49,6 +49,7 @@ extern "C" {
 #include "libguile/extensions.h"
 #include "libguile/feature.h"
 #include "libguile/filesys.h"
+#include "libguile/finalizers.h"
 #include "libguile/fluids.h"
 #include "libguile/foreign.h"
 #include "libguile/fports.h"
diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index c181b99..be430bf 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -1,6 +1,6 @@
 ## Process this file with Automake to create Makefile.in
 ##
-##     Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 
2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+##     Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 
2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
 ##
 ##   This file is part of GUILE.
 ##
@@ -142,6 +142,7 @@ address@hidden@_la_SOURCES =                                
\
        extensions.c                            \
        feature.c                               \
        filesys.c                               \
+       finalizers.c                            \
        fluids.c                                \
        foreign.c                               \
        fports.c                                \
@@ -530,6 +531,7 @@ modinclude_HEADERS =                                \
        expand.h                                \
        extensions.h                            \
        feature.h                               \
+       finalizers.h                            \
        filesys.h                               \
        fluids.h                                \
        foreign.h                               \
diff --git a/libguile/__scm.h b/libguile/__scm.h
index c4f2a1a..68ababd 100644
--- a/libguile/__scm.h
+++ b/libguile/__scm.h
@@ -192,6 +192,64 @@
 
 
 
+/* We would like gnu89 extern inline semantics, not C99 extern inline
+   semantics, so that we can be sure to avoid reifying definitions of
+   inline functions in all compilation units, which is a possibility at
+   low optimization levels, or if a user takes the address of an inline
+   function.
+
+   Hence the `__gnu_inline__' attribute, in accordance with:
+   http://gcc.gnu.org/gcc-4.3/porting_to.html .
+
+   With GCC 4.2, `__GNUC_STDC_INLINE__' is never defined (because C99 inline
+   semantics are not supported), but a warning is issued in C99 mode if
+   `__gnu_inline__' is not used.
+
+   Apple's GCC build >5400 (since Xcode 3.0) doesn't support GNU inline in
+   C99 mode and doesn't define `__GNUC_STDC_INLINE__'.  Fall back to "static
+   inline" in that case.  */
+
+# if (defined __GNUC__) && (!(((defined __APPLE_CC__) && (__APPLE_CC__ > 
5400)) && __STDC_VERSION__ >= 199901L))
+#  if (defined __GNUC_STDC_INLINE__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 2)
+#   define SCM_C_EXTERN_INLINE                                 \
+           extern __inline__ __attribute__ ((__gnu_inline__))
+#  else
+#   define SCM_C_EXTERN_INLINE extern __inline__
+#  endif
+# endif
+
+/* SCM_INLINE is a macro prepended to all public inline function
+   declarations.  Implementations of those functions should also be in
+   the header file, prefixed by SCM_INLINE_IMPLEMENTATION, and protected
+   by SCM_CAN_INLINE and a CPP define for the C file in question, like
+   SCM_INLINE_C_INCLUDING_INLINE_H.  See inline.h for an example
+   usage.  */
+
+#if defined SCM_IMPLEMENT_INLINES
+/* Reifying functions to a file, whether or not inlining is available.  */
+# define SCM_CAN_INLINE 0
+# define SCM_INLINE SCM_API
+# define SCM_INLINE_IMPLEMENTATION
+#elif defined SCM_C_INLINE
+/* Declarations when inlining is available.  */
+# define SCM_CAN_INLINE 1
+# ifdef SCM_C_EXTERN_INLINE
+#  define SCM_INLINE SCM_C_EXTERN_INLINE
+# else
+/* Fall back to static inline if GNU "extern inline" is unavailable.  */
+#  define SCM_INLINE static SCM_C_INLINE
+# endif
+# define SCM_INLINE_IMPLEMENTATION SCM_INLINE
+#else
+/* Declarations when inlining is not available.  */
+# define SCM_CAN_INLINE 0
+# define SCM_INLINE SCM_API
+/* Don't define SCM_INLINE_IMPLEMENTATION; it should never be seen in
+   this case.  */
+#endif
+
+
+
 /* {Debugging Options}
  *
  * These compile time options determine whether to include code that is only
diff --git a/libguile/finalizers.c b/libguile/finalizers.c
new file mode 100644
index 0000000..295f977
--- /dev/null
+++ b/libguile/finalizers.c
@@ -0,0 +1,182 @@
+/* Copyright (C) 2012 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
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libguile/bdw-gc.h"
+#include "libguile/_scm.h"
+#include "libguile/finalizers.h"
+#include "libguile/gc.h"
+#include "libguile/threads.h"
+
+
+
+static size_t finalization_count;
+
+
+
+
+void
+scm_i_set_finalizer (void *obj, scm_t_finalizer_proc proc, void *data)
+{
+  GC_finalization_proc prev;
+  GC_PTR prev_data;
+  GC_REGISTER_FINALIZER_NO_ORDER (obj, proc, data, &prev, &prev_data);
+}
+
+struct scm_t_chained_finalizer
+{
+  int resuscitating_p;
+  scm_t_finalizer_proc proc;
+  void *data;
+  scm_t_finalizer_proc prev;
+  void *prev_data;
+};
+
+static void
+chained_finalizer (void *obj, void *data)
+{
+  struct scm_t_chained_finalizer *chained_data = data;
+  if (chained_data->resuscitating_p)
+    {
+      if (chained_data->prev)
+        scm_i_set_finalizer (obj, chained_data->prev, chained_data->prev_data);
+      chained_data->proc (obj, chained_data->data);
+    }
+  else
+    {
+      chained_data->proc (obj, chained_data->data);
+      if (chained_data->prev)
+        chained_data->prev (obj, chained_data->prev_data);
+    }
+}
+
+void
+scm_i_add_resuscitator (void *obj, scm_t_finalizer_proc proc, void *data)
+{
+  struct scm_t_chained_finalizer *chained_data;
+  chained_data = scm_gc_malloc (sizeof (*chained_data), "chained finalizer");
+  chained_data->resuscitating_p = 1;
+  chained_data->proc = proc;
+  chained_data->data = data;
+  GC_REGISTER_FINALIZER_NO_ORDER (obj, chained_finalizer, chained_data,
+                                  &chained_data->prev,
+                                  &chained_data->prev_data);
+}
+
+static void
+shuffle_resuscitators_to_front (struct scm_t_chained_finalizer *cd)
+{
+  while (cd->prev == chained_finalizer)
+    {
+      struct scm_t_chained_finalizer *prev = cd->prev_data;
+      scm_t_finalizer_proc proc = cd->proc;
+      void *data = cd->data;
+
+      if (!prev->resuscitating_p)
+        break;
+
+      cd->resuscitating_p = 1;
+      cd->proc = prev->proc;
+      cd->data = prev->data;
+
+      prev->resuscitating_p = 0;
+      prev->proc = proc;
+      prev->data = data;
+
+      cd = prev;
+    }
+}
+
+void
+scm_i_add_finalizer (void *obj, scm_t_finalizer_proc proc, void *data)
+{
+  struct scm_t_chained_finalizer *chained_data;
+  chained_data = scm_gc_malloc (sizeof (*chained_data), "chained finalizer");
+  chained_data->resuscitating_p = 0;
+  chained_data->proc = proc;
+  chained_data->data = data;
+  GC_REGISTER_FINALIZER_NO_ORDER (obj, chained_finalizer, chained_data,
+                                  &chained_data->prev,
+                                  &chained_data->prev_data);
+  shuffle_resuscitators_to_front (chained_data);
+}
+
+
+
+
+static SCM finalizer_async_cell;
+
+static SCM
+run_finalizers_async_thunk (void)
+{
+  finalization_count += GC_invoke_finalizers ();
+  return SCM_UNSPECIFIED;
+}
+
+
+/* The function queue_finalizer_async is run by the GC when there are
+ * objects to finalize.  It will enqueue an asynchronous call to
+ * GC_invoke_finalizers() at the next SCM_TICK in this thread.
+ */
+static void
+queue_finalizer_async (void)
+{
+  scm_i_thread *t = SCM_I_CURRENT_THREAD;
+  static scm_i_pthread_mutex_t lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
+
+  scm_i_pthread_mutex_lock (&lock);
+  /* If t is NULL, that could be because we're allocating in
+     threads.c:guilify_self_1.  In that case, rely on the
+     GC_invoke_finalizers call there after the thread spins up.  */
+  if (t && scm_is_false (SCM_CDR (finalizer_async_cell)))
+    {
+      SCM_SETCDR (finalizer_async_cell, t->active_asyncs);
+      t->active_asyncs = finalizer_async_cell;
+      t->pending_asyncs = 1;
+    }
+  scm_i_pthread_mutex_unlock (&lock);
+}
+
+
+
+
+#ifndef HAVE_GC_SET_FINALIZER_NOTIFIER
+static void
+GC_set_finalizer_notifier (void (*notifier) (void))
+{
+  GC_finalizer_notifier = notifier;
+}
+#endif
+
+void
+scm_init_finalizers (void)
+{
+  /* When the async is to run, the cdr of the pair gets set to the
+     asyncs queue of the current thread.  */
+  finalizer_async_cell =
+    scm_cons (scm_c_make_gsubr ("%run-finalizers", 0, 0, 0,
+                                run_finalizers_async_thunk),
+              SCM_BOOL_F);
+  GC_set_finalizer_notifier (queue_finalizer_async);
+}
diff --git a/libguile/debug-malloc.h b/libguile/finalizers.h
similarity index 55%
copy from libguile/debug-malloc.h
copy to libguile/finalizers.h
index 7830adb..bad96e1 100644
--- a/libguile/debug-malloc.h
+++ b/libguile/finalizers.h
@@ -1,9 +1,7 @@
-/* classes: h_files */
+#ifndef SCM_FINALIZERS_H
+#define SCM_FINALIZERS_H
 
-#ifndef SCM_DEBUG_MALLOC_H
-#define SCM_DEBUG_MALLOC_H
-
-/* Copyright (C) 2000,2001, 2006, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 2012 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
@@ -27,19 +25,15 @@
 
 
 
-SCM_API void scm_malloc_register (void *obj, const char *what);
-SCM_API void scm_malloc_unregister (void *obj);
-SCM_API void scm_malloc_reregister (void *obj, void *new, const char *what);
-
-SCM_API SCM scm_malloc_stats (void);
+typedef void (*scm_t_finalizer_proc) (void *obj, void *data);
 
-SCM_INTERNAL void scm_debug_malloc_prehistory (void);
-SCM_INTERNAL void scm_init_debug_malloc (void);
+SCM_INTERNAL void scm_i_set_finalizer (void *obj, scm_t_finalizer_proc,
+                                       void *data);
+SCM_INTERNAL void scm_i_add_finalizer (void *obj, scm_t_finalizer_proc,
+                                       void *data);
+SCM_INTERNAL void scm_i_add_resuscitator (void *obj, scm_t_finalizer_proc,
+                                          void *data);
 
-#endif  /* SCM_DEBUG_MALLOC_H */
+SCM_INTERNAL void scm_init_finalizers (void);
 
-/*
-  Local Variables:
-  c-file-style: "gnu"
-  End:
-*/
+#endif  /* SCM_FINALIZERS_H */
diff --git a/libguile/foreign.c b/libguile/foreign.c
index b3d1cc6..f1d9607 100644
--- a/libguile/foreign.c
+++ b/libguile/foreign.c
@@ -160,16 +160,8 @@ scm_from_pointer (void *ptr, scm_t_pointer_finalizer 
finalizer)
       ret = scm_cell (scm_tc7_pointer, (scm_t_bits) ptr);
 
       if (finalizer)
-       {
-         /* Register a finalizer for the newly created instance.  */
-         GC_finalization_proc prev_finalizer;
-         GC_PTR prev_finalizer_data;
-         GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (ret),
-                                         pointer_finalizer_trampoline,
-                                         finalizer,
-                                         &prev_finalizer,
-                                         &prev_finalizer_data);
-       }
+        scm_i_set_finalizer (SCM2PTR (ret), pointer_finalizer_trampoline,
+                             finalizer);
     }
 
   return ret;
@@ -319,20 +311,11 @@ SCM_DEFINE (scm_set_pointer_finalizer_x, 
"set-pointer-finalizer!", 2, 0, 0,
             "Scheme. If you need a Scheme finalizer, use guardians.")
 #define FUNC_NAME s_scm_set_pointer_finalizer_x
 {
-  void *c_finalizer;
-  GC_finalization_proc prev_finalizer;
-  GC_PTR prev_finalizer_data;
-
   SCM_VALIDATE_POINTER (1, pointer);
   SCM_VALIDATE_POINTER (2, finalizer);
 
-  c_finalizer = SCM_POINTER_VALUE (finalizer);
-
-  GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (pointer),
-                                  pointer_finalizer_trampoline,
-                                  c_finalizer,
-                                  &prev_finalizer,
-                                  &prev_finalizer_data);
+  scm_i_add_finalizer (SCM2PTR (pointer), pointer_finalizer_trampoline,
+                       SCM_POINTER_VALUE (finalizer));
 
   return SCM_UNSPECIFIED;
 }
diff --git a/libguile/gc.c b/libguile/gc.c
index fd37046..b1f1605 100644
--- a/libguile/gc.c
+++ b/libguile/gc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2006, 2008, 
2009, 2010, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2006, 2008, 
2009, 2010, 2011, 2012 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
@@ -391,6 +391,9 @@ SCM_DEFINE (scm_gc, "gc", 0, 0, 0,
 #define FUNC_NAME s_scm_gc
 {
   scm_i_gc ("call");
+  /* If you're calling scm_gc(), you probably want synchronous
+     finalization.  */
+  GC_invoke_finalizers ();
   return SCM_UNSPECIFIED;
 }
 #undef FUNC_NAME
@@ -623,6 +626,7 @@ scm_storage_prehistory ()
   minimum_free_space_divisor = free_space_divisor;
   target_free_space_divisor = free_space_divisor;
   GC_set_free_space_divisor (free_space_divisor);
+  GC_set_finalize_on_demand (1);
 
   GC_INIT ();
 
diff --git a/libguile/gc.h b/libguile/gc.h
index 310569d..9f00e01 100644
--- a/libguile/gc.h
+++ b/libguile/gc.h
@@ -207,6 +207,114 @@ SCM_API char *scm_gc_strdup (const char *str, const char 
*what)
 SCM_API char *scm_gc_strndup (const char *str, size_t n, const char *what)
   SCM_MALLOC;
 
+
+#ifdef BUILDING_LIBGUILE
+#include "libguile/bdw-gc.h"
+#define SCM_GC_MALLOC(size) GC_MALLOC (size)
+#define SCM_GC_MALLOC_POINTERLESS(size) GC_MALLOC_ATOMIC (size)
+#else
+#define SCM_GC_MALLOC(size) scm_gc_malloc (size, NULL)
+#define SCM_GC_MALLOC_POINTERLESS(size) scm_gc_malloc_pointerless (size, NULL)
+#endif
+
+
+SCM_INLINE SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
+SCM_INLINE SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
+                            scm_t_bits ccr, scm_t_bits cdr);
+SCM_INLINE SCM scm_words (scm_t_bits car, scm_t_uint16 n_words);
+
+#if SCM_CAN_INLINE || defined SCM_INLINE_C_IMPLEMENTING_INLINES
+
+SCM_INLINE_IMPLEMENTATION SCM
+scm_cell (scm_t_bits car, scm_t_bits cdr)
+{
+  SCM cell = PTR2SCM (SCM_GC_MALLOC (sizeof (scm_t_cell)));
+
+  /* Initialize the type slot last so that the cell is ignored by the GC
+     until it is completely initialized.  This is only relevant when the GC
+     can actually run during this code, which it can't since the GC only runs
+     when all other threads are stopped.  */
+  SCM_GC_SET_CELL_WORD (cell, 1, cdr);
+  SCM_GC_SET_CELL_WORD (cell, 0, car);
+
+  return cell;
+}
+
+SCM_INLINE_IMPLEMENTATION SCM
+scm_double_cell (scm_t_bits car, scm_t_bits cbr,
+                scm_t_bits ccr, scm_t_bits cdr)
+{
+  SCM z;
+
+  z = PTR2SCM (SCM_GC_MALLOC (2 * sizeof (scm_t_cell)));
+  /* Initialize the type slot last so that the cell is ignored by the
+     GC until it is completely initialized.  This is only relevant
+     when the GC can actually run during this code, which it can't
+     since the GC only runs when all other threads are stopped.
+  */
+  SCM_GC_SET_CELL_WORD (z, 1, cbr);
+  SCM_GC_SET_CELL_WORD (z, 2, ccr);
+  SCM_GC_SET_CELL_WORD (z, 3, cdr);
+  SCM_GC_SET_CELL_WORD (z, 0, car);
+
+  /* When this function is inlined, it's possible that the last
+     SCM_GC_SET_CELL_WORD above will be adjacent to a following
+     initialization of z.  E.g., it occurred in scm_make_real.  GCC
+     from around version 3 (e.g., certainly 3.2) began taking
+     advantage of strict C aliasing rules which say that it's OK to
+     interchange the initialization above and the one below when the
+     pointer types appear to differ sufficiently.  We don't want that,
+     of course.  GCC allows this behaviour to be disabled with the
+     -fno-strict-aliasing option, but would also need to be supplied
+     by Guile users.  Instead, the following statements prevent the
+     reordering.
+   */
+#ifdef __GNUC__
+  __asm__ volatile ("" : : : "memory");
+#else
+  /* portable version, just in case any other compiler does the same
+     thing.  */
+  scm_remember_upto_here_1 (z);
+#endif
+
+  return z;
+}
+
+SCM_INLINE_IMPLEMENTATION SCM
+scm_words (scm_t_bits car, scm_t_uint16 n_words)
+{
+  SCM z;
+
+  z = PTR2SCM (SCM_GC_MALLOC (sizeof (scm_t_bits) * n_words));
+  SCM_GC_SET_CELL_WORD (z, 0, car);
+
+  /* FIXME: is the following concern even relevant with BDW-GC? */
+
+  /* When this function is inlined, it's possible that the last
+     SCM_GC_SET_CELL_WORD above will be adjacent to a following
+     initialization of z.  E.g., it occurred in scm_make_real.  GCC
+     from around version 3 (e.g., certainly 3.2) began taking
+     advantage of strict C aliasing rules which say that it's OK to
+     interchange the initialization above and the one below when the
+     pointer types appear to differ sufficiently.  We don't want that,
+     of course.  GCC allows this behaviour to be disabled with the
+     -fno-strict-aliasing option, but would also need to be supplied
+     by Guile users.  Instead, the following statements prevent the
+     reordering.
+   */
+#ifdef __GNUC__
+  __asm__ volatile ("" : : : "memory");
+#else
+  /* portable version, just in case any other compiler does the same
+     thing.  */
+  scm_remember_upto_here_1 (z);
+#endif
+
+  return z;
+}
+
+#endif /* SCM_CAN_INLINE || defined SCM_INLINE_C_IMPLEMENTING_INLINES */
+
 SCM_API void scm_remember_upto_here_1 (SCM obj);
 SCM_API void scm_remember_upto_here_2 (SCM obj1, SCM obj2);
 SCM_API void scm_remember_upto_here (SCM obj1, ...);
diff --git a/libguile/init.c b/libguile/init.c
index a086211..17791e2 100644
--- a/libguile/init.c
+++ b/libguile/init.c
@@ -59,6 +59,7 @@
 #include "libguile/expand.h"
 #include "libguile/feature.h"
 #include "libguile/filesys.h"
+#include "libguile/finalizers.h"
 #include "libguile/fluids.h"
 #include "libguile/fports.h"
 #include "libguile/frames.h"
@@ -423,6 +424,7 @@ scm_i_init_guile (void *base)
   scm_init_dynwind ();            /* requires smob_prehistory */
   scm_init_eq ();
   scm_init_error ();
+  scm_init_finalizers ();
   scm_init_fluids ();
   scm_init_control ();            /* requires fluids */
   scm_init_feature ();
diff --git a/libguile/inline.c b/libguile/inline.c
index 79728ff..be7670a 100644
--- a/libguile/inline.c
+++ b/libguile/inline.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2006, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2006, 2008, 2011 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
@@ -20,5 +20,8 @@
 # include <config.h>
 #endif
 
-#define SCM_INLINE_C_INCLUDING_INLINE_H 1
+#define SCM_IMPLEMENT_INLINES 1
+#define SCM_INLINE_C_IMPLEMENTING_INLINES 1
 #include "libguile/inline.h"
+#include "libguile/gc.h"
+#include "libguile/smob.h"
diff --git a/libguile/inline.h b/libguile/inline.h
index a78cac5..6b1cf5e 100644
--- a/libguile/inline.h
+++ b/libguile/inline.h
@@ -23,9 +23,9 @@
  */
 
 /* This file is for inline functions.  On platforms that don't support
-   inlining functions, they are turned into ordinary functions.  See
-   "inline.c".
-*/
+   inlining functions, they are turned into ordinary functions.  On
+   platforms that do support inline functions, the definitions are still
+   compiled into the library, once, in inline.c.  */
 
 #include <stdio.h>
 #include <string.h>
@@ -41,174 +41,27 @@
 #include "libguile/error.h"
 
 
-#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
+SCM_INLINE SCM scm_array_handle_ref (scm_t_array_handle *h, ssize_t pos);
+SCM_INLINE void scm_array_handle_set (scm_t_array_handle *h, ssize_t pos, SCM 
val);
 
-/* GCC has `__inline__' in all modes, including strict ansi.  GCC 4.3 and
-   above with `-std=c99' or `-std=gnu99' implements ISO C99 inline semantics,
-   unless `-fgnu89-inline' is used.  Here we want GNU "extern inline"
-   semantics, hence the `__gnu_inline__' attribute, in accordance with:
-   http://gcc.gnu.org/gcc-4.3/porting_to.html .
+SCM_INLINE int scm_is_pair (SCM x);
+SCM_INLINE int scm_is_string (SCM x);
 
-   With GCC 4.2, `__GNUC_STDC_INLINE__' is never defined (because C99 inline
-   semantics are not supported), but a warning is issued in C99 mode if
-   `__gnu_inline__' is not used.
+SCM_INLINE int scm_get_byte_or_eof (SCM port);
+SCM_INLINE int scm_peek_byte_or_eof (SCM port);
+SCM_INLINE void scm_putc (char c, SCM port);
+SCM_INLINE void scm_puts (const char *str_data, SCM port);
 
-   Apple's GCC build >5400 (since Xcode 3.0) doesn't support GNU inline in
-   C99 mode and doesn't define `__GNUC_STDC_INLINE__'.  Fall back to "static
-   inline" in that case.  */
 
-# if (defined __GNUC__) && (!(((defined __APPLE_CC__) && (__APPLE_CC__ > 
5400)) && __STDC_VERSION__ >= 199901L))
-#  define SCM_C_USE_EXTERN_INLINE 1
-#  if (defined __GNUC_STDC_INLINE__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 2)
-#   define SCM_C_EXTERN_INLINE                                 \
-           extern __inline__ __attribute__ ((__gnu_inline__))
-#  else
-#   define SCM_C_EXTERN_INLINE extern __inline__
-#  endif
-# elif (defined SCM_C_INLINE)
-#  define SCM_C_EXTERN_INLINE static SCM_C_INLINE
-# endif
-
-#endif /* SCM_INLINE_C_INCLUDING_INLINE_H */
-
-
-#if (!defined SCM_C_INLINE) || (defined SCM_INLINE_C_INCLUDING_INLINE_H) \
-    || (defined SCM_C_USE_EXTERN_INLINE)
-
-/* The `extern' declarations.  They should only appear when used from
-   "inline.c", when `inline' is not supported at all or when "extern inline"
-   is used.  */
-
-#include "libguile/bdw-gc.h"
-
-
-SCM_API SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
-SCM_API SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
+SCM_INLINE SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
+SCM_INLINE SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
                             scm_t_bits ccr, scm_t_bits cdr);
-SCM_API SCM scm_words (scm_t_bits car, scm_t_uint16 n_words);
-
-SCM_API SCM scm_array_handle_ref (scm_t_array_handle *h, ssize_t pos);
-SCM_API void scm_array_handle_set (scm_t_array_handle *h, ssize_t pos, SCM 
val);
-
-SCM_API int scm_is_pair (SCM x);
-SCM_API int scm_is_string (SCM x);
-
-SCM_API int scm_get_byte_or_eof (SCM port);
-SCM_API int scm_peek_byte_or_eof (SCM port);
-SCM_API void scm_putc (char c, SCM port);
-SCM_API void scm_puts (const char *str_data, SCM port);
-
-#endif
-
-
-#if defined SCM_C_EXTERN_INLINE || defined SCM_INLINE_C_INCLUDING_INLINE_H
-/* either inlining, or being included from inline.c.  We use (and
-   repeat) this long #if test here and below so that we don't have to
-   introduce any extraneous symbols into the public namespace.  We
-   only need SCM_C_INLINE to be seen publically . */
-
-#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
-SCM_C_EXTERN_INLINE
-#endif
-
-SCM
-scm_cell (scm_t_bits car, scm_t_bits cdr)
-{
-  SCM cell = PTR2SCM (GC_MALLOC (sizeof (scm_t_cell)));
-
-  /* Initialize the type slot last so that the cell is ignored by the GC
-     until it is completely initialized.  This is only relevant when the GC
-     can actually run during this code, which it can't since the GC only runs
-     when all other threads are stopped.  */
-  SCM_GC_SET_CELL_WORD (cell, 1, cdr);
-  SCM_GC_SET_CELL_WORD (cell, 0, car);
-
-  return cell;
-}
-
-#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
-SCM_C_EXTERN_INLINE
-#endif
-SCM
-scm_double_cell (scm_t_bits car, scm_t_bits cbr,
-                scm_t_bits ccr, scm_t_bits cdr)
-{
-  SCM z;
-
-  z = PTR2SCM (GC_MALLOC (2 * sizeof (scm_t_cell)));
-  /* Initialize the type slot last so that the cell is ignored by the
-     GC until it is completely initialized.  This is only relevant
-     when the GC can actually run during this code, which it can't
-     since the GC only runs when all other threads are stopped.
-  */
-  SCM_GC_SET_CELL_WORD (z, 1, cbr);
-  SCM_GC_SET_CELL_WORD (z, 2, ccr);
-  SCM_GC_SET_CELL_WORD (z, 3, cdr);
-  SCM_GC_SET_CELL_WORD (z, 0, car);
-
-  /* When this function is inlined, it's possible that the last
-     SCM_GC_SET_CELL_WORD above will be adjacent to a following
-     initialization of z.  E.g., it occurred in scm_make_real.  GCC
-     from around version 3 (e.g., certainly 3.2) began taking
-     advantage of strict C aliasing rules which say that it's OK to
-     interchange the initialization above and the one below when the
-     pointer types appear to differ sufficiently.  We don't want that,
-     of course.  GCC allows this behaviour to be disabled with the
-     -fno-strict-aliasing option, but would also need to be supplied
-     by Guile users.  Instead, the following statements prevent the
-     reordering.
-   */
-#ifdef __GNUC__
-  __asm__ volatile ("" : : : "memory");
-#else
-  /* portable version, just in case any other compiler does the same
-     thing.  */
-  scm_remember_upto_here_1 (z);
-#endif
-
-  return z;
-}
-
-#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
-SCM_C_EXTERN_INLINE
-#endif
-SCM
-scm_words (scm_t_bits car, scm_t_uint16 n_words)
-{
-  SCM z;
-
-  z = PTR2SCM (GC_MALLOC (sizeof (scm_t_bits) * n_words));
-  SCM_GC_SET_CELL_WORD (z, 0, car);
-
-  /* FIXME: is the following concern even relevant with BDW-GC? */
-
-  /* When this function is inlined, it's possible that the last
-     SCM_GC_SET_CELL_WORD above will be adjacent to a following
-     initialization of z.  E.g., it occurred in scm_make_real.  GCC
-     from around version 3 (e.g., certainly 3.2) began taking
-     advantage of strict C aliasing rules which say that it's OK to
-     interchange the initialization above and the one below when the
-     pointer types appear to differ sufficiently.  We don't want that,
-     of course.  GCC allows this behaviour to be disabled with the
-     -fno-strict-aliasing option, but would also need to be supplied
-     by Guile users.  Instead, the following statements prevent the
-     reordering.
-   */
-#ifdef __GNUC__
-  __asm__ volatile ("" : : : "memory");
-#else
-  /* portable version, just in case any other compiler does the same
-     thing.  */
-  scm_remember_upto_here_1 (z);
-#endif
+SCM_INLINE SCM scm_words (scm_t_bits car, scm_t_uint16 n_words);
 
-  return z;
-}
+#if SCM_CAN_INLINE || defined SCM_INLINE_C_IMPLEMENTING_INLINES
+/* Either inlining, or being included from inline.c.  */
 
-#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
-SCM_C_EXTERN_INLINE
-#endif
-SCM
+SCM_INLINE_IMPLEMENTATION SCM
 scm_array_handle_ref (scm_t_array_handle *h, ssize_t p)
 {
   if (SCM_UNLIKELY (p < 0 && ((size_t)-p) > h->base))
@@ -218,10 +71,7 @@ scm_array_handle_ref (scm_t_array_handle *h, ssize_t p)
   return h->impl->vref (h, h->base + p);
 }
 
-#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
-SCM_C_EXTERN_INLINE
-#endif
-void
+SCM_INLINE_IMPLEMENTATION void
 scm_array_handle_set (scm_t_array_handle *h, ssize_t p, SCM v)
 {
   if (SCM_UNLIKELY (p < 0 && ((size_t)-p) > h->base))
@@ -231,10 +81,7 @@ scm_array_handle_set (scm_t_array_handle *h, ssize_t p, SCM 
v)
   h->impl->vset (h, h->base + p, v);
 }
 
-#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
-SCM_C_EXTERN_INLINE
-#endif
-int
+SCM_INLINE_IMPLEMENTATION int
 scm_is_pair (SCM x)
 {
   /* The following "workaround_for_gcc_295" avoids bad code generated by
@@ -261,10 +108,7 @@ scm_is_pair (SCM x)
   return SCM_I_CONSP (x);
 }
 
-#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
-SCM_C_EXTERN_INLINE
-#endif
-int
+SCM_INLINE_IMPLEMENTATION int
 scm_is_string (SCM x)
 {
   return SCM_NIMP (x) && (SCM_TYP7 (x) == scm_tc7_string);
@@ -272,10 +116,7 @@ scm_is_string (SCM x)
 
 /* Port I/O.  */
 
-#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
-SCM_C_EXTERN_INLINE
-#endif
-int
+SCM_INLINE_IMPLEMENTATION int
 scm_get_byte_or_eof (SCM port)
 {
   int c;
@@ -300,10 +141,7 @@ scm_get_byte_or_eof (SCM port)
 }
 
 /* Like `scm_get_byte_or_eof' but does not change PORT's `read_pos'.  */
-#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
-SCM_C_EXTERN_INLINE
-#endif
-int
+SCM_INLINE_IMPLEMENTATION int
 scm_peek_byte_or_eof (SCM port)
 {
   int c;
@@ -327,20 +165,14 @@ scm_peek_byte_or_eof (SCM port)
   return c;
 }
 
-#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
-SCM_C_EXTERN_INLINE
-#endif
-void
+SCM_INLINE_IMPLEMENTATION void
 scm_putc (char c, SCM port)
 {
   SCM_ASSERT_TYPE (SCM_OPOUTPORTP (port), port, 0, NULL, "output port");
   scm_lfwrite (&c, 1, port);
 }
 
-#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
-SCM_C_EXTERN_INLINE
-#endif
-void
+SCM_INLINE_IMPLEMENTATION void
 scm_puts (const char *s, SCM port)
 {
   SCM_ASSERT_TYPE (SCM_OPOUTPORTP (port), port, 0, NULL, "output port");
diff --git a/libguile/numbers.c b/libguile/numbers.c
index 25e9533..0173aee 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005, 2006, 
2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005, 2006, 
2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
  *
  * Portions Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories
  * and Bellcore.  See scm_divide.
@@ -217,17 +217,13 @@ static inline SCM
 make_bignum (void)
 {
   scm_t_bits *p;
-  GC_finalization_proc prev_finalizer;
-  GC_PTR prev_finalizer_data;
 
   /* Allocate one word for the type tag and enough room for an `mpz_t'.  */
   p = scm_gc_malloc_pointerless (sizeof (scm_t_bits) + sizeof (mpz_t),
                                 "bignum");
   p[0] = scm_tc16_big;
 
-  GC_REGISTER_FINALIZER_NO_ORDER (p, finalize_bignum, NULL,
-                                 &prev_finalizer,
-                                 &prev_finalizer_data);
+  scm_i_set_finalizer (p, finalize_bignum, NULL);
 
   return SCM_PACK (p);
 }
diff --git a/libguile/ports.c b/libguile/ports.c
index 12efce8..2d8b9ed 100644
--- a/libguile/ports.c
+++ b/libguile/ports.c
@@ -546,14 +546,9 @@ static void finalize_port (GC_PTR, GC_PTR);
 static SCM_C_INLINE_KEYWORD void
 register_finalizer_for_port (SCM port)
 {
-  GC_finalization_proc prev_finalizer;
-  GC_PTR prev_finalization_data;
-
   /* Register a finalizer for PORT so that its iconv CDs get freed and
      optionally its type's `free' function gets called.  */
-  GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (port), finalize_port, 0,
-                                 &prev_finalizer,
-                                 &prev_finalization_data);
+  scm_i_set_finalizer (SCM2PTR (port), finalize_port, NULL);
 }
 
 /* Finalize the object (a port) pointed to by PTR.  */
diff --git a/libguile/smob.c b/libguile/smob.c
index 8b038f5..6a341ef 100644
--- a/libguile/smob.c
+++ b/libguile/smob.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2003, 2004, 2006, 2009, 2010, 
2011 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2003, 2004, 2006, 2009, 2010, 
2011, 2012 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
@@ -472,8 +472,8 @@ scm_make_smob (scm_t_bits tc)
 static int smob_gc_kind;
 
 
-/* The generic SMOB mark procedure that gets called for SMOBs allocated with
-   `scm_i_new_smob_with_mark_proc ()'.  */
+/* The generic SMOB mark procedure that gets called for SMOBs allocated
+   with smob_gc_kind.  */
 static struct GC_ms_entry *
 smob_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
           struct GC_ms_entry *mark_stack_limit, GC_word env)
@@ -562,28 +562,10 @@ scm_gc_mark (SCM o)
 #undef CURRENT_MARK_LIMIT
 }
 
-/* Return a SMOB with typecode TC.  The SMOB type corresponding to TC may
-   provide a custom mark procedure and it will be honored.  */
-SCM
-scm_i_new_smob_with_mark_proc (scm_t_bits tc, scm_t_bits data1,
-                              scm_t_bits data2, scm_t_bits data3)
-{
-  /* Return a double cell.  */
-  SCM cell = SCM_PACK (GC_generic_malloc (2 * sizeof (scm_t_cell),
-                                         smob_gc_kind));
-
-  SCM_SET_CELL_WORD_3 (cell, data3);
-  SCM_SET_CELL_WORD_2 (cell, data2);
-  SCM_SET_CELL_WORD_1 (cell, data1);
-  SCM_SET_CELL_WORD_0 (cell, tc);
-
-  return cell;
-}
-
 
 /* Finalize SMOB by calling its SMOB type's free function, if any.  */
-void
-scm_i_finalize_smob (GC_PTR ptr, GC_PTR data)
+static void
+finalize_smob (GC_PTR ptr, GC_PTR data)
 {
   SCM smob;
   size_t (* free_smob) (SCM);
@@ -599,6 +581,79 @@ scm_i_finalize_smob (GC_PTR ptr, GC_PTR data)
     free_smob (smob);
 }
 
+/* Return a SMOB with typecode TC.  The SMOB type corresponding to TC may
+   provide a custom mark procedure and it will be honored.  */
+SCM
+scm_i_new_smob (scm_t_bits tc, scm_t_bits data)
+{
+  scm_t_bits smobnum = SCM_TC2SMOBNUM (tc);
+  SCM ret;
+
+  /* Use the smob_gc_kind if needed to allow the mark procedure to
+     run.  Since the marker only deals with double cells, that case
+     allocates a double cell.  We leave words 2 and 3 to there initial
+     values, which is 0.  */
+  if (scm_smobs [smobnum].mark)
+    ret = PTR2SCM (GC_generic_malloc (2 * sizeof (scm_t_cell), smob_gc_kind));
+  else
+    ret = PTR2SCM (GC_MALLOC (sizeof (scm_t_cell)));
+  
+  SCM_SET_CELL_WORD_1 (ret, data);
+  SCM_SET_CELL_WORD_0 (ret, tc);
+
+  if (scm_smobs[smobnum].free)
+    scm_i_set_finalizer (SCM2PTR (ret), finalize_smob, NULL);
+
+  return ret;
+}
+
+/* Return a SMOB with typecode TC.  The SMOB type corresponding to TC may
+   provide a custom mark procedure and it will be honored.  */
+SCM
+scm_i_new_double_smob (scm_t_bits tc, scm_t_bits data1,
+                       scm_t_bits data2, scm_t_bits data3)
+{
+  scm_t_bits smobnum = SCM_TC2SMOBNUM (tc);
+  SCM ret;
+
+  /* Use the smob_gc_kind if needed to allow the mark procedure to
+     run.  */
+  if (scm_smobs [smobnum].mark)
+    ret = PTR2SCM (GC_generic_malloc (2 * sizeof (scm_t_cell), smob_gc_kind));
+  else
+    ret = PTR2SCM (GC_MALLOC (2 * sizeof (scm_t_cell)));
+  
+  SCM_SET_CELL_WORD_3 (ret, data3);
+  SCM_SET_CELL_WORD_2 (ret, data2);
+  SCM_SET_CELL_WORD_1 (ret, data1);
+  SCM_SET_CELL_WORD_0 (ret, tc);
+
+  if (scm_smobs[smobnum].free)
+    scm_i_set_finalizer (SCM2PTR (ret), finalize_smob, NULL);
+
+  return ret;
+}
+
+
+
+
+/* These two are internal details of the previous implementation of
+   SCM_NEWSMOB and are no longer used.  They are still here to preserve
+   ABI stability in the 2.0 series.  */
+void
+scm_i_finalize_smob (GC_PTR ptr, GC_PTR data)
+{
+  finalize_smob (ptr, data);
+}
+
+SCM
+scm_i_new_smob_with_mark_proc (scm_t_bits tc, scm_t_bits word1,
+                               scm_t_bits word2, scm_t_bits word3)
+{
+  return scm_new_double_smob (tc, word1, word2, word3);
+}
+
+
 
 void
 scm_smob_prehistory ()
diff --git a/libguile/smob.h b/libguile/smob.h
index 6a7ceea..cfe12c3 100644
--- a/libguile/smob.h
+++ b/libguile/smob.h
@@ -4,7 +4,7 @@
 #define SCM_SMOB_H
 
 /* Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2004, 2006, 2009,
- *   2010, 2011 Free Software Foundation, Inc.
+ *   2010, 2011, 2012 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
@@ -27,8 +27,6 @@
 #include "libguile/__scm.h"
 #include "libguile/print.h"
 
-#include "libguile/bdw-gc.h"
-
 
 
 /* This is the internal representation of a smob type */
@@ -46,78 +44,87 @@ typedef struct scm_smob_descriptor
 } scm_smob_descriptor;
 
 
+#define SCM_SMOB_TYPE_MASK             0xffff
+#define SCM_SMOB_TYPE_BITS(tc)         (tc)
+#define SCM_TC2SMOBNUM(x)              (0x0ff & ((x) >> 8))
+#define SCM_SMOBNUM(x)                 (SCM_TC2SMOBNUM (SCM_CELL_TYPE (x)))
+/* SCM_SMOBNAME can be 0 if name is missing */
+#define SCM_SMOBNAME(smobnum)          (scm_smobs[smobnum].name)
+#define SCM_SMOB_PREDICATE(tag, obj)   SCM_TYP16_PREDICATE (tag, obj)
+#define SCM_SMOB_DESCRIPTOR(x)         (scm_smobs[SCM_SMOBNUM (x)])
+#define SCM_SMOB_APPLICABLE_P(x)       (SCM_SMOB_DESCRIPTOR (x).apply)
+
+/* Maximum number of SMOB types.  */
+#define SCM_I_MAX_SMOB_TYPE_COUNT  256
+
+SCM_API long scm_numsmob;
+SCM_API scm_smob_descriptor scm_smobs[];
+
+
 
-SCM_API SCM scm_i_new_smob_with_mark_proc (scm_t_bits tc,
-                                          scm_t_bits, scm_t_bits, scm_t_bits);
-
-
-
-#define SCM_NEWSMOB(z, tc, data)                                         \
-do                                                                       \
-  {                                                                      \
-    register scm_t_bits _smobnum = SCM_TC2SMOBNUM (tc);                        
  \
-    z = (scm_smobs[_smobnum].mark                                        \
-        ? scm_i_new_smob_with_mark_proc ((tc), (scm_t_bits)(data),       \
-                                         0, 0)                           \
-        : scm_cell (tc, (scm_t_bits)(data)));                            \
-    if (scm_smobs[_smobnum].free)                                        \
-      {                                                                        
  \
-       GC_finalization_proc _prev_finalizer;                             \
-       GC_PTR _prev_finalizer_data;                                      \
-                                                                         \
-       GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (z), scm_i_finalize_smob, \
-                                       NULL,                             \
-                                       &_prev_finalizer,                 \
-                                       &_prev_finalizer_data);           \
-      }                                                                        
  \
-  }                                                                      \
-while (0)
-
-#define SCM_RETURN_NEWSMOB(tc, data)                   \
-  do { SCM __SCM_smob_answer;                          \
-       SCM_NEWSMOB (__SCM_smob_answer, (tc), (data));  \
-       return __SCM_smob_answer;                       \
-  } while (0)
-
-#define SCM_NEWSMOB2(z, tc, data1, data2)      \
-  SCM_NEWSMOB3 (z, tc, data1, data2, 0)
-
-#define SCM_RETURN_NEWSMOB2(tc, data1, data2)                          \
-  do { SCM __SCM_smob_answer;                                          \
-       SCM_NEWSMOB2 (__SCM_smob_answer, (tc), (data1), (data2));       \
-       return __SCM_smob_answer;                                       \
-  } while (0)
-
-#define SCM_NEWSMOB3(z, tc, data1, data2, data3)                         \
-do                                                                       \
-  {                                                                      \
-    register scm_t_bits _smobnum = SCM_TC2SMOBNUM (tc);                        
  \
-    z = (scm_smobs[_smobnum].mark                                        \
-        ? scm_i_new_smob_with_mark_proc (tc, (scm_t_bits)(data1),        \
-                                         (scm_t_bits)(data2),            \
-                                         (scm_t_bits)(data3))            \
-        : scm_double_cell ((tc), (scm_t_bits)(data1),                    \
-                           (scm_t_bits)(data2),                          \
-                           (scm_t_bits)(data3)));                        \
-    if (scm_smobs[_smobnum].free)                                        \
-      {                                                                        
  \
-       GC_finalization_proc _prev_finalizer;                             \
-       GC_PTR _prev_finalizer_data;                                      \
-                                                                         \
-       GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (z), scm_i_finalize_smob, \
-                                       NULL,                             \
-                                       &_prev_finalizer,                 \
-                                       &_prev_finalizer_data);           \
-      }                                                                        
  \
-  }                                                                      \
-while (0)
-
-#define SCM_RETURN_NEWSMOB3(tc, data1, data2, data3)                       \
-  do { SCM __SCM_smob_answer;                                              \
-       SCM_NEWSMOB3 (__SCM_smob_answer, (tc), (data1), (data2), (data3));   \
-       return __SCM_smob_answer;                                           \
-  } while (0)
 
+SCM_API SCM scm_i_new_smob (scm_t_bits tc, scm_t_bits);
+SCM_API SCM scm_i_new_double_smob (scm_t_bits tc, scm_t_bits,
+                                   scm_t_bits, scm_t_bits);
+
+
+SCM_INLINE SCM scm_new_smob (scm_t_bits tc, scm_t_bits);
+SCM_INLINE SCM scm_new_double_smob (scm_t_bits tc, scm_t_bits,
+                                    scm_t_bits, scm_t_bits);
+
+/* These two are internal details of the previous implementation of
+   SCM_NEWSMOB and are no longer used.  They are still here to preserve
+   ABI stability in the 2.0 series.  */
+SCM_API void scm_i_finalize_smob (GC_PTR ptr, GC_PTR data);
+SCM_API SCM scm_i_new_smob_with_mark_proc (scm_t_bits tc, scm_t_bits,
+                                           scm_t_bits, scm_t_bits);
+
+
+#if SCM_CAN_INLINE || defined SCM_INLINE_C_IMPLEMENTING_INLINES
+SCM_INLINE_IMPLEMENTATION SCM
+scm_new_smob (scm_t_bits tc, scm_t_bits data)
+{
+  scm_t_bits smobnum = SCM_TC2SMOBNUM (tc);
+
+  if (SCM_UNLIKELY (scm_smobs[smobnum].mark || scm_smobs[smobnum].free))
+    return scm_i_new_smob (tc, data);
+  else
+    return scm_cell (tc, data);
+}
+
+SCM_INLINE_IMPLEMENTATION SCM
+scm_new_double_smob (scm_t_bits tc, scm_t_bits data1,
+                     scm_t_bits data2, scm_t_bits data3)
+{
+  scm_t_bits smobnum = SCM_TC2SMOBNUM (tc);
+
+  if (SCM_UNLIKELY (scm_smobs[smobnum].mark || scm_smobs[smobnum].free))
+    return scm_i_new_double_smob (tc, data1, data2, data3);
+  else
+    return scm_double_cell (tc, data1, data2, data3);
+}
+#endif
+
+#define SCM_NEWSMOB(z, tc, data)                \
+  z = scm_new_smob ((tc), (scm_t_bits)(data))
+#define SCM_RETURN_NEWSMOB(tc, data)            \
+  return scm_new_smob ((tc), (scm_t_bits)(data))
+
+#define SCM_NEWSMOB2(z, tc, data1, data2)               \
+  z = scm_new_double_smob ((tc), (scm_t_bits)(data1),   \
+                           (scm_t_bits)(data2), 0)
+#define SCM_RETURN_NEWSMOB2(tc, data1, data2)                   \
+  return scm_new_double_smob ((tc), (scm_t_bits)(data1),        \
+                              (scm_t_bits)(data2), 0)
+
+#define SCM_NEWSMOB3(z, tc, data1, data2, data3)                        \
+  z = scm_new_double_smob ((tc), (scm_t_bits)(data1),                   \
+                           (scm_t_bits)(data2), (scm_t_bits)(data3))
+#define SCM_RETURN_NEWSMOB3(tc, data1, data2, data3)                    \
+  return scm_new_double_smob ((tc), (scm_t_bits)(data1),                \
+                              (scm_t_bits)(data2), (scm_t_bits)(data3))
+
+
 
 #define SCM_SMOB_DATA_N(x, n)          (SCM_CELL_WORD ((x), (n)))
 #define SCM_SET_SMOB_DATA_N(x, n, data)        (SCM_SET_CELL_WORD ((x), (n), 
(data)))
@@ -158,28 +165,11 @@ while (0)
 #define SCM_SMOB_OBJECT_LOC(x)         (SCM_SMOB_OBJECT_1_LOC (x)))
 
 
-#define SCM_SMOB_TYPE_MASK             0xffff
-#define SCM_SMOB_TYPE_BITS(tc)         (tc)
-#define SCM_TC2SMOBNUM(x)              (0x0ff & ((x) >> 8))
-#define SCM_SMOBNUM(x)                 (SCM_TC2SMOBNUM (SCM_CELL_TYPE (x)))
-/* SCM_SMOBNAME can be 0 if name is missing */
-#define SCM_SMOBNAME(smobnum)          (scm_smobs[smobnum].name)
-#define SCM_SMOB_PREDICATE(tag, obj)   SCM_TYP16_PREDICATE (tag, obj)
-#define SCM_SMOB_DESCRIPTOR(x)         (scm_smobs[SCM_SMOBNUM (x)])
-#define SCM_SMOB_APPLICABLE_P(x)       (SCM_SMOB_DESCRIPTOR (x).apply)
 #define SCM_SMOB_APPLY_0(x)            (scm_call_0 (x))
 #define SCM_SMOB_APPLY_1(x, a1)                (scm_call_1 (x, a1))
 #define SCM_SMOB_APPLY_2(x, a1, a2)    (scm_call_2 (x, a1, a2))
 #define SCM_SMOB_APPLY_3(x, a1, a2, rst) (scm_call_3 (x, a1, a2, a3))
 
-/* Maximum number of SMOB types.  */
-#define SCM_I_MAX_SMOB_TYPE_COUNT  256
-
-SCM_API long scm_numsmob;
-SCM_API scm_smob_descriptor scm_smobs[];
-
-SCM_API void scm_i_finalize_smob (GC_PTR obj, GC_PTR data);
-
 
 
 SCM_API SCM scm_mark0 (SCM ptr);
diff --git a/libguile/struct.c b/libguile/struct.c
index 2aa5c11..e5d95fc 100644
--- a/libguile/struct.c
+++ b/libguile/struct.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996,1997,1998,1999,2000,2001, 2003, 2004, 2006, 2007, 2008, 
2009, 2010, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 1996,1997,1998,1999,2000,2001, 2003, 2004, 2006, 2007, 2008, 
2009, 2010, 2011, 2012 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
@@ -443,16 +443,8 @@ scm_i_alloc_struct (scm_t_bits *vtable_data, int n_words)
 
   /* vtable_data can be null when making a vtable vtable */
   if (vtable_data && vtable_data[scm_vtable_index_instance_finalize])
-    {
-      /* Register a finalizer for the newly created instance.  */
-      GC_finalization_proc prev_finalizer;
-      GC_PTR prev_finalizer_data;
-      GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (ret),
-                                     struct_finalizer_trampoline,
-                                     NULL,
-                                     &prev_finalizer,
-                                     &prev_finalizer_data);
-    }
+    /* Register a finalizer for the newly created instance.  */
+    scm_i_set_finalizer (SCM2PTR (ret), struct_finalizer_trampoline, NULL);
 
   return ret;
 }
diff --git a/libguile/threads.c b/libguile/threads.c
index 7944f48..e8305b4 100644
--- a/libguile/threads.c
+++ b/libguile/threads.c
@@ -620,6 +620,9 @@ guilify_self_2 (SCM parent)
 
   t->join_queue = make_queue ();
   t->block_asyncs = 0;
+
+  /* See note in finalizers.c:queue_finalizer_async().  */
+  GC_invoke_finalizers ();
 }
 
 


hooks/post-receive
-- 
GNU Guile



reply via email to

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