[pypy-svn] r26349 - in pypy/dist/pypy: objspace/cpy objspace/cpy/test translator/goal

arigo at codespeak.net arigo at codespeak.net
Wed Apr 26 09:51:28 CEST 2006


Author: arigo
Date: Wed Apr 26 09:51:25 2006
New Revision: 26349

Modified:
   pypy/dist/pypy/objspace/cpy/ann_policy.py
   pypy/dist/pypy/objspace/cpy/capi.py
   pypy/dist/pypy/objspace/cpy/objspace.py
   pypy/dist/pypy/objspace/cpy/test/test_compile.py
   pypy/dist/pypy/objspace/cpy/wrappable.py
   pypy/dist/pypy/translator/goal/targetdemomodule.py
Log:

* "fastest blinking code of the week": removed the TrampolineEntry
    extregistry hacks for the second time.  Found a robust approach
    to annotate all the generated trampoline functions.

* more CPyObjSpace operations



Modified: pypy/dist/pypy/objspace/cpy/ann_policy.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/ann_policy.py	(original)
+++ pypy/dist/pypy/objspace/cpy/ann_policy.py	Wed Apr 26 09:51:25 2006
@@ -1,6 +1,28 @@
 from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy
+from pypy.annotation.pairtype import pair
 
 class CPyAnnotatorPolicy(PyPyAnnotatorPolicy):
     """Annotation policy to compile CPython extension modules with
     the CPyObjSpace.
     """
+
+    def __init__(self, space):
+        PyPyAnnotatorPolicy.__init__(self, single_space=space)
+        self.spaces = {}
+
+    def no_more_blocks_to_annotate(self, annotator):
+        PyPyAnnotatorPolicy.no_more_blocks_to_annotate(self, annotator)
+
+        # annotate all indirectly reachable call-back functions
+        space = self.single_space
+        pending = {}
+        while True:
+            nb_done = len(pending)
+            pending.update(space.wrap_cache)
+            if len(pending) == nb_done:
+                break
+            for obj, w_obj in pending.items():
+                pair(space, obj).follow_annotations(annotator.bookkeeper,
+                                                    w_obj)
+            # restart this loop: for all we know follow_annotations()
+            # could have found new objects

Modified: pypy/dist/pypy/objspace/cpy/capi.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/capi.py	(original)
+++ pypy/dist/pypy/objspace/cpy/capi.py	Wed Apr 26 09:51:25 2006
@@ -82,6 +82,14 @@
 PyObject_RichCompareBool.argtypes = [W_Object, W_Object, c_int]
 PyObject_RichCompareBool.restype = c_int
 
+PyObject_GetIter = pythonapi.PyObject_GetIter
+PyObject_GetIter.argtypes = [W_Object]
+PyObject_GetIter.restype = W_Object
+
+PyIter_Next = pythonapi.PyIter_Next
+PyIter_Next.argtypes = [W_Object]
+PyIter_Next.restype = W_Object
+
 
 #############################################################
 # ____________________ Sequence Protocol ____________________
@@ -118,6 +126,10 @@
 PyString_InternInPlace.argtypes = [POINTER(W_Object)]
 PyString_InternInPlace.restype = None
 
+PyString_AsString = pythonapi.PyString_AsString
+PyString_AsString.argtypes = [W_Object]
+PyString_AsString.restype = c_char_p
+
 
 ##################################################
 # ____________________ Tuples ____________________

Modified: pypy/dist/pypy/objspace/cpy/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/objspace.py	(original)
+++ pypy/dist/pypy/objspace/cpy/objspace.py	Wed Apr 26 09:51:25 2006
@@ -1,24 +1,26 @@
 from pypy.objspace.cpy.capi import *
 from pypy.annotation.pairtype import pair
 from pypy.interpreter import baseobjspace
+from pypy.interpreter.error import OperationError
 
 
-class CPyObjSpace:
+class CPyObjSpace(baseobjspace.ObjSpace):
     from pypy.objspace.cpy.capi import W_Object
 
-    def __init__(self):
-        self.fromcache = baseobjspace.InternalSpaceCache(self).getorbuild
+    def initialize(self):
+        self.options.geninterp = True
         self.w_int   = W_Object(int)
         self.w_None  = W_Object(None)
         self.w_False = W_Object(False)
         self.w_True  = W_Object(True)
+        self.w_type  = W_Object(type)
+        self.w_Exception     = W_Object(Exception)
+        self.w_StopIteration = W_Object(StopIteration)
         self.wrap_cache = {}
+        self.rev_wrap_cache = {}
 
-    def enter_cache_building_mode(self):
-        pass
-
-    def leave_cache_building_mode(self, val):
-        pass
+    def _freeze_(self):
+        return True
 
     def getbuiltinmodule(self, name):
         return PyImport_ImportModule(name)
@@ -33,6 +35,7 @@
                     import pypy.objspace.cpy.wrappable
                     result = pair(self, x).wrap()
                     self.wrap_cache[x] = result
+                    self.rev_wrap_cache[id(result)] = result, x
                     return result
         if x is None:
             return self.w_None
@@ -47,23 +50,46 @@
         assert isinstance(w_obj, W_Object)
         return w_obj.value
 
+    def finditem(self, w_obj, w_key):
+        try:
+            return self.getitem(w_obj, w_key)
+        except KeyError:   # XXX think about OperationError
+            return None
+
+    def interpclass_w(self, w_obj):
+        try:
+            return self.rev_wrap_cache[id(w_obj)][1]
+        except KeyError:
+            return None
+
+    # __________ operations with a direct CPython equivalent __________
+
     getattr = staticmethod(PyObject_GetAttr)
     getitem = staticmethod(PyObject_GetItem)
     setitem = staticmethod(PyObject_SetItem)
     int_w   = staticmethod(PyInt_AsLong)
+    str_w   = staticmethod(PyString_AsString)
+    iter    = staticmethod(PyObject_GetIter)
 
     def call_function(self, w_callable, *args_w):
         args_w += (None,)
         return PyObject_CallFunctionObjArgs(w_callable, *args_w)
 
-    def _freeze_(self):
-        return True
+    def call_args(self, w_callable, args):
+        args_w, kwds_w = args.unpack()
+        w_args = self.newtuple(args_w)
+        w_kwds = self.newdict([(self.wrap(key), w_value)
+                               for key, w_value in kwds_w.items()])
+        return PyObject_Call(w_callable, w_args, w_kwds)
 
     def new_interned_str(self, s):
         w_s = self.wrap(s)
         PyString_InternInPlace(byref(w_s))
         return w_s
 
+    def newint(self, intval):
+        return PyInt_FromLong(intval)
+
     def newdict(self, items_w):
         w_dict = PyDict_New()
         for w_key, w_value in items_w:
@@ -97,3 +123,16 @@
     def ne_w(self, w1, w2): return PyObject_RichCompareBool(w1, w2, Py_NE) != 0
     def gt_w(self, w1, w2): return PyObject_RichCompareBool(w1, w2, Py_GT) != 0
     def ge_w(self, w1, w2): return PyObject_RichCompareBool(w1, w2, Py_GE) != 0
+
+    def is_w(self, w1, w2):
+        return w1.value is w2.value   # XXX any idea not involving SomeObjects?
+    is_w.allow_someobjects = True
+
+    def is_(self, w1, w2):
+        return self.newbool(self.is_w(w1, w2))
+
+    def next(self, w_obj):
+        w_res = PyIter_Next(w_obj)
+        if not w_res:
+            raise OperationError(self.w_StopIteration, self.w_None)
+        return w_res

Modified: pypy/dist/pypy/objspace/cpy/test/test_compile.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/test/test_compile.py	(original)
+++ pypy/dist/pypy/objspace/cpy/test/test_compile.py	Wed Apr 26 09:51:25 2006
@@ -18,7 +18,7 @@
         return demo.measuretime(space, n, w_callable)
 
     fn = compile(entry_point, [int, CPyObjSpace.W_Object],
-                 annotatorpolicy = CPyAnnotatorPolicy())
+                 annotatorpolicy = CPyAnnotatorPolicy(space))
 
     res = fn(10, long)
     assert isinstance(res, int)
@@ -39,12 +39,12 @@
     def entrypoint(n):
         w_result = space.call_function(w_myfunc, space.wrap(n))
         return space.int_w(w_result)
-    return entrypoint
+    return space, entrypoint
 
 def test_annotate_bltinfunc():
-    entrypoint = maketest()
+    space, entrypoint = maketest()
     t = TranslationContext()
-    a = t.buildannotator(policy=CPyAnnotatorPolicy())
+    a = t.buildannotator(policy=CPyAnnotatorPolicy(space))
     s = a.build_types(entrypoint, [int])
     if conftest.option.view:
         t.view()
@@ -56,10 +56,31 @@
     s = a.binding(graph.getreturnvar())
     assert s.knowntype == CPyObjSpace.W_Object
 
+def test_annotate_indirect():
+    space = CPyObjSpace()
+    func = interp2app(myfunc).__spacebind__(space)
+    bltin = BuiltinFunction(func)
+    w_myfunc = space.wrap(bltin)
+    w_mylist = space.newlist([w_myfunc])
+    def entrypoint():
+        return w_mylist
+    t = TranslationContext()
+    a = t.buildannotator(policy=CPyAnnotatorPolicy(space))
+    s = a.build_types(entrypoint, [])
+    if conftest.option.view:
+        t.view()
+    # 'myfunc' should still have been annotated
+    graph = graphof(t, myfunc)
+    assert len(graph.getargs()) == 2
+    s = a.binding(graph.getargs()[1])
+    assert s.knowntype == CPyObjSpace.W_Object
+    s = a.binding(graph.getreturnvar())
+    assert s.knowntype == CPyObjSpace.W_Object
+
 def test_compile_bltinfunc():
-    entrypoint = maketest()
+    space, entrypoint = maketest()
     fn = compile(entrypoint, [int],
-                 annotatorpolicy = CPyAnnotatorPolicy())
+                 annotatorpolicy = CPyAnnotatorPolicy(space))
     res = fn(-6)
     assert res == -42
 
@@ -75,11 +96,11 @@
         w_result = space.call_function(w_measuretime, space.wrap(n),
                                                       w_callable)
         return space.int_w(w_result)
-    return entrypoint
+    return space, entrypoint
 
 def test_compile_demo():
-    entrypoint = makedemotest()
+    space, entrypoint = makedemotest()
     fn = compile(entrypoint, [int, CPyObjSpace.W_Object],
-                 annotatorpolicy = CPyAnnotatorPolicy())
+                 annotatorpolicy = CPyAnnotatorPolicy(space))
     res = fn(10, complex)
     assert isinstance(res, int)

Modified: pypy/dist/pypy/objspace/cpy/wrappable.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/wrappable.py	(original)
+++ pypy/dist/pypy/objspace/cpy/wrappable.py	Wed Apr 26 09:51:25 2006
@@ -7,10 +7,9 @@
 from pypy.annotation.pairtype import pair, pairtype
 from pypy.objspace.cpy.capi import *
 from pypy.objspace.cpy.objspace import CPyObjSpace
-from pypy.interpreter.function import BuiltinFunction
+from pypy.interpreter.function import Function
 from pypy.interpreter.gateway import BuiltinCode, ObjSpace, W_Root
 from pypy.interpreter.gateway import UnwrapSpecRecipe, Signature
-from pypy.rpython import extregistry
 
 
 class UnwrapSpec_Trampoline(UnwrapSpecRecipe):
@@ -50,11 +49,11 @@
         self.passedargs = []
 
 
-class __extend__(pairtype(CPyObjSpace, BuiltinFunction)):
+class __extend__(pairtype(CPyObjSpace, Function)):
 
     def wrap((space, func)):
         # make a built-in function
-        assert isinstance(func.code, BuiltinCode)
+        assert isinstance(func.code, BuiltinCode)   # XXX
         factory = func.code.framefactory
         bltin = factory.behavior
         unwrap_spec = factory.unwrap_spec
@@ -87,28 +86,14 @@
         exec py.code.Source('\n'.join(sourcelines)).compile() in miniglobals
 
         trampoline = miniglobals['trampoline']
+        trampoline.nb_args = len(tramp.inputargs)
         trampoline.allow_someobjects = True    # annotator hint
-        w_result = W_Object(trampoline)
+        return W_Object(trampoline)
 
-        # override the annotation behavior of 'w_result'
-        # to emulate a call to the trampoline() function at interp-level
-        BaseEntry = extregistry._lookup_cls(w_result)
+    def follow_annotations((space, func), bookkeeper, w_trampoline):
+        from pypy.annotation import model as annmodel
+        trampoline = w_trampoline.value
+        s_trampoline = bookkeeper.immutablevalue(trampoline)
+        args_s = [annmodel.SomeObject()] * trampoline.nb_args
         uniquekey = trampoline
-        nb_args = len(unwrap_spec) - 1
-
-        class TrampolineEntry(BaseEntry):
-            _about_ = w_result
-
-            def compute_annotation(self):
-                from pypy.annotation import model as annmodel
-                from pypy.annotation.bookkeeper import getbookkeeper
-
-                bookkeeper = getbookkeeper()
-                if bookkeeper is not None:   # else probably already rtyping
-                    s_trampoline = bookkeeper.immutablevalue(trampoline)
-                    args_s = [annmodel.SomeObject()]*nb_args
-                    bookkeeper.emulate_pbc_call(uniquekey, s_trampoline,
-                                                args_s)
-                return super(TrampolineEntry, self).compute_annotation()
-
-        return w_result
+        bookkeeper.emulate_pbc_call(uniquekey, s_trampoline, args_s)

Modified: pypy/dist/pypy/translator/goal/targetdemomodule.py
==============================================================================
--- pypy/dist/pypy/translator/goal/targetdemomodule.py	(original)
+++ pypy/dist/pypy/translator/goal/targetdemomodule.py	Wed Apr 26 09:51:25 2006
@@ -1,18 +1,21 @@
-from pypy.module._demo import demo
+from pypy.module._demo import Module, demo
 from pypy.objspace.cpy.ann_policy import CPyAnnotatorPolicy
 from pypy.objspace.cpy.objspace import CPyObjSpace
 import pypy.rpython.rctypes.implementation
 
 
 space = CPyObjSpace()
+Module.appleveldefs.clear()   # XXX! for now
+module = Module(space, space.wrap('_demo'))
+w_moduledict = module.getdict()
 
-def entry_point(n, w_callable):
-    return demo.measuretime(space, n, w_callable)
+def getdict():
+    return w_moduledict
 
 # _____ Define and setup target ___
 
 def target(*args):
-    return entry_point, [int, CPyObjSpace.W_Object], CPyAnnotatorPolicy()
+    return getdict, [], CPyAnnotatorPolicy(space)
 
 
 if __name__ == '__main__':
@@ -22,4 +25,4 @@
     else:
         N = int(sys.argv[1])
     print 'Timing for %d iterations...' % N
-    print entry_point(N, space.W_Object(int)), 'seconds'
+    print demo.measuretime(space, N, space.W_Object(int)), 'seconds'



More information about the Pypy-commit mailing list