393865233c894a671758a3a45b1cc00c6f75741c
[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 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
38
39 SCM_API SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
40 SCM_API SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
41 scm_t_bits ccr, scm_t_bits cdr);
42
43
44
45 #if defined SCM_C_INLINE || defined SCM_INLINE_C_INCLUDING_INLINE_H
46 /* either inlining, or being included from inline.c. We use (and
47 repeat) this long #if test here and below so that we don't have to
48 introduce any extraneous symbols into the public namespace. We
49 only need SCM_C_INLINE to be seen publically . */
50
51 extern unsigned scm_newcell2_count;
52 extern unsigned scm_newcell_count;
53
54 #if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
55 /* definitely inlining */
56 extern SCM_C_INLINE
57 #endif
58 SCM
59 scm_cell (scm_t_bits car, scm_t_bits cdr)
60 {
61 SCM z;
62 /* We retrieve the SCM pointer only once since the call to
63 SCM_FREELIST_LOC will be slightly expensive when we support
64 preemptive multithreading. SCM_FREELIST_DOC will then retrieve
65 the thread specific freelist.
66
67 Until then, SCM_FREELIST_DOC expands to (&scm_i_freelist) and the
68 following code will compile to the same as if we had worked
69 directly on the scm_i_freelist variable.
70 */
71 SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist);
72
73 if (SCM_NULLP (*freelist))
74 z = scm_gc_for_newcell (&scm_i_master_freelist, freelist);
75 else
76 {
77 z = *freelist;
78 *freelist = SCM_FREE_CELL_CDR (*freelist);
79 }
80
81 /*
82 We update scm_cells_allocated from this function. If we don't
83 update this explicitly, we will have to walk a freelist somewhere
84 later on, which seems a lot more expensive.
85 */
86 scm_cells_allocated += 1;
87
88 #if (SCM_DEBUG_CELL_ACCESSES == 1)
89 if (scm_debug_cell_accesses_p)
90 {
91 if (SCM_GC_MARK_P (z))
92 {
93 fprintf(stderr, "scm_cell tried to allocate a marked cell.\n");
94 abort();
95 }
96 else if (SCM_GC_CELL_TYPE(z) != scm_tc_free_cell)
97 {
98 fprintf(stderr, "cell from freelist is not a free cell.\n");
99 abort();
100 }
101 }
102
103 /*
104 Always set mark. Otherwise cells that are alloced before
105 scm_debug_cell_accesses_p is toggled seem invalid.
106 */
107 SCM_SET_GC_MARK (z);
108
109 /*
110 TODO: figure out if this use of mark bits is valid with
111 threading. What if another thread is doing GC at this point
112 ... ?
113 */
114
115 #endif
116
117
118 /* Initialize the type slot last so that the cell is ignored by the
119 GC until it is completely initialized. This is only relevant
120 when the GC can actually run during this code, which it can't for
121 cooperating threads, but it might be important when we get true
122 preemptive threads.
123 */
124 SCM_GC_SET_CELL_WORD (z, 1, cdr);
125 SCM_GC_SET_CELL_WORD (z, 0, car);
126
127 #if 0 /*fixme* Hmm... let's consider this later. */
128 #if !defined(SCM_USE_COOP_THREADS) && !defined(SCM_USE_NULL_THREADS) && !defined(SCM_USE_COPT_THREADS)
129 /* When we are using preemtive threads, we might need to make
130 sure that the initial values for the slots are protected until
131 the cell is completely initialized.
132 */
133 #error review me
134 scm_remember_upto_here_1 (SCM_PACK (cdr));
135 #endif
136 #endif
137
138 #if (SCM_DEBUG_CELL_ACCESSES == 1)
139 if (scm_expensive_debug_cell_accesses_p )
140 scm_i_expensive_validation_check (z);
141 #endif
142
143 return z;
144 }
145
146 #if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
147 /* definitely inlining */
148 extern SCM_C_INLINE
149 #endif
150 SCM
151 scm_double_cell (scm_t_bits car, scm_t_bits cbr,
152 scm_t_bits ccr, scm_t_bits cdr)
153 {
154 SCM z;
155 SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist2);
156
157 if (SCM_NULLP (*freelist))
158 z = scm_gc_for_newcell (&scm_i_master_freelist2, freelist);
159 else
160 {
161 z = *freelist;
162 *freelist = SCM_FREE_CELL_CDR (*freelist);
163 }
164
165 scm_cells_allocated += 2;
166
167 /* Initialize the type slot last so that the cell is ignored by the
168 GC until it is completely initialized. This is only relevant
169 when the GC can actually run during this code, which it can't for
170 cooperating threads, but it might be important when we get true
171 preemptive threads.
172 */
173 SCM_GC_SET_CELL_WORD (z, 1, cbr);
174 SCM_GC_SET_CELL_WORD (z, 2, ccr);
175 SCM_GC_SET_CELL_WORD (z, 3, cdr);
176 SCM_GC_SET_CELL_WORD (z, 0, car);
177
178 #if 0 /*fixme* Hmm... let's consider this later. */
179 #if !defined(SCM_USE_COOP_THREADS) && !defined(SCM_USE_NULL_THREADS) && !defined(SCM_USE_COPT_THREADS)
180 /* When we are using non-cooperating threads, we might need to make
181 sure that the initial values for the slots are protected until
182 the cell is completely initialized.
183 */
184 #error review me
185 scm_remember_upto_here_3 (SCM_PACK (cbr), SCM_PACK (ccr), SCM_PACK (cdr));
186 #endif
187 #endif
188
189
190 #if (SCM_DEBUG_CELL_ACCESSES == 1)
191 if (scm_debug_cell_accesses_p)
192 {
193 if (SCM_GC_MARK_P (z))
194 {
195 fprintf(stderr,
196 "scm_double_cell tried to allocate a marked cell.\n");
197 abort();
198 }
199 }
200
201 /* see above. */
202 SCM_SET_GC_MARK (z);
203
204 #endif
205
206 /* When this function is inlined, it's possible that the last
207 SCM_GC_SET_CELL_WORD above will be adjacent to a following
208 initialization of z. E.g., it occurred in scm_make_real. GCC
209 from around version 3 (e.g., certainly 3.2) began taking
210 advantage of strict C aliasing rules which say that it's OK to
211 interchange the initialization above and the one below when the
212 pointer types appear to differ sufficiently. We don't want that,
213 of course. GCC allows this behaviour to be disabled with the
214 -fno-strict-aliasing option, but would also need to be supplied
215 by Guile users. Instead, the following statements prevent the
216 reordering.
217 */
218 #ifdef __GNUC__
219 asm volatile ("" : : : "memory");
220 #else
221 /* portable version, just in case any other compiler does the same
222 thing. */
223 scm_remember_upto_here_1 (z);
224 #endif
225
226 return z;
227 }
228
229
230
231 #endif
232 #endif