Merge branch 'master' into boehm-demers-weiser-gc
[bpt/guile.git] / libguile / inline.h
index 3a4302a..09ee142 100644 (file)
@@ -6,18 +6,19 @@
 /* Copyright (C) 2001, 2002, 2003, 2004, 2006, 2008 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 2.1 of the License, or (at your option) any later version.
+ * 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
+ * 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  */
 
 /* This file is for inline functions.  On platforms that don't support
@@ -54,7 +55,7 @@
    C99 mode and doesn't define `__GNUC_STDC_INLINE__'.  Fall back to "static
    inline" in that case.  */
 
-# if (defined __GNUC__) && (!(__APPLE_CC__ > 5400 && __STDC_VERSION__ >= 199901L))
+# 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                                 \
@@ -83,6 +84,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);
@@ -188,6 +191,51 @@ scm_double_cell (scm_t_bits car, scm_t_bits cbr,
   return z;
 }
 
+#ifndef SCM_INLINE_C_INCLUDING_INLINE_H
+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