]> granicus.if.org Git - gc/commitdiff
2007-12-20 Hans Boehm <Hans.Boehm@hp.com>
authorhboehm <hboehm>
Fri, 21 Dec 2007 01:40:38 +0000 (01:40 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:41 +0000 (21:06 +0400)
* 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.

ChangeLog
alloc.c
finalize.c
include/gc.h
include/private/gc_pmark.h

index 122ebbe55ee3fb4811e311d824b0224f86e8788a..5fe90fb67c583397f962a34eb84fc157f5c15f2b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,15 @@
+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)
 
diff --git a/alloc.c b/alloc.c
index 2a8b2cde46efcafc59942bfd22fe6f64b208f551..14265fdae4807beb8d2896b055bf965428a3f035 100644 (file)
--- 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);
index 6ae36c2ddc6285c7a10b70515d2a338aecd373e9..259cd84fff10e7c0e775b0bc71c53a9c1ace98b9 100644 (file)
@@ -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;
index a23cd6e1403f1af3adc2dda5636b15663b6b9ab5..1fd1d1b2dbcc13b38f0def136485c37ab0f273f4 100644 (file)
@@ -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);
index 36083970acdcba98cd3a03d2943d8bd68085f4ce..1558dd39a21fabdc3fe966d5552ea49927c1e03e 100644 (file)
@@ -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, \