☠☠ backed out by cfc8f256cea0 ☠ ☠ | |
author | Terrence Cole <terrence@mozilla.com> |
Tue, 17 Nov 2015 11:31:27 -0800 | |
changeset 273034 | f3d2ddb4979c9909e012adafd607fc4463e32e6b |
parent 273033 | a621c6d49da11548244ba40ba131db239195c43c |
child 273035 | 02919b7d57d7f8206328f53ac0f7b2b9fe334c9b |
push id | 29693 |
push user | cbook@mozilla.com |
push date | Wed, 18 Nov 2015 13:50:33 +0000 |
treeherder | mozilla-central@1d6155d7e6c9 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jonco |
bugs | 1224038 |
milestone | 45.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/vm/ObjectGroup.cpp | file | annotate | diff | comparison | revisions | |
js/src/vm/ObjectGroup.h | file | annotate | diff | comparison | revisions |
--- a/js/src/vm/ObjectGroup.cpp +++ b/js/src/vm/ObjectGroup.cpp @@ -361,110 +361,50 @@ JSObject::setNewGroupUnknown(JSContext* * associated object may be a function (for types constructed with 'new') or a * type descriptor (for typed objects). These entries are also used for the set * of lazy groups in the compartment, which use a null associated object * (though there are only a few of these per compartment). */ struct ObjectGroupCompartment::NewEntry { ReadBarrieredObjectGroup group; - - // Note: This pointer is only used for equality and does not need a read barrier. - JSObject* associated; + ReadBarrieredObject associated; NewEntry(ObjectGroup* group, JSObject* associated) : group(group), associated(associated) {} struct Lookup { const Class* clasp; - TaggedProto hashProto; - TaggedProto matchProto; + TaggedProto proto; JSObject* associated; Lookup(const Class* clasp, TaggedProto proto, JSObject* associated) - : 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) + : clasp(clasp), proto(proto), associated(associated) {} }; static inline HashNumber hash(const Lookup& lookup) { - return PointerHasher<JSObject*, 3>::hash(lookup.hashProto.raw()) ^ + return lookup.proto.hashCode() ^ PointerHasher<const Class*, 3>::hash(lookup.clasp) ^ - PointerHasher<JSObject*, 3>::hash(lookup.associated); + MovableCellHasher<JSObject*>::hash(lookup.associated); } static inline bool match(const NewEntry& key, const Lookup& lookup) { - return key.group.unbarrieredGet()->proto() == lookup.matchProto && - (!lookup.clasp || key.group.unbarrieredGet()->clasp() == lookup.clasp) && - key.associated == lookup.associated; + TaggedProto keyProto = key.group.unbarrieredGet()->proto(); + const Class* keyClasp = key.group.unbarrieredGet()->clasp(); + JSObject* keyAssociated = key.associated.unbarrieredGet(); + return keyProto.uniqueId() == lookup.proto.uniqueId() && + (!lookup.clasp || PointerHasher<const Class*, 3>::match(keyClasp, lookup.clasp)) && + MovableCellHasher<JSObject*>::match(keyAssociated, lookup.associated); } static void rekey(NewEntry& k, const NewEntry& newKey) { k = newKey; } }; -// 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) { MOZ_ASSERT_IF(associated, proto.isObject()); MOZ_ASSERT_IF(proto.isObject(), cx->isInsideCurrentCompartment(proto.toObject())); // A null lookup clasp is used for 'new' groups with an associated @@ -548,18 +488,16 @@ ObjectGroup::defaultNewGroup(ExclusiveCo if (!group) return nullptr; if (!table->add(p, ObjectGroupCompartment::NewEntry(group, associated))) { ReportOutOfMemory(cx); return nullptr; } - ObjectGroupCompartment::newTablePostBarrier(cx, table, clasp, proto, associated); - if (proto.isObject()) { RootedObject obj(cx, proto.toObject()); if (associated) { if (associated->is<JSFunction>()) { if (!TypeNewScript::make(cx->asJSContext(), group, &associated->as<JSFunction>())) return nullptr; } else { @@ -634,18 +572,16 @@ ObjectGroup::lazySingletonGroup(Exclusiv if (!group) return nullptr; if (!table->add(p, ObjectGroupCompartment::NewEntry(group, nullptr))) { ReportOutOfMemory(cx); return nullptr; } - ObjectGroupCompartment::newTablePostBarrier(cx, table, clasp, proto, nullptr); - return group; } /* static */ void ObjectGroup::setDefaultNewGroupUnknown(JSContext* cx, const Class* clasp, HandleObject obj) { // If the object already has a new group, mark that group as unknown. ObjectGroupCompartment::NewTable* table = cx->compartment()->objectGroups.defaultNewTable; @@ -1777,64 +1713,44 @@ ObjectGroupCompartment::sweep(FreeOp* fo sweepNewTable(defaultNewTable); sweepNewTable(lazyTable); } void ObjectGroupCompartment::sweepNewTable(NewTable* table) { - if (table && table->initialized()) { - for (NewTable::Enum e(*table); !e.empty(); e.popFront()) { - NewEntry entry = e.front(); - if (IsAboutToBeFinalized(&entry.group) || - (entry.associated && IsAboutToBeFinalizedUnbarriered(&entry.associated))) - { - e.removeFront(); - } else { - /* Any rekeying necessary is handled by fixupNewObjectGroupTable() below. */ - MOZ_ASSERT(entry.group.unbarrieredGet() == e.front().group.unbarrieredGet()); - MOZ_ASSERT(entry.associated == e.front().associated); - } + if (!table || !table->initialized()) + return; + + for (NewTable::Enum e(*table); !e.empty(); e.popFront()) { + NewEntry entry = e.front(); + if (IsAboutToBeFinalized(&entry.group) || + (entry.associated && IsAboutToBeFinalized(&entry.associated))) + { + e.removeFront(); } } } void ObjectGroupCompartment::fixupNewTableAfterMovingGC(NewTable* table) { /* * Each entry's hash depends on the object's prototype and we can't tell * whether that has been moved or not in sweepNewObjectGroupTable(). */ - if (table && table->initialized()) { - for (NewTable::Enum e(*table); !e.empty(); e.popFront()) { - NewEntry entry = e.front(); - bool needRekey = false; - if (IsForwarded(entry.group.unbarrieredGet())) { - entry.group.set(Forwarded(entry.group.unbarrieredGet())); - 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); - 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); - } - } + if (!table || !table->initialized()) + return; + + for (NewTable::Enum e(*table); !e.empty(); e.popFront()) { + if (IsForwarded(e.front().group.unbarrieredGet())) + e.mutableFront().group.set(Forwarded(e.front().group.unbarrieredGet())); + if (e.front().associated && IsForwarded(e.front().associated.unbarrieredGet())) + e.mutableFront().associated.set(Forwarded(e.front().associated.unbarrieredGet())); } } #ifdef JSGC_HASH_TABLE_CHECKS void ObjectGroupCompartment::checkNewTableAfterMovingGC(NewTable* table) {
--- a/js/src/vm/ObjectGroup.h +++ b/js/src/vm/ObjectGroup.h @@ -534,17 +534,16 @@ class ObjectGroup : public gc::TenuredCe // Structure used to manage the groups in a compartment. class ObjectGroupCompartment { friend class ObjectGroup; struct NewEntry; typedef HashSet<NewEntry, NewEntry, SystemAllocPolicy> NewTable; - class NewTableRef; // Set of default 'new' or lazy groups in the compartment. NewTable* defaultNewTable; NewTable* lazyTable; struct ArrayObjectKey; typedef HashMap<ArrayObjectKey, ReadBarrieredObjectGroup, @@ -618,19 +617,16 @@ class ObjectGroupCompartment private: #ifdef JSGC_HASH_TABLE_CHECKS void checkNewTableAfterMovingGC(NewTable* table); #endif void sweepNewTable(NewTable* table); void fixupNewTableAfterMovingGC(NewTable* table); - - static void newTablePostBarrier(ExclusiveContext* cx, NewTable* table, - const Class* clasp, TaggedProto proto, JSObject* associated); }; PlainObject* NewPlainObjectWithProperties(ExclusiveContext* cx, IdValuePair* properties, size_t nproperties, NewObjectKind newKind); bool CombineArrayElementTypes(ExclusiveContext* cx, JSObject* newObj,