Author: Armin Rigo <ar...@tunes.org>
Branch: cpyext-gc-support-2
Changeset: r81953:3d1f9e7d01e1
Date: 2016-01-26 19:10 +0100
http://bitbucket.org/pypy/pypy/changeset/3d1f9e7d01e1/

Log:    in-progress

diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -2,9 +2,11 @@
 
 from pypy.interpreter.baseobjspace import W_Root, SpaceCache
 from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rtyper.extregistry import ExtRegistryEntry
 from pypy.module.cpyext.api import (
     cpython_api, bootstrap_function, PyObject, PyObjectP, ADDR,
-    CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr)
+    CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr,
+    INTERPLEVEL_API)
 from pypy.module.cpyext.state import State
 from pypy.objspace.std.typeobject import W_TypeObject
 from pypy.objspace.std.objectobject import W_ObjectObject
@@ -151,10 +153,9 @@
 def create_ref(space, w_obj, itemcount=0):
     """
     Allocates a PyObject, and fills its fields with info from the given
-    intepreter object.
+    interpreter object.
     """
-    GOES_AWAY
-    state = space.fromcache(RefcountState)
+    #state = space.fromcache(RefcountState)
     w_type = space.type(w_obj)
     if w_type.is_cpytype():
         py_obj = state.get_from_lifeline(w_obj)
@@ -173,18 +174,16 @@
     """
     Ties together a PyObject and an interpreter object.
     """
-    GOES_AWAY
     # XXX looks like a PyObject_GC_TRACK
-    ptr = rffi.cast(ADDR, py_obj)
-    state = space.fromcache(RefcountState)
+    assert py_obj.c_ob_refcnt < rawrefcount.REFCNT_FROM_PYPY
+    py_obj.c_ob_refcnt += rawrefcount.REFCNT_FROM_PYPY
     if DEBUG_REFCOUNT:
         debug_refcount("MAKREF", py_obj, w_obj)
+        assert w_obj
+        assert py_obj
         if not replace:
             assert w_obj not in state.py_objects_w2r
-        assert ptr not in state.py_objects_r2w
-    state.py_objects_w2r[w_obj] = py_obj
-    if ptr: # init_typeobject() bootstraps with NULL references
-        state.py_objects_r2w[ptr] = w_obj
+    rawrefcount.create_link_pypy(py_obj, w_obj)
 
 def make_ref(space, w_obj):
     """
@@ -232,6 +231,124 @@
     return get_typedescr(w_type.instancetypedef).realize(space, ref)
 
 
+def debug_collect():
+    rawrefcount._collect(track_allocation=False)
+
+
+def as_pyobj(space, w_obj):
+    """
+    Returns a 'PyObject *' representing the given intepreter object.
+    This doesn't give a new reference, but the returned 'PyObject *'
+    is valid at least as long as 'w_obj' is.  To be safe, you should
+    use keepalive_until_here(w_obj) some time later.
+
+    NOTE: get_pyobj_and_incref() is safer.
+    """
+    if w_obj is not None:
+        assert not is_pyobj(w_obj)
+        return XXXXXXXXXXX
+    else:
+        return lltype.nullptr(PyObject.TO)
+as_pyobj._always_inline_ = 'try'
+INTERPLEVEL_API['as_pyobj'] = as_pyobj
+
+def pyobj_has_w_obj(pyobj):
+    return rawrefcount.to_obj(W_Root, pyobj) is not None
+INTERPLEVEL_API['pyobj_has_w_obj'] = staticmethod(pyobj_has_w_obj)
+
+@specialize.ll()
+def from_pyobj(space, pyobj):
+    assert is_pyobj(pyobj)
+    if pyobj:
+        pyobj = rffi.cast(PyObject, pyobj)
+        w_obj = rawrefcount.to_obj(W_Root, pyobj)
+        if w_obj is None:
+            XXXXXXXXXXX
+        return w_obj
+    else:
+        return None
+from_pyobj._always_inline_ = 'try'
+INTERPLEVEL_API['from_pyobj'] = from_pyobj
+
+
+def is_pyobj(x):
+    if x is None or isinstance(x, W_Root):
+        return False
+    elif is_PyObject(lltype.typeOf(x)):
+        return True
+    else:
+        raise TypeError(repr(type(x)))
+INTERPLEVEL_API['is_pyobj'] = staticmethod(is_pyobj)
+
+class Entry(ExtRegistryEntry):
+    _about_ = is_pyobj
+    def compute_result_annotation(self, s_x):
+        from rpython.rtyper.llannotation import SomePtr
+        return self.bookkeeper.immutablevalue(isinstance(s_x, SomePtr))
+    def specialize_call(self, hop):
+        hop.exception_cannot_occur()
+        return hop.inputconst(lltype.Bool, hop.s_result.const)
+
+@specialize.ll()
+def get_pyobj_and_incref(space, obj):
+    """Increment the reference counter of the PyObject and return it.
+    Can be called with either a PyObject or a W_Root.
+    """
+    if obj:
+        if is_pyobj(obj):
+            pyobj = rffi.cast(PyObject, obj)
+        else:
+            pyobj = as_pyobj(space, obj)
+        assert pyobj.c_ob_refcnt > 0
+        pyobj.c_ob_refcnt += 1
+        if not is_pyobj(obj):
+            keepalive_until_here(obj)
+        return pyobj
+    else:
+        return lltype.nullptr(PyObject.TO)
+INTERPLEVEL_API['get_pyobj_and_incref'] = get_pyobj_and_incref
+
+
+@specialize.ll()
+def get_w_obj_and_decref(space, obj):
+    """Decrement the reference counter of the PyObject and return the
+    corresponding W_Root object (so the reference count is at least
+    REFCNT_FROM_PYPY and cannot be zero).  Can be called with either
+    a PyObject or a W_Root.
+    """
+    if is_pyobj(obj):
+        pyobj = rffi.cast(PyObject, obj)
+        w_obj = from_pyobj(space, pyobj)
+    else:
+        w_obj = obj
+        pyobj = as_pyobj(space, w_obj)
+    if pyobj:
+        pyobj.c_ob_refcnt -= 1
+        assert pyobj.c_ob_refcnt >= rawrefcount.REFCNT_FROM_PYPY
+        keepalive_until_here(w_obj)
+    return w_obj
+INTERPLEVEL_API['get_w_obj_and_decref'] = get_w_obj_and_decref
+
+
+@specialize.ll()
+def incref(space, obj):
+    get_pyobj_and_incref(space, obj)
+INTERPLEVEL_API['incref'] = incref
+
+@specialize.ll()
+def decref(space, obj):
+    if is_pyobj(obj):
+        obj = rffi.cast(PyObject, obj)
+        if obj:
+            assert obj.c_ob_refcnt > 0
+            obj.c_ob_refcnt -= 1
+            if obj.c_ob_refcnt == 0:
+                _Py_Dealloc(space, obj)
+    else:
+        get_w_obj_and_decref(space, obj)
+INTERPLEVEL_API['decref'] = decref
+
+
 @cpython_api([PyObject], lltype.Void)
 def Py_IncRef(space, obj):
     incref(obj)
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -21,7 +21,8 @@
 from pypy.module.cpyext.modsupport import convert_method_defs
 from pypy.module.cpyext.pyobject import (
     PyObject, make_ref, create_ref, from_ref, get_typedescr, make_typedescr,
-    track_reference, RefcountState, borrow_from, Py_DecRef)
+    track_reference, RefcountState, borrow_from, Py_DecRef,
+    get_pyobj_and_incref)
 from pypy.module.cpyext.slotdefs import (
     slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function)
 from pypy.module.cpyext.state import State
@@ -320,13 +321,13 @@
     # - object.tp_bases is a tuple
     # - tuple.tp_bases is a tuple
 
-    # insert null placeholders to please create_ref()
-    track_reference(space, lltype.nullptr(PyObject.TO), space.w_type)
-    track_reference(space, lltype.nullptr(PyObject.TO), space.w_object)
-    track_reference(space, lltype.nullptr(PyObject.TO), space.w_tuple)
-    track_reference(space, lltype.nullptr(PyObject.TO), space.w_str)
-
-    # create the objects
+    # we create the types manually here
+    py_type   = _type_alloc(space, lltype.nullptr(PyTypeObject))
+    py_object = _type_alloc(space, lltype.nullptr(PyTypeObject))
+    py_tuple  = _type_alloc(space, lltype.nullptr(PyTypeObject))
+    py_str    = _type_alloc(space, lltype.nullptr(PyTypeObject))
+    ...
+    
     py_type = create_ref(space, space.w_type)
     py_object = create_ref(space, space.w_object)
     py_tuple = create_ref(space, space.w_tuple)
@@ -459,13 +460,16 @@
 
 
 def type_alloc(space, w_metatype):
-    metatype = rffi.cast(PyTypeObjectPtr, make_ref(space, w_metatype))
+    metatype = get_pyobj_and_incref(space, w_metatype)
+    metatype = rffi.cast(PyTypeObjectPtr, metatype)
+    assert metatype
     # Don't increase refcount for non-heaptypes
-    if metatype:
-        flags = rffi.cast(lltype.Signed, metatype.c_tp_flags)
-        if not flags & Py_TPFLAGS_HEAPTYPE:
-            Py_DecRef(space, w_metatype)
+    flags = rffi.cast(lltype.Signed, metatype.c_tp_flags)
+    if not flags & Py_TPFLAGS_HEAPTYPE:
+        Py_DecRef(space, w_metatype)
+    return _type_alloc(space, metatype)
 
+def _type_alloc(space, metatype):
     heaptype = lltype.malloc(PyHeapTypeObject.TO,
                              flavor='raw', zero=True)
     pto = heaptype.c_ht_type
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to