Author: Armin Rigo <[email protected]> Branch: cpyext-gc-support Changeset: r80171:b0e71761ec30 Date: 2015-10-13 19:37 +0200 http://bitbucket.org/pypy/pypy/changeset/b0e71761ec30/
Log: Add discussion diff --git a/pypy/doc/discussion/rawrefcount.rst b/pypy/doc/discussion/rawrefcount.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/discussion/rawrefcount.rst @@ -0,0 +1,81 @@ +====================== +Rawrefcount and the GC +====================== + + +GC Interface +------------ + +"PyObject" is a raw structure with at least two fields, ob_refcnt and +ob_pypy_link. The ob_refcnt is the reference counter as used on +CPython. If the PyObject structure is linked to a live PyPy object, +its current address is stored in ob_pypy_link and ob_refcnt is bumped +by the constant REFCNT_FROM_PYPY_OBJECT. + +rawrefcount_create_link_from_pypy(p, ob) + + Makes a link between an exising object gcref 'p' and a newly + allocated PyObject structure 'ob'. Both must not be linked so far. + This adds REFCNT_FROM_PYPY_OBJECT to ob->ob_refcnt. + +rawrefcount_create_link_to_pypy(p, ob) + + Makes a link from an existing PyObject structure 'ob' to a newly + allocated W_CPyExtPlaceHolderObject 'p'. The 'p' should have a + back reference field pointing to 'ob'. This also adds + REFCNT_FROM_PYPY_OBJECT to ob->ob_refcnt. + +rawrefcount_from_obj(p) + + If there is a link from object 'p', and 'p' is not a + W_CPyExtPlaceHolderObject, returns the corresponding 'ob'. + Otherwise, returns NULL. + +rawrefcount_to_obj(ob) + + Returns ob->ob_pypy_link, cast to a GCREF. + + +Collection logic +---------------- + +Objects exising purely on the C side have ob->ob_from_pypy == NULL; +these are purely reference counted. On the other hand, if +ob->ob_from_pypy != NULL, then ob->ob_refcnt is at least +REFCNT_FROM_PYPY_OBJECT and the object is part of a "link". + +The idea is that links whose 'p' is not reachable from other PyPy +objects *and* whose 'ob->ob_refcnt' is REFCNT_FROM_PYPY_OBJECT are the +ones who die. But it is more messy because links created with +rawrefcount_create_link_to_pypy() need to have a deallocator called, +and this cannot occur immediately (and can do random things like +accessing other references this object points to, or resurrecting the +object). + +Let P = list of links created with rawrefcount_create_link_from_pypy() +and O = list of links created with rawrefcount_create_link_to_pypy(). +The PyPy objects in the list O are all W_CPyExtPlaceHolderObject: all +the data is in the PyObjects, and all references are regular +CPython-like reference counts. It is the opposite with the P links: +all references are regular PyPy references from the 'p' object, and +the 'ob' is trivial. + +So, after the collection we do this about P links: + + for (p, ob) in P: + if ob->ob_refcnt != REFCNT_FROM_PYPY_OBJECT: + mark 'p' as surviving, as well as all its dependencies + + for (p, ob) in P: + if p is not surviving: + unlink p and ob, free ob + +Afterwards, the O links are handled like this: + + for (p, ob) in O: + # p is trivial: it cannot point to other PyPy objects + if p is not surviving: + unlink p and ob + ob->ob_refcnt -= REFCNT_FROM_PYPY_OBJECT + if ob->ob_refcnt == 0: + invoke _Py_Dealloc(ob) later, outside the GC _______________________________________________ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
