[pypy-svn] r27605 - in pypy/dist/pypy/rpython/memory: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Mon May 22 17:29:07 CEST 2006
Author: cfbolz
Date: Mon May 22 17:29:06 2006
New Revision: 27605
Modified:
pypy/dist/pypy/rpython/memory/gc.py
pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
Log:
try to make recursive calls to collect not crash. does not work with stackless,
so just prevent those calls :-(. some tests.
Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py (original)
+++ pypy/dist/pypy/rpython/memory/gc.py Mon May 22 17:29:06 2006
@@ -153,6 +153,7 @@
# was already freed. The objects in 'malloced_objects' are not
# found via 'poolnodes'.
self.poolnodes = lltype.nullptr(self.POOLNODE)
+ self.collect_in_progress = False
def malloc(self, typeid, length=0):
size = self.fixed_size(typeid)
@@ -217,9 +218,14 @@
# call __del__, move the object to the list of object-without-del
import time
from pypy.rpython.lltypesystem.lloperation import llop
+ # XXX the following two lines should not be there, but without them
+ # there is a strange crash in decodestate when using stackless :-(
+ if self.collect_in_progress:
+ return
if DEBUG_PRINT:
llop.debug_print(lltype.Void, 'collecting...')
start_time = time.time()
+ self.collect_in_progress = True
roots = self.get_roots()
size_gc_header = self.gcheaderbuilder.size_gc_header
## llop.debug_view(lltype.Void, self.malloced_objects, self.poolnodes,
@@ -323,6 +329,7 @@
self.malloced_objects = firstpoolnode.linkedlist
self.poolnodes = firstpoolnode.nextnode
lltype.free(firstpoolnode, flavor='raw')
+ #llop.debug_view(lltype.Void, self.malloced_objects, self.malloced_objects_with_finalizer, size_gc_header)
if curr_heap_size > self.bytes_malloced_threshold:
self.bytes_malloced_threshold = curr_heap_size
@@ -348,23 +355,49 @@
## size_gc_header)
assert self.heap_usage + old_malloced == curr_heap_size + freed_size
- # call finalizers if needed
self.heap_usage = curr_heap_size
hdr = self.malloced_objects_with_finalizer
self.malloced_objects_with_finalizer = lltype.nullptr(self.HDR)
+ last = lltype.nullptr(self.HDR)
while hdr:
next = hdr.next
if hdr.typeid & 1:
- hdr.next = self.malloced_objects_with_finalizer
- self.malloced_objects_with_finalizer = hdr
+ hdr.next = lltype.nullptr(self.HDR)
+ if not self.malloced_objects_with_finalizer:
+ self.malloced_objects_with_finalizer = hdr
+ else:
+ last.next = hdr
hdr.typeid = hdr.typeid & (~1)
+ last = hdr
else:
obj = llmemory.cast_ptr_to_adr(hdr) + size_gc_header
finalizer = self.getfinalizer(hdr.typeid >> 1)
- finalizer(obj)
+ # make malloced_objects_with_finalizer consistent
+ # for the sake of a possible collection caused by finalizer
+ if not self.malloced_objects_with_finalizer:
+ self.malloced_objects_with_finalizer = next
+ else:
+ last.next = next
hdr.next = self.malloced_objects
self.malloced_objects = hdr
+ #llop.debug_view(lltype.Void, self.malloced_objects, self.malloced_objects_with_finalizer, size_gc_header)
+ finalizer(obj)
+ if not self.collect_in_progress: # another collection was caused?
+ return
+ if not last:
+ if self.malloced_objects_with_finalizer == next:
+ self.malloced_objects_with_finalizer = lltype.nullptr(self.HDR)
+ else:
+ # now it gets annoying: finalizer caused a malloc of something
+ # with a finalizer
+ last = self.malloced_objects_with_finalizer
+ while last.next != next:
+ last = last.next
+ last.next = lltype.nullptr(self.HDR)
+ else:
+ last.next = lltype.nullptr(self.HDR)
hdr = next
+ self.collect_in_progress = False
STATISTICS_NUMBERS = 2
Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Mon May 22 17:29:06 2006
@@ -347,6 +347,73 @@
res = run([5, 42]) #XXX pure lazyness here too
assert res == 12
+ def test_finalizer_resurrects(self):
+ class B(object):
+ pass
+ b = B()
+ b.nextid = 0
+ b.num_deleted = 0
+ class A(object):
+ def __init__(self):
+ self.id = b.nextid
+ b.nextid += 1
+ def __del__(self):
+ b.num_deleted += 1
+ b.a = self
+ def f(x, y):
+ a = A()
+ i = 0
+ while i < x:
+ i += 1
+ a = A()
+ llop.gc__collect(lltype.Void)
+ llop.gc__collect(lltype.Void)
+ aid = b.a.id
+ b.a = None
+ # check that __del__ is not called again
+ llop.gc__collect(lltype.Void)
+ llop.gc__collect(lltype.Void)
+ return b.num_deleted * 10 + aid + 100 * (b.a is None)
+ run = self.runner(f, nbargs=2)
+ res = run([5, 42]) #XXX pure lazyness here too
+ assert 160 <= res <= 165
+
+ def test_collect_during_collect(self):
+ class B(object):
+ pass
+ b = B()
+ b.nextid = 1
+ b.num_deleted = 0
+ class A(object):
+ def __init__(self):
+ self.id = b.nextid
+ b.nextid += 1
+ def __del__(self):
+ b.num_deleted += 1
+ C()
+ C()
+ llop.gc__collect(lltype.Void)
+ class C(A):
+ def __del__(self):
+ b.num_deleted += 1
+ def f(x, y):
+ persistent_a1 = A()
+ persistent_a2 = A()
+ i = 0
+ while i < x:
+ i += 1
+ a = A()
+ persistent_a3 = A()
+ persistent_a4 = A()
+ llop.gc__collect(lltype.Void)
+ llop.gc__collect(lltype.Void)
+ b.bla = persistent_a1.id + persistent_a2.id + persistent_a3.id + persistent_a4.id
+ return b.num_deleted
+ run = self.runner(f, nbargs=2)
+ # runs collect recursively 4 times
+ res = run([4, 42]) #XXX pure lazyness here too
+ assert res == 12
+
def test_cloning(self):
B = lltype.GcStruct('B', ('x', lltype.Signed))
A = lltype.GcStruct('A', ('b', lltype.Ptr(B)),
More information about the Pypy-commit
mailing list