Bug 1263772 - Use WeakCache wrapper to sweep BaseShape table; r=jonco
authorTerrence Cole <terrence@mozilla.com>
Tue, 12 Apr 2016 17:05:15 -0700
changeset 331167 86bd74d49e63a7f6a5445a1f6d254689ad9accd0
parent 331166 ab87b53b3140fbb5e9e2caa5325ae0d791ee43d4
child 331168 76e8f6ad9ded250863aabef2da248867bc96e79c
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
bugs1263772
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 1263772 - Use WeakCache wrapper to sweep BaseShape table; r=jonco
js/public/GCHashTable.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsgc.cpp
js/src/jshashutil.h
js/src/vm/Shape.cpp
--- a/js/public/GCHashTable.h
+++ b/js/public/GCHashTable.h
@@ -131,47 +131,54 @@ class GCRekeyableHashMap : public GCHash
 };
 
 template <typename Outer, typename... Args>
 class GCHashMapOperations
 {
     using Map = GCHashMap<Args...>;
     using Lookup = typename Map::Lookup;
     using Ptr = typename Map::Ptr;
-    using AddPtr = typename Map::AddPtr;
     using Range = typename Map::Range;
-    using Enum = typename Map::Enum;
 
     const Map& map() const { return static_cast<const Outer*>(this)->get(); }
 
   public:
+    using AddPtr = typename Map::AddPtr;
+
     bool initialized() const                   { return map().initialized(); }
     Ptr lookup(const Lookup& l) const          { return map().lookup(l); }
     AddPtr lookupForAdd(const Lookup& l) const { return map().lookupForAdd(l); }
     Range all() const                          { return map().all(); }
     bool empty() const                         { return map().empty(); }
     uint32_t count() const                     { return map().count(); }
     size_t capacity() const                    { return map().capacity(); }
     bool has(const Lookup& l) const            { return map().lookup(l).found(); }
+    size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+        return map().sizeOfExcludingThis(mallocSizeOf);
+    }
+    size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+        return mallocSizeOf(this) + map().sizeOfExcludingThis(mallocSizeOf);
+    }
 };
 
 template <typename Outer, typename... Args>
 class MutableGCHashMapOperations
   : public GCHashMapOperations<Outer, Args...>
 {
     using Map = GCHashMap<Args...>;
     using Lookup = typename Map::Lookup;
     using Ptr = typename Map::Ptr;
-    using AddPtr = typename Map::AddPtr;
     using Range = typename Map::Range;
-    using Enum = typename Map::Enum;
 
     Map& map() { return static_cast<Outer*>(this)->get(); }
 
   public:
+    using AddPtr = typename Map::AddPtr;
+    struct Enum : public Map::Enum { explicit Enum(Outer& o) : Map::Enum(o.map()) {} };
+
     bool init(uint32_t len = 16) { return map().init(len); }
     void clear()                 { map().clear(); }
     void finish()                { map().finish(); }
     void remove(Ptr p)           { map().remove(p); }
 
     template<typename KeyInput, typename ValueInput>
     bool add(AddPtr& p, KeyInput&& k, ValueInput&& v) {
         return map().add(p, mozilla::Forward<KeyInput>(k), mozilla::Forward<ValueInput>(v));
@@ -274,47 +281,56 @@ class GCHashSet : public HashSet<T, Hash
 };
 
 template <typename Outer, typename... Args>
 class GCHashSetOperations
 {
     using Set = GCHashSet<Args...>;
     using Lookup = typename Set::Lookup;
     using Ptr = typename Set::Ptr;
-    using AddPtr = typename Set::AddPtr;
     using Range = typename Set::Range;
-    using Enum = typename Set::Enum;
 
     const Set& set() const { return static_cast<const Outer*>(this)->get(); }
 
   public:
+    using AddPtr = typename Set::AddPtr;
+    using Entry = typename Set::Entry;
+
     bool initialized() const                   { return set().initialized(); }
     Ptr lookup(const Lookup& l) const          { return set().lookup(l); }
     AddPtr lookupForAdd(const Lookup& l) const { return set().lookupForAdd(l); }
     Range all() const                          { return set().all(); }
     bool empty() const                         { return set().empty(); }
     uint32_t count() const                     { return set().count(); }
     size_t capacity() const                    { return set().capacity(); }
     bool has(const Lookup& l) const            { return set().lookup(l).found(); }
+    size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+        return set().sizeOfExcludingThis(mallocSizeOf);
+    }
+    size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+        return mallocSizeOf(this) + set().sizeOfExcludingThis(mallocSizeOf);
+    }
 };
 
 template <typename Outer, typename... Args>
 class MutableGCHashSetOperations
   : public GCHashSetOperations<Outer, Args...>
 {
     using Set = GCHashSet<Args...>;
     using Lookup = typename Set::Lookup;
     using Ptr = typename Set::Ptr;
-    using AddPtr = typename Set::AddPtr;
     using Range = typename Set::Range;
-    using Enum = typename Set::Enum;
 
     Set& set() { return static_cast<Outer*>(this)->get(); }
 
   public:
+    using AddPtr = typename Set::AddPtr;
+    using Entry = typename Set::Entry;
+    struct Enum : public Set::Enum { explicit Enum(Outer& o) : Set::Enum(o.set()) {} };
+
     bool init(uint32_t len = 16) { return set().init(len); }
     void clear()                 { set().clear(); }
     void finish()                { set().finish(); }
     void remove(Ptr p)           { set().remove(p); }
     void remove(const Lookup& l) { set().remove(l); }
 
     template<typename TInput>
     bool add(AddPtr& p, TInput&& t) {
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -61,16 +61,17 @@ JSCompartment::JSCompartment(Zone* zone,
     data(nullptr),
     allocationMetadataBuilder(nullptr),
     lastAnimationTime(0),
     regExps(runtime_),
     globalWriteBarriered(false),
     detachedTypedObjects(0),
     objectMetadataState(ImmediateMetadata()),
     propertyTree(thisForCtor()),
+    baseShapes(zone, BaseShapeSet()),
     selfHostingScriptSource(nullptr),
     objectMetadataTable(nullptr),
     innerViews(zone, InnerViewTable()),
     lazyArrayBuffers(nullptr),
     nonSyntacticLexicalScopes_(nullptr),
     gcIncomingGrayPointers(nullptr),
     debugModeBits(0),
     watchpointMap(nullptr),
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -433,18 +433,17 @@ struct JSCompartment
                                 size_t* privateData);
 
     /*
      * Shared scope property tree, and arena-pool for allocating its nodes.
      */
     js::PropertyTree             propertyTree;
 
     /* Set of all unowned base shapes in the compartment. */
-    js::BaseShapeSet             baseShapes;
-    void sweepBaseShapeTable();
+    JS::WeakCache<js::BaseShapeSet> baseShapes;
 
     /* Set of initial shapes in the compartment. */
     js::InitialShapeSet          initialShapes;
     void sweepInitialShapeTable();
 
     // Object group tables and other state in the compartment.
     js::ObjectGroupCompartment   objectGroups;
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2447,17 +2447,16 @@ GCRuntime::sweepZoneAfterCompacting(Zone
     FreeOp* fop = rt->defaultFreeOp();
     sweepTypesAfterCompacting(zone);
     zone->sweepBreakpoints(fop);
     zone->sweepWeakMaps();
     for (auto* cache : zone->weakCaches_)
         cache->sweep();
 
     for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) {
-        c->sweepBaseShapeTable();
         c->sweepInitialShapeTable();
         c->objectGroups.sweep(fop);
         c->sweepRegExps();
         c->sweepSavedStacks();
         c->sweepGlobalObject(fop);
         c->sweepObjectPendingMetadata();
         c->sweepSelfHostingScriptSource();
         c->sweepDebugScopes();
@@ -5079,23 +5078,16 @@ SweepAtomsTask::run()
 /* virtual */ void
 SweepCCWrappersTask::run()
 {
     for (GCCompartmentGroupIter c(runtime); !c.done(); c.next())
         c->sweepCrossCompartmentWrappers();
 }
 
 /* virtual */ void
-SweepBaseShapesTask::run()
-{
-    for (GCCompartmentGroupIter c(runtime); !c.done(); c.next())
-        c->sweepBaseShapeTable();
-}
-
-/* virtual */ void
 SweepInitialShapesTask::run()
 {
     for (GCCompartmentGroupIter c(runtime); !c.done(); c.next())
         c->sweepInitialShapeTable();
 }
 
 /* virtual */ void
 SweepObjectGroupsTask::run()
@@ -5167,17 +5159,16 @@ GCRuntime::beginSweepingZoneGroup()
 #endif
     }
 
     validateIncrementalMarking();
 
     FreeOp fop(rt);
     SweepAtomsTask sweepAtomsTask(rt);
     SweepCCWrappersTask sweepCCWrappersTask(rt);
-    SweepBaseShapesTask sweepBaseShapesTask(rt);
     SweepInitialShapesTask sweepInitialShapesTask(rt);
     SweepObjectGroupsTask sweepObjectGroupsTask(rt);
     SweepRegExpsTask sweepRegExpsTask(rt);
     SweepMiscTask sweepMiscTask(rt);
     mozilla::Vector<SweepWeakCacheTask> sweepCacheTasks;
 
     for (GCZoneGroupIter zone(rt); !zone.done(); zone.next()) {
         /* Clear all weakrefs that point to unmarked things. */
@@ -5222,17 +5213,16 @@ GCRuntime::beginSweepingZoneGroup()
 
     {
         gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP_COMPARTMENTS);
         gcstats::AutoSCC scc(stats, zoneGroupIndex);
 
         {
             AutoLockHelperThreadState helperLock;
             startTask(sweepCCWrappersTask, gcstats::PHASE_SWEEP_CC_WRAPPER);
-            startTask(sweepBaseShapesTask, gcstats::PHASE_SWEEP_BASE_SHAPE);
             startTask(sweepInitialShapesTask, gcstats::PHASE_SWEEP_INITIAL_SHAPE);
             startTask(sweepObjectGroupsTask, gcstats::PHASE_SWEEP_TYPE_OBJECT);
             startTask(sweepRegExpsTask, gcstats::PHASE_SWEEP_REGEXP);
             startTask(sweepMiscTask, gcstats::PHASE_SWEEP_MISC);
             for (auto& task : sweepCacheTasks)
                 startTask(task, gcstats::PHASE_SWEEP_MISC);
         }
 
@@ -5304,17 +5294,16 @@ GCRuntime::beginSweepingZoneGroup()
     }
 
     {
         gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP_COMPARTMENTS);
         gcstats::AutoSCC scc(stats, zoneGroupIndex);
 
         AutoLockHelperThreadState helperLock;
         joinTask(sweepCCWrappersTask, gcstats::PHASE_SWEEP_CC_WRAPPER);
-        joinTask(sweepBaseShapesTask, gcstats::PHASE_SWEEP_BASE_SHAPE);
         joinTask(sweepInitialShapesTask, gcstats::PHASE_SWEEP_INITIAL_SHAPE);
         joinTask(sweepObjectGroupsTask, gcstats::PHASE_SWEEP_TYPE_OBJECT);
         joinTask(sweepRegExpsTask, gcstats::PHASE_SWEEP_REGEXP);
         joinTask(sweepMiscTask, gcstats::PHASE_SWEEP_MISC);
         for (auto& task : sweepCacheTasks)
             joinTask(task, gcstats::PHASE_SWEEP_MISC);
     }
 
--- a/js/src/jshashutil.h
+++ b/js/src/jshashutil.h
@@ -25,38 +25,51 @@ struct DependentAddPtr
     typedef typename T::Entry Entry;
 
     template <class Lookup>
     DependentAddPtr(const ExclusiveContext* cx, const T& table, const Lookup& lookup)
       : addPtr(table.lookupForAdd(lookup))
       , originalGcNumber(cx->zone()->gcNumber())
     {}
 
+    DependentAddPtr(DependentAddPtr&& other)
+      : addPtr(other.addPtr)
+      , originalGcNumber(other.originalGcNumber)
+    {}
+
     template <class KeyInput, class ValueInput>
     bool add(ExclusiveContext* cx, T& table, const KeyInput& key, const ValueInput& value) {
         bool gcHappened = originalGcNumber != cx->zone()->gcNumber();
         if (gcHappened)
             addPtr = table.lookupForAdd(key);
         if (!table.relookupOrAdd(addPtr, key, value)) {
             ReportOutOfMemory(cx);
             return false;
         }
         return true;
     }
 
-
     bool found() const                 { return addPtr.found(); }
     explicit operator bool() const     { return found(); }
     const Entry& operator*() const     { return *addPtr; }
     const Entry* operator->() const    { return &*addPtr; }
 
   private:
     AddPtr addPtr ;
     const uint64_t originalGcNumber;
 
     DependentAddPtr() = delete;
     DependentAddPtr(const DependentAddPtr&) = delete;
     DependentAddPtr& operator=(const DependentAddPtr&) = delete;
 };
 
+template <typename T, typename Lookup>
+inline auto
+MakeDependentAddPtr(const ExclusiveContext* cx, T& table, const Lookup& lookup)
+  -> DependentAddPtr<typename mozilla::RemoveReference<decltype(table)>::Type>
+{
+    using Ptr = DependentAddPtr<typename mozilla::RemoveReference<decltype(table)>::Type>;
+    return Ptr(cx, table, lookup);
+}
+
 } // namespace js
 
 #endif
--- a/js/src/vm/Shape.cpp
+++ b/js/src/vm/Shape.cpp
@@ -1288,24 +1288,24 @@ BaseShape::adoptUnowned(UnownedBaseShape
     setSlotSpan(span);
 
     assertConsistency();
 }
 
 /* static */ UnownedBaseShape*
 BaseShape::getUnowned(ExclusiveContext* cx, StackBaseShape& base)
 {
-    BaseShapeSet& table = cx->compartment()->baseShapes;
+    auto& table = cx->compartment()->baseShapes;
 
     if (!table.initialized() && !table.init()) {
         ReportOutOfMemory(cx);
         return nullptr;
     }
 
-    DependentAddPtr<BaseShapeSet> p(cx, table, base);
+    auto p = MakeDependentAddPtr(cx, table, base);
     if (p)
         return *p;
 
     BaseShape* nbase_ = Allocate<BaseShape>(cx);
     if (!nbase_)
         return nullptr;
 
     new (nbase_) BaseShape(base);
@@ -1354,31 +1354,25 @@ BaseShape::traceChildrenSkipShapeTable(J
 
 void
 BaseShape::traceShapeTable(JSTracer* trc)
 {
     if (hasTable())
         table().trace(trc);
 }
 
-void
-JSCompartment::sweepBaseShapeTable()
-{
-    baseShapes.sweep();
-}
-
 #ifdef JSGC_HASH_TABLE_CHECKS
 
 void
 JSCompartment::checkBaseShapeTableAfterMovingGC()
 {
     if (!baseShapes.initialized())
         return;
 
-    for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) {
+    for (decltype(baseShapes)::Enum e(baseShapes); !e.empty(); e.popFront()) {
         UnownedBaseShape* base = e.front().unbarrieredGet();
         CheckGCThingAfterMovingGC(base);
 
         BaseShapeSet::Ptr ptr = baseShapes.lookup(base);
         MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &e.front());
     }
 }