version 1.4, 2001/04/20 07:39:18 |
version 1.11, 2015/08/06 10:01:52 |
|
|
# include <sys/types.h> |
# include <sys/types.h> |
# endif |
# endif |
|
|
void GC_timerstart(),GC_timerstop(); |
|
|
|
/* |
/* |
* Separate free lists are maintained for different sized objects |
* Separate free lists are maintained for different sized objects |
* up to MAXOBJSZ. |
* up to MAXOBJSZ. |
Line 74 int GC_full_freq = 19; /* Every 20th collection is |
|
Line 72 int GC_full_freq = 19; /* Every 20th collection is |
|
GC_bool GC_need_full_gc = FALSE; |
GC_bool GC_need_full_gc = FALSE; |
/* Need full GC do to heap growth. */ |
/* Need full GC do to heap growth. */ |
|
|
|
#ifdef THREADS |
|
GC_bool GC_world_stopped = FALSE; |
|
# define IF_THREADS(x) x |
|
#else |
|
# define IF_THREADS(x) |
|
#endif |
|
|
word GC_used_heap_size_after_full = 0; |
word GC_used_heap_size_after_full = 0; |
|
|
char * GC_copyright[] = |
char * GC_copyright[] = |
{"Copyright 1988,1989 Hans-J. Boehm and Alan J. Demers ", |
{"Copyright 1988,1989 Hans-J. Boehm and Alan J. Demers ", |
"Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. ", |
"Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. ", |
"Copyright (c) 1996-1998 by Silicon Graphics. 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", |
"THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY", |
" EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.", |
" EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.", |
"See source code for details." }; |
"See source code for details." }; |
Line 94 extern signed_word GC_mem_found; /* Number of reclaim |
|
Line 99 extern signed_word GC_mem_found; /* Number of reclaim |
|
|
|
GC_bool GC_dont_expand = 0; |
GC_bool GC_dont_expand = 0; |
|
|
word GC_free_space_numerator = 1; |
|
word GC_free_space_divisor = 3; |
word GC_free_space_divisor = 3; |
|
word GC_free_space_numerator = 1; |
|
|
extern GC_bool GC_collection_in_progress(); |
extern GC_bool GC_collection_in_progress(); |
/* Collection is in progress, or was abandoned. */ |
/* Collection is in progress, or was abandoned. */ |
|
|
|
extern GC_bool GC_print_back_height; |
|
|
int GC_never_stop_func GC_PROTO((void)) { return(0); } |
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. */ |
CLOCK_TYPE GC_start_time; /* Time at which we stopped world. */ |
/* used only in GC_timeout_stop_func. */ |
/* used only in GC_timeout_stop_func. */ |
|
|
int GC_n_attempts = 0; /* Number of attempts at finishing */ |
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 |
# define GC_timeout_stop_func GC_never_stop_func |
#else |
#else |
int GC_timeout_stop_func GC_PROTO((void)) |
int GC_timeout_stop_func GC_PROTO((void)) |
Line 120 int GC_n_attempts = 0; /* Number of attempts at finis |
|
Line 129 int GC_n_attempts = 0; /* Number of attempts at finis |
|
if ((count++ & 3) != 0) return(0); |
if ((count++ & 3) != 0) return(0); |
GET_TIME(current_time); |
GET_TIME(current_time); |
time_diff = MS_TIME_DIFF(current_time,GC_start_time); |
time_diff = MS_TIME_DIFF(current_time,GC_start_time); |
if (time_diff >= TIME_LIMIT) { |
if (time_diff >= GC_time_limit) { |
# ifdef CONDPRINT |
# ifdef CONDPRINT |
if (GC_print_stats) { |
if (GC_print_stats) { |
GC_printf0("Abandoning stopped marking after "); |
GC_printf0("Abandoning stopped marking after "); |
Line 157 static word min_words_allocd() |
|
Line 166 static word min_words_allocd() |
|
+ (GC_large_free_bytes >> 2) |
+ (GC_large_free_bytes >> 2) |
/* use a bit more of large empty heap */ |
/* use a bit more of large empty heap */ |
+ total_root_size); |
+ total_root_size); |
if (GC_incremental) { |
if (TRUE_INCREMENTAL) { |
return (scan_size*GC_free_space_numerator) / (2 * GC_free_space_divisor); |
return scan_size * GC_free_space_numerator / (2 * GC_free_space_divisor); |
} else { |
} else { |
return (scan_size*GC_free_space_numerator) / GC_free_space_divisor; |
return scan_size * GC_free_space_numerator / GC_free_space_divisor; |
} |
} |
} |
} |
|
|
Line 179 word GC_adj_words_allocd() |
|
Line 188 word GC_adj_words_allocd() |
|
/* managed object should not alter result, assuming the client */ |
/* managed object should not alter result, assuming the client */ |
/* is playing by the rules. */ |
/* is playing by the rules. */ |
result = (signed_word)GC_words_allocd |
result = (signed_word)GC_words_allocd |
- (signed_word)GC_mem_freed - expl_managed; |
- (signed_word)GC_mem_freed |
|
+ (signed_word)GC_finalizer_mem_freed - expl_managed; |
if (result > (signed_word)GC_words_allocd) { |
if (result > (signed_word)GC_words_allocd) { |
result = GC_words_allocd; |
result = GC_words_allocd; |
/* probably client bug or unfortunate scheduling */ |
/* probably client bug or unfortunate scheduling */ |
Line 247 void GC_maybe_gc() |
|
Line 257 void GC_maybe_gc() |
|
|
|
if (GC_should_collect()) { |
if (GC_should_collect()) { |
if (!GC_incremental) { |
if (!GC_incremental) { |
GC_notify_full_gc(); |
|
GC_gcollect_inner(); |
GC_gcollect_inner(); |
n_partial_gcs = 0; |
n_partial_gcs = 0; |
return; |
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 |
# ifdef CONDPRINT |
if (GC_print_stats) { |
if (GC_print_stats) { |
GC_printf2( |
GC_printf2( |
Line 261 void GC_maybe_gc() |
|
Line 274 void GC_maybe_gc() |
|
} |
} |
# endif |
# endif |
GC_promote_black_lists(); |
GC_promote_black_lists(); |
# ifdef PARALLEL_MARK |
|
GC_wait_for_reclaim(); |
|
# endif |
|
(void)GC_reclaim_all((GC_stop_func)0, TRUE); |
(void)GC_reclaim_all((GC_stop_func)0, TRUE); |
GC_clear_marks(); |
GC_clear_marks(); |
n_partial_gcs = 0; |
n_partial_gcs = 0; |
GC_notify_full_gc(); |
GC_notify_full_gc(); |
GC_is_full_gc = TRUE; |
GC_is_full_gc = TRUE; |
} else { |
} else { |
n_partial_gcs++; |
n_partial_gcs++; |
} |
} |
|
} |
/* We try to mark with the world stopped. */ |
/* We try to mark with the world stopped. */ |
/* If we run out of time, this turns into */ |
/* If we run out of time, this turns into */ |
/* incremental marking. */ |
/* incremental marking. */ |
GET_TIME(GC_start_time); |
# ifndef NO_CLOCK |
if (GC_stopped_mark(GC_timeout_stop_func)) { |
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 |
# ifdef SAVE_CALL_CHAIN |
GC_save_callers(GC_last_stack); |
GC_save_callers(GC_last_stack); |
# endif |
# endif |
Line 294 void GC_maybe_gc() |
|
Line 308 void GC_maybe_gc() |
|
/* |
/* |
* Stop the world garbage collection. Assumes lock held, signals disabled. |
* Stop the world garbage collection. Assumes lock held, signals disabled. |
* If stop_func is not GC_never_stop_func, then abort if stop_func returns TRUE. |
* If stop_func is not GC_never_stop_func, then abort if stop_func returns TRUE. |
|
* Return TRUE if we successfully completed the collection. |
*/ |
*/ |
GC_bool GC_try_to_collect_inner(stop_func) |
GC_bool GC_try_to_collect_inner(stop_func) |
GC_stop_func stop_func; |
GC_stop_func stop_func; |
{ |
{ |
|
# ifdef CONDPRINT |
|
CLOCK_TYPE start_time, current_time; |
|
# endif |
|
if (GC_dont_gc) return FALSE; |
if (GC_incremental && GC_collection_in_progress()) { |
if (GC_incremental && GC_collection_in_progress()) { |
# ifdef CONDPRINT |
# ifdef CONDPRINT |
if (GC_print_stats) { |
if (GC_print_stats) { |
Line 311 GC_stop_func stop_func; |
|
Line 330 GC_stop_func stop_func; |
|
GC_collect_a_little_inner(1); |
GC_collect_a_little_inner(1); |
} |
} |
} |
} |
|
if (stop_func == GC_never_stop_func) GC_notify_full_gc(); |
# ifdef CONDPRINT |
# ifdef CONDPRINT |
if (GC_print_stats) { |
if (GC_print_stats) { |
|
if (GC_print_stats) GET_TIME(start_time); |
GC_printf2( |
GC_printf2( |
"Initiating full world-stop collection %lu after %ld allocd bytes\n", |
"Initiating full world-stop collection %lu after %ld allocd bytes\n", |
(unsigned long) GC_gc_no+1, |
(unsigned long) GC_gc_no+1, |
Line 351 GC_stop_func stop_func; |
|
Line 372 GC_stop_func stop_func; |
|
return(FALSE); |
return(FALSE); |
} |
} |
GC_finish_collection(); |
GC_finish_collection(); |
|
# if defined(CONDPRINT) |
|
if (GC_print_stats) { |
|
GET_TIME(current_time); |
|
GC_printf1("Complete collection took %lu msecs\n", |
|
MS_TIME_DIFF(current_time,start_time)); |
|
} |
|
# endif |
return(TRUE); |
return(TRUE); |
} |
} |
|
|
Line 366 GC_stop_func stop_func; |
|
Line 394 GC_stop_func stop_func; |
|
# define GC_RATE 10 |
# define GC_RATE 10 |
# define MAX_PRIOR_ATTEMPTS 1 |
# define MAX_PRIOR_ATTEMPTS 1 |
/* Maximum number of prior attempts at world stop marking */ |
/* 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 */ |
/* how long it takes. Doesn't count the initial root scan */ |
/* for a full GC. */ |
/* for a full GC. */ |
|
|
|
|
{ |
{ |
register int i; |
register int i; |
|
|
|
if (GC_dont_gc) return; |
if (GC_incremental && GC_collection_in_progress()) { |
if (GC_incremental && GC_collection_in_progress()) { |
for (i = GC_deficit; i < GC_RATE*n; i++) { |
for (i = GC_deficit; i < GC_RATE*n; i++) { |
if (GC_mark_some((ptr_t)0)) { |
if (GC_mark_some((ptr_t)0)) { |
|
|
# ifdef SAVE_CALL_CHAIN |
# ifdef SAVE_CALL_CHAIN |
GC_save_callers(GC_last_stack); |
GC_save_callers(GC_last_stack); |
# endif |
# 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); |
GET_TIME(GC_start_time); |
if (!GC_stopped_mark(GC_timeout_stop_func)) { |
if (!GC_stopped_mark(GC_timeout_stop_func)) { |
GC_n_attempts++; |
GC_n_attempts++; |
Line 416 int GC_collect_a_little GC_PROTO(()) |
|
Line 449 int GC_collect_a_little GC_PROTO(()) |
|
result = (int)GC_collection_in_progress(); |
result = (int)GC_collection_in_progress(); |
UNLOCK(); |
UNLOCK(); |
ENABLE_SIGNALS(); |
ENABLE_SIGNALS(); |
|
if (!result && GC_debugging_started) GC_print_all_smashed(); |
return(result); |
return(result); |
} |
} |
|
|
Line 430 GC_stop_func stop_func; |
|
Line 464 GC_stop_func stop_func; |
|
{ |
{ |
register int i; |
register int i; |
int dummy; |
int dummy; |
# ifdef PRINTTIMES |
# if defined(PRINTTIMES) || defined(CONDPRINT) |
CLOCK_TYPE start_time, current_time; |
CLOCK_TYPE start_time, current_time; |
# endif |
# endif |
|
|
STOP_WORLD(); |
|
GC_timerstart(); |
|
# ifdef PRINTTIMES |
# ifdef PRINTTIMES |
GET_TIME(start_time); |
GET_TIME(start_time); |
# endif |
# endif |
|
# if defined(CONDPRINT) && !defined(PRINTTIMES) |
|
if (GC_print_stats) GET_TIME(start_time); |
|
# endif |
|
# if defined(REGISTER_LIBRARIES_EARLY) |
|
GC_cond_register_dynamic_libraries(); |
|
# endif |
|
GC_timerstart(); |
|
STOP_WORLD(); |
|
IF_THREADS(GC_world_stopped = TRUE); |
# ifdef CONDPRINT |
# ifdef CONDPRINT |
if (GC_print_stats) { |
if (GC_print_stats) { |
GC_printf1("--> Marking for collection %lu ", |
GC_printf1("--> Marking for collection %lu ", |
Line 448 GC_stop_func stop_func; |
|
Line 489 GC_stop_func stop_func; |
|
(unsigned long) WORDS_TO_BYTES(GC_words_wasted)); |
(unsigned long) WORDS_TO_BYTES(GC_words_wasted)); |
} |
} |
# endif |
# endif |
|
# ifdef MAKE_BACK_GRAPH |
|
if (GC_print_back_height) { |
|
GC_build_back_graph(); |
|
} |
|
# endif |
|
|
/* Mark from all roots. */ |
/* Mark from all roots. */ |
/* Minimize junk left in my registers and on the stack */ |
/* Minimize junk left in my registers and on the stack */ |
Line 463 GC_stop_func stop_func; |
|
Line 509 GC_stop_func stop_func; |
|
(unsigned long)i); |
(unsigned long)i); |
} |
} |
# endif |
# endif |
GC_timerstop(); |
|
GC_deficit = i; /* Give the mutator a chance. */ |
GC_deficit = i; /* Give the mutator a chance. */ |
|
IF_THREADS(GC_world_stopped = FALSE); |
START_WORLD(); |
START_WORLD(); |
|
GC_timerstop(); |
return(FALSE); |
return(FALSE); |
} |
} |
if (GC_mark_some((ptr_t)(&dummy))) break; |
if (GC_mark_some((ptr_t)(&dummy))) break; |
Line 498 GC_stop_func stop_func; |
|
Line 545 GC_stop_func stop_func; |
|
(*GC_check_heap)(); |
(*GC_check_heap)(); |
} |
} |
|
|
|
IF_THREADS(GC_world_stopped = FALSE); |
|
START_WORLD(); |
|
GC_timerstop(); |
# ifdef PRINTTIMES |
# ifdef PRINTTIMES |
GET_TIME(current_time); |
GET_TIME(current_time); |
GC_printf1("World-stopped marking took %lu msecs\n", |
GC_printf1("World-stopped marking took %lu msecs\n", |
MS_TIME_DIFF(current_time,start_time)); |
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 |
# endif |
GC_timerstop(); |
|
START_WORLD(); |
|
return(TRUE); |
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, */ |
/* Finish up a collection. Assumes lock is held, signals are disabled, */ |
/* but the world is otherwise running. */ |
/* but the world is otherwise running. */ |
void GC_finish_collection() |
void GC_finish_collection() |
Line 531 void GC_finish_collection() |
|
Line 638 void GC_finish_collection() |
|
GC_print_address_map(); |
GC_print_address_map(); |
} |
} |
# endif |
# endif |
|
COND_DUMP; |
if (GC_find_leak) { |
if (GC_find_leak) { |
/* Mark all objects on the free list. All objects should be */ |
/* Mark all objects on the free list. All objects should be */ |
/* marked when we're done. */ |
/* marked when we're done. */ |
{ |
{ |
register word size; /* current object size */ |
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; |
int kind; |
|
ptr_t q; |
|
|
for (kind = 0; kind < GC_n_kinds; kind++) { |
for (kind = 0; kind < GC_n_kinds; kind++) { |
for (size = 1; size <= MAXOBJSZ; size++) { |
for (size = 1; size <= MAXOBJSZ; size++) { |
for (p= GC_obj_kinds[kind].ok_freelist[size]; |
q = GC_obj_kinds[kind].ok_freelist[size]; |
p != 0; p=obj_link(p)){ |
if (q != 0) GC_set_fl_marks(q); |
h = HBLKPTR(p); |
|
hhdr = HDR(h); |
|
word_no = (((word *)p) - ((word *)h)); |
|
set_mark_bit_from_hdr(hhdr, word_no); |
|
} |
|
} |
} |
} |
} |
} |
} |
Line 567 void GC_finish_collection() |
|
Line 667 void GC_finish_collection() |
|
GET_TIME(finalize_time); |
GET_TIME(finalize_time); |
# endif |
# 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 */ |
/* 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. */ |
/* Also subtract memory remaining from GC_mem_found count. */ |
/* Note that composite objects on free list are cleared. */ |
/* Note that composite objects on free list are cleared. */ |
/* Thus accidentally marking a free list is not a problem; only */ |
/* Thus accidentally marking a free list is not a problem; only */ |
/* objects on the list itself will be marked, and that's fixed here. */ |
/* objects on the list itself will be marked, and that's fixed here. */ |
{ |
{ |
register word size; /* current object size */ |
register word size; /* current object size */ |
register ptr_t p; /* pointer to current object */ |
register ptr_t q; /* 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; |
int kind; |
|
|
for (kind = 0; kind < GC_n_kinds; kind++) { |
for (kind = 0; kind < GC_n_kinds; kind++) { |
for (size = 1; size <= MAXOBJSZ; size++) { |
for (size = 1; size <= MAXOBJSZ; size++) { |
for (p= GC_obj_kinds[kind].ok_freelist[size]; |
q = GC_obj_kinds[kind].ok_freelist[size]; |
p != 0; p=obj_link(p)){ |
if (q != 0) GC_clear_fl_marks(q); |
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 |
|
} |
|
} |
} |
} |
} |
} |
} |
Line 636 void GC_finish_collection() |
|
Line 735 void GC_finish_collection() |
|
GC_words_allocd = 0; |
GC_words_allocd = 0; |
GC_words_wasted = 0; |
GC_words_wasted = 0; |
GC_mem_freed = 0; |
GC_mem_freed = 0; |
|
GC_finalizer_mem_freed = 0; |
|
|
# ifdef USE_MUNMAP |
# ifdef USE_MUNMAP |
GC_unmap_old(); |
GC_unmap_old(); |
Line 660 void GC_finish_collection() |
|
Line 760 void GC_finish_collection() |
|
int result; |
int result; |
DCL_LOCK_STATE; |
DCL_LOCK_STATE; |
|
|
|
if (GC_debugging_started) GC_print_all_smashed(); |
GC_INVOKE_FINALIZERS(); |
GC_INVOKE_FINALIZERS(); |
DISABLE_SIGNALS(); |
DISABLE_SIGNALS(); |
LOCK(); |
LOCK(); |
Line 671 void GC_finish_collection() |
|
Line 772 void GC_finish_collection() |
|
EXIT_GC(); |
EXIT_GC(); |
UNLOCK(); |
UNLOCK(); |
ENABLE_SIGNALS(); |
ENABLE_SIGNALS(); |
if(result) GC_INVOKE_FINALIZERS(); |
if(result) { |
|
if (GC_debugging_started) GC_print_all_smashed(); |
|
GC_INVOKE_FINALIZERS(); |
|
} |
return(result); |
return(result); |
} |
} |
|
|
void GC_gcollect GC_PROTO(()) |
void GC_gcollect GC_PROTO(()) |
{ |
{ |
GC_notify_full_gc(); |
|
(void)GC_try_to_collect(GC_never_stop_func); |
(void)GC_try_to_collect(GC_never_stop_func); |
|
if (GC_have_errors) GC_print_all_errors(); |
} |
} |
|
|
word GC_n_heap_sects = 0; /* Number of sections currently in heap. */ |
word GC_n_heap_sects = 0; /* Number of sections currently in heap. */ |
|
|
GC_prev_heap_addr = GC_last_heap_addr; |
GC_prev_heap_addr = GC_last_heap_addr; |
GC_last_heap_addr = (ptr_t)space; |
GC_last_heap_addr = (ptr_t)space; |
GC_add_to_heap(space, bytes); |
GC_add_to_heap(space, bytes); |
#if defined(VISUAL_LIB) |
#if defined(VISUAL) || defined(__MINGW32__) || defined(__MINGW64__) |
SendHeapSize(); |
SendHeapSize(); |
#endif |
#endif |
return(TRUE); |
return(TRUE); |
Line 883 GC_bool ignore_off_page; |
|
Line 987 GC_bool ignore_off_page; |
|
{ |
{ |
if (!GC_incremental && !GC_dont_gc && |
if (!GC_incremental && !GC_dont_gc && |
(GC_dont_expand && GC_words_allocd > 0 || GC_should_collect())) { |
(GC_dont_expand && GC_words_allocd > 0 || GC_should_collect())) { |
GC_notify_full_gc(); |
|
GC_gcollect_inner(); |
GC_gcollect_inner(); |
} else { |
} else { |
word blocks_to_get = (GC_heapsize*GC_free_space_numerator)/(HBLKSIZE*GC_free_space_divisor) |
word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor) |
+ needed_blocks; |
+ needed_blocks; |
|
|
if (blocks_to_get > MAXHINCR) { |
if (blocks_to_get > MAXHINCR) { |
Line 908 GC_bool ignore_off_page; |
|
Line 1011 GC_bool ignore_off_page; |
|
&& !GC_expand_hp_inner(needed_blocks)) { |
&& !GC_expand_hp_inner(needed_blocks)) { |
if (GC_fail_count++ < GC_max_retries) { |
if (GC_fail_count++ < GC_max_retries) { |
WARN("Out of Memory! Trying to continue ...\n", 0); |
WARN("Out of Memory! Trying to continue ...\n", 0); |
GC_notify_full_gc(); |
|
GC_gcollect_inner(); |
GC_gcollect_inner(); |
} else { |
} else { |
# if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC) |
# if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC) |
Line 938 ptr_t GC_allocobj(sz, kind) |
|
Line 1040 ptr_t GC_allocobj(sz, kind) |
|
word sz; |
word sz; |
int kind; |
int kind; |
{ |
{ |
register ptr_t * flh = &(GC_obj_kinds[kind].ok_freelist[sz]); |
ptr_t * flh = &(GC_obj_kinds[kind].ok_freelist[sz]); |
|
GC_bool tried_minor = FALSE; |
|
|
if (sz == 0) return(0); |
if (sz == 0) return(0); |
|
|
#if defined(VISUAL) |
#if defined(VISUAL) || defined(__MINGW32__) || defined(__MINGW64__) |
{ |
{ |
#include <signal.h> |
#include <signal.h> |
extern int recv_intr; |
extern int recv_intr; |
|
|
while (*flh == 0) { |
while (*flh == 0) { |
ENTER_GC(); |
ENTER_GC(); |
/* Do our share of marking work */ |
/* Do our share of marking work */ |
if(GC_incremental && !GC_dont_gc) GC_collect_a_little_inner(1); |
if(TRUE_INCREMENTAL) GC_collect_a_little_inner(1); |
/* Sweep blocks for objects of this size */ |
/* Sweep blocks for objects of this size */ |
GC_continue_reclaim(sz, kind); |
GC_continue_reclaim(sz, kind); |
EXIT_GC(); |
EXIT_GC(); |
if (*flh == 0) { |
if (*flh == 0) { |
GC_new_hblk(sz, kind); |
GC_new_hblk(sz, kind); |
} |
} |
if (*flh == 0) { |
if (*flh == 0) { |
ENTER_GC(); |
ENTER_GC(); |
if (!GC_collect_or_expand((word)1,FALSE)) { |
if (GC_incremental && GC_time_limit == GC_TIME_UNLIMITED |
|
&& ! tried_minor ) { |
|
GC_collect_a_little_inner(1); |
|
tried_minor = TRUE; |
|
} else { |
|
if (!GC_collect_or_expand((word)1,FALSE)) { |
EXIT_GC(); |
EXIT_GC(); |
return(0); |
return(0); |
|
} |
} |
} |
EXIT_GC(); |
EXIT_GC(); |
} |
} |
} |
} |
|
/* Successful allocation; reset failure count. */ |
|
GC_fail_count = 0; |
|
|
return(*flh); |
return(*flh); |
} |
} |