[pypy-svn] r26412 - in pypy/dist/pypy/translator/c: . src test winproj/extension

tismer at codespeak.net tismer at codespeak.net
Thu Apr 27 09:55:21 CEST 2006


Author: tismer
Date: Thu Apr 27 09:55:16 2006
New Revision: 26412

Modified:
   pypy/dist/pypy/translator/c/genc.py
   pypy/dist/pypy/translator/c/pyobj.py
   pypy/dist/pypy/translator/c/src/module.h
   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:
added support for creation of real PyCFunction based methods, for speed

Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py	(original)
+++ pypy/dist/pypy/translator/c/genc.py	Thu Apr 27 09:55:16 2006
@@ -33,7 +33,7 @@
         self.libraries = libraries
         self.exports = {}
 
-    def build_database(self, exports=[]):
+    def build_database(self, exports=[], pyobj_options=None):
         translator = self.translator
         db = LowLevelDatabase(translator, standalone=self.standalone, 
                               gcpolicy=self.gcpolicy, thread_enabled=self.thread_enabled)
@@ -43,6 +43,11 @@
             db.stacklessdata = StacklessData(db)
             db.use_stackless_transformation = self.use_stackless_transformation
 
+        # pass extra options into pyobjmaker
+        if pyobj_options:
+            for key, value in pyobj_options.items():
+                setattr(db.pyobjmaker, key, value)
+
         # we need a concrete gcpolicy to do this
         self.libraries += db.gcpolicy.gc_libraries()
 
@@ -720,6 +725,7 @@
         pyobjnode = database.containernodes[pyobjptr._obj]
         print >> f, '\tPyModule_AddObject(m, "%s", %s);' % (publicname,
                                                             pyobjnode.name)
+    print >> f, '\tcall_postsetup(m);'
     print >> f, '}'
     f.close()
 

Modified: pypy/dist/pypy/translator/c/pyobj.py
==============================================================================
--- pypy/dist/pypy/translator/c/pyobj.py	(original)
+++ pypy/dist/pypy/translator/c/pyobj.py	Thu Apr 27 09:55:16 2006
@@ -39,6 +39,8 @@
         self.import_hints = {} # I don't seem to need it any longer.
         # leaving the import support intact, doesn't hurt.
         self.name_for_meth = {} # get nicer wrapper names
+        self.is_method = {}
+        self.use_true_methods = False # may be overridden
 
     def nameof(self, obj, debug=None):
         if debug:
@@ -212,7 +214,8 @@
             return self.skipped_function(func)
 
         fwrapper = gen_wrapper(func, self.translator,
-                               newname=self.name_for_meth.get(func, func.__name__))
+                               newname=self.name_for_meth.get(func, func.__name__),
+                               as_method=func in self.is_method)
         pycfunctionobj = self.uniquename('gfunc_' + func.__name__)
         self.wrappers[pycfunctionobj] = func.__name__, self.getvalue(fwrapper), func.__doc__
         return pycfunctionobj
@@ -574,6 +577,7 @@
                         if ann.binding(graph.getargs()[0]).classdef is not clsdef:
                             value = new_method_graph(graph, clsdef, fname, self.translator)
                     self.name_for_meth[value] = fname
+                    self.is_method[value] = self.use_true_methods
                 yield '%s.%s = %s' % (name, key, self.nameof(value))
             if not init_seen:
                 log.WARNING('No __init__ found for %s - you cannot build instances' %

Modified: pypy/dist/pypy/translator/c/src/module.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/module.h	(original)
+++ pypy/dist/pypy/translator/c/src/module.h	Thu Apr 27 09:55:16 2006
@@ -60,8 +60,10 @@
 
 /* helper-hook for post-setup */
 static globalfunctiondef_t *globalfunctiondefsptr;
-static PyObject *postsetup_get_type_dict(PyObject *tp);
+static PyObject *postsetup_get_typedict(PyObject *tp);
+static PyObject *postsetup_get_methodname(int funcidx);
 static PyObject *postsetup_build_method(int funcidx, PyObject *type);
+int call_postsetup(PyObject *m);
 
 /* implementations */
 
@@ -145,7 +147,7 @@
 	return 0;
 }
 
-static PyObject *postsetup_get_type_dict(PyObject *tp)
+static PyObject *postsetup_get_typedict(PyObject *tp)
 {
     PyTypeObject *type = (PyTypeObject *)tp;
     PyObject *ret;
@@ -155,11 +157,39 @@
     return ret;
 }
 
+static PyObject *postsetup_get_methodname(int funcidx)
+{   
+    globalfunctiondef_t *gfuncdef = &globalfunctiondefsptr[funcidx];
+
+    if (gfuncdef->p)
+	return PyString_FromString(gfuncdef->gfunc_name);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
 static PyObject *postsetup_build_method(int funcidx, PyObject *type)
 {   
     globalfunctiondef_t *gfuncdef = &globalfunctiondefsptr[funcidx];
 
-    return PyDescr_NewMethod((PyTypeObject *)type, &gfuncdef->ml);
+    if (gfuncdef->p)
+	return PyDescr_NewMethod((PyTypeObject *)type, &gfuncdef->ml);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+int call_postsetup(PyObject *m)
+{
+    PyObject *init, *ret;
+    
+    init = PyDict_GetItemString(this_module_globals, "__init__");
+    if (init == NULL) {
+	PyErr_Clear();
+	return 0;
+    }
+    ret = PyObject_CallFunction(init, "O", m);
+    if (ret == NULL)
+	return -1;
+    return 0;
 }
 
 #endif /* PYPY_NOT_MAIN_FILE */

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	Thu Apr 27 09:55:16 2006
@@ -9,7 +9,7 @@
 
 import sys, types
 
-P = not False  # debug printing
+P = False  # debug printing
 
 def get_annotation(func):
     argstypelist = []
@@ -68,7 +68,10 @@
 
     cbuilder = CExtModuleBuilder(t, func, gcpolicy=gcpolicy)
     # explicit build of database
-    db = cbuilder.build_database(exports=exports)
+    pyobj_options = {
+        'use_true_methods': '__init__' in exports
+        }
+    db = cbuilder.build_database(exports=exports, pyobj_options=pyobj_options)
     cbuilder.generate_source(db)
     if view:
         t.viewcg()
@@ -238,38 +241,70 @@
     exec src
     del __builtin__, name, obj, src
 
-def setup_new_module(mod, modname):
-    # note the name clash with py.test on setup_module
+
+def get_methodname(funcidx):
+    pass
+
+class Entry(ExtRegistryEntry):
+    _about_ = get_methodname
+    s_result_annotation = annmodel.SomeObject()
+
+    def specialize_call(self, hop):
+        v_idx, = hop.inputargs(*hop.args_r)
+        v_res = hop.llops.gencapicall('postsetup_get_methodname', [v_idx],
+                                      resulttype=robject.pyobj_repr)
+        return v_res
+
+def build_method(funcidx):
+    pass
+
+class Entry(ExtRegistryEntry):
+    _about_ = build_method
+    s_result_annotation = annmodel.SomeObject()
+
+    def specialize_call(self, hop):
+        v_idx, v_type = hop.inputargs(*hop.args_r)
+        v_res = hop.llops.gencapicall('postsetup_build_method', [v_idx, v_type],
+                                      resulttype=robject.pyobj_repr)
+        return v_res
+
+def get_typedict(cls):
+    pass
+
+class Entry(ExtRegistryEntry):
+    _about_ = get_typedict
+    s_result_annotation = annmodel.SomeObject()
+
+    def specialize_call(self, hop):
+        v_type, = hop.inputargs(*hop.args_r)
+        v_res = hop.llops.gencapicall('postsetup_get_typedict', [v_type],
+                                      resulttype=robject.pyobj_repr)
+        return v_res
+
+def __init__(mod):
     import types
-    m = types.ModuleType(modname)
-    allobjs = mod.__dict__.values()
-    funcs = eval('[]') # or import list from __builtin__
-    # one alternative
-    #bltn = BuiltinHelper()
-    # less code:
     import __builtin__ as bltn
-    if P:print bltn.list('hallo')
-    #from twisted.internet import reactor    
-    #print dir(reactor)
-    #whow this works
-    isinstance = eval('isinstance')
-    # above is possible, this is probably a better compromise:
+    hasattr = bltn.hasattr
     isinstance = bltn.isinstance
-    for obj in allobjs:
-        if isinstance(obj, types.BuiltinFunctionType):
-            funcs.append( (obj.__name__, obj) )
-    if P:print 'funcs=', funcs
-    if P:print funcs[3:]
-    #funcs += [2, 3, 5]
-    # not yet
-    stuff = bltn.range(10)
-    if P:print stuff[3:]
-    if P:print stuff[:3]
-    if P:print stuff[3:7]
-    if P:print stuff[:-1]
-    funcs.sort()
-    return m
-
+    classes = []
+    x = 0
+    for name in mod.__all__:
+        obj = getattr(mod, name)
+        if isinstance(obj, type) and hasattr(obj, '__self__'):
+            classes.append(obj)
+    idx = 0
+    while 1:
+        name = get_methodname(idx)
+        if not name:
+            break
+        func = getattr(mod, name)
+        for cls in classes:
+            dic = get_typedict(cls)
+            for methname, value in dic.items():
+                if func is value:
+                    meth = build_method(idx, cls)
+                    dic[methname] = meth
+        idx += 1
 
 # creating an object, wrapping, unwrapping, call function, check whether __del__ is called
 def test_wrap_call_dtor():
@@ -281,7 +316,7 @@
 # exposing and using classes from a generasted extension module
 def test_expose_classes():
     m = get_compiled_module(democlass_helper2, use_boehm=not True, exports=[
-        DemoClass, DemoSubclass, DemoNotAnnotated, setup_new_module])
+        DemoClass, DemoSubclass, DemoNotAnnotated, __init__])
     obj = m.DemoClass(2, 3)
     res = obj.demo()
     assert res == DemoClass(2, 3).demo()

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	Thu Apr 27 09:55:16 2006
@@ -208,7 +208,7 @@
 			</File>
 		</Filter>
 		<File
-			RelativePath="..\..\..\..\..\..\..\Documents and Settings\ctismer\Local Settings\Temp\usession-2331\testing_1\testing_1.c">
+			RelativePath="..\..\..\..\..\..\..\Documents and Settings\ctismer\Local Settings\Temp\usession-2434\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	Thu Apr 27 09:55:16 2006
@@ -13,7 +13,7 @@
 
 ALWAYS_INLINE = False
 
-def gen_wrapper(func, translator, newname=None):
+def gen_wrapper(func, translator, newname=None, as_method=False):
     """generate a wrapper function for 'func' that can be put in a
     PyCFunction object.  The wrapper has signature
 
@@ -63,6 +63,9 @@
     varguments = []
     varnames = func.func_code.co_varnames
     func_defaults = func.func_defaults or ()
+    if as_method:
+        nb_positional_args -= 1
+        varnames = varnames[1:]
     for i in range(nb_positional_args):
         # "argument_i = decode_arg(fname, i, name, vargs, vkwds)"  or
         # "argument_i = decode_arg_def(fname, i, name, vargs, vkwds, default)"
@@ -102,6 +105,8 @@
 
     # use the rtyper to produce the conversions
     inputargs = f._obj.graph.getargs()
+    if as_method:
+        varguments.insert(0, vself)
     for i in range(len(varguments)):
         if FUNCTYPE.ARGS[i] != PyObjPtr:
             # "argument_i = type_conversion_operations(argument_i)"



More information about the Pypy-commit mailing list