[pypy-commit] pypy default: Don't invalidate already-compiled pieces of JIT code when we only
arigo
noreply at buildbot.pypy.org
Wed Jun 25 18:36:40 CEST 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r72226:cc99ff68804a
Date: 2014-06-25 18:36 +0200
http://bitbucket.org/pypy/pypy/changeset/cc99ff68804a/
Log: Don't invalidate already-compiled pieces of JIT code when we only
*add* new global variables, but only if we *change* old globals.
diff --git a/pypy/objspace/std/celldict.py b/pypy/objspace/std/celldict.py
--- a/pypy/objspace/std/celldict.py
+++ b/pypy/objspace/std/celldict.py
@@ -16,7 +16,7 @@
class ModuleCell(W_Root):
- def __init__(self, w_value=None):
+ def __init__(self, w_value):
self.w_value = w_value
def __repr__(self):
@@ -49,17 +49,24 @@
return self.erase({})
def mutated(self):
+ # A mutation means changing an existing key to point to a new value.
+ # A value is either a regular wrapped object, or a ModuleCell if we
+ # detect mutations. It means that each existing key can only trigger
+ # a mutation at most once.
self.version = VersionTag()
- def getdictvalue_no_unwrapping(self, w_dict, key):
+ def dictvalue_no_unwrapping(self, w_dict, key):
# NB: it's important to promote self here, so that self.version is a
# no-op due to the quasi-immutable field
self = jit.promote(self)
- return self._getdictvalue_no_unwrapping_pure(self.version, w_dict, key)
+ return self._dictvalue_no_unwrapping_pure(self.version, w_dict, key)
@jit.elidable_promote('0,1,2')
- def _getdictvalue_no_unwrapping_pure(self, version, w_dict, key):
- return self.unerase(w_dict.dstorage).get(key, None)
+ def _dictvalue_no_unwrapping_pure(self, version, w_dict, key):
+ # may raise KeyError. If it does, then the JIT is prevented from
+ # considering this function as elidable. This is what lets us add
+ # new keys to the dictionary without changing the version.
+ return self.unerase(w_dict.dstorage)[key]
def setitem(self, w_dict, w_key, w_value):
space = self.space
@@ -70,17 +77,20 @@
w_dict.setitem(w_key, w_value)
def setitem_str(self, w_dict, key, w_value):
- cell = self.getdictvalue_no_unwrapping(w_dict, key)
- if isinstance(cell, ModuleCell):
- cell.w_value = w_value
- return
- if cell is not None:
+ try:
+ cell = self.dictvalue_no_unwrapping(w_dict, key)
+ except KeyError:
+ pass
+ else:
+ if isinstance(cell, ModuleCell):
+ cell.w_value = w_value
+ return
# If the new value and the current value are the same, don't
# create a level of indirection, or mutate the version.
if self.space.is_w(w_value, cell):
return
w_value = ModuleCell(w_value)
- self.mutated()
+ self.mutated()
self.unerase(w_dict.dstorage)[key] = w_value
def setdefault(self, w_dict, w_key, w_default):
@@ -130,7 +140,10 @@
return w_dict.getitem(w_key)
def getitem_str(self, w_dict, key):
- cell = self.getdictvalue_no_unwrapping(w_dict, key)
+ try:
+ cell = self.dictvalue_no_unwrapping(w_dict, key)
+ except KeyError:
+ return None
return unwrap_cell(cell)
def w_keys(self, w_dict):
diff --git a/pypy/objspace/std/test/test_celldict.py b/pypy/objspace/std/test/test_celldict.py
--- a/pypy/objspace/std/test/test_celldict.py
+++ b/pypy/objspace/std/test/test_celldict.py
@@ -21,27 +21,27 @@
w_key = self.FakeString(key)
d.setitem(w_key, 1)
v2 = strategy.version
- assert v1 is not v2
+ assert v1 is v2 # doesn't change when adding new keys
assert d.getitem(w_key) == 1
- assert d.strategy.getdictvalue_no_unwrapping(d, key) == 1
+ assert d.strategy.dictvalue_no_unwrapping(d, key) == 1
d.setitem(w_key, 2)
v3 = strategy.version
assert v2 is not v3
assert d.getitem(w_key) == 2
- assert d.strategy.getdictvalue_no_unwrapping(d, key).w_value == 2
+ assert d.strategy.dictvalue_no_unwrapping(d, key).w_value == 2
d.setitem(w_key, 3)
v4 = strategy.version
assert v3 is v4
assert d.getitem(w_key) == 3
- assert d.strategy.getdictvalue_no_unwrapping(d, key).w_value == 3
+ assert d.strategy.dictvalue_no_unwrapping(d, key).w_value == 3
d.delitem(w_key)
v5 = strategy.version
assert v5 is not v4
assert d.getitem(w_key) is None
- assert d.strategy.getdictvalue_no_unwrapping(d, key) is None
+ py.test.raises(KeyError, d.strategy.dictvalue_no_unwrapping, d, key)
def test_same_key_set_twice(self):
strategy = ModuleDictStrategy(space)
@@ -52,7 +52,7 @@
x = object()
d.setitem("a", x)
v2 = strategy.version
- assert v1 is not v2
+ assert v1 is v2
d.setitem("a", x)
v3 = strategy.version
assert v2 is v3
More information about the pypy-commit
mailing list