[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