Author: Armin Rigo <ar...@tunes.org>
Branch: array-overallocation-in-nursery
Changeset: r67811:e83aae23c574
Date: 2013-11-03 12:57 +0100
http://bitbucket.org/pypy/pypy/changeset/e83aae23c574/

Log:    Test and fix

diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -1495,8 +1495,8 @@
             # Get the number of card marker bytes in the header.
             typeid = self.get_type_id(obj)
             offset_to_length = self.varsize_offset_to_length(typeid)
-            length = (obj + offset_to_length).signed[0]
-            bytes = self.card_marking_bytes_for_length(length)
+            allocated_length = (obj + offset_to_length).signed[0]
+            bytes = self.card_marking_bytes_for_length(allocated_length)
             p = llarena.getfakearenaaddress(obj - size_gc_header)
             #
             # If the object doesn't have GCFLAG_TRACK_YOUNG_PTRS, then it
@@ -1514,6 +1514,9 @@
             else:
                 # Walk the bytes encoding the card marker bits, and for
                 # each bit set, call trace_and_drag_out_of_nursery_partial().
+                offset_to_used_length = self.varsize_offset_to_used_length(
+                    typeid)
+                used_length = (obj + offset_to_used_length).signed[0]
                 interval_start = 0
                 while bytes > 0:
                     p -= 1
@@ -1526,10 +1529,10 @@
                         interval_stop = interval_start + self.card_page_indices
                         #
                         if cardbyte & 1:
-                            if interval_stop > length:
-                                interval_stop = length
-                                ll_assert(cardbyte <= 1 and bytes == 0,
-                                          "premature end of object")
+                            if interval_stop > used_length:
+                                interval_stop = used_length
+                                if interval_stop <= interval_start:
+                                    break
                             self.trace_and_drag_out_of_nursery_partial(
                                 obj, interval_start, interval_stop)
                         #
diff --git a/rpython/memory/test/snippet.py b/rpython/memory/test/snippet.py
--- a/rpython/memory/test/snippet.py
+++ b/rpython/memory/test/snippet.py
@@ -161,6 +161,46 @@
         res = self.run('from_objwithfinalizer_to_youngobj')
         assert res == 1
 
+    def define_overallocated_items_not_kept_alive(cls):
+        from rpython.rtyper.annlowlevel import cast_instance_to_gcref
+        from rpython.rtyper.lltypesystem import llmemory
+        class B:
+            count = 0
+        class A:
+            def __del__(self):
+                self.b.count += 1
+        ARRAY1 = lltype.GcArray(llmemory.GCREF, hints={'overallocated': True})
+        #ARRAY2 = lltype.GcArray(('a', llmemory.GCREF), ('n', lltype.Signed),
+        #                        hints={'overallocated': True})
+
+        def make(b):
+            a1 = lltype.malloc(ARRAY1, 10)
+            #a2 = lltype.malloc(ARRAY2, 10)
+            a1.used_length = 10
+            #a2.used_length = 10
+            i = 0
+            while i < 10:
+                a = A()
+                a.b = b
+                a1[i] = cast_instance_to_gcref(a)
+                #a2[i].a = cast_instance_to_gcref(a)
+                i += 1
+            return a1
+
+        def f():
+            b = B()
+            a1 = make(b)
+            a1.used_length = 0
+            #a2.used_length = 0
+            llop.gc__collect(lltype.Void)
+            return b.count
+        return f
+
+    def test_overallocated_items_not_kept_alive(self):
+        res = self.run('overallocated_items_not_kept_alive')
+        assert res == 10
+
+
 class SemiSpaceGCTests(SemiSpaceGCTestDefines):
     # xxx messy
 
@@ -172,5 +212,8 @@
         elif name == 'from_objwithfinalizer_to_youngobj':
             func = self.define_from_objwithfinalizer_to_youngobj()
             return self.interpret(func, [])
+        elif name == 'overallocated_items_not_kept_alive':
+            func = self.define_overallocated_items_not_kept_alive()
+            return self.interpret(func, [])
         else:
             assert 0, "don't know what to do with that"
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to