[pypy-svn] r77164 - in pypy/branch/better-map-instances/pypy/objspace/std: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Sat Sep 18 00:20:11 CEST 2010


Author: cfbolz
Date: Sat Sep 18 00:20:10 2010
New Revision: 77164

Modified:
   pypy/branch/better-map-instances/pypy/objspace/std/mapdict.py
   pypy/branch/better-map-instances/pypy/objspace/std/test/test_mapdict.py
Log:
found a bug: when calling a.__dict__.clear(), things can go wrong.


Modified: pypy/branch/better-map-instances/pypy/objspace/std/mapdict.py
==============================================================================
--- pypy/branch/better-map-instances/pypy/objspace/std/mapdict.py	(original)
+++ pypy/branch/better-map-instances/pypy/objspace/std/mapdict.py	Sat Sep 18 00:20:10 2010
@@ -70,12 +70,13 @@
         oldattr = obj._get_mapdict_map()
         if not jit.we_are_jitted():
             oldattr._size_estimate += attr.size_estimate() - oldattr.size_estimate()
+            assert oldattr.size_estimate() >= oldattr.length()
         if attr.length() > obj._mapdict_storage_length():
             # note that attr.size_estimate() is always at least attr.length()
             new_storage = [None] * attr.size_estimate()
             for i in range(obj._mapdict_storage_length()):
                 new_storage[i] = obj._mapdict_read_storage(i)
-            obj._set_mapdict_storage(new_storage)
+            obj._set_mapdict_storage_and_map(new_storage, attr)
 
         # the order is important here: first change the map, then the storage,
         # for the benefit of the special subclasses
@@ -260,8 +261,7 @@
 def _become(w_obj, new_obj):
     # this is like the _become method, really, but we cannot use that due to
     # RPython reasons
-    w_obj._set_mapdict_map(new_obj.map)
-    w_obj._set_mapdict_storage(new_obj.storage)
+    w_obj._set_mapdict_storage_and_map(new_obj.storage, new_obj.map)
 
 # ____________________________________________________________
 # object implementation
@@ -279,8 +279,7 @@
         raise NotImplementedError("abstract base class")
 
     def _become(self, new_obj):
-        self._set_mapdict_map(new_obj.map)
-        self._set_mapdict_storage(new_obj.storage)
+        self._set_mapdict_storage_and_map(new_obj.storage, new_obj.map)
 
     def _get_mapdict_map(self):
         return jit.hint(self.map, promote=True)
@@ -373,8 +372,9 @@
         self.storage[index] = value
     def _mapdict_storage_length(self):
         return len(self.storage)
-    def _set_mapdict_storage(self, storage):
+    def _set_mapdict_storage_and_map(self, storage, map):
         self.storage = storage
+        self.map = map
 
 class Object(ObjectMixin, BaseMapdictObject, W_Root):
     pass # mainly for tests
@@ -453,7 +453,8 @@
                 return len(self._mapdict_get_storage_list()) + n - 1
             return n
 
-        def _set_mapdict_storage(self, storage):
+        def _set_mapdict_storage_and_map(self, storage, map):
+            self.map = map
             len_storage = len(storage)
             for i in rangenmin1:
                 if i < len_storage:
@@ -462,8 +463,14 @@
                     erased = rerased.erase(None)
                 setattr(self, "_value%s" % i, erased)
             if len_storage < n:
+                assert not self._has_storage_list()
                 erased = rerased.erase(None)
             elif len_storage == n:
+                assert not self._has_storage_list()
+                erased = rerased.erase(storage[nmin1])
+            elif not self._has_storage_list():
+                # storage is longer than self.map.length() only due to
+                # overallocation
                 erased = rerased.erase(storage[nmin1])
             else:
                 storage_list = storage[nmin1:]

Modified: pypy/branch/better-map-instances/pypy/objspace/std/test/test_mapdict.py
==============================================================================
--- pypy/branch/better-map-instances/pypy/objspace/std/test/test_mapdict.py	(original)
+++ pypy/branch/better-map-instances/pypy/objspace/std/test/test_mapdict.py	Sat Sep 18 00:20:10 2010
@@ -516,6 +516,27 @@
         d[1] = 3
         a.__dict__ = {}
 
+    def test_dict_clear_bug(self):
+        class A(object):
+            pass
+        a = A()
+        a.x1 = 1
+        a.x2 = 1
+        a.x3 = 1
+        a.x4 = 1
+        a.x5 = 1
+        for i in range(100): # change _size_estimate of w_A.terminator
+            a1 = A()
+            a1.x1 = 1
+            a1.x2 = 1
+            a1.x3 = 1
+            a1.x4 = 1
+            a1.x5 = 1
+        d = a.__dict__
+        d.clear()
+        a.__dict__ = {1: 1}
+        assert d == {}
+
     def test_change_class_slots(self):
         skip("not supported by pypy yet")
         class A(object):



More information about the Pypy-commit mailing list