[pypy-svn] r65360 - in pypy/branch/speedup-global2/pypy: config interpreter objspace objspace/fake objspace/std objspace/std/test translator/microbench
cfbolz at codespeak.net
cfbolz at codespeak.net
Fri May 22 18:53:15 CEST 2009
Author: cfbolz
Date: Fri May 22 18:53:13 2009
New Revision: 65360
Added:
pypy/branch/speedup-global2/pypy/objspace/std/celldict.py (contents, props changed)
pypy/branch/speedup-global2/pypy/objspace/std/test/test_celldict.py (contents, props changed)
Modified:
pypy/branch/speedup-global2/pypy/config/pypyoption.py
pypy/branch/speedup-global2/pypy/interpreter/module.py
pypy/branch/speedup-global2/pypy/interpreter/pycode.py
pypy/branch/speedup-global2/pypy/objspace/fake/objspace.py
pypy/branch/speedup-global2/pypy/objspace/reflective.py
pypy/branch/speedup-global2/pypy/objspace/std/dictmultiobject.py
pypy/branch/speedup-global2/pypy/objspace/std/objspace.py
pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictmultiobject.py
pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictobject.py
pypy/branch/speedup-global2/pypy/translator/microbench/test_count1.py
Log:
Port over changes from old speedup-globals branch:
------------------------------------------------------------------------
r62765 | cfbolz | 2009-03-09 17:53:28 +0100 (Mon, 09 Mar 2009) | 3 lines
Changed paths:
A /pypy/branch/speedup-globals (from /pypy/trunk:62764)
A branch to try Armin's and mine newest idea about how to speed up global
lookups.
------------------------------------------------------------------------
r62773 | cfbolz | 2009-03-09 19:02:50 +0100 (Mon, 09 Mar 2009) | 5 lines
Changed paths:
M /pypy/branch/speedup-globals/pypy/config/pypyoption.py
M /pypy/branch/speedup-globals/pypy/interpreter/module.py
M /pypy/branch/speedup-globals/pypy/objspace/fake/objspace.py
M /pypy/branch/speedup-globals/pypy/objspace/reflective.py
M /pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py
M /pypy/branch/speedup-globals/pypy/objspace/std/objspace.py
M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py
M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictobject.py
First step to make global lookups faster: Introduce a special dict
implementation for modules, where every value in the RPython-level dict is a
cell that contains the real value. As long as the "valid" flag on such a cell is
set, it is safe to store the cell somewhere else.
------------------------------------------------------------------------
r62811 | cfbolz | 2009-03-10 16:00:52 +0100 (Tue, 10 Mar 2009) | 2 lines
Changed paths:
A /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py
M /pypy/branch/speedup-globals/pypy/objspace/std/dictmultiobject.py
M /pypy/branch/speedup-globals/pypy/objspace/std/objspace.py
A /pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py
M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_dictmultiobject.py
Actually use the cell-dict stuff to cache global lookups in frames.
------------------------------------------------------------------------
r62816 | cfbolz | 2009-03-10 16:34:17 +0100 (Tue, 10 Mar 2009) | 2 lines
Changed paths:
M /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py
help flow space
------------------------------------------------------------------------
r62819 | cfbolz | 2009-03-10 17:54:44 +0100 (Tue, 10 Mar 2009) | 2 lines
Changed paths:
M /pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py
fix typo
------------------------------------------------------------------------
r62823 | cfbolz | 2009-03-10 17:57:56 +0100 (Tue, 10 Mar 2009) | 2 lines
Changed paths:
M /pypy/branch/speedup-globals/pypy/translator/benchmark/benchmarks.py
fix gadfly
------------------------------------------------------------------------
r62827 | cfbolz | 2009-03-10 19:07:12 +0100 (Tue, 10 Mar 2009) | 4 lines
Changed paths:
M /pypy/branch/speedup-globals/pypy/interpreter/pycode.py
M /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py
It turns out that using one additional dict lookup per call negates many of the
benefits of this optimization. Therefore, attach the cache to the code object
directly.
------------------------------------------------------------------------
r62830 | cfbolz | 2009-03-10 20:38:30 +0100 (Tue, 10 Mar 2009) | 2 lines
Changed paths:
M /pypy/branch/speedup-globals/pypy/translator/microbench/test_count1.py
two more microbenchmarks
------------------------------------------------------------------------
r62845 | cfbolz | 2009-03-11 11:54:45 +0100 (Wed, 11 Mar 2009) | 2 lines
Changed paths:
M /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py
M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py
get rid of invalid flag
------------------------------------------------------------------------
r62856 | cfbolz | 2009-03-11 13:16:33 +0100 (Wed, 11 Mar 2009) | 2 lines
Changed paths:
M /pypy/branch/speedup-globals/pypy/objspace/std/celldict.py
M /pypy/branch/speedup-globals/pypy/objspace/std/test/test_celldict.py
fix a corner-case
------------------------------------------------------------------------
Modified: pypy/branch/speedup-global2/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/speedup-global2/pypy/config/pypyoption.py (original)
+++ pypy/branch/speedup-global2/pypy/config/pypyoption.py Fri May 22 18:53:13 2009
@@ -228,6 +228,13 @@
"use dictionaries optimized for flexibility",
default=False),
+ BoolOption("withcelldict",
+ "use dictionaries that are opimized for being used as module dicts",
+ default=False,
+ requires=[("objspace.std.withmultidict", True),
+ ("objspace.opcodes.CALL_LIKELY_BUILTIN", False),
+ ("objspace.honor__builtins__", False)]),
+
BoolOption("withsharingdict",
"use dictionaries that share the keys part",
default=False,
Modified: pypy/branch/speedup-global2/pypy/interpreter/module.py
==============================================================================
--- pypy/branch/speedup-global2/pypy/interpreter/module.py (original)
+++ pypy/branch/speedup-global2/pypy/interpreter/module.py Fri May 22 18:53:13 2009
@@ -11,7 +11,7 @@
def __init__(self, space, w_name, w_dict=None):
self.space = space
if w_dict is None:
- w_dict = space.newdict(track_builtin_shadowing=True)
+ w_dict = space.newdict(module=True)
self.w_dict = w_dict
self.w_name = w_name
if w_name is not None:
Modified: pypy/branch/speedup-global2/pypy/interpreter/pycode.py
==============================================================================
--- pypy/branch/speedup-global2/pypy/interpreter/pycode.py (original)
+++ pypy/branch/speedup-global2/pypy/interpreter/pycode.py Fri May 22 18:53:13 2009
@@ -111,6 +111,10 @@
self._compute_flatcall()
+ if space.config.objspace.std.withcelldict:
+ from pypy.objspace.std.celldict import init_code
+ init_code(self)
+
co_names = property(lambda self: [self.space.unwrap(w_name) for w_name in self.co_names_w]) # for trace
def signature(self):
Modified: pypy/branch/speedup-global2/pypy/objspace/fake/objspace.py
==============================================================================
--- pypy/branch/speedup-global2/pypy/objspace/fake/objspace.py (original)
+++ pypy/branch/speedup-global2/pypy/objspace/fake/objspace.py Fri May 22 18:53:13 2009
@@ -93,7 +93,7 @@
newint = make_dummy()
newlong = make_dummy()
newfloat = make_dummy()
- def newdict(self, track_builtin_shadowing=False):
+ def newdict(self, module=False):
return self.newfloat()
newlist = make_dummy()
emptylist = make_dummy()
Modified: pypy/branch/speedup-global2/pypy/objspace/reflective.py
==============================================================================
--- pypy/branch/speedup-global2/pypy/objspace/reflective.py (original)
+++ pypy/branch/speedup-global2/pypy/objspace/reflective.py Fri May 22 18:53:13 2009
@@ -137,8 +137,8 @@
return None
if opname == "newdict": # grr grr kwargs
- def fn(track_builtin_shadowing=False):
- w_obj = parentfn(track_builtin_shadowing)
+ def fn(module=False):
+ w_obj = parentfn(module)
w_newobj = user_hook(w_obj)
if w_newobj is not None:
return w_newobj
Added: pypy/branch/speedup-global2/pypy/objspace/std/celldict.py
==============================================================================
--- (empty file)
+++ pypy/branch/speedup-global2/pypy/objspace/std/celldict.py Fri May 22 18:53:13 2009
@@ -0,0 +1,248 @@
+from pypy.objspace.std.dictmultiobject import DictImplementation
+from pypy.objspace.std.dictmultiobject import IteratorImplementation
+from pypy.objspace.std.dictmultiobject import W_DictMultiObject, _is_sane_hash
+
+class ModuleCell(object):
+ def __init__(self, w_value=None):
+ self.w_value = w_value
+
+ def invalidate(self):
+ w_value = self.w_value
+ self.w_value = None
+ return w_value
+
+ def __repr__(self):
+ return "<ModuleCell: %s>" % (self.w_value, )
+
+class ModuleDictImplementation(DictImplementation):
+ def __init__(self, space):
+ self.space = space
+ self.content = {}
+ self.unshadowed_builtins = {}
+
+ def getcell(self, key, make_new=True):
+ try:
+ return self.content[key]
+ except KeyError:
+ if not make_new:
+ raise
+ result = self.content[key] = ModuleCell()
+ return result
+
+ def add_unshadowed_builtin(self, name, builtin_impl):
+ assert isinstance(builtin_impl, ModuleDictImplementation)
+ self.unshadowed_builtins[name] = builtin_impl
+
+ def invalidate_unshadowed_builtin(self, name):
+ impl = self.unshadowed_builtins[name]
+ try:
+ cell = impl.content[name]
+ except KeyError:
+ pass
+ else:
+ w_value = cell.invalidate()
+ cell = impl.content[name] = ModuleCell(w_value)
+
+ def setitem(self, w_key, w_value):
+ space = self.space
+ if space.is_w(space.type(w_key), space.w_str):
+ return self.setitem_str(w_key, w_value)
+ else:
+ return self._as_rdict().setitem(w_key, w_value)
+
+ def setitem_str(self, w_key, w_value, shadows_type=True):
+ name = self.space.str_w(w_key)
+ self.getcell(name).w_value = w_value
+
+ if name in self.unshadowed_builtins:
+ self.invalidate_unshadowed_builtin(name)
+ del self.unshadowed_builtins[name]
+
+ 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)
+ cell = self.getcell(key, False)
+ cell.invalidate()
+ del self.content[key]
+ return self
+ elif _is_sane_hash(space, w_key_type):
+ raise KeyError
+ else:
+ return self._as_rdict().delitem(w_key)
+
+ def length(self):
+ return len(self.content)
+
+ def get(self, w_lookup):
+ space = self.space
+ w_lookup_type = space.type(w_lookup)
+ if space.is_w(w_lookup_type, space.w_str):
+ try:
+ return self.getcell(space.str_w(w_lookup), False).w_value
+ except KeyError:
+ return None
+ elif _is_sane_hash(space, w_lookup_type):
+ return None
+ else:
+ return self._as_rdict().get(w_lookup)
+
+ def iteritems(self):
+ return ModuleDictItemIteratorImplementation(self.space, self)
+
+ def iterkeys(self):
+ return ModuleDictKeyIteratorImplementation(self.space, self)
+
+ def itervalues(self):
+ return ModuleDictValueIteratorImplementation(self.space, self)
+
+ def keys(self):
+ space = self.space
+ return [space.wrap(key) for key in self.content.iterkeys()]
+
+ def values(self):
+ return [cell.w_value for cell in self.content.itervalues()]
+
+ def items(self):
+ space = self.space
+ return [space.newtuple([space.wrap(key), cell.w_value])
+ for (key, cell) in self.content.iteritems()]
+
+ def _as_rdict(self):
+ newimpl = self.space.DefaultDictImpl(self.space)
+ for k, cell in self.content.iteritems():
+ newimpl.setitem(self.space.wrap(k), cell.w_value)
+ cell.invalidate()
+ for k in self.unshadowed_builtins:
+ self.invalidate_unshadowed_builtin(k)
+ return newimpl
+
+# grrrrr. just a copy-paste from StrKeyIteratorImplementation in dictmultiobject
+class ModuleDictKeyIteratorImplementation(IteratorImplementation):
+ def __init__(self, space, dictimplementation):
+ IteratorImplementation.__init__(self, space, dictimplementation)
+ self.iterator = dictimplementation.content.iterkeys()
+
+ def next_entry(self):
+ # note that this 'for' loop only runs once, at most
+ for key in self.iterator:
+ return self.space.wrap(key)
+ else:
+ return None
+
+class ModuleDictValueIteratorImplementation(IteratorImplementation):
+ def __init__(self, space, dictimplementation):
+ IteratorImplementation.__init__(self, space, dictimplementation)
+ self.iterator = dictimplementation.content.itervalues()
+
+ def next_entry(self):
+ # note that this 'for' loop only runs once, at most
+ for cell in self.iterator:
+ return cell.w_value
+ else:
+ return None
+
+class ModuleDictItemIteratorImplementation(IteratorImplementation):
+ def __init__(self, space, dictimplementation):
+ IteratorImplementation.__init__(self, space, dictimplementation)
+ self.iterator = dictimplementation.content.iteritems()
+
+ def next_entry(self):
+ # note that this 'for' loop only runs once, at most
+ for key, cell in self.iterator:
+ return self.space.newtuple([self.space.wrap(key), cell.w_value])
+ else:
+ return None
+
+
+
+
+
+
+
+class State(object):
+ def __init__(self, space):
+ self.space = space
+ self.invalidcell = ModuleCell()
+ self.always_invalid_cache = []
+ self.neverused_dictimpl = ModuleDictImplementation(space)
+
+class GlobalCacheHolder(object):
+ def __init__(self, space):
+ self.cache = None
+ state = space.fromcache(State)
+ self.dictimpl = state.neverused_dictimpl
+
+ def getcache(self, space, code, w_globals):
+ implementation = getimplementation(w_globals)
+ if self.dictimpl is implementation:
+ return self.cache
+ return self.getcache_slow(space, code, w_globals, implementation)
+ getcache._always_inline_ = True
+
+ def getcache_slow(self, space, code, w_globals, implementation):
+ state = space.fromcache(State)
+ if not isinstance(implementation, ModuleDictImplementation):
+ missing_length = max(len(code.co_names_w) - len(state.always_invalid_cache), 0)
+ state.always_invalid_cache.extend([state.invalidcell] * missing_length)
+ cache = state.always_invalid_cache
+ else:
+ cache = [state.invalidcell] * len(code.co_names_w)
+ self.cache = cache
+ self.dictimpl = implementation
+ return cache
+ getcache_slow._dont_inline_ = True
+
+def init_code(code):
+ code.globalcacheholder = GlobalCacheHolder(code.space)
+
+
+def get_global_cache(space, code, w_globals):
+ from pypy.interpreter.pycode import PyCode
+ if not isinstance(code, PyCode):
+ return []
+ holder = code.globalcacheholder
+ return holder.getcache(space, code, w_globals)
+
+def getimplementation(w_dict):
+ if type(w_dict) is W_DictMultiObject:
+ return w_dict.implementation
+ else:
+ return None
+
+def LOAD_GLOBAL(f, nameindex, *ignored):
+ cell = f.cache_for_globals[nameindex]
+ w_value = cell.w_value
+ if w_value is None:
+ # slow path
+ w_value = load_global_fill_cache(f, nameindex)
+ f.pushvalue(w_value)
+LOAD_GLOBAL._always_inline_ = True
+
+def find_cell_from_dict(implementation, name):
+ if isinstance(implementation, ModuleDictImplementation):
+ try:
+ return implementation.getcell(name, False)
+ except KeyError:
+ return None
+ return None
+
+def load_global_fill_cache(f, nameindex):
+ name = f.space.str_w(f.getname_w(nameindex))
+ implementation = getimplementation(f.w_globals)
+ if isinstance(implementation, ModuleDictImplementation):
+ cell = find_cell_from_dict(implementation, name)
+ if cell is None:
+ builtin_impl = getimplementation(f.get_builtin().getdict())
+ cell = find_cell_from_dict(builtin_impl, name)
+ if cell is not None:
+ implementation.add_unshadowed_builtin(name, builtin_impl)
+
+ if cell is not None:
+ f.cache_for_globals[nameindex] = cell
+ return cell.w_value
+ return f._load_global(f.getname_w(nameindex))
+load_global_fill_cache._dont_inline_ = True
Modified: pypy/branch/speedup-global2/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/branch/speedup-global2/pypy/objspace/std/dictmultiobject.py (original)
+++ pypy/branch/speedup-global2/pypy/objspace/std/dictmultiobject.py Fri May 22 18:53:13 2009
@@ -865,7 +865,6 @@
else:
return None
-
import time, py
class DictInfo(object):
@@ -1038,8 +1037,11 @@
class W_DictMultiObject(W_Object):
from pypy.objspace.std.dicttype import dict_typedef as typedef
- def __init__(w_self, space, wary=False, sharing=False):
- if space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary:
+ def __init__(w_self, space, wary=False, sharing=False, module=False):
+ if space.config.objspace.std.withcelldict and wary:
+ from pypy.objspace.std.celldict import ModuleDictImplementation
+ w_self.implementation = ModuleDictImplementation(space)
+ elif 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)
Modified: pypy/branch/speedup-global2/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/speedup-global2/pypy/objspace/std/objspace.py (original)
+++ pypy/branch/speedup-global2/pypy/objspace/std/objspace.py Fri May 22 18:53:13 2009
@@ -72,7 +72,16 @@
# Import all the object types and implementations
self.model = StdTypeModel(self.config)
+ from pypy.objspace.std.celldict import get_global_cache
+
class StdObjSpaceFrame(pyframe.PyFrame):
+ if self.config.objspace.std.withcelldict:
+ def __init__(self, space, code, w_globals, closure):
+ pyframe.PyFrame.__init__(self, space, code, w_globals, closure)
+ self.cache_for_globals = get_global_cache(space, code, w_globals)
+
+ from pypy.objspace.std.celldict import LOAD_GLOBAL
+
if self.config.objspace.std.optimized_int_add:
if self.config.objspace.std.withsmallint:
def BINARY_ADD(f, oparg, *ignored):
@@ -580,8 +589,8 @@
from pypy.objspace.std.listobject import W_ListObject
return W_ListObject(list_w)
- def newdict(self, track_builtin_shadowing=False):
- if self.config.objspace.opcodes.CALL_LIKELY_BUILTIN and track_builtin_shadowing:
+ def newdict(self, module=False):
+ if self.config.objspace.std.withmultidict and module:
from pypy.objspace.std.dictmultiobject import W_DictMultiObject
return W_DictMultiObject(self, wary=True)
return self.DictObjectCls(self)
Added: pypy/branch/speedup-global2/pypy/objspace/std/test/test_celldict.py
==============================================================================
--- (empty file)
+++ pypy/branch/speedup-global2/pypy/objspace/std/test/test_celldict.py Fri May 22 18:53:13 2009
@@ -0,0 +1,259 @@
+from pypy.conftest import gettestobjspace
+from pypy.objspace.std.celldict import get_global_cache, ModuleCell, ModuleDictImplementation
+from pypy.interpreter import gateway
+
+# this file tests mostly the effects of caching global lookup. The dict
+# implementation itself is tested in test_dictmultiobject.py
+
+
+class AppTestCellDict(object):
+ def setup_class(cls):
+ cls.space = gettestobjspace(**{"objspace.std.withcelldict": True})
+ cls.w_impl_used = cls.space.appexec([], """():
+ import __pypy__
+ def impl_used(obj):
+ assert "ModuleDictImplementation" in __pypy__.internal_repr(obj)
+ return impl_used
+ """)
+ def is_in_cache(space, w_code, w_globals, w_name):
+ name = space.str_w(w_name)
+ cache = get_global_cache(space, w_code, w_globals)
+ index = [space.str_w(w_n) for w_n in w_code.co_names_w].index(name)
+ return space.wrap(cache[index].w_value is not None)
+ is_in_cache = gateway.interp2app(is_in_cache)
+ cls.w_is_in_cache = cls.space.wrap(is_in_cache)
+ stored_builtins = []
+ def rescue_builtins(space):
+ w_dict = space.builtin.getdict()
+ content = {}
+ for key, cell in w_dict.implementation.content.iteritems():
+ newcell = ModuleCell()
+ newcell.w_value = cell.w_value
+ content[key] = newcell
+ stored_builtins.append(content)
+ rescue_builtins = gateway.interp2app(rescue_builtins)
+ cls.w_rescue_builtins = cls.space.wrap(rescue_builtins)
+ def restore_builtins(space):
+ w_dict = space.builtin.getdict()
+ if not isinstance(w_dict.implementation, ModuleDictImplementation):
+ w_dict.implementation = ModuleDictImplementation(space)
+ w_dict.implementation.content = stored_builtins.pop()
+ restore_builtins = gateway.interp2app(restore_builtins)
+ cls.w_restore_builtins = cls.space.wrap(restore_builtins)
+
+ def test_same_code_in_different_modules(self):
+ import sys
+ mod1 = type(sys)("abc")
+ self.impl_used(mod1.__dict__)
+ glob1 = mod1.__dict__
+ mod2 = type(sys)("abc")
+ self.impl_used(mod2.__dict__)
+ glob2 = mod2.__dict__
+ def f():
+ return x + 1
+ code = f.func_code
+ f1 = type(f)(code, glob1)
+ mod1.x = 1
+ assert not self.is_in_cache(code, glob1, "x")
+ assert f1() == 2
+ assert self.is_in_cache(code, glob1, "x")
+ assert f1() == 2
+ assert self.is_in_cache(code, glob1, "x")
+ mod1.x = 2
+ assert f1() == 3
+ assert self.is_in_cache(code, glob1, "x")
+ assert f1() == 3
+ assert self.is_in_cache(code, glob1, "x")
+ f2 = type(f)(code, glob2)
+ mod2.x = 5
+ assert not self.is_in_cache(code, glob2, "x")
+ assert f2() == 6
+ assert self.is_in_cache(code, glob2, "x")
+ assert f2() == 6
+ assert self.is_in_cache(code, glob2, "x")
+ mod2.x = 7
+ assert f2() == 8
+ assert self.is_in_cache(code, glob2, "x")
+ assert f2() == 8
+ assert self.is_in_cache(code, glob2, "x")
+
+ def test_override_builtins(self):
+ import sys, __builtin__
+ mod1 = type(sys)("abc")
+ glob1 = mod1.__dict__
+ self.impl_used(mod1.__dict__)
+ def f():
+ return len(x)
+ code = f.func_code
+ f1 = type(f)(f.func_code, glob1)
+ mod1.x = []
+ assert not self.is_in_cache(code, glob1, "len")
+ assert not self.is_in_cache(code, glob1, "x")
+ assert f1() == 0
+ assert self.is_in_cache(code, glob1, "len")
+ assert self.is_in_cache(code, glob1, "x")
+ assert f1() == 0
+ mod1.x.append(1)
+ assert f1() == 1
+ assert self.is_in_cache(code, glob1, "len")
+ assert self.is_in_cache(code, glob1, "x")
+ mod1.len = lambda x: 15
+ assert not self.is_in_cache(code, glob1, "len")
+ mod1.x.append(1)
+ assert f1() == 15
+ assert self.is_in_cache(code, glob1, "len")
+ assert f1() == 15
+ assert self.is_in_cache(code, glob1, "len")
+ del mod1.len
+ mod1.x.append(1)
+ assert not self.is_in_cache(code, glob1, "len")
+ assert f1() == 3
+ assert self.is_in_cache(code, glob1, "len")
+ assert f1() == 3
+ assert self.is_in_cache(code, glob1, "len")
+ orig_len = __builtins__.len
+ try:
+ __builtins__.len = lambda x: 12
+ mod1.x.append(1)
+ assert self.is_in_cache(code, glob1, "len")
+ assert f1() == 12
+ assert self.is_in_cache(code, glob1, "len")
+ assert f1() == 12
+ assert self.is_in_cache(code, glob1, "len")
+ finally:
+ __builtins__.len = orig_len
+
+ def test_override_builtins2(self):
+ import sys, __builtin__
+ mod1 = type(sys)("abc")
+ glob1 = mod1.__dict__
+ self.impl_used(mod1.__dict__)
+ def f():
+ return l(x)
+ code = f.func_code
+ f1 = type(f)(f.func_code, glob1)
+ mod1.x = []
+ __builtin__.l = len
+ try:
+ assert not self.is_in_cache(code, glob1, "l")
+ assert not self.is_in_cache(code, glob1, "x")
+ assert f1() == 0
+ assert self.is_in_cache(code, glob1, "l")
+ assert self.is_in_cache(code, glob1, "x")
+ assert f1() == 0
+ mod1.x.append(1)
+ assert f1() == 1
+ assert self.is_in_cache(code, glob1, "l")
+ assert self.is_in_cache(code, glob1, "x")
+ del __builtin__.l
+ mod1.l = len
+ mod1.x.append(1)
+ assert not self.is_in_cache(code, glob1, "l")
+ assert f1() == 2
+ assert self.is_in_cache(code, glob1, "l")
+ assert self.is_in_cache(code, glob1, "x")
+ finally:
+ if hasattr(__builtins__, "l"):
+ del __builtins__.l
+
+ def test_generator(self):
+ import sys, __builtin__
+ mod1 = type(sys)("abc")
+ glob1 = mod1.__dict__
+ self.impl_used(mod1.__dict__)
+ def f():
+ yield 1
+ yield x
+ yield len(x)
+ code = f.func_code
+ f1 = type(f)(f.func_code, glob1)
+ mod1.x = []
+ gen = f1()
+ assert not self.is_in_cache(code, glob1, "len")
+ assert not self.is_in_cache(code, glob1, "x")
+ v = gen.next()
+ assert v == 1
+ assert not self.is_in_cache(code, glob1, "len")
+ assert not self.is_in_cache(code, glob1, "x")
+ v = gen.next()
+ assert v is mod1.x
+ assert not self.is_in_cache(code, glob1, "len")
+ assert self.is_in_cache(code, glob1, "x")
+ v = gen.next()
+ assert v == 0
+ assert self.is_in_cache(code, glob1, "len")
+ assert self.is_in_cache(code, glob1, "x")
+
+ def test_degenerate_to_rdict(self):
+ import sys
+ mod1 = type(sys)("abc")
+ self.impl_used(mod1.__dict__)
+ glob1 = mod1.__dict__
+ def f():
+ return x + 1
+ code = f.func_code
+ f1 = type(f)(code, glob1)
+ mod1.x = 1
+ assert not self.is_in_cache(code, glob1, "x")
+ assert f1() == 2
+ assert self.is_in_cache(code, glob1, "x")
+ glob1[1] = 2
+ assert not self.is_in_cache(code, glob1, "x")
+ assert f1() == 2
+ assert not self.is_in_cache(code, glob1, "x")
+
+ def test_degenerate_builtin_to_rdict(self):
+ import sys, __builtin__
+ mod1 = type(sys)("abc")
+ self.impl_used(mod1.__dict__)
+ glob1 = mod1.__dict__
+ def f():
+ return len(x)
+ code = f.func_code
+ f1 = type(f)(code, glob1)
+ mod1.x = [1, 2]
+ assert not self.is_in_cache(code, glob1, "x")
+ assert not self.is_in_cache(code, glob1, "len")
+ assert f1() == 2
+ assert self.is_in_cache(code, glob1, "x")
+ assert self.is_in_cache(code, glob1, "len")
+ self.rescue_builtins()
+ try:
+ __builtin__.__dict__[1] = 2
+ assert not self.is_in_cache(code, glob1, "len")
+ assert f1() == 2
+ assert not self.is_in_cache(code, glob1, "len")
+ finally:
+ self.restore_builtins()
+
+ def test_mapping_as_locals(self):
+ import sys
+ if sys.version_info < (2,5) or not hasattr(sys, 'pypy_objspaceclass'):
+ skip("need CPython 2.5 or PyPy for non-dictionaries in exec statements")
+ class M(object):
+ def __getitem__(self, key):
+ return key
+ def __setitem__(self, key, value):
+ self.result[key] = value
+ m = M()
+ m.result = {}
+ exec "x=m" in {}, m
+ assert m.result == {'x': 'm'}
+ exec "y=n" in m # NOTE: this doesn't work in CPython 2.4
+ assert m.result == {'x': 'm', 'y': 'n'}
+
+ def test_subclass_of_dict_as_locals(self):
+ import sys
+ if sys.version_info < (2,5) or not hasattr(sys, 'pypy_objspaceclass'):
+ skip("need CPython 2.5 or PyPy for non-dictionaries in exec statements")
+ class M(dict):
+ def __getitem__(self, key):
+ return key
+ def __setitem__(self, key, value):
+ dict.__setitem__(self, key, value)
+ m = M()
+ exec "x=m" in {}, m
+ assert m == {'x': 'm'}
+ exec "y=n" in m # NOTE: this doesn't work in CPython 2.4
+ assert m == {'x': 'm', 'y': 'n'}
+
Modified: pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictmultiobject.py
==============================================================================
--- pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictmultiobject.py (original)
+++ pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictmultiobject.py Fri May 22 18:53:13 2009
@@ -3,6 +3,8 @@
W_DictMultiObject, setitem__DictMulti_ANY_ANY, getitem__DictMulti_ANY, \
EmptyDictImplementation, RDictImplementation, StrDictImplementation, \
SmallDictImplementation, SmallStrDictImplementation, MeasuringDictImplementation
+
+from pypy.objspace.std.celldict import ModuleDictImplementation
from pypy.conftest import gettestobjspace
from pypy.objspace.std.test import test_dictobject
@@ -58,6 +60,26 @@
a.__dict__.items() == [("abc", 12)]
+class AppTestModuleDict(object):
+ def setup_class(cls):
+ cls.space = gettestobjspace(**{"objspace.std.withcelldict": True})
+ cls.w_impl_used = cls.space.appexec([], """():
+ import __pypy__
+ def impl_used(obj):
+ assert "ModuleDictImplementation" in __pypy__.internal_repr(obj)
+ return impl_used
+ """)
+
+
+ def test_check_module_uses_module_dict(self):
+ m = type(__builtins__)("abc")
+ self.impl_used(m.__dict__)
+
+ def test_key_not_there(self):
+ d = type(__builtins__)("abc").__dict__
+ raises(KeyError, "d['def']")
+
+
class TestW_DictSmall(test_dictobject.TestW_DictObject):
def setup_class(cls):
@@ -233,3 +255,15 @@
def get_impl(self):
return self.ImplementionClass(self.space, self.string, self.string2)
+
+class TestModuleDictImplementation(TestRDictImplementation):
+ ImplementionClass = ModuleDictImplementation
+ EmptyClass = ModuleDictImplementation
+
+class TestModuleDictImplementationWithBuiltinNames(TestRDictImplementation):
+ ImplementionClass = ModuleDictImplementation
+ EmptyClass = ModuleDictImplementation
+
+ string = "int"
+ string2 = "isinstance"
+
Modified: pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictobject.py
==============================================================================
--- pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictobject.py (original)
+++ pypy/branch/speedup-global2/pypy/objspace/std/test/test_dictobject.py Fri May 22 18:53:13 2009
@@ -489,6 +489,7 @@
FakeSpace.config.objspace.std.withdictmeasurement = False
FakeSpace.config.objspace.std.withsharingdict = False
FakeSpace.config.objspace.std.withsmalldicts = False
+FakeSpace.config.objspace.std.withcelldict = False
FakeSpace.config.objspace.opcodes = Config()
FakeSpace.config.objspace.opcodes.CALL_LIKELY_BUILTIN = False
Modified: pypy/branch/speedup-global2/pypy/translator/microbench/test_count1.py
==============================================================================
--- pypy/branch/speedup-global2/pypy/translator/microbench/test_count1.py (original)
+++ pypy/branch/speedup-global2/pypy/translator/microbench/test_count1.py Fri May 22 18:53:13 2009
@@ -201,3 +201,15 @@
y = y + 1
c += 1
+def test_count_with_True():
+ x = 0
+ n = N
+ while x < n:
+ x = x + True
+
+increment = 1
+def test_count_with_global_increment():
+ x = 0
+ n = N
+ while x < n:
+ x = x + increment
More information about the Pypy-commit
mailing list