More `.gitignore'.
[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
3f520967 6/* Copyright (C) 2001, 2002, 2003, 2004, 2006, 2008 Free Software Foundation, Inc.
16ea9620 7 *
73be1d9e
MV
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
16ea9620 12 *
73be1d9e 13 * This library is distributed in the hope that it will be useful,
16ea9620 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16ea9620 17 *
73be1d9e
MV
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
92205699 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
73be1d9e 21 */
16ea9620
MV
22
23/* This file is for inline functions. On platforms that don't support
24 inlining functions, they are turned into ordinary functions. See
25 "inline.c".
26*/
27
60e7529a 28#include "libguile/__scm.h"
c8a1bdc4 29
1e71eafb
HWN
30#if (SCM_DEBUG_CELL_ACCESSES == 1)
31#include <stdio.h>
1e71eafb
HWN
32#endif
33
16ea9620
MV
34#include "libguile/pairs.h"
35#include "libguile/gc.h"
9bc4701c 36#include "libguile/threads.h"
9598a406 37#include "libguile/unif.h"
d5ad4aa6 38#include "libguile/pairs.h"
16ea9620 39
c8a1bdc4 40
3f520967
LC
41#if ((!defined SCM_C_INLINE) && (!defined SCM_INLINE_C_INCLUDING_INLINE_H)) \
42 || (defined __GNUC__)
43
44/* The `extern' declarations. They should only appear when used from
45 "inline.c", when `inline' is not supported at all or when GCC's "extern
46 inline" is used. */
47
c8a1bdc4
HWN
48SCM_API SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
49SCM_API SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
50 scm_t_bits ccr, scm_t_bits cdr);
51
9598a406
MV
52SCM_API SCM scm_array_handle_ref (scm_t_array_handle *h, ssize_t pos);
53SCM_API void scm_array_handle_set (scm_t_array_handle *h, ssize_t pos, SCM val);
16ea9620 54
3f520967
LC
55SCM_API int scm_is_pair (SCM x);
56
57#endif
58
60e7529a
RB
59
60#if defined SCM_C_INLINE || defined SCM_INLINE_C_INCLUDING_INLINE_H
61/* either inlining, or being included from inline.c. We use (and
62 repeat) this long #if test here and below so that we don't have to
63 introduce any extraneous symbols into the public namespace. We
64 only need SCM_C_INLINE to be seen publically . */
c8a1bdc4
HWN
65
66extern unsigned scm_newcell2_count;
67extern unsigned scm_newcell_count;
68
60e7529a
RB
69#if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
70/* definitely inlining */
2b2c6fca
MV
71#ifdef __GNUC__
72extern
73#else
74static
75#endif
76SCM_C_INLINE
60e7529a 77#endif
c8a1bdc4 78SCM
228a24ef 79scm_cell (scm_t_bits car, scm_t_bits cdr)
16ea9620
MV
80{
81 SCM z;
9bc4701c 82 SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist);
16ea9620 83
d2e53ed6 84 if (scm_is_null (*freelist))
9bc4701c 85 z = scm_gc_for_newcell (&scm_i_master_freelist, freelist);
c8a1bdc4 86 else
16ea9620 87 {
9bc4701c
MD
88 z = *freelist;
89 *freelist = SCM_FREE_CELL_CDR (*freelist);
16ea9620 90 }
c8a1bdc4
HWN
91
92 /*
93 We update scm_cells_allocated from this function. If we don't
94 update this explicitly, we will have to walk a freelist somewhere
95 later on, which seems a lot more expensive.
96 */
97 scm_cells_allocated += 1;
98
99#if (SCM_DEBUG_CELL_ACCESSES == 1)
100 if (scm_debug_cell_accesses_p)
1e71eafb
HWN
101 {
102 if (SCM_GC_MARK_P (z))
103 {
104 fprintf(stderr, "scm_cell tried to allocate a marked cell.\n");
105 abort();
106 }
6b69393d 107 else if (SCM_GC_CELL_WORD(z, 0) != scm_tc_free_cell)
1e71eafb
HWN
108 {
109 fprintf(stderr, "cell from freelist is not a free cell.\n");
110 abort();
111 }
112 }
113
114 /*
115 Always set mark. Otherwise cells that are alloced before
116 scm_debug_cell_accesses_p is toggled seem invalid.
117 */
118 SCM_SET_GC_MARK (z);
119
120 /*
121 TODO: figure out if this use of mark bits is valid with
122 threading. What if another thread is doing GC at this point
123 ... ?
124 */
c8a1bdc4 125
c8a1bdc4 126#endif
16ea9620 127
c8a1bdc4 128
16ea9620
MV
129 /* Initialize the type slot last so that the cell is ignored by the
130 GC until it is completely initialized. This is only relevant
b2a339f6
MV
131 when the GC can actually run during this code, which it can't
132 since the GC only runs when all other threads are stopped.
16ea9620 133 */
1fc8902f
DH
134 SCM_GC_SET_CELL_WORD (z, 1, cdr);
135 SCM_GC_SET_CELL_WORD (z, 0, car);
16ea9620 136
eab1b259
HWN
137#if (SCM_DEBUG_CELL_ACCESSES == 1)
138 if (scm_expensive_debug_cell_accesses_p )
139 scm_i_expensive_validation_check (z);
140#endif
c8a1bdc4 141
16ea9620
MV
142 return z;
143}
144
60e7529a
RB
145#if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
146/* definitely inlining */
2b2c6fca
MV
147#ifdef __GNUC__
148extern
149#else
150static
151#endif
152SCM_C_INLINE
60e7529a 153#endif
c8a1bdc4 154SCM
228a24ef
DH
155scm_double_cell (scm_t_bits car, scm_t_bits cbr,
156 scm_t_bits ccr, scm_t_bits cdr)
16ea9620 157{
5e1e20c8
MV
158 SCM z;
159 SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist2);
160
d2e53ed6 161 if (scm_is_null (*freelist))
9bc4701c 162 z = scm_gc_for_newcell (&scm_i_master_freelist2, freelist);
16ea9620
MV
163 else
164 {
9bc4701c
MD
165 z = *freelist;
166 *freelist = SCM_FREE_CELL_CDR (*freelist);
16ea9620
MV
167 }
168
c8a1bdc4
HWN
169 scm_cells_allocated += 2;
170
16ea9620
MV
171 /* Initialize the type slot last so that the cell is ignored by the
172 GC until it is completely initialized. This is only relevant
b2a339f6
MV
173 when the GC can actually run during this code, which it can't
174 since the GC only runs when all other threads are stopped.
16ea9620 175 */
1fc8902f
DH
176 SCM_GC_SET_CELL_WORD (z, 1, cbr);
177 SCM_GC_SET_CELL_WORD (z, 2, ccr);
178 SCM_GC_SET_CELL_WORD (z, 3, cdr);
179 SCM_GC_SET_CELL_WORD (z, 0, car);
16ea9620 180
c8a1bdc4
HWN
181#if (SCM_DEBUG_CELL_ACCESSES == 1)
182 if (scm_debug_cell_accesses_p)
183 {
184 if (SCM_GC_MARK_P (z))
185 {
186 fprintf(stderr,
187 "scm_double_cell tried to allocate a marked cell.\n");
188 abort();
189 }
c8a1bdc4 190 }
4ad0814a
HWN
191
192 /* see above. */
193 SCM_SET_GC_MARK (z);
194
3553e1d1
GH
195#endif
196
197 /* When this function is inlined, it's possible that the last
198 SCM_GC_SET_CELL_WORD above will be adjacent to a following
199 initialization of z. E.g., it occurred in scm_make_real. GCC
200 from around version 3 (e.g., certainly 3.2) began taking
201 advantage of strict C aliasing rules which say that it's OK to
202 interchange the initialization above and the one below when the
203 pointer types appear to differ sufficiently. We don't want that,
204 of course. GCC allows this behaviour to be disabled with the
205 -fno-strict-aliasing option, but would also need to be supplied
206 by Guile users. Instead, the following statements prevent the
207 reordering.
208 */
209#ifdef __GNUC__
cb975c21 210 __asm__ volatile ("" : : : "memory");
3553e1d1
GH
211#else
212 /* portable version, just in case any other compiler does the same
213 thing. */
214 scm_remember_upto_here_1 (z);
c8a1bdc4 215#endif
6253f3f1 216
c8a1bdc4
HWN
217 return z;
218}
6253f3f1 219
9598a406
MV
220#if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
221/* definitely inlining */
222#ifdef __GNUC__
223extern
224#else
225static
226#endif
227SCM_C_INLINE
228#endif
229SCM
230scm_array_handle_ref (scm_t_array_handle *h, ssize_t p)
231{
232 return h->ref (h, p);
233}
eab1b259 234
9598a406
MV
235#if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
236/* definitely inlining */
237#ifdef __GNUC__
238extern
239#else
240static
241#endif
242SCM_C_INLINE
243#endif
244void
245scm_array_handle_set (scm_t_array_handle *h, ssize_t p, SCM v)
246{
247 h->set (h, p, v);
248}
eab1b259 249
d5ad4aa6
MV
250#if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
251/* definitely inlining */
252#ifdef __GNUC__
253extern
254#else
255static
256#endif
257SCM_C_INLINE
258#endif
259int
260scm_is_pair (SCM x)
261{
23f2b9a3
KR
262 /* The following "workaround_for_gcc_295" avoids bad code generated by
263 i386 gcc 2.95.4 (the Debian packaged 2.95.4-24 at least).
264
265 Under the default -O2 the inlined SCM_I_CONSP test gets "optimized" so
266 the fetch of the tag word from x is done before confirming it's a
267 non-immediate (SCM_NIMP). Needless to say that bombs badly if x is a
268 immediate. This was seen to afflict scm_srfi1_split_at and something
269 deep in the bowels of ceval(). In both cases segvs resulted from
270 deferencing a random immediate value. srfi-1.test exposes the problem
271 through a short list, the immediate being SCM_EOL in that case.
272 Something in syntax.test exposed the ceval() problem.
273
274 Just "volatile SCM workaround_for_gcc_295 = lst" is enough to avoid the
275 problem, without even using that variable. The "w=w" is just to
276 prevent a warning about it being unused.
277 */
278#if defined (__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ == 95
279 volatile SCM workaround_for_gcc_295 = x;
280 workaround_for_gcc_295 = workaround_for_gcc_295;
281#endif
282
d5ad4aa6
MV
283 return SCM_I_CONSP (x);
284}
285
16ea9620 286#endif
16ea9620 287#endif