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

tismer at codespeak.net tismer at codespeak.net
Wed Apr 12 19:39:11 CEST 2006


Author: tismer
Date: Wed Apr 12 19:39:05 2006
New Revision: 25729

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/rtyper.py
   pypy/dist/pypy/translator/c/database.py
   pypy/dist/pypy/translator/c/genc.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
   pypy/dist/pypy/translator/c/wrapper.py
Log:
made object instantiation implicit, to be called during __init__.
This is much more efficient than the former approach, although
the wrapping is slightly more delicate. This also required to
add an extra hook which I dislike, since the rtyper needs to
know which function is actually being wrapped, in order to figure
out whether we are wrapping __init__ or something else.

Temporary (but tested) check-in before refactoring.

Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Wed Apr 12 19:39:05 2006
@@ -594,6 +594,7 @@
 #
 # _________________________ Conversions for CPython _________________________
 
+# part I: wrapping, destructor, preserving object identity
 
 def call_destructor(thing, repr):
     ll_call_destructor(thing, repr)
@@ -602,13 +603,13 @@
     return 42 # will be mapped
 
 def rtype_destruct_object(hop):
-    v_any, c_spec = hop.inputargs(*hop.args_r)
+    v_inst, 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])
+        repr.setfield(v_inst, '_wrapper_', null, hop.llops, opname='bare_setfield')
+    hop.genop('gc_unprotect', [v_inst])
 
 extregistry.register_value(ll_call_destructor, 
     compute_result_annotation=lambda *args: None,
@@ -623,16 +624,16 @@
 def rtype_wrap_object_create(hop):
     gencapi = hop.llops.gencapicall
     pyptr = hop.r_result
-    v_any, c_spec = hop.inputargs(*hop.args_r)
+    v_inst, c_spec = hop.inputargs(*hop.args_r)
     repr = c_spec.value
     f = call_destructor
-    hop.genop('gc_protect', [v_any])
+    hop.genop('gc_protect', [v_inst])
     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)
+    res = gencapi('PyCObject_FromVoidPtr', [v_inst, c_dtor], resulttype=pyptr)
     if repr.has_wrapper:
         cobj = res
         c_cls = hop.inputconst(pyobj_repr, repr.classdef.classdesc.pyobj)
@@ -640,7 +641,7 @@
         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)
+        repr.setfield(v_inst, '_wrapper_', res, hop.llops)
         hop.genop('gc_unprotect', [res]) # yes a weak ref
     return res
 
@@ -655,10 +656,10 @@
     return 42
 
 def rtype_wrap_object_fetch(hop):
-    v_any, c_spec = hop.inputargs(*hop.args_r)
+    v_inst, c_spec = hop.inputargs(*hop.args_r)
     repr = c_spec.value
     if repr.has_wrapper:
-        return repr.getfield(v_any, '_wrapper_', hop.llops)
+        return repr.getfield(v_inst, '_wrapper_', hop.llops)
     else:
         null = hop.inputconst(Ptr(PyObject), nullptr(PyObject))
         return null
@@ -673,15 +674,6 @@
         ret = create_pywrapper(obj, repr)
     return ret
 
-class __extend__(pairtype(PyObjRepr, InstanceRepr)):
-    def convert_from_to((r_from, r_to), v, llops):
-        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):
         c_repr = inputconst(Void, r_from)
@@ -690,6 +682,38 @@
         else:
             return llops.gendirectcall(create_pywrapper, v, c_repr)
 
+# part II: unwrapping, creating the instance
+
+class __extend__(pairtype(PyObjRepr, InstanceRepr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        if r_to.has_wrapper:
+            init, context = llops.rtyper.get_wrapping_hint(r_to.classdef)
+            if context is init:
+                # saving an extra __new__ method, we create the instance on __init__
+                v_inst = r_to.new_instance(llops)
+                gencapi = llops.gencapicall
+                rtyper = llops.rtyper
+                pyptr = r_from
+                f = call_destructor
+                ARG = r_to.lowleveltype
+                reprPBC = rtyper.annotator.bookkeeper.immutablevalue(r_to)
+                fp_dtor = rtyper.annotate_helper_fn(f, [ARG, reprPBC])
+                FUNC = FuncType([ARG, Void], Void)
+                c_dtor = inputconst(Ptr(FUNC), fp_dtor)
+                v_cobj = gencapi('PyCObject_FromVoidPtr', [v_inst, c_dtor], resulttype=pyptr)
+                c_self = inputconst(pyobj_repr, '__self__')
+                llops.genop('setattr', [v, c_self, v_cobj], resulttype=pyptr)
+                r_to.setfield(v_inst, '_wrapper_', v, llops)
+                llops.genop('gc_protect', [v_inst])
+                llops.genop('gc_unprotect', [v])
+                return v_inst
+
+            c_self = inputconst(pyobj_repr, '__self__')
+            v = llops.genop('getattr', [v, c_self], resulttype=r_from)
+        v_inst = llops.gencapicall('PyCObject_AsVoidPtr', [v], resulttype=r_to)
+        llops.genop('gc_protect', [v_inst])
+        return v_inst
+
 # ____________________________________________________________
 
 def ll_both_none(ins1, ins2):

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Wed Apr 12 19:39:05 2006
@@ -57,6 +57,7 @@
         self.instance_reprs = {}
         self.pbc_reprs = {}
         self.classdefs_with_wrapper = {}
+        self.wrapper_context = None # or add an extra arg to convertvar?
         self.concrete_calltables = {}
         self.class_pbc_attributes = {}
         self.oo_meth_impls = {}
@@ -89,7 +90,13 @@
         self.crash_on_first_typeerror = True
 
     def add_wrapper(self, clsdef):
-        self.classdefs_with_wrapper[clsdef] = clsdef
+        # record that this class has a wrapper, and what the __init__ is
+        init = getattr(clsdef.classdesc.pyobj.__init__, 'im_func', None)
+        self.classdefs_with_wrapper[clsdef] = init
+
+    def set_wrapper_context(self, obj):
+        # not nice, but we sometimes need to know which function we are wrapping
+        self.wrapper_context = obj
 
     def add_pendingsetup(self, repr): 
         assert isinstance(repr, Repr)
@@ -546,6 +553,9 @@
     def needs_wrapper(self, clsdef):
         return clsdef in self.classdefs_with_wrapper
 
+    def get_wrapping_hint(self, clsdef):
+        return self.classdefs_with_wrapper[clsdef], self.wrapper_context
+
     def getcallable(self, graph):
         def getconcretetype(v):
             return self.bindingrepr(v).lowleveltype

Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py	(original)
+++ pypy/dist/pypy/translator/c/database.py	Wed Apr 12 19:39:05 2006
@@ -21,8 +21,7 @@
 
 class LowLevelDatabase(object):
 
-    def __init__(self, translator=None, standalone=False, gcpolicy=None, thread_enabled=False,
-                 instantiators={}):
+    def __init__(self, translator=None, standalone=False, gcpolicy=None, thread_enabled=False):
         self.translator = translator
         self.standalone = standalone
         self.structdefnodes = {}
@@ -38,7 +37,7 @@
         self.infs = []
         self.namespace = CNameManager()
         if not standalone:
-            self.pyobjmaker = PyObjMaker(self.namespace, self.get, translator, instantiators)
+            self.pyobjmaker = PyObjMaker(self.namespace, self.get, translator)
         if gcpolicy is None:
             from pypy.translator.c import gc
             polname = conftest.option.gcpolicy

Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py	(original)
+++ pypy/dist/pypy/translator/c/genc.py	Wed Apr 12 19:39:05 2006
@@ -33,11 +33,10 @@
         self.libraries = libraries
         self.exports = {}
 
-    def build_database(self, exports=[], instantiators={}):
+    def build_database(self, exports=[]):
         translator = self.translator
         db = LowLevelDatabase(translator, standalone=self.standalone, 
-                              gcpolicy=self.gcpolicy, thread_enabled=self.thread_enabled,
-                              instantiators=instantiators)
+                              gcpolicy=self.gcpolicy, thread_enabled=self.thread_enabled)
 
         if self.stackless:
             from pypy.translator.c.stackless import StacklessData

Modified: pypy/dist/pypy/translator/c/pyobj.py
==============================================================================
--- pypy/dist/pypy/translator/c/pyobj.py	(original)
+++ pypy/dist/pypy/translator/c/pyobj.py	Wed Apr 12 19:39:05 2006
@@ -23,7 +23,7 @@
     reconstruct them.
     """
 
-    def __init__(self, namespace, getvalue, translator=None, instantiators={}):
+    def __init__(self, namespace, getvalue, translator=None):
         self.namespace = namespace
         self.getvalue = getvalue
         self.translator = translator
@@ -38,7 +38,6 @@
         self.wrappers = {}    # {'pycfunctionvariable': ('name', 'wrapperfn')}
         self.import_hints = {} # I don't seem to need it any longer.
         # leaving the import support intact, doesn't hurt.
-        self.instantiators = instantiators
 
     def nameof(self, obj, debug=None):
         if debug:
@@ -336,7 +335,8 @@
         return name
 
     def nameof_classobj(self, cls):
-        if cls in self.instantiators:
+        clsdef = self.translator.annotator.bookkeeper.getuniqueclassdef(cls)
+        if self.translator.rtyper.needs_wrapper(clsdef):
             return self.wrap_exported_class(cls)
 
         if cls.__doc__ and cls.__doc__.lstrip().startswith('NOT_RPYTHON'):
@@ -551,16 +551,9 @@
         if baseargs:
             baseargs = '(%s)' % baseargs
             
-        # fishing for the instantiator
-        instantiator = self.nameof(self.instantiators[cls])
         a = self.initcode.append
         a('class %s%s:'                     % (name, baseargs) )
         a('    __metaclass__ = type')
         a('    __slots__ = ["__self__"] # for PyCObject')
-        a('    def __new__(cls, *args, **kwds):')
-        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	Wed Apr 12 19:39:05 2006
@@ -4,7 +4,6 @@
 from pypy.rpython import extregistry
 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
 
 import sys
@@ -35,7 +34,6 @@
     t.buildannotator()
     rtyper = t.buildrtyper()
     bk = rtyper.annotator.bookkeeper
-    instantiators = {}
     t.annotator.build_types(func, get_annotation(func))
     if not exports:
         exports = []
@@ -43,14 +41,7 @@
     exports = exports + [('__all__', all)]
     for obj in exports:
         if isinstance(obj, type):
-            cls = obj
-            def make():
-                obj = instantiate(cls)
-                return obj
-            make.__name__ = cls.__name__ + '__new__'
-            t.annotator.build_types(make, [])
-            instantiators[cls] = make
-            clsdef = bk.getuniqueclassdef(cls)
+            clsdef = bk.getuniqueclassdef(obj)
             rtyper.add_wrapper(clsdef)
         elif callable(obj):
             t.annotator.build_types(obj, get_annotation(obj))
@@ -71,7 +62,7 @@
 
     cbuilder = CExtModuleBuilder(t, func, gcpolicy=gcpolicy)
     # explicit build of database
-    db = cbuilder.build_database(exports=exports, instantiators=instantiators)
+    db = cbuilder.build_database(exports=exports)
     cbuilder.generate_source(db)
     cbuilder.compile()
 
@@ -263,9 +254,9 @@
         DemoClass.__init__(self, b, a)
         self.c = c
 
-#    def demo(self, *other):
+    def demo(self, *other):
         #if other: print other
- #       return float(DemoClass.demo(self))
+        return float(DemoClass.demo(self))
     
     def otherdemo(self):
         return 'this is the DemoSubclass', self.a, self.b
@@ -319,38 +310,8 @@
 # _______________________________________________
 # creating our own setup function for the module
 
-def do_the_import():
-    from twisted.internet import reactor    
-    return reactor
-
-def rtype_wraptest(hop):
-    #v_obj, = hop.inputargs((robject.pyobj_repr, ))
-    from pypy.objspace.flow.model import Constant
-    v_obj = Constant(hop.args_s[0].const)
-    v = hop.genop('simple_call', [v_obj], resulttype = robject.pyobj_repr)
-    return v
-
-def wraptest(obj):
-    return obj
-extregistry.register_value(wraptest,
-        compute_result_annotation = annmodel.SomeObject(),
-        specialize_call = rtype_wraptest)
-
-# not sure what to do with the above.
-# use genpickle facility to produce a plain function?
-# create a space and run geninterp on it?
-# tweak flow space to delay the imports for this func?
-
-### XXX write up the rules how to use this ###
-
-def t2():
-    global sys
-    import sys
-
 def setup_new_module(mod, modname):
     # note the name clash with py.test on setup_module
-    #t1()
-    #t2()
     return
     from types import module
     m = module(modname)
@@ -392,6 +353,7 @@
     res = obj.demo()
     assert res == DemoClass(2, 3).demo()
 
+
 if __name__=='__main__':
     test_expose_classes()
     

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	Wed Apr 12 19:39:05 2006
@@ -208,7 +208,7 @@
 			</File>
 		</Filter>
 		<File
-			RelativePath="..\..\..\..\..\..\..\Documents and Settings\ctismer\Local Settings\Temp\usession-1751\testing_1\testing_1.c">
+			RelativePath="..\..\..\..\..\..\..\Documents and Settings\ctismer\Local Settings\Temp\usession-1965\testing_1\testing_1.c">
 		</File>
 	</Files>
 	<Globals>

Modified: pypy/dist/pypy/translator/c/wrapper.py
==============================================================================
--- pypy/dist/pypy/translator/c/wrapper.py	(original)
+++ pypy/dist/pypy/translator/c/wrapper.py	Wed Apr 12 19:39:05 2006
@@ -98,9 +98,12 @@
             assert rtyper is not None, (
                 "needs the rtyper to perform argument conversions")
             r_arg = rtyper.bindingrepr(inputargs[i])
+            # give the rtyper a chance to know which function we are wrapping
+            rtyper.set_wrapper_context(func)
             varguments[i] = newops.convertvar(varguments[i],
                                               r_from = pyobj_repr,
                                                 r_to = r_arg)
+            rtyper.set_wrapper_context(None)
 
     # "result = direct_call(func, argument_0, argument_1, ..)"
     vlist = [inputconst(typeOf(f), f)] + varguments



More information about the Pypy-commit mailing list