def stash(uv_t, obj): # uv_t = rffi.cast(struct, uv_t) index = theStash.put(obj) uv_t.c_data = rffi.cast(rffi.VOIDP, index) log(["uv"], u"Stash %s: Storing 0x%x to %d (0x%x)" % (name.decode("utf-8"), current_object_addr_as_int(obj), intmask(index), current_object_addr_as_int(uv_t)))
def stash(uv_t, obj): # uv_t = rffi.cast(struct, uv_t) index = theStash.put(obj) uv_t.c_data = rffi.cast(rffi.VOIDP, index) log(["uv"], u"Stash %s: Storing 0x%x to %d (0x%x)" % (name.decode("utf-8"), current_object_addr_as_int(obj), intmask(index), current_object_addr_as_int(uv_t)))
def unstash(uv_t): # uv_t = rffi.cast(struct, uv_t) index = rffi.cast(rffi.INT, uv_t.c_data) obj = theStash.get(index) log(["uv"], u"Stash %s: Getting 0x%x from %d (0x%x)" % (name.decode("utf-8"), current_object_addr_as_int(obj), intmask(index), current_object_addr_as_int(uv_t))) return obj
def unstash(uv_t): # uv_t = rffi.cast(struct, uv_t) index = rffi.cast(rffi.INT, uv_t.c_data) obj = theStash.get(index) log(["uv"], u"Stash %s: Getting 0x%x from %d (0x%x)" % (name.decode("utf-8"), current_object_addr_as_int(obj), intmask(index), current_object_addr_as_int(uv_t))) return obj
def fn(): a1 = A() a2 = A() return ( compute_unique_id(a1), current_object_addr_as_int(a1), compute_unique_id(a2), current_object_addr_as_int(a2), )
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 _find_map_attr_cache(self, selector): space = self.space cache = space.fromcache(MapAttrCache) SHIFT2 = r_uint.BITS - space.config.objspace.std.methodcachesizeexp SHIFT1 = SHIFT2 - 5 attrs_as_int = objectmodel.current_object_addr_as_int(self) # ^^^Note: see comment in typeobject.py for # _pure_lookup_where_with_method_cache() hash_selector = objectmodel.compute_hash(selector) product = intmask(attrs_as_int * hash_selector) attr_hash = (r_uint(product) ^ (r_uint(product) << SHIFT1)) >> SHIFT2 # ^^^Note2: same comment too cached_attr = cache.attrs[attr_hash] if cached_attr is self: cached_selector = cache.selectors[attr_hash] if cached_selector == selector: attr = cache.cached_attrs[attr_hash] if space.config.objspace.std.withmethodcachecounter: name = selector[0] cache.hits[name] = cache.hits.get(name, 0) + 1 return attr attr = self._find_map_attr(selector) cache.attrs[attr_hash] = self cache.selectors[attr_hash] = selector cache.cached_attrs[attr_hash] = attr if space.config.objspace.std.withmethodcachecounter: name = selector[0] cache.misses[name] = cache.misses.get(name, 0) + 1 return attr
def _find_map_attr_cache(self, selector): space = self.space cache = space.fromcache(MapAttrCache) SHIFT2 = r_uint.BITS - space.config.objspace.std.methodcachesizeexp SHIFT1 = SHIFT2 - 5 attrs_as_int = objectmodel.current_object_addr_as_int(self) # ^^^Note: see comment in typeobject.py for # _pure_lookup_where_with_method_cache() hash_selector = objectmodel.compute_hash(selector) product = intmask(attrs_as_int * hash_selector) attr_hash = (r_uint(product) ^ (r_uint(product) << SHIFT1)) >> SHIFT2 # ^^^Note2: same comment too cached_attr = cache.attrs[attr_hash] if cached_attr is self: cached_selector = cache.selectors[attr_hash] if cached_selector == selector: attr = cache.cached_attrs[attr_hash] if space.config.objspace.std.withmethodcachecounter: name = selector[0] cache.hits[name] = cache.hits.get(name, 0) + 1 return attr attr = self._find_map_attr(selector) cache.attrs[attr_hash] = self cache.selectors[attr_hash] = selector cache.cached_attrs[attr_hash] = attr if space.config.objspace.std.withmethodcachecounter: name = selector[0] cache.misses[name] = cache.misses.get(name, 0) + 1 return attr
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 find_map_attr(self, name, index): # attr cache space = self.space cache = space.fromcache(MapAttrCache) SHIFT2 = r_uint.BITS - space.config.objspace.std.methodcachesizeexp SHIFT1 = SHIFT2 - 5 attrs_as_int = objectmodel.current_object_addr_as_int(self) # ^^^Note: see comment in typeobject.py for # _pure_lookup_where_with_method_cache() # unrolled hash computation for 2-tuple c1 = 0x345678 c2 = 1000003 hash_name = objectmodel.compute_hash(name) hash_selector = intmask((c2 * ((c2 * c1) ^ hash_name)) ^ index) product = intmask(attrs_as_int * hash_selector) attr_hash = (r_uint(product) ^ (r_uint(product) << SHIFT1)) >> SHIFT2 # ^^^Note2: same comment too cached_attr = cache.attrs[attr_hash] if cached_attr is self: cached_name = cache.names[attr_hash] cached_index = cache.indexes[attr_hash] if cached_name == name and cached_index == index: attr = cache.cached_attrs[attr_hash] if space.config.objspace.std.withmethodcachecounter: cache.hits[name] = cache.hits.get(name, 0) + 1 return attr attr = self._find_map_attr(name, index) cache.attrs[attr_hash] = self cache.names[attr_hash] = name cache.indexes[attr_hash] = index cache.cached_attrs[attr_hash] = attr if space.config.objspace.std.withmethodcachecounter: cache.misses[name] = cache.misses.get(name, 0) + 1 return attr
def fn(): d2 = D() return str((compute_hash(d2), current_object_addr_as_int(d2), compute_hash(c), compute_hash(d), compute_hash(("Hi", None, (7.5, 2, d)))))
def _find_map_attr_cache(self, name, index): space = self.space cache = space.fromcache(MapAttrCache) SHIFT2 = r_uint.BITS - space.config.objspace.std.methodcachesizeexp SHIFT1 = SHIFT2 - 5 attrs_as_int = objectmodel.current_object_addr_as_int(self) # ^^^Note: see comment in typeobject.py for # _pure_lookup_where_with_method_cache() # unrolled hash computation for 2-tuple c1 = 0x345678 c2 = 1000003 hash_name = objectmodel.compute_hash(name) hash_selector = intmask((c2 * ((c2 * c1) ^ hash_name)) ^ index) product = intmask(attrs_as_int * hash_selector) attr_hash = (r_uint(product) ^ (r_uint(product) << SHIFT1)) >> SHIFT2 # ^^^Note2: same comment too cached_attr = cache.attrs[attr_hash] if cached_attr is self: cached_name = cache.names[attr_hash] cached_index = cache.indexes[attr_hash] if cached_name == name and cached_index == index: attr = cache.cached_attrs[attr_hash] if space.config.objspace.std.withmethodcachecounter: cache.hits[name] = cache.hits.get(name, 0) + 1 return attr attr = self._find_map_attr(name, index) cache.attrs[attr_hash] = self cache.names[attr_hash] = name cache.indexes[attr_hash] = index cache.cached_attrs[attr_hash] = attr if space.config.objspace.std.withmethodcachecounter: cache.misses[name] = cache.misses.get(name, 0) + 1 return attr
def test_current_object_addr_as_int(): from rpython.rlib.rarithmetic import intmask class Foo(object): pass foo = Foo() assert current_object_addr_as_int(foo) == intmask(id(foo))
def entry_point(loops): g = rpystone.g g.IntGlob = 0 g.BoolGlob = 0 g.Char1Glob = '\0' g.Char2Glob = '\0' for i in range(51): g.Array1Glob[i] = 0 for i in range(51): for j in range(51): g.Array2Glob[i][j] = 0 g.PtrGlb = None g.PtrGlbNext = None return rpystone.pystones(loops), current_object_addr_as_int(g)
def entry_point(loops): g = rpystone.g g.IntGlob = 0 g.BoolGlob = 0 g.Char1Glob = '\0' g.Char2Glob = '\0' for i in range(51): g.Array1Glob[i] = 0 for i in range(51): for j in range(51): g.Array2Glob[i][j] = 0 g.PtrGlb = None g.PtrGlbNext = None return rpystone.pystones(loops), current_object_addr_as_int(g)
def must_compile(self, deadframe, metainterp_sd, jitdriver_sd): jitcounter = metainterp_sd.warmrunnerdesc.jitcounter # if self.status & (self.ST_BUSY_FLAG | self.ST_TYPE_MASK) == 0: # common case: this is not a guard_value, and we are not # already busy tracing. The rest of self.status stores a # valid per-guard index in the jitcounter. hash = self.status assert hash == (self.status & self.ST_SHIFT_MASK) # # do we have the BUSY flag? If so, we're tracing right now, e.g. in an # outer invocation of the same function, so don't trace again for now. elif self.status & self.ST_BUSY_FLAG: return False # else: # we have a GUARD_VALUE that fails. from rpython.rlib.objectmodel import current_object_addr_as_int index = intmask(self.status >> self.ST_SHIFT) typetag = intmask(self.status & self.ST_TYPE_MASK) # fetch the actual value of the guard_value, possibly turning # it to an integer if typetag == self.TY_INT: intval = metainterp_sd.cpu.get_value_direct( deadframe, 'i', index) elif typetag == self.TY_REF: refval = metainterp_sd.cpu.get_value_direct( deadframe, 'r', index) intval = lltype.cast_ptr_to_int(refval) elif typetag == self.TY_FLOAT: floatval = metainterp_sd.cpu.get_value_direct( deadframe, 'f', index) intval = longlong.gethash_fast(floatval) else: assert 0, typetag if not we_are_translated(): if isinstance(intval, llmemory.AddressAsInt): intval = llmemory.cast_adr_to_int( llmemory.cast_int_to_adr(intval), "forced") hash = r_uint( current_object_addr_as_int(self) * 777767777 + intval * 1442968193) # increment = jitdriver_sd.warmstate.increment_trace_eagerness return jitcounter.tick(hash, increment)
def must_compile(self, deadframe, metainterp_sd, jitdriver_sd): jitcounter = metainterp_sd.warmrunnerdesc.jitcounter # if self.status & (self.ST_BUSY_FLAG | self.ST_TYPE_MASK) == 0: # common case: this is not a guard_value, and we are not # already busy tracing. The rest of self.status stores a # valid per-guard index in the jitcounter. hash = self.status assert hash == (self.status & self.ST_SHIFT_MASK) # # do we have the BUSY flag? If so, we're tracing right now, e.g. in an # outer invocation of the same function, so don't trace again for now. elif self.status & self.ST_BUSY_FLAG: return False # else: # we have a GUARD_VALUE that fails. from rpython.rlib.objectmodel import current_object_addr_as_int index = intmask(self.status >> self.ST_SHIFT) typetag = intmask(self.status & self.ST_TYPE_MASK) # fetch the actual value of the guard_value, possibly turning # it to an integer if typetag == self.TY_INT: intval = metainterp_sd.cpu.get_value_direct(deadframe, 'i', index) elif typetag == self.TY_REF: refval = metainterp_sd.cpu.get_value_direct(deadframe, 'r', index) intval = lltype.cast_ptr_to_int(refval) elif typetag == self.TY_FLOAT: floatval = metainterp_sd.cpu.get_value_direct(deadframe, 'f', index) intval = longlong.gethash_fast(floatval) else: assert 0, typetag if not we_are_translated(): if isinstance(intval, llmemory.AddressAsInt): intval = llmemory.cast_adr_to_int( llmemory.cast_int_to_adr(intval), "forced") hash = r_uint(current_object_addr_as_int(self) * 777767777 + intval * 1442968193) # increment = jitdriver_sd.warmstate.increment_trace_eagerness return jitcounter.tick(hash, increment)
def _pure_lookup_where_with_method_cache(w_self, name, version_tag): space = w_self.space cache = space.fromcache(MethodCache) SHIFT2 = r_uint.BITS - space.config.objspace.std.methodcachesizeexp SHIFT1 = SHIFT2 - 5 version_tag_as_int = current_object_addr_as_int(version_tag) # ^^^Note: if the version_tag object is moved by a moving GC, the # existing method cache entries won't be found any more; new # entries will be created based on the new address. The # assumption is that the version_tag object won't keep moving all # the time - so using the fast current_object_addr_as_int() instead # of a slower solution like hash() is still a good trade-off. hash_name = compute_hash(name) product = intmask(version_tag_as_int * hash_name) method_hash = (r_uint(product) ^ (r_uint(product) << SHIFT1)) >> SHIFT2 # ^^^Note2: we used to just take product>>SHIFT2, but on 64-bit # platforms SHIFT2 is really large, and we loose too much information # that way (as shown by failures of the tests that typically have # method names like 'f' who hash to a number that has only ~33 bits). cached_version_tag = cache.versions[method_hash] if cached_version_tag is version_tag: cached_name = cache.names[method_hash] if cached_name is name: tup = cache.lookup_where[method_hash] if space.config.objspace.std.withmethodcachecounter: cache.hits[name] = cache.hits.get(name, 0) + 1 # print "hit", w_self, name return tup tup = w_self._lookup_where_all_typeobjects(name) cache.versions[method_hash] = version_tag cache.names[method_hash] = name cache.lookup_where[method_hash] = tup if space.config.objspace.std.withmethodcachecounter: cache.misses[name] = cache.misses.get(name, 0) + 1 # print "miss", w_self, name return tup
def _pure_lookup_where_with_method_cache(w_self, name, version_tag): space = w_self.space cache = space.fromcache(MethodCache) SHIFT2 = r_uint.BITS - space.config.objspace.std.methodcachesizeexp SHIFT1 = SHIFT2 - 5 version_tag_as_int = current_object_addr_as_int(version_tag) # ^^^Note: if the version_tag object is moved by a moving GC, the # existing method cache entries won't be found any more; new # entries will be created based on the new address. The # assumption is that the version_tag object won't keep moving all # the time - so using the fast current_object_addr_as_int() instead # of a slower solution like hash() is still a good trade-off. hash_name = compute_hash(name) product = intmask(version_tag_as_int * hash_name) method_hash = (r_uint(product) ^ (r_uint(product) << SHIFT1)) >> SHIFT2 # ^^^Note2: we used to just take product>>SHIFT2, but on 64-bit # platforms SHIFT2 is really large, and we loose too much information # that way (as shown by failures of the tests that typically have # method names like 'f' who hash to a number that has only ~33 bits). cached_version_tag = cache.versions[method_hash] if cached_version_tag is version_tag: cached_name = cache.names[method_hash] if cached_name is name: tup = cache.lookup_where[method_hash] if space.config.objspace.std.withmethodcachecounter: cache.hits[name] = cache.hits.get(name, 0) + 1 # print "hit", w_self, name return tup tup = w_self._lookup_where_all_typeobjects(name) cache.versions[method_hash] = version_tag cache.names[method_hash] = name cache.lookup_where[method_hash] = tup if space.config.objspace.std.withmethodcachecounter: cache.misses[name] = cache.misses.get(name, 0) + 1 # print "miss", w_self, name return tup
def fn(): a1 = A() a2 = A() return (compute_unique_id(a1), current_object_addr_as_int(a1), compute_unique_id(a2), current_object_addr_as_int(a2))
def f(): x = FooBar() # on lltype, the RPython-level repr of an instance contains the # current object address return current_object_addr_as_int(x), str(x)
def f(): d2 = D() return (compute_identity_hash(d2), current_object_addr_as_int(d2), compute_identity_hash(c), compute_identity_hash(d))
def f(): x = FooBar() # on lltype, the RPython-level repr of an instance contains the # current object address return current_object_addr_as_int(x), str(x)
def test_current_object_addr_as_int(): from rpython.rlib.rarithmetic import intmask class Foo(object): pass foo = Foo() assert current_object_addr_as_int(foo) == intmask(id(foo))
def fn(): d2 = D() return str((compute_hash(d2), current_object_addr_as_int(d2), compute_hash(c), compute_hash(d), compute_hash(("Hi", None, (7.5, 2, d)))))
def f(): d2 = D() return (compute_identity_hash(d2), current_object_addr_as_int(d2), compute_identity_hash(c), compute_identity_hash(d))