Bug 911641 (part 1) - Remove about:compartments, and show the compartment and ghost window lists into about:memory. r=johns.

--HG--
extra : rebase_source : c1ef005e272048e2eb84b20bafff15bcb5aae511
This commit is contained in:
Nicholas Nethercote 2013-09-03 20:05:17 -07:00
Родитель 03da338222
Коммит fbf85946b7
14 изменённых файлов: 90 добавлений и 601 удалений

Просмотреть файл

@ -49,8 +49,7 @@ static RedirEntry kRedirMap[] = {
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT },
// aboutMemory.xhtml implements about:compartments
{ "compartments", "chrome://global/content/aboutMemory.xhtml",
{ "compartments", "chrome://global/content/aboutCompartments.xhtml",
nsIAboutModule::ALLOW_SCRIPT },
{ "memory", "chrome://global/content/aboutMemory.xhtml",
nsIAboutModule::ALLOW_SCRIPT },

Просмотреть файл

@ -716,7 +716,7 @@ ReportGhostWindowsEnumerator(nsUint64HashKey* aIDHashKey, void* aClosure)
nsIMemoryReporter::KIND_OTHER,
nsIMemoryReporter::UNITS_COUNT,
/* amount = */ 1,
/* desc = */ EmptyCString(),
/* description = */ NS_LITERAL_CSTRING("A ghost window."),
data->closure);
if (NS_FAILED(rv) && NS_SUCCEEDED(data->rv)) {

Просмотреть файл

@ -1563,12 +1563,12 @@ GetCompartmentName(JSCompartment *c, nsCString &name, bool replaceSlashes)
// Telemetry relies on this being a uni-reporter (rather than part of the "js"
// reporter).
class JSGCHeapReporter MOZ_FINAL : public MemoryUniReporter
class JSMainRuntimeGCHeapReporter MOZ_FINAL : public MemoryUniReporter
{
public:
JSGCHeapReporter()
: MemoryUniReporter("js-gc-heap", KIND_OTHER, UNITS_BYTES,
"Memory used by the garbage-collected JavaScript heap.")
JSMainRuntimeGCHeapReporter()
: MemoryUniReporter("js-main-runtime-gc-heap", KIND_OTHER, UNITS_BYTES,
"Memory used by the garbage-collected heap in the main JSRuntime.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
@ -1579,21 +1579,20 @@ private:
}
};
// Nb: js-compartments/system + js-compartments/user could be different to the
// number of compartments reported by JSReporter if a garbage collection
// occurred between them being consulted. We could move these reporters into
// JSReporter to avoid that problem, but then we couldn't easily report them
// via telemetry, so we live with the small risk of inconsistencies.
// Nb: js-main-runtime-compartments/system + js-main-runtime-compartments/user
// could be different to the number of compartments reported by JSReporter if a
// garbage collection occurred between them being consulted. We could move
// these reporters into JSReporter to avoid that problem, but then we couldn't
// easily report them via telemetry, so we live with the small risk of
// inconsistencies.
class JSCompartmentsSystemReporter MOZ_FINAL : public MemoryUniReporter
class JSMainRuntimeCompartmentsCountSystemReporter MOZ_FINAL : public MemoryUniReporter
{
public:
JSCompartmentsSystemReporter()
: MemoryUniReporter("js-compartments/system", KIND_OTHER, UNITS_COUNT,
"The number of JavaScript compartments for system code. The sum of this and "
"'js-compartments/user' might not match the number of compartments listed "
"in the 'explicit' tree if a garbage collection occurs at an inopportune "
"time, but such cases should be rare.")
JSMainRuntimeCompartmentsCountSystemReporter()
: MemoryUniReporter("js-main-runtime-compartments-count/system",
KIND_OTHER, UNITS_COUNT,
"The number of JavaScript compartments for system code in the main JSRuntime.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
@ -1603,15 +1602,13 @@ private:
}
};
class JSCompartmentsUserReporter MOZ_FINAL : public MemoryUniReporter
class JSMainRuntimeCompartmentsCountUserReporter MOZ_FINAL : public MemoryUniReporter
{
public:
JSCompartmentsUserReporter()
: MemoryUniReporter("js-compartments/user", KIND_OTHER, UNITS_COUNT,
"The number of JavaScript compartments for user code. The sum of this and "
"'js-compartments/system' might not match the number of compartments listed "
"under 'js' if a garbage collection occurs at an inopportune time, but such "
"cases should be rare.")
JSMainRuntimeCompartmentsCountUserReporter()
: MemoryUniReporter("js-main-runtime-compartments-count/user",
KIND_OTHER, UNITS_COUNT,
"The number of JavaScript compartments for user code in the main JSRuntime.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
@ -2360,13 +2357,13 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
} // namespace xpc
class JSCompartmentsReporter MOZ_FINAL : public nsIMemoryReporter
class JSMainRuntimeCompartmentsReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_IMETHOD GetName(nsACString &name) {
name.AssignLiteral("compartments");
name.AssignLiteral("js-main-runtime-compartments");
return NS_OK;
}
@ -2378,8 +2375,8 @@ class JSCompartmentsReporter MOZ_FINAL : public nsIMemoryReporter
nsCString path;
GetCompartmentName(c, path, true);
path.Insert(js::IsSystemCompartment(c)
? NS_LITERAL_CSTRING("compartments/system/")
: NS_LITERAL_CSTRING("compartments/user/"),
? NS_LITERAL_CSTRING("js-main-runtime-compartments/system/")
: NS_LITERAL_CSTRING("js-main-runtime-compartments/user/"),
0);
paths->append(path);
}
@ -2400,13 +2397,14 @@ class JSCompartmentsReporter MOZ_FINAL : public nsIMemoryReporter
// Report.
for (size_t i = 0; i < paths.length(); i++)
// These ones don't need a description, hence the "".
REPORT(nsCString(paths[i]), KIND_OTHER, UNITS_COUNT, 1, "");
REPORT(nsCString(paths[i]), KIND_OTHER, UNITS_COUNT, 1,
"A live compartment in the main JSRuntime.");
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(JSCompartmentsReporter, nsIMemoryReporter)
NS_IMPL_ISUPPORTS1(JSMainRuntimeCompartmentsReporter, nsIMemoryReporter)
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(OrphanMallocSizeOf)
@ -3044,11 +3042,11 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
if (!xpc_LocalizeRuntime(runtime))
NS_RUNTIMEABORT("xpc_LocalizeRuntime failed.");
NS_RegisterMemoryReporter(new JSGCHeapReporter());
NS_RegisterMemoryReporter(new JSCompartmentsSystemReporter());
NS_RegisterMemoryReporter(new JSCompartmentsUserReporter());
NS_RegisterMemoryReporter(new JSMainRuntimeGCHeapReporter());
NS_RegisterMemoryReporter(new JSMainRuntimeCompartmentsCountSystemReporter());
NS_RegisterMemoryReporter(new JSMainRuntimeCompartmentsCountUserReporter());
NS_RegisterMemoryReporter(new JSMainRuntimeTemporaryPeakReporter());
NS_RegisterMemoryReporter(new JSCompartmentsReporter);
NS_RegisterMemoryReporter(new JSMainRuntimeCompartmentsReporter);
// Install a JavaScript 'debugger' keyword handler in debug builds only
#ifdef DEBUG

Просмотреть файл

@ -3,8 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* This file is used for both about:memory and about:compartments.
*
* The version used for desktop is located at
* toolkit/components/aboutmemory/content/aboutMemory.css.
* Mobile-specific stuff is at the bottom of this file.

Просмотреть файл

@ -0,0 +1,16 @@
<?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>
<meta name="viewport" content="width=device-width"/>
</head>
<body>about:compartments no longer exists. The lists of compartments and
ghost windows can now be found in the "Other Measurements" section of
about:memory.</body>
</html>

Просмотреть файл

@ -3,8 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* This file is used for both about:memory and about:compartments.
*
* The version used for mobile is located at
* mobile/android/themes/core/aboutMemory.css.
* Desktop-specific stuff is at the bottom of this file.

Просмотреть файл

@ -4,8 +4,6 @@
* 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/. */
// This file is used for both about:memory and about:compartments.
// You can direct about:memory to immediately load memory reports from a file
// by providing a file= query string. For example,
//
@ -15,14 +13,9 @@
// "file=" argument, and obviously the filename is case-sensitive iff you're on
// a case-sensitive filesystem. If you specify more than one "file=" argument,
// only the first one is used.
//
// about:compartments doesn't support "file=" parameters and will ignore them
// if they're provided.
"use strict";
//---------------------------------------------------------------------------
// Code shared by about:memory and about:compartments
//---------------------------------------------------------------------------
const Cc = Components.classes;
@ -59,12 +52,6 @@ let gUnnamedProcessStr = "Main Process";
let gIsDiff = false;
{
let split = document.location.href.split('?');
// The toLowerCase() calls ensure that addresses like "ABOUT:MEMORY" work.
document.title = split[0].toLowerCase();
}
let gChildMemoryListener = undefined;
//---------------------------------------------------------------------------
@ -140,22 +127,11 @@ function addChildObserversAndUpdate(aUpdateFn)
gChildMemoryListener();
}
function onLoad()
{
if (document.title === "about:memory") {
onLoadAboutMemory();
} else if (document.title === "about:compartments") {
onLoadAboutCompartments();
} else {
assert(false, "Unknown location: " + document.title);
}
}
function onUnload()
{
// We need to check if the observer has been added before removing; in some
// circumstances (e.g. reloading the page quickly) it might not have because
// onLoadAbout{Memory,Compartments} might not fire.
// onLoad might not fire.
if (gChildMemoryListener) {
let os = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
@ -227,7 +203,7 @@ function processMemoryReportsFromFile(aReports, aIgnoreReport, aHandleReport)
// It's what is updated each time the page changes.
let gMain;
// The <div> holding the footer. Is undefined in about:compartments.
// The <div> holding the footer.
let gFooter;
// The "verbose" checkbox.
@ -260,13 +236,11 @@ function updateMainAndFooter(aMsg, aFooterAction, aClassName)
appendElementWithText(gMain, 'div', className, aMsg);
}
if (gFooter !== undefined) {
switch (aFooterAction) {
case HIDE_FOOTER: gFooter.classList.add('hidden'); break;
case SHOW_FOOTER: gFooter.classList.remove('hidden'); break;
case IGNORE_FOOTER: break;
default: assertInput(false, "bad footer action in updateMainAndFooter");
}
switch (aFooterAction) {
case HIDE_FOOTER: gFooter.classList.add('hidden'); break;
case SHOW_FOOTER: gFooter.classList.remove('hidden'); break;
case IGNORE_FOOTER: break;
default: assertInput(false, "bad footer action in updateMainAndFooter");
}
}
@ -297,8 +271,6 @@ function appendElementWithText(aP, aTagName, aClassName, aText)
return e;
}
//---------------------------------------------------------------------------
// Code specific to about:memory
//---------------------------------------------------------------------------
const kTreeDescriptions = {
@ -405,7 +377,7 @@ function appendHiddenFileInput(aP, aId, aChangeListener)
return input;
}
function onLoadAboutMemory()
function onLoad()
{
// Generate the header.
@ -438,7 +410,7 @@ function onLoadAboutMemory()
delete this.filename1;
updateAboutMemoryFromTwoFiles(filename1, file.mozFullPath);
}
});
});
const CuDesc = "Measure current memory reports and show.";
const LdDesc = "Load memory reports from file and show.";
@ -512,9 +484,9 @@ function onLoadAboutMemory()
appendElementWithText(gFooter, "div", "legend", legendText1);
appendElementWithText(gFooter, "div", "legend hiddenOnMobile", legendText2);
// See if we're loading from a file. (Because about:memory and
// about:compartments are non-standard URLs, location.search is undefined, so
// we have to use location.href instead.)
// See if we're loading from a file. (Because about:memory is a non-standard
// URL, location.search is undefined, so we have to use location.href
// instead.)
let search = location.href.split('?')[1];
if (search) {
let searchSplit = search.split('&');
@ -1041,9 +1013,9 @@ function getPCollsByProcess(aProcessReports, aForceShowSmaps)
const gSentenceRegExp = /^[A-Z].*\.\)?$/m;
// Ignore the "smaps" reporter in non-verbose mode unless we're reading from
// a file or the clipboard, and ignore the "compartments" and "ghost-windows"
// reporters all the time. (Note that reports from these reporters can reach
// here via a "content-child" reporter if they were in a child process.)
// a file or the clipboard. (Note that reports from these reporters can
// reach here via a "content-child" reporter if they were in a child
// process.)
//
// Also ignore the "resident-fast" reporter; we use the vanilla "resident"
// reporter because it's more important that we get accurate results than
@ -1056,16 +1028,12 @@ function getPCollsByProcess(aProcessReports, aForceShowSmaps)
function ignoreReporter(aName)
{
return (aName === "smaps" && !gVerbose.checked && !aForceShowSmaps) ||
aName === "compartments" ||
aName === "ghost-windows" ||
aName === "resident-fast";
}
function ignoreReport(aUnsafePath)
{
return (isSmapsPath(aUnsafePath) && !gVerbose.checked && !aForceShowSmaps) ||
aUnsafePath.startsWith("compartments/") ||
aUnsafePath.startsWith("ghost-windows/") ||
aUnsafePath == "resident-fast";
}
@ -1089,7 +1057,7 @@ function getPCollsByProcess(aProcessReports, aForceShowSmaps)
"non-sentence other description");
}
assert(aPresence === undefined ||
assert(aPresence === undefined ||
aPresence == DReport.PRESENT_IN_FIRST_ONLY ||
aPresence == DReport.PRESENT_IN_SECOND_ONLY);
@ -2001,279 +1969,3 @@ function saveReportsToFile()
};
fp.open(fpCallback);
}
//-----------------------------------------------------------------------------
// Code specific to about:compartments
//-----------------------------------------------------------------------------
function onLoadAboutCompartments()
{
// Generate the main div, where content will go. about:compartments doesn't
// have a header or footer.
gMain = appendElement(document.body, 'div', 'section');
// First generate the page, then minimize memory usage to collect any dead
// compartments, then update the page. The first generation step may sound
// unnecessary, but it avoids a short delay in showing content when the page
// is loaded, which makes test_aboutcompartments.xul more reliable (see bug
// 729018 for details).
updateAboutCompartments();
gMgr.minimizeMemoryUsage(
function() { addChildObserversAndUpdate(updateAboutCompartments); });
}
/**
* Top-level function that does the work of generating the page.
*/
function updateAboutCompartments()
{
// First, clear the contents of main. Necessary because
// updateAboutMemoryFromReporters() might be called more than once due to the
// "child-memory-reporter-update" observer.
updateMainAndFooter("", IGNORE_FOOTER);
try {
let compartmentsByProcess = getCompartmentsByProcess();
let ghostWindowsByProcess = getGhostWindowsByProcess();
// Sort our list of processes.
let processes = Object.keys(compartmentsByProcess);
processes.sort(function(aProcessA, aProcessB) {
assert(aProcessA != aProcessB,
"Elements of Object.keys() should be unique, but " +
"saw duplicate '" + aProcessA + "' elem.");
// Always put the main process first.
if (aProcessA == gUnnamedProcessStr) {
return -1;
}
if (aProcessB == gUnnamedProcessStr) {
return 1;
}
// Otherwise the order doesn't matter.
return 0;
});
// Generate output for each process.
for (let i = 0; i < processes.length; i++) {
let process = processes[i];
appendProcessAboutCompartmentsElements(gMain, process,
compartmentsByProcess[process],
ghostWindowsByProcess[process]);
}
} catch (ex) {
handleException(ex);
}
}
//---------------------------------------------------------------------------
function Compartment(aUnsafeName, aIsSystemCompartment)
{
this._unsafeName = aUnsafeName;
this._isSystemCompartment = aIsSystemCompartment;
// this._nMerged is only defined if > 1
}
Compartment.prototype = {
merge: function(aR) {
this._nMerged = this._nMerged ? this._nMerged + 1 : 2;
}
};
function getCompartmentsByProcess()
{
// Ignore anything that didn't come from the "compartments" reporter. (Note
// reports from this reporter can reach here via a "content-child" reporter
// if they were in a child process.)
function ignoreReporter(aName)
{
return !(aName == "compartments" || aName == "content-child");
}
function ignoreReport(aUnsafePath)
{
return !aUnsafePath.startsWith("compartments/");
}
let compartmentsByProcess = {};
function handleReport(aProcess, aUnsafePath, aKind, aUnits, aAmount,
aDescription)
{
let process = aProcess === "" ? gUnnamedProcessStr : aProcess;
let unsafeNames = aUnsafePath.split('/');
let isSystemCompartment;
if (unsafeNames[0] === "compartments" && unsafeNames[1] == "system" &&
unsafeNames.length == 3)
{
isSystemCompartment = true;
} else if (unsafeNames[0] === "compartments" && unsafeNames[1] == "user" &&
unsafeNames.length == 3)
{
isSystemCompartment = false;
// These null principal compartments are user compartments according to
// the JS engine, but they look odd being shown with content
// compartments, so we put them in the system compartments list.
if (unsafeNames[2].startsWith("moz-nullprincipal:{")) {
isSystemCompartment = true;
}
} else {
assertInput(false, "bad compartments path: " + aUnsafePath);
}
assertInput(aKind === KIND_OTHER, "bad compartments kind");
assertInput(aUnits === UNITS_COUNT, "bad compartments units");
assertInput(aAmount === 1, "bad compartments amount");
assertInput(aDescription === "", "bad compartments description");
let c = new Compartment(unsafeNames[2], isSystemCompartment);
if (!compartmentsByProcess[process]) {
compartmentsByProcess[process] = {};
}
let compartments = compartmentsByProcess[process];
let cOld = compartments[c._unsafeName];
if (cOld) {
// Already an entry; must be a duplicated compartment. This can happen
// legitimately. Merge them.
cOld.merge(c);
} else {
compartments[c._unsafeName] = c;
}
}
processMemoryReporters(ignoreReporter, ignoreReport, handleReport);
return compartmentsByProcess;
}
function GhostWindow(aUnsafeURL)
{
// Call it _unsafeName rather than _unsafeURL for symmetry with the
// Compartment object.
this._unsafeName = aUnsafeURL;
// this._nMerged is only defined if > 1
}
GhostWindow.prototype = {
merge: function(aR) {
this._nMerged = this._nMerged ? this._nMerged + 1 : 2;
}
};
function getGhostWindowsByProcess()
{
function ignoreReporter(aName)
{
return !(aName == "ghost-windows" || aName == "content-child");
}
function ignoreReport(aUnsafePath)
{
return !aUnsafePath.startsWith('ghost-windows/')
}
let ghostWindowsByProcess = {};
function handleReport(aProcess, aUnsafePath, aKind, aUnits, aAmount,
aDescription)
{
let unsafeSplit = aUnsafePath.split('/');
assertInput(unsafeSplit[0] === 'ghost-windows' && unsafeSplit.length === 2,
'Unexpected path in getGhostWindowsByProcess: ' + aUnsafePath);
assertInput(aKind === KIND_OTHER, "bad ghost-windows kind");
assertInput(aUnits === UNITS_COUNT, "bad ghost-windows units");
assertInput(aAmount === 1, "bad ghost-windows amount");
assertInput(aDescription === "", "bad ghost-windows description");
let unsafeURL = unsafeSplit[1];
let ghostWindow = new GhostWindow(unsafeURL);
let process = aProcess === "" ? gUnnamedProcessStr : aProcess;
if (!ghostWindowsByProcess[process]) {
ghostWindowsByProcess[process] = {};
}
if (ghostWindowsByProcess[process][unsafeURL]) {
ghostWindowsByProcess[process][unsafeURL].merge(ghostWindow);
}
else {
ghostWindowsByProcess[process][unsafeURL] = ghostWindow;
}
}
processMemoryReporters(ignoreReporter, ignoreReport, handleReport);
return ghostWindowsByProcess;
}
//---------------------------------------------------------------------------
function appendProcessAboutCompartmentsElementsHelper(aP, aEntries, aKindString)
{
// aEntries might be null or undefined, e.g. if there are no ghost windows
// for this process.
aEntries = aEntries ? aEntries : {};
appendElementWithText(aP, "h2", "", aKindString + "\n");
let uPre = appendElement(aP, "pre", "entries");
let lines = [];
for (let name in aEntries) {
let e = aEntries[name];
let line = flipBackslashes(e._unsafeName);
if (e._nMerged) {
line += ' [' + e._nMerged + ']';
}
line += '\n';
lines.push(line);
}
lines.sort();
for (let i = 0; i < lines.length; i++) {
appendElementWithText(uPre, "span", "", lines[i]);
}
appendTextNode(aP, "\n"); // gives nice spacing when we cut and paste
}
/**
* Appends the elements for a single process.
*
* @param aP
* The parent DOM node.
* @param aProcess
* The name of the process.
* @param aCompartments
* Table of Compartments for this process, indexed by _unsafeName.
* @param aGhostWindows
* Array of window URLs of ghost windows.
*/
function appendProcessAboutCompartmentsElements(aP, aProcess, aCompartments, aGhostWindows)
{
appendElementWithText(aP, "h1", "", aProcess + "\n\n");
let userCompartments = {};
let systemCompartments = {};
for (let name in aCompartments) {
let c = aCompartments[name];
if (c._isSystemCompartment) {
systemCompartments[name] = c;
}
else {
userCompartments[name] = c;
}
}
appendProcessAboutCompartmentsElementsHelper(aP, userCompartments, "User Compartments");
appendProcessAboutCompartmentsElementsHelper(aP, systemCompartments, "System Compartments");
appendProcessAboutCompartmentsElementsHelper(aP, aGhostWindows, "Ghost Windows");
}

Просмотреть файл

@ -4,11 +4,9 @@
- 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/. -->
<!-- This file is used for both about:memory and about:compartments. -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- the <title> is filled in by aboutMemory.js -->
<title>about:memory</title>
<meta name="viewport" content="width=device-width"/>
<link rel="stylesheet" href="chrome://global/skin/aboutMemory.css" type="text/css"/>
<script type="text/javascript;version=1.8" src="chrome://global/content/aboutMemory.js"/>

Просмотреть файл

@ -3,6 +3,7 @@
# 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)

Просмотреть файл

@ -8,7 +8,6 @@ MOCHITEST_CHROME_FILES = \
memory-reports-bad.json \
memory-reports-diff1.json \
memory-reports-diff2.json \
test_aboutcompartments.xul \
test_aboutmemory.xul \
test_aboutmemory2.xul \
test_aboutmemory3.xul \

Просмотреть файл

@ -1,224 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<window title="about:compartments"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<!-- This file uses fake memory reporters to test the presentation of
compartment memory reports in about:memory. test_memoryReporters.xul
uses the real memory reporters to test whether the memory reporters
are producing sensible results. -->
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml"></body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
"use strict";
const Cc = Components.classes;
const Ci = Components.interfaces;
let mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
getService(Ci.nsIMemoryReporterManager);
// Remove all the real reporters; save them to restore at the end.
mgr.blockRegistration();
var e = mgr.enumerateReporters();
var realReporters = [];
while (e.hasMoreElements()) {
var r = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
mgr.unregisterReporter(r);
realReporters.push(r);
}
// Setup various fake-but-deterministic reporters.
const KB = 1024;
const MB = KB * KB;
const NONHEAP = Ci.nsIMemoryReporter.KIND_NONHEAP;
const HEAP = Ci.nsIMemoryReporter.KIND_HEAP;
const OTHER = Ci.nsIMemoryReporter.KIND_OTHER;
const BYTES = Ci.nsIMemoryReporter.UNITS_BYTES;
const COUNT = Ci.nsIMemoryReporter.UNITS_COUNT;
var fakeReporters = [
{ name: "fake1",
collectReports: function(aCbObj, aClosure) {
function f(aP1, aP2, aK, aU, aA) {
aCbObj.callback(aP1, aP2, aK, aU, aA, "Desc.", aClosure);
}
// These should be ignored.
f("", "explicit/a", HEAP, BYTES, 222 * MB);
f("", "explicit/b/a", HEAP, BYTES, 85 * MB);
f("", "explicit/b/b", NONHEAP, BYTES, 85 * MB);
f("", "other1", OTHER, BYTES, 111 * MB);
f("", "other2", OTHER, COUNT, 888);
}
},
{ name: "fake2",
collectReports: function(aCbObj, aClosure) {
function f(aP, aK, aU, aA) {
aCbObj.callback("", aP, aK, aU, aA, "Desc.", aClosure);
}
// These shouldn't show up.
f("explicit/a/d", HEAP, BYTES, 13 * MB);
f("explicit/b/c", NONHEAP, BYTES, 10 * MB);
}
},
{ name: "content-child",
collectReports: function(aCbObj, aClosure) {
function f(aP1, aP2, aK, aU, aA, aD) {
aCbObj.callback(aP1, aP2, aK, aU, aA, aD, aClosure);
}
f("2nd", "explicit/c", HEAP, BYTES, 333 * MB, "Desc.");
f("2nd", "compartments/user/child-user-compartment", OTHER, COUNT, 1, "");
f("2nd", "compartments/system/child-system-compartment", OTHER, COUNT, 1, "");
}
},
{ name: "compartments",
collectReports: function(aCbObj, aClosure) {
function f(aP) {
aCbObj.callback("", aP, OTHER, COUNT, 1, "", aClosure);
}
f("compartments/user/http:\\\\foo.com\\");
f("compartments/user/https:\\\\bar.com\\bar?baz");
f("compartments/user/https:\\\\very-long-url.com\\very-long\\oh-so-long\\really-quite-long.html?a=2&b=3&c=4&d=5&e=abcdefghijklmnopqrstuvwxyz&f=123456789123456789123456789");
// This moz-nullprincipal one is shown under "System Compartments" even
// though its path indicates it's a user compartment.
f("compartments/user/moz-nullprincipal:{7ddefdaf-34f1-473f-9b03-50a4568ccb06}");
// This should show up once with a "[3]" suffix
f("compartments/system/[System Principal]");
f("compartments/system/[System Principal]");
f("compartments/system/[System Principal]");
f("compartments/system/atoms");
}
},
{ name: "ghost-windows",
collectReports: function(aCbObj, aClosure) {
function f(aP) {
aCbObj.callback("", aP, OTHER, COUNT, 1, "", aClosure);
}
f("ghost-windows/https:\\\\very-long-url.com\\very-long\\oh-so-long\\really-quite-long.html?a=2&b=3&c=4&d=5&e=abcdefghijklmnopqrstuvwxyz&f=123456789123456789123456789");
f("ghost-windows/http:\\\\foobar.com\\foo?bar#baz");
}
},
// These shouldn't show up.
{ name: "smaps",
collectReports: function(aCbObj, aClosure) {
// The amounts are given in pages, so multiply here by 4kb.
function f(aP, aA) {
aCbObj.callback("", aP, NONHEAP, BYTES, aA * 4 * KB, "Desc.", aClosure);
}
f("smaps/vsize/a", 24);
f("smaps/swap/a", 1);
}
}
];
for (var i = 0; i < fakeReporters.length; i++) {
mgr.registerReporterEvenIfBlocked(fakeReporters[i]);
}
]]>
</script>
<!-- vary the capitalization to make sure that works -->
<iframe id="acFrame" height="400" src="abouT:compartMENTS"></iframe>
<script type="application/javascript">
<![CDATA[
var acExpectedText =
"\
Main Process\n\
User Compartments\n\
\n\
http://foo.com/\n\
https://bar.com/bar?baz\n\
https://very-long-url.com/very-long/oh-so-long/really-quite-long.html?a=2&b=3&c=4&d=5&e=abcdefghijklmnopqrstuvwxyz&f=123456789123456789123456789\n\
\n\
System Compartments\n\
\n\
[System Principal] [3]\n\
atoms\n\
moz-nullprincipal:{7ddefdaf-34f1-473f-9b03-50a4568ccb06}\n\
\n\
Ghost Windows\n\
\n\
http://foobar.com/foo?bar#baz\n\
https://very-long-url.com/very-long/oh-so-long/really-quite-long.html?a=2&b=3&c=4&d=5&e=abcdefghijklmnopqrstuvwxyz&f=123456789123456789123456789\n\
\n\
2nd\n\
User Compartments\n\
\n\
child-user-compartment\n\
\n\
System Compartments\n\
\n\
child-system-compartment\n\
\n\
Ghost Windows\n\
\n\
";
function finish()
{
// Unregister fake reporters and re-register the real reporters, just in
// case subsequent tests rely on them.
for (var i = 0; i < fakeReporters.length; i++) {
mgr.unregisterReporter(fakeReporters[i]);
}
for (var i = 0; i < realReporters.length; i++) {
mgr.registerReporterEvenIfBlocked(realReporters[i]);
}
mgr.unblockRegistration();
SimpleTest.finish();
}
// Cut+paste the entire page and check that the cut text matches what we
// expect. This tests the output in general and also that the cutting and
// pasting works as expected.
function test(aFrameId, aExpected, aNext) {
ok(document.title === "about:compartments", "document.title is correct");
let frame = document.getElementById(aFrameId);
SimpleTest.executeSoon(function() {
frame.focus();
SimpleTest.waitForClipboard(
function(aActual) {
mostRecentActual = aActual;
return aActual === aExpected;
},
function() {
synthesizeKey("A", {accelKey: true});
synthesizeKey("C", {accelKey: true});
},
aNext,
function() {
ok(false, "pasted text doesn't match for " + aFrameId);
dump("******EXPECTED******\n");
dump(aExpected);
dump("*******ACTUAL*******\n");
dump(mostRecentActual);
dump("********************\n");
finish();
}
);
});
}
SimpleTest.waitForFocus(function() {
test(
"acFrame",
acExpectedText,
function() {
finish()
}
);
});
SimpleTest.waitForExplicitFinish();
]]>
</script>
</window>

Просмотреть файл

@ -113,6 +113,7 @@
f("other2", OTHER, BYTES, 222 * MB);
f("perc2", OTHER, PERCENTAGE, 10000);
f("perc1", OTHER, PERCENTAGE, 4567);
f("compartments/user/https:\\\\very-long-url.com\\very-long\\oh-so-long\\really-quite-long.html?a=2&b=3&c=4&d=5&e=abcdefghijklmnopqrstuvwxyz&f=123456789123456789123456789", OTHER, COUNT, 1);
}
},
{ name: "smaps",
@ -133,7 +134,7 @@
{ name: "compartments",
collectReports: function(aCbObj, aClosure) {
function f(aP) {
aCbObj.callback("", aP, OTHER, COUNT, 1, "", aClosure);
aCbObj.callback("", aP, OTHER, COUNT, 1, "Desc.", aClosure);
}
f("compartments/user/bar");
f("compartments/system/bar");
@ -272,6 +273,15 @@ Explicit Allocations\n\
\n\
Other Measurements\n\
\n\
5 (100.0%) -- compartments\n\
├──3 (60.00%) -- user\n\
│ ├──1 (20.00%) ── bar\n\
│ ├──1 (20.00%) ── foo\n\
│ └──1 (20.00%) ── https://very-long-url.com/very-long/oh-so-long/really-quite-long.html?a=2&b=3&c=4&d=5&e=abcdefghijklmnopqrstuvwxyz&f=123456789123456789123456789\n\
└──2 (40.00%) -- system\n\
├──1 (20.00%) ── bar\n\
└──1 (20.00%) ── foo\n\
\n\
166.00 MB (100.0%) -- other1\n\
├──111.00 MB (66.87%) ── a/b\n\
└───55.00 MB (33.13%) -- c\n\
@ -445,6 +455,15 @@ Swap Breakdown\n\
\n\
Other Measurements\n\
\n\
5 (100.0%) -- compartments\n\
├──3 (60.00%) -- user\n\
│ ├──1 (20.00%) ── bar\n\
│ ├──1 (20.00%) ── foo\n\
│ └──1 (20.00%) ── https://very-long-url.com/very-long/oh-so-long/really-quite-long.html?a=2&b=3&c=4&d=5&e=abcdefghijklmnopqrstuvwxyz&f=123456789123456789123456789\n\
└──2 (40.00%) -- system\n\
├──1 (20.00%) ── bar\n\
└──1 (20.00%) ── foo\n\
\n\
174,063,616 B (100.0%) -- other1\n\
├──116,391,936 B (66.87%) ── a/b\n\
└───57,671,680 B (33.13%) -- c\n\

Просмотреть файл

@ -54,9 +54,9 @@ const TELEMETRY_DELAY = 60000;
// We used to measure "explicit" too, but it could cause hangs, and the data
// was always really noisy anyway. See bug 859657.
const MEM_HISTOGRAMS = {
"js-gc-heap": "MEMORY_JS_GC_HEAP",
"js-compartments/system": "MEMORY_JS_COMPARTMENTS_SYSTEM",
"js-compartments/user": "MEMORY_JS_COMPARTMENTS_USER",
"js-main-runtime-gc-heap": "MEMORY_JS_GC_HEAP",
"js-main-runtime-compartments-count/system": "MEMORY_JS_COMPARTMENTS_SYSTEM",
"js-main-runtime-compartments-count/user": "MEMORY_JS_COMPARTMENTS_USER",
"js-main-runtime-temporary-peak": "MEMORY_JS_MAIN_RUNTIME_TEMPORARY_PEAK",
"resident-fast": "MEMORY_RESIDENT",
"vsize": "MEMORY_VSIZE",

Просмотреть файл

@ -148,11 +148,6 @@ interface nsIMemoryReporterCallback : nsISupports
* Reporters in this category must have kind NONHEAP, units BYTES, and a
* non-empty description.
*
* - The "compartments" and "ghost-windows" trees are optional. They are
* used by about:compartments. Reporters in these trees must have kind
* OTHER, units COUNT, an amount of 1, and a description that's an empty
* string.
*
* - All other reports are unconstrained except that they must have a
* description that is a sentence.
*/