[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