Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-01-03 13:01:49 +01:00
commit 1d26f02307
81 changed files with 1724 additions and 1007 deletions

View File

@ -291,7 +291,9 @@ const CustomizableWidgets = [{
defaultArea: CustomizableUI.AREA_PANEL,
onBuild: function(aDocument) {
const kPanelId = "PanelUI-popup";
let inPanel = (this.currentArea == CustomizableUI.AREA_PANEL);
let areaType = CustomizableUI.getAreaType(this.currentArea);
let inPanel = areaType == CustomizableUI.TYPE_MENU_PANEL;
let inToolbar = areaType == CustomizableUI.TYPE_TOOLBAR;
let noautoclose = inPanel ? "true" : null;
let cls = inPanel ? "panel-combined-button" : "toolbarbutton-1";
@ -358,10 +360,14 @@ const CustomizableWidgets = [{
Services.obs.addObserver(updateZoomResetButton, "browser-fullZoom:zoomChange", false);
Services.obs.addObserver(updateZoomResetButton, "browser-fullZoom:zoomReset", false);
if (inPanel && this.currentArea) {
if (inPanel) {
let panel = aDocument.getElementById(kPanelId);
panel.addEventListener("popupshowing", updateZoomResetButton);
} else {
if (inToolbar) {
let container = window.gBrowser.tabContainer;
container.addEventListener("TabSelect", updateZoomResetButton);
}
updateZoomResetButton();
}
@ -373,9 +379,13 @@ const CustomizableWidgets = [{
updateCombinedWidgetStyle(node, aArea, true);
updateZoomResetButton();
if (aArea == CustomizableUI.AREA_PANEL) {
let areaType = CustomizableUI.getAreaType(aArea);
if (areaType == CustomizableUI.TYPE_MENU_PANEL) {
let panel = aDocument.getElementById(kPanelId);
panel.addEventListener("popupshowing", updateZoomResetButton);
} else if (areaType == CustomizableUI.TYPE_TOOLBAR) {
let container = window.gBrowser.tabContainer;
container.addEventListener("TabSelect", updateZoomResetButton);
}
}.bind(this),
@ -383,9 +393,13 @@ const CustomizableWidgets = [{
if (aWidgetId != this.id)
return;
if (aPrevArea == CustomizableUI.AREA_PANEL) {
let areaType = CustomizableUI.getAreaType(aPrevArea);
if (areaType == CustomizableUI.TYPE_MENU_PANEL) {
let panel = aDocument.getElementById(kPanelId);
panel.removeEventListener("popupshowing", updateZoomResetButton);
} else if (areaType == CustomizableUI.TYPE_TOOLBAR) {
let container = window.gBrowser.tabContainer;
container.removeEventListener("TabSelect", updateZoomResetButton);
}
// When a widget is demoted to the palette ('removed'), it's visual
@ -417,6 +431,8 @@ const CustomizableWidgets = [{
Services.obs.removeObserver(updateZoomResetButton, "browser-fullZoom:zoomReset");
let panel = aDoc.getElementById(kPanelId);
panel.removeEventListener("popupshowing", updateZoomResetButton);
let container = aDoc.defaultView.gBrowser.tabContainer;
container.removeEventListener("TabSelect", updateZoomResetButton);
}.bind(this),
onWidgetDrag: function(aWidgetId, aArea) {

View File

@ -38,6 +38,7 @@ skip-if = true
# Because this test is about the menubar, it can't be run on mac
skip-if = os == "mac"
[browser_934951_zoom_in_toolbar.js]
[browser_938980_navbar_collapsed.js]
[browser_938995_indefaultstate_nonremovable.js]
[browser_940013_registerToolbarNode_calls_registerArea.js]

View File

@ -0,0 +1,68 @@
/* 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 kTimeoutInMS = 20000;
// Bug 934951 - Zoom controls percentage label doesn't update when it's in the toolbar and you navigate.
add_task(function() {
CustomizableUI.addWidgetToArea("zoom-controls", CustomizableUI.AREA_NAVBAR);
let tab1 = gBrowser.addTab("about:mozilla");
let tab2 = gBrowser.addTab("about:newtab");
gBrowser.selectedTab = tab1;
let zoomResetButton = document.getElementById("zoom-reset-button");
is(parseInt(zoomResetButton.label, 10), 100, "Default zoom is 100% for about:mozilla");
let zoomChangePromise = promiseObserverNotification("browser-fullZoom:zoomChange");
FullZoom.enlarge();
yield zoomChangePromise;
is(parseInt(zoomResetButton.label, 10), 110, "Zoom is changed to 110% for about:mozilla");
let tabSelectPromise = promiseTabSelect();
gBrowser.selectedTab = tab2;
yield tabSelectPromise;
is(parseInt(zoomResetButton.label, 10), 100, "Default zoom is 100% for about:newtab");
gBrowser.selectedTab = tab1;
let zoomResetPromise = promiseObserverNotification("browser-fullZoom:zoomReset");
FullZoom.reset();
yield zoomResetPromise;
is(parseInt(zoomResetButton.label, 10), 100, "Default zoom is 100% for about:mozilla");
CustomizableUI.reset();
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab1);
});
function promiseObserverNotification(aObserver) {
let deferred = Promise.defer();
function notificationCallback(e) {
Services.obs.removeObserver(notificationCallback, aObserver, false);
clearTimeout(timeoutId);
deferred.resolve();
};
let timeoutId = setTimeout(() => {
Services.obs.removeObserver(notificationCallback, aObserver, false);
deferred.reject("Notification '" + aObserver + "' did not happen within 20 seconds.");
}, kTimeoutInMS);
Services.obs.addObserver(notificationCallback, aObserver, false);
return deferred.promise;
}
function promiseTabSelect() {
let deferred = Promise.defer();
let container = window.gBrowser.tabContainer;
let timeoutId = setTimeout(() => {
container.removeEventListener("TabSelect", callback);
deferred.reject("TabSelect did not happen within 20 seconds");
}, kTimeoutInMS);
function callback(e) {
container.removeEventListener("TabSelect", callback);
clearTimeout(timeoutId);
executeSoon(deferred.resolve);
};
container.addEventListener("TabSelect", callback);
return deferred.promise;
}

View File

@ -130,12 +130,18 @@ this.BrowserUITelemetry = {
init: function() {
UITelemetry.addSimpleMeasureFunction("toolbars",
this.getToolbarMeasures.bind(this));
Services.obs.addObserver(this, "sessionstore-windows-restored", false);
Services.obs.addObserver(this, "browser-delayed-startup-finished", false);
},
observe: function(aSubject, aTopic, aData) {
if (aTopic == "browser-delayed-startup-finished") {
this._registerWindow(aSubject);
switch(aTopic) {
case "sessionstore-windows-restored":
this._gatherFirstWindowMeasurements();
break;
case "browser-delayed-startup-finished":
this._registerWindow(aSubject);
break;
}
},
@ -200,16 +206,23 @@ this.BrowserUITelemetry = {
},
_firstWindowMeasurements: null,
_registerWindow: function(aWindow) {
// We'll gather measurements on the first non-popup window that opens
// after it has painted. We do this here instead of waiting for
// UITelemetry to ask for our measurements because at that point
// all browser windows have probably been closed, since the vast
// majority of saved-session pings are gathered during shutdown.
if (!this._firstWindowMeasurements && aWindow.toolbar.visible) {
this._firstWindowMeasurements = this._getWindowMeasurements(aWindow);
}
_gatherFirstWindowMeasurements: function() {
// We'll gather measurements as soon as the session has restored.
// We do this here instead of waiting for UITelemetry to ask for
// our measurements because at that point all browser windows have
// probably been closed, since the vast majority of saved-session
// pings are gathered during shutdown.
let win = RecentWindow.getMostRecentBrowserWindow({
private: false,
allowPopups: false,
});
// If there are no such windows, we're out of luck. :(
this._firstWindowMeasurements = win ? this._getWindowMeasurements(win)
: {};
},
_registerWindow: function(aWindow) {
aWindow.addEventListener("unload", this);
let document = aWindow.document;
@ -419,4 +432,4 @@ function getIDBasedOnFirstIDedAncestor(aNode) {
}
return aNode.id;
}
}

View File

@ -1,4 +1,4 @@
%filter substitution
%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-reset-button, #zoom-in-button, #sync-button, #feed-button, #tabview-button, #webrtc-status-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #switch-to-metro-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button
%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-reset-button, #zoom-in-button, #sync-button, #feed-button, #webrtc-status-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #switch-to-metro-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button
%define inAnyPanel :-moz-any(:not([cui-areatype="toolbar"]),.overflowedItem)

View File

@ -258,29 +258,32 @@ static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
static PLDHashTable sEventListenerManagersHash;
class DOMEventListenerManagersHashReporter MOZ_FINAL : public MemoryUniReporter
class DOMEventListenerManagersHashReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
DOMEventListenerManagersHashReporter()
: MemoryUniReporter(
"explicit/dom/event-listener-managers-hash",
KIND_HEAP,
UNITS_BYTES,
"Memory used by the event listener manager's hash table.")
{}
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
private:
int64_t Amount()
public:
NS_DECL_ISUPPORTS
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
// We don't measure the |nsEventListenerManager| objects pointed to by the
// entries because those references are non-owning.
return sEventListenerManagersHash.ops
? PL_DHashTableSizeOfExcludingThis(&sEventListenerManagersHash,
nullptr, MallocSizeOf)
: 0;
int64_t amount = sEventListenerManagersHash.ops
? PL_DHashTableSizeOfExcludingThis(
&sEventListenerManagersHash, nullptr, MallocSizeOf)
: 0;
return MOZ_COLLECT_REPORT(
"explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES,
amount,
"Memory used by the event listener manager's hash table.");
}
};
NS_IMPL_ISUPPORTS1(DOMEventListenerManagersHashReporter, nsIMemoryReporter)
class EventListenerManagerMapEntry : public PLDHashEntryHdr
{
public:

View File

@ -688,9 +688,7 @@ public:
nsPrintfCString(
"explicit/dom/memory-file-data/large/file(length=%llu, sha1=%s)",
owner->mLength, digestString.get()),
nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES,
size,
KIND_HEAP, UNITS_BYTES, size,
nsPrintfCString(
"Memory used to back a memory file of length %llu bytes. The file "
"has a sha1 of %s.\n\n"
@ -707,9 +705,7 @@ public:
nsresult rv = aCallback->Callback(
/* process */ NS_LITERAL_CSTRING(""),
NS_LITERAL_CSTRING("explicit/dom/memory-file-data/small"),
nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES,
smallObjectsTotal,
KIND_HEAP, UNITS_BYTES, smallObjectsTotal,
nsPrintfCString(
"Memory used to back small memory files (less than %d bytes each).\n\n"
"Note that the allocator may round up a memory file's length -- "

View File

@ -29,22 +29,24 @@ static nsClassHashtable<nsCStringHashKey, DataInfo>* gDataTable;
// Memory reporting for the hash table.
namespace mozilla {
class HostObjectURLsReporter MOZ_FINAL : public MemoryUniReporter
class HostObjectURLsReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
HostObjectURLsReporter()
: MemoryUniReporter("host-object-urls",
KIND_OTHER, UNITS_COUNT,
"The number of host objects stored for access via URLs "
"(e.g. blobs passed to URL.createObjectURL).")
{}
private:
int64_t Amount() MOZ_OVERRIDE
NS_DECL_ISUPPORTS
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return gDataTable ? gDataTable->Count() : 0;
return MOZ_COLLECT_REPORT(
"host-object-urls", KIND_OTHER, UNITS_COUNT,
gDataTable ? gDataTable->Count() : 0,
"The number of host objects stored for access via URLs "
"(e.g. blobs passed to URL.createObjectURL).");
}
};
NS_IMPL_ISUPPORTS1(HostObjectURLsReporter, nsIMemoryReporter)
}
nsHostObjectProtocolHandler::nsHostObjectProtocolHandler()

View File

@ -136,17 +136,24 @@ static int64_t gCanvasAzureMemoryUsed = 0;
// This is KIND_OTHER because it's not always clear where in memory the pixels
// of a canvas are stored. Furthermore, this memory will be tracked by the
// underlying surface implementations. See bug 655638 for details.
class Canvas2dPixelsReporter MOZ_FINAL : public MemoryUniReporter
class Canvas2dPixelsReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
Canvas2dPixelsReporter()
: MemoryUniReporter("canvas-2d-pixels", KIND_OTHER, UNITS_BYTES,
"Memory used by 2D canvases. Each canvas requires (width * height * 4) bytes.")
{}
private:
int64_t Amount() MOZ_OVERRIDE { return gCanvasAzureMemoryUsed; }
public:
NS_DECL_ISUPPORTS
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return MOZ_COLLECT_REPORT(
"canvas-2d-pixels", KIND_OTHER, UNITS_BYTES,
gCanvasAzureMemoryUsed,
"Memory used by 2D canvases. Each canvas requires "
"(width * height * 4) bytes.");
}
};
NS_IMPL_ISUPPORTS1(Canvas2dPixelsReporter, nsIMemoryReporter)
class CanvasRadialGradient : public CanvasGradient
{
public:
@ -583,7 +590,7 @@ CanvasRenderingContext2D::ParseColor(const nsAString& aString,
return false;
}
if (value.GetUnit() == eCSSUnit_Color) {
if (value.IsNumericColorUnit()) {
// if we already have a color we can just use it directly
*aColor = value.GetColorValue();
} else {

View File

@ -116,17 +116,14 @@ GlobalNameHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
return true;
}
NS_IMPL_ISUPPORTS_INHERITED2(
NS_IMPL_ISUPPORTS3(
nsScriptNameSpaceManager,
MemoryUniReporter,
nsIObserver,
nsISupportsWeakReference)
nsISupportsWeakReference,
nsIMemoryReporter)
nsScriptNameSpaceManager::nsScriptNameSpaceManager()
: MemoryUniReporter("explicit/script-namespace-manager",
KIND_HEAP, UNITS_BYTES,
"Memory used for the script namespace manager.")
, mIsInitialized(false)
: mIsInitialized(false)
{
MOZ_COUNT_CTOR(nsScriptNameSpaceManager);
}
@ -863,14 +860,20 @@ static size_t
SizeOfEntryExcludingThis(PLDHashEntryHdr *aHdr, MallocSizeOf aMallocSizeOf,
void *aArg)
{
GlobalNameMapEntry* entry = static_cast<GlobalNameMapEntry*>(aHdr);
return entry->SizeOfExcludingThis(aMallocSizeOf);
GlobalNameMapEntry* entry = static_cast<GlobalNameMapEntry*>(aHdr);
return entry->SizeOfExcludingThis(aMallocSizeOf);
}
int64_t
nsScriptNameSpaceManager::Amount()
MOZ_DEFINE_MALLOC_SIZE_OF(ScriptNameSpaceManagerMallocSizeOf)
NS_IMETHODIMP
nsScriptNameSpaceManager::CollectReports(
nsIHandleReportCallback* aHandleReport, nsISupports* aData)
{
return SizeOfIncludingThis(MallocSizeOf);
return MOZ_COLLECT_REPORT(
"explicit/script-namespace-manager", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(ScriptNameSpaceManagerMallocSizeOf),
"Memory used for the script namespace manager.");
}
size_t

View File

@ -88,13 +88,14 @@ class nsICategoryManager;
class GlobalNameMapEntry;
class nsScriptNameSpaceManager : public mozilla::MemoryUniReporter,
public nsIObserver,
public nsSupportsWeakReference
class nsScriptNameSpaceManager : public nsIObserver,
public nsSupportsWeakReference,
public nsIMemoryReporter
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIMEMORYREPORTER
nsScriptNameSpaceManager();
virtual ~nsScriptNameSpaceManager();
@ -163,7 +164,6 @@ public:
void EnumerateNavigatorNames(NameEnumerator aEnumerator,
void* aClosure);
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
private:

View File

@ -500,8 +500,7 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb,
do { \
nsresult rv; \
rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
nsIMemoryReporter::KIND_OTHER, \
nsIMemoryReporter::UNITS_BYTES, _amount, \
KIND_OTHER, UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), aClosure); \
NS_ENSURE_SUCCESS(rv, rv); \
} while (0)
@ -801,6 +800,9 @@ nsWindowMemoryReporter::CheckForGhostWindows(
&ghostEnumData);
}
NS_IMPL_ISUPPORTS1(nsWindowMemoryReporter::GhostWindowsReporter,
nsIMemoryReporter)
/* static */ int64_t
nsWindowMemoryReporter::GhostWindowsReporter::DistinguishedAmount()
{

View File

@ -151,11 +151,18 @@ private:
* nsGhostWindowReporter generates the "ghost-windows" report, which counts
* the number of ghost windows present.
*/
class GhostWindowsReporter MOZ_FINAL : public mozilla::MemoryUniReporter
class GhostWindowsReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
GhostWindowsReporter()
: MemoryUniReporter("ghost-windows", KIND_OTHER, UNITS_COUNT,
NS_DECL_ISUPPORTS
static int64_t DistinguishedAmount();
NS_IMETHOD
CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData)
{
return MOZ_COLLECT_REPORT(
"ghost-windows", KIND_OTHER, UNITS_COUNT, DistinguishedAmount(),
"The number of ghost windows present (the number of nodes underneath "
"explicit/window-objects/top(none)/ghost, modulo race conditions). A ghost "
"window is not shown in any tab, does not share a domain with any non-detached "
@ -163,13 +170,8 @@ private:
"memory.ghost_window_timeout_seconds, or has survived a round of "
"about:memory's minimize memory usage button.\n\n"
"Ghost windows can happen legitimately, but they are often indicative of "
"leaks in the browser or add-ons.")
{}
static int64_t DistinguishedAmount();
private:
int64_t Amount() MOZ_OVERRIDE { return DistinguishedAmount(); }
"leaks in the browser or add-ons.");
}
};
// Protect ctor, use Init() instead.

View File

@ -246,8 +246,8 @@ ContentParentsMemoryReporter::CollectReports(nsIMemoryReporterCallback* cb,
nsresult rv = cb->Callback(/* process */ EmptyCString(),
path,
nsIMemoryReporter::KIND_OTHER,
nsIMemoryReporter::UNITS_COUNT,
KIND_OTHER,
UNITS_COUNT,
numQueuedMessages,
desc,
aClosure);

View File

@ -29,3 +29,9 @@ interface CSSStyleDeclaration {
readonly attribute CSSRule? parentRule;
};
// Mozilla extensions
partial interface CSSStyleDeclaration {
[ChromeOnly,Throws]
DOMString getAuthoredPropertyValue(DOMString property);
};

View File

@ -83,10 +83,10 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(mozHunspell)
NS_IMPL_CYCLE_COLLECTING_RELEASE(mozHunspell)
NS_INTERFACE_MAP_BEGIN(mozHunspell)
NS_INTERFACE_MAP_ENTRY(nsIMemoryReporter)
NS_INTERFACE_MAP_ENTRY(mozISpellCheckingEngine)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIMemoryReporter)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozISpellCheckingEngine)
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozHunspell)
NS_INTERFACE_MAP_END
@ -107,9 +107,7 @@ void HunspellReportMemoryDeallocation(void* ptr) {
}
mozHunspell::mozHunspell()
: MemoryUniReporter("explicit/spell-check", KIND_HEAP, UNITS_BYTES,
"Memory used by the spell-checking engine's internal data structures."),
mHunspell(nullptr)
: mHunspell(nullptr)
{
#ifdef DEBUG
// There must be only one instance of this class, due to |sAmount|
@ -131,14 +129,14 @@ mozHunspell::Init()
obs->AddObserver(this, "profile-after-change", true);
}
RegisterWeakMemoryReporter(this);
mozilla::RegisterWeakMemoryReporter(this);
return NS_OK;
}
mozHunspell::~mozHunspell()
{
UnregisterWeakMemoryReporter(this);
mozilla::UnregisterWeakMemoryReporter(this);
mPersonalDictionary = nullptr;
delete mHunspell;

View File

@ -80,10 +80,10 @@
{ 0x56c778e4, 0x1bee, 0x45f3, \
{ 0xa6, 0x89, 0x88, 0x66, 0x92, 0xa9, 0x7f, 0xe7 } }
class mozHunspell : public mozilla::MemoryUniReporter,
public mozISpellCheckingEngine,
class mozHunspell : public mozISpellCheckingEngine,
public nsIObserver,
public nsSupportsWeakReference
public nsSupportsWeakReference,
public nsIMemoryReporter
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -101,10 +101,19 @@ public:
// helper method for converting a word to the charset of the dictionary
nsresult ConvertCharset(const PRUnichar* aStr, char ** aDst);
MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
static void OnAlloc(void* ptr) { sAmount += MallocSizeOfOnAlloc(ptr); }
static void OnFree (void* ptr) { sAmount -= MallocSizeOfOnFree (ptr); }
int64_t Amount() MOZ_OVERRIDE { return sAmount; }
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return MOZ_COLLECT_REPORT(
"explicit/spell-check", KIND_HEAP, UNITS_BYTES, sAmount,
"Memory used by the spell-checking engine.");
}
protected:

View File

@ -10,6 +10,8 @@
using namespace mozilla;
using namespace mozilla::gl;
NS_IMPL_ISUPPORTS1(GfxTexturesReporter, nsIMemoryReporter)
int64_t GfxTexturesReporter::sAmount = 0;
static uint32_t GetBitsPerTexel(GLenum format, GLenum type)

View File

@ -13,12 +13,12 @@
namespace mozilla {
namespace gl {
class GfxTexturesReporter MOZ_FINAL : public MemoryUniReporter
class GfxTexturesReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
NS_DECL_ISUPPORTS
GfxTexturesReporter()
: MemoryUniReporter("gfx-textures", KIND_OTHER, UNITS_BYTES,
"Memory used for storing GL textures.")
{
#ifdef DEBUG
// There must be only one instance of this class, due to |sAmount|
@ -41,9 +41,15 @@ public:
static void UpdateAmount(MemoryUse action, GLenum format, GLenum type,
uint16_t tileSize);
private:
int64_t Amount() MOZ_OVERRIDE { return sAmount; }
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return MOZ_COLLECT_REPORT(
"gfx-textures", KIND_OTHER, UNITS_BYTES, sAmount,
"Memory used for storing GL textures.");
}
private:
static int64_t sAmount;
};

View File

@ -28,6 +28,8 @@ using namespace mozilla::ipc;
namespace mozilla {
namespace layers {
NS_IMPL_ISUPPORTS1(GfxMemoryImageReporter, nsIMemoryReporter)
mozilla::Atomic<int32_t> GfxMemoryImageReporter::sAmount(0);
mozilla::ipc::SharedMemory::SharedMemoryType OptimalShmemType()

View File

@ -12,7 +12,7 @@
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
#include "mozilla/RefPtr.h"
#include "nsIMemoryReporter.h" // for MemoryUniReporter
#include "nsIMemoryReporter.h" // for nsIMemoryReporter
#include "mozilla/Atomics.h" // for Atomic
/*
@ -145,12 +145,12 @@ protected:
friend class detail::RefCounted<ISurfaceAllocator, detail::AtomicRefCount>;
};
class GfxMemoryImageReporter MOZ_FINAL : public mozilla::MemoryUniReporter
class GfxMemoryImageReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
NS_DECL_ISUPPORTS
GfxMemoryImageReporter()
: MemoryUniReporter("explicit/gfx/heap-textures", KIND_HEAP, UNITS_BYTES,
"Heap memory shared between threads by texture clients and hosts.")
{
#ifdef DEBUG
// There must be only one instance of this class, due to |sAmount|
@ -161,6 +161,9 @@ public:
#endif
}
MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
static void DidAlloc(void* aPointer)
{
sAmount += MallocSizeOfOnAlloc(aPointer);
@ -171,9 +174,15 @@ public:
sAmount -= MallocSizeOfOnFree(aPointer);
}
private:
int64_t Amount() MOZ_OVERRIDE { return sAmount; }
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return MOZ_COLLECT_REPORT(
"explicit/gfx/heap-textures", KIND_HEAP, UNITS_BYTES, sAmount,
"Heap memory shared between threads by texture clients and hosts.");
}
private:
static mozilla::Atomic<int32_t> sAmount;
};

View File

@ -189,18 +189,14 @@ ContentTypeFromPixelFormat(android::PixelFormat aFormat)
return gfxASurface::ContentFromFormat(ImageFormatForPixelFormat(aFormat));
}
class GrallocReporter MOZ_FINAL : public MemoryUniReporter
class GrallocReporter MOZ_FINAL : public nsIMemoryReporter
{
friend class GrallocBufferActor;
public:
NS_DECL_ISUPPORTS
GrallocReporter()
: MemoryUniReporter("gralloc", KIND_OTHER, UNITS_BYTES,
"Special RAM that can be shared between processes and directly accessed by "
"both the CPU and GPU. Gralloc memory is usually a relatively precious "
"resource, with much less available than generic RAM. When it's exhausted, "
"graphics performance can suffer. This value can be incorrect because of race "
"conditions.")
{
#ifdef DEBUG
// There must be only one instance of this class, due to |sAmount|
@ -211,12 +207,24 @@ public:
#endif
}
private:
int64_t Amount() MOZ_OVERRIDE { return sAmount; }
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return MOZ_COLLECT_REPORT(
"gralloc", KIND_OTHER, UNITS_BYTES, sAmount,
"Special RAM that can be shared between processes and directly accessed by "
"both the CPU and GPU. Gralloc memory is usually a relatively precious "
"resource, with much less available than generic RAM. When it's exhausted, "
"graphics performance can suffer. This value can be incorrect because of race "
"conditions.");
}
private:
static int64_t sAmount;
};
NS_IMPL_ISUPPORTS1(GrallocReporter, nsIMemoryReporter)
int64_t GrallocReporter::sAmount = 0;
GrallocBufferActor::GrallocBufferActor()

View File

@ -31,12 +31,12 @@ using namespace mozilla::gfx;
static FT_Library gPlatformFTLibrary = nullptr;
class FreetypeReporter MOZ_FINAL : public MemoryUniReporter
class FreetypeReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
NS_DECL_ISUPPORTS
FreetypeReporter()
: MemoryUniReporter("explicit/freetype", KIND_HEAP, UNITS_BYTES,
"Memory used by Freetype.")
{
#ifdef DEBUG
// There must be only one instance of this class, due to |sAmount|
@ -47,6 +47,9 @@ public:
#endif
}
MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
static void* CountingAlloc(FT_Memory, long size)
{
void *p = malloc(size);
@ -74,12 +77,20 @@ public:
return pnew;
}
private:
int64_t Amount() MOZ_OVERRIDE { return sAmount; }
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return MOZ_COLLECT_REPORT(
"explicit/freetype", KIND_HEAP, UNITS_BYTES, sAmount,
"Memory used by Freetype.");
}
private:
static int64_t sAmount;
};
NS_IMPL_ISUPPORTS1(FreetypeReporter, nsIMemoryReporter)
int64_t FreetypeReporter::sAmount = 0;
static FT_MemoryRec_ sFreetypeMemoryRecord;

View File

@ -1376,15 +1376,13 @@ gfxFontCache::MemoryReporter::CollectReports
aCb->Callback(EmptyCString(),
NS_LITERAL_CSTRING("explicit/gfx/font-cache"),
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
sizes.mFontInstances,
KIND_HEAP, UNITS_BYTES, sizes.mFontInstances,
NS_LITERAL_CSTRING("Memory used for active font instances."),
aClosure);
aCb->Callback(EmptyCString(),
NS_LITERAL_CSTRING("explicit/gfx/font-shaped-words"),
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
sizes.mShapedWords,
KIND_HEAP, UNITS_BYTES, sizes.mShapedWords,
NS_LITERAL_CSTRING("Memory used to cache shaped glyph data."),
aClosure);

View File

@ -77,20 +77,36 @@ static const int kSupportedFeatureLevels[] =
{ D3D10_FEATURE_LEVEL_10_1, D3D10_FEATURE_LEVEL_10_0,
D3D10_FEATURE_LEVEL_9_3 };
class GfxD2DSurfaceCacheReporter MOZ_FINAL : public MemoryUniReporter
class GfxD2DSurfaceReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
GfxD2DSurfaceCacheReporter()
: MemoryUniReporter("gfx-d2d-surface-cache", KIND_OTHER, UNITS_BYTES,
"Memory used by the Direct2D internal surface cache.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
NS_DECL_ISUPPORTS
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return cairo_d2d_get_image_surface_cache_usage();
nsresult rv;
int64_t amount = cairo_d2d_get_image_surface_cache_usage();
rv = MOZ_COLLECT_REPORT(
"gfx-d2d-surface-cache", KIND_OTHER, UNITS_BYTES, amount,
"Memory used by the Direct2D internal surface cache.");
NS_ENSURE_SUCCESS(rv, rv);
cairo_device_t *device =
gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
amount = device ? cairo_d2d_get_surface_vram_usage(device) : 0;
rv = MOZ_COLLECT_REPORT(
"gfx-d2d-surface-vram", KIND_OTHER, UNITS_BYTES, amount,
"Video memory used by D2D surfaces.");
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(GfxD2DSurfaceReporter, nsIMemoryReporter)
namespace
{
@ -114,51 +130,35 @@ bool OncePreferenceDirect2DForceEnabled()
} // anonymous namespace
class GfxD2DSurfaceVramReporter MOZ_FINAL : public MemoryUniReporter
{
public:
GfxD2DSurfaceVramReporter()
: MemoryUniReporter("gfx-d2d-surface-vram", KIND_OTHER, UNITS_BYTES,
"Video memory used by D2D surfaces.")
{}
private:
int64_t Amount() MOZ_OVERRIDE {
cairo_device_t *device =
gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
return device ? cairo_d2d_get_surface_vram_usage(device) : 0;
}
};
#endif
class GfxD2DVramDrawTargetReporter MOZ_FINAL : public MemoryUniReporter
class GfxD2DVramReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
GfxD2DVramDrawTargetReporter()
: MemoryUniReporter("gfx-d2d-vram-draw-target", KIND_OTHER, UNITS_BYTES,
"Video memory used by D2D DrawTargets.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
NS_DECL_ISUPPORTS
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return Factory::GetD2DVRAMUsageDrawTarget();
nsresult rv;
rv = MOZ_COLLECT_REPORT(
"gfx-d2d-vram-draw-target", KIND_OTHER, UNITS_BYTES,
Factory::GetD2DVRAMUsageDrawTarget(),
"Video memory used by D2D DrawTargets.");
NS_ENSURE_SUCCESS(rv, rv);
rv = MOZ_COLLECT_REPORT(
"gfx-d2d-vram-source-surface", KIND_OTHER, UNITS_BYTES,
Factory::GetD2DVRAMUsageSourceSurface(),
"Video memory used by D2D SourceSurfaces.");
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
};
class GfxD2DVramSourceSurfaceReporter MOZ_FINAL : public MemoryUniReporter
{
public:
GfxD2DVramSourceSurfaceReporter()
: MemoryUniReporter("gfx-d2d-vram-source-surface",
KIND_OTHER, UNITS_BYTES,
"Video memory used by D2D SourceSurfaces.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
return Factory::GetD2DVRAMUsageSourceSurface();
}
};
NS_IMPL_ISUPPORTS1(GfxD2DVramReporter, nsIMemoryReporter)
#define GFX_USE_CLEARTYPE_ALWAYS "gfx.font_rendering.cleartype.always_use_for_content"
#define GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE "gfx.font_rendering.cleartype.use_for_downloadable_fonts"
@ -318,8 +318,7 @@ public:
do { \
nsresult rv; \
rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
nsIMemoryReporter::KIND_OTHER, \
nsIMemoryReporter::UNITS_BYTES, _amount, \
KIND_OTHER, UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), aClosure); \
NS_ENSURE_SUCCESS(rv, rv); \
} while (0)
@ -365,12 +364,10 @@ gfxWindowsPlatform::gfxWindowsPlatform()
CoInitialize(nullptr);
#ifdef CAIRO_HAS_D2D_SURFACE
RegisterStrongMemoryReporter(new GfxD2DSurfaceCacheReporter());
RegisterStrongMemoryReporter(new GfxD2DSurfaceVramReporter());
RegisterStrongMemoryReporter(new GfxD2DSurfaceReporter());
mD2DDevice = nullptr;
#endif
RegisterStrongMemoryReporter(new GfxD2DVramDrawTargetReporter());
RegisterStrongMemoryReporter(new GfxD2DVramSourceSurfaceReporter());
RegisterStrongMemoryReporter(new GfxD2DVramReporter());
UpdateRenderMode();

View File

@ -197,17 +197,14 @@ private:
* maintains high-level invariants and encapsulates the details of the surface
* cache's implementation.
*/
class SurfaceCacheImpl : public MemoryUniReporter
class SurfaceCacheImpl : public nsIMemoryReporter
{
public:
NS_DECL_ISUPPORTS
SurfaceCacheImpl(uint32_t aSurfaceCacheExpirationTimeMS,
uint32_t aSurfaceCacheSize)
: MemoryUniReporter("imagelib-surface-cache",
KIND_OTHER, UNITS_BYTES,
"Memory used by the imagelib temporary surface cache.")
, mExpirationTracker(MOZ_THIS_IN_INITIALIZER_LIST(),
: mExpirationTracker(MOZ_THIS_IN_INITIALIZER_LIST(),
aSurfaceCacheExpirationTimeMS)
, mMemoryPressureObserver(new MemoryPressureObserver)
, mMaxCost(aSurfaceCacheSize)
@ -362,9 +359,13 @@ public:
return PL_DHASH_NEXT;
}
int64_t Amount() MOZ_OVERRIDE
NS_IMETHOD
CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData)
{
return SizeOfSurfacesEstimate();
return MOZ_COLLECT_REPORT(
"imagelib-surface-cache", KIND_OTHER, UNITS_BYTES,
SizeOfSurfacesEstimate(),
"Memory used by the imagelib temporary surface cache.");
}
// XXX(seth): This is currently only an estimate and, since we don't know
@ -427,7 +428,7 @@ private:
Cost mAvailableCost;
};
NS_IMPL_ISUPPORTS_INHERITED0(SurfaceCacheImpl, MemoryUniReporter)
NS_IMPL_ISUPPORTS1(SurfaceCacheImpl, nsIMemoryReporter)
NS_IMPL_ISUPPORTS1(SurfaceCacheImpl::MemoryPressureObserver, nsIObserver)
///////////////////////////////////////////////////////////////////////////////

View File

@ -70,57 +70,57 @@ public:
do { \
nsresult rv; \
rv = callback->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
_kind, nsIMemoryReporter::UNITS_BYTES, _amount, \
_kind, UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), closure); \
NS_ENSURE_SUCCESS(rv, rv); \
} while (0)
REPORT("explicit/images/chrome/used/raw",
nsIMemoryReporter::KIND_HEAP, chrome.mUsedRaw,
KIND_HEAP, chrome.mUsedRaw,
"Memory used by in-use chrome images (compressed data).");
REPORT("explicit/images/chrome/used/uncompressed-heap",
nsIMemoryReporter::KIND_HEAP, chrome.mUsedUncompressedHeap,
KIND_HEAP, chrome.mUsedUncompressedHeap,
"Memory used by in-use chrome images (uncompressed data).");
REPORT("explicit/images/chrome/used/uncompressed-nonheap",
nsIMemoryReporter::KIND_NONHEAP, chrome.mUsedUncompressedNonheap,
KIND_NONHEAP, chrome.mUsedUncompressedNonheap,
"Memory used by in-use chrome images (uncompressed data).");
REPORT("explicit/images/chrome/unused/raw",
nsIMemoryReporter::KIND_HEAP, chrome.mUnusedRaw,
KIND_HEAP, chrome.mUnusedRaw,
"Memory used by not in-use chrome images (compressed data).");
REPORT("explicit/images/chrome/unused/uncompressed-heap",
nsIMemoryReporter::KIND_HEAP, chrome.mUnusedUncompressedHeap,
KIND_HEAP, chrome.mUnusedUncompressedHeap,
"Memory used by not in-use chrome images (uncompressed data).");
REPORT("explicit/images/chrome/unused/uncompressed-nonheap",
nsIMemoryReporter::KIND_NONHEAP, chrome.mUnusedUncompressedNonheap,
KIND_NONHEAP, chrome.mUnusedUncompressedNonheap,
"Memory used by not in-use chrome images (uncompressed data).");
REPORT("explicit/images/content/used/raw",
nsIMemoryReporter::KIND_HEAP, content.mUsedRaw,
KIND_HEAP, content.mUsedRaw,
"Memory used by in-use content images (compressed data).");
REPORT("explicit/images/content/used/uncompressed-heap",
nsIMemoryReporter::KIND_HEAP, content.mUsedUncompressedHeap,
KIND_HEAP, content.mUsedUncompressedHeap,
"Memory used by in-use content images (uncompressed data).");
REPORT("explicit/images/content/used/uncompressed-nonheap",
nsIMemoryReporter::KIND_NONHEAP, content.mUsedUncompressedNonheap,
KIND_NONHEAP, content.mUsedUncompressedNonheap,
"Memory used by in-use content images (uncompressed data).");
REPORT("explicit/images/content/unused/raw",
nsIMemoryReporter::KIND_HEAP, content.mUnusedRaw,
KIND_HEAP, content.mUnusedRaw,
"Memory used by not in-use content images (compressed data).");
REPORT("explicit/images/content/unused/uncompressed-heap",
nsIMemoryReporter::KIND_HEAP, content.mUnusedUncompressedHeap,
KIND_HEAP, content.mUnusedUncompressedHeap,
"Memory used by not in-use content images (uncompressed data).");
REPORT("explicit/images/content/unused/uncompressed-nonheap",
nsIMemoryReporter::KIND_NONHEAP, content.mUnusedUncompressedNonheap,
KIND_NONHEAP, content.mUnusedUncompressedNonheap,
"Memory used by not in-use content images (uncompressed data).");
#undef REPORT

View File

@ -17,28 +17,32 @@ namespace ipc {
static Atomic<size_t> gShmemAllocated;
static Atomic<size_t> gShmemMapped;
class ShmemAllocatedReporter MOZ_FINAL : public MemoryUniReporter
class ShmemReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
ShmemAllocatedReporter()
: MemoryUniReporter("shmem-allocated", KIND_OTHER, UNITS_BYTES,
"Memory shared with other processes that is accessible (but not necessarily "
"mapped).")
{}
private:
int64_t Amount() MOZ_OVERRIDE { return gShmemAllocated; }
NS_DECL_THREADSAFE_ISUPPORTS
NS_IMETHOD
CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData)
{
nsresult rv;
rv = MOZ_COLLECT_REPORT(
"shmem-allocated", KIND_OTHER, UNITS_BYTES, gShmemAllocated,
"Memory shared with other processes that is accessible (but not "
"necessarily mapped).");
NS_ENSURE_SUCCESS(rv, rv);
rv = MOZ_COLLECT_REPORT(
"shmem-mapped", KIND_OTHER, UNITS_BYTES, gShmemMapped,
"Memory shared with other processes that is mapped into the address "
"space.");
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
};
class ShmemMappedReporter MOZ_FINAL : public MemoryUniReporter
{
public:
ShmemMappedReporter()
: MemoryUniReporter("shmem-mapped", KIND_OTHER, UNITS_BYTES,
"Memory shared with other processes that is mapped into the address space.")
{}
private:
int64_t Amount() MOZ_OVERRIDE { return gShmemMapped; }
};
NS_IMPL_ISUPPORTS1(ShmemReporter, nsIMemoryReporter)
SharedMemory::SharedMemory()
: mAllocSize(0)
@ -46,8 +50,7 @@ SharedMemory::SharedMemory()
{
static Atomic<uint32_t> registered;
if (registered.compareExchange(0, 1)) {
RegisterStrongMemoryReporter(new ShmemAllocatedReporter());
RegisterStrongMemoryReporter(new ShmemMappedReporter());
RegisterStrongMemoryReporter(new ShmemReporter());
}
}

View File

@ -12,7 +12,7 @@ assertAsmTypeFail(USE_ASM + "function f() {} function g(i) {i=i|0} var tbl=[f,g]
assertAsmTypeFail(USE_ASM + "function f() {} function g() {return 0} var tbl=[f,g]; return f");
assertAsmTypeFail(USE_ASM + "function f(i) {i=i|0} function g(i) {i=+i} var tbl=[f,g]; return f");
assertAsmTypeFail(USE_ASM + "function f() {return 0} function g() {return 0.0} var tbl=[f,g]; return f");
assertAsmTypeFail(USE_ASM + "var tbl=0; function g() {tbl[0&1]()} return g");
assertAsmTypeFail(USE_ASM + "var tbl=0; function g() {tbl[0&1]()|0} return g");
assertEq(asmLink(asmCompile(USE_ASM + "function f() { return 42 } var tbl=[f]; return f"))(), 42);
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 0} function g() {return 1} var tbl=[f,g]; return f"))(), 0);
@ -26,6 +26,7 @@ assertAsmTypeFail(USE_ASM + "function f() {return 42} function g(i) { i=i|0; ret
assertAsmTypeFail(USE_ASM + "function f(i) {i=i|0} function g(i) { i=i|0; return tbl[i&1]()|0 } var tbl=[f,f]; return g");
assertAsmTypeFail(USE_ASM + "function f(i) {i=i|0} function g(i) { i=i|0; return tbl[i&1](3.0)|0 } var tbl=[f,f]; return g");
assertAsmTypeFail(USE_ASM + "function f(d) {d=+d} function g(i) { i=i|0; return tbl[i&1](3)|0 } var tbl=[f,f]; return g");
assertAsmTypeFail(USE_ASM + "function g() {tbl[0&1]()|0} return g");
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&1]()|0 } var tbl=[f,f]; return g"))(0), 42);
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g(i) { i=i|0; return tbl[i&1]()|0 } const tbl=[f,f]; return g"))(0), 42);
assertEq(asmLink(asmCompile(USE_ASM + "function f() {return 42} function g() {return 13} function h(i) { i=i|0; return tbl[i&1]()|0 } var tbl=[f,g]; return h"))(1), 13);

View File

@ -1209,8 +1209,9 @@ class MOZ_STACK_CLASS ModuleCompiler
unsigned mask() const { return mask_; }
unsigned globalDataOffset() const { return globalDataOffset_; }
void initElems(FuncPtrVector &&elems) { elems_ = Move(elems); JS_ASSERT(!elems_.empty()); }
unsigned numElems() const { JS_ASSERT(!elems_.empty()); return elems_.length(); }
bool initialized() const { return !elems_.empty(); }
void initElems(FuncPtrVector &&elems) { elems_ = Move(elems); JS_ASSERT(initialized()); }
unsigned numElems() const { JS_ASSERT(initialized()); return elems_.length(); }
const Func &elem(unsigned i) const { return *elems_[i]; }
};
@ -4088,6 +4089,7 @@ CheckMathBuiltinCall(FunctionCompiler &f, ParseNode *callNode, AsmJSMathBuiltin
case AsmJSMathBuiltin_log: arity = 1; doubleCallee = AsmJSImm_LogD; floatCallee = AsmJSImm_LogF; break;
case AsmJSMathBuiltin_pow: arity = 2; doubleCallee = AsmJSImm_PowD; floatCallee = AsmJSImm_Invalid; break;
case AsmJSMathBuiltin_atan2: arity = 2; doubleCallee = AsmJSImm_ATan2D; floatCallee = AsmJSImm_Invalid; break;
default: MOZ_ASSUME_UNREACHABLE("unexpected mathBuiltin");
}
if (retType == RetType::Float && floatCallee == AsmJSImm_Invalid)
@ -5702,6 +5704,11 @@ CheckFuncPtrTables(ModuleCompiler &m)
}
}
for (unsigned i = 0; i < m.numFuncPtrTables(); i++) {
if (!m.funcPtrTable(i).initialized())
return m.fail(nullptr, "expecting function-pointer table");
}
return true;
}

View File

@ -1629,22 +1629,25 @@ JSMainRuntimeCompartmentsUserDistinguishedAmount()
return JS::UserCompartmentCount(rt);
}
class JSMainRuntimeTemporaryPeakReporter MOZ_FINAL : public MemoryUniReporter
class JSMainRuntimeTemporaryPeakReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
JSMainRuntimeTemporaryPeakReporter()
: MemoryUniReporter("js-main-runtime-temporary-peak",
KIND_OTHER, UNITS_BYTES,
"The peak size of the transient storage in the main JSRuntime (the current "
"size of which is reported as 'explicit/js-non-window/runtime/temporary').")
{}
private:
int64_t Amount() MOZ_OVERRIDE
public:
NS_DECL_ISUPPORTS
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return JSMainRuntimeTemporaryPeakDistinguishedAmount();
return MOZ_COLLECT_REPORT(
"js-main-runtime-temporary-peak", KIND_OTHER, UNITS_BYTES,
JSMainRuntimeTemporaryPeakDistinguishedAmount(),
"The peak size of the transient storage in the main JSRuntime "
"(the current size of which is reported as "
"'explicit/js-non-window/runtime/temporary').");
}
};
NS_IMPL_ISUPPORTS1(JSMainRuntimeTemporaryPeakReporter, nsIMemoryReporter)
// The REPORT* macros do an unconditional report. The ZCREPORT* macros are for
// compartments and zones; they aggregate any entries smaller than
// SUNDRIES_THRESHOLD into the "sundries/gc-heap" and "sundries/malloc-heap"

View File

@ -27,9 +27,6 @@ using namespace mozilla;
nsStyleSheetService *nsStyleSheetService::gInstance = nullptr;
nsStyleSheetService::nsStyleSheetService()
: MemoryUniReporter("explicit/layout/style-sheet-service",
KIND_HEAP, UNITS_BYTES,
"Memory used for style sheets held by the style sheet service.")
{
PR_STATIC_ASSERT(0 == AGENT_SHEET && 1 == USER_SHEET && 2 == AUTHOR_SHEET);
NS_ASSERTION(!gInstance, "Someone is using CreateInstance instead of GetService");
@ -45,8 +42,8 @@ nsStyleSheetService::~nsStyleSheetService()
nsLayoutStatics::Release();
}
NS_IMPL_ISUPPORTS_INHERITED1(
nsStyleSheetService, MemoryUniReporter, nsIStyleSheetService)
NS_IMPL_ISUPPORTS2(
nsStyleSheetService, nsIStyleSheetService, nsIMemoryReporter)
void
nsStyleSheetService::RegisterFromEnumerator(nsICategoryManager *aManager,
@ -282,13 +279,19 @@ static size_t
SizeOfElementIncludingThis(nsIStyleSheet* aElement,
MallocSizeOf aMallocSizeOf, void *aData)
{
return aElement->SizeOfIncludingThis(aMallocSizeOf);
return aElement->SizeOfIncludingThis(aMallocSizeOf);
}
int64_t
nsStyleSheetService::Amount()
MOZ_DEFINE_MALLOC_SIZE_OF(StyleSheetServiceMallocSizeOf)
NS_IMETHODIMP
nsStyleSheetService::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return SizeOfIncludingThis(MallocSizeOf);
return MOZ_COLLECT_REPORT(
"explicit/layout/style-sheet-service", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(StyleSheetServiceMallocSizeOf),
"Memory used for style sheets held by the style sheet service.");
}
size_t

View File

@ -28,8 +28,8 @@ class nsIStyleSheet;
"@mozilla.org/content/style-sheet-service;1"
class nsStyleSheetService MOZ_FINAL
: public mozilla::MemoryUniReporter
, public nsIStyleSheetService
: public nsIStyleSheetService
, public nsIMemoryReporter
{
public:
nsStyleSheetService() NS_HIDDEN;
@ -37,6 +37,7 @@ class nsStyleSheetService MOZ_FINAL
NS_DECL_ISUPPORTS
NS_DECL_NSISTYLESHEETSERVICE
NS_DECL_NSIMEMORYREPORTER
NS_HIDDEN_(nsresult) Init();
@ -49,8 +50,6 @@ class nsStyleSheetService MOZ_FINAL
static nsStyleSheetService *GetInstance();
static nsStyleSheetService *gInstance;
int64_t Amount() MOZ_OVERRIDE;
private:
NS_HIDDEN_(void) RegisterFromEnumerator(nsICategoryManager *aManager,

View File

@ -433,6 +433,10 @@ Initialize()
NS_WARNING("Could not get an observer service. We will leak on shutdown.");
}
#ifdef DEBUG
nsStyleContext::AssertStyleStructMaxDifferenceValid();
#endif
return NS_OK;
}

View File

@ -400,7 +400,7 @@ load 570160.html
load 570289-1.html
load 571618-1.svg
asserts(1) load 571975-1.html # bug 574889
asserts(1) load 571995.xhtml # 761848
load 571995.xhtml
load 574958.xhtml
asserts(0-4) load 578977.html # bug 757305
load 580504-1.xhtml

View File

@ -95,7 +95,8 @@ Declaration::HasProperty(nsCSSProperty aProperty) const
bool
Declaration::AppendValueToString(nsCSSProperty aProperty,
nsAString& aResult) const
nsAString& aResult,
nsCSSValue::Serialization aSerialization) const
{
NS_ABORT_IF_FALSE(0 <= aProperty &&
aProperty < eCSSProperty_COUNT_no_shorthands,
@ -108,7 +109,7 @@ Declaration::AppendValueToString(nsCSSProperty aProperty,
return false;
}
val->AppendToString(aProperty, aResult);
val->AppendToString(aProperty, aResult, aSerialization);
return true;
}
@ -117,7 +118,8 @@ Declaration::AppendValueToString(nsCSSProperty aProperty,
static void
AppendSidesShorthandToString(const nsCSSProperty aProperties[],
const nsCSSValue* aValues[],
nsAString& aString)
nsAString& aString,
nsCSSValue::Serialization aSerialization)
{
const nsCSSValue& value1 = *aValues[0];
const nsCSSValue& value2 = *aValues[1];
@ -125,19 +127,19 @@ AppendSidesShorthandToString(const nsCSSProperty aProperties[],
const nsCSSValue& value4 = *aValues[3];
NS_ABORT_IF_FALSE(value1.GetUnit() != eCSSUnit_Null, "null value 1");
value1.AppendToString(aProperties[0], aString);
value1.AppendToString(aProperties[0], aString, aSerialization);
if (value1 != value2 || value1 != value3 || value1 != value4) {
aString.Append(PRUnichar(' '));
NS_ABORT_IF_FALSE(value2.GetUnit() != eCSSUnit_Null, "null value 2");
value2.AppendToString(aProperties[1], aString);
value2.AppendToString(aProperties[1], aString, aSerialization);
if (value1 != value3 || value2 != value4) {
aString.Append(PRUnichar(' '));
NS_ABORT_IF_FALSE(value3.GetUnit() != eCSSUnit_Null, "null value 3");
value3.AppendToString(aProperties[2], aString);
value3.AppendToString(aProperties[2], aString, aSerialization);
if (value2 != value4) {
aString.Append(PRUnichar(' '));
NS_ABORT_IF_FALSE(value4.GetUnit() != eCSSUnit_Null, "null value 4");
value4.AppendToString(aProperties[3], aString);
value4.AppendToString(aProperties[3], aString, aSerialization);
}
}
}
@ -145,12 +147,25 @@ AppendSidesShorthandToString(const nsCSSProperty aProperties[],
void
Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
{
GetValue(aProperty, aValue, nsCSSValue::eNormalized);
}
void
Declaration::GetAuthoredValue(nsCSSProperty aProperty, nsAString& aValue) const
{
GetValue(aProperty, aValue, nsCSSValue::eAuthorSpecified);
}
void
Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue,
nsCSSValue::Serialization aSerialization) const
{
aValue.Truncate(0);
// simple properties are easy.
if (!nsCSSProps::IsShorthand(aProperty)) {
AppendValueToString(aProperty, aValue);
AppendValueToString(aProperty, aValue, aSerialization);
return;
}
@ -220,17 +235,20 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
}
if (initialCount == totalCount) {
// Simplify serialization below by serializing initial up-front.
nsCSSValue(eCSSUnit_Initial).AppendToString(eCSSProperty_UNKNOWN, aValue);
nsCSSValue(eCSSUnit_Initial).AppendToString(eCSSProperty_UNKNOWN, aValue,
nsCSSValue::eNormalized);
return;
}
if (inheritCount == totalCount) {
// Simplify serialization below by serializing inherit up-front.
nsCSSValue(eCSSUnit_Inherit).AppendToString(eCSSProperty_UNKNOWN, aValue);
nsCSSValue(eCSSUnit_Inherit).AppendToString(eCSSProperty_UNKNOWN, aValue,
nsCSSValue::eNormalized);
return;
}
if (unsetCount == totalCount) {
// Simplify serialization below by serializing unset up-front.
nsCSSValue(eCSSUnit_Unset).AppendToString(eCSSProperty_UNKNOWN, aValue);
nsCSSValue(eCSSUnit_Unset).AppendToString(eCSSProperty_UNKNOWN, aValue,
nsCSSValue::eNormalized);
return;
}
if (initialCount != 0 || inheritCount != 0 || unsetCount != 0) {
@ -271,7 +289,7 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
data->ValueFor(subprops[2]),
data->ValueFor(subprops[3])
};
AppendSidesShorthandToString(subprops, vals, aValue);
AppendSidesShorthandToString(subprops, vals, aValue, aSerialization);
break;
}
case eCSSProperty_border_radius:
@ -300,10 +318,10 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
}
}
AppendSidesShorthandToString(subprops, xVals, aValue);
AppendSidesShorthandToString(subprops, xVals, aValue, aSerialization);
if (needY) {
aValue.AppendLiteral(" / ");
AppendSidesShorthandToString(subprops, yVals, aValue);
AppendSidesShorthandToString(subprops, yVals, aValue, aSerialization);
}
break;
}
@ -312,7 +330,8 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
// 'border-image-source' (when it's none), it's probably not a
// good idea since it's likely to be confusing. It would also
// require adding the extra check that we serialize *something*.
AppendValueToString(eCSSProperty_border_image_source, aValue);
AppendValueToString(eCSSProperty_border_image_source, aValue,
aSerialization);
bool sliceDefault = data->HasDefaultBorderImageSlice();
bool widthDefault = data->HasDefaultBorderImageWidth();
@ -320,16 +339,19 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
if (!sliceDefault || !widthDefault || !outsetDefault) {
aValue.Append(PRUnichar(' '));
AppendValueToString(eCSSProperty_border_image_slice, aValue);
AppendValueToString(eCSSProperty_border_image_slice, aValue,
aSerialization);
if (!widthDefault || !outsetDefault) {
aValue.Append(NS_LITERAL_STRING(" /"));
if (!widthDefault) {
aValue.Append(PRUnichar(' '));
AppendValueToString(eCSSProperty_border_image_width, aValue);
AppendValueToString(eCSSProperty_border_image_width, aValue,
aSerialization);
}
if (!outsetDefault) {
aValue.Append(NS_LITERAL_STRING(" / "));
AppendValueToString(eCSSProperty_border_image_outset, aValue);
AppendValueToString(eCSSProperty_border_image_outset, aValue,
aSerialization);
}
}
}
@ -337,7 +359,8 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
bool repeatDefault = data->HasDefaultBorderImageRepeat();
if (!repeatDefault) {
aValue.Append(PRUnichar(' '));
AppendValueToString(eCSSProperty_border_image_repeat, aValue);
AppendValueToString(eCSSProperty_border_image_repeat, aValue,
aSerialization);
}
break;
}
@ -407,13 +430,13 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
bool isMozUseTextColor =
colorValue->GetUnit() == eCSSUnit_Enumerated &&
colorValue->GetIntValue() == NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR;
if (!AppendValueToString(subprops[0], aValue) ||
if (!AppendValueToString(subprops[0], aValue, aSerialization) ||
!(aValue.Append(PRUnichar(' ')),
AppendValueToString(subprops[1], aValue)) ||
AppendValueToString(subprops[1], aValue, aSerialization)) ||
// Don't output a third value when it's -moz-use-text-color.
!(isMozUseTextColor ||
(aValue.Append(PRUnichar(' ')),
AppendValueToString(subprops[2], aValue)))) {
AppendValueToString(subprops[2], aValue, aSerialization)))) {
aValue.Truncate();
}
break;
@ -442,7 +465,7 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
nsCSSProps::SubpropertyEntryFor(aProperty);
NS_ABORT_IF_FALSE(subprops[3] == eCSSProperty_UNKNOWN,
"not box property with physical vs. logical cascading");
AppendValueToString(subprops[0], aValue);
AppendValueToString(subprops[0], aValue, aSerialization);
break;
}
case eCSSProperty_background: {
@ -475,27 +498,32 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
data->ValueFor(eCSSProperty_background_size)->
GetPairListValue();
for (;;) {
image->mValue.AppendToString(eCSSProperty_background_image, aValue);
image->mValue.AppendToString(eCSSProperty_background_image, aValue,
aSerialization);
aValue.Append(PRUnichar(' '));
repeat->mXValue.AppendToString(eCSSProperty_background_repeat, aValue);
repeat->mXValue.AppendToString(eCSSProperty_background_repeat, aValue,
aSerialization);
if (repeat->mYValue.GetUnit() != eCSSUnit_Null) {
repeat->mYValue.AppendToString(eCSSProperty_background_repeat, aValue);
repeat->mYValue.AppendToString(eCSSProperty_background_repeat, aValue,
aSerialization);
}
aValue.Append(PRUnichar(' '));
attachment->mValue.AppendToString(eCSSProperty_background_attachment,
aValue);
aValue, aSerialization);
aValue.Append(PRUnichar(' '));
position->mValue.AppendToString(eCSSProperty_background_position,
aValue);
aValue, aSerialization);
if (size->mXValue.GetUnit() != eCSSUnit_Auto ||
size->mYValue.GetUnit() != eCSSUnit_Auto) {
aValue.Append(PRUnichar(' '));
aValue.Append(PRUnichar('/'));
aValue.Append(PRUnichar(' '));
size->mXValue.AppendToString(eCSSProperty_background_size, aValue);
size->mXValue.AppendToString(eCSSProperty_background_size, aValue,
aSerialization);
aValue.Append(PRUnichar(' '));
size->mYValue.AppendToString(eCSSProperty_background_size, aValue);
size->mYValue.AppendToString(eCSSProperty_background_size, aValue,
aSerialization);
}
NS_ABORT_IF_FALSE(clip->mValue.GetUnit() == eCSSUnit_Enumerated &&
@ -518,11 +546,13 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
NS_STYLE_BG_ORIGIN_CONTENT,
"bg-clip and bg-origin style constants must agree");
aValue.Append(PRUnichar(' '));
origin->mValue.AppendToString(eCSSProperty_background_origin, aValue);
origin->mValue.AppendToString(eCSSProperty_background_origin, aValue,
aSerialization);
if (clip->mValue != origin->mValue) {
aValue.Append(PRUnichar(' '));
clip->mValue.AppendToString(eCSSProperty_background_clip, aValue);
clip->mValue.AppendToString(eCSSProperty_background_clip, aValue,
aSerialization);
}
}
@ -552,7 +582,8 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
}
aValue.Append(PRUnichar(' '));
AppendValueToString(eCSSProperty_background_color, aValue);
AppendValueToString(eCSSProperty_background_color, aValue,
aSerialization);
break;
}
case eCSSProperty_font: {
@ -629,7 +660,8 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
// This can't be represented as a shorthand.
return;
}
systemFont->AppendToString(eCSSProperty__x_system_font, aValue);
systemFont->AppendToString(eCSSProperty__x_system_font, aValue,
aSerialization);
} else {
// properties reset by this shorthand property to their
// initial values but not represented in its syntax
@ -654,35 +686,44 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
if (style->GetUnit() != eCSSUnit_Enumerated ||
style->GetIntValue() != NS_FONT_STYLE_NORMAL) {
style->AppendToString(eCSSProperty_font_style, aValue);
style->AppendToString(eCSSProperty_font_style, aValue,
aSerialization);
aValue.Append(PRUnichar(' '));
}
if (variant->GetUnit() != eCSSUnit_Enumerated ||
variant->GetIntValue() != NS_FONT_VARIANT_NORMAL) {
variant->AppendToString(eCSSProperty_font_variant, aValue);
variant->AppendToString(eCSSProperty_font_variant, aValue,
aSerialization);
aValue.Append(PRUnichar(' '));
}
if (weight->GetUnit() != eCSSUnit_Enumerated ||
weight->GetIntValue() != NS_FONT_WEIGHT_NORMAL) {
weight->AppendToString(eCSSProperty_font_weight, aValue);
weight->AppendToString(eCSSProperty_font_weight, aValue,
aSerialization);
aValue.Append(PRUnichar(' '));
}
size->AppendToString(eCSSProperty_font_size, aValue);
size->AppendToString(eCSSProperty_font_size, aValue, aSerialization);
if (lh->GetUnit() != eCSSUnit_Normal) {
aValue.Append(PRUnichar('/'));
lh->AppendToString(eCSSProperty_line_height, aValue);
lh->AppendToString(eCSSProperty_line_height, aValue, aSerialization);
}
aValue.Append(PRUnichar(' '));
family->AppendToString(eCSSProperty_font_family, aValue);
family->AppendToString(eCSSProperty_font_family, aValue,
aSerialization);
}
break;
}
case eCSSProperty_list_style:
if (AppendValueToString(eCSSProperty_list_style_type, aValue))
if (AppendValueToString(eCSSProperty_list_style_type, aValue,
aSerialization)) {
aValue.Append(PRUnichar(' '));
if (AppendValueToString(eCSSProperty_list_style_position, aValue))
}
if (AppendValueToString(eCSSProperty_list_style_position, aValue,
aSerialization)) {
aValue.Append(PRUnichar(' '));
AppendValueToString(eCSSProperty_list_style_image, aValue);
}
AppendValueToString(eCSSProperty_list_style_image, aValue,
aSerialization);
break;
case eCSSProperty_overflow: {
const nsCSSValue &xValue =
@ -690,7 +731,7 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
const nsCSSValue &yValue =
*data->ValueFor(eCSSProperty_overflow_y);
if (xValue == yValue)
xValue.AppendToString(eCSSProperty_overflow_x, aValue);
xValue.AppendToString(eCSSProperty_overflow_x, aValue, aSerialization);
break;
}
case eCSSProperty_text_decoration: {
@ -712,7 +753,8 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
return;
}
AppendValueToString(eCSSProperty_text_decoration_line, aValue);
AppendValueToString(eCSSProperty_text_decoration_line, aValue,
aSerialization);
break;
}
case eCSSProperty_transition: {
@ -747,14 +789,17 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
// If any of the other three lists has more than one element,
// we can't use the shorthand.
if (!dur->mNext && !tim->mNext && !del->mNext) {
transProp->AppendToString(eCSSProperty_transition_property, aValue);
transProp->AppendToString(eCSSProperty_transition_property, aValue,
aSerialization);
aValue.Append(PRUnichar(' '));
dur->mValue.AppendToString(eCSSProperty_transition_duration,aValue);
dur->mValue.AppendToString(eCSSProperty_transition_duration,aValue,
aSerialization);
aValue.Append(PRUnichar(' '));
tim->mValue.AppendToString(eCSSProperty_transition_timing_function,
aValue);
aValue, aSerialization);
aValue.Append(PRUnichar(' '));
del->mValue.AppendToString(eCSSProperty_transition_delay, aValue);
del->mValue.AppendToString(eCSSProperty_transition_delay, aValue,
aSerialization);
aValue.Append(PRUnichar(' '));
} else {
aValue.Truncate();
@ -767,16 +812,16 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
const nsCSSValueList* pro = transProp->GetListValue();
for (;;) {
pro->mValue.AppendToString(eCSSProperty_transition_property,
aValue);
aValue, aSerialization);
aValue.Append(PRUnichar(' '));
dur->mValue.AppendToString(eCSSProperty_transition_duration,
aValue);
aValue, aSerialization);
aValue.Append(PRUnichar(' '));
tim->mValue.AppendToString(eCSSProperty_transition_timing_function,
aValue);
aValue, aSerialization);
aValue.Append(PRUnichar(' '));
del->mValue.AppendToString(eCSSProperty_transition_delay,
aValue);
aValue, aSerialization);
pro = pro->mNext;
dur = dur->mNext;
tim = tim->mNext;
@ -819,7 +864,7 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
"animation-name must be last");
bool done = false;
for (uint32_t i = 0;;) {
lists[i]->mValue.AppendToString(subprops[i], aValue);
lists[i]->mValue.AppendToString(subprops[i], aValue, aSerialization);
lists[i] = lists[i]->mNext;
if (!lists[i]) {
done = true;
@ -851,16 +896,16 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
const nsCSSValue &startValue =
*data->ValueFor(eCSSProperty_marker_start);
if (endValue == midValue && midValue == startValue)
AppendValueToString(eCSSProperty_marker_end, aValue);
AppendValueToString(eCSSProperty_marker_end, aValue, aSerialization);
break;
}
case eCSSProperty__moz_columns: {
// Two values, column-count and column-width, separated by a space.
const nsCSSProperty* subprops =
nsCSSProps::SubpropertyEntryFor(aProperty);
AppendValueToString(subprops[0], aValue);
AppendValueToString(subprops[0], aValue, aSerialization);
aValue.Append(PRUnichar(' '));
AppendValueToString(subprops[1], aValue);
AppendValueToString(subprops[1], aValue, aSerialization);
break;
}
case eCSSProperty_flex: {
@ -868,11 +913,11 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
const nsCSSProperty* subprops =
nsCSSProps::SubpropertyEntryFor(aProperty);
AppendValueToString(subprops[0], aValue);
AppendValueToString(subprops[0], aValue, aSerialization);
aValue.Append(PRUnichar(' '));
AppendValueToString(subprops[1], aValue);
AppendValueToString(subprops[1], aValue, aSerialization);
aValue.Append(PRUnichar(' '));
AppendValueToString(subprops[2], aValue);
AppendValueToString(subprops[2], aValue, aSerialization);
break;
}
case eCSSProperty_flex_flow: {
@ -882,9 +927,9 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
NS_ABORT_IF_FALSE(subprops[2] == eCSSProperty_UNKNOWN,
"must have exactly two subproperties");
AppendValueToString(subprops[0], aValue);
AppendValueToString(subprops[0], aValue, aSerialization);
aValue.Append(PRUnichar(' '));
AppendValueToString(subprops[1], aValue);
AppendValueToString(subprops[1], aValue, aSerialization);
break;
}
case eCSSProperty__moz_transform: {
@ -893,7 +938,7 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
nsCSSProps::SubpropertyEntryFor(aProperty);
NS_ABORT_IF_FALSE(subprops[1] == eCSSProperty_UNKNOWN,
"must have exactly one subproperty");
AppendValueToString(subprops[0], aValue);
AppendValueToString(subprops[0], aValue, aSerialization);
break;
}
case eCSSProperty_all:
@ -961,7 +1006,7 @@ Declaration::AppendPropertyAndValueToString(nsCSSProperty aProperty,
AppendASCIItoUTF16(nsCSSProps::GetStringValue(aProperty), aResult);
aResult.AppendLiteral(": ");
if (aValue.IsEmpty())
AppendValueToString(aProperty, aResult);
AppendValueToString(aProperty, aResult, nsCSSValue::eNormalized);
else
aResult.Append(aValue);
if (GetValueIsImportant(aProperty)) {
@ -1096,7 +1141,8 @@ Declaration::ToString(nsAString& aString) const
// Output the shorthand font declaration that we will
// partially override later. But don't add it to
// |shorthandsUsed|, since we will have to override it.
systemFont->AppendToString(eCSSProperty__x_system_font, value);
systemFont->AppendToString(eCSSProperty__x_system_font, value,
nsCSSValue::eNormalized);
AppendPropertyAndValueToString(eCSSProperty_font, value, aString);
value.Truncate();
didSystemFont = true;

View File

@ -63,6 +63,7 @@ public:
bool HasProperty(nsCSSProperty aProperty) const;
void GetValue(nsCSSProperty aProperty, nsAString& aValue) const;
void GetAuthoredValue(nsCSSProperty aProperty, nsAString& aValue) const;
bool HasImportantData() const {
return mImportantData || mImportantVariables;
@ -278,9 +279,14 @@ private:
Declaration& operator=(const Declaration& aCopy) MOZ_DELETE;
bool operator==(const Declaration& aCopy) const MOZ_DELETE;
void GetValue(nsCSSProperty aProperty, nsAString& aValue,
nsCSSValue::Serialization aValueSerialization) const;
static void AppendImportanceToString(bool aIsImportant, nsAString& aString);
// return whether there was a value in |aValue| (i.e., it had a non-null unit)
bool AppendValueToString(nsCSSProperty aProperty, nsAString& aResult) const;
bool AppendValueToString(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aValueSerialization) const;
// Helper for ToString with strange semantics regarding aValue.
void AppendPropertyAndValueToString(nsCSSProperty aProperty,
nsAutoString& aValue,

View File

@ -738,14 +738,16 @@ protected:
int32_t ParseChoice(nsCSSValue aValues[],
const nsCSSProperty aPropIDs[], int32_t aNumIDs);
bool ParseColor(nsCSSValue& aValue);
bool ParseColorComponent(uint8_t& aComponent,
int32_t& aType, char aStop);
bool ParseNumberColorComponent(uint8_t& aComponent, char aStop);
bool ParsePercentageColorComponent(float& aComponent, char aStop);
// ParseHSLColor parses everything starting with the opening '('
// up through and including the aStop char.
bool ParseHSLColor(nscolor& aColor, char aStop);
bool ParseHSLColor(float& aHue, float& aSaturation, float& aLightness,
char aStop);
// ParseColorOpacity will enforce that the color ends with a ')'
// after the opacity
bool ParseColorOpacity(uint8_t& aOpacity);
bool ParseColorOpacity(float& aOpacity);
bool ParseEnum(nsCSSValue& aValue, const int32_t aKeywordTable[]);
bool ParseVariant(nsCSSValue& aValue,
int32_t aVariantMask,
@ -5271,12 +5273,6 @@ CSSParserImpl::ParseDeclarationBlock(uint32_t aFlags, nsCSSContextType aContext)
return declaration;
}
// The types to pass to ParseColorComponent. These correspond to the
// various datatypes that can go within rgb().
#define COLOR_TYPE_UNKNOWN 0
#define COLOR_TYPE_INTEGERS 1
#define COLOR_TYPE_PERCENTAGES 2
bool
CSSParserImpl::ParseColor(nsCSSValue& aValue)
{
@ -5292,7 +5288,12 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
case eCSSToken_Hash:
// #xxyyzz
if (NS_HexToRGB(tk->mIdent, &rgba)) {
aValue.SetColorValue(rgba);
MOZ_ASSERT(tk->mIdent.Length() == 3 || tk->mIdent.Length() == 6,
"unexpected hex color length");
nsCSSUnit unit = tk->mIdent.Length() == 3 ?
eCSSUnit_ShortHexColor :
eCSSUnit_HexColor;
aValue.SetIntegerColorValue(rgba, unit);
return true;
}
break;
@ -5316,27 +5317,54 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
case eCSSToken_Function:
if (mToken.mIdent.LowerCaseEqualsLiteral("rgb")) {
// rgb ( component , component , component )
uint8_t r, g, b;
int32_t type = COLOR_TYPE_UNKNOWN;
if (ParseColorComponent(r, type, ',') &&
ParseColorComponent(g, type, ',') &&
ParseColorComponent(b, type, ')')) {
aValue.SetColorValue(NS_RGB(r,g,b));
return true;
if (GetToken(true)) {
UngetToken();
}
if (mToken.mType == eCSSToken_Number) {
uint8_t r, g, b;
if (ParseNumberColorComponent(r, ',') &&
ParseNumberColorComponent(g, ',') &&
ParseNumberColorComponent(b, ')')) {
aValue.SetIntegerColorValue(NS_RGB(r, g, b), eCSSUnit_RGBColor);
return true;
}
} else {
float r, g, b;
if (ParsePercentageColorComponent(r, ',') &&
ParsePercentageColorComponent(g, ',') &&
ParsePercentageColorComponent(b, ')')) {
aValue.SetFloatColorValue(r, g, b, 1.0f,
eCSSUnit_PercentageRGBColor);
return true;
}
}
SkipUntil(')');
return false;
}
else if (mToken.mIdent.LowerCaseEqualsLiteral("rgba")) {
// rgba ( component , component , component , opacity )
uint8_t r, g, b, a;
int32_t type = COLOR_TYPE_UNKNOWN;
if (ParseColorComponent(r, type, ',') &&
ParseColorComponent(g, type, ',') &&
ParseColorComponent(b, type, ',') &&
ParseColorOpacity(a)) {
aValue.SetColorValue(NS_RGBA(r, g, b, a));
return true;
if (GetToken(true)) {
UngetToken();
}
if (mToken.mType == eCSSToken_Number) {
uint8_t r, g, b, a;
if (ParseNumberColorComponent(r, ',') &&
ParseNumberColorComponent(g, ',') &&
ParseNumberColorComponent(b, ',') &&
ParseColorOpacity(a)) {
aValue.SetIntegerColorValue(NS_RGBA(r, g, b, a),
eCSSUnit_RGBAColor);
return true;
}
} else {
float r, g, b, a;
if (ParsePercentageColorComponent(r, ',') &&
ParsePercentageColorComponent(g, ',') &&
ParsePercentageColorComponent(b, ',') &&
ParseColorOpacity(a)) {
aValue.SetFloatColorValue(r, g, b, a, eCSSUnit_PercentageRGBAColor);
return true;
}
}
SkipUntil(')');
return false;
@ -5344,8 +5372,9 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
else if (mToken.mIdent.LowerCaseEqualsLiteral("hsl")) {
// hsl ( hue , saturation , lightness )
// "hue" is a number, "saturation" and "lightness" are percentages.
if (ParseHSLColor(rgba, ')')) {
aValue.SetColorValue(rgba);
float h, s, l;
if (ParseHSLColor(h, s, l, ')')) {
aValue.SetFloatColorValue(h, s, l, 1.0f, eCSSUnit_HSLColor);
return true;
}
SkipUntil(')');
@ -5355,11 +5384,10 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
// hsla ( hue , saturation , lightness , opacity )
// "hue" is a number, "saturation" and "lightness" are percentages,
// "opacity" is a number.
uint8_t a;
if (ParseHSLColor(rgba, ',') &&
float h, s, l, a;
if (ParseHSLColor(h, s, l, ',') &&
ParseColorOpacity(a)) {
aValue.SetColorValue(NS_RGBA(NS_GET_R(rgba), NS_GET_G(rgba),
NS_GET_B(rgba), a));
aValue.SetFloatColorValue(h, s, l, a, eCSSUnit_HSLAColor);
return true;
}
SkipUntil(')');
@ -5414,7 +5442,7 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
break;
}
if (NS_HexToRGB(str, &rgba)) {
aValue.SetColorValue(rgba);
aValue.SetIntegerColorValue(rgba, eCSSUnit_HexColor);
return true;
}
}
@ -5425,66 +5453,25 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
return false;
}
// aType will be set if we have already parsed other color components
// in this color spec
bool
CSSParserImpl::ParseColorComponent(uint8_t& aComponent,
int32_t& aType,
char aStop)
CSSParserImpl::ParseNumberColorComponent(uint8_t& aComponent, char aStop)
{
if (!GetToken(true)) {
REPORT_UNEXPECTED_EOF(PEColorComponentEOF);
return false;
}
float value;
nsCSSToken* tk = &mToken;
switch (tk->mType) {
case eCSSToken_Number:
switch (aType) {
case COLOR_TYPE_UNKNOWN:
aType = COLOR_TYPE_INTEGERS;
break;
case COLOR_TYPE_INTEGERS:
break;
case COLOR_TYPE_PERCENTAGES:
REPORT_UNEXPECTED_TOKEN(PEExpectedPercent);
UngetToken();
return false;
default:
NS_NOTREACHED("Someone forgot to add the new color component type in here");
}
if (!mToken.mIntegerValid) {
REPORT_UNEXPECTED_TOKEN(PEExpectedInt);
UngetToken();
return false;
}
value = tk->mNumber;
break;
case eCSSToken_Percentage:
switch (aType) {
case COLOR_TYPE_UNKNOWN:
aType = COLOR_TYPE_PERCENTAGES;
break;
case COLOR_TYPE_INTEGERS:
REPORT_UNEXPECTED_TOKEN(PEExpectedInt);
UngetToken();
return false;
case COLOR_TYPE_PERCENTAGES:
break;
default:
NS_NOTREACHED("Someone forgot to add the new color component type in here");
}
value = tk->mNumber * 255.0f;
break;
default:
REPORT_UNEXPECTED_TOKEN(PEColorBadRGBContents);
if (mToken.mType != eCSSToken_Number || !mToken.mIntegerValid) {
REPORT_UNEXPECTED_TOKEN(PEExpectedInt);
UngetToken();
return false;
}
float value = mToken.mNumber;
if (value < 0.0f) value = 0.0f;
if (value > 255.0f) value = 255.0f;
if (ExpectSymbol(aStop, true)) {
if (value < 0.0f) value = 0.0f;
if (value > 255.0f) value = 255.0f;
aComponent = NSToIntRound(value);
return true;
}
@ -5492,9 +5479,35 @@ CSSParserImpl::ParseColorComponent(uint8_t& aComponent,
return false;
}
bool
CSSParserImpl::ParsePercentageColorComponent(float& aComponent, char aStop)
{
if (!GetToken(true)) {
REPORT_UNEXPECTED_EOF(PEColorComponentEOF);
return false;
}
if (mToken.mType != eCSSToken_Percentage) {
REPORT_UNEXPECTED_TOKEN(PEExpectedPercent);
UngetToken();
return false;
}
float value = mToken.mNumber;
if (value < 0.0f) value = 0.0f;
if (value > 1.0f) value = 1.0f;
if (ExpectSymbol(aStop, true)) {
aComponent = value;
return true;
}
REPORT_UNEXPECTED_TOKEN_CHAR(PEColorComponentBadTerm, aStop);
return false;
}
bool
CSSParserImpl::ParseHSLColor(nscolor& aColor,
CSSParserImpl::ParseHSLColor(float& aHue, float& aSaturation, float& aLightness,
char aStop)
{
float h, s, l;
@ -5553,7 +5566,9 @@ CSSParserImpl::ParseHSLColor(nscolor& aColor,
if (l > 1.0f) l = 1.0f;
if (ExpectSymbol(aStop, true)) {
aColor = NS_HSL2RGB(h, s, l);
aHue = h;
aSaturation = s;
aLightness = l;
return true;
}
@ -5564,6 +5579,24 @@ CSSParserImpl::ParseHSLColor(nscolor& aColor,
bool
CSSParserImpl::ParseColorOpacity(uint8_t& aOpacity)
{
float floatOpacity;
if (!ParseColorOpacity(floatOpacity)) {
return false;
}
uint8_t value = nsStyleUtil::FloatToColorComponent(floatOpacity);
// Need to compare to something slightly larger
// than 0.5 due to floating point inaccuracies.
NS_ASSERTION(fabs(255.0f*mToken.mNumber - value) <= 0.51f,
"FloatToColorComponent did something weird");
aOpacity = value;
return true;
}
bool
CSSParserImpl::ParseColorOpacity(float& aOpacity)
{
if (!GetToken(true)) {
REPORT_UNEXPECTED_EOF(PEColorOpacityEOF);
@ -5576,25 +5609,18 @@ CSSParserImpl::ParseColorOpacity(uint8_t& aOpacity)
return false;
}
if (!ExpectSymbol(')', true)) {
REPORT_UNEXPECTED_TOKEN(PEExpectedCloseParen);
return false;
}
if (mToken.mNumber < 0.0f) {
mToken.mNumber = 0.0f;
} else if (mToken.mNumber > 1.0f) {
mToken.mNumber = 1.0f;
}
uint8_t value = nsStyleUtil::FloatToColorComponent(mToken.mNumber);
// Need to compare to something slightly larger
// than 0.5 due to floating point inaccuracies.
NS_ASSERTION(fabs(255.0f*mToken.mNumber - value) <= 0.51f,
"FloatToColorComponent did something weird");
if (!ExpectSymbol(')', true)) {
REPORT_UNEXPECTED_TOKEN(PEExpectedCloseParen);
return false;
}
aOpacity = value;
aOpacity = mToken.mNumber;
return true;
}
@ -8114,7 +8140,7 @@ CSSParserImpl::ParseBackground()
// If we get to this point without seeing a color, provide a default.
if (color.GetUnit() == eCSSUnit_Null) {
color.SetColorValue(NS_RGBA(0,0,0,0));
color.SetIntegerColorValue(NS_RGBA(0,0,0,0), eCSSUnit_RGBAColor);
}
AppendValue(eCSSProperty_background_image, image);
@ -12069,8 +12095,8 @@ CSSParserImpl::ParseShadowItem(nsCSSValue& aValue, bool aIsBoxShadow)
} else {
// Must be a color (as string or color value)
NS_ASSERTION(xOrColor.GetUnit() == eCSSUnit_Ident ||
xOrColor.GetUnit() == eCSSUnit_Color ||
xOrColor.GetUnit() == eCSSUnit_EnumColor,
xOrColor.GetUnit() == eCSSUnit_EnumColor ||
xOrColor.IsNumericColorUnit(),
"Must be a color value");
val->Item(IndexColor) = xOrColor;
haveColor = true;

View File

@ -20,7 +20,7 @@
#define VARIANT_KEYWORD 0x000001 // K
#define VARIANT_LENGTH 0x000002 // L
#define VARIANT_PERCENT 0x000004 // P
#define VARIANT_COLOR 0x000008 // C eCSSUnit_Color, eCSSUnit_Ident (e.g. "red")
#define VARIANT_COLOR 0x000008 // C eCSSUnit_*Color, eCSSUnit_Ident (e.g. "red")
#define VARIANT_URL 0x000010 // U
#define VARIANT_NUMBER 0x000020 // N
#define VARIANT_INTEGER 0x000040 // I

View File

@ -1512,15 +1512,18 @@ nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID,
}
case eCSSFontDesc_Style:
val.AppendToString(eCSSProperty_font_style, aResult);
val.AppendToString(eCSSProperty_font_style, aResult,
nsCSSValue::eNormalized);
return NS_OK;
case eCSSFontDesc_Weight:
val.AppendToString(eCSSProperty_font_weight, aResult);
val.AppendToString(eCSSProperty_font_weight, aResult,
nsCSSValue::eNormalized);
return NS_OK;
case eCSSFontDesc_Stretch:
val.AppendToString(eCSSProperty_font_stretch, aResult);
val.AppendToString(eCSSProperty_font_stretch, aResult,
nsCSSValue::eNormalized);
return NS_OK;
case eCSSFontDesc_FontFeatureSettings:
@ -1528,7 +1531,8 @@ nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID,
return NS_OK;
case eCSSFontDesc_FontLanguageOverride:
val.AppendToString(eCSSProperty_font_language_override, aResult);
val.AppendToString(eCSSProperty_font_language_override, aResult,
nsCSSValue::eNormalized);
return NS_OK;
case eCSSFontDesc_Src:
@ -1588,6 +1592,15 @@ nsCSSFontFaceStyleDecl::GetPropertyValue(const nsAString & propertyName,
return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
}
NS_IMETHODIMP
nsCSSFontFaceStyleDecl::GetAuthoredPropertyValue(const nsAString& propertyName,
nsAString& aResult)
{
// We don't return any authored property values different from
// GetPropertyValue, currently.
return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
}
// nsIDOMCSSValue getPropertyCSSValue (in DOMString propertyName);
already_AddRefed<dom::CSSValue>
nsCSSFontFaceStyleDecl::GetPropertyCSSValue(const nsAString & propertyName,

View File

@ -381,7 +381,8 @@ nsMediaQuery::AppendToString(nsAString& aString) const
NS_ASSERTION(expr.mValue.IsLengthUnit(), "bad unit");
// Use 'width' as a property that takes length values
// written in the normal way.
expr.mValue.AppendToString(eCSSProperty_width, aString);
expr.mValue.AppendToString(eCSSProperty_width, aString,
nsCSSValue::eNormalized);
break;
case nsMediaFeature::eInteger:
case nsMediaFeature::eBoolInteger:
@ -389,7 +390,8 @@ nsMediaQuery::AppendToString(nsAString& aString) const
"bad unit");
// Use 'z-index' as a property that takes integer values
// written without anything extra.
expr.mValue.AppendToString(eCSSProperty_z_index, aString);
expr.mValue.AppendToString(eCSSProperty_z_index, aString,
nsCSSValue::eNormalized);
break;
case nsMediaFeature::eFloat:
{
@ -397,7 +399,8 @@ nsMediaQuery::AppendToString(nsAString& aString) const
"bad unit");
// Use 'line-height' as a property that takes float values
// written in the normal way.
expr.mValue.AppendToString(eCSSProperty_line_height, aString);
expr.mValue.AppendToString(eCSSProperty_line_height, aString,
nsCSSValue::eNormalized);
}
break;
case nsMediaFeature::eIntRatio:
@ -410,9 +413,11 @@ nsMediaQuery::AppendToString(nsAString& aString) const
"bad unit");
NS_ASSERTION(array->Item(1).GetUnit() == eCSSUnit_Integer,
"bad unit");
array->Item(0).AppendToString(eCSSProperty_z_index, aString);
array->Item(0).AppendToString(eCSSProperty_z_index, aString,
nsCSSValue::eNormalized);
aString.AppendLiteral("/");
array->Item(1).AppendToString(eCSSProperty_z_index, aString);
array->Item(1).AppendToString(eCSSProperty_z_index, aString,
nsCSSValue::eNormalized);
}
break;
case nsMediaFeature::eResolution:

View File

@ -121,9 +121,13 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
else if (eCSSUnit_Integer <= mUnit && mUnit <= eCSSUnit_EnumColor) {
mValue.mInt = aCopy.mValue.mInt;
}
else if (eCSSUnit_Color == mUnit) {
else if (IsIntegerColorUnit()) {
mValue.mColor = aCopy.mValue.mColor;
}
else if (IsFloatColorUnit()) {
mValue.mFloatColor = aCopy.mValue.mFloatColor;
mValue.mFloatColor->AddRef();
}
else if (UnitHasArrayValue()) {
mValue.mArray = aCopy.mValue.mArray;
mValue.mArray->AddRef();
@ -207,9 +211,12 @@ bool nsCSSValue::operator==(const nsCSSValue& aOther) const
else if ((eCSSUnit_Integer <= mUnit) && (mUnit <= eCSSUnit_EnumColor)) {
return mValue.mInt == aOther.mValue.mInt;
}
else if (eCSSUnit_Color == mUnit) {
else if (IsIntegerColorUnit()) {
return mValue.mColor == aOther.mValue.mColor;
}
else if (IsFloatColorUnit()) {
return *mValue.mFloatColor == *aOther.mValue.mFloatColor;
}
else if (UnitHasArrayValue()) {
return *mValue.mArray == *aOther.mValue.mArray;
}
@ -305,6 +312,8 @@ void nsCSSValue::DoReset()
{
if (UnitHasStringValue()) {
mValue.mString->Release();
} else if (IsFloatColorUnit()) {
mValue.mFloatColor->Release();
} else if (UnitHasArrayValue()) {
mValue.mArray->Release();
} else if (eCSSUnit_URL == mUnit) {
@ -375,12 +384,32 @@ void nsCSSValue::SetStringValue(const nsString& aValue,
}
void nsCSSValue::SetColorValue(nscolor aValue)
{
SetIntegerColorValue(aValue, eCSSUnit_RGBAColor);
}
void nsCSSValue::SetIntegerColorValue(nscolor aValue, nsCSSUnit aUnit)
{
Reset();
mUnit = eCSSUnit_Color;
mUnit = aUnit;
NS_ABORT_IF_FALSE(IsIntegerColorUnit(), "bad unit");
mValue.mColor = aValue;
}
void nsCSSValue::SetFloatColorValue(float aComponent1,
float aComponent2,
float aComponent3,
float aAlpha,
nsCSSUnit aUnit)
{
Reset();
mUnit = aUnit;
NS_ABORT_IF_FALSE(IsFloatColorUnit(), "bad unit");
mValue.mFloatColor =
new nsCSSValueFloatColor(aComponent1, aComponent2, aComponent3, aAlpha);
mValue.mFloatColor->AddRef();
}
void nsCSSValue::SetArrayValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
{
Reset();
@ -633,6 +662,15 @@ void nsCSSValue::StartImageLoad(nsIDocument* aDocument) const
}
}
nscolor nsCSSValue::GetColorValue() const
{
NS_ABORT_IF_FALSE(IsNumericColorUnit(), "not a color value");
if (IsFloatColorUnit()) {
return mValue.mFloatColor->GetColorValue(mUnit);
}
return mValue.mColor;
}
bool nsCSSValue::IsNonTransparentColor() const
{
// We have the value in the form it was specified in at this point, so we
@ -640,7 +678,8 @@ bool nsCSSValue::IsNonTransparentColor() const
// rgba notation.
nsDependentString buf;
return
(mUnit == eCSSUnit_Color && NS_GET_A(GetColorValue()) > 0) ||
(IsIntegerColorUnit() && NS_GET_A(GetColorValue()) > 0) ||
(IsFloatColorUnit() && mValue.mFloatColor->IsNonTransparentColor()) ||
(mUnit == eCSSUnit_Ident &&
!nsGkAtoms::transparent->Equals(GetStringValue(buf))) ||
(mUnit == eCSSUnit_EnumColor);
@ -699,9 +738,11 @@ nsCSSValue::BufferFromString(const nsString& aValue)
namespace {
struct CSSValueSerializeCalcOps {
CSSValueSerializeCalcOps(nsCSSProperty aProperty, nsAString& aResult)
CSSValueSerializeCalcOps(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aSerialization)
: mProperty(aProperty),
mResult(aResult)
mResult(aResult),
mValueSerialization(aSerialization)
{
}
@ -721,24 +762,26 @@ struct CSSValueSerializeCalcOps {
{
NS_ABORT_IF_FALSE(aValue.GetUnit() == eCSSUnit_Percent ||
aValue.IsLengthUnit(), "unexpected unit");
aValue.AppendToString(mProperty, mResult);
aValue.AppendToString(mProperty, mResult, mValueSerialization);
}
void AppendNumber(const input_type& aValue)
{
NS_ABORT_IF_FALSE(aValue.GetUnit() == eCSSUnit_Number, "unexpected unit");
aValue.AppendToString(mProperty, mResult);
aValue.AppendToString(mProperty, mResult, mValueSerialization);
}
private:
nsCSSProperty mProperty;
nsAString &mResult;
nsCSSValue::Serialization mValueSerialization;
};
} // anonymous namespace
void
nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
Serialization aSerialization) const
{
// eCSSProperty_UNKNOWN gets used for some recursive calls below.
NS_ABORT_IF_FALSE((0 <= aProperty &&
@ -805,7 +848,7 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
i == array->Count() - 1)
? eCSSProperty_list_style_type : aProperty;
if (array->Item(i).GetUnit() != eCSSUnit_Null) {
array->Item(i).AppendToString(prop, aResult);
array->Item(i).AppendToString(prop, aResult, aSerialization);
mark = true;
}
}
@ -863,7 +906,8 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
/* Now, step through the function contents, writing each of them as we go. */
for (size_t index = 1; index < array->Count(); ++index) {
array->Item(index).AppendToString(aProperty, aResult);
array->Item(index).AppendToString(aProperty, aResult,
aSerialization);
/* If we're not at the final element, append a comma. */
if (index + 1 != array->Count())
@ -875,7 +919,7 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
}
else if (IsCalcUnit()) {
NS_ABORT_IF_FALSE(GetUnit() == eCSSUnit_Calc, "unexpected unit");
CSSValueSerializeCalcOps ops(aProperty, aResult);
CSSValueSerializeCalcOps ops(aProperty, aResult, aSerialization);
css::SerializeCalc(*this, ops);
}
else if (eCSSUnit_Integer == unit) {
@ -979,32 +1023,56 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
NS_ABORT_IF_FALSE(false, "bad color value");
}
}
else if (eCSSUnit_Color == unit) {
nscolor color = GetColorValue();
if (color == NS_RGBA(0, 0, 0, 0)) {
// Use the strictest match for 'transparent' so we do correct
// round-tripping of all other rgba() values.
aResult.AppendLiteral("transparent");
} else {
uint8_t a = NS_GET_A(color);
if (a < 255) {
aResult.AppendLiteral("rgba(");
else if (IsNumericColorUnit(unit)) {
if (aSerialization == eNormalized ||
unit == eCSSUnit_RGBColor ||
unit == eCSSUnit_RGBAColor) {
nscolor color = GetColorValue();
if (aSerialization == eNormalized &&
color == NS_RGBA(0, 0, 0, 0)) {
// Use the strictest match for 'transparent' so we do correct
// round-tripping of all other rgba() values.
aResult.AppendLiteral("transparent");
} else {
aResult.AppendLiteral("rgb(");
}
uint8_t a = NS_GET_A(color);
bool showAlpha =
(aSerialization == eNormalized && a < 255) ||
(aSerialization == eAuthorSpecified &&
unit == eCSSUnit_RGBAColor);
if (showAlpha) {
aResult.AppendLiteral("rgba(");
} else {
aResult.AppendLiteral("rgb(");
}
NS_NAMED_LITERAL_STRING(comma, ", ");
NS_NAMED_LITERAL_STRING(comma, ", ");
aResult.AppendInt(NS_GET_R(color), 10);
aResult.Append(comma);
aResult.AppendInt(NS_GET_G(color), 10);
aResult.Append(comma);
aResult.AppendInt(NS_GET_B(color), 10);
if (a < 255) {
aResult.AppendInt(NS_GET_R(color), 10);
aResult.Append(comma);
aResult.AppendFloat(nsStyleUtil::ColorComponentToFloat(a));
aResult.AppendInt(NS_GET_G(color), 10);
aResult.Append(comma);
aResult.AppendInt(NS_GET_B(color), 10);
if (showAlpha) {
aResult.Append(comma);
aResult.AppendFloat(nsStyleUtil::ColorComponentToFloat(a));
}
aResult.Append(PRUnichar(')'));
}
aResult.Append(PRUnichar(')'));
} else if (eCSSUnit_HexColor == unit) {
nscolor color = GetColorValue();
aResult.Append('#');
aResult.AppendPrintf("%02x", NS_GET_R(color));
aResult.AppendPrintf("%02x", NS_GET_G(color));
aResult.AppendPrintf("%02x", NS_GET_B(color));
} else if (eCSSUnit_ShortHexColor == unit) {
nscolor color = GetColorValue();
aResult.Append('#');
aResult.AppendInt(NS_GET_R(color) / 0x11, 16);
aResult.AppendInt(NS_GET_G(color) / 0x11, 16);
aResult.AppendInt(NS_GET_B(color) / 0x11, 16);
} else {
MOZ_ASSERT(IsFloatColorUnit());
mValue.mFloatColor->AppendToString(unit, aResult);
}
}
else if (eCSSUnit_URL == unit || eCSSUnit_Image == unit) {
@ -1073,10 +1141,12 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
} else {
NS_ABORT_IF_FALSE(gradient->GetRadiusX().GetUnit() != eCSSUnit_None,
"bad unit for radial gradient explicit size");
gradient->GetRadiusX().AppendToString(aProperty, aResult);
gradient->GetRadiusX().AppendToString(aProperty, aResult,
aSerialization);
if (gradient->GetRadiusY().GetUnit() != eCSSUnit_None) {
aResult.AppendLiteral(" ");
gradient->GetRadiusY().AppendToString(aProperty, aResult);
gradient->GetRadiusY().AppendToString(aProperty, aResult,
aSerialization);
}
needSep = true;
}
@ -1092,16 +1162,16 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
if (!(gradient->mBgPos.mXValue.GetIntValue() & NS_STYLE_BG_POSITION_CENTER)) {
aResult.AppendLiteral(" ");
gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position,
aResult);
aResult, aSerialization);
}
if (!(gradient->mBgPos.mYValue.GetIntValue() & NS_STYLE_BG_POSITION_CENTER)) {
aResult.AppendLiteral(" ");
gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position,
aResult);
aResult, aSerialization);
}
needSep = true;
} else if (gradient->mAngle.GetUnit() != eCSSUnit_None) {
gradient->mAngle.AppendToString(aProperty, aResult);
gradient->mAngle.AppendToString(aProperty, aResult, aSerialization);
needSep = true;
}
} else if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None ||
@ -1115,18 +1185,18 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
}
if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None) {
gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position,
aResult);
aResult, aSerialization);
aResult.AppendLiteral(" ");
}
if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None) {
gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position,
aResult);
aResult, aSerialization);
aResult.AppendLiteral(" ");
}
if (gradient->mAngle.GetUnit() != eCSSUnit_None) {
NS_ABORT_IF_FALSE(gradient->mIsLegacySyntax,
"angle is allowed only for legacy syntax");
gradient->mAngle.AppendToString(aProperty, aResult);
gradient->mAngle.AppendToString(aProperty, aResult, aSerialization);
}
needSep = true;
}
@ -1167,10 +1237,12 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
}
for (uint32_t i = 0 ;;) {
gradient->mStops[i].mColor.AppendToString(aProperty, aResult);
gradient->mStops[i].mColor.AppendToString(aProperty, aResult,
aSerialization);
if (gradient->mStops[i].mLocation.GetUnit() != eCSSUnit_None) {
aResult.AppendLiteral(" ");
gradient->mStops[i].mLocation.AppendToString(aProperty, aResult);
gradient->mStops[i].mLocation.AppendToString(aProperty, aResult,
aSerialization);
}
if (++i == gradient->mStops.Length()) {
break;
@ -1208,23 +1280,23 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
nsStyleUtil::SerializeFunctionalAlternates(altValues, out);
aResult.Append(out);
} else {
GetPairValue().AppendToString(aProperty, aResult);
GetPairValue().AppendToString(aProperty, aResult, aSerialization);
}
} else if (eCSSUnit_Triplet == unit) {
GetTripletValue().AppendToString(aProperty, aResult);
GetTripletValue().AppendToString(aProperty, aResult, aSerialization);
} else if (eCSSUnit_Rect == unit) {
GetRectValue().AppendToString(aProperty, aResult);
GetRectValue().AppendToString(aProperty, aResult, aSerialization);
} else if (eCSSUnit_List == unit || eCSSUnit_ListDep == unit) {
GetListValue()->AppendToString(aProperty, aResult);
GetListValue()->AppendToString(aProperty, aResult, aSerialization);
} else if (eCSSUnit_SharedList == unit) {
GetSharedListValue()->AppendToString(aProperty, aResult);
GetSharedListValue()->AppendToString(aProperty, aResult, aSerialization);
} else if (eCSSUnit_PairList == unit || eCSSUnit_PairListDep == unit) {
switch (aProperty) {
case eCSSProperty_font_feature_settings:
nsStyleUtil::AppendFontFeatureSettings(*this, aResult);
break;
default:
GetPairListValue()->AppendToString(aProperty, aResult);
GetPairListValue()->AppendToString(aProperty, aResult, aSerialization);
break;
}
}
@ -1267,8 +1339,15 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
case eCSSUnit_Calc_Divided: break;
case eCSSUnit_Integer: break;
case eCSSUnit_Enumerated: break;
case eCSSUnit_EnumColor: break;
case eCSSUnit_Color: break;
case eCSSUnit_EnumColor: break;
case eCSSUnit_RGBColor: break;
case eCSSUnit_RGBAColor: break;
case eCSSUnit_HexColor: break;
case eCSSUnit_ShortHexColor: break;
case eCSSUnit_PercentageRGBColor: break;
case eCSSUnit_PercentageRGBAColor: break;
case eCSSUnit_HSLColor: break;
case eCSSUnit_HSLAColor: break;
case eCSSUnit_Percent: aResult.Append(PRUnichar('%')); break;
case eCSSUnit_Number: break;
case eCSSUnit_Gradient: break;
@ -1426,8 +1505,19 @@ nsCSSValue::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
case eCSSUnit_EnumColor:
break;
// Color: nothing extra to measure.
case eCSSUnit_Color:
// Integer Color: nothing extra to measure.
case eCSSUnit_RGBColor:
case eCSSUnit_RGBAColor:
case eCSSUnit_HexColor:
case eCSSUnit_ShortHexColor:
break;
// Float Color
case eCSSUnit_PercentageRGBColor:
case eCSSUnit_PercentageRGBAColor:
case eCSSUnit_HSLColor:
case eCSSUnit_HSLAColor:
n += mValue.mFloatColor->SizeOfIncludingThis(aMallocSizeOf);
break;
// Float: nothing extra to measure.
@ -1497,11 +1587,12 @@ nsCSSValueList::CloneInto(nsCSSValueList* aList) const
}
void
nsCSSValueList::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
nsCSSValueList::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aSerialization) const
{
const nsCSSValueList* val = this;
for (;;) {
val->mValue.AppendToString(aProperty, aResult);
val->mValue.AppendToString(aProperty, aResult, aSerialization);
val = val->mNext;
if (!val)
break;
@ -1561,10 +1652,11 @@ nsCSSValueSharedList::~nsCSSValueSharedList()
}
void
nsCSSValueSharedList::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
nsCSSValueSharedList::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aSerialization) const
{
if (mHead) {
mHead->AppendToString(aProperty, aResult);
mHead->AppendToString(aProperty, aResult, aSerialization);
}
}
@ -1606,7 +1698,8 @@ nsCSSRect::~nsCSSRect()
}
void
nsCSSRect::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
nsCSSRect::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aSerialization) const
{
NS_ABORT_IF_FALSE(mTop.GetUnit() != eCSSUnit_Null &&
mTop.GetUnit() != eCSSUnit_Inherit &&
@ -1619,24 +1712,24 @@ nsCSSRect::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
eCSSProperty_border_image_outset == aProperty) {
NS_NAMED_LITERAL_STRING(space, " ");
mTop.AppendToString(aProperty, aResult);
mTop.AppendToString(aProperty, aResult, aSerialization);
aResult.Append(space);
mRight.AppendToString(aProperty, aResult);
mRight.AppendToString(aProperty, aResult, aSerialization);
aResult.Append(space);
mBottom.AppendToString(aProperty, aResult);
mBottom.AppendToString(aProperty, aResult, aSerialization);
aResult.Append(space);
mLeft.AppendToString(aProperty, aResult);
mLeft.AppendToString(aProperty, aResult, aSerialization);
} else {
NS_NAMED_LITERAL_STRING(comma, ", ");
aResult.AppendLiteral("rect(");
mTop.AppendToString(aProperty, aResult);
mTop.AppendToString(aProperty, aResult, aSerialization);
aResult.Append(comma);
mRight.AppendToString(aProperty, aResult);
mRight.AppendToString(aProperty, aResult, aSerialization);
aResult.Append(comma);
mBottom.AppendToString(aProperty, aResult);
mBottom.AppendToString(aProperty, aResult, aSerialization);
aResult.Append(comma);
mLeft.AppendToString(aProperty, aResult);
mLeft.AppendToString(aProperty, aResult, aSerialization);
aResult.Append(PRUnichar(')'));
}
}
@ -1675,12 +1768,13 @@ static_assert(NS_SIDE_TOP == 0 && NS_SIDE_RIGHT == 1 &&
void
nsCSSValuePair::AppendToString(nsCSSProperty aProperty,
nsAString& aResult) const
nsAString& aResult,
nsCSSValue::Serialization aSerialization) const
{
mXValue.AppendToString(aProperty, aResult);
mXValue.AppendToString(aProperty, aResult, aSerialization);
if (mYValue.GetUnit() != eCSSUnit_Null) {
aResult.Append(PRUnichar(' '));
mYValue.AppendToString(aProperty, aResult);
mYValue.AppendToString(aProperty, aResult, aSerialization);
}
}
@ -1706,15 +1800,16 @@ nsCSSValuePair_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) co
void
nsCSSValueTriplet::AppendToString(nsCSSProperty aProperty,
nsAString& aResult) const
nsAString& aResult,
nsCSSValue::Serialization aSerialization) const
{
mXValue.AppendToString(aProperty, aResult);
mXValue.AppendToString(aProperty, aResult, aSerialization);
if (mYValue.GetUnit() != eCSSUnit_Null) {
aResult.Append(PRUnichar(' '));
mYValue.AppendToString(aProperty, aResult);
mYValue.AppendToString(aProperty, aResult, aSerialization);
if (mZValue.GetUnit() != eCSSUnit_Null) {
aResult.Append(PRUnichar(' '));
mZValue.AppendToString(aProperty, aResult);
mZValue.AppendToString(aProperty, aResult, aSerialization);
}
}
}
@ -1753,19 +1848,20 @@ nsCSSValuePairList::Clone() const
void
nsCSSValuePairList::AppendToString(nsCSSProperty aProperty,
nsAString& aResult) const
nsAString& aResult,
nsCSSValue::Serialization aSerialization) const
{
const nsCSSValuePairList* item = this;
for (;;) {
NS_ABORT_IF_FALSE(item->mXValue.GetUnit() != eCSSUnit_Null,
"unexpected null unit");
item->mXValue.AppendToString(aProperty, aResult);
item->mXValue.AppendToString(aProperty, aResult, aSerialization);
if (item->mXValue.GetUnit() != eCSSUnit_Inherit &&
item->mXValue.GetUnit() != eCSSUnit_Initial &&
item->mXValue.GetUnit() != eCSSUnit_Unset &&
item->mYValue.GetUnit() != eCSSUnit_Null) {
aResult.Append(PRUnichar(' '));
item->mYValue.AppendToString(aProperty, aResult);
item->mYValue.AppendToString(aProperty, aResult, aSerialization);
}
item = item->mNext;
if (!item)
@ -2052,6 +2148,93 @@ nsCSSValueTokenStream::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
return n;
}
// --- nsCSSValueFloatColor -------------
bool
nsCSSValueFloatColor::operator==(nsCSSValueFloatColor& aOther) const
{
return mComponent1 == aOther.mComponent1 &&
mComponent2 == aOther.mComponent2 &&
mComponent3 == aOther.mComponent3 &&
mAlpha == aOther.mAlpha;
}
nscolor
nsCSSValueFloatColor::GetColorValue(nsCSSUnit aUnit) const
{
MOZ_ASSERT(nsCSSValue::IsFloatColorUnit(aUnit), "unexpected unit");
if (aUnit == eCSSUnit_PercentageRGBColor ||
aUnit == eCSSUnit_PercentageRGBAColor) {
return NS_RGBA(NSToIntRound(mComponent1 * 255.0f),
NSToIntRound(mComponent2 * 255.0f),
NSToIntRound(mComponent3 * 255.0f),
NSToIntRound(mAlpha * 255.0f));
}
// HSL color
MOZ_ASSERT(aUnit == eCSSUnit_HSLColor ||
aUnit == eCSSUnit_HSLAColor);
nscolor hsl = NS_HSL2RGB(mComponent1, mComponent2, mComponent3);
return NS_RGBA(NS_GET_R(hsl),
NS_GET_G(hsl),
NS_GET_B(hsl),
NSToIntRound(mAlpha * 255.0f));
}
bool
nsCSSValueFloatColor::IsNonTransparentColor() const
{
return mAlpha > 0.0f;
}
void
nsCSSValueFloatColor::AppendToString(nsCSSUnit aUnit, nsAString& aResult) const
{
MOZ_ASSERT(nsCSSValue::IsFloatColorUnit(aUnit), "unexpected unit");
bool hasAlpha = aUnit == eCSSUnit_PercentageRGBAColor ||
aUnit == eCSSUnit_HSLAColor;
bool isHSL = aUnit == eCSSUnit_HSLColor ||
aUnit == eCSSUnit_HSLAColor;
if (isHSL) {
aResult.AppendLiteral("hsl");
} else {
aResult.AppendLiteral("rgb");
}
if (hasAlpha) {
aResult.AppendLiteral("a(");
} else {
aResult.Append('(');
}
if (isHSL) {
aResult.AppendFloat(mComponent1 * 360.0f);
aResult.AppendLiteral(", ");
} else {
aResult.AppendFloat(mComponent1 * 100.0f);
aResult.AppendLiteral("%, ");
}
aResult.AppendFloat(mComponent2 * 100.0f);
aResult.AppendLiteral("%, ");
aResult.AppendFloat(mComponent3 * 100.0f);
if (hasAlpha) {
aResult.AppendLiteral("%, ");
aResult.AppendFloat(mAlpha);
aResult.Append(')');
} else {
aResult.AppendLiteral("%)");
}
}
size_t
nsCSSValueFloatColor::SizeOfIncludingThis(
mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
return n;
}
// --- nsCSSCornerSizes -----------------
nsCSSCornerSizes::nsCSSCornerSizes(void)
@ -2092,4 +2275,3 @@ nsCSSCornerSizes::corners[4] = {
&nsCSSCornerSizes::mBottomRight,
&nsCSSCornerSizes::mBottomLeft,
};

View File

@ -209,8 +209,15 @@ enum nsCSSUnit {
eCSSUnit_Integer = 70, // (int) simple value
eCSSUnit_Enumerated = 71, // (int) value has enumerated meaning
eCSSUnit_EnumColor = 80, // (int) enumerated color (kColorKTable)
eCSSUnit_Color = 81, // (nscolor) an RGBA value
eCSSUnit_EnumColor = 80, // (int) enumerated color (kColorKTable)
eCSSUnit_RGBColor = 81, // (nscolor) an opaque RGBA value specified as rgb()
eCSSUnit_RGBAColor = 82, // (nscolor) an RGBA value specified as rgba()
eCSSUnit_HexColor = 83, // (nscolor) an opaque RGBA value specified as #rrggbb
eCSSUnit_ShortHexColor = 84, // (nscolor) an opaque RGBA value specified as #rgb
eCSSUnit_PercentageRGBColor = 85, // (nsCSSValueFloatColor*)
eCSSUnit_PercentageRGBAColor = 86, // (nsCSSValueFloatColor*)
eCSSUnit_HSLColor = 87, // (nsCSSValueFloatColor*)
eCSSUnit_HSLAColor = 88, // (nsCSSValueFloatColor*)
eCSSUnit_Percent = 90, // (float) 1.0 == 100%) value is percentage of something
eCSSUnit_Number = 91, // (float) value is numeric (usually multiplier, different behavior that percent)
@ -267,6 +274,7 @@ struct nsCSSValuePairList;
struct nsCSSValuePairList_heap;
struct nsCSSValueTriplet;
struct nsCSSValueTriplet_heap;
class nsCSSValueFloatColor;
class nsCSSValue {
public:
@ -303,11 +311,15 @@ public:
return !(*this == aOther);
}
// Enum for AppendToString's aValueSerialization argument.
enum Serialization { eNormalized, eAuthorSpecified };
/**
* Serialize |this| as a specified value for |aProperty| and append
* it to |aResult|.
*/
void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
void AppendToString(nsCSSProperty aProperty, nsAString& aResult,
Serialization aValueSerialization) const;
nsCSSUnit GetUnit() const { return mUnit; }
bool IsLengthUnit() const
@ -349,6 +361,35 @@ public:
bool UnitHasArrayValue() const
{ return eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Calc_Divided; }
// Checks for the nsCSSValue being of a particular type of color unit:
//
// - IsIntegerColorUnit returns true for:
// eCSSUnit_RGBColor -- rgb(int,int,int)
// eCSSUnit_RGBAColor -- rgba(int,int,int,float)
// eCSSUnit_HexColor -- #rrggbb
// eCSSUnit_ShortHexColor -- #rgb
//
// - IsFLoatColorUnit returns true for:
// eCSSUnit_PercentageRGBColor -- rgb(%,%,%)
// eCSSUnit_PercentageRGBAColor -- rgba(%,%,%,float)
// eCSSUnit_HSLColor -- hsl(float,%,%)
// eCSSUnit_HSLAColor -- hsla(float,%,%,float)
//
// - IsNumericColorUnit returns true for any of the above units.
//
// Note that color keywords and system colors are represented by
// eCSSUnit_EnumColor and eCSSUnit_Ident.
bool IsIntegerColorUnit() const { return IsIntegerColorUnit(mUnit); }
bool IsFloatColorUnit() const { return IsFloatColorUnit(mUnit); }
bool IsNumericColorUnit() const { return IsNumericColorUnit(mUnit); }
static bool IsIntegerColorUnit(nsCSSUnit aUnit)
{ return eCSSUnit_RGBColor <= aUnit && aUnit <= eCSSUnit_ShortHexColor; }
static bool IsFloatColorUnit(nsCSSUnit aUnit)
{ return eCSSUnit_PercentageRGBColor <= aUnit &&
aUnit <= eCSSUnit_HSLAColor; }
static bool IsNumericColorUnit(nsCSSUnit aUnit)
{ return IsIntegerColorUnit(aUnit) || IsFloatColorUnit(aUnit); }
int32_t GetIntValue() const
{
NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Integer ||
@ -402,12 +443,7 @@ public:
return GetBufferValue(mValue.mString);
}
nscolor GetColorValue() const
{
NS_ABORT_IF_FALSE((mUnit == eCSSUnit_Color), "not a color value");
return mValue.mColor;
}
nscolor GetColorValue() const;
bool IsNonTransparentColor() const;
Array* GetArrayValue() const
@ -503,6 +539,11 @@ public:
void SetFloatValue(float aValue, nsCSSUnit aUnit);
void SetStringValue(const nsString& aValue, nsCSSUnit aUnit);
void SetColorValue(nscolor aValue);
void SetIntegerColorValue(nscolor aValue, nsCSSUnit aUnit);
void SetFloatColorValue(float aComponent1,
float aComponent2,
float aComponent3,
float aAlpha, nsCSSUnit aUnit);
void SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
void SetURLValue(mozilla::css::URLValue* aURI);
void SetImageValue(mozilla::css::ImageValue* aImage);
@ -573,6 +614,7 @@ protected:
nsCSSValueSharedList* mSharedList;
nsCSSValuePairList_heap* mPairList;
nsCSSValuePairList* mPairListDependent;
nsCSSValueFloatColor* mFloatColor;
} mValue;
};
@ -687,7 +729,8 @@ struct nsCSSValueList {
nsCSSValueList* Clone() const; // makes a deep copy
void CloneInto(nsCSSValueList* aList) const; // makes a deep copy into aList
void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
void AppendToString(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aValueSerialization) const;
bool operator==(nsCSSValueList const& aOther) const;
bool operator!=(const nsCSSValueList& aOther) const
@ -737,7 +780,8 @@ struct nsCSSValueSharedList {
NS_INLINE_DECL_REFCOUNTING(nsCSSValueSharedList)
void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
void AppendToString(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aValueSerialization) const;
bool operator==(nsCSSValueSharedList const& aOther) const;
bool operator!=(const nsCSSValueSharedList& aOther) const
@ -777,7 +821,8 @@ struct nsCSSRect {
nsCSSRect(const nsCSSRect& aCopy);
~nsCSSRect();
void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
void AppendToString(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aValueSerialization) const;
bool operator==(const nsCSSRect& aOther) const {
return mTop == aOther.mTop &&
@ -906,7 +951,8 @@ struct nsCSSValuePair {
mYValue.GetUnit() != eCSSUnit_Null;
}
void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
void AppendToString(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aValueSerialization) const;
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
@ -991,7 +1037,8 @@ struct nsCSSValueTriplet {
mZValue.GetUnit() != eCSSUnit_Null;
}
void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
void AppendToString(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aValueSerialization) const;
nsCSSValue mXValue;
nsCSSValue mYValue;
@ -1048,7 +1095,8 @@ struct nsCSSValuePairList {
~nsCSSValuePairList();
nsCSSValuePairList* Clone() const; // makes a deep copy
void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
void AppendToString(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aValueSerialization) const;
bool operator==(const nsCSSValuePairList& aOther) const;
bool operator!=(const nsCSSValuePairList& aOther) const
@ -1285,6 +1333,46 @@ private:
nsCSSValueTokenStream& operator=(const nsCSSValueTokenStream& aOther) MOZ_DELETE;
};
class nsCSSValueFloatColor {
public:
nsCSSValueFloatColor(float aComponent1, float aComponent2, float aComponent3,
float aAlpha)
: mComponent1(aComponent1)
, mComponent2(aComponent2)
, mComponent3(aComponent3)
, mAlpha(aAlpha)
{
MOZ_COUNT_CTOR(nsCSSValueFloatColor);
}
~nsCSSValueFloatColor()
{
MOZ_COUNT_DTOR(nsCSSValueFloatColor);
}
bool operator==(nsCSSValueFloatColor& aOther) const;
nscolor GetColorValue(nsCSSUnit aUnit) const;
bool IsNonTransparentColor() const;
void AppendToString(nsCSSUnit aUnit, nsAString& aResult) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
NS_INLINE_DECL_REFCOUNTING(nsCSSValueFloatColor)
private:
// FIXME: We should not be clamping specified RGB color components.
float mComponent1; // 0..1 for RGB, 0..360 for HSL
float mComponent2; // 0..1
float mComponent3; // 0..1
float mAlpha; // 0..1
nsCSSValueFloatColor(const nsCSSValueFloatColor& aOther) MOZ_DELETE;
nsCSSValueFloatColor& operator=(const nsCSSValueFloatColor& aOther)
MOZ_DELETE;
};
struct nsCSSCornerSizes {
nsCSSCornerSizes(void);
nsCSSCornerSizes(const nsCSSCornerSizes& aCopy);

View File

@ -417,6 +417,15 @@ nsComputedDOMStyle::GetPropertyValue(const nsAString& aPropertyName,
return NS_OK;
}
NS_IMETHODIMP
nsComputedDOMStyle::GetAuthoredPropertyValue(const nsAString& aPropertyName,
nsAString& aReturn)
{
// Authored style doesn't make sense to return from computed DOM style,
// so just return whatever GetPropertyValue() returns.
return GetPropertyValue(aPropertyName, aReturn);
}
/* static */
already_AddRefed<nsStyleContext>
nsComputedDOMStyle::GetStyleContextForElement(Element* aElement,

View File

@ -184,6 +184,31 @@ nsDOMCSSDeclaration::GetPropertyValue(const nsAString& aPropertyName,
return GetPropertyValue(propID, aReturn);
}
NS_IMETHODIMP
nsDOMCSSDeclaration::GetAuthoredPropertyValue(const nsAString& aPropertyName,
nsAString& aReturn)
{
const nsCSSProperty propID = nsCSSProps::LookupProperty(aPropertyName,
nsCSSProps::eEnabled);
if (propID == eCSSProperty_UNKNOWN) {
aReturn.Truncate();
return NS_OK;
}
if (propID == eCSSPropertyExtra_variable) {
GetCustomPropertyValue(aPropertyName, aReturn);
return NS_OK;
}
css::Declaration* decl = GetCSSDeclaration(false);
if (!decl) {
return NS_ERROR_FAILURE;
}
decl->GetAuthoredValue(propID, aReturn);
return NS_OK;
}
NS_IMETHODIMP
nsDOMCSSDeclaration::GetPropertyPriority(const nsAString& aPropertyName,
nsAString& aReturn)

View File

@ -50,6 +50,9 @@ public:
NS_IMETHOD GetPropertyValue(const nsCSSProperty aPropID,
nsAString& aValue) = 0;
NS_IMETHOD GetAuthoredPropertyValue(const nsAString& aPropName,
nsAString& aValue) = 0;
/**
* Method analogous to nsIDOMCSSStyleDeclaration::SetProperty. This
* method does NOT allow setting a priority (the priority will
@ -125,6 +128,10 @@ public:
mozilla::ErrorResult& rv) {
rv = GetPropertyValue(aPropName, aValue);
}
void GetAuthoredPropertyValue(const nsAString& aPropName, nsString& aValue,
mozilla::ErrorResult& rv) {
rv = GetAuthoredPropertyValue(aPropName, aValue);
}
void GetPropertyPriority(const nsAString& aPropName, nsString& aPriority) {
GetPropertyPriority(aPropName, static_cast<nsAString&>(aPriority));
}
@ -145,10 +152,12 @@ public:
NS_DEFINE_STATIC_IID_ACCESSOR(nsICSSDeclaration, NS_ICSSDECLARATION_IID)
#define NS_DECL_NSICSSDECLARATION \
NS_IMETHOD GetPropertyValue(const nsCSSProperty aPropID, \
nsAString& aValue); \
NS_IMETHOD SetPropertyValue(const nsCSSProperty aPropID, \
#define NS_DECL_NSICSSDECLARATION \
NS_IMETHOD GetPropertyValue(const nsCSSProperty aPropID, \
nsAString& aValue); \
NS_IMETHOD GetAuthoredPropertyValue(const nsAString& aPropName, \
nsAString& aValue); \
NS_IMETHOD SetPropertyValue(const nsCSSProperty aPropID, \
const nsAString& aValue);
#define NS_DECL_NSIDOMCSSSTYLEDECLARATION_HELPER \

View File

@ -16,8 +16,8 @@
#include "nsIXULRuntime.h"
#include "nsCSSStyleSheet.h"
NS_IMPL_ISUPPORTS_INHERITED1(
nsLayoutStylesheetCache, MemoryUniReporter, nsIObserver)
NS_IMPL_ISUPPORTS2(
nsLayoutStylesheetCache, nsIObserver, nsIMemoryReporter)
nsresult
nsLayoutStylesheetCache::Observe(nsISupports* aSubject,
@ -142,12 +142,19 @@ nsLayoutStylesheetCache::Shutdown()
NS_IF_RELEASE(gStyleCache);
}
int64_t
nsLayoutStylesheetCache::Amount()
MOZ_DEFINE_MALLOC_SIZE_OF(LayoutStylesheetCacheMallocSizeOf)
NS_IMETHODIMP
nsLayoutStylesheetCache::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return SizeOfIncludingThis(MallocSizeOf);
return MOZ_COLLECT_REPORT(
"explicit/layout/style-sheet-cache", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(LayoutStylesheetCacheMallocSizeOf),
"Memory used for some built-in style sheets.");
}
size_t
nsLayoutStylesheetCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
@ -171,9 +178,6 @@ nsLayoutStylesheetCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
}
nsLayoutStylesheetCache::nsLayoutStylesheetCache()
: MemoryUniReporter("explicit/layout/style-sheet-cache",
KIND_HEAP, UNITS_BYTES,
"Memory used for some built-in style sheets.")
{
nsCOMPtr<nsIObserverService> obsSvc =
mozilla::services::GetObserverService();
@ -212,14 +216,14 @@ nsLayoutStylesheetCache::nsLayoutStylesheetCache()
nsLayoutStylesheetCache::~nsLayoutStylesheetCache()
{
UnregisterWeakMemoryReporter(this);
mozilla::UnregisterWeakMemoryReporter(this);
gStyleCache = nullptr;
}
void
nsLayoutStylesheetCache::InitMemoryReporter()
{
RegisterWeakMemoryReporter(this);
mozilla::RegisterWeakMemoryReporter(this);
}
void

View File

@ -24,11 +24,12 @@ class Loader;
}
class nsLayoutStylesheetCache MOZ_FINAL
: public mozilla::MemoryUniReporter
, public nsIObserver
: public nsIObserver
, public nsIMemoryReporter
{
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIMEMORYREPORTER
static nsCSSStyleSheet* ScrollbarsSheet();
static nsCSSStyleSheet* FormsSheet();
@ -40,7 +41,6 @@ class nsLayoutStylesheetCache MOZ_FINAL
static void Shutdown();
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
private:

View File

@ -850,7 +850,7 @@ static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor,
bool result = false;
nsCSSUnit unit = aValue.GetUnit();
if (eCSSUnit_Color == unit) {
if (aValue.IsNumericColorUnit()) {
aResult = aValue.GetColorValue();
result = true;
}

View File

@ -752,7 +752,9 @@ nsStyleAnimation::ComputeDistance(nsCSSProperty aProperty,
// (1) GetUnit() == eCSSUnit_Null
// (2) GetUnit() == eCSSUnit_Enumerated &&
// GetIntValue() == NS_STYLE_BOX_SHADOW_INSET
NS_ABORT_IF_FALSE(color1.GetUnit() == color2.GetUnit() &&
NS_ABORT_IF_FALSE(((color1.IsNumericColorUnit() &&
color2.IsNumericColorUnit()) ||
(color1.GetUnit() == color2.GetUnit())) &&
inset1 == inset2,
"AddWeighted should have failed");
}
@ -2685,7 +2687,7 @@ nsStyleAnimation::UncomputeValue(nsCSSProperty aProperty,
return false;
}
val.AppendToString(aProperty, aSpecifiedValue);
val.AppendToString(aProperty, aSpecifiedValue, nsCSSValue::eNormalized);
return true;
}

View File

@ -460,8 +460,11 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther,
if (this##struct_) { \
const nsStyle##struct_* other##struct_ = aOther->Style##struct_(); \
nsChangeHint maxDifference = nsStyle##struct_::MaxDifference(); \
nsChangeHint maxDifferenceNeverInherited = \
nsStyle##struct_::MaxDifferenceNeverInherited(); \
if ((compare || \
(maxDifference & aParentHintsNotHandledForDescendants)) && \
(NS_SubtractHint(maxDifference, maxDifferenceNeverInherited) & \
aParentHintsNotHandledForDescendants)) && \
!NS_IsHintSubset(maxDifference, hint) && \
this##struct_ != other##struct_) { \
NS_ASSERTION(NS_IsHintSubset( \
@ -864,3 +867,15 @@ nsStyleContext::FreeAllocations(nsPresContext *aPresContext)
shell->FreeMisc(alloc->mSize, alloc);
}
}
#ifdef DEBUG
/* static */ void
nsStyleContext::AssertStyleStructMaxDifferenceValid()
{
#define STYLE_STRUCT(name, checkdata_cb) \
MOZ_ASSERT(NS_IsHintSubset(nsStyle##name::MaxDifferenceNeverInherited(), \
nsStyle##name::MaxDifference()));
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
}
#endif

View File

@ -340,6 +340,7 @@ public:
#ifdef DEBUG
void List(FILE* out, int32_t aIndent);
static void AssertStyleStructMaxDifferenceValid();
#endif
protected:

View File

@ -79,6 +79,12 @@ public:
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_REFLOW;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
static nsChangeHint CalcFontDifference(const nsFont& aFont1, const nsFont& aFont2);
static nscoord ZoomText(nsPresContext* aPresContext, nscoord aSize);
@ -305,6 +311,11 @@ struct nsStyleColor {
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_VISUAL;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics at all.
return nsChangeHint(0);
}
void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
return aContext->AllocateFromShell(sz);
@ -333,6 +344,11 @@ struct nsStyleBackground {
static nsChangeHint MaxDifference() {
return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics at all.
return nsChangeHint(0);
}
struct Position;
friend struct Position;
@ -561,6 +577,11 @@ struct nsStyleMargin {
NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
nsChangeHint_NeedDirtyReflow));
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and
// nsChangeHint_NeedReflow as inherited hints.
return nsChangeHint(0);
}
nsStyleSides mMargin; // [reset] coord, percent, calc, auto
@ -596,6 +617,11 @@ struct nsStylePadding {
return NS_SubtractHint(NS_STYLE_HINT_REFLOW,
nsChangeHint_ClearDescendantIntrinsics);
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference can return nsChangeHint_ClearAncestorIntrinsics as an
// inherited hint.
return nsChangeHint(0);
}
nsStyleSides mPadding; // [reset] coord, percent, calc
@ -773,6 +799,12 @@ struct nsStyleBorder {
return NS_CombineHint(NS_STYLE_HINT_REFLOW,
nsChangeHint_BorderStyleNoneChange);
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
void EnsureBorderColors() {
if (!mBorderColors) {
@ -995,6 +1027,12 @@ struct nsStyleOutline {
return NS_CombineHint(nsChangeHint_AllReflowHints,
nsChangeHint_RepaintFrame);
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
nsStyleCorners mOutlineRadius; // [reset] coord, percent, calc
@ -1080,6 +1118,12 @@ struct nsStyleList {
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_FRAMECHANGE;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
imgRequestProxy* GetListStyleImage() const { return mListStyleImage; }
void SetListStyleImage(imgRequestProxy* aReq)
@ -1119,6 +1163,11 @@ struct nsStylePosition {
nsChangeHint(nsChangeHint_RecomputePosition |
nsChangeHint_UpdateOverflow));
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and
// nsChangeHint_NeedReflow as inherited hints.
return nsChangeHint(0);
}
nsStyleSides mOffset; // [reset] coord, percent, calc, auto
nsStyleCoord mWidth; // [reset] coord, percent, enum, calc, auto
@ -1284,6 +1333,12 @@ struct nsStyleTextReset {
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_REFLOW;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
nsStyleCoord mVerticalAlign; // [reset] coord, percent, calc, enum (see nsStyleConsts.h)
nsStyleTextOverflow mTextOverflow; // [reset] enum, string
@ -1313,6 +1368,12 @@ struct nsStyleText {
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_FRAMECHANGE;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
uint8_t mTextAlign; // [inherited] see nsStyleConsts.h
uint8_t mTextAlignLast; // [inherited] see nsStyleConsts.h
@ -1488,6 +1549,12 @@ struct nsStyleVisibility {
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_FRAMECHANGE;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
nsStyleImageOrientation mImageOrientation; // [inherited]
uint8_t mDirection; // [inherited] see nsStyleConsts.h NS_STYLE_DIRECTION_*
@ -1695,6 +1762,11 @@ struct nsStyleDisplay {
nsChangeHint_UpdateOverflow |
nsChangeHint_AddOrRemoveTransform);
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and
// nsChangeHint_NeedReflow as inherited hints.
return nsChangeHint(0);
}
// We guarantee that if mBinding is non-null, so are mBinding->GetURI() and
// mBinding->mOriginPrincipal.
@ -1864,6 +1936,12 @@ struct nsStyleTable {
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_FRAMECHANGE;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
uint8_t mLayoutStrategy;// [reset] see nsStyleConsts.h NS_STYLE_TABLE_LAYOUT_*
uint8_t mFrame; // [reset] see nsStyleConsts.h NS_STYLE_TABLE_FRAME_*
@ -1888,6 +1966,12 @@ struct nsStyleTableBorder {
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_FRAMECHANGE;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
nscoord mBorderSpacingX;// [inherited]
nscoord mBorderSpacingY;// [inherited]
@ -1978,6 +2062,12 @@ struct nsStyleQuotes {
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_FRAMECHANGE;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
uint32_t QuotesCount(void) const { return mQuotesCount; } // [inherited]
@ -2045,6 +2135,12 @@ struct nsStyleContent {
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_FRAMECHANGE;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
uint32_t ContentCount(void) const { return mContentCount; } // [reset]
@ -2149,6 +2245,12 @@ struct nsStyleUIReset {
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_FRAMECHANGE;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
uint8_t mUserSelect; // [reset] (selection-style)
uint8_t mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing)
@ -2202,6 +2304,12 @@ struct nsStyleUserInterface {
static nsChangeHint MaxDifference() {
return nsChangeHint(nsChangeHint_UpdateCursor | NS_STYLE_HINT_FRAMECHANGE);
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
uint8_t mUserInput; // [inherited]
uint8_t mUserModify; // [inherited] (modify-content)
@ -2237,6 +2345,12 @@ struct nsStyleXUL {
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_FRAMECHANGE;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
float mBoxFlex; // [reset] see nsStyleConsts.h
uint32_t mBoxOrdinal; // [reset] see nsStyleConsts.h
@ -2264,6 +2378,12 @@ struct nsStyleColumn {
static nsChangeHint MaxDifference() {
return NS_STYLE_HINT_FRAMECHANGE;
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
/**
* This is the maximum number of columns we can process. It's used in both
@ -2349,6 +2469,11 @@ struct nsStyleSVG {
NS_CombineHint(nsChangeHint_NeedReflow, nsChangeHint_NeedDirtyReflow)), // XXX remove nsChangeHint_NeedDirtyReflow: bug 876085
nsChangeHint_RepaintFrame);
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow as an inherited hint
// and never returns nsChangeHint_ClearAncestorIntrinsics at all.
return nsChangeHint_NeedReflow;
}
nsStyleSVGPaint mFill; // [inherited]
nsStyleSVGPaint mStroke; // [inherited]
@ -2477,6 +2602,12 @@ struct nsStyleSVGReset {
return NS_CombineHint(nsChangeHint_UpdateEffects,
NS_CombineHint(nsChangeHint_UpdateOverflow, NS_STYLE_HINT_REFLOW));
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
return NS_CombineHint(nsChangeHint_NeedReflow,
nsChangeHint_ClearAncestorIntrinsics);
}
// The backend only supports one SVG reference right now.
// Eventually, it will support multiple chained SVG reference filters and CSS
@ -2519,6 +2650,11 @@ struct nsStyleVariables {
static nsChangeHint MaxDifference() {
return nsChangeHint(0);
}
static nsChangeHint MaxDifferenceNeverInherited() {
// CalcDifference never returns nsChangeHint_NeedReflow or
// nsChangeHint_ClearAncestorIntrinsics at all.
return nsChangeHint(0);
}
mozilla::CSSVariableValues mVariables;
};

View File

@ -6,6 +6,7 @@ support-files =
hover_helper.html
[test_additional_sheets.html]
[test_author_specified_style.html]
[test_bug535806.xul]
[test_hover.html]
[test_moz_document_rules.html]

View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<title>Test for CSSStyleDeclaration.getAuthoredPropertyValue()</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<script>
var values = [
// specified value // returned from getAuthoredPropertyValue()
"#12F", "#12f",
"#1122FF", "#1122ff",
"rgb(10,20,30)", "rgb(10, 20, 30)",
"Rgb(300,20,30)", "rgb(255, 20, 30)",
"rgba(10,20,30,0.250)", "rgba(10, 20, 30, 0.25)",
"OrangeRed", "OrangeRed",
"rgb(10%,25%,99%)", "rgb(10%, 25%, 99%)",
"rgb(6.66667%,0%,0.0%)", "rgb(6.66667%, 0%, 0%)",
"HSL(0,25%,75%)", "hsl(0, 25%, 75%)",
"hsl(60,0%,0%)", "hsl(60, 0%, 0%)",
"hsla(60,50%,50%,0.1250)", "hsla(60, 50%, 50%, 0.125)",
"rgba(0,0,0,0)", "rgba(0, 0, 0, 0)"
];
var properties = [
// property to test with // fixed prefix to ignore from getAuthoredPropertyValue()
"color", "",
"background-color", "",
"background", "none repeat scroll 0% 0% "
];
var span = document.createElement("span");
for (var j = 0; j < properties.length; j += 2) {
var propertyName = properties[j];
var expectedPrefix = properties[j + 1];
for (var i = 0; i < values.length; i += 2) {
var value = values[i];
var expected = values[i + 1];
span.setAttribute("style", propertyName + ": " + value);
is(span.style.getAuthoredPropertyValue(propertyName), expectedPrefix + expected, "specified " + value);
}
}
// also test a custom property
span.setAttribute("style", "var-color: rgb(10%,25%,99%)");
is(span.style.getAuthoredPropertyValue("var-color"), " rgb(10%,25%,99%)", "specified var-color");
</script>

View File

@ -1050,14 +1050,6 @@ PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents,
return strokeExtents;
}
/*static*/ gfxRect
nsSVGUtils::PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents,
nsSVGGeometryFrame* aFrame,
const gfxMatrix& aMatrix)
{
return ::PathExtentsToMaxStrokeExtents(aPathExtents, aFrame, 0.5, aMatrix);
}
/*static*/ gfxRect
nsSVGUtils::PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents,
nsTextFrame* aFrame,

View File

@ -42,7 +42,6 @@ class nsStyleCoord;
class nsSVGDisplayContainerFrame;
class nsSVGElement;
class nsSVGEnum;
class nsSVGGeometryFrame;
class nsSVGLength2;
class nsSVGOuterSVGFrame;
class nsSVGPathGeometryFrame;
@ -507,9 +506,6 @@ public:
*
* This should die once bug 478152 is fixed.
*/
static gfxRect PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents,
nsSVGGeometryFrame* aFrame,
const gfxMatrix& aMatrix);
static gfxRect PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents,
nsTextFrame* aFrame,
const gfxMatrix& aMatrix);

View File

@ -18,7 +18,7 @@
<ProgressBar
android:id="@+id/waiting_content1"
style="@android:style/Widget.ProgressBar.Horizontal"
style="@style/Widget.ProgressBar.Horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:indeterminateOnly="true"

View File

@ -25,6 +25,8 @@
<style name="Widget.BaseTextView" parent="android:style/Widget.Holo.Light.TextView"/>
<style name="Widget.ProgressBar.Horizontal" parent="android:style/Widget.Holo.ProgressBar.Horizontal"/>
<!--
Application styles. All customizations that are not specific

View File

@ -22,6 +22,8 @@
<style name="Widget.BaseTextView" parent="android:style/Widget.TextView"/>
<style name="Widget.ProgressBar.Horizontal" parent="android:style/Widget.ProgressBar.Horizontal"/>
<!--
Application styles. All customizations that are not specific
to a particular API level can go here.

View File

@ -88,6 +88,6 @@
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>

View File

@ -301,7 +301,7 @@ PreferenceServiceReporter::CollectReports(nsIMemoryReporterCallback* aCb,
} while (0)
REPORT(NS_LITERAL_CSTRING("explicit/preferences"),
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
KIND_HEAP, UNITS_BYTES,
Preferences::SizeOfIncludingThisAndOtherStuff(PreferenceServiceMallocSizeOf),
"Memory used by the preferences system.");
@ -323,26 +323,22 @@ PreferenceServiceReporter::CollectReports(nsIMemoryReporterCallback* aCb,
"referent(pref=%s)", suspect.get());
REPORT(suspectPath,
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
totalReferentCount,
KIND_OTHER, UNITS_COUNT, totalReferentCount,
"A preference with a suspiciously large number "
"referents (symptom of a leak).");
}
REPORT(NS_LITERAL_CSTRING("preference-service/referent/strong"),
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
referentCount.numStrong,
KIND_OTHER, UNITS_COUNT, referentCount.numStrong,
"The number of strong referents held by the preference service.");
REPORT(NS_LITERAL_CSTRING("preference-service/referent/weak/alive"),
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
referentCount.numWeakAlive,
KIND_OTHER, UNITS_COUNT, referentCount.numWeakAlive,
"The number of weak referents held by the preference service "
"that are still alive.");
REPORT(NS_LITERAL_CSTRING("preference-service/referent/weak/dead"),
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
referentCount.numWeakDead,
KIND_OTHER, UNITS_COUNT, referentCount.numWeakDead,
"The number of weak referents held by the preference service "
"that are dead.");

View File

@ -717,17 +717,16 @@ nsCookieService::AppClearDataObserverInit()
* public methods
******************************************************************************/
NS_IMPL_ISUPPORTS_INHERITED5(nsCookieService, MemoryUniReporter,
nsICookieService,
nsICookieManager,
nsICookieManager2,
nsIObserver,
nsISupportsWeakReference)
NS_IMPL_ISUPPORTS6(nsCookieService,
nsICookieService,
nsICookieManager,
nsICookieManager2,
nsIObserver,
nsISupportsWeakReference,
nsIMemoryReporter)
nsCookieService::nsCookieService()
: MemoryUniReporter("explicit/cookie-service", KIND_HEAP, UNITS_BYTES,
"Memory used by the cookie service.")
, mDBState(nullptr)
: mDBState(nullptr)
, mCookieBehavior(BEHAVIOR_ACCEPT)
, mThirdPartySession(false)
, mMaxNumberOfCookies(kMaxNumberOfCookies)
@ -4354,8 +4353,14 @@ nsCookieService::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
return n;
}
int64_t
nsCookieService::Amount()
MOZ_DEFINE_MALLOC_SIZE_OF(CookieServiceMallocSizeOf)
NS_IMETHODIMP
nsCookieService::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return SizeOfIncludingThis(MallocSizeOf);
return MOZ_COLLECT_REPORT(
"explicit/cookie-service", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(CookieServiceMallocSizeOf),
"Memory used by the cookie service.");
}

View File

@ -231,23 +231,22 @@ enum OpenDBResult
* class declaration
******************************************************************************/
class nsCookieService : public mozilla::MemoryUniReporter
, public nsICookieService
class nsCookieService : public nsICookieService
, public nsICookieManager2
, public nsIObserver
, public nsSupportsWeakReference
, public nsIMemoryReporter
{
private:
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
public:
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSICOOKIESERVICE
NS_DECL_NSICOOKIEMANAGER
NS_DECL_NSICOOKIEMANAGER2
NS_DECL_NSIMEMORYREPORTER
nsCookieService();
virtual ~nsCookieService();

View File

@ -398,10 +398,7 @@ nsDNSSyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
//-----------------------------------------------------------------------------
nsDNSService::nsDNSService()
: MemoryUniReporter("explicit/network/dns-service",
KIND_HEAP, UNITS_BYTES,
"Memory used for the DNS service.")
, mLock("nsDNSServer.mLock")
: mLock("nsDNSServer.mLock")
, mFirstTime(true)
, mOffline(false)
{
@ -411,8 +408,8 @@ nsDNSService::~nsDNSService()
{
}
NS_IMPL_ISUPPORTS_INHERITED3(nsDNSService, MemoryUniReporter, nsIDNSService,
nsPIDNSService, nsIObserver)
NS_IMPL_ISUPPORTS4(nsDNSService, nsIDNSService, nsPIDNSService, nsIObserver,
nsIMemoryReporter)
/******************************************************************************
* nsDNSService impl:
@ -913,3 +910,16 @@ nsDNSService::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
mallocSizeOf);
return n;
}
MOZ_DEFINE_MALLOC_SIZE_OF(DNSServiceMallocSizeOf)
NS_IMETHODIMP
nsDNSService::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return MOZ_COLLECT_REPORT(
"explicit/network/dns-service", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(DNSServiceMallocSizeOf),
"Memory used for the DNS service.");
}

View File

@ -19,25 +19,22 @@
#include "mozilla/Mutex.h"
#include "mozilla/Attributes.h"
class nsDNSService MOZ_FINAL : public mozilla::MemoryUniReporter
, public nsPIDNSService
class nsDNSService MOZ_FINAL : public nsPIDNSService
, public nsIObserver
, public nsIMemoryReporter
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSPIDNSSERVICE
NS_DECL_NSIDNSSERVICE
NS_DECL_NSIOBSERVER
NS_DECL_NSIMEMORYREPORTER
nsDNSService();
~nsDNSService();
static nsIDNSService* GetXPCOMSingleton();
int64_t Amount() MOZ_OVERRIDE
{
return SizeOfIncludingThis(MallocSizeOf);
}
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:

View File

@ -18,8 +18,8 @@
using namespace mozilla;
NS_IMPL_ISUPPORTS_INHERITED1(nsEffectiveTLDService, MemoryUniReporter,
nsIEffectiveTLDService)
NS_IMPL_ISUPPORTS2(nsEffectiveTLDService, nsIEffectiveTLDService,
nsIMemoryReporter)
// ----------------------------------------------------------------------
@ -66,10 +66,7 @@ nsEffectiveTLDService::nsEffectiveTLDService()
// use a perfect hash, but at least we'll save a few rehashes along the way.
// Next optimization here is to precompute the hash using something like
// gperf, but one step at a time. :-)
: MemoryUniReporter("explicit/xpcom/effective-TLD-service",
KIND_HEAP, UNITS_BYTES,
"Memory used by the effective TLD service.")
, mHash(ArrayLength(nsDomainEntry::entries))
: mHash(ArrayLength(nsDomainEntry::entries))
{
}
@ -110,10 +107,16 @@ nsEffectiveTLDService::~nsEffectiveTLDService()
gService = nullptr;
}
int64_t
nsEffectiveTLDService::Amount()
MOZ_DEFINE_MALLOC_SIZE_OF(EffectiveTLDServiceMallocSizeOf)
NS_IMETHODIMP
nsEffectiveTLDService::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return SizeOfIncludingThis(MallocSizeOf);
return MOZ_COLLECT_REPORT(
"explicit/xpcom/effective-TLD-service", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(EffectiveTLDServiceMallocSizeOf),
"Memory used by the effective TLD service.");
}
size_t

View File

@ -106,17 +106,17 @@ private:
};
class nsEffectiveTLDService MOZ_FINAL
: public mozilla::MemoryUniReporter
, public nsIEffectiveTLDService
: public nsIEffectiveTLDService
, public nsIMemoryReporter
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIEFFECTIVETLDSERVICE
NS_DECL_NSIMEMORYREPORTER
nsEffectiveTLDService();
nsresult Init();
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
private:

View File

@ -1915,11 +1915,7 @@ StoreAndNotifyEmbedVisit(VisitData& aPlace,
History* History::gService = nullptr;
History::History()
: MemoryUniReporter("explicit/history-links-hashtable",
KIND_HEAP, UNITS_BYTES,
"Memory used by the hashtable that records changes to the visited state of "
"links.")
, mShuttingDown(false)
: mShuttingDown(false)
, mShutdownMutex("History::mShutdownMutex")
, mObservers(VISIT_OBSERVERS_INITIAL_CACHE_SIZE)
, mRecentlyVisitedURIsNextIndex(0)
@ -2221,10 +2217,17 @@ History::SizeOfEntryExcludingThis(KeyClass* aEntry, mozilla::MallocSizeOf aMallo
return aEntry->array.SizeOfExcludingThis(aMallocSizeOf);
}
int64_t
History::Amount()
MOZ_DEFINE_MALLOC_SIZE_OF(HistoryMallocSizeOf)
NS_IMETHODIMP
History::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return SizeOfIncludingThis(MallocSizeOf);
return MOZ_COLLECT_REPORT(
"explicit/history-links-hashtable", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(HistoryMallocSizeOf),
"Memory used by the hashtable that records changes to the visited state "
"of links.");
}
size_t
@ -2914,13 +2917,13 @@ History::Observe(nsISupports* aSubject, const char* aTopic,
////////////////////////////////////////////////////////////////////////////////
//// nsISupports
NS_IMPL_ISUPPORTS_INHERITED4(
NS_IMPL_ISUPPORTS5(
History
, MemoryUniReporter
, IHistory
, nsIDownloadHistory
, mozIAsyncHistory
, nsIObserver
, nsIMemoryReporter
)
} // namespace places

View File

@ -35,11 +35,11 @@ struct VisitData;
// Max size of History::mRecentlyVisitedURIs
#define RECENTLY_VISITED_URI_SIZE 8
class History : mozilla::MemoryUniReporter
, public IHistory
class History : public IHistory
, public nsIDownloadHistory
, public mozIAsyncHistory
, public nsIObserver
, public nsIMemoryReporter
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
@ -47,6 +47,7 @@ public:
NS_DECL_NSIDOWNLOADHISTORY
NS_DECL_MOZIASYNCHISTORY
NS_DECL_NSIOBSERVER
NS_DECL_NSIMEMORYREPORTER
History();
@ -85,7 +86,6 @@ public:
* Get the number of bytes of memory this History object is using,
* including sizeof(*this))
*/
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
/**

View File

@ -233,11 +233,12 @@ HangReports::GetDuration(unsigned aIndex) const {
}
class TelemetryImpl MOZ_FINAL
: public MemoryUniReporter
, public nsITelemetry
: public nsITelemetry
, public nsIMemoryReporter
{
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITELEMETRY
NS_DECL_NSIMEMORYREPORTER
public:
~TelemetryImpl();
@ -255,7 +256,6 @@ public:
#endif
static void RecordThreadHangStats(Telemetry::ThreadHangStats& aStats);
static nsresult GetHistogramEnumId(const char *name, Telemetry::ID *id);
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
struct Stat {
uint32_t hitCount;
@ -341,10 +341,16 @@ private:
TelemetryImpl* TelemetryImpl::sTelemetry = nullptr;
int64_t
TelemetryImpl::Amount()
MOZ_DEFINE_MALLOC_SIZE_OF(TelemetryMallocSizeOf)
NS_IMETHODIMP
TelemetryImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return SizeOfIncludingThis(MallocSizeOf);
return MOZ_COLLECT_REPORT(
"explicit/telemetry", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(TelemetryMallocSizeOf),
"Memory used by the telemetry system.");
}
size_t
@ -923,8 +929,6 @@ TelemetryImpl::AsyncFetchTelemetryData(nsIFetchTelemetryDataCallback *aCallback)
}
TelemetryImpl::TelemetryImpl():
MemoryUniReporter("explicit/telemetry", KIND_HEAP, UNITS_BYTES,
"Memory used by the telemetry system."),
mHistogramMap(Telemetry::HistogramCount),
mCanRecord(XRE_GetProcessType() == GeckoProcessType_Default),
mHashMutex("Telemetry::mHashMutex"),
@ -2233,7 +2237,7 @@ TelemetryImpl::RecordThreadHangStats(Telemetry::ThreadHangStats& aStats)
sTelemetry->mThreadHangStats.append(Move(aStats));
}
NS_IMPL_ISUPPORTS_INHERITED1(TelemetryImpl, MemoryUniReporter, nsITelemetry)
NS_IMPL_ISUPPORTS2(TelemetryImpl, nsITelemetry, nsIMemoryReporter)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelemetry, TelemetryImpl::CreateTelemetryInstance)
#define NS_TELEMETRY_CID \

View File

@ -331,69 +331,59 @@ LowMemoryEventsVirtualDistinguishedAmount()
return sNumLowVirtualMemEvents;
}
class LowMemoryEventsVirtualReporter MOZ_FINAL : public MemoryUniReporter
{
public:
LowMemoryEventsVirtualReporter()
: MemoryUniReporter("low-memory-events/virtual",
KIND_OTHER, UNITS_COUNT_CUMULATIVE,
"Number of low-virtual-memory events fired since startup. We fire such an "
"event if we notice there is less than memory.low_virtual_mem_threshold_mb of "
"virtual address space available (if zero, this behavior is disabled). The "
"process will probably crash if it runs out of virtual address space, so "
"this event is dire.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
// This memory reporter shouldn't be installed on 64-bit machines, since we
// force-disable virtual-memory tracking there.
MOZ_ASSERT(sizeof(void*) == 4);
return LowMemoryEventsVirtualDistinguishedAmount();
}
};
class LowCommitSpaceEventsReporter MOZ_FINAL : public MemoryUniReporter
{
public:
LowCommitSpaceEventsReporter()
: MemoryUniReporter("low-commit-space-events",
KIND_OTHER, UNITS_COUNT_CUMULATIVE,
"Number of low-commit-space events fired since startup. We fire such an "
"event if we notice there is less than memory.low_commit_space_threshold_mb of "
"commit space available (if zero, this behavior is disabled). Windows will "
"likely kill the process if it runs out of commit space, so this event is "
"dire.")
{}
private:
int64_t Amount() MOZ_OVERRIDE { return sNumLowCommitSpaceEvents; }
};
static int64_t
LowMemoryEventsPhysicalDistinguishedAmount()
{
return sNumLowPhysicalMemEvents;
}
class LowMemoryEventsPhysicalReporter MOZ_FINAL : public MemoryUniReporter
class LowEventsReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
LowMemoryEventsPhysicalReporter()
: MemoryUniReporter("low-memory-events/physical",
KIND_OTHER, UNITS_COUNT_CUMULATIVE,
NS_DECL_ISUPPORTS
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
nsresult rv;
// We only do virtual-memory tracking on 32-bit builds.
if (sizeof(void*) == 4) {
rv = MOZ_COLLECT_REPORT(
"low-memory-events/virtual", KIND_OTHER, UNITS_COUNT_CUMULATIVE,
LowMemoryEventsVirtualDistinguishedAmount(),
"Number of low-virtual-memory events fired since startup. We fire such an "
"event if we notice there is less than memory.low_virtual_mem_threshold_mb of "
"virtual address space available (if zero, this behavior is disabled). The "
"process will probably crash if it runs out of virtual address space, so "
"this event is dire.");
NS_ENSURE_SUCCESS(rv, rv);
}
rv = MOZ_COLLECT_REPORT(
"low-commit-space-events", KIND_OTHER, UNITS_COUNT_CUMULATIVE,
sNumLowCommitSpaceEvents,
"Number of low-commit-space events fired since startup. We fire such an "
"event if we notice there is less than memory.low_commit_space_threshold_mb of "
"commit space available (if zero, this behavior is disabled). Windows will "
"likely kill the process if it runs out of commit space, so this event is "
"dire.");
NS_ENSURE_SUCCESS(rv, rv);
rv = MOZ_COLLECT_REPORT(
"low-memory-events/physical", KIND_OTHER, UNITS_COUNT_CUMULATIVE,
LowMemoryEventsPhysicalDistinguishedAmount(),
"Number of low-physical-memory events fired since startup. We fire such an "
"event if we notice there is less than memory.low_physical_memory_threshold_mb "
"of physical memory available (if zero, this behavior is disabled). The "
"machine will start to page if it runs out of physical memory. This may "
"cause it to run slowly, but it shouldn't cause it to crash.")
{}
"cause it to run slowly, but it shouldn't cause it to crash.");
NS_ENSURE_SUCCESS(rv, rv);
private:
int64_t Amount() MOZ_OVERRIDE { return LowMemoryEventsPhysicalDistinguishedAmount(); }
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(LowEventsReporter, nsIMemoryReporter)
#endif // defined(XP_WIN)
@ -510,11 +500,7 @@ void Activate()
Preferences::AddUintVarCache(&sLowMemoryNotificationIntervalMS,
"memory.low_memory_notification_interval_ms", 10000);
RegisterStrongMemoryReporter(new LowCommitSpaceEventsReporter());
RegisterStrongMemoryReporter(new LowMemoryEventsPhysicalReporter());
if (sizeof(void*) == 4) {
RegisterStrongMemoryReporter(new LowMemoryEventsVirtualReporter());
}
RegisterStrongMemoryReporter(new LowEventsReporter());
RegisterLowMemoryEventsVirtualDistinguishedAmount(LowMemoryEventsVirtualDistinguishedAmount);
RegisterLowMemoryEventsPhysicalDistinguishedAmount(LowMemoryEventsPhysicalDistinguishedAmount);
sHooksActive = true;

View File

@ -506,75 +506,11 @@ void RunReportersForThisProcess();
return moz_malloc_size_of(aPtr); \
}
namespace mozilla {
// The following base class reduces the amount of boilerplate code required for
// memory uni-reporters. You just need to provide the following.
// - The constant values: path, kind, units, and description. They are
// arguments to the MemoryUniReporter constructor.
// - A private Amount() or public GetAmount() method. It can use the
// MallocSizeOf method if necessary. (There is also
// MallocSizeOfOn{Alloc,Free}, which can be useful.) Use Amount() if the
// reporter is infallible, and GetAmount() otherwise. (If you fail to
// provide one or the other, you'll get assertion failures when the memory
// reporter runs.)
//
// The class name of subclasses should match the path, minus the "explicit" (if
// present), and with "Reporter" at the end. For example:
// - path == "explicit/dom/xyzzy" --> DOMXyzzyReporter
// - path == "js-compartments/system" --> JSCompartmentsSystemReporter
//
class MemoryUniReporter : public nsIMemoryReporter
{
public:
MemoryUniReporter(const char* aPath, int32_t aKind, int32_t aUnits,
const char* aDescription)
: mPath(aPath)
, mKind(aKind)
, mUnits(aUnits)
, mDescription(aDescription)
{}
virtual ~MemoryUniReporter() {}
NS_DECL_THREADSAFE_ISUPPORTS
NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCallback,
nsISupports* aData)
{
int64_t amount;
nsresult rv = GetAmount(&amount);
if (NS_WARN_IF(NS_FAILED(rv)))
return rv;
return aCallback->Callback(EmptyCString(), mPath, mKind, mUnits,
amount, mDescription, aData);
}
protected:
NS_IMETHOD GetAmount(int64_t* aAmount)
{
*aAmount = Amount();
return NS_OK;
}
virtual int64_t Amount()
{
// We only reach here if neither GetAmount() nor Amount() was overridden.
MOZ_ASSERT(false);
return 0;
}
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
const nsCString mPath;
const int32_t mKind;
const int32_t mUnits;
const nsCString mDescription;
};
} // namespace mozilla
// This macro assumes the presence of appropriate |aHandleReport| and |aData|
// variables.
#define MOZ_COLLECT_REPORT(path, kind, units, amount, description) \
aHandleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(path), \
kind, units, amount, \
NS_LITERAL_CSTRING(description), aData)
%}

View File

@ -79,48 +79,46 @@ ResidentFastDistinguishedAmount(int64_t* aN)
}
#define HAVE_RESIDENT_UNIQUE_REPORTER
class ResidentUniqueReporter MOZ_FINAL : public MemoryUniReporter
class ResidentUniqueReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
ResidentUniqueReporter()
: MemoryUniReporter("resident-unique", KIND_OTHER, UNITS_BYTES,
NS_DECL_ISUPPORTS
NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
// You might be tempted to calculate USS by subtracting the "shared"
// value from the "resident" value in /proc/<pid>/statm. But at least
// on Linux, statm's "shared" value actually counts pages backed by
// files, which has little to do with whether the pages are actually
// shared. /proc/self/smaps on the other hand appears to give us the
// correct information.
FILE *f = fopen("/proc/self/smaps", "r");
if (NS_WARN_IF(!f))
return NS_ERROR_UNEXPECTED;
int64_t amount = 0;
char line[256];
while (fgets(line, sizeof(line), f)) {
long long val = 0;
if (sscanf(line, "Private_Dirty: %lld kB", &val) == 1 ||
sscanf(line, "Private_Clean: %lld kB", &val) == 1) {
amount += val * 1024; // convert from kB to bytes
}
}
fclose(f);
return MOZ_COLLECT_REPORT(
"resident-unique", KIND_OTHER, UNITS_BYTES, amount,
"Memory mapped by the process that is present in physical memory and not "
"shared with any other processes. This is also known as the process's unique "
"set size (USS). This is the amount of RAM we'd expect to be freed if we "
"closed this process.")
{}
private:
NS_IMETHOD GetAmount(int64_t *aAmount)
{
// You might be tempted to calculate USS by subtracting the "shared" value
// from the "resident" value in /proc/<pid>/statm. But at least on Linux,
// statm's "shared" value actually counts pages backed by files, which has
// little to do with whether the pages are actually shared.
// /proc/self/smaps on the other hand appears to give us the correct
// information.
*aAmount = 0;
FILE *f = fopen("/proc/self/smaps", "r");
if (NS_WARN_IF(!f))
return NS_ERROR_UNEXPECTED;
int64_t total = 0;
char line[256];
while (fgets(line, sizeof(line), f)) {
long long val = 0;
if (sscanf(line, "Private_Dirty: %lld kB", &val) == 1 ||
sscanf(line, "Private_Clean: %lld kB", &val) == 1) {
total += val * 1024; // convert from kB to bytes
}
"closed this process.");
}
*aAmount = total;
fclose(f);
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(ResidentUniqueReporter, nsIMemoryReporter)
#elif defined(__DragonFly__) || defined(__FreeBSD__) \
|| defined(__NetBSD__) || defined(__OpenBSD__)
@ -241,9 +239,8 @@ PrivateDistinguishedAmount(int64_t* aN)
{
int64_t priv;
nsresult rv = GetKinfoVmentrySelf(&priv, NULL);
if (NS_SUCCEEDED(rv))
*aN = priv * getpagesize();
NS_ENSURE_SUCCESS(rv, rv);
*aN = priv * getpagesize();
return NS_OK;
}
@ -491,78 +488,98 @@ PrivateDistinguishedAmount(int64_t* aN)
#endif // XP_<PLATFORM>
#ifdef HAVE_VSIZE_MAX_CONTIGUOUS_REPORTER
class VsizeMaxContiguousReporter MOZ_FINAL : public MemoryUniReporter
class VsizeMaxContiguousReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
VsizeMaxContiguousReporter()
: MemoryUniReporter("vsize-max-contiguous", KIND_OTHER, UNITS_BYTES,
"Size of the maximum contiguous block of available virtual memory.")
{}
NS_DECL_ISUPPORTS
NS_IMETHOD GetAmount(int64_t* aAmount)
NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return VsizeMaxContiguousDistinguishedAmount(aAmount);
int64_t amount;
nsresult rv = VsizeMaxContiguousDistinguishedAmount(&amount);
NS_ENSURE_SUCCESS(rv, rv);
return MOZ_COLLECT_REPORT(
"vsize-max-contiguous", KIND_OTHER, UNITS_BYTES, amount,
"Size of the maximum contiguous block of available virtual "
"memory.");
}
};
NS_IMPL_ISUPPORTS1(VsizeMaxContiguousReporter, nsIMemoryReporter)
#endif
#ifdef HAVE_PRIVATE_REPORTER
class PrivateReporter MOZ_FINAL : public MemoryUniReporter
class PrivateReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
PrivateReporter()
: MemoryUniReporter("private", KIND_OTHER, UNITS_BYTES,
NS_DECL_ISUPPORTS
NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
int64_t amount;
nsresult rv = PrivateDistinguishedAmount(&amount);
NS_ENSURE_SUCCESS(rv, rv);
return MOZ_COLLECT_REPORT(
"private", KIND_OTHER, UNITS_BYTES, amount,
"Memory that cannot be shared with other processes, including memory that is "
"committed and marked MEM_PRIVATE, data that is not mapped, and executable "
"pages that have been written to.")
{}
NS_IMETHOD GetAmount(int64_t* aAmount)
{
return PrivateDistinguishedAmount(aAmount);
"pages that have been written to.");
}
};
NS_IMPL_ISUPPORTS1(PrivateReporter, nsIMemoryReporter)
#endif
#ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
class VsizeReporter MOZ_FINAL : public MemoryUniReporter
class VsizeReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
VsizeReporter()
: MemoryUniReporter("vsize", KIND_OTHER, UNITS_BYTES,
NS_DECL_ISUPPORTS
NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
int64_t amount;
nsresult rv = VsizeDistinguishedAmount(&amount);
NS_ENSURE_SUCCESS(rv, rv);
return MOZ_COLLECT_REPORT(
"vsize", KIND_OTHER, UNITS_BYTES, amount,
"Memory mapped by the process, including code and data segments, the heap, "
"thread stacks, memory explicitly mapped by the process via mmap and similar "
"operations, and memory shared with other processes. This is the vsize figure "
"as reported by 'top' and 'ps'. This figure is of limited use on Mac, where "
"processes share huge amounts of memory with one another. But even on other "
"operating systems, 'resident' is a much better measure of the memory "
"resources used by the process.")
{}
NS_IMETHOD GetAmount(int64_t* aAmount)
{
return VsizeDistinguishedAmount(aAmount);
"resources used by the process.");
}
};
NS_IMPL_ISUPPORTS1(VsizeReporter, nsIMemoryReporter)
class ResidentReporter MOZ_FINAL : public MemoryUniReporter
class ResidentReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
ResidentReporter()
: MemoryUniReporter("resident", KIND_OTHER, UNITS_BYTES,
NS_DECL_ISUPPORTS
NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
int64_t amount;
nsresult rv = ResidentDistinguishedAmount(&amount);
NS_ENSURE_SUCCESS(rv, rv);
return MOZ_COLLECT_REPORT(
"resident", KIND_OTHER, UNITS_BYTES, amount,
"Memory mapped by the process that is present in physical memory, also known "
"as the resident set size (RSS). This is the best single figure to use when "
"considering the memory resources used by the process, but it depends both on "
"other processes being run and details of the OS kernel and so is best used "
"for comparing the memory usage of a single process at different points in "
"time.")
{}
NS_IMETHOD GetAmount(int64_t* aAmount)
{
return ResidentDistinguishedAmount(aAmount);
"time.");
}
};
NS_IMPL_ISUPPORTS1(ResidentReporter, nsIMemoryReporter)
#endif // HAVE_VSIZE_AND_RESIDENT_REPORTERS
#ifdef XP_UNIX
@ -571,12 +588,23 @@ public:
#define HAVE_PAGE_FAULT_REPORTERS 1
class PageFaultsSoftReporter MOZ_FINAL : public MemoryUniReporter
class PageFaultsSoftReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
PageFaultsSoftReporter()
: MemoryUniReporter("page-faults-soft", KIND_OTHER,
UNITS_COUNT_CUMULATIVE,
NS_DECL_ISUPPORTS
NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
struct rusage usage;
int err = getrusage(RUSAGE_SELF, &usage);
if (err != 0) {
return NS_ERROR_FAILURE;
}
int64_t amount = usage.ru_minflt;
return MOZ_COLLECT_REPORT(
"page-faults-soft", KIND_OTHER, UNITS_COUNT_CUMULATIVE, amount,
"The number of soft page faults (also known as 'minor page faults') that "
"have occurred since the process started. A soft page fault occurs when the "
"process tries to access a page which is present in physical memory but is "
@ -585,20 +613,10 @@ public:
"present in physical memory. A process may experience many thousands of soft "
"page faults even when the machine has plenty of available physical memory, "
"and because the OS services a soft page fault without accessing the disk, "
"they impact performance much less than hard page faults.")
{}
NS_IMETHOD GetAmount(int64_t* aAmount)
{
struct rusage usage;
int err = getrusage(RUSAGE_SELF, &usage);
if (err != 0) {
return NS_ERROR_FAILURE;
}
*aAmount = usage.ru_minflt;
return NS_OK;
"they impact performance much less than hard page faults.");
}
};
NS_IMPL_ISUPPORTS1(PageFaultsSoftReporter, nsIMemoryReporter)
static nsresult
PageFaultsHardDistinguishedAmount(int64_t* aAmount)
@ -612,12 +630,20 @@ PageFaultsHardDistinguishedAmount(int64_t* aAmount)
return NS_OK;
}
class PageFaultsHardReporter MOZ_FINAL : public MemoryUniReporter
class PageFaultsHardReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
PageFaultsHardReporter()
: MemoryUniReporter("page-faults-hard", KIND_OTHER,
UNITS_COUNT_CUMULATIVE,
NS_DECL_ISUPPORTS
NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
int64_t amount;
nsresult rv = PageFaultsHardDistinguishedAmount(&amount);
NS_ENSURE_SUCCESS(rv, rv);
return MOZ_COLLECT_REPORT(
"page-faults-hard", KIND_OTHER, UNITS_COUNT_CUMULATIVE, amount,
"The number of hard page faults (also known as 'major page faults') that have "
"occurred since the process started. A hard page fault occurs when a process "
"tries to access a page which is not present in physical memory. The "
@ -626,14 +652,12 @@ public:
"the process tries to use more memory than your machine has available, you "
"may see many thousands of hard page faults. Because accessing the disk is up "
"to a million times slower than accessing RAM, the program may run very "
"slowly when it is experiencing more than 100 or so hard page faults a second.")
{}
NS_IMETHOD GetAmount(int64_t* aAmount)
{
return PageFaultsHardDistinguishedAmount(aAmount);
"slowly when it is experiencing more than 100 or so hard page faults a "
"second.");
}
};
NS_IMPL_ISUPPORTS1(PageFaultsHardReporter, nsIMemoryReporter)
#endif // HAVE_PAGE_FAULT_REPORTERS
/**
@ -644,134 +668,88 @@ public:
#ifdef HAVE_JEMALLOC_STATS
// This has UNITS_PERCENTAGE, so it is multiplied by 100.
static int64_t
HeapAllocated()
HeapOverheadRatio(jemalloc_stats_t* aStats)
{
jemalloc_stats_t stats;
jemalloc_stats(&stats);
return (int64_t) stats.allocated;
}
// This has UNITS_PERCENTAGE, so it is multiplied by 100x.
static int64_t
HeapOverheadRatio()
{
jemalloc_stats_t stats;
jemalloc_stats(&stats);
return (int64_t) 10000 *
(stats.waste + stats.bookkeeping + stats.page_cache) /
((double)stats.allocated);
(aStats->waste + aStats->bookkeeping + aStats->page_cache) /
((double)aStats->allocated);
}
class HeapAllocatedReporter MOZ_FINAL : public MemoryUniReporter
class JemallocHeapReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
HeapAllocatedReporter()
: MemoryUniReporter("heap-allocated", KIND_OTHER, UNITS_BYTES,
NS_DECL_ISUPPORTS
NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
jemalloc_stats_t stats;
jemalloc_stats(&stats);
nsresult rv;
rv = MOZ_COLLECT_REPORT(
"heap-allocated", KIND_OTHER, UNITS_BYTES, stats.allocated,
"Memory mapped by the heap allocator that is currently allocated to the "
"application. This may exceed the amount of memory requested by the "
"application because the allocator regularly rounds up request sizes. (The "
"exact amount requested is not recorded.)")
{}
private:
int64_t Amount() MOZ_OVERRIDE { return HeapAllocated(); }
};
"exact amount requested is not recorded.)");
NS_ENSURE_SUCCESS(rv, rv);
class HeapOverheadWasteReporter MOZ_FINAL : public MemoryUniReporter
{
public:
// We mark this and the other heap-overhead reporters as KIND_NONHEAP
// because KIND_HEAP memory means "counted in heap-allocated", which this
// is not.
HeapOverheadWasteReporter()
: MemoryUniReporter("explicit/heap-overhead/waste",
KIND_NONHEAP, UNITS_BYTES,
// We mark this and the other heap-overhead reporters as KIND_NONHEAP
// because KIND_HEAP memory means "counted in heap-allocated", which
// this is not.
rv = MOZ_COLLECT_REPORT(
"explicit/heap-overhead/waste", KIND_NONHEAP, UNITS_BYTES,
stats.waste,
"Committed bytes which do not correspond to an active allocation and which the "
"allocator is not intentionally keeping alive (i.e., not 'heap-bookkeeping' or "
"'heap-page-cache'). Although the allocator will waste some space under any "
"circumstances, a large value here may indicate that the heap is highly "
"fragmented, or that allocator is performing poorly for some other reason.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
jemalloc_stats_t stats;
jemalloc_stats(&stats);
return stats.waste;
}
};
"fragmented, or that allocator is performing poorly for some other reason.");
NS_ENSURE_SUCCESS(rv, rv);
class HeapOverheadBookkeepingReporter MOZ_FINAL : public MemoryUniReporter
{
public:
HeapOverheadBookkeepingReporter()
: MemoryUniReporter("explicit/heap-overhead/bookkeeping",
KIND_NONHEAP, UNITS_BYTES,
"Committed bytes which the heap allocator uses for internal data structures.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
jemalloc_stats_t stats;
jemalloc_stats(&stats);
return stats.bookkeeping;
}
};
rv = MOZ_COLLECT_REPORT(
"explicit/heap-overhead/bookkeeping", KIND_NONHEAP, UNITS_BYTES,
stats.bookkeeping,
"Committed bytes which the heap allocator uses for internal data "
"structures.");
NS_ENSURE_SUCCESS(rv, rv);
class HeapOverheadPageCacheReporter MOZ_FINAL : public MemoryUniReporter
{
public:
HeapOverheadPageCacheReporter()
: MemoryUniReporter("explicit/heap-overhead/page-cache",
KIND_NONHEAP, UNITS_BYTES,
rv = MOZ_COLLECT_REPORT(
"explicit/heap-overhead/page-cache", KIND_NONHEAP, UNITS_BYTES,
stats.page_cache,
"Memory which the allocator could return to the operating system, but hasn't. "
"The allocator keeps this memory around as an optimization, so it doesn't "
"have to ask the OS the next time it needs to fulfill a request. This value "
"is typically not larger than a few megabytes.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
jemalloc_stats_t stats;
jemalloc_stats(&stats);
return (int64_t) stats.page_cache;
}
};
"is typically not larger than a few megabytes.");
NS_ENSURE_SUCCESS(rv, rv);
class HeapCommittedReporter MOZ_FINAL : public MemoryUniReporter
{
public:
HeapCommittedReporter()
: MemoryUniReporter("heap-committed", KIND_OTHER, UNITS_BYTES,
rv = MOZ_COLLECT_REPORT(
"heap-committed", KIND_OTHER, UNITS_BYTES,
stats.allocated + stats.waste + stats.bookkeeping + stats.page_cache,
"Memory mapped by the heap allocator that is committed, i.e. in physical "
"memory or paged to disk. This value corresponds to 'heap-allocated' + "
"'heap-waste' + 'heap-bookkeeping' + 'heap-page-cache', but because "
"these values are read at different times, the result probably won't match "
"exactly.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
jemalloc_stats_t stats;
jemalloc_stats(&stats);
return (int64_t) (stats.allocated + stats.waste +
stats.bookkeeping + stats.page_cache);
}
};
"exactly.");
NS_ENSURE_SUCCESS(rv, rv);
class HeapOverheadRatioReporter MOZ_FINAL : public MemoryUniReporter
{
public:
HeapOverheadRatioReporter()
: MemoryUniReporter("heap-overhead-ratio", KIND_OTHER,
UNITS_PERCENTAGE,
rv = MOZ_COLLECT_REPORT(
"heap-overhead-ratio", KIND_OTHER, UNITS_PERCENTAGE,
HeapOverheadRatio(&stats),
"Ratio of committed, unused bytes to allocated bytes; i.e., "
"'heap-overhead' / 'heap-allocated'. This measures the overhead of "
"the heap allocator relative to amount of memory allocated.")
{}
private:
int64_t Amount() MOZ_OVERRIDE { return HeapOverheadRatio(); }
"the heap allocator relative to amount of memory allocated.");
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(JemallocHeapReporter, nsIMemoryReporter)
#endif // HAVE_JEMALLOC_STATS
// Why is this here? At first glance, you'd think it could be defined and
@ -779,19 +757,23 @@ private:
// However, the obvious time to register it is when the table is initialized,
// and that happens before XPCOM components are initialized, which means the
// RegisterStrongMemoryReporter call fails. So instead we do it here.
class AtomTablesReporter MOZ_FINAL : public MemoryUniReporter
class AtomTablesReporter MOZ_FINAL : public nsIMemoryReporter
{
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
public:
AtomTablesReporter()
: MemoryUniReporter("explicit/atom-tables", KIND_HEAP, UNITS_BYTES,
"Memory used by the dynamic and static atoms tables.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
NS_DECL_ISUPPORTS
NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return NS_SizeOfAtomTablesIncludingThis(MallocSizeOf);
return MOZ_COLLECT_REPORT(
"explicit/atom-tables", KIND_HEAP, UNITS_BYTES,
NS_SizeOfAtomTablesIncludingThis(MallocSizeOf),
"Memory used by the dynamic and static atoms tables.");
}
};
NS_IMPL_ISUPPORTS1(AtomTablesReporter, nsIMemoryReporter)
#ifdef MOZ_DMD
@ -813,8 +795,7 @@ public:
do { \
nsresult rv; \
rv = aHandleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
nsIMemoryReporter::KIND_HEAP, \
nsIMemoryReporter::UNITS_BYTES, _amount, \
KIND_HEAP, UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), aData); \
if (NS_WARN_IF(NS_FAILED(rv))) \
return rv; \
@ -843,7 +824,6 @@ public:
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(DMDReporter, nsIMemoryReporter)
} // namespace dmd
@ -866,12 +846,7 @@ nsMemoryReporterManager::Init()
#endif
#ifdef HAVE_JEMALLOC_STATS
RegisterStrongReporter(new HeapAllocatedReporter());
RegisterStrongReporter(new HeapOverheadWasteReporter());
RegisterStrongReporter(new HeapOverheadBookkeepingReporter());
RegisterStrongReporter(new HeapOverheadPageCacheReporter());
RegisterStrongReporter(new HeapCommittedReporter());
RegisterStrongReporter(new HeapOverheadRatioReporter());
RegisterStrongReporter(new JemallocHeapReporter());
#endif
#ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
@ -1510,7 +1485,9 @@ NS_IMETHODIMP
nsMemoryReporterManager::GetHeapAllocated(int64_t* aAmount)
{
#ifdef HAVE_JEMALLOC_STATS
*aAmount = HeapAllocated();
jemalloc_stats_t stats;
jemalloc_stats(&stats);
*aAmount = stats.allocated;
return NS_OK;
#else
*aAmount = 0;
@ -1523,7 +1500,9 @@ NS_IMETHODIMP
nsMemoryReporterManager::GetHeapOverheadRatio(int64_t* aAmount)
{
#ifdef HAVE_JEMALLOC_STATS
*aAmount = HeapOverheadRatio();
jemalloc_stats_t stats;
jemalloc_stats(&stats);
*aAmount = HeapOverheadRatio(&stats);
return NS_OK;
#else
*aAmount = 0;
@ -1760,11 +1739,6 @@ nsMemoryReporterManager::SizeOfTab(nsIDOMWindow* aTopWindow,
return NS_OK;
}
// Most memory reporters don't need thread safety, but some do. Make them all
// thread-safe just to be safe. Memory reporters are created and destroyed
// infrequently enough that the performance cost should be negligible.
NS_IMPL_ISUPPORTS1(MemoryUniReporter, nsIMemoryReporter)
namespace mozilla {
nsresult

View File

@ -337,12 +337,12 @@ NS_InitXPCOM(nsIServiceManager* *result,
return NS_InitXPCOM2(result, binDirectory, nullptr);
}
class ICUReporter MOZ_FINAL : public MemoryUniReporter
class ICUReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
NS_DECL_ISUPPORTS
ICUReporter()
: MemoryUniReporter("explicit/icu", KIND_HEAP, UNITS_BYTES,
"Memory used by ICU, a Unicode and globalization support library.")
{
#ifdef DEBUG
// There must be only one instance of this class, due to |sAmount|
@ -385,9 +385,21 @@ private:
// must be thread-safe.
static Atomic<size_t> sAmount;
int64_t Amount() MOZ_OVERRIDE { return sAmount; }
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
NS_IMETHODIMP
CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData)
{
return MOZ_COLLECT_REPORT(
"explicit/icu", KIND_HEAP, UNITS_BYTES, sAmount,
"Memory used by ICU, a Unicode and globalization support library.");
}
};
NS_IMPL_ISUPPORTS1(ICUReporter, nsIMemoryReporter)
/* static */ Atomic<size_t> ICUReporter::sAmount;
EXPORT_XPCOM_API(nsresult)

View File

@ -400,7 +400,7 @@ CategoryEnumerator::enumfunc_createenumerator(const char* aStr, CategoryNode* aN
// nsCategoryManager implementations
//
NS_IMPL_QUERY_INTERFACE_INHERITED1(nsCategoryManager, MemoryUniReporter, nsICategoryManager)
NS_IMPL_QUERY_INTERFACE2(nsCategoryManager, nsICategoryManager, nsIMemoryReporter)
NS_IMETHODIMP_(nsrefcnt)
nsCategoryManager::AddRef()
@ -441,10 +441,7 @@ nsCategoryManager::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
}
nsCategoryManager::nsCategoryManager()
: MemoryUniReporter("explicit/xpcom/category-manager",
KIND_HEAP, UNITS_BYTES,
"Memory used for the XPCOM category manager.")
, mLock("nsCategoryManager")
: mLock("nsCategoryManager")
, mSuppressNotifications(false)
{
PL_INIT_ARENA_POOL(&mArena, "CategoryManagerArena",
@ -478,10 +475,16 @@ nsCategoryManager::get_category(const char* aName) {
return node;
}
int64_t
nsCategoryManager::Amount()
MOZ_DEFINE_MALLOC_SIZE_OF(CategoryManagerMallocSizeOf)
NS_IMETHODIMP
nsCategoryManager::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return SizeOfIncludingThis(MallocSizeOf);
return MOZ_COLLECT_REPORT(
"explicit/xpcom/category-manager", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(CategoryManagerMallocSizeOf),
"Memory used for the XPCOM category manager.");
}
static size_t

View File

@ -98,12 +98,13 @@ private:
* This implementation is thread-safe.
*/
class nsCategoryManager MOZ_FINAL
: public mozilla::MemoryUniReporter
, public nsICategoryManager
: public nsICategoryManager
, public nsIMemoryReporter
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICATEGORYMANAGER
NS_DECL_NSIMEMORYREPORTER
/**
* Suppress or unsuppress notifications of category changes to the
@ -124,8 +125,6 @@ public:
static nsCategoryManager* GetSingleton();
static void Destroy();
int64_t Amount() MOZ_OVERRIDE;
private:
static nsCategoryManager* gCategoryManager;

View File

@ -297,10 +297,7 @@ nsComponentManagerImpl::Create(nsISupports* aOuter, REFNSIID aIID, void** aResul
static const int CONTRACTID_HASHTABLE_INITIAL_SIZE = 2048;
nsComponentManagerImpl::nsComponentManagerImpl()
: MemoryUniReporter("explicit/xpcom/component-manager",
KIND_HEAP, UNITS_BYTES,
"Memory used for the XPCOM component manager.")
, mFactories(CONTRACTID_HASHTABLE_INITIAL_SIZE)
: mFactories(CONTRACTID_HASHTABLE_INITIAL_SIZE)
, mContractIDs(CONTRACTID_HASHTABLE_INITIAL_SIZE)
, mLock("nsComponentManagerImpl.mLock")
, mStatus(NOT_INITIALIZED)
@ -818,14 +815,14 @@ nsComponentManagerImpl::~nsComponentManagerImpl()
PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Destroyed."));
}
NS_IMPL_ISUPPORTS_INHERITED5(
NS_IMPL_ISUPPORTS6(
nsComponentManagerImpl,
MemoryUniReporter,
nsIComponentManager,
nsIServiceManager,
nsIComponentRegistrar,
nsISupportsWeakReference,
nsIInterfaceRequestor)
nsIInterfaceRequestor,
nsIMemoryReporter)
nsresult
nsComponentManagerImpl::GetInterface(const nsIID & uuid, void **result)
@ -1690,10 +1687,16 @@ SizeOfContractIDsEntryExcludingThis(nsCStringHashKey::KeyType aKey,
return aKey.SizeOfExcludingThisMustBeUnshared(aMallocSizeOf);
}
int64_t
nsComponentManagerImpl::Amount()
MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf)
NS_IMETHODIMP
nsComponentManagerImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return SizeOfIncludingThis(MallocSizeOf);
return MOZ_COLLECT_REPORT(
"explicit/xpcom/component-manager", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(ComponentManagerMallocSizeOf),
"Memory used for the XPCOM component manager.");
}
size_t

View File

@ -119,18 +119,19 @@ typedef mozilla::BaseAutoLock<SafeMutex> SafeMutexAutoLock;
typedef mozilla::BaseAutoUnlock<SafeMutex> SafeMutexAutoUnlock;
class nsComponentManagerImpl MOZ_FINAL
: public mozilla::MemoryUniReporter
, public nsIComponentManager
: public nsIComponentManager
, public nsIServiceManager
, public nsSupportsWeakReference
, public nsIComponentRegistrar
, public nsIInterfaceRequestor
, public nsIMemoryReporter
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICOMPONENTMANAGER
NS_DECL_NSICOMPONENTREGISTRAR
NS_DECL_NSIMEMORYREPORTER
static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
@ -313,7 +314,6 @@ public:
nsTArray<PendingServiceInfo> mPendingServices;
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
private:

View File

@ -26,11 +26,12 @@ class xptiTypelibGuts;
namespace mozilla {
class XPTInterfaceInfoManager MOZ_FINAL
: public mozilla::MemoryUniReporter
, public nsIInterfaceInfoManager
: public nsIInterfaceInfoManager
, public nsIMemoryReporter
{
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINTERFACEINFOMANAGER
NS_DECL_NSIMEMORYREPORTER
public:
// GetSingleton() is infallible
@ -49,7 +50,6 @@ public:
xptiInterfaceEntry* GetInterfaceEntryForIID(const nsIID *iid);
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
int64_t Amount() MOZ_OVERRIDE;
private:
XPTInterfaceInfoManager();

View File

@ -22,10 +22,10 @@
using namespace mozilla;
NS_IMPL_ISUPPORTS_INHERITED1(
NS_IMPL_ISUPPORTS2(
XPTInterfaceInfoManager,
MemoryUniReporter,
nsIInterfaceInfoManager)
nsIInterfaceInfoManager,
nsIMemoryReporter)
static StaticRefPtr<XPTInterfaceInfoManager> gInterfaceInfoManager;
@ -41,17 +41,22 @@ XPTInterfaceInfoManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
return n;
}
int64_t
XPTInterfaceInfoManager::Amount()
MOZ_DEFINE_MALLOC_SIZE_OF(XPTIMallocSizeOf)
NS_IMETHODIMP
XPTInterfaceInfoManager::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
size_t n = SizeOfIncludingThis(MallocSizeOf);
size_t amount = SizeOfIncludingThis(XPTIMallocSizeOf);
// Measure gXPTIStructArena here, too. This is a bit grotty because it
// doesn't belong to the XPTIInterfaceInfoManager, but there's no
// obviously better place to measure it.
n += XPT_SizeOfArena(gXPTIStructArena, MallocSizeOf);
amount += XPT_SizeOfArena(gXPTIStructArena, XPTIMallocSizeOf);
return n;
return MOZ_COLLECT_REPORT(
"explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES, amount,
"Memory used by the XPCOM typelib system.");
}
// static
@ -72,9 +77,7 @@ XPTInterfaceInfoManager::FreeInterfaceInfoManager()
}
XPTInterfaceInfoManager::XPTInterfaceInfoManager()
: MemoryUniReporter("explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES,
"Memory used by the XPCOM typelib system."),
mWorkingSet(),
: mWorkingSet(),
mResolveLock("XPTInterfaceInfoManager.mResolveLock")
{
}