From 7e95b8fabe4e8b636c59a321978b7b9c29927ea7 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Sat, 22 Apr 2017 13:51:57 +0200 Subject: [PATCH] Bug 1358504 - Add a 1-entry cache to ObjectGroup::defaultNewGroup. r=bhackett --- js/src/jscompartment.cpp | 1 + js/src/vm/ObjectGroup.cpp | 52 ++++++++++++++++++++++++++++----------- js/src/vm/ObjectGroup.h | 26 ++++++++++++++++++++ 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 3d64ada78824..b1a52c97f759 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -1047,6 +1047,7 @@ JSCompartment::purge() dtoaCache.purge(); newProxyCache.purge(); lastCachedNativeIterator = nullptr; + objectGroups.purge(); } void diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp index 000b02d692bd..567e82441282 100644 --- a/js/src/vm/ObjectGroup.cpp +++ b/js/src/vm/ObjectGroup.cpp @@ -461,6 +461,20 @@ class ObjectGroupCompartment::NewTable : public JS::WeakCacheproto() == 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_(cx->zone()); - if (!table || !table->init()) { - js_delete(table); - table = nullptr; - ReportOutOfMemory(cx); - return nullptr; - } - } - if (associated && !associated->is()) { MOZ_ASSERT(!clasp); if (associated->is()) { @@ -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_(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 diff --git a/js/src/vm/ObjectGroup.h b/js/src/vm/ObjectGroup.h index 21391a5d7e47..485b4cf480cd 100644 --- a/js/src/vm/ObjectGroup.h +++ b/js/src/vm/ObjectGroup.h @@ -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