*** empty log message ***
[bpt/guile.git] / libguile / inline.h
CommitLineData
16ea9620
MV
1/* classes: h_files */
2
3#ifndef SCM_INLINE_H
4#define SCM_INLINE_H
5
b1e945d7 6/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
16ea9620
MV
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this software; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
21 * Boston, MA 02111-1307 USA
22 *
23 * As a special exception, the Free Software Foundation gives permission
24 * for additional uses of the text contained in its release of GUILE.
25 *
26 * The exception is that, if you link the GUILE library with other files
27 * to produce an executable, this does not by itself cause the
28 * resulting executable to be covered by the GNU General Public License.
29 * Your use of that executable is in no way restricted on account of
30 * linking the GUILE library code into it.
31 *
32 * This exception does not however invalidate any other reasons why
33 * the executable file might be covered by the GNU General Public License.
34 *
35 * This exception applies only to the code released by the
36 * Free Software Foundation under the name GUILE. If you copy
37 * code from other Free Software Foundation releases into a copy of
38 * GUILE, as the General Public License permits, the exception does
39 * not apply to the code that you add in this way. To avoid misleading
40 * anyone as to the status of such modified files, you must delete
41 * this exception notice from them.
42 *
43 * If you write modifications of your own for GUILE, it is your choice
44 * whether to permit this exception to apply to your modifications.
45 * If you do not wish that, delete this exception notice. */
46
47/* This file is for inline functions. On platforms that don't support
48 inlining functions, they are turned into ordinary functions. See
49 "inline.c".
50*/
51
60e7529a 52#include "libguile/__scm.h"
c8a1bdc4 53
1e71eafb
HWN
54#if (SCM_DEBUG_CELL_ACCESSES == 1)
55#include <stdio.h>
1e71eafb
HWN
56#endif
57
16ea9620
MV
58#include "libguile/pairs.h"
59#include "libguile/gc.h"
9bc4701c 60#include "libguile/threads.h"
16ea9620 61
c8a1bdc4
HWN
62
63SCM_API SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
64SCM_API SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
65 scm_t_bits ccr, scm_t_bits cdr);
66
16ea9620 67
60e7529a
RB
68
69#if defined SCM_C_INLINE || defined SCM_INLINE_C_INCLUDING_INLINE_H
70/* either inlining, or being included from inline.c. We use (and
71 repeat) this long #if test here and below so that we don't have to
72 introduce any extraneous symbols into the public namespace. We
73 only need SCM_C_INLINE to be seen publically . */
c8a1bdc4
HWN
74
75extern unsigned scm_newcell2_count;
76extern unsigned scm_newcell_count;
77
60e7529a
RB
78#if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
79/* definitely inlining */
80extern SCM_C_INLINE
81#endif
c8a1bdc4 82SCM
228a24ef 83scm_cell (scm_t_bits car, scm_t_bits cdr)
16ea9620
MV
84{
85 SCM z;
9bc4701c
MD
86 /* We retrieve the SCM pointer only once since the call to
87 SCM_FREELIST_LOC will be slightly expensive when we support
88 preemptive multithreading. SCM_FREELIST_DOC will then retrieve
89 the thread specific freelist.
90
91 Until then, SCM_FREELIST_DOC expands to (&scm_i_freelist) and the
92 following code will compile to the same as if we had worked
93 directly on the scm_i_freelist variable.
94 */
95 SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist);
16ea9620 96
9bc4701c
MD
97 if (SCM_NULLP (*freelist))
98 z = scm_gc_for_newcell (&scm_i_master_freelist, freelist);
c8a1bdc4 99 else
16ea9620 100 {
9bc4701c
MD
101 z = *freelist;
102 *freelist = SCM_FREE_CELL_CDR (*freelist);
16ea9620 103 }
c8a1bdc4
HWN
104
105 /*
106 We update scm_cells_allocated from this function. If we don't
107 update this explicitly, we will have to walk a freelist somewhere
108 later on, which seems a lot more expensive.
109 */
110 scm_cells_allocated += 1;
111
112#if (SCM_DEBUG_CELL_ACCESSES == 1)
113 if (scm_debug_cell_accesses_p)
1e71eafb
HWN
114 {
115 if (SCM_GC_MARK_P (z))
116 {
117 fprintf(stderr, "scm_cell tried to allocate a marked cell.\n");
118 abort();
119 }
120 else if (SCM_GC_CELL_TYPE(z) != scm_tc_free_cell)
121 {
122 fprintf(stderr, "cell from freelist is not a free cell.\n");
123 abort();
124 }
125 }
126
127 /*
128 Always set mark. Otherwise cells that are alloced before
129 scm_debug_cell_accesses_p is toggled seem invalid.
130 */
131 SCM_SET_GC_MARK (z);
132
133 /*
134 TODO: figure out if this use of mark bits is valid with
135 threading. What if another thread is doing GC at this point
136 ... ?
137 */
c8a1bdc4 138
c8a1bdc4 139#endif
16ea9620 140
c8a1bdc4 141
16ea9620
MV
142 /* Initialize the type slot last so that the cell is ignored by the
143 GC until it is completely initialized. This is only relevant
144 when the GC can actually run during this code, which it can't for
145 cooperating threads, but it might be important when we get true
146 preemptive threads.
147 */
1fc8902f
DH
148 SCM_GC_SET_CELL_WORD (z, 1, cdr);
149 SCM_GC_SET_CELL_WORD (z, 0, car);
16ea9620 150
9bc4701c 151#if 0 /*fixme* Hmm... let's consider this later. */
60e7529a 152#if !defined(SCM_USE_COOP_THREADS) && !defined(SCM_USE_NULL_THREADS) && !defined(SCM_USE_COPT_THREADS)
389626c5 153 /* When we are using preemtive threads, we might need to make
16ea9620
MV
154 sure that the initial values for the slots are protected until
155 the cell is completely initialized.
156 */
157#error review me
158 scm_remember_upto_here_1 (SCM_PACK (cdr));
159#endif
9bc4701c 160#endif
c8a1bdc4 161
eab1b259
HWN
162#if (SCM_DEBUG_CELL_ACCESSES == 1)
163 if (scm_expensive_debug_cell_accesses_p )
164 scm_i_expensive_validation_check (z);
165#endif
c8a1bdc4 166
16ea9620
MV
167 return z;
168}
169
60e7529a
RB
170#if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
171/* definitely inlining */
172extern SCM_C_INLINE
173#endif
c8a1bdc4 174SCM
228a24ef
DH
175scm_double_cell (scm_t_bits car, scm_t_bits cbr,
176 scm_t_bits ccr, scm_t_bits cdr)
16ea9620
MV
177{
178 SCM z;
9bc4701c 179 SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist2);
16ea9620 180
9bc4701c
MD
181 if (SCM_NULLP (*freelist))
182 z = scm_gc_for_newcell (&scm_i_master_freelist2, freelist);
16ea9620
MV
183 else
184 {
9bc4701c
MD
185 z = *freelist;
186 *freelist = SCM_FREE_CELL_CDR (*freelist);
16ea9620
MV
187 }
188
c8a1bdc4
HWN
189 scm_cells_allocated += 2;
190
16ea9620
MV
191 /* Initialize the type slot last so that the cell is ignored by the
192 GC until it is completely initialized. This is only relevant
193 when the GC can actually run during this code, which it can't for
194 cooperating threads, but it might be important when we get true
195 preemptive threads.
196 */
1fc8902f
DH
197 SCM_GC_SET_CELL_WORD (z, 1, cbr);
198 SCM_GC_SET_CELL_WORD (z, 2, ccr);
199 SCM_GC_SET_CELL_WORD (z, 3, cdr);
200 SCM_GC_SET_CELL_WORD (z, 0, car);
16ea9620 201
9bc4701c 202#if 0 /*fixme* Hmm... let's consider this later. */
60e7529a 203#if !defined(SCM_USE_COOP_THREADS) && !defined(SCM_USE_NULL_THREADS) && !defined(SCM_USE_COPT_THREADS)
16ea9620
MV
204 /* When we are using non-cooperating threads, we might need to make
205 sure that the initial values for the slots are protected until
206 the cell is completely initialized.
207 */
208#error review me
209 scm_remember_upto_here_3 (SCM_PACK (cbr), SCM_PACK (ccr), SCM_PACK (cdr));
210#endif
9bc4701c 211#endif
16ea9620 212
16ea9620 213
c8a1bdc4
HWN
214#if (SCM_DEBUG_CELL_ACCESSES == 1)
215 if (scm_debug_cell_accesses_p)
216 {
217 if (SCM_GC_MARK_P (z))
218 {
219 fprintf(stderr,
220 "scm_double_cell tried to allocate a marked cell.\n");
221 abort();
222 }
c8a1bdc4 223 }
4ad0814a
HWN
224
225 /* see above. */
226 SCM_SET_GC_MARK (z);
227
3553e1d1
GH
228#endif
229
230 /* When this function is inlined, it's possible that the last
231 SCM_GC_SET_CELL_WORD above will be adjacent to a following
232 initialization of z. E.g., it occurred in scm_make_real. GCC
233 from around version 3 (e.g., certainly 3.2) began taking
234 advantage of strict C aliasing rules which say that it's OK to
235 interchange the initialization above and the one below when the
236 pointer types appear to differ sufficiently. We don't want that,
237 of course. GCC allows this behaviour to be disabled with the
238 -fno-strict-aliasing option, but would also need to be supplied
239 by Guile users. Instead, the following statements prevent the
240 reordering.
241 */
242#ifdef __GNUC__
243 asm volatile ("" : : : "memory");
244#else
245 /* portable version, just in case any other compiler does the same
246 thing. */
247 scm_remember_upto_here_1 (z);
c8a1bdc4 248#endif
6253f3f1 249
c8a1bdc4
HWN
250 return z;
251}
6253f3f1 252
eab1b259
HWN
253
254
16ea9620 255#endif
16ea9620 256#endif