{"Copyright 1988,1989 Hans-J. Boehm and Alan J. Demers ",
"Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. ",
"Copyright (c) 1996-1998 by Silicon Graphics. All rights reserved. ",
-"Copyright (c) 1999-2000 by Hewlett-Packard Company. All rights reserved. ",
+"Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved. ",
"THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY",
" EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.",
"See source code for details." };
extern GC_bool GC_collection_in_progress();
/* Collection is in progress, or was abandoned. */
+extern GC_bool GC_print_back_height;
+
int GC_never_stop_func GC_PROTO((void)) { return(0); }
+unsigned long GC_time_limit = TIME_LIMIT;
+
CLOCK_TYPE GC_start_time; /* Time at which we stopped world. */
/* used only in GC_timeout_stop_func. */
int GC_n_attempts = 0; /* Number of attempts at finishing */
- /* collection within TIME_LIMIT */
+ /* collection within GC_time_limit. */
-#ifdef SMALL_CONFIG
+#if defined(SMALL_CONFIG) || defined(NO_CLOCK)
# define GC_timeout_stop_func GC_never_stop_func
#else
int GC_timeout_stop_func GC_PROTO((void))
#ifndef NO_CLOCK
GET_TIME(current_time);
time_diff = MS_TIME_DIFF(current_time,GC_start_time);
- if (time_diff >= TIME_LIMIT) {
+ if (time_diff >= GC_time_limit) {
# ifdef CONDPRINT
if (GC_print_stats) {
GC_printf0("Abandoning stopped marking after ");
GC_gcollect_inner();
n_partial_gcs = 0;
return;
- } else if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) {
+ } else {
+# ifdef PARALLEL_MARK
+ GC_wait_for_reclaim();
+# endif
+ if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) {
# ifdef CONDPRINT
if (GC_print_stats) {
GC_printf2(
}
# endif
GC_promote_black_lists();
-# ifdef PARALLEL_MARK
- GC_wait_for_reclaim();
-# endif
(void)GC_reclaim_all((GC_stop_func)0, TRUE);
GC_clear_marks();
n_partial_gcs = 0;
GC_notify_full_gc();
GC_is_full_gc = TRUE;
- } else {
+ } else {
n_partial_gcs++;
- }
+ }
+ }
/* We try to mark with the world stopped. */
/* If we run out of time, this turns into */
/* incremental marking. */
-#ifndef NO_CLOCK
- GET_TIME(GC_start_time);
-#endif
- if (GC_stopped_mark(GC_timeout_stop_func)) {
+# ifndef NO_CLOCK
+ if (GC_time_limit != GC_TIME_UNLIMITED) { GET_TIME(GC_start_time); }
+# endif
+ if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED?
+ GC_never_stop_func : GC_timeout_stop_func)) {
# ifdef SAVE_CALL_CHAIN
GC_save_callers(GC_last_stack);
# endif
GC_bool GC_try_to_collect_inner(stop_func)
GC_stop_func stop_func;
{
+ if (GC_dont_gc) return FALSE;
if (GC_incremental && GC_collection_in_progress()) {
# ifdef CONDPRINT
if (GC_print_stats) {
# define GC_RATE 10
# define MAX_PRIOR_ATTEMPTS 1
/* Maximum number of prior attempts at world stop marking */
- /* A value of 1 means that we finish the seconf time, no matter */
+ /* A value of 1 means that we finish the second time, no matter */
/* how long it takes. Doesn't count the initial root scan */
/* for a full GC. */
{
register int i;
+ if (GC_dont_gc) return;
if (GC_incremental && GC_collection_in_progress()) {
for (i = GC_deficit; i < GC_RATE*n; i++) {
if (GC_mark_some((ptr_t)0)) {
# ifdef SAVE_CALL_CHAIN
GC_save_callers(GC_last_stack);
# endif
- if (GC_n_attempts < MAX_PRIOR_ATTEMPTS) {
+# ifdef PARALLEL_MARK
+ GC_wait_for_reclaim();
+# endif
+ if (GC_n_attempts < MAX_PRIOR_ATTEMPTS
+ && GC_time_limit != GC_TIME_UNLIMITED) {
GET_TIME(GC_start_time);
if (!GC_stopped_mark(GC_timeout_stop_func)) {
GC_n_attempts++;
{
register int i;
int dummy;
-# ifdef PRINTTIMES
+# if defined(PRINTTIMES) || defined(CONDPRINT)
CLOCK_TYPE start_time, current_time;
# endif
+# if defined(REGISTER_LIBRARIES_EARLY)
+ GC_cond_register_dynamic_libraries();
+# endif
STOP_WORLD();
# ifdef PRINTTIMES
GET_TIME(start_time);
# endif
+# if defined(CONDPRINT) && !defined(PRINTTIMES)
+ if (GC_print_stats) GET_TIME(start_time);
+# endif
# ifdef CONDPRINT
if (GC_print_stats) {
GC_printf1("--> Marking for collection %lu ",
(unsigned long) WORDS_TO_BYTES(GC_words_wasted));
}
# endif
+# ifdef MAKE_BACK_GRAPH
+ if (GC_print_back_height) {
+ GC_build_back_graph();
+ }
+# endif
/* Mark from all roots. */
/* Minimize junk left in my registers and on the stack */
GET_TIME(current_time);
GC_printf1("World-stopped marking took %lu msecs\n",
MS_TIME_DIFF(current_time,start_time));
+# else
+# ifdef CONDPRINT
+ if (GC_print_stats) {
+ GET_TIME(current_time);
+ GC_printf1("World-stopped marking took %lu msecs\n",
+ MS_TIME_DIFF(current_time,start_time));
+ }
+# endif
# endif
START_WORLD();
return(TRUE);
}
+/* Set all mark bits for the free list whose first entry is q */
+#ifdef __STDC__
+ void GC_set_fl_marks(ptr_t q)
+#else
+ void GC_set_fl_marks(q)
+ ptr_t q;
+#endif
+{
+ ptr_t p;
+ struct hblk * h, * last_h = 0;
+ hdr *hhdr;
+ int word_no;
+
+ for (p = q; p != 0; p = obj_link(p)){
+ h = HBLKPTR(p);
+ if (h != last_h) {
+ last_h = h;
+ hhdr = HDR(h);
+ }
+ word_no = (((word *)p) - ((word *)h));
+ set_mark_bit_from_hdr(hhdr, word_no);
+ }
+}
+
+/* Clear all mark bits for the free list whose first entry is q */
+/* Decrement GC_mem_found by number of words on free list. */
+#ifdef __STDC__
+ void GC_clear_fl_marks(ptr_t q)
+#else
+ void GC_clear_fl_marks(q)
+ ptr_t q;
+#endif
+{
+ ptr_t p;
+ struct hblk * h, * last_h = 0;
+ hdr *hhdr;
+ int word_no;
+
+ for (p = q; p != 0; p = obj_link(p)){
+ h = HBLKPTR(p);
+ if (h != last_h) {
+ last_h = h;
+ hhdr = HDR(h);
+ }
+ word_no = (((word *)p) - ((word *)h));
+ clear_mark_bit_from_hdr(hhdr, word_no);
+# ifdef GATHERSTATS
+ GC_mem_found -= hhdr -> hb_sz;
+# endif
+ }
+}
/* Finish up a collection. Assumes lock is held, signals are disabled, */
/* but the world is otherwise running. */
/* marked when we're done. */
{
register word size; /* current object size */
- register ptr_t p; /* pointer to current object */
- register struct hblk * h; /* pointer to block containing *p */
- register hdr * hhdr;
- register int word_no; /* "index" of *p in *q */
int kind;
+ ptr_t q;
for (kind = 0; kind < GC_n_kinds; kind++) {
for (size = 1; size <= MAXOBJSZ; size++) {
- for (p= GC_obj_kinds[kind].ok_freelist[size];
- p != 0; p=obj_link(p)){
- h = HBLKPTR(p);
- hhdr = HDR(h);
- word_no = (((word *)p) - ((word *)h));
- set_mark_bit_from_hdr(hhdr, word_no);
- }
+ q = GC_obj_kinds[kind].ok_freelist[size];
+ if (q != 0) GC_set_fl_marks(q);
}
}
}
GET_TIME(finalize_time);
# endif
+ if (GC_print_back_height) {
+# ifdef MAKE_BACK_GRAPH
+ GC_traverse_back_graph();
+# else
+# ifndef SMALL_CONFIG
+ GC_err_printf0("Back height not available: "
+ "Rebuild collector with -DMAKE_BACK_GRAPH\n");
+# endif
+# endif
+ }
+
/* Clear free list mark bits, in case they got accidentally marked */
- /* Note: HBLKPTR(p) == pointer to head of block containing *p */
- /* (or GC_find_leak is set and they were intentionally marked.) */
+ /* (or GC_find_leak is set and they were intentionally marked). */
/* Also subtract memory remaining from GC_mem_found count. */
/* Note that composite objects on free list are cleared. */
/* Thus accidentally marking a free list is not a problem; only */
/* objects on the list itself will be marked, and that's fixed here. */
{
register word size; /* current object size */
- register ptr_t p; /* pointer to current object */
- register struct hblk * h; /* pointer to block containing *p */
- register hdr * hhdr;
- register int word_no; /* "index" of *p in *q */
+ register ptr_t q; /* pointer to current object */
int kind;
for (kind = 0; kind < GC_n_kinds; kind++) {
for (size = 1; size <= MAXOBJSZ; size++) {
- for (p= GC_obj_kinds[kind].ok_freelist[size];
- p != 0; p=obj_link(p)){
- h = HBLKPTR(p);
- hhdr = HDR(h);
- word_no = (((word *)p) - ((word *)h));
- clear_mark_bit_from_hdr(hhdr, word_no);
-# ifdef GATHERSTATS
- GC_mem_found -= size;
-# endif
- }
+ q = GC_obj_kinds[kind].ok_freelist[size];
+ if (q != 0) GC_clear_fl_marks(q);
}
}
}