# include "version.h"
+#if defined(SAVE_CALL_CHAIN) && \
+ !(defined(REDIRECT_MALLOC) && defined(GC_HAVE_BUILTIN_BACKTRACE))
+# define SAVE_CALL_CHAIN_IN_GC
+ /* This is only safe if the call chain save mechanism won't end up */
+ /* calling GC_malloc. The GNU C library documentation suggests */
+ /* that backtrace doesn't use malloc, but at least the initial */
+ /* call in some versions does seem to invoke the dynamic linker, */
+ /* which uses malloc. */
+#endif
+
/* some more variables */
extern signed_word GC_mem_found; /* Number of reclaimed longwords */
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;
unsigned long time_diff;
if ((count++ & 3) != 0) return(0);
-#ifndef NO_CLOCK
GET_TIME(current_time);
time_diff = MS_TIME_DIFF(current_time,GC_start_time);
if (time_diff >= GC_time_limit) {
if (GC_print_stats) {
GC_printf0("Abandoning stopped marking after ");
GC_printf1("%lu msecs", (unsigned long)time_diff);
- GC_printf1("(attempt %d)\n", (unsigned long) GC_n_attempts);
+ GC_printf1("(attempt %ld)\n", (unsigned long) GC_n_attempts);
}
# endif
return(1);
}
-#endif
return(0);
}
#endif /* !SMALL_CONFIG */
/* had been reallocated this round. Finalization is user */
/* visible progress. And if we don't count this, we have */
/* stability problems for programs that finalize all objects. */
- result += GC_words_wasted;
+ if ((GC_words_wasted >> 3) < result)
+ result += GC_words_wasted;
/* This doesn't reflect useful work. But if there is lots of */
/* new fragmentation, the same is probably true of the heap, */
/* and the collection will be correspondingly cheaper. */
{
# define NWORDS 64
word frames[NWORDS];
+ /* Some compilers will warn that frames was set but never used. */
+ /* That's the whole idea ... */
register int i;
for (i = 0; i < NWORDS; i++) frames[i] = 0;
}
+/* Heap size at which we need a collection to avoid expanding past */
+/* limits used by blacklisting. */
+static word GC_collect_at_heapsize = (word)(-1);
+
/* Have we allocated enough to amortize a collection? */
GC_bool GC_should_collect()
{
- return(GC_adj_words_allocd() >= min_words_allocd());
+ return(GC_adj_words_allocd() >= min_words_allocd()
+ || GC_heapsize >= GC_collect_at_heapsize);
}
# 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_IN_GC
GC_save_callers(GC_last_stack);
# endif
GC_finish_collection();
}
GC_invalidate_mark_state(); /* Flush mark stack. */
GC_clear_marks();
-# ifdef SAVE_CALL_CHAIN
+# ifdef SAVE_CALL_CHAIN_IN_GC
GC_save_callers(GC_last_stack);
# endif
GC_is_full_gc = TRUE;
for (i = GC_deficit; i < GC_RATE*n; i++) {
if (GC_mark_some((ptr_t)0)) {
/* Need to finish a collection */
-# ifdef SAVE_CALL_CHAIN
+# ifdef SAVE_CALL_CHAIN_IN_GC
GC_save_callers(GC_last_stack);
# endif
# ifdef PARALLEL_MARK
# endif
}
# endif
- expansion_slop = 8 * WORDS_TO_BYTES(min_words_allocd());
- if (5 * HBLKSIZE * MAXHINCR > expansion_slop) {
- expansion_slop = 5 * HBLKSIZE * MAXHINCR;
- }
+ expansion_slop = WORDS_TO_BYTES(min_words_allocd()) + 4*MAXHINCR*HBLKSIZE;
if (GC_last_heap_addr == 0 && !((word)space & SIGNB)
- || GC_last_heap_addr != 0 && GC_last_heap_addr < (ptr_t)space) {
+ || (GC_last_heap_addr != 0 && GC_last_heap_addr < (ptr_t)space)) {
/* Assume the heap is growing up */
GC_greatest_plausible_heap_addr =
- GC_max(GC_greatest_plausible_heap_addr,
- (ptr_t)space + bytes + expansion_slop);
+ (GC_PTR)GC_max((ptr_t)GC_greatest_plausible_heap_addr,
+ (ptr_t)space + bytes + expansion_slop);
} else {
/* Heap is growing down */
GC_least_plausible_heap_addr =
- GC_min(GC_least_plausible_heap_addr,
- (ptr_t)space - expansion_slop);
+ (GC_PTR)GC_min((ptr_t)GC_least_plausible_heap_addr,
+ (ptr_t)space - expansion_slop);
}
+# if defined(LARGE_CONFIG)
+ if (((ptr_t)GC_greatest_plausible_heap_addr <= (ptr_t)space + bytes
+ || (ptr_t)GC_least_plausible_heap_addr >= (ptr_t)space)
+ && GC_heapsize > 0) {
+ /* GC_add_to_heap will fix this, but ... */
+ WARN("Too close to address space limit: blacklisting ineffective\n", 0);
+ }
+# endif
GC_prev_heap_addr = GC_last_heap_addr;
GC_last_heap_addr = (ptr_t)space;
GC_add_to_heap(space, bytes);
+ /* Force GC before we are likely to allocate past expansion_slop */
+ GC_collect_at_heapsize =
+ GC_heapsize + expansion_slop - 2*MAXHINCR*HBLKSIZE;
+# if defined(LARGE_CONFIG)
+ if (GC_collect_at_heapsize < GC_heapsize /* wrapped */)
+ GC_collect_at_heapsize = (word)(-1);
+# endif
return(TRUE);
}
GC_bool ignore_off_page;
{
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_gcollect_inner();
} else {
word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor)
if (blocks_to_get > MAXHINCR) {
word slop;
+ /* Get the minimum required to make it likely that we */
+ /* can satisfy the current request in the presence of black- */
+ /* listing. This will probably be more than MAXHINCR. */
if (ignore_off_page) {
slop = 4;
} else {