[pypy-svn] pypy default: refactor rdict a bit:

cfbolz commits-noreply at bitbucket.org
Thu Mar 24 23:38:47 CET 2011


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: 
Changeset: r42923:ef06a997e7f1
Date: 2011-03-24 23:36 +0100
http://bitbucket.org/pypy/pypy/changeset/ef06a997e7f1/

Log:	refactor rdict a bit:

	 - make ll_dict_lookup return the index plus a flag bit set if
	the entry is unused. this removes a second access to the entry
	in the caller
	    - make setdefault hash only once(!)

diff --git a/pypy/rlib/_rweakkeydict.py b/pypy/rlib/_rweakkeydict.py
--- a/pypy/rlib/_rweakkeydict.py
+++ b/pypy/rlib/_rweakkeydict.py
@@ -123,7 +123,7 @@
 @jit.dont_look_inside
 def ll_get(d, llkey):
     hash = compute_identity_hash(llkey)
-    i = rdict.ll_dict_lookup(d, llkey, hash)
+    i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
     #llop.debug_print(lltype.Void, i, 'get', hex(hash),
     #                 ll_debugrepr(d.entries[i].key),
     #                 ll_debugrepr(d.entries[i].value))
@@ -143,7 +143,7 @@
 def ll_set_nonnull(d, llkey, llvalue):
     hash = compute_identity_hash(llkey)
     keyref = weakref_create(llkey)    # GC effects here, before the rest
-    i = rdict.ll_dict_lookup(d, llkey, hash)
+    i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
     everused = d.entries.everused(i)
     d.entries[i].key = keyref
     d.entries[i].value = llvalue
@@ -160,7 +160,7 @@
 @jit.dont_look_inside
 def ll_set_null(d, llkey):
     hash = compute_identity_hash(llkey)
-    i = rdict.ll_dict_lookup(d, llkey, hash)
+    i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
     if d.entries.everused(i):
         # If the entry was ever used, clean up its key and value.
         # We don't store a NULL value, but a dead weakref, because

diff --git a/pypy/rlib/_rweakvaldict.py b/pypy/rlib/_rweakvaldict.py
--- a/pypy/rlib/_rweakvaldict.py
+++ b/pypy/rlib/_rweakvaldict.py
@@ -113,7 +113,7 @@
     @jit.dont_look_inside
     def ll_get(self, d, llkey):
         hash = self.ll_keyhash(llkey)
-        i = rdict.ll_dict_lookup(d, llkey, hash)
+        i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
         #llop.debug_print(lltype.Void, i, 'get')
         valueref = d.entries[i].value
         if valueref:
@@ -132,7 +132,7 @@
     def ll_set_nonnull(self, d, llkey, llvalue):
         hash = self.ll_keyhash(llkey)
         valueref = weakref_create(llvalue)    # GC effects here, before the rest
-        i = rdict.ll_dict_lookup(d, llkey, hash)
+        i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
         everused = d.entries.everused(i)
         d.entries[i].key = llkey
         d.entries[i].value = valueref
@@ -146,7 +146,7 @@
     @jit.dont_look_inside
     def ll_set_null(self, d, llkey):
         hash = self.ll_keyhash(llkey)
-        i = rdict.ll_dict_lookup(d, llkey, hash)
+        i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
         if d.entries.everused(i):
             # If the entry was ever used, clean up its key and value.
             # We don't store a NULL value, but a dead weakref, because

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
@@ -4,12 +4,15 @@
 from pypy.rpython.rdict import AbstractDictRepr, AbstractDictIteratorRepr,\
      rtype_newdict
 from pypy.rpython.lltypesystem import lltype
-from pypy.rlib.rarithmetic import r_uint, intmask
+from pypy.rlib.rarithmetic import r_uint, intmask, LONG_BIT
 from pypy.rlib.objectmodel import hlinvoke
 from pypy.rpython import robject
 from pypy.rlib import objectmodel
 from pypy.rpython import rmodel
 
+HIGHEST_BIT = (1 << (LONG_BIT - 2))
+MASK = (1 << (LONG_BIT - 2)) - 1
+
 # ____________________________________________________________
 #
 #  generic implementation of RPython dictionary, with parametric DICTKEY and
@@ -422,18 +425,18 @@
 
 def ll_dict_getitem(d, key):
     i = ll_dict_lookup(d, key, d.keyhash(key))
-    entries = d.entries
-    if entries.valid(i):
-        return entries[i].value 
-    else: 
-        raise KeyError 
+    if not i & HIGHEST_BIT:
+        return d.entries[i].value
+    else:
+        raise KeyError
 ll_dict_getitem.oopspec = 'dict.getitem(d, key)'
 
 def ll_dict_setitem(d, key, value):
     hash = d.keyhash(key)
     i = ll_dict_lookup(d, key, hash)
+    valid = (i & HIGHEST_BIT) == 0
+    i = i & MASK
     everused = d.entries.everused(i)
-    valid    = d.entries.valid(i)
     # set up the new entry
     ENTRY = lltype.typeOf(d.entries).TO.OF
     entry = d.entries[i]
@@ -470,7 +473,7 @@
 
 def ll_dict_delitem(d, key):
     i = ll_dict_lookup(d, key, d.keyhash(key))
-    if not d.entries.valid(i):
+    if i & HIGHEST_BIT:
         raise KeyError
     _ll_dict_del(d, i)
 ll_dict_delitem.oopspec = 'dict.delitem(d, key)'
@@ -542,7 +545,7 @@
     elif entries.everused(i):
         freeslot = i
     else:
-        return i    # pristine entry -- lookup failed
+        return i | HIGHEST_BIT # pristine entry -- lookup failed
 
     # In the loop, a deleted entry (everused and not valid) is by far
     # (factor of 100s) the least likely outcome, so test for that last.
@@ -557,7 +560,7 @@
         if not entries.everused(i):
             if freeslot == -1:
                 freeslot = i
-            return freeslot
+            return freeslot | HIGHEST_BIT
         elif entries.valid(i):
             checkingkey = entries[i].key
             if direct_compare and checkingkey == key:
@@ -712,16 +715,16 @@
 def ll_get(dict, key, default):
     i = ll_dict_lookup(dict, key, dict.keyhash(key))
     entries = dict.entries
-    if entries.valid(i):
+    if not i & HIGHEST_BIT:
         return entries[i].value
-    else: 
+    else:
         return default
 ll_get.oopspec = 'dict.get(dict, key, default)'
 
 def ll_setdefault(dict, key, default):
     i = ll_dict_lookup(dict, key, dict.keyhash(key))
     entries = dict.entries
-    if entries.valid(i):
+    if not i & HIGHEST_BIT:
         return entries[i].value
     else:
         ll_dict_setitem(dict, key, default)
@@ -818,7 +821,7 @@
 
 def ll_contains(d, key):
     i = ll_dict_lookup(d, key, d.keyhash(key))
-    return d.entries.valid(i)
+    return not i & HIGHEST_BIT
 ll_contains.oopspec = 'dict.contains(d, key)'
 
 POPITEMINDEX = lltype.Struct('PopItemIndex', ('nextindex', lltype.Signed))


More information about the Pypy-commit mailing list