Read about our upcoming Code of Conduct on this issue

Commit aadf85f0 authored by Armin Rigo's avatar Armin Rigo
Browse files

(untested) remove some code that implements keeping the hashes across translation

--HG--
branch : rpython-hash
parent 8d1318904037
......@@ -117,9 +117,7 @@ GCFLAG_VISITED = first_gcflag << 2
# The following flag is set on nursery objects of which we asked the id
# or the identityhash. It means that a space of the size of the object
# has already been allocated in the nonmovable part. The same flag is
# abused to mark prebuilt objects whose hash has been taken during
# translation and is statically recorded.
# has already been allocated in the nonmovable part.
GCFLAG_HAS_SHADOW = first_gcflag << 3
# The following flag is set temporarily on some objects during a major
......@@ -208,10 +206,6 @@ class IncrementalMiniMarkGC(MovingGCBase):
# by GCFLAG_xxx above.
HDR = lltype.Struct('header', ('tid', lltype.Signed))
typeid_is_in_field = 'tid'
withhash_flag_is_in_field = 'tid', GCFLAG_HAS_SHADOW
# ^^^ prebuilt objects may have the flag GCFLAG_HAS_SHADOW;
# then they are one word longer, the extra word storing the hash.
# During a minor collection, the objects in the nursery that are
# moved outside are changed in-place: their header is replaced with
......@@ -2640,40 +2634,22 @@ class IncrementalMiniMarkGC(MovingGCBase):
return shadow
_find_shadow._dont_inline_ = True
@specialize.arg(2)
def id_or_identityhash(self, gcobj, is_hash):
def id_or_identityhash(self, gcobj):
"""Implement the common logic of id() and identityhash()
of an object, given as a GCREF.
"""
obj = llmemory.cast_ptr_to_adr(gcobj)
#
if self.is_valid_gc_object(obj):
if self.is_in_nursery(obj):
obj = self._find_shadow(obj)
elif is_hash:
if self.header(obj).tid & GCFLAG_HAS_SHADOW:
#
# For identityhash(), we need a special case for some
# prebuilt objects: their hash must be the same before
# and after translation. It is stored as an extra word
# after the object. But we cannot use it for id()
# because the stored value might clash with a real one.
size = self.get_size(obj)
i = (obj + size).signed[0]
# Important: the returned value is not mangle_hash()ed!
return i
#
i = llmemory.cast_adr_to_int(obj)
if is_hash:
i = mangle_hash(i)
return i
return llmemory.cast_adr_to_int(obj)
id_or_identityhash._always_inline_ = True
def id(self, gcobj):
return self.id_or_identityhash(gcobj, False)
return self.id_or_identityhash(gcobj)
def identityhash(self, gcobj):
return self.id_or_identityhash(gcobj, True)
return mangle_hash(self.id_or_identityhash(gcobj))
# ----------
# Finalizers
......
......@@ -104,9 +104,7 @@ GCFLAG_VISITED = first_gcflag << 2
# The following flag is set on nursery objects of which we asked the id
# or the identityhash. It means that a space of the size of the object
# has already been allocated in the nonmovable part. The same flag is
# abused to mark prebuilt objects whose hash has been taken during
# translation and is statically recorded.
# has already been allocated in the nonmovable part.
GCFLAG_HAS_SHADOW = first_gcflag << 3
# The following flag is set temporarily on some objects during a major
......@@ -149,9 +147,6 @@ class MiniMarkGC(MovingGCBase):
# by GCFLAG_xxx above.
HDR = lltype.Struct('header', ('tid', lltype.Signed))
typeid_is_in_field = 'tid'
withhash_flag_is_in_field = 'tid', GCFLAG_HAS_SHADOW
# ^^^ prebuilt objects may have the flag GCFLAG_HAS_SHADOW;
# then they are one word longer, the extra word storing the hash.
_ADDRARRAY = lltype.Array(llmemory.Address, hints={'nolength': True})
......@@ -1868,40 +1863,22 @@ class MiniMarkGC(MovingGCBase):
return shadow
_find_shadow._dont_inline_ = True
@specialize.arg(2)
def id_or_identityhash(self, gcobj, is_hash):
def id_or_identityhash(self, gcobj):
"""Implement the common logic of id() and identityhash()
of an object, given as a GCREF.
"""
obj = llmemory.cast_ptr_to_adr(gcobj)
#
if self.is_valid_gc_object(obj):
if self.is_in_nursery(obj):
obj = self._find_shadow(obj)
elif is_hash:
if self.header(obj).tid & GCFLAG_HAS_SHADOW:
#
# For identityhash(), we need a special case for some
# prebuilt objects: their hash must be the same before
# and after translation. It is stored as an extra word
# after the object. But we cannot use it for id()
# because the stored value might clash with a real one.
size = self.get_size(obj)
i = (obj + size).signed[0]
# Important: the returned value is not mangle_hash()ed!
return i
#
i = llmemory.cast_adr_to_int(obj)
if is_hash:
i = mangle_hash(i)
return i
return llmemory.cast_adr_to_int(obj)
id_or_identityhash._always_inline_ = True
def id(self, gcobj):
return self.id_or_identityhash(gcobj, False)
return self.id_or_identityhash(gcobj)
def identityhash(self, gcobj):
return self.id_or_identityhash(gcobj, True)
return mangle_hash(self.id_or_identityhash(gcobj))
# ----------
# Finalizers
......
......@@ -48,9 +48,6 @@ class SemiSpaceGC(MovingGCBase):
HDR = lltype.Struct('header', ('tid', lltype.Signed)) # XXX or rffi.INT?
typeid_is_in_field = 'tid'
withhash_flag_is_in_field = 'tid', _GCFLAG_HASH_BASE * 0x2
# ^^^ prebuilt objects either have GC_HASH_TAKEN_ADDR or they
# have GC_HASH_HASFIELD (and then they are one word longer).
FORWARDSTUB = lltype.GcStruct('forwarding_stub',
('forw', llmemory.Address))
FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB)
......
......@@ -194,7 +194,6 @@ class BoehmGCTransformer(GCTransformer):
def gcheader_initdata(self, obj):
hdr = lltype.malloc(self.HDR, immortal=True)
#hdr.hash = lltype.identityhash_nocache(obj._as_ptr())
return hdr._obj
......
......@@ -610,18 +610,8 @@ class BaseFrameworkGCTransformer(GCTransformer):
def special_funcptr_for_type(self, TYPE):
return self.layoutbuilder.special_funcptr_for_type(TYPE)
def gc_header_for(self, obj, needs_hash=False):
def gc_header_for(self, obj):
hdr = self.gcdata.gc.gcheaderbuilder.header_of_object(obj)
withhash, flag = self.gcdata.gc.withhash_flag_is_in_field
x = getattr(hdr, withhash)
TYPE = lltype.typeOf(x)
x = lltype.cast_primitive(lltype.Signed, x)
if needs_hash:
x |= flag # set the flag in the header
else:
x &= ~flag # clear the flag in the header
x = lltype.cast_primitive(TYPE, x)
setattr(hdr, withhash, x)
return hdr
def get_hash_offset(self, T):
......@@ -1514,22 +1504,9 @@ class BaseFrameworkGCTransformer(GCTransformer):
def gcheader_initdata(self, obj):
o = lltype.top_container(obj)
needs_hash = self.get_prebuilt_hash(o) is not None
hdr = self.gc_header_for(o, needs_hash)
hdr = self.gc_header_for(o)
return hdr._obj
def DISABLED_get_prebuilt_hash(self, obj):
# for prebuilt objects that need to have their hash stored and
# restored. Note that only structures that are StructNodes all
# the way have their hash stored (and not e.g. structs with var-
# sized arrays at the end). 'obj' must be the top_container.
TYPE = lltype.typeOf(obj)
if not isinstance(TYPE, lltype.GcStruct):
return None
if TYPE._is_varsize():
return None
return getattr(obj, '_hash_cache_', None)
def get_finalizer_queue_index(self, hop):
fq_tag = hop.spaceop.args[0].value
assert 'FinalizerQueue TAG' in fq_tag.expr
......
......@@ -18,8 +18,7 @@ ADDRESS_VOID_FUNC = lltype.FuncType([llmemory.Address], lltype.Void)
class RefcountingGCTransformer(GCTransformer):
malloc_zero_filled = True
HDR = lltype.Struct("header", ("refcount", lltype.Signed),
("hash", lltype.Signed))
HDR = lltype.Struct("header", ("refcount", lltype.Signed))
def __init__(self, translator):
super(RefcountingGCTransformer, self).__init__(translator, inline=True)
......@@ -78,9 +77,7 @@ class RefcountingGCTransformer(GCTransformer):
def ll_identityhash(addr):
obj = llmemory.cast_adr_to_ptr(addr, HDRPTR)
h = obj.hash
if h == 0:
obj.hash = h = llmemory.cast_adr_to_int(addr)
h = llmemory.cast_adr_to_int(addr)
return h
if self.translator:
......@@ -178,7 +175,6 @@ class RefcountingGCTransformer(GCTransformer):
if not self.gcheaderbuilder.get_header(p):
hdr = self.gcheaderbuilder.new_header(p)
hdr.refcount = sys.maxint // 2
hdr.hash = lltype.identityhash_nocache(p)
def static_deallocation_funcptr_for_type(self, TYPE):
if TYPE in self.static_deallocator_funcptrs:
......
......@@ -374,9 +374,6 @@ class BaseGCTransformer(object):
return hop.cast_result(rmodel.inputconst(lltype.Ptr(ARRAY_TYPEID_MAP),
lltype.nullptr(ARRAY_TYPEID_MAP)))
def get_prebuilt_hash(self, obj):
return None
class MinimalGCTransformer(BaseGCTransformer):
def __init__(self, parenttransformer):
......
......@@ -484,17 +484,11 @@ def compute_identity_hash(x):
"""RPython equivalent of object.__hash__(x). This returns the
so-called 'identity hash', which is the non-overridable default hash
of Python. Can be called for any RPython-level object that turns
into a GC object, but not NULL. The value is not guaranteed to be the
same before and after translation, except for RPython instances on the
lltypesystem.
into a GC object, but not NULL. The value will be different before
and after translation.
"""
assert x is not None
result = object.__hash__(x)
try:
x.__dict__['__precomputed_identity_hash'] = result
except (TypeError, AttributeError):
pass
return result
return object.__hash__(x)
def compute_unique_id(x):
"""RPython equivalent of id(x). The 'x' must be an RPython-level
......
......@@ -1380,20 +1380,11 @@ class _abstract_ptr(object):
return callb(*args)
raise TypeError("%r instance is not a function" % (self._T,))
def _identityhash(self, cache=True):
def _identityhash(self):
p = normalizeptr(self)
try:
return p._obj._hash_cache_
except AttributeError:
assert self._T._gckind == 'gc'
assert self # not for NULL
result = hash(p._obj)
if cache:
try:
p._obj._hash_cache_ = result
except AttributeError:
pass
return result
assert self._T._gckind == 'gc'
assert self # not for NULL
return hash(p._obj)
class _ptr(_abstract_ptr):
__slots__ = ('_TYPE',
......@@ -1759,7 +1750,7 @@ def _get_empty_instance_of_struct_variety(flds):
class _struct(_parentable):
_kind = "structure"
__slots__ = ('_hash_cache_', '_compilation_info')
__slots__ = ('_compilation_info',)
def __new__(self, TYPE, n=None, initialization=None, parent=None,
parentindex=None):
......@@ -2442,24 +2433,6 @@ def ann_identityhash(s_obj):
return SomeInteger()
def identityhash_nocache(p):
"""Version of identityhash() to use from backends that don't care about
caching."""
assert p
return p._identityhash(cache=False)
def init_identity_hash(p, value):
"""For a prebuilt object p, initialize its hash value to 'value'."""
assert isinstance(typeOf(p), Ptr)
p = normalizeptr(p)
if not p:
raise ValueError("cannot change hash(NULL)!")
if hasattr(p._obj, '_hash_cache_'):
raise ValueError("the hash of %r was already computed" % (p,))
if typeOf(p).TO._is_varsize():
raise ValueError("init_identity_hash(): not for varsized types")
p._obj._hash_cache_ = intmask(value)
def isCompatibleType(TYPE1, TYPE2):
return TYPE1._is_compatible(TYPE2)
......
......@@ -785,7 +785,6 @@ class InstanceRepr(Repr):
def initialize_prebuilt_instance(self, value, classdef, result):
# must fill in the hash cache before the other ones
# (see test_circular_hash_initialization)
self.initialize_prebuilt_hash(value, result)
self._initialize_data_flattenrec(self.initialize_prebuilt_data,
value, classdef, result)
......@@ -943,11 +942,6 @@ class InstanceRepr(Repr):
rclass = getclassrepr(self.rtyper, classdef)
result.typeptr = rclass.getvtable()
def initialize_prebuilt_hash(self, value, result):
llattrvalue = getattr(value, '__precomputed_identity_hash', None)
if llattrvalue is not None:
lltype.init_identity_hash(result, llattrvalue)
def getfieldrepr(self, attr):
"""Return the repr used for the given attribute."""
if attr in self.fields:
......
......@@ -623,52 +623,6 @@ class StructNode(ContainerNode):
assert not USESLOTS or '__dict__' not in dir(StructNode)
class GcStructNodeWithHash(StructNode):
# for the outermost level of nested structures, if it has a _hash_cache_.
nodekind = 'struct'
if USESLOTS:
__slots__ = ()
def get_hash_typename(self):
return 'struct _hashT_%s @' % self.name
def forward_declaration(self):
T = self.getTYPE()
assert self.typename == self.implementationtypename # no array part
hash_typename = self.get_hash_typename()
hash_offset = self.db.gctransformer.get_hash_offset(T)
yield '%s {' % cdecl(hash_typename, '')
yield '\tunion {'
yield '\t\t%s;' % cdecl(self.implementationtypename, 'head')
yield '\t\tchar pad[%s];' % name_signed(hash_offset, self.db)
yield '\t} u;'
yield '\tlong hash;'
yield '};'
yield '%s;' % (
forward_cdecl(hash_typename, '_hash_' + self.name,
self.db.standalone, self.is_thread_local()),)
yield '#define %s _hash_%s.u.head' % (self.name, self.name)
def implementation(self):
hash_typename = self.get_hash_typename()
hash = self.db.gctransformer.get_prebuilt_hash(self.obj)
assert hash is not None
lines = list(self.initializationexpr())
lines.insert(0, '%s = { {' % (
cdecl(hash_typename, '_hash_' + self.name,
self.is_thread_local()),))
lines.append('}, %s /* hash */ };' % name_signed(hash, self.db))
return lines
def gcstructnode_factory(db, T, obj):
if (db.gctransformer and
db.gctransformer.get_prebuilt_hash(obj) is not None):
DISABLED
cls = GcStructNodeWithHash
else:
cls = StructNode
return cls(db, T, obj)
class ArrayNode(ContainerNode):
nodekind = 'array'
......@@ -1058,7 +1012,7 @@ class GroupNode(ContainerNode):
ContainerNodeFactory = {
Struct: StructNode,
GcStruct: gcstructnode_factory,
GcStruct: StructNode,
Array: ArrayNode,
GcArray: ArrayNode,
FixedSizeArray: FixedSizeArrayNode,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment