[pypy-svn] r54479 - in pypy/branch/gc-tweak/pypy/rpython/memory: . gc

arigo at codespeak.net arigo at codespeak.net
Tue May 6 16:39:34 CEST 2008


Author: arigo
Date: Tue May  6 16:39:32 2008
New Revision: 54479

Modified:
   pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py
   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/gctypelayout.py
   pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py
Log:
Try to cover as many invariants as possible in the debug checks.


Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py	Tue May  6 16:39:32 2008
@@ -150,7 +150,7 @@
     trace._annspecialcase_ = 'specialize:arg(2)'
 
     def debug_check_consistency(self):
-        """To use around a collection.  If self.DEBUG is set, this
+        """To use after a collection.  If self.DEBUG is set, this
         enumerates all roots and trace all objects to check if we didn't
         accidentally free a reachable object or forgot to update a pointer
         to an object that moved.
@@ -176,11 +176,16 @@
                 if obj:
                     record(obj)
 
-            self.root_walker.walk_roots(callback, callback, callback)
+            self.root_walker._walk_prebuilt_gc(record)
+            self.root_walker.walk_roots(callback, callback, None)
             while pending:
                 obj = pending.pop()
+                self.debug_check_object(obj)
                 self.trace(obj, callback2, None)
 
+    def debug_check_object(self, obj):
+        pass
+
 
 class MovingGCBase(GCBase):
     moving_gc = True

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	Tue May  6 16:39:32 2008
@@ -321,7 +321,6 @@
             ll_assert(self.nursery_size <= self.top_of_space - self.free,
                          "obtain_free_space failed to do its job")
         if self.nursery:
-            self.debug_check_consistency()
             if DEBUG_PRINT:
                 llop.debug_print(lltype.Void, "minor collect")
             # a nursery-only collection
@@ -444,6 +443,48 @@
         # overridden by HybridGC
         return (self.header(obj).tid & GCFLAG_EXTERNAL) != 0
 
+    def debug_check_object(self, obj):
+        """Check the invariants about 'obj' that should be true
+        between collections."""
+        SemiSpaceGC.debug_check_object(self, obj)
+        tid = self.header(obj).tid
+        if tid & GCFLAG_NO_YOUNG_PTRS:
+            def _no_nursery_pointer(root, ignored):
+                assert not self.is_in_nursery(root.address[0])
+            assert not self.is_in_nursery(obj)
+            self.trace(obj, _no_nursery_pointer, None)
+        elif not self.is_in_nursery(obj):
+            assert self.header(obj)._obj in self._d_oopty
+        if tid & GCFLAG_NO_HEAP_PTRS:
+            def _no_gen1or2_pointer(root, ignored):
+                target = root.address[0]
+                assert not target or self.is_last_generation(target)
+            assert self.is_last_generation(obj)
+            self.trace(obj, _no_gen1or2_pointer, None)
+        elif self.is_last_generation(obj):
+            assert self.header(obj)._obj in self._d_lgro
+
+    def debug_check_consistency(self):
+        if self.DEBUG:
+            self._make_dict("old_objects_pointing_to_young", "_d_oopty")
+            self._make_dict("last_generation_root_objects", "_d_lgro")
+            SemiSpaceGC.debug_check_consistency(self)
+            def check1(obj, ignored):
+                assert not (self.header(obj).tid & GCFLAG_NO_YOUNG_PTRS)
+            def check2(obj, ignored):
+                assert not (self.header(obj).tid & GCFLAG_NO_HEAP_PTRS)
+            self.old_objects_pointing_to_young.foreach(check1, None)
+            self.last_generation_root_objects.foreach(check2, None)
+
+    def _make_dict(self, attr, shortattr):
+        result = {}
+        def _add_dict(obj, ignored):
+            hdrobj = self.header(obj)._obj
+            result[hdrobj] = True
+        lst = getattr(self, attr)
+        lst.foreach(_add_dict, None)
+        setattr(self, shortattr, result)
+
 # ____________________________________________________________
 
 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	Tue May  6 16:39:32 2008
@@ -264,12 +264,6 @@
         # At the start of a collection, the GCFLAG_UNVISITED bit is set
         # exactly on the objects in gen2_rawmalloced_objects.  Only
         # raw_malloc'ed objects can ever have this bit set.
-        if self.DEBUG:
-            def check_bit(obj, expected):
-                assert self.header(obj).tid & GCFLAG_UNVISITED == expected
-            self.gen2_rawmalloced_objects.foreach(check_bit, GCFLAG_UNVISITED)
-            self.gen3_rawmalloced_objects.foreach(check_bit, 0)
-
         self.count_semispaceonly_collects += 1
         if self.is_collecting_gen3():
             # set the GCFLAG_UNVISITED on all rawmalloced generation-3 objects
@@ -469,3 +463,28 @@
                              "nonmoving freed:     ",
                              dead_size, "bytes in",
                              dead_count, "objs")
+
+    def debug_check_object(self, obj):
+        """Check the invariants about 'obj' that should be true
+        between collections."""
+        GenerationGC.debug_check_object(self, obj)
+        tid = self.header(obj).tid
+        if tid & GCFLAG_UNVISITED:
+            assert self.header(obj)._obj in self._d_gen2ro
+
+    def debug_check_consistency(self):
+        if self.DEBUG:
+            self._make_dict("gen2_rawmalloced_objects", "_d_gen2ro")
+            GenerationGC.debug_check_consistency(self)
+            def check_gen2(obj, ignored):
+                tid = self.header(obj).tid
+                assert tid & GCFLAG_EXTERNAL
+                assert tid & GCFLAG_UNVISITED
+                assert (tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX
+            def check_gen3(obj, ignored):
+                tid = self.header(obj).tid
+                assert tid & GCFLAG_EXTERNAL
+                assert not (tid & GCFLAG_UNVISITED)
+                assert (tid & GCFLAG_AGE_MASK) == GCFLAG_AGE_MAX
+            self.gen2_rawmalloced_objects.foreach(check_gen2, None)
+            self.gen3_rawmalloced_objects.foreach(check_gen3, None)

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	Tue May  6 16:39:32 2008
@@ -202,13 +202,13 @@
         self.max_space_size = size
 
     def collect(self):
+        self.debug_check_consistency()
         self.semispace_collect()
         # the indirection is required by the fact that collect() is referred
         # to by the gc transformer, and the default argument would crash
         # (this is also a hook for the HybridGC)
 
     def semispace_collect(self, size_changing=False):
-        self.debug_check_consistency()
         if DEBUG_PRINT:
             import time
             llop.debug_print(lltype.Void)
@@ -571,5 +571,14 @@
         finally:
             self.finalizer_lock_count -= 1
 
+    def debug_check_object(self, obj):
+        """Check the invariants about 'obj' that should be true
+        between collections."""
+        tid = self.header(obj).tid
+        if not (tid & GCFLAG_EXTERNAL):
+            assert not (tid & GCFLAG_FORWARDED)
+        assert (self.tospace <= obj < self.free) == (not (tid&GCFLAG_EXTERNAL))
+        assert not (tid & GCFLAG_FINALIZATION_ORDERING)
+
     STATISTICS_NUMBERS = 0
 

Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py	(original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py	Tue May  6 16:39:32 2008
@@ -193,6 +193,9 @@
         self.addresses_of_static_ptrs = []
         # this lists contains pointers in raw Structs and Arrays
         self.addresses_of_static_ptrs_in_nongc = []
+        # for debugging, the following list collects all the prebuilt
+        # GcStructs and GcArrays
+        self.all_prebuilt_gc = []
         self.finalizer_funcptrs = {}
         self.offsettable_cache = {}
         self.next_typeid_cache = {}
@@ -280,6 +283,7 @@
             hdr = gc.gcheaderbuilder.new_header(value)
             adr = llmemory.cast_ptr_to_adr(hdr)
             gc.init_gc_object_immortal(adr, typeid)
+            self.all_prebuilt_gc.append(value)
 
         # The following collects the addresses of all the fields that have
         # a GC Pointer type, inside the current prebuilt object.  All such

Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py	(original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py	Tue May  6 16:39:32 2008
@@ -25,8 +25,9 @@
             TYPE = lltype.typeOf(obj)
             layoutbuilder.consider_constant(TYPE, obj, self.gc)
 
-        self.constantroots = list(layoutbuilder.addresses_of_static_ptrs)
+        self.constantroots = layoutbuilder.addresses_of_static_ptrs
         self.constantrootsnongc = layoutbuilder.addresses_of_static_ptrs_in_nongc
+        self._all_prebuilt_gc = layoutbuilder.all_prebuilt_gc
 
     # ____________________________________________________________
     #
@@ -133,6 +134,10 @@
                 if addrofaddr.address[0]:
                     collect_stack_root(gc, addrofaddr)
 
+    def _walk_prebuilt_gc(self, collect):    # debugging only!  not RPython
+        for obj in self.gcheap._all_prebuilt_gc:
+            collect(llmemory.cast_ptr_to_adr(obj._as_ptr()))
+
 
 class DirectRunLayoutBuilder(gctypelayout.TypeLayoutBuilder):
 


More information about the pypy-svn mailing list