Author: Maciej Fijalkowski <fij...@gmail.com>
Branch: rdict-experiments-2
Changeset: r59812:b07d28a54bea
Date: 2013-01-06 19:29 +0200
http://bitbucket.org/pypy/pypy/changeset/b07d28a54bea/

Log:    hack hack and test test

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
@@ -339,7 +339,7 @@
     return ENTRIES.fasthashfn(entries[i].key)
 
 def ll_get_value(d, i):
-    return d.entries[i].value
+    return d.entries[d.indexes[i]].value
 
 def ll_keyhash_custom(d, key):
     DICT = lltype.typeOf(d).TO
@@ -384,7 +384,7 @@
         rc = d.resize_counter - 3
         if rc <= 0:       # if needed, resize the dict -- before the insertion
             ll_dict_resize(d)
-            index = ll_dict_lookup_clean(d, hash)
+            index = d.indexes[ll_dict_lookup_clean(d, hash)]
             # then redo the lookup for 'key'
             entry = d.entries[index]
             rc = d.resize_counter - 3
@@ -431,13 +431,24 @@
 
 @jit.look_inside_iff(lambda d, i: jit.isvirtual(d) and jit.isconstant(i))
 def _ll_dict_del(d, i):
-    XXX
-    d.entries.mark_deleted(i)
+    index = d.indexes[i]
+    d.indexes[i] = DELETED
     d.num_items -= 1
-    # clear the key and the value if they are GC pointers
     ENTRIES = lltype.typeOf(d.entries).TO
     ENTRY = ENTRIES.OF
-    entry = d.entries[i]
+    if index != d.num_items:
+        old_entry = d.entries[d.num_items]
+        key = old_entry.key
+        to_insert_i = ll_dict_lookup(d, key, d.keyhash(key))
+        d.indexes[to_insert_i] = index
+        # copy the value
+        new_entry = d.entries[index]
+        new_entry.key = key
+        new_entry.value = old_entry.value
+        if hasattr(ENTRY, 'f_hash'):
+            new_entry.f_hash = old_entry.f_hash
+    # clear the key and the value if they are GC pointers
+    entry = d.entries[d.num_items]
     if ENTRIES.must_clear_key:
         entry.key = lltype.nullptr(ENTRY.key.TO)
     if ENTRIES.must_clear_value:
@@ -499,7 +510,7 @@
     if index >= 0:
         checkingkey = entries[index].key
         if checkingkey == key:
-            return index   # found the entry
+            return i   # found the entry
         if d.keyeq is not None and entries.hash(index) == hash:
             # correct hash, maybe the key is e.g. a different pointer to
             # an equal object
@@ -510,7 +521,7 @@
                     # the compare did major nasty stuff to the dict: start over
                     return ll_dict_lookup(d, key, hash)
             if found:
-                return index   # found the entry
+                return i   # found the entry
         freeslot = -1
     elif index == DELETED:
         freeslot = i
@@ -548,7 +559,7 @@
                         # start over
                         return ll_dict_lookup(d, key, hash)
                 if found:
-                    return index   # found the entry
+                    return i   # found the entry
         elif freeslot == -1:
             freeslot = i
         perturb >>= PERTURB_SHIFT
diff --git a/pypy/rpython/test/test_rdict.py b/pypy/rpython/test/test_rdict.py
--- a/pypy/rpython/test/test_rdict.py
+++ b/pypy/rpython/test/test_rdict.py
@@ -25,17 +25,43 @@
 
 
 class TestRDictDirect(object):
-    def test_dict_creation(self):
+    def _get_str_dict(self):
+        # STR -> lltype.Signed
         DICT = rdict.get_ll_dict(lltype.Ptr(rstr.STR), lltype.Signed,
                                  
ll_fasthash_function=rstr.LLHelpers.ll_strhash,
                                  ll_hash_function=rstr.LLHelpers.ll_strhash,
                                  ll_eq_function=rstr.LLHelpers.ll_streq)
+        return DICT
+    
+    def test_dict_creation(self):
+        DICT = self._get_str_dict()
         ll_d = rdict.ll_newdict(DICT)
         rdict.ll_dict_setitem(ll_d, llstr("abc"), 13)
         assert (len([i for i in ll_d.indexes if i == rdict.FREE]) ==
                 rdict.DICT_INITSIZE - 1)
         assert rdict.ll_dict_getitem(ll_d, llstr("abc")) == 13
 
+    def test_dict_del_lastitem(self):
+        DICT = self._get_str_dict()
+        ll_d = rdict.ll_newdict(DICT)
+        py.test.raises(KeyError, rdict.ll_dict_delitem, ll_d, llstr("abc"))
+        rdict.ll_dict_setitem(ll_d, llstr("abc"), 13)
+        py.test.raises(KeyError, rdict.ll_dict_delitem, ll_d, llstr("def"))
+        rdict.ll_dict_delitem(ll_d, llstr("abc"))
+        assert (len([i for i in ll_d.indexes if i == rdict.FREE]) ==
+                rdict.DICT_INITSIZE - 1)
+        assert (len([i for i in ll_d.indexes if i == rdict.DELETED]) == 1)
+        py.test.raises(KeyError, rdict.ll_dict_getitem, ll_d, llstr("abc"))
+
+    def test_dict_del_not_lastitem(self):
+        DICT = self._get_str_dict()
+        ll_d = rdict.ll_newdict(DICT)
+        rdict.ll_dict_setitem(ll_d, llstr("abc"), 13)
+        rdict.ll_dict_setitem(ll_d, llstr("def"), 15)
+        rdict.ll_dict_delitem(ll_d, llstr("abc"))
+        assert (len([i for i in ll_d.indexes if i == rdict.FREE]) ==
+                rdict.DICT_INITSIZE - 2)
+        assert (len([i for i in ll_d.indexes if i == rdict.DELETED]) == 1)
 
 class BaseTestRdict(BaseRtypingTest):
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to