[pypy-svn] r35900 - in pypy/dist: lib-python/modified-2.4.1 pypy/config pypy/interpreter pypy/interpreter/astcompiler pypy/module/__builtin__ pypy/module/__builtin__/test pypy/objspace/std
mwh at codespeak.net
mwh at codespeak.net
Tue Dec 19 19:19:45 CET 2006
Author: mwh
Date: Tue Dec 19 19:19:44 2006
New Revision: 35900
Modified:
pypy/dist/lib-python/modified-2.4.1/opcode.py
pypy/dist/pypy/config/pypyoption.py
pypy/dist/pypy/interpreter/astcompiler/pycodegen.py
pypy/dist/pypy/interpreter/module.py
pypy/dist/pypy/interpreter/pyopcode.py
pypy/dist/pypy/module/__builtin__/__init__.py
pypy/dist/pypy/module/__builtin__/test/test_builtin.py
pypy/dist/pypy/objspace/std/dictmultiobject.py
pypy/dist/pypy/objspace/std/objspace.py
Log:
merge builtin-call-speedup-2. gives ~10% on richards, a bit less on pystone.
--objspace-opcodes-CALL_LIKELY_BUILTIN to enable.
Modified: pypy/dist/lib-python/modified-2.4.1/opcode.py
==============================================================================
--- pypy/dist/lib-python/modified-2.4.1/opcode.py (original)
+++ pypy/dist/lib-python/modified-2.4.1/opcode.py Tue Dec 19 19:19:44 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/dist/pypy/config/pypyoption.py
==============================================================================
--- pypy/dist/pypy/config/pypyoption.py (original)
+++ pypy/dist/pypy/config/pypyoption.py Tue Dec 19 19:19:44 2006
@@ -38,6 +38,10 @@
cmdline='--compiler'),
OptionDescription("opcodes", "opcodes to enable in the interpreter", [
+ BoolOption("CALL_LIKELY_BUILTIN", "emit a special bytecode for likely calls to builtin functions",
+ default=False,
+ requires=[("objspace.usepycfiles", False),
+ ("objspace.std.withmultidict", True)])
]),
BoolOption("nofaking", "disallow faking in the object space",
Modified: pypy/dist/pypy/interpreter/astcompiler/pycodegen.py
==============================================================================
--- pypy/dist/pypy/interpreter/astcompiler/pycodegen.py (original)
+++ pypy/dist/pypy/interpreter/astcompiler/pycodegen.py Tue Dec 19 19:19:44 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.opcodes.CALL_LIKELY_BUILTIN:
+ 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/dist/pypy/interpreter/module.py
==============================================================================
--- pypy/dist/pypy/interpreter/module.py (original)
+++ pypy/dist/pypy/interpreter/module.py Tue Dec 19 19:19:44 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/dist/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyopcode.py (original)
+++ pypy/dist/pypy/interpreter/pyopcode.py Tue Dec 19 19:19:44 2006
@@ -874,6 +874,36 @@
def SET_LINENO(f, lineno, *ignored):
pass
+ def CALL_LIKELY_BUILTIN(f, oparg, *ignored):
+ from pypy.module.__builtin__ import OPTIMIZED_BUILTINS, Module
+ from pypy.objspace.std.dictmultiobject import W_DictMultiObject
+ w_globals = f.w_globals
+ num = oparg >> 8
+ assert isinstance(w_globals, W_DictMultiObject)
+ w_value = w_globals.implementation.get_builtin_indexed(num)
+ if w_value is None:
+ w_builtins = f.builtin
+ assert isinstance(w_builtins, Module)
+ w_builtin_dict = w_builtins.w_dict
+ assert isinstance(w_builtin_dict, W_DictMultiObject)
+ w_value = w_builtin_dict.implementation.get_builtin_indexed(num)
+## if w_value is not None:
+## print "CALL_LIKELY_BUILTIN fast"
+ if w_value is None:
+ varname = OPTIMIZED_BUILTINS[num]
+ message = "global name '%s' is not defined" % varname
+ raise OperationError(f.space.w_NameError,
+ f.space.wrap(message))
+ nargs = oparg & 0xff
+ w_function = w_value
+ try:
+ w_result = f.space.call_valuestack(w_function, nargs, f.valuestack)
+ # XXX XXX fix the problem of resume points!
+ #rstack.resume_point("CALL_FUNCTION", f, nargs, returns=w_result)
+ finally:
+ f.valuestack.drop(nargs)
+ f.valuestack.push(w_result)
+
## def EXTENDED_ARG(f, oparg, *ignored):
## opcode = f.nextop()
## oparg = oparg<<16 | f.nextarg()
Modified: pypy/dist/pypy/module/__builtin__/__init__.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/__init__.py (original)
+++ pypy/dist/pypy/module/__builtin__/__init__.py Tue Dec 19 19:19:44 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/dist/pypy/module/__builtin__/test/test_builtin.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/test/test_builtin.py (original)
+++ pypy/dist/pypy/module/__builtin__/test/test_builtin.py Tue Dec 19 19:19:44 2006
@@ -449,6 +449,42 @@
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.opcodes.CALL_LIKELY_BUILTIN": True})
+ assert cls.space.config.objspace.opcodes.CALL_LIKELY_BUILTIN
+
+ # 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"]()
+
+ def test_delete_from_builtins(self):
+ s = """ """
+ # XXX write this test!
+
class TestInternal:
def setup_method(self,method):
Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/dictmultiobject.py (original)
+++ pypy/dist/pypy/objspace/std/dictmultiobject.py Tue Dec 19 19:19:44 2006
@@ -1,6 +1,7 @@
import py
from pypy.objspace.std.objspace import *
from pypy.interpreter import gateway
+from pypy.module.__builtin__.__init__ import BUILTIN_TO_INDEX, OPTIMIZED_BUILTINS
from pypy.rlib.objectmodel import r_dict, we_are_translated
@@ -54,6 +55,7 @@
## def itervalues(self):
## pass
+
def keys(self):
return [w_k for w_k in self.iterkeys()]
def values(self):
@@ -61,6 +63,14 @@
def items(self):
return [(w_key, w_value) or w_key, w_value in self.iteritems()]
+# the following method only makes sense when the option to use the
+# CALL_LIKELY_BUILTIN opcode is set. Otherwise it won't even be seen
+# by the annotator
+ def get_builtin_indexed(self, i):
+ w_key = self.space.wrap(OPTIMIZED_BUILTINS[i])
+ return self.get(w_key)
+
+
class EmptyDictImplementation(DictImplementation):
def __init__(self, space):
self.space = space
@@ -312,8 +322,7 @@
def setitem(self, w_key, w_value):
space = self.space
if space.is_w(space.type(w_key), space.w_str):
- self.content[space.str_w(w_key)] = w_value
- return self
+ return self.setitem_str(w_key, w_value)
else:
return self._as_rdict().setitem(w_key, w_value)
@@ -375,6 +384,37 @@
newimpl.setitem(self.space.wrap(k), w_v)
return newimpl
+class WaryDictImplementation(StrDictImplementation):
+ def __init__(self, space):
+ StrDictImplementation.__init__(self, space)
+ self.shadowed = [None] * len(BUILTIN_TO_INDEX)
+
+ def setitem_str(self, w_key, w_value):
+ key = self.space.str_w(w_key)
+ i = BUILTIN_TO_INDEX.get(key, -1)
+ if i != -1:
+ self.shadowed[i] = w_value
+ self.content[key] = w_value
+ return self
+
+ def delitem(self, w_key):
+ space = self.space
+ w_key_type = space.type(w_key)
+ if space.is_w(w_key_type, space.w_str):
+ key = space.str_w(w_key)
+ del self.content[key]
+ i = BUILTIN_TO_INDEX.get(key, -1)
+ if i != -1:
+ self.shadowed[i] = None
+ return self
+ elif _is_sane_hash(space, w_key_type):
+ raise KeyError
+ else:
+ return self._as_rdict().delitem(w_key)
+
+ def get_builtin_indexed(self, i):
+ return self.shadowed[i]
+
class RDictImplementation(DictImplementation):
def __init__(self, space):
self.space = space
@@ -721,8 +761,10 @@
class W_DictMultiObject(W_Object):
from pypy.objspace.std.dicttype import dict_typedef as typedef
- def __init__(w_self, space, sharing=False):
- if space.config.objspace.std.withdictmeasurement:
+ def __init__(w_self, space, wary=False, sharing=False):
+ if space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary:
+ w_self.implementation = WaryDictImplementation(space)
+ elif space.config.objspace.std.withdictmeasurement:
w_self.implementation = MeasuringDictImplementation(space)
elif space.config.objspace.std.withsharingdict and sharing:
w_self.implementation = SharedDictImplementation(space)
Modified: pypy/dist/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/std/objspace.py (original)
+++ pypy/dist/pypy/objspace/std/objspace.py Tue Dec 19 19:19:44 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.opcodes.CALL_LIKELY_BUILTIN and track_builtin_shadowing:
+ from pypy.objspace.std.dictmultiobject import W_DictMultiObject
+ return W_DictMultiObject(self, wary=True)
return self.DictObjectCls(self)
def newslice(self, w_start, w_end, w_step):
More information about the Pypy-commit
mailing list