[pypy-commit] pypy gc-del-3: Pass all of test_incminimark_gc
arigo
pypy.commits at gmail.com
Tue May 3 15:31:18 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: gc-del-3
Changeset: r84176:a12a83151bb7
Date: 2016-05-03 21:31 +0200
http://bitbucket.org/pypy/pypy/changeset/a12a83151bb7/
Log: Pass all of test_incminimark_gc
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -2587,20 +2587,23 @@
# ----------
# Finalizers
+ def call_destructor(self, obj):
+ destructor = self.destructor_or_custom_trace(self.get_type_id(obj))
+ ll_assert(bool(destructor), "no destructor found")
+ destructor(obj)
+
def deal_with_young_objects_with_destructors(self):
"""We can reasonably assume that destructors don't do
anything fancy and *just* call them. Among other things
they won't resurrect objects
"""
- while self.young_objects_with_light_finalizers.non_empty():
- obj = self.young_objects_with_light_finalizers.pop()
+ while self.young_objects_with_destructors.non_empty():
+ obj = self.young_objects_with_destructors.pop()
if not self.is_forwarded(obj):
- finalizer = self.getlightfinalizer(self.get_type_id(obj))
- ll_assert(bool(finalizer), "no light finalizer found")
- finalizer(obj)
+ self.call_destructor(obj)
else:
obj = self.get_forwarding_address(obj)
- self.old_objects_with_light_finalizers.append(obj)
+ self.old_objects_with_destructors.append(obj)
def deal_with_old_objects_with_destructors(self):
"""We can reasonably assume that destructors don't do
@@ -2608,18 +2611,16 @@
they won't resurrect objects
"""
new_objects = self.AddressStack()
- while self.old_objects_with_light_finalizers.non_empty():
- obj = self.old_objects_with_light_finalizers.pop()
+ while self.old_objects_with_destructors.non_empty():
+ obj = self.old_objects_with_destructors.pop()
if self.header(obj).tid & GCFLAG_VISITED:
# surviving
new_objects.append(obj)
else:
# dying
- finalizer = self.getlightfinalizer(self.get_type_id(obj))
- ll_assert(bool(finalizer), "no light finalizer found")
- finalizer(obj)
- self.old_objects_with_light_finalizers.delete()
- self.old_objects_with_light_finalizers = new_objects
+ self.call_destructor(obj)
+ self.old_objects_with_destructors.delete()
+ self.old_objects_with_destructors = new_objects
def deal_with_young_objects_with_finalizers(self):
while self.probably_young_objects_with_finalizers.non_empty():
diff --git a/rpython/memory/test/gc_test_base.py b/rpython/memory/test/gc_test_base.py
--- a/rpython/memory/test/gc_test_base.py
+++ b/rpython/memory/test/gc_test_base.py
@@ -282,7 +282,7 @@
llop.gc__collect(lltype.Void)
aid = b.a.id
b.a = None
- # check that __del__ is not called again
+ # check that finalizer_trigger() 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)
@@ -409,23 +409,32 @@
res = self.interpret(f, [])
assert res
- def test_cycle_with_weakref_and_del(self):
+ def test_cycle_with_weakref_and_finalizer(self):
import weakref
class A(object):
count = 0
a = A()
class B(object):
- def __del__(self):
- # when __del__ is called, the weakref to c should be dead
- if self.ref() is None:
- a.count += 10 # ok
- else:
- a.count = 666 # not ok
+ pass
+ class FQ(rgc.FinalizerQueue):
+ Class = B
+ def finalizer_trigger(self):
+ while True:
+ b = self.next_dead()
+ if b is None:
+ break
+ # when we are here, the weakref to c should be dead
+ if b.ref() is None:
+ a.count += 10 # ok
+ else:
+ a.count = 666 # not ok
+ fq = FQ()
class C(object):
pass
def g():
c = C()
c.b = B()
+ fq.register_finalizer(c.b)
ref = weakref.ref(c)
c.b.ref = ref
return ref
@@ -445,23 +454,32 @@
a = A()
expected_invalid = self.WREF_IS_INVALID_BEFORE_DEL_IS_CALLED
class B(object):
- def __del__(self):
- # when __del__ is called, the weakref to myself is still valid
+ pass
+ class FQ(rgc.FinalizerQueue):
+ Class = B
+ def finalizer_trigger(self):
+ # when we are here, the weakref to myself is still valid
# in RPython with most GCs. However, this can lead to strange
# bugs with incminimark. https://bugs.pypy.org/issue1687
# So with incminimark, we expect the opposite.
- if expected_invalid:
- if self.ref() is None:
- a.count += 10 # ok
+ while True:
+ b = self.next_dead()
+ if b is None:
+ break
+ if expected_invalid:
+ if b.ref() is None:
+ a.count += 10 # ok
+ else:
+ a.count = 666 # not ok
else:
- a.count = 666 # not ok
- else:
- if self.ref() is self:
- a.count += 10 # ok
- else:
- a.count = 666 # not ok
+ if b.ref() is self:
+ a.count += 10 # ok
+ else:
+ a.count = 666 # not ok
+ fq = FQ()
def g():
b = B()
+ fq.register_finalizer(b)
ref = weakref.ref(b)
b.ref = ref
return ref
@@ -479,10 +497,19 @@
class A(object):
pass
class B(object):
- def __del__(self):
- self.wref().x += 1
+ pass
+ class FQ(rgc.FinalizerQueue):
+ Class = B
+ def finalizer_trigger(self):
+ while True:
+ b = self.next_dead()
+ if b is None:
+ break
+ b.wref().x += 1
+ fq = FQ()
def g(a):
b = B()
+ fq.register_finalizer(b)
b.wref = weakref.ref(a)
# the only way to reach this weakref is via B, which is an
# object with finalizer (but the weakref itself points to
@@ -567,15 +594,24 @@
def __init__(self):
self.id = b.nextid
b.nextid += 1
- def __del__(self):
- llop.gc__collect(lltype.Void)
- b.num_deleted += 1
- C()
- C()
+ fq.register_finalizer(self)
class C(A):
- def __del__(self):
- b.num_deleted += 1
- b.num_deleted_c += 1
+ pass
+ class FQ(rgc.FinalizerQueue):
+ Class = A
+ def finalizer_trigger(self):
+ while True:
+ a = self.next_dead()
+ if a is None:
+ break
+ llop.gc__collect(lltype.Void)
+ b.num_deleted += 1
+ if isinstance(a, C):
+ b.num_deleted_c += 1
+ else:
+ C()
+ C()
+ fq = FQ()
def f(x, y):
persistent_a1 = A()
persistent_a2 = A()
diff --git a/rpython/memory/test/snippet.py b/rpython/memory/test/snippet.py
--- a/rpython/memory/test/snippet.py
+++ b/rpython/memory/test/snippet.py
@@ -53,7 +53,7 @@
def set_age_of(c, newvalue):
# NB. this used to be a dictionary, but setting into a dict
# consumes memory. This has the effect that this test's
- # __del__ methods can consume more memory and potentially
+ # finalizer_trigger method can consume more memory and potentially
# cause another collection. This would result in objects
# being unexpectedly destroyed at the same 'state.time'.
state.age[ord(c) - ord('a')] = newvalue
@@ -160,11 +160,22 @@
class B:
count = 0
class A:
- def __del__(self):
- self.b.count += 1
+ pass
+
+ class FQ(rgc.FinalizerQueue):
+ Class = A
+ def finalizer_trigger(self):
+ while True:
+ a = self.next_dead()
+ if a is None:
+ break
+ a.b.count += 1
+ fq = FQ()
+
def g():
b = B()
a = A()
+ fq.register_finalizer(a)
a.b = b
i = 0
lst = [None]
More information about the pypy-commit
mailing list