bug 1096718 - - display time measured spent in each compartment r=billm,mossop
authorBrad Lassey <blassey@mozilla.com>
Tue, 13 Jan 2015 17:38:05 -0800
changeset 223566 96f157725203bf9da767eff53ac46e0f22196f72
parent 223565 56c85ebbf6d0feb418788d402906d50d00566e55
child 223676 b2d1d57c25b9c3a2b484884792aa6bfb99a6db31
push id10803
push userblassey@mozilla.com
push dateWed, 14 Jan 2015 01:40:39 +0000
treeherderfx-team@96f157725203 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm, mossop
bugs1096718
milestone38.0a1
bug 1096718 - - display time measured spent in each compartment r=billm,mossop
docshell/base/nsAboutRedirector.cpp
docshell/build/nsDocShellModule.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcpublic.h
toolkit/components/aboutcompartments/content/aboutCompartments.js
toolkit/components/aboutcompartments/content/aboutCompartments.xhtml
toolkit/components/aboutcompartments/jar.mn
toolkit/components/aboutcompartments/moz.build
toolkit/components/aboutcompartments/nsCompartmentInfo.cpp
toolkit/components/aboutcompartments/nsCompartmentInfo.h
toolkit/components/aboutcompartments/nsICompartmentInfo.idl
toolkit/components/aboutmemory/jar.mn
toolkit/components/moz.build
xpcom/build/XPCOMInit.cpp
xpcom/build/XPCOMModule.inc
xpcom/build/nsXPCOMCID.h
--- a/docshell/base/nsAboutRedirector.cpp
+++ b/docshell/base/nsAboutRedirector.cpp
@@ -46,20 +46,19 @@ static RedirEntry kRedirMap[] = {
     { "buildconfig", "chrome://global/content/buildconfig.html",
       nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT },
     { "license", "chrome://global/content/license.html",
       nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT },
     { "neterror", "chrome://global/content/netError.xhtml",
       nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
       nsIAboutModule::ALLOW_SCRIPT |
       nsIAboutModule::HIDE_FROM_ABOUTABOUT },
+    { "memory", "chrome://global/content/aboutMemory.xhtml",
+      nsIAboutModule::ALLOW_SCRIPT },
     { "compartments", "chrome://global/content/aboutCompartments.xhtml",
-      nsIAboutModule::ALLOW_SCRIPT |
-      nsIAboutModule::HIDE_FROM_ABOUTABOUT },
-    { "memory", "chrome://global/content/aboutMemory.xhtml",
       nsIAboutModule::ALLOW_SCRIPT },
     { "addons", "chrome://mozapps/content/extensions/extensions.xul",
       nsIAboutModule::ALLOW_SCRIPT },
     { "newaddon", "chrome://mozapps/content/extensions/newaddon.xul",
       nsIAboutModule::ALLOW_SCRIPT |
       nsIAboutModule::HIDE_FROM_ABOUTABOUT },
     { "support", "chrome://global/content/aboutSupport.xhtml",
       nsIAboutModule::ALLOW_SCRIPT },
--- a/docshell/build/nsDocShellModule.cpp
+++ b/docshell/build/nsDocShellModule.cpp
@@ -163,16 +163,17 @@ const mozilla::Module::ContractIDEntry k
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "plugins", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "mozilla", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "logo", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "buildconfig", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "license", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "neterror", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "compartments", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "memory", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
+  { NS_ABOUT_MODULE_CONTRACTID_PREFIX "compartments", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "addons", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "newaddon", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "support", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "telemetry", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "networking", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "webrtc", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "srcdoc", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_URI_LOADER_CONTRACTID, &kNS_URI_LOADER_CID },
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -162,16 +162,40 @@ JS_GetEmptyStringValue(JSContext *cx)
 
 JS_PUBLIC_API(JSString *)
 JS_GetEmptyString(JSRuntime *rt)
 {
     MOZ_ASSERT(rt->hasContexts());
     return rt->emptyString;
 }
 
+JS_PUBLIC_API(bool)
+JS_GetCompartmentStats(JSRuntime *rt, CompartmentStatsVector &stats)
+{
+    if (!stats.resizeUninitialized(rt->numCompartments))
+        return false;
+
+    size_t pos = 0;
+    for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
+        CompartmentTimeStats *stat = &stats[pos];
+        stat->time = c.get()->totalTime;
+        stat->compartment = c.get();
+        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>");
+        }
+        pos++;
+    }
+    return true;
+}
+
 namespace js {
 
 void
 AssertHeapIsIdle(JSRuntime *rt)
 {
     MOZ_ASSERT(!rt->isHeapBusy());
 }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1037,16 +1037,29 @@ extern JS_PUBLIC_API(jsval)
 JS_GetPositiveInfinityValue(JSContext *cx);
 
 extern JS_PUBLIC_API(jsval)
 JS_GetEmptyStringValue(JSContext *cx);
 
 extern JS_PUBLIC_API(JSString *)
 JS_GetEmptyString(JSRuntime *rt);
 
+struct CompartmentTimeStats {
+    char compartmentName[1024];
+    JSAddonId *addonId;
+    JSCompartment *compartment;
+    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);
+
 /*
  * Format is a string of the following characters (spaces are insignificant),
  * specifying the tabulated type conversions:
  *
  *   b      bool            Boolean
  *   c      char16_t        ECMA uint16_t, Unicode character
  *   i      int32_t         ECMA int32_t
  *   j      int32_t         ECMA int32_t (used to be different)
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -340,18 +340,26 @@ xpc::TraceXPCGlobal(JSTracer *trc, JSObj
     // We might be called from a GC during the creation of a global, before we've
     // been able to set up the compartment private or the XPCWrappedNativeScope,
     // so we need to null-check those.
     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/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -134,16 +134,19 @@ IsXrayWrapper(JSObject *obj);
 // To emphasize the obvious: the return value here is not necessarily same-
 // compartment with the argument.
 JSObject *
 XrayAwareCalleeGlobal(JSObject *fun);
 
 void
 TraceXPCGlobal(JSTracer *trc, JSObject *obj);
 
+uint64_t
+GetCompartmentCPOWMicroseconds(JSCompartment *compartment);
+
 } /* namespace xpc */
 
 namespace JS {
 
 struct RuntimeStats;
 
 }
 
new file mode 100644
--- /dev/null
+++ b/toolkit/components/aboutcompartments/content/aboutCompartments.js
@@ -0,0 +1,75 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-*/
+/* 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/. */
+
+"use strict";
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm", {});
+
+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]
+            };
+        }
+    }
+    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.label;
+            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);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/components/aboutcompartments/content/aboutCompartments.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.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/. -->
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>about:compartments</title>
+    <script type="text/javascript;version=1.8" src="chrome://global/content/aboutCompartments.js"></script>
+    <style>
+      td.addon {
+        display: inline-block;
+        width: 400px;
+      }
+      td.time {
+        display: inline-block;
+        width: 100px;
+      }
+      td.cpow {
+        display: inline-block;
+        width: 100px;
+      }
+      .header {
+        font-weight: bold;
+      }
+      tr.details {
+        font-weight: lighter;
+        color: gray;
+        display: none;
+      }
+    </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>
new file mode 100644
--- /dev/null
+++ b/toolkit/components/aboutcompartments/jar.mn
@@ -0,0 +1,7 @@
+# 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/.
+
+toolkit.jar:
++ content/global/aboutCompartments.xhtml               (content/aboutCompartments.xhtml)
++ content/global/aboutCompartments.js                  (content/aboutCompartments.js)
new file mode 100644
--- /dev/null
+++ b/toolkit/components/aboutcompartments/moz.build
@@ -0,0 +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/.
+
+JAR_MANIFESTS += ['jar.mn']
+
+XPIDL_MODULE = 'compartments'
+
+XPIDL_SOURCES += [
+    'nsICompartmentInfo.idl',
+]
+
+UNIFIED_SOURCES += [
+    'nsCompartmentInfo.cpp'
+]
+
+EXPORTS += [
+    'nsCompartmentInfo.h'
+]
+
+FINAL_LIBRARY = 'xul'
new file mode 100644
--- /dev/null
+++ b/toolkit/components/aboutcompartments/nsCompartmentInfo.cpp
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsCompartmentInfo.h"
+#include "nsMemory.h"
+#include "nsLiteralString.h"
+#include "nsCRTGlue.h"
+#include "nsIJSRuntimeService.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIMutableArray.h"
+#include "nsJSUtils.h"
+#include "xpcpublic.h"
+
+class nsCompartment : public nsICompartment {
+public:
+  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){
+    aCompartmentName.Assign(mCompartmentName);
+    return NS_OK;
+  };
+
+  /* readonly attribute unsigned long time; */
+  NS_IMETHOD GetTime(uint64_t* aTime) {
+    *aTime = mTime;
+    return NS_OK;
+  }
+  /* readonly attribute wstring addon id; */
+  NS_IMETHOD GetAddonId(nsAString& aAddonId){
+    aAddonId.Assign(mAddonId);
+    return NS_OK;
+  };
+
+  /* readonly attribute unsigned long CPOW time; */
+  NS_IMETHOD GetCPOWTime(uint64_t* aCPOWTime) {
+    *aCPOWTime = mCPOWTime;
+    return NS_OK;
+  }
+
+private:
+  nsString mCompartmentName;
+  nsString mAddonId;
+  uint64_t mTime;
+  uint64_t mCPOWTime;
+  virtual ~nsCompartment() {}
+};
+
+NS_IMPL_ISUPPORTS(nsCompartment, nsICompartment)
+NS_IMPL_ISUPPORTS(nsCompartmentInfo, nsICompartmentInfo)
+
+nsCompartmentInfo::nsCompartmentInfo()
+{
+}
+
+nsCompartmentInfo::~nsCompartmentInfo()
+{
+}
+
+NS_IMETHODIMP
+nsCompartmentInfo::GetCompartments(nsIArray** aCompartments)
+{
+  JSRuntime* rt;
+  nsCOMPtr<nsIJSRuntimeService> svc(do_GetService("@mozilla.org/js/xpc/RuntimeService;1"));
+  NS_ENSURE_TRUE(svc, NS_ERROR_FAILURE);
+  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++) {
+    nsString addonId;
+    if (stats[pos].addonId) {
+      AssignJSFlatString(addonId, (JSFlatString*)stats[pos].addonId);
+    } else {
+      addonId.AssignLiteral("<non-addon>");
+    }
+
+    uint32_t cpowTime = xpc::GetCompartmentCPOWMicroseconds(stats[pos].compartment);
+    nsCString compartmentName(stats[pos].compartmentName);
+    NS_ConvertUTF8toUTF16 name(compartmentName);
+    compartments->AppendElement(new nsCompartment(name, addonId, stats[pos].time, cpowTime), false);
+  }
+  compartments.forget(aCompartments);
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/components/aboutcompartments/nsCompartmentInfo.h
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef nsCompartmentInfo_h
+#define nsCompartmentInfo_h
+
+#include "nsICompartmentInfo.h"
+
+class nsCompartmentInfo : public nsICompartmentInfo
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSICOMPARTMENTINFO
+
+  nsCompartmentInfo();
+
+private:
+  virtual ~nsCompartmentInfo();
+
+protected:
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/toolkit/components/aboutcompartments/nsICompartmentInfo.idl
@@ -0,0 +1,31 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-*/
+/* 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(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;
+  /* time spent processing CPOWs in microseconds */
+  readonly attribute unsigned long long CPOWTime;
+};
+
+[scriptable, builtinclass, uuid(5795113a-39a1-4087-ba09-98b7d07d025a)]
+interface nsICompartmentInfo : nsISupports {
+  nsIArray getCompartments();
+};
+
+%{C++
+#define NS_COMPARTMENT_INFO_CID \
+{ 0x2d3c2f2d, 0x698d, 0x471d, \
+{ 0xba, 0x3e, 0x14, 0x44, 0xdd, 0x52, 0x1e, 0x29 } }
+%}
--- a/toolkit/components/aboutmemory/jar.mn
+++ b/toolkit/components/aboutmemory/jar.mn
@@ -1,9 +1,8 @@
 # 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/.
 
 toolkit.jar:
-+ content/global/aboutCompartments.xhtml               (content/aboutCompartments.xhtml)
 + content/global/aboutMemory.js                        (content/aboutMemory.js)
 + content/global/aboutMemory.xhtml                     (content/aboutMemory.xhtml)
 + content/global/aboutMemory.css                       (content/aboutMemory.css)
--- a/toolkit/components/moz.build
+++ b/toolkit/components/moz.build
@@ -5,16 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # These component dirs are built for all apps (including suite)
 if CONFIG['MOZ_ENABLE_XREMOTE']:
     DIRS += ['remote']
 
 DIRS += [
     'aboutcache',
+    'aboutcompartments',
     'aboutmemory',
     'addoncompat',
     'alerts',
     'apppicker',
     'asyncshutdown',
     'commandlines',
     'console',
     'contentprefs',
--- a/xpcom/build/XPCOMInit.cpp
+++ b/xpcom/build/XPCOMInit.cpp
@@ -45,16 +45,18 @@
 
 #include "nsComponentManager.h"
 #include "nsCategoryManagerUtils.h"
 #include "nsIServiceManager.h"
 
 #include "nsThreadManager.h"
 #include "nsThreadPool.h"
 
+#include "nsCompartmentInfo.h"
+
 #include "xptinfo.h"
 #include "nsIInterfaceInfoManager.h"
 #include "xptiprivate.h"
 #include "mozilla/XPTInterfaceInfoManager.h"
 
 #include "nsTimerImpl.h"
 #include "TimerThread.h"
 
@@ -229,16 +231,18 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacUtil
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemInfo, Init)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMemoryReporterManager, Init)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMemoryInfoDumper)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStatusReporterManager, Init)
 
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsCompartmentInfo)
+
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsIOUtil)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSecurityConsoleMessage)
 
 static nsresult
 nsThreadManagerGetSingleton(nsISupports* aOuter,
                             const nsIID& aIID,
                             void** aInstancePtr)
--- a/xpcom/build/XPCOMModule.inc
+++ b/xpcom/build/XPCOMModule.inc
@@ -77,8 +77,9 @@
 
     COMPONENT(SYSTEMINFO, nsSystemInfoConstructor)
     COMPONENT(MEMORY_REPORTER_MANAGER, nsMemoryReporterManagerConstructor)
     COMPONENT(MEMORY_INFO_DUMPER, nsMemoryInfoDumperConstructor)
     COMPONENT(IOUTIL, nsIOUtilConstructor)
     COMPONENT(CYCLE_COLLECTOR_LOGGER, nsCycleCollectorLoggerConstructor)
     COMPONENT(MESSAGE_LOOP, nsMessageLoopConstructor)
     COMPONENT(STATUS_REPORTER_MANAGER, nsStatusReporterManagerConstructor)
+    COMPONENT(COMPARTMENT_INFO, nsCompartmentInfoConstructor)
\ No newline at end of file
--- a/xpcom/build/nsXPCOMCID.h
+++ b/xpcom/build/nsXPCOMCID.h
@@ -85,16 +85,18 @@
  */
 #define NS_CYCLE_COLLECTOR_LOGGER_CONTRACTID "@mozilla.org/cycle-collector-logger;1"
 
 /**
  * nsMessageLoop contract id
  */
 #define NS_MESSAGE_LOOP_CONTRACTID "@mozilla.org/message-loop;1"
 
+#define NS_COMPARTMENT_INFO_CONTRACTID "@mozilla.org/compartment-info;1"
+
 /**
  * The following are the CIDs and Contract IDs of the nsISupports wrappers for
  * primative types.
  */
 #define NS_SUPPORTS_ID_CID \
 { 0xacf8dc40, 0x4a25, 0x11d3, \
 { 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
 #define NS_SUPPORTS_ID_CONTRACTID "@mozilla.org/supports-id;1"