[pypy-commit] pypy cpyext-gc-support: test create_link_pypy() with REFCNT_FROM_PYPY

arigo noreply at buildbot.pypy.org
Fri Oct 16 14:10:24 EDT 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cpyext-gc-support
Changeset: r80291:97943215d17a
Date: 2015-10-16 20:10 +0200
http://bitbucket.org/pypy/pypy/changeset/97943215d17a/

Log:	test create_link_pypy() with REFCNT_FROM_PYPY

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
@@ -2761,7 +2761,7 @@
     def _pyobj(self, pyobjaddr):
         return llmemory.cast_adr_to_ptr(pyobjaddr, self.PYOBJ_HDR_PTR)
 
-    def rawrefcount_init(self):
+    def rawrefcount_init(self, dealloc_callback):
         # see pypy/doc/discussion/rawrefcount.rst
         if not self.rrc_enabled:
             self.rrc_p_list_young = self.AddressStack()
@@ -2772,6 +2772,7 @@
             p = lltype.malloc(self._ADDRARRAY, 1, flavor='raw',
                               track_allocation=False)
             self.rrc_singleaddr = llmemory.cast_ptr_to_adr(p)
+            self.rrc_dealloc_callback = dealloc_callback
             self.rrc_enabled = True
 
     def check_no_more_rawrefcount_state(self):
@@ -2854,19 +2855,19 @@
         from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_DIRECT
         #
         rc = self._pyobj(pyobject).ob_refcnt
-        if rc == REFCNT_FROM_PYPY_DIRECT:
+        if rc >= REFCNT_FROM_PYPY_DIRECT:
+            ll_assert(rc == REFCNT_FROM_PYPY_DIRECT,
+                    "cpyext: rrc_trace() should have marked the pypy obj alive")
             lltype.free(self._pyobj(pyobject), flavor='raw')
         else:
+            ll_assert(rc >= REFCNT_FROM_PYPY, "refcount underflow?")
             ll_assert(rc < int(REFCNT_FROM_PYPY_DIRECT * 0.99),
                       "refcount underflow from REFCNT_FROM_PYPY_DIRECT?")
-            if rc > REFCNT_FROM_PYPY_DIRECT:
-                rc -= REFCNT_FROM_PYPY_DIRECT
-            else:
-                ll_assert(rc >= REFCNT_FROM_PYPY, "refcount underflow?")
-                rc -= REFCNT_FROM_PYPY
-                if rc == 0:
-                    xxx  # _Py_Dealloc(pyobject)
+            rc -= REFCNT_FROM_PYPY
             self._pyobj(pyobject).ob_refcnt = rc
+            self._pyobj(pyobject).ob_pypy_link = 0
+            if rc == 0:
+                self.rrc_dealloc_callback(pyobject)
     _rrc_free._always_inline_ = True
 
     def rrc_major_collection_trace(self):
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
@@ -31,7 +31,8 @@
         r1.ob_refcnt = rc
         r1.ob_pypy_link = 0
         r1addr = llmemory.cast_ptr_to_adr(r1)
-        self.gc.rawrefcount_init()
+        self.dealloc = []
+        self.gc.rawrefcount_init(self.dealloc.append)
         if is_pyobj:
             assert not is_direct
             self.gc.rawrefcount_create_link_pyobj(p1ref, r1addr)
@@ -87,6 +88,7 @@
         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):
         p1, p1ref, r1, r1addr, check_alive = (
@@ -105,3 +107,47 @@
         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_pypy_nondirect_survives_from_raw(self):
+        p1, p1ref, r1, r1addr, check_alive = (
+            self._rawrefcount_pair(42, is_direct=False))
+        check_alive(0)
+        r1.ob_refcnt += 1
+        self.gc.minor_collection()
+        check_alive(+1)
+        self.gc.collect()
+        check_alive(+1)
+        r1.ob_refcnt -= 1
+        self.gc.minor_collection()
+        p1 = check_alive(0)
+        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_pypy_nondirect_survives_from_obj(self):
+        p1, p1ref, r1, r1addr, check_alive = (
+            self._rawrefcount_pair(42, is_direct=False))
+        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')


More information about the pypy-commit mailing list