*** empty log message ***
[bpt/guile.git] / libguile / gc-card.c
CommitLineData
eb01cb64 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2004 Free Software Foundation, Inc.
c8a1bdc4 2 *
73be1d9e
MV
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
c8a1bdc4 7 *
73be1d9e 8 * This library is distributed in the hope that it will be useful,
c8a1bdc4 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
c8a1bdc4 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
c8a1bdc4
HWN
17
18
be3ff021 19#include <stdio.h>
660e30c5 20#include <gmp.h>
be3ff021 21
c8a1bdc4
HWN
22#include "libguile/_scm.h"
23#include "libguile/eval.h"
29c4382a 24#include "libguile/numbers.h"
c8a1bdc4
HWN
25#include "libguile/stime.h"
26#include "libguile/stackchk.h"
27#include "libguile/struct.h"
28#include "libguile/smob.h"
29#include "libguile/unif.h"
30#include "libguile/async.h"
31#include "libguile/ports.h"
32#include "libguile/root.h"
33#include "libguile/strings.h"
34#include "libguile/vectors.h"
35#include "libguile/weaks.h"
36#include "libguile/hashtab.h"
37#include "libguile/tags.h"
38#include "libguile/private-gc.h"
39#include "libguile/validate.h"
40#include "libguile/deprecation.h"
41#include "libguile/gc.h"
d315ee57 42#include "libguile/srfi-4.h"
c8a1bdc4
HWN
43
44#include "libguile/private-gc.h"
45
46long int scm_i_deprecated_memory_return;
47
48
ffd72400
HWN
49/* During collection, this accumulates structures which are to be freed.
50 */
51SCM scm_i_structs_to_free;
52
53
c8a1bdc4
HWN
54/*
55 Init all the free cells in CARD, prepending to *FREE_LIST.
56
57 Return: number of free cells found in this card.
58
59 It would be cleaner to have a separate function sweep_value(), but
60 that is too slow (functions with switch statements can't be
61 inlined).
06e80f59
HWN
62
63
64
c8a1bdc4 65
06e80f59
HWN
66 NOTE:
67
68 This function is quite efficient. However, for many types of cells,
69 allocation and a de-allocation involves calling malloc() and
70 free().
c8a1bdc4 71
06e80f59
HWN
72 This is costly for small objects (due to malloc/free overhead.)
73 (should measure this).
74
75 It might also be bad for threads: if several threads are allocating
76 strings concurrently, then mallocs for both threads may have to
77 fiddle with locks.
78
79 It might be interesting to add a separate memory pool for small
80 objects to each freelist.
81
82 --hwn.
83 */
c8a1bdc4 84int
1383773b 85scm_i_sweep_card (scm_t_cell * p, SCM *free_list, scm_t_heap_segment*seg)
c8a1bdc4
HWN
86#define FUNC_NAME "sweep_card"
87{
88 scm_t_c_bvec_long *bitvec = SCM_GC_CARD_BVEC(p);
89 scm_t_cell * end = p + SCM_GC_CARD_N_CELLS;
1383773b 90 int span = seg->span;
c8a1bdc4
HWN
91 int offset =SCM_MAX (SCM_GC_CARD_N_HEADER_CELLS, span);
92 int free_count = 0;
93
eab1b259
HWN
94 ++ scm_gc_running_p;
95
c8a1bdc4
HWN
96 /*
97 I tried something fancy with shifting by one bit every word from
dff96e95 98 the bitvec in turn, but it wasn't any faster, but quite a bit
c8a1bdc4
HWN
99 hairier.
100 */
101 for (p += offset; p < end; p += span, offset += span)
102 {
f96460ce 103 SCM scmptr = PTR2SCM (p);
c8a1bdc4
HWN
104 if (SCM_C_BVEC_GET (bitvec, offset))
105 continue;
106
107 switch (SCM_TYP7 (scmptr))
108 {
109 case scm_tcs_struct:
b4a1358c
MD
110 /* The card can be swept more than once. Check that it's
111 * the first time!
112 */
f96460ce 113 if (!SCM_STRUCT_GC_CHAIN (scmptr))
b4a1358c
MD
114 {
115 /* Structs need to be freed in a special order.
116 * This is handled by GC C hooks in struct.c.
117 */
f96460ce 118 SCM_SET_STRUCT_GC_CHAIN (scmptr, scm_i_structs_to_free);
b4a1358c
MD
119 scm_i_structs_to_free = scmptr;
120 }
c8a1bdc4
HWN
121 continue;
122
123 case scm_tcs_cons_imcar:
124 case scm_tcs_cons_nimcar:
125 case scm_tcs_closures:
126 case scm_tc7_pws:
127 break;
128 case scm_tc7_wvect:
129 case scm_tc7_vector:
b8b154fd
MV
130 scm_i_vector_free (scmptr);
131 break;
132
c8a1bdc4
HWN
133#ifdef CCLO
134 case scm_tc7_cclo:
135 scm_gc_free (SCM_CCLO_BASE (scmptr),
136 SCM_CCLO_LENGTH (scmptr) * sizeof (SCM),
137 "compiled closure");
138 break;
139#endif
b7a7750a 140
534c55a9
DH
141 case scm_tc7_number:
142 switch SCM_TYP16 (scmptr)
143 {
144 case scm_tc16_real:
145 break;
146 case scm_tc16_big:
147 mpz_clear (SCM_I_BIG_MPZ (scmptr));
148 /* nothing else to do here since the mpz is in a double cell */
149 break;
150 case scm_tc16_complex:
151 scm_gc_free (SCM_COMPLEX_MEM (scmptr), sizeof (scm_t_complex),
152 "complex");
153 break;
f92e85f7
MV
154 case scm_tc16_fraction:
155 /* nothing to do here since the num/denum of a fraction
156 are proper SCM objects themselves. */
157 break;
534c55a9
DH
158 }
159 break;
c8a1bdc4 160 case scm_tc7_string:
eb01cb64
MV
161 scm_i_string_free (scmptr);
162 break;
163 case scm_tc7_stringbuf:
164 scm_i_stringbuf_free (scmptr);
c8a1bdc4
HWN
165 break;
166 case scm_tc7_symbol:
eb01cb64 167 scm_i_symbol_free (scmptr);
c8a1bdc4
HWN
168 break;
169 case scm_tc7_variable:
170 break;
171 case scm_tcs_subrs:
172 /* the various "subrs" (primitives) are never freed */
173 continue;
174 case scm_tc7_port:
175 if SCM_OPENP (scmptr)
176 {
177 int k = SCM_PTOBNUM (scmptr);
178 size_t mm;
179#if (SCM_DEBUG_CELL_ACCESSES == 1)
180 if (!(k < scm_numptob))
be3ff021
HWN
181 {
182 fprintf (stderr, "undefined port type");
183 abort();
184 }
c8a1bdc4
HWN
185#endif
186 /* Keep "revealed" ports alive. */
187 if (scm_revealed_count (scmptr) > 0)
188 continue;
189
190 /* Yes, I really do mean scm_ptobs[k].free */
191 /* rather than ftobs[k].close. .close */
192 /* is for explicit CLOSE-PORT by user */
193 mm = scm_ptobs[k].free (scmptr);
194
195 if (mm != 0)
196 {
197#if SCM_ENABLE_DEPRECATED == 1
198 scm_c_issue_deprecation_warning
199 ("Returning non-0 from a port free function is "
200 "deprecated. Use scm_gc_free et al instead.");
201 scm_c_issue_deprecation_warning_fmt
202 ("(You just returned non-0 while freeing a %s.)",
203 SCM_PTOBNAME (k));
204 scm_i_deprecated_memory_return += mm;
205#else
206 abort ();
207#endif
208 }
209
210 SCM_SETSTREAM (scmptr, 0);
211 scm_remove_from_port_table (scmptr);
212 scm_gc_ports_collected++;
213 SCM_CLR_PORT_OPEN_FLAG (scmptr);
214 }
215 break;
216 case scm_tc7_smob:
217 switch SCM_TYP16 (scmptr)
218 {
219 case scm_tc_free_cell:
c8a1bdc4
HWN
220 break;
221 default:
222 {
223 int k;
224 k = SCM_SMOBNUM (scmptr);
225#if (SCM_DEBUG_CELL_ACCESSES == 1)
226 if (!(k < scm_numsmob))
be3ff021
HWN
227 {
228 fprintf (stderr, "undefined smob type");
229 abort();
230 }
c8a1bdc4
HWN
231#endif
232 if (scm_smobs[k].free)
233 {
234 size_t mm;
235 mm = scm_smobs[k].free (scmptr);
236 if (mm != 0)
237 {
238#if SCM_ENABLE_DEPRECATED == 1
239 scm_c_issue_deprecation_warning
240 ("Returning non-0 from a smob free function is "
241 "deprecated. Use scm_gc_free et al instead.");
242 scm_c_issue_deprecation_warning_fmt
243 ("(You just returned non-0 while freeing a %s.)",
244 SCM_SMOBNAME (k));
245 scm_i_deprecated_memory_return += mm;
246#else
247 abort();
248#endif
249 }
250 }
251 break;
252 }
253 }
254 break;
255 default:
be3ff021
HWN
256 fprintf (stderr, "unknown type");
257 abort();
c8a1bdc4
HWN
258 }
259
726f82e7 260 SCM_GC_SET_CELL_WORD (scmptr, 0, scm_tc_free_cell);
f96460ce
DH
261 SCM_SET_FREE_CELL_CDR (scmptr, PTR2SCM (*free_list));
262 *free_list = scmptr;
c8a1bdc4
HWN
263 free_count ++;
264 }
eab1b259
HWN
265
266 --scm_gc_running_p;
c8a1bdc4
HWN
267 return free_count;
268}
269#undef FUNC_NAME
270
271
272/*
273 Like sweep, but no complicated logic to do the sweeping.
274 */
275int
1383773b
HWN
276scm_i_init_card_freelist (scm_t_cell * card, SCM *free_list,
277 scm_t_heap_segment*seg)
c8a1bdc4 278{
1383773b 279 int span = seg->span;
c8a1bdc4
HWN
280 scm_t_cell *end = card + SCM_GC_CARD_N_CELLS;
281 scm_t_cell *p = end - span;
282
1383773b
HWN
283 scm_t_c_bvec_long * bvec_ptr = (scm_t_c_bvec_long* ) seg->bounds[1];
284 int idx = (card - seg->bounds[0]) / SCM_GC_CARD_N_CELLS;
285
286 bvec_ptr += idx *SCM_GC_CARD_BVEC_SIZE_IN_LONGS;
c5b0618d 287 SCM_GC_SET_CELL_BVEC (card, bvec_ptr);
1383773b 288
c8a1bdc4
HWN
289 /*
290 ASSUMPTION: n_header_cells <= 2.
291 */
292 for (; p > card; p -= span)
293 {
f96460ce 294 const SCM scmptr = PTR2SCM (p);
726f82e7 295 SCM_GC_SET_CELL_WORD (scmptr, 0, scm_tc_free_cell);
f96460ce
DH
296 SCM_SET_FREE_CELL_CDR (scmptr, PTR2SCM (*free_list));
297 *free_list = scmptr;
c8a1bdc4
HWN
298 }
299
300 return SCM_GC_CARD_N_CELLS - SCM_MAX(span, SCM_GC_CARD_N_HEADER_CELLS);
301}
302
303
d0624e39 304#if (SCM_DEBUG_DEBUGGING_SUPPORT == 1)
c8a1bdc4 305
94fb5a6e 306typedef struct scm_dbg_t_list_cell {
c8a1bdc4 307 scm_t_bits car;
94fb5a6e
DH
308 struct scm_dbg_t_list_cell * cdr;
309} scm_dbg_t_list_cell;
c8a1bdc4 310
eab1b259 311
94fb5a6e 312typedef struct scm_dbg_t_double_cell {
eab1b259
HWN
313 scm_t_bits word_0;
314 scm_t_bits word_1;
315 scm_t_bits word_2;
316 scm_t_bits word_3;
94fb5a6e 317} scm_dbg_t_double_cell;
eab1b259
HWN
318
319
94fb5a6e
DH
320int scm_dbg_gc_marked_p (SCM obj);
321scm_t_cell * scm_dbg_gc_get_card (SCM obj);
322long * scm_dbg_gc_get_bvec (SCM obj);
323
324
325int
326scm_dbg_gc_marked_p (SCM obj)
327{
328 if (!SCM_IMP (obj))
329 return SCM_GC_MARK_P(obj);
330 else
331 return 0;
332}
c8a1bdc4
HWN
333
334scm_t_cell *
94fb5a6e 335scm_dbg_gc_get_card (SCM obj)
c8a1bdc4 336{
94fb5a6e
DH
337 if (!SCM_IMP (obj))
338 return SCM_GC_CELL_CARD(obj);
339 else
340 return NULL;
c8a1bdc4
HWN
341}
342
343long *
94fb5a6e 344scm_dbg_gc_get_bvec (SCM obj)
c8a1bdc4 345{
94fb5a6e
DH
346 if (!SCM_IMP (obj))
347 return SCM_GC_CARD_BVEC (SCM_GC_CELL_CARD (obj));
348 else
349 return NULL;
c8a1bdc4 350}
94fb5a6e 351
c8a1bdc4 352#endif