[pypy-svn] r23018 - pypy/dist/pypy/interpreter

pedronis at codespeak.net pedronis at codespeak.net
Sat Feb 4 03:58:14 CET 2006


Author: pedronis
Date: Sat Feb  4 03:58:10 2006
New Revision: 23018

Modified:
   pypy/dist/pypy/interpreter/argument.py
   pypy/dist/pypy/interpreter/eval.py
   pypy/dist/pypy/interpreter/function.py
   pypy/dist/pypy/interpreter/gateway.py
   pypy/dist/pypy/interpreter/pycode.py
Log:
refactoring: delegate frame creation etc logic to code objects, this enables some optimisations that were not possible
before at all, parsing of arguments was eager which was a serious waste if the target had an __args__ argument.
Use a pass-through logic for those cases.

instance creation microbenchmark goes from 33x slower on my machine to 10x

probably calling of geinterp builtins gains something too.





Modified: pypy/dist/pypy/interpreter/argument.py
==============================================================================
--- pypy/dist/pypy/interpreter/argument.py	(original)
+++ pypy/dist/pypy/interpreter/argument.py	Sat Feb  4 03:58:10 2006
@@ -63,6 +63,9 @@
         "Return a new Arguments with a new argument inserted first."
         return ArgumentsPrepended(self, w_firstarg)
 
+    def popfirst(self):
+        return None, None
+
     def match_signature(self, signature, defaults_w):
         """Parse args and kwargs according to the signature of a code object,
         or raise an ArgErr in case of failure.
@@ -89,6 +92,9 @@
         "Return the first argument for inspection."
         return self.w_firstarg
 
+    def popfirst(self):
+        return self.w_firstarg, self.args
+
     def __repr__(self):
         return 'ArgumentsPrepended(%r, %r)' % (self.args, self.w_firstarg)
 
@@ -151,6 +157,13 @@
             return None
         return self.valuestack.top(self.nargs - 1)
 
+    def popfirst(self):
+        if self.nargs <= 0:
+            return None, None
+        valuestack = self.valuestack
+        newnargs = self.nargs-1
+        return valuestack.top(newnargs), ArgumentsFromValuestack(self.space, valuestack, newnargs)
+        
     def __repr__(self):
         return 'ArgumentsFromValuestack(%r, %r)' % (self.valuestack, self.nargs)
 
@@ -169,7 +182,8 @@
         elif self.nargs < argcount:
             raise ValueError, "not enough arguments (%d expected)" % argcount
         data_w = [None] * self.nargs
-        for i in range(self.nargs):
+        nargs = self.nargs
+        for i in range(nargs):
             data_w[i] = self.valuestack.top(nargs - 1 - i)
         return data_w
 

Modified: pypy/dist/pypy/interpreter/eval.py
==============================================================================
--- pypy/dist/pypy/interpreter/eval.py	(original)
+++ pypy/dist/pypy/interpreter/eval.py	Sat Feb  4 03:58:10 2006
@@ -50,6 +50,15 @@
     def getdocstring(self):
         return None
 
+    def funcrun(self, func, args):
+        frame = self.create_frame(func.space, func.w_func_globals,
+                                  func.closure)
+        sig = self.signature()
+        scope_w = args.parse(func.name, sig, func.defs_w)
+        frame.setfastscope(scope_w)
+        return frame.run()
+
+        
     # a performance hack (see gateway.BuiltinCode1/2/3 and pycode.PyCode)
     def fastcall_0(self, space, func):
         return None

Modified: pypy/dist/pypy/interpreter/function.py
==============================================================================
--- pypy/dist/pypy/interpreter/function.py	(original)
+++ pypy/dist/pypy/interpreter/function.py	Sat Feb  4 03:58:10 2006
@@ -34,20 +34,8 @@
         return "<Function %s>" % self.name
 
     def call_args(self, args):
-        frame = self.code.create_frame(self.space, self.w_func_globals,
-                                       self.closure)
-        sig = self.code.signature()
-        # XXX start of hack for performance
-        if frame.setfastscope is PyFrame.setfastscope:
-            args_matched = args.parse_into_scope(frame.fastlocals_w, self.name,
-                                                 sig, self.defs_w)
-            frame.init_cells(args_matched)
-        # XXX end of hack for performance
-        else:
-            scope_w = args.parse(self.name, sig, self.defs_w)
-            frame.setfastscope(scope_w)
-        return frame.run()
-
+        return self.code.funcrun(self, args) # delegate activation to code
+    
     def funccall(self, *args_w): # speed hack
         if len(args_w) == 0:
             w_res = self.code.fastcall_0(self.space, self)

Modified: pypy/dist/pypy/interpreter/gateway.py
==============================================================================
--- pypy/dist/pypy/interpreter/gateway.py	(original)
+++ pypy/dist/pypy/interpreter/gateway.py	Sat Feb  4 03:58:10 2006
@@ -506,11 +506,16 @@
             try:
                 arity, fastfunc = make_fastfunc(func, unwrap_spec)
             except FastFuncNotSupported:
-                pass
+                if unwrap_spec == [ObjSpace, Arguments]:
+                    self.__class__ = BuiltinCodePassThroughArguments0
+                    self.func__args__ = func
+                elif unwrap_spec == [ObjSpace, W_Root, Arguments]:
+                    self.__class__ = BuiltinCodePassThroughArguments1
+                    self.func__args__ = func
             else:
                 self.__class__ = globals()['BuiltinCode%d' % arity]
                 setattr(self, 'fastfunc_%d' % arity, fastfunc)
- 
+
 
     def create_frame(self, space, w_globals, closure=None):
         return self.framefactory.create(space, self, w_globals)
@@ -524,6 +529,44 @@
 
 # (verbose) performance hack below
 
+class BuiltinCodePassThroughArguments0(BuiltinCode):
+
+    def funcrun(self, func, args):
+        space = func.space
+        try:
+            w_result = self.func__args__(space, args)
+        except KeyboardInterrupt: 
+            raise OperationError(space.w_KeyboardInterrupt, space.w_None) 
+        except MemoryError: 
+            raise OperationError(space.w_MemoryError, space.w_None) 
+        except RuntimeError, e: 
+            raise OperationError(space.w_RuntimeError, 
+                                 space.wrap("internal error: " + str(e))) 
+        if w_result is None:
+            w_result = space.w_None
+        return w_result
+
+class BuiltinCodePassThroughArguments1(BuiltinCode):
+
+    def funcrun(self, func, args):
+        space = func.space
+        w_obj, newargs = args.popfirst()
+        if w_obj is not None:
+            try:
+                w_result = self.func__args__(space, w_obj, newargs)
+            except KeyboardInterrupt: 
+                raise OperationError(space.w_KeyboardInterrupt, space.w_None) 
+            except MemoryError: 
+                raise OperationError(space.w_MemoryError, space.w_None) 
+            except RuntimeError, e: 
+                raise OperationError(space.w_RuntimeError, 
+                                     space.wrap("internal error: " + str(e))) 
+            if w_result is None:
+                w_result = space.w_None
+            return w_result
+        else:
+            return BuiltinCode.funcrun(self, func, args)
+
 class BuiltinCode0(BuiltinCode):
     def fastcall_0(self, space, w_func):
         try:

Modified: pypy/dist/pypy/interpreter/pycode.py
==============================================================================
--- pypy/dist/pypy/interpreter/pycode.py	(original)
+++ pypy/dist/pypy/interpreter/pycode.py	Sat Feb  4 03:58:10 2006
@@ -216,6 +216,16 @@
             return frame.run()
         return None
 
+    def funcrun(self, func, args):
+        frame = self.create_frame(self.space, func.w_func_globals,
+                                  func.closure)
+        sig = self._signature
+        # speed hack
+        args_matched = args.parse_into_scope(frame.fastlocals_w, func.name,
+                                             sig, func.defs_w)
+        frame.init_cells(args_matched)
+        return frame.run()
+
     def create_frame(self, space, w_globals, closure=None):
         "Create an empty PyFrame suitable for this code object."
         # select the appropriate kind of frame



More information about the Pypy-commit mailing list