summaryrefslogtreecommitdiff
path: root/libguile/inline.h
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2008-09-16 12:10:52 +0200
committerLudovic Courtès <ludo@gnu.org>2008-09-16 12:10:52 +0200
commit737219ddbb026289521df207710f0d5310d0f4d1 (patch)
tree1a5ffa06d2da0b4acab8fc454a0bb3ba3b871e81 /libguile/inline.h
parent3db825b0677614b1fe8fd135a1bd125dde6c03e1 (diff)
downloadguile-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.h47
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);