1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2004, 2005, 2006, 2009 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 License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful, but
9 * 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
32 extern unsigned long * __libc_ia64_register_backing_store_base
;
35 #include "libguile/_scm.h"
36 #include "libguile/eval.h"
37 #include "libguile/stime.h"
38 #include "libguile/stackchk.h"
39 #include "libguile/struct.h"
40 #include "libguile/smob.h"
41 #include "libguile/unif.h"
42 #include "libguile/async.h"
43 #include "libguile/ports.h"
44 #include "libguile/root.h"
45 #include "libguile/strings.h"
46 #include "libguile/vectors.h"
47 #include "libguile/weaks.h"
48 #include "libguile/hashtab.h"
49 #include "libguile/tags.h"
50 #include "libguile/private-gc.h"
51 #include "libguile/validate.h"
52 #include "libguile/deprecation.h"
53 #include "libguile/gc.h"
54 #include "libguile/guardians.h"
56 #ifdef GUILE_DEBUG_MALLOC
57 #include "libguile/debug-malloc.h"
68 int scm_i_marking
= 0;
71 Entry point for this file.
80 scm_i_init_weak_vectors_for_gc ();
81 scm_i_init_guardians_for_gc ();
83 scm_i_clear_mark_space ();
84 scm_i_find_heap_calls
= 0;
85 /* Mark every thread's stack and registers */
86 scm_threads_mark_stacks ();
90 scm_gc_mark (scm_sys_protects
[j
]);
92 /* mark the registered roots */
95 for (i
= 0; i
< SCM_HASHTABLE_N_BUCKETS (scm_gc_registered_roots
); ++i
)
97 SCM l
= SCM_HASHTABLE_BUCKET (scm_gc_registered_roots
, i
);
98 for (; !scm_is_null (l
); l
= SCM_CDR (l
))
100 SCM
*p
= (SCM
*) (scm_to_ulong (SCM_CAAR (l
)));
112 /* Mark the non-weak references of weak vectors. For a weak key
113 alist vector, this would mark the values for keys that are
114 marked. We need to do this in a loop until everything
115 settles down since the newly marked values might be keys in
116 other weak key alist vectors, for example.
118 again
= scm_i_mark_weak_vectors_non_weaks ();
122 /* Now we scan all marked guardians and move all unmarked objects
123 from the accessible to the inaccessible list.
125 scm_i_identify_inaccessible_guardeds ();
127 /* When we have identified all inaccessible objects, we can mark
130 again
= scm_i_mark_inaccessible_guardeds ();
132 /* This marking might have changed the situation for weak vectors
133 and might have turned up new guardians that need to be processed,
134 so we do it all over again.
139 /* Nothing new marked in this round, we are done.
144 /* Remove all unmarked entries from the weak vectors.
146 scm_i_remove_weaks_from_weak_vectors ();
148 /* Bring hashtables upto date.
150 scm_i_scan_weak_hashtables ();
158 Mark an object precisely, then recurse.
161 scm_gc_mark (SCM ptr
)
166 if (SCM_GC_MARK_P (ptr
))
171 static const char msg
[]
172 = "Should only call scm_gc_mark() during GC.";
173 scm_c_issue_deprecation_warning (msg
);
176 SCM_SET_GC_MARK (ptr
);
177 scm_gc_mark_dependencies (ptr
);
181 scm_i_ensure_marking (void)
183 assert (scm_i_marking
);
188 Mark the dependencies of an object.
192 Should prefetch objects before marking, i.e. if marking a cell, we
193 should prefetch the car, and then mark the cdr. This will improve CPU
194 cache misses, because the car is more likely to be in cache when we
197 See http://www.hpl.hp.com/techreports/2000/HPL-2000-99.pdf, reducing
198 garbage collector cache misses.
200 Prefetch is supported on GCC >= 3.1
204 Tried this with GCC 3.1.1 -- the time differences are barely measurable.
205 Perhaps this would work better with an explicit markstack?
211 scm_gc_mark_dependencies (SCM p
)
212 #define FUNC_NAME "scm_gc_mark_dependencies"
219 scm_mark_dependencies_again
:
221 cell_type
= SCM_GC_CELL_TYPE (ptr
);
222 switch (SCM_ITAG7 (cell_type
))
224 case scm_tcs_cons_nimcar
:
225 if (SCM_IMP (SCM_CDR (ptr
)))
232 scm_gc_mark (SCM_CAR (ptr
));
235 case scm_tcs_cons_imcar
:
240 scm_gc_mark (SCM_SETTER (ptr
));
241 ptr
= SCM_PROCEDURE (ptr
);
245 /* XXX - use less explicit code. */
246 scm_t_bits word0
= SCM_CELL_WORD_0 (ptr
) - scm_tc3_struct
;
247 scm_t_bits
* vtable_data
= (scm_t_bits
*) word0
;
248 SCM layout
= SCM_PACK (vtable_data
[scm_vtable_index_layout
]);
249 long len
= scm_i_symbol_length (layout
);
250 const char *fields_desc
= scm_i_symbol_chars (layout
);
251 scm_t_bits
*struct_data
= (scm_t_bits
*) SCM_STRUCT_DATA (ptr
);
253 if (vtable_data
[scm_struct_i_flags
] & SCM_STRUCTF_ENTITY
)
255 scm_gc_mark (SCM_PACK (struct_data
[scm_struct_i_procedure
]));
256 scm_gc_mark (SCM_PACK (struct_data
[scm_struct_i_setter
]));
262 for (x
= 0; x
< len
- 2; x
+= 2, ++struct_data
)
263 if (fields_desc
[x
] == 'p')
264 scm_gc_mark (SCM_PACK (*struct_data
));
265 if (fields_desc
[x
] == 'p')
267 if (SCM_LAYOUT_TAILP (fields_desc
[x
+ 1]))
268 for (x
= *struct_data
++; x
; --x
, ++struct_data
)
269 scm_gc_mark (SCM_PACK (*struct_data
));
271 scm_gc_mark (SCM_PACK (*struct_data
));
275 ptr
= SCM_PACK (vtable_data
[scm_vtable_index_vtable
]);
279 case scm_tcs_closures
:
280 if (SCM_IMP (SCM_ENV (ptr
)))
282 ptr
= SCM_CLOSCAR (ptr
);
285 scm_gc_mark (SCM_CLOSCAR (ptr
));
289 i
= SCM_SIMPLE_VECTOR_LENGTH (ptr
);
294 SCM elt
= SCM_SIMPLE_VECTOR_REF (ptr
, i
);
298 ptr
= SCM_SIMPLE_VECTOR_REF (ptr
, 0);
302 ptr
= scm_i_string_mark (ptr
);
304 case scm_tc7_stringbuf
:
305 ptr
= scm_i_stringbuf_mark (ptr
);
309 if (SCM_TYP16 (ptr
) == scm_tc16_fraction
)
311 scm_gc_mark (SCM_CELL_OBJECT_1 (ptr
));
312 ptr
= SCM_CELL_OBJECT_2 (ptr
);
318 scm_i_mark_weak_vector (ptr
);
322 ptr
= scm_i_symbol_mark (ptr
);
324 case scm_tc7_variable
:
325 ptr
= SCM_CELL_OBJECT_1 (ptr
);
328 if (SCM_CELL_WORD_2 (ptr
) && *(SCM
*)SCM_CELL_WORD_2 (ptr
))
329 /* the generic associated with this primitive */
330 scm_gc_mark (*(SCM
*)SCM_CELL_WORD_2 (ptr
));
331 if (SCM_NIMP (((SCM
*)SCM_CELL_WORD_3 (ptr
))[1]))
332 scm_gc_mark (((SCM
*)SCM_CELL_WORD_3 (ptr
))[1]); /* props */
333 ptr
= ((SCM
*)SCM_CELL_WORD_3 (ptr
))[0]; /* name */
336 i
= SCM_PTOBNUM (ptr
);
337 #if (SCM_DEBUG_CELL_ACCESSES == 1)
338 if (!(i
< scm_numptob
))
340 fprintf (stderr
, "undefined port type");
344 if (SCM_PTAB_ENTRY (ptr
))
345 scm_gc_mark (SCM_FILENAME (ptr
));
346 if (scm_ptobs
[i
].mark
)
348 ptr
= (scm_ptobs
[i
].mark
) (ptr
);
355 switch (SCM_TYP16 (ptr
))
356 { /* should be faster than going through scm_smobs */
357 case scm_tc_free_cell
:
358 /* We have detected a free cell. This can happen if non-object data
359 * on the C stack points into guile's heap and is scanned during
360 * conservative marking. */
363 i
= SCM_SMOBNUM (ptr
);
364 #if (SCM_DEBUG_CELL_ACCESSES == 1)
365 if (!(i
< scm_numsmob
))
367 fprintf (stderr
, "undefined smob type");
371 if (scm_smobs
[i
].mark
)
373 ptr
= (scm_smobs
[i
].mark
) (ptr
);
381 fprintf (stderr
, "unknown type");
386 If we got here, then exhausted recursion options for PTR. we
387 return (careful not to mark PTR, it might be the argument that we
398 int valid_cell
= CELL_P (ptr
);
401 #if (SCM_DEBUG_CELL_ACCESSES == 1)
402 if (scm_debug_cell_accesses_p
)
404 /* We are in debug mode. Check the ptr exhaustively. */
406 valid_cell
= valid_cell
&& scm_in_heap_p (ptr
);
412 fprintf (stderr
, "rogue pointer in heap");
417 if (SCM_GC_MARK_P (ptr
))
420 SCM_SET_GC_MARK (ptr
);
422 goto scm_mark_dependencies_again
;
428 /* Mark a region conservatively */
430 scm_mark_locations (SCM_STACKITEM x
[], unsigned long n
)
434 for (m
= 0; m
< n
; ++m
)
436 SCM obj
= * (SCM
*) &x
[m
];
437 long int segment
= scm_i_find_heap_segment_containing_object (obj
);
444 /* The function scm_in_heap_p determines whether an SCM value can be regarded as a
445 * pointer to a cell on the heap.
448 scm_in_heap_p (SCM value
)
450 long int segment
= scm_i_find_heap_segment_containing_object (value
);
451 return (segment
>= 0);
455 #if SCM_ENABLE_DEPRECATED == 1
457 /* If an allocated cell is detected during garbage collection, this
458 * means that some code has just obtained the object but was preempted
459 * before the initialization of the object was completed. This meanst
460 * that some entries of the allocated cell may already contain SCM
461 * objects. Therefore, allocated cells are scanned conservatively.
464 scm_t_bits scm_tc16_allocated
;
467 allocated_mark (SCM cell
)
469 unsigned long int cell_segment
= scm_i_find_heap_segment_containing_object (cell
);
470 unsigned int span
= scm_i_heap_segment_table
[cell_segment
]->span
;
473 for (i
= 1; i
!= span
* 2; ++i
)
475 SCM obj
= SCM_CELL_OBJECT (cell
, i
);
476 long int obj_segment
= scm_i_find_heap_segment_containing_object (obj
);
477 if (obj_segment
>= 0)
484 scm_deprecated_newcell (void)
486 scm_c_issue_deprecation_warning
487 ("SCM_NEWCELL is deprecated. Use `scm_cell' instead.\n");
489 return scm_cell (scm_tc16_allocated
, 0);
493 scm_deprecated_newcell2 (void)
495 scm_c_issue_deprecation_warning
496 ("SCM_NEWCELL2 is deprecated. Use `scm_double_cell' instead.\n");
498 return scm_double_cell (scm_tc16_allocated
, 0, 0, 0);
501 #endif /* SCM_ENABLE_DEPRECATED == 1 */
505 scm_gc_init_mark (void)
507 #if SCM_ENABLE_DEPRECATED == 1
508 scm_tc16_allocated
= scm_make_smob_type ("allocated cell", 0);
509 scm_set_smob_mark (scm_tc16_allocated
, allocated_mark
);