mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 22:55:23 +00:00
Backout f8c3e1e0e597515ee78c04d561a88669054710d9 (Bug 1224038) for bustage on a CLOSED TREE.
This commit is contained in:
parent
263b6bd7fe
commit
3c9927c9fa
@ -452,10 +452,6 @@ class HeapPtr : public WriteBarrieredBase<T>
|
||||
|
||||
DECLARE_POINTER_ASSIGN_OPS(HeapPtr, T);
|
||||
|
||||
T unbarrieredGet() const {
|
||||
return this->value;
|
||||
}
|
||||
|
||||
private:
|
||||
void set(const T& v) {
|
||||
this->pre();
|
||||
|
@ -430,16 +430,9 @@ struct Zone : public JS::shadow::Zone,
|
||||
uniqueIds_.remove(cell);
|
||||
}
|
||||
|
||||
// When finished parsing off-thread, transfer any UIDs we created in the
|
||||
// off-thread zone into the target zone.
|
||||
void adoptUniqueIds(JS::Zone* source) {
|
||||
js::AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
for (js::gc::UniqueIdMap::Enum e(source->uniqueIds_); !e.empty(); e.popFront()) {
|
||||
MOZ_ASSERT(!uniqueIds_.has(e.front().key()));
|
||||
if (!uniqueIds_.put(e.front().key(), e.front().value()))
|
||||
oomUnsafe.crash("failed to transfer unique ids from off-main-thread");
|
||||
}
|
||||
source->uniqueIds_.clear();
|
||||
// Off-thread parsing should not result in any UIDs being created.
|
||||
void assertNoUniqueIdsInZone() const {
|
||||
MOZ_ASSERT(uniqueIds_.count() == 0);
|
||||
}
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
|
@ -6931,13 +6931,15 @@ gc::MergeCompartments(JSCompartment* source, JSCompartment* target)
|
||||
for (CompartmentsInZoneIter c(source->zone()); !c.done(); c.next())
|
||||
MOZ_ASSERT(c.get() == source);
|
||||
|
||||
// Merge the allocator, stats and UIDs in source's zone into target's zone.
|
||||
// Merge the allocator in source's zone into target's zone.
|
||||
target->zone()->arenas.adoptArenas(rt, &source->zone()->arenas);
|
||||
target->zone()->usage.adopt(source->zone()->usage);
|
||||
target->zone()->adoptUniqueIds(source->zone());
|
||||
|
||||
// Merge other info in source's zone into target's zone.
|
||||
target->zone()->types.typeLifoAlloc.transferFrom(&source->zone()->types.typeLifoAlloc);
|
||||
|
||||
// Ensure that we did not create any UIDs when running off-thread.
|
||||
source->zone()->assertNoUniqueIdsInZone();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "gc/StoreBuffer.h"
|
||||
#include "gc/Zone.h"
|
||||
#include "vm/ArrayObject.h"
|
||||
#include "vm/TaggedProto.h"
|
||||
#include "vm/UnboxedObject.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
@ -377,30 +376,33 @@ struct ObjectGroupCompartment::NewEntry
|
||||
|
||||
struct Lookup {
|
||||
const Class* clasp;
|
||||
uint64_t protoUID;
|
||||
uint64_t assocUID;
|
||||
TaggedProto hashProto;
|
||||
TaggedProto matchProto;
|
||||
JSObject* associated;
|
||||
|
||||
Lookup(const Class* clasp, TaggedProto proto, JSObject* associated)
|
||||
: clasp(clasp),
|
||||
protoUID(proto.uniqueId()),
|
||||
assocUID(associated ? associated->zone()->getUniqueIdInfallible(associated) : 0)
|
||||
: clasp(clasp), hashProto(proto), matchProto(proto), associated(associated)
|
||||
{}
|
||||
|
||||
/*
|
||||
* For use by generational post barriers only. Look up an entry whose
|
||||
* proto has been moved, but was hashed with the original value.
|
||||
*/
|
||||
Lookup(const Class* clasp, TaggedProto hashProto, TaggedProto matchProto, JSObject* associated)
|
||||
: clasp(clasp), hashProto(hashProto), matchProto(matchProto), associated(associated)
|
||||
{}
|
||||
};
|
||||
|
||||
static inline HashNumber hash(const Lookup& lookup) {
|
||||
HashNumber hash = uintptr_t(lookup.clasp);
|
||||
hash = mozilla::RotateLeft(hash, 4) ^ Zone::UniqueIdToHash(lookup.protoUID);
|
||||
hash = mozilla::RotateLeft(hash, 4) ^ Zone::UniqueIdToHash(lookup.assocUID);
|
||||
return hash;
|
||||
return PointerHasher<JSObject*, 3>::hash(lookup.hashProto.raw()) ^
|
||||
PointerHasher<const Class*, 3>::hash(lookup.clasp) ^
|
||||
PointerHasher<JSObject*, 3>::hash(lookup.associated);
|
||||
}
|
||||
|
||||
static inline bool match(const NewEntry& key, const Lookup& lookup) {
|
||||
if (lookup.clasp && key.group.unbarrieredGet()->clasp() != lookup.clasp)
|
||||
return false;
|
||||
if (key.group.unbarrieredGet()->proto().unbarrieredGet().uniqueId() != lookup.protoUID)
|
||||
return false;
|
||||
return !key.associated ||
|
||||
key.associated->zone()->getUniqueIdInfallible(key.associated) == lookup.assocUID;
|
||||
return key.group.unbarrieredGet()->proto() == lookup.matchProto &&
|
||||
(!lookup.clasp || key.group.unbarrieredGet()->clasp() == lookup.clasp) &&
|
||||
key.associated == lookup.associated;
|
||||
}
|
||||
|
||||
static void rekey(NewEntry& k, const NewEntry& newKey) { k = newKey; }
|
||||
@ -411,6 +413,58 @@ struct ObjectGroupCompartment::NewEntry
|
||||
}
|
||||
};
|
||||
|
||||
// This class is used to add a post barrier on a NewTable entry, as the key is
|
||||
// calculated from a prototype object which may be moved by generational GC.
|
||||
class ObjectGroupCompartment::NewTableRef : public gc::BufferableRef
|
||||
{
|
||||
NewTable* table;
|
||||
const Class* clasp;
|
||||
JSObject* proto;
|
||||
JSObject* associated;
|
||||
|
||||
public:
|
||||
NewTableRef(NewTable* table, const Class* clasp, JSObject* proto, JSObject* associated)
|
||||
: table(table), clasp(clasp), proto(proto), associated(associated)
|
||||
{}
|
||||
|
||||
void trace(JSTracer* trc) override {
|
||||
JSObject* prior = proto;
|
||||
TraceManuallyBarrieredEdge(trc, &proto, "newObjectGroups set prototype");
|
||||
if (prior == proto)
|
||||
return;
|
||||
|
||||
NewTable::Ptr p = table->lookup(NewTable::Lookup(clasp, TaggedProto(prior),
|
||||
TaggedProto(proto),
|
||||
associated));
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
table->rekeyAs(NewTable::Lookup(clasp, TaggedProto(prior), TaggedProto(proto), associated),
|
||||
NewTable::Lookup(clasp, TaggedProto(proto), associated), *p);
|
||||
}
|
||||
};
|
||||
|
||||
/* static */ void
|
||||
ObjectGroupCompartment::newTablePostBarrier(ExclusiveContext* cx, NewTable* table,
|
||||
const Class* clasp, TaggedProto proto,
|
||||
JSObject* associated)
|
||||
{
|
||||
MOZ_ASSERT_IF(associated, !IsInsideNursery(associated));
|
||||
|
||||
if (!proto.isObject())
|
||||
return;
|
||||
|
||||
if (!cx->isJSContext()) {
|
||||
MOZ_ASSERT(!IsInsideNursery(proto.toObject()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsInsideNursery(proto.toObject())) {
|
||||
gc::StoreBuffer& sb = cx->asJSContext()->runtime()->gc.storeBuffer;
|
||||
sb.putGeneric(NewTableRef(table, clasp, proto.toObject(), associated));
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ ObjectGroup*
|
||||
ObjectGroup::defaultNewGroup(ExclusiveContext* cx, const Class* clasp,
|
||||
TaggedProto proto, JSObject* associated)
|
||||
@ -504,6 +558,8 @@ ObjectGroup::defaultNewGroup(ExclusiveContext* cx, const Class* clasp,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ObjectGroupCompartment::newTablePostBarrier(cx, table, clasp, proto, associated);
|
||||
|
||||
if (proto.isObject()) {
|
||||
RootedObject obj(cx, proto.toObject());
|
||||
|
||||
@ -588,6 +644,8 @@ ObjectGroup::lazySingletonGroup(ExclusiveContext* cx, const Class* clasp, Tagged
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ObjectGroupCompartment::newTablePostBarrier(cx, table, clasp, proto, nullptr);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
@ -1753,17 +1811,28 @@ ObjectGroupCompartment::fixupNewTableAfterMovingGC(NewTable* table)
|
||||
*/
|
||||
if (table && table->initialized()) {
|
||||
for (NewTable::Enum e(*table); !e.empty(); e.popFront()) {
|
||||
NewEntry& entry = e.mutableFront();
|
||||
|
||||
if (IsForwarded(entry.group.unbarrieredGet()))
|
||||
NewEntry entry = e.front();
|
||||
bool needRekey = false;
|
||||
if (IsForwarded(entry.group.unbarrieredGet())) {
|
||||
entry.group.set(Forwarded(entry.group.unbarrieredGet()));
|
||||
|
||||
if (entry.associated && IsForwarded(entry.associated))
|
||||
needRekey = true;
|
||||
}
|
||||
TaggedProto proto = entry.group.unbarrieredGet()->proto();
|
||||
if (proto.isObject() && IsForwarded(proto.toObject())) {
|
||||
proto = TaggedProto(Forwarded(proto.toObject()));
|
||||
needRekey = true;
|
||||
}
|
||||
if (entry.associated && IsForwarded(entry.associated)) {
|
||||
entry.associated = Forwarded(entry.associated);
|
||||
|
||||
TaggedProto proto = entry.group.unbarrieredGet()->proto().unbarrieredGet();
|
||||
if (proto.isObject() && IsForwarded(proto.toObject()))
|
||||
entry.group.unbarrieredGet()->proto().unsafeSet(TaggedProto(Forwarded(proto.toObject())));
|
||||
needRekey = true;
|
||||
}
|
||||
if (needRekey) {
|
||||
const Class* clasp = entry.group.unbarrieredGet()->clasp();
|
||||
if (entry.associated && entry.associated->is<JSFunction>())
|
||||
clasp = nullptr;
|
||||
NewEntry::Lookup lookup(clasp, proto, entry.associated);
|
||||
e.rekeyFront(lookup, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -540,6 +540,7 @@ class ObjectGroupCompartment
|
||||
|
||||
struct NewEntry;
|
||||
using NewTable = js::GCHashSet<NewEntry, NewEntry, SystemAllocPolicy>;
|
||||
class NewTableRef;
|
||||
|
||||
// Set of default 'new' or lazy groups in the compartment.
|
||||
NewTable* defaultNewTable;
|
||||
@ -626,6 +627,9 @@ class ObjectGroupCompartment
|
||||
#endif
|
||||
|
||||
void fixupNewTableAfterMovingGC(NewTable* table);
|
||||
|
||||
static void newTablePostBarrier(ExclusiveContext* cx, NewTable* table,
|
||||
const Class* clasp, TaggedProto proto, JSObject* associated);
|
||||
};
|
||||
|
||||
PlainObject*
|
||||
|
@ -29,25 +29,3 @@ InternalGCMethods<TaggedProto>::postBarrier(TaggedProto* vp, TaggedProto prev, T
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
HashNumber
|
||||
js::TaggedProto::hashCode() const
|
||||
{
|
||||
if (isLazy())
|
||||
return HashNumber(1);
|
||||
JSObject* obj = toObjectOrNull();
|
||||
if (!obj)
|
||||
return HashNumber(0);
|
||||
return obj->zone()->getHashCodeInfallible(obj);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
js::TaggedProto::uniqueId() const
|
||||
{
|
||||
if (isLazy())
|
||||
return uint64_t(1);
|
||||
JSObject* obj = toObjectOrNull();
|
||||
if (!obj)
|
||||
return uint64_t(0);
|
||||
return obj->zone()->getUniqueIdInfallible(obj);
|
||||
}
|
||||
|
@ -44,9 +44,6 @@ class TaggedProto : public JS::Traceable
|
||||
bool operator ==(const TaggedProto& other) const { return proto == other.proto; }
|
||||
bool operator !=(const TaggedProto& other) const { return proto != other.proto; }
|
||||
|
||||
HashNumber hashCode() const;
|
||||
uint64_t uniqueId() const;
|
||||
|
||||
static void trace(TaggedProto* protop, JSTracer* trc) {
|
||||
TraceManuallyBarrieredEdge(trc, protop, "TaggedProto");
|
||||
}
|
||||
@ -89,8 +86,6 @@ class TaggedProtoOperations
|
||||
inline JSObject* toObject() const { return value().toObject(); }
|
||||
inline JSObject* toObjectOrNull() const { return value().toObjectOrNull(); }
|
||||
JSObject* raw() const { return value().raw(); }
|
||||
HashNumber hashCode() const { return value().hashCode(); }
|
||||
uint64_t uniqueId() const { return value().hashCode(); }
|
||||
};
|
||||
|
||||
template <>
|
||||
|
Loading…
Reference in New Issue
Block a user