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

arigo at codespeak.net arigo at codespeak.net
Tue May 6 18:30:34 CEST 2008


Author: arigo
Date: Tue May  6 18:30:34 2008
New Revision: 54483

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/support.py
Log:
Make the consistency checking logic RPython.


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 18:30:34 2008
@@ -7,7 +7,12 @@
     needs_write_barrier = False
     malloc_zero_filled = False
     prebuilt_gc_objects_are_static_roots = True
-    DEBUG = False      # set to True for test_gc.py
+
+    # The following flag enables costly consistency checks after each
+    # collection.  It is automatically set to True by test_gc.py.  The
+    # checking logic is translatable, so the flag can be set to True
+    # here before translation.
+    DEBUG = False
 
     def set_query_functions(self, is_varsize, has_gcptr_in_varsize,
                             is_gcarrayofgcptr,
@@ -151,37 +156,37 @@
 
     def debug_check_consistency(self):
         """To use after a collection.  If self.DEBUG is set, this
-        enumerates all roots and trace all objects to check if we didn't
+        enumerates all roots and traces all objects to check if we didn't
         accidentally free a reachable object or forgot to update a pointer
         to an object that moved.
         """
         if self.DEBUG:
-            # this part is not rpython
-            seen = {}
-            pending = []
-
-            def record(obj):
-                hdrobj = self.header(obj)._obj
-                if hdrobj not in seen:
-                    seen[hdrobj] = True
-                    pending.append(obj)
-
-            def callback(self, root):
-                obj = root.address[0]
-                assert obj
-                record(obj)
-
-            def callback2(pointer, ignored):
-                obj = pointer.address[0]
-                if obj:
-                    record(obj)
-
-            self.root_walker._walk_prebuilt_gc(record)
-            self.root_walker.walk_roots(callback, callback, None)
-            while pending:
+            from pypy.rlib.objectmodel import we_are_translated
+            self._debug_seen = self.AddressStack()
+            self._debug_pending = self.AddressStack()
+            if not we_are_translated():
+                self.root_walker._walk_prebuilt_gc(self._debug_record)
+            callback = GCBase._debug_callback
+            self.root_walker.walk_roots(callback, callback, callback)
+            pending = self._debug_pending
+            while pending.non_empty():
                 obj = pending.pop()
                 self.debug_check_object(obj)
-                self.trace(obj, callback2, None)
+                self.trace(obj, self._debug_callback2, None)
+
+    def _debug_record(self, obj):
+        seen = self._debug_seen
+        if not seen.contains(obj):
+            seen.append(obj)
+            self._debug_pending.append(obj)
+    def _debug_callback(self, root):
+        obj = root.address[0]
+        ll_assert(bool(obj), "NULL address from walk_roots()")
+        self._debug_record(obj)
+    def _debug_callback2(self, pointer, ignored):
+        obj = pointer.address[0]
+        if obj:
+            self._debug_record(obj)
 
     def debug_check_object(self, obj):
         pass

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 18:30:34 2008
@@ -449,41 +449,42 @@
         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)
+            ll_assert(not self.is_in_nursery(obj),
+                      "nursery object with GCFLAG_NO_YOUNG_PTRS")
+            self.trace(obj, self._debug_no_nursery_pointer, None)
         elif not self.is_in_nursery(obj):
-            assert self.header(obj)._obj in self._d_oopty
+            ll_assert(self.old_objects_pointing_to_young.contains(obj),
+                      "missing from old_objects_pointing_to_young")
         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)
+            ll_assert(self.is_last_generation(obj),
+                      "GCFLAG_NO_HEAP_PTRS on non-3rd-generation object")
+            self.trace(obj, self._debug_no_gen1or2_pointer, None)
         elif self.is_last_generation(obj):
-            assert self.header(obj)._obj in self._d_lgro
+            ll_assert(self.last_generation_root_objects.contains(obj),
+                      "missing from last_generation_root_objects")
+
+    def _debug_no_nursery_pointer(self, root, ignored):
+        ll_assert(not self.is_in_nursery(root.address[0]),
+                  "GCFLAG_NO_YOUNG_PTRS but found a young pointer")
+    def _debug_no_gen1or2_pointer(self, root, ignored):
+        target = root.address[0]
+        ll_assert(not target or self.is_last_generation(target),
+                  "GCFLAG_NO_HEAP_PTRS but found a pointer to gen1or2")
 
     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)
+            self.old_objects_pointing_to_young.foreach(
+                self._debug_check_flag_1, None)
+            self.last_generation_root_objects.foreach(
+                self._debug_check_flag_2, None)
+
+    def _debug_check_flag_1(self, obj, ignored):
+        ll_assert(not (self.header(obj).tid & GCFLAG_NO_YOUNG_PTRS),
+                  "unexpected GCFLAG_NO_YOUNG_PTRS")
+    def _debug_check_flag_2(self, obj, ignored):
+        ll_assert(not (self.header(obj).tid & GCFLAG_NO_HEAP_PTRS),
+                  "unexpected GCFLAG_NO_HEAP_PTRS")
 
 # ____________________________________________________________
 

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 18:30:34 2008
@@ -470,21 +470,28 @@
         GenerationGC.debug_check_object(self, obj)
         tid = self.header(obj).tid
         if tid & GCFLAG_UNVISITED:
-            assert self.header(obj)._obj in self._d_gen2ro
+            ll_assert(self.gen2_rawmalloced_objects.contains(obj),
+                      "GCFLAG_UNVISITED on non-gen2 object")
 
     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)
+            self.gen2_rawmalloced_objects.foreach(self._debug_check_gen2, None)
+            self.gen3_rawmalloced_objects.foreach(self._debug_check_gen3, None)
+
+    def _debug_check_gen2(self, obj, ignored):
+        tid = self.header(obj).tid
+        ll_assert(bool(tid & GCFLAG_EXTERNAL),
+                  "gen2: missing GCFLAG_EXTERNAL")
+        ll_assert(bool(tid & GCFLAG_UNVISITED),
+                  "gen2: missing GCFLAG_UNVISITED")
+        ll_assert((tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX,
+                  "gen2: age field too large")
+    def _debug_check_gen3(self, obj, ignored):
+        tid = self.header(obj).tid
+        ll_assert(bool(tid & GCFLAG_EXTERNAL),
+                  "gen3: missing GCFLAG_EXTERNAL")
+        ll_assert(not (tid & GCFLAG_UNVISITED),
+                  "gen3: unexpected GCFLAG_UNVISITED")
+        ll_assert((tid & GCFLAG_AGE_MASK) == GCFLAG_AGE_MAX,
+                  "gen3: wrong age field")

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 18:30:34 2008
@@ -575,10 +575,16 @@
         """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)
+        if tid & GCFLAG_EXTERNAL:
+            ll_assert(tid & GCFLAG_FORWARDED, "bug: external+!forwarded")
+            ll_assert(not (self.tospace <= obj < self.free),
+                      "external flag but object inside the semispaces")
+        else:
+            ll_assert(not (tid & GCFLAG_FORWARDED), "bug: !external+forwarded")
+            ll_assert(self.tospace <= obj < self.free,
+                      "!external flag but object outside the semispaces")
+        ll_assert(not (tid & GCFLAG_FINALIZATION_ORDERING),
+                  "unexpected 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 18:30:34 2008
@@ -291,10 +291,10 @@
         # they could be changed later to point to GC heap objects.
         adr = llmemory.cast_ptr_to_adr(value._as_ptr())
         if TYPE._gckind == "gc":
-            if not gc.prebuilt_gc_objects_are_static_roots:
-                return
-            else:
+            if gc.prebuilt_gc_objects_are_static_roots or gc.DEBUG:
                 appendto = self.addresses_of_static_ptrs
+            else:
+                return
         else:
             appendto = self.addresses_of_static_ptrs_in_nongc
         for a in gc_pointers_inside(value, adr, mutable_only=True):

Modified: pypy/branch/gc-tweak/pypy/rpython/memory/support.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/support.py	(original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/support.py	Tue May  6 18:30:34 2008
@@ -124,6 +124,20 @@
                 count = chunk_size
         foreach._annspecialcase_ = 'specialize:arg(1)'
 
+        def contains(self, addr):
+            """Check if 'addr' is in the list.  That's just a linear scan,
+            so it's slow!"""
+            chunk = self.chunk
+            count = self.used_in_last_chunk
+            while chunk:
+                while count > 0:
+                    count -= 1
+                    if chunk.items[count] == addr:
+                        return True
+                chunk = chunk.next
+                count = chunk_size
+            return False
+
     cache[chunk_size] = AddressStack
     return AddressStack
 



More information about the Pypy-commit mailing list