Backed out changeset 33a1af83a77f (bug 1224038) for breaking SM tests.

--HG--
extra : rebase_source : f28bbe20e879206562e01bc97d8f8317629043bc
This commit is contained in:
Terrence Cole 2016-03-08 20:06:10 -08:00
Родитель c9d3c84ee0
Коммит 233d8e3b94
8 изменённых файлов: 103 добавлений и 67 удалений

Просмотреть файл

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