Author: Lukas Diekmann <[email protected]>
Branch: type-specialized-instances
Changeset: r49473:c905b06f965f
Date: 2011-11-16 14:17 +0100
http://bitbucket.org/pypy/pypy/changeset/c905b06f965f/

Log:    read attributes only through Attribute class. fixed tests

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
@@ -84,7 +84,6 @@
                 if space.config.objspace.std.withmethodcachecounter:
                     name = selector[0]
                     cache.hits[name] = cache.hits.get(name, 0) + 1
-                # XXX return the correct Attribute here
                 return attr
         attr = self._findmap(selector)
         if attr is None:
@@ -160,7 +159,7 @@
         # the order is important here: first change the map, then the storage,
         # for the benefit of the special subclasses
         obj._set_mapdict_map(attr)
-        obj._mapdict_write_storage(attr.position, w_value)
+        attr.write_attr(obj, w_value) 
#obj._mapdict_write_storage(attr.position, w_value)
 
     def materialize_r_dict(self, space, obj, dict_w):
         raise NotImplementedError("abstract base class")
@@ -280,11 +279,14 @@
 
     def read_attr(self, obj):
         # XXX do the unerasing (and wrapping) here
-        return obj._mapdict_read_storage(self.position)
+        erased = obj._mapdict_read_storage(self.position)
+        w_value = unerase_item(erased)
+        return w_value
 
     def write_attr(self, obj, w_value):
         # XXX do the unerasing (and unwrapping) here
-        obj._mapdict_write_storage(self.position, w_value)
+        erased = erase_item(w_value)
+        obj._mapdict_write_storage(self.position, erased)
 
     def delete(self, obj, selector):
         if selector == self.selector:
@@ -317,7 +319,7 @@
         new_obj = self.back.materialize_r_dict(space, obj, dict_w)
         if self.selector[1] == DICT:
             w_attr = space.wrap(self.selector[0])
-            dict_w[w_attr] = obj._mapdict_read_storage(self.position)
+            dict_w[w_attr] = self.read_attr(obj)
         else:
             self._copy_attr(obj, new_obj)
         return new_obj
@@ -550,20 +552,19 @@
                 for i in rangenmin1:
                     if index == i:
                         erased = getattr(self, "_value%s" % i)
-                        return unerase_item(erased)
+                        return erased
             if self._has_storage_list():
                 return self._mapdict_get_storage_list()[index - nmin1]
             erased = getattr(self, "_value%s" % nmin1)
-            return unerase_item(erased)
+            return erased
 
-        def _mapdict_write_storage(self, index, value):
-            erased = erase_item(value)
+        def _mapdict_write_storage(self, index, erased):
             for i in rangenmin1:
                 if index == i:
                     setattr(self, "_value%s" % i, erased)
                     return
             if self._has_storage_list():
-                self._mapdict_get_storage_list()[index - nmin1] = value
+                self._mapdict_get_storage_list()[index - nmin1] = erased
                 return
             setattr(self, "_value%s" % nmin1, erased)
 
@@ -577,21 +578,23 @@
             len_storage = len(storage)
             for i in rangenmin1:
                 if i < len_storage:
-                    erased = erase_item(storage[i])
+                    erased = storage[i]
                 else:
+                    # XXX later: use correct erase method from attribute
                     erased = erase_item(None)
                 setattr(self, "_value%s" % i, erased)
             has_storage_list = self._has_storage_list()
             if len_storage < n:
                 assert not has_storage_list
+                # XXX later: use correct erase method from attribute
                 erased = erase_item(None)
             elif len_storage == n:
                 assert not has_storage_list
-                erased = erase_item(storage[nmin1])
+                erased = storage[nmin1]
             elif not has_storage_list:
                 # storage is longer than self.map.length() only due to
                 # overallocation
-                erased = erase_item(storage[nmin1])
+                erased = storage[nmin1]
                 # in theory, we should be ultra-paranoid and check all entries,
                 # but checking just one should catch most problems anyway:
                 assert storage[n] is None
@@ -771,14 +774,14 @@
     pycode._mapdict_caches = [INVALID_CACHE_ENTRY] * num_entries
 
 @jit.dont_look_inside
-def _fill_cache(pycode, nameindex, map, version_tag, index, w_method=None):
+def _fill_cache(pycode, nameindex, map, version_tag, attr, w_method=None):
     entry = pycode._mapdict_caches[nameindex]
     if entry is INVALID_CACHE_ENTRY:
         entry = CacheEntry()
         pycode._mapdict_caches[nameindex] = entry
     entry.map_wref = weakref.ref(map)
     entry.version_tag = version_tag
-    entry.index = index
+    entry.attr = attr
     entry.w_method = w_method
     if pycode.space.config.objspace.std.withmethodcachecounter:
         entry.failure_counter += 1
@@ -790,7 +793,7 @@
     map = w_obj._get_mapdict_map()
     if entry.is_valid_for_map(map) and entry.w_method is None:
         # everything matches, it's incredibly fast
-        return w_obj._mapdict_read_storage(entry.index)
+        return entry.attr.read_attr(w_obj) #._mapdict_read_storage(entry.index)
     return LOAD_ATTR_slowpath(pycode, w_obj, nameindex, map)
 LOAD_ATTR_caching._always_inline_ = True
 
@@ -836,7 +839,7 @@
                 if attr is not None:
                     # Note that if map.terminator is a DevolvedDictTerminator,
                     # map.index() will always return -1 if selector[1]==DICT.
-                    _fill_cache(pycode, nameindex, map, version_tag, 
attr.position)
+                    _fill_cache(pycode, nameindex, map, version_tag, attr)
                     return attr.read_attr(w_obj) 
#w_obj._mapdict_read_storage(index)
     if space.config.objspace.std.withmethodcachecounter:
         INVALID_CACHE_ENTRY.failure_counter += 1
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
@@ -23,7 +23,14 @@
     class typedef:
         hasdict = False
 
+def erase_storage_items(items):
+    return [erase_item(item) for item in items]
+
+def unerase_storage_items(storage):
+    return [unerase_item(item) for item in storage]
+
 def test_plain_attribute():
+
     w_cls = "class"
     aa = PlainAttribute(("b", DICT),
                         PlainAttribute(("a", DICT),
@@ -33,18 +40,18 @@
     assert aa.get_terminator() is aa.terminator
 
     obj = Object()
-    obj.map, obj.storage = aa, [10, 20]
+    obj.map, obj.storage = aa, erase_storage_items([10, 20])
     assert obj.getdictvalue(space, "a") == 10
     assert obj.getdictvalue(space, "b") == 20
     assert obj.getdictvalue(space, "c") is None
 
     obj = Object()
-    obj.map, obj.storage = aa, [30, 40]
+    obj.map, obj.storage = aa, erase_storage_items([30, 40])
     obj.setdictvalue(space, "a", 50)
-    assert obj.storage == [50, 40]
+    assert unerase_storage_items(obj.storage) == [50, 40]
     assert obj.getdictvalue(space, "a") == 50
     obj.setdictvalue(space, "b", 60)
-    assert obj.storage == [50, 60]
+    assert unerase_storage_items(obj.storage) == [50, 60]
     assert obj.getdictvalue(space, "b") == 60
 
     assert aa.length() == 2
@@ -73,7 +80,7 @@
     cls = Class()
     obj = cls.instantiate()
     obj.setdictvalue(space, "a", 10)
-    assert obj.storage == [10]
+    assert unerase_storage_items(obj.storage) == [10]
     assert obj.getdictvalue(space, "a") == 10
     assert obj.getdictvalue(space, "b") is None
     assert obj.getdictvalue(space, "c") is None
@@ -83,7 +90,7 @@
     assert obj.getdictvalue(space, "c") is None
 
     obj.setdictvalue(space, "b", 30)
-    assert obj.storage == [20, 30]
+    assert unerase_storage_items(obj.storage) == [20, 30]
     assert obj.getdictvalue(space, "a") == 20
     assert obj.getdictvalue(space, "b") == 30
     assert obj.getdictvalue(space, "c") is None
@@ -106,12 +113,12 @@
         obj.setdictvalue(space, "a", 50)
         obj.setdictvalue(space, "b", 60)
         obj.setdictvalue(space, "c", 70)
-        assert obj.storage == [50, 60, 70]
+        assert unerase_storage_items(obj.storage) == [50, 60, 70]
         res = obj.deldictvalue(space, dattr)
         assert res
         s = [50, 60, 70]
         del s[i]
-        assert obj.storage == s
+        assert unerase_storage_items(obj.storage) == s
 
     obj = c.instantiate()
     obj.setdictvalue(space, "a", 50)
@@ -134,7 +141,7 @@
     c2 = Class()
     obj.setclass(space, c2)
     assert obj.getclass(space) is c2
-    assert obj.storage == [50, 60, 70]
+    assert unerase_storage_items(obj.storage) == [50, 60, 70]
 
 def test_special():
     from pypy.module._weakref.interp__weakref import WeakrefLifeline
@@ -150,7 +157,7 @@
     assert obj.getdictvalue(space, "a") == 50
     assert obj.getdictvalue(space, "b") == 60
     assert obj.getdictvalue(space, "c") == 70
-    assert obj.storage == [50, 60, 70, lifeline1]
+    assert unerase_storage_items(obj.storage) == [50, 60, 70, lifeline1]
     assert obj.getweakref() is lifeline1
 
     obj2 = c.instantiate()
@@ -158,7 +165,7 @@
     obj2.setdictvalue(space, "b", 160)
     obj2.setdictvalue(space, "c", 170)
     obj2.setweakref(space, lifeline2)
-    assert obj2.storage == [150, 160, 170, lifeline2]
+    assert unerase_storage_items(obj2.storage) == [150, 160, 170, lifeline2]
     assert obj2.getweakref() is lifeline2
 
     assert obj2.map is obj.map
@@ -188,7 +195,7 @@
     assert obj.getslotvalue(a) == 50
     assert obj.getslotvalue(b) == 60
     assert obj.getslotvalue(c) == 70
-    assert obj.storage == [50, 60, 70]
+    assert unerase_storage_items(obj.storage) == [50, 60, 70]
 
     obj.setdictvalue(space, "a", 5)
     obj.setdictvalue(space, "b", 6)
@@ -199,7 +206,7 @@
     assert obj.getslotvalue(a) == 50
     assert obj.getslotvalue(b) == 60
     assert obj.getslotvalue(c) == 70
-    assert obj.storage == [50, 60, 70, 5, 6, 7]
+    assert unerase_storage_items(obj.storage) == [50, 60, 70, 5, 6, 7]
 
     obj2 = cls.instantiate()
     obj2.setslotvalue(a, 501)
@@ -208,13 +215,13 @@
     obj2.setdictvalue(space, "a", 51)
     obj2.setdictvalue(space, "b", 61)
     obj2.setdictvalue(space, "c", 71)
-    assert obj2.storage == [501, 601, 701, 51, 61, 71]
+    assert unerase_storage_items(obj2.storage) == [501, 601, 701, 51, 61, 71]
     assert obj.map is obj2.map
 
     assert obj2.getslotvalue(b) == 601
     assert obj2.delslotvalue(b)
     assert obj2.getslotvalue(b) is None
-    assert obj2.storage == [501, 701, 51, 61, 71]
+    assert unerase_storage_items(obj2.storage) == [501, 701, 51, 61, 71]
     assert not obj2.delslotvalue(b)
 
 
@@ -228,7 +235,7 @@
     obj.setslotvalue(b, 60)
     assert obj.getslotvalue(a) == 50
     assert obj.getslotvalue(b) == 60
-    assert obj.storage == [50, 60]
+    assert unerase_storage_items(obj.storage) == [50, 60]
     assert not obj.setdictvalue(space, "a", 70)
 
 def test_getdict():
@@ -253,7 +260,7 @@
     obj.setdictvalue(space, "a", 5)
     obj.setdictvalue(space, "b", 6)
     obj.setdictvalue(space, "c", 7)
-    assert obj.storage == [50, 60, 70, 5, 6, 7]
+    assert unerase_storage_items(obj.storage) == [50, 60, 70, 5, 6, 7]
 
     class FakeDict(W_DictMultiObject):
         def __init__(self, d):
@@ -270,7 +277,7 @@
     assert flag
     materialize_r_dict(space, obj, d)
     assert d == {"a": 5, "b": 6, "c": 7}
-    assert obj.storage == [50, 60, 70, w_d]
+    assert unerase_storage_items(obj.storage) == [50, 60, 70, w_d]
 
 
 def test_size_prediction():
@@ -442,6 +449,17 @@
     def setup_class(cls):
         cls.space = gettestobjspace(**{"objspace.std.withmapdict": True})
 
+    def test_reading_twice(self):
+        class A(object):
+            pass
+        a = A()
+        a.x = 42
+
+        assert a.x == 42
+        print "read once"
+        assert a.x == 42
+        print "read twice"
+
     def test_simple(self):
         class A(object):
             pass
@@ -664,6 +682,7 @@
             INVALID_CACHE_ENTRY.failure_counter = 0
             #
             w_res = space.call_function(w_func)
+            print w_res
             assert space.eq_w(w_res, space.wrap(42))
             #
             entry = w_code._mapdict_caches[nameindex]
@@ -677,6 +696,15 @@
         check.unwrap_spec = [gateway.ObjSpace, gateway.W_Root, str]
         cls.w_check = cls.space.wrap(gateway.interp2app(check))
 
+    def test_do_not_change_while_counting(self):
+        class A(object):
+            pass
+        a = A()
+        a.x = 42
+
+        assert a.x == 42
+        assert a.x == 42
+
     def test_simple(self):
         class A(object):
             pass
@@ -685,7 +713,14 @@
         def f():
             return a.x
         #
+        print "1"
+        assert a.x == 42
+        print "2"
+        assert a.x == 42
+        print "3"
+        print "first check"
         res = self.check(f, 'x')
+        print "second check"
         assert res == (1, 0, 0)
         res = self.check(f, 'x')
         assert res == (0, 1, 0)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to