Author: Carl Friedrich Bolz <[email protected]>
Branch: value-profiling
Changeset: r79955:4a9ec1573aca
Date: 2015-10-03 15:38 +0100
http://bitbucket.org/pypy/pypy/changeset/4a9ec1573aca/
Log: merge
diff --git a/pypy/interpreter/test/test_valueprof.py
b/pypy/interpreter/test/test_valueprof.py
--- a/pypy/interpreter/test/test_valueprof.py
+++ b/pypy/interpreter/test/test_valueprof.py
@@ -124,3 +124,37 @@
v.see_write(OtherValue())
assert v._vprof_status == SEEN_TOO_MUCH
+def test_write_not_necessary_int():
+ v = ValueProf()
+ assert v._vprof_status == SEEN_NOTHING
+ res = v.see_write(ValueInt(1))
+ assert not res
+ res = v.see_write(ValueInt(1))
+ assert res
+ res = v.see_write(ValueInt(1))
+ assert res
+ res = v.see_write(ValueInt(2))
+ assert not res
+ res = v.see_write(ValueInt(2))
+ assert not res
+ res = v.see_write(Value())
+ assert not res
+
+def test_write_not_necessary_obj():
+ v = ValueProf()
+ assert v._vprof_status == SEEN_NOTHING
+ val = Value()
+ res = v.see_write(val)
+ assert not res
+ res = v.see_write(val)
+ assert res
+ res = v.see_write(val)
+ assert res
+ res = v.see_write(ValueInt(1))
+ assert not res
+ res = v.see_write(ValueInt(2))
+ assert not res
+ res = v.see_write(ValueInt(2))
+ assert not res
+ res = v.see_write(Value())
+ assert not res
diff --git a/pypy/interpreter/valueprof.py b/pypy/interpreter/valueprof.py
--- a/pypy/interpreter/valueprof.py
+++ b/pypy/interpreter/valueprof.py
@@ -29,13 +29,17 @@
raise NotImplementedError("abstract base")
def see_write(self, w_value):
+ """ inform the value profiler of a write. returns False, unless the
+ value is known to be a constant, and w_value that constant (in that
+ case the caller can elide the write to the actual object, if that
+ object already stores a value). """
status = self._vprof_status
if status == SEEN_TOO_MUCH:
- return
+ return False
if w_value is None:
self._vprof_status = SEEN_TOO_MUCH
- return
+ return False
if status == SEEN_NOTHING:
if self.is_int(w_value):
@@ -55,6 +59,8 @@
if self.read_constant_int() != self.get_int_val(w_value):
self._vprof_status = SEEN_CONSTANT_CLASS
self._vprof_const_cls = w_value.__class__
+ else:
+ return True
else:
self._vprof_status = SEEN_TOO_MUCH
elif status == SEEN_CONSTANT_OBJ:
@@ -66,10 +72,13 @@
self._vprof_status = SEEN_CONSTANT_CLASS
else:
self._vprof_status = SEEN_TOO_MUCH
+ else:
+ return True
elif status == SEEN_CONSTANT_CLASS:
cls = self.read_constant_cls()
if cls is not w_value.__class__:
self._vprof_status = SEEN_TOO_MUCH
+ return False
def can_fold_read_int(self):
return self._vprof_status == SEEN_CONSTANT_INT
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -63,10 +63,14 @@
attr = self.find_map_attr(selector)
if attr is None:
return self.terminator._write_terminator(obj, selector, w_value)
- attr.see_write(w_value)
+ write_unnecessary = attr.see_write(w_value)
if not attr.ever_mutated:
attr.ever_mutated = True
- obj._mapdict_write_storage(attr.storageindex, w_value)
+ # if this path is taken, the storage is already filled from the time we
+ # did the map transition. Therefore, if the value profiler says so, we
+ # can not do the write
+ if not write_unnecessary:
+ obj._mapdict_write_storage(attr.storageindex, w_value)
return True
def delete(self, obj, selector):
diff --git a/pypy/objspace/std/test/test_mapdict.py
b/pypy/objspace/std/test/test_mapdict.py
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -397,6 +397,25 @@
assert obj.getdictvalue(space, "a") == a
assert seen == [(a, Value), (a, Value)]
+
+def test_value_profiling_elide_write(monkeypatch):
+ monkeypatch.setattr(jit, "we_are_jitted", lambda : True)
+ class Value(object):
+ pass
+ a = Value()
+ cls = Class()
+ obj = cls.instantiate()
+ a1 = Value()
+ obj.setdictvalue(space, "a", a1)
+ obj = cls.instantiate()
+ obj.setdictvalue(space, "a", a1)
+ storage = obj.storage
+ # replace storage, both reads and writes of a1 should still work
+ obj.storage = None
+ assert obj.getdictvalue(space, "a") is a1
+ obj.setdictvalue(space, "a", a1)
+ assert obj.getdictvalue(space, "a") is a1
+
# ___________________________________________________________
# dict tests
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit