[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