Author: Carl Friedrich Bolz <cfb...@gmx.de>
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
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to