*** 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 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
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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"
16ea9620 37
c8a1bdc4
HWN
38
39SCM_API SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
40SCM_API SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
41 scm_t_bits ccr, scm_t_bits cdr);
42
16ea9620 43
60e7529a
RB
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 . */
c8a1bdc4
HWN
50
51extern unsigned scm_newcell2_count;
52extern unsigned scm_newcell_count;
53
60e7529a
RB
54#if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
55/* definitely inlining */
56extern SCM_C_INLINE
57#endif
c8a1bdc4 58SCM
228a24ef 59scm_cell (scm_t_bits car, scm_t_bits cdr)
16ea9620
MV
60{
61 SCM z;
9bc4701c
MD
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);
16ea9620 72
9bc4701c
MD
73 if (SCM_NULLP (*freelist))
74 z = scm_gc_for_newcell (&scm_i_master_freelist, freelist);
c8a1bdc4 75 else
16ea9620 76 {
9bc4701c
MD
77 z = *freelist;
78 *freelist = SCM_FREE_CELL_CDR (*freelist);
16ea9620 79 }
c8a1bdc4
HWN
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)
1e71eafb
HWN
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 */
c8a1bdc4 114
c8a1bdc4 115#endif
16ea9620 116
c8a1bdc4 117
16ea9620
MV
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 */
1fc8902f
DH
124 SCM_GC_SET_CELL_WORD (z, 1, cdr);
125 SCM_GC_SET_CELL_WORD (z, 0, car);
16ea9620 126
9bc4701c 127#if 0 /*fixme* Hmm... let's consider this later. */
60e7529a 128#if !defined(SCM_USE_COOP_THREADS) && !defined(SCM_USE_NULL_THREADS) && !defined(SCM_USE_COPT_THREADS)
389626c5 129 /* When we are using preemtive threads, we might need to make
16ea9620
MV
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
9bc4701c 136#endif
c8a1bdc4 137
eab1b259
HWN
138#if (SCM_DEBUG_CELL_ACCESSES == 1)
139 if (scm_expensive_debug_cell_accesses_p )
140 scm_i_expensive_validation_check (z);
141#endif
c8a1bdc4 142
16ea9620
MV
143 return z;
144}
145
60e7529a
RB
146#if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
147/* definitely inlining */
148extern SCM_C_INLINE
149#endif
c8a1bdc4 150SCM
228a24ef
DH
151scm_double_cell (scm_t_bits car, scm_t_bits cbr,
152 scm_t_bits ccr, scm_t_bits cdr)
16ea9620
MV
153{
154 SCM z;
9bc4701c 155 SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist2);
16ea9620 156
9bc4701c
MD
157 if (SCM_NULLP (*freelist))
158 z = scm_gc_for_newcell (&scm_i_master_freelist2, freelist);
16ea9620
MV
159 else
160 {
9bc4701c
MD
161 z = *freelist;
162 *freelist = SCM_FREE_CELL_CDR (*freelist);
16ea9620
MV
163 }
164
c8a1bdc4
HWN
165 scm_cells_allocated += 2;
166
16ea9620
MV
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 */
1fc8902f
DH
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);
16ea9620 177
9bc4701c 178#if 0 /*fixme* Hmm... let's consider this later. */
60e7529a 179#if !defined(SCM_USE_COOP_THREADS) && !defined(SCM_USE_NULL_THREADS) && !defined(SCM_USE_COPT_THREADS)
16ea9620
MV
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
9bc4701c 187#endif
16ea9620 188
16ea9620 189
c8a1bdc4
HWN
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 }
c8a1bdc4 199 }
4ad0814a
HWN
200
201 /* see above. */
202 SCM_SET_GC_MARK (z);
203
3553e1d1
GH
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);
c8a1bdc4 224#endif
6253f3f1 225
c8a1bdc4
HWN
226 return z;
227}
6253f3f1 228
eab1b259
HWN
229
230
16ea9620 231#endif
16ea9620 232#endif