1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002 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. */
51 extern unsigned long * __libc_ia64_register_backing_store_base
;
54 #include "libguile/_scm.h"
55 #include "libguile/eval.h"
56 #include "libguile/stime.h"
57 #include "libguile/stackchk.h"
58 #include "libguile/struct.h"
59 #include "libguile/smob.h"
60 #include "libguile/unif.h"
61 #include "libguile/async.h"
62 #include "libguile/ports.h"
63 #include "libguile/root.h"
64 #include "libguile/strings.h"
65 #include "libguile/vectors.h"
66 #include "libguile/weaks.h"
67 #include "libguile/hashtab.h"
68 #include "libguile/tags.h"
69 #include "libguile/private-gc.h"
70 #include "libguile/validate.h"
71 #include "libguile/deprecation.h"
72 #include "libguile/gc.h"
74 #ifdef GUILE_DEBUG_MALLOC
75 #include "libguile/debug-malloc.h"
90 # define SCM_MARK_BACKING_STORE() do { \
92 SCM_STACKITEM * top, * bot; \
94 scm_mark_locations ((SCM_STACKITEM *) &ctx.uc_mcontext, \
95 ((size_t) (sizeof (SCM_STACKITEM) - 1 + sizeof ctx.uc_mcontext) \
96 / sizeof (SCM_STACKITEM))); \
97 bot = (SCM_STACKITEM *) __libc_ia64_register_backing_store_base; \
98 top = (SCM_STACKITEM *) ctx.uc_mcontext.sc_ar_bsp; \
99 scm_mark_locations (bot, top - bot); } while (0)
101 # define SCM_MARK_BACKING_STORE()
105 Entry point for this file.
113 scm_i_clear_mark_space ();
117 /* Mark objects on the C stack. */
118 SCM_FLUSH_REGISTER_WINDOWS
;
119 /* This assumes that all registers are saved into the jmp_buf */
120 setjmp (scm_save_regs_gc_mark
);
121 scm_mark_locations ((SCM_STACKITEM
*) scm_save_regs_gc_mark
,
122 ( (size_t) (sizeof (SCM_STACKITEM
) - 1 +
123 sizeof scm_save_regs_gc_mark
)
124 / sizeof (SCM_STACKITEM
)));
127 unsigned long stack_len
= scm_stack_size (scm_stack_base
);
128 #ifdef SCM_STACK_GROWS_UP
129 scm_mark_locations (scm_stack_base
, stack_len
);
131 scm_mark_locations (scm_stack_base
- stack_len
, stack_len
);
134 SCM_MARK_BACKING_STORE();
136 #else /* USE_THREADS */
138 /* Mark every thread's stack and registers */
139 scm_threads_mark_stacks ();
141 #endif /* USE_THREADS */
143 j
= SCM_NUM_PROTECTS
;
145 scm_gc_mark (scm_sys_protects
[j
]);
147 /* mark the registered roots */
150 for (i
= 0; i
< SCM_VECTOR_LENGTH (scm_gc_registered_roots
); ++i
)
152 SCM l
= SCM_VELTS (scm_gc_registered_roots
)[i
];
153 for (; !SCM_NULLP (l
); l
= SCM_CDR (l
))
155 SCM
*p
= (SCM
*) (scm_num2long (SCM_CAAR (l
), 0, NULL
));
161 /* FIXME: we should have a means to register C functions to be run
162 * in different phases of GC
164 scm_mark_subr_table ();
167 scm_gc_mark (scm_root
->handle
);
176 Mark an object precisely, then recurse.
179 scm_gc_mark (SCM ptr
)
184 if (SCM_GC_MARK_P (ptr
))
187 SCM_SET_GC_MARK (ptr
);
188 scm_gc_mark_dependencies (ptr
);
193 Mark the dependencies of an object.
197 Should prefetch objects before marking, i.e. if marking a cell, we
198 should prefetch the car, and then mark the cdr. This will improve CPU
199 cache misses, because the car is more likely to be in core when we
202 See http://www.hpl.hp.com/techreports/2000/HPL-2000-99.pdf, reducing
203 garbage collector cache misses.
205 Prefetch is supported on GCC >= 3.1
209 Tried this with GCC 3.1.1 -- the time differences are barely measurable.
210 Perhaps this would work better with an explicit markstack?
215 scm_gc_mark_dependencies (SCM p
)
216 #define FUNC_NAME "scm_gc_mark_dependencies"
220 scm_t_bits cell_type
;
223 scm_mark_dependencies_again
:
225 cell_type
= SCM_GC_CELL_TYPE (ptr
);
226 switch (SCM_ITAG7 (cell_type
))
228 case scm_tcs_cons_nimcar
:
229 if (SCM_IMP (SCM_CDR (ptr
)))
236 scm_gc_mark (SCM_CAR (ptr
));
239 case scm_tcs_cons_imcar
:
244 scm_gc_mark (SCM_SETTER (ptr
));
245 ptr
= SCM_PROCEDURE (ptr
);
249 /* XXX - use less explicit code. */
250 scm_t_bits word0
= SCM_CELL_WORD_0 (ptr
) - scm_tc3_struct
;
251 scm_t_bits
* vtable_data
= (scm_t_bits
*) word0
;
252 SCM layout
= SCM_PACK (vtable_data
[scm_vtable_index_layout
]);
253 long len
= SCM_SYMBOL_LENGTH (layout
);
254 char * fields_desc
= SCM_SYMBOL_CHARS (layout
);
255 scm_t_bits
* struct_data
= (scm_t_bits
*) SCM_STRUCT_DATA (ptr
);
257 if (vtable_data
[scm_struct_i_flags
] & SCM_STRUCTF_ENTITY
)
259 scm_gc_mark (SCM_PACK (struct_data
[scm_struct_i_procedure
]));
260 scm_gc_mark (SCM_PACK (struct_data
[scm_struct_i_setter
]));
266 for (x
= 0; x
< len
- 2; x
+= 2, ++struct_data
)
267 if (fields_desc
[x
] == 'p')
268 scm_gc_mark (SCM_PACK (*struct_data
));
269 if (fields_desc
[x
] == 'p')
271 if (SCM_LAYOUT_TAILP (fields_desc
[x
+ 1]))
272 for (x
= *struct_data
++; x
; --x
, ++struct_data
)
273 scm_gc_mark (SCM_PACK (*struct_data
));
275 scm_gc_mark (SCM_PACK (*struct_data
));
279 ptr
= SCM_PACK (vtable_data
[scm_vtable_index_vtable
]);
283 case scm_tcs_closures
:
284 if (SCM_IMP (SCM_ENV (ptr
)))
286 ptr
= SCM_CLOSCAR (ptr
);
289 scm_gc_mark (SCM_CLOSCAR (ptr
));
293 i
= SCM_VECTOR_LENGTH (ptr
);
298 if (SCM_NIMP (SCM_VELTS (ptr
)[i
]))
299 scm_gc_mark (SCM_VELTS (ptr
)[i
]);
301 ptr
= SCM_VELTS (ptr
)[0];
306 size_t i
= SCM_CCLO_LENGTH (ptr
);
308 for (j
= 1; j
!= i
; ++j
)
310 SCM obj
= SCM_CCLO_REF (ptr
, j
);
314 ptr
= SCM_CCLO_REF (ptr
, 0);
327 #ifdef HAVE_LONG_LONGS
335 SCM_SET_WVECT_GC_CHAIN (ptr
, scm_weak_vectors
);
336 scm_weak_vectors
= ptr
;
337 if (SCM_IS_WHVEC_ANY (ptr
))
344 len
= SCM_VECTOR_LENGTH (ptr
);
345 weak_keys
= SCM_IS_WHVEC (ptr
) || SCM_IS_WHVEC_B (ptr
);
346 weak_values
= SCM_IS_WHVEC_V (ptr
) || SCM_IS_WHVEC_B (ptr
);
348 for (x
= 0; x
< len
; ++x
)
351 alist
= SCM_VELTS (ptr
)[x
];
353 /* mark everything on the alist except the keys or
354 * values, according to weak_values and weak_keys. */
355 while ( SCM_CONSP (alist
)
356 && !SCM_GC_MARK_P (alist
)
357 && SCM_CONSP (SCM_CAR (alist
)))
362 kvpair
= SCM_CAR (alist
);
363 next_alist
= SCM_CDR (alist
);
366 * SCM_SET_GC_MARK (alist);
367 * SCM_SET_GC_MARK (kvpair);
369 * It may be that either the key or value is protected by
370 * an escaped reference to part of the spine of this alist.
371 * If we mark the spine here, and only mark one or neither of the
372 * key and value, they may never be properly marked.
373 * This leads to a horrible situation in which an alist containing
374 * freelist cells is exported.
376 * So only mark the spines of these arrays last of all marking.
377 * If somebody confuses us by constructing a weak vector
378 * with a circular alist then we are hosed, but at least we
379 * won't prematurely drop table entries.
382 scm_gc_mark (SCM_CAR (kvpair
));
384 scm_gc_mark (SCM_CDR (kvpair
));
387 if (SCM_NIMP (alist
))
394 ptr
= SCM_PROP_SLOTS (ptr
);
396 case scm_tc7_variable
:
397 ptr
= SCM_CELL_OBJECT_1 (ptr
);
402 i
= SCM_PTOBNUM (ptr
);
403 #if (SCM_DEBUG_CELL_ACCESSES == 1)
404 if (!(i
< scm_numptob
))
405 SCM_MISC_ERROR ("undefined port type", SCM_EOL
);
407 if (SCM_PTAB_ENTRY(ptr
))
408 scm_gc_mark (SCM_FILENAME (ptr
));
409 if (scm_ptobs
[i
].mark
)
411 ptr
= (scm_ptobs
[i
].mark
) (ptr
);
418 switch (SCM_TYP16 (ptr
))
419 { /* should be faster than going through scm_smobs */
420 case scm_tc_free_cell
:
421 /* We have detected a free cell. This can happen if non-object data
422 * on the C stack points into guile's heap and is scanned during
423 * conservative marking. */
427 case scm_tc16_complex
:
430 i
= SCM_SMOBNUM (ptr
);
431 #if (SCM_DEBUG_CELL_ACCESSES == 1)
432 if (!(i
< scm_numsmob
))
433 SCM_MISC_ERROR ("undefined smob type", SCM_EOL
);
435 if (scm_smobs
[i
].mark
)
437 ptr
= (scm_smobs
[i
].mark
) (ptr
);
445 SCM_MISC_ERROR ("unknown type", SCM_EOL
);
449 If we got here, then exhausted recursion options for PTR. we
450 return (careful not to mark PTR, it might be the argument that we
461 int valid_cell
= CELL_P (ptr
);
464 #if (SCM_DEBUG_CELL_ACCESSES == 1)
465 if (scm_debug_cell_accesses_p
)
467 /* We are in debug mode. Check the ptr exhaustively. */
469 valid_cell
= valid_cell
&& (scm_i_find_heap_segment_containing_object (ptr
) >= 0);
474 SCM_MISC_ERROR ("rogue pointer in heap", SCM_EOL
);
477 if (SCM_GC_MARK_P (ptr
))
480 SCM_SET_GC_MARK (ptr
);
481 goto scm_mark_dependencies_again
;
488 /* Mark a region conservatively */
490 scm_mark_locations (SCM_STACKITEM x
[], unsigned long n
)
494 for (m
= 0; m
< n
; ++m
)
496 SCM obj
= * (SCM
*) &x
[m
];
497 long int segment
= scm_i_find_heap_segment_containing_object (obj
);
504 /* The function scm_in_heap_p determines whether an SCM value can be regarded as a
505 * pointer to a cell on the heap.
508 scm_in_heap_p (SCM value
)
510 long int segment
= scm_i_find_heap_segment_containing_object (value
);
511 return (segment
>= 0);
515 #if SCM_ENABLE_DEPRECATED == 1
517 /* If an allocated cell is detected during garbage collection, this
518 * means that some code has just obtained the object but was preempted
519 * before the initialization of the object was completed. This meanst
520 * that some entries of the allocated cell may already contain SCM
521 * objects. Therefore, allocated cells are scanned conservatively.
524 scm_t_bits scm_tc16_allocated
;
527 allocated_mark (SCM cell
)
529 unsigned long int cell_segment
= scm_i_find_heap_segment_containing_object (cell
);
530 unsigned int span
= scm_i_heap_segment_table
[cell_segment
]->span
;
533 for (i
= 1; i
!= span
* 2; ++i
)
535 SCM obj
= SCM_CELL_OBJECT (cell
, i
);
536 long int obj_segment
= scm_i_find_heap_segment_containing_object (obj
);
537 if (obj_segment
>= 0)
544 scm_deprecated_newcell (void)
546 scm_c_issue_deprecation_warning
547 ("SCM_NEWCELL is deprecated. Use `scm_cell' instead.\n");
549 return scm_cell (scm_tc16_allocated
, 0);
553 scm_deprecated_newcell2 (void)
555 scm_c_issue_deprecation_warning
556 ("SCM_NEWCELL2 is deprecated. Use `scm_double_cell' instead.\n");
558 return scm_double_cell (scm_tc16_allocated
, 0, 0, 0);
561 #endif /* SCM_ENABLE_DEPRECATED == 1 */
565 scm_gc_init_mark(void)
567 #if SCM_ENABLE_DEPRECATED == 1
568 scm_tc16_allocated
= scm_make_smob_type ("allocated cell", 0);
569 scm_set_smob_mark (scm_tc16_allocated
, allocated_mark
);