Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit