[pypy-svn] r73098 - in pypy/branch/reduce-instance-size-experiments/pypy/objspace/std: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Mon Mar 29 18:23:45 CEST 2010


Author: cfbolz
Date: Mon Mar 29 18:23:44 2010
New Revision: 73098

Modified:
   pypy/branch/reduce-instance-size-experiments/pypy/objspace/std/sharingdict.py
   pypy/branch/reduce-instance-size-experiments/pypy/objspace/std/test/test_sharingdict.py
Log:
refactor to have a new "AttributeShape" object. will add new functionality to
that object soon.


Modified: pypy/branch/reduce-instance-size-experiments/pypy/objspace/std/sharingdict.py
==============================================================================
--- pypy/branch/reduce-instance-size-experiments/pypy/objspace/std/sharingdict.py	(original)
+++ pypy/branch/reduce-instance-size-experiments/pypy/objspace/std/sharingdict.py	Mon Mar 29 18:23:44 2010
@@ -10,9 +10,10 @@
     _immutable_fields_ = ["keys", "length", "back_struct", "other_structs",
                           "last_key"]
 
-    def __init__(self, keys=None, length=0,
+    def __init__(self, space, keys=None, length=0,
                  last_key=None,
                  back_struct=None):
+        self.space = space
         if keys is None:
             keys = {}
         self.keys = keys
@@ -27,15 +28,15 @@
 
     def new_structure(self, added_key):
         keys = self.keys.copy()
-        keys[added_key] = len(self.keys)
-        new_structure = SharedStructure(keys, self.length + 1,
+        keys[added_key] = AttributeShape(self.space, len(self.keys))
+        new_structure = SharedStructure(self.space, keys, self.length + 1,
                                         added_key, self)
         self.other_structs.set(added_key, new_structure)
         return new_structure
 
     @purefunction_promote('0')
-    def lookup_position(self, key):
-        return self.keys.get(key, -1)
+    def lookup_attribute(self, key):
+        return self.keys.get(key, None)
 
     @purefunction_promote('0')
     def get_next_structure(self, key):
@@ -50,6 +51,51 @@
     def size_estimate(self):
         return self._size_estimate >> NUM_DIGITS
 
+    def convert_to(self, new_structure, entries):
+        if new_structure.length > len(entries):
+            new_entries = [erase(self.space, None)] * new_structure.size_estimate()
+            for i in range(len(entries)):
+                new_entries[i] = entries[i]
+            entries = new_entries
+        assert self.length + 1 == new_structure.length
+        return entries
+
+    @purefunction_promote('0')
+    def find_structure_del_key(self, num_back):
+        keys = [None] * num_back
+        for i in range(num_back):
+            keys[i] = self.last_key
+            self = self.back_struct
+        # go back the structure that contains the deleted key
+        self = self.back_struct
+        for i in range(num_back - 1, -1, -1):
+            self = self.get_next_structure(keys[i])
+        return self
+
+
+class AttributeShape(object):
+    _immutable_ = True
+    def __init__(self, space, index):
+        self.space = space
+        self.index = index
+
+    def getfield(self, fields):
+        return unerase(self.space, fields[self.index])
+    def setfield(self, fields, val):
+        fields[self.index] = erase(self.space, val)
+    def delfield(self, fields, structure):
+        struct_len = structure.length
+        num_back = struct_len - self.index - 1
+        if num_back > 0:
+            for i in range(self.index, struct_len - 1):
+                fields[i] = fields[i + 1]
+        # don't make the entries list shorter, new keys might be added soon
+        fields[struct_len - 1] = erase(self.space, None)
+        return structure.find_structure_del_key(num_back)
+
+
+        
+
 def erase(space, w_value):
     if not space.config.objspace.std.withsharingtaggingdict:
         return w_value
@@ -74,7 +120,7 @@
 
 class State(object):
     def __init__(self, space):
-        self.empty_structure = SharedStructure()
+        self.empty_structure = SharedStructure(space)
         self.emptylist = []
 
 
@@ -96,10 +142,10 @@
             return self._as_rdict().getitem(w_lookup)
 
     def impl_getitem_str(self, lookup):
-        i = self.structure.lookup_position(lookup)
-        if i == -1:
+        attr = self.structure.lookup_attribute(lookup)
+        if attr is None:
             return None
-        return unerase(self.space, self.entries[i])
+        return attr.getfield(self.entries)
 
     def impl_setitem(self, w_key, w_value):
         space = self.space
@@ -110,20 +156,14 @@
 
     @unroll_safe
     def impl_setitem_str(self, key, w_value, shadows_type=True):
-        e_value = erase(self.space, w_value)
-        i = self.structure.lookup_position(key)
-        if i != -1:
-            self.entries[i] = e_value
+        attr = self.structure.lookup_attribute(key)
+        if attr is not None:
+            attr.setfield(self.space, w_value)
             return
         new_structure = self.structure.get_next_structure(key)
-        if new_structure.length > len(self.entries):
-            new_entries = [erase(self.space, None)] * new_structure.size_estimate()
-            for i in range(len(self.entries)):
-                new_entries[i] = self.entries[i]
-            self.entries = new_entries
-
-        self.entries[new_structure.length - 1] = e_value
-        assert self.structure.length + 1 == new_structure.length
+        self.entries = self.structure.convert_to(new_structure, self.entries)
+        attr = new_structure.lookup_attribute(key)
+        attr.setfield(self.entries, w_value)
         self.structure = new_structure
             
     def impl_delitem(self, w_key):
@@ -131,27 +171,10 @@
         w_key_type = space.type(w_key)
         if space.is_w(w_key_type, space.w_str):
             key = space.str_w(w_key)
-            pos = self.structure.lookup_position(key)
-            if pos == -1:
+            attr = self.structure.lookup_attribute(key)
+            if attr is None:
                 raise KeyError
-            struct_len = self.structure.length
-            num_back = struct_len - pos - 1
-
-            if num_back > 0:
-                for i in range(pos, struct_len - 1):
-                    self.entries[i] = self.entries[i + 1]
-            # don't make the entries list shorter, new keys might be added soon
-            self.entries[struct_len - 1] = erase(self.space, None)
-            structure = self.structure
-            keys = [None] * num_back
-            for i in range(num_back):
-                keys[i] = structure.last_key
-                structure = structure.back_struct
-            # go back the structure that contains the deleted key
-            structure = structure.back_struct
-            for i in range(num_back - 1, -1, -1):
-                structure = structure.get_next_structure(keys[i])
-            self.structure = structure
+            self.structure = attr.delfield(self.entries, self.structure)
         elif _is_sane_hash(space, w_key_type):
             raise KeyError
         else:
@@ -166,7 +189,7 @@
     def impl_keys(self):
         space = self.space
         return [space.wrap(key)
-                    for (key, item) in self.structure.keys.iteritems()]
+                    for (key, _) in self.structure.keys.iteritems()]
 
     def impl_values(self):
         return [unerase(self.space, self.entries[i])
@@ -176,17 +199,17 @@
         space = self.space
         return [space.newtuple([
                         space.wrap(key),
-                        unerase(self.space, self.entries[item])])
-                    for (key, item) in self.structure.keys.iteritems()]
+                        attr.getfield(self.entries)])
+                    for (key, attr) in self.structure.keys.iteritems()]
     def impl_clear(self):
         space = self.space
         self.structure = space.fromcache(State).empty_structure
         self.entries = space.fromcache(State).emptylist
     def _as_rdict(self):
         r_dict_content = self.initialize_as_rdict()
-        for k, i in self.structure.keys.items():
-            r_dict_content[self.space.wrap(k)] = unerase(
-                self.space, self.entries[i])
+        for k, attr in self.structure.keys.items():
+            r_dict_content[self.space.wrap(k)] = attr.getfield(
+                self.entries)
         self._clear_fields()
         return self
 
@@ -202,8 +225,8 @@
     def next_entry(self):
         implementation = self.dictimplementation
         assert isinstance(implementation, SharedDictImplementation)
-        for key, index in self.iterator:
-            e_value = implementation.entries[index]
-            return self.space.wrap(key), unerase(self.space, e_value)
+        for key, attr in self.iterator:
+            w_value = attr.getfield(implementation.entries)
+            return self.space.wrap(key), w_value
         else:
             return None, None

Modified: pypy/branch/reduce-instance-size-experiments/pypy/objspace/std/test/test_sharingdict.py
==============================================================================
--- pypy/branch/reduce-instance-size-experiments/pypy/objspace/std/test/test_sharingdict.py	(original)
+++ pypy/branch/reduce-instance-size-experiments/pypy/objspace/std/test/test_sharingdict.py	Mon Mar 29 18:23:44 2010
@@ -11,7 +11,7 @@
     return structure
 
 def test_size_estimate():
-    empty_structure = SharedStructure()
+    empty_structure = SharedStructure(None)
     instances = []
     for i in range(100):
         instances.append(instance_with_keys(empty_structure, "a", "b", "c", "d", "e", "f"))
@@ -21,7 +21,7 @@
     assert empty_structure.other_structs.get("x").size_estimate() == 2
 
 def test_size_estimate2():
-    empty_structure = SharedStructure()
+    empty_structure = SharedStructure(None)
     instances = []
     for i in range(100):
         instances.append(instance_with_keys(empty_structure, "a", "b", "c", "d", "e", "f"))
@@ -33,6 +33,8 @@
 
 def unerase_entries(space, d):
     return [unerase(space, e) for e in d.entries]
+def key_positions(d):
+    return dict([(key, attr.index) for key, attr in d.structure.keys.items()])
 
 def test_delete():
     space = FakeSpace()
@@ -43,7 +45,7 @@
     d.delitem("b")
     assert d.r_dict_content is None
     assert unerase_entries(space, d) == [1, 3, None]
-    assert d.structure.keys == {"a": 0, "c": 1}
+    assert key_positions(d) == {"a": 0, "c": 1}
     assert d.getitem("a") == 1
     assert d.getitem("c") == 3
     assert d.getitem("b") is None
@@ -51,11 +53,11 @@
 
     d.delitem("c")
     assert unerase_entries(space, d) == [1, None, None]
-    assert d.structure.keys == {"a": 0}
+    assert key_positions(d) == {"a": 0}
 
     d.delitem("a")
     assert unerase_entries(space, d) == [None, None, None]
-    assert d.structure.keys == {}
+    assert key_positions(d) == {}
 
     d = SharedDictImplementation(space)
     d.setitem_str("a", 1)
@@ -69,4 +71,4 @@
     d.setitem_str("i", 9)
     d.delitem("d")
     assert unerase_entries(space, d) == [1, 2, 3, 5, 6, 7, 8, 9, None]
-    assert d.structure.keys == {"a": 0, "b": 1, "c": 2, "e": 3, "f": 4, "g": 5, "h": 6, "i": 7}
+    assert key_positions(d) == {"a": 0, "b": 1, "c": 2, "e": 3, "f": 4, "g": 5, "h": 6, "i": 7}



More information about the Pypy-commit mailing list