1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
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.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "libguile/_scm.h"
26 #include "libguile/eval.h"
27 #include "libguile/numbers.h"
28 #include "libguile/stime.h"
29 #include "libguile/stackchk.h"
30 #include "libguile/struct.h"
31 #include "libguile/smob.h"
32 #include "libguile/unif.h"
33 #include "libguile/async.h"
34 #include "libguile/ports.h"
35 #include "libguile/root.h"
36 #include "libguile/strings.h"
37 #include "libguile/vectors.h"
38 #include "libguile/weaks.h"
39 #include "libguile/hashtab.h"
40 #include "libguile/tags.h"
41 #include "libguile/private-gc.h"
42 #include "libguile/validate.h"
43 #include "libguile/deprecation.h"
44 #include "libguile/gc.h"
45 #include "libguile/srfi-4.h"
47 #include "libguile/private-gc.h"
49 long int scm_i_deprecated_memory_return;
52 /* During collection, this accumulates structures which are to be freed.
54 SCM scm_i_structs_to_free;
58 Init all the free cells in CARD, prepending to *FREE_LIST.
60 Return: number of free cells found in this card.
62 It would be cleaner to have a separate function sweep_value(), but
63 that is too slow (functions with switch statements can't be
71 This function is quite efficient. However, for many types of cells,
72 allocation and a de-allocation involves calling malloc() and
75 This is costly for small objects (due to malloc/free overhead.)
76 (should measure this).
78 It might also be bad for threads: if several threads are allocating
79 strings concurrently, then mallocs for both threads may have to
82 It might be interesting to add a separate memory pool for small
83 objects to each freelist.
88 scm_i_sweep_card (scm_t_cell * p, SCM *free_list, scm_t_heap_segment*seg)
89 #define FUNC_NAME "sweep_card"
91 scm_t_c_bvec_long *bitvec = SCM_GC_CARD_BVEC(p);
92 scm_t_cell * end = p + SCM_GC_CARD_N_CELLS;
94 int offset =SCM_MAX (SCM_GC_CARD_N_HEADER_CELLS, span);
98 I tried something fancy with shifting by one bit every word from
99 the bitvec in turn, but it wasn't any faster, but quite a bit
102 for (p += offset; p < end; p += span, offset += span)
104 SCM scmptr = PTR2SCM (p);
105 if (SCM_C_BVEC_GET (bitvec, offset))
108 switch (SCM_TYP7 (scmptr))
111 /* The card can be swept more than once. Check that it's
114 if (!SCM_STRUCT_GC_CHAIN (scmptr))
116 /* Structs need to be freed in a special order.
117 * This is handled by GC C hooks in struct.c.
119 SCM_SET_STRUCT_GC_CHAIN (scmptr, scm_i_structs_to_free);
120 scm_i_structs_to_free = scmptr;
124 case scm_tcs_cons_imcar:
125 case scm_tcs_cons_nimcar:
126 case scm_tcs_closures:
131 scm_i_vector_free (scmptr);
136 scm_gc_free (SCM_CCLO_BASE (scmptr),
137 SCM_CCLO_LENGTH (scmptr) * sizeof (SCM),
143 switch SCM_TYP16 (scmptr)
148 mpz_clear (SCM_I_BIG_MPZ (scmptr));
149 /* nothing else to do here since the mpz is in a double cell */
151 case scm_tc16_complex:
152 scm_gc_free (SCM_COMPLEX_MEM (scmptr), sizeof (scm_t_complex),
155 case scm_tc16_fraction:
156 /* nothing to do here since the num/denum of a fraction
157 are proper SCM objects themselves. */
162 scm_i_string_free (scmptr);
164 case scm_tc7_stringbuf:
165 scm_i_stringbuf_free (scmptr);
168 scm_i_symbol_free (scmptr);
170 case scm_tc7_variable:
173 /* the various "subrs" (primitives) are never freed */
176 if SCM_OPENP (scmptr)
178 int k = SCM_PTOBNUM (scmptr);
180 #if (SCM_DEBUG_CELL_ACCESSES == 1)
181 if (!(k < scm_numptob))
183 fprintf (stderr, "undefined port type");
187 /* Keep "revealed" ports alive. */
188 if (scm_revealed_count (scmptr) > 0)
191 /* Yes, I really do mean scm_ptobs[k].free */
192 /* rather than ftobs[k].close. .close */
193 /* is for explicit CLOSE-PORT by user */
194 mm = scm_ptobs[k].free (scmptr);
198 #if SCM_ENABLE_DEPRECATED == 1
199 scm_c_issue_deprecation_warning
200 ("Returning non-0 from a port free function is "
201 "deprecated. Use scm_gc_free et al instead.");
202 scm_c_issue_deprecation_warning_fmt
203 ("(You just returned non-0 while freeing a %s.)",
205 scm_i_deprecated_memory_return += mm;
211 SCM_SETSTREAM (scmptr, 0);
212 scm_remove_from_port_table (scmptr);
213 scm_gc_ports_collected++;
214 SCM_CLR_PORT_OPEN_FLAG (scmptr);
218 switch SCM_TYP16 (scmptr)
220 case scm_tc_free_cell:
226 k = SCM_SMOBNUM (scmptr);
227 #if (SCM_DEBUG_CELL_ACCESSES == 1)
228 if (!(k < scm_numsmob))
230 fprintf (stderr, "undefined smob type");
234 if (scm_smobs[k].free)
237 mm = scm_smobs[k].free (scmptr);
240 #if SCM_ENABLE_DEPRECATED == 1
241 scm_c_issue_deprecation_warning
242 ("Returning non-0 from a smob free function is "
243 "deprecated. Use scm_gc_free et al instead.");
244 scm_c_issue_deprecation_warning_fmt
245 ("(You just returned non-0 while freeing a %s.)",
247 scm_i_deprecated_memory_return += mm;
258 fprintf (stderr, "unknown type");
262 SCM_GC_SET_CELL_WORD (scmptr, 0, scm_tc_free_cell);
263 SCM_SET_FREE_CELL_CDR (scmptr, PTR2SCM (*free_list));
274 Like sweep, but no complicated logic to do the sweeping.
277 scm_i_init_card_freelist (scm_t_cell * card, SCM *free_list,
278 scm_t_heap_segment*seg)
280 int span = seg->span;
281 scm_t_cell *end = card + SCM_GC_CARD_N_CELLS;
282 scm_t_cell *p = end - span;
284 scm_t_c_bvec_long * bvec_ptr = (scm_t_c_bvec_long* ) seg->bounds[1];
285 int idx = (card - seg->bounds[0]) / SCM_GC_CARD_N_CELLS;
287 bvec_ptr += idx *SCM_GC_CARD_BVEC_SIZE_IN_LONGS;
288 SCM_GC_SET_CELL_BVEC (card, bvec_ptr);
291 ASSUMPTION: n_header_cells <= 2.
293 for (; p > card; p -= span)
295 const SCM scmptr = PTR2SCM (p);
296 SCM_GC_SET_CELL_WORD (scmptr, 0, scm_tc_free_cell);
297 SCM_SET_FREE_CELL_CDR (scmptr, PTR2SCM (*free_list));
301 return SCM_GC_CARD_N_CELLS - SCM_MAX(span, SCM_GC_CARD_N_HEADER_CELLS);
306 scm_i_card_statistics (scm_t_cell *p, SCM hashtab, scm_t_heap_segment *seg)
308 scm_t_c_bvec_long *bitvec = SCM_GC_CARD_BVEC(p);
309 scm_t_cell * end = p + SCM_GC_CARD_N_CELLS;
310 int span = seg->span;
311 int offset = SCM_MAX (SCM_GC_CARD_N_HEADER_CELLS, span);
314 /* Card P hasn't been initialized yet by `scm_i_init_card_freelist ()'. */
317 for (p += offset; p < end; p += span, offset += span)
320 SCM scmptr = PTR2SCM (p);
322 if (!SCM_C_BVEC_GET (bitvec, offset))
325 tag = SCM_TYP7 (scmptr);
326 if (tag == scm_tc7_smob || tag == scm_tc7_number)
328 /* Record smobs and numbers under 16 bits of the tag, so the
329 different smob objects are distinguished, and likewise the
330 different numbers big, real, complex and fraction. */
331 tag = SCM_TYP16(scmptr);
336 case scm_tcs_cons_imcar:
339 case scm_tcs_cons_nimcar:
344 tag = scm_tc3_struct;
346 case scm_tcs_closures:
347 tag = scm_tc3_closure;
355 SCM handle = scm_hashq_create_handle_x (hashtab,
356 scm_from_int (tag), SCM_INUM0);
357 SCM_SETCDR (handle, scm_from_int (scm_to_int (SCM_CDR (handle)) + 1));
362 /* TAG is the tag word of a cell, return a string which is its name, or NULL
363 if unknown. Currently this is only used by gc-live-object-stats and the
364 distinctions between types are oriented towards what that code records
365 while scanning what's alive. */
367 scm_i_tag_name (scm_t_bits tag)
369 switch (tag & 0x7F) /* 7 bits */
373 case scm_tcs_cons_imcar:
374 return "cons (immediate car)";
375 case scm_tcs_cons_nimcar:
376 return "cons (non-immediate car)";
377 case scm_tcs_closures:
382 return "weak vector";
387 return "compiled closure";
396 case scm_tc16_complex:
397 return "complex number";
398 case scm_tc16_fraction:
401 /* shouldn't reach here unless there's a new class of numbers */
405 case scm_tc7_stringbuf:
406 return "string buffer";
409 case scm_tc7_variable:
416 /* scm_tc_free_cell is smob 0, the name field in that scm_smobs[]
417 entry should be ok for our return here */
418 return scm_smobs[SCM_TC2SMOBNUM(tag)].name;
425 #if (SCM_DEBUG_DEBUGGING_SUPPORT == 1)
427 typedef struct scm_dbg_t_list_cell {
429 struct scm_dbg_t_list_cell * cdr;
430 } scm_dbg_t_list_cell;
433 typedef struct scm_dbg_t_double_cell {
438 } scm_dbg_t_double_cell;
441 int scm_dbg_gc_marked_p (SCM obj);
442 scm_t_cell * scm_dbg_gc_get_card (SCM obj);
443 scm_t_c_bvec_long * scm_dbg_gc_get_bvec (SCM obj);
447 scm_dbg_gc_marked_p (SCM obj)
450 return SCM_GC_MARK_P(obj);
456 scm_dbg_gc_get_card (SCM obj)
459 return SCM_GC_CELL_CARD(obj);
465 scm_dbg_gc_get_bvec (SCM obj)
468 return SCM_GC_CARD_BVEC (SCM_GC_CELL_CARD (obj));