Bug 1358504 - Add a 1-entry cache to ObjectGroup::defaultNewGroup. r=bhackett

This commit is contained in:
Jan de Mooij 2017-04-22 13:51:57 +02:00
parent 012fd2ffcb
commit 7e95b8fabe
3 changed files with 65 additions and 14 deletions

View File

@ -1047,6 +1047,7 @@ JSCompartment::purge()
dtoaCache.purge();
newProxyCache.purge();
lastCachedNativeIterator = nullptr;
objectGroups.purge();
}
void

View File

@ -461,6 +461,20 @@ class ObjectGroupCompartment::NewTable : public JS::WeakCache<js::GCHashSet<NewE
explicit NewTable(Zone* zone) : Base(zone, Table()) {}
};
MOZ_ALWAYS_INLINE ObjectGroup*
ObjectGroupCompartment::DefaultNewGroupCache::lookup(const Class* clasp, TaggedProto proto,
JSObject* associated)
{
if (group_ &&
associated_ == associated &&
group_->proto() == proto &&
(!clasp || group_->clasp() == clasp))
{
return group_;
}
return nullptr;
}
/* static */ ObjectGroup*
ObjectGroup::defaultNewGroup(JSContext* cx, const Class* clasp,
TaggedProto proto, JSObject* associated)
@ -473,20 +487,6 @@ ObjectGroup::defaultNewGroup(JSContext* cx, const Class* clasp,
// unboxed plain object.
MOZ_ASSERT_IF(!clasp, !!associated);
AutoEnterAnalysis enter(cx);
ObjectGroupCompartment::NewTable*& table = cx->compartment()->objectGroups.defaultNewTable;
if (!table) {
table = cx->new_<ObjectGroupCompartment::NewTable>(cx->zone());
if (!table || !table->init()) {
js_delete(table);
table = nullptr;
ReportOutOfMemory(cx);
return nullptr;
}
}
if (associated && !associated->is<TypeDescr>()) {
MOZ_ASSERT(!clasp);
if (associated->is<JSFunction>()) {
@ -513,6 +513,25 @@ ObjectGroup::defaultNewGroup(JSContext* cx, const Class* clasp,
clasp = &PlainObject::class_;
}
ObjectGroupCompartment& groups = cx->compartment()->objectGroups;
if (ObjectGroup* group = groups.defaultNewGroupCache.lookup(clasp, proto, associated))
return group;
AutoEnterAnalysis enter(cx);
ObjectGroupCompartment::NewTable*& table = groups.defaultNewTable;
if (!table) {
table = cx->new_<ObjectGroupCompartment::NewTable>(cx->zone());
if (!table || !table->init()) {
js_delete(table);
table = nullptr;
ReportOutOfMemory(cx);
return nullptr;
}
}
if (proto.isObject() && !proto.toObject()->isDelegate()) {
RootedObject protoObj(cx, proto.toObject());
if (!JSObject::setDelegate(cx, protoObj))
@ -536,6 +555,7 @@ ObjectGroup::defaultNewGroup(JSContext* cx, const Class* clasp,
MOZ_ASSERT_IF(!clasp, group->clasp() == &PlainObject::class_ ||
group->clasp() == &UnboxedPlainObject::class_);
MOZ_ASSERT(group->proto() == proto);
groups.defaultNewGroupCache.put(group, associated);
return group;
}
@ -582,6 +602,7 @@ ObjectGroup::defaultNewGroup(JSContext* cx, const Class* clasp,
AddTypePropertyId(cx, group, nullptr, NameToId(names.columnNumber), TypeSet::Int32Type());
}
groups.defaultNewGroupCache.put(group, associated);
return group;
}
@ -1681,6 +1702,7 @@ ObjectGroupCompartment::removeDefaultNewGroup(const Class* clasp, TaggedProto pr
MOZ_RELEASE_ASSERT(p);
defaultNewTable->get().remove(p);
defaultNewGroupCache.purge();
}
void
@ -1692,6 +1714,7 @@ ObjectGroupCompartment::replaceDefaultNewGroup(const Class* clasp, TaggedProto p
auto p = defaultNewTable->lookup(lookup);
MOZ_RELEASE_ASSERT(p);
defaultNewTable->get().remove(p);
defaultNewGroupCache.purge();
{
AutoEnterOOMUnsafeRegion oomUnsafe;
if (!defaultNewTable->putNew(lookup, NewEntry(group, associated)))
@ -1770,6 +1793,7 @@ ObjectGroupCompartment::clearTables()
defaultNewTable->clear();
if (lazyTable && lazyTable->initialized())
lazyTable->clear();
defaultNewGroupCache.purge();
}
/* static */ bool

View File

@ -566,6 +566,28 @@ class ObjectGroupCompartment
NewTable* defaultNewTable;
NewTable* lazyTable;
// Cache for defaultNewGroup. Purged on GC.
class DefaultNewGroupCache
{
ObjectGroup* group_;
JSObject* associated_;
public:
DefaultNewGroupCache() { purge(); }
void purge() {
group_ = nullptr;
}
void put(ObjectGroup* group, JSObject* associated) {
group_ = group;
associated_ = associated;
}
MOZ_ALWAYS_INLINE ObjectGroup* lookup(const Class* clasp, TaggedProto proto,
JSObject* associated);
};
DefaultNewGroupCache defaultNewGroupCache;
struct ArrayObjectKey;
using ArrayObjectTable = js::GCRekeyableHashMap<ArrayObjectKey,
ReadBarrieredObjectGroup,
@ -628,6 +650,10 @@ class ObjectGroupCompartment
void sweep(FreeOp* fop);
void purge() {
defaultNewGroupCache.purge();
}
#ifdef JSGC_HASH_TABLE_CHECKS
void checkTablesAfterMovingGC() {
checkNewTableAfterMovingGC(defaultNewTable);