wingo pushed a commit to branch wip-whippet
in repository guile.

commit 8141c35ec4d5e9eb6901a7ffd244984a6a7101a0
Author: Andy Wingo <wi...@pobox.com>
AuthorDate: Fri Jun 20 14:22:52 2025 +0200

    Change to not inline scm_cell / scm_double_cell / scm_words
    
    * libguile/gc-malloc.c (scm_cell):
    (scm_double_cell):
    (scm_words): Implement here.
    * libguile/gc.h:
    * libguile/inline.c: Not here.
---
 libguile/gc-malloc.c |  50 ++++++++++++++++++++++++++
 libguile/gc.h        | 100 +++------------------------------------------------
 libguile/inline.c    |   1 -
 3 files changed, 54 insertions(+), 97 deletions(-)

diff --git a/libguile/gc-malloc.c b/libguile/gc-malloc.c
index 30a8ad089..647d391df 100644
--- a/libguile/gc-malloc.c
+++ b/libguile/gc-malloc.c
@@ -207,3 +207,53 @@ scm_gc_strdup (const char *str, const char *what)
 {
   return scm_gc_strndup (str, strlen (str), what);
 }
+
+SCM
+scm_cell (scm_t_bits car, scm_t_bits cdr)
+{
+  scm_t_bits *words = scm_allocate_sloppy (SCM_I_CURRENT_THREAD,
+                                           sizeof (scm_t_bits) * 2);
+
+  words[0] = car;
+  words[1] = cdr;
+
+  /* Probably the user isn't accessing the object as a "scm_t_bits*", and
+     in standard C that would allow the compiler to treat the above
+     writes as not aliasing the "struct scm_pair" or whatever that the
+     user actually wants, which can result in correctness-breaking
+     optimizations.  Therefore Guile compiles with -fno-strict-aliasing,
+     and doesn't expose this function for inlining.  It would be nice if
+     Guile could be written in fully standard C, but that's not where
+     we're at right now.  */
+
+  return SCM_PACK_POINTER (words);
+}
+
+SCM
+scm_double_cell (scm_t_bits car, scm_t_bits cbr,
+                scm_t_bits ccr, scm_t_bits cdr)
+{
+  scm_t_bits *words = scm_allocate_sloppy (SCM_I_CURRENT_THREAD,
+                                           sizeof (scm_t_bits) * 4);
+
+  words[0] = car;
+  words[1] = cbr;
+  words[2] = ccr;
+  words[3] = cdr;
+
+  /* See above notes about strict aliasing.  */
+
+  return SCM_PACK_POINTER (words);
+}
+
+SCM
+scm_words (scm_t_bits car, uint32_t n_words)
+{
+  scm_t_bits *words = scm_allocate_sloppy (SCM_I_CURRENT_THREAD,
+                                           sizeof (scm_t_bits) * n_words);
+  words[0] = car;
+
+  /* See above notes about strict aliasing.  */
+
+  return SCM_PACK_POINTER (words);
+}
diff --git a/libguile/gc.h b/libguile/gc.h
index 91da59946..34717f2f6 100644
--- a/libguile/gc.h
+++ b/libguile/gc.h
@@ -142,102 +142,10 @@ SCM_API char *scm_gc_strndup (const char *str, size_t n, 
const char *what)
 #define SCM_GC_MALLOC_POINTERLESS(size) scm_gc_malloc_pointerless (size, NULL)
 
 
-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, uint32_t 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 = SCM_PACK_POINTER (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 = SCM_PACK_POINTER (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 behavior 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, uint32_t n_words)
-{
-  SCM z;
-
-  z = SCM_PACK_POINTER (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 behavior 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 scm_cell (scm_t_bits car, scm_t_bits cdr);
+SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
+                     scm_t_bits ccr, scm_t_bits cdr);
+SCM scm_words (scm_t_bits car, uint32_t n_words);
 
 SCM_API void scm_remember_upto_here_1 (SCM obj);
 SCM_API void scm_remember_upto_here_2 (SCM obj1, SCM obj2);
diff --git a/libguile/inline.c b/libguile/inline.c
index 8796e9712..4e71481cf 100644
--- a/libguile/inline.c
+++ b/libguile/inline.c
@@ -26,7 +26,6 @@
 
 #include "array-handle.h"
 #include "chars.h"
-#include "gc.h"
 #include "pairs.h"
 #include "ports.h"
 #include "strings.h"

Reply via email to