[pypy-svn] r57882 - in pypy/branch/garden-call-code-2/pypy/interpreter: . test
pedronis at codespeak.net
pedronis at codespeak.net
Sat Sep 6 15:04:14 CEST 2008
Author: pedronis
Date: Sat Sep 6 15:04:07 2008
New Revision: 57882
Modified:
pypy/branch/garden-call-code-2/pypy/interpreter/eval.py
pypy/branch/garden-call-code-2/pypy/interpreter/function.py
pypy/branch/garden-call-code-2/pypy/interpreter/pycode.py
pypy/branch/garden-call-code-2/pypy/interpreter/test/test_function.py
Log:
Switch away from having fastcall_* methods on PyCode, calling python functions with more than 4 args is now a bit faster.
Noisy slow downs in some other corners though.
Modified: pypy/branch/garden-call-code-2/pypy/interpreter/eval.py
==============================================================================
--- pypy/branch/garden-call-code-2/pypy/interpreter/eval.py (original)
+++ pypy/branch/garden-call-code-2/pypy/interpreter/eval.py Sat Sep 6 15:04:07 2008
@@ -62,18 +62,6 @@
def funcrun_obj(self, func, w_obj, args):
return self.funcrun(func, args.prepend(w_obj))
-
- # a performance hack (see gateway.BuiltinCode1/2/3 and pycode.PyCode)
- def fastcall_0(self, space, func):
- raise NotImplementedError
- def fastcall_1(self, space, func, w1):
- raise NotImplementedError
- def fastcall_2(self, space, func, w1, w2):
- raise NotImplementedError
- def fastcall_3(self, space, func, w1, w2, w3):
- raise NotImplementedError
- def fastcall_4(self, space, func, w1, w2, w3, w4):
- raise NotImplementedError
class Frame(Wrappable):
"""A frame is an environment supporting the execution of a code object.
Modified: pypy/branch/garden-call-code-2/pypy/interpreter/function.py
==============================================================================
--- pypy/branch/garden-call-code-2/pypy/interpreter/function.py (original)
+++ pypy/branch/garden-call-code-2/pypy/interpreter/function.py Sat Sep 6 15:04:07 2008
@@ -6,11 +6,14 @@
attribute.
"""
+from pypy.rlib.unroll import unrolling_iterable
from pypy.interpreter.error import OperationError
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.eval import Code
from pypy.interpreter.argument import Arguments, ArgumentsFromValuestack
+funccallunrolling = unrolling_iterable(range(4))
+
class Function(Wrappable):
"""A function is a code object captured with some environment:
an object space, a dictionary of globals, default arguments,
@@ -44,24 +47,40 @@
return self.code
def funccall(self, *args_w): # speed hack
+ from pypy.interpreter import gateway
+ from pypy.interpreter.pycode import PyCode
+
code = self.getcode() # hook for the jit
nargs = len(args_w)
fast_natural_arity = code.fast_natural_arity
if nargs == fast_natural_arity:
if nargs == 0:
+ assert isinstance(code, gateway.BuiltinCode0)
return code.fastcall_0(self.space, self)
elif nargs == 1:
+ assert isinstance(code, gateway.BuiltinCode1)
return code.fastcall_1(self.space, self, args_w[0])
elif nargs == 2:
+ assert isinstance(code, gateway.BuiltinCode2)
return code.fastcall_2(self.space, self, args_w[0], args_w[1])
elif nargs == 3:
+ assert isinstance(code, gateway.BuiltinCode3)
return code.fastcall_3(self.space, self, args_w[0],
args_w[1], args_w[2])
elif nargs == 4:
+ assert isinstance(code, gateway.BuiltinCode4)
return code.fastcall_4(self.space, self, args_w[0],
args_w[1], args_w[2], args_w[3])
+ elif (nargs|PyCode.FLATPYCALL) == fast_natural_arity:
+ assert isinstance(code, PyCode)
+ if nargs < 5:
+ new_frame = self.space.createframe(code, self.w_func_globals,
+ self.closure)
+ for i in funccallunrolling:
+ if i < nargs:
+ new_frame.fastlocals_w[i] = args_w[i]
+ return new_frame.run()
elif nargs >= 1 and fast_natural_arity == -1:
- from pypy.interpreter import gateway
assert isinstance(code, gateway.BuiltinCodePassThroughArguments1)
return code.funcrun_obj(self, args_w[0],
Arguments(self.space,
@@ -70,37 +89,33 @@
def funccall_valuestack(self, nargs, frame): # speed hack
from pypy.interpreter import gateway
+ from pypy.interpreter.pycode import PyCode
+
code = self.getcode() # hook for the jit
fast_natural_arity = code.fast_natural_arity
if nargs == fast_natural_arity:
- from pypy.interpreter.pycode import PyCode
- if type(code) is PyCode:
- new_frame = self.space.createframe(code, self.w_func_globals,
- self.closure)
- for i in xrange(nargs):
- w_arg = frame.peekvalue(nargs-1-i)
- new_frame.fastlocals_w[i] = w_arg
- return new_frame.run()
- else:
- if nargs == 0:
- assert isinstance(code, gateway.BuiltinCode0)
- return code.fastcall_0(self.space, self)
- elif nargs == 1:
- assert isinstance(code, gateway.BuiltinCode1)
- return code.fastcall_1(self.space, self, frame.peekvalue(0))
- elif nargs == 2:
- assert isinstance(code, gateway.BuiltinCode2)
- return code.fastcall_2(self.space, self, frame.peekvalue(1),
- frame.peekvalue(0))
- elif nargs == 3:
- assert isinstance(code, gateway.BuiltinCode3)
- return code.fastcall_3(self.space, self, frame.peekvalue(2),
- frame.peekvalue(1), frame.peekvalue(0))
- elif nargs == 4:
- assert isinstance(code, gateway.BuiltinCode4)
- return code.fastcall_4(self.space, self, frame.peekvalue(3),
- frame.peekvalue(2), frame.peekvalue(1),
- frame.peekvalue(0))
+ if nargs == 0:
+ assert isinstance(code, gateway.BuiltinCode0)
+ return code.fastcall_0(self.space, self)
+ elif nargs == 1:
+ assert isinstance(code, gateway.BuiltinCode1)
+ return code.fastcall_1(self.space, self, frame.peekvalue(0))
+ elif nargs == 2:
+ assert isinstance(code, gateway.BuiltinCode2)
+ return code.fastcall_2(self.space, self, frame.peekvalue(1),
+ frame.peekvalue(0))
+ elif nargs == 3:
+ assert isinstance(code, gateway.BuiltinCode3)
+ return code.fastcall_3(self.space, self, frame.peekvalue(2),
+ frame.peekvalue(1), frame.peekvalue(0))
+ elif nargs == 4:
+ assert isinstance(code, gateway.BuiltinCode4)
+ return code.fastcall_4(self.space, self, frame.peekvalue(3),
+ frame.peekvalue(2), frame.peekvalue(1),
+ frame.peekvalue(0))
+ elif (nargs|PyCode.FLATPYCALL) == fast_natural_arity:
+ assert isinstance(code, PyCode)
+ return self._flat_pycall(code, nargs, frame)
elif fast_natural_arity == -1 and nargs >= 1:
assert isinstance(code, gateway.BuiltinCodePassThroughArguments1)
w_obj = frame.peekvalue(nargs-1)
@@ -118,6 +133,15 @@
if isinstance(args, ArgumentsFromValuestack):
args.frame = None
+ def _flat_pycall(self, code, nargs, frame):
+ # code is a PyCode
+ new_frame = self.space.createframe(code, self.w_func_globals,
+ self.closure)
+ for i in xrange(nargs):
+ w_arg = frame.peekvalue(nargs-1-i)
+ new_frame.fastlocals_w[i] = w_arg
+ return new_frame.run()
+
def getdict(self):
if self.w_func_dict is None:
self.w_func_dict = self.space.newdict()
Modified: pypy/branch/garden-call-code-2/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/garden-call-code-2/pypy/interpreter/pycode.py (original)
+++ pypy/branch/garden-call-code-2/pypy/interpreter/pycode.py Sat Sep 6 15:04:07 2008
@@ -108,7 +108,7 @@
self._args_as_cellvars.append(-1) # pad
self._args_as_cellvars[i] = j
- self._compute_fastcall()
+ self._compute_flatcall()
co_names = property(lambda self: [self.space.unwrap(w_name) for w_name in self.co_names_w]) # for trace
@@ -159,51 +159,20 @@
freevars, cellvars, hidden_applevel)
_code_new_w = staticmethod(_code_new_w)
+
+ FLATPYCALL = 0x100
- def _compute_fastcall(self):
+ def _compute_flatcall(self):
# Speed hack!
self.fast_natural_arity = -99
if self.co_flags & (CO_VARARGS | CO_VARKEYWORDS):
return
if len(self._args_as_cellvars) > 0:
return
-
- self.fast_natural_arity = self.co_argcount
-
- def fastcall_0(self, space, w_func):
- frame = space.createframe(self, w_func.w_func_globals,
- w_func.closure)
- return frame.run()
-
- def fastcall_1(self, space, w_func, w_arg):
- frame = space.createframe(self, w_func.w_func_globals,
- w_func.closure)
- frame.fastlocals_w[0] = w_arg # frame.setfastscope([w_arg])
- return frame.run()
-
- def fastcall_2(self, space, w_func, w_arg1, w_arg2):
- frame = space.createframe(self, w_func.w_func_globals,
- w_func.closure)
- frame.fastlocals_w[0] = w_arg1 # frame.setfastscope([w_arg])
- frame.fastlocals_w[1] = w_arg2
- return frame.run()
-
- def fastcall_3(self, space, w_func, w_arg1, w_arg2, w_arg3):
- frame = space.createframe(self, w_func.w_func_globals,
- w_func.closure)
- frame.fastlocals_w[0] = w_arg1 # frame.setfastscope([w_arg])
- frame.fastlocals_w[1] = w_arg2
- frame.fastlocals_w[2] = w_arg3
- return frame.run()
-
- def fastcall_4(self, space, w_func, w_arg1, w_arg2, w_arg3, w_arg4):
- frame = space.createframe(self, w_func.w_func_globals,
- w_func.closure)
- frame.fastlocals_w[0] = w_arg1 # frame.setfastscope([w_arg])
- frame.fastlocals_w[1] = w_arg2
- frame.fastlocals_w[2] = w_arg3
- frame.fastlocals_w[3] = w_arg4
- return frame.run()
+ if self.co_argcount > 0xff:
+ return
+
+ self.fast_natural_arity = PyCode.FLATPYCALL | self.co_argcount
def funcrun(self, func, args):
frame = self.space.createframe(self, func.w_func_globals,
Modified: pypy/branch/garden-call-code-2/pypy/interpreter/test/test_function.py
==============================================================================
--- pypy/branch/garden-call-code-2/pypy/interpreter/test/test_function.py (original)
+++ pypy/branch/garden-call-code-2/pypy/interpreter/test/test_function.py Sat Sep 6 15:04:07 2008
@@ -474,7 +474,7 @@
code = PyCode._from_code(self.space, f.func_code)
fn = Function(self.space, code, self.space.newdict())
- assert fn.code.fast_natural_arity == i
+ assert fn.code.fast_natural_arity == i|PyCode.FLATPYCALL
if i < 5:
def bomb(*args):
@@ -488,7 +488,7 @@
check = space.is_true(space.eq(w_res, space.wrap(res)))
assert check
- def test_fastcall(self):
+ def test_flatcall(self):
space = self.space
def f(a):
@@ -496,7 +496,7 @@
code = PyCode._from_code(self.space, f.func_code)
fn = Function(self.space, code, self.space.newdict())
- assert fn.code.fast_natural_arity == 1
+ assert fn.code.fast_natural_arity == 1|PyCode.FLATPYCALL
def bomb(*args):
assert False, "shortcutting should have avoided this"
@@ -515,7 +515,7 @@
assert w_res is w_3
- def test_fastcall_method(self):
+ def test_flatcall_method(self):
space = self.space
def f(self, a):
@@ -523,7 +523,7 @@
code = PyCode._from_code(self.space, f.func_code)
fn = Function(self.space, code, self.space.newdict())
- assert fn.code.fast_natural_arity == 2
+ assert fn.code.fast_natural_arity == 2|PyCode.FLATPYCALL
def bomb(*args):
assert False, "shortcutting should have avoided this"
More information about the Pypy-commit
mailing list