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