[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