[pypy-svn] r54546 - in pypy/branch/gc-tweak/pypy/rpython/memory: gc test

arigo at codespeak.net arigo at codespeak.net
Thu May 8 11:05:02 CEST 2008


Author: arigo
Date: Thu May  8 11:05:01 2008
New Revision: 54546

Modified:
   pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py
   pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py
   pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py
   pypy/branch/gc-tweak/pypy/rpython/memory/test/test_gc.py
Log:
Fix a bug, with test.  See comment in GenerationGC.collect_roots.


Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py	(original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py	Thu May  8 11:05:01 2008
@@ -287,11 +287,22 @@
             self.objects_with_weakrefs.append(obj)
 
     def collect_roots(self):
+        """GenerationGC: collects all roots.
+           HybridGC: collects all roots, excluding the generation 3 ones.
+        """
+        # Warning!  References from static (and possibly gen3) objects
+        # are found by collect_last_generation_roots(), which must be
+        # called *first*!  If it is called after walk_roots(), then the
+        # HybridGC explodes if one of the _collect_root causes an object
+        # to be added to self.last_generation_root_objects.  Indeed, in
+        # this case, the newly added object is traced twice: once by
+        # collect_last_generation_roots() and once because it was added
+        # in self.rawmalloced_objects_to_trace.
+        self.collect_last_generation_roots()
         self.root_walker.walk_roots(
             SemiSpaceGC._collect_root,  # stack roots
             SemiSpaceGC._collect_root,  # static in prebuilt non-gc structures
             None)   # we don't need the static in prebuilt gc objects
-        self.collect_last_generation_roots()
 
     def collect_last_generation_roots(self):
         stack = self.last_generation_root_objects
@@ -337,7 +348,7 @@
             llarena.arena_reset(self.nursery, self.nursery_size, True)
             if DEBUG_PRINT:
                 llop.debug_print(lltype.Void, "percent survived:", float(scan - beginning) / self.nursery_size)
-            self.debug_check_consistency()
+            #self.debug_check_consistency()   # -- quite expensive
         else:
             # no nursery - this occurs after a full collect, triggered either
             # just above or by some previous non-nursery-based allocation.
@@ -490,6 +501,12 @@
         ll_assert(not (self.header(obj).tid & GCFLAG_NO_HEAP_PTRS),
                   "unexpected GCFLAG_NO_HEAP_PTRS")
 
+    def debug_check_can_copy(self, obj):
+        if self.is_in_nursery(obj):
+            pass    # it's ok to copy an object out of the nursery
+        else:
+            SemiSpaceGC.debug_check_can_copy(self, obj)
+
 # ____________________________________________________________
 
 import os

Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py	(original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py	Thu May  8 11:05:01 2008
@@ -88,6 +88,8 @@
     def __init__(self, *args, **kwds):
         large_object = kwds.pop('large_object', 24)
         large_object_gcptrs = kwds.pop('large_object_gcptrs', 32)
+        self.generation3_collect_threshold = kwds.pop(
+            'generation3_collect_threshold', GENERATION3_COLLECT_THRESHOLD)
         GenerationGC.__init__(self, *args, **kwds)
 
         # Objects whose total size is at least 'large_object' bytes are
@@ -250,12 +252,12 @@
     # external objects of 3rd generation.
 
     def collect(self):
-        self.count_semispaceonly_collects = GENERATION3_COLLECT_THRESHOLD
+        self.count_semispaceonly_collects = self.generation3_collect_threshold
         GenerationGC.collect(self)
 
     def is_collecting_gen3(self):
         count = self.count_semispaceonly_collects
-        return count >= GENERATION3_COLLECT_THRESHOLD
+        return count >= self.generation3_collect_threshold
 
     # ___________________________________________________________________
     # the following methods are hook into SemiSpaceGC.semispace_collect()
@@ -338,12 +340,12 @@
         # NB. the object can have a finalizer or be a weakref, but
         # it's not an issue.
         totalsize = self.size_gc_header() + objsize
-        if DEBUG_PRINT:
-            self._nonmoving_copy_count += 1
-            self._nonmoving_copy_size += raw_malloc_usage(totalsize)
         newaddr = self.allocate_external_object(totalsize)
         if not newaddr:
             return llmemory.NULL   # can't raise MemoryError during a collect()
+        if DEBUG_PRINT:
+            self._nonmoving_copy_count += 1
+            self._nonmoving_copy_size += raw_malloc_usage(totalsize)
 
         llmemory.raw_memcopy(obj - self.size_gc_header(), newaddr, totalsize)
         newobj = newaddr + self.size_gc_header()

Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py	(original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py	Thu May  8 11:05:01 2008
@@ -317,6 +317,8 @@
         root.address[0] = self.copy(root.address[0])
 
     def copy(self, obj):
+        if self.DEBUG:
+            self.debug_check_can_copy(obj)
         if self.is_forwarded(obj):
             #llop.debug_print(lltype.Void, obj, "already copied to", self.get_forwarding_address(obj))
             return self.get_forwarding_address(obj)
@@ -586,5 +588,9 @@
         ll_assert(not (tid & GCFLAG_FINALIZATION_ORDERING),
                   "unexpected GCFLAG_FINALIZATION_ORDERING")
 
+    def debug_check_can_copy(self, obj):
+        ll_assert(not (self.tospace <= obj < self.free),
+                  "copy() on already-copied object")
+
     STATISTICS_NUMBERS = 0
 

Modified: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/test/test_gc.py	(original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/test/test_gc.py	Thu May  8 11:05:01 2008
@@ -478,3 +478,46 @@
             return b.num_deleted
         res = self.interpret(f, [15])
         assert res == 16
+
+class TestHybridGCSmallHeap(GCTest):
+    from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass
+    GC_PARAMS = {'space_size': 192,
+                 'min_nursery_size': 48,
+                 'nursery_size': 48,
+                 'large_object': 12,
+                 'large_object_gcptrs': 12,
+                 'generation3_collect_threshold': 5,
+                 }
+
+    def test_gen3_to_gen2_refs(self):
+        class A(object):
+            def __init__(self):
+                self.x1 = -1
+        def f(x):
+            loop = A()
+            loop.next = loop
+            loop.prev = loop
+            i = 0
+            while i < x:
+                i += 1
+                a1 = A()
+                a1.x1 = i
+                a2 = A()
+                a2.x1 = i + 1000
+                a1.prev = loop.prev
+                a1.prev.next = a1
+                a1.next = loop
+                loop.prev = a1
+                a2.prev = loop
+                a2.next = loop.next
+                a2.next.prev = a2
+                loop.next = a2
+            i = 0
+            a = loop
+            while True:
+                a = a.next
+                i += 1
+                if a is loop:
+                    return i
+        res = self.interpret(f, [200])
+        assert res == 401



More information about the Pypy-commit mailing list