Backed out changesets 06c511b6093e, dbec0bed9bf5, bfedb105396e (bug 1088831) for causing various assertions on a CLOSED TREE.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 13 Nov 2014 21:11:24 -0500
changeset 215692 44ba0c1d88cb2b2f6c89d22f2d5bc3e45ce9433a
parent 215691 725e54a559d6f97d894774fd235fcd146225b256
child 215693 0144dbebb8ca98dc94b5cb925630014d33e5cba5
push id27823
push usercbook@mozilla.com
push dateFri, 14 Nov 2014 11:59:57 +0000
treeherdermozilla-central@bbb68df450c2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1088831
milestone36.0a1
backs out06c511b6093ea188b8675ed73116f3da4fa5797b
dbec0bed9bf5cb2bf6a2e66b41f35e11a6b2615c
bfedb105396ee4713a7d0a7b1b4d0dc85d6f89dc
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
Backed out changesets 06c511b6093e, dbec0bed9bf5, bfedb105396e (bug 1088831) for causing various assertions on a CLOSED TREE.
js/src/gc/Statistics.cpp
js/src/gc/Statistics.h
js/src/gc/StoreBuffer.cpp
js/src/gc/StoreBuffer.h
js/src/gc/Verifier.cpp
js/src/jsgc.cpp
js/src/shell/js.cpp
--- a/js/src/gc/Statistics.cpp
+++ b/js/src/gc/Statistics.cpp
@@ -22,17 +22,16 @@
 #include "vm/HelperThreads.h"
 #include "vm/Runtime.h"
 
 using namespace js;
 using namespace js::gc;
 using namespace js::gcstats;
 
 using mozilla::PodArrayZero;
-using mozilla::PodZero;
 
 /* Except for the first and last, slices of less than 10ms are not reported. */
 static const int64_t SLICE_MIN_REPORT_TIME = 10 * PRMJ_USEC_PER_MSEC;
 
 class gcstats::StatisticsSerializer
 {
     typedef Vector<char, 128, SystemAllocPolicy> CharBuffer;
     CharBuffer buf_;
@@ -279,17 +278,16 @@ struct PhaseInfo
     Phase index;
     const char *name;
     Phase parent;
 };
 
 static const Phase PHASE_NO_PARENT = PHASE_LIMIT;
 
 static const PhaseInfo phases[] = {
-    { PHASE_MUTATOR, "Mutator Running", PHASE_NO_PARENT },
     { PHASE_GC_BEGIN, "Begin Callback", PHASE_NO_PARENT },
     { PHASE_WAIT_BACKGROUND_THREAD, "Wait Background Thread", PHASE_NO_PARENT },
     { PHASE_MARK_DISCARD_CODE, "Mark Discard Code", PHASE_NO_PARENT },
     { PHASE_PURGE, "Purge", PHASE_NO_PARENT },
     { PHASE_MARK, "Mark", PHASE_NO_PARENT },
         { PHASE_MARK_ROOTS, "Mark Roots", PHASE_MARK },
         { PHASE_MARK_DELAYED, "Mark Delayed", PHASE_MARK },
     { PHASE_SWEEP, "Sweep", PHASE_NO_PARENT },
@@ -323,19 +321,16 @@ static const PhaseInfo phases[] = {
         { PHASE_SWEEP_JITCODE, "Sweep JIT code", PHASE_SWEEP },
         { PHASE_FINALIZE_END, "Finalize End Callback", PHASE_SWEEP },
         { PHASE_DESTROY, "Deallocate", PHASE_SWEEP },
     { PHASE_COMPACT, "Compact", PHASE_NO_PARENT },
         { PHASE_COMPACT_MOVE, "Compact Move", PHASE_COMPACT },
         { PHASE_COMPACT_UPDATE, "Compact Update", PHASE_COMPACT, },
             { PHASE_COMPACT_UPDATE_GRAY, "Compact Update Gray", PHASE_COMPACT_UPDATE, },
     { PHASE_GC_END, "End Callback", PHASE_NO_PARENT },
-    { PHASE_MINOR_GC, "Minor GC", PHASE_NO_PARENT },
-        { PHASE_COMPACT_STOREBUFFER_IN_MINOR_GC, "Compact Store Buffers", PHASE_MINOR_GC },
-    { PHASE_COMPACT_STOREBUFFER_NO_PARENT, "Compact Store Buffers (toplevel)", PHASE_NO_PARENT },
     { PHASE_LIMIT, nullptr, PHASE_NO_PARENT }
 };
 
 static void
 FormatPhaseTimes(StatisticsSerializer &ss, const char *name, int64_t *times)
 {
     ss.beginObject(name);
     for (unsigned i = 0; phases[i].name; i++)
@@ -385,18 +380,16 @@ Statistics::formatData(StatisticsSeriali
         ss.appendDecimal("Max Pause", "ms", t(longest));
     else
         ss.appendString("Reason", ExplainReason(slices[0].reason));
     ss.appendDecimal("Total Time", "ms", t(total));
     ss.appendNumber("Zones Collected", "%d", "", zoneStats.collectedZoneCount);
     ss.appendNumber("Total Zones", "%d", "", zoneStats.zoneCount);
     ss.appendNumber("Total Compartments", "%d", "", zoneStats.compartmentCount);
     ss.appendNumber("Minor GCs", "%d", "", counts[STAT_MINOR_GC]);
-    ss.appendNumber("Store Buffer Compactions", "%d", "", counts[STAT_COMPACT_STOREBUFFER]);
-    ss.appendNumber("Store Buffer Overflows", "%d", "", counts[STAT_STOREBUFFER_OVERFLOW]);
     ss.appendNumber("MMU (20ms)", "%d", "%", int(mmu20 * 100));
     ss.appendNumber("MMU (50ms)", "%d", "%", int(mmu50 * 100));
     ss.appendDecimal("SCC Sweep Total", "ms", t(sccTotal));
     ss.appendDecimal("SCC Sweep Max Pause", "ms", t(sccLongest));
     if (nonincrementalReason || ss.isJSON()) {
         ss.appendString("Nonincremental Reason",
                         nonincrementalReason ? nonincrementalReason : "none");
     }
@@ -478,35 +471,31 @@ Statistics::formatDescription()
     const char *format =
 "=================================================================\n\
   Invocation Kind: %s\n\
   Reason: %s\n\
   Incremental: %s%s\n\
   Zones Collected: %d of %d\n\
   Compartments Collected: %d of %d\n\
   MinorGCs since last GC: %d\n\
-  Store Buffer Compactions: %d\n\
-  Store Buffer Overflows: %d\n\
   MMU 20ms:%.1f%%; 50ms:%.1f%%\n\
   SCC Sweep Total (MaxPause): %.3fms (%.3fms)\n\
   HeapSize: %.3f MiB\n\
   Chunk Delta (magnitude): %+d  (%d)\n\
 ";
     char buffer[1024];
     memset(buffer, 0, sizeof(buffer));
     JS_snprintf(buffer, sizeof(buffer), format,
                 ExplainInvocationKind(gckind),
                 ExplainReason(slices[0].reason),
                 nonincrementalReason ? "no - " : "yes",
                                                   nonincrementalReason ? nonincrementalReason : "",
                 zoneStats.collectedZoneCount, zoneStats.zoneCount,
                 zoneStats.collectedCompartmentCount, zoneStats.compartmentCount,
                 counts[STAT_MINOR_GC],
-                counts[STAT_COMPACT_STOREBUFFER],
-                counts[STAT_STOREBUFFER_OVERFLOW],
                 mmu20 * 100., mmu50 * 100.,
                 t(sccTotal), t(sccLongest),
                 double(preBytes) / 1024. / 1024.,
                 counts[STAT_NEW_CHUNK] - counts[STAT_DESTROY_CHUNK], counts[STAT_NEW_CHUNK] +
                                                                   counts[STAT_DESTROY_CHUNK]);
     return make_string_copy(buffer);
 }
 
@@ -639,27 +628,23 @@ Statistics::formatJSON(uint64_t timestam
 
 Statistics::Statistics(JSRuntime *rt)
   : runtime(rt),
     startupTime(PRMJ_Now()),
     fp(nullptr),
     fullFormat(false),
     gcDepth(0),
     nonincrementalReason(nullptr),
-    timingMutator(false),
-    timedGCStart(0),
     preBytes(0),
     maxPauseInInterval(0),
     phaseNestingDepth(0),
     sliceCallback(nullptr)
 {
     PodArrayZero(phaseTotals);
     PodArrayZero(counts);
-    PodArrayZero(phaseStartTimes);
-    PodArrayZero(phaseTimes);
 
     char *env = getenv("MOZ_GCTIMER");
     if (!env || strcmp(env, "none") == 0) {
         fp = nullptr;
         return;
     }
 
     if (strcmp(env, "stdout") == 0) {
@@ -733,16 +718,19 @@ Statistics::printStats()
                 t(phaseTimes[PHASE_SWEEP]));
     }
     fflush(fp);
 }
 
 void
 Statistics::beginGC(JSGCInvocationKind kind)
 {
+    PodArrayZero(phaseStartTimes);
+    PodArrayZero(phaseTimes);
+
     slices.clearAndFree();
     sccTimes.clearAndFree();
     gckind = kind;
     nonincrementalReason = nullptr;
 
     preBytes = runtime->gc.usage.gcBytes();
 }
 
@@ -774,21 +762,16 @@ Statistics::endGC()
         (*cb)(JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS, t(sccLongest));
 
         double mmu50 = computeMMU(50 * PRMJ_USEC_PER_MSEC);
         (*cb)(JS_TELEMETRY_GC_MMU_50, mmu50 * 100);
     }
 
     if (fp)
         printStats();
-
-    // Clear the timers at the end of a GC because we accumulate time for some
-    // phases (eg storebuffer compaction) during the mutator's run.
-    PodZero(&phaseStartTimes[PHASE_GC_BEGIN], PHASE_LIMIT - PHASE_GC_BEGIN);
-    PodZero(&phaseTimes[PHASE_GC_BEGIN], PHASE_LIMIT - PHASE_GC_BEGIN);
 }
 
 void
 Statistics::beginSlice(const ZoneGCStats &zoneStats, JSGCInvocationKind gckind,
                        JS::gcreason::Reason reason)
 {
     this->zoneStats = zoneStats;
 
@@ -836,92 +819,42 @@ Statistics::endSlice()
     }
 
     /* Do this after the slice callback since it uses these values. */
     if (last)
         PodArrayZero(counts);
 }
 
 void
-Statistics::startTimingMutator()
-{
-    MOZ_ASSERT(!timingMutator);
-
-    // Should only be called from outside of GC
-    MOZ_ASSERT(phaseNestingDepth == 0);
-
-    timingMutator = true;
-    timedGCTime = 0;
-    phaseStartTimes[PHASE_MUTATOR] = 0;
-    phaseTimes[PHASE_MUTATOR] = 0;
-    timedGCStart = 0;
-
-    beginPhase(PHASE_MUTATOR);
-}
-
-void
-Statistics::stopTimingMutator(double &mutator_ms, double &gc_ms)
-{
-    MOZ_ASSERT(timingMutator);
-
-    // Should only be called from outside of GC
-    MOZ_ASSERT(phaseNestingDepth == 1 && phaseNesting[0] == PHASE_MUTATOR);
-
-    endPhase(PHASE_MUTATOR);
-    mutator_ms = t(phaseTimes[PHASE_MUTATOR]);
-    gc_ms = t(timedGCTime);
-    timingMutator = false;
-}
-
-void
 Statistics::beginPhase(Phase phase)
 {
     /* Guard against re-entry */
     MOZ_ASSERT(!phaseStartTimes[phase]);
 
-    if (timingMutator) {
-        if (phaseNestingDepth == 1 && phaseNesting[0] == PHASE_MUTATOR) {
-            endPhase(PHASE_MUTATOR);
-            timedGCStart = PRMJ_Now();
-        }
-    }
-
 #ifdef DEBUG
     MOZ_ASSERT(phases[phase].index == phase);
     Phase parent = phaseNestingDepth ? phaseNesting[phaseNestingDepth - 1] : PHASE_NO_PARENT;
     MOZ_ASSERT(phaseNestingDepth < MAX_NESTING);
     MOZ_ASSERT_IF(gcDepth == 1, phases[phase].parent == parent);
-    MOZ_ASSERT_IF(phase == PHASE_COMPACT_STOREBUFFER_IN_MINOR_GC, parent == PHASE_MINOR_GC);
-    MOZ_ASSERT_IF(phase == PHASE_COMPACT_STOREBUFFER_NO_PARENT, parent == PHASE_NO_PARENT);
-
     phaseNesting[phaseNestingDepth] = phase;
     phaseNestingDepth++;
 #endif
 
     phaseStartTimes[phase] = PRMJ_Now();
 }
 
 void
 Statistics::endPhase(Phase phase)
 {
     phaseNestingDepth--;
 
-    int64_t now = PRMJ_Now();
-    int64_t t = now - phaseStartTimes[phase];
-    if (!slices.empty())
-        slices.back().phaseTimes[phase] += t;
+    int64_t t = PRMJ_Now() - phaseStartTimes[phase];
+    slices.back().phaseTimes[phase] += t;
     phaseTimes[phase] += t;
     phaseStartTimes[phase] = 0;
-
-    if (timingMutator) {
-        if (phaseNestingDepth == 0 && phase != PHASE_MUTATOR) {
-            timedGCTime += now - timedGCStart;
-            beginPhase(PHASE_MUTATOR);
-        }
-    }
 }
 
 void
 Statistics::endParallelPhase(Phase phase, const GCParallelTask *task)
 {
     phaseNestingDepth--;
 
     slices.back().phaseTimes[phase] += task->duration();
--- a/js/src/gc/Statistics.h
+++ b/js/src/gc/Statistics.h
@@ -22,17 +22,16 @@ struct JSCompartment;
 
 namespace js {
 
 class GCParallelTask;
 
 namespace gcstats {
 
 enum Phase {
-    PHASE_MUTATOR,
     PHASE_GC_BEGIN,
     PHASE_WAIT_BACKGROUND_THREAD,
     PHASE_MARK_DISCARD_CODE,
     PHASE_PURGE,
     PHASE_MARK,
     PHASE_MARK_ROOTS,
     PHASE_MARK_DELAYED,
     PHASE_SWEEP,
@@ -66,35 +65,25 @@ enum Phase {
     PHASE_SWEEP_JITCODE,
     PHASE_FINALIZE_END,
     PHASE_DESTROY,
     PHASE_COMPACT,
     PHASE_COMPACT_MOVE,
     PHASE_COMPACT_UPDATE,
     PHASE_COMPACT_UPDATE_GRAY,
     PHASE_GC_END,
-    PHASE_MINOR_GC,
-    PHASE_COMPACT_STOREBUFFER_IN_MINOR_GC,
-    PHASE_COMPACT_STOREBUFFER_NO_PARENT,
 
     PHASE_LIMIT
 };
 
 enum Stat {
     STAT_NEW_CHUNK,
     STAT_DESTROY_CHUNK,
     STAT_MINOR_GC,
 
-    // Number of times the storebuffers were compacted
-    STAT_COMPACT_STOREBUFFER,
-
-    // Number of times a 'put' into a storebuffer overflowed, triggering a
-    // compaction
-    STAT_STOREBUFFER_OVERFLOW,
-
     STAT_LIMIT
 };
 
 class StatisticsSerializer;
 
 struct ZoneGCStats
 {
     /* Number of zones collected in this GC. */
@@ -124,19 +113,16 @@ struct Statistics
     void beginPhase(Phase phase);
     void endPhase(Phase phase);
     void endParallelPhase(Phase phase, const GCParallelTask *task);
 
     void beginSlice(const ZoneGCStats &zoneStats, JSGCInvocationKind gckind,
                     JS::gcreason::Reason reason);
     void endSlice();
 
-    void startTimingMutator();
-    void stopTimingMutator(double &mutator_ms, double &gc_ms);
-
     void reset(const char *reason) { slices.back().resetReason = reason; }
     void nonincremental(const char *reason) { nonincrementalReason = reason; }
 
     void count(Stat s) {
         MOZ_ASSERT(s < STAT_LIMIT);
         counts[s]++;
     }
 
@@ -188,42 +174,37 @@ struct Statistics
         int64_t duration() const { return end - start; }
     };
 
     Vector<SliceData, 8, SystemAllocPolicy> slices;
 
     /* Most recent time when the given phase started. */
     int64_t phaseStartTimes[PHASE_LIMIT];
 
-    /* Are we currently timing mutator vs GC time? */
-    bool timingMutator;
-
-    /* Bookkeeping for GC timings when timingMutator is true */
-    int64_t timedGCStart;
-    int64_t timedGCTime;
-
     /* Total time in a given phase for this GC. */
     int64_t phaseTimes[PHASE_LIMIT];
 
     /* Total time in a given phase over all GCs. */
     int64_t phaseTotals[PHASE_LIMIT];
 
     /* Number of events of this type for this GC. */
     unsigned int counts[STAT_LIMIT];
 
     /* Allocated space before the GC started. */
     size_t preBytes;
 
     /* Records the maximum GC pause in an API-controlled interval (in us). */
     int64_t maxPauseInInterval;
 
+#ifdef DEBUG
     /* Phases that are currently on stack. */
     static const size_t MAX_NESTING = 8;
     Phase phaseNesting[MAX_NESTING];
-    size_t phaseNestingDepth;
+#endif
+    mozilla::DebugOnly<size_t> phaseNestingDepth;
 
     /* Sweep times for SCCs of compartments. */
     Vector<int64_t, 0, SystemAllocPolicy> sccTimes;
 
     JS::GCSliceCallback sliceCallback;
 
     void beginGC(JSGCInvocationKind kind);
     void endGC();
--- a/js/src/gc/StoreBuffer.cpp
+++ b/js/src/gc/StoreBuffer.cpp
@@ -5,32 +5,25 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifdef JSGC_GENERATIONAL
 
 #include "gc/StoreBuffer.h"
 
 #include "mozilla/Assertions.h"
 
-#include "gc/Statistics.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/ForkJoin.h"
 
 #include "jsgcinlines.h"
 
 using namespace js;
 using namespace js::gc;
 using mozilla::ReentrancyGuard;
 
-gcstats::Statistics&
-StoreBuffer::stats()
-{
-    return runtime_->gc.stats;
-}
-
 /*** Edges ***/
 
 void
 StoreBuffer::SlotsEdge::mark(JSTracer *trc)
 {
     NativeObject *obj = object();
 
     // Beware JSObject::swap exchanging a native object for a non-native one.
@@ -95,30 +88,26 @@ template <typename T>
 void
 StoreBuffer::MonoTypeBuffer<T>::handleOverflow(StoreBuffer *owner)
 {
     if (!owner->isAboutToOverflow()) {
         /*
          * Compact the buffer now, and if that fails to free enough space then
          * trigger a minor collection.
          */
-        gcstats::AutoPhase ap(owner->stats(), gcstats::PHASE_COMPACT_STOREBUFFER_NO_PARENT);
-        owner->stats().count(gcstats::STAT_STOREBUFFER_OVERFLOW);
         compact(owner);
         if (isLowOnSpace())
             owner->setAboutToOverflow();
     } else {
          /*
           * A minor GC has already been triggered, so there's no point
           * compacting unless the buffer is totally full.
           */
-        if (storage_->availableInCurrentChunk() < sizeof(T)) {
-            owner->stats().count(gcstats::STAT_STOREBUFFER_OVERFLOW);
-            maybeCompact(owner, gcstats::PHASE_COMPACT_STOREBUFFER_NO_PARENT);
-        }
+        if (storage_->availableInCurrentChunk() < sizeof(T))
+            maybeCompact(owner);
     }
 }
 
 template <typename T>
 void
 StoreBuffer::MonoTypeBuffer<T>::compactRemoveDuplicates(StoreBuffer *owner)
 {
     typedef HashSet<T, typename T::Hasher, SystemAllocPolicy> DedupSet;
@@ -136,50 +125,46 @@ StoreBuffer::MonoTypeBuffer<T>::compactR
 
             /* Failure to insert will leave the set with duplicates. Oh well. */
             duplicates.put(*edge);
         }
     }
     storage_->release(insert.mark());
 
     duplicates.clear();
-    owner->stats().count(gcstats::STAT_COMPACT_STOREBUFFER);
 }
 
 template <typename T>
 void
 StoreBuffer::MonoTypeBuffer<T>::compact(StoreBuffer *owner)
 {
     MOZ_ASSERT(storage_);
     compactRemoveDuplicates(owner);
     usedAtLastCompact_ = storage_->used();
 }
 
 template <typename T>
 void
-StoreBuffer::MonoTypeBuffer<T>::maybeCompact(StoreBuffer *owner, int phase)
+StoreBuffer::MonoTypeBuffer<T>::maybeCompact(StoreBuffer *owner)
 {
     MOZ_ASSERT(storage_);
-    if (storage_->used() != usedAtLastCompact_) {
-        gcstats::AutoPhase ap(owner->stats(), static_cast<gcstats::Phase>(phase));
+    if (storage_->used() != usedAtLastCompact_)
         compact(owner);
-    }
 }
 
 template <typename T>
 void
 StoreBuffer::MonoTypeBuffer<T>::mark(StoreBuffer *owner, JSTracer *trc)
 {
     MOZ_ASSERT(owner->isEnabled());
     ReentrancyGuard g(*owner);
     if (!storage_)
         return;
 
-    maybeCompact(owner, gcstats::PHASE_COMPACT_STOREBUFFER_IN_MINOR_GC);
-
+    maybeCompact(owner);
     for (LifoAlloc::Enum e(*storage_); !e.empty(); e.popFront<T>()) {
         T *edge = e.get<T>();
         edge->mark(trc);
     }
 }
 
 /*** RelocatableMonoTypeBuffer ***/
 
--- a/js/src/gc/StoreBuffer.h
+++ b/js/src/gc/StoreBuffer.h
@@ -17,20 +17,16 @@
 
 #include "ds/LifoAlloc.h"
 #include "gc/Nursery.h"
 #include "gc/Tracer.h"
 #include "js/MemoryMetrics.h"
 
 namespace js {
 
-namespace gcstats {
-struct Statistics;
-}
-
 MOZ_NORETURN void
 CrashAtUnhandlableOOM(const char *reason);
 
 namespace gc {
 
 /*
  * BufferableRef represents an abstract reference for use in the generational
  * GC's remembered set. Entries in the store buffer that cannot be represented
@@ -139,17 +135,17 @@ class StoreBuffer
 
         /*
          * Attempts to reduce the usage of the buffer by removing unnecessary
          * entries.
          */
         virtual void compact(StoreBuffer *owner);
 
         /* Compacts if any entries have been added since the last compaction. */
-        void maybeCompact(StoreBuffer *owner, int phase);
+        void maybeCompact(StoreBuffer *owner);
 
         /* Add one item to the buffer. */
         void put(StoreBuffer *owner, const T &t) {
             MOZ_ASSERT(storage_);
 
             T *tp = storage_->new_<T>(t);
             if (!tp)
                 CrashAtUnhandlableOOM("Failed to allocate for MonoTypeBuffer::put.");
@@ -488,18 +484,16 @@ class StoreBuffer
     void putGeneric(const T &t) { putFromAnyThread(bufferGeneric, t);}
 
     /* Insert or update a callback entry. */
     template <typename Key>
     void putCallback(void (*callback)(JSTracer *trc, Key *key, void *data), Key *key, void *data) {
         putFromAnyThread(bufferGeneric, CallbackRef<Key>(callback, key, data));
     }
 
-    gcstats::Statistics& stats();
-
     /* Methods to mark the source of all edges in the store buffer. */
     void markAll(JSTracer *trc);
     void markValues(JSTracer *trc)            { bufferVal.mark(this, trc); }
     void markCells(JSTracer *trc)             { bufferCell.mark(this, trc); }
     void markSlots(JSTracer *trc)             { bufferSlot.mark(this, trc); }
     void markWholeCells(JSTracer *trc)        { bufferWholeCell.mark(this, trc); }
     void markRelocatableValues(JSTracer *trc) { bufferRelocVal.mark(this, trc); }
     void markRelocatableCells(JSTracer *trc)  { bufferRelocCell.mark(this, trc); }
--- a/js/src/gc/Verifier.cpp
+++ b/js/src/gc/Verifier.cpp
@@ -498,20 +498,17 @@ js::gc::GCRuntime::endVerifyPostBarriers
     VerifyPostTracer::EdgeSet edges;
     AutoPrepareForTracing prep(rt, SkipAtoms);
 
     /* Visit every entry in the store buffer and put the edges in a hash set. */
     trc->setTraceCallback(PostVerifierCollectStoreBufferEdges);
     if (!edges.init())
         goto oom;
     trc->edges = &edges;
-    {
-        gcstats::AutoPhase ap(stats, gcstats::PHASE_MINOR_GC);
-        storeBuffer.markAll(trc);
-    }
+    storeBuffer.markAll(trc);
 
     /* Walk the heap to find any edges not the the |edges| set. */
     trc->setTraceCallback(PostVerifierVisitEdge);
     for (GCZoneGroupIter zone(rt); !zone.done(); zone.next()) {
         for (size_t kind = 0; kind < FINALIZE_LIMIT; ++kind) {
             for (ZoneCellIterUnderGC cells(zone, AllocKind(kind)); !cells.done(); cells.next()) {
                 Cell *src = cells.getCell();
                 JS_TraceChildren(trc, src, MapAllocToTraceKind(AllocKind(kind)));
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -6277,32 +6277,30 @@ GCRuntime::onOutOfMallocMemory()
     // malloc request.
     decommitAllWithoutUnlocking(lock);
 }
 
 void
 GCRuntime::minorGC(JS::gcreason::Reason reason)
 {
 #ifdef JSGC_GENERATIONAL
-    gcstats::AutoPhase ap(stats, gcstats::PHASE_MINOR_GC);
     minorGCRequested = false;
     TraceLogger *logger = TraceLoggerForMainThread(rt);
     AutoTraceLog logMinorGC(logger, TraceLogger::MinorGC);
     nursery.collect(rt, reason, nullptr);
     MOZ_ASSERT_IF(!rt->mainThread.suppressGC, nursery.isEmpty());
 #endif
 }
 
 void
 GCRuntime::minorGC(JSContext *cx, JS::gcreason::Reason reason)
 {
     // Alternate to the runtime-taking form above which allows marking type
     // objects as needing pretenuring.
 #ifdef JSGC_GENERATIONAL
-    gcstats::AutoPhase ap(stats, gcstats::PHASE_MINOR_GC);
     minorGCRequested = false;
     TraceLogger *logger = TraceLoggerForMainThread(rt);
     AutoTraceLog logMinorGC(logger, TraceLogger::MinorGC);
     Nursery::TypeObjectList pretenureTypes;
     nursery.collect(rt, reason, &pretenureTypes);
     for (size_t i = 0; i < pretenureTypes.length(); i++) {
         if (pretenureTypes[i]->canPreTenure())
             pretenureTypes[i]->setShouldPreTenure(cx);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1664,53 +1664,16 @@ Quit(JSContext *cx, unsigned argc, jsval
 
     CallArgs args = CallArgsFromVp(argc, vp);
     JS_ConvertArguments(cx, args, "/ i", &gExitCode);
 
     gQuitting = true;
     return false;
 }
 
-static bool
-StartTimingMutator(JSContext *cx, unsigned argc, jsval *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    if (args.length() > 0) {
-        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
-                             JSSMSG_TOO_MANY_ARGS, "startTimingMutator");
-        return false;
-    }
-
-    cx->runtime()->gc.stats.startTimingMutator();
-    args.rval().setUndefined();
-    return true;
-}
-
-static bool
-StopTimingMutator(JSContext *cx, unsigned argc, jsval *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    if (args.length() > 0) {
-        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
-                             JSSMSG_TOO_MANY_ARGS, "stopTimingMutator");
-        return false;
-    }
-
-    double mutator_ms, gc_ms;
-    cx->runtime()->gc.stats.stopTimingMutator(mutator_ms, gc_ms);
-    double total_ms = mutator_ms + gc_ms;
-    if (total_ms > 0) {
-        fprintf(gOutFile, "Mutator: %.3fms (%.1f%%), GC: %.3fms (%.1f%%)\n",
-                mutator_ms, mutator_ms / total_ms * 100.0, gc_ms, gc_ms / total_ms * 100.0);
-    }
-
-    args.rval().setUndefined();
-    return true;
-}
-
 static const char *
 ToSource(JSContext *cx, MutableHandleValue vp, JSAutoByteString *bytes)
 {
     JSString *str = JS_ValueToSource(cx, vp);
     if (str) {
         vp.setString(str);
         if (bytes->encodeLatin1(cx, str))
             return bytes->ptr();
@@ -4305,24 +4268,16 @@ static const JSFunctionSpecWithHelp shel
 "quit()",
 "  Quit the shell."),
 
     JS_FN_HELP("assertEq", AssertEq, 2, 0,
 "assertEq(actual, expected[, msg])",
 "  Throw if the first two arguments are not the same (both +0 or both -0,\n"
 "  both NaN, or non-zero and ===)."),
 
-    JS_FN_HELP("startTimingMutator", StartTimingMutator, 0, 0,
-"startTimingMutator()",
-"  Start accounting time to mutator vs GC."),
-
-    JS_FN_HELP("stopTimingMutator", StopTimingMutator, 0, 0,
-"stopTimingMutator()",
-"  Stop accounting time to mutator vs GC and dump the results."),
-
     JS_FN_HELP("throwError", ThrowError, 0, 0,
 "throwError()",
 "  Throw an error from JS_ReportError."),
 
 #ifdef DEBUG
     JS_FN_HELP("disassemble", DisassembleToString, 1, 0,
 "disassemble([fun])",
 "  Return the disassembly for the given function."),