Backed out changeset d7d9bbfa72c5 (bug 674779) for m-bc orange on a CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Thu, 26 Feb 2015 17:55:37 -0800
changeset 231111 00ccf3b425fdd5b5a79f9af887712bdfd3494500
parent 231110 571a4b02be275acc928fa329945b0f3a8724b334
child 231112 577937f4dce7cfcf2ec5d3485f8bdb0ba42f3952
push id28344
push userryanvm@gmail.com
push dateFri, 27 Feb 2015 18:20:08 +0000
treeherdermozilla-central@9dd9d1e5b43c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs674779
milestone39.0a1
backs outd7d9bbfa72c5b58e01aff2ba7fc524e6203889e5
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 changeset d7d9bbfa72c5 (bug 674779) for m-bc orange on a CLOSED TREE
js/ipc/CPOWTimer.cpp
js/ipc/moz.build
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jspubtd.h
js/src/vm/Interpreter.cpp
js/src/vm/Runtime.cpp
js/src/vm/Runtime.h
js/xpconnect/idl/xpccomponents.idl
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
toolkit/components/aboutcompartments/content/aboutCompartments.js
toolkit/components/aboutcompartments/content/aboutCompartments.xhtml
toolkit/components/aboutcompartments/moz.build
toolkit/components/aboutcompartments/nsCompartmentInfo.cpp
toolkit/components/aboutcompartments/nsICompartmentInfo.idl
toolkit/components/aboutcompartments/tests/mochi/browser.ini
toolkit/components/aboutcompartments/tests/mochi/browser_compartments.html
toolkit/components/aboutcompartments/tests/mochi/browser_compartments.js
toolkit/components/aboutcompartments/tests/mochi/content.js
toolkit/modules/AddonWatcher.jsm
--- a/js/ipc/CPOWTimer.cpp
+++ b/js/ipc/CPOWTimer.cpp
@@ -14,16 +14,14 @@ CPOWTimer::~CPOWTimer()
     /* This is a best effort to find the compartment responsible for this CPOW call */
     nsIGlobalObject *global = mozilla::dom::GetIncumbentGlobal();
     if (!global)
         return;
     JSObject *obj = global->GetGlobalJSObject();
     if (!obj)
         return;
     JSCompartment *compartment = js::GetObjectCompartment(obj);
-    if (!compartment)
+    xpc::CompartmentPrivate *compartmentPrivate = xpc::CompartmentPrivate::Get(compartment);
+    if (!compartmentPrivate)
         return;
-    js::PerformanceData *performance = js::GetPerformanceData(compartment);
-    if (!performance)
-        return;
-    uint64_t time = PR_IntervalToMicroseconds(PR_IntervalNow() - startInterval);
-    performance->cpowTime += time;
+    PRIntervalTime time = PR_IntervalNow() - startInterval;
+    compartmentPrivate->CPOWTime += time;
 }
--- a/js/ipc/moz.build
+++ b/js/ipc/moz.build
@@ -30,13 +30,12 @@ EXPORTS.mozilla.jsipc = [
     'CpowHolder.h',
     'CrossProcessObjectWrappers.h',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/js/ipc',
     '/js/public',
-    '/js/src',
     '/js/xpconnect/src',
     '/js/xpconnect/wrappers',
 ]
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -168,19 +168,18 @@ JS_GetEmptyString(JSRuntime *rt)
 JS_PUBLIC_API(bool)
 JS_GetCompartmentStats(JSRuntime *rt, CompartmentStatsVector &stats)
 {
     for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
         if (!stats.growBy(1))
             return false;
 
         CompartmentTimeStats *stat = &stats.back();
+        stat->time = c.get()->totalTime;
         stat->compartment = c.get();
-        stat->performance = stat->compartment->performance;
-        stat->isSystem = stat->compartment->isSystem;
         stat->addonId = c.get()->addonId;
         if (rt->compartmentNameCallback) {
             (*rt->compartmentNameCallback)(rt, stat->compartment,
                                            stat->compartmentName,
                                            MOZ_ARRAY_LENGTH(stat->compartmentName));
         } else {
             strcpy(stat->compartmentName, "<unknown>");
         }
@@ -5797,16 +5796,8 @@ JS::CaptureCurrentStack(JSContext *cx, J
     return true;
 }
 
 JS_PUBLIC_API(Zone *)
 JS::GetObjectZone(JSObject *obj)
 {
     return obj->zone();
 }
-
-JS_PUBLIC_API(PerformanceData*)
-js::GetPerformanceData(JSCompartment *c)
-{
-    if (!c)
-        return nullptr;
-    return &c->performance;
-}
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -970,18 +970,18 @@ JS_GetEmptyStringValue(JSContext *cx);
 
 extern JS_PUBLIC_API(JSString *)
 JS_GetEmptyString(JSRuntime *rt);
 
 struct CompartmentTimeStats {
     char compartmentName[1024];
     JSAddonId *addonId;
     JSCompartment *compartment;
-    bool isSystem;
-    js::PerformanceData performance;
+    uint64_t time;  // microseconds
+    uint64_t cpowTime; // microseconds
 };
 
 typedef js::Vector<CompartmentTimeStats, 0, js::SystemAllocPolicy> CompartmentStatsVector;
 
 extern JS_PUBLIC_API(bool)
 JS_GetCompartmentStats(JSRuntime *rt, CompartmentStatsVector &stats);
 
 extern JS_PUBLIC_API(bool)
@@ -5121,38 +5121,9 @@ GetSavedFrameParent(JSContext *cx, Handl
  * cx's compartment. Defaults to the empty string.
  */
 extern JS_PUBLIC_API(bool)
 StringifySavedFrameStack(JSContext *cx, HandleObject stack, MutableHandleString stringp);
 
 
 } /* namespace JS */
 
-
-/* Stopwatch-based CPU monitoring. */
-
-namespace js {
-
-/**
- * Reset any stopwatch currently measuring.
- *
- * This function is designed to be called when we process a new event.
- */
-extern JS_PUBLIC_API(void)
-ResetStopwatches(JSRuntime*);
-
-/**
- * Turn on/off stopwatch-based CPU monitoring.
- */
-extern JS_PUBLIC_API(void)
-SetStopwatchActive(JSRuntime*, bool);
-extern JS_PUBLIC_API(bool)
-IsStopwatchActive(JSRuntime*);
-
-/**
- * Access the performance information stored in a compartment.
- */
-extern JS_PUBLIC_API(PerformanceData*)
-GetPerformanceData(JSCompartment*);
-
-} /* namespace js */
-
 #endif /* jsapi_h */
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -45,16 +45,17 @@ JSCompartment::JSCompartment(Zone *zone,
     isSelfHosting(false),
     marked(true),
     addonId(options.addonIdOrNull()),
 #ifdef DEBUG
     firedOnNewGlobalObject(false),
 #endif
     global_(nullptr),
     enterCompartmentDepth(0),
+    totalTime(0),
     data(nullptr),
     objectMetadataCallback(nullptr),
     lastAnimationTime(0),
     regExps(runtime_),
     globalWriteBarriered(false),
     neuteredTypedObjects(0),
     propertyTree(thisForCtor()),
     selfHostingScriptSource(nullptr),
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -165,22 +165,28 @@ struct JSCompartment
     friend struct JSContext;
     friend class js::ExclusiveContext;
     js::ReadBarrieredGlobalObject global_;
 
     unsigned                     enterCompartmentDepth;
     int64_t                      startInterval;
 
   public:
-    js::PerformanceData performance;
+    int64_t                      totalTime;
     void enter() {
+        if (addonId && !enterCompartmentDepth) {
+            startInterval = PRMJ_Now();
+        }
         enterCompartmentDepth++;
     }
     void leave() {
         enterCompartmentDepth--;
+        if (addonId && !enterCompartmentDepth) {
+            totalTime += (PRMJ_Now() - startInterval);
+        }
     }
     bool hasBeenEntered() { return !!enterCompartmentDepth; }
 
     JS::Zone *zone() { return zone_; }
     const JS::Zone *zone() const { return zone_; }
     JS::CompartmentOptions &options() { return options_; }
     const JS::CompartmentOptions &options() const { return options_; }
 
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -474,65 +474,11 @@ struct PerThreadDataFriendFields
         // Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp|
         return reinterpret_cast<const PerThreadDataFriendFields *>(
             reinterpret_cast<const char*>(rt) + RuntimeMainThreadOffset);
     }
 
     template <typename T> friend class JS::Rooted;
 };
 
-// Container for performance data
-struct PerformanceData {
-    // Jank indicator.
-    //
-    // missedFrames[i] == number of times execution of this
-    // compartment caused us to miss at least 2^i successive frames -
-    // we assume that a frame lasts 16ms.
-    uint64_t missedFrames[8];
-
-    // Total amount of time spent executing code in this compartment,
-    // in microseconds, since process launch.
-    uint64_t totalUserTime;
-    uint64_t totalSystemTime;
-    uint64_t ownUserTime;
-    uint64_t ownSystemTime;
-    uint64_t cpowTime;
-
-    // Total number of time code was executed in this compartment,
-    // since process launch.
-    uint64_t visits;
-
-    PerformanceData()
-        : totalUserTime(0)
-        , totalSystemTime(0)
-        , ownUserTime(0)
-        , ownSystemTime(0)
-        , cpowTime(0)
-        , visits(0)
-    {
-        memset(missedFrames, 0, sizeof(missedFrames));
-    }
-    PerformanceData(const PerformanceData& from)
-        : totalUserTime(from.totalUserTime)
-        , totalSystemTime(from.totalSystemTime)
-        , ownUserTime(from.ownUserTime)
-        , ownSystemTime(from.ownSystemTime)
-        , cpowTime(from.cpowTime)
-        , visits(from.visits)
-    {
-        memcpy(missedFrames, from.missedFrames, sizeof(missedFrames));
-    }
-    PerformanceData& operator=(const PerformanceData& from)
-    {
-        memcpy(missedFrames, from.missedFrames, sizeof(missedFrames));
-        totalUserTime = from.totalUserTime;
-        totalSystemTime = from.totalSystemTime;
-        ownUserTime = from.ownUserTime;
-        ownSystemTime = from.ownSystemTime;
-        cpowTime = from.cpowTime;
-        visits = from.visits;
-        return *this;
-    }
-};
-
 } /* namespace js */
 
 #endif /* jspubtd_h */
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*
  * JavaScript bytecode interpreter.
  */
 
 #include "vm/Interpreter-inl.h"
 
-#include "mozilla/ArrayUtils.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/PodOperations.h"
 
 #include <string.h>
 
 #include "jsarray.h"
 #include "jsatom.h"
@@ -48,23 +47,16 @@
 
 #include "jit/JitFrames-inl.h"
 #include "vm/Debugger-inl.h"
 #include "vm/NativeObject-inl.h"
 #include "vm/Probes-inl.h"
 #include "vm/ScopeObject-inl.h"
 #include "vm/Stack-inl.h"
 
-#if defined(XP_UNIX)
-#include <sys/resource.h>
-#elif defined(XP_WIN)
-#include <Processthreadsapi.h>
-#include <Windows.h>
-#endif // defined(XP_UNIX) || defined(XP_WIN)
-
 using namespace js;
 using namespace js::gc;
 
 using mozilla::DebugOnly;
 using mozilla::NumberEqualsInt32;
 using mozilla::PodCopy;
 using JS::ForOfIterator;
 
@@ -414,201 +406,21 @@ InvokeState::pushInterpreterFrame(JSCont
 
 InterpreterFrame *
 ExecuteState::pushInterpreterFrame(JSContext *cx)
 {
     return cx->runtime()->interpreterStack().pushExecuteFrame(cx, script_, thisv_, scopeChain_,
                                                               type_, evalInFrame_);
 }
 
-namespace js {
-
-// Implementation of per-compartment performance measurement.
-//
-//
-// All mutable state is stored in `Runtime::stopwatch`.
-struct AutoStopwatch MOZ_FINAL
-{
-    // If the stopwatch is active, constructing an instance of
-    // AutoStopwatch causes it to become the current owner of the
-    // stopwatch.
-    //
-    // Previous owner is restored upon destruction.
-    explicit inline AutoStopwatch(JSContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-        : parent_(nullptr)
-        , context_(cx)
-        , descendentsUserTime_(0)
-        , descendentsSystemTime_(0)
-    {
-        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-        JSRuntime *runtime = context_->runtime();
-        if (!runtime->stopwatch.isActive)
-            return;
-
-
-#if defined(XP_UNIX)
-        int err = getrusage(RUSAGE_SELF, &timeStamp_);
-        if (err)
-            return;
-#elif defined(XP_WIN)
-        FILETIME creationTime; // Ignored
-        FILETIME exitTime; // Ignored
-
-        BOOL success = GetProcessTimes(GetCurrentProcess(),
-                                       &creationTime, &exitTime,
-                                       &kernelTimeStamp_, &userTimeStamp_);
-        if (!success)
-            return;
-#endif // defined(XP_UNIX) || defined(XP_WIN)
-
-        // Push on top of previous owner.
-        parent_ = runtime->stopwatch.owner;
-        runtime->stopwatch.owner = this;
-    }
-
-    // If the stopwatch is active, destructing an instance of
-    // AutoStopwatch causes ownership to return to the previous owner.
-    inline ~AutoStopwatch()
-    {
-        JSRuntime *runtime = context_->runtime();
-        if (runtime->stopwatch.owner != this) {
-            // We are not the owner of the stopwatch, either because
-            // we never acquired it, because we have entered a nested
-            // event loop, or because some stopwatch lower on the
-            // stack encountered an error.
-            // If there is any ongoing measure, discard it.
-            return;
-        }
-
-        // If this destructor cannot proceed to completion without error,
-        // prepare to cancel any ongoing measure.
-        runtime->stopwatch.owner = nullptr;
-
-        // Durations in museconds of the total user/system time spent
-        // by the entire process between construction and destruction
-        // of this object.
-        uint64_t totalUserTime, totalSystemTime;
-
-#if defined(XP_UNIX)
-        struct rusage stop;
-        int err = getrusage(RUSAGE_SELF, &stop);
-        if (err)
-            return;
-
-        totalUserTime =
-            (stop.ru_utime.tv_usec - timeStamp_.ru_utime.tv_usec)
-            + (stop.ru_utime.tv_sec - timeStamp_.ru_utime.tv_sec) * 1000000;
-        totalSystemTime =
-            (stop.ru_stime.tv_usec - timeStamp_.ru_stime.tv_usec)
-            + (stop.ru_stime.tv_sec - timeStamp_.ru_stime.tv_sec) * 1000000;
-#elif defined(XP_WIN)
-        FILETIME creationTime; // Ignored
-        FILETIME exitTime; // Ignored
-        FILETIME kernelTime;
-        FILETIME userTime;
-        BOOL success = GetProcessTimes(GetCurrentProcess(),
-                                       &creationTime, &exitTime,
-                                       &kernelTime, &userTime);
-        if (!success)
-            return;
-
-        // Convert values to a data structure that supports arithmetics.
-        ULARGE_INTEGER userTimeInt, userTimeStampInt;
-        userTimeInt.LowPart = userTime.dwLowDateTime;
-        userTimeInt.HighPart = userTime.dwHighDateTime;
-        userTimeStampInt.LowPart = userTimeStamp_.dwLowDateTime;
-        userTimeStampInt.HighPart = userTimeStamp_.dwHighDateTime;
-
-        totalUserTime = (userTimeInt.QuadPart - userTimeStampInt.QuadPart) / 10;  // 100 ns to 1 mus
-
-        ULARGE_INTEGER kernelTimeInt, kernelTimeStampInt;
-        kernelTimeInt.LowPart = kernelTime.dwLowDateTime;
-        kernelTimeInt.HighPart = kernelTime.dwHighDateTime;
-        kernelTimeStampInt.LowPart = kernelTimeStamp_.dwLowDateTime;
-        kernelTimeStampInt.HighPart = kernelTimeStamp_.dwHighDateTime;
-
-        totalSystemTime = (kernelTimeInt.QuadPart - kernelTimeStampInt.QuadPart) / 10;  // 100 ns to 1 mus
-#endif // defined(XP_UNIX) || defined (XP_WIN)
-
-        // Process durations.
-        //
-        // Note that durations are per-process, while our measures attempt
-        // to be per-thread. In other words, the data we extract may be
-        // badly skewed by activity on other threads. We can only hope that
-        // things will eventually average out.
-
-        JSCompartment *compartment = context_->compartment();
-        compartment->performance.visits++;
-        compartment->performance.totalUserTime += totalUserTime;
-        compartment->performance.totalSystemTime += totalSystemTime;
-
-        uint64_t ownUserTime = totalUserTime - descendentsUserTime_;
-        uint64_t ownSystemTime = totalSystemTime - descendentsSystemTime_;
-        compartment->performance.ownUserTime += ownUserTime;
-        compartment->performance.ownSystemTime += ownSystemTime;
-
-        if (parent_) {
-            // The time we just spent executing code in this compartment
-            // should be substracted to determine the parent's own time.
-            parent_->descendentsUserTime_ += totalUserTime;
-            parent_->descendentsSystemTime_ += totalSystemTime;
-        }
-
-        uint64_t totalDuration = totalUserTime + totalSystemTime;
-
-        // Store performance information in the compartment
-
-        uint64_t missedFrames = 16 * 1000; // Duration of one frame, i.e. 16ms in museconds
-        for (size_t i = 0; i < ArrayLength(compartment->performance.missedFrames); ++i) {
-            if (totalDuration < missedFrames)
-                break;
-            compartment->performance.missedFrames[i]++;
-            missedFrames *= 2;
-        }
-
-        runtime->stopwatch.owner = parent_;
-    }
-
-  private:
-    // The AutoStopwatch for the caller compartment.
-    AutoStopwatch *parent_;
-
-    // The context with which this object was initialized.
-    JSContext *context_;
-
-    // Total time spent so far executing compartments that have been
-    // called by this compartment, in museconds. These values are
-    // updated upon destruction of callee AutoStopwatch instances.
-    uint64_t descendentsUserTime_;
-    uint64_t descendentsSystemTime_;
-
-    // Kernel and user time at the time of construction of this
-    // instance of AutoStopwatch. Unspecified if the stopwatch is not
-    // active.
-#if defined(XP_UNIX)
-    struct rusage timeStamp_;
-#elif defined(XP_WIN)
-    FILETIME kernelTimeStamp_;
-    FILETIME userTimeStamp_;
-#endif // defined(XP_UNIX) || defined(XP_WIN)
-
-    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-};
-
-}
-
 bool
 js::RunScript(JSContext *cx, RunState &state)
 {
     JS_CHECK_RECURSION(cx, return false);
 
-#if defined(NIGHTLY_BUILD)
-    js::AutoStopwatch stopwatch(cx);
-#endif // defined(NIGHTLY_BUILD)
-
     SPSEntryMarker marker(cx->runtime(), state.script());
 
     state.script()->ensureNonLazyCanonicalFunction(cx);
 
     if (jit::IsIonEnabled(cx)) {
         jit::MethodStatus status = jit::CanEnter(cx, state);
         if (status == jit::Method_Error)
             return false;
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -843,26 +843,8 @@ js::AssertCurrentThreadCanLock(RuntimeLo
 
 JS_FRIEND_API(void)
 JS::UpdateJSRuntimeProfilerSampleBufferGen(JSRuntime *runtime, uint32_t generation,
                                            uint32_t lapCount)
 {
     runtime->setProfilerSampleBufferGen(generation);
     runtime->updateProfilerSampleBufferLapCount(lapCount);
 }
-
-void
-js::ResetStopwatches(JSRuntime *rt)
-{
-    rt->stopwatch.reset();
-}
-
-void
-js::SetStopwatchActive(JSRuntime *rt, bool isActive)
-{
-    rt->stopwatch.isActive = isActive;
-}
-
-bool
-js::IsStopwatchActive(JSRuntime *rt)
-{
-    return rt->stopwatch.isActive;
-}
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -561,17 +561,16 @@ class PerThreadData : public PerThreadDa
 
 #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
     js::jit::Simulator *simulator() const;
 #endif
 };
 
 class AutoLockForExclusiveAccess;
 
-struct AutoStopwatch;
 } // namespace js
 
 struct JSRuntime : public JS::shadow::Runtime,
                    public js::MallocProvider<JSRuntime>
 {
     /*
      * Per-thread data for the main thread that is associated with
      * this JSRuntime, as opposed to any worker threads used in
@@ -1416,63 +1415,16 @@ struct JSRuntime : public JS::shadow::Ru
     /*
      * Debugger.Memory functions like takeCensus use this embedding-provided
      * function to assess the size of malloc'd blocks of memory.
      */
     mozilla::MallocSizeOf debuggerMallocSizeOf;
 
     /* Last time at which an animation was played for this runtime. */
     int64_t lastAnimationTime;
-
-  public:
-
-    /* ------------------------------------------
-       Performance measurements
-       ------------------------------------------ */
-    struct Stopwatch {
-        /**
-         * The current owner of the stopwatch.
-         *
-         * This is `nullptr` if we have not started executing JS code
-         * in this tick yet, or if we are not using stopwatch
-         * monitoring. If monitoring is activated, whenever we
-         * instantiate an `AutoStopwatch`, it becomes the owner, and
-         * whenever we destruct it, it returns ownership to the
-         * previous owner.
-         *
-         * Note that `owner` is reset to `nullptr` if we start
-         * processing a nested event. By design, this has the
-         * side-effect of discarding any ongoing measurement that
-         * would otherwise be completely skewed by the nested event
-         * loop.
-         */
-        js::AutoStopwatch *owner;
-
-        /**
-         * `true` if stopwatch monitoring is active, `false` otherwise.
-         */
-        bool isActive;
-
-        Stopwatch()
-            : owner(nullptr)
-            , isActive(false)
-        { }
-
-        /**
-         * Reset the stopwatch.
-         *
-         * This method is meant to be called whewnever we start processing
-         * an event, to ensure that stop any ongoing measurement that would
-         * otherwise provide irrelevant results.
-         */
-        void reset() {
-            owner = nullptr;
-        }
-    };
-    Stopwatch stopwatch;
 };
 
 namespace js {
 
 // When entering JIT code, the calling JSContext* is stored into the thread's
 // PerThreadData. This function retrieves the JSContext with the pre-condition
 // that the caller is JIT code or C++ called directly from JIT code. This
 // function should not be called from arbitrary locations since the JSContext
--- a/js/xpconnect/idl/xpccomponents.idl
+++ b/js/xpconnect/idl/xpccomponents.idl
@@ -117,17 +117,17 @@ interface nsIXPCComponents_utils_Sandbox
 interface ScheduledGCCallback : nsISupports
 {
     void callback();
 };
 
 /**
 * interface of Components.utils
 */
-[scriptable, uuid(9b153002-3bc6-4d83-b825-64d21b13a098)]
+[scriptable, uuid(2617a800-63c1-11e4-9803-0800200c9a66)]
 interface nsIXPCComponents_Utils : nsISupports
 {
 
     /* reportError is designed to be called from JavaScript only.
      *
      * It will report a JS Error object to the JS console, and return. It
      * is meant for use in exception handler blocks which want to "eat"
      * an exception, but still want to report it to the console.
@@ -674,24 +674,16 @@ interface nsIXPCComponents_Utils : nsISu
     [implicit_jscontext]
     void setAddonInterposition(in ACString addonId, in nsIAddonInterposition interposition);
 
     /*
      * Return a fractional number of milliseconds from process
      * startup, measured with a monotonic clock.
      */
     double now();
-
-    /*
-     * Whether we are currently monitoring CPU use on this thread.
-     *
-     * Note that CPU monitoring is rather expensive, so it generally
-     * not be active at all times.
-     */
-    attribute boolean stopwatchMonitoring;
 };
 
 /**
 * Interface for the 'Components' object.
 *
 * The first interface contains things that are available to non-chrome XBL code
 * that runs in a scope with an nsExpandedPrincipal. The second interface
 * includes members that are only exposed to chrome.
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3524,32 +3524,16 @@ NS_IMETHODIMP
 nsXPCComponents_Utils::Now(double *aRetval)
 {
     bool isInconsistent = false;
     TimeStamp start = TimeStamp::ProcessCreation(isInconsistent);
     *aRetval = (TimeStamp::Now() - start).ToMilliseconds();
     return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXPCComponents_Utils::SetStopwatchMonitoring(bool aValue)
-{
-    JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
-    SetStopwatchActive(rt, aValue);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPCComponents_Utils::GetStopwatchMonitoring(bool* aResult)
-{
-    JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
-    *aResult = IsStopwatchActive(rt);
-    return NS_OK;
-}
-
 /***************************************************************************/
 /***************************************************************************/
 /***************************************************************************/
 
 
 nsXPCComponentsBase::nsXPCComponentsBase(XPCWrappedNativeScope* aScope)
     :   mScope(aScope)
 {
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -343,16 +343,23 @@ xpc::TraceXPCGlobal(JSTracer *trc, JSObj
     xpc::CompartmentPrivate* compartmentPrivate = xpc::CompartmentPrivate::Get(obj);
     if (compartmentPrivate && compartmentPrivate->scope)
         compartmentPrivate->scope->TraceInside(trc);
 }
 
 
 namespace xpc {
 
+uint64_t
+GetCompartmentCPOWMicroseconds(JSCompartment *compartment)
+{
+    xpc::CompartmentPrivate *compartmentPrivate = xpc::CompartmentPrivate::Get(compartment);
+    return compartmentPrivate ? PR_IntervalToMicroseconds(compartmentPrivate->CPOWTime) : 0;
+}
+
 JSObject*
 CreateGlobalObject(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal,
                    JS::CompartmentOptions& aOptions)
 {
     MOZ_ASSERT(NS_IsMainThread(), "using a principal off the main thread?");
     MOZ_ASSERT(principal);
 
     MOZ_RELEASE_ASSERT(principal != nsContentUtils::GetNullSubjectPrincipal(),
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -621,17 +621,16 @@ public:
     void InitSingletonScopes();
     void DeleteSingletonScopes();
 
     PRTime GetWatchdogTimestamp(WatchdogTimestampCategory aCategory);
 
     void OnProcessNextEvent() {
         mSlowScriptCheckpoint = mozilla::TimeStamp::NowLoRes();
         mSlowScriptSecondHalf = false;
-        js::ResetStopwatches(Get()->Runtime());
     }
     void OnAfterProcessNextEvent() {
         mSlowScriptCheckpoint = mozilla::TimeStamp();
         mSlowScriptSecondHalf = false;
     }
 
     nsTArray<nsXPCWrappedJS*>& WrappedJSToReleaseArray() { return mWrappedJSToReleaseArray; }
 
@@ -3619,16 +3618,17 @@ public:
     };
 
     explicit CompartmentPrivate(JSCompartment *c)
         : wantXrays(false)
         , writeToGlobalPrototype(false)
         , skipWriteToGlobalPrototype(false)
         , universalXPConnectEnabled(false)
         , forcePermissiveCOWs(false)
+        , CPOWTime(0)
         , skipCOWCallableChecks(false)
         , scriptability(c)
         , scope(nullptr)
     {
         MOZ_COUNT_CTOR(xpc::CompartmentPrivate);
         mozilla::PodArrayZero(wrapperDenialWarnings);
     }
 
@@ -3672,16 +3672,19 @@ public:
     // This is only ever set during mochitest runs when enablePrivilege is called.
     // It allows the SpecialPowers scope to waive the normal chrome security
     // wrappers and expose properties directly to content. This lets us avoid a
     // bunch of overhead and complexity in our SpecialPowers automation glue.
     //
     // Using it in production is inherently unsafe.
     bool forcePermissiveCOWs;
 
+    // A running count of how much time we've spent processing CPOWs.
+    PRIntervalTime               CPOWTime;
+
     // Disables the XPConnect security checks that deny access to callables and
     // accessor descriptors on COWs. Do not use this unless you are bholley.
     bool skipCOWCallableChecks;
 
     // Whether we've emitted a warning about a property that was filtered out
     // by a security wrapper. See XrayWrapper.cpp.
     bool wrapperDenialWarnings[WrapperDenialTypeCount];
 
--- a/toolkit/components/aboutcompartments/content/aboutCompartments.js
+++ b/toolkit/components/aboutcompartments/content/aboutCompartments.js
@@ -5,163 +5,71 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm", {});
 
-/**
- * The various measures we extract from a nsICompartment.
- */
-const MEASURES = [
-  {key: "totalUserTime", label: "Total user (µs)"},
-  {key: "totalSystemTime", label: "Total system (µs)"},
-  {key: "ownUserTime", label: "Own user (µs)"},
-  {key: "ownSystemTime", label: "Own system (µs)"},
-  {key: "cpowTime", label: "CPOW (µs)"},
-  {key: "visits", label: "Activations"},
-];
-
-/**
- * All information on a single owner (add-on, page, built-ins).
- *
- * @param {string} id A unique identifier.
- * @param {string} kind One of "<addon>", "<built-in>", "<page>".
- * @param {string|null} A name for this owner. Not expected for add-ons.
- */
-function Owner(id, kind, name) {
-  for (let {key} of MEASURES) {
-    this[key] = 0;
-  }
-  this.compartments = [];
-  this.id = id;
-  this.kind = kind;
-  this.name = name;
-}
-Owner.prototype = {
-  add: function(compartment) {
-    this.compartments.push(compartment);
-    for (let {key} of MEASURES) {
-      this[key] += compartment[key];
+function go() {
+    let compartmentInfo = Cc["@mozilla.org/compartment-info;1"]
+            .getService(Ci.nsICompartmentInfo);
+    let compartments = compartmentInfo.getCompartments();
+    let count = compartments.length;
+    let addons = {};
+    for (let i = 0; i < count; i++) {
+        let compartment = compartments.queryElementAt(i, Ci.nsICompartment);
+        if (addons[compartment.addonId]) {
+            addons[compartment.addonId].time += compartment.time;
+            addons[compartment.addonId].CPOWTime += compartment.CPOWTime;
+            addons[compartment.addonId].compartments.push(compartment);
+        } else {
+            addons[compartment.addonId] = {
+                time: compartment.time,
+                CPOWTime: compartment.CPOWTime,
+                compartments: [compartment]
+            };
+        }
     }
-  },
-  promiseName: function() {
-    if (this.kind != "<addon>") {
-      return Promise.resolve(this.name);
+    let dataDiv = document.getElementById("data");
+    for (let addon in addons) {
+        let el = document.createElement("tr");
+        let name = document.createElement("td");
+        let time = document.createElement("td");
+        let cpow = document.createElement("td");
+        name.className = "addon";
+        time.className = "time";
+        cpow.className = "cpow";
+        name.textContent = addon;
+        AddonManager.getAddonByID(addon, function(a) {
+            if (a) {
+                name.textContent = a.name;
+            }
+        });
+        time.textContent = addons[addon].time +"μs";
+        cpow.textContent = addons[addon].CPOWTime +"μs";
+        el.appendChild(time);
+        el.appendChild(cpow);
+        el.appendChild(name);
+        let div = document.createElement("tr");
+        for (let comp of addons[addon].compartments) {
+            let c = document.createElement("tr");
+            let name = document.createElement("td");
+            let time = document.createElement("td");
+            let cpow = document.createElement("td");
+            name.className = "addon";
+            time.className = "time";
+            cpow.className = "cpow";
+            name.textContent = comp.compartmentName;
+            time.textContent = comp.time +"μs";
+            cpow.textContent = comp.CPOWTime +"μs";
+            c.appendChild(time);
+            c.appendChild(cpow);
+            c.appendChild(name);
+            div.appendChild(c);
+            div.className = "details";
+        }
+        el.addEventListener("click", function() { div.style.display = (div.style.display != "block" ? "block" : "none"); });
+        el.appendChild(div);
+        dataDiv.appendChild(el);
     }
-    return new Promise(resolve =>
-      AddonManager.getAddonByID(this.id, a =>
-        resolve(a?a.name:null)
-      )
-    );
-  }
-};
-
-function getStatistics() {
-  let compartmentInfo = Cc["@mozilla.org/compartment-info;1"]
-          .getService(Ci.nsICompartmentInfo);
-  let compartments = compartmentInfo.getCompartments();
-  let count = compartments.length;
-  let data = {};
-  for (let i = 0; i < count; i++) {
-    let compartment = compartments.queryElementAt(i, Ci.nsICompartment);
-    let kind, id, name;
-    if (!compartment.isSystem) {
-      name = id = compartment.compartmentName;
-      kind = "<page>";
-    } else if (compartment.addonId == "<non-addon>") {
-      id = kind = name = "<built-in>";
-    } else {
-      name = id = compartment.addonId;
-      kind = "<addon>";
-    }
-    let key = kind + ":" + id;
-    let owner = data[key];
-    if (!owner) {
-      owner = data[key] = new Owner(id, kind, name);
-    }
-    owner.add(compartment);
-  }
-  return [data[k] for (k of Object.keys(data))].sort((a, b) => a.totalUserTime <= b.totalUserTime);
 }
-
-function update() {
-  try {
-    console.log("Updating");
-
-    // Activate (or reactivate) monitoring
-    Cu.stopwatchMonitoring = true;
-
-    let dataElt = document.getElementById("data");
-    dataElt.innerHTML = "";
-
-    // Generate table headers
-    let headerElt = document.createElement("tr");
-    dataElt.appendChild(headerElt);
-    for (let column of [...MEASURES, {key:"compartments", name: "Compartments"}, {key: "name", name: ""}]) {
-      let el = document.createElement("td");
-      el.classList.add(column.key);
-      el.classList.add("header");
-      el.textContent = column.label;
-      headerElt.appendChild(el);
-    }
-
-    // Generate table contents
-    let data = getStatistics();
-    console.log("Data", data);
-    for (let item of data) {
-      // Make sure that we don't show compartments with
-      // no time spent.
-      let show = false;
-      for (let column of MEASURES) {
-        if (item[column.key]) {
-          show = true;
-        }
-      }
-      if (!show) {
-        continue;
-      }
-
-      let row = document.createElement("tr");
-      row.classList.add(item.kind);
-      dataElt.appendChild(row);
-
-      // Measures
-      for (let column of MEASURES) {
-        let el = document.createElement("td");
-        el.classList.add(column.key);
-        el.classList.add("contents");
-        el.textContent = item[column.key];
-        row.appendChild(el);
-      }
-
-      // Number of compartments
-      let el = document.createElement("td");
-      el.classList.add("contents");
-      el.classList.add("compartments");
-      el.textContent = item.compartments.length;
-      row.appendChild(el);
-
-      // Name
-      el = document.createElement("td");
-      el.classList.add("contents");
-      el.classList.add("name");
-      row.appendChild(el);
-      item.promiseName().then(name => {
-        name ? el.textContent = name : item.id;
-      });
-    }
-  } catch (ex) {
-    console.error(ex);
-  }
-}
-
-function stop() {
-  Cu.stopwatchMonitoring = false;
-}
-
-function go() {
-  update();
-  window.setInterval(update, 5000);
-  window.addEventListener("beforeunload", stop);
-}
--- a/toolkit/components/aboutcompartments/content/aboutCompartments.xhtml
+++ b/toolkit/components/aboutcompartments/content/aboutCompartments.xhtml
@@ -24,24 +24,20 @@
       .header {
         font-weight: bold;
       }
       tr.details {
         font-weight: lighter;
         color: gray;
         display: none;
       }
-      tr.addons {
-        background-color: white;
-      }
-      tr.builtins {
-        background-color: rgb(1, 1, .5);
-      }
-      tr.pages {
-        background-color: rgb(.5, 1, 1);
-      }
     </style>
   </head>
   <body onload="go()">
     <table id="data">
+      <tr class="header">
+        <td class="time">time</td>
+        <td class="cpow">time in CPOWs</td>
+        <td class="addon">name</td>
+      </tr>
     </table>
   </body>
 </html>
--- a/toolkit/components/aboutcompartments/moz.build
+++ b/toolkit/components/aboutcompartments/moz.build
@@ -1,27 +1,23 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-FAIL_ON_WARNINGS = True
-
 JAR_MANIFESTS += ['jar.mn']
 
 XPIDL_MODULE = 'compartments'
 
 XPIDL_SOURCES += [
     'nsICompartmentInfo.idl',
 ]
 
 UNIFIED_SOURCES += [
     'nsCompartmentInfo.cpp'
 ]
 
 EXPORTS += [
     'nsCompartmentInfo.h'
 ]
 
-BROWSER_CHROME_MANIFESTS += ['tests/mochi/browser.ini']
-
 FINAL_LIBRARY = 'xul'
--- a/toolkit/components/aboutcompartments/nsCompartmentInfo.cpp
+++ b/toolkit/components/aboutcompartments/nsCompartmentInfo.cpp
@@ -7,97 +7,53 @@
 #include "nsMemory.h"
 #include "nsLiteralString.h"
 #include "nsCRTGlue.h"
 #include "nsIJSRuntimeService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIMutableArray.h"
 #include "nsJSUtils.h"
 #include "xpcpublic.h"
-#include "jspubtd.h"
 
 class nsCompartment : public nsICompartment {
 public:
-  nsCompartment(nsAString& aCompartmentName, nsAString& aAddonId, bool aIsSystem, js::PerformanceData aPerformanceData)
-    : mCompartmentName(aCompartmentName)
-    , mAddonId(aAddonId)
-    , mIsSystem(aIsSystem)
-    , mPerformanceData(aPerformanceData)
-  {}
+  nsCompartment(nsAString& aCompartmentName, nsAString& aAddonId,
+                uint64_t aTime, uint64_t aCPOWTime)
+    : mCompartmentName(aCompartmentName), mAddonId(aAddonId), mTime(aTime), mCPOWTime(aCPOWTime) {}
 
   NS_DECL_ISUPPORTS
 
   /* readonly attribute wstring compartmentName; */
   NS_IMETHOD GetCompartmentName(nsAString& aCompartmentName) MOZ_OVERRIDE {
     aCompartmentName.Assign(mCompartmentName);
     return NS_OK;
   };
 
+  /* readonly attribute unsigned long time; */
+  NS_IMETHOD GetTime(uint64_t* aTime) MOZ_OVERRIDE {
+    *aTime = mTime;
+    return NS_OK;
+  }
   /* readonly attribute wstring addon id; */
   NS_IMETHOD GetAddonId(nsAString& aAddonId) MOZ_OVERRIDE {
     aAddonId.Assign(mAddonId);
     return NS_OK;
   };
 
-  /* readonly attribute unsigned long long totalUserTime; */
-  NS_IMETHOD GetTotalUserTime(uint64_t *aTotalUserTime) {
-    *aTotalUserTime = mPerformanceData.totalUserTime;
-    return NS_OK;
-  };
-
-  /* readonly attribute unsigned long long totalSystemTime; */
-  NS_IMETHOD GetTotalSystemTime(uint64_t *aTotalSystemTime) {
-    *aTotalSystemTime = mPerformanceData.totalSystemTime;
-    return NS_OK;
-  };
-
-  /* readonly attribute unsigned long long ownUserTime; */
-  NS_IMETHOD GetOwnUserTime(uint64_t *aOwnUserTime) {
-    *aOwnUserTime = mPerformanceData.ownUserTime;
-    return NS_OK;
-  };
-
-  /* readonly attribute unsigned long long ownSystemTime; */
-  NS_IMETHOD GetOwnSystemTime(uint64_t *aOwnSystemTime) {
-    *aOwnSystemTime = mPerformanceData.ownSystemTime;
-    return NS_OK;
-  };
-
-  /* readonly attribute unsigned long long CPOWTime; */
-  NS_IMETHOD GetCPOWTime(uint64_t *aCpowTime) {
-    *aCpowTime = mPerformanceData.cpowTime;
-    return NS_OK;
-  };
-
-  /* readonly attribute unsigned long long visits; */
-  NS_IMETHOD GetVisits(uint64_t *aVisits) {
-    *aVisits = mPerformanceData.visits;
-    return NS_OK;
-  };
-
-  /* unsigned long long getMissedFrames (in unsigned long i); */
-  NS_IMETHOD GetMissedFrames(uint32_t i, uint64_t *_retval) {
-    if (i >= mozilla::ArrayLength(mPerformanceData.missedFrames)) {
-      return NS_ERROR_INVALID_ARG;
-    }
-    *_retval = mPerformanceData.missedFrames[i];
-    return NS_OK;
-  };
-
-  NS_IMETHOD GetIsSystem(bool *_retval) {
-    *_retval = mIsSystem;
+  /* readonly attribute unsigned long CPOW time; */
+  NS_IMETHOD GetCPOWTime(uint64_t* aCPOWTime) MOZ_OVERRIDE {
+    *aCPOWTime = mCPOWTime;
     return NS_OK;
   }
 
 private:
   nsString mCompartmentName;
   nsString mAddonId;
-  bool mIsSystem;
-  js::PerformanceData mPerformanceData;
-
+  uint64_t mTime;
+  uint64_t mCPOWTime;
   virtual ~nsCompartment() {}
 };
 
 NS_IMPL_ISUPPORTS(nsCompartment, nsICompartment)
 NS_IMPL_ISUPPORTS(nsCompartmentInfo, nsICompartmentInfo)
 
 nsCompartmentInfo::nsCompartmentInfo()
 {
@@ -116,24 +72,23 @@ nsCompartmentInfo::GetCompartments(nsIAr
   svc->GetRuntime(&rt);
   nsCOMPtr<nsIMutableArray> compartments = do_CreateInstance(NS_ARRAY_CONTRACTID);
   CompartmentStatsVector stats;
   if (!JS_GetCompartmentStats(rt, stats))
     return NS_ERROR_OUT_OF_MEMORY;
 
   size_t num = stats.length();
   for (size_t pos = 0; pos < num; pos++) {
-    CompartmentTimeStats *c = &stats[pos];
     nsString addonId;
-    if (c->addonId) {
-      AssignJSFlatString(addonId, (JSFlatString*)c->addonId);
+    if (stats[pos].addonId) {
+      AssignJSFlatString(addonId, (JSFlatString*)stats[pos].addonId);
     } else {
       addonId.AssignLiteral("<non-addon>");
     }
 
-    nsCString compartmentName(c->compartmentName);
+    uint32_t cpowTime = xpc::GetCompartmentCPOWMicroseconds(stats[pos].compartment);
+    nsCString compartmentName(stats[pos].compartmentName);
     NS_ConvertUTF8toUTF16 name(compartmentName);
-
-    compartments->AppendElement(new nsCompartment(name, addonId, c->isSystem, c->performance), false);
+    compartments->AppendElement(new nsCompartment(name, addonId, stats[pos].time, cpowTime), false);
   }
   compartments.forget(aCompartments);
   return NS_OK;
 }
--- a/toolkit/components/aboutcompartments/nsICompartmentInfo.idl
+++ b/toolkit/components/aboutcompartments/nsICompartmentInfo.idl
@@ -2,62 +2,26 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "nsIArray.idl"
 
-[scriptable, uuid(3a23d383-052e-4199-8914-74c037fe359e)]
+[scriptable, uuid(13dd4c09-ff11-4943-8dc2-d96eb69c963b)]
 interface nsICompartment : nsISupports {
   /* name of compartment */
   readonly attribute AString compartmentName;
-
+  /* time spent executing code in this compartment in microseconds */
+  readonly attribute unsigned long long time;
   /* the id of the addon associated with this compartment, or null */
   readonly attribute AString addonId;
-
-  /*
-    Total amount of time spent executing code in this compartment, in
-    microseconds.
-
-    Note that these durations are only computed while
-    Components.utils.stopwatchMonitoring == true and that they are never
-    reset to 0.
-  */
-  readonly attribute unsigned long long totalUserTime;
-  readonly attribute unsigned long long totalSystemTime;
-  readonly attribute unsigned long long ownUserTime;
-  readonly attribute unsigned long long ownSystemTime;
+  /* time spent processing CPOWs in microseconds */
   readonly attribute unsigned long long CPOWTime;
-
-  /* Number of times we have executed code in this compartment.
-     Updated only while Components.utils.stopwatchMonitoring == true,
-     never reset to 0.
-  */
-  readonly attribute unsigned long long visits;
-
-  /* `true` if this is a system compartment (either an add-on or a built-in).*/
-  readonly attribute bool isSystem;
-
-  /**
-   * The number of times execution of code in this compartment has apparently
-   * caused frame drops.
-   *
-   * getMissedFrames(0): number of times we have dropped at least 1 frame
-   * getMissedFrames(1): number of times we have dropped at least 2 successive frames
-   * ...
-   * getMissedFrames(i): number of times we have dropped at least 2^i successive frames
-   *
-   * Updated only while Components.utils.stopwatchMonitoring == true,
-   * never reset to 0.
-   */
-  unsigned long long getMissedFrames(in unsigned long i);
-  /* Number of values that may be consulted in `getMissedFrames`.*/
-  const unsigned long MISSED_FRAMES_RANGE = 8;
 };
 
 [scriptable, builtinclass, uuid(5795113a-39a1-4087-ba09-98b7d07d025a)]
 interface nsICompartmentInfo : nsISupports {
   nsIArray getCompartments();
 };
 
 %{C++
deleted file mode 100644
--- a/toolkit/components/aboutcompartments/tests/mochi/browser.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-[DEFAULT]
-support-files =
-  browser_compartments.html
-  content.js
-
-[browser_compartments.js]
deleted file mode 100644
--- a/toolkit/components/aboutcompartments/tests/mochi/browser_compartments.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>
-    browser_compartments.html
-  </title>
-  <script type="text/javascript">
-  // Use some CPU
-  // Compute an arbitrary value, print it out to make sure that the JS
-  // engine doesn't discard all our computation.
-  var date = Date.now();
-  var array = [];
-  var i = 0;
-  while (Date.now() - date <= 200) {
-    array[i%2] = i++;
-  }
-  console.log("Arbitrary value", array);
-  </script>
-</head>
-<body>
-browser_compartments.html
-</body>
-</html>
deleted file mode 100644
--- a/toolkit/components/aboutcompartments/tests/mochi/browser_compartments.js
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-
-"use strict";
-
-
-const ROOT = getRootDirectory(gTestPath);
-const FRAME_SCRIPTS = [
-  ROOT + "content.js",
-];
-const URL = "chrome://mochitests/content/browser/toolkit/components/aboutcompartments/tests/mochi/browser_compartments.html";
-
-let mm = Cc["@mozilla.org/globalmessagemanager;1"]
-           .getService(Ci.nsIMessageListenerManager);
-
-for (let script of FRAME_SCRIPTS) {
-  mm.loadFrameScript(script, true);
-}
-
-registerCleanupFunction(() => {
-  for (let script of FRAME_SCRIPTS) {
-    mm.removeDelayedFrameScript(script, true);
-  }
-});
-
-function promiseContentResponse(browser, name, message) {
-  let mm = browser.messageManager;
-  let promise = new Promise(resolve => {
-    function removeListener() {
-      mm.removeMessageListener(name, listener);
-    }
-
-    function listener(msg) {
-      removeListener();
-      resolve(msg.data);
-    }
-
-    mm.addMessageListener(name, listener);
-    registerCleanupFunction(removeListener);
-  });
-  mm.sendAsyncMessage(name, message);
-  return promise;
-}
-
-function getStatistics() {
-  let compartmentInfo = Cc["@mozilla.org/compartment-info;1"]
-          .getService(Ci.nsICompartmentInfo);
-  let data = compartmentInfo.getCompartments();
-  let result = [];
-  for (let i = 0; i < data.length; ++i) {
-    result.push(data.queryElementAt(i, Ci.nsICompartment));
-  }
-  return result;
-}
-
-function* promiseTabLoadEvent(tab, url)
-{
-  return new Promise(function (resolve, reject) {
-    function handleLoadEvent(event) {
-      if (event.originalTarget != tab.linkedBrowser.contentDocument ||
-          event.target.location.href == "about:blank" ||
-          (url && event.target.location.href != url)) {
-        return;
-      }
-
-      tab.linkedBrowser.removeEventListener("load", handleLoadEvent, true);
-      resolve(event);
-    }
-
-    tab.linkedBrowser.addEventListener("load", handleLoadEvent, true, true);
-    if (url)
-      tab.linkedBrowser.loadURI(url);
-  });
-}
-
-add_task(function* init() {
-  let monitoring = Cu.stopwatchMonitoring;
-  Cu.stopwatchMonitoring = true;
-  registerCleanupFunction(() => {
-    Cu.stopwatchMonitoring = monitoring;
-  });
-});
-
-add_task(function* test() {
-  info("Extracting initial state");
-  let stats0 = getStatistics();
-  Assert.notEqual(stats0.length, 0, "There is more than one compartment");
-  Assert.ok(!stats0.find(stat => stat.compartmentName.indexOf(URL) != -1),
-    "The url doesn't appear yet");
-  stats0.forEach(stat => {
-    Assert.ok(stat.totalUserTime >= stat.ownUserTime, "Total >= own user time: " + stat.compartmentName);
-    Assert.ok(stat.totalSystemTime >= stat.ownSystemTime, "Total >= own system time: " + stat.compartmentName);
-  });
-
-  let newTab = gBrowser.addTab();
-  let browser = newTab.linkedBrowser;
-  // Setup monitoring in the tab
-  info("Setting up monitoring in the tab");
-  let childMonitoring = yield promiseContentResponse(browser, "compartments-test:setMonitoring", true);
-
-  info("Waiting for load to be complete");
-  yield promiseTabLoadEvent(newTab, URL);
-
-  if (!gMultiProcessBrowser) {
-    // In non-e10s mode, the stats are counted in the single process
-    let stats1 = getStatistics();
-    let pageStats = stats1.find(stat => stat.compartmentName.indexOf(URL) != -1);
-    Assert.notEqual(pageStats, null, "The new page appears in the single-process statistics");
-    Assert.notEqual(pageStats.totalUserTime, 0, "Total single-process user time is > 0");
-  }
-
-  // Regardless of e10s, the stats should be accessible in the content process (or pseudo-process)
-  let stats2 = yield promiseContentResponse(browser, "compartments-test:getCompartments", null);
-  let pageStats = stats2.find(stat => stat.compartmentName.indexOf(URL) != -1);
-  Assert.notEqual(pageStats, null, "The new page appears in the content statistics");
-  Assert.notEqual(pageStats.totalUserTime, 0, "Total content user time is > 0");
-  Assert.ok(pageStats.totalUserTime >= 1000, "Total content user time is at least 1ms");
-
-  // Cleanup
-  yield promiseContentResponse(browser, "compartments-test:setMonitoring", childMonitoring);
-  gBrowser.removeTab(newTab);
-});
deleted file mode 100644
--- a/toolkit/components/aboutcompartments/tests/mochi/content.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { utils: Cu, classes: Cc, interfaces: Ci } = Components;
-
-addMessageListener("compartments-test:setMonitoring", msg => {
-  let stopwatchMonitoring = Cu.stopwatchMonitoring;
-  Cu.stopwatchMonitoring = msg.data;
-  sendAsyncMessage("compartments-test:setMonitoring", stopwatchMonitoring);
-});
-
-addMessageListener("compartments-test:getCompartments", () => {
-  let compartmentInfo = Cc["@mozilla.org/compartment-info;1"]
-          .getService(Ci.nsICompartmentInfo);
-  let data = compartmentInfo.getCompartments();
-  let result = [];
-  for (let i = 0; i < data.length; ++i) {
-    let xpcom = data.queryElementAt(i, Ci.nsICompartment);
-    let object = {};
-    for (let k of Object.keys(xpcom)) {
-      let value = xpcom[k];
-      if (typeof value != "function") {
-        object[k] = value;
-      }
-    }
-    object.frames = [];
-    for (let i = 0; i < Ci.nsICompartment.MISSED_FRAMES_RANGE; ++i) {
-      object.frames[i] = xpcom.getMissedFrames(i);
-    }
-    result.push(object);
-  }
-  sendAsyncMessage("compartments-test:getCompartments", result);
-});
--- a/toolkit/modules/AddonWatcher.jsm
+++ b/toolkit/modules/AddonWatcher.jsm
@@ -21,44 +21,38 @@ let AddonWatcher = {
   _interval: 1500,
   _ignoreList: null,
   init: function(callback) {
     if (!callback) {
       return;
     }
 
     if (this._callback) {
-      // Already initialized
       return;
     }
 
     this._interval = Preferences.get("browser.addon-watch.interval", 15000);
     if (this._interval == -1) {
-      // Deactivated by preferences
       return;
     }
 
     this._callback = callback;
     try {
       this._ignoreList = new Set(JSON.parse(Preferences.get("browser.addon-watch.ignore", null)));
     } catch (ex) {
       // probably some malformed JSON, ignore and carry on
       this._ignoreList = new Set();
     }
-
-    // Start monitoring
-    Cu.stopwatchMonitoring = true;
     this._timer.initWithCallback(this._checkAddons.bind(this), this._interval, Ci.nsITimer.TYPE_REPEATING_SLACK);
   },
   uninit: function() {
     if (this._timer) {
       this._timer.cancel();
       this._timer = null;
     }
-    Cu.stopwatchMonitoring = false;
   },
   _checkAddons: function() {
     let compartmentInfo = Cc["@mozilla.org/compartment-info;1"]
       .getService(Ci.nsICompartmentInfo);
     let compartments = compartmentInfo.getCompartments();
     let count = compartments.length;
     let addons = {};
     for (let i = 0; i < count; i++) {