[pypy-svn] r23017 - pypy/dist/pypy/interpreter
pedronis at codespeak.net
pedronis at codespeak.net
Sat Feb 4 02:28:55 CET 2006
Author: pedronis
Date: Sat Feb 4 02:28:54 2006
New Revision: 23017
Modified:
pypy/dist/pypy/interpreter/gateway.py
Log:
use fastcall paths for functions needing unwrapping too. This improve quite a bit
test_call_sin (3x->2x) and test_count_in_slot
Some logic to not do this too eagerly. There's still likely some bloat, and duplication
of code between the fastfunc and the builtin frame. This needs further consideration.
Modified: pypy/dist/pypy/interpreter/gateway.py
==============================================================================
--- pypy/dist/pypy/interpreter/gateway.py (original)
+++ pypy/dist/pypy/interpreter/gateway.py Sat Feb 4 02:28:54 2006
@@ -224,6 +224,52 @@
emit_sig.through_scope_w += 1
emit_sig.run_args.append("self.%s_arg%d" % (name,cur))
+ # unwrapping code for fastfunc argument handling
+
+ def fastfunc_unwrap(self, el, info):
+ self.dispatch("fastfunc_unwrap", el, None, info)
+
+ def fastfunc_unwrap_function(self, (func, cls), ignore, info):
+ raise FastFuncNotSupported
+
+ def fastfunc_unwrap__Wrappable(self, el, ignore, info):
+ name = el.__name__
+ cur = info.narg
+ info.unwrap.append("space.interp_w(%s, w%d)" % (name, cur))
+ info.miniglobals[name] = el
+ info.narg += 1
+
+ def fastfunc_unwrap__ObjSpace(self, el, ignore, info):
+ if info.index != 0:
+ raise FastFuncNotSupported
+ info.unwrap.append("space")
+
+ def fastfunc_unwrap__W_Root(self, el, ignore, info):
+ cur = info.narg
+ info.unwrap.append("w%d" % cur)
+ info.narg += 1
+
+ def fastfunc_unwrap__Arguments(self, el, ignore, info):
+ raise FastFuncNotSupported
+
+ def fastfunc_unwrap_starargs(self, el, ignore, info):
+ raise FastFuncNotSupported
+
+ def fastfunc_unwrap_args_w(self, el, ignore, info):
+ raise FastFuncNotSupported
+
+ def fastfunc_unwrap_w_args(self, el, ignore, info):
+ raise FastFuncNotSupported
+
+ def fastfunc_unwrap__object(self, el, ignore, info):
+ if el not in (int, str, float):
+ assert False, "unsupported basic type in uwnrap_spec"
+ name = el.__name__
+ cur = info.narg
+ info.unwrap.append("space.%s_w(w%d)" % (name,cur))
+ info.narg +=1
+
+
class BuiltinFrame(eval.Frame):
"Frame emulation for BuiltinCode."
# Subclasses of this are defined with the function to delegate to attached through miniglobals.
@@ -356,7 +402,46 @@
BuiltinCodeSignature(name=name, unwrap_spec=unwrap_spec))
return emit_sig.make_frame_factory(func)
+class FastFuncNotSupported(Exception):
+ pass
+class FastFuncInfo(object):
+ def __init__(self):
+ self.index = 0
+ self.narg = 0
+ self.unwrap = []
+ self.miniglobals = {}
+
+def make_fastfunc(func, unwrap_spec):
+ info = FastFuncInfo()
+ recipe = UnwrapSpecRecipe().fastfunc_unwrap
+ for el in unwrap_spec:
+ recipe(el, info)
+ info.index += 1
+ if info.narg > 4:
+ raise FastFuncNotSupported
+ args = ['space'] + ['w%d' % n for n in range(info.narg)]
+ if args == info.unwrap:
+ fastfunc = func
+ else:
+ # try to avoid excessive bloat
+ if func.__module__ == 'pypy.interpreter.astcompiler.ast':
+ raise FastFuncNotSupported
+ if (not func.__module__.startswith('pypy.module.__builtin__') and
+ not func.__module__.startswith('pypy.module.sys') and
+ not func.__module__.startswith('pypy.module.math')):
+ if not func.__name__.startswith('descr'):
+ raise FastFuncNotSupported
+ d = {}
+ info.miniglobals['func'] = func
+ source = """if 1:
+ def fastfunc_%s_%d(%s):
+ return func(%s)
+ \n""" % (func.__name__, info.narg, ', '.join(args), ', '.join(info.unwrap))
+ exec compile2(source) in info.miniglobals, d
+ fastfunc = d['fastfunc_%s_%d' % (func.__name__, info.narg)]
+ return info.narg, fastfunc
+
class BuiltinCode(eval.Code):
"The code object implementing a built-in (interpreter-level) hook."
hidden_applevel = True
@@ -417,21 +502,15 @@
self.framefactory = make_builtin_frame_factory(func, orig_sig, unwrap_spec)
# speed hack
- if unwrap_spec == [ObjSpace]:
- self.__class__ = BuiltinCode0
- self.fastfunc_0 = func
- 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
- elif unwrap_spec == [ObjSpace, W_Root, W_Root, W_Root, W_Root]:
- self.__class__ = BuiltinCode4
- self.fastfunc_4 = func
+ if 0 <= len(unwrap_spec) <= 5:
+ try:
+ arity, fastfunc = make_fastfunc(func, unwrap_spec)
+ except FastFuncNotSupported:
+ pass
+ 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)
More information about the Pypy-commit
mailing list