Author: Armin Rigo <ar...@tunes.org>
Branch: cpyext-gc-support
Changeset: r80337:21a3dead2ef1
Date: 2015-10-19 15:32 +0200
http://bitbucket.org/pypy/pypy/changeset/21a3dead2ef1/

Log:    in-progress: from_pyobj()

diff --git a/pypy/module/cpyext/intobject.py b/pypy/module/cpyext/intobject.py
--- a/pypy/module/cpyext/intobject.py
+++ b/pypy/module/cpyext/intobject.py
@@ -19,11 +19,12 @@
 @bootstrap_function
 def init_intobject(space):
     "Type description of PyIntObject"
-    from pypy.objspace.std.intobject import W_AbstractIntObject
+    from pypy.objspace.std.intobject import W_AbstractIntObject, W_IntObject
     setup_class_for_cpyext(W_AbstractIntObject,
                            basestruct=PyIntObject.TO,
-                           fill_pyobj=int_fill_pyobj)
-                           #realize=int_realize)
+                           fill_pyobj=int_fill_pyobj,
+                           realize=int_realize,
+                           realize_subclass_of=W_IntObject)
 
 def int_fill_pyobj(space, w_obj, py_int):
     """
@@ -32,15 +33,9 @@
     """
     py_int.c_ob_ival = space.int_w(w_obj)
 
-def int_realize(space, obj):
-    intval = rffi.cast(lltype.Signed, rffi.cast(PyIntObject, obj).c_ob_ival)
-    w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
-    w_obj = space.allocate_instance(W_IntObject, w_type)
-    w_obj.__init__(intval)
-    track_reference(space, obj, w_obj)
-    state = space.fromcache(RefcountState)
-    state.set_lifeline(w_obj, obj)
-    return w_obj
+def int_realize(space, w_obj, py_obj):
+    intval = rffi.cast(lltype.Signed, rffi.cast(PyIntObject, py_obj).c_ob_ival)
+    W_IntObject.__init__(w_obj, intval)
 
 PyInt_Check, PyInt_CheckExact = build_type_checkers("Int")
 
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
@@ -134,6 +134,7 @@
     else:
         return _get_typedescr_1(typedef)
 
+
 #________________________________________________________
 # type description
 
@@ -143,17 +144,20 @@
     basestruct: The basic structure to allocate
     alloc_pyobj: default create_pyobj calls this to get the PyObject
     fill_pyobj: default create_pyobj calls this after attaching is done
-    realize   : Function called to create a pypy object from a raw struct
+    realize   : Function called to create a pypy object from a PyObject
     dealloc   : a cpython_api(external=False), similar to PyObject_dealloc
     """
 
     tp_basestruct = kw.pop('basestruct', PyObject.TO)
     tp_alloc_pyobj  = kw.pop('alloc_pyobj', None)
     tp_fill_pyobj   = kw.pop('fill_pyobj', None)
-    force_create_pyobj = kw.pop('force_create_pyobj', False)
-    #tp_realize    = kw.pop('realize', None)
+    tp_realize      = kw.pop('realize', None)
+    force_create_pyobj  = kw.pop('force_create_pyobj', False)
+    realize_subclass_of = kw.pop('realize_subclass_of', None)
     #tp_dealloc    = kw.pop('dealloc', None)
-    assert not kw, "Extra arguments to make_typedescr"
+    assert not kw, "Extra arguments to make_typedescr: %s" % kw.keys()
+
+    assert 'cpyext_basestruct' not in W_Class.__dict__    # double set
 
     if tp_alloc_pyobj or tp_fill_pyobj or force_create_pyobj:
         #
@@ -186,6 +190,22 @@
             keepalive_until_here(self)
         W_Class.cpyext_fill_prebuilt_pyobj = cpyext_fill_prebuilt_pyobj
 
+    if tp_realize or realize_subclass_of:
+        W_CPyExtPlaceHolder = get_cpyextplaceholder_subclass(
+            realize_subclass_of or W_Class)
+        if tp_realize:
+            tp_realize._always_inline_ = True
+        #
+        def cpyext_realize(space, pyobj):
+            w_obj = W_CPyExtPlaceHolder(pyobj)
+            if tp_realize:
+                tp_realize(space, w_obj, pyobj)
+            return w_obj
+        #
+        typedef = realize_subclass_of.typedef
+        assert not hasattr(typedef, 'cpyext_realize')
+        typedef.cpyext_realize = cpyext_realize
+
     W_Class.cpyext_basestruct = tp_basestruct
 
 
@@ -210,13 +230,62 @@
         ob = w_type.cpyext_create_pyobj(space)
         pto = rffi.cast(PyTypeObjectPtr, ob)
     return pto
-
 W_TypeObject.cpyext_c_type_object = lltype.nullptr(PyTypeObjectPtr.TO)
 
-
 @bootstrap_function
 def init_pyobject(space):
-    setup_class_for_cpyext(W_Root, force_create_pyobj=True)
+    setup_class_for_cpyext(W_Root, force_create_pyobj=True,
+                           realize_subclass_of=W_ObjectObject)
+
+
+#________________________________________________________
+# W_CPyExtPlaceHolderObject
+
+# When we ask for the convertion of a PyObject to a W_Root and there
+# is none, we look up the correct W_Root subclass to use (W_IntObject,
+# etc., or W_ObjectObject by default), take the W_CPyExtPlaceHolder
+# special subclass of it, and instantiate that.  W_CPyExtPlaceHolder
+# adds the field "cpyext_pyobj" pointing back to the PyObject.
+# W_CPyExtPlaceHolder is made using the following memo function.
+
+@specialize.memo()
+def get_cpyextplaceholder_subclass(W_Class):
+    try:
+        return W_Class.__dict__['_cpyextplaceholder_subclass']
+    except KeyError:
+        pass
+    assert W_Class is not W_TypeObject
+
+    class W_CPyExtPlaceHolder(W_Class):
+        def __init__(self, pyobj):
+            self.cpyext_pyobj = pyobj
+        def cpyext_as_pyobj(self, space):
+            return self.cpyext_pyobj
+
+    W_CPyExtPlaceHolder.__name__ = W_Class.__name__ + '_CPyExtPlaceHolder'
+    W_Class._cpyextplaceholder_subclass = W_CPyExtPlaceHolder
+    return W_CPyExtPlaceHolder
+
+
+
+def _default_cpyext_as_pyobj(self, space):
+    """Default implementation for most classes in PyPy.
+    Overridden by the W_CPyExtPlaceHolder subclasses."""
+    ob = rawrefcount.from_obj(PyObject, self)
+    if not ob:
+        ob = self.cpyext_create_pyobj(space)
+    return ob
+W_Root.cpyext_as_pyobj = _default_cpyext_as_pyobj
+
+def _type_cpyext_as_pyobj(self, space):
+    ob = get_c_ob_type(space, self)
+    return rffi.cast(PyObject, ob)
+W_TypeObject.cpyext_as_pyobj = _type_cpyext_as_pyobj
+W_TypeObject._cpyextplaceholder_subclass = W_TypeObject
+
+def _create_w_obj_from_pyobj(space, pyobj):
+    w_type = from_pyobj(pyobj.c_ob_type)
+    return w_type.instancetypedef.cpyext_realize(space, pyobj)
 
 #________________________________________________________
 # refcounted object support
@@ -385,13 +454,7 @@
     use keepalive_until_here(w_obj) some time later.
     """
     assert not is_pyobj(w_obj)
-    assert w_obj is not None
-    #if isinstance(w_obj, W_CPyExtPlaceHolderObject):
-    #    xxx
-    ob = rawrefcount.from_obj(PyObject, w_obj)
-    if not ob:
-        ob = w_obj.cpyext_create_pyobj(space)
-    return ob
+    return w_obj.cpyext_as_pyobj(space)
 as_pyobj._always_inline_ = True
 
 def as_xpyobj(space, w_obj):
@@ -408,7 +471,7 @@
     pyobj = rffi.cast(PyObject, pyobj)
     w_obj = rawrefcount.to_obj(W_Root, pyobj)
     if w_obj is None:
-        w_obj = _create_w_obj_from_pyobj(pyobj)
+        w_obj = _create_w_obj_from_pyobj(space, pyobj)
     return w_obj
 from_pyobj._always_inline_ = True
 
@@ -432,10 +495,7 @@
     _about_ = is_pyobj
     def compute_result_annotation(self, s_x):
         from rpython.rtyper.llannotation import SomePtr
-        if isinstance(s_x, SomePtr):
-            return self.bookkeeper.immutablevalue(True)
-        else:
-            return self.bookkeeper.immutablevalue(False)
+        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)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to