mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-25 20:01:50 +00:00
Backed out changeset 33a1af83a77f (bug 1224038) for breaking SM tests.
--HG-- extra : rebase_source : f28bbe20e879206562e01bc97d8f8317629043bc
This commit is contained in:
parent
c9d3c84ee0
commit
233d8e3b94
@ -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();
|
||||
|
@ -650,8 +650,7 @@ class GCRuntime
|
||||
|
||||
uint64_t nextCellUniqueId() {
|
||||
MOZ_ASSERT(nextCellUniqueId_ > 0);
|
||||
uint64_t uid = ++nextCellUniqueId_;
|
||||
return uid;
|
||||
return nextCellUniqueId_++;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1031,7 +1030,7 @@ class GCRuntime
|
||||
size_t maxMallocBytes;
|
||||
|
||||
// An incrementing id used to assign unique ids to cells that require one.
|
||||
mozilla::Atomic<uint64_t, mozilla::SequentiallyConsistent> nextCellUniqueId_;
|
||||
uint64_t nextCellUniqueId_;
|
||||
|
||||
/*
|
||||
* Number of the committed arenas in all GC chunks including empty chunks.
|
||||
|
@ -431,16 +431,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
|
||||
|
@ -6906,13 +6906,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
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "gc/StoreBuffer.h"
|
||||
#include "gc/Zone.h"
|
||||
#include "vm/ArrayObject.h"
|
||||
#include "vm/TaggedProto.h"
|
||||
#include "vm/UnboxedObject.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
@ -378,30 +377,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; }
|
||||
@ -412,6 +414,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)
|
||||
@ -505,6 +559,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());
|
||||
|
||||
@ -583,6 +639,8 @@ ObjectGroup::lazySingletonGroup(ExclusiveContext* cx, const Class* clasp, Tagged
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ObjectGroupCompartment::newTablePostBarrier(cx, table, clasp, proto, nullptr);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
@ -1750,11 +1808,13 @@ ObjectGroupCompartment::fixupNewTableAfterMovingGC(NewTable* table)
|
||||
if (table && table->initialized()) {
|
||||
for (NewTable::Enum e(*table); !e.empty(); e.popFront()) {
|
||||
NewEntry entry = e.front();
|
||||
|
||||
ObjectGroup* group = entry.group.unbarrieredGet();
|
||||
if (IsForwarded(group)) {
|
||||
group = Forwarded(group);
|
||||
|
||||
bool needRekey = false;
|
||||
if (IsForwarded(entry.group.unbarrieredGet())) {
|
||||
group = Forwarded(entry.group.unbarrieredGet());
|
||||
entry.group.set(group);
|
||||
needRekey = true;
|
||||
}
|
||||
TaggedProto proto = group->proto();
|
||||
if (proto.isObject() && IsForwarded(proto.toObject())) {
|
||||
@ -1762,9 +1822,19 @@ ObjectGroupCompartment::fixupNewTableAfterMovingGC(NewTable* table)
|
||||
// Update the group's proto here so that we are able to lookup
|
||||
// entries in this table before all object pointers are updated.
|
||||
group->proto() = proto;
|
||||
needRekey = true;
|
||||
}
|
||||
if (entry.associated && IsForwarded(entry.associated))
|
||||
if (entry.associated && IsForwarded(entry.associated)) {
|
||||
entry.associated = Forwarded(entry.associated);
|
||||
needRekey = true;
|
||||
}
|
||||
if (needRekey) {
|
||||
const Class* clasp = group->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*
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "gc/Zone.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -31,25 +30,3 @@ InternalBarrierMethods<TaggedProto>::postBarrier(TaggedProto* vp, TaggedProto pr
|
||||
}
|
||||
|
||||
} // 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);
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
void trace(JSTracer* trc) {
|
||||
if (isObject())
|
||||
TraceManuallyBarrieredEdge(trc, &proto, "TaggedProto");
|
||||
@ -86,8 +83,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().uniqueId(); }
|
||||
};
|
||||
|
||||
template <>
|
||||
|
Loading…
x
Reference in New Issue
Block a user