(prototype_to_type): Bugfix: Don't compare prototype to
[bpt/guile.git] / libguile / inline.h
1 /* classes: h_files */
2
3 #ifndef SCM_INLINE_H
4 #define SCM_INLINE_H
5
6 /* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
7 *
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.
12 *
13 * This library 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 GNU
16 * Lesser General Public License for more details.
17 *
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
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
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
28 #include "libguile/__scm.h"
29
30 #if (SCM_DEBUG_CELL_ACCESSES == 1)
31 #include <stdio.h>
32 #endif
33
34 #include "libguile/pairs.h"
35 #include "libguile/gc.h"
36 #include "libguile/threads.h"
37 #include "libguile/unif.h"
38
39
40 SCM_API SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
41 SCM_API SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
42 scm_t_bits ccr, scm_t_bits cdr);
43
44 SCM_API SCM scm_array_handle_ref (scm_t_array_handle *h, ssize_t pos);
45 SCM_API void scm_array_handle_set (scm_t_array_handle *h, ssize_t pos, SCM val);
46
47
48 #if defined SCM_C_INLINE || defined SCM_INLINE_C_INCLUDING_INLINE_H
49 /* either inlining, or being included from inline.c. We use (and
50 repeat) this long #if test here and below so that we don't have to
51 introduce any extraneous symbols into the public namespace. We
52 only need SCM_C_INLINE to be seen publically . */
53
54 extern unsigned scm_newcell2_count;
55 extern unsigned scm_newcell_count;
56
57 #if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
58 /* definitely inlining */
59 #ifdef __GNUC__
60 extern
61 #else
62 static
63 #endif
64 SCM_C_INLINE
65 #endif
66 SCM
67 scm_cell (scm_t_bits car, scm_t_bits cdr)
68 {
69 SCM z;
70 /* We retrieve the SCM pointer only once since the call to
71 SCM_FREELIST_LOC will be slightly expensive when we support
72 preemptive multithreading. SCM_FREELIST_LOC will then retrieve
73 the thread specific freelist.
74
75 Until then, SCM_FREELIST_DOC expands to (&scm_i_freelist) and the
76 following code will compile to the same as if we had worked
77 directly on the scm_i_freelist variable.
78 */
79 SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist);
80
81 if (scm_gc_running_p)
82 {
83 abort();
84 }
85
86 if (scm_is_null (*freelist))
87 z = scm_gc_for_newcell (&scm_i_master_freelist, freelist);
88 else
89 {
90 z = *freelist;
91 *freelist = SCM_FREE_CELL_CDR (*freelist);
92 }
93
94 /*
95 We update scm_cells_allocated from this function. If we don't
96 update this explicitly, we will have to walk a freelist somewhere
97 later on, which seems a lot more expensive.
98 */
99 scm_cells_allocated += 1;
100
101 #if (SCM_DEBUG_CELL_ACCESSES == 1)
102 if (scm_debug_cell_accesses_p)
103 {
104 if (SCM_GC_MARK_P (z))
105 {
106 fprintf(stderr, "scm_cell tried to allocate a marked cell.\n");
107 abort();
108 }
109 else if (SCM_GC_CELL_WORD(z, 0) != scm_tc_free_cell)
110 {
111 fprintf(stderr, "cell from freelist is not a free cell.\n");
112 abort();
113 }
114 }
115
116 /*
117 Always set mark. Otherwise cells that are alloced before
118 scm_debug_cell_accesses_p is toggled seem invalid.
119 */
120 SCM_SET_GC_MARK (z);
121
122 /*
123 TODO: figure out if this use of mark bits is valid with
124 threading. What if another thread is doing GC at this point
125 ... ?
126 */
127
128 #endif
129
130
131 /* Initialize the type slot last so that the cell is ignored by the
132 GC until it is completely initialized. This is only relevant
133 when the GC can actually run during this code, which it can't for
134 cooperating threads, but it might be important when we get true
135 preemptive threads.
136 */
137 SCM_GC_SET_CELL_WORD (z, 1, cdr);
138 SCM_GC_SET_CELL_WORD (z, 0, car);
139
140 #if 0 /*fixme* Hmm... let's consider this later. */
141 #if !defined(SCM_USE_COOP_THREADS) && !defined(SCM_USE_NULL_THREADS) && !defined(SCM_USE_COPT_THREADS)
142 /* When we are using preemtive threads, we might need to make
143 sure that the initial values for the slots are protected until
144 the cell is completely initialized.
145 */
146 #error review me
147 scm_remember_upto_here_1 (SCM_PACK (cdr));
148 #endif
149 #endif
150
151 #if (SCM_DEBUG_CELL_ACCESSES == 1)
152 if (scm_expensive_debug_cell_accesses_p )
153 scm_i_expensive_validation_check (z);
154 #endif
155
156 return z;
157 }
158
159 #if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
160 /* definitely inlining */
161 #ifdef __GNUC__
162 extern
163 #else
164 static
165 #endif
166 SCM_C_INLINE
167 #endif
168 SCM
169 scm_double_cell (scm_t_bits car, scm_t_bits cbr,
170 scm_t_bits ccr, scm_t_bits cdr)
171 {
172 SCM z;
173 SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist2);
174
175 if (scm_gc_running_p)
176 {
177 abort();
178 }
179
180 if (scm_is_null (*freelist))
181 z = scm_gc_for_newcell (&scm_i_master_freelist2, freelist);
182 else
183 {
184 z = *freelist;
185 *freelist = SCM_FREE_CELL_CDR (*freelist);
186 }
187
188 scm_cells_allocated += 2;
189
190 /* Initialize the type slot last so that the cell is ignored by the
191 GC until it is completely initialized. This is only relevant
192 when the GC can actually run during this code, which it can't for
193 cooperating threads, but it might be important when we get true
194 preemptive threads.
195 */
196 SCM_GC_SET_CELL_WORD (z, 1, cbr);
197 SCM_GC_SET_CELL_WORD (z, 2, ccr);
198 SCM_GC_SET_CELL_WORD (z, 3, cdr);
199 SCM_GC_SET_CELL_WORD (z, 0, car);
200
201 #if 0 /*fixme* Hmm... let's consider this later. */
202 #if !defined(SCM_USE_COOP_THREADS) && !defined(SCM_USE_NULL_THREADS) && !defined(SCM_USE_COPT_THREADS)
203 /* When we are using non-cooperating threads, we might need to make
204 sure that the initial values for the slots are protected until
205 the cell is completely initialized.
206 */
207 #error review me
208 scm_remember_upto_here_3 (SCM_PACK (cbr), SCM_PACK (ccr), SCM_PACK (cdr));
209 #endif
210 #endif
211
212
213 #if (SCM_DEBUG_CELL_ACCESSES == 1)
214 if (scm_debug_cell_accesses_p)
215 {
216 if (SCM_GC_MARK_P (z))
217 {
218 fprintf(stderr,
219 "scm_double_cell tried to allocate a marked cell.\n");
220 abort();
221 }
222 }
223
224 /* see above. */
225 SCM_SET_GC_MARK (z);
226
227 #endif
228
229 /* When this function is inlined, it's possible that the last
230 SCM_GC_SET_CELL_WORD above will be adjacent to a following
231 initialization of z. E.g., it occurred in scm_make_real. GCC
232 from around version 3 (e.g., certainly 3.2) began taking
233 advantage of strict C aliasing rules which say that it's OK to
234 interchange the initialization above and the one below when the
235 pointer types appear to differ sufficiently. We don't want that,
236 of course. GCC allows this behaviour to be disabled with the
237 -fno-strict-aliasing option, but would also need to be supplied
238 by Guile users. Instead, the following statements prevent the
239 reordering.
240 */
241 #ifdef __GNUC__
242 asm volatile ("" : : : "memory");
243 #else
244 /* portable version, just in case any other compiler does the same
245 thing. */
246 scm_remember_upto_here_1 (z);
247 #endif
248
249 return z;
250 }
251
252 #if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
253 /* definitely inlining */
254 #ifdef __GNUC__
255 extern
256 #else
257 static
258 #endif
259 SCM_C_INLINE
260 #endif
261 SCM
262 scm_array_handle_ref (scm_t_array_handle *h, ssize_t p)
263 {
264 return h->ref (h, p);
265 }
266
267 #if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
268 /* definitely inlining */
269 #ifdef __GNUC__
270 extern
271 #else
272 static
273 #endif
274 SCM_C_INLINE
275 #endif
276 void
277 scm_array_handle_set (scm_t_array_handle *h, ssize_t p, SCM v)
278 {
279 h->set (h, p, v);
280 }
281
282 #endif
283 #endif