зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1224050 - Use stable hashing for the IntialShapesTable; r=jonco
--HG-- extra : rebase_source : bb234ac7eac0503f8d7dec84ea8cf02894b3edf2
This commit is contained in:
Родитель
7b557b47a9
Коммит
bd531e5bce
|
@ -1349,12 +1349,13 @@ BaseShape::finalize(FreeOp* fop)
|
|||
}
|
||||
|
||||
inline
|
||||
InitialShapeEntry::InitialShapeEntry() : shape(nullptr), proto(nullptr)
|
||||
InitialShapeEntry::InitialShapeEntry() : shape(nullptr), proto(TaggedProto(nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
InitialShapeEntry::InitialShapeEntry(const ReadBarrieredShape& shape, TaggedProto proto)
|
||||
InitialShapeEntry::InitialShapeEntry(const ReadBarriered<Shape*>& shape,
|
||||
const ReadBarriered<TaggedProto>& proto)
|
||||
: shape(shape), proto(proto)
|
||||
{
|
||||
}
|
||||
|
@ -1368,73 +1369,20 @@ InitialShapeEntry::getLookup() const
|
|||
/* static */ inline HashNumber
|
||||
InitialShapeEntry::hash(const Lookup& lookup)
|
||||
{
|
||||
HashNumber hash = uintptr_t(lookup.clasp) >> 3;
|
||||
hash = RotateLeft(hash, 4) ^
|
||||
(uintptr_t(lookup.hashProto.toWord()) >> 3);
|
||||
return hash + lookup.nfixed;
|
||||
return (RotateLeft(uintptr_t(lookup.clasp) >> 3, 4) ^ lookup.proto.hashCode()) +
|
||||
lookup.nfixed;
|
||||
}
|
||||
|
||||
/* static */ inline bool
|
||||
InitialShapeEntry::match(const InitialShapeEntry& key, const Lookup& lookup)
|
||||
{
|
||||
const Shape* shape = *key.shape.unsafeGet();
|
||||
const Shape* shape = key.shape.unbarrieredGet();
|
||||
return lookup.clasp == shape->getObjectClass()
|
||||
&& lookup.matchProto.toWord() == key.proto.toWord()
|
||||
&& lookup.nfixed == shape->numFixedSlots()
|
||||
&& lookup.baseFlags == shape->getObjectFlags();
|
||||
&& lookup.baseFlags == shape->getObjectFlags()
|
||||
&& lookup.proto.uniqueId() == key.proto.unbarrieredGet().uniqueId();
|
||||
}
|
||||
|
||||
/*
|
||||
* This class is used to add a post barrier on the initialShapes set, as the key
|
||||
* is calculated based on objects which may be moved by generational GC.
|
||||
*/
|
||||
class InitialShapeSetRef : public BufferableRef
|
||||
{
|
||||
InitialShapeSet* set;
|
||||
const Class* clasp;
|
||||
TaggedProto proto;
|
||||
size_t nfixed;
|
||||
uint32_t objectFlags;
|
||||
|
||||
public:
|
||||
InitialShapeSetRef(InitialShapeSet* set,
|
||||
const Class* clasp,
|
||||
TaggedProto proto,
|
||||
size_t nfixed,
|
||||
uint32_t objectFlags)
|
||||
: set(set),
|
||||
clasp(clasp),
|
||||
proto(proto),
|
||||
nfixed(nfixed),
|
||||
objectFlags(objectFlags)
|
||||
{}
|
||||
|
||||
void trace(JSTracer* trc) override {
|
||||
TaggedProto priorProto = proto;
|
||||
if (proto.isObject()) {
|
||||
TraceManuallyBarrieredEdge(trc, reinterpret_cast<JSObject**>(&proto),
|
||||
"initialShapes set proto");
|
||||
}
|
||||
if (proto == priorProto)
|
||||
return;
|
||||
|
||||
/* Find the original entry, which must still be present. */
|
||||
InitialShapeEntry::Lookup lookup(clasp, priorProto, nfixed, objectFlags);
|
||||
InitialShapeSet::Ptr p = set->lookup(lookup);
|
||||
MOZ_ASSERT(p);
|
||||
|
||||
/* Update the entry's possibly-moved proto, and ensure lookup will still match. */
|
||||
InitialShapeEntry& entry = const_cast<InitialShapeEntry&>(*p);
|
||||
entry.proto = proto;
|
||||
lookup.matchProto = proto;
|
||||
|
||||
/* Rekey the entry. */
|
||||
set->rekeyAs(lookup,
|
||||
InitialShapeEntry::Lookup(clasp, proto, nfixed, objectFlags),
|
||||
*p);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
|
||||
void
|
||||
|
@ -1450,7 +1398,7 @@ JSCompartment::checkInitialShapesTableAfterMovingGC()
|
|||
*/
|
||||
for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) {
|
||||
InitialShapeEntry entry = e.front();
|
||||
TaggedProto proto = entry.proto;
|
||||
TaggedProto proto = entry.proto.unbarrieredGet();
|
||||
Shape* shape = entry.shape.unbarrieredGet();
|
||||
|
||||
if (proto.isObject())
|
||||
|
@ -1511,15 +1459,9 @@ EmptyShape::getInitialShape(ExclusiveContext* cx, const Class* clasp, TaggedProt
|
|||
return nullptr;
|
||||
|
||||
Lookup lookup(clasp, protoRoot, nfixed, objectFlags);
|
||||
if (!p.add(cx, table, lookup, InitialShapeEntry(ReadBarrieredShape(shape), protoRoot)))
|
||||
if (!p.add(cx, table, lookup, InitialShapeEntry(shape, protoRoot.get()))) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
|
||||
// Post-barrier for the initial shape table update.
|
||||
if (cx->isJSContext()) {
|
||||
if (protoRoot.isObject() && IsInsideNursery(protoRoot.toObject())) {
|
||||
InitialShapeSetRef ref(&table, clasp, protoRoot, nfixed, objectFlags);
|
||||
cx->asJSContext()->runtime()->gc.storeBuffer.putGeneric(ref);
|
||||
}
|
||||
}
|
||||
|
||||
return shape;
|
||||
|
|
|
@ -1079,31 +1079,29 @@ struct InitialShapeEntry
|
|||
* certain classes (e.g. String, RegExp) which may add certain baked-in
|
||||
* properties.
|
||||
*/
|
||||
ReadBarrieredShape shape;
|
||||
ReadBarriered<Shape*> shape;
|
||||
|
||||
/*
|
||||
* Matching prototype for the entry. The shape of an object determines its
|
||||
* prototype, but the prototype cannot be determined from the shape itself.
|
||||
*/
|
||||
TaggedProto proto;
|
||||
ReadBarriered<TaggedProto> proto;
|
||||
|
||||
/* State used to determine a match on an initial shape. */
|
||||
struct Lookup {
|
||||
const Class* clasp;
|
||||
TaggedProto hashProto;
|
||||
TaggedProto matchProto;
|
||||
TaggedProto proto;
|
||||
uint32_t nfixed;
|
||||
uint32_t baseFlags;
|
||||
|
||||
Lookup(const Class* clasp, TaggedProto proto, uint32_t nfixed, uint32_t baseFlags)
|
||||
: clasp(clasp),
|
||||
hashProto(proto), matchProto(proto),
|
||||
nfixed(nfixed), baseFlags(baseFlags)
|
||||
: clasp(clasp), proto(proto), nfixed(nfixed), baseFlags(baseFlags)
|
||||
{}
|
||||
};
|
||||
|
||||
inline InitialShapeEntry();
|
||||
inline InitialShapeEntry(const ReadBarrieredShape& shape, TaggedProto proto);
|
||||
inline InitialShapeEntry(const ReadBarriered<Shape*>& shape,
|
||||
const ReadBarriered<TaggedProto>& proto);
|
||||
|
||||
inline Lookup getLookup() const;
|
||||
|
||||
|
|
|
@ -30,17 +30,18 @@ InternalBarrierMethods<TaggedProto>::postBarrier(TaggedProto* vp, TaggedProto pr
|
|||
nextObj);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
InternalBarrierMethods<TaggedProto>::readBarrier(const TaggedProto& proto)
|
||||
{
|
||||
InternalBarrierMethods<JSObject*>::readBarrier(proto.toObjectOrNull());
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
js::HashNumber
|
||||
js::TaggedProto::hashCode() const
|
||||
{
|
||||
if (isLazy())
|
||||
return HashNumber(1);
|
||||
JSObject* obj = toObjectOrNull();
|
||||
if (!obj)
|
||||
return HashNumber(0);
|
||||
return obj->zone()->getHashCodeInfallible(obj);
|
||||
return Zone::UniqueIdToHash(uniqueId());
|
||||
}
|
||||
|
||||
uint64_t
|
||||
|
|
|
@ -63,6 +63,8 @@ struct InternalBarrierMethods<TaggedProto>
|
|||
|
||||
static void postBarrier(TaggedProto* vp, TaggedProto prev, TaggedProto next);
|
||||
|
||||
static void readBarrier(const TaggedProto& proto);
|
||||
|
||||
static bool isMarkableTaggedPointer(TaggedProto proto) {
|
||||
return proto.isObject();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче