1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "libguile/_scm.h"
23 #include "libguile/eval.h"
24 #include "libguile/numbers.h"
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"
44 #include "libguile/private-gc.h"
46 long int scm_i_deprecated_memory_return
;
49 /* During collection, this accumulates structures which are to be freed.
51 SCM scm_i_structs_to_free
;
55 Init all the free cells in CARD, prepending to *FREE_LIST.
57 Return: number of free cells found in this card.
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
68 This function is quite efficient. However, for many types of cells,
69 allocation and a de-allocation involves calling malloc() and
72 This is costly for small objects (due to malloc/free overhead.)
73 (should measure this).
75 It might also be bad for threads: if several threads are allocating
76 strings concurrently, then mallocs for both threads may have to
79 It might be interesting to add a separate memory pool for small
80 objects to each freelist.
85 scm_i_sweep_card (scm_t_cell
* p
, SCM
*free_list
, scm_t_heap_segment
*seg
)
86 #define FUNC_NAME "sweep_card"
88 scm_t_c_bvec_long
*bitvec
= SCM_GC_CARD_BVEC(p
);
89 scm_t_cell
* end
= p
+ SCM_GC_CARD_N_CELLS
;
91 int offset
=SCM_MAX (SCM_GC_CARD_N_HEADER_CELLS
, span
);
97 I tried something fancy with shifting by one bit every word from
98 the bitvec in turn, but it wasn't any faster, but quite a bit
101 for (p
+= offset
; p
< end
; p
+= span
, offset
+= span
)
103 SCM scmptr
= PTR2SCM (p
);
104 if (SCM_C_BVEC_GET (bitvec
, offset
))
107 switch (SCM_TYP7 (scmptr
))
110 /* The card can be swept more than once. Check that it's
113 if (!SCM_STRUCT_GC_CHAIN (scmptr
))
115 /* Structs need to be freed in a special order.
116 * This is handled by GC C hooks in struct.c.
118 SCM_SET_STRUCT_GC_CHAIN (scmptr
, scm_i_structs_to_free
);
119 scm_i_structs_to_free
= scmptr
;
123 case scm_tcs_cons_imcar
:
124 case scm_tcs_cons_nimcar
:
125 case scm_tcs_closures
:
131 unsigned long int length
= SCM_VECTOR_LENGTH (scmptr
);
134 scm_gc_free (SCM_VECTOR_BASE (scmptr
),
135 length
* sizeof (scm_t_bits
),
142 scm_gc_free (SCM_CCLO_BASE (scmptr
),
143 SCM_CCLO_LENGTH (scmptr
) * sizeof (SCM
),
150 unsigned long int length
= SCM_BITVECTOR_LENGTH (scmptr
);
153 scm_gc_free (SCM_BITVECTOR_BASE (scmptr
),
155 * ((length
+SCM_LONG_BIT
-1) / SCM_LONG_BIT
)),
164 #if SCM_SIZEOF_LONG_LONG != 0
170 scm_gc_free (SCM_UVECTOR_BASE (scmptr
),
171 (SCM_UVECTOR_LENGTH (scmptr
)
172 * scm_uniform_element_size (scmptr
)),
177 switch SCM_TYP16 (scmptr
)
182 mpz_clear (SCM_I_BIG_MPZ (scmptr
));
183 /* nothing else to do here since the mpz is in a double cell */
185 case scm_tc16_complex
:
186 scm_gc_free (SCM_COMPLEX_MEM (scmptr
), sizeof (scm_t_complex
),
189 case scm_tc16_fraction
:
190 /* nothing to do here since the num/denum of a fraction
191 are proper SCM objects themselves. */
196 scm_gc_free (SCM_STRING_CHARS (scmptr
),
197 SCM_STRING_LENGTH (scmptr
) + 1, "string");
200 scm_gc_free (SCM_SYMBOL_CHARS (scmptr
),
201 SCM_SYMBOL_LENGTH (scmptr
) + 1, "symbol");
203 case scm_tc7_variable
:
206 /* the various "subrs" (primitives) are never freed */
209 if SCM_OPENP (scmptr
)
211 int k
= SCM_PTOBNUM (scmptr
);
213 #if (SCM_DEBUG_CELL_ACCESSES == 1)
214 if (!(k
< scm_numptob
))
216 fprintf (stderr
, "undefined port type");
220 /* Keep "revealed" ports alive. */
221 if (scm_revealed_count (scmptr
) > 0)
224 /* Yes, I really do mean scm_ptobs[k].free */
225 /* rather than ftobs[k].close. .close */
226 /* is for explicit CLOSE-PORT by user */
227 mm
= scm_ptobs
[k
].free (scmptr
);
231 #if SCM_ENABLE_DEPRECATED == 1
232 scm_c_issue_deprecation_warning
233 ("Returning non-0 from a port free function is "
234 "deprecated. Use scm_gc_free et al instead.");
235 scm_c_issue_deprecation_warning_fmt
236 ("(You just returned non-0 while freeing a %s.)",
238 scm_i_deprecated_memory_return
+= mm
;
244 SCM_SETSTREAM (scmptr
, 0);
245 scm_remove_from_port_table (scmptr
);
246 scm_gc_ports_collected
++;
247 SCM_CLR_PORT_OPEN_FLAG (scmptr
);
251 switch SCM_TYP16 (scmptr
)
253 case scm_tc_free_cell
:
258 k
= SCM_SMOBNUM (scmptr
);
259 #if (SCM_DEBUG_CELL_ACCESSES == 1)
260 if (!(k
< scm_numsmob
))
262 fprintf (stderr
, "undefined smob type");
266 if (scm_smobs
[k
].free
)
269 mm
= scm_smobs
[k
].free (scmptr
);
272 #if SCM_ENABLE_DEPRECATED == 1
273 scm_c_issue_deprecation_warning
274 ("Returning non-0 from a smob free function is "
275 "deprecated. Use scm_gc_free et al instead.");
276 scm_c_issue_deprecation_warning_fmt
277 ("(You just returned non-0 while freeing a %s.)",
279 scm_i_deprecated_memory_return
+= mm
;
290 fprintf (stderr
, "unknown type");
295 SCM_SET_CELL_TYPE (scmptr
, scm_tc_free_cell
);
296 SCM_SET_FREE_CELL_CDR (scmptr
, PTR2SCM (*free_list
));
308 Like sweep, but no complicated logic to do the sweeping.
311 scm_i_init_card_freelist (scm_t_cell
* card
, SCM
*free_list
,
312 scm_t_heap_segment
*seg
)
314 int span
= seg
->span
;
315 scm_t_cell
*end
= card
+ SCM_GC_CARD_N_CELLS
;
316 scm_t_cell
*p
= end
- span
;
318 scm_t_c_bvec_long
* bvec_ptr
= (scm_t_c_bvec_long
* ) seg
->bounds
[1];
319 int idx
= (card
- seg
->bounds
[0]) / SCM_GC_CARD_N_CELLS
;
321 bvec_ptr
+= idx
*SCM_GC_CARD_BVEC_SIZE_IN_LONGS
;
322 SCM_GC_SET_CELL_BVEC (card
, bvec_ptr
);
325 ASSUMPTION: n_header_cells <= 2.
327 for (; p
> card
; p
-= span
)
329 const SCM scmptr
= PTR2SCM (p
);
330 SCM_SET_CELL_TYPE (scmptr
, scm_tc_free_cell
);
331 SCM_SET_FREE_CELL_CDR (scmptr
, PTR2SCM (*free_list
));
335 return SCM_GC_CARD_N_CELLS
- SCM_MAX(span
, SCM_GC_CARD_N_HEADER_CELLS
);
339 #if (SCM_DEBUG_DEBUGGING_SUPPORT == 1)
341 typedef struct scm_dbg_t_list_cell
{
343 struct scm_dbg_t_list_cell
* cdr
;
344 } scm_dbg_t_list_cell
;
347 typedef struct scm_dbg_t_double_cell
{
352 } scm_dbg_t_double_cell
;
355 int scm_dbg_gc_marked_p (SCM obj
);
356 scm_t_cell
* scm_dbg_gc_get_card (SCM obj
);
357 long * scm_dbg_gc_get_bvec (SCM obj
);
361 scm_dbg_gc_marked_p (SCM obj
)
364 return SCM_GC_MARK_P(obj
);
370 scm_dbg_gc_get_card (SCM obj
)
373 return SCM_GC_CELL_CARD(obj
);
379 scm_dbg_gc_get_bvec (SCM obj
)
382 return SCM_GC_CARD_BVEC (SCM_GC_CELL_CARD (obj
));