92 |
|
|
93 |
# include "version.h" |
# include "version.h" |
94 |
|
|
95 |
|
#if defined(SAVE_CALL_CHAIN) && \ |
96 |
|
!(defined(REDIRECT_MALLOC) && defined(GC_HAVE_BUILTIN_BACKTRACE)) |
97 |
|
# define SAVE_CALL_CHAIN_IN_GC |
98 |
|
/* This is only safe if the call chain save mechanism won't end up */ |
99 |
|
/* calling GC_malloc. The GNU C library documentation suggests */ |
100 |
|
/* that backtrace doesn't use malloc, but at least the initial */ |
101 |
|
/* call in some versions does seem to invoke the dynamic linker, */ |
102 |
|
/* which uses malloc. */ |
103 |
|
#endif |
104 |
|
|
105 |
/* some more variables */ |
/* some more variables */ |
106 |
|
|
107 |
extern signed_word GC_mem_found; /* Number of reclaimed longwords */ |
extern signed_word GC_mem_found; /* Number of reclaimed longwords */ |
114 |
extern GC_bool GC_collection_in_progress(); |
extern GC_bool GC_collection_in_progress(); |
115 |
/* Collection is in progress, or was abandoned. */ |
/* Collection is in progress, or was abandoned. */ |
116 |
|
|
|
extern GC_bool GC_print_back_height; |
|
|
|
|
117 |
int GC_never_stop_func GC_PROTO((void)) { return(0); } |
int GC_never_stop_func GC_PROTO((void)) { return(0); } |
118 |
|
|
119 |
unsigned long GC_time_limit = TIME_LIMIT; |
unsigned long GC_time_limit = TIME_LIMIT; |
141 |
if (GC_print_stats) { |
if (GC_print_stats) { |
142 |
GC_printf0("Abandoning stopped marking after "); |
GC_printf0("Abandoning stopped marking after "); |
143 |
GC_printf1("%lu msecs", (unsigned long)time_diff); |
GC_printf1("%lu msecs", (unsigned long)time_diff); |
144 |
GC_printf1("(attempt %d)\n", (unsigned long) GC_n_attempts); |
GC_printf1("(attempt %ld)\n", (unsigned long) GC_n_attempts); |
145 |
} |
} |
146 |
# endif |
# endif |
147 |
return(1); |
return(1); |
206 |
/* had been reallocated this round. Finalization is user */ |
/* had been reallocated this round. Finalization is user */ |
207 |
/* visible progress. And if we don't count this, we have */ |
/* visible progress. And if we don't count this, we have */ |
208 |
/* stability problems for programs that finalize all objects. */ |
/* stability problems for programs that finalize all objects. */ |
209 |
result += GC_words_wasted; |
if ((GC_words_wasted >> 3) < result) |
210 |
|
result += GC_words_wasted; |
211 |
/* This doesn't reflect useful work. But if there is lots of */ |
/* This doesn't reflect useful work. But if there is lots of */ |
212 |
/* new fragmentation, the same is probably true of the heap, */ |
/* new fragmentation, the same is probably true of the heap, */ |
213 |
/* and the collection will be correspondingly cheaper. */ |
/* and the collection will be correspondingly cheaper. */ |
232 |
{ |
{ |
233 |
# define NWORDS 64 |
# define NWORDS 64 |
234 |
word frames[NWORDS]; |
word frames[NWORDS]; |
235 |
|
/* Some compilers will warn that frames was set but never used. */ |
236 |
|
/* That's the whole idea ... */ |
237 |
register int i; |
register int i; |
238 |
|
|
239 |
for (i = 0; i < NWORDS; i++) frames[i] = 0; |
for (i = 0; i < NWORDS; i++) frames[i] = 0; |
306 |
# endif |
# endif |
307 |
if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED? |
if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED? |
308 |
GC_never_stop_func : GC_timeout_stop_func)) { |
GC_never_stop_func : GC_timeout_stop_func)) { |
309 |
# ifdef SAVE_CALL_CHAIN |
# ifdef SAVE_CALL_CHAIN_IN_GC |
310 |
GC_save_callers(GC_last_stack); |
GC_save_callers(GC_last_stack); |
311 |
# endif |
# endif |
312 |
GC_finish_collection(); |
GC_finish_collection(); |
371 |
} |
} |
372 |
GC_invalidate_mark_state(); /* Flush mark stack. */ |
GC_invalidate_mark_state(); /* Flush mark stack. */ |
373 |
GC_clear_marks(); |
GC_clear_marks(); |
374 |
# ifdef SAVE_CALL_CHAIN |
# ifdef SAVE_CALL_CHAIN_IN_GC |
375 |
GC_save_callers(GC_last_stack); |
GC_save_callers(GC_last_stack); |
376 |
# endif |
# endif |
377 |
GC_is_full_gc = TRUE; |
GC_is_full_gc = TRUE; |
426 |
for (i = GC_deficit; i < GC_RATE*n; i++) { |
for (i = GC_deficit; i < GC_RATE*n; i++) { |
427 |
if (GC_mark_some((ptr_t)0)) { |
if (GC_mark_some((ptr_t)0)) { |
428 |
/* Need to finish a collection */ |
/* Need to finish a collection */ |
429 |
# ifdef SAVE_CALL_CHAIN |
# ifdef SAVE_CALL_CHAIN_IN_GC |
430 |
GC_save_callers(GC_last_stack); |
GC_save_callers(GC_last_stack); |
431 |
# endif |
# endif |
432 |
# ifdef PARALLEL_MARK |
# ifdef PARALLEL_MARK |
942 |
# endif |
# endif |
943 |
expansion_slop = WORDS_TO_BYTES(min_words_allocd()) + 4*MAXHINCR*HBLKSIZE; |
expansion_slop = WORDS_TO_BYTES(min_words_allocd()) + 4*MAXHINCR*HBLKSIZE; |
944 |
if (GC_last_heap_addr == 0 && !((word)space & SIGNB) |
if (GC_last_heap_addr == 0 && !((word)space & SIGNB) |
945 |
|| GC_last_heap_addr != 0 && GC_last_heap_addr < (ptr_t)space) { |
|| (GC_last_heap_addr != 0 && GC_last_heap_addr < (ptr_t)space)) { |
946 |
/* Assume the heap is growing up */ |
/* Assume the heap is growing up */ |
947 |
GC_greatest_plausible_heap_addr = |
GC_greatest_plausible_heap_addr = |
948 |
(GC_PTR)GC_max((ptr_t)GC_greatest_plausible_heap_addr, |
(GC_PTR)GC_max((ptr_t)GC_greatest_plausible_heap_addr, |
953 |
(GC_PTR)GC_min((ptr_t)GC_least_plausible_heap_addr, |
(GC_PTR)GC_min((ptr_t)GC_least_plausible_heap_addr, |
954 |
(ptr_t)space - expansion_slop); |
(ptr_t)space - expansion_slop); |
955 |
} |
} |
|
/* Force GC before we are likely to allocate past expansion_slop */ |
|
|
GC_collect_at_heapsize = |
|
|
GC_heapsize + expansion_slop - 2*MAXHINCR*HBLKSIZE; |
|
956 |
# if defined(LARGE_CONFIG) |
# if defined(LARGE_CONFIG) |
|
if (GC_collect_at_heapsize < GC_heapsize /* wrapped */) |
|
|
GC_collect_at_heapsize = (word)(-1); |
|
957 |
if (((ptr_t)GC_greatest_plausible_heap_addr <= (ptr_t)space + bytes |
if (((ptr_t)GC_greatest_plausible_heap_addr <= (ptr_t)space + bytes |
958 |
|| (ptr_t)GC_least_plausible_heap_addr >= (ptr_t)space) |
|| (ptr_t)GC_least_plausible_heap_addr >= (ptr_t)space) |
959 |
&& GC_heapsize > 0) { |
&& GC_heapsize > 0) { |
964 |
GC_prev_heap_addr = GC_last_heap_addr; |
GC_prev_heap_addr = GC_last_heap_addr; |
965 |
GC_last_heap_addr = (ptr_t)space; |
GC_last_heap_addr = (ptr_t)space; |
966 |
GC_add_to_heap(space, bytes); |
GC_add_to_heap(space, bytes); |
967 |
|
/* Force GC before we are likely to allocate past expansion_slop */ |
968 |
|
GC_collect_at_heapsize = |
969 |
|
GC_heapsize + expansion_slop - 2*MAXHINCR*HBLKSIZE; |
970 |
|
# if defined(LARGE_CONFIG) |
971 |
|
if (GC_collect_at_heapsize < GC_heapsize /* wrapped */) |
972 |
|
GC_collect_at_heapsize = (word)(-1); |
973 |
|
# endif |
974 |
return(TRUE); |
return(TRUE); |
975 |
} |
} |
976 |
|
|
1005 |
GC_bool ignore_off_page; |
GC_bool ignore_off_page; |
1006 |
{ |
{ |
1007 |
if (!GC_incremental && !GC_dont_gc && |
if (!GC_incremental && !GC_dont_gc && |
1008 |
(GC_dont_expand && GC_words_allocd > 0 || GC_should_collect())) { |
((GC_dont_expand && GC_words_allocd > 0) || GC_should_collect())) { |
1009 |
GC_gcollect_inner(); |
GC_gcollect_inner(); |
1010 |
} else { |
} else { |
1011 |
word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor) |
word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor) |
1014 |
if (blocks_to_get > MAXHINCR) { |
if (blocks_to_get > MAXHINCR) { |
1015 |
word slop; |
word slop; |
1016 |
|
|
1017 |
|
/* Get the minimum required to make it likely that we */ |
1018 |
|
/* can satisfy the current request in the presence of black- */ |
1019 |
|
/* listing. This will probably be more than MAXHINCR. */ |
1020 |
if (ignore_off_page) { |
if (ignore_off_page) { |
1021 |
slop = 4; |
slop = 4; |
1022 |
} else { |
} else { |