[pypy-commit] pypy keys_with_hash: getitem_with_hash

arigo noreply at buildbot.pypy.org
Tue Sep 1 10:38:50 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: keys_with_hash
Changeset: r79336:a2de5fee1e30
Date: 2015-09-01 10:34 +0200
http://bitbucket.org/pypy/pypy/changeset/a2de5fee1e30/

Log:	getitem_with_hash

diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -475,6 +475,10 @@
         pair(self, s_key).setitem(s_value)
     method_setitem_with_hash.can_only_throw = _dict_can_only_throw_nothing
 
+    def method_getitem_with_hash(self, s_key, s_hash):
+        return pair(self, s_key).getitem()
+    method_getitem_with_hash.can_only_throw = _dict_can_only_throw_keyerror
+
 @op.contains.register(SomeString)
 @op.contains.register(SomeUnicodeString)
 def contains_String(annotator, string, char):
diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py
--- a/rpython/rlib/objectmodel.py
+++ b/rpython/rlib/objectmodel.py
@@ -788,23 +788,23 @@
         d = d.keys()
     return reversed(d)
 
+def _expected_hash(d, key):
+    if isinstance(d, r_dict):
+        xxx
+    else:
+        return compute_hash(key)
+
 def iterkeys_with_hash(d):
     """Iterates (key, hash) pairs without recomputing the hash."""
     if not we_are_translated():
-        if isinstance(d, r_dict):
-            xxx
-        else:
-            return ((k, compute_hash(k)) for k in d)
+        return ((k, _expected_hash(d, k)) for k in d)
     return d.iterkeys_with_hash()
 
 def contains_with_hash(d, key, h):
     """Same as 'key in d'.  The extra argument is the hash.  Use this only
     if you got the hash just now from some other ..._with_hash() function."""
     if not we_are_translated():
-        if isinstance(d, r_dict):
-            xxx
-        else:
-            assert compute_hash(key) == h
+        assert _expected_hash(d, key) == h
         return key in d
     return d.contains_with_hash(key, h)
 
@@ -812,14 +812,19 @@
     """Same as 'd[key] = value'.  The extra argument is the hash.  Use this only
     if you got the hash just now from some other ..._with_hash() function."""
     if not we_are_translated():
-        if isinstance(d, r_dict):
-            xxx
-        else:
-            assert compute_hash(key) == h
+        assert _expected_hash(d, key) == h
         d[key] = value
         return
     d.setitem_with_hash(key, h, value)
 
+def getitem_with_hash(d, key, h):
+    """Same as 'd[key]'.  The extra argument is the hash.  Use this only
+    if you got the hash just now from some other ..._with_hash() function."""
+    if not we_are_translated():
+        assert _expected_hash(d, key) == h
+        return d[key]
+    return d.getitem_with_hash(key, h)
+
 # ____________________________________________________________
 
 def import_from_mixin(M, special_methods=['__init__', '__del__']):
diff --git a/rpython/rlib/test/test_objectmodel.py b/rpython/rlib/test/test_objectmodel.py
--- a/rpython/rlib/test/test_objectmodel.py
+++ b/rpython/rlib/test/test_objectmodel.py
@@ -627,6 +627,15 @@
     res = interpret(f, [27])
     assert res == 42
 
+def test_getitem_with_hash():
+    def f(i):
+        d = {i+.5: 42, i+.6: -612}
+        return getitem_with_hash(d, i+.5, compute_hash(i+.5))
+
+    assert f(29) == 42
+    res = interpret(f, [27])
+    assert res == 42
+
 def test_import_from_mixin():
     class M:    # old-style
         def f(self): pass
diff --git a/rpython/rtyper/lltypesystem/rordereddict.py b/rpython/rtyper/lltypesystem/rordereddict.py
--- a/rpython/rtyper/lltypesystem/rordereddict.py
+++ b/rpython/rtyper/lltypesystem/rordereddict.py
@@ -379,6 +379,16 @@
         hop.gendirectcall(ll_dict_setitem_with_hash,
                           v_dict, v_key, v_hash, v_value)
 
+    def rtype_method_getitem_with_hash(self, hop):
+        v_dict, v_key, v_hash = hop.inputargs(
+            self, self.key_repr, lltype.Signed)
+        if not self.custom_eq_hash:
+            hop.has_implicit_exception(KeyError)  # record that we know about it
+        hop.exception_is_here()
+        v_res = hop.gendirectcall(ll_dict_getitem_with_hash,
+                                  v_dict, v_key, v_hash)
+        return self.recast_value(hop.llops, v_res)
+
 class __extend__(pairtype(OrderedDictRepr, rmodel.Repr)):
 
     def rtype_getitem((r_dict, r_key), hop):
@@ -568,6 +578,13 @@
     else:
         raise KeyError
 
+def ll_dict_getitem_with_hash(d, key, hash):
+    index = d.lookup_function(d, key, hash, FLAG_LOOKUP)
+    if index >= 0:
+        return d.entries[index].value
+    else:
+        raise KeyError
+
 def ll_dict_setitem(d, key, value):
     hash = d.keyhash(key)
     index = d.lookup_function(d, key, hash, FLAG_STORE)


More information about the pypy-commit mailing list