Author: Carl Friedrich Bolz <cfb...@gmx.de>
Branch: value-profiling
Changeset: r78897:5a064b6c607a
Date: 2015-08-11 16:08 +0200
http://bitbucket.org/pypy/pypy/changeset/5a064b6c607a/

Log:    (arigo, cfbolz): also support value profiling of instance attributes

diff --git a/pypy/interpreter/valueprof.py b/pypy/interpreter/valueprof.py
--- a/pypy/interpreter/valueprof.py
+++ b/pypy/interpreter/valueprof.py
@@ -47,8 +47,12 @@
             if status != SEEN_TOO_MUCH:
                 self._vprof_status = SEEN_TOO_MUCH
         elif status == SEEN_NOTHING:
-            self._vprof_value_wref = ref(value)
-            self._vprof_status = SEEN_OBJ
+            try:
+                self._vprof_value_wref = ref(value)
+                self._vprof_status = SEEN_OBJ
+            except TypeError:
+                # for tests, which really use unwrapped ints in a few places
+                self._vprof_status = SEEN_TOO_MUCH
         elif status == SEEN_INT:
             self._vprof_status = SEEN_TOO_MUCH
         elif status == SEEN_OBJ:
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
@@ -4,6 +4,7 @@
 from rpython.rlib.rarithmetic import intmask, r_uint
 
 from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter import valueprof
 from pypy.objspace.std.dictmultiobject import (
     W_DictMultiObject, DictStrategy, ObjectDictStrategy, BaseKeyIterator,
     BaseValueIterator, BaseItemIterator, _never_equal_to_string
@@ -30,9 +31,17 @@
         self.terminator = terminator
 
     def read(self, obj, selector):
+        from pypy.objspace.std.intobject import W_IntObject
         attr = self.find_map_attr(selector)
         if attr is None:
             return self.terminator._read_terminator(obj, selector)
+        # XXX move to PlainAttribute?
+        if attr.can_fold_read_int():
+            return W_IntObject(attr.read_constant_int())
+        elif attr.can_fold_read_obj():
+            w_res = attr.try_read_constant_obj()
+            if w_res is not None:
+                return w_res
         if (
             jit.isconstant(attr.storageindex) and
             jit.isconstant(obj) and
@@ -50,6 +59,7 @@
         attr = self.find_map_attr(selector)
         if attr is None:
             return self.terminator._write_terminator(obj, selector, w_value)
+        attr.see_write(w_value)
         if not attr.ever_mutated:
             attr.ever_mutated = True
         obj._mapdict_write_storage(attr.storageindex, w_value)
@@ -170,6 +180,7 @@
         # for the benefit of the special subclasses
         obj._set_mapdict_map(attr)
         obj._mapdict_write_storage(attr.storageindex, w_value)
+        attr.see_write(w_value)
 
     def materialize_r_dict(self, space, obj, dict_w):
         raise NotImplementedError("abstract base class")
@@ -274,8 +285,10 @@
             terminator = terminator.devolved_dict_terminator
         return Terminator.set_terminator(self, obj, terminator)
 
+
 class PlainAttribute(AbstractAttribute):
     _immutable_fields_ = ['selector', 'storageindex', 'back', 'ever_mutated?']
+    objectmodel.import_from_mixin(valueprof.ValueProf)
 
     def __init__(self, selector, back):
         AbstractAttribute.__init__(self, back.space, back.terminator)
@@ -284,6 +297,19 @@
         self.back = back
         self._size_estimate = self.length() * NUM_DIGITS_POW2
         self.ever_mutated = False
+        self.init_valueprof()
+
+    # ____________________________________________________________
+    # methods for ValueProf mixin
+    def is_int(self, w_obj):
+        from pypy.objspace.std.intobject import W_IntObject
+        return type(w_obj) is W_IntObject
+
+    def get_int_val(self, w_obj):
+        from pypy.objspace.std.intobject import W_IntObject
+        assert isinstance(w_obj, W_IntObject)
+        return w_obj.intval
+    # ____________________________________________________________
 
     def _copy_attr(self, obj, new_obj):
         w_value = self.read(obj, self.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
@@ -348,6 +348,31 @@
                 obj.setdictvalue(space, a, 50)
         assert c.terminator.size_estimate() in [(i + 10) // 2, (i + 11) // 2]
 
+def test_value_profiling(monkeypatch):
+    class Value:
+        pass
+    a = Value()
+    cls = Class()
+    obj = cls.instantiate()
+    obj.setdictvalue(space, "a", a)
+    obj = cls.instantiate()
+    obj.setdictvalue(space, "a", a)
+    obj.setdictvalue(space, "a", a)
+
+    def _mapdict_read_storage(storageindex):
+        assert 0 # not reached
+
+    obj._mapdict_read_storage = _mapdict_read_storage
+
+    assert obj.getdictvalue(space, "a") == a
+    assert obj.getdictvalue(space, "a") == a
+
+    obj = cls.instantiate()
+    obj.setdictvalue(space, "a", a)
+    obj.setdictvalue(space, "a", Value())
+    assert not obj.map.can_fold_read_obj()
+
+
 # ___________________________________________________________
 # dict tests
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to