[pypy-svn] r25175 - in pypy/dist/pypy: rpython/lltypesystem translator/c translator/c/test translator/c/winproj/extension

tismer at codespeak.net tismer at codespeak.net
Fri Mar 31 10:02:42 CEST 2006


Author: tismer
Date: Fri Mar 31 10:02:37 2006
New Revision: 25175

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/translator/c/pyobj.py
   pypy/dist/pypy/translator/c/test/test_wrapping.py
   pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj
Log:
finished two-way wrapping of objects.
That is:
- RPython classes can be instantiated from CPython by calling the wrapper class
- return values from RPython methods or funtions automatically instantiate their wrapper class
- object indentity is preserved: wrapped(rpyinst) is wrapped(rpyinst) always holds.

There is one bad spot which needs support from the gc gurus:
In order to clear a weak reference, I abused "bare_setfield"  (blush)

Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Fri Mar 31 10:02:37 2006
@@ -19,6 +19,7 @@
      FuncType, Bool, Signed, functionptr, FuncType, PyObject
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython import extregistry
+from pypy.annotation import model as annmodel
 
 #
 #  There is one "vtable" per user class, with the following structure:
@@ -456,14 +457,15 @@
                 raise MissingRTypeAttribute(attr)
             return self.rbase.getfield(vinst, attr, llops, force_cast=True)
 
-    def setfield(self, vinst, attr, vvalue, llops, force_cast=False):
+    def setfield(self, vinst, attr, vvalue, llops, force_cast=False, opname='setfield'):
         """Write the given attribute (or __class__ for the type) of 'vinst'."""
         if attr in self.fields:
             mangled_name, r = self.fields[attr]
             cname = inputconst(Void, mangled_name)
             if force_cast:
                 vinst = llops.genop('cast_pointer', [vinst], resulttype=self)
-            llops.genop('setfield', [vinst, cname, vvalue])
+            llops.genop(opname, [vinst, cname, vvalue])
+            # XXX this is a temporary hack to clear a dead PyObject
         else:
             if self.classdef is None:
                 raise MissingRTypeAttribute(attr)
@@ -592,55 +594,100 @@
 # _________________________ Conversions for CPython _________________________
 
 
-def call_destructor(thing):
-    ll_call_destructor(thing)
+def call_destructor(thing, repr):
+    ll_call_destructor(thing, repr)
 
-def ll_call_destructor(thang):
+def ll_call_destructor(thang, repr):
     return 42 # will be mapped
 
-def ll_clear_wrapper(inst):
-    # Note: we must ensure to enforce creation of this extra field.
-    # this is done when we set up the instantiators in XXX which module???
-    pass # inst.inst___wrapper__ = None
-    #inst.fields.au = 42
-    #setattr(inst, 'inst___wrapper__', None)
-    #inst.inst___wrapper__ = Ptr(33)#inst.inst___wrapper__
-    #p = ll_cast_to_object(inst)
-
-    #inst.inst___wrapper__ = nullptr(PyObject)
-    #inst.inst_a = 42
-    inst._wrapper_ = nullptr(PyObject)
-    
 def rtype_destruct_object(hop):
-    v, = hop.inputargs(*hop.args_r)
-    #repr = hop.args_r[0]
-    null = hop.inputconst(Ptr(PyObject), nullptr(PyObject))
-    #repr.setfield('wrapper', null)
-    #hop.gendirectcall(ll_clear_wrapper, v)
-    hop.genop('gc_unprotect', [v])
+    v_any, c_spec = hop.inputargs(*hop.args_r)
+    repr = c_spec.value
+    if repr.has_wrapper:
+        null = hop.inputconst(Ptr(PyObject), nullptr(PyObject))
+        # XXX this is a hack! We need an operation to remove a broken PyObject
+        repr.setfield(v_any, '_wrapper_', null, hop.llops, opname='bare_setfield')
+    hop.genop('gc_unprotect', [v_any])
 
 extregistry.register_value(ll_call_destructor, 
-    compute_result_annotation=lambda *args:None,
+    compute_result_annotation=lambda *args: None,
     specialize_call=rtype_destruct_object)
 
+def create_pywrapper(thing, repr):
+    return ll_create_pywrapper(thing, repr)
+
+def ll_create_pywrapper(thing, repr):
+    return 42
+
+def rtype_wrap_object_create(hop):
+    gencapi = hop.llops.gencapicall
+    pyptr = hop.r_result
+    v_any, c_spec = hop.inputargs(*hop.args_r)
+    repr = c_spec.value
+    f = call_destructor
+    hop.genop('gc_protect', [v_any])
+    ARG = repr.lowleveltype
+    reprPBC = hop.rtyper.annotator.bookkeeper.immutablevalue(repr)
+    fp_dtor = hop.rtyper.annotate_helper_fn(f, [ARG, reprPBC])
+    FUNC = FuncType([ARG, Void], Void)
+    c_dtor = hop.inputconst(Ptr(FUNC), fp_dtor)
+    res = gencapi('PyCObject_FromVoidPtr', [v_any, c_dtor], resulttype=hop.r_result)
+    if repr.has_wrapper:
+        cobj = res
+        c_cls = hop.inputconst(pyobj_repr, repr.classdef.classdesc.pyobj)
+        c_0 = hop.inputconst(Signed, 0)
+        res = gencapi('PyType_GenericAlloc', [c_cls, c_0], resulttype=pyptr)
+        c_self = hop.inputconst(pyobj_repr, '__self__')
+        v_result = hop.genop('setattr', [res, c_self, cobj], resulttype=pyptr)
+        repr.setfield(v_any, '_wrapper_', res, hop.llops)
+        hop.genop('gc_unprotect', [res]) # yes a weak ref
+    return res
+
+extregistry.register_value(ll_create_pywrapper, 
+    compute_result_annotation=annmodel.SomePtr(Ptr(PyObject)), 
+    specialize_call=rtype_wrap_object_create)
+
+def fetch_pywrapper(thing, repr):
+    return ll_fetch_pywrapper(thing, repr)
+
+def ll_fetch_pywrapper(thing, repr):
+    return 42
+
+def rtype_wrap_object_fetch(hop):
+    v_any, c_spec = hop.inputargs(*hop.args_r)
+    repr = c_spec.value
+    if repr.has_wrapper:
+        return repr.getfield(v_any, '_wrapper_', hop.llops)
+    else:
+        null = hop.inputconst(Ptr(PyObject), nullptr(PyObject))
+        return null
+
+extregistry.register_value(ll_fetch_pywrapper, 
+    compute_result_annotation=annmodel.SomePtr(Ptr(PyObject)), 
+    specialize_call=rtype_wrap_object_fetch)
+    
+def ll_wrap_object(obj, repr):
+    ret = fetch_pywrapper(obj, repr)
+    if not ret:
+        ret = create_pywrapper(obj, repr)
+    return ret
+
 class __extend__(pairtype(PyObjRepr, InstanceRepr)):
     def convert_from_to((r_from, r_to), v, llops):
-        v_adr = llops.gencapicall('PyCObject_AsVoidPtr', [v],
-                                  resulttype=r_to)
+        if r_to.has_wrapper:
+            c_self = inputconst(pyobj_repr, '__self__')
+            v = llops.genop('getattr', [v, c_self], resulttype=r_from)
+        v_adr = llops.gencapicall('PyCObject_AsVoidPtr', [v], resulttype=r_to)
         llops.genop('gc_protect', [v_adr])
         return v_adr
 
 class __extend__(pairtype(InstanceRepr, PyObjRepr)):
     def convert_from_to((r_from, r_to), v, llops):
-        f = call_destructor
-        llops.genop('gc_protect', [v])
-        ARGTYPE = r_from.lowleveltype
-        FUNCTYPE = FuncType([ARGTYPE], Void)
-        fp_dtor = llops.rtyper.annotate_helper_fn(f, [ARGTYPE])
-        c_dtor = inputconst(Ptr(FUNCTYPE), fp_dtor)
-        v_result = llops.gencapicall('PyCObject_FromVoidPtr', [v, c_dtor],
-                                     resulttype=pyobj_repr)
-        return v_result
+        c_repr = inputconst(Void, r_from)
+        if r_from.has_wrapper:
+            return llops.gendirectcall(ll_wrap_object, v, c_repr)
+        else:
+            return llops.gendirectcall(create_pywrapper, v, c_repr)
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/translator/c/pyobj.py
==============================================================================
--- pypy/dist/pypy/translator/c/pyobj.py	(original)
+++ pypy/dist/pypy/translator/c/pyobj.py	Fri Mar 31 10:02:37 2006
@@ -547,8 +547,9 @@
                 if self.shouldskipfunc(value):
                     log.WARNING("skipped class function: %r" % value)
                     continue
-                yield '%s.%s = property(lambda self:%s.__get__(self.__self__))' % (
-                    name, key, self.nameof(value))
+#                yield '%s.%s = property(lambda self:%s.__get__(self.__self__))' % (
+#                    name, key, self.nameof(value))
+                yield '%s.%s = %s' % (name, key, self.nameof(value))
 
         baseargs = ", ".join(basenames)
         if baseargs:
@@ -561,8 +562,9 @@
         a('    __metaclass__ = type')
         a('    __slots__ = ["__self__"] # for PyCObject')
         a('    def __new__(cls, *args, **kwds):')
-        a('        inst = object.__new__(cls)')
-        a('        inst.__self__ = %s()'    % instantiator)
-        a('        return inst')
+        a('        return %s()'             % instantiator )
+        # XXX
+        # I would like to use instantiator directly, but don't know
+        # how to create a function that ignores all args
         self.later(initclassobj())
         return name

Modified: pypy/dist/pypy/translator/c/test/test_wrapping.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_wrapping.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_wrapping.py	Fri Mar 31 10:02:37 2006
@@ -5,6 +5,7 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.objectmodel import instantiate
+from pypy.rpython import robject, rclass
 
 P = False  # debug printing
 
@@ -103,15 +104,24 @@
 def rtype_destruct_object(hop):
     v_any, c_spec = hop.inputargs(*hop.args_r)
     repr = c_spec.value
-    if '_wrapper_' in repr.allinstancefields:
+    if repr.has_wrapper:
         null = hop.inputconst(lltype.Ptr(lltype.PyObject), lltype.nullptr(lltype.PyObject))
+        v_wrapper = repr.getfield(v_any, '_wrapper_', hop.llops)
+        hop.genop('gc_protect', [v_wrapper]) # un-weaken the ref
+        hop.genop('gc_protect', [v_wrapper]) # don't trigger again!
         repr.setfield(v_any, '_wrapper_', null, hop.llops)
     hop.genop('gc_unprotect', [v_any])
 
 def rtype_unwrap_object(hop):
+    pyptr = hop.args_r[0]
+    klass = hop.args_s[1].const
+    classdef = hop.rtyper.annotator.bookkeeper.getuniqueclassdef(klass)
+    repr = rclass.getinstancerepr(hop.rtyper, classdef, True)
     v_pyobj, v_type = hop.inputargs(*hop.args_r)
-    v_adr = hop.llops.gencapicall('PyCObject_AsVoidPtr', [v_pyobj],
-                                  resulttype=hop.r_result)
+    if repr.has_wrapper:
+        c_self = hop.inputconst(robject.pyobj_repr, '__self__')
+        v_pyobj = hop.genop('getattr', [v_pyobj, c_self], resulttype=pyptr)
+    v_adr = hop.llops.gencapicall('PyCObject_AsVoidPtr', [v_pyobj], resulttype=hop.r_result)
     hop.genop('gc_protect', [v_adr])
     return v_adr
 
@@ -119,7 +129,7 @@
     v_any, = hop.inputargs(*hop.args_r)
     repr = hop.args_r[0]
     c_repr = hop.inputconst(lltype.Void, repr)
-    if '_wrapper_' in repr.allinstancefields:
+    if repr.has_wrapper:
         return hop.gendirectcall(ll_wrap_object, v_any, c_repr)
     else:
         return hop.gendirectcall(create_pywrapper, v_any, c_repr)
@@ -130,31 +140,38 @@
         ret = create_pywrapper(obj, repr)
     return ret
 
-def create_pywrapper(thing, sr):
+def create_pywrapper(thing, repr):
     return ll_create_pywrapper(thing, sr)
 
-def ll_create_pywrapper(thing, sr):
+def ll_create_pywrapper(thing, repr):
     return 42
 
-def fetch_pywrapper(thing, sr):
-    return ll_fetch_pywrapper(thing, sr)
+def fetch_pywrapper(thing, repr):
+    return ll_fetch_pywrapper(thing, repr)
 
-def ll_fetch_pywrapper(thing):
+def ll_fetch_pywrapper(thing, repr):
     return 42
 
 def rtype_wrap_object_create(hop):
+    gencapi = hop.llops.gencapicall
+    pyptr = hop.r_result
     v_any, c_spec = hop.inputargs(*hop.args_r)
     repr = c_spec.value
     f = call_destructor
     hop.genop('gc_protect', [v_any])
-    ARGTYPE = repr.lowleveltype
+    ARG = repr.lowleveltype
     reprPBC = hop.rtyper.annotator.bookkeeper.immutablevalue(repr)
-    fp_dtor = hop.rtyper.annotate_helper_fn(f, [ARGTYPE, reprPBC])
-    FUNCTYPE = lltype.FuncType([ARGTYPE, lltype.Void], lltype.Void)
-    c_dtor = hop.inputconst(lltype.Ptr(FUNCTYPE), fp_dtor)
-    res = hop.llops.gencapicall('PyCObject_FromVoidPtr', [v_any, c_dtor],
-                                resulttype=hop.r_result)
-    if '_wrapper_' in repr.allinstancefields:
+    fp_dtor = hop.rtyper.annotate_helper_fn(f, [ARG, reprPBC])
+    FUNC = lltype.FuncType([ARG, lltype.Void], lltype.Void)
+    c_dtor = hop.inputconst(lltype.Ptr(FUNC), fp_dtor)
+    res = gencapi('PyCObject_FromVoidPtr', [v_any, c_dtor], resulttype=pyptr)
+    if repr.has_wrapper:
+        cobj = res
+        c_cls = hop.inputconst(robject.pyobj_repr, repr.classdef.classdesc.pyobj)
+        c_0 = hop.inputconst(lltype.Signed, 0)
+        res = gencapi('PyType_GenericAlloc', [c_cls, c_0], resulttype=pyptr)
+        c_self = hop.inputconst(robject.pyobj_repr, '__self__')
+        hop.genop('setattr', [res, c_self, cobj], resulttype=pyptr)
         repr.setfield(v_any, '_wrapper_', res, hop.llops)
         hop.genop('gc_unprotect', [res]) # yes a weak ref
     return res
@@ -162,7 +179,7 @@
 def rtype_wrap_object_fetch(hop):
     v_any, c_spec = hop.inputargs(*hop.args_r)
     repr = c_spec.value
-    if '_wrapper_' in repr.allinstancefields:
+    if repr.has_wrapper:
         return repr.getfield(v_any, '_wrapper_', hop.llops)
     else:
         null = hop.inputconst(lltype.Ptr(lltype.PyObject), lltype.nullptr(lltype.PyObject))

Modified: pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj
==============================================================================
--- pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj	(original)
+++ pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj	Fri Mar 31 10:02:37 2006
@@ -208,7 +208,7 @@
 			</File>
 		</Filter>
 		<File
-			RelativePath="..\..\..\..\..\..\..\Documents and Settings\ctismer\Local Settings\Temp\usession-964\testing_1\testing_1.c">
+			RelativePath="..\..\..\..\..\..\..\Documents and Settings\ctismer\Local Settings\Temp\usession-1496\testing_1\testing_1.c">
 		</File>
 	</Files>
 	<Globals>



More information about the Pypy-commit mailing list