Backout f8c3e1e0e597515ee78c04d561a88669054710d9 (Bug 1224038) for bustage on a CLOSED TREE.

This commit is contained in:
Terrence Cole 2016-01-26 17:23:43 -08:00
parent 263b6bd7fe
commit 3c9927c9fa
7 changed files with 105 additions and 68 deletions

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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);
}
}
}
}

View File

@ -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*

View File

@ -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);
}

View File

@ -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 <>