From: hboehm Date: Fri, 21 Dec 2007 01:40:38 +0000 (+0000) Subject: 2007-12-20 Hans Boehm X-Git-Tag: gc7_1alpha2~13 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=67f39b1b09fcc52361e19d0472b3bb459d384c88;p=gc 2007-12-20 Hans Boehm * alloc.c: Deal correctly with address wrapping for GC_greatest_plausible_heap_addr and GC_least_plausible_heap_addr. * finalize.c, include/gc.h (GC_register_disappearing_link, GC_register_finalizer_inner): Improve out-of-memory handling. * include/private/gc_pmark.h: Fix comment spelling. --- diff --git a/ChangeLog b/ChangeLog index 122ebbe5..5fe90fb6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,15 @@ +2007-12-20 Hans Boehm + + * alloc.c: Deal correctly with address wrapping for + GC_greatest_plausible_heap_addr and GC_least_plausible_heap_addr. + * finalize.c, include/gc.h (GC_register_disappearing_link, + GC_register_finalizer_inner): Improve out-of-memory handling. + * include/private/gc_pmark.h: Fix comment spelling. + 2007-12-18 Hans Boehm (really mainly Peter Wang) - * include/gc_inline.h, include/gc_tiny_fl.h: cleanups to make usable in other - contexts. + * include/gc_inline.h, include/gc_tiny_fl.h: cleanups to make usable + in other contexts. 2007-12-18 Hans Boehm (really Radek Polak) diff --git a/alloc.c b/alloc.c index 2a8b2cde..14265fda 100644 --- a/alloc.c +++ b/alloc.c @@ -782,6 +782,7 @@ word GC_n_heap_sects = 0; /* Number of sections currently in heap. */ void GC_add_to_heap(struct hblk *p, size_t bytes) { hdr * phdr; + word endp; if (GC_n_heap_sects >= MAX_HEAP_SECTS) { ABORT("Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS"); @@ -793,6 +794,20 @@ void GC_add_to_heap(struct hblk *p, size_t bytes) /* which is entirely appropriate. */ return; } + while ((word)p <= HBLKSIZE) { + /* Can't handle memory near address zero. */ + ++p; + bytes -= HBLKSIZE; + if (0 == bytes) return; + } + endp = (word)p + bytes; + if (endp <= (word)p) { + /* Address wrapped. */ + bytes -= HBLKSIZE; + if (0 == bytes) return; + endp -= HBLKSIZE; + } + GC_ASSERT(endp > (word)p && endp == (word)p + bytes); GC_heap_sects[GC_n_heap_sects].hs_start = (ptr_t)p; GC_heap_sects[GC_n_heap_sects].hs_bytes = bytes; GC_n_heap_sects++; @@ -809,7 +824,7 @@ void GC_add_to_heap(struct hblk *p, size_t bytes) /* here. */ } if ((ptr_t)p + bytes >= (ptr_t)GC_greatest_plausible_heap_addr) { - GC_greatest_plausible_heap_addr = (void *)((ptr_t)p + bytes); + GC_greatest_plausible_heap_addr = (void *)endp; } } @@ -839,12 +854,12 @@ void GC_print_heap_sects(void) void * GC_least_plausible_heap_addr = (void *)ONES; void * GC_greatest_plausible_heap_addr = 0; -static INLINE ptr_t GC_max(ptr_t x, ptr_t y) +static INLINE word GC_max(word x, word y) { return(x > y? x : y); } -static INLINE ptr_t GC_min(ptr_t x, ptr_t y) +static INLINE word GC_min(word x, word y) { return(x < y? x : y); } @@ -897,27 +912,27 @@ GC_bool GC_expand_hp_inner(word n) (unsigned long)bytes, (unsigned long)GC_bytes_allocd); } + /* Adjust heap limits generously for blacklisting to work better. */ + /* GC_add_to_heap performs minimal adjustment need for correctness. */ expansion_slop = min_bytes_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)) { /* Assume the heap is growing up */ - GC_greatest_plausible_heap_addr = - (void *)GC_max((ptr_t)GC_greatest_plausible_heap_addr, - (ptr_t)space + bytes + expansion_slop); + word new_limit = (word)space + bytes + expansion_slop; + if (new_limit > (word)space) { + GC_greatest_plausible_heap_addr = + (void *)GC_max((word)GC_greatest_plausible_heap_addr, + (word)new_limit); + } } else { /* Heap is growing down */ - GC_least_plausible_heap_addr = - (void *)GC_min((ptr_t)GC_least_plausible_heap_addr, - (ptr_t)space - expansion_slop); + word new_limit = (word)space - expansion_slop; + if (new_limit < (word)space) { + GC_least_plausible_heap_addr = + (void *)GC_min((word)GC_least_plausible_heap_addr, + (word)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); diff --git a/finalize.c b/finalize.c index 6ae36c2d..259cd84f 100644 --- a/finalize.c +++ b/finalize.c @@ -188,7 +188,7 @@ int GC_general_register_disappearing_link(void * * link, void * obj) GC_oom_fn(sizeof(struct disappearing_link)); if (0 == new_dl) { GC_finalization_failures++; - return(0); + return(2); } /* It's not likely we'll make it here, but ... */ # ifdef THREADS @@ -392,7 +392,6 @@ GC_API void GC_register_finalizer_inner(void * obj, } new_fo = (struct finalizable_object *) GC_INTERNAL_MALLOC(sizeof(struct finalizable_object),NORMAL); - GC_ASSERT(GC_size(new_fo) >= sizeof(struct finalizable_object)); if (EXPECT(0 == new_fo, FALSE)) { # ifdef THREADS UNLOCK(); @@ -408,6 +407,7 @@ GC_API void GC_register_finalizer_inner(void * obj, LOCK(); # endif } + GC_ASSERT(GC_size(new_fo) >= sizeof(struct finalizable_object)); new_fo -> fo_hidden_base = (word)HIDE_POINTER(base); new_fo -> fo_fn = fn; new_fo -> fo_client_data = (ptr_t)cd; diff --git a/include/gc.h b/include/gc.h index a23cd6e1..1fd1d1b2 100644 --- a/include/gc.h +++ b/include/gc.h @@ -732,8 +732,9 @@ GC_API int GC_register_disappearing_link(void * * link ); /* be allowed here, instead of just clearing a pointer. */ /* But this causes problems if that action alters, or */ /* examines connectivity. */ - /* Returns 1 if link was already registered, 0 */ - /* otherwise. */ + /* Returns 1 if link was already registered, 0 if */ + /* registration succeeded, 2 if it failed for lack of */ + /* memory, and GC_oom_fn did not handle the problem. */ /* Only exists for backward compatibility. See below: */ GC_API int GC_general_register_disappearing_link (void * * link, void * obj); diff --git a/include/private/gc_pmark.h b/include/private/gc_pmark.h index 36083970..1558dd39 100644 --- a/include/private/gc_pmark.h +++ b/include/private/gc_pmark.h @@ -244,10 +244,10 @@ exit_label: ; \ /* push the contents of the object on the mark stack. Current points */ /* to the bginning of the object. We rely on the fact that the */ /* preceding header calculation will succeed for a pointer past the */ -/* forst page of an object, only if it is in fact a valid pointer */ +/* first page of an object, only if it is in fact a valid pointer */ /* to the object. Thus we can omit the otherwise necessary tests */ -/* here. Note in particular tha the "displ" value is the displacement */ -/* from the beggining of the heap block, which may itself be in the */ +/* here. Note in particular that the "displ" value is the displacement */ +/* from the beginning of the heap block, which may itself be in the */ /* interior of a large object. */ #ifdef MARK_BIT_PER_GRANULE # define PUSH_CONTENTS_HDR(current, mark_stack_top, mark_stack_limit, \