[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