Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
Brindusan Cristian 2019-04-02 18:50:37 +03:00
commit f0bb72977e
109 changed files with 2017 additions and 2288 deletions

View File

@ -32,6 +32,11 @@ XPCOMUtils.defineLazyGetter(this, "PageMenuChild", () => {
return new tmp.PageMenuChild();
});
XPCOMUtils.defineLazyGetter(this, "ReferrerInfo", () =>
Components.Constructor("@mozilla.org/referrer-info;1",
"nsIReferrerInfo",
"init"));
const messageListeners = {
"ContextMenu:BookmarkFrame": function(aMessage) {
let frame = this.getTarget(aMessage).ownerDocument;
@ -602,6 +607,15 @@ class ContextMenuChild extends ActorChild {
data.context.targetAsCPOW = targetAsCPOW;
data.referrerInfo = new ReferrerInfo(
referrerPolicy,
!context.linkHasNoReferrer,
data.documentURIObject);
data.frameReferrerInfo = new ReferrerInfo(
referrerPolicy,
!context.linkHasNoReferrer,
referrer ? Services.io.newURI(referrer) : null);
mainWin.setContextMenuContentData(data);
}
}

View File

@ -314,8 +314,7 @@ function openLinkIn(url, where, params) {
var aAllowThirdPartyFixup = params.allowThirdPartyFixup;
var aPostData = params.postData;
var aCharset = params.charset;
var aReferrerInfo = ("referrerInfo" in params)
? params.referrerInfo
var aReferrerInfo = params.referrerInfo ? params.referrerInfo
: new ReferrerInfo(Ci.nsIHttpChannel.REFERRER_POLICY_UNSET, true, null);
var aRelatedToCurrent = params.relatedToCurrent;
var aAllowInheritPrincipal = !!params.allowInheritPrincipal;

View File

@ -50,6 +50,20 @@ var MigrationWizard = { /* exported MigrationWizard */
}
}
document.addEventListener("wizardcancel", function() { MigrationWizard.onWizardCancel(); });
document.getElementById("selectProfile").addEventListener("pageshow", function() { MigrationWizard.onSelectProfilePageShow(); });
document.getElementById("importItems").addEventListener("pageshow", function() { MigrationWizard.onImportItemsPageShow(); });
document.getElementById("migrating").addEventListener("pageshow", function() { MigrationWizard.onMigratingPageShow(); });
document.getElementById("done").addEventListener("pageshow", function() { MigrationWizard.onDonePageShow(); });
document.getElementById("selectProfile").addEventListener("pagerewound", function() { MigrationWizard.onSelectProfilePageRewound(); });
document.getElementById("importItems").addEventListener("pagerewound", function() { MigrationWizard.onImportItemsPageRewound(); });
document.getElementById("selectProfile").addEventListener("pageadvanced", function() { MigrationWizard.onSelectProfilePageAdvanced(); });
document.getElementById("importItems").addEventListener("pageadvanced", function() { MigrationWizard.onImportItemsPageAdvanced(); });
document.getElementById("importSource").addEventListener("pageadvanced", function(e) { MigrationWizard.onImportSourcePageAdvanced(e); });
this.onImportSourcePageShow();
},
@ -145,7 +159,7 @@ var MigrationWizard = { /* exported MigrationWizard */
}
},
onImportSourcePageAdvanced() {
onImportSourcePageAdvanced(event) {
var newSource = document.getElementById("importSourceGroup").selectedItem.id;
if (newSource == "nothing") {
@ -155,7 +169,7 @@ var MigrationWizard = { /* exported MigrationWizard */
Services.telemetry.getHistogramById("FX_MIGRATION_SOURCE_BROWSER")
.add(MigrationUtils.getSourceIdForTelemetry("nothing"));
document.documentElement.cancel();
return false;
event.preventDefault();
}
if (!this._migrator || (newSource != this._source)) {
@ -184,7 +198,6 @@ var MigrationWizard = { /* exported MigrationWizard */
else
this._selectedProfile = null;
}
return undefined;
},
// 2 - [Profile Selection]

View File

@ -15,15 +15,13 @@
onunload="MigrationWizard.uninit()"
style="width: 40em;"
buttons="accept,cancel"
branded="true"
onwizardcancel="return MigrationWizard.onWizardCancel();">
branded="true">
<script type="application/javascript" src="chrome://global/content/customElements.js"/>
<script type="application/javascript" src="chrome://browser/content/migration/migration.js"/>
<wizardpage id="importSource" pageid="importSource" next="selectProfile"
label="&importSource.title;"
onpageadvanced="return MigrationWizard.onImportSourcePageAdvanced();">
label="&importSource.title;">
#ifdef XP_WIN
<description id="importAll" control="importSourceGroup">&importFrom.label;</description>
#else
@ -60,10 +58,7 @@
</wizardpage>
<wizardpage id="selectProfile" pageid="selectProfile" label="&selectProfile.title;"
next="importItems"
onpageshow="return MigrationWizard.onSelectProfilePageShow();"
onpagerewound="return MigrationWizard.onSelectProfilePageRewound();"
onpageadvanced="return MigrationWizard.onSelectProfilePageAdvanced();">
next="importItems">
<description control="profiles">&selectProfile.label;</description>
<radiogroup id="profiles" align="left"/>
@ -71,9 +66,6 @@
<wizardpage id="importItems" pageid="importItems" label="&importItems.title;"
next="migrating"
onpageshow="return MigrationWizard.onImportItemsPageShow();"
onpagerewound="return MigrationWizard.onImportItemsPageRewound();"
onpageadvanced="return MigrationWizard.onImportItemsPageAdvanced();"
oncommand="MigrationWizard.onImportItemCommand();">
<description control="dataSources">&importItems.label;</description>
@ -81,19 +73,16 @@
</wizardpage>
<wizardpage id="migrating" pageid="migrating" label="&migrating.title;"
next="done"
onpageshow="MigrationWizard.onMigratingPageShow();">
next="done">
<description control="migratingItems">&migrating.label;</description>
<vbox id="migratingItems" style="overflow: auto;" align="left" role="group"/>
</wizardpage>
<wizardpage id="done" pageid="done" label="&done.title;"
onpageshow="MigrationWizard.onDonePageShow();">
<wizardpage id="done" pageid="done" label="&done.title;">
<description control="doneItems">&done.label;</description>
<vbox id="doneItems" style="overflow: auto;" align="left" role="group"/>
</wizardpage>
</wizard>

View File

@ -1318,7 +1318,10 @@ var UITour = {
urlbar.value = SEARCH_STRING;
urlbar.select();
if (quantumbar) {
urlbar.startQuery();
urlbar.startQuery({
searchString: SEARCH_STRING,
allowAutofill: false,
});
} else {
urlbar.controller.startSearch(SEARCH_STRING);
}

View File

@ -463,14 +463,12 @@ class UrlbarAbstraction {
url: urls.length > 0 ? urls[0].textContent : null,
typeIcon: typeIconStyle["background-image"],
};
let actionElement = element.getElementsByClassName("urlbarView-action")[0];
let urlElement = element.getElementsByClassName("urlbarView-url")[0];
details.element = {
action: actionElement,
action: element.getElementsByClassName("urlbarView-action")[0],
row: element,
separator: urlElement || actionElement,
separator: element.getElementsByClassName("urlbarView-title-separator")[0],
title: element.getElementsByClassName("urlbarView-title")[0],
url: urlElement,
url: element.getElementsByClassName("urlbarView-url")[0],
};
if (details.type == UrlbarUtils.RESULT_TYPE.SEARCH) {
details.searchParams = {

View File

@ -1319,7 +1319,6 @@ menuitem.panel-subview-footer@menuStateActive@,
-moz-box-pack: end;
margin-inline-start: 10px;
margin-inline-end: auto;
color: var(--panel-disabled-color);
}
#PanelUI-remotetabs-tabslist > toolbarbutton[itemtype="tab"],

View File

@ -47,6 +47,6 @@
"patches": [
"static-llvm-symbolizer.patch",
"find_symbolizer_linux.patch",
"rename_gcov_flush_.patch"
"rename_gcov_flush.patch"
]
}

View File

@ -18,7 +18,7 @@
"patches": [
"static-llvm-symbolizer.patch",
"find_symbolizer_linux.patch",
"rename_gcov_flush_.patch",
"rename_gcov_flush.patch",
"android-mangling-error.patch"
]
}

View File

@ -22,6 +22,7 @@
"ld": "/builds/worker/workspace/build/src/clang/bin/clang",
"patches": [
"static-llvm-symbolizer.patch",
"rename_gcov_flush.patch",
"compiler-rt-cross-compile.patch",
"compiler-rt-no-codesign.patch"
]

View File

@ -25,3 +25,16 @@ index 9af64ed332c..bcebe303ff4 100644
Builder.CreateCall(GCOVFlush);
I->getParent()->splitBasicBlock(I);
}
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index e113f9a679..b3a07b18c0 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1058,7 +1058,7 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
// runtime's functionality.
if (hasExportSymbolDirective(Args)) {
if (needsGCovInstrumentation(Args)) {
- addExportedSymbol(CmdArgs, "___gcov_flush");
+ addExportedSymbol(CmdArgs, "___custom_llvm_gcov_flush");
addExportedSymbol(CmdArgs, "_flush_fn_list");
addExportedSymbol(CmdArgs, "_writeout_fn_list");
} else {

View File

@ -24,6 +24,7 @@ const { remoteClientManager } =
const {
CONNECT_RUNTIME_FAILURE,
CONNECT_RUNTIME_NOT_RESPONDING,
CONNECT_RUNTIME_START,
CONNECT_RUNTIME_SUCCESS,
DEBUG_TARGET_PANE,
@ -52,6 +53,8 @@ const {
WATCH_RUNTIME_SUCCESS,
} = require("../constants");
const CONNECTION_TIMING_OUT_DELAY = 3000;
async function getRuntimeIcon(channel) {
return (channel === "release" || channel === "beta" || channel === "aurora")
? `chrome://devtools/skin/images/aboutdebugging-firefox-${ channel }.svg`
@ -69,7 +72,14 @@ function onMultiE10sUpdated() {
function connectRuntime(id) {
return async (dispatch, getState) => {
dispatch({ type: CONNECT_RUNTIME_START });
dispatch({ type: CONNECT_RUNTIME_START, id });
const connectionNotRespondingTimer = setTimeout(() => {
// If connecting to the runtime takes time over CONNECTION_TIMING_OUT_DELAY,
// we assume the connection prompt is showing on the runtime, show a dialog
// to let user know that.
dispatch({ type: CONNECT_RUNTIME_NOT_RESPONDING, id });
}, CONNECTION_TIMING_OUT_DELAY);
try {
const runtime = findRuntimeById(id, getState().runtimes);
const clientWrapper = await createClientForRuntime(runtime);
@ -135,7 +145,9 @@ function connectRuntime(id) {
},
});
} catch (e) {
dispatch({ type: CONNECT_RUNTIME_FAILURE, error: e });
dispatch({ type: CONNECT_RUNTIME_FAILURE, id, error: e });
} finally {
clearTimeout(connectionNotRespondingTimer);
}
};
}
@ -144,6 +156,9 @@ function createThisFirefoxRuntime() {
return (dispatch, getState) => {
const thisFirefoxRuntime = {
id: RUNTIMES.THIS_FIREFOX,
isConnecting: false,
isConnectionFailed: false,
isConnectionNotResponding: false,
isUnknown: false,
name: l10n.getString("about-debugging-this-firefox-runtime-name"),
type: RUNTIMES.THIS_FIREFOX,
@ -302,6 +317,9 @@ function updateNetworkRuntimes(locations) {
extra: {
connectionParameters: { host, port: parseInt(port, 10) },
},
isConnecting: false,
isConnectionFailed: false,
isConnectionNotResponding: false,
isUnknown: false,
name: location,
type: RUNTIMES.NETWORK,
@ -322,6 +340,9 @@ function updateUSBRuntimes(adbRuntimes) {
connectionParameters,
deviceName: adbRuntime.deviceName,
},
isConnecting: false,
isConnectionFailed: false,
isConnectionNotResponding: false,
isUnknown: adbRuntime.isUnknown(),
name: adbRuntime.shortName,
type: RUNTIMES.USB,
@ -363,12 +384,23 @@ function updateRemoteRuntimes(runtimes, type) {
await dispatch(Actions.selectPage(PAGE_TYPES.RUNTIME, RUNTIMES.THIS_FIREFOX));
}
// Retrieve runtimeDetails from existing runtimes.
// For existing runtimes, transfer all properties that are not available in the
// runtime objects passed to this method:
// - runtimeDetails (set by about:debugging after a successful connection)
// - isConnecting (set by about:debugging during the connection)
// - isConnectionFailed (set by about:debugging if connection was failed)
// - isConnectionNotResponding
// (set by about:debugging if connection is taking too much time)
runtimes.forEach(runtime => {
const existingRuntime = findRuntimeById(runtime.id, getState().runtimes);
const isConnectionValid = existingRuntime && existingRuntime.runtimeDetails &&
!existingRuntime.runtimeDetails.clientWrapper.isClosed();
runtime.runtimeDetails = isConnectionValid ? existingRuntime.runtimeDetails : null;
runtime.isConnecting = existingRuntime ? existingRuntime.isConnecting : false;
runtime.isConnectionFailed =
existingRuntime ? existingRuntime.isConnectionFailed : false;
runtime.isConnectionNotResponding =
existingRuntime ? existingRuntime.isConnectionNotResponding : false;
});
const existingRuntimes = getAllRuntimes(getState().runtimes);

View File

@ -163,6 +163,11 @@ p, h1 {
color: currentColor;
}
/* Text needs to wrap anywhere */
.word-wrap-anywhere {
word-wrap: anywhere;
}
/*
* Typography
*/

View File

@ -113,6 +113,9 @@ class Sidebar extends PureComponent {
icon,
key: keyId,
isConnected: runtimeHasDetails,
isConnecting: runtime.isConnecting,
isConnectionFailed: runtime.isConnectionFailed,
isConnectionNotResponding: runtime.isConnectionNotResponding,
isSelected,
isUnknown: runtime.isUnknown,
name,

View File

@ -11,8 +11,10 @@ const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const FluentReact = require("devtools/client/shared/vendor/fluent-react");
const Localized = createFactory(FluentReact.Localized);
const Message = createFactory(require("../shared/Message"));
const SidebarItem = createFactory(require("./SidebarItem"));
const Actions = require("../../actions/index");
const { MESSAGE_LEVEL } = require("../../constants");
/**
* This component displays a runtime item of the Sidebar component.
@ -26,6 +28,9 @@ class SidebarRuntimeItem extends PureComponent {
getString: PropTypes.func.isRequired,
icon: PropTypes.string.isRequired,
isConnected: PropTypes.bool.isRequired,
isConnecting: PropTypes.bool.isRequired,
isConnectionFailed: PropTypes.bool.isRequired,
isConnectionNotResponding: PropTypes.bool.isRequired,
isSelected: PropTypes.bool.isRequired,
isUnknown: PropTypes.bool.isRequired,
name: PropTypes.string.isRequired,
@ -34,19 +39,74 @@ class SidebarRuntimeItem extends PureComponent {
}
renderConnectButton() {
const { isConnecting } = this.props;
const localizationId = isConnecting
? "about-debugging-sidebar-item-connect-button-connecting"
: "about-debugging-sidebar-item-connect-button";
return Localized(
{
id: "about-debugging-sidebar-item-connect-button",
id: localizationId,
},
dom.button(
{
className: "default-button default-button--micro js-connect-button",
disabled: isConnecting,
onClick: () => {
const { dispatch, runtimeId } = this.props;
dispatch(Actions.connectRuntime(runtimeId));
},
},
"Connect"
localizationId
)
);
}
renderConnectionError() {
const { isConnectionFailed } = this.props;
if (!isConnectionFailed) {
return null;
}
const localizationId =
"about-debugging-sidebar-item-connect-button-connection-failed";
return Message(
{
level: MESSAGE_LEVEL.ERROR,
key: "connection-error",
className: "qa-connection-error",
},
Localized(
{
id: localizationId,
},
dom.p({ className: "word-wrap-anywhere" }, localizationId)
)
);
}
renderConnectionNotResponding() {
const { isConnectionNotResponding } = this.props;
if (!isConnectionNotResponding) {
return null;
}
const localizationId =
"about-debugging-sidebar-item-connect-button-connection-not-responding";
return Message(
{
level: MESSAGE_LEVEL.WARNING,
key: "connection-not-responding",
className: "qa-connection-not-responding",
},
Localized(
{
id: localizationId,
},
dom.p({ className: "word-wrap-anywhere" }, localizationId)
)
);
}
@ -115,9 +175,11 @@ class SidebarRuntimeItem extends PureComponent {
getString("aboutdebugging-sidebar-runtime-connection-status-connected") :
getString("aboutdebugging-sidebar-runtime-connection-status-disconnected");
return SidebarItem(
return [
SidebarItem(
{
className: "sidebar-item--tall",
key: "sidebar-item",
isSelected,
to: isConnected ? `/runtime/${encodeURIComponent(runtimeId)}` : null,
},
@ -135,8 +197,11 @@ class SidebarRuntimeItem extends PureComponent {
),
this.renderName(),
!isUnknown && !isConnected ? this.renderConnectButton() : null
)
);
),
),
this.renderConnectionError(),
this.renderConnectionNotResponding(),
];
}
}

View File

@ -16,6 +16,7 @@ const actionTypes = {
ADB_ADDON_UNINSTALL_FAILURE: "ADB_ADDON_UNINSTALL_FAILURE",
ADB_ADDON_STATUS_UPDATED: "ADB_ADDON_STATUS_UPDATED",
CONNECT_RUNTIME_FAILURE: "CONNECT_RUNTIME_FAILURE",
CONNECT_RUNTIME_NOT_RESPONDING: "CONNECT_RUNTIME_NOT_RESPONDING",
CONNECT_RUNTIME_START: "CONNECT_RUNTIME_START",
CONNECT_RUNTIME_SUCCESS: "CONNECT_RUNTIME_SUCCESS",
DEBUG_TARGET_COLLAPSIBILITY_UPDATED: "DEBUG_TARGET_COLLAPSIBILITY_UPDATED",

View File

@ -5,6 +5,9 @@
"use strict";
const {
CONNECT_RUNTIME_FAILURE,
CONNECT_RUNTIME_NOT_RESPONDING,
CONNECT_RUNTIME_START,
CONNECT_RUNTIME_SUCCESS,
DISCONNECT_RUNTIME_SUCCESS,
RUNTIMES,
@ -72,10 +75,41 @@ function _updateRuntimeById(runtimeId, updatedRuntime, state) {
function runtimesReducer(state = RuntimesState(), action) {
switch (action.type) {
case CONNECT_RUNTIME_START: {
const { id } = action;
const updatedState = {
isConnecting: true,
isConnectionFailed: false,
isConnectionNotResponding: false,
};
return _updateRuntimeById(id, updatedState, state);
}
case CONNECT_RUNTIME_NOT_RESPONDING: {
const { id } = action;
return _updateRuntimeById(id, { isConnectionNotResponding: true }, state);
}
case CONNECT_RUNTIME_SUCCESS: {
const { id, runtimeDetails, type } = action.runtime;
remoteClientManager.setClient(id, type, runtimeDetails.clientWrapper.client);
return _updateRuntimeById(id, { runtimeDetails }, state);
const updatedState = {
isConnecting: false,
isConnectionFailed: false,
isConnectionNotResponding: false,
runtimeDetails,
};
return _updateRuntimeById(id, updatedState, state);
}
case CONNECT_RUNTIME_FAILURE: {
const { id } = action;
const updatedState = {
isConnecting: false,
isConnectionFailed: true,
isConnectionNotResponding: false,
};
return _updateRuntimeById(id, updatedState, state);
}
case DISCONNECT_RUNTIME_SUCCESS: {

View File

@ -115,6 +115,17 @@ const runtime = {
// unavailable on this-firefox runtime
extra: PropTypes.shape(runtimeExtra),
// this flag will be true when start to connect to the runtime, will be false after
// connected or has failures.
isConnecting: PropTypes.bool.isRequired,
// this flag will be true when the connection failed.
isConnectionFailed: PropTypes.bool.isRequired,
// will be true if connecting to runtime is taking time, will be false after connecting
// or failing.
isConnectionNotResponding: PropTypes.bool.isRequired,
// unknown runtimes are placeholders for devices where the runtime has not been started
// yet. For instance an ADB device connected without a compatible runtime running.
isUnknown: PropTypes.bool.isRequired,

View File

@ -86,6 +86,7 @@ skip-if = debug || asan || serviceworker_e10s # Frequent intermittent failures,
[browser_aboutdebugging_serviceworker_timeout.js]
skip-if = debug || asan # Frequent intermittent failures, Bug 1522800
[browser_aboutdebugging_serviceworker_unregister.js]
[browser_aboutdebugging_sidebar_connection_state.js]
[browser_aboutdebugging_sidebar_network_runtimes.js]
[browser_aboutdebugging_sidebar_usb_runtime.js]
[browser_aboutdebugging_sidebar_usb_runtime_connect.js]

View File

@ -0,0 +1,78 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const RUNTIME_ID = "test-runtime-id";
const RUNTIME_NAME = "test runtime name";
const RUNTIME_DEVICE_NAME = "test device name";
const RUNTIME_SHORT_NAME = "test short name";
// Test following connection state tests.
// * Connect button label and state will change during connecting.
// * Show error message if connection failed.
// * Show warninng if connection has been taken time.
add_task(async function() {
const mocks = new Mocks();
const { document, tab } = await openAboutDebugging();
mocks.createUSBRuntime(RUNTIME_ID, {
name: RUNTIME_NAME,
deviceName: RUNTIME_DEVICE_NAME,
shortName: RUNTIME_SHORT_NAME,
});
mocks.emitUSBUpdate();
info("Wait until the USB sidebar item appears");
await waitUntil(() => findSidebarItemByText(RUNTIME_DEVICE_NAME, document));
const usbRuntimeSidebarItem = findSidebarItemByText(RUNTIME_DEVICE_NAME, document);
const connectButton = usbRuntimeSidebarItem.querySelector(".js-connect-button");
info("Simulate to happen connection error");
mocks.runtimeClientFactoryMock.createClientForRuntime = async (runtime) => {
throw new Error("Dummy connection error");
};
info("Check whether the error message displayed after clicking connect button");
connectButton.click();
await waitUntil(() => document.querySelector(".qa-connection-error"));
ok(true, "Error message displays when connection failed");
info("Simulate to wait for the connection prompt on remote runtime");
let resumeConnection;
const resumeConnectionPromise = new Promise(r => {
resumeConnection = r;
});
mocks.runtimeClientFactoryMock.createClientForRuntime = async (runtime) => {
await resumeConnectionPromise;
return mocks._clients[runtime.type][runtime.id];
};
info("Click on the connect button and wait until it disappears");
connectButton.click();
info("Check whether a warning of connection not responding displays after 3sec");
await waitUntil(() => document.querySelector(".qa-connection-not-responding"));
ok(document.querySelector(".qa-connection-not-responding"),
"A warning of connection not responding displays");
ok(connectButton.disabled, "State of the connect button displays");
ok(connectButton.textContent.startsWith("Connecting"),
"Label of the connect button changes");
ok(!document.querySelector(".qa-connection-error"), "Error message disappears");
info("Unblock the connection and check the message and connect button disappear");
resumeConnection();
await waitUntil(() => !usbRuntimeSidebarItem.querySelector(".js-connect-button"));
ok(!document.querySelector(".qa-connection-error"), "Error disappears");
ok(!document.querySelector(".qa-connection-not-responding"), "Warning disappears");
info("Remove a USB runtime");
mocks.removeUSBRuntime(RUNTIME_ID);
mocks.emitUSBUpdate();
info("Wait until the USB sidebar item disappears");
await waitUntil(() => !findSidebarItemByText(RUNTIME_DEVICE_NAME, document) &&
!findSidebarItemByText(RUNTIME_SHORT_NAME, document));
await removeTab(tab);
});

View File

@ -93,7 +93,8 @@ function getElements(grip, mode) {
attributes,
nodeName,
isAfterPseudoElement,
isBeforePseudoElement
isBeforePseudoElement,
isMarkerPseudoElement
} = grip.preview;
const nodeNameElement = span(
{
@ -102,13 +103,16 @@ function getElements(grip, mode) {
nodeName
);
if (isAfterPseudoElement || isBeforePseudoElement) {
return [
span(
{ className: "attrName" },
`::${isAfterPseudoElement ? "after" : "before"}`
)
];
let pseudoNodeName;
if (isAfterPseudoElement) {
pseudoNodeName = "after";
} else if (isBeforePseudoElement) {
pseudoNodeName = "before";
} else if (isMarkerPseudoElement) {
pseudoNodeName = "marker";
}
if (pseudoNodeName) {
return [span({ className: "attrName" }, `::${pseudoNodeName}`)];
}
if (mode === MODE.TINY) {

View File

@ -248,6 +248,19 @@ stubs.set("NodeWithLongStringAttribute", {
}
});
stubs.set("MarkerPseudoElement", {
type: "object",
actor: "server1.conn1.child1/obj26",
preview: {
kind: "DOMNode",
nodeType: 1,
nodeName: "_moz_generated_content_marker",
attributes: {},
attributesLength: 0,
isMarkerPseudoElement: true
}
});
stubs.set("BeforePseudoElement", {
type: "object",
actor: "server1.conn1.child1/obj27",

View File

@ -465,6 +465,35 @@ describe("ElementNode - Element attribute cropping", () => {
});
});
describe("ElementNode - : Marker pseudo element", () => {
const stub = stubs.get("MarkerPseudoElement");
it("selects ElementNode Rep", () => {
expect(getRep(stub)).toBe(ElementNode.rep);
});
it("renders with expected text content", () => {
const renderedComponent = shallow(
ElementNode.rep({
object: stub
})
);
expect(renderedComponent.text()).toEqual("::marker");
});
it("renders with expected text content in tiny mode", () => {
const renderedComponent = shallow(
ElementNode.rep({
object: stub,
mode: MODE.TINY
})
);
expect(renderedComponent.text()).toEqual("::marker");
});
});
describe("ElementNode - : Before pseudo element", () => {
const stub = stubs.get("BeforePseudoElement");

View File

@ -101,7 +101,7 @@
.expression-container:hover .expression-container__close-btn,
.expression-container__close-btn:focus-within {
top: calc(50% - 8px);
top: 0;
}
[dir="ltr"] .expression-container__close-btn {

View File

@ -428,8 +428,12 @@ HTMLBreadcrumbs.prototype = {
*/
prettyPrintNodeAsText: function(node) {
let text = node.isShadowRoot ? SHADOW_ROOT_TAGNAME : node.displayName;
if (node.isPseudoElement) {
text = node.isBeforePseudoElement ? "::before" : "::after";
if (node.isMarkerPseudoElement) {
text = "::marker";
} else if (node.isBeforePseudoElement) {
text = "::before";
} else if (node.isAfterPseudoElement) {
text = "::after";
}
if (node.id) {
@ -472,8 +476,12 @@ HTMLBreadcrumbs.prototype = {
pseudosLabel.className = "breadcrumbs-widget-item-pseudo-classes plain";
let tagText = node.isShadowRoot ? SHADOW_ROOT_TAGNAME : node.displayName;
if (node.isPseudoElement) {
tagText = node.isBeforePseudoElement ? "::before" : "::after";
if (node.isMarkerPseudoElement) {
tagText = "::marker";
} else if (node.isBeforePseudoElement) {
tagText = "::before";
} else if (node.isAfterPseudoElement) {
tagText = "::after";
}
let idText = node.id ? ("#" + node.id) : "";
let classesText = "";

View File

@ -2180,13 +2180,17 @@ MarkupView.prototype = {
nextSibling = target.parentNode.container.node;
}
if (nextSibling && nextSibling.isBeforePseudoElement) {
nextSibling = target.parentNode.parentNode.children[1].container.node;
if (nextSibling) {
while (
nextSibling.isMarkerPseudoElement || nextSibling.isBeforePseudoElement
) {
nextSibling = this.getContainer(nextSibling).elt.nextSibling.container.node;
}
if (nextSibling && nextSibling.isAfterPseudoElement) {
if (nextSibling.isAfterPseudoElement) {
parent = target.parentNode.container.node.parentNode();
nextSibling = null;
}
}
if (parent.nodeType !== nodeConstants.ELEMENT_NODE) {
return null;

View File

@ -115,6 +115,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) || (os == "win" && processor ==
[browser_markup_display_node_02.js]
[browser_markup_dragdrop_autoscroll_01.js]
[browser_markup_dragdrop_autoscroll_02.js]
[browser_markup_dragdrop_before_marker_pseudo.js]
[browser_markup_dragdrop_distance.js]
[browser_markup_dragdrop_draggable.js]
[browser_markup_dragdrop_dragRootNode.js]
@ -201,6 +202,7 @@ subsuite = clipboard
[browser_markup_shadowdom_delete.js]
[browser_markup_shadowdom_dynamic.js]
[browser_markup_shadowdom_hover.js]
[browser_markup_shadowdom_marker_and_before_pseudos.js]
[browser_markup_shadowdom_maxchildren.js]
[browser_markup_shadowdom_mutations_shadow.js]
[browser_markup_shadowdom_navigation.js]

View File

@ -14,9 +14,9 @@ add_task(async function() {
data:text/html;charset=utf-8,
<h1>foo</h1>
<span>bar</span>
<ul>
<li></li>
</ul>`);
<dl>
<dt></dt>
</dl>`);
const markup = inspector.markup;
const doc = markup.doc;
const win = doc.defaultView;
@ -25,7 +25,7 @@ add_task(async function() {
const bodyContainer = await getContainerForSelector("body", inspector);
const spanContainer = await getContainerForSelector("span", inspector);
const headerContainer = await getContainerForSelector("h1", inspector);
const listContainer = await getContainerForSelector("ul", inspector);
const listContainer = await getContainerForSelector("dl", inspector);
// Focus on the tree element.
rootElt.focus();
@ -71,7 +71,7 @@ add_task(async function() {
"Closed tree item should have aria-expanded unset");
info("Selecting and expanding list container");
await selectNode("ul", inspector);
await selectNode("dl", inspector);
EventUtils.synthesizeKey("VK_RIGHT", {}, win);
await waitForMultipleChildrenUpdates(inspector);
@ -80,7 +80,7 @@ add_task(async function() {
"Active descendant should not be set to list container tagLine");
is(listContainer.tagLine.getAttribute("aria-expanded"), "true",
"Open tree item should have aria-expanded set");
const listItemContainer = await getContainerForSelector("li", inspector);
const listItemContainer = await getContainerForSelector("dt", inspector);
is(listItemContainer.tagLine.getAttribute("aria-level"),
TOP_CONTAINER_LEVEL + 1,
"Grand child container tagLine should have nested level up to date");

View File

@ -0,0 +1,62 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test drag and dropping a node before a ::marker pseudo.
const TEST_URL = URL_ROOT + "doc_markup_dragdrop.html";
add_task(async function() {
const {inspector} = await openInspectorForURL(TEST_URL);
info("Expand #list node");
const parentFront = await getNodeFront("#list", inspector);
await inspector.markup.expandNode(parentFront.parentNode());
await inspector.markup.expandNode(parentFront);
await waitForMultipleChildrenUpdates(inspector);
info("Scroll #list into view");
const parentContainer = await getContainerForNodeFront(parentFront, inspector);
parentContainer.elt.scrollIntoView(true);
info("Test placing an element before a ::marker psuedo");
await moveElementBeforeMarker("#last-list-child", parentFront, inspector);
const childNodes = await getChildrenOf(parentFront, inspector);
is(childNodes[0], "_moz_generated_content_marker",
"::marker is still the first child of #list");
is(childNodes[1], "last-list-child",
"#last-list-child is now the second child of #list");
is(childNodes[2], "first-list-child",
"#first-list-child is now the last child of #list");
});
async function moveElementBeforeMarker(selector, parentFront, inspector) {
info(`Placing ${selector} before its parent's ::marker`);
const container = await getContainerForSelector(selector, inspector);
const parentContainer = await getContainerForNodeFront(parentFront, inspector);
const offsetY = (parentContainer.tagLine.offsetTop +
parentContainer.tagLine.offsetHeight) - container.tagLine.offsetTop;
const onMutated = inspector.once("markupmutation");
const uiUpdate = inspector.once("inspector-updated");
await simulateNodeDragAndDrop(inspector, selector, 0, offsetY);
const mutations = await onMutated;
await uiUpdate;
is(mutations.length, 2, "2 mutations were received");
}
async function getChildrenOf(parentFront, {walker}) {
const {nodes} = await walker.children(parentFront);
return nodes.map(node => {
if (node.isMarkerPseudoElement) {
return node.displayName;
}
return node.id;
});
}

View File

@ -0,0 +1,112 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
requestLongerTimeout(1);
// Test a few static pages using webcomponents with ::marker and ::before
// pseudos and check that they are displayed as expected in the markup view.
const TEST_DATA = [
{
// Test that ::before on an empty shadow host is displayed when the host
// has a ::marker.
title: "::before after ::marker, empty node",
url: `data:text/html;charset=utf-8,
<style>
test-component { display: list-item; }
test-component::before { content: "before-host" }
</style>
<test-component></test-component>
<script>
'use strict';
customElements.define('test-component', class extends HTMLElement {
constructor() {
super();
let shadowRoot = this.attachShadow({mode: "#MODE#"});
}
});
</script>`,
tree: `
test-component
#shadow-root
::marker
::before`,
}, {
// Test ::before on a shadow host with content is displayed when the host
// has a ::marker.
title: "::before after ::marker, non-empty node",
url: `data:text/html;charset=utf-8,
<style>
test-component { display: list-item }
test-component::before { content: "before-host" }
</style>
<test-component>
<div class="light-dom"></div>
</test-component>
<script>
"use strict";
customElements.define("test-component", class extends HTMLElement {
constructor() {
super();
let shadowRoot = this.attachShadow({mode: "#MODE#"});
shadowRoot.innerHTML = "<slot>default content</slot>";
}
});
</script>`,
tree: `
test-component
#shadow-root
slot
div!slotted
::marker
::before
class="light-dom"`,
}, {
// Test just ::marker on a shadow host
title: "just ::marker, no ::before",
url: `data:text/html;charset=utf-8,
<style>
test-component { display: list-item }
</style>
<test-component></test-component>
<script>
"use strict";
customElements.define("test-component", class extends HTMLElement {
constructor() {
super();
let shadowRoot = this.attachShadow({mode: "#MODE#"});
}
});
</script>`,
tree: `
test-component
#shadow-root
::marker`,
},
];
for (const {url, tree, title} of TEST_DATA) {
// Test each configuration in both open and closed modes
add_task(async function() {
info(`Testing: [${title}] in OPEN mode`);
const {inspector, tab} = await openInspectorForURL(url.replace(/#MODE#/g, "open"));
await assertMarkupViewAsTree(tree, "test-component", inspector);
await removeTab(tab);
});
add_task(async function() {
info(`Testing: [${title}] in CLOSED mode`);
const {inspector, tab} = await openInspectorForURL(url.replace(/#MODE#/g, "closed"));
await assertMarkupViewAsTree(tree, "test-component", inspector);
await removeTab(tab);
});
}

View File

@ -25,6 +25,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=858038
<div slot="slot1" class="slotted2">slot1-2</div>
</test-component>
<ol>
<li id="list"><span id="first-list-child"
>List item start</span><span id="last-list-child"
>List item end</span></li>
</ol>
<script>
"use strict";
customElements.define("test-component", class extends HTMLElement {

View File

@ -16,7 +16,13 @@ function ReadOnlyEditor(container, node) {
if (node.isPseudoElement) {
this.tag.classList.add("theme-fg-color3");
this.tag.textContent = node.isBeforePseudoElement ? "::before" : "::after";
if (node.isMarkerPseudoElement) {
this.tag.textContent = "::marker";
} else if (node.isBeforePseudoElement) {
this.tag.textContent = "::before";
} else if (node.isAfterPseudoElement) {
this.tag.textContent = "::after";
}
} else if (node.nodeType == nodeConstants.DOCUMENT_TYPE_NODE) {
this.elt.classList.add("comment", "doctype");
this.tag.textContent = node.doctypeString;

View File

@ -21,6 +21,7 @@ add_task(async function() {
await testBottomLeft(inspector, view);
await testParagraph(inspector, view);
await testBody(inspector, view);
await testList(inspector, view);
});
async function testTopLeft(inspector, view) {
@ -31,6 +32,7 @@ async function testTopLeft(inspector, view) {
firstLineRulesNb: 2,
firstLetterRulesNb: 1,
selectionRulesNb: 1,
markerRulesNb: 0,
afterRulesNb: 1,
beforeRulesNb: 2,
}
@ -123,6 +125,7 @@ async function testTopRight(inspector, view) {
firstLineRulesNb: 1,
firstLetterRulesNb: 1,
selectionRulesNb: 0,
markerRulesNb: 0,
beforeRulesNb: 2,
afterRulesNb: 1,
});
@ -145,6 +148,7 @@ async function testBottomRight(inspector, view) {
firstLineRulesNb: 1,
firstLetterRulesNb: 1,
selectionRulesNb: 0,
markerRulesNb: 0,
beforeRulesNb: 3,
afterRulesNb: 1,
});
@ -156,6 +160,7 @@ async function testBottomLeft(inspector, view) {
firstLineRulesNb: 1,
firstLetterRulesNb: 1,
selectionRulesNb: 0,
markerRulesNb: 0,
beforeRulesNb: 2,
afterRulesNb: 1,
});
@ -168,6 +173,7 @@ async function testParagraph(inspector, view) {
firstLineRulesNb: 1,
firstLetterRulesNb: 1,
selectionRulesNb: 2,
markerRulesNb: 0,
beforeRulesNb: 0,
afterRulesNb: 0,
});
@ -197,6 +203,20 @@ async function testBody(inspector, view) {
is(gutters.length, 0, "There are no gutter headings");
}
async function testList(inspector, view) {
await assertPseudoElementRulesNumbers("#list", inspector, view, {
elementRulesNb: 4,
firstLineRulesNb: 1,
firstLetterRulesNb: 1,
selectionRulesNb: 0,
markerRulesNb: 1,
beforeRulesNb: 1,
afterRulesNb: 1,
});
assertGutters(view);
}
function convertTextPropsToString(textProps) {
return textProps.map(t => t.name + ": " + t.value).join("; ");
}
@ -218,6 +238,8 @@ async function assertPseudoElementRulesNumbers(selector, inspector, view, ruleNb
rule.pseudoElement === ":first-letter"),
selectionRules: elementStyle.rules.filter(rule =>
rule.pseudoElement === ":selection"),
markerRules: elementStyle.rules.filter(rule =>
rule.pseudoElement === ":marker"),
beforeRules: elementStyle.rules.filter(rule =>
rule.pseudoElement === ":before"),
afterRules: elementStyle.rules.filter(rule =>
@ -232,6 +254,8 @@ async function assertPseudoElementRulesNumbers(selector, inspector, view, ruleNb
selector + " has the correct number of :first-letter rules");
is(rules.selectionRules.length, ruleNbs.selectionRulesNb,
selector + " has the correct number of :selection rules");
is(rules.markerRules.length, ruleNbs.markerRulesNb,
selector + " has the correct number of :marker rules");
is(rules.beforeRules.length, ruleNbs.beforeRulesNb,
selector + " has the correct number of :before rules");
is(rules.afterRules.length, ruleNbs.afterRulesNb,

View File

@ -26,4 +26,18 @@ add_task(async function() {
is(afterElement.tagName, "_moz_generated_content_after",
"tag name is correct");
await selectNode(afterElement, inspector);
const listNode = await getNodeFront("#list", inspector);
const listChildren = await inspector.markup.walker.children(listNode);
is(listChildren.nodes.length, 4, "<li> has correct number of children");
const markerElement = listChildren.nodes[0];
is(markerElement.tagName, "_moz_generated_content_marker",
"tag name is correct");
await selectNode(markerElement, inspector);
const listBeforeElement = listChildren.nodes[1];
is(listBeforeElement.tagName, "_moz_generated_content_before",
"tag name is correct");
await selectNode(listBeforeElement, inspector);
});

View File

@ -106,6 +106,10 @@ p:first-letter {
left:0;
}
#list::marker {
color: purple;
}
</style>
</head>
<body>
@ -127,5 +131,9 @@ p:first-letter {
<p>Bottom Left<br />Position</p>
</div>
<ol>
<li id="list" class="box">List element</li>
</ol>
</body>
</html>

View File

@ -139,10 +139,15 @@ function getSelectorFromGrip(grip) {
nodeName,
isAfterPseudoElement,
isBeforePseudoElement,
isMarkerPseudoElement,
} = grip.preview;
if (isAfterPseudoElement || isBeforePseudoElement) {
return `::${isAfterPseudoElement ? "after" : "before"}`;
if (isAfterPseudoElement) {
return "::after";
} else if (isBeforePseudoElement) {
return "::before";
} else if (isMarkerPseudoElement) {
return "::marker";
}
let selector = nodeName;
@ -200,6 +205,7 @@ function translateNodeFrontToGrip(nodeFront) {
attributesLength: attributes.length,
isAfterPseudoElement: nodeFront.isAfterPseudoElement,
isBeforePseudoElement: nodeFront.isBeforePseudoElement,
isMarkerPseudoElement: nodeFront.isMarkerPseudoElement,
// All the grid containers are assumed to be in the DOM tree.
isConnected: true,
// nodeName is already lowerCased in Node grips

View File

@ -46,6 +46,16 @@ about-debugging-sidebar-no-devices = No devices discovered
# Clicking on the button will attempt to connect to the runtime.
about-debugging-sidebar-item-connect-button = Connect
# Text displayed in buttons found in sidebar items when the runtime is connecting.
about-debugging-sidebar-item-connect-button-connecting = Connecting…
# Text displayed in buttons found in sidebar items when the connection failed.
about-debugging-sidebar-item-connect-button-connection-failed = Connection failed
# Text displayed in connection warning on sidebar item of the runtime when connecting to
# the runtime is taking too much time.
about-debugging-sidebar-item-connect-button-connection-not-responding = Connection still pending, check for messages on the target browser
# Temporary text displayed in sidebar items representing remote runtimes after
# successfully connecting to them. Temporary UI, do not localize.
about-debugging-sidebar-item-connected-label = Connected

View File

@ -63,6 +63,10 @@ const SUMMARY_REFERRER_POLICY = L10N.getStr("netmonitor.summary.referrerPolicy")
/**
* Headers panel component
* Lists basic information about the request
*
* In http/2 all response headers are in small case.
* See: https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor/request_details#Headers
* RFC: https://tools.ietf.org/html/rfc7540#section-8.1.2
*/
class HeadersPanel extends Component {
static get propTypes() {

View File

@ -187,7 +187,6 @@ skip-if = os == 'win' # bug 1391264
[browser_net_set-cookie-same-site.js]
[browser_net_simple-request-data.js]
[browser_net_simple-request-details.js]
skip-if = true # Bug 1258809
[browser_net_simple-request.js]
[browser_net_sort-01.js]
[browser_net_sort-02.js]

View File

@ -13,14 +13,13 @@ add_task(async function() {
const { tab, monitor } = await initNetMonitor(SIMPLE_SJS);
info("Starting test... ");
const { document, store, windowRequire, NetMonitorView } = monitor.panelWin;
const { document, store, windowRequire } = monitor.panelWin;
const Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
const { EVENTS } = windowRequire("devtools/client/netmonitor/src/constants");
const { PANELS } = windowRequire("devtools/client/netmonitor/src/constants");
const {
getSelectedRequest,
getSortedRequests,
} = windowRequire("devtools/client/netmonitor/src/selectors/index");
const Editor = require("devtools/client/shared/sourceeditor/editor");
store.dispatch(Actions.batchEnable(false));
@ -35,6 +34,8 @@ add_task(async function() {
is(!!document.querySelector(".network-details-panel"), false,
"The network details panel should still be hidden after first request.");
const waitForHeaders = waitForDOM(document, ".headers-overview");
store.dispatch(Actions.toggleNetworkDetails());
isnot(getSelectedRequest(store.getState()), undefined,
@ -44,11 +45,13 @@ add_task(async function() {
is(!!document.querySelector(".network-details-panel"), true,
"The network details panel should not be hidden after toggle button was pressed.");
testHeadersTab();
await waitForHeaders;
await testHeadersTab();
await testCookiesTab();
testParamsTab();
await testParamsTab();
await testResponseTab();
testTimingsTab();
await testTimingsTab();
return teardown(monitor);
function getSelectedIndex(state) {
@ -58,215 +61,195 @@ add_task(async function() {
return getSortedRequests(state).findIndex(r => r.id === state.requests.selectedId);
}
function testHeadersTab() {
const tabEl = document.querySelectorAll("#details-pane tab")[0];
const tabpanel = document.querySelectorAll("#details-pane tabpanel")[0];
async function testHeadersTab() {
const tabEl = document.querySelectorAll(".network-details-panel .tabs-menu a")[0];
const tabpanel = document.querySelector(".network-details-panel .tab-panel");
is(tabEl.getAttribute("selected"), "true",
is(tabEl.getAttribute("aria-selected"), "true",
"The headers tab in the network details pane should be selected.");
is(tabpanel.querySelector("#headers-summary-url-value").getAttribute("value"),
// Request URL
is(tabpanel.querySelectorAll(".tabpanel-summary-value")[0].innerText,
SIMPLE_SJS, "The url summary value is incorrect.");
is(tabpanel.querySelector("#headers-summary-url-value").getAttribute("tooltiptext"),
SIMPLE_SJS, "The url summary tooltiptext is incorrect.");
is(tabpanel.querySelector("#headers-summary-method-value").getAttribute("value"),
// Request method
is(tabpanel.querySelectorAll(".tabpanel-summary-value")[1].innerText,
"GET", "The method summary value is incorrect.");
is(tabpanel.querySelector("#headers-summary-address-value").getAttribute("value"),
// Remote address
is(tabpanel.querySelectorAll(".tabpanel-summary-value")[2].innerText,
"127.0.0.1:8888", "The remote address summary value is incorrect.");
is(tabpanel.querySelector("#headers-summary-status-circle").getAttribute("data-code"),
// Status code
is(tabpanel.querySelector(".requests-list-status-code").innerText,
"200", "The status summary code is incorrect.");
is(tabpanel.querySelector("#headers-summary-status-value").getAttribute("value"),
"200 Och Aye", "The status summary value is incorrect.");
is(tabpanel.querySelector(".status-text").getAttribute("value"),
"Och Aye", "The status summary value is incorrect.");
// Version
is(tabpanel.querySelectorAll(".tabpanel-summary-value")[4].innerText,
"HTTP/1.1", "The HTTP version is incorrect.");
is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
await waitForRequestData(store, ["requestHeaders", "responseHeaders"]);
is(tabpanel.querySelectorAll(".treeTable tbody .tree-section").length, 2,
"There should be 2 header scopes displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".variable-or-property").length, 19,
"There should be 19 header values displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
"The empty notice should not be displayed in this tabpanel.");
is(tabpanel.querySelectorAll(":not(.tree-section) > .treeLabelCell").length,
23, "There should be 23 header values displayed in this tabpanel.");
const responseScope = tabpanel.querySelectorAll(".variables-view-scope")[0];
const requestScope = tabpanel.querySelectorAll(".variables-view-scope")[1];
const headersTable = tabpanel.querySelector(".treeTable tbody");
const responseScope = headersTable.querySelectorAll("tr[id^='/Response headers']");
const requestScope = headersTable.querySelectorAll("tr[id^='/Request headers']");
is(responseScope.querySelector(".name").getAttribute("value"),
L10N.getStr("responseHeaders") + " (" +
L10N.getFormatStr("networkMenu.sizeKB",
L10N.numberWithDecimals(330 / 1024, 3)) + ")",
ok(headersTable.querySelectorAll(".tree-section .treeLabel")[0].innerHTML
.match(new RegExp(L10N.getStr("responseHeaders") + " \\([0-9]+ .+\\)")),
"The response headers scope doesn't have the correct title.");
ok(requestScope.querySelector(".name").getAttribute("value").includes(
L10N.getStr("requestHeaders") + " (0"),
ok(headersTable.querySelectorAll(".tree-section .treeLabel")[1].innerHTML.includes(
L10N.getStr("requestHeaders") + " ("),
"The request headers scope doesn't have the correct title.");
// Can't test for full request headers title because the size may
// vary across platforms ("User-Agent" header differs). We're pretty
// sure it's smaller than 1 MB though, so it starts with a 0.
is(responseScope.querySelectorAll(".variables-view-variable .name")[0]
.getAttribute("value"),
"Cache-Control", "The first response header name was incorrect.");
is(responseScope.querySelectorAll(".variables-view-variable .value")[0]
.getAttribute("value"),
"\"no-cache, no-store, must-revalidate\"",
"The first response header value was incorrect.");
is(responseScope.querySelectorAll(".variables-view-variable .name")[1]
.getAttribute("value"),
"Connection", "The second response header name was incorrect.");
is(responseScope.querySelectorAll(".variables-view-variable .value")[1]
.getAttribute("value"),
"\"close\"", "The second response header value was incorrect.");
is(responseScope.querySelectorAll(".variables-view-variable .name")[2]
.getAttribute("value"),
"Content-Length", "The third response header name was incorrect.");
is(responseScope.querySelectorAll(".variables-view-variable .value")[2]
.getAttribute("value"),
"\"12\"", "The third response header value was incorrect.");
is(responseScope.querySelectorAll(".variables-view-variable .name")[3]
.getAttribute("value"),
"Content-Type", "The fourth response header name was incorrect.");
is(responseScope.querySelectorAll(".variables-view-variable .value")[3]
.getAttribute("value"),
"\"text/plain; charset=utf-8\"", "The fourth response header value was incorrect.");
is(responseScope.querySelectorAll(".variables-view-variable .name")[9]
.getAttribute("value"),
"foo-bar", "The last response header name was incorrect.");
is(responseScope.querySelectorAll(".variables-view-variable .value")[9]
.getAttribute("value"),
"\"baz\"", "The last response header value was incorrect.");
const responseHeaders = [
{
name: "cache-control",
value: "no-cache, no-store, must-revalidate",
pos: "first",
index: 1,
},
{
name: "connection",
value: "close",
pos: "second",
index: 2,
},
{
name: "content-length",
value: "12",
pos: "third",
index: 3,
},
{
name: "content-type",
value: "text/plain; charset=utf-8",
pos: "fourth",
index: 4,
},
{
name: "foo-bar",
value: "baz",
pos: "seventh",
index: 7,
},
];
responseHeaders.forEach((header) => {
is(responseScope[header.index].querySelector(".treeLabel").innerHTML,
header.name, `The ${header.pos} response header name was incorrect.`);
is(responseScope[header.index].querySelector(".objectBox").innerHTML,
header.value, `The ${header.pos} response header value was incorrect.`);
});
is(requestScope.querySelectorAll(".variables-view-variable .name")[0]
.getAttribute("value"),
"Host", "The first request header name was incorrect.");
is(requestScope.querySelectorAll(".variables-view-variable .value")[0]
.getAttribute("value"),
"\"example.com\"", "The first request header value was incorrect.");
is(requestScope.querySelectorAll(".variables-view-variable .name")[6]
.getAttribute("value"),
"Connection", "The ante-penultimate request header name was incorrect.");
is(requestScope.querySelectorAll(".variables-view-variable .value")[6]
.getAttribute("value"),
"\"keep-alive\"", "The ante-penultimate request header value was incorrect.");
is(requestScope.querySelectorAll(".variables-view-variable .name")[7]
.getAttribute("value"),
"Pragma", "The penultimate request header name was incorrect.");
is(requestScope.querySelectorAll(".variables-view-variable .value")[7]
.getAttribute("value"),
"\"no-cache\"", "The penultimate request header value was incorrect.");
is(requestScope.querySelectorAll(".variables-view-variable .name")[8]
.getAttribute("value"),
"Cache-Control", "The last request header name was incorrect.");
is(requestScope.querySelectorAll(".variables-view-variable .value")[8]
.getAttribute("value"),
"\"no-cache\"", "The last request header value was incorrect.");
const requestHeaders = [
{
name: "Cache-Control",
value: "no-cache",
pos: "fourth",
index: 4,
},
{
name: "Connection",
value: "keep-alive",
pos: "fifth",
index: 5,
},
{
name: "Host",
value: "example.com",
pos: "seventh",
index: 7,
},
{
name: "Pragma",
value: "no-cache",
pos: "eighth",
index: 8,
},
];
requestHeaders.forEach((header) => {
is(requestScope[header.index].querySelector(".treeLabel").innerHTML,
header.name, `The ${header.pos} request header name was incorrect.`);
is(requestScope[header.index].querySelector(".objectBox").innerHTML,
header.value, `The ${header.pos} request header value was incorrect.`);
});
}
async function testCookiesTab() {
const onEvent = monitor.panelWin.api.once(EVENTS.TAB_UPDATED);
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll("#details-pane tab")[1]);
await onEvent;
const tabpanel = await selectTab(PANELS.COOKIES, 1);
const tabEl = document.querySelectorAll("#details-pane tab")[1];
const tabpanel = document.querySelectorAll("#details-pane tabpanel")[1];
is(tabEl.getAttribute("selected"), "true",
"The cookies tab in the network details pane should be selected.");
is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
const cookieTable = tabpanel.querySelector(".treeTable tbody");
is(cookieTable.querySelectorAll(".tree-section").length, 2,
"There should be 2 cookie scopes displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".variable-or-property").length, 6,
"There should be 6 cookie values displayed in this tabpanel.");
// 2 Cookies in response - 1 httpOnly and 1 value for each cookie - total 6
is(cookieTable.querySelectorAll("tr[id^='/Response cookies/'").length, 6,
"There should be 6 rows displayed in response cookies table");
is(cookieTable.querySelectorAll("tr[id^='/Request cookies/'").length, 2,
"There should be 2 cookie values displayed in request cookies table.");
}
function testParamsTab() {
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll("#details-pane tab")[2]);
async function testParamsTab() {
const tabpanel = await selectTab(PANELS.PARAMS, 2);
const tabEl = document.querySelectorAll("#details-pane tab")[2];
const tabpanel = document.querySelectorAll("#details-pane tabpanel")[2];
is(tabEl.getAttribute("selected"), "true",
"The params tab in the network details pane should be selected.");
is(tabpanel.querySelectorAll(".variables-view-scope").length, 0,
is(tabpanel.querySelectorAll(".panel-container").length, 0,
"There should be no param scopes displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".variable-or-property").length, 0,
"There should be no param values displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 1,
is(tabpanel.querySelectorAll(".empty-notice").length, 1,
"The empty notice should be displayed in this tabpanel.");
is(tabpanel.querySelector("#request-params-box")
.hasAttribute("hidden"), false,
"The request params box should not be hidden.");
is(tabpanel.querySelector("#request-post-data-textarea-box")
.hasAttribute("hidden"), true,
"The request post data textarea box should be hidden.");
}
async function testResponseTab() {
const onEvent = monitor.panelWin.api.once(EVENTS.TAB_UPDATED);
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll("#details-pane tab")[3]);
await onEvent;
const tabpanel = await selectTab(PANELS.RESPONSE, 3);
await waitForDOM(document, ".treeTable tbody");
const tabEl = document.querySelectorAll("#details-pane tab")[3];
const tabpanel = document.querySelectorAll("#details-pane tabpanel")[3];
is(tabEl.getAttribute("selected"), "true",
"The response tab in the network details pane should be selected.");
is(tabpanel.querySelector("#response-content-info-header")
.hasAttribute("hidden"), true,
"The response info header should be hidden.");
is(tabpanel.querySelector("#response-content-json-box")
.hasAttribute("hidden"), true,
"The response content json box should be hidden.");
is(tabpanel.querySelector("#response-content-textarea-box")
.hasAttribute("hidden"), false,
"The response content textarea box should not be hidden.");
is(tabpanel.querySelector("#response-content-image-box")
.hasAttribute("hidden"), true,
"The response content image box should be hidden.");
const editor = await NetMonitorView.editor("#response-content-textarea");
is(editor.getText(), "Hello world!",
"The text shown in the source editor is incorrect.");
is(editor.getMode(), Editor.modes.text,
"The mode active in the source editor is incorrect.");
const responseTable = tabpanel.querySelector(".treeTable tbody");
is(responseTable.querySelectorAll(".tree-section").length, 1,
"There should be 1 response scope displayed in this tabpanel.");
is(responseTable.querySelectorAll(".editor-row-container").length, 1,
"The response payload tab should be open initially.");
}
function testTimingsTab() {
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll("#details-pane tab")[4]);
async function testTimingsTab() {
const tabpanel = await selectTab(PANELS.TIMINGS, 4);
const tabEl = document.querySelectorAll("#details-pane tab")[4];
const tabpanel = document.querySelectorAll("#details-pane tabpanel")[4];
const displayFormat = new RegExp(/[0-9]+ ms$/);
const propsToVerify = [
"blocked",
"dns",
"connect",
"ssl",
"send",
"wait",
"receive",
];
is(tabEl.getAttribute("selected"), "true",
"The timings tab in the network details pane should be selected.");
// To ensure that test case for a new property is written, otherwise this
// test will fail
is(tabpanel.querySelectorAll(".tabpanel-summary-container").length,
propsToVerify.length,
`There should be exactly ${propsToVerify.length} values
displayed in this tabpanel`);
ok(tabpanel.querySelector("#timings-summary-blocked .requests-list-timings-total")
.getAttribute("value").match(/[0-9]+/),
"The blocked timing info does not appear to be correct.");
propsToVerify.forEach((propName) => {
ok(tabpanel.querySelector(`#timings-summary-${propName}
.requests-list-timings-total`)
.innerHTML.match(displayFormat),
`The ${propName} timing info does not appear to be correct.`);
});
}
ok(tabpanel.querySelector("#timings-summary-dns .requests-list-timings-total")
.getAttribute("value").match(/[0-9]+/),
"The dns timing info does not appear to be correct.");
async function selectTab(tabName, pos) {
const tabEl = document.querySelectorAll(".network-details-panel .tabs-menu a")[pos];
ok(tabpanel.querySelector("#timings-summary-connect .requests-list-timings-total")
.getAttribute("value").match(/[0-9]+/),
"The connect timing info does not appear to be correct.");
const onPanelOpen = waitForDOM(document, `#${tabName}-panel`);
EventUtils.sendMouseEvent({ type: "click" }, tabEl);
await onPanelOpen;
ok(tabpanel.querySelector("#timings-summary-send .requests-list-timings-total")
.getAttribute("value").match(/[0-9]+/),
"The send timing info does not appear to be correct.");
is(tabEl.getAttribute("aria-selected"), "true",
`The ${tabName} tab in the network details pane should be selected.`);
ok(tabpanel.querySelector("#timings-summary-wait .requests-list-timings-total")
.getAttribute("value").match(/[0-9]+/),
"The wait timing info does not appear to be correct.");
ok(tabpanel.querySelector("#timings-summary-receive .requests-list-timings-total")
.getAttribute("value").match(/[0-9]+/),
"The receive timing info does not appear to be correct.");
return document.querySelector(".network-details-panel .tab-panel");
}
});

View File

@ -6282,14 +6282,23 @@ function getElements(grip, mode) {
attributes,
nodeName,
isAfterPseudoElement,
isBeforePseudoElement
isBeforePseudoElement,
isMarkerPseudoElement
} = grip.preview;
const nodeNameElement = span({
className: "tag-name"
}, nodeName);
if (isAfterPseudoElement || isBeforePseudoElement) {
return [span({ className: "attrName" }, `::${isAfterPseudoElement ? "after" : "before"}`)];
let pseudoNodeName;
if (isAfterPseudoElement) {
pseudoNodeName = "after";
} else if (isBeforePseudoElement) {
pseudoNodeName = "before";
} else if (isMarkerPseudoElement) {
pseudoNodeName = "marker";
}
if (pseudoNodeName) {
return [span({ className: "attrName" }, `::${pseudoNodeName}`)];
}
if (mode === MODE.TINY) {

View File

@ -61,7 +61,7 @@ class ConsoleOutput extends Component {
messagesTableData: PropTypes.object.isRequired,
messagesRepeat: PropTypes.object.isRequired,
warningGroups: PropTypes.object.isRequired,
isInWarningGroup: PropTypes.isRequired,
isInWarningGroup: PropTypes.func,
networkMessagesUpdate: PropTypes.object.isRequired,
visibleMessages: PropTypes.array.isRequired,
networkMessageActiveTabId: PropTypes.string.isRequired,

View File

@ -665,7 +665,7 @@ CssLogic.getSelectors = function(domRule) {
*
* @returns {Object}
* - {DOMNode} node The non-anonymous node
* - {string} pseudo One of ':before', ':after', or null.
* - {string} pseudo One of ':marker', ':before', ':after', or null.
*/
CssLogic.getBindingElementAndPseudo = getBindingElementAndPseudo;

View File

@ -12,6 +12,7 @@ const Services = require("Services");
const {
isAfterPseudoElement,
isBeforePseudoElement,
isMarkerPseudoElement,
isNativeAnonymous,
} = require("devtools/shared/layout/utils");
const Debugger = require("Debugger");
@ -389,7 +390,7 @@ class JQueryEventCollector extends MainEventCollector {
// If jQuery is not on the page, if this is an anonymous node or a pseudo
// element we need to return early.
if (!jQuery || isNativeAnonymous(node) ||
if (!jQuery || isNativeAnonymous(node) || isMarkerPseudoElement(node) ||
isBeforePseudoElement(node) || isAfterPseudoElement(node)) {
if (checkOnly) {
return false;

View File

@ -18,6 +18,7 @@ loader.lazyRequireGetter(this, "isAfterPseudoElement", "devtools/shared/layout/u
loader.lazyRequireGetter(this, "isAnonymous", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "isBeforePseudoElement", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "isDirectShadowHostChild", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "isMarkerPseudoElement", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "isNativeAnonymous", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "isShadowAnonymous", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "isShadowHost", "devtools/shared/layout/utils", true);
@ -127,6 +128,7 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
attrs: this.writeAttrs(),
customElementLocation: this.getCustomElementLocation(),
isMarkerPseudoElement: isMarkerPseudoElement(this.rawNode),
isBeforePseudoElement: isBeforePseudoElement(this.rawNode),
isAfterPseudoElement: isAfterPseudoElement(this.rawNode),
isAnonymous: isAnonymous(this.rawNode),
@ -186,7 +188,9 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
get numChildren() {
// For pseudo elements, childNodes.length returns 1, but the walker
// will return 0.
if (isBeforePseudoElement(this.rawNode) || isAfterPseudoElement(this.rawNode)) {
if (isMarkerPseudoElement(this.rawNode) ||
isBeforePseudoElement(this.rawNode) || isAfterPseudoElement(this.rawNode)
) {
return 0;
}

View File

@ -60,13 +60,14 @@ function isInXULDocument(el) {
/**
* This DeepTreeWalker filter skips whitespace text nodes and anonymous
* content with the exception of ::before and ::after and anonymous content
* in XUL document (needed to show all elements in the browser toolbox).
* content with the exception of ::marker, ::before, and ::after, plus anonymous
* content in XUL document (needed to show all elements in the browser toolbox).
*/
function standardTreeWalkerFilter(node) {
// ::before and ::after are native anonymous content, but we always
// ::marker, ::before, and ::after are native anonymous content, but we always
// want to show them
if (node.nodeName === "_moz_generated_content_before" ||
if (node.nodeName === "_moz_generated_content_marker" ||
node.nodeName === "_moz_generated_content_before" ||
node.nodeName === "_moz_generated_content_after") {
return nodeFilterConstants.FILTER_ACCEPT;
}

View File

@ -17,6 +17,7 @@ loader.lazyRequireGetter(this, "isAfterPseudoElement", "devtools/shared/layout/u
loader.lazyRequireGetter(this, "isAnonymous", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "isBeforePseudoElement", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "isDirectShadowHostChild", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "isMarkerPseudoElement", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "isNativeAnonymous", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "isShadowHost", "devtools/shared/layout/utils", true);
loader.lazyRequireGetter(this, "isShadowRoot", "devtools/shared/layout/utils", true);
@ -87,6 +88,7 @@ const PSEUDO_SELECTORS = [
[":disabled", 0],
[":checked", 1],
["::selection", 0],
["::marker", 0],
];
const HELPER_SHEET = "data:text/css;charset=utf-8," + encodeURIComponent(`
@ -536,7 +538,8 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
*/
inlineTextChild: function({ rawNode }) {
// Quick checks to prevent creating a new walker if possible.
if (isBeforePseudoElement(rawNode) ||
if (isMarkerPseudoElement(rawNode) ||
isBeforePseudoElement(rawNode) ||
isAfterPseudoElement(rawNode) ||
isShadowHost(rawNode) ||
rawNode.nodeType != Node.ELEMENT_NODE ||
@ -865,10 +868,14 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
}
if (shadowHost) {
// Use anonymous walkers to fetch ::before / ::after pseudo elements
// Use anonymous walkers to fetch ::marker / ::before / ::after pseudo
// elements
const firstChildWalker = this.getDocumentWalker(node.rawNode);
const first = firstChildWalker.firstChild();
const hasBefore = first && first.nodeName === "_moz_generated_content_before";
const hasMarker = first && first.nodeName === "_moz_generated_content_marker";
const maybeBeforeNode = hasMarker ? firstChildWalker.nextSibling() : first;
const hasBefore = maybeBeforeNode &&
maybeBeforeNode.nodeName === "_moz_generated_content_before";
const lastChildWalker = this.getDocumentWalker(node.rawNode);
const last = lastChildWalker.lastChild();
@ -877,8 +884,10 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
nodes = [
// #shadow-root
...(hideShadowRoot ? [] : [node.rawNode.openOrClosedShadowRoot]),
// ::marker
...(hasMarker ? [first] : []),
// ::before
...(hasBefore ? [first] : []),
...(hasBefore ? [maybeBeforeNode] : []),
// shadow host direct children
...nodes,
// native anonymous content for UA widgets

View File

@ -93,7 +93,10 @@ WalkerIndex.prototype = {
// For each element node, we get the tagname and all attributes names
// and values
const localName = node.localName;
if (localName === "_moz_generated_content_before") {
if (localName === "_moz_generated_content_marker") {
this._addToIndex("tag", node, "::marker");
this._addToIndex("text", node, node.textContent.trim());
} else if (localName === "_moz_generated_content_before") {
this._addToIndex("tag", node, "::before");
this._addToIndex("text", node, node.textContent.trim());
} else if (localName === "_moz_generated_content_after") {

View File

@ -267,6 +267,9 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
return this._form.hasEventListeners;
}
get isMarkerPseudoElement() {
return this._form.isMarkerPseudoElement;
}
get isBeforePseudoElement() {
return this._form.isBeforePseudoElement;
}
@ -274,7 +277,8 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
return this._form.isAfterPseudoElement;
}
get isPseudoElement() {
return this.isBeforePseudoElement || this.isAfterPseudoElement;
return this.isBeforePseudoElement || this.isAfterPseudoElement ||
this.isMarkerPseudoElement;
}
get isAnonymous() {
return this._form.isAnonymous;

View File

@ -456,19 +456,22 @@ exports.getCssPath = getCssPath;
exports.getXPath = getXPath;
/**
* Given a node, check to see if it is a ::before or ::after element.
* Given a node, check to see if it is a ::marker, ::before, or ::after element.
* If so, return the node that is accessible from within the document
* (the parent of the anonymous node), along with which pseudo element
* it was. Otherwise, return the node itself.
*
* @returns {Object}
* - {DOMNode} node The non-anonymous node
* - {string} pseudo One of ':before', ':after', or null.
* - {string} pseudo One of ':marker', ':before', ':after', or null.
*/
function getBindingElementAndPseudo(node) {
let bindingElement = node;
let pseudo = null;
if (node.nodeName == "_moz_generated_content_before") {
if (node.nodeName == "_moz_generated_content_marker") {
bindingElement = node.parentNode;
pseudo = ":marker";
} else if (node.nodeName == "_moz_generated_content_before") {
bindingElement = node.parentNode;
pseudo = ":before";
} else if (node.nodeName == "_moz_generated_content_after") {

View File

@ -638,6 +638,7 @@ exports.isShadowHost = isShadowHost;
function isDirectShadowHostChild(node) {
// Pseudo elements and native anonymous elements are always part of the anonymous tree.
if (
isMarkerPseudoElement(node) ||
isBeforePseudoElement(node) ||
isAfterPseudoElement(node) ||
isNativeAnonymous(node)) {
@ -649,6 +650,17 @@ function isDirectShadowHostChild(node) {
}
exports.isDirectShadowHostChild = isDirectShadowHostChild;
/**
* Determine whether a node is a ::marker pseudo.
*
* @param {DOMNode} node
* @return {Boolean}
*/
function isMarkerPseudoElement(node) {
return node.nodeName === "_moz_generated_content_marker";
}
exports.isMarkerPseudoElement = isMarkerPseudoElement;
/**
* Determine whether a node is a ::before pseudo.
*

View File

@ -62,19 +62,24 @@ void ReleaseDataBuffer_s(const uint8_t* buf, void* user_data) {
}
void DAV1DDecoder::ReleaseDataBuffer(const uint8_t* buf) {
// The release callback may be called on a
// different thread defined by third party
// dav1d execution. Post a task into TaskQueue
// to ensure mDecodingBuffers is only ever
// accessed on the TaskQueue
// The release callback may be called on a different thread defined by the
// third party dav1d execution. In that case post a task into TaskQueue to
// ensure that mDecodingBuffers is only ever accessed on the TaskQueue.
RefPtr<DAV1DDecoder> self = this;
nsresult rv = mTaskQueue->Dispatch(
NS_NewRunnableFunction("DAV1DDecoder::ReleaseDataBuffer", [self, buf]() {
auto releaseBuffer = [self, buf] {
MOZ_ASSERT(self->mTaskQueue->IsCurrentThreadIn());
DebugOnly<bool> found = self->mDecodingBuffers.Remove(buf);
MOZ_ASSERT(found);
}));
};
if (mTaskQueue->IsCurrentThreadIn()) {
releaseBuffer();
} else {
nsresult rv = mTaskQueue->Dispatch(NS_NewRunnableFunction(
"DAV1DDecoder::ReleaseDataBuffer", std::move(releaseBuffer)));
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
Unused << rv;
}
}
RefPtr<MediaDataDecoder::DecodePromise> DAV1DDecoder::InvokeDecode(

View File

@ -403,6 +403,7 @@ class gfxPrefs final {
DECL_GFX_PREF(Live, "dom.vr.puppet.submitframe", VRPuppetSubmitFrame, uint32_t, 0);
DECL_GFX_PREF(Live, "dom.vr.display.rafMaxDuration", VRDisplayRafMaxDuration, uint32_t, 50);
DECL_GFX_PREF(Once, "dom.vr.process.enabled", VRProcessEnabled, bool, false);
DECL_GFX_PREF(Once, "dom.vr.process.startup_timeout_ms", VRProcessTimeoutMs, int32_t, 5000);
DECL_GFX_PREF(Once, "dom.vr.service.enabled", VRServiceEnabled, bool, true);
DECL_GFX_PREF(Live, "dom.w3c_pointer_events.enabled", PointerEventsEnabled, bool, false);

View File

@ -9,6 +9,7 @@ using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
include "VRMessageUtils.h";
include GraphicsMessages;
include MemoryReportTypes;
include protocol PVRGPU;
include "VRMessageUtils.h";
@ -27,11 +28,19 @@ parent:
async UpdateVar(GfxVarUpdate var);
async OpenVRControllerActionPathToVR(nsCString aPath);
async OpenVRControllerManifestPathToVR(OpenVRControllerType aType, nsCString aPath);
async RequestMemoryReport(uint32_t generation,
bool anonymize,
bool minimizeMemoryUsage,
FileDescriptor? DMDFile);
child:
// Sent when the GPU process has initialized devices. This occurs once, after
// Init().
async InitComplete();
async OpenVRControllerActionPathToParent(nsCString aPath);
async OpenVRControllerManifestPathToParent(OpenVRControllerType aType, nsCString aPath);
async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
async AddMemoryReport(MemoryReport aReport);
async FinishMemoryReport(uint32_t aGeneration);
};
} // namespace gfx

View File

@ -12,6 +12,7 @@
#include "mozilla/SystemGroup.h"
#include "mozilla/Telemetry.h"
#include "mozilla/VsyncDispatcher.h"
#include "mozilla/dom/MemoryReportRequest.h"
#include "mozilla/ipc/CrashReporterHost.h"
namespace mozilla {
@ -66,10 +67,29 @@ class OpenVRControllerManifestManager {
StaticRefPtr<OpenVRControllerManifestManager> sOpenVRControllerManifestManager;
VRChild::VRChild(VRProcessParent* aHost) : mHost(aHost) {
VRChild::VRChild(VRProcessParent* aHost)
: mHost(aHost),
mVRReady(false) {
MOZ_ASSERT(XRE_IsParentProcess());
}
mozilla::ipc::IPCResult VRChild::RecvAddMemoryReport(
const MemoryReport& aReport) {
if (mMemoryReportRequest) {
mMemoryReportRequest->RecvReport(aReport);
}
return IPC_OK();
}
mozilla::ipc::IPCResult VRChild::RecvFinishMemoryReport(
const uint32_t& aGeneration) {
if (mMemoryReportRequest) {
mMemoryReportRequest->Finish(aGeneration);
mMemoryReportRequest = nullptr;
}
return IPC_OK();
}
void VRChild::ActorDestroy(ActorDestroyReason aWhy) {
if (aWhy == AbnormalShutdown) {
if (mCrashReporter) {
@ -144,6 +164,14 @@ void VRChild::Init() {
gfxVars::AddReceiver(this);
}
bool VRChild::EnsureVRReady() {
if (!mVRReady) {
return false;
}
return true;
}
mozilla::ipc::IPCResult VRChild::RecvOpenVRControllerActionPathToParent(
const nsCString& aPath) {
sOpenVRControllerManifestManager->SetOpenVRControllerActionPath(aPath);
@ -157,6 +185,12 @@ mozilla::ipc::IPCResult VRChild::RecvOpenVRControllerManifestPathToParent(
return IPC_OK();
}
mozilla::ipc::IPCResult VRChild::RecvInitComplete() {
// We synchronously requested VR parameters before this arrived.
mVRReady = true;
return IPC_OK();
}
mozilla::ipc::IPCResult VRChild::RecvInitCrashReporter(
Shmem&& aShmem, const NativeThreadId& aThreadId) {
mCrashReporter = MakeUnique<ipc::CrashReporterHost>(GeckoProcessType_VR,
@ -165,6 +199,16 @@ mozilla::ipc::IPCResult VRChild::RecvInitCrashReporter(
return IPC_OK();
}
bool VRChild::SendRequestMemoryReport(const uint32_t& aGeneration,
const bool& aAnonymize,
const bool& aMinimizeMemoryUsage,
const Maybe<FileDescriptor>& aDMDFile) {
mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
Unused << PVRChild::SendRequestMemoryReport(aGeneration, aAnonymize,
aMinimizeMemoryUsage, aDMDFile);
return true;
}
void VRChild::OnVarChanged(const GfxVarUpdate& aVar) { SendUpdateVar(aVar); }
class DeferredDeleteVRChild : public Runnable {

View File

@ -16,12 +16,16 @@ namespace mozilla {
namespace ipc {
class CrashReporterHost;
} // namespace ipc
namespace dom {
class MemoryReportRequestHost;
} // namespace dom
namespace gfx {
class VRProcessParent;
class VRChild;
class VRChild final : public PVRChild, public gfxVarReceiver {
typedef mozilla::dom::MemoryReportRequestHost MemoryReportRequestHost;
friend class PVRChild;
public:
@ -30,7 +34,12 @@ class VRChild final : public PVRChild, public gfxVarReceiver {
static void Destroy(UniquePtr<VRChild>&& aChild);
void Init();
bool EnsureVRReady();
virtual void OnVarChanged(const GfxVarUpdate& aVar) override;
bool SendRequestMemoryReport(const uint32_t& aGeneration,
const bool& aAnonymize,
const bool& aMinimizeMemoryUsage,
const Maybe<ipc::FileDescriptor>& aDMDFile);
protected:
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
@ -38,12 +47,18 @@ class VRChild final : public PVRChild, public gfxVarReceiver {
const nsCString& aPath);
mozilla::ipc::IPCResult RecvOpenVRControllerManifestPathToParent(
const OpenVRControllerType& aType, const nsCString& aPath);
mozilla::ipc::IPCResult RecvInitComplete();
mozilla::ipc::IPCResult RecvInitCrashReporter(
Shmem&& shmem, const NativeThreadId& aThreadId);
mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport);
mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration);
private:
VRProcessParent* mHost;
UniquePtr<ipc::CrashReporterHost> mCrashReporter;
UniquePtr<MemoryReportRequestHost> mMemoryReportRequest;
bool mVRReady;
};
} // namespace gfx

View File

@ -9,12 +9,14 @@
#include "VRManager.h"
#include "gfxConfig.h"
#include "nsDebugImpl.h"
#include "ProcessUtils.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/ipc/CrashReporterClient.h"
#include "mozilla/ipc/ProcessChild.h"
#if defined(XP_WIN)
# include <process.h>
# include "mozilla/gfx/DeviceManagerDx.h"
#endif
@ -39,6 +41,8 @@ IPCResult VRParent::RecvNewGPUVRManager(Endpoint<PVRGPUParent>&& aEndpoint) {
IPCResult VRParent::RecvInit(nsTArray<GfxPrefSetting>&& prefs,
nsTArray<GfxVarUpdate>&& vars,
const DevicePrefs& devicePrefs) {
Unused << SendInitComplete();
const nsTArray<gfxPrefs::Pref*>& globalPrefs = gfxPrefs::all();
for (auto& setting : prefs) {
gfxPrefs::Pref* pref = globalPrefs[setting.index()];
@ -93,6 +97,23 @@ mozilla::ipc::IPCResult VRParent::RecvOpenVRControllerManifestPathToVR(
return IPC_OK();
}
mozilla::ipc::IPCResult VRParent::RecvRequestMemoryReport(
const uint32_t& aGeneration, const bool& aAnonymize,
const bool& aMinimizeMemoryUsage, const Maybe<FileDescriptor>& aDMDFile) {
MOZ_ASSERT(XRE_IsVRProcess());
nsPrintfCString processName("VR (pid %u)", (unsigned)getpid());
mozilla::dom::MemoryReportRequestClient::Start(
aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName,
[&](const MemoryReport& aReport) {
Unused << SendAddMemoryReport(aReport);
},
[&](const uint32_t& aGeneration) {
return SendFinishMemoryReport(aGeneration);
});
return IPC_OK();
}
void VRParent::ActorDestroy(ActorDestroyReason aWhy) {
if (AbnormalShutdown == aWhy) {
NS_WARNING("Shutting down VR process early due to a crash!");
@ -161,6 +182,7 @@ bool VRParent::Init(base::ProcessId aParentPid, const char* aParentBuildID,
return false;
}
mozilla::ipc::SetThisProcessName("VR Process");
return true;
}

View File

@ -46,6 +46,10 @@ class VRParent final : public PVRParent {
const nsCString& aPath);
mozilla::ipc::IPCResult RecvOpenVRControllerManifestPathToVR(
const OpenVRControllerType& aType, const nsCString& aPath);
mozilla::ipc::IPCResult RecvRequestMemoryReport(
const uint32_t& generation, const bool& anonymize,
const bool& minimizeMemoryUsage,
const Maybe<ipc::FileDescriptor>& DMDFile);
private:
nsCString mOpenVRControllerAction;

View File

@ -10,6 +10,7 @@
#include "VRChild.h"
#include "VRGPUChild.h"
#include "VRGPUParent.h"
#include "mozilla/MemoryReportingProcess.h"
namespace mozilla {
namespace gfx {
@ -30,7 +31,7 @@ void VRProcessManager::Initialize() {
/* static */
void VRProcessManager::Shutdown() { sSingleton = nullptr; }
VRProcessManager::VRProcessManager() : mProcess(nullptr) {
VRProcessManager::VRProcessManager() : mProcess(nullptr), mVRChild(nullptr) {
MOZ_COUNT_CTOR(VRProcessManager);
mObserver = new Observer(this);
@ -79,14 +80,43 @@ void VRProcessManager::DestroyProcess() {
mProcess->Shutdown();
mProcess = nullptr;
mVRChild = nullptr;
CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::VRProcessStatus,
NS_LITERAL_CSTRING("Destroyed"));
}
bool VRProcessManager::EnsureVRReady() {
if (mProcess && !mProcess->IsConnected()) {
if (!mProcess->WaitForLaunch()) {
// If this fails, we should have fired OnProcessLaunchComplete and
// removed the process.
MOZ_ASSERT(!mProcess && !mVRChild);
return false;
}
}
if (mVRChild) {
if (mVRChild->EnsureVRReady()) {
return true;
}
// If the initialization above fails, we likely have a GPU process teardown
// waiting in our message queue (or will soon). We need to ensure we don't
// restart it later because if we fail here, our callers assume they should
// fall back to a combined UI/GPU process. This also ensures our internal
// state is consistent (e.g. process token is reset).
DisableVRProcess("Failed to initialize VR process");
}
return false;
}
void VRProcessManager::OnProcessLaunchComplete(VRProcessParent* aParent) {
MOZ_ASSERT(mProcess && mProcess == aParent);
mVRChild = mProcess->GetActor();
if (!mProcess->IsConnected()) {
DestroyProcess();
return;
@ -166,5 +196,57 @@ void VRProcessManager::OnXPCOMShutdown() {
VRChild* VRProcessManager::GetVRChild() { return mProcess->GetActor(); }
class VRMemoryReporter : public MemoryReportingProcess {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRMemoryReporter, override)
bool IsAlive() const override {
if (VRProcessManager* vpm = VRProcessManager::Get()) {
return !!vpm->GetVRChild();
}
return false;
}
bool SendRequestMemoryReport(const uint32_t& aGeneration,
const bool& aAnonymize,
const bool& aMinimizeMemoryUsage,
const Maybe<FileDescriptor>& aDMDFile) override {
VRChild* child = GetChild();
if (!child) {
return false;
}
return child->SendRequestMemoryReport(aGeneration, aAnonymize,
aMinimizeMemoryUsage, aDMDFile);
}
int32_t Pid() const override {
if (VRChild* child = GetChild()) {
return (int32_t)child->OtherPid();
}
return 0;
}
private:
VRChild* GetChild() const {
if (VRProcessManager* vpm = VRProcessManager::Get()) {
if (VRChild* child = vpm->GetVRChild()) {
return child;
}
}
return nullptr;
}
protected:
~VRMemoryReporter() = default;
};
RefPtr<MemoryReportingProcess> VRProcessManager::GetProcessMemoryReporter() {
if (!EnsureVRReady()) {
return nullptr;
}
return new VRMemoryReporter();
}
} // namespace gfx
} // namespace mozilla

View File

@ -9,6 +9,7 @@
#include "VRProcessParent.h"
namespace mozilla {
class MemoryReportingProcess;
namespace gfx {
class VRManagerChild;
@ -27,10 +28,19 @@ class VRProcessManager final : public VRProcessParent::Listener {
// If not using a VR process, launch a new VR process asynchronously.
void LaunchVRProcess();
// Ensure that VR-bound methods can be used. If no VR process is being
// used, or one is launched and ready, this function returns immediately.
// Otherwise it blocks until the VR process has finished launching.
bool EnsureVRReady();
bool CreateGPUBridges(base::ProcessId aOtherProcess,
mozilla::ipc::Endpoint<PVRGPUChild>* aOutVRBridge);
VRChild* GetVRChild();
// If a VR process is present, create a MemoryReportingProcess object.
// Otherwise, return null.
RefPtr<MemoryReportingProcess> GetProcessMemoryReporter();
virtual void OnProcessLaunchComplete(VRProcessParent* aParent) override;
virtual void OnProcessUnexpectedShutdown(VRProcessParent* aParent) override;
@ -65,6 +75,7 @@ class VRProcessManager final : public VRProcessParent::Listener {
RefPtr<Observer> mObserver;
VRProcessParent* mProcess;
VRChild* mVRChild;
};
} // namespace gfx

View File

@ -33,6 +33,7 @@ VRProcessParent::VRProcessParent(Listener* aListener)
: GeckoChildProcessHost(GeckoProcessType_VR),
mTaskFactory(this),
mListener(aListener),
mLaunchPhase(LaunchPhase::Unlaunched),
mChannelClosed(false),
mShutdownRequested(false) {
MOZ_COUNT_CTOR(VRProcessParent);
@ -49,19 +50,47 @@ VRProcessParent::~VRProcessParent() {
}
bool VRProcessParent::Launch() {
MOZ_ASSERT(mLaunchPhase == LaunchPhase::Unlaunched);
MOZ_ASSERT(!mVRChild);
mLaunchThread = NS_GetCurrentThread();
mLaunchPhase = LaunchPhase::Waiting;
std::vector<std::string> extraArgs;
nsCString parentBuildID(mozilla::PlatformBuildID());
extraArgs.push_back("-parentBuildID");
extraArgs.push_back(parentBuildID.get());
if (!GeckoChildProcessHost::AsyncLaunch(extraArgs)) {
mLaunchPhase = LaunchPhase::Complete;
return false;
}
return true;
}
bool VRProcessParent::WaitForLaunch() {
if (mLaunchPhase == LaunchPhase::Complete) {
return !!mVRChild;
}
int32_t timeoutMs = gfxPrefs::VRProcessTimeoutMs();
// If one of the following environment variables are set we can effectively
// ignore the timeout - as we can guarantee the compositor process will be
// terminated
if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS") ||
PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) {
timeoutMs = 0;
}
// Our caller expects the connection to be finished after we return, so we
// immediately set up the IPDL actor and fire callbacks. The IO thread will
// still dispatch a notification to the main thread - we'll just ignore it.
bool result = GeckoChildProcessHost::WaitUntilConnected(timeoutMs);
InitAfterConnect(result);
return result;
}
void VRProcessParent::Shutdown() {
MOZ_ASSERT(!mShutdownRequested);
mListener = nullptr;
@ -101,6 +130,10 @@ void VRProcessParent::DestroyProcess() {
}
void VRProcessParent::InitAfterConnect(bool aSucceeded) {
MOZ_ASSERT(mLaunchPhase == LaunchPhase::Waiting);
MOZ_ASSERT(!mVRChild);
mLaunchPhase = LaunchPhase::Complete;
if (aSucceeded) {
mVRChild = MakeUnique<VRChild>(this);
@ -157,10 +190,16 @@ void VRProcessParent::OnChannelConnected(int32_t peer_pid) {
NS_DispatchToMainThread(runnable);
}
void VRProcessParent::OnChannelConnectedTask() { InitAfterConnect(true); }
void VRProcessParent::OnChannelConnectedTask() {
if (mLaunchPhase == LaunchPhase::Waiting) {
InitAfterConnect(true);
}
}
void VRProcessParent::OnChannelErrorTask() {
MOZ_ASSERT(false, "VR process channel error.");
if (mLaunchPhase == LaunchPhase::Waiting) {
InitAfterConnect(false);
}
}
void VRProcessParent::OnChannelClosed() {

View File

@ -32,6 +32,11 @@ class VRProcessParent final : public mozilla::ipc::GeckoChildProcessHost {
explicit VRProcessParent(Listener* aListener);
bool Launch();
// If the process is being launched, block until it has launched and
// connected. If a launch task is pending, it will fire immediately.
//
// Returns true if the process is successfully connected; false otherwise.
bool WaitForLaunch();
void Shutdown();
void DestroyProcess();
bool CanShutdown() override { return true; }
@ -45,6 +50,9 @@ class VRProcessParent final : public mozilla::ipc::GeckoChildProcessHost {
base::ProcessId OtherPid();
VRChild* GetActor() const { return mVRChild.get(); }
// Return a unique id for this process, guaranteed not to be shared with any
// past or future instance of VRProcessParent.
uint64_t GetProcessToken() const;
private:
~VRProcessParent();
@ -59,6 +67,8 @@ class VRProcessParent final : public mozilla::ipc::GeckoChildProcessHost {
nsCOMPtr<nsIThread> mLaunchThread;
Listener* mListener;
enum class LaunchPhase { Unlaunched, Waiting, Complete };
LaunchPhase mLaunchPhase;
bool mChannelClosed;
bool mShutdownRequested;
};

View File

@ -224,7 +224,7 @@ bool BytecodeEmitter::markSimpleBreakpoint() {
bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, ptrdiff_t* offset) {
*offset = code().length();
if (!code().growBy(delta)) {
if (!code().growByUninitialized(delta)) {
ReportOutOfMemory(cx);
return false;
}
@ -9193,7 +9193,7 @@ bool BytecodeEmitter::emitTree(
static bool AllocSrcNote(JSContext* cx, SrcNotesVector& notes,
unsigned* index) {
if (!notes.growBy(1)) {
if (!notes.growByUninitialized(1)) {
ReportOutOfMemory(cx);
return false;
}

View File

@ -0,0 +1,28 @@
// If the async function's promise is already resolved, any attempt to return
// a differerent return value gets ignored.
let g = newGlobal({newCompartment: true});
g.eval(`
async function f() {
throw "ok";
}
`);
let dbg = new Debugger(g);
let hits = 0;
dbg.onEnterFrame = frame => {
frame.onPop = () => {
hits += 1;
// Normal functions can override the return value, but async functions
// have already resolved their promise, so this return request will get
// ignored.
return {return: "FAIL"};
};
};
g.f().catch(x => {
assertEq(hits, 1);
assertEq(x, "ok");
});

View File

@ -0,0 +1,28 @@
// If the async function's promise is already resolved, any attempt to return
// a differerent return value gets ignored.
let g = newGlobal({newCompartment: true});
g.eval(`
async function f() {
return "ok";
}
`);
let dbg = new Debugger(g);
let hits = 0;
dbg.onEnterFrame = frame => {
frame.onPop = () => {
hits += 1;
// Normal functions can override the return value, but async functions
// have already resolved their promise, so this return request will get
// ignored.
return {return: "FAIL"};
};
};
g.f().then(x => {
assertEq(hits, 1);
assertEq(x, "ok");
});

View File

@ -442,24 +442,25 @@ static inline bool IsInlinableFallback(ICFallbackStub* icEntry) {
#endif
static inline void* GetStubReturnAddress(JSContext* cx, jsbytecode* pc) {
JitRealm* jitRealm = cx->realm()->jitRealm();
const BaselineICFallbackCode& code =
cx->runtime()->jitRuntime()->baselineICFallbackCode();
if (IsGetPropPC(pc)) {
return jitRealm->bailoutReturnAddr(BailoutReturnStub::GetProp);
return code.bailoutReturnAddr(BailoutReturnKind::GetProp);
}
if (IsSetPropPC(pc)) {
return jitRealm->bailoutReturnAddr(BailoutReturnStub::SetProp);
return code.bailoutReturnAddr(BailoutReturnKind::SetProp);
}
if (IsGetElemPC(pc)) {
return jitRealm->bailoutReturnAddr(BailoutReturnStub::GetElem);
return code.bailoutReturnAddr(BailoutReturnKind::GetElem);
}
// This should be a call op of some kind, now.
MOZ_ASSERT(IsCallPC(pc) && !IsSpreadCallPC(pc));
if (IsConstructorCallPC(pc)) {
return jitRealm->bailoutReturnAddr(BailoutReturnStub::New);
return code.bailoutReturnAddr(BailoutReturnKind::New);
}
return jitRealm->bailoutReturnAddr(BailoutReturnStub::Call);
return code.bailoutReturnAddr(BailoutReturnKind::Call);
}
static inline jsbytecode* GetNextNonLoopEntryPc(jsbytecode* pc,

View File

@ -36,6 +36,7 @@
#include "vm/Opcodes.h"
#include "vm/SelfHosting.h"
#include "vm/TypedArrayObject.h"
#include "vtune/VTuneWrapper.h"
#include "builtin/Boolean-inl.h"
@ -54,6 +55,26 @@ using mozilla::DebugOnly;
namespace js {
namespace jit {
// Class used to emit all Baseline IC fallback code when initializing the
// JitRuntime.
class MOZ_RAII FallbackICCodeCompiler final : public ICStubCompilerBase {
BaselineICFallbackCode& code;
MacroAssembler& masm;
MOZ_MUST_USE bool emitCall(bool isSpread, bool isConstructing);
MOZ_MUST_USE bool emitGetElem(bool hasReceiver);
MOZ_MUST_USE bool emitGetProp(bool hasReceiver);
public:
FallbackICCodeCompiler(JSContext* cx, BaselineICFallbackCode& code,
MacroAssembler& masm)
: ICStubCompilerBase(cx), code(code), masm(masm) {}
#define DEF_METHOD(kind) MOZ_MUST_USE bool emit_##kind();
IC_BASELINE_FALLBACK_CODE_KIND_LIST(DEF_METHOD)
#undef DEF_METHOD
};
#ifdef JS_JITSPEW
void FallbackICSpew(JSContext* cx, ICFallbackStub* stub, const char* fmt, ...) {
if (JitSpewEnabled(JitSpew_BaselineICFallback)) {
@ -108,14 +129,39 @@ void ICEntry::trace(JSTracer* trc) {
}
}
// Allocator for Baseline IC fallback stubs. These stubs use trampoline code
// stored in JitRuntime.
class MOZ_RAII FallbackStubAllocator {
JSContext* cx_;
ICStubSpace& stubSpace_;
const BaselineICFallbackCode& code_;
public:
FallbackStubAllocator(JSContext* cx, ICStubSpace& stubSpace)
: cx_(cx),
stubSpace_(stubSpace),
code_(cx->runtime()->jitRuntime()->baselineICFallbackCode()) {}
template <typename T, typename... Args>
T* newStub(BaselineICFallbackKind kind, Args&&... args) {
TrampolinePtr addr = code_.addr(kind);
return ICStub::NewFallback<T>(cx_, &stubSpace_, addr,
std::forward<Args>(args)...);
}
};
/* static */
UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
MOZ_ASSERT(cx->realm()->jitRealm());
MOZ_ASSERT(jit::IsBaselineEnabled(cx));
FallbackICStubSpace stubSpace;
FallbackStubAllocator alloc(cx, stubSpace);
js::Vector<ICEntry, 16, SystemAllocPolicy> icEntries;
using Kind = BaselineICFallbackKind;
auto addIC = [cx, &icEntries, script](jsbytecode* pc, ICStub* stub) {
if (!stub) {
MOZ_ASSERT(cx->isExceptionPending());
@ -133,14 +179,16 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
// Note: we pass a nullptr pc to indicate this is a non-op IC.
// See ICEntry::NonOpPCOffset.
if (JSFunction* fun = script->functionNonDelazifying()) {
ICTypeMonitor_Fallback::Compiler compiler(cx, uint32_t(0));
if (!addIC(nullptr, compiler.getStub(&stubSpace))) {
ICStub* stub =
alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor, nullptr, 0);
if (!addIC(nullptr, stub)) {
return nullptr;
}
for (size_t i = 0; i < fun->nargs(); i++) {
ICTypeMonitor_Fallback::Compiler compiler(cx, i + 1);
if (!addIC(nullptr, compiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor,
nullptr, i + 1);
if (!addIC(nullptr, stub)) {
return nullptr;
}
}
@ -166,8 +214,8 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_OR:
case JSOP_IFEQ:
case JSOP_IFNE: {
ICToBool_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICToBool_Fallback>(Kind::ToBool);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
@ -176,8 +224,8 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_NEG:
case JSOP_INC:
case JSOP_DEC: {
ICUnaryArith_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICUnaryArith_Fallback>(Kind::UnaryArith);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
@ -194,8 +242,8 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_DIV:
case JSOP_MOD:
case JSOP_POW: {
ICBinaryArith_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICBinaryArith_Fallback>(Kind::BinaryArith);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
@ -208,15 +256,16 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_GE:
case JSOP_STRICTEQ:
case JSOP_STRICTNE: {
ICCompare_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICCompare_Fallback>(Kind::Compare);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_LOOPENTRY: {
ICWarmUpCounter_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub =
alloc.newStub<ICWarmUpCounter_Fallback>(Kind::WarmUpCounter);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
@ -227,16 +276,17 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
if (!group) {
return nullptr;
}
ICNewArray_Fallback::Compiler stubCompiler(cx, group);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub =
alloc.newStub<ICNewArray_Fallback>(Kind::NewArray, group);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_NEWOBJECT:
case JSOP_NEWINIT: {
ICNewObject_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICNewObject_Fallback>(Kind::NewObject);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
@ -247,8 +297,8 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_INITELEM_INC:
case JSOP_SETELEM:
case JSOP_STRICTSETELEM: {
ICSetElem_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICSetElem_Fallback>(Kind::SetElem);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
@ -263,8 +313,8 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_STRICTSETNAME:
case JSOP_SETGNAME:
case JSOP_STRICTSETGNAME: {
ICSetProp_Fallback::Compiler compiler(cx);
if (!addIC(pc, compiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICSetProp_Fallback>(Kind::SetProp);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
@ -272,66 +322,78 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_GETPROP:
case JSOP_CALLPROP:
case JSOP_LENGTH:
case JSOP_GETPROP_SUPER:
case JSOP_GETBOUNDNAME: {
bool hasReceiver = (op == JSOP_GETPROP_SUPER);
ICGetProp_Fallback::Compiler compiler(cx, hasReceiver);
if (!addIC(pc, compiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICGetProp_Fallback>(Kind::GetProp);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_GETPROP_SUPER: {
ICStub* stub = alloc.newStub<ICGetProp_Fallback>(Kind::GetPropSuper);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_GETELEM:
case JSOP_CALLELEM:
case JSOP_CALLELEM: {
ICStub* stub = alloc.newStub<ICGetElem_Fallback>(Kind::GetElem);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_GETELEM_SUPER: {
bool hasReceiver = (op == JSOP_GETELEM_SUPER);
ICGetElem_Fallback::Compiler stubCompiler(cx, hasReceiver);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICGetElem_Fallback>(Kind::GetElemSuper);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_IN: {
ICIn_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICIn_Fallback>(Kind::In);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_HASOWN: {
ICHasOwn_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICHasOwn_Fallback>(Kind::HasOwn);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_GETNAME:
case JSOP_GETGNAME: {
ICGetName_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICGetName_Fallback>(Kind::GetName);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_BINDNAME:
case JSOP_BINDGNAME: {
ICBindName_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICBindName_Fallback>(Kind::BindName);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_GETALIASEDVAR:
case JSOP_GETIMPORT: {
ICTypeMonitor_Fallback::Compiler compiler(cx, nullptr);
if (!addIC(pc, compiler.getStub(&stubSpace))) {
ICStub* stub =
alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor, nullptr);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_GETINTRINSIC: {
ICGetIntrinsic_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub =
alloc.newStub<ICGetIntrinsic_Fallback>(Kind::GetIntrinsic);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
@ -339,54 +401,60 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_CALL:
case JSOP_CALL_IGNORES_RV:
case JSOP_CALLITER:
case JSOP_SUPERCALL:
case JSOP_FUNCALL:
case JSOP_FUNAPPLY:
case JSOP_NEW:
case JSOP_EVAL:
case JSOP_STRICTEVAL: {
bool construct = JSOp(*pc) == JSOP_NEW || JSOp(*pc) == JSOP_SUPERCALL;
ICCall_Fallback::Compiler stubCompiler(cx,
/* isConstructing = */ construct,
/* isSpread = */ false);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::Call);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_SUPERCALL:
case JSOP_NEW: {
ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::CallConstructing);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_SPREADCALL:
case JSOP_SPREADSUPERCALL:
case JSOP_SPREADNEW:
case JSOP_SPREADEVAL:
case JSOP_STRICTSPREADEVAL: {
bool construct =
JSOp(*pc) == JSOP_SPREADNEW || JSOp(*pc) == JSOP_SPREADSUPERCALL;
ICCall_Fallback::Compiler stubCompiler(cx,
/* isConstructing = */ construct,
/* isSpread = */ true);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::SpreadCall);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_SPREADSUPERCALL:
case JSOP_SPREADNEW: {
ICStub* stub =
alloc.newStub<ICCall_Fallback>(Kind::SpreadCallConstructing);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_INSTANCEOF: {
ICInstanceOf_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICInstanceOf_Fallback>(Kind::InstanceOf);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_TYPEOF:
case JSOP_TYPEOFEXPR: {
ICTypeOf_Fallback::Compiler stubCompiler(cx);
if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICTypeOf_Fallback>(Kind::TypeOf);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
}
case JSOP_ITER: {
ICGetIterator_Fallback::Compiler compiler(cx);
if (!addIC(pc, compiler.getStub(&stubSpace))) {
ICStub* stub = alloc.newStub<ICGetIterator_Fallback>(Kind::GetIterator);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
@ -398,8 +466,9 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
if (!templateObject) {
return nullptr;
}
ICRest_Fallback::Compiler compiler(cx, templateObject);
if (!addIC(pc, compiler.getStub(&stubSpace))) {
ICStub* stub =
alloc.newStub<ICRest_Fallback>(Kind::Rest, templateObject);
if (!addIC(pc, stub)) {
return nullptr;
}
break;
@ -504,11 +573,6 @@ bool ICStub::makesGCCalls() const {
}
}
void ICStub::traceCode(JSTracer* trc, const char* name) {
JitCode* stubJitCode = jitCode();
TraceManuallyBarrieredEdge(trc, &stubJitCode, name);
}
void ICStub::updateCode(JitCode* code) {
// Write barrier on the old code.
JitCode::writeBarrierPre(jitCode());
@ -517,7 +581,11 @@ void ICStub::updateCode(JitCode* code) {
/* static */
void ICStub::trace(JSTracer* trc) {
traceCode(trc, "shared-stub-jitcode");
// Fallback stubs use runtime-wide trampoline code we don't need to trace.
if (!usesTrampolineCode()) {
JitCode* stubJitCode = jitCode();
TraceManuallyBarrieredEdge(trc, &stubJitCode, "baseline-ic-stub-code");
}
// If the stub is a monitored fallback stub, then trace the monitor ICs
// hanging off of that stub. We don't need to worry about the regular
@ -781,8 +849,7 @@ bool DoWarmUpCounterFallbackOSR(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICWarmUpCounter_Fallback::Compiler::generateStubCode(
MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_WarmUpCounter() {
// Push a stub frame so that we can perform a non-tail call.
enterStubFrame(masm, R1.scratchReg());
@ -1005,12 +1072,14 @@ bool ICMonitoredFallbackStub::initMonitoringChain(JSContext* cx,
JSScript* script) {
MOZ_ASSERT(fallbackMonitorStub_ == nullptr);
ICTypeMonitor_Fallback::Compiler compiler(cx, this);
ICStubSpace* space = script->icScript()->fallbackStubSpace();
ICTypeMonitor_Fallback* stub = compiler.getStub(space);
FallbackStubAllocator alloc(cx, *space);
auto* stub = alloc.newStub<ICTypeMonitor_Fallback>(
BaselineICFallbackKind::TypeMonitor, this);
if (!stub) {
return false;
}
fallbackMonitorStub_ = stub;
return true;
}
@ -1030,8 +1099,9 @@ bool ICMonitoredFallbackStub::addMonitorStubForValue(JSContext* cx,
bool ICUpdatedStub::initUpdatingChain(JSContext* cx, ICStubSpace* space) {
MOZ_ASSERT(firstUpdateStub_ == nullptr);
ICTypeUpdate_Fallback::Compiler compiler(cx);
ICTypeUpdate_Fallback* stub = compiler.getStub(space);
FallbackStubAllocator alloc(cx, *space);
auto* stub =
alloc.newStub<ICTypeUpdate_Fallback>(BaselineICFallbackKind::TypeUpdate);
if (!stub) {
return false;
}
@ -1049,6 +1119,17 @@ ICStubSpace* ICStubCompiler::StubSpaceForStub(bool makesGCCalls,
return script->zone()->jitZone()->optimizedStubSpace();
}
static void InitMacroAssemblerForICStub(StackMacroAssembler& masm) {
#ifndef JS_USE_LINK_REGISTER
// The first value contains the return addres,
// which we pull into ICTailCallReg for tail calls.
masm.adjustFrame(sizeof(intptr_t));
#endif
#ifdef JS_CODEGEN_ARM
masm.setSecondScratchReg(BaselineSecondScratchReg);
#endif
}
JitCode* ICStubCompiler::getStubCode() {
JitRealm* realm = cx->realm()->jitRealm();
@ -1062,14 +1143,7 @@ JitCode* ICStubCompiler::getStubCode() {
// Compile new stubcode.
JitContext jctx(cx, nullptr);
StackMacroAssembler masm;
#ifndef JS_USE_LINK_REGISTER
// The first value contains the return addres,
// which we pull into ICTailCallReg for tail calls.
masm.adjustFrame(sizeof(intptr_t));
#endif
#ifdef JS_CODEGEN_ARM
masm.setSecondScratchReg(BaselineSecondScratchReg);
#endif
InitMacroAssemblerForICStub(masm);
if (!generateStubCode(masm)) {
return nullptr;
@ -1085,10 +1159,6 @@ JitCode* ICStubCompiler::getStubCode() {
return nullptr;
}
// After generating code, run postGenerateStubCode(). We must not fail
// after this point.
postGenerateStubCode(masm, newStubCode);
MOZ_ASSERT(entersStubFrame_ == ICStub::NonCacheIRStubMakesGCCalls(kind));
MOZ_ASSERT(!inStubFrame_);
@ -1099,7 +1169,7 @@ JitCode* ICStubCompiler::getStubCode() {
return newStubCode;
}
bool ICStubCompiler::tailCallVMInternal(MacroAssembler& masm,
bool ICStubCompilerBase::tailCallVMInternal(MacroAssembler& masm,
TailCallVMFunctionId id) {
TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(id);
const VMFunctionData& fun = GetVMFunction(id);
@ -1109,7 +1179,7 @@ bool ICStubCompiler::tailCallVMInternal(MacroAssembler& masm,
return true;
}
bool ICStubCompiler::callVMInternal(MacroAssembler& masm, VMFunctionId id) {
bool ICStubCompilerBase::callVMInternal(MacroAssembler& masm, VMFunctionId id) {
MOZ_ASSERT(inStubFrame_);
TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(id);
@ -1120,18 +1190,19 @@ bool ICStubCompiler::callVMInternal(MacroAssembler& masm, VMFunctionId id) {
}
template <typename Fn, Fn fn>
bool ICStubCompiler::callVM(MacroAssembler& masm) {
bool ICStubCompilerBase::callVM(MacroAssembler& masm) {
VMFunctionId id = VMFunctionToId<Fn, fn>::id;
return callVMInternal(masm, id);
}
template <typename Fn, Fn fn>
bool ICStubCompiler::tailCallVM(MacroAssembler& masm) {
bool ICStubCompilerBase::tailCallVM(MacroAssembler& masm) {
TailCallVMFunctionId id = TailCallVMFunctionToId<Fn, fn>::id;
return tailCallVMInternal(masm, id);
}
void ICStubCompiler::enterStubFrame(MacroAssembler& masm, Register scratch) {
void ICStubCompilerBase::enterStubFrame(MacroAssembler& masm,
Register scratch) {
EmitBaselineEnterStubFrame(masm, scratch);
#ifdef DEBUG
framePushedAtEnterStubFrame_ = masm.framePushed();
@ -1145,7 +1216,7 @@ void ICStubCompiler::enterStubFrame(MacroAssembler& masm, Register scratch) {
#endif
}
void ICStubCompiler::assumeStubFrame() {
void ICStubCompilerBase::assumeStubFrame() {
MOZ_ASSERT(!inStubFrame_);
inStubFrame_ = true;
@ -1158,7 +1229,8 @@ void ICStubCompiler::assumeStubFrame() {
#endif
}
void ICStubCompiler::leaveStubFrame(MacroAssembler& masm, bool calledIntoIon) {
void ICStubCompilerBase::leaveStubFrame(MacroAssembler& masm,
bool calledIntoIon) {
MOZ_ASSERT(entersStubFrame_ && inStubFrame_);
inStubFrame_ = false;
@ -1171,7 +1243,8 @@ void ICStubCompiler::leaveStubFrame(MacroAssembler& masm, bool calledIntoIon) {
EmitBaselineLeaveStubFrame(masm, calledIntoIon);
}
void ICStubCompiler::pushStubPayload(MacroAssembler& masm, Register scratch) {
void ICStubCompilerBase::pushStubPayload(MacroAssembler& masm,
Register scratch) {
if (inStubFrame_) {
masm.loadPtr(Address(BaselineFrameReg, 0), scratch);
masm.pushBaselineFramePtr(scratch, scratch);
@ -1180,7 +1253,8 @@ void ICStubCompiler::pushStubPayload(MacroAssembler& masm, Register scratch) {
}
}
void ICStubCompiler::PushStubPayload(MacroAssembler& masm, Register scratch) {
void ICStubCompilerBase::PushStubPayload(MacroAssembler& masm,
Register scratch) {
pushStubPayload(masm, scratch);
masm.adjustFrame(sizeof(intptr_t));
}
@ -1427,7 +1501,7 @@ bool DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame,
return stub->addMonitorStubForValue(cx, frame, types, value);
}
bool ICTypeMonitor_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_TypeMonitor() {
MOZ_ASSERT(R0 == JSReturnOperand);
// Restore the tail call register.
@ -1766,7 +1840,7 @@ bool DoTypeUpdateFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICTypeUpdate_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_TypeUpdate() {
// Just store false into R1.scratchReg() and return.
masm.move32(Imm32(0), R1.scratchReg());
EmitReturnFromIC(masm);
@ -1892,7 +1966,7 @@ bool DoToBoolFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICToBool_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_ToBool() {
MOZ_ASSERT(R0 == JSReturnOperand);
// Restore the tail call register.
@ -2106,14 +2180,14 @@ bool DoGetElemSuperFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICGetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emitGetElem(bool hasReceiver) {
MOZ_ASSERT(R0 == JSReturnOperand);
// Restore the tail call register.
EmitRestoreTailCallReg(masm);
// Super property getters use a |this| that differs from base object
if (hasReceiver_) {
if (hasReceiver) {
// State: receiver in R0, index in R1, obj on the stack
// Ensure stack is fully synced for the expression decompiler.
@ -2157,7 +2231,13 @@ bool ICGetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
// Ion inlined frames. The return address pushed onto reconstructed stack
// will point here.
assumeStubFrame();
bailoutReturnOffset_.bind(masm.currentOffset());
if (hasReceiver) {
code.initBailoutReturnOffset(BailoutReturnKind::GetElemSuper,
masm.currentOffset());
} else {
code.initBailoutReturnOffset(BailoutReturnKind::GetElem,
masm.currentOffset());
}
leaveStubFrame(masm, true);
@ -2175,12 +2255,12 @@ bool ICGetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
return true;
}
void ICGetElem_Fallback::Compiler::postGenerateStubCode(MacroAssembler& masm,
Handle<JitCode*> code) {
BailoutReturnStub kind = hasReceiver_ ? BailoutReturnStub::GetElemSuper
: BailoutReturnStub::GetElem;
void* address = code->raw() + bailoutReturnOffset_.offset();
cx->realm()->jitRealm()->initBailoutReturnAddr(address, getKey(), kind);
bool FallbackICCodeCompiler::emit_GetElem() {
return emitGetElem(/* hasReceiver = */ false);
}
bool FallbackICCodeCompiler::emit_GetElemSuper() {
return emitGetElem(/* hasReceiver = */ true);
}
static void SetUpdateStubData(ICCacheIR_Updated* stub,
@ -2326,7 +2406,7 @@ bool DoSetElemFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICSetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_SetElem() {
MOZ_ASSERT(R0 == JSReturnOperand);
EmitRestoreTailCallReg(masm);
@ -2467,7 +2547,7 @@ bool DoInFallback(JSContext* cx, BaselineFrame* frame, ICIn_Fallback* stub,
return true;
}
bool ICIn_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_In() {
EmitRestoreTailCallReg(masm);
// Sync for the decompiler.
@ -2509,7 +2589,7 @@ bool DoHasOwnFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICHasOwn_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_HasOwn() {
EmitRestoreTailCallReg(masm);
// Sync for the decompiler.
@ -2572,7 +2652,7 @@ bool DoGetNameFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICGetName_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_GetName() {
MOZ_ASSERT(R0 == JSReturnOperand);
EmitRestoreTailCallReg(masm);
@ -2616,7 +2696,7 @@ bool DoBindNameFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICBindName_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_BindName() {
MOZ_ASSERT(R0 == JSReturnOperand);
EmitRestoreTailCallReg(masm);
@ -2662,7 +2742,7 @@ bool DoGetIntrinsicFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICGetIntrinsic_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_GetIntrinsic() {
EmitRestoreTailCallReg(masm);
masm.push(ICStubReg);
@ -2837,13 +2917,13 @@ bool DoGetPropSuperFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICGetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emitGetProp(bool hasReceiver) {
MOZ_ASSERT(R0 == JSReturnOperand);
EmitRestoreTailCallReg(masm);
// Super property getters use a |this| that differs from base object
if (hasReceiver_) {
if (hasReceiver) {
// Push arguments.
masm.pushValue(R0);
masm.pushValue(R1);
@ -2875,7 +2955,13 @@ bool ICGetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
// Ion inlined frames. The return address pushed onto reconstructed stack
// will point here.
assumeStubFrame();
bailoutReturnOffset_.bind(masm.currentOffset());
if (hasReceiver) {
code.initBailoutReturnOffset(BailoutReturnKind::GetPropSuper,
masm.currentOffset());
} else {
code.initBailoutReturnOffset(BailoutReturnKind::GetProp,
masm.currentOffset());
}
leaveStubFrame(masm, true);
@ -2893,12 +2979,12 @@ bool ICGetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
return true;
}
void ICGetProp_Fallback::Compiler::postGenerateStubCode(MacroAssembler& masm,
Handle<JitCode*> code) {
BailoutReturnStub kind = hasReceiver_ ? BailoutReturnStub::GetPropSuper
: BailoutReturnStub::GetProp;
void* address = code->raw() + bailoutReturnOffset_.offset();
cx->realm()->jitRealm()->initBailoutReturnAddr(address, getKey(), kind);
bool FallbackICCodeCompiler::emit_GetProp() {
return emitGetProp(/* hasReceiver = */ false);
}
bool FallbackICCodeCompiler::emit_GetPropSuper() {
return emitGetProp(/* hasReceiver = */ true);
}
//
@ -3045,7 +3131,7 @@ bool DoSetPropFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICSetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_SetProp() {
MOZ_ASSERT(R0 == JSReturnOperand);
EmitRestoreTailCallReg(masm);
@ -3079,7 +3165,8 @@ bool ICSetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
// Ion inlined frames. The return address pushed onto reconstructed stack
// will point here.
assumeStubFrame();
bailoutReturnOffset_.bind(masm.currentOffset());
code.initBailoutReturnOffset(BailoutReturnKind::SetProp,
masm.currentOffset());
leaveStubFrame(masm, true);
EmitReturnFromIC(masm);
@ -3087,13 +3174,6 @@ bool ICSetProp_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
return true;
}
void ICSetProp_Fallback::Compiler::postGenerateStubCode(MacroAssembler& masm,
Handle<JitCode*> code) {
BailoutReturnStub kind = BailoutReturnStub::SetProp;
void* address = code->raw() + bailoutReturnOffset_.offset();
cx->realm()->jitRealm()->initBailoutReturnAddr(address, getKey(), kind);
}
//
// Call_Fallback
//
@ -3886,7 +3966,7 @@ bool DoSpreadCallFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
void ICCallStubCompiler::pushCallArguments(MacroAssembler& masm,
void ICStubCompilerBase::pushCallArguments(MacroAssembler& masm,
AllocatableGeneralRegisterSet regs,
Register argcReg, bool isJitCall,
bool isConstructing) {
@ -4195,7 +4275,7 @@ void ICCallStubCompiler::pushArrayArguments(
masm.bind(&copyDone);
}
bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emitCall(bool isSpread, bool isConstructing) {
MOZ_ASSERT(R0 == JSReturnOperand);
// Values are on the stack left-to-right. Calling convention wants them
@ -4204,7 +4284,7 @@ bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
if (MOZ_UNLIKELY(isSpread_)) {
if (MOZ_UNLIKELY(isSpread)) {
// Push a stub frame so that we can perform a non-tail call.
enterStubFrame(masm, R1.scratchReg());
@ -4213,22 +4293,26 @@ bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
// calling enterStubFrame.
// newTarget
if (isConstructing_) {
uint32_t valueOffset = 0;
if (isConstructing) {
masm.pushValue(Address(BaselineFrameReg, STUB_FRAME_SIZE));
valueOffset++;
}
// array
uint32_t valueOffset = isConstructing_;
masm.pushValue(Address(BaselineFrameReg,
valueOffset++ * sizeof(Value) + STUB_FRAME_SIZE));
valueOffset * sizeof(Value) + STUB_FRAME_SIZE));
valueOffset++;
// this
masm.pushValue(Address(BaselineFrameReg,
valueOffset++ * sizeof(Value) + STUB_FRAME_SIZE));
valueOffset * sizeof(Value) + STUB_FRAME_SIZE));
valueOffset++;
// callee
masm.pushValue(Address(BaselineFrameReg,
valueOffset++ * sizeof(Value) + STUB_FRAME_SIZE));
valueOffset * sizeof(Value) + STUB_FRAME_SIZE));
valueOffset++;
masm.push(masm.getStackPointer());
masm.push(ICStubReg);
@ -4255,7 +4339,7 @@ bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
regs.take(R0.scratchReg()); // argc.
pushCallArguments(masm, regs, R0.scratchReg(), /* isJitCall = */ false,
isConstructing_);
isConstructing);
masm.push(masm.getStackPointer());
masm.push(R0.scratchReg());
@ -4276,7 +4360,14 @@ bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
// Ion inlined frames. The return address pushed onto reconstructed stack
// will point here.
assumeStubFrame();
bailoutReturnOffset_.bind(masm.currentOffset());
MOZ_ASSERT(!isSpread);
if (isConstructing) {
code.initBailoutReturnOffset(BailoutReturnKind::New, masm.currentOffset());
} else {
code.initBailoutReturnOffset(BailoutReturnKind::Call, masm.currentOffset());
}
// Load passed-in ThisV into R1 just in case it's needed. Need to do this
// before we leave the stub frame since that info will be lost.
@ -4287,7 +4378,7 @@ bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
// If this is a |constructing| call, if the callee returns a non-object, we
// replace it with the |this| object passed in.
if (isConstructing_) {
if (isConstructing) {
MOZ_ASSERT(JSReturnOperand == R0);
Label skipThisReplace;
@ -4315,16 +4406,20 @@ bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
return true;
}
void ICCall_Fallback::Compiler::postGenerateStubCode(MacroAssembler& masm,
Handle<JitCode*> code) {
if (MOZ_UNLIKELY(isSpread_)) {
return;
}
bool FallbackICCodeCompiler::emit_Call() {
return emitCall(/* isSpread = */ false, /* isConstructing = */ false);
}
void* address = code->raw() + bailoutReturnOffset_.offset();
BailoutReturnStub kind =
isConstructing_ ? BailoutReturnStub::New : BailoutReturnStub::Call;
cx->realm()->jitRealm()->initBailoutReturnAddr(address, getKey(), kind);
bool FallbackICCodeCompiler::emit_CallConstructing() {
return emitCall(/* isSpread = */ false, /* isConstructing = */ true);
}
bool FallbackICCodeCompiler::emit_SpreadCall() {
return emitCall(/* isSpread = */ true, /* isConstructing = */ false);
}
bool FallbackICCodeCompiler::emit_SpreadCallConstructing() {
return emitCall(/* isSpread = */ true, /* isConstructing = */ true);
}
bool ICCallScriptedCompiler::generateStubCode(MacroAssembler& masm) {
@ -5281,7 +5376,7 @@ bool DoGetIteratorFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICGetIterator_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_GetIterator() {
EmitRestoreTailCallReg(masm);
// Sync stack for the decompiler.
@ -5339,7 +5434,7 @@ bool DoInstanceOfFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICInstanceOf_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_InstanceOf() {
EmitRestoreTailCallReg(masm);
// Sync stack for the decompiler.
@ -5375,7 +5470,7 @@ bool DoTypeOfFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICTypeOf_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_TypeOf() {
EmitRestoreTailCallReg(masm);
masm.pushValue(R0);
@ -5464,7 +5559,7 @@ bool DoRestFallback(JSContext* cx, BaselineFrame* frame, ICRest_Fallback* stub,
return true;
}
bool ICRest_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_Rest() {
EmitRestoreTailCallReg(masm);
masm.push(ICStubReg);
@ -5531,7 +5626,7 @@ bool DoUnaryArithFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICUnaryArith_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_UnaryArith() {
MOZ_ASSERT(R0 == JSReturnOperand);
// Restore the tail call register.
@ -5655,7 +5750,7 @@ bool DoBinaryArithFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICBinaryArith_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_BinaryArith() {
MOZ_ASSERT(R0 == JSReturnOperand);
// Restore the tail call register.
@ -5752,7 +5847,7 @@ bool DoCompareFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICCompare_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_Compare() {
MOZ_ASSERT(R0 == JSReturnOperand);
// Restore the tail call register.
@ -5813,7 +5908,7 @@ bool DoNewArrayFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICNewArray_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_NewArray() {
EmitRestoreTailCallReg(masm);
masm.push(R0.scratchReg()); // length
@ -5868,7 +5963,7 @@ bool DoNewObjectFallback(JSContext* cx, BaselineFrame* frame,
return true;
}
bool ICNewObject_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
bool FallbackICCodeCompiler::emit_NewObject() {
EmitRestoreTailCallReg(masm);
masm.push(ICStubReg); // stub.
@ -5879,5 +5974,42 @@ bool ICNewObject_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
return tailCallVM<Fn, DoNewObjectFallback>(masm);
}
bool JitRuntime::generateBaselineICFallbackCode(JSContext* cx) {
StackMacroAssembler masm;
BaselineICFallbackCode& fallbackCode = baselineICFallbackCode_.ref();
FallbackICCodeCompiler compiler(cx, fallbackCode, masm);
JitSpew(JitSpew_Codegen, "# Emitting Baseline IC fallback code");
#define EMIT_CODE(kind) \
{ \
uint32_t offset = startTrampolineCode(masm); \
InitMacroAssemblerForICStub(masm); \
if (!compiler.emit_##kind()) { \
return false; \
} \
fallbackCode.initOffset(BaselineICFallbackKind::kind, offset); \
}
IC_BASELINE_FALLBACK_CODE_KIND_LIST(EMIT_CODE)
#undef EMIT_CODE
Linker linker(masm, "BaselineICFallback");
JitCode* code = linker.newCode(cx, CodeKind::Other);
if (!code) {
return false;
}
#ifdef JS_ION_PERF
writePerfSpewerJitCodeProfile(code, "BaselineICFallback");
#endif
#ifdef MOZ_VTUNE
vtune::MarkStub(code, "BaselineICFallback");
#endif
fallbackCode.initCode(code);
return true;
}
} // namespace jit
} // namespace js

View File

@ -503,7 +503,6 @@ class ICStub {
Updated = 0x4
};
void traceCode(JSTracer* trc, const char* name);
void updateCode(JitCode* stubCode);
void trace(JSTracer* trc);
@ -520,6 +519,16 @@ class ICStub {
return result;
}
template <typename T, typename... Args>
static T* NewFallback(JSContext* cx, ICStubSpace* space, TrampolinePtr code,
Args&&... args) {
T* result = space->allocate<T>(code, std::forward<Args>(args)...);
if (MOZ_UNLIKELY(!result)) {
ReportOutOfMemory(cx);
}
return result;
}
protected:
// The raw jitcode to call for this stub.
uint8_t* stubCode_;
@ -537,8 +546,8 @@ class ICStub {
Trait trait_ : 3;
Kind kind_ : 13;
inline ICStub(Kind kind, JitCode* stubCode)
: stubCode_(stubCode->raw()),
inline ICStub(Kind kind, uint8_t* stubCode)
: stubCode_(stubCode),
next_(nullptr),
extra_(0),
trait_(Regular),
@ -546,14 +555,22 @@ class ICStub {
MOZ_ASSERT(stubCode != nullptr);
}
inline ICStub(Kind kind, Trait trait, JitCode* stubCode)
: stubCode_(stubCode->raw()),
inline ICStub(Kind kind, JitCode* stubCode) : ICStub(kind, stubCode->raw()) {
MOZ_ASSERT(stubCode != nullptr);
}
inline ICStub(Kind kind, Trait trait, uint8_t* stubCode)
: stubCode_(stubCode),
next_(nullptr),
extra_(0),
trait_(trait),
kind_(kind) {
MOZ_ASSERT(stubCode != nullptr);
}
inline ICStub(Kind kind, Trait trait, JitCode* stubCode)
: ICStub(kind, trait, stubCode->raw()) {
MOZ_ASSERT(stubCode != nullptr);
}
inline Trait trait() const {
// Workaround for MSVC reading trait_ as signed value.
@ -640,7 +657,15 @@ class ICStub {
inline ICStub** addressOfNext() { return &next_; }
inline JitCode* jitCode() { return JitCode::FromExecutable(stubCode_); }
bool usesTrampolineCode() const {
// All fallback code is stored in a single JitCode instance, so we can't
// call JitCode::FromExecutable on the raw pointer.
return isFallback() || isTypeMonitor_Fallback() || isTypeUpdate_Fallback();
}
JitCode* jitCode() {
MOZ_ASSERT(!usesTrampolineCode());
return JitCode::FromExecutable(stubCode_);
}
inline uint8_t* rawStubCode() const { return stubCode_; }
@ -705,15 +730,15 @@ class ICFallbackStub : public ICStub {
// last stub's "next_" field.
ICStub** lastStubPtrAddr_;
ICFallbackStub(Kind kind, JitCode* stubCode)
: ICStub(kind, ICStub::Fallback, stubCode),
ICFallbackStub(Kind kind, TrampolinePtr stubCode)
: ICStub(kind, ICStub::Fallback, stubCode.value),
icEntry_(nullptr),
state_(),
enteredCount_(0),
lastStubPtrAddr_(nullptr) {}
ICFallbackStub(Kind kind, Trait trait, JitCode* stubCode)
: ICStub(kind, trait, stubCode),
ICFallbackStub(Kind kind, Trait trait, TrampolinePtr stubCode)
: ICStub(kind, trait, stubCode.value),
icEntry_(nullptr),
state_(),
enteredCount_(0),
@ -954,41 +979,21 @@ class ICCacheIR_Updated : public ICUpdatedStub,
};
// Base class for stubcode compilers.
class ICStubCompiler {
// Prevent GC in the middle of stub compilation.
js::gc::AutoSuppressGC suppressGC;
class ICStubCompilerBase {
protected:
JSContext* cx;
ICStub::Kind kind;
bool inStubFrame_;
bool inStubFrame_ = false;
#ifdef DEBUG
bool entersStubFrame_;
uint32_t framePushedAtEnterStubFrame_;
bool entersStubFrame_ = false;
uint32_t framePushedAtEnterStubFrame_ = 0;
#endif
// By default the stubcode key is just the kind.
virtual int32_t getKey() const { return static_cast<int32_t>(kind); }
explicit ICStubCompilerBase(JSContext* cx) : cx(cx) {}
virtual MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) = 0;
virtual void postGenerateStubCode(MacroAssembler& masm,
Handle<JitCode*> genCode) {}
JitCode* getStubCode();
ICStubCompiler(JSContext* cx, ICStub::Kind kind)
: suppressGC(cx),
cx(cx),
kind(kind),
inStubFrame_(false)
#ifdef DEBUG
,
entersStubFrame_(false),
framePushedAtEnterStubFrame_(0)
#endif
{
}
void pushCallArguments(MacroAssembler& masm,
AllocatableGeneralRegisterSet regs, Register argcReg,
bool isJitCall, bool isConstructing = false);
// Push a payload specialized per compiler needed to execute stubs.
void PushStubPayload(MacroAssembler& masm, Register scratch);
@ -1056,6 +1061,24 @@ class ICStubCompiler {
return regs;
}
};
class ICStubCompiler : public ICStubCompilerBase {
// Prevent GC in the middle of stub compilation.
js::gc::AutoSuppressGC suppressGC;
protected:
ICStub::Kind kind;
// By default the stubcode key is just the kind.
virtual int32_t getKey() const { return static_cast<int32_t>(kind); }
virtual MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) = 0;
JitCode* getStubCode();
ICStubCompiler(JSContext* cx, ICStub::Kind kind)
: ICStubCompilerBase(cx), suppressGC(cx), kind(kind) {}
protected:
template <typename T, typename... Args>
@ -1080,23 +1103,8 @@ class ICStubCompiler {
class ICWarmUpCounter_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICWarmUpCounter_Fallback(JitCode* stubCode)
explicit ICWarmUpCounter_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(ICStub::WarmUpCounter_Fallback, stubCode) {}
public:
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::WarmUpCounter_Fallback) {}
ICWarmUpCounter_Fallback* getStub(ICStubSpace* space) override {
return newStub<ICWarmUpCounter_Fallback>(space, getStubCode());
}
};
};
// Monitored fallback stubs - as the name implies.
@ -1106,7 +1114,7 @@ class ICMonitoredFallbackStub : public ICFallbackStub {
// getFallbackMonitorStub if needed.
ICTypeMonitor_Fallback* fallbackMonitorStub_;
ICMonitoredFallbackStub(Kind kind, JitCode* stubCode)
ICMonitoredFallbackStub(Kind kind, TrampolinePtr stubCode)
: ICFallbackStub(kind, ICStub::MonitoredFallback, stubCode),
fallbackMonitorStub_(nullptr) {}
@ -1251,10 +1259,10 @@ class ICTypeMonitor_Fallback : public ICStub {
static const uint32_t BYTECODE_INDEX = (1 << 23) - 1;
ICTypeMonitor_Fallback(JitCode* stubCode,
ICTypeMonitor_Fallback(TrampolinePtr stubCode,
ICMonitoredFallbackStub* mainFallbackStub,
uint32_t argumentIndex)
: ICStub(ICStub::TypeMonitor_Fallback, stubCode),
uint32_t argumentIndex = BYTECODE_INDEX)
: ICStub(ICStub::TypeMonitor_Fallback, stubCode.value),
mainFallbackStub_(mainFallbackStub),
firstMonitorStub_(thisFromCtor()),
lastMonitorStubPtrAddr_(nullptr),
@ -1348,31 +1356,6 @@ class ICTypeMonitor_Fallback : public ICStub {
HandleValue val);
void resetMonitorStubChain(Zone* zone);
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
ICMonitoredFallbackStub* mainFallbackStub_;
uint32_t argumentIndex_;
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
Compiler(JSContext* cx, ICMonitoredFallbackStub* mainFallbackStub)
: ICStubCompiler(cx, ICStub::TypeMonitor_Fallback),
mainFallbackStub_(mainFallbackStub),
argumentIndex_(BYTECODE_INDEX) {}
Compiler(JSContext* cx, uint32_t argumentIndex)
: ICStubCompiler(cx, ICStub::TypeMonitor_Fallback),
mainFallbackStub_(nullptr),
argumentIndex_(argumentIndex) {}
ICTypeMonitor_Fallback* getStub(ICStubSpace* space) override {
return newStub<ICTypeMonitor_Fallback>(space, getStubCode(),
mainFallbackStub_, argumentIndex_);
}
};
};
class ICTypeMonitor_PrimitiveSet : public TypeCheckPrimitiveSetStub {
@ -1494,23 +1477,8 @@ class ICTypeMonitor_AnyValue : public ICStub {
class ICTypeUpdate_Fallback : public ICStub {
friend class ICStubSpace;
explicit ICTypeUpdate_Fallback(JitCode* stubCode)
: ICStub(ICStub::TypeUpdate_Fallback, stubCode) {}
public:
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::TypeUpdate_Fallback) {}
ICTypeUpdate_Fallback* getStub(ICStubSpace* space) override {
return newStub<ICTypeUpdate_Fallback>(space, getStubCode());
}
};
explicit ICTypeUpdate_Fallback(TrampolinePtr stubCode)
: ICStub(ICStub::TypeUpdate_Fallback, stubCode.value) {}
};
class ICTypeUpdate_PrimitiveSet : public TypeCheckPrimitiveSetStub {
@ -1633,25 +1601,11 @@ class ICTypeUpdate_AnyValue : public ICStub {
class ICToBool_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICToBool_Fallback(JitCode* stubCode)
explicit ICToBool_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(ICStub::ToBool_Fallback, stubCode) {}
public:
static const uint32_t MAX_OPTIMIZED_STUBS = 8;
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::ToBool_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICToBool_Fallback>(space, getStubCode());
}
};
};
// GetElem
@ -1661,7 +1615,7 @@ class ICToBool_Fallback : public ICFallbackStub {
class ICGetElem_Fallback : public ICMonitoredFallbackStub {
friend class ICStubSpace;
explicit ICGetElem_Fallback(JitCode* stubCode)
explicit ICGetElem_Fallback(TrampolinePtr stubCode)
: ICMonitoredFallbackStub(ICStub::GetElem_Fallback, stubCode) {}
static const uint16_t EXTRA_NEGATIVE_INDEX = 0x1;
@ -1673,30 +1627,6 @@ class ICGetElem_Fallback : public ICMonitoredFallbackStub {
void setSawNonIntegerIndex() { extra_ |= SAW_NON_INTEGER_INDEX_BIT; }
bool sawNonIntegerIndex() const { return extra_ & SAW_NON_INTEGER_INDEX_BIT; }
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
protected:
CodeOffset bailoutReturnOffset_;
bool hasReceiver_;
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
void postGenerateStubCode(MacroAssembler& masm,
Handle<JitCode*> code) override;
virtual int32_t getKey() const override {
return static_cast<int32_t>(kind) |
(static_cast<int32_t>(hasReceiver_) << 16);
}
public:
explicit Compiler(JSContext* cx, bool hasReceiver = false)
: ICStubCompiler(cx, ICStub::GetElem_Fallback),
hasReceiver_(hasReceiver) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICGetElem_Fallback>(space, getStubCode());
}
};
};
// SetElem
@ -1706,7 +1636,7 @@ class ICGetElem_Fallback : public ICMonitoredFallbackStub {
class ICSetElem_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICSetElem_Fallback(JitCode* stubCode)
explicit ICSetElem_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(ICStub::SetElem_Fallback, stubCode) {}
static const size_t HasDenseAddFlag = 0x1;
@ -1718,20 +1648,6 @@ class ICSetElem_Fallback : public ICFallbackStub {
void noteHasTypedArrayOOB() { extra_ |= HasTypedArrayOOBFlag; }
bool hasTypedArrayOOB() const { return extra_ & HasTypedArrayOOBFlag; }
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::SetElem_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICSetElem_Fallback>(space, getStubCode());
}
};
};
// In
@ -1739,22 +1655,8 @@ class ICSetElem_Fallback : public ICFallbackStub {
class ICIn_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICIn_Fallback(JitCode* stubCode)
explicit ICIn_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(ICStub::In_Fallback, stubCode) {}
public:
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::In_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICIn_Fallback>(space, getStubCode());
}
};
};
// HasOwn
@ -1762,22 +1664,8 @@ class ICIn_Fallback : public ICFallbackStub {
class ICHasOwn_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICHasOwn_Fallback(JitCode* stubCode)
explicit ICHasOwn_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(ICStub::HasOwn_Fallback, stubCode) {}
public:
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::HasOwn_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICHasOwn_Fallback>(space, getStubCode());
}
};
};
// GetName
@ -1786,22 +1674,8 @@ class ICHasOwn_Fallback : public ICFallbackStub {
class ICGetName_Fallback : public ICMonitoredFallbackStub {
friend class ICStubSpace;
explicit ICGetName_Fallback(JitCode* stubCode)
explicit ICGetName_Fallback(TrampolinePtr stubCode)
: ICMonitoredFallbackStub(ICStub::GetName_Fallback, stubCode) {}
public:
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::GetName_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICGetName_Fallback>(space, getStubCode());
}
};
};
// BindName
@ -1809,22 +1683,8 @@ class ICGetName_Fallback : public ICMonitoredFallbackStub {
class ICBindName_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICBindName_Fallback(JitCode* stubCode)
explicit ICBindName_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(ICStub::BindName_Fallback, stubCode) {}
public:
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::BindName_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICBindName_Fallback>(space, getStubCode());
}
};
};
// GetIntrinsic
@ -1832,22 +1692,8 @@ class ICBindName_Fallback : public ICFallbackStub {
class ICGetIntrinsic_Fallback : public ICMonitoredFallbackStub {
friend class ICStubSpace;
explicit ICGetIntrinsic_Fallback(JitCode* stubCode)
explicit ICGetIntrinsic_Fallback(TrampolinePtr stubCode)
: ICMonitoredFallbackStub(ICStub::GetIntrinsic_Fallback, stubCode) {}
public:
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::GetIntrinsic_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICGetIntrinsic_Fallback>(space, getStubCode());
}
};
};
// GetProp
@ -1857,7 +1703,7 @@ class ICGetIntrinsic_Fallback : public ICMonitoredFallbackStub {
class ICGetProp_Fallback : public ICMonitoredFallbackStub {
friend class ICStubSpace;
explicit ICGetProp_Fallback(JitCode* stubCode)
explicit ICGetProp_Fallback(TrampolinePtr stubCode)
: ICMonitoredFallbackStub(ICStub::GetProp_Fallback, stubCode) {}
public:
@ -1867,29 +1713,6 @@ class ICGetProp_Fallback : public ICMonitoredFallbackStub {
bool hasAccessedGetter() const {
return extra_ & (1u << ACCESSED_GETTER_BIT);
}
class Compiler : public ICStubCompiler {
protected:
CodeOffset bailoutReturnOffset_;
bool hasReceiver_;
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
void postGenerateStubCode(MacroAssembler& masm,
Handle<JitCode*> code) override;
virtual int32_t getKey() const override {
return static_cast<int32_t>(kind) |
(static_cast<int32_t>(hasReceiver_) << 16);
}
public:
explicit Compiler(JSContext* cx, bool hasReceiver = false)
: ICStubCompiler(cx, ICStub::GetProp_Fallback),
hasReceiver_(hasReceiver) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICGetProp_Fallback>(space, getStubCode());
}
};
};
// SetProp
@ -1901,25 +1724,8 @@ class ICGetProp_Fallback : public ICMonitoredFallbackStub {
class ICSetProp_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICSetProp_Fallback(JitCode* stubCode)
explicit ICSetProp_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(ICStub::SetProp_Fallback, stubCode) {}
public:
class Compiler : public ICStubCompiler {
protected:
CodeOffset bailoutReturnOffset_;
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
void postGenerateStubCode(MacroAssembler& masm,
Handle<JitCode*> code) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::SetProp_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICSetProp_Fallback>(space, getStubCode());
}
};
};
// Call
@ -1939,9 +1745,6 @@ class ICCallStubCompiler : public ICStubCompiler {
enum FunApplyThing { FunApply_MagicArgs, FunApply_Array };
void pushCallArguments(MacroAssembler& masm,
AllocatableGeneralRegisterSet regs, Register argcReg,
bool isJitCall, bool isConstructing = false);
void pushSpreadCallArguments(MacroAssembler& masm,
AllocatableGeneralRegisterSet regs,
Register argcReg, bool isJitCall,
@ -1964,7 +1767,7 @@ class ICCall_Fallback : public ICMonitoredFallbackStub {
static const uint32_t MAX_OPTIMIZED_STUBS = 16;
private:
explicit ICCall_Fallback(JitCode* stubCode)
explicit ICCall_Fallback(TrampolinePtr stubCode)
: ICMonitoredFallbackStub(ICStub::Call_Fallback, stubCode) {}
public:
@ -1973,33 +1776,6 @@ class ICCall_Fallback : public ICMonitoredFallbackStub {
// Return hasStub(Call_AnyNative) after Call_AnyNative stub is added.
return false;
}
// Compiler for this stub kind.
class Compiler : public ICCallStubCompiler {
protected:
bool isConstructing_;
bool isSpread_;
CodeOffset bailoutReturnOffset_;
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
void postGenerateStubCode(MacroAssembler& masm,
Handle<JitCode*> code) override;
virtual int32_t getKey() const override {
return static_cast<int32_t>(kind) |
(static_cast<int32_t>(isSpread_) << 16) |
(static_cast<int32_t>(isConstructing_) << 17);
}
public:
Compiler(JSContext* cx, bool isConstructing, bool isSpread)
: ICCallStubCompiler(cx, ICStub::Call_Fallback),
isConstructing_(isConstructing),
isSpread_(isSpread) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICCall_Fallback>(space, getStubCode());
}
};
};
class ICCall_Scripted : public ICMonitoredStub {
@ -2421,22 +2197,8 @@ class ICCall_ConstStringSplit : public ICMonitoredStub {
class ICGetIterator_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICGetIterator_Fallback(JitCode* stubCode)
explicit ICGetIterator_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(ICStub::GetIterator_Fallback, stubCode) {}
public:
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::GetIterator_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICGetIterator_Fallback>(space, getStubCode());
}
};
};
// InstanceOf
@ -2444,22 +2206,8 @@ class ICGetIterator_Fallback : public ICFallbackStub {
class ICInstanceOf_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICInstanceOf_Fallback(JitCode* stubCode)
explicit ICInstanceOf_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(ICStub::InstanceOf_Fallback, stubCode) {}
public:
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::InstanceOf_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICInstanceOf_Fallback>(space, getStubCode());
}
};
};
// TypeOf
@ -2468,24 +2216,11 @@ class ICInstanceOf_Fallback : public ICFallbackStub {
class ICTypeOf_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICTypeOf_Fallback(JitCode* stubCode)
explicit ICTypeOf_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(ICStub::TypeOf_Fallback, stubCode) {}
public:
static const uint32_t MAX_OPTIMIZED_STUBS = 6;
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::TypeOf_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICTypeOf_Fallback>(space, getStubCode());
}
};
};
class ICRest_Fallback : public ICFallbackStub {
@ -2493,7 +2228,7 @@ class ICRest_Fallback : public ICFallbackStub {
GCPtrArrayObject templateObject_;
ICRest_Fallback(JitCode* stubCode, ArrayObject* templateObject)
ICRest_Fallback(TrampolinePtr stubCode, ArrayObject* templateObject)
: ICFallbackStub(ICStub::Rest_Fallback, stubCode),
templateObject_(templateObject) {}
@ -2501,21 +2236,6 @@ class ICRest_Fallback : public ICFallbackStub {
static const uint32_t MAX_OPTIMIZED_STUBS = 8;
GCPtrArrayObject& templateObject() { return templateObject_; }
class Compiler : public ICStubCompiler {
protected:
RootedArrayObject templateObject;
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
Compiler(JSContext* cx, ArrayObject* templateObject)
: ICStubCompiler(cx, ICStub::Rest_Fallback),
templateObject(cx, templateObject) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICRest_Fallback>(space, getStubCode(), templateObject);
}
};
};
// UnaryArith
@ -2527,7 +2247,7 @@ class ICRest_Fallback : public ICFallbackStub {
class ICUnaryArith_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICUnaryArith_Fallback(JitCode* stubCode)
explicit ICUnaryArith_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(UnaryArith_Fallback, stubCode) {
extra_ = 0;
}
@ -2535,20 +2255,6 @@ class ICUnaryArith_Fallback : public ICFallbackStub {
public:
bool sawDoubleResult() { return extra_; }
void setSawDoubleResult() { extra_ = 1; }
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::UnaryArith_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICUnaryArith_Fallback>(space, getStubCode());
}
};
};
// Compare
@ -2564,23 +2270,8 @@ class ICUnaryArith_Fallback : public ICFallbackStub {
class ICCompare_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICCompare_Fallback(JitCode* stubCode)
explicit ICCompare_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(ICStub::Compare_Fallback, stubCode) {}
public:
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::Compare_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICCompare_Fallback>(space, getStubCode());
}
};
};
// BinaryArith
@ -2591,7 +2282,7 @@ class ICCompare_Fallback : public ICFallbackStub {
class ICBinaryArith_Fallback : public ICFallbackStub {
friend class ICStubSpace;
explicit ICBinaryArith_Fallback(JitCode* stubCode)
explicit ICBinaryArith_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(BinaryArith_Fallback, stubCode) {
extra_ = 0;
}
@ -2603,20 +2294,6 @@ class ICBinaryArith_Fallback : public ICFallbackStub {
bool sawDoubleResult() const { return extra_ & SAW_DOUBLE_RESULT_BIT; }
void setSawDoubleResult() { extra_ |= SAW_DOUBLE_RESULT_BIT; }
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::BinaryArith_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICBinaryArith_Fallback>(space, getStubCode());
}
};
};
// JSOP_NEWARRAY
@ -2630,26 +2307,12 @@ class ICNewArray_Fallback : public ICFallbackStub {
// template object itself is not.
GCPtrObjectGroup templateGroup_;
ICNewArray_Fallback(JitCode* stubCode, ObjectGroup* templateGroup)
ICNewArray_Fallback(TrampolinePtr stubCode, ObjectGroup* templateGroup)
: ICFallbackStub(ICStub::NewArray_Fallback, stubCode),
templateObject_(nullptr),
templateGroup_(templateGroup) {}
public:
class Compiler : public ICStubCompiler {
RootedObjectGroup templateGroup;
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
Compiler(JSContext* cx, ObjectGroup* templateGroup)
: ICStubCompiler(cx, ICStub::NewArray_Fallback),
templateGroup(cx, templateGroup) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICNewArray_Fallback>(space, getStubCode(), templateGroup);
}
};
GCPtrObject& templateObject() { return templateObject_; }
void setTemplateObject(JSObject* obj) {
@ -2672,23 +2335,11 @@ class ICNewObject_Fallback : public ICFallbackStub {
GCPtrObject templateObject_;
explicit ICNewObject_Fallback(JitCode* stubCode)
explicit ICNewObject_Fallback(TrampolinePtr stubCode)
: ICFallbackStub(ICStub::NewObject_Fallback, stubCode),
templateObject_(nullptr) {}
public:
class Compiler : public ICStubCompiler {
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::NewObject_Fallback) {}
ICStub* getStub(ICStubSpace* space) override {
return newStub<ICNewObject_Fallback>(space, getStubCode());
}
};
GCPtrObject& templateObject() { return templateObject_; }
void setTemplateObject(JSObject* obj) { templateObject_ = obj; }

View File

@ -10,7 +10,8 @@
namespace js {
namespace jit {
// List of IC stub kinds that can only run in Baseline.
// List of Baseline IC stub kinds. The stub kind determines the structure of the
// ICStub data.
#define IC_BASELINE_STUB_KIND_LIST(_) \
_(WarmUpCounter_Fallback) \
\
@ -60,7 +61,6 @@ namespace jit {
_(GetIterator_Fallback) \
\
_(InstanceOf_Fallback) \
_(InstanceOf_Function) \
\
_(TypeOf_Fallback) \
\
@ -76,6 +76,41 @@ namespace jit {
_(CacheIR_Monitored) \
_(CacheIR_Updated)
// List of fallback trampolines. Each of these fallback trampolines exists as
// part of the JitRuntime. Note that some fallback stubs in previous list may
// have multiple trampolines in this list. For example, Call_Fallback has
// constructing/spread variants here with different calling conventions needing
// different trampolines.
#define IC_BASELINE_FALLBACK_CODE_KIND_LIST(_) \
_(WarmUpCounter) \
_(TypeMonitor) \
_(TypeUpdate) \
_(NewArray) \
_(NewObject) \
_(ToBool) \
_(UnaryArith) \
_(Call) \
_(CallConstructing) \
_(SpreadCall) \
_(SpreadCallConstructing) \
_(GetElem) \
_(GetElemSuper) \
_(SetElem) \
_(In) \
_(HasOwn) \
_(GetName) \
_(BindName) \
_(GetIntrinsic) \
_(SetProp) \
_(GetIterator) \
_(InstanceOf) \
_(TypeOf) \
_(Rest) \
_(BinaryArith) \
_(Compare) \
_(GetProp) \
_(GetPropSuper)
} // namespace jit
} // namespace js

View File

@ -200,6 +200,23 @@ bool JitRuntime::initialize(JSContext* cx) {
JitContext jctx(cx, nullptr);
if (!generateTrampolines(cx)) {
return false;
}
if (!generateBaselineICFallbackCode(cx)) {
return false;
}
jitcodeGlobalTable_ = cx->new_<JitcodeGlobalTable>();
if (!jitcodeGlobalTable_) {
return false;
}
return true;
}
bool JitRuntime::generateTrampolines(JSContext* cx) {
StackMacroAssembler masm;
Label bailoutTail;
@ -305,11 +322,6 @@ bool JitRuntime::initialize(JSContext* cx) {
vtune::MarkStub(trampolineCode_, "Trampolines");
#endif
jitcodeGlobalTable_ = cx->new_<JitcodeGlobalTable>();
if (!jitcodeGlobalTable_) {
return false;
}
return true;
}
@ -561,14 +573,6 @@ void JitRealm::sweep(JS::Realm* realm) {
stubCodes_->sweep();
// If the sweep removed a bailout Fallback stub, nullptr the corresponding
// return addr.
for (auto& it : bailoutReturnStubInfo_) {
if (!stubCodes_->lookup(it.key)) {
it = BailoutReturnStubInfo();
}
}
for (ReadBarrieredJitCode& stub : stubs_) {
if (stub && IsAboutToBeFinalized(&stub)) {
stub.set(nullptr);

View File

@ -9,11 +9,13 @@
#include "mozilla/Array.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/MemoryReporting.h"
#include <utility>
#include "builtin/TypedObject.h"
#include "jit/BaselineICList.h"
#include "jit/CompileInfo.h"
#include "jit/ICStubSpace.h"
#include "jit/IonCode.h"
@ -62,6 +64,60 @@ struct EnterJitData {
bool constructing;
};
enum class BaselineICFallbackKind {
#define DEF_ENUM_KIND(kind) kind,
IC_BASELINE_FALLBACK_CODE_KIND_LIST(DEF_ENUM_KIND)
#undef DEF_ENUM_KIND
Count
};
enum class BailoutReturnKind {
GetProp,
GetPropSuper,
SetProp,
GetElem,
GetElemSuper,
Call,
New,
Count
};
// Class storing code and offsets for all Baseline IC fallback trampolines. This
// is stored in JitRuntime and generated when creating the JitRuntime.
class BaselineICFallbackCode {
JitCode* code_ = nullptr;
using OffsetArray =
mozilla::EnumeratedArray<BaselineICFallbackKind,
BaselineICFallbackKind::Count, uint32_t>;
OffsetArray offsets_ = {};
// Keep track of offset into various baseline stubs' code at return
// point from called script.
using BailoutReturnArray =
mozilla::EnumeratedArray<BailoutReturnKind, BailoutReturnKind::Count,
uint32_t>;
BailoutReturnArray bailoutReturnOffsets_ = {};
public:
BaselineICFallbackCode() = default;
BaselineICFallbackCode(const BaselineICFallbackCode&) = delete;
void operator=(const BaselineICFallbackCode&) = delete;
void initOffset(BaselineICFallbackKind kind, uint32_t offset) {
offsets_[kind] = offset;
}
void initCode(JitCode* code) { code_ = code; }
void initBailoutReturnOffset(BailoutReturnKind kind, uint32_t offset) {
bailoutReturnOffsets_[kind] = offset;
}
TrampolinePtr addr(BaselineICFallbackKind kind) const {
return TrampolinePtr(code_->raw() + offsets_[kind]);
}
uint8_t* bailoutReturnAddr(BailoutReturnKind kind) const {
return code_->raw() + bailoutReturnOffsets_[kind];
}
};
typedef void (*EnterJitCode)(void* code, unsigned argc, Value* argv,
InterpreterFrame* fp, CalleeToken calleeToken,
JSObject* envChain, size_t numStackValues,
@ -155,6 +211,8 @@ class JitRuntime {
// trampolineCode_.
VMWrapperOffsets tailCallFunctionWrapperOffsets_;
MainThreadData<BaselineICFallbackCode> baselineICFallbackCode_;
// Global table of jitcode native address => bytecode address mappings.
UnprotectedData<JitcodeGlobalTable*> jitcodeGlobalTable_;
@ -181,6 +239,9 @@ class JitRuntime {
MainThreadData<uint64_t> disambiguationId_;
private:
bool generateTrampolines(JSContext* cx);
bool generateBaselineICFallbackCode(JSContext* cx);
void generateLazyLinkStub(MacroAssembler& masm);
void generateInterpreterStub(MacroAssembler& masm);
void generateDoubleToInt32ValueStub(MacroAssembler& masm);
@ -242,6 +303,10 @@ class JitRuntime {
ExecutableAllocator& execAlloc() { return execAlloc_.ref(); }
const BaselineICFallbackCode& baselineICFallbackCode() const {
return baselineICFallbackCode_.ref();
}
IonCompilationId nextCompilationId() {
return IonCompilationId(nextCompilationId_++);
}
@ -471,17 +536,6 @@ class JitZone {
void purgeIonCacheIRStubInfo() { ionCacheIRStubInfoSet_.clearAndCompact(); }
};
enum class BailoutReturnStub {
GetProp,
GetPropSuper,
SetProp,
GetElem,
GetElemSuper,
Call,
New,
Count
};
class JitRealm {
friend class JitActivation;
@ -491,20 +545,6 @@ class JitRealm {
ZoneAllocPolicy, IcStubCodeMapGCPolicy<uint32_t>>;
ICStubCodeMap* stubCodes_;
// Keep track of offset into various baseline stubs' code at return
// point from called script.
struct BailoutReturnStubInfo {
void* addr;
uint32_t key;
BailoutReturnStubInfo() : addr(nullptr), key(0) {}
BailoutReturnStubInfo(void* addr_, uint32_t key_)
: addr(addr_), key(key_) {}
};
mozilla::EnumeratedArray<BailoutReturnStub, BailoutReturnStub::Count,
BailoutReturnStubInfo>
bailoutReturnStubInfo_;
// The JitRealm stores stubs to concatenate strings inline and perform RegExp
// calls inline. These bake in zone and realm specific pointers and can't be
// stored in JitRuntime. They also are dependent on the value of
@ -557,14 +597,6 @@ class JitRealm {
}
return true;
}
void initBailoutReturnAddr(void* addr, uint32_t key, BailoutReturnStub kind) {
MOZ_ASSERT(bailoutReturnStubInfo_[kind].addr == nullptr);
bailoutReturnStubInfo_[kind] = BailoutReturnStubInfo{addr, key};
}
void* bailoutReturnAddr(BailoutReturnStub kind) {
MOZ_ASSERT(bailoutReturnStubInfo_[kind].addr);
return bailoutReturnStubInfo_[kind].addr;
}
JitRealm();
~JitRealm();

View File

@ -1645,12 +1645,14 @@ static void AdjustGeneratorResumptionValue(JSContext* cx,
cx, &genObj->as<AsyncFunctionGeneratorObject>());
// 1. `return <value>` fulfills and returns the async function's promise.
JSObject* promise = AsyncFunctionResolve(
cx, asyncGenObj, vp, AsyncFunctionResolveKind::Fulfill);
if (!promise) {
Rooted<PromiseObject*> promise(cx, asyncGenObj->promise());
if (promise->state() == JS::PromiseState::Pending) {
if (!AsyncFunctionResolve(cx, asyncGenObj, vp,
AsyncFunctionResolveKind::Fulfill)) {
getAndClearExceptionThenThrow();
return;
}
}
vp.setObject(*promise);
// 2. The generator must be closed.

View File

@ -1065,19 +1065,19 @@ WasmToken WasmTokenStream::next() {
if (consume(u"const")) {
return WasmToken(WasmToken::Const, ValType::F32, begin, cur_);
}
if (consume(u"convert_s/i32")) {
if (consume(u"convert_i32_s") || consume(u"convert_s/i32")) {
return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertSI32,
begin, cur_);
}
if (consume(u"convert_u/i32")) {
if (consume(u"convert_i32_u") || consume(u"convert_u/i32")) {
return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertUI32,
begin, cur_);
}
if (consume(u"convert_s/i64")) {
if (consume(u"convert_i64_s") || consume(u"convert_s/i64")) {
return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertSI64,
begin, cur_);
}
if (consume(u"convert_u/i64")) {
if (consume(u"convert_i64_u") || consume(u"convert_u/i64")) {
return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertUI64,
begin, cur_);
}
@ -1087,7 +1087,7 @@ WasmToken WasmTokenStream::next() {
}
break;
case 'd':
if (consume(u"demote/f64")) {
if (consume(u"demote_f64") || consume(u"demote/f64")) {
return WasmToken(WasmToken::ConversionOpcode, Op::F32DemoteF64,
begin, cur_);
}
@ -1159,7 +1159,7 @@ WasmToken WasmTokenStream::next() {
}
break;
case 'r':
if (consume(u"reinterpret/i32")) {
if (consume(u"reinterpret_i32") || consume(u"reinterpret/i32")) {
return WasmToken(WasmToken::ConversionOpcode,
Op::F32ReinterpretI32, begin, cur_);
}
@ -1209,19 +1209,19 @@ WasmToken WasmTokenStream::next() {
if (consume(u"const")) {
return WasmToken(WasmToken::Const, ValType::F64, begin, cur_);
}
if (consume(u"convert_s/i32")) {
if (consume(u"convert_i32_s") || consume(u"convert_s/i32")) {
return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertSI32,
begin, cur_);
}
if (consume(u"convert_u/i32")) {
if (consume(u"convert_i32_u") || consume(u"convert_u/i32")) {
return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertUI32,
begin, cur_);
}
if (consume(u"convert_s/i64")) {
if (consume(u"convert_i64_s") || consume(u"convert_s/i64")) {
return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertSI64,
begin, cur_);
}
if (consume(u"convert_u/i64")) {
if (consume(u"convert_i64_u") || consume(u"convert_u/i64")) {
return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertUI64,
begin, cur_);
}
@ -1299,13 +1299,13 @@ WasmToken WasmTokenStream::next() {
}
break;
case 'p':
if (consume(u"promote/f32")) {
if (consume(u"promote_f32") || consume(u"promote/f32")) {
return WasmToken(WasmToken::ConversionOpcode, Op::F64PromoteF32,
begin, cur_);
}
break;
case 'r':
if (consume(u"reinterpret/i64")) {
if (consume(u"reinterpret_i64") || consume(u"reinterpret/i64")) {
return WasmToken(WasmToken::UnaryOpcode, Op::F64ReinterpretI64,
begin, cur_);
}
@ -1377,11 +1377,11 @@ WasmToken WasmTokenStream::next() {
cur_);
}
if (consume(u"atomic.")) {
if (consume(u"rmw8_u.add")) {
if (consume(u"rmw8.add_u") || consume(u"rmw8_u.add")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicAdd8U,
begin, cur_);
}
if (consume(u"rmw16_u.add")) {
if (consume(u"rmw16.add_u") || consume(u"rmw16_u.add")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I32AtomicAdd16U, begin, cur_);
}
@ -1389,11 +1389,11 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicAdd,
begin, cur_);
}
if (consume(u"rmw8_u.and")) {
if (consume(u"rmw8.and_u") || consume(u"rmw8_u.and")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicAnd8U,
begin, cur_);
}
if (consume(u"rmw16_u.and")) {
if (consume(u"rmw16.and_u") || consume(u"rmw16_u.and")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I32AtomicAnd16U, begin, cur_);
}
@ -1401,11 +1401,11 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicAnd,
begin, cur_);
}
if (consume(u"rmw8_u.cmpxchg")) {
if (consume(u"rmw8.cmpxchg_u") || consume(u"rmw8_u.cmpxchg")) {
return WasmToken(WasmToken::AtomicCmpXchg,
ThreadOp::I32AtomicCmpXchg8U, begin, cur_);
}
if (consume(u"rmw16_u.cmpxchg")) {
if (consume(u"rmw16.cmpxchg_u") || consume(u"rmw16_u.cmpxchg")) {
return WasmToken(WasmToken::AtomicCmpXchg,
ThreadOp::I32AtomicCmpXchg16U, begin, cur_);
}
@ -1425,11 +1425,11 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::AtomicLoad, ThreadOp::I32AtomicLoad,
begin, cur_);
}
if (consume(u"rmw8_u.or")) {
if (consume(u"rmw8.or_u") || consume(u"rmw8_u.or")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicOr8U,
begin, cur_);
}
if (consume(u"rmw16_u.or")) {
if (consume(u"rmw16.or_u") || consume(u"rmw16_u.or")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicOr16U,
begin, cur_);
}
@ -1449,11 +1449,11 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::AtomicStore,
ThreadOp::I32AtomicStore, begin, cur_);
}
if (consume(u"rmw8_u.sub")) {
if (consume(u"rmw8.sub_u") || consume(u"rmw8_u.sub")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicSub8U,
begin, cur_);
}
if (consume(u"rmw16_u.sub")) {
if (consume(u"rmw16.sub_u") || consume(u"rmw16_u.sub")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I32AtomicSub16U, begin, cur_);
}
@ -1461,11 +1461,11 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicSub,
begin, cur_);
}
if (consume(u"rmw8_u.xor")) {
if (consume(u"rmw8.xor_u") || consume(u"rmw8_u.xor")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicXor8U,
begin, cur_);
}
if (consume(u"rmw16_u.xor")) {
if (consume(u"rmw16.xor_u") || consume(u"rmw16_u.xor")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I32AtomicXor16U, begin, cur_);
}
@ -1473,11 +1473,11 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicXor,
begin, cur_);
}
if (consume(u"rmw8_u.xchg")) {
if (consume(u"rmw8.xchg_u") || consume(u"rmw8_u.xchg")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I32AtomicXchg8U, begin, cur_);
}
if (consume(u"rmw16_u.xchg")) {
if (consume(u"rmw16.xchg_u") || consume(u"rmw16_u.xchg")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I32AtomicXchg16U, begin, cur_);
}
@ -1607,7 +1607,7 @@ WasmToken WasmTokenStream::next() {
}
break;
case 'r':
if (consume(u"reinterpret/f32")) {
if (consume(u"reinterpret_f32") || consume(u"reinterpret/f32")) {
return WasmToken(WasmToken::UnaryOpcode, Op::I32ReinterpretF32,
begin, cur_);
}
@ -1659,41 +1659,41 @@ WasmToken WasmTokenStream::next() {
}
break;
case 't':
if (consume(u"trunc_s/f32")) {
if (consume(u"trunc_f32_s") || consume(u"trunc_s/f32")) {
return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncSF32,
begin, cur_);
}
if (consume(u"trunc_s/f64")) {
if (consume(u"trunc_f64_s") || consume(u"trunc_s/f64")) {
return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncSF64,
begin, cur_);
}
if (consume(u"trunc_u/f32")) {
if (consume(u"trunc_f32_u") || consume(u"trunc_u/f32")) {
return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncUF32,
begin, cur_);
}
if (consume(u"trunc_u/f64")) {
if (consume(u"trunc_f64_u") || consume(u"trunc_u/f64")) {
return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncUF64,
begin, cur_);
}
if (consume(u"trunc_s:sat/f32")) {
if (consume(u"trunc_sat_f32_s") || consume(u"trunc_s:sat/f32")) {
return WasmToken(WasmToken::ExtraConversionOpcode,
MiscOp::I32TruncSSatF32, begin, cur_);
}
if (consume(u"trunc_s:sat/f64")) {
if (consume(u"trunc_sat_f64_s") || consume(u"trunc_s:sat/f64")) {
return WasmToken(WasmToken::ExtraConversionOpcode,
MiscOp::I32TruncSSatF64, begin, cur_);
}
if (consume(u"trunc_u:sat/f32")) {
if (consume(u"trunc_sat_f32_u") || consume(u"trunc_u:sat/f32")) {
return WasmToken(WasmToken::ExtraConversionOpcode,
MiscOp::I32TruncUSatF32, begin, cur_);
}
if (consume(u"trunc_u:sat/f64")) {
if (consume(u"trunc_sat_f64_u") || consume(u"trunc_u:sat/f64")) {
return WasmToken(WasmToken::ExtraConversionOpcode,
MiscOp::I32TruncUSatF64, begin, cur_);
}
break;
case 'w':
if (consume(u"wrap/i64")) {
if (consume(u"wrap_i64") || consume(u"wrap/i64")) {
return WasmToken(WasmToken::ConversionOpcode, Op::I32WrapI64,
begin, cur_);
}
@ -1723,15 +1723,15 @@ WasmToken WasmTokenStream::next() {
cur_);
}
if (consume(u"atomic.")) {
if (consume(u"rmw8_u.add")) {
if (consume(u"rmw8.add_u") || consume(u"rmw8_u.add")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicAdd8U,
begin, cur_);
}
if (consume(u"rmw16_u.add")) {
if (consume(u"rmw16.add_u") || consume(u"rmw16_u.add")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I64AtomicAdd16U, begin, cur_);
}
if (consume(u"rmw32_u.add")) {
if (consume(u"rmw32.add_u") || consume(u"rmw32_u.add")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I64AtomicAdd32U, begin, cur_);
}
@ -1739,15 +1739,15 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicAdd,
begin, cur_);
}
if (consume(u"rmw8_u.and")) {
if (consume(u"rmw8.and_u") || consume(u"rmw8_u.and")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicAnd8U,
begin, cur_);
}
if (consume(u"rmw16_u.and")) {
if (consume(u"rmw16.and_u") || consume(u"rmw16_u.and")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I64AtomicAnd16U, begin, cur_);
}
if (consume(u"rmw32_u.and")) {
if (consume(u"rmw32.and_u") || consume(u"rmw32_u.and")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I64AtomicAnd32U, begin, cur_);
}
@ -1755,15 +1755,15 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicAnd,
begin, cur_);
}
if (consume(u"rmw8_u.cmpxchg")) {
if (consume(u"rmw8.cmpxchg_u") || consume(u"rmw8_u.cmpxchg")) {
return WasmToken(WasmToken::AtomicCmpXchg,
ThreadOp::I64AtomicCmpXchg8U, begin, cur_);
}
if (consume(u"rmw16_u.cmpxchg")) {
if (consume(u"rmw16.cmpxchg_u") || consume(u"rmw16_u.cmpxchg")) {
return WasmToken(WasmToken::AtomicCmpXchg,
ThreadOp::I64AtomicCmpXchg16U, begin, cur_);
}
if (consume(u"rmw32_u.cmpxchg")) {
if (consume(u"rmw32.cmpxchg_u") || consume(u"rmw32_u.cmpxchg")) {
return WasmToken(WasmToken::AtomicCmpXchg,
ThreadOp::I64AtomicCmpXchg32U, begin, cur_);
}
@ -1787,15 +1787,15 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::AtomicLoad, ThreadOp::I64AtomicLoad,
begin, cur_);
}
if (consume(u"rmw8_u.or")) {
if (consume(u"rmw8.or_u") || consume(u"rmw8_u.or")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicOr8U,
begin, cur_);
}
if (consume(u"rmw16_u.or")) {
if (consume(u"rmw16.or_u") || consume(u"rmw16_u.or")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicOr16U,
begin, cur_);
}
if (consume(u"rmw32_u.or")) {
if (consume(u"rmw32.or_u") || consume(u"rmw32_u.or")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicOr32U,
begin, cur_);
}
@ -1819,15 +1819,15 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::AtomicStore,
ThreadOp::I64AtomicStore, begin, cur_);
}
if (consume(u"rmw8_u.sub")) {
if (consume(u"rmw8.sub_u") || consume(u"rmw8_u.sub")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicSub8U,
begin, cur_);
}
if (consume(u"rmw16_u.sub")) {
if (consume(u"rmw16.sub_u") || consume(u"rmw16_u.sub")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I64AtomicSub16U, begin, cur_);
}
if (consume(u"rmw32_u.sub")) {
if (consume(u"rmw32.sub_u") || consume(u"rmw32_u.sub")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I64AtomicSub32U, begin, cur_);
}
@ -1835,15 +1835,15 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicSub,
begin, cur_);
}
if (consume(u"rmw8_u.xor")) {
if (consume(u"rmw8.xor_u") || consume(u"rmw8_u.xor")) {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicXor8U,
begin, cur_);
}
if (consume(u"rmw16_u.xor")) {
if (consume(u"rmw16.xor_u") || consume(u"rmw16_u.xor")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I64AtomicXor16U, begin, cur_);
}
if (consume(u"rmw32_u.xor")) {
if (consume(u"rmw32.xor_u") || consume(u"rmw32_u.xor")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I64AtomicXor32U, begin, cur_);
}
@ -1851,15 +1851,15 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I64AtomicXor,
begin, cur_);
}
if (consume(u"rmw8_u.xchg")) {
if (consume(u"rmw8.xchg_u") || consume(u"rmw8_u.xchg")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I64AtomicXchg8U, begin, cur_);
}
if (consume(u"rmw16_u.xchg")) {
if (consume(u"rmw16.xchg_u") || consume(u"rmw16_u.xchg")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I64AtomicXchg16U, begin, cur_);
}
if (consume(u"rmw32_u.xchg")) {
if (consume(u"rmw32.xchg_u") || consume(u"rmw32_u.xchg")) {
return WasmToken(WasmToken::AtomicRMW,
ThreadOp::I64AtomicXchg32U, begin, cur_);
}
@ -1902,11 +1902,11 @@ WasmToken WasmTokenStream::next() {
return WasmToken(WasmToken::ComparisonOpcode, Op::I64Eq, begin,
cur_);
}
if (consume(u"extend_s/i32")) {
if (consume(u"extend_i32_s") || consume(u"extend_s/i32")) {
return WasmToken(WasmToken::ConversionOpcode, Op::I64ExtendSI32,
begin, cur_);
}
if (consume(u"extend_u/i32")) {
if (consume(u"extend_i32_u") || consume(u"extend_u/i32")) {
return WasmToken(WasmToken::ConversionOpcode, Op::I64ExtendUI32,
begin, cur_);
}
@ -2007,7 +2007,7 @@ WasmToken WasmTokenStream::next() {
}
break;
case 'r':
if (consume(u"reinterpret/f64")) {
if (consume(u"reinterpret_f64") || consume(u"reinterpret/f64")) {
return WasmToken(WasmToken::UnaryOpcode, Op::I64ReinterpretF64,
begin, cur_);
}
@ -2062,35 +2062,35 @@ WasmToken WasmTokenStream::next() {
}
break;
case 't':
if (consume(u"trunc_s/f32")) {
if (consume(u"trunc_f32_s") || consume(u"trunc_s/f32")) {
return WasmToken(WasmToken::ConversionOpcode, Op::I64TruncSF32,
begin, cur_);
}
if (consume(u"trunc_s/f64")) {
if (consume(u"trunc_f64_s") || consume(u"trunc_s/f64")) {
return WasmToken(WasmToken::ConversionOpcode, Op::I64TruncSF64,
begin, cur_);
}
if (consume(u"trunc_u/f32")) {
if (consume(u"trunc_f32_u") || consume(u"trunc_u/f32")) {
return WasmToken(WasmToken::ConversionOpcode, Op::I64TruncUF32,
begin, cur_);
}
if (consume(u"trunc_u/f64")) {
if (consume(u"trunc_f64_u") || consume(u"trunc_u/f64")) {
return WasmToken(WasmToken::ConversionOpcode, Op::I64TruncUF64,
begin, cur_);
}
if (consume(u"trunc_s:sat/f32")) {
if (consume(u"trunc_sat_f32_s") || consume(u"trunc_s:sat/f32")) {
return WasmToken(WasmToken::ExtraConversionOpcode,
MiscOp::I64TruncSSatF32, begin, cur_);
}
if (consume(u"trunc_s:sat/f64")) {
if (consume(u"trunc_sat_f64_s") || consume(u"trunc_s:sat/f64")) {
return WasmToken(WasmToken::ExtraConversionOpcode,
MiscOp::I64TruncSSatF64, begin, cur_);
}
if (consume(u"trunc_u:sat/f32")) {
if (consume(u"trunc_sat_f32_u") || consume(u"trunc_u:sat/f32")) {
return WasmToken(WasmToken::ExtraConversionOpcode,
MiscOp::I64TruncUSatF32, begin, cur_);
}
if (consume(u"trunc_u:sat/f64")) {
if (consume(u"trunc_sat_f64_u") || consume(u"trunc_u:sat/f64")) {
return WasmToken(WasmToken::ExtraConversionOpcode,
MiscOp::I64TruncUSatF64, begin, cur_);
}
@ -2125,6 +2125,9 @@ WasmToken WasmTokenStream::next() {
if (consume(u".set")) {
return WasmToken(WasmToken::SetLocal, begin, cur_);
}
if (consume(u".tee")) {
return WasmToken(WasmToken::TeeLocal, begin, cur_);
}
return WasmToken(WasmToken::Local, begin, cur_);
}
if (consume(u"loop")) {

View File

@ -409,6 +409,13 @@ function runTest() {
// (TEST 18) Test passing valid url() source strings to the FontFace
// constructor.
var p = Promise.resolve();
// The sub-test is very fragile on Android platform, see Bug 1455824,
// especially Comment 34.
if (navigator.appVersion.includes("Android")) {
return p;
}
sourceWindows.forEach(function({ win, what }) {
p = p.then(function() {
var srcTests = Promise.resolve();

View File

@ -21,6 +21,14 @@
</switch>
</switch>
</svg>
<svg>
<switch>
<mask>
<text id="g">Vendredi</text>
</mask>
<a></a>
</switch>
</svg>
</body>
<script>
function go() {
@ -30,5 +38,6 @@ function go() {
d.getComputedTextLength();
e.getComputedTextLength();
f.getComputedTextLength();
g.getComputedTextLength();
}
</script>

View File

@ -139,20 +139,23 @@ nsIFrame* nsSVGSwitchFrame::GetFrameForPoint(const gfxPoint& aPoint) {
return nullptr;
}
static bool shouldReflowSVGTextFrameInside(nsIFrame* aFrame) {
return aFrame->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer) ||
aFrame->IsSVGForeignObjectFrame() ||
!aFrame->IsFrameOfType(nsIFrame::eSVG);
}
void nsSVGSwitchFrame::AlwaysReflowSVGTextFrameDoForOneKid(nsIFrame* aKid) {
if (!NS_SUBTREE_DIRTY(aKid)) {
return;
}
LayoutFrameType type = aKid->Type();
if (type == LayoutFrameType::SVGText) {
if (aKid->IsSVGTextFrame()) {
MOZ_ASSERT(!aKid->HasAnyStateBits(NS_FRAME_IS_NONDISPLAY),
"A non-display SVGTextFrame directly contained in a display "
"container?");
static_cast<SVGTextFrame*>(aKid)->ReflowSVG();
} else if (aKid->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer) ||
type == LayoutFrameType::SVGForeignObject ||
!aKid->IsFrameOfType(nsIFrame::eSVG)) {
} else if (shouldReflowSVGTextFrameInside(aKid)) {
if (!aKid->HasAnyStateBits(NS_FRAME_IS_NONDISPLAY)) {
for (nsIFrame* kid : aKid->PrincipalChildList()) {
AlwaysReflowSVGTextFrameDoForOneKid(kid);
@ -222,6 +225,10 @@ void nsSVGSwitchFrame::ReflowSVG() {
// nsLayoutUtils::UnionChildOverflow since SVG frame's all use the same
// frame list, and we're iterating over that list now anyway.
ConsiderChildOverflow(overflowRects, child);
} else if (child && shouldReflowSVGTextFrameInside(child)) {
MOZ_ASSERT(child->HasAnyStateBits(NS_FRAME_IS_NONDISPLAY),
"Check for this explicitly in the |if|, then");
ReflowSVGNonDisplayText(child);
}
if (isFirstReflow) {

View File

@ -2696,7 +2696,7 @@ pref("csp.overrule_about_uris_without_csp_whitelist", false);
pref("csp.skip_about_page_has_csp_assert", false);
// assertion flag will be set to false after fixing Bug 1473549
pref("security.allow_eval_with_system_principal", false);
pref("security.uris_using_eval_with_system_principal", "autocomplete.xml,redux.js,react-redux.js,content-task.js,content-task.js,tree.xml,dialog.xml,preferencesbindings.js,wizard.xml,lodash.js,jszip.js,sinon-7.2.7.js,ajv-4.1.1.js,updates.js,setup,jsol.js,parent_utils.js,chrometask_chromescript");
pref("security.uris_using_eval_with_system_principal", "autocomplete.xml,redux.js,react-redux.js,content-task.js,content-task.js,tree.xml,dialog.xml,preferencesbindings.js,lodash.js,jszip.js,sinon-7.2.7.js,ajv-4.1.1.js,updates.js,setup,jsol.js,parent_utils.js,chrometask_chromescript");
#endif
// Default Content Security Policy to apply to signed contents.

View File

@ -673,7 +673,7 @@ class BaseBootstrapper(object):
print('Your version of Rust (%s) is new enough.' % version)
rustup = self.which('rustup', cargo_bin)
if rustup:
self.ensure_rust_targets(rustup)
self.ensure_rust_targets(rustup, version)
return
if version:
@ -697,7 +697,7 @@ class BaseBootstrapper(object):
print('Will try to install Rust.')
self.install_rust()
def ensure_rust_targets(self, rustup):
def ensure_rust_targets(self, rustup, rust_version):
"""Make sure appropriate cross target libraries are installed."""
target_list = subprocess.check_output([rustup, 'target', 'list'])
targets = [line.split()[0] for line in target_list.splitlines()
@ -712,7 +712,11 @@ class BaseBootstrapper(object):
if 'mobile_android' in self.application:
# Let's add the most common targets.
android_targets = ('thumbv7neon-linux-androideabi',
if LooseVersion(rust_version) < '1.33':
arm_target = 'armv7-linux-androideabi'
else:
arm_target = 'thumbv7neon-linux-androideabi'
android_targets = (arm_target,
'aarch64-linux-android',
'i686-linux-android',
'x86_64-linux-android', )

View File

@ -1,4 +1,9 @@
job-defaults:
# Run only on try and code-review tasks
# to avoid running clang tools on the whole codebase
run-on-projects:
- try
platform: linux64/opt
attributes:
code-review: true

View File

@ -17,7 +17,6 @@ page_timeout = 30000
gecko_profile_interval = 1
gecko_profile_entries = 2000000
alert_on = fcp, loadtime
screen_capture=true
[raptor-tp6-ebay-mitm-404-recordings-202-firefox]
apps = firefox

View File

@ -55,11 +55,12 @@ var NormandyApi = {
},
absolutify(url) {
const apiBase = prefs.getCharPref("api_url");
const server = new URL(apiBase).origin;
if (url.startsWith("http")) {
return url;
} else if (url.startsWith("/")) {
}
const apiBase = prefs.getCharPref("api_url");
const server = new URL(apiBase).origin;
if (url.startsWith("/")) {
return server + url;
}
throw new Error("Can't use relative urls");
@ -87,27 +88,47 @@ var NormandyApi = {
const rawText = await objectsResponse.text();
const objectsWithSigs = JSON.parse(rawText);
const verifiedObjects = [];
for (const objectWithSig of objectsWithSigs) {
const {signature, x5u} = objectWithSig.signature;
const object = objectWithSig[type];
const serialized = CanonicalJSON.stringify(object);
return Promise.all(
objectsWithSigs.map(async (item) => {
// Check that the rawtext (the object and the signature)
// includes the CanonicalJSON version of the object. This isn't
// strictly needed, but it is a great benefit for debugging
// signature problems.
const object = item[type];
const serialized = CanonicalJSON.stringify(object);
if (!rawText.includes(serialized)) {
log.debug(rawText, serialized);
throw new NormandyApi.InvalidSignatureError(
`Canonical ${type} serialization does not match!`);
}
// Verify content signature using cryptography (will throw if fails).
await this.verifyObjectSignature(serialized, item.signature, type);
return object;
})
);
},
/**
* Verify content signature, by serializing the specified `object` as
* canonical JSON, and using the Normandy signer verifier to check that
* it matches the signature specified in `signaturePayload`.
*
* @param {object|String} data The object (or string) to be checked
* @param {object} signaturePayload The signature information
* @param {String} signaturePayload.x5u The certificate chain URL
* @param {String} signaturePayload.signature base64 signature bytes
* @param {String} type The object type (eg. `"recipe"`, `"action"`)
*
* @throws {NormandyApi.InvalidSignatureError} if signature is invalid.
*/
async verifyObjectSignature(data, signaturePayload, type) {
const { signature, x5u } = signaturePayload;
const certChainResponse = await this.get(this.absolutify(x5u));
const certChain = await certChainResponse.text();
const builtSignature = `p384ecdsa=${signature}`;
const serialized = typeof data == "string" ? data : CanonicalJSON.stringify(data);
const verifier = Cc["@mozilla.org/security/contentsignatureverifier;1"]
.createInstance(Ci.nsIContentSignatureVerifier);
@ -126,11 +147,6 @@ var NormandyApi = {
if (!valid) {
throw new NormandyApi.InvalidSignatureError(`${type} signature is not valid`);
}
verifiedObjects.push(object);
}
return verifiedObjects;
},
/**

View File

@ -50,7 +50,7 @@ const PREFS_TO_WATCH = [
XPCOMUtils.defineLazyGetter(this, "gRemoteSettingsClient", () => {
return RemoteSettings(REMOTE_SETTINGS_COLLECTION, {
filterFunc: async recipe => (await RecipeRunner.checkFilter(recipe)) ? recipe : null,
filterFunc: async entry => (await RecipeRunner.checkFilter(entry.recipe)) ? entry : null,
});
});
@ -215,7 +215,15 @@ var RecipeRunner = {
try {
recipesToRun = await this.loadRecipes();
} catch (e) {
// The legacy call to `Normandy.fetchRecipes()` can throw.
// Either we failed at fetching the recipes from server (legacy),
// or the recipes signature verification failed.
let status = Uptake.RUNNER_SERVER_ERROR;
if (/NetworkError/.test(e)) {
status = Uptake.RUNNER_NETWORK_ERROR;
} else if (e instanceof NormandyApi.InvalidSignatureError) {
status = Uptake.RUNNER_INVALID_SIGNATURE;
}
await Uptake.reportRunner(status);
return;
}
@ -242,10 +250,17 @@ var RecipeRunner = {
*/
async loadRecipes() {
// If RemoteSettings is enabled, we read the list of recipes from there.
// The JEXL filtering is done via the provided callback.
// The JEXL filtering is done via the provided callback (see `gRemoteSettingsClient`).
if (await FeatureGate.isEnabled("normandy-remote-settings")) {
return gRemoteSettingsClient.get();
// First, fetch recipes whose JEXL filters match.
const entries = await gRemoteSettingsClient.get();
// Then, verify the signature of each recipe. It will throw if invalid.
return Promise.all(entries.map(async ( { recipe, signature } ) => {
await NormandyApi.verifyObjectSignature(recipe, signature, "recipe");
return recipe;
}));
}
// Obtain the recipes from the Normandy server (legacy).
let recipes;
try {
@ -257,14 +272,6 @@ var RecipeRunner = {
} catch (e) {
const apiUrl = Services.prefs.getCharPref(API_URL_PREF);
log.error(`Could not fetch recipes from ${apiUrl}: "${e}"`);
let status = Uptake.RUNNER_SERVER_ERROR;
if (/NetworkError/.test(e)) {
status = Uptake.RUNNER_NETWORK_ERROR;
} else if (e instanceof NormandyApi.InvalidSignatureError) {
status = Uptake.RUNNER_INVALID_SIGNATURE;
}
await Uptake.reportRunner(status);
throw e;
}
// Evaluate recipe filters

View File

@ -205,33 +205,42 @@ decorate_task(
["features.normandy-remote-settings.enabled", true],
],
}),
withStub(NormandyApi, "verifyObjectSignature"),
withStub(ActionsManager.prototype, "runRecipe"),
withStub(ActionsManager.prototype, "fetchRemoteActions"),
withStub(ActionsManager.prototype, "finalize"),
withStub(Uptake, "reportRecipe"),
async function testReadFromRemoteSettings(
verifyObjectSignatureStub,
runRecipeStub,
fetchRemoteActionsStub,
finalizeStub,
reportRecipeStub,
) {
const matchRecipe = { id: "match", action: "matchAction", filter_expression: "true", _status: "synced", enabled: true };
const noMatchRecipe = { id: "noMatch", action: "noMatchAction", filter_expression: "false", _status: "synced", enabled: true };
const missingRecipe = { id: "missing", action: "missingAction", filter_expression: "true", _status: "synced", enabled: true };
const matchRecipe = { name: "match", action: "matchAction", filter_expression: "true" };
const noMatchRecipe = { name: "noMatch", action: "noMatchAction", filter_expression: "false" };
const missingRecipe = { name: "missing", action: "missingAction", filter_expression: "true" };
const rsCollection = await RecipeRunner._remoteSettingsClientForTesting.openCollection();
await rsCollection.create(matchRecipe, { synced: true });
await rsCollection.create(noMatchRecipe, { synced: true });
await rsCollection.create(missingRecipe, { synced: true });
await rsCollection.clear();
const fakeSig = { signature: "abc" };
await rsCollection.create({ id: "match", recipe: matchRecipe, signature: fakeSig }, { synced: true });
await rsCollection.create({ id: "noMatch", recipe: noMatchRecipe, signature: fakeSig }, { synced: true });
await rsCollection.create({ id: "missing", recipe: missingRecipe, signature: fakeSig }, { synced: true });
await rsCollection.db.saveLastModified(42);
rsCollection.db.close();
await RecipeRunner.run();
Assert.deepEqual(
verifyObjectSignatureStub.args,
[[matchRecipe, fakeSig, "recipe"], [missingRecipe, fakeSig, "recipe"]],
"recipes with matching filters should have their signature verified",
);
Assert.deepEqual(
runRecipeStub.args,
[[matchRecipe], [missingRecipe]],
"recipe with matching filters should be executed",
"recipes with matching filters should be executed",
);
Assert.deepEqual(
reportRecipeStub.args,
@ -241,6 +250,42 @@ decorate_task(
}
);
decorate_task(
withPrefEnv({
set: [
["features.normandy-remote-settings.enabled", true],
],
}),
withStub(ActionsManager.prototype, "runRecipe"),
withStub(NormandyApi, "get"),
withStub(Uptake, "reportRunner"),
async function testBadSignatureFromRemoteSettings(
runRecipeStub,
normandyGetStub,
reportRunnerStub,
) {
normandyGetStub.resolves({ async text() { return "---CERT x5u----"; } });
const matchRecipe = { name: "badSig", action: "matchAction", filter_expression: "true" };
const rsCollection = await RecipeRunner._remoteSettingsClientForTesting.openCollection();
await rsCollection.clear();
const badSig = { x5u: "http://localhost/x5u", signature: "abc" };
await rsCollection.create({ id: "badSig", recipe: matchRecipe, signature: badSig }, { synced: true });
await rsCollection.db.saveLastModified(42);
rsCollection.db.close();
await RecipeRunner.run();
ok(!runRecipeStub.called, "no recipe is executed");
Assert.deepEqual(
reportRunnerStub.args,
[[Uptake.RUNNER_INVALID_SIGNATURE]],
"RecipeRunner should report uptake telemetry",
);
}
);
decorate_task(
withMockNormandyApi,
async function testRunFetchFail(mockApi) {

View File

@ -41,7 +41,6 @@ skip-if = (os == 'linux' && debug) #Bug 1199778
[test_classifier_match.html]
[test_classifier_worker.html]
[test_classify_by_default.html]
skip-if = (os == 'android') #Bug 1538662
[test_classify_ping.html]
skip-if = (verify && debug && (os == 'win' || os == 'mac'))
[test_classify_track.html]

View File

@ -14,9 +14,6 @@
</div>
<pre id="test">
<iframe id="testFrame1"></iframe>
<iframe id="testFrame2"></iframe>
<script class="testbody" type="text/javascript">
// To add a request to test, add the request in trackerFrame.html
@ -44,8 +41,9 @@ function setup() {
});
}
function loadTestFrame(withcookie, frameId) {
function loadTestWindow(withcookie) {
return new Promise(resolve => {
let win;
let query = withcookie ? "with-cookie" : "without-cookie";
fetch(trackerFrame + "?callback=" + query, {
credentials: "include",
@ -57,12 +55,12 @@ function loadTestFrame(withcookie, frameId) {
(withcookie ? "with" : "without") + " cookie";
ok(trackers_found.includes(tracker), description);
}
win.close();
resolve();
});
});
let frame = document.getElementById(frameId);
frame.src = "trackerFrame.html";
win = window.open("trackerFrame.html");
});
}
@ -77,13 +75,13 @@ async function runTests() {
await setup();
await loadTestFrame(true, "testFrame1");
await loadTestWindow(true);
await SpecialPowers.pushPrefEnv({set: [
[ "privacy.trackingprotection.annotate_channels", true],
]});
await loadTestFrame(false, "testFrame2");
await loadTestWindow(false);
SimpleTest.finish();
}

View File

@ -444,18 +444,7 @@
event.initEvent(aType, true, true);
// handle dom event handlers
var noCancel = aTarget.dispatchEvent(event);
// handle any xml attribute event handlers
var handler = aTarget.getAttribute("on"+aType);
if (handler != "") {
var fn = new Function("event", handler);
var returned = fn.apply(aTarget, [event]);
if (returned == false)
noCancel = false;
}
return noCancel;
return aTarget.dispatchEvent(event);
]]>
</body>
</method>

View File

@ -308,6 +308,30 @@ var gUpdates = {
this._cacheButtonStrings("extra1");
this._cacheButtonStrings("extra2");
document.addEventListener("wizardfinish", function() { gUpdates.onWizardFinish(); });
document.addEventListener("wizardcancel", function() { gUpdates.onWizardCancel(); });
document.addEventListener("wizardnext", function() { gUpdates.onWizardNext(); });
document.getElementById("checking").addEventListener("pageshow", function() { gCheckingPage.onPageShow(); });
document.getElementById("noupdatesfound").addEventListener("pageshow", function() { gNoUpdatesPage.onPageShow(); });
document.getElementById("manualUpdate").addEventListener("pageshow", function() { gManualUpdatePage.onPageShow(); });
document.getElementById("unsupported").addEventListener("pageshow", function() { gUnsupportedPage.onPageShow(); });
document.getElementById("updatesfoundbasic").addEventListener("pageshow", function() { gUpdatesFoundBasicPage.onPageShow(); });
document.getElementById("downloading").addEventListener("pageshow", function() { gDownloadingPage.onPageShow(); });
document.getElementById("errors").addEventListener("pageshow", function() { gErrorsPage.onPageShow(); });
document.getElementById("errorextra").addEventListener("pageshow", function() { gErrorExtraPage.onPageShow(); });
document.getElementById("errorpatching").addEventListener("pageshow", function() { gErrorPatchingPage.onPageShow(); });
document.getElementById("finished").addEventListener("pageshow", function() { gFinishedPage.onPageShow(); });
document.getElementById("finishedBackground").addEventListener("pageshow", function() { gFinishedPage.onPageShowBackground(); });
document.getElementById("updatesfoundbasic").addEventListener("extra1", function() { gUpdatesFoundBasicPage.onExtra1(); });
document.getElementById("downloading").addEventListener("extra1", function() { gDownloadingPage.onHide(); });
document.getElementById("finished").addEventListener("extra1", function() { gFinishedPage.onExtra1(); });
document.getElementById("finishedBackground").addEventListener("extra1", function() { gFinishedPage.onExtra1(); });
document.getElementById("updatesfoundbasic").addEventListener("extra2", function() { gUpdatesFoundBasicPage.onExtra2(); });
document.getElementById("finishedBackground").addEventListener("extra2", function() { gFinishedPage.onExtra2(); });
// Advance to the Start page.
this.getStartPageID(function(startPageID) {
LOG("gUpdates", "onLoad - setting current page to startpage " + startPageID);

View File

@ -24,9 +24,6 @@
title="&updateWizard.title;"
windowtype="Update:Wizard"
style="width: auto; height: auto"
onwizardfinish="gUpdates.onWizardFinish();"
onwizardcancel="gUpdates.onWizardCancel();"
onwizardnext="gUpdates.onWizardNext();"
onload="gUpdates.onLoad();"
onunload="gUpdates.onUnload();">
@ -47,7 +44,7 @@
<wizardpage id="dummy" pageid="dummy" firstpage="true"/>
<wizardpage id="checking" pageid="checking" next="noupdatesfound"
object="gCheckingPage" onpageshow="gCheckingPage.onPageShow();">
object="gCheckingPage">
<updateheader label="&checking.title;"/>
<vbox class="update-content" flex="1">
<label>&updateCheck.label;</label>
@ -57,7 +54,7 @@
</wizardpage>
<wizardpage id="noupdatesfound" pageid="noupdatesfound"
object="gNoUpdatesPage" onpageshow="gNoUpdatesPage.onPageShow();">
object="gNoUpdatesPage">
<updateheader label="&noupdatesfound.title;"/>
<vbox class="update-content" flex="1">
<label id="noUpdatesAutoEnabled" hidden="true">&noupdatesautoenabled.intro;</label>
@ -65,8 +62,7 @@
</vbox>
</wizardpage>
<wizardpage id="manualUpdate" pageid="manualUpdate" object="gManualUpdatePage"
onpageshow="gManualUpdatePage.onPageShow();">
<wizardpage id="manualUpdate" pageid="manualUpdate" object="gManualUpdatePage">
<updateheader label="&manualUpdate.title;"/>
<vbox class="update-content" flex="1">
<label id="manualUpdateDesc">&manualUpdate.desc;</label>
@ -82,8 +78,7 @@
</wizardpage>
<wizardpage id="unsupported" pageid="unsupported"
object="gUnsupportedPage"
onpageshow="gUnsupportedPage.onPageShow();">
object="gUnsupportedPage">
<updateheader label="&unsupported.title;"/>
<vbox class="update-content" flex="1">
<description flex="1">&unsupported.label;
@ -95,10 +90,7 @@
</wizardpage>
<wizardpage id="updatesfoundbasic" pageid="updatesfoundbasic"
object="gUpdatesFoundBasicPage" next="downloading"
onpageshow="gUpdatesFoundBasicPage.onPageShow();"
onextra1="gUpdatesFoundBasicPage.onExtra1();"
onextra2="gUpdatesFoundBasicPage.onExtra2();">
object="gUpdatesFoundBasicPage" next="downloading">
<updateheader id="updatesFoundBasicHeader" label=""/>
<vbox class="update-content" flex="1">
<label id="updatesFoundInto"/>
@ -117,8 +109,7 @@
</wizardpage>
<wizardpage id="downloading" pageid="downloading"
object="gDownloadingPage" onextra1="gDownloadingPage.onHide();"
onpageshow="gDownloadingPage.onPageShow();">
object="gDownloadingPage">
<updateheader label="&downloadPage.title;"/>
<vbox class="update-content" flex="1">
<hbox id="downloadStatusProgress">
@ -138,8 +129,7 @@
</vbox>
</wizardpage>
<wizardpage id="errors" pageid="errors" object="gErrorsPage"
onpageshow="gErrorsPage.onPageShow();">
<wizardpage id="errors" pageid="errors" object="gErrorsPage">
<updateheader label="&error.title;"/>
<vbox class="update-content" flex="1">
<label id="errorIntro">&error.label;</label>
@ -155,8 +145,7 @@
</wizardpage>
<wizardpage id="errorextra" pageid="errorextra"
object="gErrorExtraPage"
onpageshow="gErrorExtraPage.onPageShow();">
object="gErrorExtraPage">
<updateheader label="&error.title;"/>
<vbox class="update-content" flex="1">
<label id="bgErrorLabel">&genericBackgroundError.label;</label>
@ -168,17 +157,14 @@
</wizardpage>
<wizardpage id="errorpatching" pageid="errorpatching" next="downloading"
object="gErrorPatchingPage"
onpageshow="gErrorPatchingPage.onPageShow();">
object="gErrorPatchingPage">
<updateheader label="&error.title;"/>
<vbox class="update-content" flex="1">
<label>&errorpatching.intro;</label>
</vbox>
</wizardpage>
<wizardpage id="finished" pageid="finished" object="gFinishedPage"
onpageshow="gFinishedPage.onPageShow();"
onextra1="gFinishedPage.onExtra1()">
<wizardpage id="finished" pageid="finished" object="gFinishedPage">
<updateheader label="&finishedPage.title;"/>
<vbox class="update-content" flex="1">
<label>&finishedPage.text;</label>
@ -186,9 +172,7 @@
</wizardpage>
<wizardpage id="finishedBackground" pageid="finishedBackground"
object="gFinishedPage" onextra1="gFinishedPage.onExtra1()"
onextra2="gFinishedPage.onExtra2()"
onpageshow="gFinishedPage.onPageShowBackground();">
object="gFinishedPage">
<updateheader label="&finishedPage.title;"/>
<vbox class="update-content" flex="1">
<label>&finishedBackgroundPage.text;</label>

View File

@ -31,6 +31,9 @@ function initWizard() {
// Initialize the profile location display.
gProfileDisplay = document.getElementById("profileDisplay").firstChild;
document.addEventListener("wizardfinish", onFinish);
document.getElementById("explanation").addEventListener("pageshow", enableNextButton);
document.getElementById("createProfile").addEventListener("pageshow", initSecondWizardPage);
setDisplayToDefaultFolder();
} catch (e) {
window.close();
@ -169,7 +172,7 @@ function enableNextButton() {
document.documentElement.canAdvance = true;
}
function onFinish() {
function onFinish(event) {
var profileName = document.getElementById("profileName").value;
var profile;
@ -184,7 +187,8 @@ function onFinish() {
Services.prompt.alert(window, profileCreationFailedTitle,
profileCreationFailed + "\n" + e);
return false;
event.preventDefault();
return;
}
// window.opener is false if the Create Profile Wizard was opened from the
@ -199,7 +203,4 @@ function onFinish() {
var dialogParams = window.arguments[0].QueryInterface(I.nsIDialogParamBlock);
dialogParams.objects.insertElementAt(profileLock, 0);
}
// Exit the wizard.
return true;
}

View File

@ -17,7 +17,6 @@
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onwizardfinish="return onFinish();"
onload="initWizard();"
style="&window.size;">
<script type="application/javascript"
@ -28,7 +27,7 @@
<script type="application/javascript" src="chrome://mozapps/content/profile/createProfileWizard.js"/>
<wizardpage id="explanation" onpageshow="enableNextButton();">
<wizardpage id="explanation">
<description>&profileCreationExplanation_1.text;</description>
<description>&profileCreationExplanation_2.text;</description>
<description>&profileCreationExplanation_3.text;</description>
@ -44,7 +43,7 @@
#endif
</wizardpage>
<wizardpage id="createProfile" onpageshow="initSecondWizardPage();">
<wizardpage id="createProfile">
<description>&profileCreationIntro.text;</description>
<label accesskey="&profilePrompt.accesskey;" control="ProfileName">&profilePrompt.label;</label>

View File

@ -134,6 +134,7 @@ clang_checkers:
- name: readability-misleading-indentation
- name: readability-non-const-parameter
- name: readability-redundant-control-flow
- name: readability-redundant-preprocessor
- name: readability-redundant-smartptr-get
- name: readability-redundant-string-cstr
- name: readability-redundant-string-init

View File

@ -33,7 +33,7 @@ using namespace mozilla;
// Linux, to avoid naming clashes in builds which mix GCC and LLVM. So, when we
// are building with LLVM exclusively, we need to use __custom_llvm_gcov_flush
// instead.
#if defined(XP_LINUX) && defined(__clang__)
#if !defined(XP_WIN) && defined(__clang__)
# define __gcov_flush __custom_llvm_gcov_flush
#endif

View File

@ -27,6 +27,7 @@
#endif
#include "nsNetCID.h"
#include "nsThread.h"
#include "VRProcessManager.h"
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReportingProcess.h"
#include "mozilla/PodOperations.h"
@ -1814,6 +1815,12 @@ nsresult nsMemoryReporterManager::StartGettingReports() {
}
}
if (gfx::VRProcessManager* vr = gfx::VRProcessManager::Get()) {
if (RefPtr<MemoryReportingProcess> proc = vr->GetProcessMemoryReporter()) {
s->mChildrenPending.AppendElement(proc.forget());
}
}
if (!mIsRegistrationBlocked && net::gIOService) {
if (RefPtr<MemoryReportingProcess> proc =
net::gIOService->GetSocketProcessMemoryReporter()) {

View File

@ -67,7 +67,7 @@ Classes = [
'type': 'nsMemoryReporterManager',
'headers': ['/xpcom/base/nsMemoryReporterManager.h'],
'init_method': 'Init',
'processes': ProcessSelector.ALLOW_IN_GPU_AND_SOCKET_PROCESS,
'processes': ProcessSelector.ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS,
},
{
'cid': '{7b4eeb20-d781-11d4-8a83-0010a4e0c9ca}',

View File

@ -26,7 +26,7 @@ if CONFIG['OS_ARCH'] == 'GNU':
'xptcstubs_gcc_x86_unix.cpp'
]
if CONFIG['OS_ARCH'] in ('Linux', 'Bitrig', 'DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD') or \
if CONFIG['OS_ARCH'] in ('Linux', 'Bitrig', 'DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD', 'SunOS') or \
CONFIG['OS_ARCH'].startswith('GNU_'):
if CONFIG['CPU_ARCH'] == 'x86_64':
SOURCES += [
@ -49,41 +49,6 @@ if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'):
'xptcstubs_ipf64.cpp'
]
if CONFIG['OS_ARCH'] == 'SunOS' and CONFIG['INTEL_ARCHITECTURE']:
if CONFIG['CPU_ARCH'] == 'x86_64':
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
SOURCES += [
'xptcinvoke_asm_x86_64_unix.S',
'xptcinvoke_x86_64_unix.cpp',
'xptcstubs_x86_64_linux.cpp'
]
else:
GENERATED_FILES = [
'xptcstubsdef_asm.solx86',
]
ASFLAGS += ['-xarch=amd64']
SOURCES += [
'xptcinvoke_x86_64_solaris.cpp',
'xptcstubs_asm_x86_64_solaris_SUNW.s',
'xptcstubs_x86_64_solaris.cpp',
]
else:
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
SOURCES += [
'xptcinvoke_gcc_x86_unix.cpp',
'xptcstubs_gcc_x86_unix.cpp'
]
else:
GENERATED_FILES = [
'xptcstubsdef_asm.solx86',
]
SOURCES += [
'xptcinvoke_asm_x86_solaris_SUNW.s',
'xptcinvoke_x86_solaris.cpp',
'xptcstubs_asm_x86_solaris_SUNW.s',
'xptcstubs_x86_solaris.cpp'
]
if CONFIG['CPU_ARCH'] == 'Alpha':
if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD', 'NetBSD'):
SOURCES += [
@ -240,7 +205,7 @@ if CONFIG['OS_ARCH'] == 'OpenBSD' and CONFIG['CPU_ARCH'] == 'sparc':
'xptcstubs_sparc_openbsd.cpp',
]
if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD', 'Linux') and CONFIG['CPU_ARCH'] == 'sparc64':
if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD', 'Linux', 'SunOS') and CONFIG['CPU_ARCH'] == 'sparc64':
SOURCES += [
'xptcinvoke_asm_sparc64_openbsd.s',
'xptcinvoke_sparc64_openbsd.cpp',
@ -248,35 +213,6 @@ if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD', 'Linux') and CONFIG['CPU_ARCH'] =
'xptcstubs_sparc64_openbsd.cpp',
]
if CONFIG['OS_ARCH'] == 'SunOS' and not CONFIG['INTEL_ARCHITECTURE']:
if CONFIG['HAVE_64BIT_BUILD']:
ASFLAGS += ['-xarch=v9']
SOURCES += [
'xptcinvoke_sparcv9_solaris.cpp',
'xptcstubs_sparcv9_solaris.cpp',
]
else:
SOURCES += [
'xptcinvoke_sparc_solaris.cpp',
'xptcstubs_sparc_solaris.cpp',
]
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
SOURCES += [
'xptcinvoke_asm_sparc_solaris_GCC3.s',
'xptcstubs_asm_sparc_solaris.s',
]
else:
if CONFIG['HAVE_64BIT_BUILD']:
SOURCES += [
'xptcinvoke_asm_sparcv9_solaris_SUNW.s',
'xptcstubs_asm_sparcv9_solaris.s',
]
else:
SOURCES += [
'xptcinvoke_asm_sparc_solaris_SUNW.s',
'xptcstubs_asm_sparc_solaris.s',
]
if CONFIG['OS_ARCH'] == 'Linux':
if CONFIG['CPU_ARCH'] == 's390':
SOURCES += [

View File

@ -1,52 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
/*
* Platform specific code to invoke XPCOM methods on native objects for
* solaris/sparc with gcc 3 ABI.
*/
.global NS_InvokeByIndex
/*
* NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
* uint32_t paramCount, nsXPTCVariant* params);
*/
NS_InvokeByIndex:
save %sp,-(64 + 32),%sp ! room for the register window and
! struct pointer, rounded up to 0 % 32
mov %i2,%o0 ! paramCount
call invoke_count_words ! returns the required stack size in %o0
mov %i3,%o1 ! params
sll %o0,2,%l0 ! number of bytes
sub %sp,%l0,%sp ! create the additional stack space
mov %sp,%o0 ! pointer for copied args
add %o0,72,%o0 ! step past the register window, the
! struct result pointer and the 'this' slot
mov %i2,%o1 ! paramCount
call invoke_copy_to_stack
mov %i3,%o2 ! params
!
! calculate the target address from the vtable
!
ld [%i0],%l1 ! *that --> vTable
sll %i1,2,%i1 ! multiply index by 4
add %i1,%l1,%l1 ! l1 now points to vTable entry
ld [%l1],%l0 ! target address
.L5: ld [%sp + 88],%o5
.L4: ld [%sp + 84],%o4
.L3: ld [%sp + 80],%o3
.L2: ld [%sp + 76],%o2
.L1: ld [%sp + 72],%o1
.L0:
jmpl %l0,%o7 ! call the routine
! always have a 'this', from the incoming 'that'
mov %i0,%o0
mov %o0,%i0 ! propagate return value
ret
restore

View File

@ -1,56 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
/* Platform specific code to invoke XPCOM methods on native objects */
.global NS_InvokeByIndex
.type NS_InvokeByIndex, #function
/*
NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
uint32_t paramCount, nsXPTCVariant* params);
*/
NS_InvokeByIndex:
save %sp,-(64 + 32),%sp ! room for the register window and
! struct pointer, rounded up to 0 % 32
sll %i2,3,%l0 ! assume the worst case
! paramCount * 2 * 4 bytes
cmp %l0, 0 ! are there any args? If not,
be .invoke ! no need to copy args to stack
sub %sp,%l0,%sp ! create the additional stack space
add %sp,72,%o0 ! step past the register window, the
! struct result pointer and the 'this' slot
mov %i2,%o1 ! paramCount
call invoke_copy_to_stack
mov %i3,%o2 ! params
!
! load arguments from stack into the outgoing registers
!
ld [%sp + 72],%o1
ld [%sp + 76],%o2
ld [%sp + 80],%o3
ld [%sp + 84],%o4
ld [%sp + 88],%o5
!
! calculate the target address from the vtable
!
.invoke:
sll %i1,2,%l0 ! index *= 4
add %l0,8,%l0 ! there are 2 extra entries in the vTable
ld [%i0],%l1 ! *that --> address of vtable
ld [%l0 + %l1],%l0 ! that->vtable[index * 4 + 8] --> address
jmpl %l0,%o7 ! call the routine
mov %i0,%o0 ! move 'this' pointer to out register
mov %o0,%i0 ! propagate return value
ret
restore
.size NS_InvokeByIndex, .-NS_InvokeByIndex

View File

@ -1,85 +0,0 @@
/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
Platform specific code to invoke XPCOM methods on native objects
for sparcv9 Solaris.
See the SPARC Compliance Definition (SCD) Chapter 3
for more information about what is going on here, including
the use of BIAS (0x7ff).
The SCD is available from http://www.sparc.com/.
*/
.global NS_InvokeByIndex
.type NS_InvokeByIndex, #function
/*
NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
uint32_t paramCount, nsXPTCVariant* params);
*/
NS_InvokeByIndex:
save %sp,-(128 + 64),%sp ! room for the register window and
! struct pointer, rounded up to 0 % 64
sll %i2,4,%l0 ! assume the worst case
! paramCount * 2 * 8 bytes
cmp %l0, 0 ! are there any args? If not,
be .invoke ! no need to copy args to stack
sub %sp,%l0,%sp ! create the additional stack space
add %sp,0x7ff+136,%o0 ! step past the register window, the
! struct result pointer and the 'this' slot
mov %i2,%o1 ! paramCount
call invoke_copy_to_stack
mov %i3,%o2 ! params
!
! load arguments from stack into the outgoing registers
! BIAS is 0x7ff (2047)
!
! load the %o1..5 64bit (extended word) output registers registers
ldx [%sp + 0x7ff + 136],%o1 ! %i1
ldx [%sp + 0x7ff + 144],%o2 ! %i2
ldx [%sp + 0x7ff + 152],%o3 ! %i3
ldx [%sp + 0x7ff + 160],%o4 ! %i4
ldx [%sp + 0x7ff + 168],%o5 ! %i5
! load the even number double registers starting with %d2
ldd [%sp + 0x7ff + 136],%d2
ldd [%sp + 0x7ff + 144],%d4
ldd [%sp + 0x7ff + 152],%d6
ldd [%sp + 0x7ff + 160],%d8
ldd [%sp + 0x7ff + 168],%d10
ldd [%sp + 0x7ff + 176],%d12
ldd [%sp + 0x7ff + 184],%d14
ldd [%sp + 0x7ff + 192],%d16
ldd [%sp + 0x7ff + 200],%d18
ldd [%sp + 0x7ff + 208],%d20
ldd [%sp + 0x7ff + 216],%d22
ldd [%sp + 0x7ff + 224],%d24
ldd [%sp + 0x7ff + 232],%d26
ldd [%sp + 0x7ff + 240],%d28
ldd [%sp + 0x7ff + 248],%d30
!
! calculate the target address from the vtable
!
.invoke:
sll %i1,3,%l0 ! index *= 8
add %l0,16,%l0 ! there are 2 extra entries in the vTable (16bytes)
ldx [%i0],%l1 ! *that --> address of vtable
ldx [%l0 + %l1],%l0 ! that->vtable[index * 8 + 16] --> address
jmpl %l0,%o7 ! call the routine
mov %i0,%o0 ! move 'this' pointer to out register
mov %o0,%i0 ! propagate return value
ret
restore
.size NS_InvokeByIndex, .-NS_InvokeByIndex

View File

@ -1,55 +0,0 @@
.globl NS_InvokeByIndex
.type NS_InvokeByIndex, @function
NS_InvokeByIndex:
push %ebp
movl %esp,%ebp
push %ebx
call .CG0.66
.CG0.66:
pop %ebx
addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx
push 20(%ebp)
push 16(%ebp)
push 12(%ebp)
push 8(%ebp)
/ INLINE: invoke_by_index
pushl %ebx
pushl %esi
movl %esp, %ebx
pushl 0x14(%ebp)
pushl 0x10(%ebp)
call invoke_count_words
mov %ebx, %esp
sall $0x2 , %eax
subl %eax, %esp
movl %esp, %esi
pushl %esp
pushl 0x14(%ebp)
pushl 0x10(%ebp)
call invoke_copy_to_stack
movl %esi, %esp
movl 0x8(%ebp), %ecx
pushl %ecx
movl (%ecx), %edx
movl 0xc(%ebp), %eax
movl 0x8(%edx, %eax, 4), %edx
call *%edx
mov %ebx, %esp
popl %esi
popl %ebx
/ INLINE_END
addl $16,%esp
pop %ebx
movl %ebp,%esp
pop %ebp
ret
.size NS_InvokeByIndex, . - NS_InvokeByIndex

View File

@ -30,9 +30,9 @@ invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
{
if (regCount < 5) regCount++;
if (l_s->IsPtrData())
if (l_s->IsIndirect())
{
*l_d = (uint64_t)l_s->ptr;
*l_d = (uint64_t) &l_s->val;
continue;
}
switch (l_s->type)

Some files were not shown because too many files have changed in this diff Show More