def test_hash_preservation(self): from rpython.rlib.objectmodel import current_object_addr_as_int from rpython.rlib.objectmodel import compute_identity_hash class C: pass class D(C): pass c = C() d = D() h_c = compute_identity_hash(c) h_d = compute_identity_hash(d) # def f(): d2 = D() return (compute_identity_hash(d2), current_object_addr_as_int(d2), compute_identity_hash(c), compute_identity_hash(d)) res = self.interpret(f, []) # xxx the following test is too precise, checking the exact # implementation. On Python 2.7 it doesn't work anyway, because # object.__hash__(x) is different from id(x). The test is disabled # for now, and nobody should rely on compute_identity_hash() returning # a value that is (or was) the current_object_addr_as_int(). # --- disabled: assert res.item0 == res.item1 # the following property is essential on top of the lltypesystem # otherwise prebuilt dictionaries are broken. assert res.item2 == h_c assert res.item3 == h_d
def main(argv): print[ objectmodel.compute_identity_hash(argv), objectmodel.compute_identity_hash(argv), objectmodel.compute_identity_hash(argv) ] return 9
def _func_key_hash(unique_cache, fargs, fresult, ellipsis, abi): x = compute_identity_hash(fresult) for w_arg in fargs: y = compute_identity_hash(w_arg) x = intmask((1000003 * x) ^ y) x ^= (ellipsis - abi) if unique_cache.for_testing: # constant-folded to False in translation; x &= 3 # but for test, keep only 2 bits of hash return x
def _func_key_hash(unique_cache, fargs, fresult, ellipsis, abi): x = compute_identity_hash(fresult) for w_arg in fargs: y = compute_identity_hash(w_arg) x = intmask((1000003 * x) ^ y) x ^= ellipsis + 2 * abi if unique_cache.for_testing: # constant-folded to False in translation; x &= 3 # but for test, keep only 2 bits of hash return x
def fn(): objects = [] hashes = [] for i in range(200): rgc.collect(0) # nursery-only collection, if possible obj = A() objects.append(obj) hashes.append(compute_identity_hash(obj)) unique = {} for i in range(len(objects)): assert compute_identity_hash(objects[i]) == hashes[i] unique[hashes[i]] = None return len(unique)
def f1(): d2 = D() # xxx we assume that current_object_addr_as_int is defined as # simply returning the identity hash current_identityhash = current_object_addr_as_int(d2) instance_hash = compute_identity_hash(d2) return current_identityhash == instance_hash
def define_hash_preservation(cls): class C: pass class D(C): pass c = C() d = D() h_d = compute_hash(d) # force to be cached on 'd', but not on 'c' h_t = compute_hash(("Hi", None, (7.5, 2, d))) S = lltype.GcStruct('S', ('x', lltype.Signed), ('a', lltype.Array(lltype.Signed))) s = lltype.malloc(S, 15, zero=True) h_s = compute_identity_hash(s) # varsized: hash not saved/restored # def f(): if compute_hash(c) != compute_identity_hash(c): return 12 if compute_hash(d) != h_d: return 13 if compute_hash(("Hi", None, (7.5, 2, d))) != h_t: return 14 c2 = C() h_c2 = compute_hash(c2) if compute_hash(c2) != h_c2: return 15 if compute_identity_hash(s) == h_s: return 16 # unlikely i = 0 while i < 6: rgc.collect() if compute_hash(c2) != h_c2: return i i += 1 return 42 return f
def test_compute_identity_hash(): class Foo(object): def __hash__(self): return 42 foo = Foo() h = compute_identity_hash(foo) assert h == object.__hash__(foo) assert h == getattr(foo, '__precomputed_identity_hash')
def hash(self): """ Create a conservative integer hash of this object. If two objects are equal, then they must hash equal. """ return compute_identity_hash(self)
def test_compute_identity_hash(): class Foo(object): def __hash__(self): return 42 foo = Foo() h = compute_identity_hash(foo) assert h == object.__hash__(foo)
def ll_set_null(d, llkey): hash = compute_identity_hash(llkey) 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 # the entry must still be marked as everused(). d.entries[i].key = llmemory.dead_wref d.entries[i].value = NULLVALUE
def build(xr, n): "Build the identity hashes of all n objects of the chain." i = 0 while i < n: xr.hash = compute_identity_hash(xr) # ^^^ likely to trigger a collection xr = xr.prev i += 1 assert xr is None
def ll_get(d, llkey): hash = compute_identity_hash(llkey) 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)) # NB. ll_valid() above was just called at least on entry i, so if # it is an invalid entry with a dead weakref, the value was reset # to NULLVALUE. return d.entries[i].value
def ll_get(d, llkey): hash = compute_identity_hash(llkey) 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)) # NB. ll_valid() above was just called at least on entry i, so if # it is an invalid entry with a dead weakref, the value was reset # to NULLVALUE. return d.entries[i].value
def check(xr, n, step): "Check that the identity hashes are still correct." i = 0 while i < n: if xr.hash != compute_identity_hash(xr): os.write(2, "wrong hash! i=%d, n=%d, step=%d\n" % (i, n, step)) raise ValueError xr = xr.prev i += 1 assert xr is None
def f(): if compute_hash(c) != compute_identity_hash(c): return 12 if compute_hash(d) != h_d: return 13 if compute_hash(("Hi", None, (7.5, 2, d))) != h_t: return 14 c2 = C() h_c2 = compute_hash(c2) if compute_hash(c2) != h_c2: return 15 if compute_identity_hash(s) == h_s: return 16 # unlikely i = 0 while i < 6: rgc.collect() if compute_hash(c2) != h_c2: return i i += 1 return 42
def descr_hash(self, space): w_func = self.getattr(space, "__hash__", False) if w_func is None: w_eq = self.getattr(space, "__eq__", False) w_cmp = self.getattr(space, "__cmp__", False) if w_eq is not None or w_cmp is not None: raise OperationError(space.w_TypeError, space.wrap("unhashable instance")) else: return space.wrap(compute_identity_hash(self)) w_ret = space.call_function(w_func) if not space.isinstance_w(w_ret, space.w_int) and not space.isinstance_w(w_ret, space.w_long): raise OperationError(space.w_TypeError, space.wrap("__hash__ must return int or long")) return w_ret
def descr_hash(self, space): w_func = self.getattr(space, '__hash__', False) if w_func is None: w_eq = self.getattr(space, '__eq__', False) w_cmp = self.getattr(space, '__cmp__', False) if w_eq is not None or w_cmp is not None: raise oefmt(space.w_TypeError, "unhashable instance") else: return space.newint(compute_identity_hash(self)) w_ret = space.call_function(w_func) if (not space.isinstance_w(w_ret, space.w_int) and not space.isinstance_w(w_ret, space.w_long)): raise oefmt(space.w_TypeError, "__hash__ must return int or long") return w_ret
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) & rdict.MASK everused = d.entries.everused(i) d.entries[i].key = keyref d.entries[i].value = llvalue d.entries[i].f_hash = hash #llop.debug_print(lltype.Void, i, 'stored', hex(hash), # ll_debugrepr(llkey), # ll_debugrepr(llvalue)) if not everused: d.resize_counter -= 3 if d.resize_counter <= 0: #llop.debug_print(lltype.Void, 'RESIZE') ll_weakdict_resize(d)
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) & rdict.MASK everused = d.entries.everused(i) d.entries[i].key = keyref d.entries[i].value = llvalue d.entries[i].f_hash = hash # llop.debug_print(lltype.Void, i, 'stored', hex(hash), # ll_debugrepr(llkey), # ll_debugrepr(llvalue)) if not everused: d.resize_counter -= 3 if d.resize_counter <= 0: # llop.debug_print(lltype.Void, 'RESIZE') ll_weakdict_resize(d)
def computeHash(self, depth): """ Compute the sameness hash. This is the correct method to override to customize the sameness hash. Transparent objects are expected to customize their sameness hash. The `depth` parameter controls how many levels of structural recursion a nested object should include in the hash. """ from typhon.objects.auditors import selfless, transparentStamp stamps = self.auditorStamps() if selfless in stamps and transparentStamp in stamps: return self.call(u"_uncall", []).computeHash(depth) # Here, if it existed, would lie Semitransparent hashing. return compute_identity_hash(self)
def f(i): assert compute_hash(i) == compute_hash(42) assert compute_hash(i + 1.0) == compute_hash(43.0) assert compute_hash("Hello" + str(i)) == compute_hash("Hello42") if i == 42: p = None else: p = Foo() assert compute_hash(p) == compute_hash(None) assert (compute_hash(("world", None, i, 7.5)) == compute_hash( ("world", None, 42, 7.5))) q = Foo() assert compute_hash(q) == compute_identity_hash(q) from rpython.rlib.rfloat import INFINITY, NAN assert compute_hash(INFINITY) == 314159 assert compute_hash(-INFINITY) == -271828 assert compute_hash(NAN) == 0 return i * 2
def f(i): assert compute_hash(i) == compute_hash(42) assert compute_hash(i + 1.0) == compute_hash(43.0) assert compute_hash("Hello" + str(i)) == compute_hash("Hello42") if i == 42: p = None else: p = Foo() assert compute_hash(p) == compute_hash(None) assert (compute_hash(("world", None, i, 7.5)) == compute_hash(("world", None, 42, 7.5))) q = Foo() assert compute_hash(q) == compute_identity_hash(q) from rpython.rlib.rfloat import INFINITY, NAN assert compute_hash(INFINITY) == 314159 assert compute_hash(-INFINITY) == -271828 assert compute_hash(NAN) == 0 return i * 2
def _func_key_hash((fargs, w_fresult, ellipsis)): x = compute_identity_hash(w_fresult) ^ ellipsis for w_arg in fargs: y = compute_identity_hash(w_arg) x = intmask((1000003 * x) ^ y) return x
def _get_hash_(self): return compute_identity_hash(self)
def fringeHash(self): return compute_identity_hash(self.identity) ^ hashFringePath(self.path)
def samenessHash(obj, depth, path, fringe): """ Generate a hash code for an object that may not be completely settled. Equality of hash code implies sameness of objects. The generated hash is valid until settledness of a component changes. """ if depth <= 0: # not gonna look any further for the purposes of hash computation, but # we do have to know about unsettled refs if samenessFringe(obj, path, fringe): # obj is settled. return -1 elif fringe is None: raise userError(u"Must be settled") else: # not settled. return -1 o = resolution(obj) if o is NullObject: return 0 # Objects that do their own hashing. if ( isinstance(o, BoolObject) or isinstance(o, CharObject) or isinstance(o, DoubleObject) or isinstance(o, IntObject) or isinstance(o, BigInt) or isinstance(o, StrObject) or isinstance(o, BytesObject) or isinstance(o, TraversalKey) ): return o.hash() # Lists. if isinstance(o, ConstList): oList = unwrapList(o) result = len(oList) for i, x in enumerate(oList): if fringe is None: fr = None else: fr = FringePath(i, path) result ^= i ^ samenessHash(x, depth - 1, fr, fringe) return result # The empty map. (Uncalls contain maps, thus this base case.) if isinstance(o, ConstMap) and len(o.objectMap) == 0: return 127 from typhon.objects.proxy import FarRef, DisconnectedRef if isinstance(o, FarRef) or isinstance(o, DisconnectedRef): return samenessHash(o.handler, depth, path, fringe) # Other objects compared by structure. if selfless in o.auditorStamps(): if transparentStamp in o.auditorStamps(): return samenessHash(o.call(u"_uncall", []), depth, path, fringe) # XXX Semitransparent support goes here # Objects compared by identity. if isResolved(o): return compute_identity_hash(o) elif fringe is None: raise userError(u"Must be settled") # Unresolved refs. fringe.append(FringeNode(o, path)) return -1
def descrlist_hash(l): res = 0x345678 for descr in l: y = compute_identity_hash(descr) res = intmask((1000003 * res) ^ y) return res
def ll_debugrepr(x): if x: h = compute_identity_hash(x) else: h = 0 return "<%x>" % (h,)
def method_hash(self, space): return space.newint(compute_identity_hash(self))
def ll_debugrepr(x): if x: h = compute_identity_hash(x) else: h = 0 return '<%x>' % (h, )
def _hashcode(ivkbl, frame, interpreter): rcvr = frame.pop() frame.push(interpreter.get_universe().new_integer( compute_identity_hash(rcvr.get_embedded_string())))
def hash(self): import pixie.vm.rt as rt return rt.wrap(compute_identity_hash(self))
def hash(self): return compute_identity_hash(self.content)
def samenessHash(obj, depth, path, fringe): """ Generate a hash code for an object that may not be completely settled. Equality of hash code implies sameness of objects. The generated hash is valid until settledness of a component changes. """ if depth <= 0: # not gonna look any further for the purposes of hash computation, but # we do have to know about unsettled refs if samenessFringe(obj, path, fringe): # obj is settled. return -1 elif fringe is None: raise userError(u"Must be settled") else: # not settled. return -1 o = resolution(obj) if o is NullObject: return 0 # Objects that do their own hashing. if (isinstance(o, BoolObject) or isinstance(o, CharObject) or isinstance(o, DoubleObject) or isinstance(o, IntObject) or isinstance(o, BigInt) or isinstance(o, StrObject) or isinstance(o, BytesObject) or isinstance(o, TraversalKey)): return o.hash() # Lists. if isinstance(o, ConstList): oList = unwrapList(o) result = len(oList) for i, x in enumerate(oList): if fringe is None: fr = None else: fr = FringePath(i, path) result ^= i ^ samenessHash(x, depth - 1, fr, fringe) return result # The empty map. (Uncalls contain maps, thus this base case.) if isinstance(o, ConstMap) and len(o.objectMap) == 0: return 127 from typhon.objects.proxy import FarRef, DisconnectedRef if isinstance(o, FarRef) or isinstance(o, DisconnectedRef): return samenessHash(o.handler, depth, path, fringe) # Other objects compared by structure. if selfless in o.auditorStamps(): if transparentStamp in o.auditorStamps(): return samenessHash(o.call(u"_uncall", []), depth, path, fringe) # XXX Semitransparent support goes here # Objects compared by identity. if isResolved(o): return compute_identity_hash(o) elif fringe is None: raise userError(u"Must be settled") # Unresolved refs. fringe.append(FringeNode(o, path)) return -1
def _hashcode(ivkbl, rcvr, args, meta_level): return ivkbl.get_universe().new_integer(compute_identity_hash(rcvr))
def f(n): z = Z() got = my_gethash(z) expected = compute_identity_hash(z) return got - expected
def f(): d2 = D() return (compute_identity_hash(d2), compute_identity_hash(c), compute_identity_hash(d))
def default_identity_hash(space, w_obj): w_unique_id = w_obj.immutable_unique_id(space) if w_unique_id is None: # common case return space.wrap(compute_identity_hash(w_obj)) else: return space.hash(w_unique_id)
def computeHash(self, depth): return compute_identity_hash(self)
def f(): d2 = D() return (compute_identity_hash(d2), current_object_addr_as_int(d2), compute_identity_hash(c), compute_identity_hash(d))
def samenessHash(obj, depth, fringe, path=None): """ Generate a hash code for an object that may not be completely settled. If two objects are the same, then they will have identical hashes. The generated hash is valid until settledness of a component changes. """ if depth <= 0: # not gonna look any further for the purposes of hash computation, but # we do have to know about unsettled refs if samenessFringe(obj, path, fringe): # obj is settled. return -1 elif fringe is None: raise userError(u"Must be settled") else: # not settled. return -1 o = resolution(obj) # The constants have their own special hash values. if o is NullObject: return 0 if o is TrueObject: return 1 if o is FalseObject: return 2 # Objects that do their own hashing. if (isinstance(o, CharObject) or isinstance(o, DoubleObject) or isinstance(o, IntObject) or isinstance(o, BigInt) or isinstance(o, StrObject) or isinstance(o, BytesObject) or isinstance(o, TraversalKey)): return o.computeHash(depth) # Lists. if isinstance(o, ConstList): oList = unwrapList(o) result = len(oList) for i, x in enumerate(oList): if fringe is None: fr = None else: fr = FringePath(i, path) result ^= i ^ samenessHash(x, depth - 1, fringe, path=fr) return result # The empty map. (Uncalls contain maps, thus this base case.) if isinstance(o, ConstMap) and o.empty(): return 127 from typhon.objects.proxy import FarRef, DisconnectedRef if isinstance(o, FarRef) or isinstance(o, DisconnectedRef): return samenessHash(o.handler, depth, fringe, path=path) # Other objects compared by structure. if selfless in o.auditorStamps(): if transparentStamp in o.auditorStamps(): return samenessHash(o.call(u"_uncall", []), depth, fringe, path=path) if semitransparentStamp in o.auditorStamps(): p = o.call(u"_uncall", []) if not isinstance(p, SealedPortrayal): userError( u'Semitransparent portrayal was not a SealedPortrayal!') return samenessHash(p.portrayal, depth, fringe, path=path) # Objects compared by identity. if isResolved(o): return compute_identity_hash(o) elif fringe is None: raise userError(u"Must be settled") # Unresolved refs. fringe.append(FringeNode(o, path)) return -1