[pypy-svn] r34975 - in pypy/branch/builtin-call-speedup: lib-python/modified-2.4.1 pypy/config pypy/interpreter pypy/interpreter/astcompiler pypy/module/__builtin__ pypy/module/__builtin__/test pypy/objspace/std
cfbolz at codespeak.net
cfbolz at codespeak.net
Sat Nov 25 23:39:04 CET 2006
Author: cfbolz
Date: Sat Nov 25 23:38:59 2006
New Revision: 34975
Added:
pypy/branch/builtin-call-speedup/pypy/objspace/std/warydictobject.py
Modified:
pypy/branch/builtin-call-speedup/lib-python/modified-2.4.1/opcode.py
pypy/branch/builtin-call-speedup/pypy/config/pypyoption.py
pypy/branch/builtin-call-speedup/pypy/interpreter/astcompiler/pycodegen.py
pypy/branch/builtin-call-speedup/pypy/interpreter/module.py
pypy/branch/builtin-call-speedup/pypy/interpreter/pycode.py
pypy/branch/builtin-call-speedup/pypy/module/__builtin__/__init__.py
pypy/branch/builtin-call-speedup/pypy/module/__builtin__/test/test_builtin.py
pypy/branch/builtin-call-speedup/pypy/objspace/std/model.py
pypy/branch/builtin-call-speedup/pypy/objspace/std/objspace.py
Log:
first round of trying to make builtin lookups faster (nearly as fast as a local
lookup) while still behaving correctly when builtins are shadowed.
Modified: pypy/branch/builtin-call-speedup/lib-python/modified-2.4.1/opcode.py
==============================================================================
--- pypy/branch/builtin-call-speedup/lib-python/modified-2.4.1/opcode.py (original)
+++ pypy/branch/builtin-call-speedup/lib-python/modified-2.4.1/opcode.py Sat Nov 25 23:38:59 2006
@@ -187,4 +187,7 @@
def_op('EXTENDED_ARG', 143)
EXTENDED_ARG = 143
+# pypy modification, experimental bytecode
+def_op('CALL_LIKELY_BUILTIN', 144) # #args + (#kwargs << 8)
+
del def_op, name_op, jrel_op, jabs_op
Modified: pypy/branch/builtin-call-speedup/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/builtin-call-speedup/pypy/config/pypyoption.py (original)
+++ pypy/branch/builtin-call-speedup/pypy/config/pypyoption.py Sat Nov 25 23:38:59 2006
@@ -59,6 +59,9 @@
"keep track of bytecode usage",
default=False),
+ BoolOption("withfastbuiltins", "speed up calls to builtin functions",
+ default=False, requires=[("objspace.usepycfiles", False)]),
+
BoolOption("usepycfiles", "Write and read pyc files when importing",
default=True),
Modified: pypy/branch/builtin-call-speedup/pypy/interpreter/astcompiler/pycodegen.py
==============================================================================
--- pypy/branch/builtin-call-speedup/pypy/interpreter/astcompiler/pycodegen.py (original)
+++ pypy/branch/builtin-call-speedup/pypy/interpreter/astcompiler/pycodegen.py Sat Nov 25 23:38:59 2006
@@ -30,6 +30,8 @@
TRY_FINALLY = 3
END_FINALLY = 4
+from pypy.module.__builtin__.__init__ import BUILTIN_TO_INDEX
+
def compileFile(filename, display=0):
f = open(filename, 'U')
buf = f.read()
@@ -1005,6 +1007,8 @@
self.emit('EXEC_STMT')
def visitCallFunc(self, node):
+ if self.emit_builtin_call(node):
+ return
pos = 0
kw = 0
self.set_lineno(node)
@@ -1024,6 +1028,35 @@
opcode = callfunc_opcode_info[ have_star*2 + have_dstar]
self.emitop_int(opcode, kw << 8 | pos)
+ def emit_builtin_call(self, node):
+ if not self.space.config.objspace.withfastbuiltins:
+ return False
+ if node.star_args is not None or node.dstar_args is not None:
+ return False
+ pos = 0
+ # check for kw args
+ for arg in node.args:
+ if isinstance(arg, ast.Keyword):
+ return False
+ else:
+ pos = pos + 1
+ func = node.node
+ if not isinstance(func, ast.Name):
+ return False
+
+ name = func.varname
+ scope = self.scope.check_name(name)
+ # YYY
+ index = BUILTIN_TO_INDEX.get(name, -1)
+ if ((scope == SC_GLOBAL or
+ (scope == SC_DEFAULT and self.optimized and self.localsfullyknown))
+ and index != -1):
+ for arg in node.args:
+ arg.accept(self)
+ self.emitop_int("CALL_LIKELY_BUILTIN", index << 8 | pos)
+ return True
+ return False
+
def visitPrint(self, node):
self.set_lineno(node)
if node.dest:
Modified: pypy/branch/builtin-call-speedup/pypy/interpreter/module.py
==============================================================================
--- pypy/branch/builtin-call-speedup/pypy/interpreter/module.py (original)
+++ pypy/branch/builtin-call-speedup/pypy/interpreter/module.py Sat Nov 25 23:38:59 2006
@@ -10,7 +10,7 @@
def __init__(self, space, w_name, w_dict=None):
self.space = space
if w_dict is None:
- w_dict = space.newdict()
+ w_dict = space.newdict(track_builtin_shadowing=True)
self.w_dict = w_dict
self.w_name = w_name
if w_name is not None:
Modified: pypy/branch/builtin-call-speedup/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/builtin-call-speedup/pypy/interpreter/pycode.py (original)
+++ pypy/branch/builtin-call-speedup/pypy/interpreter/pycode.py Sat Nov 25 23:38:59 2006
@@ -51,6 +51,7 @@
NESTED = 1
GENERATOR = 2
+CALLSPECIAL = 4
frame_classes = []
@@ -59,6 +60,8 @@
from pypy.interpreter.pyopcode import PyInterpFrame
from pypy.interpreter.nestedscope import PyNestedScopeFrame
from pypy.interpreter.generator import GeneratorFrameMixin
+ from pypy.interpreter.generator import GeneratorFrameMixin
+ from pypy.interpreter.specialcode import CallLikelyBuiltinMixin
class PyGeneratorFrame(GeneratorFrameMixin, PyInterpFrame):
pass
@@ -66,11 +69,30 @@
class PyNestedScopeGeneratorFrame(GeneratorFrameMixin, PyNestedScopeFrame):
pass
- frame_classes.extend([None]*4)
+ class PyCallSpecialInterpFrame(PyInterpFrame, CallLikelyBuiltinMixin):
+ pass
+
+ class PyCallSpecialNestedScopeFrame(
+ PyNestedScopeFrame, CallLikelyBuiltinMixin):
+ pass
+
+ class PyCallSpecialGeneratorFrame(
+ PyGeneratorFrame, CallLikelyBuiltinMixin):
+ pass
+
+ class PyCallSpecialNestedScopeGeneratorFrame(
+ PyNestedScopeGeneratorFrame, CallLikelyBuiltinMixin):
+ pass
+
+ frame_classes.extend([None] * 8)
frame_classes[0] = PyInterpFrame
frame_classes[NESTED] = PyNestedScopeFrame
frame_classes[GENERATOR] = PyGeneratorFrame
frame_classes[NESTED|GENERATOR] = PyNestedScopeGeneratorFrame
+ frame_classes[CALLSPECIAL] = PyCallSpecialInterpFrame
+ frame_classes[NESTED|CALLSPECIAL] = PyCallSpecialNestedScopeFrame
+ frame_classes[GENERATOR|CALLSPECIAL] = PyCallSpecialGeneratorFrame
+ frame_classes[NESTED|GENERATOR|CALLSPECIAL] = PyCallSpecialNestedScopeGeneratorFrame
class PyCode(eval.Code):
@@ -257,6 +279,8 @@
choose |= NESTED
if self.co_flags & CO_GENERATOR:
choose |= GENERATOR
+ if self.space.config.objspace.withfastbuiltins:
+ choose |= CALLSPECIAL
Frame = frame_classes[choose]
return Frame
Modified: pypy/branch/builtin-call-speedup/pypy/module/__builtin__/__init__.py
==============================================================================
--- pypy/branch/builtin-call-speedup/pypy/module/__builtin__/__init__.py (original)
+++ pypy/branch/builtin-call-speedup/pypy/module/__builtin__/__init__.py Sat Nov 25 23:38:59 2006
@@ -1,6 +1,22 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter import module
-from pypy.interpreter.mixedmodule import MixedModule
+from pypy.interpreter.mixedmodule import MixedModule
+
+# put builtins here that should be optimized somehow
+
+OPTIMIZED_BUILTINS = ["len", "range", "xrange", "min", "max", "enumerate",
+ "isinstance", "type", "zip", "file", "open", "abs", "chr", "unichr",
+ "ord", "pow", "repr", "hash", "oct", "hex", "round", "cmp", "getattr",
+ "setattr", "delattr", "callable", "int", "str", "float"]
+
+assert len(OPTIMIZED_BUILTINS) <= 256
+
+BUILTIN_TO_INDEX = {}
+
+for i, name in enumerate(OPTIMIZED_BUILTINS):
+ BUILTIN_TO_INDEX[name] = i
+
+assert len(OPTIMIZED_BUILTINS) == len(BUILTIN_TO_INDEX)
class Module(MixedModule):
"""Built-in functions, exceptions, and other objects."""
@@ -141,6 +157,9 @@
def setup_after_space_initialization(self):
"""NOT_RPYTHON"""
space = self.space
+ self.builtins_by_index = [None] * len(OPTIMIZED_BUILTINS)
+ for i, name in enumerate(OPTIMIZED_BUILTINS):
+ self.builtins_by_index[i] = space.getattr(self, space.wrap(name))
# call installations for pickle support
for name in self.loaders.keys():
if name.startswith('_install_pickle_support_for_'):
Modified: pypy/branch/builtin-call-speedup/pypy/module/__builtin__/test/test_builtin.py
==============================================================================
--- pypy/branch/builtin-call-speedup/pypy/module/__builtin__/test/test_builtin.py (original)
+++ pypy/branch/builtin-call-speedup/pypy/module/__builtin__/test/test_builtin.py Sat Nov 25 23:38:59 2006
@@ -433,6 +433,38 @@
raises(TypeError, hasattr, x, None)
raises(TypeError, hasattr, x, 42)
+class AppTestBuiltinOptimized(object):
+ def setup_class(cls):
+ from pypy.conftest import gettestobjspace
+ cls.space = gettestobjspace(**{"objspace.withfastbuiltins": True})
+ assert cls.space.config.objspace.withfastbuiltins
+
+ # hum, we need to invoke the compiler explicitely
+ def test_xrange_len(self):
+ s = """def test():
+ x = xrange(33)
+ assert len(x) == 33
+ x = xrange(33.2)
+ assert len(x) == 33
+ x = xrange(33,0,-1)
+ assert len(x) == 33
+ x = xrange(33,0)
+ assert len(x) == 0
+ x = xrange(33,0.2)
+ assert len(x) == 0
+ x = xrange(0,33)
+ assert len(x) == 33
+ x = xrange(0,33,-1)
+ assert len(x) == 0
+ x = xrange(0,33,2)
+ assert len(x) == 17
+ x = xrange(0,32,2)
+ assert len(x) == 16
+ """
+ ns = {}
+ exec s in ns
+ ns["test"]()
+
class TestInternal:
def setup_method(self,method):
Modified: pypy/branch/builtin-call-speedup/pypy/objspace/std/model.py
==============================================================================
--- pypy/branch/builtin-call-speedup/pypy/objspace/std/model.py (original)
+++ pypy/branch/builtin-call-speedup/pypy/objspace/std/model.py Sat Nov 25 23:38:59 2006
@@ -65,6 +65,7 @@
from pypy.objspace.std import dictobject
from pypy.objspace.std import dictstrobject
from pypy.objspace.std import dictmultiobject
+ from pypy.objspace.std import warydictobject
from pypy.objspace.std import stringobject
from pypy.objspace.std import strsliceobject
from pypy.objspace.std import strjoinobject
@@ -109,8 +110,13 @@
self.typeorder[setobject.W_FrozensetObject] = []
self.typeorder[setobject.W_SetIterObject] = []
+ # XXX add to option_to_typename somehow
+ if config.objspace.withfastbuiltins:
+ self.typeorder[warydictobject.W_WaryDictObject] = []
+
imported_but_not_registered = {
dictobject.W_DictObject: True,
+ warydictobject.W_WaryDictObject: True,
dictobject.W_DictIterObject: True,
}
for option, value in config.objspace.std:
Modified: pypy/branch/builtin-call-speedup/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/builtin-call-speedup/pypy/objspace/std/objspace.py (original)
+++ pypy/branch/builtin-call-speedup/pypy/objspace/std/objspace.py Sat Nov 25 23:38:59 2006
@@ -363,7 +363,10 @@
def newlist(self, list_w):
return W_ListObject(list_w)
- def newdict(self):
+ def newdict(self, track_builtin_shadowing=False):
+ if self.config.objspace.withfastbuiltins and track_builtin_shadowing:
+ from pypy.objspace.std.warydictobject import W_WaryDictObject
+ return W_WaryDictObject(self)
return self.DictObjectCls(self)
def newslice(self, w_start, w_end, w_step):
Added: pypy/branch/builtin-call-speedup/pypy/objspace/std/warydictobject.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtin-call-speedup/pypy/objspace/std/warydictobject.py Sat Nov 25 23:38:59 2006
@@ -0,0 +1,43 @@
+
+from pypy.objspace.std.objspace import *
+from pypy.interpreter import gateway
+from pypy.objspace.std.dictobject import W_DictObject
+from pypy.objspace.std.stringobject import W_StringObject
+
+from pypy.rlib.objectmodel import r_dict
+
+class W_WaryDictObject(W_DictObject):
+ def __init__(w_self, space, wary_of=None, w_otherdict=None):
+ from pypy.module.__builtin__.__init__ import BUILTIN_TO_INDEX
+ W_DictObject.__init__(w_self, space, w_otherdict)
+ if wary_of is None:
+ wary_of = BUILTIN_TO_INDEX
+ if w_otherdict is None:
+ w_self.shadowed = [False] * len(wary_of)
+ else:
+ w_self.shadowed = [True] * len(wary_of)
+ w_self.wary_of = wary_of
+
+registerimplementation(W_WaryDictObject)
+
+def setitem__WaryDict_ANY_ANY(space, w_dict, w_key, w_newvalue):
+ if space.is_true(space.isinstance(w_key, space.w_str)):
+ s = space.str_w(w_key)
+ i = w_dict.wary_of.get(s, -1)
+ if i != -1:
+ w_dict.shadowed[i] = True
+ w_dict.content[w_key] = w_newvalue
+
+def delitem__WaryDict_ANY(space, w_dict, w_lookup):
+ try:
+ if space.is_true(space.isinstance(w_lookup, space.w_str)):
+ s = space.str_w(w_lookup)
+ i = w_dict.wary_of.get(s, -1)
+ if i != -1:
+ w_dict.shadowed[i] = False
+ del w_dict.content[w_lookup]
+ except KeyError:
+ raise OperationError(space.w_KeyError, w_lookup)
+
+from pypy.objspace.std import dicttype
+register_all(vars(), dicttype)
More information about the Pypy-commit
mailing list