[pypy-commit] pypy rdict-experiments-2: interface changes + fixes for strange hashes

fijal noreply at buildbot.pypy.org
Mon Jan 7 02:22:07 CET 2013


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: rdict-experiments-2
Changeset: r59834:10d7c1636f47
Date: 2013-01-07 03:21 +0200
http://bitbucket.org/pypy/pypy/changeset/10d7c1636f47/

Log:	interface changes + fixes for strange hashes

diff --git a/pypy/rpython/lltypesystem/rdict.py b/pypy/rpython/lltypesystem/rdict.py
--- a/pypy/rpython/lltypesystem/rdict.py
+++ b/pypy/rpython/lltypesystem/rdict.py
@@ -78,7 +78,10 @@
     DICTENTRY = lltype.Struct("dictentry", *entryfields)
     DICTENTRYARRAY = lltype.GcArray(DICTENTRY,
                                     adtmeths=entrymeths)
-    array_adtmeths = {'allocate': lltype.typeMethod(_ll_malloc_indexes)}
+    array_adtmeths = {'allocate': lltype.typeMethod(_ll_malloc_indexes),
+                      'getitem': ll_dict_index_getitem,
+                      'setitem': ll_dict_index_setitem}
+    
     fields = [("num_items", lltype.Signed),
               ("resize_counter", lltype.Signed),
               ("entries", lltype.Ptr(DICTENTRYARRAY)),
@@ -150,11 +153,14 @@
         if isinstance(self.DICT, lltype.GcForwardReference):
             DICTKEY = self.key_repr.lowleveltype
             DICTVALUE = self.value_repr.lowleveltype
-            get_ll_dict(DICTKEY, DICTVALUE, DICT=self.DICT,
-                 ll_fasthash_function=self.key_repr.get_ll_fasthash_function(),
-                 ll_hash_function=self.key_repr.get_ll_hash_function(),
-                 ll_eq_function=self.key_repr.get_ll_eq_function(),
-                 get_custom_eq_hash=self.custom_eq_hash)
+            kwd = {}
+            if self.custom_eq_hash:
+                kwd['custom_eq_hash'] = self.custom_eq_hash
+            else:
+                kwd['ll_hash_function'] = self.key_repr.get_ll_hash_function()
+                kwd['ll_eq_function'] = self.key_repr.get_ll_eq_function()
+                kwd['ll_fasthash_function'] = self.key_repr.get_ll_fasthash_function()
+            get_ll_dict(DICTKEY, DICTVALUE, DICT=self.DICT, **kwd)
             if self.custom_eq_hash is not None:
                 self.r_rdict_eqfn, self.r_rdict_hashfn = self.custom_eq_hash()
 
@@ -344,8 +350,20 @@
     ENTRIES = lltype.typeOf(entries).TO
     return ENTRIES.fasthashfn(entries[i].key)
 
+def ll_dict_index_getitem(indexes, i):
+    return indexes[i]
+
+def ll_dict_index_setitem(indexes, i, v):
+    indexes[i] = v
+
+def ll_dict_copy_indexes(from_indexes, to_indexes):
+    i = 0
+    while i < len(from_indexes):
+        to_indexes.setitem(i, from_indexes.getitem(i))
+        i += 1
+
 def ll_get_value(d, i):
-    return d.entries[d.indexes[i]].value
+    return d.entries[d.indexes.getitem(i)].value
 
 def ll_keyhash_custom(d, key):
     DICT = lltype.typeOf(d).TO
@@ -385,7 +403,7 @@
     valid = (i & HIGHEST_BIT) == 0
     i = i & MASK
     ENTRY = lltype.typeOf(d.entries).TO.OF
-    index = d.indexes[i]
+    index = d.indexes.getitem(i)
     if index == FREE:
         index = d.num_items
         entry = d.entries[index]
@@ -401,12 +419,12 @@
             ll_assert(rc > 0, "ll_dict_resize failed?")
         ll_assert(index < len(d.entries), "invalid insert")
         d.resize_counter = rc
-        d.indexes[i] = index
+        d.indexes.setitem(i, index)
         entry.value = value
     elif index == DELETED:
         index = d.num_items
         entry = d.entries[index]        
-        d.indexes[i] = index
+        d.indexes.setitem(i, index)
         entry.value = value
     else:
         # override an existing or deleted entry
@@ -426,7 +444,7 @@
 
 @jit.look_inside_iff(lambda d, i: jit.isvirtual(d) and jit.isconstant(i))
 def _ll_dict_del(d, i):
-    index = d.indexes[i]
+    index = d.indexes.getitem(i)
     ENTRIES = lltype.typeOf(d.entries).TO
     ENTRY = ENTRIES.OF
     if index != d.num_items - 1:
@@ -434,7 +452,7 @@
         key = old_entry.key
         to_insert_i = ll_dict_lookup(d, key, d.keyhash(key))
         ll_assert(not to_insert_i & HIGHEST_BIT, "invalid entry")
-        d.indexes[to_insert_i] = index
+        d.indexes.setitem(to_insert_i, index)
         # copy the value
         new_entry = d.entries[index]
         new_entry.key = key
@@ -442,7 +460,7 @@
         if hasattr(ENTRY, 'f_hash'):
             new_entry.f_hash = old_entry.f_hash
     # clear the key and the value if they are GC pointers
-    d.indexes[i] = DELETED
+    d.indexes.setitem(i, DELETED)
     d.num_items -= 1
     entry = d.entries[d.num_items]
     if ENTRIES.clear_key:
@@ -478,18 +496,23 @@
         new_size *= 2
     #
     new_item_size = new_size // 3 * 2 + 1
-    d.entries = lltype.typeOf(old_entries).TO.allocate(new_item_size)
     d.indexes = lltype.typeOf(d).TO.indexes.TO.allocate(new_size)
     d.resize_counter = new_item_size - d.num_items
     i = 0
     indexes = d.indexes
     while i < old_size:
-        index = old_indexes[i]
+        index = old_indexes.getitem(i)
         if old_entries.valid(index):
-            indexes[ll_dict_lookup_clean(d, old_entries.hash(index))] = index
+            pos = ll_dict_lookup_clean(d, old_entries.hash(index))
+            indexes.setitem(pos, index)
         i += 1
-    rgc.ll_arraycopy(old_entries, d.entries, 0, 0, min(len(old_entries),
-                                                       len(d.entries)))
+    if len(old_entries) != new_item_size:
+        d.entries = lltype.typeOf(old_entries).TO.allocate(new_item_size)
+        rgc.ll_arraycopy(old_entries, d.entries, 0, 0, min(len(old_entries),
+                                                           len(d.entries)))
+    else:
+        # we just removed deleted items, but we didn't do anything else special
+        d.entries = old_entries
 ll_dict_resize.oopspec = 'dict.resize(d)'
 
 # ------- a port of CPython's dictobject.c's lookdict implementation -------
@@ -514,7 +537,7 @@
     # do the first try before any looping
     ENTRIES = lltype.typeOf(entries).TO
     direct_compare = not hasattr(ENTRIES, 'no_direct_compare')
-    index = indexes[i]
+    index = indexes.getitem(i)
     if entries.valid(index):
         checkingkey = entries[index].key
         if direct_compare and checkingkey == key:
@@ -526,7 +549,8 @@
             #llop.debug_print(lltype.Void, "comparing keys", ll_debugrepr(checkingkey), ll_debugrepr(key), found)
             if d.paranoia:
                 if (entries != d.entries or
-                    not entries.valid(indexes[i]) or entries[index].key != checkingkey):
+                    not entries.valid(indexes.getitem(i))
+                    or entries[index].key != checkingkey):
                     # the compare did major nasty stuff to the dict: start over
                     return ll_dict_lookup(d, key, hash)
             if found:
@@ -545,7 +569,7 @@
         i = r_uint(i)
         i = (i << 2) + i + perturb + 1
         i = intmask(i) & mask
-        index = indexes[i]
+        index = indexes.getitem(i)
         # keep 'i' as a signed number here, to consistently pass signed
         # arguments to the small helper methods.
         if index == FREE:
@@ -562,7 +586,7 @@
                 found = d.keyeq(checkingkey, key)
                 if d.paranoia:
                     if (entries != d.entries or
-                        not entries.valid(indexes[i]) or
+                        not entries.valid(indexes.getitem(i)) or
                         entries[index].key != checkingkey):
                         # the compare did major nasty stuff to the dict:
                         # start over
@@ -581,7 +605,7 @@
     mask = len(indexes) - 1
     i = hash & mask
     perturb = r_uint(hash)
-    while d.indexes[i] != FREE:
+    while indexes.getitem(i) != FREE:
         i = r_uint(i)
         i = (i << 2) + i + perturb + 1
         i = intmask(i) & mask
@@ -601,10 +625,10 @@
     # XXX don't use _ll_items_allocate because of jit.unroll_safe,
     #     should be *really* jit_unroll_iff
     d.indexes = lltype.malloc(DICT.indexes.TO, DICT_INITSIZE)
+    d.num_items = 0
     for i in range(DICT_INITSIZE):
-        d.indexes[i] = FREE
+        d.indexes.setitem(i, FREE)
     d.entries = DICT.entries.TO.allocate(DICT_ITEMS_INITSIZE)    
-    d.num_items = 0
     d.resize_counter = DICT_ITEMS_INITSIZE
     return d
 
@@ -739,7 +763,8 @@
     d.resize_counter = dict.resize_counter
     if hasattr(DICT, 'fnkeyeq'):   d.fnkeyeq   = dict.fnkeyeq
     if hasattr(DICT, 'fnkeyhash'): d.fnkeyhash = dict.fnkeyhash
-    rgc.ll_arraycopy(dict.indexes, d.indexes, 0, 0, len(dict.indexes))
+    ll_dict_copy_indexes(dict.indexes, d.indexes)
+    #rgc.ll_arraycopy(dict.indexes, d.indexes, 0, 0, len(dict.indexes))
     rgc.ll_arraycopy(dict.entries, d.entries, 0, 0, len(dict.entries))
     return d
 ll_copy.oopspec = 'dict.copy(dict)'


More information about the pypy-commit mailing list