Author: Armin Rigo <ar...@tunes.org>
Branch: keys_with_hash
Changeset: r79335:908587219ea9
Date: 2015-09-01 10:29 +0200
http://bitbucket.org/pypy/pypy/changeset/908587219ea9/

Log:    setitem_with_hash

diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py
--- a/rpython/annotator/binaryop.py
+++ b/rpython/annotator/binaryop.py
@@ -519,26 +519,32 @@
         return dic1.__class__(dic1.dictdef.union(dic2.dictdef))
 
 
+def _dict_can_only_throw_keyerror(s_dct, *ignore):
+    if s_dct.dictdef.dictkey.custom_eq_hash:
+        return None    # r_dict: can throw anything
+    return [KeyError]
+
+def _dict_can_only_throw_nothing(s_dct, *ignore):
+    if s_dct.dictdef.dictkey.custom_eq_hash:
+        return None    # r_dict: can throw anything
+    return []          # else: no possible exception
+
+
 class __extend__(pairtype(SomeDict, SomeObject)):
 
-    def _can_only_throw(dic1, *ignore):
-        if dic1.dictdef.dictkey.custom_eq_hash:
-            return None
-        return [KeyError]
-
     def getitem((dic1, obj2)):
         dic1.dictdef.generalize_key(obj2)
         return dic1.dictdef.read_value()
-    getitem.can_only_throw = _can_only_throw
+    getitem.can_only_throw = _dict_can_only_throw_keyerror
 
     def setitem((dic1, obj2), s_value):
         dic1.dictdef.generalize_key(obj2)
         dic1.dictdef.generalize_value(s_value)
-    setitem.can_only_throw = _can_only_throw
+    setitem.can_only_throw = _dict_can_only_throw_nothing
 
     def delitem((dic1, obj2)):
         dic1.dictdef.generalize_key(obj2)
-    delitem.can_only_throw = _can_only_throw
+    delitem.can_only_throw = _dict_can_only_throw_keyerror
 
 
 class __extend__(pairtype(SomeTuple, SomeInteger)):
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -4,6 +4,7 @@
 
 from __future__ import absolute_import
 
+from rpython.tool.pairtype import pair
 from rpython.flowspace.operation import op
 from rpython.flowspace.model import const, Constant
 from rpython.flowspace.argument import CallSpec
@@ -16,6 +17,8 @@
 from rpython.annotator.bookkeeper import getbookkeeper, immutablevalue
 from rpython.annotator import builtin
 from rpython.annotator.binaryop import _clone ## XXX where to put this?
+from rpython.annotator.binaryop import _dict_can_only_throw_keyerror
+from rpython.annotator.binaryop import _dict_can_only_throw_nothing
 from rpython.annotator.model import AnnotatorError
 from rpython.annotator.argument import simple_args, complex_args
 
@@ -364,11 +367,6 @@
         raise AnnotatorError("%s: not proven to have non-negative stop" % 
error)
 
 
-def _can_only_throw(s_dct, *ignore):
-    if s_dct.dictdef.dictkey.custom_eq_hash:
-        return None    # r_dict: can throw anything
-    return []          # else: no possible exception
-
 def dict_contains(s_dct, s_element):
     s_dct.dictdef.generalize_key(s_element)
     if s_dct._is_empty():
@@ -381,7 +379,7 @@
 def contains_SomeDict(annotator, dct, element):
     return dict_contains(annotator.annotation(dct),
                          annotator.annotation(element))
-contains_SomeDict.can_only_throw = _can_only_throw
+contains_SomeDict.can_only_throw = _dict_can_only_throw_nothing
 
 class __extend__(SomeDict):
 
@@ -471,6 +469,11 @@
 
     def method_contains_with_hash(self, s_key, s_hash):
         return dict_contains(self, s_key)
+    method_contains_with_hash.can_only_throw = _dict_can_only_throw_nothing
+
+    def method_setitem_with_hash(self, s_key, s_hash, s_value):
+        pair(self, s_key).setitem(s_value)
+    method_setitem_with_hash.can_only_throw = _dict_can_only_throw_nothing
 
 @op.contains.register(SomeString)
 @op.contains.register(SomeUnicodeString)
diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py
--- a/rpython/rlib/objectmodel.py
+++ b/rpython/rlib/objectmodel.py
@@ -808,6 +808,18 @@
         return key in d
     return d.contains_with_hash(key, h)
 
+def setitem_with_hash(d, key, h, value):
+    """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
+        d[key] = value
+        return
+    d.setitem_with_hash(key, h, value)
+
 # ____________________________________________________________
 
 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
@@ -597,8 +597,6 @@
         d = {i+.0: 5, i+.5: 6}
         total = 0
         for k, h in iterkeys_with_hash(d):
-            print k, h
-            print compute_hash(k)
             total += k * h
         total -= (i + 0.0) * compute_hash(i + 0.0)
         total -= (i + 0.5) * compute_hash(i + 0.5)
@@ -618,6 +616,17 @@
     f(29)
     interpret(f, [29])
 
+def test_setitem_with_hash():
+    def f(i):
+        d = {}
+        setitem_with_hash(d, i+.5, compute_hash(i+.5), 42)
+        setitem_with_hash(d, i+.6, compute_hash(i+.6), -612)
+        return d[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
@@ -369,6 +369,16 @@
         return hop.gendirectcall(ll_dict_contains_with_hash,
                                  v_dict, v_key, v_hash)
 
+    def rtype_method_setitem_with_hash(self, hop):
+        v_dict, v_key, v_hash, v_value = hop.inputargs(
+            self, self.key_repr, lltype.Signed, self.value_repr)
+        if self.custom_eq_hash:
+            hop.exception_is_here()
+        else:
+            hop.exception_cannot_occur()
+        hop.gendirectcall(ll_dict_setitem_with_hash,
+                          v_dict, v_key, v_hash, v_value)
+
 class __extend__(pairtype(OrderedDictRepr, rmodel.Repr)):
 
     def rtype_getitem((r_dict, r_key), hop):
@@ -563,6 +573,10 @@
     index = d.lookup_function(d, key, hash, FLAG_STORE)
     return _ll_dict_setitem_lookup_done(d, key, value, hash, index)
 
+def ll_dict_setitem_with_hash(d, key, hash, value):
+    index = d.lookup_function(d, key, hash, FLAG_STORE)
+    return _ll_dict_setitem_lookup_done(d, key, value, hash, index)
+
 # It may be safe to look inside always, it has a few branches though, and their
 # frequencies needs to be investigated.
 @jit.look_inside_iff(lambda d, key, value, hash, i: jit.isvirtual(d) and 
jit.isconstant(key))
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to