Author: Armin Rigo <[email protected]>
Branch: cpyext-gc-support
Changeset: r80211:aff2ddf11c01
Date: 2015-10-14 18:31 +0200
http://bitbucket.org/pypy/pypy/changeset/aff2ddf11c01/
Log: Make three versions: create_link_pypy, create_link_pyobj,
create_link_shared
diff --git a/rpython/rlib/rawrefcount.py b/rpython/rlib/rawrefcount.py
--- a/rpython/rlib/rawrefcount.py
+++ b/rpython/rlib/rawrefcount.py
@@ -14,10 +14,11 @@
_p_list = [] # not rpython
_o_list = [] # not rpython
+_s_list = [] # not rpython
-def create_link_from_pypy(p, ob):
- "NOT_RPYTHON"
+def create_link_pypy(p, ob):
+ "NOT_RPYTHON: a link where the PyPy object contains all the data"
assert not hasattr(p, '__rawrefcount')
assert not ob.ob_pypy_link
ob.ob_pypy_link = rgc.cast_instance_to_gcref(p)
@@ -25,13 +26,26 @@
p.__rawrefcount = ob
_p_list.append(ob)
-def create_link_to_pypy(p, ob):
- "NOT_RPYTHON"
+def create_link_pyobj(p, ob):
+ """NOT_RPYTHON: a link where the PyObject contains all the data.
+ from_obj() will not work on this 'p'."""
+ assert not hasattr(p, '__rawrefcount')
assert not ob.ob_pypy_link
ob.ob_pypy_link = rgc.cast_instance_to_gcref(p)
ob.ob_refcnt += REFCNT_FROM_PYPY_OBJECT
+ p.__rawrefcount = lltype.nullptr(lltype.typeOf(ob).TO)
_o_list.append(ob)
+def create_link_shared(p, ob):
+ """NOT_RPYTHON: a link where both p and ob contain some data.
+ from_obj() will not work on this 'p'."""
+ assert not hasattr(p, '__rawrefcount')
+ assert not ob.ob_pypy_link
+ ob.ob_pypy_link = rgc.cast_instance_to_gcref(p)
+ ob.ob_refcnt += REFCNT_FROM_PYPY_OBJECT
+ p.__rawrefcount = lltype.nullptr(lltype.typeOf(ob).TO)
+ _s_list.append(ob)
+
def from_obj(OBTYPE, p):
"NOT_RPYTHON"
null = lltype.nullptr(OBTYPE)
@@ -56,32 +70,55 @@
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:
+ def detach(ob, wr_list):
assert ob.ob_refcnt >= REFCNT_FROM_PYPY_OBJECT
- if ob.ob_refcnt == REFCNT_FROM_PYPY_OBJECT:
- wr_p_list.append(weakref.ref(ob))
- else:
- 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
+ wr_list.append((ob, weakref.ref(p)))
+
+ global _p_list, _o_list, _s_list
+ wr_p_list = []
+ new_p_list = []
+ for ob in _p_list:
+ if ob.ob_refcnt > REFCNT_FROM_PYPY_OBJECT:
+ new_p_list.append(ob)
+ else:
+ wr_p_list.append(weakref.ref(ob))
+ ob = None
+ _p_list = Ellipsis
+
+ wr_s_list = []
+ new_s_list = []
+ for ob in _s_list:
+ if ob.ob_refcnt > REFCNT_FROM_PYPY_OBJECT:
+ new_s_list.append(ob)
+ else:
+ detach(ob, wr_s_list)
+ ob = None
+ _s_list = Ellipsis
+
+ wr_o_list = []
+ for ob in _o_list:
+ detach(ob, wr_o_list)
_o_list = Ellipsis
- #
+
rgc.collect() # forces the cycles to be resolved and the weakrefs to die
rgc.collect()
rgc.collect()
- #
+
+ def attach(ob, wr, final_list):
+ assert ob.ob_refcnt >= REFCNT_FROM_PYPY_OBJECT
+ p = wr()
+ if p is not None:
+ ob.ob_pypy_link = rgc.cast_instance_to_gcref(p)
+ final_list.append(ob)
+ else:
+ ob.ob_refcnt -= REFCNT_FROM_PYPY_OBJECT
+ if ob.ob_refcnt == 0:
+ dealloc.append(ob)
+
_p_list = new_p_list
for wr in wr_p_list:
ob = wr()
@@ -89,17 +126,12 @@
_p_list.append(ob)
#
dealloc = []
+ _s_list = new_s_list
+ for ob, wr in wr_s_list:
+ attach(ob, wr, _s_list)
_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)
+ attach(ob, wr, _o_list)
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
@@ -17,24 +17,35 @@
def setup_method(self, meth):
del rawrefcount._p_list[:]
del rawrefcount._o_list[:]
+ del rawrefcount._s_list[:]
- def test_create_link_from_pypy(self):
+ def test_create_link_pypy(self):
p = W_Root(42)
ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
track_allocation=False)
assert rawrefcount.from_obj(PyObjectS, p) == lltype.nullptr(PyObjectS)
assert rawrefcount.to_obj(W_Root, ob) == None
- rawrefcount.create_link_from_pypy(p, ob)
+ rawrefcount.create_link_pypy(p, ob)
assert rawrefcount.from_obj(PyObjectS, p) == ob
assert rawrefcount.to_obj(W_Root, ob) == p
- def test_create_link_to_pypy(self):
+ def test_create_link_pyobj(self):
p = W_Root(42)
ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
track_allocation=False)
assert rawrefcount.from_obj(PyObjectS, p) == lltype.nullptr(PyObjectS)
assert rawrefcount.to_obj(W_Root, ob) == None
- rawrefcount.create_link_to_pypy(p, ob)
+ rawrefcount.create_link_pyobj(p, ob)
+ assert rawrefcount.from_obj(PyObjectS, p) == lltype.nullptr(PyObjectS)
+ assert rawrefcount.to_obj(W_Root, ob) == p
+
+ def test_create_link_shared(self):
+ p = W_Root(42)
+ ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
+ track_allocation=False)
+ assert rawrefcount.from_obj(PyObjectS, p) == lltype.nullptr(PyObjectS)
+ assert rawrefcount.to_obj(W_Root, ob) == None
+ rawrefcount.create_link_shared(p, ob)
assert rawrefcount.from_obj(PyObjectS, p) == lltype.nullptr(PyObjectS)
assert rawrefcount.to_obj(W_Root, ob) == p
@@ -42,7 +53,7 @@
p = W_Root(42)
ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
track_allocation=False)
- rawrefcount.create_link_from_pypy(p, ob)
+ rawrefcount.create_link_pypy(p, ob)
assert rawrefcount._p_list == [ob]
wr_ob = weakref.ref(ob)
wr_p = weakref.ref(p)
@@ -56,7 +67,7 @@
p = W_Root(42)
ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
track_allocation=False)
- rawrefcount.create_link_from_pypy(p, ob)
+ rawrefcount.create_link_pypy(p, ob)
assert rawrefcount._p_list == [ob]
wr_ob = weakref.ref(ob)
wr_p = weakref.ref(p)
@@ -74,7 +85,7 @@
p = W_Root(42)
ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
track_allocation=False)
- rawrefcount.create_link_from_pypy(p, ob)
+ rawrefcount.create_link_pypy(p, ob)
assert rawrefcount._p_list == [ob]
wr_ob = weakref.ref(ob)
del ob # p remains
@@ -89,7 +100,7 @@
p = W_Root(42)
ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
track_allocation=False)
- rawrefcount.create_link_to_pypy(p, ob)
+ rawrefcount.create_link_pyobj(p, ob)
assert rawrefcount._o_list == [ob]
wr_ob = weakref.ref(ob)
wr_p = weakref.ref(p)
@@ -105,8 +116,8 @@
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)
+ p.pyobj = ob
+ rawrefcount.create_link_pyobj(p, ob)
assert rawrefcount._o_list == [ob]
wr_ob = weakref.ref(ob)
wr_p = weakref.ref(p)
@@ -124,8 +135,8 @@
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)
+ p.pyobj = ob
+ rawrefcount.create_link_pyobj(p, ob)
assert rawrefcount._o_list == [ob]
wr_ob = weakref.ref(ob)
del ob # p remains
@@ -135,4 +146,54 @@
assert ob is not None
assert rawrefcount._o_list == [ob]
assert rawrefcount.to_obj(W_Root, ob) == p
- assert p._rawrefcount == ob
+ assert p.pyobj == ob
+
+ def test_collect_s_dies(self):
+ p = W_Root(42)
+ ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
+ track_allocation=False)
+ rawrefcount.create_link_shared(p, ob)
+ assert rawrefcount._s_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._s_list == []
+ assert wr_p() is None
+
+ def test_collect_s_keepalive_pyobject(self):
+ p = W_Root(42)
+ ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
+ track_allocation=False)
+ p.pyobj = ob
+ rawrefcount.create_link_shared(p, ob)
+ assert rawrefcount._s_list == [ob]
+ wr_ob = weakref.ref(ob)
+ wr_p = weakref.ref(p)
+ ob.ob_refcnt += 1 # <=
+ del ob, p
+ rawrefcount._collect()
+ ob = wr_ob()
+ p = wr_p()
+ assert ob is not None and p is not None
+ assert rawrefcount._s_list == [ob]
+ assert rawrefcount.to_obj(W_Root, ob) == p
+
+ def test_collect_s_keepalive_w_root(self):
+ p = W_Root(42)
+ ob = lltype.malloc(PyObjectS, flavor='raw', zero=True,
+ track_allocation=False)
+ p.pyobj = ob
+ rawrefcount.create_link_shared(p, ob)
+ assert rawrefcount._s_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._s_list == [ob]
+ assert rawrefcount.to_obj(W_Root, ob) == p
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit