1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003 Free Software Foundation, Inc.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program 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
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
55 extern unsigned long * __libc_ia64_register_backing_store_base
;
58 #include "libguile/_scm.h"
59 #include "libguile/eval.h"
60 #include "libguile/stime.h"
61 #include "libguile/stackchk.h"
62 #include "libguile/struct.h"
63 #include "libguile/smob.h"
64 #include "libguile/unif.h"
65 #include "libguile/async.h"
66 #include "libguile/ports.h"
67 #include "libguile/root.h"
68 #include "libguile/strings.h"
69 #include "libguile/vectors.h"
70 #include "libguile/weaks.h"
71 #include "libguile/hashtab.h"
72 #include "libguile/tags.h"
73 #include "libguile/private-gc.h"
74 #include "libguile/validate.h"
75 #include "libguile/deprecation.h"
76 #include "libguile/gc.h"
78 #ifdef GUILE_DEBUG_MALLOC
79 #include "libguile/debug-malloc.h"
91 # define SCM_MARK_BACKING_STORE() do { \
93 SCM_STACKITEM * top, * bot; \
95 scm_mark_locations ((SCM_STACKITEM *) &ctx.uc_mcontext, \
96 ((size_t) (sizeof (SCM_STACKITEM) - 1 + sizeof ctx.uc_mcontext) \
97 / sizeof (SCM_STACKITEM))); \
98 bot = (SCM_STACKITEM *) __libc_ia64_register_backing_store_base; \
99 top = (SCM_STACKITEM *) ctx.uc_mcontext.sc_ar_bsp; \
100 scm_mark_locations (bot, top - bot); } while (0)
102 # define SCM_MARK_BACKING_STORE()
107 Entry point for this file.
115 scm_i_clear_mark_space ();
117 /* Mark every thread's stack and registers */
118 scm_threads_mark_stacks ();
120 j
= SCM_NUM_PROTECTS
;
122 scm_gc_mark (scm_sys_protects
[j
]);
124 /* mark the registered roots */
127 for (i
= 0; i
< SCM_HASHTABLE_N_BUCKETS (scm_gc_registered_roots
); ++i
)
129 SCM l
= SCM_HASHTABLE_BUCKETS (scm_gc_registered_roots
)[i
];
130 for (; !SCM_NULLP (l
); l
= SCM_CDR (l
))
132 SCM
*p
= (SCM
*) (scm_num2long (SCM_CAAR (l
), 0, NULL
));
139 /* FIXME: we should have a means to register C functions to be run
140 * in different phases of GC
142 scm_mark_subr_table ();
149 Mark an object precisely, then recurse.
152 scm_gc_mark (SCM ptr
)
157 if (SCM_GC_MARK_P (ptr
))
162 SCM_SET_GC_MARK (ptr
);
163 scm_gc_mark_dependencies (ptr
);
168 Mark the dependencies of an object.
172 Should prefetch objects before marking, i.e. if marking a cell, we
173 should prefetch the car, and then mark the cdr. This will improve CPU
174 cache misses, because the car is more likely to be in core when we
177 See http://www.hpl.hp.com/techreports/2000/HPL-2000-99.pdf, reducing
178 garbage collector cache misses.
180 Prefetch is supported on GCC >= 3.1
184 Tried this with GCC 3.1.1 -- the time differences are barely measurable.
185 Perhaps this would work better with an explicit markstack?
190 scm_gc_mark_dependencies (SCM p
)
191 #define FUNC_NAME "scm_gc_mark_dependencies"
195 scm_t_bits cell_type
;
198 scm_mark_dependencies_again
:
200 cell_type
= SCM_GC_CELL_TYPE (ptr
);
201 switch (SCM_ITAG7 (cell_type
))
203 case scm_tcs_cons_nimcar
:
204 if (SCM_IMP (SCM_CDR (ptr
)))
211 scm_gc_mark (SCM_CAR (ptr
));
214 case scm_tcs_cons_imcar
:
219 scm_gc_mark (SCM_SETTER (ptr
));
220 ptr
= SCM_PROCEDURE (ptr
);
224 /* XXX - use less explicit code. */
225 scm_t_bits word0
= SCM_CELL_WORD_0 (ptr
) - scm_tc3_struct
;
226 scm_t_bits
* vtable_data
= (scm_t_bits
*) word0
;
227 SCM layout
= SCM_PACK (vtable_data
[scm_vtable_index_layout
]);
228 long len
= SCM_SYMBOL_LENGTH (layout
);
229 char * fields_desc
= SCM_SYMBOL_CHARS (layout
);
230 scm_t_bits
* struct_data
= (scm_t_bits
*) SCM_STRUCT_DATA (ptr
);
232 if (vtable_data
[scm_struct_i_flags
] & SCM_STRUCTF_ENTITY
)
234 scm_gc_mark (SCM_PACK (struct_data
[scm_struct_i_procedure
]));
235 scm_gc_mark (SCM_PACK (struct_data
[scm_struct_i_setter
]));
241 for (x
= 0; x
< len
- 2; x
+= 2, ++struct_data
)
242 if (fields_desc
[x
] == 'p')
243 scm_gc_mark (SCM_PACK (*struct_data
));
244 if (fields_desc
[x
] == 'p')
246 if (SCM_LAYOUT_TAILP (fields_desc
[x
+ 1]))
247 for (x
= *struct_data
++; x
; --x
, ++struct_data
)
248 scm_gc_mark (SCM_PACK (*struct_data
));
250 scm_gc_mark (SCM_PACK (*struct_data
));
254 ptr
= SCM_PACK (vtable_data
[scm_vtable_index_vtable
]);
258 case scm_tcs_closures
:
259 if (SCM_IMP (SCM_ENV (ptr
)))
261 ptr
= SCM_CLOSCAR (ptr
);
264 scm_gc_mark (SCM_CLOSCAR (ptr
));
268 i
= SCM_VECTOR_LENGTH (ptr
);
273 if (SCM_NIMP (SCM_VELTS (ptr
)[i
]))
274 scm_gc_mark (SCM_VELTS (ptr
)[i
]);
276 ptr
= SCM_VELTS (ptr
)[0];
281 size_t i
= SCM_CCLO_LENGTH (ptr
);
283 for (j
= 1; j
!= i
; ++j
)
285 SCM obj
= SCM_CCLO_REF (ptr
, j
);
289 ptr
= SCM_CCLO_REF (ptr
, 0);
293 #ifdef SCM_HAVE_ARRAYS
302 #if SCM_SIZEOF_LONG_LONG != 0
310 SCM_SET_WVECT_GC_CHAIN (ptr
, scm_weak_vectors
);
311 scm_weak_vectors
= ptr
;
312 if (SCM_IS_WHVEC_ANY (ptr
))
319 len
= SCM_VECTOR_LENGTH (ptr
);
320 weak_keys
= SCM_WVECT_WEAK_KEY_P (ptr
);
321 weak_values
= SCM_WVECT_WEAK_VALUE_P (ptr
);
323 for (x
= 0; x
< len
; ++x
)
326 alist
= SCM_VELTS (ptr
)[x
];
328 /* mark everything on the alist except the keys or
329 * values, according to weak_values and weak_keys. */
330 while ( SCM_CONSP (alist
)
331 && !SCM_GC_MARK_P (alist
)
332 && SCM_CONSP (SCM_CAR (alist
)))
337 kvpair
= SCM_CAR (alist
);
338 next_alist
= SCM_CDR (alist
);
341 * SCM_SET_GC_MARK (alist);
342 * SCM_SET_GC_MARK (kvpair);
344 * It may be that either the key or value is protected by
345 * an escaped reference to part of the spine of this alist.
346 * If we mark the spine here, and only mark one or neither of the
347 * key and value, they may never be properly marked.
348 * This leads to a horrible situation in which an alist containing
349 * freelist cells is exported.
351 * So only mark the spines of these arrays last of all marking.
352 * If somebody confuses us by constructing a weak vector
353 * with a circular alist then we are hosed, but at least we
354 * won't prematurely drop table entries.
357 scm_gc_mark (SCM_CAR (kvpair
));
359 scm_gc_mark (SCM_CDR (kvpair
));
362 if (SCM_NIMP (alist
))
369 ptr
= SCM_PROP_SLOTS (ptr
);
371 case scm_tc7_variable
:
372 ptr
= SCM_CELL_OBJECT_1 (ptr
);
377 i
= SCM_PTOBNUM (ptr
);
378 #if (SCM_DEBUG_CELL_ACCESSES == 1)
379 if (!(i
< scm_numptob
))
381 fprintf (stderr
, "undefined port type");
385 if (SCM_PTAB_ENTRY(ptr
))
386 scm_gc_mark (SCM_FILENAME (ptr
));
387 if (scm_ptobs
[i
].mark
)
389 ptr
= (scm_ptobs
[i
].mark
) (ptr
);
396 switch (SCM_TYP16 (ptr
))
397 { /* should be faster than going through scm_smobs */
398 case scm_tc_free_cell
:
399 /* We have detected a free cell. This can happen if non-object data
400 * on the C stack points into guile's heap and is scanned during
401 * conservative marking. */
405 case scm_tc16_complex
:
408 i
= SCM_SMOBNUM (ptr
);
409 #if (SCM_DEBUG_CELL_ACCESSES == 1)
410 if (!(i
< scm_numsmob
))
412 fprintf (stderr
, "undefined smob type");
416 if (scm_smobs
[i
].mark
)
418 ptr
= (scm_smobs
[i
].mark
) (ptr
);
426 fprintf (stderr
, "unknown type");
431 If we got here, then exhausted recursion options for PTR. we
432 return (careful not to mark PTR, it might be the argument that we
443 int valid_cell
= CELL_P (ptr
);
446 #if (SCM_DEBUG_CELL_ACCESSES == 1)
447 if (scm_debug_cell_accesses_p
)
449 /* We are in debug mode. Check the ptr exhaustively. */
451 valid_cell
= valid_cell
&& (scm_i_find_heap_segment_containing_object (ptr
) >= 0);
457 fprintf (stderr
, "rogue pointer in heap");
462 if (SCM_GC_MARK_P (ptr
))
467 SCM_SET_GC_MARK (ptr
);
469 goto scm_mark_dependencies_again
;
477 /* Mark a region conservatively */
479 scm_mark_locations (SCM_STACKITEM x
[], unsigned long n
)
483 for (m
= 0; m
< n
; ++m
)
485 SCM obj
= * (SCM
*) &x
[m
];
486 long int segment
= scm_i_find_heap_segment_containing_object (obj
);
493 /* The function scm_in_heap_p determines whether an SCM value can be regarded as a
494 * pointer to a cell on the heap.
497 scm_in_heap_p (SCM value
)
499 long int segment
= scm_i_find_heap_segment_containing_object (value
);
500 return (segment
>= 0);
504 #if SCM_ENABLE_DEPRECATED == 1
506 /* If an allocated cell is detected during garbage collection, this
507 * means that some code has just obtained the object but was preempted
508 * before the initialization of the object was completed. This meanst
509 * that some entries of the allocated cell may already contain SCM
510 * objects. Therefore, allocated cells are scanned conservatively.
513 scm_t_bits scm_tc16_allocated
;
516 allocated_mark (SCM cell
)
518 unsigned long int cell_segment
= scm_i_find_heap_segment_containing_object (cell
);
519 unsigned int span
= scm_i_heap_segment_table
[cell_segment
]->span
;
522 for (i
= 1; i
!= span
* 2; ++i
)
524 SCM obj
= SCM_CELL_OBJECT (cell
, i
);
525 long int obj_segment
= scm_i_find_heap_segment_containing_object (obj
);
526 if (obj_segment
>= 0)
533 scm_deprecated_newcell (void)
535 scm_c_issue_deprecation_warning
536 ("SCM_NEWCELL is deprecated. Use `scm_cell' instead.\n");
538 return scm_cell (scm_tc16_allocated
, 0);
542 scm_deprecated_newcell2 (void)
544 scm_c_issue_deprecation_warning
545 ("SCM_NEWCELL2 is deprecated. Use `scm_double_cell' instead.\n");
547 return scm_double_cell (scm_tc16_allocated
, 0, 0, 0);
550 #endif /* SCM_ENABLE_DEPRECATED == 1 */
554 scm_gc_init_mark(void)
556 #if SCM_ENABLE_DEPRECATED == 1
557 scm_tc16_allocated
= scm_make_smob_type ("allocated cell", 0);
558 scm_set_smob_mark (scm_tc16_allocated
, allocated_mark
);