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"