[pypy-svn] r32151 - in pypy/branch/rdict-index-based/pypy/rpython: lltypesystem test

mwh at codespeak.net mwh at codespeak.net
Mon Sep 11 14:48:20 CEST 2006


Author: mwh
Date: Mon Sep 11 14:48:19 2006
New Revision: 32151

Modified:
   pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py
   pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py
Log:
move all the adt methods onto the dictionary rather than the entry.
haven't made much attempt to make the code look natural, but it's not too bad
apart from ll_dict_resize which is really really horrible.


Modified: pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py	(original)
+++ pypy/branch/rdict-index-based/pypy/rpython/lltypesystem/rdict.py	Mon Sep 11 14:48:19 2006
@@ -93,6 +93,7 @@
             nullkeymarker = not self.key_repr.can_ll_be_null(s_key)
             nullvaluemarker = not self.value_repr.can_ll_be_null(s_value)
 
+            entrymeths['entry_has_f_everused'] = 0
             if nullkeymarker:
                 entrymeths['everused'] = ll_everused_from_key
             elif nullvaluemarker:
@@ -100,11 +101,13 @@
             else:
                 entryfields.append(("f_everused", lltype.Bool))
                 entrymeths['everused'] = ll_everused_from_flag
+                entrymeths['entry_has_f_everused'] = 1
 
             # * if the key or the value can also contain a "dummy" non-null
             #   marker, we use it for deleted entries.
             rtyper = self.rtyper
             dummy_obj = self.key_repr.get_ll_dummyval_obj(rtyper, s_key)
+            entrymeths['entry_has_f_valid'] = 0
             if dummy_obj:
                 entrymeths['dummy_obj'] = dummy_obj
                 entrymeths['valid'] = ll_valid_from_key
@@ -122,6 +125,7 @@
                     entrymeths['must_clear_value'] = False
                 else:
                     entryfields.append(("f_valid", lltype.Bool))
+                    entrymeths['entry_has_f_valid'] = 1
                     entrymeths['valid'] = ll_valid_from_flag
                     entrymeths['mark_deleted'] = ll_mark_deleted_in_flag
 
@@ -133,15 +137,18 @@
                 fasthashfn = None
             else:
                 fasthashfn = self.key_repr.get_ll_fasthash_function()
+                
+            entrymeths['entry_has_f_hash'] = 0
             if fasthashfn is None:
                 entryfields.append(("f_hash", lltype.Signed))
+                entrymeths['entry_has_f_hash'] = 1
                 entrymeths['hash'] = ll_hash_from_cache
             else:
                 entrymeths['hash'] = ll_hash_recomputed
                 entrymeths['fasthashfn'] = fasthashfn
 
             # Build the lltype data structures
-            self.DICTENTRY = lltype.Struct("dictentry", adtmeths=entrymeths,
+            self.DICTENTRY = lltype.Struct("dictentry", #adtmeths=entrymeths,
                                            *entryfields)
             self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY)
             fields =          [ ("num_items", lltype.Signed),
@@ -170,6 +177,7 @@
                     'keyeq':    ll_keyeq,
                     'paranoia': False,
                     }
+            adtmeths.update(entrymeths)
             self.DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths,
                                              *fields))
 
@@ -331,47 +339,47 @@
 #  be direct_call'ed from rtyped flow graphs, which means that they will
 #  get flowed and annotated, mostly with SomePtr.
 
-def ll_everused_from_flag(entry):
-    return entry.f_everused
+def ll_everused_from_flag(d, i):
+    return d.entries[i].f_everused
 
-def ll_everused_from_key(entry):
-    return bool(entry.key)
+def ll_everused_from_key(d, i):
+    return bool(d.entries[i].key)
 
-def ll_everused_from_value(entry):
-    return bool(entry.value)
+def ll_everused_from_value(d, i):
+    return bool(d.entries[i].value)
 
-def ll_valid_from_flag(entry):
-    return entry.f_valid
-
-def ll_mark_deleted_in_flag(entry):
-    entry.f_valid = False
-
-def ll_valid_from_key(entry):
-    ENTRY = lltype.typeOf(entry).TO
-    dummy = ENTRY.dummy_obj.ll_dummy_value
-    return entry.everused() and entry.key != dummy
-
-def ll_mark_deleted_in_key(entry):
-    ENTRY = lltype.typeOf(entry).TO
-    dummy = ENTRY.dummy_obj.ll_dummy_value
-    entry.key = dummy
-
-def ll_valid_from_value(entry):
-    ENTRY = lltype.typeOf(entry).TO
-    dummy = ENTRY.dummy_obj.ll_dummy_value
-    return entry.everused() and entry.value != dummy
-
-def ll_mark_deleted_in_value(entry):
-    ENTRY = lltype.typeOf(entry).TO
-    dummy = ENTRY.dummy_obj.ll_dummy_value
-    entry.value = dummy
-
-def ll_hash_from_cache(entry):
-    return entry.f_hash
-
-def ll_hash_recomputed(entry):
-    ENTRY = lltype.typeOf(entry).TO
-    return ENTRY.fasthashfn(entry.key)
+def ll_valid_from_flag(d, i):
+    return d.entries[i].f_valid
+
+def ll_mark_deleted_in_flag(d, i):
+    d.entries[i].f_valid = False
+
+def ll_valid_from_key(d, i):
+    DICT = lltype.typeOf(d).TO
+    dummy = DICT.dummy_obj.ll_dummy_value
+    return d.everused(i) and d.entries[i].key != dummy
+
+def ll_mark_deleted_in_key(d, i):
+    DICT = lltype.typeOf(d).TO
+    dummy = DICT.dummy_obj.ll_dummy_value
+    d.entries[i].key = dummy
+
+def ll_valid_from_value(d, i):
+    DICT = lltype.typeOf(d).TO
+    dummy = DICT.dummy_obj.ll_dummy_value
+    return d.everused(i) and d.entries[i].value != dummy
+
+def ll_mark_deleted_in_value(d, i):
+    DICT = lltype.typeOf(d).TO
+    dummy = DICT.dummy_obj.ll_dummy_value
+    d.entries[i].value = dummy
+
+def ll_hash_from_cache(d, i):
+    return d.entries[i].f_hash
+
+def ll_hash_recomputed(d, i):
+    DICT = lltype.typeOf(d).TO
+    return DICT.fasthashfn(d.entries[i].key)
 
 def ll_keyhash_custom(d, key):
     DICT = lltype.typeOf(d).TO
@@ -389,28 +397,29 @@
     return bool(d) and d.num_items != 0
 
 def ll_dict_getitem(d, key):
-    entry = d.entries[ll_dict_lookup(d, key, d.keyhash(key))]
-    if entry.valid():
-        return entry.value 
+    i = ll_dict_lookup(d, key, d.keyhash(key))
+    if d.valid(i):
+        return d.entries[i].value 
     else: 
         raise KeyError 
 
 def ll_dict_setitem(d, key, value):
     hash = d.keyhash(key)
-    entry = d.entries[ll_dict_lookup(d, key, hash)]
-    everused = entry.everused()
-    valid    = entry.valid()
+    i = ll_dict_lookup(d, key, hash)
+    entry = d.entries[i]
+    everused = d.everused(i)
+    valid    = d.valid(i)
     # set up the new entry
-    ENTRY = lltype.typeOf(entry).TO
+    DICT = lltype.typeOf(d).TO
     entry.value = value
     if valid:
         return
     entry.key = key
-    if hasattr(ENTRY, 'f_hash'):  entry.f_hash = hash
-    if hasattr(ENTRY, 'f_valid'): entry.f_valid = True
+    if DICT.entry_has_f_hash:  entry.f_hash = hash
+    if DICT.entry_has_f_valid: entry.f_valid = True
     d.num_items += 1
     if not everused:
-        if hasattr(ENTRY, 'f_everused'): entry.f_everused = True
+        if DICT.entry_has_f_everused: entry.f_everused = True
         d.num_pristine_entries -= 1
         if d.num_pristine_entries <= len(d.entries) / 3:
             ll_dict_resize(d)
@@ -422,52 +431,76 @@
     # of never calling d.keyhash() and d.keyeq(), so it cannot call back
     # to user code.  ll_dict_insertclean() doesn't resize the dict, either.
     entry = d.entries[ll_dict_lookup_clean(d, hash)]
-    ENTRY = lltype.typeOf(entry).TO
+    DICT = lltype.typeOf(d).TO
     entry.value = value
     entry.key = key
-    if hasattr(ENTRY, 'f_hash'):     entry.f_hash = hash
-    if hasattr(ENTRY, 'f_valid'):    entry.f_valid = True
-    if hasattr(ENTRY, 'f_everused'): entry.f_everused = True
+    if DICT.entry_has_f_hash:     entry.f_hash = hash
+    if DICT.entry_has_f_valid:    entry.f_valid = True
+    if DICT.entry_has_f_everused: entry.f_everused = True
     d.num_items += 1
     d.num_pristine_entries -= 1
 
 def ll_dict_delitem(d, key):
-    entry = d.entries[ll_dict_lookup(d, key, d.keyhash(key))]
-    if not entry.valid():
+    i = ll_dict_lookup(d, key, d.keyhash(key))
+    if not d.valid(i):
         raise KeyError
-    entry.mark_deleted()
+    entry = d.entries[i]
+    d.mark_deleted(i)
     d.num_items -= 1
     # clear the key and the value if they are GC pointers
-    ENTRY = lltype.typeOf(entry).TO
-    if ENTRY.must_clear_key:
+    DICT = lltype.typeOf(d).TO
+    if DICT.must_clear_key:
         key = entry.key   # careful about destructor side effects:
                           # keep key alive until entry.value has also
                           # been zeroed (if it must be)
-        entry.key = lltype.nullptr(ENTRY.key.TO)
-    if ENTRY.must_clear_value:
-        entry.value = lltype.nullptr(ENTRY.value.TO)
+        entry.key = lltype.nullptr(DICT.entries.OF.key.TO)
+    if DICT.must_clear_value:
+        entry.value = lltype.nullptr(DICT.entries.OF.value.TO)
     num_entries = len(d.entries)
     if num_entries > DICT_INITSIZE and d.num_items < num_entries / 4:
         ll_dict_resize(d)
 
 def ll_dict_resize(d):
     old_entries = d.entries
-    old_size = len(old_entries) 
+    old_size = len(old_entries)
     # make a 'new_size' estimate and shrink it if there are many
     # deleted entry markers
     new_size = old_size * 2
     while new_size > DICT_INITSIZE and d.num_items < new_size / 4:
         new_size /= 2
-    d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size, zero=True)
-    d.num_items = 0
-    d.num_pristine_entries = new_size
+    new_entries = lltype.malloc(lltype.typeOf(d).TO.entries.TO, new_size, zero=True)
+    new_num_items = 0
+    new_num_pristine_entries = new_size
     i = 0
     while i < old_size:
-        entry = old_entries[i]
-        if entry.valid():
-            ll_dict_insertclean(d, entry.key, entry.value, entry.hash())
+        entry = d.entries[i]
+        if d.valid(i):
+
+            # AAAAAAAAAAA
+            hash = d.hash(i)
+
+            old_entries = d.entries
+            old_num_items = d.num_items
+            old_num_pristine_entries = d.num_pristine_entries
+            d.entries = new_entries
+            d.num_items = new_num_items
+            d.num_pristine_entries = new_num_pristine_entries
+
+            ll_dict_insertclean(d, entry.key, entry.value, hash)
+
+            new_entries = d.entries
+            new_num_items = d.num_items
+            new_num_pristine_entries = d.num_pristine_entries
+            d.entries = old_entries
+            d.num_items = old_num_items
+            d.num_pristine_entries = old_num_pristine_entries
+
         i += 1
 
+    d.entries = new_entries
+    d.num_items = new_num_items
+    d.num_pristine_entries = new_num_pristine_entries
+
 # ------- a port of CPython's dictobject.c's lookdict implementation -------
 PERTURB_SHIFT = 5
 
@@ -480,22 +513,22 @@
     entry = entries[i]
     found_freeslot = False
     freeslot_index = r_uint(0)
-    if entry.valid():
+    if d.valid(i):
         checkingkey = entry.key
         if checkingkey == key:
             return i   # found the entry
-        if d.keyeq is not None and entry.hash() == hash:
+        if d.keyeq is not None and d.hash(i) == hash:
             # correct hash, maybe the key is e.g. a different pointer to
             # an equal object
             found = d.keyeq(checkingkey, key)
             if DICT.paranoia:
                 if (entries != d.entries or
-                    not entry.valid() or entry.key != checkingkey):
+                    not d.valid(i) or entry.key != checkingkey):
                     # the compare did major nasty stuff to the dict: start over
                     return ll_dict_lookup(d, key, hash)
             if found:
                 return i   # found the entry
-    elif entry.everused():
+    elif d.everused(i):
         freeslot_index = i
         found_freeslot = True
     else:
@@ -507,22 +540,22 @@
     while 1: 
         i = ((i << 2) + i + perturb + 1) & mask
         entry = entries[i]
-        if not entry.everused():
+        if not d.everused(i):
             if found_freeslot:
                 return freeslot_index
             else:
                 return i
-        elif entry.valid():
+        elif d.valid(i):
             checkingkey = entry.key
             if checkingkey == key:
                 return i
-            if d.keyeq is not None and entry.hash() == hash:
+            if d.keyeq is not None and d.hash(i) == hash:
                 # correct hash, maybe the key is e.g. a different pointer to
                 # an equal object
                 found = d.keyeq(checkingkey, key)
                 if DICT.paranoia:
                     if (entries != d.entries or
-                        not entry.valid() or entry.key != checkingkey):
+                        not d.valid(i) or entry.key != checkingkey):
                         # the compare did major nasty stuff to the dict:
                         # start over
                         return ll_dict_lookup(d, key, hash)
@@ -542,7 +575,7 @@
     i = r_uint(hash & mask) 
     entry = entries[i]
     perturb = r_uint(hash) 
-    while entry.everused():
+    while d.everused(i):
         i = ((i << 2) + i + perturb + 1) & mask
         entry = entries[i]
         perturb >>= PERTURB_SHIFT
@@ -620,8 +653,9 @@
         entries_len = len(entries)
         while index < entries_len:
             entry = entries[index]
+            i = index
             index = index + 1
-            if entry.valid():
+            if dict.valid(i):
                 iter.index = index
                 if RETURNTYPE is lltype.Void:
                     return None
@@ -631,6 +665,9 @@
                     r.item1 = recast(RETURNTYPE.TO.item1, entry.value)
                     return r
                 elif func is dum_keys:
+                    from pypy.rpython.lltypesystem.lloperation import llop
+                    from pypy.rpython.lltypesystem.lltype import Void
+                    llop.debug_print(Void, entry.key)
                     return entry.key
                 elif func is dum_values:
                     return entry.value
@@ -642,16 +679,16 @@
 # methods
 
 def ll_get(dict, key, default):
-    entry = dict.entries[ll_dict_lookup(dict, key, dict.keyhash(key))]
-    if entry.valid():
-        return entry.value
+    i = ll_dict_lookup(dict, key, dict.keyhash(key))
+    if dict.valid(i):
+        return dict.entries[i].value
     else: 
         return default
 
 def ll_setdefault(dict, key, default):
-    entry = dict.entries[ll_dict_lookup(dict, key, dict.keyhash(key))]
-    if entry.valid():
-        return entry.value
+    i = ll_dict_lookup(dict, key, dict.keyhash(key))
+    if dict.valid(i):
+        return dict.entries[i].value
     else:
         ll_dict_setitem(dict, key, default)
         return default
@@ -669,12 +706,12 @@
     while i < dictsize:
         d_entry = d.entries[i]
         entry = dict.entries[i]
-        ENTRY = lltype.typeOf(entry).TO
+        DICT = lltype.typeOf(dict).TO
         d_entry.key = entry.key
-        if hasattr(ENTRY, 'f_valid'):    d_entry.f_valid    = entry.f_valid
-        if hasattr(ENTRY, 'f_everused'): d_entry.f_everused = entry.f_everused
+        if DICT.entry_has_f_valid:    d_entry.f_valid    = entry.f_valid
+        if DICT.entry_has_f_everused: d_entry.f_everused = entry.f_everused
         d_entry.value = entry.value
-        if hasattr(ENTRY, 'f_hash'):     d_entry.f_hash     = entry.f_hash
+        if DICT.entry_has_f_hash:     d_entry.f_hash     = entry.f_hash
         i += 1
     return d
 
@@ -692,7 +729,7 @@
     i = 0
     while i < d2len:
         entry = entries[i]
-        if entry.valid():
+        if dic2.valid(i):
             ll_dict_setitem(dic1, entry.key, entry.value)
         i += 1
 
@@ -716,7 +753,7 @@
     p = 0
     while i < dlen:
         entry = entries[i]
-        if entry.valid():
+        if dic.valid(i):
             ELEM = lltype.typeOf(items).TO.OF
             if ELEM is not lltype.Void:
                 if func is dum_items:
@@ -733,5 +770,5 @@
     return res
 
 def ll_contains(d, key):
-    entry = d.entries[ll_dict_lookup(d, key, d.keyhash(key))]
-    return entry.valid()
+    i = ll_dict_lookup(d, key, d.keyhash(key))
+    return d.valid(i)

Modified: pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py
==============================================================================
--- pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py	(original)
+++ pypy/branch/rdict-index-based/pypy/rpython/test/test_rdict.py	Mon Sep 11 14:48:19 2006
@@ -548,7 +548,7 @@
 
         res = self.interpret(func2, [ord(x), ord(y)])
         for i in range(len(res.entries)): 
-            assert not (res.entries[i].everused() and not res.entries[i].valid())
+            assert not (res.everused(i) and not res.valid(i))
 
         def func3(c0, c1, c2, c3, c4, c5, c6, c7):
             d = {}
@@ -568,7 +568,7 @@
                                    for i in range(rdict.DICT_INITSIZE)])
         count_frees = 0
         for i in range(len(res.entries)):
-            if not res.entries[i].everused():
+            if not res.everused(i):
                 count_frees += 1
         assert count_frees >= 3
 
@@ -659,8 +659,8 @@
         res = self.interpret(f, [])
         assert res.item0 == True
         DICT = lltype.typeOf(res.item1).TO
-        assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None string keys
-        assert not hasattr(DICT.entries.TO.OF, 'f_valid')   # strings have a dummy
+        assert not DICT.entry_has_f_everused# non-None string keys
+        assert not DICT.entry_has_f_valid   # strings have a dummy
 
     def test_opt_nullvaluemarker(self):
         def f(n):
@@ -670,8 +670,8 @@
         res = self.interpret(f, [-5])
         assert res.item0 == 4
         DICT = lltype.typeOf(res.item1).TO
-        assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None str values
-        assert not hasattr(DICT.entries.TO.OF, 'f_valid')   # strs have a dummy
+        assert not DICT.entry_has_f_everused# non-None string keys
+        assert not DICT.entry_has_f_valid   # strings have a dummy
 
     def test_opt_nonullmarker(self):
         class A:
@@ -687,8 +687,8 @@
         res = self.interpret(f, [-5])
         assert res.item0 == -5441
         DICT = lltype.typeOf(res.item1).TO
-        assert hasattr(DICT.entries.TO.OF, 'f_everused') # can-be-None A instances
-        assert not hasattr(DICT.entries.TO.OF, 'f_valid')# with a dummy A instance
+        assert DICT.entry_has_f_everused # can-be-None A instances
+        assert not DICT.entry_has_f_valid# with a dummy A instance
 
         res = self.interpret(f, [6])
         assert res.item0 == -5441
@@ -703,8 +703,8 @@
         assert res.item0 == 1
         assert res.item1 == 24
         DICT = lltype.typeOf(res.item2).TO
-        assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero
-        assert not hasattr(DICT.entries.TO.OF, 'f_valid')# nonneg int: dummy -1
+        assert DICT.entry_has_f_everused # all ints can be zero
+        assert not DICT.entry_has_f_valid# nonneg int: dummy -1
 
     def test_opt_no_dummy(self):
         def f(n):
@@ -716,8 +716,8 @@
         assert res.item0 == 1
         assert res.item1 == -24
         DICT = lltype.typeOf(res.item2).TO
-        assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero
-        assert hasattr(DICT.entries.TO.OF, 'f_valid')    # no dummy available
+        assert DICT.entry_has_f_everused # all ints can be zero
+        assert DICT.entry_has_f_valid    # no dummy available
 
     def test_opt_multiple_identical_dicts(self):
         def f(n):
@@ -748,7 +748,3 @@
             return dic[i]
         res = self.interpret(func, [5])
         assert res.ll_get(5) is res
-
-
-
-



More information about the Pypy-commit mailing list