+2007-12-20 Hans Boehm <Hans.Boehm@hp.com>
+
+ * 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 <Hans.Boehm@hp.com> (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 <Hans.Boehm@hp.com> (really Radek Polak)
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");
/* 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++;
/* 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;
}
}
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);
}
(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);
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
}
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();
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;
/* 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);
/* 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, \