зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. CLOSED TREE
This commit is contained in:
Коммит
952908fda0
|
@ -189,9 +189,6 @@ dom/media/webspeech/**
|
|||
dom/messagechannel/**
|
||||
dom/midi/**
|
||||
dom/network/**
|
||||
dom/notification/Notification*.*
|
||||
dom/notification/test/browser/**
|
||||
dom/notification/test/mochitest/**
|
||||
dom/payments/**
|
||||
dom/performance/**
|
||||
dom/permission/**
|
||||
|
|
|
@ -811,8 +811,7 @@ nsresult Accessible::HandleAccEvent(AccEvent* aEvent) {
|
|||
nsAutoCString strMarker;
|
||||
strMarker.AppendLiteral("A11y Event - ");
|
||||
strMarker.Append(strEventType);
|
||||
profiler_add_marker(strMarker.get(),
|
||||
js::ProfilingStackFrame::Category::OTHER);
|
||||
profiler_add_marker(strMarker.get(), JS::ProfilingCategoryPair::OTHER);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ browser.jar:
|
|||
skin/classic/browser/places/editBookmark.css (places/editBookmark.css)
|
||||
* skin/classic/browser/places/sidebar.css (places/sidebar.css)
|
||||
skin/classic/browser/places/organizer.css (places/organizer.css)
|
||||
skin/classic/browser/places/organizer.xml (places/organizer.xml)
|
||||
skin/classic/browser/places/toolbarDropMarker.png (places/toolbarDropMarker.png)
|
||||
skin/classic/browser/preferences/alwaysAsk.png (preferences/alwaysAsk.png)
|
||||
skin/classic/browser/preferences/preferences.css (preferences/preferences.css)
|
||||
|
|
|
@ -61,7 +61,6 @@
|
|||
/* Menu */
|
||||
#placesMenu > menu {
|
||||
padding-inline-start: 4px;
|
||||
-moz-binding: url("chrome://browser/skin/places/organizer.xml#toolbarbutton-dropdown");
|
||||
-moz-appearance: toolbarbutton;
|
||||
}
|
||||
|
||||
|
@ -71,7 +70,9 @@
|
|||
color: ButtonText;
|
||||
}
|
||||
|
||||
#placesMenu > menu > .menubar-right {
|
||||
#placesMenu > menu::after {
|
||||
content: "";
|
||||
display: -moz-box;
|
||||
-moz-appearance: toolbarbutton-dropdown;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<bindings id="organizerBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<binding id="toolbarbutton-dropdown"
|
||||
extends="chrome://global/content/bindings/menu.xml#menu-base">
|
||||
<content>
|
||||
<xul:image class="menubar-left" xbl:inherits="src=image"/>
|
||||
<xul:label class="menubar-text" xbl:inherits="value=label,accesskey,crop" crop="right"/>
|
||||
<xul:hbox class="menubar-right"/>
|
||||
<children includes="menupopup"/>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
|
@ -7,7 +7,7 @@ const { L10N } = require("devtools/client/performance/modules/global");
|
|||
|
||||
/**
|
||||
* Details about each label stack frame category.
|
||||
* To be kept in sync with the js::ProfilingStackFrame::Category in ProfilingStack.h
|
||||
* To be kept in sync with the JS::ProfilingCategory enum in ProfilingCategory.h
|
||||
*/
|
||||
const CATEGORIES = [{
|
||||
color: "#d99b28",
|
||||
|
|
|
@ -138,7 +138,7 @@ CustomizedReload.prototype = {
|
|||
if (this.injectedScript) {
|
||||
// Listen to the newly created document elements only if there is an
|
||||
// injectedScript to evaluate.
|
||||
Services.obs.addObserver(this, "document-element-inserted");
|
||||
Services.obs.addObserver(this, "initial-document-element-inserted");
|
||||
}
|
||||
|
||||
// Watch the loading progress and clear the current CustomizedReload once the
|
||||
|
@ -159,7 +159,7 @@ CustomizedReload.prototype = {
|
|||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
if (topic !== "document-element-inserted") {
|
||||
if (topic !== "initial-document-element-inserted") {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -232,7 +232,7 @@ CustomizedReload.prototype = {
|
|||
this.docShell.removeProgressListener(this);
|
||||
|
||||
if (this.injectedScript) {
|
||||
Services.obs.removeObserver(this, "document-element-inserted");
|
||||
Services.obs.removeObserver(this, "initial-document-element-inserted");
|
||||
}
|
||||
|
||||
// Reset the customized user agent.
|
||||
|
|
|
@ -9363,6 +9363,7 @@ class UnblockParsingPromiseHandler final : public PromiseNativeHandler {
|
|||
mParser = do_GetWeakReference(parser);
|
||||
mDocument = aDocument;
|
||||
mDocument->BlockOnload();
|
||||
mDocument->BlockDOMContentLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9396,9 +9397,17 @@ class UnblockParsingPromiseHandler final : public PromiseNativeHandler {
|
|||
if (parser == docParser) {
|
||||
parser->UnblockParser();
|
||||
parser->ContinueInterruptedParsingAsync();
|
||||
mDocument->UnblockOnload(false);
|
||||
}
|
||||
}
|
||||
if (mDocument) {
|
||||
// We blocked DOMContentLoaded and load events on this document. Unblock
|
||||
// them. Note that we want to do that no matter what's going on with the
|
||||
// parser state for this document. Maybe someone caused it to stop being
|
||||
// parsed, so CreatorParserOrNull() is returning null, but we still want
|
||||
// to unblock these.
|
||||
mDocument->UnblockDOMContentLoaded();
|
||||
mDocument->UnblockOnload(false);
|
||||
}
|
||||
mParser = nullptr;
|
||||
mDocument = nullptr;
|
||||
}
|
||||
|
|
|
@ -973,6 +973,31 @@ int32_t Element::ScrollWidth() {
|
|||
}
|
||||
|
||||
nsRect Element::GetClientAreaRect() {
|
||||
Document* doc = OwnerDoc();
|
||||
nsPresContext* presContext = doc->GetPresContext();
|
||||
|
||||
// We can avoid a layout flush if this is the scrolling element of the
|
||||
// document, we have overlay scrollbars, and we aren't embedded in another
|
||||
// document
|
||||
bool overlayScrollbars =
|
||||
LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0;
|
||||
bool rootContentDocument =
|
||||
presContext && presContext->IsRootContentDocument();
|
||||
if (overlayScrollbars && rootContentDocument &&
|
||||
doc->IsScrollingElement(this)) {
|
||||
// We will always have a pres shell if we have a pres context, and we will
|
||||
// only get here if we have a pres context from the root content document
|
||||
// check
|
||||
nsIPresShell* presShell = doc->GetShell();
|
||||
|
||||
// Ensure up to date dimensions, but don't reflow
|
||||
RefPtr<nsViewManager> viewManager = presShell->GetViewManager();
|
||||
if (viewManager) {
|
||||
viewManager->FlushDelayedResize(false);
|
||||
}
|
||||
return nsRect(nsPoint(), presContext->GetVisibleArea().Size());
|
||||
}
|
||||
|
||||
nsIFrame* frame;
|
||||
nsIScrollableFrame* sf = GetScrollFrame(&frame);
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ void TimeoutManager::MoveIdleToActive() {
|
|||
int(delta.ToMilliseconds()));
|
||||
// don't have end before start...
|
||||
profiler_add_marker(
|
||||
"setTimeout deferred release", js::ProfilingStackFrame::Category::DOM,
|
||||
"setTimeout deferred release", JS::ProfilingCategoryPair::DOM,
|
||||
MakeUnique<TextMarkerPayload>(
|
||||
marker, delta.ToMilliseconds() >= 0 ? timeout->When() : now,
|
||||
now));
|
||||
|
@ -960,7 +960,7 @@ void TimeoutManager::RunTimeout(const TimeStamp& aNow,
|
|||
int(delta.ToMilliseconds()), int(runtime.ToMilliseconds()));
|
||||
// don't have end before start...
|
||||
profiler_add_marker(
|
||||
"setTimeout", js::ProfilingStackFrame::Category::DOM,
|
||||
"setTimeout", JS::ProfilingCategoryPair::DOM,
|
||||
MakeUnique<TextMarkerPayload>(
|
||||
marker, delta.ToMilliseconds() >= 0 ? timeout->When() : now,
|
||||
now));
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "nsViewManager.h"
|
||||
#include "nsAtom.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsGlobalWindowInner.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsIOfflineCacheUpdate.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
|
@ -1553,10 +1554,20 @@ void nsContentSink::NotifyDocElementCreated(Document* aDoc) {
|
|||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
observerService->NotifyObservers(
|
||||
ToSupports(aDoc), "document-element-inserted", EmptyString().get());
|
||||
MOZ_ASSERT(observerService);
|
||||
|
||||
auto* win = nsGlobalWindowInner::Cast(aDoc->GetInnerWindow());
|
||||
bool fireInitialInsertion = !win || !win->DidFireDocElemInserted();
|
||||
if (win) {
|
||||
win->SetDidFireDocElemInserted();
|
||||
}
|
||||
if (fireInitialInsertion) {
|
||||
observerService->NotifyObservers(ToSupports(aDoc),
|
||||
"initial-document-element-inserted",
|
||||
EmptyString().get());
|
||||
}
|
||||
observerService->NotifyObservers(
|
||||
ToSupports(aDoc), "document-element-inserted", EmptyString().get());
|
||||
|
||||
nsContentUtils::DispatchChromeEvent(
|
||||
aDoc, ToSupports(aDoc), NS_LITERAL_STRING("DOMDocElementInserted"),
|
||||
|
|
|
@ -162,7 +162,7 @@ void nsDOMNavigationTiming::NotifyLoadEventEnd() {
|
|||
DECLARE_DOCSHELL_AND_HISTORY_ID(mDocShell);
|
||||
PAGELOAD_LOG(("%s", marker.get()));
|
||||
profiler_add_marker(
|
||||
"DocumentLoad", js::ProfilingStackFrame::Category::DOM,
|
||||
"DocumentLoad", JS::ProfilingCategoryPair::DOM,
|
||||
MakeUnique<TextMarkerPayload>(marker, mNavigationStart, mLoadEventEnd,
|
||||
docShellId, docShellHistoryId));
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ void nsDOMNavigationTiming::TTITimeout(nsITimer* aTimer) {
|
|||
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(mDocShell);
|
||||
profiler_add_marker(
|
||||
"TTFI", js::ProfilingStackFrame::Category::DOM,
|
||||
"TTFI", JS::ProfilingCategoryPair::DOM,
|
||||
MakeUnique<TextMarkerPayload>(marker, mNavigationStart, mTTFI,
|
||||
docShellId, docShellHistoryId));
|
||||
}
|
||||
|
@ -392,7 +392,7 @@ void nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument() {
|
|||
PAGELOAD_LOG(("%s", marker.get()));
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(mDocShell);
|
||||
profiler_add_marker(
|
||||
"FirstNonBlankPaint", js::ProfilingStackFrame::Category::DOM,
|
||||
"FirstNonBlankPaint", JS::ProfilingCategoryPair::DOM,
|
||||
MakeUnique<TextMarkerPayload>(marker, mNavigationStart, mNonBlankPaint,
|
||||
docShellId, docShellHistoryId));
|
||||
}
|
||||
|
@ -441,11 +441,10 @@ void nsDOMNavigationTiming::NotifyContentfulPaintForRootContentDocument(
|
|||
"and first non-blank paint");
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(mDocShell);
|
||||
PAGELOAD_LOG(("%s", marker.get()));
|
||||
profiler_add_marker(
|
||||
"FirstContentfulPaint", js::ProfilingStackFrame::Category::DOM,
|
||||
MakeUnique<TextMarkerPayload>(marker, mNavigationStart,
|
||||
mContentfulPaint, docShellId,
|
||||
docShellHistoryId));
|
||||
profiler_add_marker("FirstContentfulPaint", JS::ProfilingCategoryPair::DOM,
|
||||
MakeUnique<TextMarkerPayload>(
|
||||
marker, mNavigationStart, mContentfulPaint,
|
||||
docShellId, docShellHistoryId));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -492,11 +491,10 @@ void nsDOMNavigationTiming::NotifyDOMContentFlushedForRootContentDocument() {
|
|||
"and DOMContentFlushed");
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(mDocShell);
|
||||
PAGELOAD_LOG(("%s", marker.get()));
|
||||
profiler_add_marker(
|
||||
"DOMContentFlushed", js::ProfilingStackFrame::Category::DOM,
|
||||
MakeUnique<TextMarkerPayload>(marker, mNavigationStart,
|
||||
mDOMContentFlushed, docShellId,
|
||||
docShellHistoryId));
|
||||
profiler_add_marker("DOMContentFlushed", JS::ProfilingCategoryPair::DOM,
|
||||
MakeUnique<TextMarkerPayload>(
|
||||
marker, mNavigationStart, mDOMContentFlushed,
|
||||
docShellId, docShellHistoryId));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -856,6 +856,7 @@ nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter* aOuterWindow)
|
|||
mHasFocus(false),
|
||||
mShowFocusRingForContent(false),
|
||||
mFocusByKeyOccurred(false),
|
||||
mDidFireDocElemInserted(false),
|
||||
mHasGamepad(false),
|
||||
mHasVREvents(false),
|
||||
mHasVRDisplayActivateEvents(false),
|
||||
|
|
|
@ -863,6 +863,9 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
|||
|
||||
bool ShouldResistFingerprinting();
|
||||
|
||||
bool DidFireDocElemInserted() const { return mDidFireDocElemInserted; }
|
||||
void SetDidFireDocElemInserted() { mDidFireDocElemInserted = true; }
|
||||
|
||||
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> OpenDialog(
|
||||
JSContext* aCx, const nsAString& aUrl, const nsAString& aName,
|
||||
const nsAString& aOptions,
|
||||
|
@ -1317,6 +1320,10 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
|||
// should be displayed.
|
||||
bool mFocusByKeyOccurred : 1;
|
||||
|
||||
// True if we have notified document-element-inserted observers for this
|
||||
// document.
|
||||
bool mDidFireDocElemInserted : 1;
|
||||
|
||||
// Indicates whether this window wants gamepad input events
|
||||
bool mHasGamepad : 1;
|
||||
|
||||
|
|
|
@ -2585,8 +2585,8 @@ inline static Element* FindMatchingElementWithId(
|
|||
|
||||
Element* nsINode::QuerySelector(const nsAString& aSelector,
|
||||
ErrorResult& aResult) {
|
||||
AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("nsINode::QuerySelector", DOM,
|
||||
aSelector);
|
||||
AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("nsINode::QuerySelector",
|
||||
LAYOUT_SelectorQuery, aSelector);
|
||||
|
||||
const RawServoSelectorList* list = ParseSelectorList(aSelector, aResult);
|
||||
if (!list) {
|
||||
|
@ -2599,8 +2599,8 @@ Element* nsINode::QuerySelector(const nsAString& aSelector,
|
|||
|
||||
already_AddRefed<nsINodeList> nsINode::QuerySelectorAll(
|
||||
const nsAString& aSelector, ErrorResult& aResult) {
|
||||
AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("nsINode::QuerySelectorAll", DOM,
|
||||
aSelector);
|
||||
AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("nsINode::QuerySelectorAll",
|
||||
LAYOUT_SelectorQuery, aSelector);
|
||||
|
||||
RefPtr<nsSimpleContentList> contentList = new nsSimpleContentList(this);
|
||||
const RawServoSelectorList* list = ParseSelectorList(aSelector, aResult);
|
||||
|
|
|
@ -118,7 +118,7 @@ nsJSUtils::ExecutionContext::ExecutionContext(JSContext* aCx,
|
|||
#ifdef MOZ_GECKO_PROFILER
|
||||
mAutoProfilerLabel("nsJSUtils::ExecutionContext",
|
||||
/* dynamicStr */ nullptr,
|
||||
js::ProfilingStackFrame::Category::JS),
|
||||
JS::ProfilingCategoryPair::JS),
|
||||
#endif
|
||||
mCx(aCx),
|
||||
mRealm(aCx, aGlobal),
|
||||
|
|
|
@ -1025,7 +1025,7 @@ static bool ShouldClearTargets(WidgetEvent* aEvent) {
|
|||
docShell = nsContentUtils::GetDocShellForEventTarget(aEvent->mTarget);
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
|
||||
profiler_add_marker(
|
||||
"DOMEvent", js::ProfilingStackFrame::Category::DOM,
|
||||
"DOMEvent", JS::ProfilingCategoryPair::DOM,
|
||||
MakeUnique<DOMEventMarkerPayload>(
|
||||
typeStr, aEvent->mTimeStamp, "DOMEvent",
|
||||
TRACING_INTERVAL_START, docShellId, docShellHistoryId));
|
||||
|
@ -1034,7 +1034,7 @@ static bool ShouldClearTargets(WidgetEvent* aEvent) {
|
|||
aCallback, cd);
|
||||
|
||||
profiler_add_marker(
|
||||
"DOMEvent", js::ProfilingStackFrame::Category::DOM,
|
||||
"DOMEvent", JS::ProfilingCategoryPair::DOM,
|
||||
MakeUnique<DOMEventMarkerPayload>(
|
||||
typeStr, aEvent->mTimeStamp, "DOMEvent", TRACING_INTERVAL_END,
|
||||
docShellId, docShellHistoryId));
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "nsDocElementCreatedNotificationRunner.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIChannel.h"
|
||||
|
@ -905,6 +906,9 @@ void HTMLContentSink::NotifyRootInsertion() {
|
|||
// contexts, since we just inserted the root and notified on
|
||||
// our whole tree
|
||||
UpdateChildCounts();
|
||||
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new nsDocElementCreatedNotificationRunner(mDocument));
|
||||
}
|
||||
|
||||
void HTMLContentSink::UpdateChildCounts() {
|
||||
|
|
|
@ -9,16 +9,11 @@ var EXPORTED_SYMBOLS = [];
|
|||
const DEBUG = false;
|
||||
function debug(s) { dump("-*- NotificationDB component: " + s + "\n"); }
|
||||
|
||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
const {OS} = ChromeUtils.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "notificationStorage",
|
||||
"@mozilla.org/notificationStorage;1",
|
||||
"nsINotificationStorage");
|
||||
|
||||
const NOTIFICATION_STORE_DIR = OS.Constants.Path.profileDir;
|
||||
const NOTIFICATION_STORE_PATH =
|
||||
OS.Path.join(NOTIFICATION_STORE_DIR, "notificationstore.json");
|
||||
|
@ -26,7 +21,7 @@ const NOTIFICATION_STORE_PATH =
|
|||
const kMessages = [
|
||||
"Notification:Save",
|
||||
"Notification:Delete",
|
||||
"Notification:GetAll"
|
||||
"Notification:GetAll",
|
||||
];
|
||||
|
||||
var NotificationDB = {
|
||||
|
@ -34,7 +29,7 @@ var NotificationDB = {
|
|||
// Ensure we won't call init() while xpcom-shutdown is performed
|
||||
_shutdownInProgress: false,
|
||||
|
||||
init: function() {
|
||||
init() {
|
||||
if (this._shutdownInProgress) {
|
||||
return;
|
||||
}
|
||||
|
@ -50,19 +45,19 @@ var NotificationDB = {
|
|||
this.registerListeners();
|
||||
},
|
||||
|
||||
registerListeners: function() {
|
||||
registerListeners() {
|
||||
for (let message of kMessages) {
|
||||
Services.ppmm.addMessageListener(message, this);
|
||||
}
|
||||
},
|
||||
|
||||
unregisterListeners: function() {
|
||||
unregisterListeners() {
|
||||
for (let message of kMessages) {
|
||||
Services.ppmm.removeMessageListener(message, this);
|
||||
}
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
observe(aSubject, aTopic, aData) {
|
||||
if (DEBUG) debug("Topic: " + aTopic);
|
||||
if (aTopic == "xpcom-shutdown") {
|
||||
this._shutdownInProgress = true;
|
||||
|
@ -71,7 +66,7 @@ var NotificationDB = {
|
|||
}
|
||||
},
|
||||
|
||||
filterNonAppNotifications: function(notifications) {
|
||||
filterNonAppNotifications(notifications) {
|
||||
for (let origin in notifications) {
|
||||
let persistentNotificationCount = 0;
|
||||
for (let id in notifications[origin]) {
|
||||
|
@ -91,7 +86,7 @@ var NotificationDB = {
|
|||
},
|
||||
|
||||
// Attempt to read notification file, if it's not there we will create it.
|
||||
load: function() {
|
||||
load() {
|
||||
var promise = OS.File.read(NOTIFICATION_STORE_PATH, { encoding: "utf-8"});
|
||||
return promise.then(
|
||||
data => {
|
||||
|
@ -126,9 +121,9 @@ var NotificationDB = {
|
|||
},
|
||||
|
||||
// Creates the notification directory.
|
||||
createStore: function() {
|
||||
createStore() {
|
||||
var promise = OS.File.makeDir(NOTIFICATION_STORE_DIR, {
|
||||
ignoreExisting: true
|
||||
ignoreExisting: true,
|
||||
});
|
||||
return promise.then(
|
||||
this.createFile.bind(this)
|
||||
|
@ -136,26 +131,25 @@ var NotificationDB = {
|
|||
},
|
||||
|
||||
// Creates the notification file once the directory is created.
|
||||
createFile: function() {
|
||||
createFile() {
|
||||
return OS.File.writeAtomic(NOTIFICATION_STORE_PATH, "");
|
||||
},
|
||||
|
||||
// Save current notifications to the file.
|
||||
save: function() {
|
||||
save() {
|
||||
var data = JSON.stringify(this.notifications);
|
||||
return OS.File.writeAtomic(NOTIFICATION_STORE_PATH, data, { encoding: "utf-8"});
|
||||
},
|
||||
|
||||
// Helper function: promise will be resolved once file exists and/or is loaded.
|
||||
ensureLoaded: function() {
|
||||
ensureLoaded() {
|
||||
if (!this.loaded) {
|
||||
return this.load();
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
receiveMessage: function(message) {
|
||||
receiveMessage(message) {
|
||||
if (DEBUG) { debug("Received message:" + message.name); }
|
||||
|
||||
// sendAsyncMessage can fail if the child process exits during a
|
||||
|
@ -174,13 +168,13 @@ var NotificationDB = {
|
|||
returnMessage("Notification:GetAll:Return:OK", {
|
||||
requestID: message.data.requestID,
|
||||
origin: message.data.origin,
|
||||
notifications: notifications
|
||||
notifications,
|
||||
});
|
||||
}).catch(function(error) {
|
||||
returnMessage("Notification:GetAll:Return:KO", {
|
||||
requestID: message.data.requestID,
|
||||
origin: message.data.origin,
|
||||
errorMsg: error
|
||||
errorMsg: error,
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
@ -188,12 +182,12 @@ var NotificationDB = {
|
|||
case "Notification:Save":
|
||||
this.queueTask("save", message.data).then(function() {
|
||||
returnMessage("Notification:Save:Return:OK", {
|
||||
requestID: message.data.requestID
|
||||
requestID: message.data.requestID,
|
||||
});
|
||||
}).catch(function(error) {
|
||||
returnMessage("Notification:Save:Return:KO", {
|
||||
requestID: message.data.requestID,
|
||||
errorMsg: error
|
||||
errorMsg: error,
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
@ -201,12 +195,12 @@ var NotificationDB = {
|
|||
case "Notification:Delete":
|
||||
this.queueTask("delete", message.data).then(function() {
|
||||
returnMessage("Notification:Delete:Return:OK", {
|
||||
requestID: message.data.requestID
|
||||
requestID: message.data.requestID,
|
||||
});
|
||||
}).catch(function(error) {
|
||||
returnMessage("Notification:Delete:Return:KO", {
|
||||
requestID: message.data.requestID,
|
||||
errorMsg: error
|
||||
errorMsg: error,
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
@ -218,15 +212,15 @@ var NotificationDB = {
|
|||
|
||||
// We need to make sure any read/write operations are atomic,
|
||||
// so use a queue to run each operation sequentially.
|
||||
queueTask: function(operation, data) {
|
||||
queueTask(operation, data) {
|
||||
if (DEBUG) { debug("Queueing task: " + operation); }
|
||||
|
||||
var defer = {};
|
||||
|
||||
this.tasks.push({
|
||||
operation: operation,
|
||||
data: data,
|
||||
defer: defer
|
||||
operation,
|
||||
data,
|
||||
defer,
|
||||
});
|
||||
|
||||
var promise = new Promise(function(resolve, reject) {
|
||||
|
@ -243,7 +237,7 @@ var NotificationDB = {
|
|||
return promise;
|
||||
},
|
||||
|
||||
runNextTask: function() {
|
||||
runNextTask() {
|
||||
if (this.tasks.length === 0) {
|
||||
if (DEBUG) { debug("No more tasks to run, queue depleted"); }
|
||||
this.runningTask = null;
|
||||
|
@ -259,17 +253,17 @@ var NotificationDB = {
|
|||
switch (task.operation) {
|
||||
case "getall":
|
||||
return this.taskGetAll(task.data);
|
||||
break;
|
||||
|
||||
case "save":
|
||||
return this.taskSave(task.data);
|
||||
break;
|
||||
|
||||
case "delete":
|
||||
return this.taskDelete(task.data);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return Promise.reject(
|
||||
new Error(`Found a task with unknown operation ${task.operation}`));
|
||||
}
|
||||
})
|
||||
.then(payload => {
|
||||
if (DEBUG) {
|
||||
|
@ -281,14 +275,14 @@ var NotificationDB = {
|
|||
if (DEBUG) {
|
||||
debug("Error while running " + this.runningTask.operation + ": " + err);
|
||||
}
|
||||
this.runningTask.defer.reject(new String(err));
|
||||
this.runningTask.defer.reject(err);
|
||||
})
|
||||
.then(() => {
|
||||
this.runNextTask();
|
||||
});
|
||||
},
|
||||
|
||||
taskGetAll: function(data) {
|
||||
taskGetAll(data) {
|
||||
if (DEBUG) { debug("Task, getting all"); }
|
||||
var origin = data.origin;
|
||||
var notifications = [];
|
||||
|
@ -308,7 +302,7 @@ var NotificationDB = {
|
|||
return Promise.resolve(notifications);
|
||||
},
|
||||
|
||||
taskSave: function(data) {
|
||||
taskSave(data) {
|
||||
if (DEBUG) { debug("Task, saving"); }
|
||||
var origin = data.origin;
|
||||
var notification = data.notification;
|
||||
|
@ -331,7 +325,7 @@ var NotificationDB = {
|
|||
return this.save();
|
||||
},
|
||||
|
||||
taskDelete: function(data) {
|
||||
taskDelete(data) {
|
||||
if (DEBUG) { debug("Task, deleting"); }
|
||||
var origin = data.origin;
|
||||
var id = data.id;
|
||||
|
@ -352,7 +346,7 @@ var NotificationDB = {
|
|||
}
|
||||
delete this.notifications[origin][id];
|
||||
return this.save();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
NotificationDB.init();
|
||||
|
|
|
@ -19,7 +19,7 @@ const kMessages = [
|
|||
kMessageNotificationGetAllOk,
|
||||
kMessageNotificationGetAllKo,
|
||||
kMessageNotificationSaveKo,
|
||||
kMessageNotificationDeleteKo
|
||||
kMessageNotificationDeleteKo,
|
||||
];
|
||||
|
||||
function NotificationStorage() {
|
||||
|
@ -34,19 +34,19 @@ function NotificationStorage() {
|
|||
|
||||
NotificationStorage.prototype = {
|
||||
|
||||
registerListeners: function() {
|
||||
registerListeners() {
|
||||
for (let message of kMessages) {
|
||||
Services.cpmm.addMessageListener(message, this);
|
||||
}
|
||||
},
|
||||
|
||||
unregisterListeners: function() {
|
||||
unregisterListeners() {
|
||||
for (let message of kMessages) {
|
||||
Services.cpmm.removeMessageListener(message, this);
|
||||
}
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
observe(aSubject, aTopic, aData) {
|
||||
if (DEBUG) debug("Topic: " + aTopic);
|
||||
if (aTopic === "xpcom-shutdown") {
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
|
@ -54,37 +54,37 @@ NotificationStorage.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
put: function(origin, id, title, dir, lang, body, tag, icon, alertName,
|
||||
put(origin, id, title, dir, lang, body, tag, icon, alertName,
|
||||
data, behavior, serviceWorkerRegistrationScope) {
|
||||
if (DEBUG) { debug("PUT: " + origin + " " + id + ": " + title); }
|
||||
var notification = {
|
||||
id: id,
|
||||
title: title,
|
||||
dir: dir,
|
||||
lang: lang,
|
||||
body: body,
|
||||
tag: tag,
|
||||
icon: icon,
|
||||
alertName: alertName,
|
||||
id,
|
||||
title,
|
||||
dir,
|
||||
lang,
|
||||
body,
|
||||
tag,
|
||||
icon,
|
||||
alertName,
|
||||
timestamp: new Date().getTime(),
|
||||
origin: origin,
|
||||
data: data,
|
||||
origin,
|
||||
data,
|
||||
mozbehavior: behavior,
|
||||
serviceWorkerRegistrationScope: serviceWorkerRegistrationScope,
|
||||
serviceWorkerRegistrationScope,
|
||||
};
|
||||
|
||||
Services.cpmm.sendAsyncMessage("Notification:Save", {
|
||||
origin: origin,
|
||||
notification: notification
|
||||
origin,
|
||||
notification,
|
||||
});
|
||||
},
|
||||
|
||||
get: function(origin, tag, callback) {
|
||||
get(origin, tag, callback) {
|
||||
if (DEBUG) { debug("GET: " + origin + " " + tag); }
|
||||
this._fetchFromDB(origin, tag, callback);
|
||||
},
|
||||
|
||||
getByID: function(origin, id, callback) {
|
||||
getByID(origin, id, callback) {
|
||||
if (DEBUG) { debug("GETBYID: " + origin + " " + id); }
|
||||
var GetByIDProxyCallback = function(id, originalCallback) {
|
||||
this.searchID = id;
|
||||
|
@ -103,15 +103,15 @@ NotificationStorage.prototype = {
|
|||
return this.get(origin, "", new GetByIDProxyCallback(id, callback));
|
||||
},
|
||||
|
||||
delete: function(origin, id) {
|
||||
delete(origin, id) {
|
||||
if (DEBUG) { debug("DELETE: " + id); }
|
||||
Services.cpmm.sendAsyncMessage("Notification:Delete", {
|
||||
origin: origin,
|
||||
id: id
|
||||
origin,
|
||||
id,
|
||||
});
|
||||
},
|
||||
|
||||
receiveMessage: function(message) {
|
||||
receiveMessage(message) {
|
||||
var request = this._requests[message.data.requestID];
|
||||
|
||||
switch (message.name) {
|
||||
|
@ -142,7 +142,7 @@ NotificationStorage.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_fetchFromDB: function(origin, tag, callback) {
|
||||
_fetchFromDB(origin, tag, callback) {
|
||||
var request = {
|
||||
origin,
|
||||
tag,
|
||||
|
@ -157,7 +157,7 @@ NotificationStorage.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
_returnNotifications: function(notifications, origin, tag, callback) {
|
||||
_returnNotifications(notifications, origin, tag, callback) {
|
||||
// Pass each notification back separately.
|
||||
// The callback is called asynchronously to match the behaviour when
|
||||
// fetching from the database.
|
||||
|
|
|
@ -51,7 +51,7 @@ function tabWithRequest(task, permission) {
|
|||
url: TEST_URL,
|
||||
}, async function(browser) {
|
||||
let requestPromise = ContentTask.spawn(browser, {
|
||||
permission
|
||||
permission,
|
||||
}, async function({permission}) {
|
||||
function requestCallback(perm) {
|
||||
is(perm, permission,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
var MockServices = (function () {
|
||||
/* eslint-disable mozilla/use-chromeutils-generateqi */
|
||||
var MockServices = (function() {
|
||||
"use strict";
|
||||
|
||||
const MOCK_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components)
|
||||
|
@ -16,7 +17,7 @@ var MockServices = (function () {
|
|||
|
||||
var activeAppNotifications = Object.create(null);
|
||||
|
||||
window.addEventListener('mock-notification-close-event', function(e) {
|
||||
window.addEventListener("mock-notification-close-event", function(e) {
|
||||
for (var alertName in activeAlertNotifications) {
|
||||
var notif = activeAlertNotifications[alertName];
|
||||
if (notif.title === e.detail.title) {
|
||||
|
@ -29,39 +30,39 @@ var MockServices = (function () {
|
|||
});
|
||||
|
||||
var mockAlertsService = {
|
||||
showPersistentNotification: function(persistentData, alert, alertListener) {
|
||||
showPersistentNotification(persistentData, alert, alertListener) {
|
||||
this.showAlert(alert, alertListener);
|
||||
},
|
||||
|
||||
showAlert: function(alert, alertListener) {
|
||||
showAlert(alert, alertListener) {
|
||||
var listener = SpecialPowers.wrap(alertListener);
|
||||
activeAlertNotifications[alert.name] = {
|
||||
listener: listener,
|
||||
listener,
|
||||
cookie: alert.cookie,
|
||||
title: alert.title
|
||||
title: alert.title,
|
||||
};
|
||||
|
||||
// fake async alert show event
|
||||
if (listener) {
|
||||
setTimeout(function () {
|
||||
setTimeout(function() {
|
||||
listener.observe(null, "alertshow", alert.cookie);
|
||||
}, 100);
|
||||
setTimeout(function () {
|
||||
setTimeout(function() {
|
||||
listener.observe(null, "alertclickcallback", alert.cookie);
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
|
||||
showAlertNotification: function(imageUrl, title, text, textClickable,
|
||||
showAlertNotification(imageUrl, title, text, textClickable,
|
||||
cookie, alertListener, name) {
|
||||
this.showAlert({
|
||||
name: name,
|
||||
cookie: cookie,
|
||||
title: title
|
||||
name,
|
||||
cookie,
|
||||
title,
|
||||
}, alertListener);
|
||||
},
|
||||
|
||||
closeAlert: function(name) {
|
||||
closeAlert(name) {
|
||||
var alertNotification = activeAlertNotifications[name];
|
||||
if (alertNotification) {
|
||||
if (alertNotification.listener) {
|
||||
|
@ -76,7 +77,7 @@ var MockServices = (function () {
|
|||
}
|
||||
},
|
||||
|
||||
QueryInterface: function(aIID) {
|
||||
QueryInterface(aIID) {
|
||||
if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) ||
|
||||
SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) {
|
||||
return this;
|
||||
|
@ -84,18 +85,18 @@ var MockServices = (function () {
|
|||
throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
createInstance: function(aOuter, aIID) {
|
||||
createInstance(aOuter, aIID) {
|
||||
if (aOuter != null) {
|
||||
throw SpecialPowers.Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
return this.QueryInterface(aIID);
|
||||
}
|
||||
},
|
||||
};
|
||||
mockAlertsService = SpecialPowers.wrapCallbackObject(mockAlertsService);
|
||||
|
||||
// MockServices API
|
||||
return {
|
||||
register: function () {
|
||||
register() {
|
||||
registrar.registerFactory(MOCK_ALERTS_CID, "alerts service",
|
||||
ALERTS_SERVICE_CONTRACT_ID,
|
||||
mockAlertsService);
|
||||
|
@ -105,13 +106,13 @@ var MockServices = (function () {
|
|||
mockAlertsService);
|
||||
},
|
||||
|
||||
unregister: function () {
|
||||
unregister() {
|
||||
registrar.unregisterFactory(MOCK_ALERTS_CID, mockAlertsService);
|
||||
registrar.unregisterFactory(MOCK_SYSTEM_ALERTS_CID, mockAlertsService);
|
||||
},
|
||||
|
||||
activeAlertNotifications: activeAlertNotifications,
|
||||
activeAlertNotifications,
|
||||
|
||||
activeAppNotifications: activeAppNotifications,
|
||||
activeAppNotifications,
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
var NotificationTest = (function () {
|
||||
var NotificationTest = (function() {
|
||||
"use strict";
|
||||
|
||||
function info(msg, name) {
|
||||
|
@ -22,7 +22,8 @@ var NotificationTest = (function () {
|
|||
|
||||
(function executeRemainingTests(remainingTests) {
|
||||
if (!remainingTests.length) {
|
||||
return callback();
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
var nextTest = remainingTests.shift();
|
||||
|
@ -43,9 +44,9 @@ var NotificationTest = (function () {
|
|||
})(tests);
|
||||
}
|
||||
|
||||
var fakeCustomData = (function () {
|
||||
var fakeCustomData = (function() {
|
||||
var buffer = new ArrayBuffer(2);
|
||||
var dv = new DataView(buffer).setInt16(0, 42, true);
|
||||
new DataView(buffer).setInt16(0, 42, true);
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = canvas.height = 100;
|
||||
var context = canvas.getContext("2d");
|
||||
|
@ -60,53 +61,53 @@ var NotificationTest = (function () {
|
|||
a: 123,
|
||||
b: "test",
|
||||
c: true,
|
||||
d: [1, 2, 3]
|
||||
d: [1, 2, 3],
|
||||
},
|
||||
date: new Date(2013, 2, 1, 1, 10),
|
||||
regexp: new RegExp("[^.]+"),
|
||||
arrayBuffer: buffer,
|
||||
imageData: context.createImageData(100, 100),
|
||||
map: map,
|
||||
set: set
|
||||
map,
|
||||
set,
|
||||
};
|
||||
})();
|
||||
|
||||
// NotificationTest API
|
||||
return {
|
||||
run: function (tests, callback) {
|
||||
run(tests, callback) {
|
||||
setup_testing_env();
|
||||
|
||||
addLoadEvent(function () {
|
||||
executeTests(tests, function () {
|
||||
addLoadEvent(function() {
|
||||
executeTests(tests, function() {
|
||||
teardown_testing_env();
|
||||
callback && callback();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
allowNotifications: function () {
|
||||
allowNotifications() {
|
||||
SpecialPowers.setBoolPref("notification.prompt.testing.allow", true);
|
||||
},
|
||||
|
||||
denyNotifications: function () {
|
||||
denyNotifications() {
|
||||
SpecialPowers.setBoolPref("notification.prompt.testing.allow", false);
|
||||
},
|
||||
|
||||
clickNotification: function (notification) {
|
||||
clickNotification(notification) {
|
||||
// TODO: how??
|
||||
},
|
||||
|
||||
fireCloseEvent: function (title) {
|
||||
fireCloseEvent(title) {
|
||||
window.dispatchEvent(new CustomEvent("mock-notification-close-event", {
|
||||
detail: {
|
||||
title: title
|
||||
}
|
||||
title,
|
||||
},
|
||||
}));
|
||||
},
|
||||
|
||||
info: info,
|
||||
info,
|
||||
|
||||
customDataMatches: function(dataObj) {
|
||||
customDataMatches(dataObj) {
|
||||
var url = "http://www.domain.com";
|
||||
try {
|
||||
return (JSON.stringify(dataObj.primitives) ===
|
||||
|
@ -119,7 +120,7 @@ var NotificationTest = (function () {
|
|||
JSON.stringify(fakeCustomData.imageData.data)) &&
|
||||
(dataObj.map.get("test") == 42) &&
|
||||
(dataObj.set.has(4) && dataObj.set.has(2));
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
@ -130,7 +131,7 @@ var NotificationTest = (function () {
|
|||
icon: "icon.jpg",
|
||||
lang: "en-US",
|
||||
dir: "ltr",
|
||||
data: fakeCustomData
|
||||
}
|
||||
data: fakeCustomData,
|
||||
},
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
SimpleTest.requestFlakyTimeout("untriaged");
|
||||
|
||||
var steps = [
|
||||
function () {
|
||||
function() {
|
||||
info("Test notification spec");
|
||||
ok(Notification, "Notification constructor exists");
|
||||
ok(Notification.permission, "Notification.permission exists");
|
||||
|
@ -27,12 +27,12 @@
|
|||
ok(Notification.get, "Notification.get exists");
|
||||
},
|
||||
|
||||
function () {
|
||||
function() {
|
||||
info("Test requestPermission without callback");
|
||||
Notification.requestPermission();
|
||||
},
|
||||
|
||||
function (done) {
|
||||
function(done) {
|
||||
info("Test requestPermission deny");
|
||||
function assertPermissionDenied(perm) {
|
||||
is(perm, "denied", "Permission should be denied.");
|
||||
|
@ -48,7 +48,7 @@
|
|||
.then(done);
|
||||
},
|
||||
|
||||
function (done) {
|
||||
function(done) {
|
||||
info("Test requestPermission grant");
|
||||
function assertPermissionGranted(perm) {
|
||||
is(perm, "granted", "Permission should be granted.");
|
||||
|
@ -64,7 +64,7 @@
|
|||
.then(done);
|
||||
},
|
||||
|
||||
function (done) {
|
||||
function(done) {
|
||||
info("Test invalid requestPermission");
|
||||
Notification.requestPermission({})
|
||||
.then(_ => {
|
||||
|
@ -75,7 +75,7 @@
|
|||
.then(done);
|
||||
},
|
||||
|
||||
function (done) {
|
||||
function(done) {
|
||||
info("Test create notification");
|
||||
|
||||
options = NotificationTest.payload;
|
||||
|
@ -101,27 +101,27 @@
|
|||
// store notification in test context
|
||||
this.notification = notification;
|
||||
|
||||
notification.onshow = function () {
|
||||
notification.onshow = function() {
|
||||
ok(true, "onshow handler should be called");
|
||||
done();
|
||||
};
|
||||
},
|
||||
|
||||
function (done) {
|
||||
function(done) {
|
||||
info("Test closing a notification");
|
||||
var notification = this.notification;
|
||||
|
||||
notification.onclose = function () {
|
||||
notification.onclose = function() {
|
||||
ok(true, "onclose handler should be called");
|
||||
done();
|
||||
};
|
||||
|
||||
notification.close();
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
MockServices.register();
|
||||
NotificationTest.run(steps, function () {
|
||||
NotificationTest.run(steps, function() {
|
||||
MockServices.unregister();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Notification Basics</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="MockServices.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="NotificationTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
|
@ -17,7 +17,7 @@
|
|||
|
||||
function deleteAllNotifications(done) {
|
||||
var promise = Notification.get();
|
||||
promise.then(function (notifications) {
|
||||
promise.then(function(notifications) {
|
||||
notifications.forEach(function(notification) {
|
||||
notification.close();
|
||||
});
|
||||
|
@ -28,16 +28,16 @@
|
|||
var info = NotificationTest.info;
|
||||
|
||||
var steps = [
|
||||
function (done) {
|
||||
function(done) {
|
||||
info("Test that Notifcation.get fulfills the promise");
|
||||
var promise = Notification.get();
|
||||
ok(promise.then, "should return a promise");
|
||||
|
||||
// Create a new notification to make sure
|
||||
// Notification.get() works while creating
|
||||
var notification = new Notification("this is a test");
|
||||
new Notification("this is a test");
|
||||
|
||||
promise.then(function () {
|
||||
promise.then(function() {
|
||||
ok(true, "promise should be fulfilled");
|
||||
done();
|
||||
});
|
||||
|
@ -45,28 +45,28 @@
|
|||
|
||||
deleteAllNotifications,
|
||||
|
||||
function (done) {
|
||||
function(done) {
|
||||
info("Test adding a notification, and making sure get returns it");
|
||||
NotificationTest.allowNotifications();
|
||||
var options = NotificationTest.payload;
|
||||
|
||||
var notification = new Notification("This is a title", options);
|
||||
var promise = Notification.get();
|
||||
promise.then(function (notifications) {
|
||||
promise.then(function(notifications) {
|
||||
ok(notifications.length, "should return notifications");
|
||||
for (var i = 0; i < notifications.length; i++) {
|
||||
var notification = notifications[i];
|
||||
if (notification.tag === options.tag) {
|
||||
var currentNotification = notifications[i];
|
||||
if (currentNotification.tag === options.tag) {
|
||||
ok(true, "should contain newly created notification");
|
||||
for (var key in options) {
|
||||
if (key === "data") {
|
||||
ok(NotificationTest.customDataMatches(notification.data),
|
||||
ok(NotificationTest.customDataMatches(currentNotification.data),
|
||||
"data property should match");
|
||||
continue;
|
||||
}
|
||||
is(notification[key], options[key], key + " property should match");
|
||||
is(currentNotification[key], options[key], key + " property should match");
|
||||
}
|
||||
notification.close();
|
||||
currentNotification.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -76,19 +76,19 @@
|
|||
notification.onclose = done;
|
||||
},
|
||||
|
||||
function (done) {
|
||||
function(done) {
|
||||
info("Testing fetching notification by tag filter");
|
||||
var n1 = new Notification("title1", {tag: "tag1"});
|
||||
var n2 = new Notification("title2", {tag: "tag2"});
|
||||
var n3 = new Notification("title3", {tag: "tag3"});
|
||||
var promise = Notification.get({tag: "tag3"});
|
||||
promise.then(function (notifications) {
|
||||
promise.then(function(notifications) {
|
||||
var notification = notifications[0];
|
||||
is(notifications.length, 1, "should return 1 notification");
|
||||
is(notifications[0].title, "title3", "titles should match");
|
||||
is(notifications[0].tag, "tag3", "tags should match");
|
||||
is(notification.title, "title3", "titles should match");
|
||||
is(notification.tag, "tag3", "tags should match");
|
||||
var closeCount = 0;
|
||||
var waitForAll = function () {
|
||||
var waitForAll = function() {
|
||||
if (++closeCount >= 3) {
|
||||
done();
|
||||
}
|
||||
|
@ -104,22 +104,22 @@
|
|||
|
||||
deleteAllNotifications,
|
||||
|
||||
function (done) {
|
||||
function(done) {
|
||||
info("Testing fetching no notifications");
|
||||
var promise = Notification.get();
|
||||
promise.then(function (notifications) {
|
||||
promise.then(function(notifications) {
|
||||
is(notifications.length, 0, "should return 0 notifications");
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
function (done) {
|
||||
function(done) {
|
||||
info("Testing fetching multiple notifications");
|
||||
var n1 = new Notification("title1");
|
||||
var n2 = new Notification("title2");
|
||||
var n3 = new Notification("title3");
|
||||
var promise = Notification.get();
|
||||
promise.then(function (notifications) {
|
||||
promise.then(function(notifications) {
|
||||
is(notifications.length, 3, "should return 3 notifications");
|
||||
n1.close();
|
||||
n2.close();
|
||||
|
@ -130,7 +130,7 @@
|
|||
|
||||
deleteAllNotifications,
|
||||
|
||||
function (done) {
|
||||
function(done) {
|
||||
info("Testing 'alertfinished' removes the notification from DB");
|
||||
var n = new Notification("test-title" + Math.random());
|
||||
n.onclose = function() {
|
||||
|
@ -146,11 +146,11 @@
|
|||
NotificationTest.fireCloseEvent(n.title);
|
||||
}, 100);
|
||||
};
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
MockServices.register();
|
||||
NotificationTest.run(steps, function () {
|
||||
NotificationTest.run(steps, function() {
|
||||
MockServices.unregister();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -19,24 +19,25 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=782211
|
|||
<pre id="test">
|
||||
</pre>
|
||||
<script type="text/javascript">
|
||||
/* eslint-disable mozilla/use-chromeutils-generateqi */
|
||||
const MOCK_CID = SpecialPowers.wrap(SpecialPowers.Components).ID("{dbe37e64-d9a3-402c-8d8a-0826c619f7ad}");
|
||||
const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
|
||||
|
||||
var mockAlertsService = {
|
||||
showAlert: function(alert, alertListener) {
|
||||
showAlert(alert, alertListener) {
|
||||
notificationsCreated.push(alert.name);
|
||||
if (notificationsCreated.length == 3) {
|
||||
checkNotifications();
|
||||
}
|
||||
},
|
||||
|
||||
showAlertNotification: function(imageUrl, title, text, textClickable,
|
||||
cookie, alertListener, name, dir,
|
||||
lang, data) {
|
||||
this.showAlert({ name: name });
|
||||
showAlertNotification(imageUrl, title, text, textClickable,
|
||||
cookie, alertListener, name, dir,
|
||||
lang, data) {
|
||||
this.showAlert({ name });
|
||||
},
|
||||
|
||||
QueryInterface: function(aIID) {
|
||||
QueryInterface(aIID) {
|
||||
if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) ||
|
||||
SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) {
|
||||
return this;
|
||||
|
@ -44,12 +45,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=782211
|
|||
throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
createInstance: function(aOuter, aIID) {
|
||||
createInstance(aOuter, aIID) {
|
||||
if (aOuter != null) {
|
||||
throw SpecialPowers.Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
return this.QueryInterface(aIID);
|
||||
}
|
||||
},
|
||||
};
|
||||
mockAlertsService = SpecialPowers.wrapCallbackObject(mockAlertsService);
|
||||
|
||||
|
@ -91,14 +92,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=782211
|
|||
// Load two frames with the same origin that create notification with the same tag.
|
||||
// Both pages should generate notifications with the same name, and thus the second
|
||||
// notification should replace the first.
|
||||
frames["sameDomain"].location.href = "http://test1.example.org:80/tests/dom/notification/test/mochitest/create_notification.html";
|
||||
frames["anotherSameDomain"].location.href = "http://test1.example.org:80/tests/dom/notification/test/mochitest/create_notification.html";
|
||||
frames.sameDomain.location.href = "http://test1.example.org:80/tests/dom/notification/test/mochitest/create_notification.html";
|
||||
frames.anotherSameDomain.location.href = "http://test1.example.org:80/tests/dom/notification/test/mochitest/create_notification.html";
|
||||
// Load a frame with a different origin that creates a notification with the same tag.
|
||||
// The notification name should be different and thus no notifications should be replaced.
|
||||
frames["crossDomain"].location.href = "http://test2.example.org:80/tests/dom/notification/test/mochitest/create_notification.html";
|
||||
frames.crossDomain.location.href = "http://test2.example.org:80/tests/dom/notification/test/mochitest/create_notification.html";
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [["notification.prompt.testing", true],
|
||||
SpecialPowers.pushPrefEnv({"set": [["notification.prompt.testing", true],
|
||||
["notification.prompt.testing.allow", true]]},
|
||||
showNotifications);
|
||||
} else {
|
||||
|
|
|
@ -225,7 +225,7 @@ void Performance::Mark(const nsAString& aName, ErrorResult& aRv) {
|
|||
nsContentUtils::GetDocShellForEventTarget(et);
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
|
||||
profiler_add_marker(
|
||||
"UserTiming", js::ProfilingStackFrame::Category::DOM,
|
||||
"UserTiming", JS::ProfilingCategoryPair::DOM,
|
||||
MakeUnique<UserTimingMarkerPayload>(aName, TimeStamp::Now(), docShellId,
|
||||
docShellHistoryId));
|
||||
}
|
||||
|
@ -321,7 +321,7 @@ void Performance::Measure(const nsAString& aName,
|
|||
nsCOMPtr<nsIDocShell> docShell =
|
||||
nsContentUtils::GetDocShellForEventTarget(et);
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
|
||||
profiler_add_marker("UserTiming", js::ProfilingStackFrame::Category::DOM,
|
||||
profiler_add_marker("UserTiming", JS::ProfilingCategoryPair::DOM,
|
||||
MakeUnique<UserTimingMarkerPayload>(
|
||||
aName, startMark, endMark, startTimeStamp,
|
||||
endTimeStamp, docShellId, docShellHistoryId));
|
||||
|
|
|
@ -567,7 +567,7 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
|
|||
#ifdef MOZ_GECKO_PROFILER
|
||||
,
|
||||
mAutoProfilerLabel(
|
||||
"", aReason, js::ProfilingStackFrame::Category::JS,
|
||||
"", aReason, JS::ProfilingCategoryPair::JS,
|
||||
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS))
|
||||
#endif
|
||||
{
|
||||
|
|
|
@ -164,8 +164,7 @@ void LayerManager::PayloadPresented() {
|
|||
"Payload Presented, type: %d latency: %dms\n",
|
||||
int32_t(payload.mType),
|
||||
int32_t((presented - payload.mTimeStamp).ToMilliseconds()));
|
||||
profiler_add_marker(marker.get(),
|
||||
js::ProfilingStackFrame::Category::GRAPHICS);
|
||||
profiler_add_marker(marker.get(), JS::ProfilingCategoryPair::GRAPHICS);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ void ProfilerScreenshots::SubmitScreenshot(
|
|||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add a marker with the data URL.
|
||||
profiler_add_marker_for_thread(
|
||||
sourceThread, js::ProfilingStackFrame::Category::GRAPHICS,
|
||||
sourceThread, JS::ProfilingCategoryPair::GRAPHICS,
|
||||
"CompositorScreenshot",
|
||||
MakeUnique<ScreenshotPayload>(timeStamp, std::move(dataURL),
|
||||
originalSize, windowIdentifier));
|
||||
|
|
|
@ -434,7 +434,7 @@ CompositorBridgeChild* ClientLayerManager::GetCompositorBridgeChild() {
|
|||
}
|
||||
|
||||
void ClientLayerManager::FlushAsyncPaints() {
|
||||
AUTO_PROFILER_LABEL("ClientLayerManager::FlushAsyncPaints", GRAPHICS);
|
||||
AUTO_PROFILER_LABEL_CATEGORY_PAIR(GRAPHICS_FlushingAsyncPaints);
|
||||
|
||||
CompositorBridgeChild* cbc = GetCompositorBridgeChild();
|
||||
if (cbc) {
|
||||
|
|
|
@ -307,8 +307,6 @@ bool ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
|
|||
const nsIntPoint& aTileOrigin,
|
||||
nsIntRegion& aDirtyRegion,
|
||||
TilePaintFlags aFlags) {
|
||||
AUTO_PROFILER_LABEL("ClientMultiTiledLayerBuffer::ValidateTile", GRAPHICS);
|
||||
|
||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||
if (aDirtyRegion.IsComplex()) {
|
||||
printf_stderr("Complex region\n");
|
||||
|
|
|
@ -578,6 +578,7 @@ Maybe<AcquiredBackBuffer> TileClient::AcquireBackBuffer(
|
|||
CompositableClient& aCompositable, const nsIntRegion& aDirtyRegion,
|
||||
const nsIntRegion& aVisibleRegion, gfxContentType aContent,
|
||||
SurfaceMode aMode, TilePaintFlags aFlags) {
|
||||
AUTO_PROFILER_LABEL("TileClient::AcquireBackBuffer", GRAPHICS_TileAllocation);
|
||||
if (!mAllocator) {
|
||||
gfxCriticalError() << "[TileClient] Missing TextureClientAllocator.";
|
||||
return Nothing();
|
||||
|
|
|
@ -88,7 +88,7 @@ void CompositorScreenshotGrabber::MaybeProcessQueue() {
|
|||
void CompositorScreenshotGrabber::NotifyEmptyFrame() {
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
profiler_add_marker("NoCompositorScreenshot because nothing changed",
|
||||
js::ProfilingStackFrame::Category::GRAPHICS);
|
||||
JS::ProfilingCategoryPair::GRAPHICS);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -100,8 +100,7 @@ static void PrintUniformityInfo(Layer* aLayer) {
|
|||
}
|
||||
|
||||
Point translation = transform.As2D().GetTranslation();
|
||||
profiler_add_marker("LayerTranslation",
|
||||
js::ProfilingStackFrame::Category::GRAPHICS,
|
||||
profiler_add_marker("LayerTranslation", JS::ProfilingCategoryPair::GRAPHICS,
|
||||
MakeUnique<LayerTranslationMarkerPayload>(
|
||||
aLayer, translation, TimeStamp::Now()));
|
||||
#endif
|
||||
|
|
|
@ -1908,8 +1908,7 @@ CompositorBridgeParent::GetAPZCTreeManager(LayersId aLayersId) {
|
|||
static void InsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp) {
|
||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||
if (profiler_thread_is_being_profiled()) {
|
||||
profiler_add_marker("VsyncTimestamp",
|
||||
js::ProfilingStackFrame::Category::GRAPHICS,
|
||||
profiler_add_marker("VsyncTimestamp", JS::ProfilingCategoryPair::GRAPHICS,
|
||||
MakeUnique<VsyncMarkerPayload>(aVsyncTimestamp));
|
||||
}
|
||||
}
|
||||
|
@ -2452,8 +2451,8 @@ int32_t RecordContentFrameTime(
|
|||
}
|
||||
};
|
||||
profiler_add_marker_for_thread(
|
||||
profiler_current_thread_id(),
|
||||
js::ProfilingStackFrame::Category::GRAPHICS, "CONTENT_FRAME_TIME",
|
||||
profiler_current_thread_id(), JS::ProfilingCategoryPair::GRAPHICS,
|
||||
"CONTENT_FRAME_TIME",
|
||||
MakeUnique<ContentFramePayload>(aTxnStart, aCompositeEnd));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -380,8 +380,8 @@ void CrossProcessCompositorBridgeParent::ShadowLayersUpdated(
|
|||
}
|
||||
};
|
||||
profiler_add_marker_for_thread(
|
||||
profiler_current_thread_id(),
|
||||
js::ProfilingStackFrame::Category::GRAPHICS, "CONTENT_FULL_PAINT_TIME",
|
||||
profiler_current_thread_id(), JS::ProfilingCategoryPair::GRAPHICS,
|
||||
"CONTENT_FULL_PAINT_TIME",
|
||||
MakeUnique<ContentBuildPayload>(aInfo.transactionStart(), endTime));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -104,7 +104,7 @@ void MLGPUScreenshotGrabber::MaybeProcessQueue() {
|
|||
void MLGPUScreenshotGrabber::NotifyEmptyFrame() {
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
profiler_add_marker("NoCompositorScreenshot because nothing changed",
|
||||
js::ProfilingStackFrame::Category::GRAPHICS);
|
||||
JS::ProfilingCategoryPair::GRAPHICS);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -52,16 +52,14 @@ bool is_in_render_thread() {
|
|||
|
||||
void gecko_profiler_start_marker(const char* name) {
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
profiler_tracing("WebRender", name,
|
||||
js::ProfilingStackFrame::Category::GRAPHICS,
|
||||
profiler_tracing("WebRender", name, JS::ProfilingCategoryPair::GRAPHICS,
|
||||
TRACING_INTERVAL_START);
|
||||
#endif
|
||||
}
|
||||
|
||||
void gecko_profiler_end_marker(const char* name) {
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
profiler_tracing("WebRender", name,
|
||||
js::ProfilingStackFrame::Category::GRAPHICS,
|
||||
profiler_tracing("WebRender", name, JS::ProfilingCategoryPair::GRAPHICS,
|
||||
TRACING_INTERVAL_END);
|
||||
#endif
|
||||
}
|
||||
|
@ -206,8 +204,7 @@ class SceneBuiltNotification : public wr::NotificationHandler {
|
|||
|
||||
profiler_add_marker_for_thread(
|
||||
profiler_current_thread_id(),
|
||||
js::ProfilingStackFrame::Category::GRAPHICS,
|
||||
"CONTENT_FULL_PAINT_TIME",
|
||||
JS::ProfilingCategoryPair::GRAPHICS, "CONTENT_FULL_PAINT_TIME",
|
||||
MakeUnique<ContentFullPaintPayload>(startTime, endTime));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1426,6 +1426,8 @@ void WebRenderCommandBuilder::BuildWebRenderCommands(
|
|||
wr::IpcResourceUpdateQueue& aResourceUpdates, nsDisplayList* aDisplayList,
|
||||
nsDisplayListBuilder* aDisplayListBuilder, WebRenderScrollData& aScrollData,
|
||||
wr::LayoutSize& aContentSize, nsTArray<wr::FilterOp>&& aFilters) {
|
||||
AUTO_PROFILER_LABEL_CATEGORY_PAIR(GRAPHICS_WRDisplayList);
|
||||
|
||||
StackingContextHelper sc;
|
||||
aScrollData = WebRenderScrollData(mManager);
|
||||
MOZ_ASSERT(mLayerScrollData.empty());
|
||||
|
|
|
@ -119,7 +119,7 @@ LexerResult Decoder::Decode(IResumable* aOnResume /* = nullptr */) {
|
|||
|
||||
LexerResult lexerResult(TerminalState::FAILURE);
|
||||
{
|
||||
AUTO_PROFILER_LABEL("Decoder::Decode", GRAPHICS);
|
||||
AUTO_PROFILER_LABEL_CATEGORY_PAIR(GRAPHICS_ImageDecoding);
|
||||
AutoRecordDecoderTelemetry telemetry(this);
|
||||
|
||||
lexerResult = DoDecode(*mIterator, aOnResume);
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef js_ProfilingCategory_h
|
||||
#define js_ProfilingCategory_h
|
||||
|
||||
#include "jstypes.h" // JS_FRIEND_API
|
||||
|
||||
// clang-format off
|
||||
|
||||
// This higher-order macro lists all categories with their subcategories.
|
||||
//
|
||||
// PROFILING_CATEGORY_LIST(BEGIN_CATEGORY, SUBCATEGORY, END_CATEGORY)
|
||||
// BEGIN_CATEGORY(name, labelAsString, colorAsString)
|
||||
// SUBCATEGORY(category, name, labelAsString)
|
||||
// END_CATEGORY
|
||||
//
|
||||
// The list of available color names for categories is:
|
||||
// transparent, grey, purple, yellow, orange, lightblue, green, blue, magenta
|
||||
//
|
||||
// Categories and subcategories are used for stack-based instrumentation. They
|
||||
// are specified in label frames in the profiling stack, see ProfilingStack.h.
|
||||
// At any point, the category pair of the topmost profiler label frame in the
|
||||
// label stack determines the category pair of that stack.
|
||||
// Each category describes a type of workload that the CPU can be busy with.
|
||||
// Categories should be non-overlapping: the list of categories should be
|
||||
// chosen in such a way that every possible stack can be mapped to a single
|
||||
// category unambiguously.
|
||||
|
||||
#define PROFILING_CATEGORY_LIST(BEGIN_CATEGORY, SUBCATEGORY, END_CATEGORY) \
|
||||
BEGIN_CATEGORY(IDLE, "Idle", "transparent") \
|
||||
SUBCATEGORY(IDLE, IDLE, "Other") \
|
||||
END_CATEGORY \
|
||||
BEGIN_CATEGORY(OTHER, "Other", "grey") \
|
||||
SUBCATEGORY(OTHER, OTHER, "Other") \
|
||||
END_CATEGORY \
|
||||
BEGIN_CATEGORY(LAYOUT, "Layout", "purple") \
|
||||
SUBCATEGORY(LAYOUT, LAYOUT, "Other") \
|
||||
SUBCATEGORY(LAYOUT, LAYOUT_FrameConstruction, "Frame construction") \
|
||||
SUBCATEGORY(LAYOUT, LAYOUT_Reflow, "Reflow") \
|
||||
SUBCATEGORY(LAYOUT, LAYOUT_CSSParsing, "CSS parsing") \
|
||||
SUBCATEGORY(LAYOUT, LAYOUT_SelectorQuery, "Selector query") \
|
||||
SUBCATEGORY(LAYOUT, LAYOUT_StyleComputation, "Style computation") \
|
||||
END_CATEGORY \
|
||||
BEGIN_CATEGORY(JS, "JavaScript", "yellow") \
|
||||
SUBCATEGORY(JS, JS, "Other") \
|
||||
END_CATEGORY \
|
||||
BEGIN_CATEGORY(GCCC, "GC / CC", "orange") \
|
||||
SUBCATEGORY(GCCC, GCCC, "Other") \
|
||||
END_CATEGORY \
|
||||
BEGIN_CATEGORY(NETWORK, "Network", "lightblue") \
|
||||
SUBCATEGORY(NETWORK, NETWORK, "Other") \
|
||||
END_CATEGORY \
|
||||
BEGIN_CATEGORY(GRAPHICS, "Graphics", "green") \
|
||||
SUBCATEGORY(GRAPHICS, GRAPHICS, "Other") \
|
||||
SUBCATEGORY(GRAPHICS, GRAPHICS_DisplayListBuilding, "DisplayList building") \
|
||||
SUBCATEGORY(GRAPHICS, GRAPHICS_DisplayListMerging, "DisplayList merging") \
|
||||
SUBCATEGORY(GRAPHICS, GRAPHICS_LayerBuilding, "Layer building") \
|
||||
SUBCATEGORY(GRAPHICS, GRAPHICS_TileAllocation, "Tile allocation") \
|
||||
SUBCATEGORY(GRAPHICS, GRAPHICS_WRDisplayList, "WebRender display list") \
|
||||
SUBCATEGORY(GRAPHICS, GRAPHICS_Rasterization, "Rasterization") \
|
||||
SUBCATEGORY(GRAPHICS, GRAPHICS_FlushingAsyncPaints, "Flushing async paints") \
|
||||
SUBCATEGORY(GRAPHICS, GRAPHICS_ImageDecoding, "Image decoding") \
|
||||
END_CATEGORY \
|
||||
BEGIN_CATEGORY(DOM, "DOM", "blue") \
|
||||
SUBCATEGORY(DOM, DOM, "Other") \
|
||||
END_CATEGORY
|
||||
|
||||
namespace JS {
|
||||
|
||||
// An enum that lists all possible category pairs in one list.
|
||||
// This is the enum that is used in profiler stack labels. Having one list that
|
||||
// includes subcategories from all categories in one list allows assigning the
|
||||
// category pair to a stack label with just one number.
|
||||
#define CATEGORY_ENUM_BEGIN_CATEGORY(name, labelAsString, color)
|
||||
#define CATEGORY_ENUM_SUBCATEGORY(supercategory, name, labelAsString) name,
|
||||
#define CATEGORY_ENUM_END_CATEGORY
|
||||
enum class ProfilingCategoryPair : uint32_t {
|
||||
PROFILING_CATEGORY_LIST(CATEGORY_ENUM_BEGIN_CATEGORY,
|
||||
CATEGORY_ENUM_SUBCATEGORY,
|
||||
CATEGORY_ENUM_END_CATEGORY)
|
||||
COUNT,
|
||||
LAST = COUNT - 1,
|
||||
};
|
||||
#undef CATEGORY_ENUM_BEGIN_CATEGORY
|
||||
#undef CATEGORY_ENUM_SUBCATEGORY
|
||||
#undef CATEGORY_ENUM_END_CATEGORY
|
||||
|
||||
// An enum that lists just the categories without their subcategories.
|
||||
#define SUPERCATEGORY_ENUM_BEGIN_CATEGORY(name, labelAsString, color) name,
|
||||
#define SUPERCATEGORY_ENUM_SUBCATEGORY(supercategory, name, labelAsString)
|
||||
#define SUPERCATEGORY_ENUM_END_CATEGORY
|
||||
enum class ProfilingCategory : uint32_t {
|
||||
PROFILING_CATEGORY_LIST(SUPERCATEGORY_ENUM_BEGIN_CATEGORY,
|
||||
SUPERCATEGORY_ENUM_SUBCATEGORY,
|
||||
SUPERCATEGORY_ENUM_END_CATEGORY)
|
||||
COUNT,
|
||||
LAST = COUNT - 1,
|
||||
};
|
||||
#undef SUPERCATEGORY_ENUM_BEGIN_CATEGORY
|
||||
#undef SUPERCATEGORY_ENUM_SUBCATEGORY
|
||||
#undef SUPERCATEGORY_ENUM_END_CATEGORY
|
||||
|
||||
// clang-format on
|
||||
|
||||
struct ProfilingCategoryPairInfo {
|
||||
ProfilingCategory mCategory;
|
||||
uint32_t mSubcategoryIndex;
|
||||
const char* mLabel;
|
||||
};
|
||||
|
||||
JS_FRIEND_API const ProfilingCategoryPairInfo& GetProfilingCategoryPairInfo(
|
||||
ProfilingCategoryPair aCategoryPair);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif /* js_ProfilingCategory_h */
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "jstypes.h"
|
||||
|
||||
#include "js/ProfilingCategory.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/Utility.h"
|
||||
|
||||
|
@ -156,10 +157,10 @@ class ProfilingStackFrame {
|
|||
mozilla::recordreplay::Behavior::DontPreserve>
|
||||
pcOffsetIfJS_;
|
||||
|
||||
// Bits 0...7 hold the Flags. Bits 8...31 hold the category.
|
||||
// Bits 0...8 hold the Flags. Bits 9...31 hold the category pair.
|
||||
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire,
|
||||
mozilla::recordreplay::Behavior::DontPreserve>
|
||||
flagsAndCategory_;
|
||||
flagsAndCategoryPair_;
|
||||
|
||||
static int32_t pcToOffset(JSScript* aScript, jsbytecode* aPc);
|
||||
|
||||
|
@ -172,13 +173,13 @@ class ProfilingStackFrame {
|
|||
spOrScript = spScript;
|
||||
int32_t offsetIfJS = other.pcOffsetIfJS_;
|
||||
pcOffsetIfJS_ = offsetIfJS;
|
||||
uint32_t flagsAndCategory = other.flagsAndCategory_;
|
||||
flagsAndCategory_ = flagsAndCategory;
|
||||
uint32_t flagsAndCategory = other.flagsAndCategoryPair_;
|
||||
flagsAndCategoryPair_ = flagsAndCategory;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// 8 bits for the flags.
|
||||
// That leaves 32 - 8 = 25 bits for the category.
|
||||
// 9 bits for the flags.
|
||||
// That leaves 32 - 9 = 23 bits for the category pair.
|
||||
enum class Flags : uint32_t {
|
||||
// The first three flags describe the kind of the frame and are
|
||||
// mutually exclusive. (We still give them individual bits for
|
||||
|
@ -216,69 +217,70 @@ class ProfilingStackFrame {
|
|||
// tree view.
|
||||
RELEVANT_FOR_JS = 1 << 7,
|
||||
|
||||
FLAGS_BITCOUNT = 8,
|
||||
// If set, causes the label on this ProfilingStackFrame to be ignored
|
||||
// and to be replaced by the subcategory's label.
|
||||
LABEL_DETERMINED_BY_CATEGORY_PAIR = 1 << 8,
|
||||
|
||||
FLAGS_BITCOUNT = 9,
|
||||
FLAGS_MASK = (1 << FLAGS_BITCOUNT) - 1
|
||||
};
|
||||
|
||||
// Keep these in sync with devtools/client/performance/modules/categories.js
|
||||
enum class Category : uint32_t {
|
||||
IDLE,
|
||||
OTHER,
|
||||
LAYOUT,
|
||||
JS,
|
||||
GCCC,
|
||||
NETWORK,
|
||||
GRAPHICS,
|
||||
DOM,
|
||||
|
||||
FIRST = OTHER,
|
||||
LAST = DOM,
|
||||
};
|
||||
|
||||
static_assert(uint32_t(Category::LAST) <=
|
||||
(UINT32_MAX >> uint32_t(Flags::FLAGS_BITCOUNT)),
|
||||
"Too many categories to fit into u32 with together with the "
|
||||
"reserved bits for the flags");
|
||||
static_assert(
|
||||
uint32_t(JS::ProfilingCategoryPair::LAST) <=
|
||||
(UINT32_MAX >> uint32_t(Flags::FLAGS_BITCOUNT)),
|
||||
"Too many category pairs to fit into u32 with together with the "
|
||||
"reserved bits for the flags");
|
||||
|
||||
bool isLabelFrame() const {
|
||||
return uint32_t(flagsAndCategory_) & uint32_t(Flags::IS_LABEL_FRAME);
|
||||
return uint32_t(flagsAndCategoryPair_) & uint32_t(Flags::IS_LABEL_FRAME);
|
||||
}
|
||||
|
||||
bool isSpMarkerFrame() const {
|
||||
return uint32_t(flagsAndCategory_) & uint32_t(Flags::IS_SP_MARKER_FRAME);
|
||||
return uint32_t(flagsAndCategoryPair_) &
|
||||
uint32_t(Flags::IS_SP_MARKER_FRAME);
|
||||
}
|
||||
|
||||
bool isJsFrame() const {
|
||||
return uint32_t(flagsAndCategory_) & uint32_t(Flags::IS_JS_FRAME);
|
||||
return uint32_t(flagsAndCategoryPair_) & uint32_t(Flags::IS_JS_FRAME);
|
||||
}
|
||||
|
||||
bool isOSRFrame() const {
|
||||
return uint32_t(flagsAndCategory_) & uint32_t(Flags::JS_OSR);
|
||||
return uint32_t(flagsAndCategoryPair_) & uint32_t(Flags::JS_OSR);
|
||||
}
|
||||
|
||||
void setIsOSRFrame(bool isOSR) {
|
||||
if (isOSR) {
|
||||
flagsAndCategory_ = uint32_t(flagsAndCategory_) | uint32_t(Flags::JS_OSR);
|
||||
flagsAndCategoryPair_ =
|
||||
uint32_t(flagsAndCategoryPair_) | uint32_t(Flags::JS_OSR);
|
||||
} else {
|
||||
flagsAndCategory_ =
|
||||
uint32_t(flagsAndCategory_) & ~uint32_t(Flags::JS_OSR);
|
||||
flagsAndCategoryPair_ =
|
||||
uint32_t(flagsAndCategoryPair_) & ~uint32_t(Flags::JS_OSR);
|
||||
}
|
||||
}
|
||||
|
||||
void setLabel(const char* aLabel) { label_ = aLabel; }
|
||||
const char* label() const { return label_; }
|
||||
const char* label() const {
|
||||
uint32_t flagsAndCategoryPair = flagsAndCategoryPair_;
|
||||
if (flagsAndCategoryPair &
|
||||
uint32_t(Flags::LABEL_DETERMINED_BY_CATEGORY_PAIR)) {
|
||||
auto categoryPair = JS::ProfilingCategoryPair(
|
||||
flagsAndCategoryPair >> uint32_t(Flags::FLAGS_BITCOUNT));
|
||||
return JS::GetProfilingCategoryPairInfo(categoryPair).mLabel;
|
||||
}
|
||||
return label_;
|
||||
}
|
||||
|
||||
const char* dynamicString() const { return dynamicString_; }
|
||||
|
||||
void initLabelFrame(const char* aLabel, const char* aDynamicString, void* sp,
|
||||
Category aCategory, uint32_t aFlags) {
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
uint32_t aFlags) {
|
||||
label_ = aLabel;
|
||||
dynamicString_ = aDynamicString;
|
||||
spOrScript = sp;
|
||||
// pcOffsetIfJS_ is not set and must not be used on label frames.
|
||||
flagsAndCategory_ =
|
||||
flagsAndCategoryPair_ =
|
||||
uint32_t(Flags::IS_LABEL_FRAME) |
|
||||
(uint32_t(aCategory) << uint32_t(Flags::FLAGS_BITCOUNT)) | aFlags;
|
||||
(uint32_t(aCategoryPair) << uint32_t(Flags::FLAGS_BITCOUNT)) | aFlags;
|
||||
MOZ_ASSERT(isLabelFrame());
|
||||
}
|
||||
|
||||
|
@ -287,9 +289,9 @@ class ProfilingStackFrame {
|
|||
dynamicString_ = nullptr;
|
||||
spOrScript = sp;
|
||||
// pcOffsetIfJS_ is not set and must not be used on sp marker frames.
|
||||
flagsAndCategory_ =
|
||||
uint32_t(Flags::IS_SP_MARKER_FRAME) |
|
||||
(uint32_t(Category::OTHER) << uint32_t(Flags::FLAGS_BITCOUNT));
|
||||
flagsAndCategoryPair_ = uint32_t(Flags::IS_SP_MARKER_FRAME) |
|
||||
(uint32_t(JS::ProfilingCategoryPair::OTHER)
|
||||
<< uint32_t(Flags::FLAGS_BITCOUNT));
|
||||
MOZ_ASSERT(isSpMarkerFrame());
|
||||
}
|
||||
|
||||
|
@ -299,18 +301,19 @@ class ProfilingStackFrame {
|
|||
dynamicString_ = aDynamicString;
|
||||
spOrScript = aScript;
|
||||
pcOffsetIfJS_ = pcToOffset(aScript, aPc);
|
||||
flagsAndCategory_ =
|
||||
uint32_t(Flags::IS_JS_FRAME) |
|
||||
(uint32_t(Category::JS) << uint32_t(Flags::FLAGS_BITCOUNT));
|
||||
flagsAndCategoryPair_ =
|
||||
uint32_t(Flags::IS_JS_FRAME) | (uint32_t(JS::ProfilingCategoryPair::JS)
|
||||
<< uint32_t(Flags::FLAGS_BITCOUNT));
|
||||
MOZ_ASSERT(isJsFrame());
|
||||
}
|
||||
|
||||
uint32_t flags() const {
|
||||
return uint32_t(flagsAndCategory_) & uint32_t(Flags::FLAGS_MASK);
|
||||
return uint32_t(flagsAndCategoryPair_) & uint32_t(Flags::FLAGS_MASK);
|
||||
}
|
||||
|
||||
Category category() const {
|
||||
return Category(flagsAndCategory_ >> uint32_t(Flags::FLAGS_BITCOUNT));
|
||||
JS::ProfilingCategoryPair categoryPair() const {
|
||||
return JS::ProfilingCategoryPair(flagsAndCategoryPair_ >>
|
||||
uint32_t(Flags::FLAGS_BITCOUNT));
|
||||
}
|
||||
|
||||
void* stackAddress() const {
|
||||
|
@ -390,7 +393,7 @@ class ProfilingStack final {
|
|||
~ProfilingStack();
|
||||
|
||||
void pushLabelFrame(const char* label, const char* dynamicString, void* sp,
|
||||
js::ProfilingStackFrame::Category category,
|
||||
JS::ProfilingCategoryPair categoryPair,
|
||||
uint32_t flags = 0) {
|
||||
// This thread is the only one that ever changes the value of
|
||||
// stackPointer.
|
||||
|
@ -402,8 +405,8 @@ class ProfilingStack final {
|
|||
if (MOZ_UNLIKELY(stackPointerVal >= capacity)) {
|
||||
ensureCapacitySlow();
|
||||
}
|
||||
frames[stackPointerVal].initLabelFrame(label, dynamicString, sp, category,
|
||||
flags);
|
||||
frames[stackPointerVal].initLabelFrame(label, dynamicString, sp,
|
||||
categoryPair, flags);
|
||||
|
||||
// This must happen at the end! The compiler will not reorder this
|
||||
// update because stackPointer is Atomic<..., ReleaseAcquire>, so any
|
||||
|
|
|
@ -1382,7 +1382,7 @@ bool js::array_join(JSContext* cx, unsigned argc, Value* vp) {
|
|||
}
|
||||
|
||||
AutoGeckoProfilerEntry pseudoFrame(
|
||||
cx, "Array.prototype.join", ProfilingStackFrame::Category::JS,
|
||||
cx, "Array.prototype.join", JS::ProfilingCategoryPair::JS,
|
||||
uint32_t(ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
|
@ -1657,7 +1657,7 @@ static DenseElementResult ArrayReverseDenseKernel(JSContext* cx,
|
|||
// 22.1.3.21 Array.prototype.reverse ( )
|
||||
bool js::array_reverse(JSContext* cx, unsigned argc, Value* vp) {
|
||||
AutoGeckoProfilerEntry pseudoFrame(
|
||||
cx, "Array.prototype.reverse", ProfilingStackFrame::Category::JS,
|
||||
cx, "Array.prototype.reverse", JS::ProfilingCategoryPair::JS,
|
||||
uint32_t(ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
|
@ -2381,7 +2381,7 @@ bool js::NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v) {
|
|||
// 22.1.3.18 Array.prototype.push ( ...items )
|
||||
bool js::array_push(JSContext* cx, unsigned argc, Value* vp) {
|
||||
AutoGeckoProfilerEntry pseudoFrame(
|
||||
cx, "Array.prototype.push", ProfilingStackFrame::Category::JS,
|
||||
cx, "Array.prototype.push", JS::ProfilingCategoryPair::JS,
|
||||
uint32_t(ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
|
@ -2442,7 +2442,7 @@ bool js::array_push(JSContext* cx, unsigned argc, Value* vp) {
|
|||
// 22.1.3.17 Array.prototype.pop ( )
|
||||
bool js::array_pop(JSContext* cx, unsigned argc, Value* vp) {
|
||||
AutoGeckoProfilerEntry pseudoFrame(
|
||||
cx, "Array.prototype.pop", ProfilingStackFrame::Category::JS,
|
||||
cx, "Array.prototype.pop", JS::ProfilingCategoryPair::JS,
|
||||
uint32_t(ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
|
@ -2562,7 +2562,7 @@ static DenseElementResult ArrayShiftDenseKernel(JSContext* cx, HandleObject obj,
|
|||
// 22.1.3.22 Array.prototype.shift ( )
|
||||
bool js::array_shift(JSContext* cx, unsigned argc, Value* vp) {
|
||||
AutoGeckoProfilerEntry pseudoFrame(
|
||||
cx, "Array.prototype.shift", ProfilingStackFrame::Category::JS,
|
||||
cx, "Array.prototype.shift", JS::ProfilingCategoryPair::JS,
|
||||
uint32_t(ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
|
@ -2648,7 +2648,7 @@ bool js::array_shift(JSContext* cx, unsigned argc, Value* vp) {
|
|||
// 22.1.3.29 Array.prototype.unshift ( ...items )
|
||||
bool js::array_unshift(JSContext* cx, unsigned argc, Value* vp) {
|
||||
AutoGeckoProfilerEntry pseudoFrame(
|
||||
cx, "Array.prototype.unshift", ProfilingStackFrame::Category::JS,
|
||||
cx, "Array.prototype.unshift", JS::ProfilingCategoryPair::JS,
|
||||
uint32_t(ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
|
@ -2908,7 +2908,7 @@ static bool CopyArrayElements(JSContext* cx, HandleObject obj, uint64_t begin,
|
|||
static bool array_splice_impl(JSContext* cx, unsigned argc, Value* vp,
|
||||
bool returnValueIsUsed) {
|
||||
AutoGeckoProfilerEntry pseudoFrame(
|
||||
cx, "Array.prototype.splice", ProfilingStackFrame::Category::JS,
|
||||
cx, "Array.prototype.splice", JS::ProfilingCategoryPair::JS,
|
||||
uint32_t(ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
|
@ -3504,7 +3504,7 @@ static bool ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint64_t begin,
|
|||
/* ES 2016 draft Mar 25, 2016 22.1.3.23. */
|
||||
bool js::array_slice(JSContext* cx, unsigned argc, Value* vp) {
|
||||
AutoGeckoProfilerEntry pseudoFrame(
|
||||
cx, "Array.prototype.slice", ProfilingStackFrame::Category::JS,
|
||||
cx, "Array.prototype.slice", JS::ProfilingCategoryPair::JS,
|
||||
uint32_t(ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
|
|
|
@ -6711,7 +6711,7 @@ AutoHeapSession::AutoHeapSession(JSRuntime* rt, JS::HeapState heapState)
|
|||
prevState(rt->heapState_),
|
||||
profilingStackFrame(rt->mainContextFromOwnThread(),
|
||||
HeapStateToLabel(heapState),
|
||||
ProfilingStackFrame::Category::GCCC) {
|
||||
JS::ProfilingCategoryPair::GCCC) {
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
||||
MOZ_ASSERT(prevState == JS::HeapState::Idle);
|
||||
MOZ_ASSERT(heapState != JS::HeapState::Idle);
|
||||
|
|
|
@ -3590,9 +3590,9 @@ static bool UnmarkGrayGCThing(JSRuntime* rt, JS::GCCellPtr thing) {
|
|||
// replay, so disallow recorded events from occurring in the tracer.
|
||||
mozilla::recordreplay::AutoDisallowThreadEvents d;
|
||||
|
||||
AutoGeckoProfilerEntry profilingStackFrame(
|
||||
rt->mainContextFromOwnThread(), "UnmarkGrayGCThing",
|
||||
ProfilingStackFrame::Category::GCCC);
|
||||
AutoGeckoProfilerEntry profilingStackFrame(rt->mainContextFromOwnThread(),
|
||||
"UnmarkGrayGCThing",
|
||||
JS::ProfilingCategoryPair::GCCC);
|
||||
|
||||
UnmarkGrayTracer unmarker(rt);
|
||||
gcstats::AutoPhase innerPhase(rt->gc.stats(),
|
||||
|
|
|
@ -67,7 +67,7 @@ class MOZ_RAII BaselineCacheIRCompiler : public CacheIRCompiler {
|
|||
bool makesGCCalls() const { return makesGCCalls_; }
|
||||
|
||||
private:
|
||||
#define DEFINE_OP(op) MOZ_MUST_USE bool emit##op();
|
||||
#define DEFINE_OP(op, ...) MOZ_MUST_USE bool emit##op();
|
||||
CACHE_IR_OPS(DEFINE_OP)
|
||||
#undef DEFINE_OP
|
||||
|
||||
|
@ -192,7 +192,7 @@ JitCode* BaselineCacheIRCompiler::compile() {
|
|||
|
||||
do {
|
||||
switch (reader.readOp()) {
|
||||
#define DEFINE_OP(op) \
|
||||
#define DEFINE_OP(op, ...) \
|
||||
case CacheOp::op: \
|
||||
if (!emit##op()) return nullptr; \
|
||||
break;
|
||||
|
@ -202,7 +202,9 @@ JitCode* BaselineCacheIRCompiler::compile() {
|
|||
default:
|
||||
MOZ_CRASH("Invalid op");
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
assertAllArgumentsConsumed();
|
||||
#endif
|
||||
allocator.nextOp();
|
||||
} while (reader.more());
|
||||
|
||||
|
|
|
@ -34,6 +34,45 @@ const char* const js::jit::CacheKindNames[] = {
|
|||
#undef DEFINE_KIND
|
||||
};
|
||||
|
||||
// We need to enter the namespace here so that the definition of
|
||||
// CacheIROpFormat::OpLengths can see CacheIROpFormat::ArgType
|
||||
// (without defining None/Id/Field/etc everywhere else in this file.)
|
||||
namespace js {
|
||||
namespace jit {
|
||||
namespace CacheIROpFormat {
|
||||
|
||||
static constexpr uint32_t CacheIROpLength(ArgType arg) {
|
||||
switch (arg) {
|
||||
case None:
|
||||
return 0;
|
||||
case Id:
|
||||
return sizeof(uint8_t);
|
||||
case Field:
|
||||
return sizeof(uint8_t);
|
||||
case Byte:
|
||||
return sizeof(uint8_t);
|
||||
case Int32:
|
||||
case UInt32:
|
||||
return sizeof(uint32_t);
|
||||
case Word:
|
||||
return sizeof(uintptr_t);
|
||||
}
|
||||
}
|
||||
template <typename... Args>
|
||||
static constexpr uint32_t CacheIROpLength(ArgType arg, Args... args) {
|
||||
return CacheIROpLength(arg) + CacheIROpLength(args...);
|
||||
}
|
||||
|
||||
const uint32_t OpLengths[] = {
|
||||
#define OPLENGTH(op, ...) 1 + CacheIROpLength(__VA_ARGS__),
|
||||
CACHE_IR_OPS(OPLENGTH)
|
||||
#undef OPLENGTH
|
||||
};
|
||||
|
||||
} // namespace CacheIROpFormat
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
void CacheIRWriter::assertSameCompartment(JSObject* obj) {
|
||||
cx_->debugOnlyCheck(obj);
|
||||
}
|
||||
|
|
|
@ -173,192 +173,216 @@ enum class CacheKind : uint8_t {
|
|||
|
||||
extern const char* const CacheKindNames[];
|
||||
|
||||
#define CACHE_IR_OPS(_) \
|
||||
_(GuardIsObject) \
|
||||
_(GuardIsObjectOrNull) \
|
||||
_(GuardIsNullOrUndefined) \
|
||||
_(GuardIsNotNullOrUndefined) \
|
||||
_(GuardIsNull) \
|
||||
_(GuardIsUndefined) \
|
||||
_(GuardIsBoolean) \
|
||||
_(GuardIsString) \
|
||||
_(GuardIsSymbol) \
|
||||
_(GuardIsBigInt) \
|
||||
_(GuardIsNumber) \
|
||||
_(GuardIsInt32) \
|
||||
_(GuardIsInt32Index) \
|
||||
_(GuardType) \
|
||||
_(GuardShape) \
|
||||
_(GuardGroup) \
|
||||
_(GuardProto) \
|
||||
_(GuardClass) /* Guard an object class, per GuardClassKind */ \
|
||||
_(GuardAnyClass) /* Guard an arbitrary class for an object */ \
|
||||
_(GuardCompartment) \
|
||||
_(GuardIsExtensible) \
|
||||
_(GuardIsNativeFunction) \
|
||||
_(GuardIsNativeObject) \
|
||||
_(GuardIsProxy) \
|
||||
_(GuardHasProxyHandler) \
|
||||
_(GuardNotDOMProxy) \
|
||||
_(GuardSpecificObject) \
|
||||
_(GuardSpecificAtom) \
|
||||
_(GuardSpecificSymbol) \
|
||||
_(GuardSpecificInt32Immediate) \
|
||||
_(GuardNoDetachedTypedObjects) \
|
||||
_(GuardMagicValue) \
|
||||
_(GuardFrameHasNoArgumentsObject) \
|
||||
_(GuardNoDenseElements) \
|
||||
_(GuardNoUnboxedExpando) \
|
||||
_(GuardAndLoadUnboxedExpando) \
|
||||
_(GuardAndGetIndexFromString) \
|
||||
_(GuardAndGetNumberFromString) \
|
||||
_(GuardAndGetIterator) \
|
||||
_(GuardHasGetterSetter) \
|
||||
_(GuardGroupHasUnanalyzedNewScript) \
|
||||
_(GuardIndexIsNonNegative) \
|
||||
_(GuardIndexGreaterThanDenseCapacity) \
|
||||
_(GuardIndexGreaterThanArrayLength) \
|
||||
_(GuardIndexIsValidUpdateOrAdd) \
|
||||
_(GuardIndexGreaterThanDenseInitLength) \
|
||||
_(GuardTagNotEqual) \
|
||||
_(GuardXrayExpandoShapeAndDefaultProto) \
|
||||
_(GuardFunctionPrototype) \
|
||||
_(GuardNoAllocationMetadataBuilder) \
|
||||
_(GuardObjectGroupNotPretenured) \
|
||||
_(LoadStackValue) \
|
||||
_(LoadObject) \
|
||||
_(LoadProto) \
|
||||
_(LoadEnclosingEnvironment) \
|
||||
_(LoadWrapperTarget) \
|
||||
_(LoadValueTag) \
|
||||
\
|
||||
_(TruncateDoubleToUInt32) \
|
||||
\
|
||||
_(MegamorphicLoadSlotResult) \
|
||||
_(MegamorphicLoadSlotByValueResult) \
|
||||
_(MegamorphicStoreSlot) \
|
||||
_(MegamorphicSetElement) \
|
||||
_(MegamorphicHasPropResult) \
|
||||
\
|
||||
/* See CacheIR.cpp 'DOM proxies' comment. */ \
|
||||
_(LoadDOMExpandoValue) \
|
||||
_(LoadDOMExpandoValueGuardGeneration) \
|
||||
_(LoadDOMExpandoValueIgnoreGeneration) \
|
||||
_(GuardDOMExpandoMissingOrGuardShape) \
|
||||
\
|
||||
_(StoreFixedSlot) \
|
||||
_(StoreDynamicSlot) \
|
||||
_(AddAndStoreFixedSlot) \
|
||||
_(AddAndStoreDynamicSlot) \
|
||||
_(AllocateAndStoreDynamicSlot) \
|
||||
_(StoreTypedObjectReferenceProperty) \
|
||||
_(StoreTypedObjectScalarProperty) \
|
||||
_(StoreUnboxedProperty) \
|
||||
_(StoreDenseElement) \
|
||||
_(StoreDenseElementHole) \
|
||||
_(ArrayPush) \
|
||||
_(ArrayJoinResult) \
|
||||
_(StoreTypedElement) \
|
||||
_(CallNativeSetter) \
|
||||
_(CallScriptedSetter) \
|
||||
_(CallSetArrayLength) \
|
||||
_(CallProxySet) \
|
||||
_(CallProxySetByValue) \
|
||||
_(CallAddOrUpdateSparseElementHelper) \
|
||||
_(CallInt32ToString) \
|
||||
_(CallNumberToString) \
|
||||
\
|
||||
/* The *Result ops load a value into the cache's result register. */ \
|
||||
_(LoadFixedSlotResult) \
|
||||
_(LoadDynamicSlotResult) \
|
||||
_(LoadUnboxedPropertyResult) \
|
||||
_(LoadTypedObjectResult) \
|
||||
_(LoadDenseElementResult) \
|
||||
_(LoadDenseElementHoleResult) \
|
||||
_(CallGetSparseElementResult) \
|
||||
_(LoadDenseElementExistsResult) \
|
||||
_(LoadTypedElementExistsResult) \
|
||||
_(LoadDenseElementHoleExistsResult) \
|
||||
_(LoadTypedElementResult) \
|
||||
_(LoadInt32ArrayLengthResult) \
|
||||
_(LoadArgumentsObjectArgResult) \
|
||||
_(LoadArgumentsObjectLengthResult) \
|
||||
_(LoadFunctionLengthResult) \
|
||||
_(LoadStringCharResult) \
|
||||
_(LoadStringLengthResult) \
|
||||
_(LoadFrameCalleeResult) \
|
||||
_(LoadFrameNumActualArgsResult) \
|
||||
_(LoadFrameArgumentResult) \
|
||||
_(LoadEnvironmentFixedSlotResult) \
|
||||
_(LoadEnvironmentDynamicSlotResult) \
|
||||
_(LoadObjectResult) \
|
||||
_(CallScriptedGetterResult) \
|
||||
_(CallNativeGetterResult) \
|
||||
_(CallProxyGetResult) \
|
||||
_(CallProxyGetByValueResult) \
|
||||
_(CallProxyHasPropResult) \
|
||||
_(CallObjectHasSparseElementResult) \
|
||||
_(CallNativeGetElementResult) \
|
||||
_(LoadUndefinedResult) \
|
||||
_(LoadBooleanResult) \
|
||||
_(LoadStringResult) \
|
||||
_(LoadInstanceOfObjectResult) \
|
||||
_(LoadTypeOfObjectResult) \
|
||||
_(DoubleAddResult) \
|
||||
_(DoubleSubResult) \
|
||||
_(DoubleMulResult) \
|
||||
_(DoubleDivResult) \
|
||||
_(DoubleModResult) \
|
||||
_(Int32AddResult) \
|
||||
_(Int32SubResult) \
|
||||
_(Int32MulResult) \
|
||||
_(Int32DivResult) \
|
||||
_(Int32ModResult) \
|
||||
_(Int32BitOrResult) \
|
||||
_(Int32BitXorResult) \
|
||||
_(Int32BitAndResult) \
|
||||
_(Int32LeftShiftResult) \
|
||||
_(Int32RightShiftResult) \
|
||||
_(Int32URightShiftResult) \
|
||||
_(Int32NotResult) \
|
||||
_(Int32NegationResult) \
|
||||
_(DoubleNegationResult) \
|
||||
_(Int32IncResult) \
|
||||
_(Int32DecResult) \
|
||||
_(DoubleIncResult) \
|
||||
_(DoubleDecResult) \
|
||||
_(LoadInt32TruthyResult) \
|
||||
_(LoadDoubleTruthyResult) \
|
||||
_(LoadStringTruthyResult) \
|
||||
_(LoadObjectTruthyResult) \
|
||||
_(LoadValueResult) \
|
||||
_(LoadNewObjectFromTemplateResult) \
|
||||
\
|
||||
_(CallStringSplitResult) \
|
||||
_(CallStringConcatResult) \
|
||||
_(CallStringObjectConcatResult) \
|
||||
_(CallIsSuspendedGeneratorResult) \
|
||||
\
|
||||
_(CompareStringResult) \
|
||||
_(CompareObjectResult) \
|
||||
_(CompareSymbolResult) \
|
||||
_(CompareInt32Result) \
|
||||
_(CompareDoubleResult) \
|
||||
_(CompareObjectUndefinedNullResult) \
|
||||
\
|
||||
_(CallPrintString) \
|
||||
_(Breakpoint) \
|
||||
\
|
||||
_(TypeMonitorResult) \
|
||||
_(ReturnFromIC) \
|
||||
_(WrapResult)
|
||||
// This namespace exists to make it possible to use unqualified
|
||||
// argument types in CACHE_IR_OPS without letting the symbols escape
|
||||
// into the global namespace. Any code that consumes the argument
|
||||
// information must have CacheIROpFormat in scope.
|
||||
namespace CacheIROpFormat {
|
||||
enum ArgType {
|
||||
None,
|
||||
Id,
|
||||
Field,
|
||||
Byte,
|
||||
Int32,
|
||||
UInt32,
|
||||
Word,
|
||||
};
|
||||
|
||||
extern const uint32_t OpLengths[];
|
||||
} // namespace CacheIROpFormat
|
||||
|
||||
#define CACHE_IR_OPS(_) \
|
||||
_(GuardIsObject, Id) \
|
||||
_(GuardIsObjectOrNull, Id) \
|
||||
_(GuardIsNullOrUndefined, Id) \
|
||||
_(GuardIsNotNullOrUndefined, Id) \
|
||||
_(GuardIsNull, Id) \
|
||||
_(GuardIsUndefined, Id) \
|
||||
_(GuardIsBoolean, Id, Id) \
|
||||
_(GuardIsString, Id) \
|
||||
_(GuardIsSymbol, Id) \
|
||||
_(GuardIsBigInt, Id) \
|
||||
_(GuardIsNumber, Id) \
|
||||
_(GuardIsInt32, Id, Id) \
|
||||
_(GuardIsInt32Index, Id, Id) \
|
||||
_(GuardType, Id, Byte) \
|
||||
_(GuardShape, Id, Field) \
|
||||
_(GuardGroup, Id, Field) \
|
||||
_(GuardProto, Id, Field) \
|
||||
_(GuardClass, Id, Byte) /* Guard per GuardClassKind */ \
|
||||
_(GuardAnyClass, Id, Field) /* Guard an arbitrary class */ \
|
||||
_(GuardCompartment, Id, Field, Field) \
|
||||
_(GuardIsExtensible, Id) \
|
||||
_(GuardIsNativeFunction, Id, Word) \
|
||||
_(GuardIsNativeObject, Id) \
|
||||
_(GuardIsProxy, Id) \
|
||||
_(GuardHasProxyHandler, Id, Field) \
|
||||
_(GuardNotDOMProxy, Id) \
|
||||
_(GuardSpecificObject, Id, Field) \
|
||||
_(GuardSpecificAtom, Id, Field) \
|
||||
_(GuardSpecificSymbol, Id, Field) \
|
||||
_(GuardSpecificInt32Immediate, Id, Int32, Byte) \
|
||||
_(GuardNoDetachedTypedObjects, None) \
|
||||
_(GuardMagicValue, Id, Byte) \
|
||||
_(GuardFrameHasNoArgumentsObject, None) \
|
||||
_(GuardNoDenseElements, Id) \
|
||||
_(GuardNoUnboxedExpando, Id) \
|
||||
_(GuardAndLoadUnboxedExpando, Id, Id) \
|
||||
_(GuardAndGetIndexFromString, Id, Id) \
|
||||
_(GuardAndGetNumberFromString, Id, Id) \
|
||||
_(GuardAndGetIterator, Id, Id, Field, Field) \
|
||||
_(GuardHasGetterSetter, Id, Field) \
|
||||
_(GuardGroupHasUnanalyzedNewScript, Field) \
|
||||
_(GuardIndexIsNonNegative, Id) \
|
||||
_(GuardIndexGreaterThanDenseCapacity, Id, Id) \
|
||||
_(GuardIndexGreaterThanArrayLength, Id, Id) \
|
||||
_(GuardIndexIsValidUpdateOrAdd, Id, Id) \
|
||||
_(GuardIndexGreaterThanDenseInitLength, Id, Id) \
|
||||
_(GuardTagNotEqual, Id, Id) \
|
||||
_(GuardXrayExpandoShapeAndDefaultProto, Id, Byte, Field) \
|
||||
_(GuardFunctionPrototype, Id, Id, Field) \
|
||||
_(GuardNoAllocationMetadataBuilder, None) \
|
||||
_(GuardObjectGroupNotPretenured, Field) \
|
||||
_(LoadStackValue, Id, UInt32) \
|
||||
_(LoadObject, Id, Field) \
|
||||
_(LoadProto, Id, Id) \
|
||||
_(LoadEnclosingEnvironment, Id, Id) \
|
||||
_(LoadWrapperTarget, Id, Id) \
|
||||
_(LoadValueTag, Id, Id) \
|
||||
\
|
||||
_(TruncateDoubleToUInt32, Id, Id) \
|
||||
\
|
||||
_(MegamorphicLoadSlotResult, Id, Field, Byte) \
|
||||
_(MegamorphicLoadSlotByValueResult, Id, Id, Byte) \
|
||||
_(MegamorphicStoreSlot, Id, Field, Id, Byte) \
|
||||
_(MegamorphicSetElement, Id, Id, Id, Byte) \
|
||||
_(MegamorphicHasPropResult, Id, Id, Byte) \
|
||||
\
|
||||
/* See CacheIR.cpp 'DOM proxies' comment. */ \
|
||||
_(LoadDOMExpandoValue, Id, Id) \
|
||||
_(LoadDOMExpandoValueGuardGeneration, Id, Field, Field, Id) \
|
||||
_(LoadDOMExpandoValueIgnoreGeneration, Id, Id) \
|
||||
_(GuardDOMExpandoMissingOrGuardShape, Id, Field) \
|
||||
\
|
||||
_(StoreFixedSlot, Id, Field, Id) \
|
||||
_(StoreDynamicSlot, Id, Field, Id) \
|
||||
_(AddAndStoreFixedSlot, Id, Field, Id, Byte, Field, Field) \
|
||||
_(AddAndStoreDynamicSlot, Id, Field, Id, Byte, Field, Field) \
|
||||
_(AllocateAndStoreDynamicSlot, Id, Field, Id, Byte, Field, Field, Field) \
|
||||
_(StoreTypedObjectReferenceProperty, Id, Field, Byte, Byte, Id) \
|
||||
_(StoreTypedObjectScalarProperty, Id, Field, Byte, Byte, Id) \
|
||||
_(StoreUnboxedProperty, Id, Byte, Field, Id) \
|
||||
_(StoreDenseElement, Id, Id, Id) \
|
||||
_(StoreDenseElementHole, Id, Id, Id, Byte) \
|
||||
_(ArrayPush, Id, Id) \
|
||||
_(ArrayJoinResult, Id) \
|
||||
_(StoreTypedElement, Id, Id, Id, Byte, Byte, Byte) \
|
||||
_(CallNativeSetter, Id, Id, Field) \
|
||||
_(CallScriptedSetter, Id, Field, Id, Byte) \
|
||||
_(CallSetArrayLength, Id, Byte, Id) \
|
||||
_(CallProxySet, Id, Id, Field, Byte) \
|
||||
_(CallProxySetByValue, Id, Id, Id, Byte) \
|
||||
_(CallAddOrUpdateSparseElementHelper, Id, Id, Id, Byte) \
|
||||
_(CallInt32ToString, Id, Id) \
|
||||
_(CallNumberToString, Id, Id) \
|
||||
\
|
||||
/* The *Result ops load a value into the cache's result register. */ \
|
||||
_(LoadFixedSlotResult, Id, Field) \
|
||||
_(LoadDynamicSlotResult, Id, Field) \
|
||||
_(LoadUnboxedPropertyResult, Id, Byte, Field) \
|
||||
_(LoadTypedObjectResult, Id, Byte, Byte, Field) \
|
||||
_(LoadDenseElementResult, Id, Id) \
|
||||
_(LoadDenseElementHoleResult, Id, Id) \
|
||||
_(CallGetSparseElementResult, Id, Id) \
|
||||
_(LoadDenseElementExistsResult, Id, Id) \
|
||||
_(LoadTypedElementExistsResult, Id, Id, Byte) \
|
||||
_(LoadDenseElementHoleExistsResult, Id, Id) \
|
||||
_(LoadTypedElementResult, Id, Id, Byte, Byte) \
|
||||
_(LoadInt32ArrayLengthResult, Id) \
|
||||
_(LoadArgumentsObjectArgResult, Id, Id) \
|
||||
_(LoadArgumentsObjectLengthResult, Id) \
|
||||
_(LoadFunctionLengthResult, Id) \
|
||||
_(LoadStringCharResult, Id, Id) \
|
||||
_(LoadStringLengthResult, Id) \
|
||||
_(LoadFrameCalleeResult, None) \
|
||||
_(LoadFrameNumActualArgsResult, None) \
|
||||
_(LoadFrameArgumentResult, Id) \
|
||||
_(LoadEnvironmentFixedSlotResult, Id, Field) \
|
||||
_(LoadEnvironmentDynamicSlotResult, Id, Field) \
|
||||
_(LoadObjectResult, Id) \
|
||||
_(CallScriptedGetterResult, Id, Field, Byte) \
|
||||
_(CallNativeGetterResult, Id, Field) \
|
||||
_(CallProxyGetResult, Id, Field) \
|
||||
_(CallProxyGetByValueResult, Id, Id) \
|
||||
_(CallProxyHasPropResult, Id, Id, Byte) \
|
||||
_(CallObjectHasSparseElementResult, Id, Id) \
|
||||
_(CallNativeGetElementResult, Id, Id) \
|
||||
_(LoadUndefinedResult, None) \
|
||||
_(LoadBooleanResult, Byte) \
|
||||
_(LoadStringResult, Field) \
|
||||
_(LoadInstanceOfObjectResult, Id, Id) \
|
||||
_(LoadTypeOfObjectResult, Id) \
|
||||
_(DoubleAddResult, Id, Id) \
|
||||
_(DoubleSubResult, Id, Id) \
|
||||
_(DoubleMulResult, Id, Id) \
|
||||
_(DoubleDivResult, Id, Id) \
|
||||
_(DoubleModResult, Id, Id) \
|
||||
_(Int32AddResult, Id, Id) \
|
||||
_(Int32SubResult, Id, Id) \
|
||||
_(Int32MulResult, Id, Id) \
|
||||
_(Int32DivResult, Id, Id) \
|
||||
_(Int32ModResult, Id, Id) \
|
||||
_(Int32BitOrResult, Id, Id) \
|
||||
_(Int32BitXorResult, Id, Id) \
|
||||
_(Int32BitAndResult, Id, Id) \
|
||||
_(Int32LeftShiftResult, Id, Id) \
|
||||
_(Int32RightShiftResult, Id, Id) \
|
||||
_(Int32URightShiftResult, Id, Id, Byte) \
|
||||
_(Int32NotResult, Id) \
|
||||
_(Int32NegationResult, Id) \
|
||||
_(DoubleNegationResult, Id) \
|
||||
_(Int32IncResult, Id) \
|
||||
_(Int32DecResult, Id) \
|
||||
_(DoubleIncResult, Id) \
|
||||
_(DoubleDecResult, Id) \
|
||||
_(LoadInt32TruthyResult, Id) \
|
||||
_(LoadDoubleTruthyResult, Id) \
|
||||
_(LoadStringTruthyResult, Id) \
|
||||
_(LoadObjectTruthyResult, Id) \
|
||||
_(LoadValueResult, Field) \
|
||||
_(LoadNewObjectFromTemplateResult, Field, UInt32, UInt32) \
|
||||
\
|
||||
_(CallStringSplitResult, Id, Id, Field) \
|
||||
_(CallStringConcatResult, Id, Id) \
|
||||
_(CallStringObjectConcatResult, Id, Id) \
|
||||
_(CallIsSuspendedGeneratorResult, Id) \
|
||||
\
|
||||
_(CompareStringResult, Id, Id, Byte) \
|
||||
_(CompareObjectResult, Id, Id, Byte) \
|
||||
_(CompareSymbolResult, Id, Id, Byte) \
|
||||
_(CompareInt32Result, Id, Id, Byte) \
|
||||
_(CompareDoubleResult, Id, Id, Byte) \
|
||||
_(CompareObjectUndefinedNullResult, Id, Byte) \
|
||||
\
|
||||
_(CallPrintString, Word) \
|
||||
_(Breakpoint, None) \
|
||||
\
|
||||
_(TypeMonitorResult, None) \
|
||||
_(ReturnFromIC, None) \
|
||||
_(WrapResult, None)
|
||||
|
||||
enum class CacheOp {
|
||||
#define DEFINE_OP(op) op,
|
||||
#define DEFINE_OP(op, ...) op,
|
||||
CACHE_IR_OPS(DEFINE_OP)
|
||||
#undef DEFINE_OP
|
||||
};
|
||||
|
||||
const char* const CacheIrOpNames[] = {
|
||||
#define OPNAME(op, ...) #op,
|
||||
CACHE_IR_OPS(OPNAME)
|
||||
#undef OPNAME
|
||||
};
|
||||
|
||||
class StubField {
|
||||
public:
|
||||
enum class Type : uint8_t {
|
||||
|
@ -500,8 +524,8 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter {
|
|||
operandLastUsed_[opId.id()] = nextInstructionId_ - 1;
|
||||
}
|
||||
|
||||
void writeInt32Immediate(int32_t i32) { buffer_.writeSigned(i32); }
|
||||
void writeUint32Immediate(uint32_t u32) { buffer_.writeUnsigned(u32); }
|
||||
void writeInt32Immediate(int32_t i32) { buffer_.writeFixedUint32_t(i32); }
|
||||
void writeUint32Immediate(uint32_t u32) { buffer_.writeFixedUint32_t(u32); }
|
||||
void writePointer(void* ptr) { buffer_.writeRawPointer(ptr); }
|
||||
|
||||
void writeOpWithOperandId(CacheOp op, OperandId opId) {
|
||||
|
@ -757,8 +781,7 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter {
|
|||
void guardSpecificInt32Immediate(
|
||||
Int32OperandId operand, int32_t expected,
|
||||
Assembler::Condition cond = Assembler::Equal) {
|
||||
writeOp(CacheOp::GuardSpecificInt32Immediate);
|
||||
writeOperandId(operand);
|
||||
writeOpWithOperandId(CacheOp::GuardSpecificInt32Immediate, operand);
|
||||
writeInt32Immediate(expected);
|
||||
buffer_.writeByte(uint32_t(cond));
|
||||
}
|
||||
|
@ -1344,8 +1367,7 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter {
|
|||
}
|
||||
void loadInstanceOfObjectResult(ValOperandId lhs, ObjOperandId protoId,
|
||||
uint32_t slot) {
|
||||
writeOp(CacheOp::LoadInstanceOfObjectResult);
|
||||
writeOperandId(lhs);
|
||||
writeOpWithOperandId(CacheOp::LoadInstanceOfObjectResult, lhs);
|
||||
writeOperandId(protoId);
|
||||
}
|
||||
void loadTypeOfObjectResult(ObjOperandId obj) {
|
||||
|
@ -1387,8 +1409,7 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter {
|
|||
}
|
||||
void callStringSplitResult(StringOperandId str, StringOperandId sep,
|
||||
ObjectGroup* group) {
|
||||
writeOp(CacheOp::CallStringSplitResult);
|
||||
writeOperandId(str);
|
||||
writeOpWithOperandId(CacheOp::CallStringSplitResult, str);
|
||||
writeOperandId(sep);
|
||||
addStubField(uintptr_t(group), StubField::Type::ObjectGroup);
|
||||
}
|
||||
|
@ -1482,8 +1503,8 @@ class MOZ_RAII CacheIRReader {
|
|||
uint32_t typeDescrKey() { return buffer_.readByte(); }
|
||||
JSWhyMagic whyMagic() { return JSWhyMagic(buffer_.readByte()); }
|
||||
JSOp jsop() { return JSOp(buffer_.readByte()); }
|
||||
int32_t int32Immediate() { return buffer_.readSigned(); }
|
||||
uint32_t uint32Immediate() { return buffer_.readUnsigned(); }
|
||||
int32_t int32Immediate() { return int32_t(buffer_.readFixedUint32_t()); }
|
||||
uint32_t uint32Immediate() { return buffer_.readFixedUint32_t(); }
|
||||
void* pointer() { return buffer_.readRawPointer(); }
|
||||
|
||||
ReferenceType referenceTypeDescrType() {
|
||||
|
@ -1522,6 +1543,7 @@ class MOZ_RAII CacheIRReader {
|
|||
buffer_.seek(pos, 0);
|
||||
return false;
|
||||
}
|
||||
const uint8_t* currentPosition() const { return buffer_.currentPosition(); }
|
||||
};
|
||||
|
||||
class MOZ_RAII IRGenerator {
|
||||
|
|
|
@ -727,6 +727,23 @@ class MOZ_RAII CacheIRCompiler {
|
|||
|
||||
StubFieldPolicy stubFieldPolicy_;
|
||||
|
||||
#ifdef DEBUG
|
||||
const uint8_t* currentVerificationPosition_;
|
||||
|
||||
// Verify that the number of bytes consumed by the compiler matches
|
||||
// up with the opcode signature in CACHE_IR_OPS.
|
||||
void assertAllArgumentsConsumed() {
|
||||
CacheOp prevOp = CacheOp(*currentVerificationPosition_);
|
||||
uint32_t expectedLength = CacheIROpFormat::OpLengths[uint8_t(prevOp)];
|
||||
|
||||
const uint8_t* newPosition = reader.currentPosition();
|
||||
MOZ_ASSERT(newPosition > currentVerificationPosition_);
|
||||
uint32_t actualLength = newPosition - currentVerificationPosition_;
|
||||
MOZ_ASSERT(actualLength == expectedLength);
|
||||
currentVerificationPosition_ = newPosition;
|
||||
};
|
||||
#endif
|
||||
|
||||
CacheIRCompiler(JSContext* cx, const CacheIRWriter& writer,
|
||||
uint32_t stubDataOffset, Mode mode, StubFieldPolicy policy)
|
||||
: cx_(cx),
|
||||
|
@ -738,6 +755,9 @@ class MOZ_RAII CacheIRCompiler {
|
|||
stubDataOffset_(stubDataOffset),
|
||||
stubFieldPolicy_(policy) {
|
||||
MOZ_ASSERT(!writer.failed());
|
||||
#ifdef DEBUG
|
||||
currentVerificationPosition_ = reader.currentPosition();
|
||||
#endif
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool addFailurePath(FailurePath** failure);
|
||||
|
|
|
@ -192,6 +192,72 @@ void CacheIRSpewer::opcodeProperty(const char* name, const JSOp op) {
|
|||
j.endStringProperty();
|
||||
}
|
||||
|
||||
void CacheIRSpewer::CacheIRArgs(JSONPrinter& j, CacheIRReader& r,
|
||||
CacheIROpFormat::ArgType arg) {
|
||||
j.beginObject();
|
||||
switch (arg) {
|
||||
case CacheIROpFormat::None:
|
||||
break;
|
||||
case CacheIROpFormat::Id:
|
||||
j.property("Id", r.readByte());
|
||||
break;
|
||||
case CacheIROpFormat::Field:
|
||||
j.property("Field", r.readByte());
|
||||
break;
|
||||
case CacheIROpFormat::Byte:
|
||||
j.property("Byte", r.readByte());
|
||||
break;
|
||||
case CacheIROpFormat::Int32:
|
||||
j.property("Int32", r.int32Immediate());
|
||||
break;
|
||||
case CacheIROpFormat::UInt32:
|
||||
j.property("Uint32", r.uint32Immediate());
|
||||
break;
|
||||
case CacheIROpFormat::Word:
|
||||
j.property("Word", uintptr_t(r.pointer()));
|
||||
break;
|
||||
}
|
||||
j.endObject();
|
||||
}
|
||||
template <typename... Args>
|
||||
void CacheIRSpewer::CacheIRArgs(JSONPrinter& j, CacheIRReader& r,
|
||||
CacheIROpFormat::ArgType arg, Args... args) {
|
||||
using namespace js::jit::CacheIROpFormat;
|
||||
|
||||
CacheIRArgs(j, r, arg);
|
||||
CacheIRArgs(j, r, args...);
|
||||
}
|
||||
|
||||
void CacheIRSpewer::cacheIRSequence(CacheIRReader& reader) {
|
||||
using namespace js::jit::CacheIROpFormat;
|
||||
|
||||
MOZ_ASSERT(enabled());
|
||||
JSONPrinter& j = json_.ref();
|
||||
|
||||
j.beginListProperty("cacheIR");
|
||||
while (reader.more()) {
|
||||
j.beginObject();
|
||||
CacheOp op = reader.readOp();
|
||||
j.property("op", CacheIrOpNames[uint32_t(op)]);
|
||||
j.beginListProperty("args");
|
||||
|
||||
switch (op) {
|
||||
# define DEFINE_OP(op, ...) \
|
||||
case CacheOp::op: \
|
||||
CacheIRArgs(j, reader, __VA_ARGS__); \
|
||||
break;
|
||||
CACHE_IR_OPS(DEFINE_OP)
|
||||
# undef DEFINE_OP
|
||||
default:
|
||||
MOZ_CRASH("unreachable");
|
||||
}
|
||||
|
||||
j.endList();
|
||||
j.endObject();
|
||||
}
|
||||
j.endList();
|
||||
}
|
||||
|
||||
void CacheIRSpewer::attached(const char* name) {
|
||||
MOZ_ASSERT(enabled());
|
||||
json_.ref().property("attached", name);
|
||||
|
|
|
@ -50,6 +50,12 @@ class CacheIRSpewer {
|
|||
void beginCache(const IRGenerator& generator);
|
||||
void valueProperty(const char* name, const Value& v);
|
||||
void opcodeProperty(const char* name, const JSOp op);
|
||||
void cacheIRSequence(CacheIRReader& reader);
|
||||
void CacheIRArgs(JSONPrinter& j, CacheIRReader& r,
|
||||
CacheIROpFormat::ArgType arg);
|
||||
template <typename... Args>
|
||||
void CacheIRArgs(JSONPrinter& j, CacheIRReader& r,
|
||||
CacheIROpFormat::ArgType arg, Args... args);
|
||||
void attached(const char* name);
|
||||
void endCache();
|
||||
|
||||
|
@ -73,6 +79,10 @@ class CacheIRSpewer {
|
|||
|
||||
~Guard() {
|
||||
if (sp_.enabled()) {
|
||||
if (gen_.writerRef().codeLength() > 0) {
|
||||
CacheIRReader reader(gen_.writerRef());
|
||||
sp_.cacheIRSequence(reader);
|
||||
}
|
||||
if (name_ != nullptr) {
|
||||
sp_.attached(name_);
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ class MOZ_RAII IonCacheIRCompiler : public CacheIRCompiler {
|
|||
stubJitCodeOffset_.emplace(masm.PushWithPatch(ImmPtr((void*)-1)));
|
||||
}
|
||||
|
||||
#define DEFINE_OP(op) MOZ_MUST_USE bool emit##op();
|
||||
#define DEFINE_OP(op, ...) MOZ_MUST_USE bool emit##op();
|
||||
CACHE_IR_OPS(DEFINE_OP)
|
||||
#undef DEFINE_OP
|
||||
};
|
||||
|
@ -588,7 +588,7 @@ JitCode* IonCacheIRCompiler::compile() {
|
|||
|
||||
do {
|
||||
switch (reader.readOp()) {
|
||||
#define DEFINE_OP(op) \
|
||||
#define DEFINE_OP(op, ...) \
|
||||
case CacheOp::op: \
|
||||
if (!emit##op()) return nullptr; \
|
||||
break;
|
||||
|
@ -598,7 +598,9 @@ JitCode* IonCacheIRCompiler::compile() {
|
|||
default:
|
||||
MOZ_CRASH("Invalid op");
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
assertAllArgumentsConsumed();
|
||||
#endif
|
||||
allocator.nextOp();
|
||||
} while (reader.more());
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ EXPORTS.js += [
|
|||
'../public/OffThreadScriptCompilation.h',
|
||||
'../public/Principals.h',
|
||||
'../public/Printf.h',
|
||||
'../public/ProfilingCategory.h',
|
||||
'../public/ProfilingFrameIterator.h',
|
||||
'../public/ProfilingStack.h',
|
||||
'../public/Promise.h',
|
||||
|
|
|
@ -79,7 +79,7 @@ GeckoProfilerEntryMarker::~GeckoProfilerEntryMarker() {
|
|||
|
||||
MOZ_ALWAYS_INLINE
|
||||
AutoGeckoProfilerEntry::AutoGeckoProfilerEntry(
|
||||
JSContext* cx, const char* label, ProfilingStackFrame::Category category,
|
||||
JSContext* cx, const char* label, JS::ProfilingCategoryPair categoryPair,
|
||||
uint32_t flags MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
|
||||
: profiler_(&cx->geckoProfiler()) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
|
@ -92,7 +92,8 @@ AutoGeckoProfilerEntry::AutoGeckoProfilerEntry(
|
|||
#endif
|
||||
profiler_->profilingStack_->pushLabelFrame(label,
|
||||
/* dynamicString = */ nullptr,
|
||||
/* sp = */ this, category, flags);
|
||||
/* sp = */ this, categoryPair,
|
||||
flags);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "vm/GeckoProfiler-inl.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
#include "jsnum.h"
|
||||
|
@ -476,3 +477,60 @@ AutoSuppressProfilerSampling::~AutoSuppressProfilerSampling() {
|
|||
cx_->enableProfilerSampling();
|
||||
}
|
||||
}
|
||||
|
||||
namespace JS {
|
||||
|
||||
// clang-format off
|
||||
|
||||
// ProfilingSubcategory_X:
|
||||
// One enum for each category X, listing that category's subcategories. This
|
||||
// allows the sProfilingCategoryInfo macro construction below to look up a
|
||||
// per-category index for a subcategory.
|
||||
#define SUBCATEGORY_ENUMS_BEGIN_CATEGORY(name, labelAsString, color) \
|
||||
enum class ProfilingSubcategory_##name : uint32_t {
|
||||
#define SUBCATEGORY_ENUMS_SUBCATEGORY(category, name, labelAsString) \
|
||||
name,
|
||||
#define SUBCATEGORY_ENUMS_END_CATEGORY \
|
||||
};
|
||||
PROFILING_CATEGORY_LIST(SUBCATEGORY_ENUMS_BEGIN_CATEGORY,
|
||||
SUBCATEGORY_ENUMS_SUBCATEGORY,
|
||||
SUBCATEGORY_ENUMS_END_CATEGORY)
|
||||
#undef SUBCATEGORY_ENUMS_BEGIN_CATEGORY
|
||||
#undef SUBCATEGORY_ENUMS_SUBCATEGORY
|
||||
#undef SUBCATEGORY_ENUMS_END_CATEGORY
|
||||
|
||||
// sProfilingCategoryPairInfo:
|
||||
// A list of ProfilingCategoryPairInfos with the same order as
|
||||
// ProfilingCategoryPair, which can be used to map a ProfilingCategoryPair to
|
||||
// its information.
|
||||
#define CATEGORY_INFO_BEGIN_CATEGORY(name, labelAsString, color)
|
||||
#define CATEGORY_INFO_SUBCATEGORY(category, name, labelAsString) \
|
||||
{ProfilingCategory::category, \
|
||||
uint32_t(ProfilingSubcategory_##category::name), labelAsString},
|
||||
#define CATEGORY_INFO_END_CATEGORY
|
||||
const ProfilingCategoryPairInfo sProfilingCategoryPairInfo[] = {
|
||||
PROFILING_CATEGORY_LIST(CATEGORY_INFO_BEGIN_CATEGORY,
|
||||
CATEGORY_INFO_SUBCATEGORY,
|
||||
CATEGORY_INFO_END_CATEGORY)
|
||||
};
|
||||
#undef CATEGORY_INFO_BEGIN_CATEGORY
|
||||
#undef CATEGORY_INFO_SUBCATEGORY
|
||||
#undef CATEGORY_INFO_END_CATEGORY
|
||||
|
||||
// clang-format on
|
||||
|
||||
JS_FRIEND_API const ProfilingCategoryPairInfo& GetProfilingCategoryPairInfo(
|
||||
ProfilingCategoryPair aCategoryPair) {
|
||||
static_assert(
|
||||
MOZ_ARRAY_LENGTH(sProfilingCategoryPairInfo) ==
|
||||
uint32_t(ProfilingCategoryPair::COUNT),
|
||||
"sProfilingCategoryPairInfo and ProfilingCategory need to have the "
|
||||
"same order and the same length");
|
||||
|
||||
uint32_t categoryPairIndex = uint32_t(aCategoryPair);
|
||||
MOZ_RELEASE_ASSERT(categoryPairIndex <=
|
||||
uint32_t(ProfilingCategoryPair::LAST));
|
||||
return sProfilingCategoryPairInfo[categoryPairIndex];
|
||||
}
|
||||
|
||||
} // namespace JS
|
||||
|
|
|
@ -177,8 +177,7 @@ class MOZ_NONHEAP_CLASS AutoGeckoProfilerEntry {
|
|||
public:
|
||||
explicit MOZ_ALWAYS_INLINE AutoGeckoProfilerEntry(
|
||||
JSContext* cx, const char* label,
|
||||
ProfilingStackFrame::Category category =
|
||||
ProfilingStackFrame::Category::JS,
|
||||
JS::ProfilingCategoryPair categoryPair = JS::ProfilingCategoryPair::JS,
|
||||
uint32_t flags = 0 MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||
MOZ_ALWAYS_INLINE ~AutoGeckoProfilerEntry();
|
||||
|
||||
|
|
|
@ -57,9 +57,9 @@ GlobalHelperThreadState* gHelperThreadState = nullptr;
|
|||
#define PROFILER_RAII_PASTE(id, line) id##line
|
||||
#define PROFILER_RAII_EXPAND(id, line) PROFILER_RAII_PASTE(id, line)
|
||||
#define PROFILER_RAII PROFILER_RAII_EXPAND(raiiObject, __LINE__)
|
||||
#define AUTO_PROFILER_LABEL(label, category) \
|
||||
#define AUTO_PROFILER_LABEL(label, categoryPair) \
|
||||
HelperThread::AutoProfilerLabel PROFILER_RAII( \
|
||||
this, label, js::ProfilingStackFrame::Category::category)
|
||||
this, label, JS::ProfilingCategoryPair::categoryPair)
|
||||
|
||||
bool js::CreateHelperThreadsState() {
|
||||
MOZ_ASSERT(!gHelperThreadState);
|
||||
|
@ -2410,10 +2410,10 @@ const HelperThread::TaskSpec HelperThread::taskSpecs[] = {
|
|||
|
||||
HelperThread::AutoProfilerLabel::AutoProfilerLabel(
|
||||
HelperThread* helperThread, const char* label,
|
||||
ProfilingStackFrame::Category category)
|
||||
JS::ProfilingCategoryPair categoryPair)
|
||||
: profilingStack(helperThread->profilingStack) {
|
||||
if (profilingStack) {
|
||||
profilingStack->pushLabelFrame(label, nullptr, this, category);
|
||||
profilingStack->pushLabelFrame(label, nullptr, this, categoryPair);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -426,7 +426,7 @@ struct HelperThread {
|
|||
private:
|
||||
struct AutoProfilerLabel {
|
||||
AutoProfilerLabel(HelperThread* helperThread, const char* label,
|
||||
ProfilingStackFrame::Category category);
|
||||
JS::ProfilingCategoryPair categoryPair);
|
||||
~AutoProfilerLabel();
|
||||
|
||||
private:
|
||||
|
|
|
@ -39,7 +39,7 @@ class MOZ_RAII AutoProfilerStyleMarker {
|
|||
return;
|
||||
}
|
||||
ServoTraversalStatistics::sActive = false;
|
||||
profiler_add_marker("Styles", js::ProfilingStackFrame::Category::LAYOUT,
|
||||
profiler_add_marker("Styles", JS::ProfilingCategoryPair::LAYOUT,
|
||||
MakeUnique<StyleMarkerPayload>(
|
||||
mStartTime, TimeStamp::Now(), std::move(mCause),
|
||||
ServoTraversalStatistics::sSingleton, mDocShellId,
|
||||
|
|
|
@ -8850,7 +8850,7 @@ bool nsIPresShell::DoReflow(nsIFrame* target, bool aInterruptible,
|
|||
#ifdef MOZ_GECKO_PROFILER
|
||||
nsIURI* uri = mDocument->GetDocumentURI();
|
||||
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(
|
||||
"PresShell::DoReflow", LAYOUT,
|
||||
"Reflow", LAYOUT_Reflow,
|
||||
uri ? uri->GetSpecOrDefault() : NS_LITERAL_CSTRING("N/A"));
|
||||
#endif
|
||||
|
||||
|
@ -8881,7 +8881,7 @@ bool nsIPresShell::DoReflow(nsIFrame* target, bool aInterruptible,
|
|||
#ifdef MOZ_GECKO_PROFILER
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);
|
||||
AutoProfilerTracing tracingLayoutFlush(
|
||||
"Paint", "Reflow", js::ProfilingStackFrame::Category::LAYOUT,
|
||||
"Paint", "Reflow", JS::ProfilingCategoryPair::LAYOUT,
|
||||
std::move(mReflowCause), docShellId, docShellHistoryId);
|
||||
mReflowCause = nullptr;
|
||||
#endif
|
||||
|
|
|
@ -2508,7 +2508,8 @@ nsIFrame* nsCSSFrameConstructor::ConstructDocElementFrame(
|
|||
}
|
||||
|
||||
nsIFrame* nsCSSFrameConstructor::ConstructRootFrame() {
|
||||
AUTO_PROFILER_LABEL("nsCSSFrameConstructor::ConstructRootFrame", LAYOUT);
|
||||
AUTO_PROFILER_LABEL("nsCSSFrameConstructor::ConstructRootFrame",
|
||||
LAYOUT_FrameConstruction);
|
||||
AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
|
||||
|
||||
ServoStyleSet* styleSet = mPresShell->StyleSet();
|
||||
|
@ -6616,7 +6617,8 @@ void nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
|
|||
MOZ_ASSERT(aInsertionKind == InsertionKind::Sync ||
|
||||
!RestyleManager()->IsInStyleRefresh());
|
||||
|
||||
AUTO_PROFILER_LABEL("nsCSSFrameConstructor::ContentAppended", LAYOUT);
|
||||
AUTO_PROFILER_LABEL("nsCSSFrameConstructor::ContentAppended",
|
||||
LAYOUT_FrameConstruction);
|
||||
AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -6914,7 +6916,8 @@ void nsCSSFrameConstructor::ContentRangeInserted(
|
|||
MOZ_ASSERT(aInsertionKind == InsertionKind::Sync ||
|
||||
!RestyleManager()->IsInStyleRefresh());
|
||||
|
||||
AUTO_PROFILER_LABEL("nsCSSFrameConstructor::ContentRangeInserted", LAYOUT);
|
||||
AUTO_PROFILER_LABEL("nsCSSFrameConstructor::ContentRangeInserted",
|
||||
LAYOUT_FrameConstruction);
|
||||
AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
|
||||
|
||||
MOZ_ASSERT(aStartChild, "must always pass a child");
|
||||
|
@ -7363,7 +7366,8 @@ bool nsCSSFrameConstructor::ContentRemoved(nsIContent* aChild,
|
|||
MOZ_ASSERT(aChild);
|
||||
MOZ_ASSERT(!aChild->IsRootOfAnonymousSubtree() || !aOldNextSibling,
|
||||
"Anonymous roots don't have siblings");
|
||||
AUTO_PROFILER_LABEL("nsCSSFrameConstructor::ContentRemoved", LAYOUT);
|
||||
AUTO_PROFILER_LABEL("nsCSSFrameConstructor::ContentRemoved",
|
||||
LAYOUT_FrameConstruction);
|
||||
AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
|
||||
nsPresContext* presContext = mPresShell->GetPresContext();
|
||||
MOZ_ASSERT(presContext, "Our presShell should have a valid presContext");
|
||||
|
@ -7753,7 +7757,8 @@ bool nsCSSFrameConstructor::EnsureFrameForTextNodeIsCreatedAfterFlush(
|
|||
|
||||
void nsCSSFrameConstructor::CharacterDataChanged(
|
||||
nsIContent* aContent, const CharacterDataChangeInfo& aInfo) {
|
||||
AUTO_PROFILER_LABEL("nsCSSFrameConstructor::CharacterDataChanged", LAYOUT);
|
||||
AUTO_PROFILER_LABEL("nsCSSFrameConstructor::CharacterDataChanged",
|
||||
LAYOUT_FrameConstruction);
|
||||
AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
|
||||
|
||||
if ((aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) &&
|
||||
|
|
|
@ -3534,7 +3534,7 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
|
|||
PartialUpdateResult updateState = PartialUpdateResult::Failed;
|
||||
|
||||
{
|
||||
AUTO_PROFILER_LABEL("nsLayoutUtils::PaintFrame:BuildDisplayList", GRAPHICS);
|
||||
AUTO_PROFILER_LABEL_CATEGORY_PAIR(GRAPHICS_DisplayListBuilding);
|
||||
AUTO_PROFILER_TRACING("Paint", "DisplayList", GRAPHICS);
|
||||
|
||||
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::DisplayList);
|
||||
|
@ -6761,7 +6761,8 @@ static ImgDrawResult DrawImageInternal(
|
|||
SamplingFilter aSamplingFilter, const nsRect& aDest, const nsRect& aFill,
|
||||
const nsSize& aRepeatSize, const nsPoint& aAnchor, const nsRect& aDirty,
|
||||
uint32_t aImageFlags, ExtendMode aExtendMode, float aOpacity) {
|
||||
AUTO_PROFILER_LABEL("nsLayoutUtils::DrawBackgroundImage", GRAPHICS);
|
||||
AUTO_PROFILER_LABEL("nsLayoutUtils::DrawBackgroundImage",
|
||||
GRAPHICS_Rasterization);
|
||||
|
||||
Maybe<SVGImageContext> svgContext(Some(SVGImageContext(Some(aImageSize))));
|
||||
SVGImageContext::MaybeStoreContextPaint(svgContext, aForFrame, aImage);
|
||||
|
|
|
@ -51,7 +51,8 @@ void ViewportFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
|||
|
||||
void ViewportFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) {
|
||||
AUTO_PROFILER_LABEL("ViewportFrame::BuildDisplayList", GRAPHICS);
|
||||
AUTO_PROFILER_LABEL("ViewportFrame::BuildDisplayList",
|
||||
GRAPHICS_DisplayListBuilding);
|
||||
|
||||
if (nsIFrame* kid = mFrames.FirstChild()) {
|
||||
// make the kid's BorderBackground our own. This ensures that the canvas
|
||||
|
|
|
@ -5574,21 +5574,35 @@ void ScrollFrameHelper::UpdateMinimumScaleSize(
|
|||
}
|
||||
|
||||
nsViewportInfo viewportInfo = doc->GetViewportInfo(displaySize);
|
||||
nsSize maximumPossibleSize =
|
||||
CSSSize::ToAppUnits(ScreenSize(displaySize) / viewportInfo.GetMinZoom());
|
||||
|
||||
mMinimumScaleSize =
|
||||
Min(maximumPossibleSize,
|
||||
nsSize(aScrollableOverflow.XMost(), aScrollableOverflow.YMost()));
|
||||
mMinimumScaleSize = Max(aICBSize, mMinimumScaleSize);
|
||||
// The intrinsic minimum scale is the scale that fits the entire content
|
||||
// width into the visual viewport.
|
||||
CSSToScreenScale intrinsicMinScale(
|
||||
displaySize.width / CSSRect::FromAppUnits(aScrollableOverflow).XMost());
|
||||
|
||||
// Chrome doesn't allow overflow-y:hidden region reachable if there is no
|
||||
// overflow-x:hidden region.
|
||||
// The scale used to compute the minimum-scale size is the larger of the
|
||||
// intrinsic minimum and the min-scale from the meta viewport tag.
|
||||
CSSToScreenScale minScale =
|
||||
std::max(intrinsicMinScale, viewportInfo.GetMinZoom());
|
||||
|
||||
// The minimum-scale size is the size of the visual viewport when zoomed
|
||||
// to be the minimum scale.
|
||||
mMinimumScaleSize = CSSSize::ToAppUnits(ScreenSize(displaySize) / minScale);
|
||||
|
||||
// Clamp the min-scale size so it's not taller than the content height.
|
||||
// TODO: Bug 1508177: We can drop this condition once after we shrink the
|
||||
// content even if no content area gets visible.
|
||||
if (mMinimumScaleSize.width != aICBSize.width) {
|
||||
mIsUsingMinimumScaleSize = true;
|
||||
}
|
||||
mMinimumScaleSize =
|
||||
Min(mMinimumScaleSize,
|
||||
nsSize(aScrollableOverflow.XMost(), aScrollableOverflow.YMost()));
|
||||
|
||||
// Ensure the minimum-scale size is never smaller than the ICB size.
|
||||
// That could happen if a page has a meta viewport tag with large explicitly
|
||||
// specified viewport dimensions (making the ICB large) and also a large
|
||||
// minimum scale (making the min-scale size small).
|
||||
mMinimumScaleSize = Max(aICBSize, mMinimumScaleSize);
|
||||
|
||||
mIsUsingMinimumScaleSize = true;
|
||||
}
|
||||
|
||||
bool ScrollFrameHelper::ReflowFinished() {
|
||||
|
|
|
@ -4393,7 +4393,8 @@ static void ProcessDisplayItemMarker(DisplayItemEntryType aMarker,
|
|||
* of ContainerState::Finish.
|
||||
*/
|
||||
void ContainerState::ProcessDisplayItems(nsDisplayList* aList) {
|
||||
AUTO_PROFILER_LABEL("ContainerState::ProcessDisplayItems", GRAPHICS);
|
||||
AUTO_PROFILER_LABEL("ContainerState::ProcessDisplayItems",
|
||||
GRAPHICS_LayerBuilding);
|
||||
|
||||
nsPoint topLeft(0, 0);
|
||||
|
||||
|
@ -6941,10 +6942,11 @@ void FrameLayerBuilder::PaintItems(std::vector<AssignedDisplayItem>& aItems,
|
|||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
AUTO_PROFILER_LABEL_DYNAMIC_CSTR("FrameLayerBuilder::PaintItems", GRAPHICS,
|
||||
item->Name());
|
||||
AUTO_PROFILER_LABEL_DYNAMIC_CSTR("FrameLayerBuilder::PaintItems",
|
||||
GRAPHICS_Rasterization, item->Name());
|
||||
#else
|
||||
AUTO_PROFILER_LABEL("FrameLayerBuilder::PaintItems", GRAPHICS);
|
||||
AUTO_PROFILER_LABEL("FrameLayerBuilder::PaintItems",
|
||||
GRAPHICS_Rasterization);
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT((opacityLevel == 0 && !cdi.mHasOpacity) ||
|
||||
|
@ -7117,7 +7119,8 @@ static void DrawForcedBackgroundColor(DrawTarget& aDrawTarget,
|
|||
void* aCallbackData) {
|
||||
DrawTarget& aDrawTarget = *aContext->GetDrawTarget();
|
||||
|
||||
AUTO_PROFILER_LABEL("FrameLayerBuilder::DrawPaintedLayer", GRAPHICS);
|
||||
AUTO_PROFILER_LABEL("FrameLayerBuilder::DrawPaintedLayer",
|
||||
GRAPHICS_Rasterization);
|
||||
|
||||
nsDisplayListBuilder* builder =
|
||||
static_cast<nsDisplayListBuilder*>(aCallbackData);
|
||||
|
|
|
@ -658,6 +658,8 @@ bool RetainedDisplayListBuilder::MergeDisplayLists(
|
|||
RetainedDisplayList* aOutList,
|
||||
mozilla::Maybe<const mozilla::ActiveScrolledRoot*>& aOutContainerASR,
|
||||
nsDisplayItem* aOuterItem) {
|
||||
AUTO_PROFILER_LABEL_CATEGORY_PAIR(GRAPHICS_DisplayListMerging);
|
||||
|
||||
MergeState merge(this, *aOldList,
|
||||
aOuterItem ? aOuterItem->GetPerFrameKey() : 0);
|
||||
|
||||
|
|
|
@ -2466,6 +2466,7 @@ FrameLayerBuilder* nsDisplayList::BuildLayers(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
RefPtr<ContainerLayer> root;
|
||||
{
|
||||
AUTO_PROFILER_LABEL_CATEGORY_PAIR(GRAPHICS_LayerBuilding);
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
nsCOMPtr<nsIDocShell> docShell = presContext->GetDocShell();
|
||||
AUTO_PROFILER_TRACING_DOCSHELL("Paint", "LayerBuilding", GRAPHICS,
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<html class="reftest-wait">
|
||||
<meta name="viewport" content="width=device-width minimum-scale=0.25 initial-scale=1.0">
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
div {
|
||||
position: absolute;
|
||||
}
|
||||
.B {
|
||||
width: 200%;
|
||||
height: 400%;
|
||||
background: white;
|
||||
}
|
||||
.C {
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
<div class="B"></div>
|
||||
<div class="C"></div>
|
||||
<script>
|
||||
document.addEventListener('MozReftestInvalidate', () => {
|
||||
// The page here is twice the width of the ICB, and four times the height.
|
||||
// We want the layout viewport to be expanded to be twice the width and
|
||||
// height of the ICB (to maintain aspect ratio), rather than four times the
|
||||
// height.
|
||||
// To test this, scroll to the end of the layout scroll range.
|
||||
// If the layout viewport is expanded too much, we have no layout scroll
|
||||
// range, so nothing will happen, and a green area will remain in view.
|
||||
// If the layout viewport is expanded to the desired size, a white area
|
||||
// will be scrolled into view, matching the reference page.
|
||||
window.scrollTo(window.scrollMaxX, window.scrollMaxY);
|
||||
document.documentElement.classList.remove('reftest-wait');
|
||||
});
|
||||
</script>
|
||||
</html>
|
|
@ -22,3 +22,4 @@ skip-if(winWidget||webrender) == vertical-overflow-hidden-region.html about:blan
|
|||
skip-if(winWidget||webrender) == scroll-to-unreachable-area.html scroll-to-unreachable-area-ref.html
|
||||
skip-if(winWidget||webrender) == wrapped-text-at-icb.html wrapped-text-at-icb-ref.html
|
||||
skip-if(winWidget||webrender) == not-able-to-scrollTo.html about:blank
|
||||
skip-if(winWidget||webrender) == min-scale-aspect-ratio.html about:blank
|
||||
|
|
|
@ -1578,7 +1578,7 @@ Loader::Completed Loader::ParseSheet(const nsACString& aBytes,
|
|||
SheetLoadData* aLoadData,
|
||||
AllowAsyncParse aAllowAsync) {
|
||||
LOG(("css::Loader::ParseSheet"));
|
||||
AUTO_PROFILER_LABEL("css::Loader::ParseSheet", LAYOUT);
|
||||
AUTO_PROFILER_LABEL("css::Loader::ParseSheet", LAYOUT_CSSParsing);
|
||||
MOZ_ASSERT(aLoadData);
|
||||
aLoadData->mIsBeingParsed = true;
|
||||
|
||||
|
|
|
@ -860,6 +860,7 @@ already_AddRefed<ComputedStyle> ServoStyleSet::ProbePseudoElementStyle(
|
|||
}
|
||||
|
||||
bool ServoStyleSet::StyleDocument(ServoTraversalFlags aFlags) {
|
||||
AUTO_PROFILER_LABEL_CATEGORY_PAIR(LAYOUT_StyleComputation);
|
||||
MOZ_ASSERT(GetPresContext(), "Styling a document without a shell?");
|
||||
|
||||
if (!mDocument->GetServoRestyleRoot()) {
|
||||
|
|
|
@ -272,6 +272,8 @@ nsresult nsDOMCSSDeclaration::ModifyDeclaration(
|
|||
nsresult nsDOMCSSDeclaration::ParsePropertyValue(
|
||||
const nsCSSPropertyID aPropID, const nsAString& aPropValue,
|
||||
bool aIsImportant, nsIPrincipal* aSubjectPrincipal) {
|
||||
AUTO_PROFILER_LABEL_CATEGORY_PAIR(LAYOUT_CSSParsing);
|
||||
|
||||
DeclarationBlockMutationClosure closure = {};
|
||||
MutationClosureData closureData;
|
||||
GetPropertyChangeClosure(&closure, &closureData);
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
//
|
||||
// Note that this class is slightly slower than the other AutoProfilerLabel,
|
||||
// and it lacks the macro wrappers. It also is effectively hardwired to use
|
||||
// js::ProfilingStackFrame::Category::OTHER as the category, because that's what
|
||||
// the callbacks provided by the profiler use. (Specifying the category in
|
||||
// this file would require #including ProfilingStack.h in mozglue, which we
|
||||
// JS::ProfilingCategory::OTHER as the category pair, because that's what
|
||||
// the callbacks provided by the profiler use. (Specifying the categories in
|
||||
// this file would require #including ProfilingCategory.h in mozglue, which we
|
||||
// don't want to do.)
|
||||
|
||||
class ProfilingStack;
|
||||
|
|
|
@ -267,7 +267,7 @@ browser.Context = class {
|
|||
* Retrieves the current tabmodal UI object. According to the browser
|
||||
* associated with the currently selected tab.
|
||||
*/
|
||||
getTabModalUI() {
|
||||
getTabModal() {
|
||||
let br = this.contentBrowser;
|
||||
if (!br.hasAttribute("tabmodalPromptShowing")) {
|
||||
return null;
|
||||
|
@ -278,7 +278,7 @@ browser.Context = class {
|
|||
let modalElements = br.parentNode.getElementsByTagNameNS(
|
||||
XUL_NS, "tabmodalprompt");
|
||||
|
||||
return br.tabModalPromptBox.prompts.get(modalElements[0]).ui;
|
||||
return br.tabModalPromptBox.prompts.get(modalElements[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,6 +37,7 @@ const {
|
|||
WebElement,
|
||||
} = ChromeUtils.import("chrome://marionette/content/element.js");
|
||||
const {
|
||||
ElementNotInteractableError,
|
||||
InsecureCertificateError,
|
||||
InvalidArgumentError,
|
||||
InvalidCookieDomainError,
|
||||
|
@ -3225,12 +3226,24 @@ GeckoDriver.prototype.sendKeysToDialog = async function(cmd) {
|
|||
assert.open(this.getCurrentWindow());
|
||||
this._checkIfAlertIsPresent();
|
||||
|
||||
let text = assert.string(cmd.parameters.text);
|
||||
let promptType = this.dialog.args.promptType;
|
||||
|
||||
switch (promptType) {
|
||||
case "alert":
|
||||
case "confirm":
|
||||
throw new ElementNotInteractableError(
|
||||
`User prompt of type ${promptType} is not interactable`);
|
||||
case "prompt":
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationError(
|
||||
`User prompt of type ${promptType} is not supported`);
|
||||
}
|
||||
|
||||
// see toolkit/components/prompts/content/commonDialog.js
|
||||
let {loginTextbox} = this.dialog.ui;
|
||||
loginTextbox.value = "";
|
||||
|
||||
await interaction.sendKeysToElement(
|
||||
loginTextbox, cmd.parameters.text, this.a11yChecks);
|
||||
loginTextbox.value = text;
|
||||
};
|
||||
|
||||
GeckoDriver.prototype._checkIfAlertIsPresent = function() {
|
||||
|
|
|
@ -143,11 +143,19 @@ modal.Dialog = class {
|
|||
return null;
|
||||
}
|
||||
|
||||
get ui() {
|
||||
get tabModal() {
|
||||
let win = this.window;
|
||||
if (win) {
|
||||
return win.Dialog.ui;
|
||||
return win.Dialog;
|
||||
}
|
||||
return this.curBrowser_.getTabModalUI();
|
||||
return this.curBrowser_.getTabModal();
|
||||
}
|
||||
|
||||
get args() {
|
||||
return this.tabModal.args;
|
||||
}
|
||||
|
||||
get ui() {
|
||||
return this.tabModal.ui;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -356,7 +356,7 @@ class UserPrompt(object):
|
|||
@text.setter
|
||||
@command
|
||||
def text(self, value):
|
||||
body = {"value": list(value)}
|
||||
body = {"text": value}
|
||||
self.session.send_session_command("POST", "alert/text", body=body)
|
||||
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import pytest
|
|||
from webdriver.transport import Response
|
||||
|
||||
from tests.support.asserts import assert_error, assert_success
|
||||
from tests.support.authentication import basic_authentication
|
||||
from tests.support.inline import inline
|
||||
|
||||
|
||||
|
@ -55,7 +56,14 @@ def test_alert_element_not_interactable(session, dialog_type):
|
|||
assert_error(response, "element not interactable")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text", ["", "Federer", " Fed erer "])
|
||||
def test_alert_unsupported_operation(session):
|
||||
session.url = basic_authentication()
|
||||
|
||||
response = send_alert_text(session, "Federer")
|
||||
assert_error(response, "unsupported operation")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text", ["", "Federer", " Fed erer ", "Fed\terer"])
|
||||
def test_send_alert_text(session, page, text):
|
||||
send_response = send_alert_text(session, text)
|
||||
assert_success(send_response)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import urllib
|
||||
|
||||
|
||||
def basic_authentication(username=None, password=None, protocol="http"):
|
||||
from .fixtures import server_config, url
|
||||
build_url = url(server_config())
|
||||
|
||||
query = {}
|
||||
|
||||
return build_url("/webdriver/tests/support/authentication.py",
|
||||
query=urllib.urlencode(query),
|
||||
protocol=protocol)
|
||||
|
||||
|
||||
def main(request, response):
|
||||
user = request.auth.username
|
||||
password = request.auth.password
|
||||
|
||||
if user == "user" and password == "password":
|
||||
return "Authentication done"
|
||||
|
||||
realm = "test"
|
||||
if "realm" in request.GET:
|
||||
realm = request.GET.first("realm")
|
||||
|
||||
return ((401, "Unauthorized"),
|
||||
[("WWW-Authenticate", 'Basic realm="' + realm + '"')],
|
||||
"Please login with credentials 'user' and 'password'")
|
|
@ -498,7 +498,7 @@ void BackgroundHangThread::ReportHang(TimeDuration aHangTime) {
|
|||
TimeStamp endTime = TimeStamp::Now();
|
||||
TimeStamp startTime = endTime - aHangTime;
|
||||
profiler_add_marker_for_thread(
|
||||
mStackHelper.GetThreadId(), js::ProfilingStackFrame::Category::OTHER,
|
||||
mStackHelper.GetThreadId(), JS::ProfilingCategoryPair::OTHER,
|
||||
"BHR-detected hang", MakeUnique<HangMarkerPayload>(startTime, endTime));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -373,7 +373,7 @@ ExtensionPageChild = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Create a privileged context at document-element-inserted.
|
||||
* Create a privileged context at initial-document-element-inserted.
|
||||
*
|
||||
* @param {BrowserExtensionContent} extension
|
||||
* The extension for which the context should be created.
|
||||
|
|
|
@ -55,6 +55,8 @@ using dom::Promise;
|
|||
#define OBS_TOPIC_PRELOAD_SCRIPT "web-extension-preload-content-script"
|
||||
#define OBS_TOPIC_LOAD_SCRIPT "web-extension-load-content-script"
|
||||
|
||||
static const char kDocElementInserted[] = "initial-document-element-inserted";
|
||||
|
||||
static mozIExtensionProcessScript& ProcessScript() {
|
||||
static nsCOMPtr<mozIExtensionProcessScript> sProcessScript;
|
||||
|
||||
|
@ -235,8 +237,7 @@ ExtensionPolicyService::CollectReports(nsIHandleReportCallback* aHandleReport,
|
|||
*****************************************************************************/
|
||||
|
||||
void ExtensionPolicyService::RegisterObservers() {
|
||||
mObs->AddObserver(this, "content-document-global-created", false);
|
||||
mObs->AddObserver(this, "document-element-inserted", false);
|
||||
mObs->AddObserver(this, kDocElementInserted, false);
|
||||
mObs->AddObserver(this, "tab-content-frameloader-created", false);
|
||||
if (XRE_IsContentProcess()) {
|
||||
mObs->AddObserver(this, "http-on-opening-request", false);
|
||||
|
@ -244,8 +245,7 @@ void ExtensionPolicyService::RegisterObservers() {
|
|||
}
|
||||
|
||||
void ExtensionPolicyService::UnregisterObservers() {
|
||||
mObs->RemoveObserver(this, "content-document-global-created");
|
||||
mObs->RemoveObserver(this, "document-element-inserted");
|
||||
mObs->RemoveObserver(this, kDocElementInserted);
|
||||
mObs->RemoveObserver(this, "tab-content-frameloader-created");
|
||||
if (XRE_IsContentProcess()) {
|
||||
mObs->RemoveObserver(this, "http-on-opening-request");
|
||||
|
@ -255,12 +255,7 @@ void ExtensionPolicyService::UnregisterObservers() {
|
|||
nsresult ExtensionPolicyService::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData) {
|
||||
if (!strcmp(aTopic, "content-document-global-created")) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win = do_QueryInterface(aSubject);
|
||||
if (win) {
|
||||
CheckWindow(win);
|
||||
}
|
||||
} else if (!strcmp(aTopic, "document-element-inserted")) {
|
||||
if (!strcmp(aTopic, kDocElementInserted)) {
|
||||
nsCOMPtr<Document> doc = do_QueryInterface(aSubject);
|
||||
if (doc) {
|
||||
CheckDocument(doc);
|
||||
|
@ -478,34 +473,6 @@ void ExtensionPolicyService::CheckDocument(Document* aDocument) {
|
|||
}
|
||||
}
|
||||
|
||||
// Checks for loads of about:blank into new window globals, and loads any
|
||||
// matching content scripts. about:blank loads do not trigger document element
|
||||
// inserted events, so they're the only load type that are special cased this
|
||||
// way.
|
||||
void ExtensionPolicyService::CheckWindow(nsPIDOMWindowOuter* aWindow) {
|
||||
// We only care about non-initial document loads here. The initial
|
||||
// about:blank document will usually be re-used to load another document.
|
||||
RefPtr<Document> doc = aWindow->GetExtantDoc();
|
||||
if (!doc || doc->IsInitialDocument() ||
|
||||
doc->GetReadyStateEnum() == Document::READYSTATE_UNINITIALIZED) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> docUri = doc->GetDocumentURI();
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (!docUri || NS_FAILED(NS_GetURIWithoutRef(docUri, getter_AddRefs(uri))) ||
|
||||
!NS_IsAboutBlank(uri)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIDocShell* docShell = aWindow->GetDocShell();
|
||||
if (RefPtr<ContentFrameMessageManager> mm = docShell->GetMessageManager()) {
|
||||
if (mMessageManagers.Contains(mm)) {
|
||||
CheckContentScripts(aWindow, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionPolicyService::CheckContentScripts(const DocInfo& aDocInfo,
|
||||
bool aIsPreload) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> win;
|
||||
|
|
|
@ -103,7 +103,6 @@ class ExtensionPolicyService final : public nsIAddonPolicyService,
|
|||
|
||||
void CheckRequest(nsIChannel* aChannel);
|
||||
void CheckDocument(dom::Document* aDocument);
|
||||
void CheckWindow(nsPIDOMWindowOuter* aWindow);
|
||||
|
||||
void CheckContentScripts(const DocInfo& aDocInfo, bool aIsPreload);
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ subsuite = clipboard
|
|||
[browser_passwordmgr_switchtab.js]
|
||||
[browser_passwordmgrdlg.js]
|
||||
[browser_private_window.js]
|
||||
skip-if = os == "linux" #Bug 1526614
|
||||
support-files =
|
||||
subtst_privbrowsing_1.html
|
||||
subtst_privbrowsing_2.html
|
||||
|
|
|
@ -58,7 +58,7 @@ void ProfileBuffer::AddStoredMarker(ProfilerMarker* aStoredMarker) {
|
|||
void ProfileBuffer::CollectCodeLocation(
|
||||
const char* aLabel, const char* aStr, uint32_t aFrameFlags,
|
||||
const Maybe<uint32_t>& aLineNumber, const Maybe<uint32_t>& aColumnNumber,
|
||||
const Maybe<js::ProfilingStackFrame::Category>& aCategory) {
|
||||
const Maybe<JS::ProfilingCategoryPair>& aCategoryPair) {
|
||||
AddEntry(ProfileBufferEntry::Label(aLabel));
|
||||
AddEntry(ProfileBufferEntry::FrameFlags(uint64_t(aFrameFlags)));
|
||||
|
||||
|
@ -87,8 +87,8 @@ void ProfileBuffer::CollectCodeLocation(
|
|||
AddEntry(ProfileBufferEntry::ColumnNumber(*aColumnNumber));
|
||||
}
|
||||
|
||||
if (aCategory.isSome()) {
|
||||
AddEntry(ProfileBufferEntry::Category(int(*aCategory)));
|
||||
if (aCategoryPair.isSome()) {
|
||||
AddEntry(ProfileBufferEntry::CategoryPair(int(*aCategoryPair)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,5 +186,5 @@ void ProfileBufferCollector::CollectProfilingStackFrame(
|
|||
}
|
||||
|
||||
mBuf.CollectCodeLocation(label, dynamicString, aFrame.flags(), line, column,
|
||||
Some(aFrame.category()));
|
||||
Some(aFrame.categoryPair()));
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ class ProfileBuffer final {
|
|||
const char* aLabel, const char* aStr, uint32_t aFrameFlags,
|
||||
const mozilla::Maybe<uint32_t>& aLineNumber,
|
||||
const mozilla::Maybe<uint32_t>& aColumnNumber,
|
||||
const mozilla::Maybe<js::ProfilingStackFrame::Category>& aCategory);
|
||||
const mozilla::Maybe<JS::ProfilingCategoryPair>& aCategoryPair);
|
||||
|
||||
// Maximum size of a frameKey string that we'll handle.
|
||||
static const size_t kMaxFrameKeyLength = 512;
|
||||
|
|
|
@ -357,7 +357,7 @@ bool UniqueStacks::FrameKey::NormalFrameData::operator==(
|
|||
const NormalFrameData& aOther) const {
|
||||
return mLocation == aOther.mLocation &&
|
||||
mRelevantForJS == aOther.mRelevantForJS && mLine == aOther.mLine &&
|
||||
mColumn == aOther.mColumn && mCategory == aOther.mCategory;
|
||||
mColumn == aOther.mColumn && mCategoryPair == aOther.mCategoryPair;
|
||||
}
|
||||
|
||||
bool UniqueStacks::FrameKey::JITFrameData::operator==(
|
||||
|
@ -380,8 +380,8 @@ uint32_t UniqueStacks::FrameKey::Hash() const {
|
|||
if (data.mColumn.isSome()) {
|
||||
hash = AddToHash(hash, *data.mColumn);
|
||||
}
|
||||
if (data.mCategory.isSome()) {
|
||||
hash = AddToHash(hash, *data.mCategory);
|
||||
if (data.mCategoryPair.isSome()) {
|
||||
hash = AddToHash(hash, uint32_t(*data.mCategoryPair));
|
||||
}
|
||||
} else {
|
||||
const JITFrameData& data = mData.as<JITFrameData>();
|
||||
|
@ -527,8 +527,10 @@ void UniqueStacks::StreamNonJITFrame(const FrameKey& aFrame) {
|
|||
if (data.mColumn.isSome()) {
|
||||
writer.IntElement(COLUMN, *data.mColumn);
|
||||
}
|
||||
if (data.mCategory.isSome()) {
|
||||
writer.IntElement(CATEGORY, *data.mCategory);
|
||||
if (data.mCategoryPair.isSome()) {
|
||||
const JS::ProfilingCategoryPairInfo& info =
|
||||
JS::GetProfilingCategoryPairInfo(*data.mCategoryPair);
|
||||
writer.IntElement(CATEGORY, uint32_t(info.mCategory));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -785,7 +787,7 @@ class EntryGetter {
|
|||
// ThreadId
|
||||
// Time
|
||||
// ( NativeLeafAddr
|
||||
// | Label FrameFlags? DynamicStringFragment* LineNumber? Category?
|
||||
// | Label FrameFlags? DynamicStringFragment* LineNumber? CategoryPair?
|
||||
// | JitReturnAddr
|
||||
// )+
|
||||
// Marker*
|
||||
|
@ -821,15 +823,15 @@ class EntryGetter {
|
|||
// - ProfilingStack frames without a dynamic string:
|
||||
//
|
||||
// Label("js::RunScript")
|
||||
// Category(ProfilingStackFrame::Category::JS)
|
||||
// CategoryPair(JS::ProfilingCategoryPair::JS)
|
||||
//
|
||||
// Label("XREMain::XRE_main")
|
||||
// LineNumber(4660)
|
||||
// Category(ProfilingStackFrame::Category::OTHER)
|
||||
// CategoryPair(JS::ProfilingCategoryPair::OTHER)
|
||||
//
|
||||
// Label("ElementRestyler::ComputeStyleChangeFor")
|
||||
// LineNumber(3003)
|
||||
// Category(ProfilingStackFrame::Category::CSS)
|
||||
// CategoryPair(JS::ProfilingCategoryPair::CSS)
|
||||
//
|
||||
// - ProfilingStack frames with a dynamic string:
|
||||
//
|
||||
|
@ -838,7 +840,7 @@ class EntryGetter {
|
|||
// DynamicStringFragment("domwindo")
|
||||
// DynamicStringFragment("wopened")
|
||||
// LineNumber(291)
|
||||
// Category(ProfilingStackFrame::Category::OTHER)
|
||||
// CategoryPair(JS::ProfilingCategoryPair::OTHER)
|
||||
//
|
||||
// Label("")
|
||||
// FrameFlags(uint64_t(ProfilingStackFrame::Flags::IS_JS_FRAME))
|
||||
|
@ -851,7 +853,7 @@ class EntryGetter {
|
|||
// DynamicStringFragment("ay.js:5)")
|
||||
// DynamicStringFragment("") # this string holds the closing '\0'
|
||||
// LineNumber(25)
|
||||
// Category(ProfilingStackFrame::Category::JS)
|
||||
// CategoryPair(JS::ProfilingCategoryPair::JS)
|
||||
//
|
||||
// Label("")
|
||||
// FrameFlags(uint64_t(ProfilingStackFrame::Flags::IS_JS_FRAME))
|
||||
|
@ -859,7 +861,7 @@ class EntryGetter {
|
|||
// DynamicStringFragment("elf-host")
|
||||
// DynamicStringFragment("ed:914)")
|
||||
// LineNumber(945)
|
||||
// Category(ProfilingStackFrame::Category::JS)
|
||||
// CategoryPair(JS::ProfilingCategoryPair::JS)
|
||||
//
|
||||
// - A profiling stack frame with a dynamic string, but with privacy enabled:
|
||||
//
|
||||
|
@ -868,7 +870,7 @@ class EntryGetter {
|
|||
// DynamicStringFragment("(private")
|
||||
// DynamicStringFragment(")")
|
||||
// LineNumber(291)
|
||||
// Category(ProfilingStackFrame::Category::OTHER)
|
||||
// CategoryPair(JS::ProfilingCategoryPair::OTHER)
|
||||
//
|
||||
// - A profiling stack frame with an overly long dynamic string:
|
||||
//
|
||||
|
@ -877,7 +879,7 @@ class EntryGetter {
|
|||
// DynamicStringFragment("(too lon")
|
||||
// DynamicStringFragment("g)")
|
||||
// LineNumber(100)
|
||||
// Category(ProfilingStackFrame::Category::NETWORK)
|
||||
// CategoryPair(JS::ProfilingCategoryPair::NETWORK)
|
||||
//
|
||||
// - A wasm JIT frame:
|
||||
//
|
||||
|
@ -1062,15 +1064,16 @@ void ProfileBuffer::StreamSamplesToJSON(SpliceableJSONWriter& aWriter,
|
|||
e.Next();
|
||||
}
|
||||
|
||||
Maybe<unsigned> category;
|
||||
if (e.Has() && e.Get().IsCategory()) {
|
||||
category = Some(unsigned(e.Get().GetInt()));
|
||||
Maybe<JS::ProfilingCategoryPair> categoryPair;
|
||||
if (e.Has() && e.Get().IsCategoryPair()) {
|
||||
categoryPair =
|
||||
Some(JS::ProfilingCategoryPair(uint32_t(e.Get().GetInt())));
|
||||
e.Next();
|
||||
}
|
||||
|
||||
stack = aUniqueStacks.AppendFrame(
|
||||
stack, UniqueStacks::FrameKey(std::move(frameLabel), relevantForJS,
|
||||
line, column, category));
|
||||
line, column, categoryPair));
|
||||
|
||||
} else if (e.Get().IsJitReturnAddr()) {
|
||||
numFrames++;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "ProfileJSONWriter.h"
|
||||
|
||||
#include "gtest/MozGtestFriend.h"
|
||||
#include "js/ProfilingCategory.h"
|
||||
#include "js/ProfilingFrameIterator.h"
|
||||
#include "js/TrackedOptimizationInfo.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
|
@ -27,7 +28,7 @@ class ProfilerMarker;
|
|||
// NOTE! If you add entries, you need to verify if they need to be added to the
|
||||
// switch statement in DuplicateLastSample!
|
||||
#define FOR_EACH_PROFILE_BUFFER_ENTRY_KIND(MACRO) \
|
||||
MACRO(Category, int) \
|
||||
MACRO(CategoryPair, int) \
|
||||
MACRO(CollectionStart, double) \
|
||||
MACRO(CollectionEnd, double) \
|
||||
MACRO(Label, const char*) \
|
||||
|
@ -224,9 +225,9 @@ class UniqueStacks {
|
|||
FrameKey(nsCString&& aLocation, bool aRelevantForJS,
|
||||
const mozilla::Maybe<unsigned>& aLine,
|
||||
const mozilla::Maybe<unsigned>& aColumn,
|
||||
const mozilla::Maybe<unsigned>& aCategory)
|
||||
const mozilla::Maybe<JS::ProfilingCategoryPair>& aCategoryPair)
|
||||
: mData(NormalFrameData{aLocation, aRelevantForJS, aLine, aColumn,
|
||||
aCategory}) {}
|
||||
aCategoryPair}) {}
|
||||
|
||||
FrameKey(void* aJITAddress, uint32_t aJITDepth, uint32_t aRangeIndex)
|
||||
: mData(JITFrameData{aJITAddress, aJITDepth, aRangeIndex}) {}
|
||||
|
@ -245,7 +246,7 @@ class UniqueStacks {
|
|||
bool mRelevantForJS;
|
||||
mozilla::Maybe<unsigned> mLine;
|
||||
mozilla::Maybe<unsigned> mColumn;
|
||||
mozilla::Maybe<unsigned> mCategory;
|
||||
mozilla::Maybe<JS::ProfilingCategoryPair> mCategoryPair;
|
||||
};
|
||||
struct JITFrameData {
|
||||
bool operator==(const JITFrameData& aOther) const;
|
||||
|
|
|
@ -21,7 +21,7 @@ class ProfilerMarker {
|
|||
|
||||
public:
|
||||
explicit ProfilerMarker(
|
||||
const char* aMarkerName, js::ProfilingStackFrame::Category aCategory,
|
||||
const char* aMarkerName, JS::ProfilingCategoryPair aCategoryPair,
|
||||
int aThreadId,
|
||||
mozilla::UniquePtr<ProfilerMarkerPayload> aPayload = nullptr,
|
||||
double aTime = 0)
|
||||
|
@ -31,7 +31,7 @@ class ProfilerMarker {
|
|||
mTime(aTime),
|
||||
mPositionInBuffer{0},
|
||||
mThreadId{aThreadId},
|
||||
mCategory{aCategory} {}
|
||||
mCategoryPair{aCategoryPair} {}
|
||||
|
||||
void SetPositionInBuffer(uint64_t aPosition) {
|
||||
mPositionInBuffer = aPosition;
|
||||
|
@ -55,7 +55,9 @@ class ProfilerMarker {
|
|||
{
|
||||
aUniqueStacks.mUniqueStrings->WriteElement(aWriter, mMarkerName.get());
|
||||
aWriter.DoubleElement(mTime);
|
||||
aWriter.IntElement(unsigned(mCategory));
|
||||
const JS::ProfilingCategoryPairInfo& info =
|
||||
JS::GetProfilingCategoryPairInfo(mCategoryPair);
|
||||
aWriter.IntElement(unsigned(info.mCategory));
|
||||
// TODO: Store the callsite for this marker if available:
|
||||
// if have location data
|
||||
// b.NameValue(marker, "location", ...);
|
||||
|
@ -75,7 +77,7 @@ class ProfilerMarker {
|
|||
double mTime;
|
||||
uint64_t mPositionInBuffer;
|
||||
int mThreadId;
|
||||
js::ProfilingStackFrame::Category mCategory;
|
||||
JS::ProfilingCategoryPair mCategoryPair;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -38,13 +38,13 @@ class RacyRegisteredThread final {
|
|||
bool IsBeingProfiled() const { return mIsBeingProfiled; }
|
||||
|
||||
void AddPendingMarker(const char* aMarkerName,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
mozilla::UniquePtr<ProfilerMarkerPayload> aPayload,
|
||||
double aTime) {
|
||||
// Note: We don't assert on mIsBeingProfiled, because it could have changed
|
||||
// between the check in the caller and now.
|
||||
ProfilerMarker* marker = new ProfilerMarker(
|
||||
aMarkerName, aCategory, mThreadId, std::move(aPayload), aTime);
|
||||
aMarkerName, aCategoryPair, mThreadId, std::move(aPayload), aTime);
|
||||
mPendingMarkers.insert(marker);
|
||||
}
|
||||
|
||||
|
|
|
@ -1708,41 +1708,21 @@ static void StreamTaskTracer(PSLockRef aLock, SpliceableJSONWriter& aWriter) {
|
|||
}
|
||||
|
||||
static void StreamCategories(SpliceableJSONWriter& aWriter) {
|
||||
// Same order as ProfilingStackFrame::Category.
|
||||
// The list of available color names is:
|
||||
// transparent, grey, purple, yellow, orange, lightblue, green, blue, magenta
|
||||
aWriter.Start();
|
||||
aWriter.StringProperty("name", "Idle");
|
||||
aWriter.StringProperty("color", "transparent");
|
||||
aWriter.EndObject();
|
||||
aWriter.Start();
|
||||
aWriter.StringProperty("name", "Other");
|
||||
aWriter.StringProperty("color", "grey");
|
||||
aWriter.EndObject();
|
||||
aWriter.Start();
|
||||
aWriter.StringProperty("name", "Layout");
|
||||
aWriter.StringProperty("color", "purple");
|
||||
aWriter.EndObject();
|
||||
aWriter.Start();
|
||||
aWriter.StringProperty("name", "JavaScript");
|
||||
aWriter.StringProperty("color", "yellow");
|
||||
aWriter.EndObject();
|
||||
aWriter.Start();
|
||||
aWriter.StringProperty("name", "GC / CC");
|
||||
aWriter.StringProperty("color", "orange");
|
||||
aWriter.EndObject();
|
||||
aWriter.Start();
|
||||
aWriter.StringProperty("name", "Network");
|
||||
aWriter.StringProperty("color", "lightblue");
|
||||
aWriter.EndObject();
|
||||
aWriter.Start();
|
||||
aWriter.StringProperty("name", "Graphics");
|
||||
aWriter.StringProperty("color", "green");
|
||||
aWriter.EndObject();
|
||||
aWriter.Start();
|
||||
aWriter.StringProperty("name", "DOM");
|
||||
aWriter.StringProperty("color", "blue");
|
||||
aWriter.EndObject();
|
||||
// Same order as ProfilingCategory.
|
||||
|
||||
#define CATEGORY_JSON_BEGIN_CATEGORY(name, labelAsString, color) \
|
||||
aWriter.Start(); \
|
||||
aWriter.StringProperty("name", labelAsString); \
|
||||
aWriter.StringProperty("color", color);
|
||||
#define CATEGORY_JSON_SUBCATEGORY(category, name, labelAsString)
|
||||
#define CATEGORY_JSON_END_CATEGORY aWriter.EndObject();
|
||||
|
||||
PROFILING_CATEGORY_LIST(CATEGORY_JSON_BEGIN_CATEGORY,
|
||||
CATEGORY_JSON_SUBCATEGORY, CATEGORY_JSON_END_CATEGORY)
|
||||
|
||||
#undef CATEGORY_JSON_BEGIN_CATEGORY
|
||||
#undef CATEGORY_JSON_SUBCATEGORY
|
||||
#undef CATEGORY_JSON_END_CATEGORY
|
||||
}
|
||||
|
||||
static void StreamMetaJSCustomObject(PSLockRef aLock,
|
||||
|
@ -1936,22 +1916,22 @@ static UniquePtr<ProfileBuffer> CollectJavaThreadProfileData() {
|
|||
}
|
||||
nsCString frameNameString = frameName->ToCString();
|
||||
|
||||
// Compute a category for the frame:
|
||||
// Compute a category pair for the frame:
|
||||
// - IDLE for the wait function android.os.MessageQueue.nativePollOnce()
|
||||
// - OTHER for any function that's directly called by that wait function
|
||||
// - no category on everything else
|
||||
Maybe<js::ProfilingStackFrame::Category> category;
|
||||
Maybe<JS::ProfilingCategoryPair> categoryPair;
|
||||
if (frameNameString.EqualsLiteral(
|
||||
"android.os.MessageQueue.nativePollOnce()")) {
|
||||
category = Some(js::ProfilingStackFrame::Category::IDLE);
|
||||
categoryPair = Some(JS::ProfilingCategoryPair::IDLE);
|
||||
parentFrameWasIdleFrame = true;
|
||||
} else if (parentFrameWasIdleFrame) {
|
||||
category = Some(js::ProfilingStackFrame::Category::OTHER);
|
||||
categoryPair = Some(JS::ProfilingCategoryPair::OTHER);
|
||||
parentFrameWasIdleFrame = false;
|
||||
}
|
||||
|
||||
buffer->CollectCodeLocation("", frameNameString.get(), 0, Nothing(),
|
||||
Nothing(), category);
|
||||
Nothing(), categoryPair);
|
||||
}
|
||||
sampleId++;
|
||||
}
|
||||
|
@ -2635,7 +2615,7 @@ ProfilingStack* MozGlueLabelEnter(const char* aLabel,
|
|||
ProfilingStack* profilingStack = AutoProfilerLabel::sProfilingStack.get();
|
||||
if (profilingStack) {
|
||||
profilingStack->pushLabelFrame(aLabel, aDynamicString, aSp,
|
||||
js::ProfilingStackFrame::Category::OTHER);
|
||||
JS::ProfilingCategoryPair::OTHER);
|
||||
}
|
||||
return profilingStack;
|
||||
}
|
||||
|
@ -3685,7 +3665,7 @@ void ProfilerBacktraceDestructor::operator()(ProfilerBacktrace* aBacktrace) {
|
|||
}
|
||||
|
||||
static void racy_profiler_add_marker(
|
||||
const char* aMarkerName, js::ProfilingStackFrame::Category aCategory,
|
||||
const char* aMarkerName, JS::ProfilingCategoryPair aCategoryPair,
|
||||
UniquePtr<ProfilerMarkerPayload> aPayload) {
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||
|
||||
|
@ -3707,11 +3687,11 @@ static void racy_profiler_add_marker(
|
|||
: TimeStamp::Now();
|
||||
TimeDuration delta = origin - CorePS::ProcessStartTime();
|
||||
racyRegisteredThread->AddPendingMarker(
|
||||
aMarkerName, aCategory, std::move(aPayload), delta.ToMilliseconds());
|
||||
aMarkerName, aCategoryPair, std::move(aPayload), delta.ToMilliseconds());
|
||||
}
|
||||
|
||||
void profiler_add_marker(const char* aMarkerName,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
UniquePtr<ProfilerMarkerPayload> aPayload) {
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||
|
||||
|
@ -3720,19 +3700,18 @@ void profiler_add_marker(const char* aMarkerName,
|
|||
return;
|
||||
}
|
||||
|
||||
racy_profiler_add_marker(aMarkerName, aCategory, std::move(aPayload));
|
||||
racy_profiler_add_marker(aMarkerName, aCategoryPair, std::move(aPayload));
|
||||
}
|
||||
|
||||
void profiler_add_marker(const char* aMarkerName,
|
||||
js::ProfilingStackFrame::Category aCategory) {
|
||||
profiler_add_marker(aMarkerName, aCategory, nullptr);
|
||||
JS::ProfilingCategoryPair aCategoryPair) {
|
||||
profiler_add_marker(aMarkerName, aCategoryPair, nullptr);
|
||||
}
|
||||
|
||||
// This is a simplified version of profiler_add_marker that can be easily passed
|
||||
// into the JS engine.
|
||||
void profiler_add_js_marker(const char* aMarkerName) {
|
||||
profiler_add_marker(aMarkerName, js::ProfilingStackFrame::Category::JS,
|
||||
nullptr);
|
||||
profiler_add_marker(aMarkerName, JS::ProfilingCategoryPair::JS, nullptr);
|
||||
}
|
||||
|
||||
void profiler_add_network_marker(
|
||||
|
@ -3757,7 +3736,7 @@ void profiler_add_network_marker(
|
|||
char name[2048];
|
||||
SprintfLiteral(name, "Load %d: %s", id, PromiseFlatCString(spec).get());
|
||||
profiler_add_marker(
|
||||
name, js::ProfilingStackFrame::Category::NETWORK,
|
||||
name, JS::ProfilingCategoryPair::NETWORK,
|
||||
MakeUnique<NetworkMarkerPayload>(
|
||||
static_cast<int64_t>(aChannelId), PromiseFlatCString(spec).get(),
|
||||
aType, aStart, aEnd, aPriority, aCount, aCacheDisposition, aTimings,
|
||||
|
@ -3767,7 +3746,7 @@ void profiler_add_network_marker(
|
|||
// This logic needs to add a marker for a different thread, so we actually need
|
||||
// to lock here.
|
||||
void profiler_add_marker_for_thread(int aThreadId,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
const char* aMarkerName,
|
||||
UniquePtr<ProfilerMarkerPayload> aPayload) {
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||
|
@ -3783,8 +3762,8 @@ void profiler_add_marker_for_thread(int aThreadId,
|
|||
: TimeStamp::Now();
|
||||
TimeDuration delta = origin - CorePS::ProcessStartTime();
|
||||
ProfilerMarker* marker =
|
||||
new ProfilerMarker(aMarkerName, aCategory, aThreadId, std::move(aPayload),
|
||||
delta.ToMilliseconds());
|
||||
new ProfilerMarker(aMarkerName, aCategoryPair, aThreadId,
|
||||
std::move(aPayload), delta.ToMilliseconds());
|
||||
|
||||
#ifdef DEBUG
|
||||
// Assert that our thread ID makes sense
|
||||
|
@ -3808,7 +3787,7 @@ void profiler_add_marker_for_thread(int aThreadId,
|
|||
}
|
||||
|
||||
void profiler_tracing(const char* aCategoryString, const char* aMarkerName,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
TracingKind aKind, const Maybe<nsID>& aDocShellId,
|
||||
const Maybe<uint32_t>& aDocShellHistoryId) {
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||
|
@ -3822,11 +3801,11 @@ void profiler_tracing(const char* aCategoryString, const char* aMarkerName,
|
|||
|
||||
auto payload = MakeUnique<TracingMarkerPayload>(
|
||||
aCategoryString, aKind, aDocShellId, aDocShellHistoryId);
|
||||
racy_profiler_add_marker(aMarkerName, aCategory, std::move(payload));
|
||||
racy_profiler_add_marker(aMarkerName, aCategoryPair, std::move(payload));
|
||||
}
|
||||
|
||||
void profiler_tracing(const char* aCategoryString, const char* aMarkerName,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
TracingKind aKind, UniqueProfilerBacktrace aCause,
|
||||
const Maybe<nsID>& aDocShellId,
|
||||
const Maybe<uint32_t>& aDocShellHistoryId) {
|
||||
|
@ -3842,18 +3821,18 @@ void profiler_tracing(const char* aCategoryString, const char* aMarkerName,
|
|||
auto payload =
|
||||
MakeUnique<TracingMarkerPayload>(aCategoryString, aKind, aDocShellId,
|
||||
aDocShellHistoryId, std::move(aCause));
|
||||
racy_profiler_add_marker(aMarkerName, aCategory, std::move(payload));
|
||||
racy_profiler_add_marker(aMarkerName, aCategoryPair, std::move(payload));
|
||||
}
|
||||
|
||||
void profiler_add_text_marker(
|
||||
const char* aMarkerName, const nsACString& aText,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
const mozilla::TimeStamp& aStartTime, const mozilla::TimeStamp& aEndTime,
|
||||
const mozilla::Maybe<nsID>& aDocShellId,
|
||||
const mozilla::Maybe<uint32_t>& aDocShellHistoryId,
|
||||
UniqueProfilerBacktrace aCause) {
|
||||
profiler_add_marker(
|
||||
aMarkerName, aCategory,
|
||||
aMarkerName, aCategoryPair,
|
||||
MakeUnique<TextMarkerPayload>(aText, aStartTime, aEndTime, aDocShellId,
|
||||
aDocShellHistoryId, std::move(aCause)));
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ void ProfilerIOInterposeObserver::Observe(Observation& aObservation) {
|
|||
nsString filename;
|
||||
aObservation.Filename(filename);
|
||||
profiler_add_marker(
|
||||
"DiskIO", js::ProfilingStackFrame::Category::OTHER,
|
||||
"DiskIO", JS::ProfilingCategoryPair::OTHER,
|
||||
MakeUnique<DiskIOMarkerPayload>(
|
||||
aObservation.ObservedOperationString(), aObservation.Reference(),
|
||||
NS_ConvertUTF16toUTF8(filename).get(), aObservation.Start(),
|
||||
|
|
|
@ -157,7 +157,7 @@ nsProfiler::ResumeSampling() {
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsProfiler::AddMarker(const char* aMarker) {
|
||||
profiler_add_marker(aMarker, js::ProfilingStackFrame::Category::OTHER);
|
||||
profiler_add_marker(aMarker, JS::ProfilingCategoryPair::OTHER);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,30 +41,31 @@
|
|||
# define PROFILER_SET_JS_CONTEXT(cx)
|
||||
# define PROFILER_CLEAR_JS_CONTEXT()
|
||||
|
||||
# define AUTO_PROFILER_LABEL(label, category)
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_CSTR(label, category, cStr)
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(label, category, nsCStr)
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(label, category, nsStr)
|
||||
# define AUTO_PROFILER_LABEL_FAST(label, category, ctx)
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, category, \
|
||||
# define AUTO_PROFILER_LABEL(label, categoryPair)
|
||||
# define AUTO_PROFILER_LABEL_CATEGORY_PAIR(categoryPair)
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_CSTR(label, categoryPair, cStr)
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(label, categoryPair, nsCStr)
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(label, categoryPair, nsStr)
|
||||
# define AUTO_PROFILER_LABEL_FAST(label, categoryPair, ctx)
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, categoryPair, \
|
||||
ctx, flags)
|
||||
|
||||
# define PROFILER_ADD_MARKER(markerName, category)
|
||||
# define PROFILER_ADD_MARKER(markerName, categoryPair)
|
||||
# define PROFILER_ADD_NETWORK_MARKER(uri, pri, channel, type, start, end, \
|
||||
count, cache, timings, redirect)
|
||||
|
||||
# define DECLARE_DOCSHELL_AND_HISTORY_ID(docShell)
|
||||
# define PROFILER_TRACING(categoryString, markerName, category, kind)
|
||||
# define PROFILER_TRACING_DOCSHELL(categoryString, markerName, category, \
|
||||
# define PROFILER_TRACING(categoryString, markerName, categoryPair, kind)
|
||||
# define PROFILER_TRACING_DOCSHELL(categoryString, markerName, categoryPair, \
|
||||
kind, docshell)
|
||||
# define AUTO_PROFILER_TRACING(categoryString, markerName, category)
|
||||
# define AUTO_PROFILER_TRACING_DOCSHELL(categoryString, markerName, category, \
|
||||
docShell)
|
||||
# define AUTO_PROFILER_TEXT_MARKER_CAUSE(markerName, text, category, cause)
|
||||
# define AUTO_PROFILER_TEXT_MARKER_DOCSHELL(markerName, text, category, \
|
||||
# define AUTO_PROFILER_TRACING(categoryString, markerName, categoryPair)
|
||||
# define AUTO_PROFILER_TRACING_DOCSHELL(categoryString, markerName, \
|
||||
categoryPair, docShell)
|
||||
# define AUTO_PROFILER_TEXT_MARKER_CAUSE(markerName, text, categoryPair, cause)
|
||||
# define AUTO_PROFILER_TEXT_MARKER_DOCSHELL(markerName, text, categoryPair, \
|
||||
docShell)
|
||||
# define AUTO_PROFILER_TEXT_MARKER_DOCSHELL_CAUSE(markerName, text, category, \
|
||||
docShell, cause)
|
||||
# define AUTO_PROFILER_TEXT_MARKER_DOCSHELL_CAUSE( \
|
||||
markerName, text, categoryPair, docShell, cause)
|
||||
|
||||
#else // !MOZ_GECKO_PROFILER
|
||||
|
||||
|
@ -518,9 +519,19 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
|
|||
//
|
||||
// Use AUTO_PROFILER_LABEL_DYNAMIC_* if you want to add additional / dynamic
|
||||
// information to the label stack frame.
|
||||
# define AUTO_PROFILER_LABEL(label, category) \
|
||||
mozilla::AutoProfilerLabel PROFILER_RAII( \
|
||||
label, nullptr, js::ProfilingStackFrame::Category::category)
|
||||
# define AUTO_PROFILER_LABEL(label, categoryPair) \
|
||||
mozilla::AutoProfilerLabel PROFILER_RAII( \
|
||||
label, nullptr, JS::ProfilingCategoryPair::categoryPair)
|
||||
|
||||
// Similar to AUTO_PROFILER_LABEL, but with only one argument: the category
|
||||
// pair. The label string is taken from the category pair. This is convenient
|
||||
// for labels like AUTO_PROFILER_LABEL_CATEGORY_PAIR(GRAPHICS_LayerBuilding)
|
||||
// which would otherwise just repeat the string.
|
||||
# define AUTO_PROFILER_LABEL_CATEGORY_PAIR(categoryPair) \
|
||||
mozilla::AutoProfilerLabel PROFILER_RAII( \
|
||||
"", nullptr, JS::ProfilingCategoryPair::categoryPair, \
|
||||
uint32_t(js::ProfilingStackFrame::Flags:: \
|
||||
LABEL_DETERMINED_BY_CATEGORY_PAIR))
|
||||
|
||||
// Similar to AUTO_PROFILER_LABEL, but with an additional string. The inserted
|
||||
// RAII object stores the cStr pointer in a field; it does not copy the string.
|
||||
|
@ -541,9 +552,9 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
|
|||
// profile buffer can just store the raw pointers to the literal strings.
|
||||
// Consequently, AUTO_PROFILER_LABEL frames take up considerably less space in
|
||||
// the profile buffer than AUTO_PROFILER_LABEL_DYNAMIC_* frames.
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_CSTR(label, category, cStr) \
|
||||
mozilla::AutoProfilerLabel PROFILER_RAII( \
|
||||
label, cStr, js::ProfilingStackFrame::Category::category)
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_CSTR(label, categoryPair, cStr) \
|
||||
mozilla::AutoProfilerLabel PROFILER_RAII( \
|
||||
label, cStr, JS::ProfilingCategoryPair::categoryPair)
|
||||
|
||||
// Similar to AUTO_PROFILER_LABEL_DYNAMIC_CSTR, but takes an nsACString.
|
||||
//
|
||||
|
@ -552,14 +563,13 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
|
|||
// cost of the string assignment unless the profiler is active. Therefore,
|
||||
// unlike AUTO_PROFILER_LABEL and AUTO_PROFILER_LABEL_DYNAMIC_CSTR, this macro
|
||||
// doesn't push/pop a label when the profiler is inactive.
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(label, category, nsCStr) \
|
||||
mozilla::Maybe<nsAutoCString> autoCStr; \
|
||||
mozilla::Maybe<AutoProfilerLabel> raiiObjectNsCString; \
|
||||
if (profiler_is_active()) { \
|
||||
autoCStr.emplace(nsCStr); \
|
||||
raiiObjectNsCString.emplace( \
|
||||
label, autoCStr->get(), \
|
||||
js::ProfilingStackFrame::Category::category); \
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(label, categoryPair, nsCStr) \
|
||||
mozilla::Maybe<nsAutoCString> autoCStr; \
|
||||
mozilla::Maybe<AutoProfilerLabel> raiiObjectNsCString; \
|
||||
if (profiler_is_active()) { \
|
||||
autoCStr.emplace(nsCStr); \
|
||||
raiiObjectNsCString.emplace(label, autoCStr->get(), \
|
||||
JS::ProfilingCategoryPair::categoryPair); \
|
||||
}
|
||||
|
||||
// Similar to AUTO_PROFILER_LABEL_DYNAMIC_CSTR, but takes an nsString that is
|
||||
|
@ -570,14 +580,14 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
|
|||
// the runtime cost of the string conversion unless the profiler is active.
|
||||
// Therefore, unlike AUTO_PROFILER_LABEL and AUTO_PROFILER_LABEL_DYNAMIC_CSTR,
|
||||
// this macro doesn't push/pop a label when the profiler is inactive.
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(label, category, nsStr) \
|
||||
mozilla::Maybe<NS_LossyConvertUTF16toASCII> asciiStr; \
|
||||
mozilla::Maybe<AutoProfilerLabel> raiiObjectLossyNsString; \
|
||||
if (profiler_is_active()) { \
|
||||
asciiStr.emplace(nsStr); \
|
||||
raiiObjectLossyNsString.emplace( \
|
||||
label, asciiStr->get(), \
|
||||
js::ProfilingStackFrame::Category::category); \
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(label, categoryPair, \
|
||||
nsStr) \
|
||||
mozilla::Maybe<NS_LossyConvertUTF16toASCII> asciiStr; \
|
||||
mozilla::Maybe<AutoProfilerLabel> raiiObjectLossyNsString; \
|
||||
if (profiler_is_active()) { \
|
||||
asciiStr.emplace(nsStr); \
|
||||
raiiObjectLossyNsString.emplace( \
|
||||
label, asciiStr->get(), JS::ProfilingCategoryPair::categoryPair); \
|
||||
}
|
||||
|
||||
// Similar to AUTO_PROFILER_LABEL, but accepting a JSContext* parameter, and a
|
||||
|
@ -586,18 +596,18 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
|
|||
// noticeable. It avoids overhead from the TLS lookup because it can get the
|
||||
// ProfilingStack from the JS context, and avoids almost all overhead in the
|
||||
// case where the profiler is disabled.
|
||||
# define AUTO_PROFILER_LABEL_FAST(label, category, ctx) \
|
||||
mozilla::AutoProfilerLabel PROFILER_RAII( \
|
||||
ctx, label, nullptr, js::ProfilingStackFrame::Category::category)
|
||||
# define AUTO_PROFILER_LABEL_FAST(label, categoryPair, ctx) \
|
||||
mozilla::AutoProfilerLabel PROFILER_RAII( \
|
||||
ctx, label, nullptr, JS::ProfilingCategoryPair::categoryPair)
|
||||
|
||||
// Similar to AUTO_PROFILER_LABEL_FAST, but also takes an extra string and an
|
||||
// additional set of flags. The flags parameter should carry values from the
|
||||
// js::ProfilingStackFrame::Flags enum.
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, category, \
|
||||
ctx, flags) \
|
||||
mozilla::AutoProfilerLabel PROFILER_RAII( \
|
||||
ctx, label, dynamicString, \
|
||||
js::ProfilingStackFrame::Category::category, flags)
|
||||
# define AUTO_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, categoryPair, \
|
||||
ctx, flags) \
|
||||
mozilla::AutoProfilerLabel PROFILER_RAII( \
|
||||
ctx, label, dynamicString, JS::ProfilingCategoryPair::categoryPair, \
|
||||
flags)
|
||||
|
||||
// Insert a marker in the profile timeline. This is useful to delimit something
|
||||
// important happening such as the first paint. Unlike labels, which are only
|
||||
|
@ -607,19 +617,19 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
|
|||
// certain length of time. A no-op if the profiler is inactive or in privacy
|
||||
// mode.
|
||||
|
||||
# define PROFILER_ADD_MARKER(markerName, category) \
|
||||
profiler_add_marker(markerName, js::ProfilingStackFrame::Category::category)
|
||||
# define PROFILER_ADD_MARKER(markerName, categoryPair) \
|
||||
profiler_add_marker(markerName, JS::ProfilingCategoryPair::categoryPair)
|
||||
|
||||
void profiler_add_marker(const char* aMarkerName,
|
||||
js::ProfilingStackFrame::Category aCategory);
|
||||
JS::ProfilingCategoryPair aCategoryPair);
|
||||
void profiler_add_marker(const char* aMarkerName,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
mozilla::UniquePtr<ProfilerMarkerPayload> aPayload);
|
||||
void profiler_add_js_marker(const char* aMarkerName);
|
||||
|
||||
// Insert a marker in the profile timeline for a specified thread.
|
||||
void profiler_add_marker_for_thread(
|
||||
int aThreadId, js::ProfilingStackFrame::Category aCategory,
|
||||
int aThreadId, JS::ProfilingCategoryPair aCategoryPair,
|
||||
const char* aMarkerName,
|
||||
mozilla::UniquePtr<ProfilerMarkerPayload> aPayload);
|
||||
|
||||
|
@ -664,41 +674,39 @@ enum TracingKind {
|
|||
// Adds a tracing marker to the profile. A no-op if the profiler is inactive or
|
||||
// in privacy mode.
|
||||
|
||||
# define PROFILER_TRACING(categoryString, markerName, category, kind) \
|
||||
profiler_tracing(categoryString, markerName, \
|
||||
js::ProfilingStackFrame::Category::category, kind)
|
||||
# define PROFILER_TRACING_DOCSHELL(categoryString, markerName, category, \
|
||||
kind, docShell) \
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell); \
|
||||
profiler_tracing(categoryString, markerName, \
|
||||
js::ProfilingStackFrame::Category::category, kind, \
|
||||
# define PROFILER_TRACING(categoryString, markerName, categoryPair, kind) \
|
||||
profiler_tracing(categoryString, markerName, \
|
||||
JS::ProfilingCategoryPair::categoryPair, kind)
|
||||
# define PROFILER_TRACING_DOCSHELL(categoryString, markerName, categoryPair, \
|
||||
kind, docShell) \
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell); \
|
||||
profiler_tracing(categoryString, markerName, \
|
||||
JS::ProfilingCategoryPair::categoryPair, kind, \
|
||||
docShellId, docShellHistoryId)
|
||||
|
||||
void profiler_tracing(
|
||||
const char* aCategoryString, const char* aMarkerName,
|
||||
js::ProfilingStackFrame::Category aCategory, TracingKind aKind,
|
||||
JS::ProfilingCategoryPair aCategoryPair, TracingKind aKind,
|
||||
const mozilla::Maybe<nsID>& aDocShellId = mozilla::Nothing(),
|
||||
const mozilla::Maybe<uint32_t>& aDocShellHistoryId = mozilla::Nothing());
|
||||
void profiler_tracing(
|
||||
const char* aCategoryString, const char* aMarkerName,
|
||||
js::ProfilingStackFrame::Category aCategory, TracingKind aKind,
|
||||
JS::ProfilingCategoryPair aCategoryPair, TracingKind aKind,
|
||||
UniqueProfilerBacktrace aCause,
|
||||
const mozilla::Maybe<nsID>& aDocShellId = mozilla::Nothing(),
|
||||
const mozilla::Maybe<uint32_t>& aDocShellHistoryId = mozilla::Nothing());
|
||||
|
||||
// Adds a START/END pair of tracing markers.
|
||||
# define AUTO_PROFILER_TRACING(categoryString, markerName, category) \
|
||||
mozilla::AutoProfilerTracing PROFILER_RAII( \
|
||||
categoryString, markerName, \
|
||||
js::ProfilingStackFrame::Category::category, mozilla::Nothing(), \
|
||||
mozilla::Nothing())
|
||||
# define AUTO_PROFILER_TRACING_DOCSHELL(categoryString, markerName, category, \
|
||||
docShell) \
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell); \
|
||||
mozilla::AutoProfilerTracing PROFILER_RAII( \
|
||||
categoryString, markerName, \
|
||||
js::ProfilingStackFrame::Category::category, docShellId, \
|
||||
docShellHistoryId)
|
||||
# define AUTO_PROFILER_TRACING(categoryString, markerName, categoryPair) \
|
||||
mozilla::AutoProfilerTracing PROFILER_RAII( \
|
||||
categoryString, markerName, JS::ProfilingCategoryPair::categoryPair, \
|
||||
mozilla::Nothing(), mozilla::Nothing())
|
||||
# define AUTO_PROFILER_TRACING_DOCSHELL(categoryString, markerName, \
|
||||
categoryPair, docShell) \
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell); \
|
||||
mozilla::AutoProfilerTracing PROFILER_RAII( \
|
||||
categoryString, markerName, JS::ProfilingCategoryPair::categoryPair, \
|
||||
docShellId, docShellHistoryId)
|
||||
|
||||
// Add a text marker. Text markers are similar to tracing markers, with the
|
||||
// difference that text markers have their "text" separate from the marker name;
|
||||
|
@ -708,7 +716,7 @@ void profiler_tracing(
|
|||
// into one marker.
|
||||
void profiler_add_text_marker(
|
||||
const char* aMarkerName, const nsACString& aText,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
const mozilla::TimeStamp& aStartTime, const mozilla::TimeStamp& aEndTime,
|
||||
const mozilla::Maybe<nsID>& aDocShellId = mozilla::Nothing(),
|
||||
const mozilla::Maybe<uint32_t>& aDocShellHistoryId = mozilla::Nothing(),
|
||||
|
@ -717,14 +725,14 @@ void profiler_add_text_marker(
|
|||
class MOZ_RAII AutoProfilerTextMarker {
|
||||
public:
|
||||
AutoProfilerTextMarker(const char* aMarkerName, const nsACString& aText,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
const mozilla::Maybe<nsID>& aDocShellId,
|
||||
const mozilla::Maybe<uint32_t>& aDocShellHistoryId,
|
||||
UniqueProfilerBacktrace&& aCause =
|
||||
nullptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mMarkerName(aMarkerName),
|
||||
mText(aText),
|
||||
mCategory(aCategory),
|
||||
mCategoryPair(aCategoryPair),
|
||||
mStartTime(mozilla::TimeStamp::Now()),
|
||||
mCause(std::move(aCause)),
|
||||
mDocShellId(aDocShellId),
|
||||
|
@ -733,9 +741,8 @@ class MOZ_RAII AutoProfilerTextMarker {
|
|||
}
|
||||
|
||||
~AutoProfilerTextMarker() {
|
||||
profiler_add_text_marker(mMarkerName, mText,
|
||||
js::ProfilingStackFrame::Category::LAYOUT,
|
||||
mStartTime, mozilla::TimeStamp::Now(), mDocShellId,
|
||||
profiler_add_text_marker(mMarkerName, mText, mCategoryPair, mStartTime,
|
||||
mozilla::TimeStamp::Now(), mDocShellId,
|
||||
mDocShellHistoryId, std::move(mCause));
|
||||
}
|
||||
|
||||
|
@ -743,31 +750,32 @@ class MOZ_RAII AutoProfilerTextMarker {
|
|||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
const char* mMarkerName;
|
||||
nsCString mText;
|
||||
const js::ProfilingStackFrame::Category mCategory;
|
||||
const JS::ProfilingCategoryPair mCategoryPair;
|
||||
mozilla::TimeStamp mStartTime;
|
||||
UniqueProfilerBacktrace mCause;
|
||||
const mozilla::Maybe<nsID> mDocShellId;
|
||||
const mozilla::Maybe<uint32_t> mDocShellHistoryId;
|
||||
};
|
||||
|
||||
# define AUTO_PROFILER_TEXT_MARKER_CAUSE(markerName, text, category, cause) \
|
||||
AutoProfilerTextMarker PROFILER_RAII( \
|
||||
markerName, text, js::ProfilingStackFrame::Category::category, \
|
||||
Nothing(), Nothing(), cause)
|
||||
# define AUTO_PROFILER_TEXT_MARKER_CAUSE(markerName, text, categoryPair, \
|
||||
cause) \
|
||||
AutoProfilerTextMarker PROFILER_RAII( \
|
||||
markerName, text, JS::ProfilingCategoryPair::categoryPair, Nothing(), \
|
||||
Nothing(), cause)
|
||||
|
||||
# define AUTO_PROFILER_TEXT_MARKER_DOCSHELL(markerName, text, category, \
|
||||
docShell) \
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell); \
|
||||
AutoProfilerTextMarker PROFILER_RAII( \
|
||||
markerName, text, js::ProfilingStackFrame::Category::category, \
|
||||
docShellId, docShellHistoryId)
|
||||
|
||||
# define AUTO_PROFILER_TEXT_MARKER_DOCSHELL_CAUSE(markerName, text, category, \
|
||||
docShell, cause) \
|
||||
# define AUTO_PROFILER_TEXT_MARKER_DOCSHELL(markerName, text, categoryPair, \
|
||||
docShell) \
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell); \
|
||||
AutoProfilerTextMarker PROFILER_RAII( \
|
||||
markerName, text, js::ProfilingStackFrame::Category::category, \
|
||||
docShellId, docShellHistoryId, cause)
|
||||
markerName, text, JS::ProfilingCategoryPair::categoryPair, docShellId, \
|
||||
docShellHistoryId)
|
||||
|
||||
# define AUTO_PROFILER_TEXT_MARKER_DOCSHELL_CAUSE( \
|
||||
markerName, text, categoryPair, docShell, cause) \
|
||||
DECLARE_DOCSHELL_AND_HISTORY_ID(docShell); \
|
||||
AutoProfilerTextMarker PROFILER_RAII( \
|
||||
markerName, text, JS::ProfilingCategoryPair::categoryPair, docShellId, \
|
||||
docShellHistoryId, cause)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Output profiles
|
||||
|
@ -882,12 +890,12 @@ class MOZ_RAII AutoProfilerLabel {
|
|||
public:
|
||||
// This is the AUTO_PROFILER_LABEL and AUTO_PROFILER_LABEL_DYNAMIC variant.
|
||||
AutoProfilerLabel(const char* aLabel, const char* aDynamicString,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
uint32_t aFlags = 0 MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
|
||||
// Get the ProfilingStack from TLS.
|
||||
Push(sProfilingStack.get(), aLabel, aDynamicString, aCategory, aFlags);
|
||||
Push(sProfilingStack.get(), aLabel, aDynamicString, aCategoryPair, aFlags);
|
||||
}
|
||||
|
||||
// This is the AUTO_PROFILER_LABEL_FAST variant. It retrieves the
|
||||
|
@ -895,22 +903,22 @@ class MOZ_RAII AutoProfilerLabel {
|
|||
// inactive.
|
||||
AutoProfilerLabel(JSContext* aJSContext, const char* aLabel,
|
||||
const char* aDynamicString,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
uint32_t aFlags MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
Push(js::GetContextProfilingStackIfEnabled(aJSContext), aLabel,
|
||||
aDynamicString, aCategory, aFlags);
|
||||
aDynamicString, aCategoryPair, aFlags);
|
||||
}
|
||||
|
||||
void Push(ProfilingStack* aProfilingStack, const char* aLabel,
|
||||
const char* aDynamicString,
|
||||
js::ProfilingStackFrame::Category aCategory, uint32_t aFlags = 0) {
|
||||
const char* aDynamicString, JS::ProfilingCategoryPair aCategoryPair,
|
||||
uint32_t aFlags = 0) {
|
||||
// This function runs both on and off the main thread.
|
||||
|
||||
mProfilingStack = aProfilingStack;
|
||||
if (mProfilingStack) {
|
||||
mProfilingStack->pushLabelFrame(aLabel, aDynamicString, this, aCategory,
|
||||
aFlags);
|
||||
mProfilingStack->pushLabelFrame(aLabel, aDynamicString, this,
|
||||
aCategoryPair, aFlags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -937,39 +945,39 @@ class MOZ_RAII AutoProfilerLabel {
|
|||
class MOZ_RAII AutoProfilerTracing {
|
||||
public:
|
||||
AutoProfilerTracing(const char* aCategoryString, const char* aMarkerName,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
const mozilla::Maybe<nsID>& aDocShellId,
|
||||
const mozilla::Maybe<uint32_t>& aDocShellHistoryId
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mCategoryString(aCategoryString),
|
||||
mMarkerName(aMarkerName),
|
||||
mCategory(aCategory),
|
||||
mCategoryPair(aCategoryPair),
|
||||
mDocShellId(aDocShellId),
|
||||
mDocShellHistoryId(aDocShellHistoryId) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
profiler_tracing(mCategoryString, mMarkerName, aCategory,
|
||||
profiler_tracing(mCategoryString, mMarkerName, aCategoryPair,
|
||||
TRACING_INTERVAL_START, mDocShellId, mDocShellHistoryId);
|
||||
}
|
||||
|
||||
AutoProfilerTracing(const char* aCategoryString, const char* aMarkerName,
|
||||
js::ProfilingStackFrame::Category aCategory,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
UniqueProfilerBacktrace aBacktrace,
|
||||
const mozilla::Maybe<nsID>& aDocShellId,
|
||||
const mozilla::Maybe<uint32_t>& aDocShellHistoryId
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mCategoryString(aCategoryString),
|
||||
mMarkerName(aMarkerName),
|
||||
mCategory(aCategory),
|
||||
mCategoryPair(aCategoryPair),
|
||||
mDocShellId(aDocShellId),
|
||||
mDocShellHistoryId(aDocShellHistoryId) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
profiler_tracing(mCategoryString, mMarkerName, aCategory,
|
||||
profiler_tracing(mCategoryString, mMarkerName, aCategoryPair,
|
||||
TRACING_INTERVAL_START, std::move(aBacktrace), mDocShellId,
|
||||
mDocShellHistoryId);
|
||||
}
|
||||
|
||||
~AutoProfilerTracing() {
|
||||
profiler_tracing(mCategoryString, mMarkerName, mCategory,
|
||||
profiler_tracing(mCategoryString, mMarkerName, mCategoryPair,
|
||||
TRACING_INTERVAL_END, mDocShellId, mDocShellHistoryId);
|
||||
}
|
||||
|
||||
|
@ -977,7 +985,7 @@ class MOZ_RAII AutoProfilerTracing {
|
|||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
const char* mCategoryString;
|
||||
const char* mMarkerName;
|
||||
const js::ProfilingStackFrame::Category mCategory;
|
||||
const JS::ProfilingCategoryPair mCategoryPair;
|
||||
const mozilla::Maybe<nsID> mDocShellId;
|
||||
const mozilla::Maybe<uint32_t> mDocShellHistoryId;
|
||||
};
|
||||
|
|
|
@ -459,28 +459,27 @@ TEST(GeckoProfiler, Markers) {
|
|||
profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
|
||||
filters, MOZ_ARRAY_LENGTH(filters));
|
||||
|
||||
profiler_tracing("A", "B", js::ProfilingStackFrame::Category::OTHER,
|
||||
TRACING_EVENT);
|
||||
profiler_tracing("A", "B", JS::ProfilingCategoryPair::OTHER, TRACING_EVENT);
|
||||
PROFILER_TRACING("A", "C", OTHER, TRACING_INTERVAL_START);
|
||||
PROFILER_TRACING("A", "C", OTHER, TRACING_INTERVAL_END);
|
||||
|
||||
UniqueProfilerBacktrace bt = profiler_get_backtrace();
|
||||
profiler_tracing("B", "A", js::ProfilingStackFrame::Category::OTHER,
|
||||
TRACING_EVENT, std::move(bt));
|
||||
profiler_tracing("B", "A", JS::ProfilingCategoryPair::OTHER, TRACING_EVENT,
|
||||
std::move(bt));
|
||||
|
||||
{ AUTO_PROFILER_TRACING("C", "A", OTHER); }
|
||||
|
||||
profiler_add_marker("M1", js::ProfilingStackFrame::Category::OTHER);
|
||||
profiler_add_marker("M2", js::ProfilingStackFrame::Category::OTHER,
|
||||
profiler_add_marker("M1", JS::ProfilingCategoryPair::OTHER);
|
||||
profiler_add_marker("M2", JS::ProfilingCategoryPair::OTHER,
|
||||
MakeUnique<TracingMarkerPayload>("C", TRACING_EVENT));
|
||||
PROFILER_ADD_MARKER("M3", OTHER);
|
||||
profiler_add_marker("M4", js::ProfilingStackFrame::Category::OTHER,
|
||||
profiler_add_marker("M4", JS::ProfilingCategoryPair::OTHER,
|
||||
MakeUnique<TracingMarkerPayload>(
|
||||
"C", TRACING_EVENT, mozilla::Nothing(),
|
||||
mozilla::Nothing(), profiler_get_backtrace()));
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
profiler_add_marker("M5", js::ProfilingStackFrame::Category::OTHER,
|
||||
profiler_add_marker("M5", JS::ProfilingCategoryPair::OTHER,
|
||||
MakeUnique<GTestMarkerPayload>(i));
|
||||
}
|
||||
|
||||
|
@ -539,7 +538,7 @@ TEST(GeckoProfiler, Markers) {
|
|||
ASSERT_TRUE(GTestMarkerPayload::sNumDestroyed == 10);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
profiler_add_marker("M5", js::ProfilingStackFrame::Category::OTHER,
|
||||
profiler_add_marker("M5", JS::ProfilingCategoryPair::OTHER,
|
||||
MakeUnique<GTestMarkerPayload>(i));
|
||||
}
|
||||
|
||||
|
@ -569,10 +568,10 @@ TEST(GeckoProfiler, DurationLimit) {
|
|||
GTestMarkerPayload::sNumStreamed = 0;
|
||||
GTestMarkerPayload::sNumDestroyed = 0;
|
||||
|
||||
profiler_add_marker("M1", js::ProfilingStackFrame::Category::OTHER,
|
||||
profiler_add_marker("M1", JS::ProfilingCategoryPair::OTHER,
|
||||
MakeUnique<GTestMarkerPayload>(1));
|
||||
PR_Sleep(PR_MillisecondsToInterval(1100));
|
||||
profiler_add_marker("M2", js::ProfilingStackFrame::Category::OTHER,
|
||||
profiler_add_marker("M2", JS::ProfilingCategoryPair::OTHER,
|
||||
MakeUnique<GTestMarkerPayload>(2));
|
||||
PR_Sleep(PR_MillisecondsToInterval(500));
|
||||
|
||||
|
@ -785,10 +784,9 @@ TEST(GeckoProfiler, ProfilingStack) {
|
|||
ASSERT_TRUE(profiler_get_backtrace());
|
||||
}
|
||||
|
||||
AutoProfilerLabel label1("A", nullptr,
|
||||
js::ProfilingStackFrame::Category::DOM);
|
||||
AutoProfilerLabel label1("A", nullptr, JS::ProfilingCategoryPair::DOM);
|
||||
AutoProfilerLabel label2("A", dynamic.get(),
|
||||
js::ProfilingStackFrame::Category::NETWORK);
|
||||
JS::ProfilingCategoryPair::NETWORK);
|
||||
ASSERT_TRUE(profiler_get_backtrace());
|
||||
|
||||
profiler_stop();
|
||||
|
|
|
@ -798,13 +798,13 @@ void CycleCollectedJSRuntime::TraverseNativeRoots(
|
|||
if (profiler_thread_is_being_profiled()) {
|
||||
if (aProgress == JS::GC_CYCLE_END) {
|
||||
profiler_add_marker(
|
||||
"GCMajor", js::ProfilingStackFrame::Category::GCCC,
|
||||
"GCMajor", JS::ProfilingCategoryPair::GCCC,
|
||||
MakeUnique<GCMajorMarkerPayload>(aDesc.startTime(aContext),
|
||||
aDesc.endTime(aContext),
|
||||
aDesc.formatJSONProfiler(aContext)));
|
||||
} else if (aProgress == JS::GC_SLICE_END) {
|
||||
profiler_add_marker(
|
||||
"GCSlice", js::ProfilingStackFrame::Category::GCCC,
|
||||
"GCSlice", JS::ProfilingCategoryPair::GCCC,
|
||||
MakeUnique<GCSliceMarkerPayload>(
|
||||
aDesc.lastSliceStart(aContext), aDesc.lastSliceEnd(aContext),
|
||||
aDesc.sliceToJSONProfiler(aContext)));
|
||||
|
@ -885,7 +885,7 @@ class MinorGCMarker : public TimelineMarker {
|
|||
#ifdef MOZ_GECKO_PROFILER
|
||||
else if (aProgress == JS::GCNurseryProgress::GC_NURSERY_COLLECTION_END &&
|
||||
profiler_thread_is_being_profiled()) {
|
||||
profiler_add_marker("GCMinor", js::ProfilingStackFrame::Category::GCCC,
|
||||
profiler_add_marker("GCMinor", JS::ProfilingCategoryPair::GCCC,
|
||||
MakeUnique<GCMinorMarkerPayload>(
|
||||
self->mLatestNurseryCollectionStart,
|
||||
TimeStamp::Now(), JS::MinorGcToJSON(aContext)));
|
||||
|
|
|
@ -412,7 +412,7 @@ class LogModuleManager {
|
|||
#ifdef MOZ_GECKO_PROFILER
|
||||
if (mAddProfilerMarker && profiler_is_active()) {
|
||||
profiler_add_marker(
|
||||
"LogMessages", js::ProfilingStackFrame::Category::OTHER,
|
||||
"LogMessages", JS::ProfilingCategoryPair::OTHER,
|
||||
MakeUnique<LogMarkerPayload>(aName, buffToWrite, TimeStamp::Now()));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1177,7 +1177,7 @@ nsThread::ProcessNextEvent(bool aMayWait, bool* aResult) {
|
|||
profiler_add_marker(
|
||||
(priority != EventQueuePriority::Idle) ? "LongTask"
|
||||
: "LongIdleTask",
|
||||
js::ProfilingStackFrame::Category::OTHER,
|
||||
JS::ProfilingCategoryPair::OTHER,
|
||||
MakeUnique<LongTaskMarkerPayload>(mCurrentEventStart, now));
|
||||
}
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче