зеркало из 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
|
inline
|
||||||
InitialShapeEntry::InitialShapeEntry() : shape(nullptr), proto(nullptr)
|
InitialShapeEntry::InitialShapeEntry() : shape(nullptr), proto(TaggedProto(nullptr))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
InitialShapeEntry::InitialShapeEntry(const ReadBarrieredShape& shape, TaggedProto proto)
|
InitialShapeEntry::InitialShapeEntry(const ReadBarriered<Shape*>& shape,
|
||||||
|
const ReadBarriered<TaggedProto>& proto)
|
||||||
: shape(shape), proto(proto)
|
: shape(shape), proto(proto)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -1368,73 +1369,20 @@ InitialShapeEntry::getLookup() const
|
||||||
/* static */ inline HashNumber
|
/* static */ inline HashNumber
|
||||||
InitialShapeEntry::hash(const Lookup& lookup)
|
InitialShapeEntry::hash(const Lookup& lookup)
|
||||||
{
|
{
|
||||||
HashNumber hash = uintptr_t(lookup.clasp) >> 3;
|
return (RotateLeft(uintptr_t(lookup.clasp) >> 3, 4) ^ lookup.proto.hashCode()) +
|
||||||
hash = RotateLeft(hash, 4) ^
|
lookup.nfixed;
|
||||||
(uintptr_t(lookup.hashProto.toWord()) >> 3);
|
|
||||||
return hash + lookup.nfixed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ inline bool
|
/* static */ inline bool
|
||||||
InitialShapeEntry::match(const InitialShapeEntry& key, const Lookup& lookup)
|
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()
|
return lookup.clasp == shape->getObjectClass()
|
||||||
&& lookup.matchProto.toWord() == key.proto.toWord()
|
|
||||||
&& lookup.nfixed == shape->numFixedSlots()
|
&& 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
|
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1450,7 +1398,7 @@ JSCompartment::checkInitialShapesTableAfterMovingGC()
|
||||||
*/
|
*/
|
||||||
for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) {
|
for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) {
|
||||||
InitialShapeEntry entry = e.front();
|
InitialShapeEntry entry = e.front();
|
||||||
TaggedProto proto = entry.proto;
|
TaggedProto proto = entry.proto.unbarrieredGet();
|
||||||
Shape* shape = entry.shape.unbarrieredGet();
|
Shape* shape = entry.shape.unbarrieredGet();
|
||||||
|
|
||||||
if (proto.isObject())
|
if (proto.isObject())
|
||||||
|
@ -1511,15 +1459,9 @@ EmptyShape::getInitialShape(ExclusiveContext* cx, const Class* clasp, TaggedProt
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Lookup lookup(clasp, protoRoot, nfixed, objectFlags);
|
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;
|
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;
|
return shape;
|
||||||
|
|
|
@ -1079,31 +1079,29 @@ struct InitialShapeEntry
|
||||||
* certain classes (e.g. String, RegExp) which may add certain baked-in
|
* certain classes (e.g. String, RegExp) which may add certain baked-in
|
||||||
* properties.
|
* properties.
|
||||||
*/
|
*/
|
||||||
ReadBarrieredShape shape;
|
ReadBarriered<Shape*> shape;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Matching prototype for the entry. The shape of an object determines its
|
* Matching prototype for the entry. The shape of an object determines its
|
||||||
* prototype, but the prototype cannot be determined from the shape itself.
|
* 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. */
|
/* State used to determine a match on an initial shape. */
|
||||||
struct Lookup {
|
struct Lookup {
|
||||||
const Class* clasp;
|
const Class* clasp;
|
||||||
TaggedProto hashProto;
|
TaggedProto proto;
|
||||||
TaggedProto matchProto;
|
|
||||||
uint32_t nfixed;
|
uint32_t nfixed;
|
||||||
uint32_t baseFlags;
|
uint32_t baseFlags;
|
||||||
|
|
||||||
Lookup(const Class* clasp, TaggedProto proto, uint32_t nfixed, uint32_t baseFlags)
|
Lookup(const Class* clasp, TaggedProto proto, uint32_t nfixed, uint32_t baseFlags)
|
||||||
: clasp(clasp),
|
: clasp(clasp), proto(proto), nfixed(nfixed), baseFlags(baseFlags)
|
||||||
hashProto(proto), matchProto(proto),
|
|
||||||
nfixed(nfixed), baseFlags(baseFlags)
|
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline InitialShapeEntry();
|
inline InitialShapeEntry();
|
||||||
inline InitialShapeEntry(const ReadBarrieredShape& shape, TaggedProto proto);
|
inline InitialShapeEntry(const ReadBarriered<Shape*>& shape,
|
||||||
|
const ReadBarriered<TaggedProto>& proto);
|
||||||
|
|
||||||
inline Lookup getLookup() const;
|
inline Lookup getLookup() const;
|
||||||
|
|
||||||
|
|
|
@ -30,17 +30,18 @@ InternalBarrierMethods<TaggedProto>::postBarrier(TaggedProto* vp, TaggedProto pr
|
||||||
nextObj);
|
nextObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
InternalBarrierMethods<TaggedProto>::readBarrier(const TaggedProto& proto)
|
||||||
|
{
|
||||||
|
InternalBarrierMethods<JSObject*>::readBarrier(proto.toObjectOrNull());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
js::HashNumber
|
js::HashNumber
|
||||||
js::TaggedProto::hashCode() const
|
js::TaggedProto::hashCode() const
|
||||||
{
|
{
|
||||||
if (isLazy())
|
return Zone::UniqueIdToHash(uniqueId());
|
||||||
return HashNumber(1);
|
|
||||||
JSObject* obj = toObjectOrNull();
|
|
||||||
if (!obj)
|
|
||||||
return HashNumber(0);
|
|
||||||
return obj->zone()->getHashCodeInfallible(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
|
|
|
@ -63,6 +63,8 @@ struct InternalBarrierMethods<TaggedProto>
|
||||||
|
|
||||||
static void postBarrier(TaggedProto* vp, TaggedProto prev, TaggedProto next);
|
static void postBarrier(TaggedProto* vp, TaggedProto prev, TaggedProto next);
|
||||||
|
|
||||||
|
static void readBarrier(const TaggedProto& proto);
|
||||||
|
|
||||||
static bool isMarkableTaggedPointer(TaggedProto proto) {
|
static bool isMarkableTaggedPointer(TaggedProto proto) {
|
||||||
return proto.isObject();
|
return proto.isObject();
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче