* __scm.h (SCM_ALLOW_INTS_ONLY): Removed.
[bpt/guile.git] / libguile / inline.h
index d4cd676..7d5b20d 100644 (file)
@@ -3,7 +3,7 @@
 #ifndef SCM_INLINE_H
 #define SCM_INLINE_H
 
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -57,6 +57,7 @@
 
 #include "libguile/pairs.h"
 #include "libguile/gc.h"
+#include "libguile/threads.h"
 
 
 SCM_API SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
@@ -79,15 +80,23 @@ SCM
 scm_cell (scm_t_bits car, scm_t_bits cdr)
 {
   SCM z;
+  /* We retrieve the SCM pointer only once since the call to
+     SCM_FREELIST_LOC will be slightly expensive when we support
+     preemptive multithreading.  SCM_FREELIST_DOC will then retrieve
+     the thread specific freelist.
+   
+     Until then, SCM_FREELIST_DOC expands to (&scm_i_freelist) and the
+     following code will compile to the same as if we had worked
+     directly on the scm_i_freelist variable.
+   */
+  SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist);
 
-  if (SCM_NULLP (scm_i_freelist))
-    {
-      z = scm_gc_for_newcell (&scm_i_master_freelist, &scm_i_freelist);
-    }
+  if (SCM_NULLP (*freelist))
+    z = scm_gc_for_newcell (&scm_i_master_freelist, freelist);
   else
     {
-      z = scm_i_freelist;
-      scm_i_freelist = SCM_FREE_CELL_CDR (scm_i_freelist);
+      z = *freelist;
+      *freelist = SCM_FREE_CELL_CDR (*freelist);
     }
 
   /*
@@ -136,9 +145,9 @@ scm_cell (scm_t_bits car, scm_t_bits cdr)
   SCM_GC_SET_CELL_WORD (z, 1, cdr);
   SCM_GC_SET_CELL_WORD (z, 0, car);
 
-#ifdef USE_THREADS
-#ifndef USE_COOP_THREADS
-  /* When we are using non-cooperating threads, we might need to make
+#if 0 /*fixme* Hmm... let's consider this later. */
+#if !defined(USE_COOP_THREADS) && !defined(USE_NULL_THREADS) && !defined(USE_COPT_THREADS)
+  /* When we are using preemtive threads, we might need to make
      sure that the initial values for the slots are protected until
      the cell is completely initialized.
   */
@@ -147,7 +156,6 @@ scm_cell (scm_t_bits car, scm_t_bits cdr)
 #endif
 #endif
 
-
 #if (SCM_DEBUG_CELL_ACCESSES == 1)
   if (scm_expensive_debug_cell_accesses_p )
     scm_i_expensive_validation_check (z);
@@ -162,16 +170,14 @@ scm_double_cell (scm_t_bits car, scm_t_bits cbr,
                 scm_t_bits ccr, scm_t_bits cdr)
 {
   SCM z;
+  SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist2);
 
-
-  if (SCM_NULLP (scm_i_freelist2))
-    {
-      z = scm_gc_for_newcell (&scm_i_master_freelist2, &scm_i_freelist2);
-    }
+  if (SCM_NULLP (*freelist))
+    z = scm_gc_for_newcell (&scm_i_master_freelist2, freelist);
   else
     {
-      z = scm_i_freelist2;
-      scm_i_freelist2 = SCM_FREE_CELL_CDR (scm_i_freelist2);
+      z = *freelist;
+      *freelist = SCM_FREE_CELL_CDR (*freelist);
     }
 
   scm_cells_allocated += 2;
@@ -187,8 +193,8 @@ scm_double_cell (scm_t_bits car, scm_t_bits cbr,
   SCM_GC_SET_CELL_WORD (z, 3, cdr);
   SCM_GC_SET_CELL_WORD (z, 0, car);
 
-#ifdef USE_THREADS
-#ifndef USE_COOP_THREADS
+#if 0 /*fixme* Hmm... let's consider this later. */
+#if !defined(USE_COOP_THREADS) && !defined(USE_NULL_THREADS) && !defined(USE_COPT_THREADS)
   /* When we are using non-cooperating threads, we might need to make
      sure that the initial values for the slots are protected until
      the cell is completely initialized.
@@ -213,6 +219,26 @@ scm_double_cell (scm_t_bits car, scm_t_bits cbr,
   /* see above. */
   SCM_SET_GC_MARK (z);
 
+#endif
+
+  /* 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;