[pypy-commit] pypy cpyext-gc-support: the O list
arigo
noreply at buildbot.pypy.org
Fri Oct 16 14:38:15 EDT 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cpyext-gc-support
Changeset: r80293:b1e55d190a36
Date: 2015-10-16 20:38 +0200
http://bitbucket.org/pypy/pypy/changeset/b1e55d190a36/
Log: the O list
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
@@ -2793,6 +2793,17 @@
self._pyobj(pyobject).ob_pypy_link = objint
self.rrc_p_dict.setitem(obj, pyobject)
+ def rawrefcount_create_link_pyobj(self, gcobj, pyobject):
+ ll_assert(self.rrc_enabled, "rawrefcount.init not called")
+ obj = llmemory.cast_ptr_to_adr(gcobj)
+ if self.is_young_object(obj):
+ self.rrc_o_list_young.append(pyobject)
+ else:
+ self.rrc_o_list_old.append(pyobject)
+ objint = llmemory.cast_adr_to_int(obj, mode="symbolic")
+ self._pyobj(pyobject).ob_pypy_link = objint
+ # there is no rrc_o_dict
+
def rawrefcount_from_obj(self, gcobj):
obj = llmemory.cast_ptr_to_adr(gcobj)
return self.rrc_p_dict.get(obj)
@@ -2822,9 +2833,15 @@
def rrc_minor_collection_free(self):
lst = self.rrc_p_list_young
while lst.non_empty():
- self._rrc_minor_free(lst.pop(), self.rrc_p_list_old)
+ self._rrc_minor_free(lst.pop(), self.rrc_p_list_old,
+ self.rrc_p_dict)
+ lst = self.rrc_o_list_young
+ no_o_dict = self.null_address_dict()
+ while lst.non_empty():
+ self._rrc_minor_free(lst.pop(), self.rrc_o_list_old,
+ no_o_dict)
- def _rrc_minor_free(self, pyobject, surviving_list):
+ def _rrc_minor_free(self, pyobject, surviving_list, surviving_dict):
intobj = self._pyobj(pyobject).ob_pypy_link
obj = llmemory.cast_int_to_adr(intobj)
if self.is_in_nursery(obj):
@@ -2833,7 +2850,8 @@
obj = self.get_forwarding_address(obj)
intobj = llmemory.cast_adr_to_int(obj, mode="symbolic")
self._pyobj(pyobject).ob_pypy_link = intobj
- self.rrc_p_dict.setitem(obj, pyobject)
+ if surviving_dict:
+ surviving_dict.setitem(obj, pyobject)
surviving = True
else:
surviving = False
@@ -2901,6 +2919,14 @@
if new_p_dict:
self.rrc_p_dict.delete()
self.rrc_p_dict = new_p_dict
+ #
+ new_o_list = self.AddressStack()
+ no_o_dict = self.null_address_dict()
+ while self.rrc_o_list_old.non_empty():
+ self._rrc_major_free(self.rrc_o_list_old.pop(), new_o_list,
+ no_o_dict)
+ self.rrc_o_list_old.delete()
+ self.rrc_o_list_old = new_o_list
def _rrc_major_free(self, pyobject, surviving_list, surviving_dict):
intobj = self._pyobj(pyobject).ob_pypy_link
diff --git a/rpython/memory/gc/test/test_rawrefcount.py b/rpython/memory/gc/test/test_rawrefcount.py
--- a/rpython/memory/gc/test/test_rawrefcount.py
+++ b/rpython/memory/gc/test/test_rawrefcount.py
@@ -18,7 +18,8 @@
class TestRawRefCount(BaseDirectGCTest):
GCClass = IncrementalMiniMarkGC
- def _rawrefcount_pair(self, intval, is_direct=False, is_pyobj=False):
+ def _rawrefcount_pair(self, intval, is_direct=False, is_pyobj=False,
+ create_old=False):
if is_direct:
rc = REFCNT_FROM_PYPY_DIRECT
else:
@@ -26,6 +27,10 @@
#
p1 = self.malloc(S)
p1.x = intval
+ if create_old:
+ self.stackroots.append(p1)
+ self.gc.minor_collection()
+ p1 = self.stackroots.pop()
p1ref = lltype.cast_opaque_ptr(llmemory.GCREF, p1)
r1 = lltype.malloc(PYOBJ_HDR, flavor='raw')
r1.ob_refcnt = rc
@@ -46,14 +51,21 @@
assert r1.ob_pypy_link != 0
p1ref = self.gc.rawrefcount_to_obj(r1addr)
p1 = lltype.cast_opaque_ptr(lltype.Ptr(S), p1ref)
- assert p1.x == 42
- assert self.gc.rawrefcount_from_obj(p1ref) == r1addr
+ assert p1.x == intval
+ if not is_pyobj:
+ assert self.gc.rawrefcount_from_obj(p1ref) == r1addr
+ else:
+ # NB. this is not strictly always the case, because of
+ # dead entries remaining behind; but for these simple
+ # tests it is useful to detect unexpected rrc_p_dict
+ # entries
+ assert self.gc.rawrefcount_from_obj(p1ref) == llmemory.NULL
return p1
return p1, p1ref, r1, r1addr, check_alive
- def test_rawrefcount_objects_basic(self):
+ def test_rawrefcount_objects_basic(self, old=False):
p1, p1ref, r1, r1addr, check_alive = (
- self._rawrefcount_pair(42, is_direct=True))
+ self._rawrefcount_pair(42, is_direct=True, create_old=old))
p2 = self.malloc(S)
p2.x = 84
p2ref = lltype.cast_opaque_ptr(llmemory.GCREF, p2)
@@ -72,9 +84,9 @@
lltype.free(r1, flavor='raw')
lltype.free(r2, flavor='raw')
- def test_rawrefcount_objects_collection_survives_from_raw(self):
+ def test_rawrefcount_objects_collection_survives_from_raw(self, old=False):
p1, p1ref, r1, r1addr, check_alive = (
- self._rawrefcount_pair(42, is_direct=True))
+ self._rawrefcount_pair(42, is_direct=True, create_old=old))
check_alive(0)
r1.ob_refcnt += 1
self.gc.minor_collection()
@@ -90,19 +102,22 @@
self.gc.check_no_more_rawrefcount_state()
assert self.dealloc == []
- def test_rawrefcount_dies_quickly(self):
+ def test_rawrefcount_dies_quickly(self, old=False):
p1, p1ref, r1, r1addr, check_alive = (
- self._rawrefcount_pair(42, is_direct=True))
+ self._rawrefcount_pair(42, is_direct=True, create_old=old))
check_alive(0)
self.gc.minor_collection()
+ if old:
+ check_alive(0)
+ self.gc.collect()
py.test.raises(RuntimeError, "r1.ob_refcnt") # dead
py.test.raises(RuntimeError, "p1.x") # dead
self.gc.check_no_more_rawrefcount_state()
assert self.dealloc == []
- def test_rawrefcount_objects_collection_survives_from_obj(self):
+ def test_rawrefcount_objects_collection_survives_from_obj(self, old=False):
p1, p1ref, r1, r1addr, check_alive = (
- self._rawrefcount_pair(42, is_direct=True))
+ self._rawrefcount_pair(42, is_direct=True, create_old=old))
check_alive(0)
self.stackroots.append(p1)
self.gc.minor_collection()
@@ -119,9 +134,18 @@
self.gc.check_no_more_rawrefcount_state()
assert self.dealloc == []
- def test_pypy_nondirect_survives_from_raw(self):
+ def test_rawrefcount_objects_basic_old(self):
+ self.test_rawrefcount_objects_basic(old=True)
+ def test_rawrefcount_objects_collection_survives_from_raw_old(self):
+ self.test_rawrefcount_objects_collection_survives_from_raw(old=True)
+ def test_rawrefcount_dies_quickly_old(self):
+ self.test_rawrefcount_dies_quickly(old=True)
+ def test_rawrefcount_objects_collection_survives_from_obj_old(self):
+ self.test_rawrefcount_objects_collection_survives_from_obj(old=True)
+
+ def test_pypy_nondirect_survives_from_raw(self, old=False):
p1, p1ref, r1, r1addr, check_alive = (
- self._rawrefcount_pair(42, is_direct=False))
+ self._rawrefcount_pair(42, is_direct=False, create_old=old))
check_alive(0)
r1.ob_refcnt += 1
self.gc.minor_collection()
@@ -140,9 +164,9 @@
self.gc.check_no_more_rawrefcount_state()
lltype.free(r1, flavor='raw')
- def test_pypy_nondirect_survives_from_obj(self):
+ def test_pypy_nondirect_survives_from_obj(self, old=False):
p1, p1ref, r1, r1addr, check_alive = (
- self._rawrefcount_pair(42, is_direct=False))
+ self._rawrefcount_pair(42, is_direct=False, create_old=old))
check_alive(0)
self.stackroots.append(p1)
self.gc.minor_collection()
@@ -162,14 +186,77 @@
self.gc.check_no_more_rawrefcount_state()
lltype.free(r1, flavor='raw')
- def test_pypy_nondirect_dies_quickly(self):
+ def test_pypy_nondirect_dies_quickly(self, old=False):
p1, p1ref, r1, r1addr, check_alive = (
- self._rawrefcount_pair(42, is_direct=False))
+ self._rawrefcount_pair(42, is_direct=False, create_old=old))
check_alive(0)
self.gc.minor_collection()
+ if old:
+ check_alive(0)
+ self.gc.collect()
py.test.raises(RuntimeError, "p1.x") # dead
assert r1.ob_refcnt == 0
assert r1.ob_pypy_link == 0
assert self.dealloc == [r1addr]
self.gc.check_no_more_rawrefcount_state()
lltype.free(r1, flavor='raw')
+
+ def test_pypy_nondirect_survives_from_raw_old(self):
+ self.test_pypy_nondirect_survives_from_raw(old=True)
+ def test_pypy_nondirect_survives_from_obj_old(self):
+ self.test_pypy_nondirect_survives_from_obj(old=True)
+ def test_pypy_nondirect_dies_quickly_old(self):
+ self.test_pypy_nondirect_dies_quickly(old=True)
+
+ def test_pyobject_pypy_link_dies_on_minor_collection(self):
+ p1, p1ref, r1, r1addr, check_alive = (
+ self._rawrefcount_pair(42, is_pyobj=True))
+ check_alive(0)
+ r1.ob_refcnt += 1 # the pyobject is kept alive
+ self.gc.minor_collection()
+ assert r1.ob_refcnt == 1 # refcnt dropped to 1
+ assert r1.ob_pypy_link == 0 # detached
+ assert self.dealloc == []
+ self.gc.check_no_more_rawrefcount_state()
+ lltype.free(r1, flavor='raw')
+
+ def test_pyobject_dies(self, old=False):
+ p1, p1ref, r1, r1addr, check_alive = (
+ self._rawrefcount_pair(42, is_pyobj=True, create_old=old))
+ check_alive(0)
+ self.gc.minor_collection()
+ if old:
+ check_alive(0)
+ self.gc.collect()
+ assert r1.ob_refcnt == 0 # refcnt dropped to 0
+ assert r1.ob_pypy_link == 0 # detached
+ assert self.dealloc == [r1addr]
+ self.gc.check_no_more_rawrefcount_state()
+ lltype.free(r1, flavor='raw')
+
+ def test_pyobject_survives_from_obj(self, old=False):
+ p1, p1ref, r1, r1addr, check_alive = (
+ self._rawrefcount_pair(42, is_pyobj=True, create_old=old))
+ check_alive(0)
+ self.stackroots.append(p1)
+ self.gc.minor_collection()
+ check_alive(0)
+ self.gc.collect()
+ check_alive(0)
+ p1 = self.stackroots.pop()
+ self.gc.minor_collection()
+ check_alive(0)
+ assert p1.x == 42
+ assert self.dealloc == []
+ self.gc.collect()
+ py.test.raises(RuntimeError, "p1.x") # dead
+ assert r1.ob_refcnt == 0
+ assert r1.ob_pypy_link == 0
+ assert self.dealloc == [r1addr]
+ self.gc.check_no_more_rawrefcount_state()
+ lltype.free(r1, flavor='raw')
+
+ def test_pyobject_dies_old(self):
+ self.test_pyobject_dies(old=True)
+ def test_pyobject_survives_from_obj_old(self):
+ self.test_pyobject_survives_from_obj(old=True)
More information about the pypy-commit
mailing list