Author: Armin Rigo <[email protected]>
Branch: cpyext-gc-support
Changeset: r80193:7dce6c22637b
Date: 2015-10-14 09:36 +0200
http://bitbucket.org/pypy/pypy/changeset/7dce6c22637b/

Log:    Collecting the O list

diff --git a/rpython/rlib/rawrefcount.py b/rpython/rlib/rawrefcount.py
--- a/rpython/rlib/rawrefcount.py
+++ b/rpython/rlib/rawrefcount.py
@@ -52,23 +52,55 @@
         return p
 
 def _collect():
-    "NOT_RPYTHON: for tests only"
-    global _p_list
-    wrlist = []
-    newlist = []
+    """NOT_RPYTHON: for tests only.  Emulates a GC collection.
+    Returns the list of ob's whose _Py_Dealloc() should be called,
+    from the O list.
+    """
+    global _p_list, _o_list
+    wr_p_list = []
+    new_p_list = []
     for ob in _p_list:
         assert ob.ob_refcnt >= REFCNT_FROM_PYPY_OBJECT
         if ob.ob_refcnt == REFCNT_FROM_PYPY_OBJECT:
-            wrlist.append(weakref.ref(ob))
+            wr_p_list.append(weakref.ref(ob))
         else:
-            newlist.append(ob)
-    _p_list = newlist
-    del ob
+            new_p_list.append(ob)
+        ob = None
+    _p_list = Ellipsis
+    #
+    wr_o_list = []
+    for ob in _o_list:
+        assert ob.ob_pypy_link
+        p = rgc.try_cast_gcref_to_instance(object, ob.ob_pypy_link)
+        assert p is not None
+        ob.ob_pypy_link = lltype.nullptr(llmemory.GCREF.TO)
+        wr_o_list.append((ob, weakref.ref(p)))
+        p = None
+    _o_list = Ellipsis
+    #
     rgc.collect()  # forces the cycles to be resolved and the weakrefs to die
-    for wr in wrlist:
+    rgc.collect()
+    rgc.collect()
+    #
+    _p_list = new_p_list
+    for wr in wr_p_list:
         ob = wr()
         if ob is not None:
-            newlist.append(ob)
+            _p_list.append(ob)
+    #
+    dealloc = []
+    _o_list = []
+    for ob, wr in wr_o_list:
+        p = wr()
+        if p is not None:
+            ob.ob_pypy_link = rgc.cast_instance_to_gcref(p)
+            _o_list.append(ob)
+        else:
+            assert ob.ob_refcnt >= REFCNT_FROM_PYPY_OBJECT
+            ob.ob_refcnt -= REFCNT_FROM_PYPY_OBJECT
+            if ob.ob_refcnt == 0:
+                dealloc.append(ob)
+    return dealloc
 
 # ____________________________________________________________
 
diff --git a/rpython/rlib/test/test_rawrefcount.py 
b/rpython/rlib/test/test_rawrefcount.py
--- a/rpython/rlib/test/test_rawrefcount.py
+++ b/rpython/rlib/test/test_rawrefcount.py
@@ -38,7 +38,7 @@
         assert rawrefcount.from_obj(PyObjectS, p) == lltype.nullptr(PyObjectS)
         assert rawrefcount.to_obj(W_Root, ob) == p
 
-    def test_collect_dies(self):
+    def test_collect_p_dies(self):
         p = W_Root(42)
         ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
                            track_allocation=False)
@@ -52,7 +52,7 @@
         assert wr_ob() is None
         assert wr_p() is None
 
-    def test_collect_keepalive_pyobject(self):
+    def test_collect_p_keepalive_pyobject(self):
         p = W_Root(42)
         ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
                            track_allocation=False)
@@ -70,7 +70,7 @@
         assert rawrefcount.to_obj(W_Root, ob) == p
         assert rawrefcount.from_obj(PyObjectS, p) == ob
 
-    def test_collect_keepalive_w_root(self):
+    def test_collect_p_keepalive_w_root(self):
         p = W_Root(42)
         ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
                            track_allocation=False)
@@ -84,3 +84,55 @@
         assert rawrefcount._p_list == [ob]
         assert rawrefcount.to_obj(W_Root, ob) == p
         assert rawrefcount.from_obj(PyObjectS, p) == ob
+
+    def test_collect_o_dies(self):
+        p = W_Root(42)
+        ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
+                           track_allocation=False)
+        rawrefcount.create_link_to_pypy(p, ob)
+        assert rawrefcount._o_list == [ob]
+        wr_ob = weakref.ref(ob)
+        wr_p = weakref.ref(p)
+        del ob, p
+        dealloc = rawrefcount._collect()
+        ob = wr_ob()
+        assert ob is not None
+        assert dealloc == [ob]
+        assert rawrefcount._o_list == []
+        assert wr_p() is None
+
+    def test_collect_o_keepalive_pyobject(self):
+        p = W_Root(42)
+        ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
+                           track_allocation=False)
+        p._rawrefcount = ob
+        rawrefcount.create_link_to_pypy(p, ob)
+        assert rawrefcount._o_list == [ob]
+        wr_ob = weakref.ref(ob)
+        wr_p = weakref.ref(p)
+        ob.ob_refcnt += 1      # <=
+        del p
+        dealloc = rawrefcount._collect()
+        assert dealloc == []
+        p = wr_p()
+        assert p is None            # was unlinked
+        assert ob.ob_refcnt == 1    # != REFCNT_FROM_PYPY_OBJECT + 1
+        assert rawrefcount._o_list == []
+        assert rawrefcount.to_obj(W_Root, ob) == None
+
+    def test_collect_o_keepalive_w_root(self):
+        p = W_Root(42)
+        ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
+                           track_allocation=False)
+        p._rawrefcount = ob
+        rawrefcount.create_link_to_pypy(p, ob)
+        assert rawrefcount._o_list == [ob]
+        wr_ob = weakref.ref(ob)
+        del ob       # p remains
+        dealloc = rawrefcount._collect()
+        assert dealloc == []
+        ob = wr_ob()
+        assert ob is not None
+        assert rawrefcount._o_list == [ob]
+        assert rawrefcount.to_obj(W_Root, ob) == p
+        assert p._rawrefcount == ob
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to