Bug 1265483 - Use WeakCache to automate sweeping of ObjectGroupCompartment::NewTable; r=jonco
authorTerrence Cole <terrence@mozilla.com>
Wed, 20 Apr 2016 15:17:25 -0700
changeset 332248 ddd7892d4ed6c18b9bbc1a6e25803b5e628452a7
parent 332247 bba81310ba7bdcadbbfee29c09bfb1fca9ac274e
child 332249 eb272cc767ac5a4f2bdcb6d8c1cce7f13db4d65d
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1265483
milestone48.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
Bug 1265483 - Use WeakCache to automate sweeping of ObjectGroupCompartment::NewTable; r=jonco
js/public/SweepingAPI.h
js/src/vm/ObjectGroup.cpp
js/src/vm/ObjectGroup.h
--- a/js/public/SweepingAPI.h
+++ b/js/public/SweepingAPI.h
@@ -26,23 +26,26 @@ RegisterWeakCache(JS::Zone* zone, JS::We
 // list of such caches that are swept during each GC.
 template <typename T>
 class WeakCache : public js::WeakCacheBase<T>,
                   private mozilla::LinkedListElement<WeakCache<T>>
 {
     friend class mozilla::LinkedListElement<WeakCache<T>>;
     friend class mozilla::LinkedList<WeakCache<T>>;
 
+    WeakCache() = delete;
     WeakCache(const WeakCache&) = delete;
 
     using SweepFn = void (*)(T*);
     SweepFn sweeper;
     T cache;
 
   public:
+    using Type = T;
+
     template <typename U>
     WeakCache(Zone* zone, U&& initial)
       : cache(mozilla::Forward<U>(initial))
     {
         sweeper = js::GCPolicy<T>::sweep;
         shadow::RegisterWeakCache(zone, reinterpret_cast<WeakCache<void*>*>(this));
     }
     WeakCache(WeakCache&& other)
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -407,16 +407,26 @@ struct ObjectGroupCompartment::NewEntry
     static void rekey(NewEntry& k, const NewEntry& newKey) { k = newKey; }
 
     bool needsSweep() {
         return (IsAboutToBeFinalized(&group) ||
                 (associated && IsAboutToBeFinalizedUnbarriered(&associated)));
     }
 };
 
+class ObjectGroupCompartment::NewTable : public JS::WeakCache<js::GCHashSet<NewEntry, NewEntry,
+                                                                            SystemAllocPolicy>>
+{
+    using Table = js::GCHashSet<NewEntry, NewEntry, SystemAllocPolicy>;
+    using Base = JS::WeakCache<Table>;
+
+  public:
+    explicit NewTable(Zone* zone) : Base(zone, Table()) {}
+};
+
 /* 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
@@ -424,17 +434,17 @@ ObjectGroup::defaultNewGroup(ExclusiveCo
     // 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>();
+        table = cx->new_<ObjectGroupCompartment::NewTable>(cx->zone());
         if (!table || !table->init()) {
             js_delete(table);
             table = nullptr;
             ReportOutOfMemory(cx);
             return nullptr;
         }
     }
 
@@ -546,17 +556,17 @@ ObjectGroup::defaultNewGroup(ExclusiveCo
 /* static */ ObjectGroup*
 ObjectGroup::lazySingletonGroup(ExclusiveContext* cx, const Class* clasp, TaggedProto proto)
 {
     MOZ_ASSERT_IF(proto.isObject(), cx->compartment() == proto.toObject()->compartment());
 
     ObjectGroupCompartment::NewTable*& table = cx->compartment()->objectGroups.lazyTable;
 
     if (!table) {
-        table = cx->new_<ObjectGroupCompartment::NewTable>();
+        table = cx->new_<ObjectGroupCompartment::NewTable>(cx->zone());
         if (!table || !table->init()) {
             ReportOutOfMemory(cx);
             js_delete(table);
             table = nullptr;
             return nullptr;
         }
     }
 
@@ -588,32 +598,32 @@ ObjectGroup::lazySingletonGroup(Exclusiv
 
 /* 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;
     if (table) {
         Rooted<TaggedProto> taggedProto(cx, TaggedProto(obj));
-        ObjectGroupCompartment::NewTable::Ptr p =
-            table->lookup(ObjectGroupCompartment::NewEntry::Lookup(clasp, taggedProto, nullptr));
+        auto lookup = ObjectGroupCompartment::NewEntry::Lookup(clasp, taggedProto, nullptr);
+        auto p = table->lookup(lookup);
         if (p)
             MarkObjectGroupUnknownProperties(cx, p->group);
     }
 }
 
 #ifdef DEBUG
 /* static */ bool
 ObjectGroup::hasDefaultNewGroup(JSObject* proto, const Class* clasp, ObjectGroup* group)
 {
     ObjectGroupCompartment::NewTable* table = proto->compartment()->objectGroups.defaultNewTable;
 
     if (table) {
-        ObjectGroupCompartment::NewTable::Ptr p =
-            table->lookup(ObjectGroupCompartment::NewEntry::Lookup(clasp, TaggedProto(proto), nullptr));
+        auto lookup = ObjectGroupCompartment::NewEntry::Lookup(clasp, TaggedProto(proto), nullptr);
+        auto p = table->lookup(lookup);
         return p && p->group == group;
     }
     return false;
 }
 #endif /* DEBUG */
 
 inline const Class*
 GetClassForProtoKey(JSProtoKey key)
@@ -1609,31 +1619,31 @@ ObjectGroupCompartment::~ObjectGroupComp
     js_delete(plainObjectTable);
     js_delete(allocationSiteTable);
 }
 
 void
 ObjectGroupCompartment::removeDefaultNewGroup(const Class* clasp, TaggedProto proto,
                                               JSObject* associated)
 {
-    NewTable::Ptr p = defaultNewTable->lookup(NewEntry::Lookup(clasp, proto, associated));
+    auto p = defaultNewTable->lookup(NewEntry::Lookup(clasp, proto, associated));
     MOZ_RELEASE_ASSERT(p);
 
-    defaultNewTable->remove(p);
+    defaultNewTable->get().remove(p);
 }
 
 void
 ObjectGroupCompartment::replaceDefaultNewGroup(const Class* clasp, TaggedProto proto,
                                                JSObject* associated, ObjectGroup* group)
 {
     NewEntry::Lookup lookup(clasp, proto, associated);
 
-    NewTable::Ptr p = defaultNewTable->lookup(lookup);
+    auto p = defaultNewTable->lookup(lookup);
     MOZ_RELEASE_ASSERT(p);
-    defaultNewTable->remove(p);
+    defaultNewTable->get().remove(p);
     {
         AutoEnterOOMUnsafeRegion oomUnsafe;
         if (!defaultNewTable->putNew(lookup, NewEntry(group, associated)))
             oomUnsafe.crash("Inconsistent object table");
     }
 }
 
 /* static */
@@ -1729,20 +1739,16 @@ ObjectGroupCompartment::sweep(FreeOp* fo
      */
 
     if (arrayObjectTable)
         arrayObjectTable->sweep();
     if (plainObjectTable)
         plainObjectTable->sweep();
     if (allocationSiteTable)
         allocationSiteTable->sweep();
-    if (defaultNewTable)
-        defaultNewTable->sweep();
-    if (lazyTable)
-        lazyTable->sweep();
 }
 
 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().
@@ -1789,14 +1795,14 @@ ObjectGroupCompartment::checkNewTableAft
             CheckGCThingAfterMovingGC(proto.toObject());
         CheckGCThingAfterMovingGC(entry.associated);
 
         const Class* clasp = entry.group.unbarrieredGet()->clasp();
         if (entry.associated && entry.associated->is<JSFunction>())
             clasp = nullptr;
 
         NewEntry::Lookup lookup(clasp, proto, entry.associated);
-        NewTable::Ptr ptr = table->lookup(lookup);
+        auto ptr = table->lookup(lookup);
         MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &e.front());
     }
 }
 
 #endif // JSGC_HASH_TABLE_CHECKS
--- a/js/src/vm/ObjectGroup.h
+++ b/js/src/vm/ObjectGroup.h
@@ -535,17 +535,17 @@ class ObjectGroup : public gc::TenuredCe
 };
 
 // Structure used to manage the groups in a compartment.
 class ObjectGroupCompartment
 {
     friend class ObjectGroup;
 
     struct NewEntry;
-    using NewTable = js::GCHashSet<NewEntry, NewEntry, SystemAllocPolicy>;
+    class NewTable;
 
     // Set of default 'new' or lazy groups in the compartment.
     NewTable* defaultNewTable;
     NewTable* lazyTable;
 
     struct ArrayObjectKey;
     using ArrayObjectTable = js::GCRekeyableHashMap<ArrayObjectKey,
                                                     ReadBarrieredObjectGroup,