diff options
author | Ludovic Courtès <ludo@gnu.org> | 2008-09-16 12:10:52 +0200 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2008-09-16 12:10:52 +0200 |
commit | 737219ddbb026289521df207710f0d5310d0f4d1 (patch) | |
tree | 1a5ffa06d2da0b4acab8fc454a0bb3ba3b871e81 /libguile/inline.h | |
parent | 3db825b0677614b1fe8fd135a1bd125dde6c03e1 (diff) | |
download | guile-737219ddbb026289521df207710f0d5310d0f4d1.tar.gz |
Add `scm_immutable_double_cell ()'.
* libguile/inline.h (scm_immutable_double_cell): New.
Diffstat (limited to 'libguile/inline.h')
-rw-r--r-- | libguile/inline.h | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/libguile/inline.h b/libguile/inline.h index 3a4302afc..7d2dabaad 100644 --- a/libguile/inline.h +++ b/libguile/inline.h @@ -83,6 +83,8 @@ SCM_API SCM scm_cell (scm_t_bits car, scm_t_bits cdr); SCM_API SCM scm_immutable_cell (scm_t_bits car, scm_t_bits cdr); SCM_API SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr, scm_t_bits ccr, scm_t_bits cdr); +SCM_API SCM scm_immutable_double_cell (scm_t_bits car, scm_t_bits cbr, + scm_t_bits ccr, scm_t_bits cdr); 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); @@ -192,6 +194,51 @@ scm_double_cell (scm_t_bits car, scm_t_bits cbr, SCM_C_EXTERN_INLINE #endif SCM +scm_immutable_double_cell (scm_t_bits car, scm_t_bits cbr, + scm_t_bits ccr, scm_t_bits cdr) +{ + SCM z; + + z = SCM_PACK ((scm_t_bits) (GC_MALLOC_STUBBORN (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); + + GC_END_STUBBORN_CHANGE ((void *) z); + + /* 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_array_handle_ref (scm_t_array_handle *h, ssize_t p) { return h->ref (h, p); |