[pypy-svn] r17086 - in pypy/dist/pypy: interpreter objspace

arigo at codespeak.net arigo at codespeak.net
Tue Aug 30 17:08:58 CEST 2005


Author: arigo
Date: Tue Aug 30 17:08:54 2005
New Revision: 17086

Modified:
   pypy/dist/pypy/interpreter/eval.py
   pypy/dist/pypy/interpreter/gateway.py
   pypy/dist/pypy/objspace/descroperation.py
Log:
Enormous speed increase following discussion with Samuele about how incredibly
indirect something like a space.add() between two integers actually is.

This introduces a rather isolated shortcut, which even makes sense when
reading the source of descroperation.py, where the non-shortcut case of
space.get_and_call_function() can be seen as a fall-back for the uncommon
general case.



Modified: pypy/dist/pypy/interpreter/eval.py
==============================================================================
--- pypy/dist/pypy/interpreter/eval.py	(original)
+++ pypy/dist/pypy/interpreter/eval.py	Tue Aug 30 17:08:54 2005
@@ -50,6 +50,10 @@
     def getdocstring(self):
         return None
 
+    fastcall_1 = None
+    fastcall_2 = None
+    fastcall_3 = None
+
 class Frame(Wrappable):
     """A frame is an environment supporting the execution of a code object.
     Abstract base class."""

Modified: pypy/dist/pypy/interpreter/gateway.py
==============================================================================
--- pypy/dist/pypy/interpreter/gateway.py	(original)
+++ pypy/dist/pypy/interpreter/gateway.py	Tue Aug 30 17:08:54 2005
@@ -396,6 +396,17 @@
 
         self.framecls = make_builtin_frame_class(func, orig_sig, unwrap_spec)
 
+        # speed hack
+        if unwrap_spec == [ObjSpace, W_Root]:
+            self.__class__ = BuiltinCode1
+            self.fastfunc_1 = func
+        elif unwrap_spec == [ObjSpace, W_Root, W_Root]:
+            self.__class__ = BuiltinCode2
+            self.fastfunc_2 = func
+        elif unwrap_spec == [ObjSpace, W_Root, W_Root, W_Root]:
+            self.__class__ = BuiltinCode3
+            self.fastfunc_3 = func
+
     def create_frame(self, space, w_globals, closure=None):
         return self.framecls(space, self, w_globals)
 
@@ -405,6 +416,18 @@
     def getdocstring(self):
         return self.docstring
 
+class BuiltinCode1(BuiltinCode):
+    def fastcall_1(self, space, w1):
+        return self.fastfunc_1(space, w1)
+
+class BuiltinCode2(BuiltinCode):
+    def fastcall_2(self, space, w1, w2):
+        return self.fastfunc_2(space, w1, w2)
+
+class BuiltinCode3(BuiltinCode):
+    def fastcall_3(self, space, w1, w2, w3):
+        return self.fastfunc_3(space, w1, w2, w3)
+
 class interp2app(Wrappable):
     """Build a gateway that calls 'f' at interp-level."""
 

Modified: pypy/dist/pypy/objspace/descroperation.py
==============================================================================
--- pypy/dist/pypy/objspace/descroperation.py	(original)
+++ pypy/dist/pypy/objspace/descroperation.py	Tue Aug 30 17:08:54 2005
@@ -80,8 +80,29 @@
             return space.call_args(w_impl, args)
 
     def get_and_call_function(space, w_descr, w_obj, *args_w):
-        args = Arguments(space, list(args_w))
-        return space.get_and_call_args(w_descr, w_obj, args)
+        descr = space.interpclass_w(w_descr)
+        # a special case for performance and to avoid infinite recursion
+        if type(descr) is Function:
+            # the fastcall paths are purely for performance, but the resulting
+            # increase of speed is huge
+            if len(args_w) == 0:
+                fastcall_1 = descr.code.fastcall_1
+                if fastcall_1:
+                    return fastcall_1(space, w_obj)
+            elif len(args_w) == 1:
+                fastcall_2 = descr.code.fastcall_2
+                if fastcall_2:
+                    return fastcall_2(space, w_obj, args_w[0])
+            elif len(args_w) == 2:
+                fastcall_3 = descr.code.fastcall_3
+                if fastcall_3:
+                    return fastcall_3(space, w_obj, args_w[0], args_w[1])
+            args = Arguments(space, list(args_w))
+            return descr.call_args(args.prepend(w_obj))
+        else:
+            args = Arguments(space, list(args_w))
+            w_impl = space.get(w_descr, w_obj)
+            return space.call_args(w_impl, args)
 
     def call_args(space, w_obj, args):
         # a special case for performance



More information about the Pypy-commit mailing list