--- a/addon-sdk/source/lib/sdk/ui/frame/view.html
+++ b/addon-sdk/source/lib/sdk/ui/frame/view.html
@@ -1,18 +1,18 @@
-<script>
-// HACK: This is not an ideal way to deliver chrome messages
-// to a innef frame content but seems only way that would
-// make `event.source` an this (outer frame) window.
-window.onmessage = function(event) {
- var frame = document.querySelector("iframe");
- var content = frame.contentWindow;
- // If message is posted from chrome it has no `event.source`.
- if (event.source === null)
- content.postMessage(event.data, "*");
-};
-// Hack: Ideally we would have used srcdoc on iframe, but in
-// that case origin of document is either content which is unable
-// to load add-on resources or a chrome to which add-on resource
-// can not send messages back.
-document.documentElement.style.overflow = "hidden";
-document.documentElement.innerHTML = atob(location.hash.substr(1));
-</script>
+<!DOCTYPE html>
+<html>
+ <head>
+ <script>
+ // HACK: This is not an ideal way to deliver chrome messages
+ // to an inner frame content but seems only way that would
+ // make `event.source` this (outer frame) window.
+ window.onmessage = function(event) {
+ var frame = document.querySelector("iframe");
+ var content = frame.contentWindow;
+ // If message is posted from chrome it has no `event.source`.
+ if (event.source === null)
+ content.postMessage(event.data, "*");
+ };
+ </script>
+ </head>
+ <body style="overflow: hidden"></body>
+</html>
--- a/addon-sdk/source/lib/sdk/ui/frame/view.js
+++ b/addon-sdk/source/lib/sdk/ui/frame/view.js
@@ -58,39 +58,45 @@ const registerFrame = ({id, url}) => {
id: id,
type: "custom",
removable: true,
onBuild: document => {
let view = document.createElementNS(XUL_NS, "toolbaritem");
view.setAttribute("id", id);
view.setAttribute("flex", 2);
- let innerFrame = document.createElementNS(HTML_NS, "iframe");
- innerFrame.setAttribute("id", id);
- innerFrame.setAttribute("src", url);
- innerFrame.setAttribute("seamless", "seamless");
- innerFrame.setAttribute("sandbox", "allow-scripts");
- innerFrame.setAttribute("scrolling", "no");
- innerFrame.setAttribute("data-is-sdk-inner-frame", true);
- innerFrame.setAttribute("style", [ "border:none",
- "position:absolute", "width:100%", "top: 0",
- "left: 0", "overflow: hidden"].join(";"));
-
let outerFrame = document.createElementNS(XUL_NS, "iframe");
- outerFrame.setAttribute("src", OUTER_FRAME_URI + "#" +
- encode(innerFrame.outerHTML));
+ outerFrame.setAttribute("src", OUTER_FRAME_URI);
outerFrame.setAttribute("id", "outer-" + id);
outerFrame.setAttribute("data-is-sdk-outer-frame", true);
outerFrame.setAttribute("type", "content");
outerFrame.setAttribute("transparent", true);
outerFrame.setAttribute("flex", 2);
outerFrame.setAttribute("style", "overflow: hidden;");
outerFrame.setAttribute("scrolling", "no");
outerFrame.setAttribute("disablehistory", true);
outerFrame.setAttribute("seamless", "seamless");
+ outerFrame.addEventListener("load", function onload() {
+ outerFrame.removeEventListener("load", onload, true);
+
+ let doc = outerFrame.contentDocument;
+
+ let innerFrame = doc.createElementNS(HTML_NS, "iframe");
+ innerFrame.setAttribute("id", id);
+ innerFrame.setAttribute("src", url);
+ innerFrame.setAttribute("seamless", "seamless");
+ innerFrame.setAttribute("sandbox", "allow-scripts");
+ innerFrame.setAttribute("scrolling", "no");
+ innerFrame.setAttribute("data-is-sdk-inner-frame", true);
+ innerFrame.setAttribute("style", [ "border:none",
+ "position:absolute", "width:100%", "top: 0",
+ "left: 0", "overflow: hidden"].join(";"));
+
+ doc.body.appendChild(innerFrame);
+ }, true);
view.appendChild(outerFrame);
return view;
}
});
};
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -133,19 +133,16 @@ pref("app.update.badge", false);
// when it finishes downloading them.
pref("app.update.staging.enabled", true);
// Update service URL:
pref("app.update.url", "https://aus5.mozilla.org/update/6/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%SYSTEM_CAPABILITIES%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
// app.update.url.manual is in branding section
// app.update.url.details is in branding section
-// User-settable override to app.update.url for testing purposes.
-//pref("app.update.url.override", "");
-
// app.update.interval is in branding section
// app.update.promptWaitTime is in branding section
// Show the Update Checking/Ready UI when the user was idle for x seconds
pref("app.update.idletime", 60);
// Whether or not to attempt using the service for updates.
#ifdef MOZ_MAINTENANCE_SERVICE
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_disabled.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_disabled.js
@@ -36,30 +36,33 @@ add_task(function* testDisabled() {
browser.test.sendMessage("ready");
},
});
yield extension.startup();
yield extension.awaitMessage("ready");
yield clickBrowserAction(extension);
+ yield new Promise(resolve => setTimeout(resolve, 0));
extension.sendMessage("check-clicked", true);
yield extension.awaitMessage("next-test");
extension.sendMessage("disable");
yield extension.awaitMessage("next-test");
yield clickBrowserAction(extension);
+ yield new Promise(resolve => setTimeout(resolve, 0));
extension.sendMessage("check-clicked", false);
yield extension.awaitMessage("next-test");
extension.sendMessage("enable");
yield extension.awaitMessage("next-test");
yield clickBrowserAction(extension);
+ yield new Promise(resolve => setTimeout(resolve, 0));
extension.sendMessage("check-clicked", true);
yield extension.awaitMessage("next-test");
yield extension.unload();
});
--- a/browser/components/extensions/test/browser/browser_ext_windows_create_tabId.js
+++ b/browser/components/extensions/test/browser/browser_ext_windows_create_tabId.js
@@ -91,24 +91,29 @@ add_task(function* testWindowCreate() {
browser.test.log("Try to create a window with an invalid tabId");
await browser.test.assertRejects(
browser.windows.create({tabId: 0}),
/Invalid tab ID: 0/,
"Create call failed as expected");
browser.test.log("Try to create a window with two URLs");
- [, , window] = await Promise.all([
+ let readyPromise = Promise.all([
// tabs.onUpdated can be invoked between the call of windows.create and
// the invocation of its callback/promise, so set up the listeners
// before creating the window.
promiseTabUpdated("http://example.com/"),
promiseTabUpdated("http://example.org/"),
- browser.windows.create({url: ["http://example.com/", "http://example.org/"]}),
]);
+
+ await new Promise(resolve => setTimeout(resolve, 0));
+
+ window = await browser.windows.create({url: ["http://example.com/", "http://example.org/"]});
+ await readyPromise;
+
browser.test.assertEq(2, window.tabs.length, "2 tabs were opened in new window");
browser.test.assertEq("about:blank", window.tabs[0].url, "about:blank, page not loaded yet");
browser.test.assertEq("about:blank", window.tabs[1].url, "about:blank, page not loaded yet");
window = await browser.windows.get(window.id, {populate: true});
browser.test.assertEq(2, window.tabs.length, "2 tabs were opened in new window");
browser.test.assertEq("http://example.com/", window.tabs[0].url, "Correct URL was loaded in tab 1");
--- a/browser/components/migration/MSMigrationUtils.jsm
+++ b/browser/components/migration/MSMigrationUtils.jsm
@@ -559,17 +559,17 @@ Cookies.prototype = {
} catch (ex) {
Components.utils.reportError("Unable to migrate cookie: " + ex);
success = false;
} finally {
aCallback(success);
}
};
fileReader.addEventListener("loadend", onLoadEnd, false);
- fileReader.readAsText(new File(aFile));
+ fileReader.readAsText(File.createFromNsIFile(aFile));
},
/**
* Parses a cookie file buffer and returns an array of the contained cookies.
*
* The cookie file format is a newline-separated-values with a "*" used as
* delimeter between multiple records.
* Each cookie has the following fields:
--- a/browser/extensions/e10srollout/bootstrap.js
+++ b/browser/extensions/e10srollout/bootstrap.js
@@ -165,20 +165,10 @@ function optedOut() {
/* If this function returns a non-empty string, it
* means that this particular user should be temporarily
* disqualified due to some particular reason.
* If a user shouldn't be disqualified, then an empty
* string must be returned.
*/
function getTemporaryDisqualification() {
- let applicationLanguage =
- Cc["@mozilla.org/chrome/chrome-registry;1"]
- .getService(Ci.nsIXULChromeRegistry)
- .getSelectedLocale("global")
- .split("-")[0];
-
- if (applicationLanguage == "ru") {
- return "ru";
- }
-
return "";
}
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,3 +1,3 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js
-Current extension version is: 1.6.304
+Current extension version is: 1.6.315
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -19,18 +19,18 @@
} else if (typeof exports !== 'undefined') {
factory(exports);
} else {
factory(root['pdfjsDistBuildPdf'] = {});
}
}(this, function (exports) {
// Use strict in our context only - users might not want it
'use strict';
- var pdfjsVersion = '1.6.304';
- var pdfjsBuild = 'b4100ba';
+ var pdfjsVersion = '1.6.315';
+ var pdfjsBuild = 'a139c75';
var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : null;
var pdfjsLibs = {};
(function pdfjsWrapper() {
(function (root, factory) {
factory(root.pdfjsSharedUtil = {});
}(this, function (exports) {
var globalScope = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this;
var FONT_IDENTITY_MATRIX = [
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -19,18 +19,18 @@
} else if (typeof exports !== 'undefined') {
factory(exports);
} else {
factory(root['pdfjsDistBuildPdfWorker'] = {});
}
}(this, function (exports) {
// Use strict in our context only - users might not want it
'use strict';
- var pdfjsVersion = '1.6.304';
- var pdfjsBuild = 'b4100ba';
+ var pdfjsVersion = '1.6.315';
+ var pdfjsBuild = 'a139c75';
var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : null;
var pdfjsLibs = {};
(function pdfjsWrapper() {
(function (root, factory) {
factory(root.pdfjsCoreArithmeticDecoder = {});
}(this, function (exports) {
/* This class implements the QM Coder decoding as defined in
* JPEG 2000 Part I Final Committee Draft Version 1.0
@@ -45074,16 +45074,39 @@
}
break;
case 'Named':
var namedAction = action.get('N');
if (isName(namedAction)) {
resultObj.action = namedAction.name;
}
break;
+ case 'JavaScript':
+ var jsAction = action.get('JS'), js;
+ if (isStream(jsAction)) {
+ js = bytesToString(jsAction.getBytes());
+ } else if (isString(jsAction)) {
+ js = jsAction;
+ }
+ if (js) {
+ // Attempt to recover valid URLs from 'JS' entries with certain
+ // white-listed formats, e.g.
+ // - window.open('http://example.com')
+ // - app.launchURL('http://example.com', true)
+ var URL_OPEN_METHODS = [
+ 'app.launchURL',
+ 'window.open'
+ ];
+ var regex = new RegExp('^(?:' + URL_OPEN_METHODS.join('|') + ')' + '\\((?:\'|\")(\\S+)(?:\'|\")(?:,|\\))');
+ var jsUrl = regex.exec(stringToPDFString(js), 'i');
+ if (jsUrl && jsUrl[1]) {
+ url = jsUrl[1];
+ break;
+ }
+ }
default:
warn('Catalog_parseDestDictionary: Unrecognized link type "' + linkType + '".');
break;
}
} else if (destDict.has('Dest')) {
// Simple destination link.
dest = destDict.get('Dest');
}
--- a/browser/extensions/pdfjs/content/web/viewer.css
+++ b/browser/extensions/pdfjs/content/web/viewer.css
@@ -321,42 +321,16 @@ select {
cursor: none;
}
.pdfPresentationMode.pdfPresentationModeControls > *,
.pdfPresentationMode.pdfPresentationModeControls .textLayer > div {
cursor: default;
}
-/* outer/inner center provides horizontal center */
-.outerCenter {
- pointer-events: none;
- position: relative;
-}
-html[dir='ltr'] .outerCenter {
- float: right;
- right: 50%;
-}
-html[dir='rtl'] .outerCenter {
- float: left;
- left: 50%;
-}
-.innerCenter {
- pointer-events: auto;
- position: relative;
-}
-html[dir='ltr'] .innerCenter {
- float: right;
- right: -50%;
-}
-html[dir='rtl'] .innerCenter {
- float: left;
- left: -50%;
-}
-
#outerContainer {
width: 100%;
height: 100%;
position: relative;
}
#sidebarContainer {
position: absolute;
@@ -660,34 +634,29 @@ html[dir='ltr'] .doorHangerRight:before
font-style: italic;
color: #A6B7D0;
}
#findInput.notFound {
background-color: rgb(255, 102, 102);
}
-html[dir='ltr'] #toolbarViewerLeft {
- margin-left: -1px;
-}
-html[dir='rtl'] #toolbarViewerRight {
- margin-right: -1px;
+#toolbarViewerMiddle {
+ position: absolute;
+ left: 50%;
+ transform: translateX(-50%);
}
html[dir='ltr'] #toolbarViewerLeft,
html[dir='rtl'] #toolbarViewerRight {
- position: absolute;
- top: 0;
- left: 0;
+ float: left;
}
html[dir='ltr'] #toolbarViewerRight,
html[dir='rtl'] #toolbarViewerLeft {
- position: absolute;
- top: 0;
- right: 0;
+ float: right;
}
html[dir='ltr'] #toolbarViewerLeft > *,
html[dir='ltr'] #toolbarViewerMiddle > *,
html[dir='ltr'] #toolbarViewerRight > *,
html[dir='ltr'] .findbar > * {
position: relative;
float: left;
}
@@ -1953,48 +1922,57 @@ html[dir='rtl'] #documentPropertiesOverl
}
.visibleLargeView,
.visibleMediumView,
.visibleSmallView {
display: none;
}
-@media all and (max-width: 960px) {
- html[dir='ltr'] #outerContainer.sidebarMoving .outerCenter,
- html[dir='ltr'] #outerContainer.sidebarOpen .outerCenter {
- float: left;
- left: 205px;
- }
- html[dir='rtl'] #outerContainer.sidebarMoving .outerCenter,
- html[dir='rtl'] #outerContainer.sidebarOpen .outerCenter {
- float: right;
- right: 205px;
+@media all and (max-width: 1040px) {
+ #outerContainer.sidebarMoving #toolbarViewerMiddle,
+ #outerContainer.sidebarOpen #toolbarViewerMiddle {
+ display: table;
+ margin: auto;
+ left: auto;
+ position: inherit;
+ transform: none;
}
}
-@media all and (max-width: 900px) {
+@media all and (max-width: 980px) {
+ .sidebarMoving .hiddenLargeView,
.sidebarOpen .hiddenLargeView {
display: none;
}
+ .sidebarMoving .visibleLargeView,
.sidebarOpen .visibleLargeView {
display: inherit;
}
}
-@media all and (max-width: 860px) {
+@media all and (max-width: 900px) {
+ #toolbarViewerMiddle {
+ display: table;
+ margin: auto;
+ left: auto;
+ position: inherit;
+ transform: none;
+ }
+ .sidebarMoving .hiddenMediumView,
.sidebarOpen .hiddenMediumView {
display: none;
}
+ .sidebarMoving .visibleMediumView,
.sidebarOpen .visibleMediumView {
display: inherit;
}
}
-@media all and (max-width: 770px) {
+@media all and (max-width: 840px) {
#sidebarContainer {
top: 32px;
z-index: 100;
}
.loadingInProgress #sidebarContainer {
top: 37px;
}
#sidebarContent {
@@ -2004,72 +1982,53 @@ html[dir='rtl'] #documentPropertiesOverl
html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer {
left: 0px;
}
html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer {
right: 0px;
}
- html[dir='ltr'] .outerCenter {
- float: left;
- left: 205px;
- }
- html[dir='rtl'] .outerCenter {
- float: right;
- right: 205px;
- }
-
#outerContainer .hiddenLargeView,
#outerContainer .hiddenMediumView {
display: inherit;
}
#outerContainer .visibleLargeView,
#outerContainer .visibleMediumView {
display: none;
}
}
-@media all and (max-width: 700px) {
+@media all and (max-width: 770px) {
#outerContainer .hiddenLargeView {
display: none;
}
#outerContainer .visibleLargeView {
display: inherit;
}
}
-@media all and (max-width: 660px) {
+@media all and (max-width: 700px) {
#outerContainer .hiddenMediumView {
display: none;
}
#outerContainer .visibleMediumView {
display: inherit;
}
}
-@media all and (max-width: 600px) {
+@media all and (max-width: 640px) {
.hiddenSmallView {
display: none;
}
.visibleSmallView {
display: inherit;
}
- html[dir='ltr'] #outerContainer.sidebarMoving .outerCenter,
- html[dir='ltr'] #outerContainer.sidebarOpen .outerCenter,
- html[dir='ltr'] .outerCenter {
- left: 156px;
- }
- html[dir='rtl'] #outerContainer.sidebarMoving .outerCenter,
- html[dir='rtl'] #outerContainer.sidebarOpen .outerCenter,
- html[dir='rtl'] .outerCenter {
- right: 156px;
- }
.toolbarButtonSpacer {
width: 0;
}
}
-@media all and (max-width: 510px) {
+@media all and (max-width: 535px) {
#scaleSelectContainer {
display: none;
}
}
--- a/browser/extensions/pdfjs/content/web/viewer.html
+++ b/browser/extensions/pdfjs/content/web/viewer.html
@@ -189,45 +189,43 @@ See https://github.com/adobe-type-tools/
</a>
<div class="verticalToolbarSeparator hiddenSmallView"></div>
<button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="36" data-l10n-id="tools">
<span data-l10n-id="tools_label">Tools</span>
</button>
</div>
- <div class="outerCenter">
- <div class="innerCenter" id="toolbarViewerMiddle">
- <div class="splitToolbarButton">
- <button id="zoomOut" class="toolbarButton zoomOut" title="Zoom Out" tabindex="21" data-l10n-id="zoom_out">
- <span data-l10n-id="zoom_out_label">Zoom Out</span>
- </button>
- <div class="splitToolbarButtonSeparator"></div>
- <button id="zoomIn" class="toolbarButton zoomIn" title="Zoom In" tabindex="22" data-l10n-id="zoom_in">
- <span data-l10n-id="zoom_in_label">Zoom In</span>
- </button>
- </div>
- <span id="scaleSelectContainer" class="dropdownToolbarButton">
- <select id="scaleSelect" title="Zoom" tabindex="23" data-l10n-id="zoom">
- <option id="pageAutoOption" title="" value="auto" selected="selected" data-l10n-id="page_scale_auto">Automatic Zoom</option>
- <option id="pageActualOption" title="" value="page-actual" data-l10n-id="page_scale_actual">Actual Size</option>
- <option id="pageFitOption" title="" value="page-fit" data-l10n-id="page_scale_fit">Fit Page</option>
- <option id="pageWidthOption" title="" value="page-width" data-l10n-id="page_scale_width">Full Width</option>
- <option id="customScaleOption" title="" value="custom" hidden="true"></option>
- <option title="" value="0.5" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 50 }'>50%</option>
- <option title="" value="0.75" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 75 }'>75%</option>
- <option title="" value="1" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 100 }'>100%</option>
- <option title="" value="1.25" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 125 }'>125%</option>
- <option title="" value="1.5" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 150 }'>150%</option>
- <option title="" value="2" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 200 }'>200%</option>
- <option title="" value="3" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 300 }'>300%</option>
- <option title="" value="4" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 400 }'>400%</option>
- </select>
- </span>
+ <div id="toolbarViewerMiddle">
+ <div class="splitToolbarButton">
+ <button id="zoomOut" class="toolbarButton zoomOut" title="Zoom Out" tabindex="21" data-l10n-id="zoom_out">
+ <span data-l10n-id="zoom_out_label">Zoom Out</span>
+ </button>
+ <div class="splitToolbarButtonSeparator"></div>
+ <button id="zoomIn" class="toolbarButton zoomIn" title="Zoom In" tabindex="22" data-l10n-id="zoom_in">
+ <span data-l10n-id="zoom_in_label">Zoom In</span>
+ </button>
</div>
+ <span id="scaleSelectContainer" class="dropdownToolbarButton">
+ <select id="scaleSelect" title="Zoom" tabindex="23" data-l10n-id="zoom">
+ <option id="pageAutoOption" title="" value="auto" selected="selected" data-l10n-id="page_scale_auto">Automatic Zoom</option>
+ <option id="pageActualOption" title="" value="page-actual" data-l10n-id="page_scale_actual">Actual Size</option>
+ <option id="pageFitOption" title="" value="page-fit" data-l10n-id="page_scale_fit">Fit Page</option>
+ <option id="pageWidthOption" title="" value="page-width" data-l10n-id="page_scale_width">Full Width</option>
+ <option id="customScaleOption" title="" value="custom" disabled="disabled" hidden="true"></option>
+ <option title="" value="0.5" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 50 }'>50%</option>
+ <option title="" value="0.75" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 75 }'>75%</option>
+ <option title="" value="1" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 100 }'>100%</option>
+ <option title="" value="1.25" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 125 }'>125%</option>
+ <option title="" value="1.5" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 150 }'>150%</option>
+ <option title="" value="2" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 200 }'>200%</option>
+ <option title="" value="3" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 300 }'>300%</option>
+ <option title="" value="4" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 400 }'>400%</option>
+ </select>
+ </span>
</div>
</div>
<div id="loadingBar">
<div class="progress">
<div class="glimmer">
</div>
</div>
</div>
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -529,48 +529,42 @@ Inspector.prototype = {
setupSidebar: function () {
let tabbox = this.panelDoc.querySelector("#inspector-sidebar");
this.sidebar = new ToolSidebar(tabbox, this, "inspector", {
showAllTabsMenu: true
});
let defaultTab = Services.prefs.getCharPref("devtools.inspector.activeSidebar");
+ this._setDefaultSidebar = (event, toolId) => {
+ Services.prefs.setCharPref("devtools.inspector.activeSidebar", toolId);
+ };
+
+ this.sidebar.on("select", this._setDefaultSidebar);
+
if (!Services.prefs.getBoolPref("devtools.fontinspector.enabled") &&
defaultTab == "fontinspector") {
defaultTab = "ruleview";
}
// Append all side panels
this.sidebar.addExistingTab(
"ruleview",
INSPECTOR_L10N.getStr("inspector.sidebar.ruleViewTitle"),
defaultTab == "ruleview");
this.sidebar.addExistingTab(
"computedview",
INSPECTOR_L10N.getStr("inspector.sidebar.computedViewTitle"),
defaultTab == "computedview");
- this._setDefaultSidebar = (event, toolId) => {
- Services.prefs.setCharPref("devtools.inspector.activeSidebar", toolId);
- };
-
- this.sidebar.on("select", this._setDefaultSidebar);
-
this.ruleview = new RuleViewTool(this, this.panelWin);
this.computedview = new ComputedViewTool(this, this.panelWin);
if (Services.prefs.getBoolPref("devtools.layoutview.enabled")) {
- this.sidebar.addExistingTab(
- "layoutview",
- INSPECTOR_L10N.getStr("inspector.sidebar.layoutViewTitle"),
- defaultTab == "layoutview"
- );
-
const {LayoutView} = require("devtools/client/inspector/layout/layout");
this.layoutview = new LayoutView(this, this.panelWin);
}
if (this.target.form.animationsActor) {
this.sidebar.addFrameTab(
"animationinspector",
INSPECTOR_L10N.getStr("inspector.sidebar.animationInspectorTitle"),
--- a/devtools/client/inspector/inspector.xhtml
+++ b/devtools/client/inspector/inspector.xhtml
@@ -186,21 +186,16 @@
<div id="propertyContainer" class="theme-separator" tabindex="0">
</div>
<div id="computedview-no-results" hidden="" data-localization="content=inspector.noProperties"></div>
</div>
</div>
</div>
- <div id="sidebar-panel-layoutview" class="devtools-monospace theme-sidebar inspector-tabpanel"
- data-localization-bundle="devtools/client/locales/inspector.properties">
- <div id="layoutview-container"></div>
- </div>
-
<div id="sidebar-panel-fontinspector" class="devtools-monospace theme-sidebar inspector-tabpanel"
data-localization-bundle="devtools/client/locales/font-inspector.properties">
<div class="devtools-toolbar">
<div class="devtools-searchbox">
<input id="font-preview-text-input" class="devtools-textinput" type="search"
data-localization="placeholder=fontinspector.previewText"/>
</div>
<label id="font-showall" class="theme-link"
--- a/devtools/client/inspector/layout/components/App.js
+++ b/devtools/client/inspector/layout/components/App.js
@@ -13,17 +13,17 @@ const Grid = createFactory(require("./Gr
const App = createClass({
displayName: "App",
render() {
return dom.div(
{
- id: "layoutview-container-focusable",
+ id: "layoutview-container",
},
Accordion({
items: [
{ header: getStr("layout.header"),
component: Grid,
opened: true }
]
})
--- a/devtools/client/inspector/layout/layout.js
+++ b/devtools/client/inspector/layout/layout.js
@@ -1,36 +1,52 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
-const { createFactory, createElement } =
- require("devtools/client/shared/vendor/react");
-const ReactDOM = require("devtools/client/shared/vendor/react-dom");
+const Services = require("Services");
+const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
const { Provider } = require("devtools/client/shared/vendor/react-redux");
const App = createFactory(require("./components/app"));
const Store = require("./store");
+const { LocalizationHelper } = require("devtools/shared/l10n");
+const INSPECTOR_L10N =
+ new LocalizationHelper("devtools/client/locales/inspector.properties");
+
function LayoutView(inspector, window) {
this.inspector = inspector;
this.document = window.document;
this.store = null;
this.init();
}
LayoutView.prototype = {
init() {
let store = this.store = Store();
- let provider = createElement(Provider, { store }, App());
- ReactDOM.render(provider, this.document.querySelector("#layoutview-container"));
+ let provider = createElement(Provider, {
+ store,
+ id: "layoutview",
+ title: INSPECTOR_L10N.getStr("inspector.sidebar.layoutViewTitle"),
+ key: "layoutview",
+ }, App());
+
+ let defaultTab = Services.prefs.getCharPref("devtools.inspector.activeSidebar");
+
+ this.inspector.addSidebarTab(
+ "layoutview",
+ INSPECTOR_L10N.getStr("inspector.sidebar.layoutViewTitle"),
+ provider,
+ defaultTab == "layoutview"
+ );
},
destroy() {
this.inspector = null;
this.document = null;
this.store = null;
},
};
--- a/devtools/client/preferences/devtools.js
+++ b/devtools/client/preferences/devtools.js
@@ -95,22 +95,17 @@ pref("devtools.debugger.remote-timeout",
pref("devtools.debugger.pause-on-exceptions", false);
pref("devtools.debugger.ignore-caught-exceptions", true);
pref("devtools.debugger.source-maps-enabled", true);
pref("devtools.debugger.client-source-maps-enabled", true);
pref("devtools.debugger.pretty-print-enabled", true);
pref("devtools.debugger.auto-pretty-print", false);
pref("devtools.debugger.auto-black-box", true);
pref("devtools.debugger.workers", false);
-
-#if defined(NIGHTLY_BUILD)
pref("devtools.debugger.new-debugger-frontend", true);
-#else
-pref("devtools.debugger.new-debugger-frontend", false);
-#endif
// The default Debugger UI settings
pref("devtools.debugger.ui.panes-workers-and-sources-width", 200);
pref("devtools.debugger.ui.panes-instruments-width", 300);
pref("devtools.debugger.ui.panes-visible-on-startup", false);
pref("devtools.debugger.ui.variables-sorting-enabled", true);
pref("devtools.debugger.ui.variables-only-enum-visible", false);
pref("devtools.debugger.ui.variables-searchbox-visible", false);
--- a/devtools/client/themes/layout.css
+++ b/devtools/client/themes/layout.css
@@ -1,27 +1,14 @@
/* 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/. */
-#sidebar-panel-layoutview {
- margin: 0;
- display: flex;
- flex-direction: column;
- width: 100%;
- height: 100%;
-}
-
#layoutview-container {
height: 100%;
- overflow: auto;
-}
-
-#layoutview-container-focusable {
- height: 100%;
- outline: none;
+ width: 100%;
}
.layoutview-no-grids {
font-style: italic;
text-align: center;
padding: 0.5em;
}
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1723,17 +1723,19 @@ nsDocShell::MaybeInitTiming()
mBlankTiming = false;
}
}
if (!mTiming) {
mTiming = new nsDOMNavigationTiming();
}
- mTiming->NotifyNavigationStart();
+ mTiming->NotifyNavigationStart(
+ mIsActive ? nsDOMNavigationTiming::DocShellState::eActive
+ : nsDOMNavigationTiming::DocShellState::eInactive);
}
//
// Bug 13871: Prevent frameset spoofing
//
// This routine answers: 'Is origin's document from same domain as
// target's document?'
//
@@ -6214,16 +6216,30 @@ nsDocShell::SetIsActive(bool aIsActive)
ScreenOrientation::UpdateActiveOrientationLock(orientation);
}
}
doc->PostVisibilityUpdateEvent();
}
}
+ // Tell the nsDOMNavigationTiming about it
+ RefPtr<nsDOMNavigationTiming> timing = mTiming;
+ if (!timing && mContentViewer) {
+ nsIDocument* doc = mContentViewer->GetDocument();
+ if (doc) {
+ timing = doc->GetNavigationTiming();
+ }
+ }
+ if (timing) {
+ timing->NotifyDocShellStateChanged(
+ aIsActive ? nsDOMNavigationTiming::DocShellState::eActive
+ : nsDOMNavigationTiming::DocShellState::eInactive);
+ }
+
// Recursively tell all of our children, but don't tell <iframe mozbrowser>
// children; they handle their state separately.
nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
while (iter.HasMore()) {
nsCOMPtr<nsIDocShell> docshell = do_QueryObject(iter.GetNext());
if (!docshell) {
continue;
}
@@ -9855,28 +9871,20 @@ nsDocShell::InternalLoad(nsIURI* aURI,
nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
// requestingElement docshell type = current docshell type.
MOZ_ASSERT(mItemType == elementDocShell->ItemType(),
"subframes should have the same docshell type as their parent");
#endif
}
- // XXXbz would be nice to know the loading principal here... but we don't
- nsCOMPtr<nsIPrincipal> requestingPrincipal = aTriggeringPrincipal;
- if (!requestingPrincipal && aReferrer) {
- rv =
- CreatePrincipalFromReferrer(aReferrer, getter_AddRefs(requestingPrincipal));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(contentType,
aURI,
- requestingPrincipal,
+ aTriggeringPrincipal,
requestingContext,
EmptyCString(), // mime guess
nullptr, // extra
&shouldLoad);
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
if (NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) {
return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
--- a/dom/base/DOMIntersectionObserver.cpp
+++ b/dom/base/DOMIntersectionObserver.cpp
@@ -154,25 +154,33 @@ DOMIntersectionObserver::Observe(Element
aTarget.RegisterIntersectionObserver(this);
mObservationTargets.PutEntry(&aTarget);
Connect();
}
void
DOMIntersectionObserver::Unobserve(Element& aTarget)
{
- if (!mObservationTargets.Contains(&aTarget)) {
- return;
+ if (UnlinkTarget(aTarget)) {
+ aTarget.UnregisterIntersectionObserver(this);
}
- if (mObservationTargets.Count() == 1) {
- Disconnect();
- return;
- }
- aTarget.UnregisterIntersectionObserver(this);
- mObservationTargets.RemoveEntry(&aTarget);
+}
+
+bool
+DOMIntersectionObserver::UnlinkTarget(Element& aTarget)
+{
+ if (!mObservationTargets.Contains(&aTarget)) {
+ return false;
+ }
+ if (mObservationTargets.Count() == 1) {
+ Disconnect();
+ return false;
+ }
+ mObservationTargets.RemoveEntry(&aTarget);
+ return true;
}
void
DOMIntersectionObserver::Connect()
{
if (mConnected) {
return;
}
@@ -187,18 +195,20 @@ DOMIntersectionObserver::Disconnect()
if (!mConnected) {
return;
}
for (auto iter = mObservationTargets.Iter(); !iter.Done(); iter.Next()) {
Element* target = iter.Get()->GetKey();
target->UnregisterIntersectionObserver(this);
}
mObservationTargets.Clear();
- nsIDocument* document = mOwner->GetExtantDoc();
- document->RemoveIntersectionObserver(this);
+ if (mOwner) {
+ nsIDocument* document = mOwner->GetExtantDoc();
+ document->RemoveIntersectionObserver(this);
+ }
mConnected = false;
}
void
DOMIntersectionObserver::TakeRecords(nsTArray<RefPtr<DOMIntersectionObserverEntry>>& aRetVal)
{
aRetVal.SwapElements(mQueuedEntries);
mQueuedEntries.Clear();
--- a/dom/base/DOMIntersectionObserver.h
+++ b/dom/base/DOMIntersectionObserver.h
@@ -137,17 +137,19 @@ public:
return mRoot;
}
void GetRootMargin(mozilla::dom::DOMString& aRetVal);
void GetThresholds(nsTArray<double>& aRetVal);
void Observe(Element& aTarget);
void Unobserve(Element& aTarget);
+ bool UnlinkTarget(Element& aTarget);
void Disconnect();
+
void TakeRecords(nsTArray<RefPtr<DOMIntersectionObserverEntry>>& aRetVal);
mozilla::dom::IntersectionCallback* IntersectionCallback() { return mCallback; }
bool SetRootMargin(const nsAString& aString);
void Update(nsIDocument* aDocument, DOMHighResTimeStamp time);
void Notify();
--- a/dom/base/File.cpp
+++ b/dom/base/File.cpp
@@ -559,46 +559,20 @@ File::Constructor(const GlobalObject& aG
impl->SetLastModified(aBag.mLastModified.Value());
}
RefPtr<File> file = new File(aGlobal.GetAsSupports(), impl);
return file.forget();
}
/* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
- Blob& aData,
- const ChromeFilePropertyBag& aBag,
- ErrorResult& aRv)
-{
- if (!nsContentUtils::ThreadsafeIsCallerChrome()) {
- aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(NS_LITERAL_STRING("Argument 1 of File.constructor"));
- return nullptr;
- }
-
- RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(EmptyString());
- impl->InitializeChromeFile(aData, aBag, aRv);
- if (aRv.Failed()) {
- return nullptr;
- }
- MOZ_ASSERT(impl->IsFile());
-
- if (aBag.mLastModified.WasPassed()) {
- impl->SetLastModified(aBag.mLastModified.Value());
- }
-
- RefPtr<File> domFile = new File(aGlobal.GetAsSupports(), impl);
- return domFile.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
- nsIFile* aData,
- const ChromeFilePropertyBag& aBag,
- ErrorResult& aRv)
+File::CreateFromNsIFile(const GlobalObject& aGlobal,
+ nsIFile* aData,
+ const ChromeFilePropertyBag& aBag,
+ ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
if (!nsContentUtils::IsCallerChrome()) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
@@ -614,20 +588,20 @@ File::Constructor(const GlobalObject& aG
impl->SetLastModified(aBag.mLastModified.Value());
}
RefPtr<File> domFile = new File(aGlobal.GetAsSupports(), impl);
return domFile.forget();
}
/* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
- const nsAString& aData,
- const ChromeFilePropertyBag& aBag,
- ErrorResult& aRv)
+File::CreateFromFileName(const GlobalObject& aGlobal,
+ const nsAString& aData,
+ const ChromeFilePropertyBag& aBag,
+ ErrorResult& aRv)
{
if (!nsContentUtils::ThreadsafeIsCallerChrome()) {
aRv.ThrowTypeError<MSG_MISSING_ARGUMENTS>(NS_LITERAL_STRING("File"));
return nullptr;
}
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
--- a/dom/base/File.h
+++ b/dom/base/File.h
@@ -206,36 +206,29 @@ public:
// File constructor
static already_AddRefed<File>
Constructor(const GlobalObject& aGlobal,
const Sequence<BlobPart>& aData,
const nsAString& aName,
const FilePropertyBag& aBag,
ErrorResult& aRv);
- // File constructor - ChromeOnly
- static already_AddRefed<File>
- Constructor(const GlobalObject& aGlobal,
- Blob& aData,
- const ChromeFilePropertyBag& aBag,
- ErrorResult& aRv);
-
- // File constructor - ChromeOnly
+ // ChromeOnly
static already_AddRefed<File>
- Constructor(const GlobalObject& aGlobal,
- const nsAString& aData,
- const ChromeFilePropertyBag& aBag,
- ErrorResult& aRv);
+ CreateFromFileName(const GlobalObject& aGlobal,
+ const nsAString& aData,
+ const ChromeFilePropertyBag& aBag,
+ ErrorResult& aRv);
- // File constructor - ChromeOnly
+ // ChromeOnly
static already_AddRefed<File>
- Constructor(const GlobalObject& aGlobal,
- nsIFile* aData,
- const ChromeFilePropertyBag& aBag,
- ErrorResult& aRv);
+ CreateFromNsIFile(const GlobalObject& aGlobal,
+ nsIFile* aData,
+ const ChromeFilePropertyBag& aBag,
+ ErrorResult& aRv);
void GetName(nsAString& aName) const;
int64_t GetLastModified(ErrorResult& aRv);
Date GetLastModifiedDate(ErrorResult& aRv);
// GetPath and SetPath are currently used only for the webkitRelativePath
--- a/dom/base/nsDOMDataChannel.cpp
+++ b/dom/base/nsDOMDataChannel.cpp
@@ -352,27 +352,27 @@ nsDOMDataChannel::Send(nsIInputStream* a
if (state == mozilla::DataChannel::CLOSING ||
state == mozilla::DataChannel::CLOSED) {
return;
}
MOZ_ASSERT(state == mozilla::DataChannel::OPEN,
"Unknown state in nsDOMDataChannel::Send");
- int32_t sent;
+ bool sent;
if (aMsgStream) {
sent = mDataChannel->SendBinaryStream(aMsgStream, aMsgLength);
} else {
if (aIsBinary) {
sent = mDataChannel->SendBinaryMsg(aMsgString);
} else {
sent = mDataChannel->SendMsg(aMsgString);
}
}
- if (sent < 0) {
+ if (!sent) {
aRv.Throw(NS_ERROR_FAILURE);
}
}
nsresult
nsDOMDataChannel::DoOnMessageAvailable(const nsACString& aData,
bool aBinary)
{
--- a/dom/base/nsDOMNavigationTiming.cpp
+++ b/dom/base/nsDOMNavigationTiming.cpp
@@ -1,20 +1,23 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsDOMNavigationTiming.h"
+
+#include "GeckoProfiler.h"
#include "nsCOMPtr.h"
#include "nsContentUtils.h"
#include "nsIScriptSecurityManager.h"
#include "prtime.h"
#include "nsIURI.h"
+#include "nsPrintfCString.h"
#include "mozilla/dom/PerformanceNavigation.h"
#include "mozilla/TimeStamp.h"
nsDOMNavigationTiming::nsDOMNavigationTiming()
{
Clear();
}
@@ -40,16 +43,17 @@ nsDOMNavigationTiming::Clear()
mLoadEventStartSet = false;
mLoadEventEndSet = false;
mDOMLoadingSet = false;
mDOMInteractiveSet = false;
mDOMContentLoadedEventStartSet = false;
mDOMContentLoadedEventEndSet = false;
mDOMCompleteSet = false;
+ mDocShellHasBeenActiveSinceNavigationStart = false;
}
DOMTimeMilliSec
nsDOMNavigationTiming::TimeStampToDOM(mozilla::TimeStamp aStamp) const
{
if (aStamp.IsNull()) {
return 0;
}
@@ -58,20 +62,21 @@ nsDOMNavigationTiming::TimeStampToDOM(mo
}
DOMTimeMilliSec nsDOMNavigationTiming::DurationFromStart()
{
return TimeStampToDOM(mozilla::TimeStamp::Now());
}
void
-nsDOMNavigationTiming::NotifyNavigationStart()
+nsDOMNavigationTiming::NotifyNavigationStart(DocShellState aDocShellState)
{
mNavigationStartHighRes = (double)PR_Now() / PR_USEC_PER_MSEC;
mNavigationStartTimeStamp = mozilla::TimeStamp::Now();
+ mDocShellHasBeenActiveSinceNavigationStart = (aDocShellState == DocShellState::eActive);
}
void
nsDOMNavigationTiming::NotifyFetchStart(nsIURI* aURI, Type aNavigationType)
{
mNavigationType = aNavigationType;
// At the unload event time we don't really know the loading uri.
// Need it for later check for unload timing access.
@@ -176,16 +181,54 @@ nsDOMNavigationTiming::NotifyDOMContentL
{
if (!mDOMContentLoadedEventEndSet) {
mLoadedURI = aURI;
mDOMContentLoadedEventEnd = DurationFromStart();
mDOMContentLoadedEventEndSet = true;
}
}
+void
+nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!mNavigationStartTimeStamp.IsNull());
+
+ if (!mNonBlankPaintTimeStamp.IsNull()) {
+ return;
+ }
+
+ mNonBlankPaintTimeStamp = TimeStamp::Now();
+ TimeDuration elapsed = mNonBlankPaintTimeStamp - mNavigationStartTimeStamp;
+
+ if (profiler_is_active()) {
+ nsAutoCString spec;
+ if (mLoadedURI) {
+ mLoadedURI->GetSpec(spec);
+ }
+ nsPrintfCString marker("Non-blank paint after %dms for URL %s, %s",
+ int(elapsed.ToMilliseconds()), spec.get(),
+ mDocShellHasBeenActiveSinceNavigationStart ? "foreground tab" : "this tab was inactive some of the time between navigation start and first non-blank paint");
+ PROFILER_MARKER(marker.get());
+ }
+
+ if (mDocShellHasBeenActiveSinceNavigationStart) {
+ Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_NON_BLANK_PAINT_MS,
+ mNavigationStartTimeStamp,
+ mNonBlankPaintTimeStamp);
+ }
+}
+
+void
+nsDOMNavigationTiming::NotifyDocShellStateChanged(DocShellState aDocShellState)
+{
+ mDocShellHasBeenActiveSinceNavigationStart &=
+ (aDocShellState == DocShellState::eActive);
+}
+
DOMTimeMilliSec
nsDOMNavigationTiming::GetUnloadEventStart()
{
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
nsresult rv = ssm->CheckSameOriginURI(mLoadedURI, mUnloadedURI, false);
if (NS_SUCCEEDED(rv)) {
return mUnloadStart;
}
--- a/dom/base/nsDOMNavigationTiming.h
+++ b/dom/base/nsDOMNavigationTiming.h
@@ -76,32 +76,41 @@ public:
{
return mLoadEventStart;
}
DOMTimeMilliSec GetLoadEventEnd() const
{
return mLoadEventEnd;
}
- void NotifyNavigationStart();
+ enum class DocShellState : uint8_t {
+ eActive,
+ eInactive
+ };
+
+ void NotifyNavigationStart(DocShellState aDocShellState);
void NotifyFetchStart(nsIURI* aURI, Type aNavigationType);
void NotifyBeforeUnload();
void NotifyUnloadAccepted(nsIURI* aOldURI);
void NotifyUnloadEventStart();
void NotifyUnloadEventEnd();
void NotifyLoadEventStart();
void NotifyLoadEventEnd();
// Document changes state to 'loading' before connecting to timing
void SetDOMLoadingTimeStamp(nsIURI* aURI, mozilla::TimeStamp aValue);
void NotifyDOMLoading(nsIURI* aURI);
void NotifyDOMInteractive(nsIURI* aURI);
void NotifyDOMComplete(nsIURI* aURI);
void NotifyDOMContentLoadedStart(nsIURI* aURI);
void NotifyDOMContentLoadedEnd(nsIURI* aURI);
+
+ void NotifyNonBlankPaintForRootContentDocument();
+ void NotifyDocShellStateChanged(DocShellState aDocShellState);
+
DOMTimeMilliSec TimeStampToDOM(mozilla::TimeStamp aStamp) const;
inline DOMHighResTimeStamp TimeStampToDOMHighRes(mozilla::TimeStamp aStamp)
{
mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp;
return duration.ToMilliseconds();
}
@@ -112,16 +121,17 @@ private:
void Clear();
nsCOMPtr<nsIURI> mUnloadedURI;
nsCOMPtr<nsIURI> mLoadedURI;
Type mNavigationType;
DOMHighResTimeStamp mNavigationStartHighRes;
mozilla::TimeStamp mNavigationStartTimeStamp;
+ mozilla::TimeStamp mNonBlankPaintTimeStamp;
DOMTimeMilliSec DurationFromStart();
DOMTimeMilliSec mBeforeUnloadStart;
DOMTimeMilliSec mUnloadStart;
DOMTimeMilliSec mUnloadEnd;
DOMTimeMilliSec mLoadEventStart;
DOMTimeMilliSec mLoadEventEnd;
@@ -136,11 +146,12 @@ private:
// once.
bool mLoadEventStartSet : 1;
bool mLoadEventEndSet : 1;
bool mDOMLoadingSet : 1;
bool mDOMInteractiveSet : 1;
bool mDOMContentLoadedEventStartSet : 1;
bool mDOMContentLoadedEventEndSet : 1;
bool mDOMCompleteSet : 1;
+ bool mDocShellHasBeenActiveSinceNavigationStart : 1;
};
#endif /* nsDOMNavigationTiming_h___ */
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -292,16 +292,25 @@ nsNodeUtils::LastRelease(nsINode* aNode)
nsINode::nsSlots* slots = aNode->GetExistingSlots();
if (slots) {
if (!slots->mMutationObservers.IsEmpty()) {
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(slots->mMutationObservers,
nsIMutationObserver,
NodeWillBeDestroyed, (aNode));
}
+ if (aNode->IsElement()) {
+ Element* elem = aNode->AsElement();
+ FragmentOrElement::nsDOMSlots* domSlots =
+ static_cast<FragmentOrElement::nsDOMSlots*>(slots);
+ for (auto& reg : domSlots->mRegisteredIntersectionObservers) {
+ reg.observer->UnlinkTarget(*elem);
+ }
+ }
+
delete slots;
aNode->mSlots = nullptr;
}
// Kill properties first since that may run external code, so we want to
// be in as complete state as possible at that time.
if (aNode->IsNodeOfType(nsINode::eDOCUMENT)) {
// Delete all properties before tearing down the document. Some of the
--- a/dom/base/test/bug403852_fileOpener.js
+++ b/dom/base/test/bug403852_fileOpener.js
@@ -4,14 +4,14 @@ Cu.importGlobalProperties(["File"]);
var testFile = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get("ProfD", Ci.nsIFile);
testFile.append("prefs.js");
addMessageListener("file.open", function () {
sendAsyncMessage("file.opened", {
- file: new File(testFile),
+ file: File.createFromNsIFile(testFile),
mtime: testFile.lastModifiedTime,
- fileWithDate: new File(testFile, { lastModified: 123 }),
+ fileWithDate: File.createFromNsIFile(testFile, { lastModified: 123 }),
fileDate: 123,
});
});
--- a/dom/base/test/bug578096LoadChromeScript.js
+++ b/dom/base/test/bug578096LoadChromeScript.js
@@ -2,15 +2,15 @@ var file;
Components.utils.importGlobalProperties(["File"]);
addMessageListener("file.create", function (message) {
file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("TmpD", Components.interfaces.nsIFile);
file.append("foo.txt");
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o600);
- sendAsyncMessage("file.created", new File(file));
+ sendAsyncMessage("file.created", File.createFromNsIFile(file));
});
addMessageListener("file.remove", function (message) {
file.remove(false);
sendAsyncMessage("file.removed", {});
});
--- a/dom/base/test/chrome/test_bug914381.html
+++ b/dom/base/test/chrome/test_bug914381.html
@@ -30,19 +30,19 @@ function createFileWithData(fileData) {
outStream.write(fileData, fileData.length);
outStream.close();
return testFile;
}
/** Test for Bug 914381. File's created in JS using an nsIFile should allow mozGetFullPathInternal calls to succeed **/
var file = createFileWithData("Test bug 914381");
-var f = new File(file);
+var f = File.createFromNsIFile(file);
is(f.mozFullPathInternal, undefined, "mozFullPathInternal is undefined from js");
is(f.mozFullPath, file.path, "mozFullPath returns path if created with nsIFile");
-f = new File(file.path);
+f = File.createFromFileName(file.path);
is(f.mozFullPathInternal, undefined, "mozFullPathInternal is undefined from js");
is(f.mozFullPath, "", "mozFullPath returns blank if created with a string");
</script>
</pre>
</body>
</html>
--- a/dom/base/test/chrome/test_fileconstructor.xul
+++ b/dom/base/test/chrome/test_fileconstructor.xul
@@ -37,43 +37,36 @@ var file = Components.classes["@mozilla.
// man I wish this were simpler ...
file.append("chrome");
file.append("dom");
file.append("base");
file.append("test");
file.append("chrome");
file.append("fileconstructor_file.png");
-doTest(new File(file.path));
-doTest(new File(file));
+doTest(File.createFromFileName(file.path));
+doTest(File.createFromNsIFile(file));
function doTest(domfile) {
ok(domfile instanceof File, "File() should return a File");
is(domfile.type, "image/png", "File should be a PNG");
is(domfile.size, 95, "File has size 95 (and more importantly we can read it)");
}
try {
- var boomfile = new File();
- ok(false, "This should never be reached!");
-} catch (e) {
- ok(true, "Botched file constructor attempts throw and do not crash.");
-}
-
-try {
- var nonexistentfile = new File("i/sure/hope/this/does/not/exist/anywhere.txt");
+ var nonexistentfile = File.createFromFileName("i/sure/hope/this/does/not/exist/anywhere.txt");
ok(false, "This should never be reached!");
} catch (e) {
ok(true, "Attempt to construct a non-existent file should fail.");
}
try {
var dir = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("CurWorkD", Components.interfaces.nsIFile);
- var dirfile = new File(dir);
+ var dirfile = File.createFromNsIFile(dir);
ok(false, "This should never be reached!");
} catch (e) {
ok(true, "Attempt to construct a file from a directory should fail.");
}
]]>
</script>
</window>
--- a/dom/base/test/chrome/test_fileconstructor_tempfile.xul
+++ b/dom/base/test/chrome/test_fileconstructor_tempfile.xul
@@ -67,17 +67,17 @@ try {
.createInstance(Ci.nsIFileOutputStream);
outStream.init(tmp, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
// Create a scoped DOMFile so the gc will happily get rid of it.
{
- let dirfile = new File(tmp, { temporary: true });
+ let dirfile = File.createFromNsIFile(tmp, { temporary: true });
ok(true, "Temporary File() created");
let reader = new FileReader();
reader.readAsArrayBuffer(dirfile);
reader.onload = function(event) {
let buffer = event.target.result;
ok(buffer.byteLength > 0,
"Blob size should be > 0 : " + buffer.byteLength);
cleanup(tmp);
--- a/dom/base/test/create_file_objects.js
+++ b/dom/base/test/create_file_objects.js
@@ -1,10 +1,10 @@
Components.utils.importGlobalProperties(['File']);
addMessageListener("create-file-objects", function(message) {
let files = []
for (fileName of message.fileNames) {
- files.push(new File(fileName));
+ files.push(File.createFromFileName(fileName));
}
sendAsyncMessage("created-file-objects", files);
});
--- a/dom/base/test/file_bug1198095.js
+++ b/dom/base/test/file_bug1198095.js
@@ -8,17 +8,17 @@ function createFileWithData(message) {
var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0o666, 0);
outStream.write(message, message.length);
outStream.close();
- var domFile = new File(testFile);
+ var domFile = File.createFromNsIFile(testFile);
return domFile;
}
addMessageListener("file.open", function (message) {
sendAsyncMessage("file.opened", createFileWithData(message));
});
addMessageListener("file.modify", function (message) {
--- a/dom/base/test/fileapi_chromeScript.js
+++ b/dom/base/test/fileapi_chromeScript.js
@@ -12,17 +12,17 @@ function createFileWithData(fileData) {
var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0o666, 0);
if (willDelete) {
fileData = "some irrelevant test data\n";
}
outStream.write(fileData, fileData.length);
outStream.close();
- var domFile = new File(testFile);
+ var domFile = File.createFromNsIFile(testFile);
if (willDelete) {
testFile.remove(/* recursive: */ false);
}
return domFile;
}
addMessageListener("files.open", function (message) {
sendAsyncMessage("files.opened", message.map(createFileWithData));
--- a/dom/base/test/script_bug1238440.js
+++ b/dom/base/test/script_bug1238440.js
@@ -6,17 +6,17 @@ var tmpFile;
function writeFile(text, answer) {
var stream = Cc["@mozilla.org/network/file-output-stream;1"]
.createInstance(Ci.nsIFileOutputStream);
stream.init(tmpFile, 0x02 | 0x08 | 0x10, 0o600, 0);
stream.write(text, text.length);
stream.close();
sendAsyncMessage(answer, {
- file: new File(tmpFile)
+ file: File.createFromNsIFile(tmpFile)
});
}
addMessageListener("file.open", function (e) {
tmpFile = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get('TmpD', Ci.nsIFile)
--- a/dom/base/test/script_postmessages_fileList.js
+++ b/dom/base/test/script_postmessages_fileList.js
@@ -4,17 +4,17 @@ Cu.importGlobalProperties(["File"]);
addMessageListener("file.open", function () {
var testFile = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get("ProfD", Ci.nsIFile);
testFile.append("prefs.js");
sendAsyncMessage("file.opened", {
- file: new File(testFile)
+ file: File.createFromNsIFile(testFile)
});
});
addMessageListener("dir.open", function () {
var testFile = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get("ProfD", Ci.nsIFile);
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -518,12 +518,18 @@ public:
// Allow converting to const sequences as needed
operator const Sequence<T>&() const {
return *reinterpret_cast<const Sequence<T>*>(this);
}
};
} // namespace binding_detail
+// Enum to represent a system or non-system caller type.
+enum class CallerType {
+ System,
+ NonSystem
+};
+
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_BindingDeclarations_h__
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1592,16 +1592,21 @@ DOMInterfaces = {
# Keep this in sync with TestInterface
'headerFile': 'TestExampleInterface-example.h',
'register': False,
'binaryNames': { 'methodRenamedFrom': 'methodRenamedTo',
'attributeGetterRenamedFrom': 'attributeGetterRenamedTo',
'attributeRenamedFrom': 'attributeRenamedTo' }
},
+'TestExampleWorkerInterface' : {
+ 'headerFile': 'TestExampleWorkerInterface-example.h',
+ 'register': False,
+ },
+
'TestExampleProxyInterface' : {
'headerFile': 'TestExampleProxyInterface-example.h',
'register': False
},
'TestDeprecatedInterface' : {
# Keep this in sync with TestExampleInterface
'headerFile': 'TestBindingHeader.h',
@@ -1629,16 +1634,21 @@ DOMInterfaces = {
'register': False,
},
'TestProtoObjectHackedNamespace' : {
'headerFile': 'TestBindingHeader.h',
'register': False,
},
+'TestWorkerExposedInterface' : {
+ 'headerFile': 'TestBindingHeader.h',
+ 'register': False,
+ },
+
}
# These are temporary, until they've been converted to use new DOM bindings
def addExternalIface(iface, nativeType=None, headerFile=None,
notflattened=False):
if iface in DOMInterfaces:
raise Exception('Interface declared both as WebIDL and External interface')
domInterface = {
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -6906,25 +6906,28 @@ def needScopeObject(returnType, argument
class CGCallGenerator(CGThing):
"""
A class to generate an actual call to a C++ object. Assumes that the C++
object is stored in a variable whose name is given by the |object| argument.
needsSubjectPrincipal is a boolean indicating whether the call should
receive the subject nsIPrincipal as argument.
+ needsCallerType is a boolean indicating whether the call should receive
+ a PrincipalType for the caller.
+
isFallible is a boolean indicating whether the call should be fallible.
resultVar: If the returnType is not void, then the result of the call is
stored in a C++ variable named by resultVar. The caller is responsible for
declaring the result variable. If the caller doesn't care about the result
value, resultVar can be omitted.
"""
- def __init__(self, isFallible, needsSubjectPrincipal, arguments, argsPre,
- returnType, extendedAttributes, descriptor,
+ def __init__(self, isFallible, needsSubjectPrincipal, needsCallerType,
+ arguments, argsPre, returnType, extendedAttributes, descriptor,
nativeMethodName, static, object="self", argsPost=[],
resultVar=None):
CGThing.__init__(self)
result, resultOutParam, resultRooter, resultArgs, resultConversion = \
getRetvalDeclarationForType(returnType, descriptor)
args = CGList([CGGeneric(arg) for arg in argsPre], ", ")
@@ -6976,16 +6979,19 @@ class CGCallGenerator(CGThing):
args.append(CGGeneric(resultVar))
else:
assert resultOutParam == "ptr"
args.append(CGGeneric("&" + resultVar))
if needsSubjectPrincipal:
args.append(CGGeneric("subjectPrincipal"))
+ if needsCallerType:
+ args.append(CGGeneric("callerType"))
+
if isFallible:
args.append(CGGeneric("rv"))
args.extend(CGGeneric(arg) for arg in argsPost)
# Build up our actual call
self.cgRoot = CGList([])
call = CGGeneric(nativeMethodName)
@@ -7042,16 +7048,34 @@ class CGCallGenerator(CGThing):
"""
$*{getPrincipal}
// Initializing a nonnull is pretty darn annoying...
NonNull<nsIPrincipal> subjectPrincipal;
subjectPrincipal = static_cast<nsIPrincipal*>(nsJSPrincipals::get(principals));
""",
getPrincipal=getPrincipal)))
+ if needsCallerType:
+ # Note that we do not want to use
+ # IsCallerChrome/ThreadsafeIsCallerChrome directly because those
+ # will pull in the check for UniversalXPConnect, which we ideally
+ # don't want to have in the new thing we're doing here. If not
+ # NS_IsMainThread(), though, we'll go ahead and call
+ # ThreasafeIsCallerChrome(), since that won't mess with
+ # UnivesalXPConnect and we don't want to worry about the right
+ # worker includes here.
+ callerCheck = CGGeneric("callerType = nsContentUtils::IsSystemPrincipal(nsContentUtils::SubjectPrincipal()) ? CallerType::System : CallerType::NonSystem;\n")
+ if descriptor.interface.isExposedInAnyWorker():
+ callerCheck = CGIfElseWrapper(
+ "NS_IsMainThread()",
+ callerCheck,
+ CGGeneric("callerType = nsContentUtils::ThreadsafeIsCallerChrome() ? CallerType::System : CallerType::NonSystem;\n"));
+ self.cgRoot.prepend(callerCheck)
+ self.cgRoot.prepend(CGGeneric("CallerType callerType;\n"))
+
if isFallible:
self.cgRoot.prepend(CGGeneric("binding_detail::FastErrorResult rv;\n"))
self.cgRoot.append(CGGeneric(dedent(
"""
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
return false;
}
""")))
@@ -7214,16 +7238,18 @@ def wrapArgIntoCurrentCompartment(arg, v
if wrap and isOptional:
wrap = CGIfWrapper(wrap, "%s.WasPassed()" % origValue)
return wrap
def needsContainsHack(m):
return m.getExtendedAttribute("ReturnValueNeedsContainsHack")
+def needsCallerType(m):
+ return m.getExtendedAttribute("NeedsCallerType")
class CGPerSignatureCall(CGThing):
"""
This class handles the guts of generating code for a particular
call signature. A call signature consists of four things:
1) A return type, which can be None to indicate that there is no
actual return value (e.g. this is an attribute setter) or an
@@ -7513,16 +7539,17 @@ class CGPerSignatureCall(CGThing):
else:
cgThings.append(CGIterableMethodGenerator(descriptor,
idlNode.maplikeOrSetlikeOrIterable,
idlNode.identifier.name))
else:
cgThings.append(CGCallGenerator(
self.isFallible(),
idlNode.getExtendedAttribute('NeedsSubjectPrincipal'),
+ needsCallerType(idlNode),
self.getArguments(), argsPre, returnType,
self.extendedAttributes, descriptor,
nativeMethodName,
static, argsPost=argsPost, resultVar=resultVar))
if useCounterName:
# Generate a telemetry call for when [UseCounter] is used.
code = "SetDocumentAndPageUseCounter(cx, obj, eUseCounter_%s);\n" % useCounterName
@@ -13633,17 +13660,18 @@ class CGBindingRoot(CGThing):
bindingHeaders["mozilla/Preferences.h"] = any(
descriptorRequiresPreferences(d) for d in descriptors)
bindingHeaders["mozilla/dom/DOMJSProxyHandler.h"] = any(
d.concrete and d.proxy for d in descriptors)
def descriptorHasChromeOnly(desc):
ctor = desc.interface.ctor()
- return (any(isChromeOnly(a) or needsContainsHack(a)
+ return (any(isChromeOnly(a) or needsContainsHack(a) or
+ needsCallerType(a)
for a in desc.interface.members) or
desc.interface.getExtendedAttribute("ChromeOnly") is not None or
# JS-implemented interfaces with an interface object get a
# chromeonly _create method. And interfaces with an
# interface object might have a ChromeOnly constructor.
(desc.interface.hasInterfaceObject() and
(desc.interface.isJSImplemented() or
(ctor and isChromeOnly(ctor)))) or
@@ -14076,17 +14104,24 @@ class CGNativeMember(ClassMethod):
"aRetVal"))
elif returnType.isAny():
args.append(Argument("JS::MutableHandle<JS::Value>", "aRetVal"))
elif returnType.isObject() or returnType.isSpiderMonkeyInterface():
args.append(Argument("JS::MutableHandle<JSObject*>", "aRetVal"))
# And the nsIPrincipal
if self.member.getExtendedAttribute('NeedsSubjectPrincipal'):
- args.append(Argument("nsIPrincipal&", "aPrincipal"))
+ # Cheat and assume self.descriptorProvider is a descriptor
+ if self.descriptorProvider.interface.isExposedInAnyWorker():
+ args.append(Argument("Maybe<nsIPrincipal*>", "aSubjectPrincipal"))
+ else:
+ args.append(Argument("nsIPrincipal&", "aPrincipal"))
+ # And the caller type, if desired.
+ if needsCallerType(self.member):
+ args.append(Argument("CallerType", "aCallerType"))
# And the ErrorResult
if 'infallible' not in self.extendedAttrs:
# Use aRv so it won't conflict with local vars named "rv"
args.append(Argument("ErrorResult&", "aRv"))
# The legacycaller thisval
if self.member.isMethod() and self.member.isLegacycaller():
# If it has an identifier, we can't deal with it yet
assert self.member.isIdentifierLess()
--- a/dom/bindings/docs/index.rst
+++ b/dom/bindings/docs/index.rst
@@ -78,17 +78,18 @@ Parser unit tests
The current mechanism for this is ``mach webidl-parser-test``.
Mochitests
There are various mochitests under ``dom/bindings/test``. They should
be runnable through the standard mechanisms.
Working with test interfaces
``TestExampleGenBinding.cpp`` calls into methods from the
- ``TestExampleInterface`` and ``TestExampleProxyInterface`` interfaces.
+ ``TestExampleInterface``, ``TestExampleProxyInterface``,
+ and ``TestExampleWorkerInterface`` interfaces.
These interfaces need to be generated as part of the build. These
interfaces should not be exported or packaged.
There is a ``compiletests`` make target in ``dom/bindings`` that
isn't part of the build that facilitates turnkey code generation
and test file compilation.
Minimal rebuilds
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -4221,16 +4221,17 @@ class IDLAttribute(IDLInterfaceMember):
identifier == "GetterThrows" or
identifier == "ChromeOnly" or
identifier == "Func" or
identifier == "SecureContext" or
identifier == "Frozen" or
identifier == "NewObject" or
identifier == "UnsafeInPrerendering" or
identifier == "NeedsSubjectPrincipal" or
+ identifier == "NeedsCallerType" or
identifier == "ReturnValueNeedsContainsHack" or
identifier == "BinaryName"):
# Known attributes that we don't need to do anything with here
pass
else:
raise WebIDLError("Unknown extended attribute %s on attribute" % identifier,
[attr.location])
IDLInterfaceMember.handleExtendedAttribute(self, attr)
@@ -4939,16 +4940,17 @@ class IDLMethod(IDLInterfaceMember, IDLS
identifier == "ChromeOnly" or
identifier == "UnsafeInPrerendering" or
identifier == "Pref" or
identifier == "Deprecated" or
identifier == "Func" or
identifier == "SecureContext" or
identifier == "BinaryName" or
identifier == "NeedsSubjectPrincipal" or
+ identifier == "NeedsCallerType" or
identifier == "StaticClassOverride"):
# Known attributes that we don't need to do anything with here
pass
else:
raise WebIDLError("Unknown extended attribute %s on method" % identifier,
[attr.location])
IDLInterfaceMember.handleExtendedAttribute(self, attr)
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -931,16 +931,19 @@ public:
void SetThrowingAttr(bool arg, ErrorResult& aRv);
bool GetThrowingGetterAttr(ErrorResult& aRv) const;
void SetThrowingGetterAttr(bool arg);
bool ThrowingSetterAttr() const;
void SetThrowingSetterAttr(bool arg, ErrorResult& aRv);
void NeedsSubjectPrincipalMethod(nsIPrincipal&);
bool NeedsSubjectPrincipalAttr(nsIPrincipal&);
void SetNeedsSubjectPrincipalAttr(bool, nsIPrincipal&);
+ void NeedsCallerTypeMethod(CallerType);
+ bool NeedsCallerTypeAttr(CallerType);
+ void SetNeedsCallerTypeAttr(bool, CallerType);
int16_t LegacyCall(const JS::Value&, uint32_t, TestInterface&);
void PassArgsWithDefaults(JSContext*, const Optional<int32_t>&,
TestInterface*, const Dict&, double,
const Optional<float>&);
void SetDashed_attribute(int8_t);
int8_t Dashed_attribute();
void Dashed_method();
@@ -1400,12 +1403,29 @@ public:
};
class TestRenamedNamespace {
};
class TestProtoObjectHackedNamespace {
};
+class TestWorkerExposedInterface : public nsISupports,
+ public nsWrapperCache
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // We need a GetParentObject to make binding codegen happy
+ nsISupports* GetParentObject();
+
+ void NeedsSubjectPrincipalMethod(Maybe<nsIPrincipal*>);
+ bool NeedsSubjectPrincipalAttr(Maybe<nsIPrincipal*>);
+ void SetNeedsSubjectPrincipalAttr(bool, Maybe<nsIPrincipal*>);
+ void NeedsCallerTypeMethod(CallerType);
+ bool NeedsCallerTypeAttr(CallerType);
+ void SetNeedsCallerTypeAttr(bool, CallerType);
+};
+
} // namespace dom
} // namespace mozilla
#endif /* TestBindingHeader_h */
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -940,16 +940,18 @@ interface TestInterface {
[PutForwards=writableByte, LenientThis] readonly attribute TestInterface putForwardsAttr2;
[PutForwards=writableByte, ChromeOnly] readonly attribute TestInterface putForwardsAttr3;
[Throws] void throwingMethod();
[Throws] attribute boolean throwingAttr;
[GetterThrows] attribute boolean throwingGetterAttr;
[SetterThrows] attribute boolean throwingSetterAttr;
[NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
[NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
+ [NeedsCallerType] void needsCallerTypeMethod();
+ [NeedsCallerType] attribute boolean needsCallerTypeAttr;
legacycaller short(unsigned long arg1, TestInterface arg2);
void passArgsWithDefaults(optional long arg1,
optional TestInterface? arg2 = null,
optional Dict arg3, optional double arg4 = 5.0,
optional float arg5);
attribute any jsonifierShouldSkipThis;
attribute TestParentInterface jsonifierShouldSkipThis2;
@@ -1247,8 +1249,16 @@ namespace TestRenamedNamespace {
[ProtoObjectHack]
namespace TestProtoObjectHackedNamespace {
};
[SecureContext]
interface TestSecureContextInterface {
static void alsoSecureContext();
};
+
+[Exposed=(Window,Worker)]
+interface TestWorkerExposedInterface {
+ [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
+ [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
+ [NeedsCallerType] void needsCallerTypeMethod();
+ [NeedsCallerType] attribute boolean needsCallerTypeAttr;
+};
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -770,16 +770,18 @@ interface TestExampleInterface {
[PutForwards=writableByte, LenientThis] readonly attribute TestExampleInterface putForwardsAttr2;
[PutForwards=writableByte, ChromeOnly] readonly attribute TestExampleInterface putForwardsAttr3;
[Throws] void throwingMethod();
[Throws] attribute boolean throwingAttr;
[GetterThrows] attribute boolean throwingGetterAttr;
[SetterThrows] attribute boolean throwingSetterAttr;
[NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
[NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
+ [NeedsCallerType] void needsCallerTypeMethod();
+ [NeedsCallerType] attribute boolean needsCallerTypeAttr;
legacycaller short(unsigned long arg1, TestInterface arg2);
void passArgsWithDefaults(optional long arg1,
optional TestInterface? arg2 = null,
optional Dict arg3, optional double arg4 = 5.0,
optional float arg5);
attribute any jsonifierShouldSkipThis;
attribute TestParentInterface jsonifierShouldSkipThis2;
attribute TestCallbackInterface jsonifierShouldSkipThis3;
@@ -794,8 +796,16 @@ interface TestExampleInterface {
interface TestExampleProxyInterface {
getter long longIndexedGetter(unsigned long ix);
setter creator void longIndexedSetter(unsigned long y, long z);
stringifier DOMString myStringifier();
getter short shortNameGetter(DOMString nom);
deleter void (DOMString nomnom);
setter creator void shortNamedSetter(DOMString me, short value);
};
+
+[Exposed=(Window,Worker)]
+interface TestExampleWorkerInterface {
+ [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
+ [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
+ [NeedsCallerType] void needsCallerTypeMethod();
+ [NeedsCallerType] attribute boolean needsCallerTypeAttr;
+};
--- a/dom/bindings/test/moz.build
+++ b/dom/bindings/test/moz.build
@@ -34,16 +34,17 @@ PREPROCESSED_TEST_WEBIDL_FILES += [
'TestCodeGen.webidl',
'TestExampleGen.webidl',
'TestJSImplGen.webidl',
]
WEBIDL_EXAMPLE_INTERFACES += [
'TestExampleInterface',
'TestExampleProxyInterface',
+ 'TestExampleWorkerInterface',
]
# Bug 932082 tracks having bindings use namespaced includes.
LOCAL_INCLUDES += [
'!/dist/include/mozilla/dom',
]
LOCAL_INCLUDES += [
--- a/dom/canvas/WebGL2ContextBuffers.cpp
+++ b/dom/canvas/WebGL2ContextBuffers.cpp
@@ -59,20 +59,28 @@ WebGL2Context::CopyBufferSubData(GLenum
};
if (!fnValidateOffsetSize("read", readOffset, readBuffer) ||
!fnValidateOffsetSize("write", writeOffset, writeBuffer))
{
return;
}
- if (readBuffer == writeBuffer &&
- !ValidateDataRanges(readOffset, writeOffset, size, funcName))
- {
- return;
+ if (readBuffer == writeBuffer) {
+ MOZ_ASSERT((CheckedInt<WebGLsizeiptr>(readOffset) + size).isValid());
+ MOZ_ASSERT((CheckedInt<WebGLsizeiptr>(writeOffset) + size).isValid());
+
+ const bool separate = (readOffset + size <= writeOffset ||
+ writeOffset + size <= readOffset);
+ if (!separate) {
+ ErrorInvalidValue("%s: ranges [readOffset, readOffset + size) and"
+ " [writeOffset, writeOffset + size) overlap",
+ funcName);
+ return;
+ }
}
const auto& readType = readBuffer->Content();
const auto& writeType = writeBuffer->Content();
MOZ_ASSERT(readType != WebGLBuffer::Kind::Undefined);
MOZ_ASSERT(writeType != WebGLBuffer::Kind::Undefined);
if (writeType != readType) {
ErrorInvalidOperation("%s: Can't copy %s data to %s data.",
--- a/dom/canvas/WebGL2ContextFramebuffers.cpp
+++ b/dom/canvas/WebGL2ContextFramebuffers.cpp
@@ -84,17 +84,17 @@ WebGL2Context::FramebufferTextureLayer(G
fb = mBoundReadFramebuffer;
break;
default:
MOZ_CRASH("GFX: Bad target.");
}
if (!fb)
- return ErrorInvalidOperation("%a: Xannot modify framebuffer 0.");
+ return ErrorInvalidOperation("%s: Cannot modify framebuffer 0.", funcName);
fb->FramebufferTextureLayer(funcName, attachment, texture, level, layer);
}
JS::Value
WebGL2Context::GetFramebufferAttachmentParameter(JSContext* cx,
GLenum target,
GLenum attachment,
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -1494,18 +1494,16 @@ protected:
// Validation functions (implemented in WebGLContextValidate.cpp)
bool InitAndValidateGL(FailureReason* const out_failReason);
bool ValidateBlendEquationEnum(GLenum cap, const char* info);
bool ValidateBlendFuncDstEnum(GLenum mode, const char* info);
bool ValidateBlendFuncSrcEnum(GLenum mode, const char* info);
bool ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor,
const char* info);
- bool ValidateDataRanges(WebGLintptr readOffset, WebGLintptr writeOffset, WebGLsizeiptr size, const char* info);
- bool ValidateTextureTargetEnum(GLenum target, const char* info);
bool ValidateComparisonEnum(GLenum target, const char* info);
bool ValidateStencilOpEnum(GLenum action, const char* info);
bool ValidateFaceEnum(GLenum face, const char* info);
bool ValidateTexInputData(GLenum type, js::Scalar::Type jsArrayType,
WebGLTexImageFunc func, WebGLTexDimensions dims);
bool ValidateDrawModeEnum(GLenum mode, const char* info);
bool ValidateAttribIndex(GLuint index, const char* info);
bool ValidateAttribPointer(bool integerMode, GLuint index, GLint size, GLenum type,
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -117,59 +117,16 @@ WebGLContext::ValidateBlendFuncEnumsComp
ErrorInvalidOperation("%s are mutually incompatible, see section 6.8 in"
" the WebGL 1.0 spec", info);
return false;
}
return true;
}
-/**
- * Check data ranges [readOffset, readOffset + size] and [writeOffset,
- * writeOffset + size] for overlap.
- *
- * It is assumed that offset and size have already been validated.
- */
-bool
-WebGLContext::ValidateDataRanges(WebGLintptr readOffset, WebGLintptr writeOffset, WebGLsizeiptr size, const char* info)
-{
- MOZ_ASSERT((CheckedInt<WebGLsizeiptr>(readOffset) + size).isValid());
- MOZ_ASSERT((CheckedInt<WebGLsizeiptr>(writeOffset) + size).isValid());
-
- bool separate = (readOffset + size < writeOffset || writeOffset + size < readOffset);
- if (!separate) {
- ErrorInvalidValue("%s: ranges [readOffset, readOffset + size) and [writeOffset, "
- "writeOffset + size) overlap", info);
- }
-
- return separate;
-}
-
-bool
-WebGLContext::ValidateTextureTargetEnum(GLenum target, const char* info)
-{
- switch (target) {
- case LOCAL_GL_TEXTURE_2D:
- case LOCAL_GL_TEXTURE_CUBE_MAP:
- return true;
-
- case LOCAL_GL_TEXTURE_3D:
- if (IsWebGL2())
- return true;
-
- break;
-
- default:
- break;
- }
-
- ErrorInvalidEnumInfo(info, target);
- return false;
-}
-
bool
WebGLContext::ValidateComparisonEnum(GLenum target, const char* info)
{
switch (target) {
case LOCAL_GL_NEVER:
case LOCAL_GL_LESS:
case LOCAL_GL_LEQUAL:
case LOCAL_GL_GREATER:
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -515,17 +515,17 @@ WebGLProgram::BindAttribLocation(GLuint
if (loc >= mContext->MaxVertexAttribs()) {
mContext->ErrorInvalidValue("bindAttribLocation: `location` must be less than"
" MAX_VERTEX_ATTRIBS.");
return;
}
if (StringBeginsWith(name, NS_LITERAL_STRING("gl_"))) {
- mContext->ErrorInvalidOperation("bindAttribLocation: Can't set the location of a"
+ mContext->ErrorInvalidOperation("bindAttribLocation: Can't set the location of a"
" name that starts with 'gl_'.");
return;
}
NS_LossyConvertUTF16toASCII asciiName(name);
auto res = mNextLink_BoundAttribLocs.insert({asciiName, loc});
--- a/dom/filesystem/compat/tests/script_entries.js
+++ b/dom/filesystem/compat/tests/script_entries.js
@@ -31,17 +31,17 @@ addMessageListener("entries.open", funct
file2.append('bar.txt');
file2.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o600);
var dir2 = dir1.clone();
dir2.append('subsubdir');
dir2.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o700);
sendAsyncMessage("entries.opened", {
- data: [ new Directory(tmpDir.path), new File(tmpFile) ]
+ data: [ new Directory(tmpDir.path), File.createFromNsIFile(tmpFile) ]
});
});
addMessageListener("entries.delete", function(e) {
tmpFile.remove(true);
tmpDir.remove(true);
sendAsyncMessage("entries.deleted");
});
--- a/dom/filesystem/tests/script_fileList.js
+++ b/dom/filesystem/tests/script_fileList.js
@@ -119,11 +119,11 @@ addMessageListener("dir.open", function
addMessageListener("file.open", function (e) {
var testFile = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get("ProfD", Ci.nsIFile);
testFile.append("prefs.js");
sendAsyncMessage("file.opened", {
- file: new File(testFile)
+ file: File.createFromNsIFile(testFile)
});
});
--- a/dom/html/test/formSubmission_chrome.js
+++ b/dom/html/test/formSubmission_chrome.js
@@ -1,6 +1,6 @@
var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.importGlobalProperties(["File"]);
addMessageListener("files.open", function (message) {
- sendAsyncMessage("files.opened", message.map(path => new File(path)));
+ sendAsyncMessage("files.opened", message.map(path => File.createFromFileName(path)));
});
--- a/dom/html/test/simpleFileOpener.js
+++ b/dom/html/test/simpleFileOpener.js
@@ -9,17 +9,17 @@ addMessageListener("file.open", function
file = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
file.append(stem);
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
}
sendAsyncMessage("file.opened", {
fullPath: file.path,
leafName: file.leafName,
- domFile: new File(file),
+ domFile: File.createFromNsIFile(file),
});
} catch(e) {
sendAsyncMessage("fail", e.toString());
}
});
addMessageListener("file.remove", function () {
try {
--- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
+++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
@@ -632,17 +632,17 @@ var SpecialPowers = {
}
let outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE
filePerms, 0);
if (request.data) {
outStream.write(request.data, request.data.length);
outStream.close();
}
- filePaths.push(new File(testFile.path, request.options));
+ filePaths.push(File.createFromFileName(testFile.path, request.options));
createdFiles.push(testFile);
});
setTimeout(function () {
callback(filePaths);
}, 0);
},
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -195,16 +195,17 @@ private:
RefPtr<MediaDataDecoder> mDecoder;
MozPromiseRequestHolder<TokenPromise> mTokenPromise;
MozPromiseRequestHolder<InitPromise> mInitPromise;
~Data()
{
mTokenPromise.DisconnectIfExists();
mInitPromise.DisconnectIfExists();
if (mDecoder) {
+ mDecoder->Flush();
mDecoder->Shutdown();
}
}
} mAudio, mVideo;
void RunStage(TrackType aTrack);
MediaResult DoCreateDecoder(TrackType aTrack);
void DoInitDecoder(TrackType aTrack);
--- a/dom/media/ipc/RemoteVideoDecoder.cpp
+++ b/dom/media/ipc/RemoteVideoDecoder.cpp
@@ -6,16 +6,17 @@
#include "RemoteVideoDecoder.h"
#include "VideoDecoderChild.h"
#include "VideoDecoderManagerChild.h"
#include "mozilla/layers/TextureClient.h"
#include "base/thread.h"
#include "MediaInfo.h"
#include "MediaPrefs.h"
#include "ImageContainer.h"
+#include "mozilla/layers/SynchronousTask.h"
namespace mozilla {
namespace dom {
using base::Thread;
using namespace ipc;
using namespace layers;
using namespace gfx;
@@ -91,21 +92,24 @@ RemoteVideoDecoder::Drain()
self->mActor->Drain();
}), NS_DISPATCH_NORMAL);
}
void
RemoteVideoDecoder::Shutdown()
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+ SynchronousTask task("Shutdown");
RefPtr<RemoteVideoDecoder> self = this;
- VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([self]() {
+ VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([&]() {
+ AutoCompleteTask complete(&task);
MOZ_ASSERT(self->mActor);
self->mActor->Shutdown();
}), NS_DISPATCH_NORMAL);
+ task.Wait();
}
bool
RemoteVideoDecoder::IsHardwareAccelerated(nsACString& aFailureReason) const
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
return mActor->IsHardwareAccelerated(aFailureReason);
}
@@ -155,18 +159,18 @@ RemoteDecoderModule::CreateVideoDecoder(
}
MediaDataDecoderCallback* callback = aParams.mCallback;
MOZ_ASSERT(callback->OnReaderTaskQueue());
RefPtr<RemoteVideoDecoder> object = new RemoteVideoDecoder(callback);
VideoInfo info = aParams.VideoConfig();
- RefPtr<layers::KnowsCompositor> knowsCompositor = aParams.mKnowsCompositor;
+ TextureFactoryIdentifier ident = aParams.mKnowsCompositor->GetTextureFactoryIdentifier();
VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([=]() {
- object->mActor->InitIPDL(callback, info, knowsCompositor);
+ object->mActor->InitIPDL(callback, info, ident);
}), NS_DISPATCH_NORMAL);
return object.forget();
}
} // namespace dom
} // namespace mozilla
--- a/dom/media/ipc/VideoDecoderChild.cpp
+++ b/dom/media/ipc/VideoDecoderChild.cpp
@@ -47,41 +47,49 @@ VideoDecoderChild::RecvOutput(const Vide
RefPtr<VideoData> video = VideoData::CreateFromImage(info,
aData.base().offset(),
aData.base().time(),
aData.base().duration(),
image,
aData.base().keyframe(),
aData.base().timecode(),
IntRect());
- mCallback->Output(video);
+ if (mCallback) {
+ mCallback->Output(video);
+ }
return true;
}
bool
VideoDecoderChild::RecvInputExhausted()
{
AssertOnManagerThread();
- mCallback->InputExhausted();
+ if (mCallback) {
+ mCallback->InputExhausted();
+ }
return true;
}
bool
VideoDecoderChild::RecvDrainComplete()
{
AssertOnManagerThread();
- mCallback->DrainComplete();
+ if (mCallback) {
+ mCallback->DrainComplete();
+ }
return true;
}
bool
VideoDecoderChild::RecvError(const nsresult& aError)
{
AssertOnManagerThread();
- mCallback->Error(aError);
+ if (mCallback) {
+ mCallback->Error(aError);
+ }
return true;
}
bool
VideoDecoderChild::RecvInitComplete(const bool& aHardware, const nsCString& aHardwareReason)
{
AssertOnManagerThread();
mInitPromise.Resolve(TrackInfo::kVideoTrack, __func__);
@@ -102,45 +110,45 @@ VideoDecoderChild::RecvInitFailed(const
void
VideoDecoderChild::ActorDestroy(ActorDestroyReason aWhy)
{
if (aWhy == AbnormalShutdown) {
// Defer reporting an error until we've recreated the manager so that
// it'll be safe for MediaFormatReader to recreate decoders
RefPtr<VideoDecoderChild> ref = this;
GetManager()->RunWhenRecreated(NS_NewRunnableFunction([=]() {
- if (ref->mInitialized) {
+ if (ref->mInitialized && ref->mCallback) {
ref->mCallback->Error(NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER);
} else {
ref->mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER, __func__);
}
}));
}
mCanSend = false;
}
void
VideoDecoderChild::InitIPDL(MediaDataDecoderCallback* aCallback,
const VideoInfo& aVideoInfo,
- layers::KnowsCompositor* aKnowsCompositor)
+ const layers::TextureFactoryIdentifier& aIdentifier)
{
RefPtr<VideoDecoderManagerChild> manager = VideoDecoderManagerChild::GetSingleton();
// If the manager isn't available, then don't initialize mIPDLSelfRef and leave
// us in an error state. We'll then immediately reject the promise when Init()
// is called and the caller can try again. Hopefully by then the new manager is
// ready, or we've notified the caller of it being no longer available.
// If not, then the cycle repeats until we're ready.
if (!manager || !manager->CanSend()) {
return;
}
mIPDLSelfRef = this;
mCallback = aCallback;
mVideoInfo = aVideoInfo;
- mKnowsCompositor = aKnowsCompositor;
+ mIdentifier = aIdentifier;
if (manager->SendPVideoDecoderConstructor(this)) {
mCanSend = true;
}
}
void
VideoDecoderChild::DestroyIPDL()
{
@@ -164,17 +172,17 @@ VideoDecoderChild::Init()
if (!mIPDLSelfRef) {
return MediaDataDecoder::InitPromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
}
// If we failed to send this, then we'll still resolve the Init promise
// as ActorDestroy handles it.
if (mCanSend) {
- SendInit(mVideoInfo, mKnowsCompositor->GetTextureFactoryIdentifier());
+ SendInit(mVideoInfo, mIdentifier);
}
return mInitPromise.Ensure(__func__);
}
void
VideoDecoderChild::Input(MediaRawData* aSample)
{
AssertOnManagerThread();
@@ -220,16 +228,17 @@ VideoDecoderChild::Drain()
SendDrain();
}
}
void
VideoDecoderChild::Shutdown()
{
AssertOnManagerThread();
+ mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
if (mCanSend) {
SendShutdown();
}
mInitialized = false;
}
bool
VideoDecoderChild::IsHardwareAccelerated(nsACString& aFailureReason) const
--- a/dom/media/ipc/VideoDecoderChild.h
+++ b/dom/media/ipc/VideoDecoderChild.h
@@ -41,17 +41,17 @@ public:
void Drain();
void Shutdown();
bool IsHardwareAccelerated(nsACString& aFailureReason) const;
void SetSeekThreshold(const media::TimeUnit& aTime);
MOZ_IS_CLASS_INIT
void InitIPDL(MediaDataDecoderCallback* aCallback,
const VideoInfo& aVideoInfo,
- layers::KnowsCompositor* aKnowsCompositor);
+ const layers::TextureFactoryIdentifier& aIdentifier);
void DestroyIPDL();
// Called from IPDL when our actor has been destroyed
void IPDLActorDestroyed();
VideoDecoderManagerChild* GetManager();
private:
@@ -62,17 +62,17 @@ private:
RefPtr<VideoDecoderChild> mIPDLSelfRef;
RefPtr<nsIThread> mThread;
MediaDataDecoderCallback* mCallback;
MozPromiseHolder<MediaDataDecoder::InitPromise> mInitPromise;
VideoInfo mVideoInfo;
- RefPtr<layers::KnowsCompositor> mKnowsCompositor;
+ layers::TextureFactoryIdentifier mIdentifier;
nsCString mHardwareAcceleratedReason;
bool mCanSend;
bool mInitialized;
bool mIsHardwareAccelerated;
};
} // namespace dom
} // namespace mozilla
--- a/dom/media/ipc/VideoDecoderManagerParent.cpp
+++ b/dom/media/ipc/VideoDecoderManagerParent.cpp
@@ -12,16 +12,17 @@
#include "nsIObserverService.h"
#include "nsIObserver.h"
#include "nsIEventTarget.h"
#include "nsThreadUtils.h"
#include "ImageContainer.h"
#include "mozilla/layers/VideoBridgeChild.h"
#include "mozilla/SharedThreadPool.h"
#include "mozilla/layers/ImageDataSerializer.h"
+#include "mozilla/SyncRunnable.h"
#if XP_WIN
#include <objbase.h>
#endif
namespace mozilla {
namespace dom {
@@ -96,24 +97,33 @@ VideoDecoderManagerParent::StartupThread
observerService->AddObserver(obs, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
}
void
VideoDecoderManagerParent::ShutdownThreads()
{
sManagerTaskQueue->BeginShutdown();
sManagerTaskQueue->AwaitShutdownAndIdle();
+ sManagerTaskQueue = nullptr;
- sVideoDecoderManagerThread->Dispatch(NS_NewRunnableFunction([]() {
- layers::VideoBridgeChild::Shutdown();
- }), NS_DISPATCH_SYNC);
sVideoDecoderManagerThread->Shutdown();
sVideoDecoderManagerThread = nullptr;
}
+void
+VideoDecoderManagerParent::ShutdownVideoBridge()
+{
+ if (sVideoDecoderManagerThread) {
+ RefPtr<Runnable> task = NS_NewRunnableFunction([]() {
+ VideoBridgeChild::Shutdown();
+ });
+ SyncRunnable::DispatchToThread(sVideoDecoderManagerThread, task);
+ }
+}
+
bool
VideoDecoderManagerParent::OnManagerThread()
{
return NS_GetCurrentThread() == sVideoDecoderManagerThread;
}
bool
VideoDecoderManagerParent::CreateForContent(Endpoint<PVideoDecoderManagerParent>&& aEndpoint)
--- a/dom/media/ipc/VideoDecoderManagerParent.h
+++ b/dom/media/ipc/VideoDecoderManagerParent.h
@@ -19,16 +19,18 @@ public:
static bool CreateForContent(Endpoint<PVideoDecoderManagerParent>&& aEndpoint);
// Can be called from any thread
SurfaceDescriptorGPUVideo StoreImage(layers::Image* aImage, layers::TextureClient* aTexture);
static void StartupThreads();
static void ShutdownThreads();
+ static void ShutdownVideoBridge();
+
bool OnManagerThread();
protected:
PVideoDecoderParent* AllocPVideoDecoderParent() override;
bool DeallocPVideoDecoderParent(PVideoDecoderParent* actor) override;
bool RecvReadback(const SurfaceDescriptorGPUVideo& aSD, SurfaceDescriptor* aResult) override;
bool RecvDeallocateSurfaceDescriptorGPUVideo(const SurfaceDescriptorGPUVideo& aSD) override;
--- a/dom/media/ipc/VideoDecoderParent.cpp
+++ b/dom/media/ipc/VideoDecoderParent.cpp
@@ -132,33 +132,37 @@ VideoDecoderParent::RecvInput(const Medi
mDecoder->Input(data);
return true;
}
bool
VideoDecoderParent::RecvFlush()
{
MOZ_ASSERT(!mDestroyed);
- mDecoder->Flush();
+ if (mDecoder) {
+ mDecoder->Flush();
+ }
return true;
}
bool
VideoDecoderParent::RecvDrain()
{
MOZ_ASSERT(!mDestroyed);
mDecoder->Drain();
return true;
}
bool
VideoDecoderParent::RecvShutdown()
{
MOZ_ASSERT(!mDestroyed);
- mDecoder->Shutdown();
+ if (mDecoder) {
+ mDecoder->Shutdown();
+ }
mDecoder = nullptr;
return true;
}
bool
VideoDecoderParent::RecvSetSeekThreshold(const int64_t& aTime)
{
MOZ_ASSERT(!mDestroyed);
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -25,16 +25,17 @@
#include "IMFYCbCrImage.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/Telemetry.h"
#include "nsPrintfCString.h"
#include "MediaTelemetryConstants.h"
#include "GMPUtils.h" // For SplitAt. TODO: Move SplitAt to a central place.
#include "MP4Decoder.h"
#include "VPXDecoder.h"
+#include "mozilla/SyncRunnable.h"
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
using mozilla::layers::Image;
using mozilla::layers::IMFYCbCrImage;
using mozilla::layers::LayerManager;
using mozilla::layers::LayersBackend;
@@ -366,17 +367,19 @@ WMFVideoMFTManager::InitializeDXVA(bool
new CreateDXVAManagerEvent(aForceD3D9 ? LayersBackend::LAYERS_D3D9
: backend,
mKnowsCompositor,
mDXVAFailureReason);
if (NS_IsMainThread()) {
event->Run();
} else {
- NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
+ // This logic needs to run on the main thread
+ nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+ mozilla::SyncRunnable::DispatchToThread(mainThread, event);
}
mDXVA2Manager = event->mDXVA2Manager;
return mDXVA2Manager != nullptr;
}
bool
WMFVideoMFTManager::ValidateVideoInfo()
@@ -602,17 +605,19 @@ WMFVideoMFTManager::CanUseDXVA(IMFMediaT
// The supports config check must be done on the main thread since we have
// a crash guard protecting it.
RefPtr<SupportsConfigEvent> event =
new SupportsConfigEvent(mDXVA2Manager, aType, framerate);
if (NS_IsMainThread()) {
event->Run();
} else {
- NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
+ // This logic needs to run on the main thread
+ nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+ mozilla::SyncRunnable::DispatchToThread(mainThread, event);
}
return event->mSupportsConfig;
}
HRESULT
WMFVideoMFTManager::ConfigureVideoFrameGeometry()
{
--- a/dom/webidl/File.webidl
+++ b/dom/webidl/File.webidl
@@ -6,22 +6,16 @@
* The origin of this IDL file is
* https://w3c.github.io/FileAPI/#file
*/
interface nsIFile;
[Constructor(sequence<BlobPart> fileBits,
USVString fileName, optional FilePropertyBag options),
-
- // These constructors are just for chrome callers:
- Constructor(Blob fileBits, optional ChromeFilePropertyBag options),
- Constructor(nsIFile fileBits, optional ChromeFilePropertyBag options),
- Constructor(USVString fileBits, optional ChromeFilePropertyBag options),
-
Exposed=(Window,Worker)]
interface File : Blob {
readonly attribute DOMString name;
[GetterThrows]
readonly attribute long long lastModified;
};
@@ -40,9 +34,17 @@ partial interface File {
[GetterThrows, Deprecated="FileLastModifiedDate"]
readonly attribute Date lastModifiedDate;
[BinaryName="path", Func="mozilla::dom::Directory::WebkitBlinkDirectoryPickerEnabled"]
readonly attribute USVString webkitRelativePath;
[GetterThrows, ChromeOnly]
readonly attribute DOMString mozFullPath;
+
+ [ChromeOnly, Throws]
+ static File createFromNsIFile(nsIFile file,
+ optional ChromeFilePropertyBag options);
+
+ [ChromeOnly, Throws]
+ static File createFromFileName(USVString fileName,
+ optional ChromeFilePropertyBag options);
};
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -250,22 +250,16 @@ interface WindowModal {
[Throws, Func="nsGlobalWindow::IsModalContentWindow", NeedsSubjectPrincipal]
readonly attribute any dialogArguments;
[Throws, Func="nsGlobalWindow::IsModalContentWindow", NeedsSubjectPrincipal]
attribute any returnValue;
};
Window implements WindowModal;
-// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#self-caches
-partial interface Window {
-[Throws, Func="mozilla::dom::cache::CacheStorage::PrefEnabled", SameObject]
-readonly attribute CacheStorage caches;
-};
-
// Mozilla-specific stuff
partial interface Window {
//[NewObject, Throws] CSSStyleDeclaration getDefaultComputedStyle(Element elt, optional DOMString pseudoElt = "");
[NewObject, Throws] CSSStyleDeclaration? getDefaultComputedStyle(Element elt, optional DOMString pseudoElt = "");
// Mozilla extensions
/**
* Method for scrolling this window by a number of lines.
--- a/dom/webidl/WindowOrWorkerGlobalScope.webidl
+++ b/dom/webidl/WindowOrWorkerGlobalScope.webidl
@@ -2,16 +2,17 @@
/* 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/.
*
* The origin of this IDL file is:
* https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope-mixin
* https://fetch.spec.whatwg.org/#fetch-method
* https://w3c.github.io/webappsec-secure-contexts/#monkey-patching-global-object
+ * https://w3c.github.io/ServiceWorker/#self-caches
*/
// https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope-mixin
[NoInterfaceObject, Exposed=(Window,Worker)]
interface WindowOrWorkerGlobalScope {
// XXXbz We don't implement 'origin' yet on either window or worker globals.
// See bug 1306170.
// [Replaceable] readonly attribute USVString origin;
@@ -55,16 +56,22 @@ partial interface WindowOrWorkerGlobalSc
// http://w3c.github.io/IndexedDB/#factory-interface
partial interface WindowOrWorkerGlobalScope {
// readonly attribute IDBFactory indexedDB;
[Throws]
readonly attribute IDBFactory? indexedDB;
};
+// https://w3c.github.io/ServiceWorker/#self-caches
+partial interface WindowOrWorkerGlobalScope {
+ [Throws, Func="mozilla::dom::cache::CacheStorage::PrefEnabled", SameObject]
+ readonly attribute CacheStorage caches;
+};
+
// Mozilla extensions
partial interface WindowOrWorkerGlobalScope {
// Extensions to ImageBitmap bits.
// Bug 1141979 - [FoxEye] Extend ImageBitmap with interfaces to access its
// underlying image data
//
// Note:
// Overloaded functions cannot have different "extended attributes",
--- a/dom/webidl/WorkerGlobalScope.webidl
+++ b/dom/webidl/WorkerGlobalScope.webidl
@@ -30,22 +30,16 @@ interface WorkerGlobalScope : EventTarge
partial interface WorkerGlobalScope {
[Throws]
void importScripts(DOMString... urls);
readonly attribute WorkerNavigator navigator;
};
-// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#self-caches
-partial interface WorkerGlobalScope {
-[Throws, Func="mozilla::dom::cache::CacheStorage::PrefEnabled", SameObject]
-readonly attribute CacheStorage caches;
-};
-
WorkerGlobalScope implements GlobalCrypto;
WorkerGlobalScope implements WindowOrWorkerGlobalScope;
// Not implemented yet: bug 1072107.
// WorkerGlobalScope implements FontFaceSource;
// Mozilla extensions
partial interface WorkerGlobalScope {
--- a/dom/workers/test/fileapi_chromeScript.js
+++ b/dom/workers/test/fileapi_chromeScript.js
@@ -12,17 +12,17 @@ function createFileWithData(fileData) {
var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0o666, 0);
if (willDelete) {
fileData = "some irrelevant test data\n";
}
outStream.write(fileData, fileData.length);
outStream.close();
- var domFile = new File(testFile);
+ var domFile = File.createFromNsIFile(testFile);
if (willDelete) {
testFile.remove(/* recursive: */ false);
}
return domFile;
}
addMessageListener("files.open", function (message) {
sendAsyncMessage("files.opened", message.map(createFileWithData));
--- a/dom/workers/test/script_bug1301094.js
+++ b/dom/workers/test/script_bug1301094.js
@@ -5,11 +5,11 @@ addMessageListener("file.open", function
var tmpFile = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get('TmpD', Ci.nsIFile)
tmpFile.append('file.txt');
tmpFile.createUnique(Components.interfaces.nsIFile.FILE_TYPE, 0o600);
sendAsyncMessage("file.opened", {
- data: new File(tmpFile)
+ data: File.createFromNsIFile(tmpFile)
});
});
--- a/editor/libeditor/CompositionTransaction.cpp
+++ b/editor/libeditor/CompositionTransaction.cpp
@@ -1,16 +1,17 @@
/* -*- Mode: C++; 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/. */
#include "CompositionTransaction.h"
#include "mozilla/EditorBase.h" // mEditorBase
+#include "mozilla/SelectionState.h" // RangeUpdater
#include "mozilla/dom/Selection.h" // local var
#include "mozilla/dom/Text.h" // mTextNode
#include "nsAString.h" // params
#include "nsDebug.h" // for NS_ASSERTION, etc
#include "nsError.h" // for NS_SUCCEEDED, NS_FAILED, etc
#include "nsIPresShell.h" // nsISelectionController constants
#include "nsRange.h" // local var
#include "nsQueryObject.h" // for do_QueryObject
@@ -20,25 +21,28 @@ namespace mozilla {
using namespace dom;
CompositionTransaction::CompositionTransaction(
Text& aTextNode,
uint32_t aOffset,
uint32_t aReplaceLength,
TextRangeArray* aTextRangeArray,
const nsAString& aStringToInsert,
- EditorBase& aEditorBase)
+ EditorBase& aEditorBase,
+ RangeUpdater* aRangeUpdater)
: mTextNode(&aTextNode)
, mOffset(aOffset)
, mReplaceLength(aReplaceLength)
, mRanges(aTextRangeArray)
, mStringToInsert(aStringToInsert)
, mEditorBase(aEditorBase)
+ , mRangeUpdater(aRangeUpdater)
, mFixed(false)
{
+ MOZ_ASSERT(mTextNode->TextLength() >= mOffset);
}
CompositionTransaction::~CompositionTransaction()
{
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(CompositionTransaction, EditTransactionBase,
mTextNode)
@@ -62,22 +66,42 @@ CompositionTransaction::DoTransaction()
NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
// Advance caret: This requires the presentation shell to get the selection.
if (mReplaceLength == 0) {
nsresult rv = mTextNode->InsertData(mOffset, mStringToInsert);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
+ mRangeUpdater->SelAdjInsertText(*mTextNode, mOffset, mStringToInsert);
} else {
+ uint32_t replaceableLength = mTextNode->TextLength() - mOffset;
nsresult rv =
mTextNode->ReplaceData(mOffset, mReplaceLength, mStringToInsert);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
+ mRangeUpdater->SelAdjDeleteText(mTextNode, mOffset, mReplaceLength);
+ mRangeUpdater->SelAdjInsertText(*mTextNode, mOffset, mStringToInsert);
+
+ // If IME text node is multiple node, ReplaceData doesn't remove all IME
+ // text. So we need remove remained text into other text node.
+ if (replaceableLength < mReplaceLength) {
+ int32_t remainLength = mReplaceLength - replaceableLength;
+ nsCOMPtr<nsINode> node = mTextNode->GetNextSibling();
+ while (node && node->IsNodeOfType(nsINode::eTEXT) &&
+ remainLength > 0) {
+ Text* text = static_cast<Text*>(node.get());
+ uint32_t textLength = text->TextLength();
+ text->DeleteData(0, remainLength);
+ mRangeUpdater->SelAdjDeleteText(text, 0, remainLength);
+ remainLength -= textLength;
+ node = node->GetNextSibling();
+ }
+ }
}
nsresult rv = SetSelectionForRanges();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
--- a/editor/libeditor/CompositionTransaction.h
+++ b/editor/libeditor/CompositionTransaction.h
@@ -12,16 +12,17 @@
#define NS_IMETEXTTXN_IID \
{ 0xb391355d, 0x346c, 0x43d1, \
{ 0x85, 0xed, 0x9e, 0x65, 0xbe, 0xe7, 0x7e, 0x48 } }
namespace mozilla {
class EditorBase;
+class RangeUpdater;
class TextRangeArray;
namespace dom {
class Text;
} // namespace dom
/**
* CompositionTransaction stores all edit for a composition, i.e.,
@@ -30,30 +31,32 @@ class Text;
* ranges and commit or cancel the composition.
*/
class CompositionTransaction final : public EditTransactionBase
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMETEXTTXN_IID)
/**
- * @param aTextNode The text content node.
+ * @param aTextNode The start node of text content.
* @param aOffset The location in aTextNode to do the insertion.
* @param aReplaceLength The length of text to replace. 0 means not
* replacing existing text.
* @param aTextRangeArray Clauses and/or caret information. This may be
* null.
* @param aString The new text to insert.
* @param aEditorBase Used to get and set the selection.
+ * @param aRangeUpdater The range updater
*/
CompositionTransaction(dom::Text& aTextNode,
uint32_t aOffset, uint32_t aReplaceLength,
TextRangeArray* aTextRangeArray,
const nsAString& aString,
- EditorBase& aEditorBase);
+ EditorBase& aEditorBase,
+ RangeUpdater* aRangeUpdater);
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CompositionTransaction,
EditTransactionBase)
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_EDITTRANSACTIONBASE
@@ -84,16 +87,18 @@ private:
RefPtr<TextRangeArray> mRanges;
// The text to insert into mTextNode at mOffset.
nsString mStringToInsert;
// The editor, which is used to get the selection controller.
EditorBase& mEditorBase;
+ RangeUpdater* mRangeUpdater;
+
bool mFixed;
};
NS_DEFINE_STATIC_IID_ACCESSOR(CompositionTransaction, NS_IMETEXTTXN_IID)
} // namespace mozilla
#endif // #ifndef CompositionTransaction_h
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -922,16 +922,17 @@ EditorBase::BeginPlaceHolderTransaction(
// time to turn on the batch
BeginUpdateViewBatch();
mPlaceHolderTxn = nullptr;
mPlaceHolderName = aName;
RefPtr<Selection> selection = GetSelection();
if (selection) {
mSelState = new SelectionState();
mSelState->SaveSelection(selection);
+ mRangeUpdater.RegisterSelectionState(*mSelState);
}
}
mPlaceHolderBatch++;
return NS_OK;
}
NS_IMETHODIMP
@@ -973,16 +974,17 @@ EditorBase::EndPlaceHolderTransaction()
// cached for frame offset are Not available now
if (selection) {
selection->SetCanCacheFrameOffset(false);
}
if (mSelState) {
// we saved the selection state, but never got to hand it to placeholder
// (else we ould have nulled out this pointer), so destroy it to prevent leaks.
+ mRangeUpdater.DropSelectionState(*mSelState);
delete mSelState;
mSelState = nullptr;
}
// We might have never made a placeholder if no action took place.
if (mPlaceHolderTxn) {
nsCOMPtr<nsIAbsorbingTransaction> plcTxn = do_QueryReferent(mPlaceHolderTxn);
if (plcTxn) {
plcTxn->EndPlaceHolderBatch();
@@ -2431,18 +2433,18 @@ EditorBase::InsertTextImpl(const nsAStri
nsresult
EditorBase::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
Text& aTextNode,
int32_t aOffset,
bool aSuppressIME)
{
RefPtr<EditTransactionBase> transaction;
bool isIMETransaction = false;
- int32_t replacedOffset = 0;
- int32_t replacedLength = 0;
+ RefPtr<Text> insertedTextNode = &aTextNode;
+ int32_t insertedOffset = aOffset;
// aSuppressIME is used when editor must insert text, yet this text is not
// part of the current IME operation. Example: adjusting whitespace around an
// IME insertion.
if (ShouldHandleIMEComposition() && !aSuppressIME) {
if (!mIMETextNode) {
mIMETextNode = &aTextNode;
mIMETextOffset = aOffset;
}
@@ -2462,48 +2464,41 @@ EditorBase::InsertTextIntoTextNodeImpl(c
textRange.mStartOffset, textRange.Length());
}
transaction = CreateTxnForComposition(aStringToInsert);
isIMETransaction = true;
// All characters of the composition string will be replaced with
// aStringToInsert. So, we need to emulate to remove the composition
// string.
- replacedOffset = mIMETextOffset;
- replacedLength = mIMETextLength;
+ insertedTextNode = mIMETextNode;
+ insertedOffset = mIMETextOffset;
mIMETextLength = aStringToInsert.Length();
} else {
transaction = CreateTxnForInsertText(aStringToInsert, aTextNode, aOffset);
}
// Let listeners know what's up
for (auto& listener : mActionListeners) {
listener->WillInsertText(
- static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()), aOffset,
- aStringToInsert);
+ static_cast<nsIDOMCharacterData*>(insertedTextNode->AsDOMNode()),
+ insertedOffset, aStringToInsert);
}
// XXX We may not need these view batches anymore. This is handled at a
// higher level now I believe.
BeginUpdateViewBatch();
nsresult rv = DoTransaction(transaction);
EndUpdateViewBatch();
- if (replacedLength) {
- mRangeUpdater.SelAdjDeleteText(
- static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()),
- replacedOffset, replacedLength);
- }
- mRangeUpdater.SelAdjInsertText(aTextNode, aOffset, aStringToInsert);
-
// let listeners know what happened
for (auto& listener : mActionListeners) {
listener->DidInsertText(
- static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()),
- aOffset, aStringToInsert, rv);
+ static_cast<nsIDOMCharacterData*>(insertedTextNode->AsDOMNode()),
+ insertedOffset, aStringToInsert, rv);
}
// Added some cruft here for bug 43366. Layout was crashing because we left
// an empty text node lying around in the document. So I delete empty text
// nodes caused by IME. I have to mark the IME transaction as "fixed", which
// means that furure IME txns won't merge with it. This is because we don't
// want future IME txns trying to put their text into a node that is no
// longer in the document. This does not break undo/redo, because all these
@@ -2610,17 +2605,18 @@ EditorBase::NotifyDocumentListeners(
}
already_AddRefed<InsertTextTransaction>
EditorBase::CreateTxnForInsertText(const nsAString& aStringToInsert,
Text& aTextNode,
int32_t aOffset)
{
RefPtr<InsertTextTransaction> transaction =
- new InsertTextTransaction(aTextNode, aOffset, aStringToInsert, *this);
+ new InsertTextTransaction(aTextNode, aOffset, aStringToInsert, *this,
+ &mRangeUpdater);
return transaction.forget();
}
nsresult
EditorBase::DeleteText(nsGenericDOMDataNode& aCharData,
uint32_t aOffset,
uint32_t aLength)
{
@@ -4240,17 +4236,17 @@ EditorBase::CreateTxnForComposition(cons
{
MOZ_ASSERT(mIMETextNode);
// During handling IME composition, mComposition must have been initialized.
// TODO: We can simplify CompositionTransaction::Init() with TextComposition
// class.
RefPtr<CompositionTransaction> transaction =
new CompositionTransaction(*mIMETextNode, mIMETextOffset, mIMETextLength,
mComposition->GetRanges(), aStringToInsert,
- *this);
+ *this, &mRangeUpdater);
return transaction.forget();
}
NS_IMETHODIMP
EditorBase::CreateTxnForAddStyleSheet(StyleSheet* aSheet,
AddStyleSheetTransaction** aTransaction)
{
RefPtr<AddStyleSheetTransaction> transaction = new AddStyleSheetTransaction();
--- a/editor/libeditor/InsertTextTransaction.cpp
+++ b/editor/libeditor/InsertTextTransaction.cpp
@@ -1,35 +1,38 @@
/* -*- Mode: C++; 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/. */
#include "InsertTextTransaction.h"
#include "mozilla/EditorBase.h" // mEditorBase
+#include "mozilla/SelectionState.h" // RangeUpdater
#include "mozilla/dom/Selection.h" // Selection local var
#include "mozilla/dom/Text.h" // mTextNode
#include "nsAString.h" // nsAString parameter
#include "nsDebug.h" // for NS_ASSERTION, etc.
#include "nsError.h" // for NS_OK, etc.
#include "nsQueryObject.h" // for do_QueryObject
namespace mozilla {
using namespace dom;
InsertTextTransaction::InsertTextTransaction(Text& aTextNode,
uint32_t aOffset,
const nsAString& aStringToInsert,
- EditorBase& aEditorBase)
+ EditorBase& aEditorBase,
+ RangeUpdater* aRangeUpdater)
: mTextNode(&aTextNode)
, mOffset(aOffset)
, mStringToInsert(aStringToInsert)
, mEditorBase(aEditorBase)
+ , mRangeUpdater(aRangeUpdater)
{
}
InsertTextTransaction::~InsertTextTransaction()
{
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertTextTransaction, EditTransactionBase,
@@ -56,16 +59,17 @@ InsertTextTransaction::DoTransaction()
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
DebugOnly<nsresult> rv =
selection->Collapse(mTextNode, mOffset + mStringToInsert.Length());
NS_ASSERTION(NS_SUCCEEDED(rv),
"Selection could not be collapsed after insert");
} else {
// Do nothing - DOM Range gravity will adjust selection
}
+ mRangeUpdater->SelAdjInsertText(*mTextNode, mOffset, mStringToInsert);
return NS_OK;
}
NS_IMETHODIMP
InsertTextTransaction::UndoTransaction()
{
return mTextNode->DeleteData(mOffset, mStringToInsert.Length());
--- a/editor/libeditor/InsertTextTransaction.h
+++ b/editor/libeditor/InsertTextTransaction.h
@@ -17,16 +17,18 @@ class nsITransaction;
#define NS_INSERTTEXTTXN_IID \
{ 0x8c9ad77f, 0x22a7, 0x4d01, \
{ 0xb1, 0x59, 0x8a, 0x0f, 0xdb, 0x1d, 0x08, 0xe9 } }
namespace mozilla {
class EditorBase;
+class RangeUpdater;
+
namespace dom {
class Text;
} // namespace dom
/**
* A transaction that inserts text into a content node.
*/
class InsertTextTransaction final : public EditTransactionBase
@@ -34,19 +36,21 @@ class InsertTextTransaction final : publ
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_INSERTTEXTTXN_IID)
/**
* @param aElement The text content node.
* @param aOffset The location in aElement to do the insertion.
* @param aString The new text to insert.
* @param aPresShell Used to get and set the selection.
+ * @param aRangeUpdater The range updater
*/
InsertTextTransaction(dom::Text& aTextNode, uint32_t aOffset,
- const nsAString& aString, EditorBase& aEditorBase);
+ const nsAString& aString, EditorBase& aEditorBase,
+ RangeUpdater* aRangeUpdater);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(InsertTextTransaction,
EditTransactionBase)
NS_DECL_EDITTRANSACTIONBASE
NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override;
@@ -68,15 +72,17 @@ private:
// The offset into mTextNode where the insertion is to take place.
uint32_t mOffset;
// The text to insert into mTextNode at mOffset.
nsString mStringToInsert;
// The editor, which we'll need to get the selection.
EditorBase& mEditorBase;
+
+ RangeUpdater* mRangeUpdater;
};
NS_DEFINE_STATIC_IID_ACCESSOR(InsertTextTransaction, NS_INSERTTEXTTXN_IID)
} // namespace mozilla
#endif // #ifndef InsertTextTransaction_h
--- a/editor/libeditor/tests/mochitest.ini
+++ b/editor/libeditor/tests/mochitest.ini
@@ -205,16 +205,18 @@ skip-if = os == 'android'
subsuite = clipboard
skip-if = toolkit == 'android'
[test_bug1248128.html]
[test_bug1250010.html]
[test_bug1257363.html]
[test_bug1248185.html]
[test_bug1258085.html]
[test_bug1268736.html]
+[test_bug1310912.html]
+skip-if = toolkit == 'android' # bug 1315898
[test_bug1315065.html]
[test_CF_HTML_clipboard.html]
subsuite = clipboard
[test_composition_event_created_in_chrome.html]
[test_contenteditable_focus.html]
[test_dom_input_event_on_htmleditor.html]
skip-if = toolkit == 'android' # bug 1054087
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_bug1310912.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1310912
+-->
+<html>
+<head>
+ <title>Test for Bug 1310912</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1310912">Mozilla Bug 1310912</a>
+<p id="display"></p>
+<div id="content" style="display: none;">
+
+</div>
+
+<div id="editable1" contenteditable="true">ABC</div>
+<pre id="test">
+
+<script class="testbody" type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ let elm = document.getElementById("editable1");
+
+ elm.focus();
+ let sel = window.getSelection();
+ sel.collapse(elm.childNodes[0], elm.textContent.length);
+
+ synthesizeCompositionChange({
+ composition: {
+ string: "DEF",
+ clauses: [
+ { length: 3, attr: COMPOSITION_ATTR_RAW_CLAUSE }
+ ]
+ },
+ caret: { start: 3, length: 0 }
+ });
+ ok(elm.textContent == "ABCDEF", "composing text should be set");
+
+ window.getSelection().getRangeAt(0).insertNode(document.createTextNode(""));
+ synthesizeCompositionChange({
+ composition: {
+ string: "GHI",
+ clauses: [
+ { length: 3, attr: COMPOSITION_ATTR_CONVERTED_CLAUSE }
+ ]
+ },
+ caret: { start: 0, length: 0 }
+ });
+ ok(elm.textContent == "ABCGHI", "composing text should be replaced");
+
+ window.getSelection().getRangeAt(0).insertNode(document.createTextNode(""));
+ synthesizeCompositionChange({
+ composition: {
+ string: "JKL",
+ clauses: [
+ { length: 3, attr: COMPOSITION_ATTR_CONVERTED_CLAUSE }
+ ]
+ },
+ caret: { start: 0, length: 0 }
+ });
+ ok(elm.textContent == "ABCJKL", "composing text should be replaced");
+
+ window.getSelection().getRangeAt(0).insertNode(document.createTextNode(""));
+ synthesizeCompositionChange({
+ composition: {
+ string: "MNO",
+ clauses: [
+ { length: 3, attr: COMPOSITION_ATTR_CONVERTED_CLAUSE }
+ ]
+ },
+ caret: { start: 1, length: 0 }
+ });
+ ok(elm.textContent == "ABCMNO", "composing text should be replaced");
+
+ window.getSelection().getRangeAt(0).insertNode(document.createTextNode(""));
+ synthesizeComposition({ type: "compositioncommitasis" });
+ ok(elm.textContent == "ABCMNO", "composing text should be committed");
+
+ synthesizeKey("Z", { accelKey: true });
+ ok(elm.textContent == "ABC", "text should be undoed");
+
+ synthesizeKey("Z", { accelKey: true, shiftKey: true });
+ ok(elm.textContent == "ABCMNO", "text should be redoed");
+
+ SimpleTest.finish();
+});
+</script>
+</pre>
+</body>
+</html>
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -17,16 +17,17 @@
#include "mozilla/ipc/CrashReporterClient.h"
#include "mozilla/ipc/ProcessChild.h"
#include "mozilla/layers/APZThreadUtils.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/dom/VideoDecoderManagerParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/ImageBridgeParent.h"
+#include "mozilla/dom/VideoDecoderManagerChild.h"
#include "mozilla/layers/LayerTreeOwnerTracker.h"
#include "nsDebugImpl.h"
#include "nsExceptionHandler.h"
#include "nsThreadManager.h"
#include "prenv.h"
#include "ProcessUtils.h"
#include "VRManager.h"
#include "VRManagerParent.h"
@@ -363,16 +364,17 @@ GPUParent::ActorDestroy(ActorDestroyReas
// state.
ProcessChild::QuickExit();
#endif
if (mVsyncBridge) {
mVsyncBridge->Shutdown();
mVsyncBridge = nullptr;
}
+ dom::VideoDecoderManagerParent::ShutdownVideoBridge();
CompositorThreadHolder::Shutdown();
Factory::ShutDown();
#if defined(XP_WIN)
DeviceManagerDx::Shutdown();
DeviceManagerD3D9::Shutdown();
#endif
LayerTreeOwnerTracker::Shutdown();
gfxVars::Shutdown();
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -789,17 +789,17 @@ DXGITextureHostD3D11::LockInternal()
{
if (!GetDevice()) {
NS_WARNING("trying to lock a TextureHost without a D3D device");
return false;
}
if (!mTextureSource) {
if (!mTexture && !OpenSharedHandle()) {
- gfxWindowsPlatform::GetPlatform()->ForceDeviceReset(ForcedDeviceResetReason::OPENSHAREDHANDLE);
+ DeviceManagerDx::Get()->ForceDeviceReset(ForcedDeviceResetReason::OPENSHAREDHANDLE);
return false;
}
mTextureSource = new DataTextureSourceD3D11(mFormat, mCompositor, mTexture);
}
mIsLocked = LockD3DTexture(mTextureSource->GetD3D11Texture());
@@ -1207,17 +1207,17 @@ SyncObjectD3D11::FinalizeFrame()
if (!mD3D11Texture && mD3D11SyncedTextures.size()) {
RefPtr<ID3D11Device> device = DeviceManagerDx::Get()->GetContentDevice();
hr = device->OpenSharedResource(mHandle, __uuidof(ID3D11Texture2D), (void**)(ID3D11Texture2D**)getter_AddRefs(mD3D11Texture));
if (FAILED(hr) || !mD3D11Texture) {
gfxCriticalError() << "Failed to D3D11 OpenSharedResource for frame finalization: " << hexa(hr);
- if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) {
+ if (DeviceManagerDx::Get()->HasDeviceReset()) {
return;
}
gfxDevCrash(LogReason::D3D11FinalizeFrame) << "Without device reset: " << hexa(hr);
}
// test QI
RefPtr<IDXGIKeyedMutex> mutex;
@@ -1233,30 +1233,30 @@ SyncObjectD3D11::FinalizeFrame()
if (mD3D11SyncedTextures.size()) {
RefPtr<IDXGIKeyedMutex> mutex;
hr = mD3D11Texture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
{
AutoTextureLock(mutex, hr, 20000);
if (hr == WAIT_TIMEOUT) {
- if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) {
+ if (DeviceManagerDx::Get()->HasDeviceReset()) {
gfxWarning() << "AcquireSync timed out because of device reset.";
return;
}
gfxDevCrash(LogReason::D3D11SyncLock) << "Timeout on the D3D11 sync lock";
}
D3D11_BOX box;
box.front = box.top = box.left = 0;
box.back = box.bottom = box.right = 1;
RefPtr<ID3D11Device> dev = DeviceManagerDx::Get()->GetContentDevice();
if (!dev) {
- if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) {
+ if (DeviceManagerDx::Get()->HasDeviceReset()) {
return;
}
MOZ_CRASH("GFX: Invalid D3D11 content device");
}
RefPtr<ID3D11DeviceContext> ctx;
dev->GetImmediateContext(getter_AddRefs(ctx));
--- a/gfx/layers/d3d9/CompositorD3D9.cpp
+++ b/gfx/layers/d3d9/CompositorD3D9.cpp
@@ -12,16 +12,17 @@
#include "mozilla/layers/Effects.h"
#include "nsWindowsHelpers.h"
#include "Nv3DVUtils.h"
#include "gfxFailure.h"
#include "mozilla/layers/LayerManagerComposite.h"
#include "gfxPrefs.h"
#include "gfxCrashReporterUtils.h"
#include "gfxUtils.h"
+#include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/widget/WinCompositorWidget.h"
#include "D3D9SurfaceImage.h"
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
@@ -674,17 +675,17 @@ CompositorD3D9::Ready()
void
CompositorD3D9::FailedToResetDevice() {
mFailedResetAttempts += 1;
// 10 is a totally arbitrary number that we may want to increase or decrease
// depending on how things behave in the wild.
if (mFailedResetAttempts > 10) {
mFailedResetAttempts = 0;
- gfxWindowsPlatform::GetPlatform()->D3D9DeviceReset();
+ DeviceManagerDx::Get()->NotifyD3D9DeviceReset();
gfxCriticalNote << "[D3D9] Unable to get a working D3D9 Compositor";
}
}
void
CompositorD3D9::BeginFrame(const nsIntRegion& aInvalidRegion,
const IntRect *aClipRectIn,
const IntRect& aRenderBounds,
--- a/gfx/layers/ipc/VideoBridgeChild.cpp
+++ b/gfx/layers/ipc/VideoBridgeChild.cpp
@@ -18,30 +18,33 @@ VideoBridgeChild::Startup()
sVideoBridgeChildSingleton = new VideoBridgeChild();
RefPtr<VideoBridgeParent> parent = new VideoBridgeParent();
MessageLoop* loop = CompositorThreadHolder::Loop();
sVideoBridgeChildSingleton->Open(parent->GetIPCChannel(),
loop,
ipc::ChildSide);
+ sVideoBridgeChildSingleton->mIPDLSelfRef = sVideoBridgeChildSingleton;
parent->SetOtherProcessId(base::GetCurrentProcId());
}
/* static */ void
VideoBridgeChild::Shutdown()
{
- sVideoBridgeChildSingleton = nullptr;
-
+ if (sVideoBridgeChildSingleton) {
+ sVideoBridgeChildSingleton->Close();
+ sVideoBridgeChildSingleton = nullptr;
+ }
}
VideoBridgeChild::VideoBridgeChild()
: mMessageLoop(MessageLoop::current())
+ , mCanSend(true)
{
- sVideoBridgeChildSingleton = this;
}
VideoBridgeChild::~VideoBridgeChild()
{
}
VideoBridgeChild*
VideoBridgeChild::GetSingleton()
@@ -83,16 +86,28 @@ VideoBridgeChild::AllocPTextureChild(con
}
bool
VideoBridgeChild::DeallocPTextureChild(PTextureChild* actor)
{
return TextureClient::DestroyIPDLActor(actor);
}
+void
+VideoBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+ mCanSend = false;
+}
+
+void
+VideoBridgeChild::DeallocPVideoBridgeChild()
+{
+ mIPDLSelfRef = nullptr;
+}
+
PTextureChild*
VideoBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags,
uint64_t aSerial)
{
MOZ_ASSERT(CanSend());
return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, aSerial);
--- a/gfx/layers/ipc/VideoBridgeChild.h
+++ b/gfx/layers/ipc/VideoBridgeChild.h
@@ -26,16 +26,20 @@ public:
// PVideoBridgeChild
PTextureChild* AllocPTextureChild(const SurfaceDescriptor& aSharedData,
const LayersBackend& aLayersBackend,
const TextureFlags& aFlags,
const uint64_t& aSerial) override;
bool DeallocPTextureChild(PTextureChild* actor) override;
+ void ActorDestroy(ActorDestroyReason aWhy) override;
+ void DeallocPVideoBridgeChild() override;
+
+
// ISurfaceAllocator
bool AllocUnsafeShmem(size_t aSize,
mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
mozilla::ipc::Shmem* aShmem) override;
bool AllocShmem(size_t aSize,
mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
mozilla::ipc::Shmem* aShmem) override;
bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
@@ -49,21 +53,23 @@ public:
// ClientIPCAllocator
base::ProcessId GetParentPid() const override { return OtherPid(); }
MessageLoop * GetMessageLoop() const override { return mMessageLoop; }
void CancelWaitForRecycle(uint64_t aTextureId) override { MOZ_ASSERT(false, "NO RECYCLING HERE"); }
// ISurfaceAllocator
bool IsSameProcess() const override;
- bool CanSend() { return true; }
+ bool CanSend() { return mCanSend; }
private:
VideoBridgeChild();
~VideoBridgeChild();
+ RefPtr<VideoBridgeChild> mIPDLSelfRef;
MessageLoop* mMessageLoop;
+ bool mCanSend;
};
} // namespace layers
} // namespace mozilla
#endif
--- a/gfx/src/DriverCrashGuard.cpp
+++ b/gfx/src/DriverCrashGuard.cpp
@@ -61,16 +61,21 @@ DriverCrashGuard::InitializeIfNeeded()
mInitialized = true;
Initialize();
}
static inline bool
AreCrashGuardsEnabled()
{
+ // Crash guard isn't supported in the GPU process since the entire
+ // process is basically a crash guard.
+ if (XRE_IsGPUProcess()) {
+ return false;
+ }
#ifdef NIGHTLY_BUILD
// We only use the crash guard on non-nightly channels, since the nightly
// channel is for development and having graphics features perma-disabled
// is rather annoying. Unless the user forces is with an environment
// variable, which comes in handy for testing.
return gfxEnv::ForceCrashGuardNightly();
#else
// Check to see if all guards have been disabled through the environment.
--- a/gfx/thebes/DeviceManagerDx.cpp
+++ b/gfx/thebes/DeviceManagerDx.cpp
@@ -574,28 +574,31 @@ void
DeviceManagerDx::ResetDevices()
{
MutexAutoLock lock(mDeviceLock);
mAdapter = nullptr;
mCompositorDevice = nullptr;
mContentDevice = nullptr;
mDeviceStatus = Nothing();
+ mDeviceResetReason = Nothing();
Factory::SetDirect3D11Device(nullptr);
}
bool
DeviceManagerDx::MaybeResetAndReacquireDevices()
{
DeviceResetReason resetReason;
- if (!GetAnyDeviceRemovedReason(&resetReason)) {
+ if (!HasDeviceReset(&resetReason)) {
return false;
}
- Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(resetReason));
+ if (resetReason != DeviceResetReason::FORCED_RESET) {
+ Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(resetReason));
+ }
bool createCompositorDevice = !!mCompositorDevice;
bool createContentDevice = !!mContentDevice;
ResetDevices();
if (createCompositorDevice && !CreateCompositorDevices()) {
// Just stop, don't try anything more
@@ -651,45 +654,94 @@ static DeviceResetReason HResultToResetR
case E_OUTOFMEMORY:
return DeviceResetReason::OUT_OF_MEMORY;
default:
MOZ_ASSERT(false);
}
return DeviceResetReason::UNKNOWN;
}
+bool
+DeviceManagerDx::HasDeviceReset(DeviceResetReason* aOutReason)
+{
+ MutexAutoLock lock(mDeviceLock);
+
+ if (mDeviceResetReason) {
+ *aOutReason = mDeviceResetReason.value();
+ return true;
+ }
+
+ DeviceResetReason reason;
+ if (GetAnyDeviceRemovedReason(&reason)) {
+ mDeviceResetReason = Some(reason);
+ *aOutReason = reason;
+ return true;
+ }
+
+ return false;
+}
+
static inline bool
-DidDeviceReset(RefPtr<ID3D11Device> aDevice, DeviceResetReason* aOutReason)
+DidDeviceReset(const RefPtr<ID3D11Device>& aDevice, DeviceResetReason* aOutReason)
{
if (!aDevice) {
return false;
}
HRESULT hr = aDevice->GetDeviceRemovedReason();
if (hr == S_OK) {
return false;
}
*aOutReason = HResultToResetReason(hr);
return true;
}
bool
DeviceManagerDx::GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason)
{
- // Note: this can be called off the main thread, so we need to use
- // our threadsafe getters.
- if (DidDeviceReset(GetCompositorDevice(), aOutReason) ||
- DidDeviceReset(GetContentDevice(), aOutReason))
+ // Caller must own the lock, since we access devices directly, and can be
+ // called from any thread.
+ mDeviceLock.AssertCurrentThreadOwns();
+
+ if (DidDeviceReset(mCompositorDevice, aOutReason) ||
+ DidDeviceReset(mContentDevice, aOutReason))
{
return true;
}
+
+ if (XRE_IsParentProcess() &&
+ NS_IsMainThread() &&
+ gfxPrefs::DeviceResetForTesting())
+ {
+ gfxPrefs::SetDeviceResetForTesting(0);
+ *aOutReason = DeviceResetReason::FORCED_RESET;
+ return true;
+ }
+
return false;
}
void
+DeviceManagerDx::ForceDeviceReset(ForcedDeviceResetReason aReason)
+{
+ Telemetry::Accumulate(Telemetry::FORCED_DEVICE_RESET_REASON, uint32_t(aReason));
+ {
+ MutexAutoLock lock(mDeviceLock);
+ mDeviceResetReason = Some(DeviceResetReason::FORCED_RESET);
+ }
+}
+
+void
+DeviceManagerDx::NotifyD3D9DeviceReset()
+{
+ MutexAutoLock lock(mDeviceLock);
+ mDeviceResetReason = Some(DeviceResetReason::D3D9_RESET);
+}
+
+void
DeviceManagerDx::DisableD3D11AfterCrash()
{
gfxConfig::Disable(Feature::D3D11_COMPOSITING,
FeatureStatus::CrashedInHandler,
"Crashed while acquiring a Direct3D11 device",
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_CRASH"));
ResetDevices();
}
--- a/gfx/thebes/DeviceManagerDx.h
+++ b/gfx/thebes/DeviceManagerDx.h
@@ -71,29 +71,33 @@ public:
void CreateContentDevices();
void ImportDeviceInfo(const D3D11DeviceStatus& aDeviceStatus);
void ExportDeviceInfo(D3D11DeviceStatus* aOut);
void ResetDevices();
void InitializeDirectDraw();
- // Call GetDeviceRemovedReason on each device until one returns
- // a failure.
- bool GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason);
-
// Reset and reacquire the devices if a reset has happened.
// Returns whether a reset occurred not whether reacquiring
// was successful.
bool MaybeResetAndReacquireDevices();
// Test whether we can acquire a DXGI 1.2-compatible adapter. This should
// only be called on startup before devices are initialized.
bool CheckRemotePresentSupport();
+ // Device reset helpers.
+ bool HasDeviceReset(DeviceResetReason* aOutReason = nullptr);
+
+ // Note: these set the cached device reset reason, which will be picked up
+ // on the next frame.
+ void ForceDeviceReset(ForcedDeviceResetReason aReason);
+ void NotifyD3D9DeviceReset();
+
private:
IDXGIAdapter1 *GetDXGIAdapter();
void DisableD3D11AfterCrash();
void CreateCompositorDevice(mozilla::gfx::FeatureState& d3d11);
bool CreateCompositorDeviceHelper(
mozilla::gfx::FeatureState& aD3d11,
@@ -111,16 +115,20 @@ private:
HRESULT& aResOut,
RefPtr<ID3D11Device>& aOutDevice);
bool ContentAdapterIsParentAdapter(ID3D11Device* device);
bool LoadD3D11();
void ReleaseD3D11();
+ // Call GetDeviceRemovedReason on each device until one returns
+ // a failure.
+ bool GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason);
+
private:
static StaticAutoPtr<DeviceManagerDx> sInstance;
// This is assigned during device creation. Afterwards, it is released if
// devices failed, and "forgotten" if devices succeeded (meaning, we leak
// the ref and unassign the module).
nsModuleHandle mD3D11Module;
@@ -131,14 +139,16 @@ private:
RefPtr<ID3D11Device> mContentDevice;
RefPtr<ID3D11Device> mDecoderDevice;
bool mCompositorDeviceSupportsVideo;
Maybe<D3D11DeviceStatus> mDeviceStatus;
nsModuleHandle mDirectDrawDLL;
RefPtr<IDirectDraw7> mDirectDraw;
+
+ Maybe<DeviceResetReason> mDeviceResetReason;
};
} // namespace gfx
} // namespace mozilla
#endif // mozilla_gfx_thebes_DeviceManagerDx_h
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -125,17 +125,18 @@ enum class DeviceResetReason
OK = 0,
HUNG,
REMOVED,
RESET,
DRIVER_ERROR,
INVALID_CALL,
OUT_OF_MEMORY,
FORCED_RESET,
- UNKNOWN
+ UNKNOWN,
+ D3D9_RESET
};
enum class ForcedDeviceResetReason
{
OPENSHAREDHANDLE = 0,
COMPOSITOR_UPDATED,
};
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -305,19 +305,16 @@ public:
return NS_OK;
}
};
NS_IMPL_ISUPPORTS(D3DSharedTexturesReporter, nsIMemoryReporter)
gfxWindowsPlatform::gfxWindowsPlatform()
: mRenderMode(RENDER_GDI)
- , mHasDeviceReset(false)
- , mHasFakeDeviceReset(false)
- , mHasD3D9DeviceReset(false)
{
mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
mUseClearTypeAlways = UNINITIALIZED_VALUE;
/*
* Initialize COM
*/
CoInitialize(nullptr);
@@ -434,30 +431,23 @@ gfxWindowsPlatform::InitDWriteSupport()
bool
gfxWindowsPlatform::HandleDeviceReset()
{
DeviceResetReason resetReason = DeviceResetReason::OK;
if (!DidRenderingDeviceReset(&resetReason)) {
return false;
}
- if (!mHasFakeDeviceReset) {
+ if (resetReason != DeviceResetReason::FORCED_RESET) {
Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(resetReason));
}
// Remove devices and adapters.
DeviceManagerDx::Get()->ResetDevices();
- // Reset local state. Note: we leave feature status variables as-is. They
- // will be recomputed by InitializeDevices().
- mHasDeviceReset = false;
- mHasFakeDeviceReset = false;
- mHasD3D9DeviceReset = false;
- mDeviceResetReason = DeviceResetReason::OK;
-
imgLoader::NormalLoader()->ClearCache(true);
imgLoader::NormalLoader()->ClearCache(false);
imgLoader::PrivateBrowsingLoader()->ClearCache(true);
imgLoader::PrivateBrowsingLoader()->ClearCache(false);
gfxAlphaBoxBlur::ShutdownBlurCache();
if (XRE_IsContentProcess()) {
// Fetch updated device parameters.
@@ -512,25 +502,16 @@ gfxWindowsPlatform::UpdateRenderMode()
<< ", D2D1 status:" << FeatureStatusToString(gfxConfig::GetValue(Feature::DIRECT2D))
<< ", content:" << int(GetDefaultContentBackend())
<< ", compositor:" << int(GetCompositorBackend());
MOZ_CRASH("GFX: Failed to update reference draw target after device reset");
}
}
}
-void
-gfxWindowsPlatform::ForceDeviceReset(ForcedDeviceResetReason aReason)
-{
- Telemetry::Accumulate(Telemetry::FORCED_DEVICE_RESET_REASON, uint32_t(aReason));
-
- mDeviceResetReason = DeviceResetReason::FORCED_RESET;
- mHasDeviceReset = true;
-}
-
mozilla::gfx::BackendType
gfxWindowsPlatform::GetContentBackendFor(mozilla::layers::LayersBackend aLayers)
{
mozilla::gfx::BackendType defaultBackend = gfxPlatform::GetDefaultContentBackend();
if (aLayers == LayersBackend::LAYERS_D3D11) {
return defaultBackend;
}
@@ -911,67 +892,31 @@ gfxWindowsPlatform::IsFontFormatSupporte
if (aFormatFlags != 0) {
return false;
}
// no format hint set, need to look at data
return true;
}
-void
-gfxWindowsPlatform::CompositorUpdated()
-{
- ForceDeviceReset(ForcedDeviceResetReason::COMPOSITOR_UPDATED);
- UpdateRenderMode();
-}
-
-void
-gfxWindowsPlatform::TestDeviceReset(DeviceResetReason aReason)
-{
- if (mHasDeviceReset) {
- return;
- }
- mHasDeviceReset = true;
- mHasFakeDeviceReset = true;
- mDeviceResetReason = aReason;
-}
-
bool
gfxWindowsPlatform::DidRenderingDeviceReset(DeviceResetReason* aResetReason)
{
- if (mHasDeviceReset) {
- if (aResetReason) {
- *aResetReason = mDeviceResetReason;
- }
- return true;
+ DeviceManagerDx* dm = DeviceManagerDx::Get();
+ if (!dm) {
+ return false;
}
- if (aResetReason) {
- *aResetReason = DeviceResetReason::OK;
- }
+ return dm->HasDeviceReset(aResetReason);
+}
- if (DeviceManagerDx::Get()->GetAnyDeviceRemovedReason(&mDeviceResetReason)) {
- mHasDeviceReset = true;
- if (aResetReason) {
- *aResetReason = mDeviceResetReason;
- }
- return true;
- }
-
- if (mHasD3D9DeviceReset) {
- return true;
- }
- if (XRE_IsParentProcess() && gfxPrefs::DeviceResetForTesting()) {
- TestDeviceReset((DeviceResetReason)gfxPrefs::DeviceResetForTesting());
- if (aResetReason) {
- *aResetReason = mDeviceResetReason;
- }
- gfxPrefs::SetDeviceResetForTesting(0);
- return true;
- }
- return false;
+void
+gfxWindowsPlatform::CompositorUpdated()
+{
+ DeviceManagerDx::Get()->ForceDeviceReset(ForcedDeviceResetReason::COMPOSITOR_UPDATED);
+ UpdateRenderMode();
}
BOOL CALLBACK
InvalidateWindowForDeviceReset(HWND aWnd, LPARAM aMsg)
{
RedrawWindow(aWnd, nullptr, nullptr,
RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_FRAME);
return TRUE;
@@ -1327,21 +1272,16 @@ gfxWindowsPlatform::SetupClearTypeParams
getter_AddRefs(mRenderingParams[TEXT_RENDERING_NORMAL]));
GetDWriteFactory()->CreateCustomRenderingParams(gamma, contrast, level,
dwriteGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
getter_AddRefs(mRenderingParams[TEXT_RENDERING_GDI_CLASSIC]));
}
}
-void
-gfxWindowsPlatform::D3D9DeviceReset() {
- mHasD3D9DeviceReset = true;
-}
-
ReadbackManagerD3D11*
gfxWindowsPlatform::GetReadbackManager()
{
if (!mD3D11ReadbackManager) {
mD3D11ReadbackManager = new ReadbackManagerD3D11();
}
return mD3D11ReadbackManager;
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -146,21 +146,16 @@ public:
/**
* Updates render mode with relation to the current preferences and
* available devices.
*/
void UpdateRenderMode();
/**
- * Forces all GPU resources to be recreated on the next frame.
- */
- void ForceDeviceReset(ForcedDeviceResetReason aReason);
-
- /**
* Verifies a D2D device is present and working, will attempt to create one
* it is non-functional or non-existant.
*
* \param aAttemptForce Attempt to force D2D cairo device creation by using
* cairo device creation routines.
*/
void VerifyD2DDevice(bool aAttemptForce);
@@ -206,36 +201,32 @@ public:
IDWriteFactory *GetDWriteFactory() { return mDWriteFactory; }
inline bool DWriteEnabled() { return !!mDWriteFactory; }
inline DWRITE_MEASURING_MODE DWriteMeasuringMode() { return mMeasuringMode; }
IDWriteRenderingParams *GetRenderingParams(TextRenderingMode aRenderMode)
{ return mRenderingParams[aRenderMode]; }
public:
- void D3D9DeviceReset();
-
bool DwmCompositionEnabled();
mozilla::layers::ReadbackManagerD3D11* GetReadbackManager();
static bool IsOptimus();
bool SupportsApzWheelInput() const override {
return true;
}
bool SupportsApzTouchInput() const override;
// Recreate devices as needed for a device reset. Returns true if a device
// reset occurred.
bool HandleDeviceReset();
void UpdateBackendPrefs();
- void TestDeviceReset(DeviceResetReason aReason);
-
virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() override;
static mozilla::Atomic<size_t> sD3D11SharedTextures;
static mozilla::Atomic<size_t> sD3D9SharedTextures;
bool SupportsPluginDirectBitmapDrawing() override {
return true;
}
bool SupportsPluginDirectDXGIDrawing();
@@ -277,19 +268,14 @@ private:
void InitializeD3D11Config();
void InitializeD2DConfig();
void InitializeDirectDrawConfig();
RefPtr<IDWriteFactory> mDWriteFactory;
RefPtr<IDWriteRenderingParams> mRenderingParams[TEXT_RENDERING_COUNT];
DWRITE_MEASURING_MODE mMeasuringMode;
- bool mHasDeviceReset;
- bool mHasFakeDeviceReset;
- mozilla::Atomic<bool> mHasD3D9DeviceReset;
- DeviceResetReason mDeviceResetReason;
-
RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
nsTArray<D3D_FEATURE_LEVEL> mFeatureLevels;
};
#endif /* GFX_WINDOWS_PLATFORM_H */
--- a/image/SVGDocumentWrapper.cpp
+++ b/image/SVGDocumentWrapper.cpp
@@ -357,17 +357,17 @@ SVGDocumentWrapper::SetupViewer(nsIReque
// document needs this navigation timing object for time computation, such
// as to calculate current time stamp based on the start time of navigation
// time object.
//
// For a root document, DocShell would do these sort of things
// automatically. Since there is no DocShell for this wrapped SVG document,
// we must set it up manually.
RefPtr<nsDOMNavigationTiming> timing = new nsDOMNavigationTiming();
- timing->NotifyNavigationStart();
+ timing->NotifyNavigationStart(nsDOMNavigationTiming::DocShellState::eInactive);
viewer->SetNavigationTiming(timing);
nsCOMPtr<nsIParser> parser = do_QueryInterface(listener);
NS_ENSURE_TRUE(parser, NS_ERROR_UNEXPECTED);
// XML-only, because this is for SVG content
nsCOMPtr<nsIContentSink> sink = parser->GetContentSink();
NS_ENSURE_TRUE(sink, NS_ERROR_UNEXPECTED);
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -512,17 +512,17 @@ IsProxy(JSContext* cx, unsigned argc, Va
args.rval().setBoolean(args[0].toObject().is<ProxyObject>());
return true;
}
static bool
WasmIsSupported(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
- args.rval().setBoolean(wasm::HasCompilerSupport(cx));
+ args.rval().setBoolean(wasm::HasSupport(cx));
return true;
}
static bool
WasmTextToBinary(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject callee(cx, &args.callee());
--- a/js/src/builtin/TypedArray.js
+++ b/js/src/builtin/TypedArray.js
@@ -1651,22 +1651,16 @@ function ArrayBufferSlice(start, end) {
// Step 22.
return new_;
}
function IsDetachedBufferThis() {
return IsDetachedBuffer(this);
}
-function ArrayBufferStaticSlice(buf, start, end) {
- if (arguments.length < 1)
- ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'ArrayBuffer.slice');
- return callFunction(ArrayBufferSlice, buf, start, end);
-}
-
// ES 2016 draft Mar 25, 2016 24.1.3.3.
function ArrayBufferSpecies() {
// Step 1.
return this;
}
_SetCanonicalName(ArrayBufferSpecies, "get [Symbol.species]");
// Shared memory and atomics proposal (30 Oct 2016)
--- a/js/src/builtin/Utilities.js
+++ b/js/src/builtin/Utilities.js
@@ -143,17 +143,17 @@ function GetIterator(obj, method) {
if (arguments.length === 1)
method = GetMethod(obj, std_iterator);
// Steps 3-4.
var iterator = callContentFunction(method, obj);
// Step 5.
if (!IsObject(iterator))
- ThrowTypeError(JSMSG_NOT_ITERABLE, ToString(iterator));
+ ThrowTypeError(JSMSG_NOT_ITERATOR, ToString(iterator));
// Step 6.
return iterator;
}
var _builtinCtorsCache = {__proto__: null};
function GetBuiltinConstructor(builtinName) {
--- a/js/src/ds/PageProtectingVector.h
+++ b/js/src/ds/PageProtectingVector.h
@@ -73,30 +73,28 @@ class PageProtectingVector final
unprotectedBytes += offsetToPage;
offsetToPage = (pageSize - (uintptr_t(vector.begin()) & pageMask)) & pageMask;
unprotectedBytes -= offsetToPage;
protectionEnabled = vector.capacity() >= protectionLowerBound &&
vector.capacity() >= pageSize + offsetToPage;
}
void protect() {
- MOZ_ASSERT(!regionUnprotected);
- if (protectionEnabled && unprotectedBytes >= intptr_t(pageSize)) {
+ if (!regionUnprotected && protectionEnabled && unprotectedBytes >= intptr_t(pageSize)) {
size_t toProtect = size_t(unprotectedBytes) & ~pageMask;
uintptr_t addr = uintptr_t(vector.begin()) + offsetToPage + protectedBytes;
gc::MakePagesReadOnly(reinterpret_cast<void*>(addr), toProtect);
unprotectedBytes -= toProtect;
protectedBytes += toProtect;
}
}
void unprotect() {
- MOZ_ASSERT(!regionUnprotected);
MOZ_ASSERT_IF(!protectionEnabled, !protectedBytes);
- if (protectedBytes) {
+ if (!regionUnprotected && protectedBytes) {
uintptr_t addr = uintptr_t(vector.begin()) + offsetToPage;
gc::UnprotectPages(reinterpret_cast<void*>(addr), protectedBytes);
unprotectedBytes += protectedBytes;
protectedBytes = 0;
}
}
void protectNewBuffer() {
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -5981,16 +5981,18 @@ BytecodeEmitter::emitIterator()
return false;
if (!emitElemOpBase(JSOP_CALLELEM)) // OBJ ITERFN
return false;
if (!emit1(JSOP_SWAP)) // ITERFN OBJ
return false;
if (!emitCall(JSOP_CALLITER, 0)) // ITER
return false;
checkTypeSet(JSOP_CALLITER);
+ if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) // ITER
+ return false;
return true;
}
bool
BytecodeEmitter::emitSpread(bool allowSelfHosted)
{
LoopControl loopInfo(this, StatementKind::Spread);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/arraybuffer-slice-warn.js
@@ -0,0 +1,13 @@
+// ArrayBuffer.slice should be warned once and only once.
+
+enableLastWarning();
+
+ArrayBuffer.slice(new ArrayBuffer(10), 1);
+var warning = getLastWarning();
+assertEq(warning !== null, true, "warning should be generated");
+assertEq(warning.name, "Warning");
+
+clearLastWarning();
+ArrayBuffer.slice(new ArrayBuffer(10), 1);
+warning = getLastWarning();
+assertEq(warning, null, "warning should not generated for 2nd ocurrence");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/async-lazy.js
@@ -0,0 +1,24 @@
+async function f1(a, b) {
+ let x = await 10;
+ return x;
+};
+var toStringResult = f1.toString();
+
+async function f2(a, b) {
+ // arguments.callee gets wrapped function from unwrapped function.
+ return arguments.callee;
+};
+
+relazifyFunctions();
+
+// toString gets unwrapped function from wrapped function.
+assertEq(f1.toString(), toStringResult);
+
+var ans = 0;
+f1().then(x => { ans = x; });
+drainJobQueue();
+assertEq(ans, 10);
+
+f2().then(x => { ans = x; });
+drainJobQueue();
+assertEq(ans, f2);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/async.js
@@ -0,0 +1,32 @@
+load(libdir + 'bytecode-cache.js');
+
+async function f1(a, b) {
+ let x = await 10;
+ return x;
+};
+var toStringResult = f1.toString();
+
+var test = `
+async function f1(a, b) {
+ let x = await 10;
+ return x;
+};
+// toString gets unwrapped function from wrapped function.
+assertEq(f1.toString(), \`${toStringResult}\`);
+
+var ans = 0;
+f1().then(x => { ans = x; });
+drainJobQueue();
+assertEq(ans, 10);
+
+async function f2(a, b) {
+ // arguments.callee gets wrapped function from unwrapped function.
+ return arguments.callee;
+};
+
+f2().then(x => { ans = x; });
+drainJobQueue();
+assertEq(ans, f2);
+`;
+
+evalWithCache(test, { assertEqBytecode: true, checkFrozen: true});
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1531,16 +1531,20 @@ class MacroAssemblerARMCompat : public M
ma_ldr(Address(WasmTlsReg, offsetof(wasm::TlsData, memoryBase)), HeapReg, scratch);
ma_ldr(Address(WasmTlsReg, offsetof(wasm::TlsData, globalData)), GlobalReg, scratch);
ma_add(Imm32(WasmGlobalRegBias), GlobalReg, scratch);
}
// Instrumentation for entering and leaving the profiler.
void profilerEnterFrame(Register framePtr, Register scratch);
void profilerExitFrame();
+
+ struct AutoPrepareForPatching {
+ explicit AutoPrepareForPatching(MacroAssemblerARMCompat&) {}
+ };
};
typedef MacroAssemblerARMCompat MacroAssemblerSpecific;
} // namespace jit
} // namespace js
#endif /* jit_arm_MacroAssembler_arm_h */
--- a/js/src/jit/arm64/MacroAssembler-arm64.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64.h
@@ -2311,16 +2311,20 @@ class MacroAssemblerCompat : public vixl
}
// FIXME: Should be in Assembler?
// FIXME: Should be const?
uint32_t currentOffset() const {
return nextOffset().getOffset();
}
+ struct AutoPrepareForPatching {
+ explicit AutoPrepareForPatching(MacroAssemblerCompat&) {}
+ };
+
protected:
bool buildOOLFakeExitFrame(void* fakeReturnAddr) {
uint32_t descriptor = MakeFrameDescriptor(framePushed(), JitFrame_IonJS,
ExitFrameLayout::Size());
Push(Imm32(descriptor));
Push(ImmPtr(fakeReturnAddr));
return true;
}
--- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h
+++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h
@@ -244,14 +244,19 @@ class MacroAssemblerMIPSShared : public
Register output);
void atomicExchange(int nbytes, bool signExtend, const Address& address, Register value,
Register valueTemp, Register offsetTemp, Register maskTemp,
Register output);
void atomicExchange(int nbytes, bool signExtend, const BaseIndex& address, Register value,
Register valueTemp, Register offsetTemp, Register maskTemp,
Register output);
+
+ public:
+ struct AutoPrepareForPatching {
+ explicit AutoPrepareForPatching(MacroAssemblerMIPSShared&) {}
+ };
};
} // namespace jit
} // namespace js
#endif /* jit_mips_shared_MacroAssembler_mips_shared_h */
--- a/js/src/jit/x86-shared/Assembler-x86-shared.h
+++ b/js/src/jit/x86-shared/Assembler-x86-shared.h
@@ -1052,27 +1052,34 @@ class AssemblerX86Shared : public Assemb
default:
MOZ_CRASH("unexpected operand kind");
}
}
CodeOffset callWithPatch() {
return CodeOffset(masm.call().offset());
}
+
+ struct AutoPrepareForPatching : X86Encoding::AutoUnprotectAssemblerBufferRegion {
+ explicit AutoPrepareForPatching(AssemblerX86Shared& masm)
+ : X86Encoding::AutoUnprotectAssemblerBufferRegion(masm.masm, 0, masm.size())
+ {}
+ };
+
void patchCall(uint32_t callerOffset, uint32_t calleeOffset) {
+ // The caller uses AutoUnprotectBuffer.
unsigned char* code = masm.data();
- X86Encoding::AutoUnprotectAssemblerBufferRegion unprotect(masm, callerOffset - 4, 4);
X86Encoding::SetRel32(code + callerOffset, code + calleeOffset);
}
CodeOffset farJumpWithPatch() {
return CodeOffset(masm.jmp().offset());
}
void patchFarJump(CodeOffset farJump, uint32_t targetOffset) {
+ // The caller uses AutoUnprotectBuffer.
unsigned char* code = masm.data();
- X86Encoding::AutoUnprotectAssemblerBufferRegion unprotect(masm, farJump.offset() - 4, 4);
X86Encoding::SetRel32(code + farJump.offset(), code + targetOffset);
}
static void repatchFarJump(uint8_t* code, uint32_t farJumpOffset, uint32_t targetOffset) {
X86Encoding::SetRel32(code + farJumpOffset, code + targetOffset);
}
CodeOffset twoByteNop() {
return CodeOffset(masm.twoByteNop().offset());
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -67,16 +67,17 @@ MSG_DEF(JSMSG_REDECLARED_VAR, 2
MSG_DEF(JSMSG_UNDECLARED_VAR, 1, JSEXN_REFERENCEERR, "assignment to undeclared variable {0}")
MSG_DEF(JSMSG_GETTER_ONLY, 0, JSEXN_TYPEERR, "setting a property that has only a getter")
MSG_DEF(JSMSG_OVERWRITING_ACCESSOR, 1, JSEXN_TYPEERR, "can't overwrite accessor property {0}")
MSG_DEF(JSMSG_UNDEFINED_PROP, 1, JSEXN_REFERENCEERR, "reference to undefined property {0}")
MSG_DEF(JSMSG_INVALID_MAP_ITERABLE, 1, JSEXN_TYPEERR, "iterable for {0} should have array-like objects")
MSG_DEF(JSMSG_NESTING_GENERATOR, 0, JSEXN_TYPEERR, "already executing generator")
MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}")
MSG_DEF(JSMSG_OBJECT_WATCH_DEPRECATED, 0, JSEXN_WARN, "Object.prototype.watch and unwatch are very slow, non-standard, and deprecated; use a getter/setter instead")
+MSG_DEF(JSMSG_ARRAYBUFFER_SLICE_DEPRECATED, 0, JSEXN_WARN, "ArrayBuffer.slice is deprecated; use ArrayBuffer.prototype.slice instead")
MSG_DEF(JSMSG_BAD_SURROGATE_CHAR, 1, JSEXN_TYPEERR, "bad surrogate character {0}")
MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large")
MSG_DEF(JSMSG_MALFORMED_UTF8_CHAR, 1, JSEXN_TYPEERR, "malformed UTF-8 character sequence at offset {0}")
MSG_DEF(JSMSG_BUILTIN_CTOR_NO_NEW, 1, JSEXN_TYPEERR, "calling a builtin {0} constructor without new is forbidden")
MSG_DEF(JSMSG_BAD_GENERATOR_YIELD, 1, JSEXN_TYPEERR, "yield from closing generator {0}")
MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE, 0, JSEXN_TYPEERR, "reduce of empty array with no initial value")
MSG_DEF(JSMSG_UNEXPECTED_TYPE, 2, JSEXN_TYPEERR, "{0} is {1}")
MSG_DEF(JSMSG_MISSING_FUN_ARG, 2, JSEXN_TYPEERR, "missing argument {0} when calling function {1}")
@@ -87,17 +88,19 @@ MSG_DEF(JSMSG_OBJECT_NOT_EXTENSIBLE, 1
MSG_DEF(JSMSG_CANT_DEFINE_PROP_OBJECT_NOT_EXTENSIBLE, 2, JSEXN_TYPEERR, "can't define property {1}: {0} is not extensible")
MSG_DEF(JSMSG_CANT_REDEFINE_PROP, 1, JSEXN_TYPEERR, "can't redefine non-configurable property {0}")
MSG_DEF(JSMSG_CANT_REDEFINE_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't redefine array length")
MSG_DEF(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't define array index property past the end of an array with non-writable length")
MSG_DEF(JSMSG_BAD_GET_SET_FIELD, 1, JSEXN_TYPEERR, "property descriptor's {0} field is neither undefined nor a function")
MSG_DEF(JSMSG_THROW_TYPE_ERROR, 0, JSEXN_TYPEERR, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them")
MSG_DEF(JSMSG_NOT_EXPECTED_TYPE, 3, JSEXN_TYPEERR, "{0}: expected {1}, got {2}")
MSG_DEF(JSMSG_NOT_ITERABLE, 1, JSEXN_TYPEERR, "{0} is not iterable")
+MSG_DEF(JSMSG_NOT_ITERATOR, 1, JSEXN_TYPEERR, "{0} is not iterator")
MSG_DEF(JSMSG_ALREADY_HAS_PRAGMA, 2, JSEXN_WARN, "{0} is being assigned a {1}, but already has one")
+MSG_DEF(JSMSG_GET_ITER_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "[Symbol.iterator]() returned a non-object value")
MSG_DEF(JSMSG_NEXT_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "iterator.next() returned a non-object value")
MSG_DEF(JSMSG_CANT_SET_PROTO, 0, JSEXN_TYPEERR, "can't set prototype of this object")
MSG_DEF(JSMSG_CANT_SET_PROTO_OF, 1, JSEXN_TYPEERR, "can't set prototype of {0}")
MSG_DEF(JSMSG_CANT_SET_PROTO_CYCLE, 0, JSEXN_TYPEERR, "can't set prototype: it would cause a prototype chain cycle")
MSG_DEF(JSMSG_INVALID_ARG_TYPE, 3, JSEXN_TYPEERR, "Invalid type: {0} can't be a{1} {2}")
MSG_DEF(JSMSG_TERMINATED, 1, JSEXN_ERR, "Script terminated by timeout at:\n{0}")
MSG_DEF(JSMSG_PROTO_NOT_OBJORNULL, 1, JSEXN_TYPEERR, "{0}.prototype is not an object or null")
MSG_DEF(JSMSG_CANT_CALL_CLASS_CONSTRUCTOR, 0, JSEXN_TYPEERR, "class constructors must be invoked with |new|")
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -65,16 +65,17 @@
#include "js/Conversions.h"
#include "js/Date.h"
#include "js/Initialization.h"
#include "js/Proxy.h"
#include "js/SliceBudget.h"
#include "js/StructuredClone.h"
#include "js/UniquePtr.h"
#include "js/Utility.h"
+#include "vm/AsyncFunction.h"
#include "vm/DateObject.h"
#include "vm/Debugger.h"
#include "vm/EnvironmentObject.h"
#include "vm/ErrorObject.h"
#include "vm/HelperThreads.h"
#include "vm/Interpreter.h"
#include "vm/RegExpStatics.h"
#include "vm/Runtime.h"
@@ -3522,16 +3523,21 @@ CloneFunctionObject(JSContext* cx, Handl
return nullptr;
}
if (IsAsmJSModule(fun)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
return nullptr;
}
+ if (IsWrappedAsyncFunction(fun)) {
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
+ return nullptr;
+ }
+
if (CanReuseScriptForClone(cx->compartment(), fun, env)) {
// If the script is to be reused, either the script can already handle
// non-syntactic scopes, or there is only the standard global lexical
// scope.
#ifdef DEBUG
// Fail here if we OOM during debug asserting.
// CloneFunctionReuseScript will delazify the script anyways, so we
// are not creating an extra failure condition for DEBUG builds.
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -311,16 +311,17 @@ js::XDRScript(XDRState<mode>* xdr, Handl
ArgumentsHasVarBinding,
NeedsArgsObj,
HasMappedArgsObj,
FunctionHasThisBinding,
FunctionHasExtraBodyVarScope,
IsGeneratorExp,
IsLegacyGenerator,
IsStarGenerator,
+ IsAsync,
OwnSource,
ExplicitUseStrict,
SelfHosted,
HasSingleton,
TreatAsRunOnce,
HasLazyScript,
HasNonSyntacticScope,
HasInnerFunctions,
@@ -424,16 +425,18 @@ js::XDRScript(XDRState<mode>* xdr, Handl
if (!enclosingScript || enclosingScript->scriptSource() != script->scriptSource())
scriptBits |= (1 << OwnSource);
if (script->isGeneratorExp())
scriptBits |= (1 << IsGeneratorExp);
if (script->isLegacyGenerator())
scriptBits |= (1 << IsLegacyGenerator);
if (script->isStarGenerator())
scriptBits |= (1 << IsStarGenerator);
+ if (script->asyncKind() == AsyncFunction)
+ scriptBits |= (1 << IsAsync);
if (script->hasSingletons())
scriptBits |= (1 << HasSingleton);
if (script->treatAsRunOnce())
scriptBits |= (1 << TreatAsRunOnce);
if (script->isRelazifiable())
scriptBits |= (1 << HasLazyScript);
if (script->hasNonSyntacticScope())
scriptBits |= (1 << HasNonSyntacticScope);
@@ -572,16 +575,19 @@ js::XDRScript(XDRState<mode>* xdr, Handl
if (scriptBits & (1 << IsDefaultClassConstructor))
script->isDefaultClassConstructor_ = true;
if (scriptBits & (1 << IsLegacyGenerator)) {
MOZ_ASSERT(!(scriptBits & (1 << IsStarGenerator)));
script->setGeneratorKind(LegacyGenerator);
} else if (scriptBits & (1 << IsStarGenerator))
script->setGeneratorKind(StarGenerator);
+
+ if (scriptBits & (1 << IsAsync))
+ script->setAsyncKind(AsyncFunction);
}
JS_STATIC_ASSERT(sizeof(jsbytecode) == 1);
JS_STATIC_ASSERT(sizeof(jssrcnote) == 1);
if (scriptBits & (1 << OwnSource)) {
if (!script->scriptSource()->performXDR<mode>(xdr))
return false;
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Destructuring/iterator-primitive.js
@@ -0,0 +1,36 @@
+var BUGNUMBER = 1021835;
+var summary = "Returning non-object from @@iterator should throw";
+
+print(BUGNUMBER + ": " + summary);
+
+let primitives = [
+ 1,
+ true,
+ undefined,
+ null,
+ "foo",
+ Symbol.iterator
+];
+
+function f([]) {
+}
+
+for (let primitive of primitives) {
+ let obj = {
+ [Symbol.iterator]() {
+ return primitive;
+ }
+ };
+ assertThrowsInstanceOf(() => {
+ let [] = obj;
+ }, TypeError);
+ assertThrowsInstanceOf(() => {
+ [] = obj;
+ }, TypeError);
+ assertThrowsInstanceOf(() => {
+ f(obj);
+ }, TypeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Function/spread-iterator-primitive.js
@@ -0,0 +1,28 @@
+var BUGNUMBER = 1021835;
+var summary = "Returning non-object from @@iterator should throw";
+
+print(BUGNUMBER + ": " + summary);
+
+let primitives = [
+ 1,
+ true,
+ undefined,
+ null,
+ "foo",
+ Symbol.iterator
+];
+
+function f() {
+}
+
+for (let primitive of primitives) {
+ let arg = {
+ [Symbol.iterator]() {
+ return primitive;
+ }
+ };
+ assertThrowsInstanceOf(() => f(...arg), TypeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Generators/yield-star-iterator-primitive.js
@@ -0,0 +1,31 @@
+var BUGNUMBER = 1021835;
+var summary = "Returning non-object from @@iterator should throw";
+
+print(BUGNUMBER + ": " + summary);
+
+let primitives = [
+ 1,
+ true,
+ undefined,
+ null,
+ "foo",
+ Symbol.iterator
+];
+
+for (let primitive of primitives) {
+ let obj = {
+ [Symbol.iterator]() {
+ return primitive;
+ }
+ };
+ assertThrowsInstanceOf(() => {
+ function* g() {
+ yield* obj;
+ }
+ for (let x of g()) {
+ }
+ }, TypeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Map/constructor-iterator-primitive.js
@@ -0,0 +1,34 @@
+var BUGNUMBER = 1021835;
+var summary = "Returning non-object from @@iterator should throw";
+
+print(BUGNUMBER + ": " + summary);
+
+let ctors = [
+ Map,
+ Set,
+ WeakMap,
+ WeakSet
+];
+
+let primitives = [
+ 1,
+ true,
+ undefined,
+ null,
+ "foo",
+ Symbol.iterator
+];
+
+for (let ctor of ctors) {
+ for (let primitive of primitives) {
+ let arg = {
+ [Symbol.iterator]() {
+ return primitive;
+ }
+ };
+ assertThrowsInstanceOf(() => new ctor(arg), TypeError);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Promise/iterator-primitive.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
+
+var BUGNUMBER = 1021835;
+var summary = "Returning non-object from @@iterator should throw";
+
+print(BUGNUMBER + ": " + summary);
+
+let primitives = [
+ 1,
+ true,
+ undefined,
+ null,
+ "foo",
+ Symbol.iterator
+];
+
+for (let primitive of primitives) {
+ let arg = {
+ [Symbol.iterator]() {
+ return primitive;
+ }
+ };
+ assertEventuallyThrows(Promise.all(arg), TypeError);
+ assertEventuallyThrows(Promise.race(arg), TypeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Statements/for-of-iterator-primitive.js
@@ -0,0 +1,28 @@
+var BUGNUMBER = 1021835;
+var summary = "Returning non-object from @@iterator should throw";
+
+print(BUGNUMBER + ": " + summary);
+
+let primitives = [
+ 1,
+ true,
+ undefined,
+ null,
+ "foo",
+ Symbol.iterator
+];
+
+for (let primitive of primitives) {
+ let obj = {
+ [Symbol.iterator]() {
+ return primitive;
+ }
+ };
+ assertThrowsInstanceOf(() => {
+ for (let x of obj) {
+ }
+ }, TypeError);
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedArray/constructor-iterator-primitive.js
@@ -0,0 +1,29 @@
+var BUGNUMBER = 1021835;
+var summary = "Returning non-object from @@iterator should throw";
+
+print(BUGNUMBER + ": " + summary);
+
+let primitives = [
+ 1,
+ true,
+ undefined,
+ null,
+ "foo",
+ Symbol.iterator
+];
+
+for (let ctor of typedArrayConstructors) {
+ for (let primitive of primitives) {
+ let arg = {
+ [Symbol.iterator]() {
+ return primitive;
+ }
+ };
+ assertThrowsInstanceOf(() => {
+ new ctor(arg);
+ }, TypeError);
+ }
+}
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_7/AsyncFunctions/clone.js
@@ -0,0 +1,7 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs clone
+
+// Async function cannot be cloned.
+assertThrowsInstanceOf(() => clone(async function f() {}), TypeError);
+
+if (typeof reportCompare === "function")
+ reportCompare(true, true);
--- a/js/src/tests/ecma_7/AsyncFunctions/shell.js
+++ b/js/src/tests/ecma_7/AsyncFunctions/shell.js
@@ -1,26 +0,0 @@
-(function(global) {
- function getPromiseResult(promise) {
- var result, error, caught = false;
- promise.then(r => { result = r; },
- e => { caught = true; error = e; });
- drainJobQueue();
- if (caught)
- throw error;
- return result;
- }
-
- function assertEventuallyEq(promise, expected) {
- assertEq(getPromiseResult(promise), expected);
- }
- global.assertEventuallyEq = assertEventuallyEq;
-
- function assertEventuallyThrows(promise, expectedErrorType) {
- assertThrowsInstanceOf(() => getPromiseResult(promise), expectedErrorType);
- };
- global.assertEventuallyThrows = assertEventuallyThrows;
-
- function assertEventuallyDeepEq(promise, expected) {
- assertDeepEq(getPromiseResult(promise), expected);
- };
- global.assertEventuallyDeepEq = assertEventuallyDeepEq;
-})(this);
--- a/js/src/tests/shell.js
+++ b/js/src/tests/shell.js
@@ -319,16 +319,42 @@
function OptLevel(i) {
i = Number(i);
var cx = GetContext();
cx.setOptimizationLevel(i);
}
global.OptLevel = OptLevel;
})(this);
+(function(global) {
+ function getPromiseResult(promise) {
+ var result, error, caught = false;
+ promise.then(r => { result = r; },
+ e => { caught = true; error = e; });
+ drainJobQueue();
+ if (caught)
+ throw error;
+ return result;
+ }
+
+ function assertEventuallyEq(promise, expected) {
+ assertEq(getPromiseResult(promise), expected);
+ }
+ global.assertEventuallyEq = assertEventuallyEq;
+
+ function assertEventuallyThrows(promise, expectedErrorType) {
+ assertThrowsInstanceOf(() => getPromiseResult(promise), expectedErrorType);
+ };
+ global.assertEventuallyThrows = assertEventuallyThrows;
+
+ function assertEventuallyDeepEq(promise, expected) {
+ assertDeepEq(getPromiseResult(promise), expected);
+ };
+ global.assertEventuallyDeepEq = assertEventuallyDeepEq;
+})(this);
var STATUS = "STATUS: ";
var gDelayTestDriverEnd = false;
var gTestcases = new Array();
var gTc = gTestcases.length;
var summary = '';
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -39,16 +39,17 @@
#include "gc/Barrier.h"
#include "gc/Marking.h"
#include "gc/Memory.h"
#include "js/Conversions.h"
#include "js/MemoryMetrics.h"
#include "vm/GlobalObject.h"
#include "vm/Interpreter.h"
+#include "vm/SelfHosting.h"
#include "vm/SharedArrayObject.h"
#include "vm/WrapperObject.h"
#include "wasm/WasmSignalHandlers.h"
#include "wasm/WasmTypes.h"
#include "jsatominlines.h"
#include "vm/NativeObject-inl.h"
@@ -82,16 +83,35 @@ js::ToClampedIndex(JSContext* cx, Handle
result = 0;
} else if (uint32_t(result) > length) {
result = length;
}
*out = uint32_t(result);
return true;
}
+static bool
+arraybuffer_static_slice(JSContext* cx, unsigned argc, Value* vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ if (args.length() < 1) {
+ ReportMissingArg(cx, args.calleev(), 1);
+ return false;
+ }
+
+ if (!GlobalObject::warnOnceAboutArrayBufferSlice(cx, cx->global()))
+ return false;
+
+ FixedInvokeArgs<2> args2(cx);
+ args2[0].set(args.get(1));
+ args2[1].set(args.get(2));
+ return CallSelfHostedFunction(cx, "ArrayBufferSlice", args[0], args2, args.rval());
+}
+
/*
* ArrayBufferObject
*
* This class holds the underlying raw buffer that the TypedArrayObject classes
* access. It can be created explicitly and passed to a TypedArrayObject, or
* can be created implicitly by constructing a TypedArrayObject with a size.
*/
@@ -135,17 +155,17 @@ static const ClassOps ArrayBufferObjectC
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
ArrayBufferObject::trace,
};
static const JSFunctionSpec static_functions[] = {
JS_FN("isView", ArrayBufferObject::fun_isView, 1, 0),
- JS_SELF_HOSTED_FN("slice", "ArrayBufferStaticSlice", 3, 0),
+ JS_FN("slice", arraybuffer_static_slice, 3, 0),
JS_FS_END
};
static const JSPropertySpec static_properties[] = {
JS_SELF_HOSTED_SYM_GET(species, "ArrayBufferSpecies", 0),
JS_PS_END
};
--- a/js/src/vm/ForOfIterator.cpp
+++ b/js/src/vm/ForOfIterator.cpp
@@ -69,20 +69,20 @@ ForOfIterator::init(HandleValue iterable
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_NOT_ITERABLE, bytes.get());
return false;
}
RootedValue res(cx);
if (!js::Call(cx, callee, iterable, &res))
return false;
- iterator = ToObject(cx, res);
- if (!iterator)
- return false;
+ if (!res.isObject())
+ return ThrowCheckIsObject(cx, CheckIsObjectKind::GetIterator);
+ iterator = &res.toObject();
return true;
}
inline bool
ForOfIterator::nextFromOptimizedArray(MutableHandleValue vp, bool* done)
{
MOZ_ASSERT(index != NOT_ARRAY);
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -94,17 +94,17 @@ js::GlobalObject::getTypedObjectModule()
MOZ_ASSERT(v.isObject());
return v.toObject().as<TypedObjectModuleObject>();
}
/* static */ bool
GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key)
{
if (key == JSProto_WebAssembly)
- return !wasm::HasCompilerSupport(cx);
+ return !wasm::HasSupport(cx);
#ifdef ENABLE_SHARED_ARRAY_BUFFER
// Return true if the given constructor has been disabled at run-time.
switch (key) {
case JSProto_Atomics:
case JSProto_SharedArrayBuffer:
return !cx->compartment()->creationOptions().getSharedMemoryAndAtomicsEnabled();
default:
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -125,16 +125,17 @@ class GlobalObject : public NativeObject
* we won't expose GlobalObject, so just assert that the two values are
* synchronized.
*/
static_assert(JSCLASS_GLOBAL_SLOT_COUNT == RESERVED_SLOTS,
"global object slot counts are inconsistent");
enum WarnOnceFlag : int32_t {
WARN_WATCH_DEPRECATED = 1 << 0,
+ WARN_ARRAYBUFFER_SLICE_DEPRECATED = 1 << 1,
};
// Emit the specified warning if the given slot in |obj|'s global isn't
// true, then set the slot to true. Thus calling this method warns once
// for each global object it's called on, and every other call does
// nothing.
static bool
warnOnceAbout(JSContext* cx, HandleObject obj, WarnOnceFlag flag, unsigned errorNumber);
@@ -720,16 +721,22 @@ class GlobalObject : public NativeObject
// in which |obj| was created, if no prior warning was given.
static bool warnOnceAboutWatch(JSContext* cx, HandleObject obj) {
// Temporarily disabled until we've provided a watch/unwatch workaround for
// debuggers like Firebug (bug 934669).
//return warnOnceAbout(cx, obj, WARN_WATCH_DEPRECATED, JSMSG_OBJECT_WATCH_DEPRECATED);
return true;
}
+ // Warn about use of the deprecated (static) ArrayBuffer.slice method.
+ static bool warnOnceAboutArrayBufferSlice(JSContext* cx, HandleObject obj) {
+ return warnOnceAbout(cx, obj, WARN_ARRAYBUFFER_SLICE_DEPRECATED,
+ JSMSG_ARRAYBUFFER_SLICE_DEPRECATED);
+ }
+
static bool getOrCreateEval(JSContext* cx, Handle<GlobalObject*> global,
MutableHandleObject eval);
// Infallibly test whether the given value is the eval function for this global.
bool valueIsEval(const Value& val);
// Implemented in jsiter.cpp.
static bool initIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -5028,16 +5028,19 @@ js::ReportRuntimeRedeclaration(JSContext
bool
js::ThrowCheckIsObject(JSContext* cx, CheckIsObjectKind kind)
{
switch (kind) {
case CheckIsObjectKind::IteratorNext:
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NEXT_RETURNED_PRIMITIVE);
break;
+ case CheckIsObjectKind::GetIterator:
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_GET_ITER_RETURNED_PRIMITIVE);
+ break;
default:
MOZ_CRASH("Unknown kind");
}
return false;
}
bool
js::ThrowUninitializedThis(JSContext* cx, AbstractFramePtr frame)
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -556,17 +556,18 @@ ReportRuntimeLexicalError(JSContext* cx,
// The parser only reports redeclarations that occurs within a single
// script. Due to the extensibility of the global lexical scope, we also check
// for redeclarations during runtime in JSOP_DEF{VAR,LET,CONST}.
void
ReportRuntimeRedeclaration(JSContext* cx, HandlePropertyName name, const char* redeclKind);
enum class CheckIsObjectKind : uint8_t {
- IteratorNext
+ IteratorNext,
+ GetIterator
};
bool
ThrowCheckIsObject(JSContext* cx, CheckIsObjectKind kind);
bool
ThrowUninitializedThis(JSContext* cx, AbstractFramePtr frame);
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -2727,116 +2727,116 @@ IsLiteralInt(ModuleValidator& m, ParseNo
return IsNumericLiteral(m, pn) &&
IsLiteralInt(ExtractNumericLiteral(m, pn), u32);
}
/*****************************************************************************/
namespace {
-#define CASE(TYPE, OP) case SimdOperation::Fn_##OP: return Expr::TYPE##OP;
+#define CASE(TYPE, OP) case SimdOperation::Fn_##OP: return Op::TYPE##OP;
#define I8x16CASE(OP) CASE(I8x16, OP)
#define I16x8CASE(OP) CASE(I16x8, OP)
#define I32x4CASE(OP) CASE(I32x4, OP)
#define F32x4CASE(OP) CASE(F32x4, OP)
#define B8x16CASE(OP) CASE(B8x16, OP)
#define B16x8CASE(OP) CASE(B16x8, OP)
#define B32x4CASE(OP) CASE(B32x4, OP)
#define ENUMERATE(TYPE, FOR_ALL, DO) \
switch(op) { \
- case SimdOperation::Constructor: return Expr::TYPE##Constructor; \
+ case SimdOperation::Constructor: return Op::TYPE##Constructor; \
FOR_ALL(DO) \
default: break; \
}
-static inline Expr
-SimdToExpr(SimdType type, SimdOperation op)
+static inline Op
+SimdToOp(SimdType type, SimdOperation op)
{
switch (type) {
case SimdType::Uint8x16:
// Handle the special unsigned opcodes, then fall through to Int8x16.
switch (op) {
- case SimdOperation::Fn_addSaturate: return Expr::I8x16addSaturateU;
- case SimdOperation::Fn_subSaturate: return Expr::I8x16subSaturateU;
- case SimdOperation::Fn_extractLane: return Expr::I8x16extractLaneU;
- case SimdOperation::Fn_shiftRightByScalar: return Expr::I8x16shiftRightByScalarU;
- case SimdOperation::Fn_lessThan: return Expr::I8x16lessThanU;
- case SimdOperation::Fn_lessThanOrEqual: return Expr::I8x16lessThanOrEqualU;
- case SimdOperation::Fn_greaterThan: return Expr::I8x16greaterThanU;
- case SimdOperation::Fn_greaterThanOrEqual: return Expr::I8x16greaterThanOrEqualU;
- case SimdOperation::Fn_fromInt8x16Bits: return Expr::Limit;
+ case SimdOperation::Fn_addSaturate: return Op::I8x16addSaturateU;
+ case SimdOperation::Fn_subSaturate: return Op::I8x16subSaturateU;
+ case SimdOperation::Fn_extractLane: return Op::I8x16extractLaneU;
+ case SimdOperation::Fn_shiftRightByScalar: return Op::I8x16shiftRightByScalarU;
+ case SimdOperation::Fn_lessThan: return Op::I8x16lessThanU;
+ case SimdOperation::Fn_lessThanOrEqual: return Op::I8x16lessThanOrEqualU;
+ case SimdOperation::Fn_greaterThan: return Op::I8x16greaterThanU;
+ case SimdOperation::Fn_greaterThanOrEqual: return Op::I8x16greaterThanOrEqualU;
+ case SimdOperation::Fn_fromInt8x16Bits: return Op::Limit;
default: break;
}
MOZ_FALLTHROUGH;
case SimdType::Int8x16:
// Bitcasts Uint8x16 <--> Int8x16 become noops.
switch (op) {
- case SimdOperation::Fn_fromUint8x16Bits: return Expr::Limit;
- case SimdOperation::Fn_fromUint16x8Bits: return Expr::I8x16fromInt16x8Bits;
- case SimdOperation::Fn_fromUint32x4Bits: return Expr::I8x16fromInt32x4Bits;
+ case SimdOperation::Fn_fromUint8x16Bits: return Op::Limit;
+ case SimdOperation::Fn_fromUint16x8Bits: return Op::I8x16fromInt16x8Bits;
+ case SimdOperation::Fn_fromUint32x4Bits: return Op::I8x16fromInt32x4Bits;
default: break;
}
ENUMERATE(I8x16, FORALL_INT8X16_ASMJS_OP, I8x16CASE)
break;
case SimdType::Uint16x8:
// Handle the special unsigned opcodes, then fall through to Int16x8.
switch(op) {
- case SimdOperation::Fn_addSaturate: return Expr::I16x8addSaturateU;
- case SimdOperation::Fn_subSaturate: return Expr::I16x8subSaturateU;
- case SimdOperation::Fn_extractLane: return Expr::I16x8extractLaneU;
- case SimdOperation::Fn_shiftRightByScalar: return Expr::I16x8shiftRightByScalarU;
- case SimdOperation::Fn_lessThan: return Expr::I16x8lessThanU;
- case SimdOperation::Fn_lessThanOrEqual: return Expr::I16x8lessThanOrEqualU;
- case SimdOperation::Fn_greaterThan: return Expr::I16x8greaterThanU;
- case SimdOperation::Fn_greaterThanOrEqual: return Expr::I16x8greaterThanOrEqualU;
- case SimdOperation::Fn_fromInt16x8Bits: return Expr::Limit;
+ case SimdOperation::Fn_addSaturate: return Op::I16x8addSaturateU;
+ case SimdOperation::Fn_subSaturate: return Op::I16x8subSaturateU;
+ case SimdOperation::Fn_extractLane: return Op::I16x8extractLaneU;
+ case SimdOperation::Fn_shiftRightByScalar: return Op::I16x8shiftRightByScalarU;
+ case SimdOperation::Fn_lessThan: return Op::I16x8lessThanU;
+ case SimdOperation::Fn_lessThanOrEqual: return Op::I16x8lessThanOrEqualU;
+ case SimdOperation::Fn_greaterThan: return Op::I16x8greaterThanU;
+ case SimdOperation::Fn_greaterThanOrEqual: return Op::I16x8greaterThanOrEqualU;
+ case SimdOperation::Fn_fromInt16x8Bits: return Op::Limit;
default: break;
}
MOZ_FALLTHROUGH;
case SimdType::Int16x8:
// Bitcasts Uint16x8 <--> Int16x8 become noops.
switch (op) {
- case SimdOperation::Fn_fromUint8x16Bits: return Expr::I16x8fromInt8x16Bits;
- case SimdOperation::Fn_fromUint16x8Bits: return Expr::Limit;
- case SimdOperation::Fn_fromUint32x4Bits: return Expr::I16x8fromInt32x4Bits;
+ case SimdOperation::Fn_fromUint8x16Bits: return Op::I16x8fromInt8x16Bits;
+ case SimdOperation::Fn_fromUint16x8Bits: return Op::Limit;
+ case SimdOperation::Fn_fromUint32x4Bits: return Op::I16x8fromInt32x4Bits;
default: break;
}
ENUMERATE(I16x8, FORALL_INT16X8_ASMJS_OP, I16x8CASE)
break;
case SimdType::Uint32x4:
// Handle the special unsigned opcodes, then fall through to Int32x4.
switch(op) {
- case SimdOperation::Fn_shiftRightByScalar: return Expr::I32x4shiftRightByScalarU;
- case SimdOperation::Fn_lessThan: return Expr::I32x4lessThanU;
- case SimdOperation::Fn_lessThanOrEqual: return Expr::I32x4lessThanOrEqualU;
- case SimdOperation::Fn_greaterThan: return Expr::I32x4greaterThanU;
- case SimdOperation::Fn_greaterThanOrEqual: return Expr::I32x4greaterThanOrEqualU;
- case SimdOperation::Fn_fromFloat32x4: return Expr::I32x4fromFloat32x4U;
- case SimdOperation::Fn_fromInt32x4Bits: return Expr::Limit;
+ case SimdOperation::Fn_shiftRightByScalar: return Op::I32x4shiftRightByScalarU;
+ case SimdOperation::Fn_lessThan: return Op::I32x4lessThanU;
+ case SimdOperation::Fn_lessThanOrEqual: return Op::I32x4lessThanOrEqualU;
+ case SimdOperation::Fn_greaterThan: return Op::I32x4greaterThanU;
+ case SimdOperation::Fn_greaterThanOrEqual: return Op::I32x4greaterThanOrEqualU;
+ case SimdOperation::Fn_fromFloat32x4: return Op::I32x4fromFloat32x4U;
+ case SimdOperation::Fn_fromInt32x4Bits: return Op::Limit;
default: break;
}
MOZ_FALLTHROUGH;
case SimdType::Int32x4:
// Bitcasts Uint32x4 <--> Int32x4 become noops.
switch (op) {
- case SimdOperation::Fn_fromUint8x16Bits: return Expr::I32x4fromInt8x16Bits;
- case SimdOperation::Fn_fromUint16x8Bits: return Expr::I32x4fromInt16x8Bits;
- case SimdOperation::Fn_fromUint32x4Bits: return Expr::Limit;
+ case SimdOperation::Fn_fromUint8x16Bits: return Op::I32x4fromInt8x16Bits;
+ case SimdOperation::Fn_fromUint16x8Bits: return Op::I32x4fromInt16x8Bits;
+ case SimdOperation::Fn_fromUint32x4Bits: return Op::Limit;
default: break;
}
ENUMERATE(I32x4, FORALL_INT32X4_ASMJS_OP, I32x4CASE)
break;
case SimdType::Float32x4:
switch (op) {
- case SimdOperation::Fn_fromUint8x16Bits: return Expr::F32x4fromInt8x16Bits;
- case SimdOperation::Fn_fromUint16x8Bits: return Expr::F32x4fromInt16x8Bits;
- case SimdOperation::Fn_fromUint32x4Bits: return Expr::F32x4fromInt32x4Bits;
+ case SimdOperation::Fn_fromUint8x16Bits: return Op::F32x4fromInt8x16Bits;
+ case SimdOperation::Fn_fromUint16x8Bits: return Op::F32x4fromInt16x8Bits;
+ case SimdOperation::Fn_fromUint32x4Bits: return Op::F32x4fromInt32x4Bits;
default: break;
}
ENUMERATE(F32x4, FORALL_FLOAT32X4_ASMJS_OP, F32x4CASE)
break;
case SimdType::Bool8x16:
ENUMERATE(B8x16, FORALL_BOOL_SIMD_OP, B8x16CASE)
break;
@@ -2993,116 +2993,116 @@ class MOZ_STACK_CLASS FunctionValidator
void setReturnedType(ExprType ret) {
ret_ = ret;
hasAlreadyReturned_ = true;
}
/**************************************************************** Labels */
private:
- bool writeBr(uint32_t absolute, Expr expr = Expr::Br) {
- MOZ_ASSERT(expr == Expr::Br || expr == Expr::BrIf);
+ bool writeBr(uint32_t absolute, Op op = Op::Br) {
+ MOZ_ASSERT(op == Op::Br || op == Op::BrIf);
MOZ_ASSERT(absolute < blockDepth_);
- return encoder().writeExpr(expr) &&
+ return encoder().writeOp(op) &&
encoder().writeVarU32(blockDepth_ - 1 - absolute);
}
void removeLabel(PropertyName* label, LabelMap* map) {
LabelMap::Ptr p = map->lookup(label);
MOZ_ASSERT(p);
map->remove(p);
}
public:
bool pushBreakableBlock() {
- return encoder().writeExpr(Expr::Block) &&
+ return encoder().writeOp(Op::Block) &&
encoder().writeFixedU8(uint8_t(ExprType::Void)) &&
breakableStack_.append(blockDepth_++);
}
bool popBreakableBlock() {
JS_ALWAYS_TRUE(breakableStack_.popCopy() == --blockDepth_);
- return encoder().writeExpr(Expr::End);
+ return encoder().writeOp(Op::End);
}
bool pushUnbreakableBlock(const NameVector* labels = nullptr) {
if (labels) {
for (PropertyName* label : *labels) {
if (!breakLabels_.putNew(label, blockDepth_))
return false;
}
}
blockDepth_++;
- return encoder().writeExpr(Expr::Block) &&
+ return encoder().writeOp(Op::Block) &&
encoder().writeFixedU8(uint8_t(ExprType::Void));
}
bool popUnbreakableBlock(const NameVector* labels = nullptr) {
if (labels) {
for (PropertyName* label : *labels)
removeLabel(label, &breakLabels_);
}
--blockDepth_;
- return encoder().writeExpr(Expr::End);
+ return encoder().writeOp(Op::End);
}
bool pushContinuableBlock() {
- return encoder().writeExpr(Expr::Block) &&
+ return encoder().writeOp(Op::Block) &&
encoder().writeFixedU8(uint8_t(ExprType::Void)) &&
continuableStack_.append(blockDepth_++);
}
bool popContinuableBlock() {
JS_ALWAYS_TRUE(continuableStack_.popCopy() == --blockDepth_);
- return encoder().writeExpr(Expr::End);
+ return encoder().writeOp(Op::End);
}
bool pushLoop() {
- return encoder().writeExpr(Expr::Block) &&
+ return encoder().writeOp(Op::Block) &&
encoder().writeFixedU8(uint8_t(ExprType::Void)) &&
- encoder().writeExpr(Expr::Loop) &&
+ encoder().writeOp(Op::Loop) &&
encoder().writeFixedU8(uint8_t(ExprType::Void)) &&
breakableStack_.append(blockDepth_++) &&
continuableStack_.append(blockDepth_++);
}
bool popLoop() {
JS_ALWAYS_TRUE(continuableStack_.popCopy() == --blockDepth_);
JS_ALWAYS_TRUE(breakableStack_.popCopy() == --blockDepth_);
- return encoder().writeExpr(Expr::End) &&
- encoder().writeExpr(Expr::End);
+ return encoder().writeOp(Op::End) &&
+ encoder().writeOp(Op::End);
}
bool pushIf(size_t* typeAt) {
++blockDepth_;
- return encoder().writeExpr(Expr::If) &&
+ return encoder().writeOp(Op::If) &&
encoder().writePatchableFixedU7(typeAt);
}
bool switchToElse() {
MOZ_ASSERT(blockDepth_ > 0);
- return encoder().writeExpr(Expr::Else);
+ return encoder().writeOp(Op::Else);
}
void setIfType(size_t typeAt, ExprType type) {
encoder().patchFixedU7(typeAt, uint8_t(type));
}
bool popIf() {
MOZ_ASSERT(blockDepth_ > 0);
--blockDepth_;
- return encoder().writeExpr(Expr::End);
+ return encoder().writeOp(Op::End);
}
bool popIf(size_t typeAt, ExprType type) {
MOZ_ASSERT(blockDepth_ > 0);
--blockDepth_;
- if (!encoder().writeExpr(Expr::End))
+ if (!encoder().writeOp(Op::End))
return false;
setIfType(typeAt, type);
return true;
}
bool writeBreakIf() {
- return writeBr(breakableStack_.back(), Expr::BrIf);
+ return writeBr(breakableStack_.back(), Op::BrIf);
}
bool writeContinueIf() {
- return writeBr(continuableStack_.back(), Expr::BrIf);
+ return writeBr(continuableStack_.back(), Op::BrIf);
}
bool writeUnlabeledBreakOrContinue(bool isBreak) {
return writeBr(isBreak? breakableStack_.back() : continuableStack_.back());
}
bool writeContinue() {
return writeBr(continuableStack_.back());
}
@@ -3146,75 +3146,75 @@ class MOZ_STACK_CLASS FunctionValidator
size_t numLocals() const { return locals_.count(); }
/**************************************************** Encoding interface */
Encoder& encoder() { return *encoder_; }
MOZ_MUST_USE bool writeInt32Lit(int32_t i32) {
- return encoder().writeExpr(Expr::I32Const) &&
+ return encoder().writeOp(Op::I32Const) &&
encoder().writeVarS32(i32);
}
MOZ_MUST_USE bool writeConstExpr(const NumLit& lit) {
switch (lit.which()) {
case NumLit::Fixnum:
case NumLit::NegativeInt:
case NumLit::BigUnsigned:
return writeInt32Lit(lit.toInt32());
case NumLit::Float:
- return encoder().writeExpr(Expr::F32Const) &&
+ return encoder().writeOp(Op::F32Const) &&
encoder().writeFixedF32(lit.toFloat());
case NumLit::Double:
- return encoder().writeExpr(Expr::F64Const) &&
+ return encoder().writeOp(Op::F64Const) &&
encoder().writeFixedF64(lit.toDouble());
case NumLit::Int8x16:
case NumLit::Uint8x16:
- return encoder().writeExpr(Expr::I8x16Const) &&
+ return encoder().writeOp(Op::I8x16Const) &&
encoder().writeFixedI8x16(lit.simdValue().asInt8x16());
case NumLit::Int16x8:
case NumLit::Uint16x8:
- return encoder().writeExpr(Expr::I16x8Const) &&
+ return encoder().writeOp(Op::I16x8Const) &&
encoder().writeFixedI16x8(lit.simdValue().asInt16x8());
case NumLit::Int32x4:
case NumLit::Uint32x4:
- return encoder().writeExpr(Expr::I32x4Const) &&
+ return encoder().writeOp(Op::I32x4Const) &&
encoder().writeFixedI32x4(lit.simdValue().asInt32x4());
case NumLit::Float32x4:
- return encoder().writeExpr(Expr::F32x4Const) &&
+ return encoder().writeOp(Op::F32x4Const) &&
encoder().writeFixedF32x4(lit.simdValue().asFloat32x4());
case NumLit::Bool8x16:
// Boolean vectors use the Int8x16 memory representation.
- return encoder().writeExpr(Expr::B8x16Const) &&
+ return encoder().writeOp(Op::B8x16Const) &&
encoder().writeFixedI8x16(lit.simdValue().asInt8x16());
case NumLit::Bool16x8:
// Boolean vectors use the Int16x8 memory representation.
- return encoder().writeExpr(Expr::B16x8Const) &&
+ return encoder().writeOp(Op::B16x8Const) &&
encoder().writeFixedI16x8(lit.simdValue().asInt16x8());
case NumLit::Bool32x4:
// Boolean vectors use the Int32x4 memory representation.
- return encoder().writeExpr(Expr::B32x4Const) &&
+ return encoder().writeOp(Op::B32x4Const) &&
encoder().writeFixedI32x4(lit.simdValue().asInt32x4());
case NumLit::OutOfRangeInt:
break;
}
MOZ_CRASH("unexpected literal type");
}
- MOZ_MUST_USE bool writeCall(ParseNode* pn, Expr op) {
- return encoder().writeExpr(op) &&
+ MOZ_MUST_USE bool writeCall(ParseNode* pn, Op op) {
+ return encoder().writeOp(op) &&
fg_.addCallSiteLineNum(m().tokenStream().srcCoords.lineNum(pn->pn_pos.begin));
}
MOZ_MUST_USE bool prepareCall(ParseNode* pn) {
return fg_.addCallSiteLineNum(m().tokenStream().srcCoords.lineNum(pn->pn_pos.begin));
}
- MOZ_MUST_USE bool writeSimdOp(SimdType simdType, SimdOperation op) {
- Expr expr = SimdToExpr(simdType, op);
- if (expr == Expr::Limit)
+ MOZ_MUST_USE bool writeSimdOp(SimdType simdType, SimdOperation simdOp) {
+ Op op = SimdToOp(simdType, simdOp);
+ if (op == Op::Limit)
return true;
- return encoder().writeExpr(expr);
+ return encoder().writeOp(op);
}
};
} /* anonymous namespace */
/*****************************************************************************/
// asm.js type-checking and code-generation algorithm
@@ -3873,17 +3873,17 @@ IsLiteralOrConst(FunctionValidator& f, P
*lit = ExtractNumericLiteral(f.m(), pn);
return true;
}
static bool
CheckFinalReturn(FunctionValidator& f, ParseNode* lastNonEmptyStmt)
{
- if (!f.encoder().writeExpr(Expr::End))
+ if (!f.encoder().writeOp(Op::End))
return false;
if (!f.hasAlreadyReturned()) {
f.setReturnedType(ExprType::Void);
return true;
}
if (!lastNonEmptyStmt->isKind(PNK_RETURN) && !IsVoid(f.returnedType()))
@@ -3944,28 +3944,28 @@ CheckVariables(FunctionValidator& f, Par
return false;
for (uint32_t i = 0; i < inits.length(); i++) {
NumLit lit = inits[i];
if (lit.isZeroBits())
continue;
if (!f.writeConstExpr(lit))
return false;
- if (!f.encoder().writeExpr(Expr::SetLocal))
+ if (!f.encoder().writeOp(Op::SetLocal))
return false;
if (!f.encoder().writeVarU32(firstVar + i))
return false;
}
*stmtIter = stmt;
return true;
}
static bool
-CheckExpr(FunctionValidator& f, ParseNode* expr, Type* type);
+CheckExpr(FunctionValidator& f, ParseNode* op, Type* type);
static bool
CheckNumericLiteral(FunctionValidator& f, ParseNode* num, Type* type)
{
NumLit lit = ExtractNumericLiteral(f.m(), num);
if (!lit.valid())
return f.fail(num, "numeric literal out of representable integer range");
*type = Type::lit(lit);
@@ -3973,33 +3973,33 @@ CheckNumericLiteral(FunctionValidator& f
}
static bool
CheckVarRef(FunctionValidator& f, ParseNode* varRef, Type* type)
{
PropertyName* name = varRef->name();
if (const FunctionValidator::Local* local = f.lookupLocal(name)) {
- if (!f.encoder().writeExpr(Expr::GetLocal))
+ if (!f.encoder().writeOp(Op::GetLocal))
return false;
if (!f.encoder().writeVarU32(local->slot))
return false;
*type = local->type;
return true;
}
if (const ModuleValidator::Global* global = f.lookupGlobal(name)) {
switch (global->which()) {
case ModuleValidator::Global::ConstantLiteral:
*type = global->varOrConstType();
return f.writeConstExpr(global->constLiteralValue());
case ModuleValidator::Global::ConstantImport:
case ModuleValidator::Global::Variable: {
*type = global->varOrConstType();
- return f.encoder().writeExpr(Expr::GetGlobal) &&
+ return f.encoder().writeOp(Op::GetGlobal) &&
f.encoder().writeVarU32(global->varOrConstIndex());
}
case ModuleValidator::Global::Function:
case ModuleValidator::Global::FFI:
case ModuleValidator::Global::MathBuiltinFunction:
case ModuleValidator::Global::AtomicsBuiltinFunction:
case ModuleValidator::Global::FuncPtrTable:
case ModuleValidator::Global::ArrayView:
@@ -4097,17 +4097,17 @@ CheckArrayAccess(FunctionValidator& f, P
return f.failf(pointerNode, "%s is not a subtype of int", pointerType.toChars());
}
}
// Don't generate the mask op if there is no need for it which could happen for
// a shift of zero or a SIMD access.
if (mask != NoMask) {
return f.writeInt32Lit(mask) &&
- f.encoder().writeExpr(Expr::I32And);
+ f.encoder().writeOp(Op::I32And);
}
return true;
}
static bool
CheckAndPrepareArrayAccess(FunctionValidator& f, ParseNode* viewName, ParseNode* indexExpr,
bool isSimd, Scalar::Type* viewType)
@@ -4135,24 +4135,24 @@ static bool
CheckLoadArray(FunctionValidator& f, ParseNode* elem, Type* type)
{
Scalar::Type viewType;
if (!CheckAndPrepareArrayAccess(f, ElemBase(elem), ElemIndex(elem), NoSimd, &viewType))
return false;
switch (viewType) {
- case Scalar::Int8: if (!f.encoder().writeExpr(Expr::I32Load8S)) return false; break;
- case Scalar::Uint8: if (!f.encoder().writeExpr(Expr::I32Load8U)) return false; break;
- case Scalar::Int16: if (!f.encoder().writeExpr(Expr::I32Load16S)) return false; break;
- case Scalar::Uint16: if (!f.encoder().writeExpr(Expr::I32Load16U)) return false; break;
+ case Scalar::Int8: if (!f.encoder().writeOp(Op::I32Load8S)) return false; break;
+ case Scalar::Uint8: if (!f.encoder().writeOp(Op::I32Load8U)) return false; break;
+ case Scalar::Int16: if (!f.encoder().writeOp(Op::I32Load16S)) return false; break;
+ case Scalar::Uint16: if (!f.encoder().writeOp(Op::I32Load16U)) return false; break;
case Scalar::Uint32:
- case Scalar::Int32: if (!f.encoder().writeExpr(Expr::I32Load)) return false; break;
- case Scalar::Float32: if (!f.encoder().writeExpr(Expr::F32Load)) return false; break;
- case Scalar::Float64: if (!f.encoder().writeExpr(Expr::F64Load)) return false; break;
+ case Scalar::Int32: if (!f.encoder().writeOp(Op::I32Load)) return false; break;
+ case Scalar::Float32: if (!f.encoder().writeOp(Op::F32Load)) return false; break;
+ case Scalar::Float64: if (!f.encoder().writeOp(Op::F64Load)) return false; break;
default: MOZ_CRASH("unexpected scalar type");
}
switch (viewType) {
case Scalar::Int8:
case Scalar::Int16:
case Scalar::Int32:
case Scalar::Uint8:
@@ -4206,44 +4206,44 @@ CheckStoreArray(FunctionValidator& f, Pa
break;
default:
MOZ_CRASH("Unexpected view type");
}
switch (viewType) {
case Scalar::Int8:
case Scalar::Uint8:
- if (!f.encoder().writeExpr(Expr::I32TeeStore8))
+ if (!f.encoder().writeOp(Op::I32TeeStore8))
return false;
break;
case Scalar::Int16:
case Scalar::Uint16:
- if (!f.encoder().writeExpr(Expr::I32TeeStore16))
+ if (!f.encoder().writeOp(Op::I32TeeStore16))
return false;
break;
case Scalar::Int32:
case Scalar::Uint32:
- if (!f.encoder().writeExpr(Expr::I32TeeStore))
+ if (!f.encoder().writeOp(Op::I32TeeStore))
return false;
break;
case Scalar::Float32:
if (rhsType.isFloatish()) {
- if (!f.encoder().writeExpr(Expr::F32TeeStore))
+ if (!f.encoder().writeOp(Op::F32TeeStore))
return false;
} else {
- if (!f.encoder().writeExpr(Expr::F64TeeStoreF32))
+ if (!f.encoder().writeOp(Op::F64TeeStoreF32))
return false;
}
break;
case Scalar::Float64:
if (rhsType.isFloatish()) {
- if (!f.encoder().writeExpr(Expr::F32TeeStoreF64))
+ if (!f.encoder().writeOp(Op::F32TeeStoreF64))
return false;
} else {
- if (!f.encoder().writeExpr(Expr::F64TeeStore))
+ if (!f.encoder().writeOp(Op::F64TeeStore))
return false;
}
break;
default: MOZ_CRASH("unexpected scalar type");
}
if (!WriteArrayAccessFlags(f, viewType))
return false;
@@ -4257,17 +4257,17 @@ CheckAssignName(FunctionValidator& f, Pa
{
RootedPropertyName name(f.cx(), lhs->name());
if (const FunctionValidator::Local* lhsVar = f.lookupLocal(name)) {
Type rhsType;
if (!CheckExpr(f, rhs, &rhsType))
return false;
- if (!f.encoder().writeExpr(Expr::TeeLocal))
+ if (!f.encoder().writeOp(Op::TeeLocal))
return false;
if (!f.encoder().writeVarU32(lhsVar->slot))
return false;
if (!(rhsType <= lhsVar->type)) {
return f.failf(lhs, "%s is not a subtype of %s",
rhsType.toChars(), lhsVar->type.toChars());
}
@@ -4281,17 +4281,17 @@ CheckAssignName(FunctionValidator& f, Pa
Type rhsType;
if (!CheckExpr(f, rhs, &rhsType))
return false;
Type globType = global->varOrConstType();
if (!(rhsType <= globType))
return f.failf(lhs, "%s is not a subtype of %s", rhsType.toChars(), globType.toChars());
- if (!f.encoder().writeExpr(Expr::TeeGlobal))
+ if (!f.encoder().writeOp(Op::TeeGlobal))
return false;
if (!f.encoder().writeVarU32(global->varOrConstIndex()))
return false;
*type = rhsType;
return true;
}
@@ -4333,17 +4333,17 @@ CheckMathIMul(FunctionValidator& f, Pars
return false;
if (!lhsType.isIntish())
return f.failf(lhs, "%s is not a subtype of intish", lhsType.toChars());
if (!rhsType.isIntish())
return f.failf(rhs, "%s is not a subtype of intish", rhsType.toChars());
*type = Type::Signed;
- return f.encoder().writeExpr(Expr::I32Mul);
+ return f.encoder().writeOp(Op::I32Mul);
}
static bool
CheckMathClz32(FunctionValidator& f, ParseNode* call, Type* type)
{
if (CallArgListLength(call) != 1)
return f.fail(call, "Math.clz32 must be passed 1 argument");
@@ -4352,44 +4352,44 @@ CheckMathClz32(FunctionValidator& f, Par
Type argType;
if (!CheckExpr(f, arg, &argType))
return false;
if (!argType.isIntish())
return f.failf(arg, "%s is not a subtype of intish", argType.toChars());
*type = Type::Fixnum;
- return f.encoder().writeExpr(Expr::I32Clz);
+ return f.encoder().writeOp(Op::I32Clz);
}
static bool
CheckMathAbs(FunctionValidator& f, ParseNode* call, Type* type)
{
if (CallArgListLength(call) != 1)
return f.fail(call, "Math.abs must be passed 1 argument");
ParseNode* arg = CallArgList(call);
Type argType;
if (!CheckExpr(f, arg, &argType))
return false;
if (argType.isSigned()) {
*type = Type::Unsigned;
- return f.encoder().writeExpr(Expr::I32Abs);
+ return f.encoder().writeOp(Op::I32Abs);
}
if (argType.isMaybeDouble()) {
*type = Type::Double;
- return f.encoder().writeExpr(Expr::F64Abs);
+ return f.encoder().writeOp(Op::F64Abs);
}
if (argType.isMaybeFloat()) {
*type = Type::Floatish;
- return f.encoder().writeExpr(Expr::F32Abs);
+ return f.encoder().writeOp(Op::F32Abs);
}
return f.failf(call, "%s is not a subtype of signed, float? or double?", argType.toChars());
}
static bool
CheckMathSqrt(FunctionValidator& f, ParseNode* call, Type* type)
{
@@ -4399,66 +4399,66 @@ CheckMathSqrt(FunctionValidator& f, Pars
ParseNode* arg = CallArgList(call);
Type argType;
if (!CheckExpr(f, arg, &argType))
return false;
if (argType.isMaybeDouble()) {
*type = Type::Double;
- return f.encoder().writeExpr(Expr::F64Sqrt);
+ return f.encoder().writeOp(Op::F64Sqrt);
}
if (argType.isMaybeFloat()) {
*type = Type::Floatish;
- return f.encoder().writeExpr(Expr::F32Sqrt);
+ return f.encoder().writeOp(Op::F32Sqrt);
}
return f.failf(call, "%s is neither a subtype of double? nor float?", argType.toChars());
}
static bool
CheckMathMinMax(FunctionValidator& f, ParseNode* callNode, bool isMax, Type* type)
{
if (CallArgListLength(callNode) < 2)
return f.fail(callNode, "Math.min/max must be passed at least 2 arguments");
ParseNode* firstArg = CallArgList(callNode);
Type firstType;
if (!CheckExpr(f, firstArg, &firstType))
return false;
- Expr expr;
+ Op op;
if (firstType.isMaybeDouble()) {
*type = Type::Double;
firstType = Type::MaybeDouble;
- expr = isMax ? Expr::F64Max : Expr::F64Min;
+ op = isMax ? Op::F64Max : Op::F64Min;
} else if (firstType.isMaybeFloat()) {
*type = Type::Float;
firstType = Type::MaybeFloat;
- expr = isMax ? Expr::F32Max : Expr::F32Min;
+ op = isMax ? Op::F32Max : Op::F32Min;
} else if (firstType.isSigned()) {
*type = Type::Signed;
firstType = Type::Signed;
- expr = isMax ? Expr::I32Max : Expr::I32Min;
+ op = isMax ? Op::I32Max : Op::I32Min;
} else {
return f.failf(firstArg, "%s is not a subtype of double?, float? or signed",
firstType.toChars());
}
unsigned numArgs = CallArgListLength(callNode);
ParseNode* nextArg = NextNode(firstArg);
for (unsigned i = 1; i < numArgs; i++, nextArg = NextNode(nextArg)) {
Type nextType;
if (!CheckExpr(f, nextArg, &nextType))
return false;
if (!(nextType <= firstType))
return f.failf(nextArg, "%s is not a subtype of %s", nextType.toChars(), firstType.toChars());
- if (!f.encoder().writeExpr(expr))
+ if (!f.encoder().writeOp(op))
return false;
}
return true;
}
static bool
CheckSharedArrayAtomicAccess(FunctionValidator& f, ParseNode* viewName, ParseNode* indexExpr,
@@ -4485,36 +4485,36 @@ CheckSharedArrayAtomicAccess(FunctionVal
default:
return f.failf(viewName, "not an integer array");
}
return true;
}
static bool
-WriteAtomicOperator(FunctionValidator& f, Expr opcode, Scalar::Type viewType)
-{
- return f.encoder().writeExpr(opcode) &&
+WriteAtomicOperator(FunctionValidator& f, Op opcode, Scalar::Type viewType)
+{
+ return f.encoder().writeOp(opcode) &&
f.encoder().writeFixedU8(viewType);
}
static bool
CheckAtomicsLoad(FunctionValidator& f, ParseNode* call, Type* type)
{
if (CallArgListLength(call) != 2)
return f.fail(call, "Atomics.load must be passed 2 arguments");
ParseNode* arrayArg = CallArgList(call);
ParseNode* indexArg = NextNode(arrayArg);
Scalar::Type viewType;
if (!CheckSharedArrayAtomicAccess(f, arrayArg, indexArg, &viewType))
return false;
- if (!WriteAtomicOperator(f, Expr::I32AtomicsLoad, viewType))
+ if (!WriteAtomicOperator(f, Op::I32AtomicsLoad, viewType))
return false;
if (!WriteArrayAccessFlags(f, viewType))
return false;
*type = Type::Int;
return true;
}
@@ -4535,17 +4535,17 @@ CheckAtomicsStore(FunctionValidator& f,
if (!rhsType.isIntish())
return f.failf(arrayArg, "%s is not a subtype of intish", rhsType.toChars());
Scalar::Type viewType;
if (!CheckSharedArrayAtomicAccess(f, arrayArg, indexArg, &viewType))
return false;
- if (!WriteAtomicOperator(f, Expr::I32AtomicsStore, viewType))
+ if (!WriteAtomicOperator(f, Op::I32AtomicsStore, viewType))
return false;
if (!WriteArrayAccessFlags(f, viewType))
return false;
*type = rhsType;
return true;
}
@@ -4566,17 +4566,17 @@ CheckAtomicsBinop(FunctionValidator& f,
if (!valueArgType.isIntish())
return f.failf(valueArg, "%s is not a subtype of intish", valueArgType.toChars());
Scalar::Type viewType;
if (!CheckSharedArrayAtomicAccess(f, arrayArg, indexArg, &viewType))
return false;
- if (!WriteAtomicOperator(f, Expr::I32AtomicsBinOp, viewType))
+ if (!WriteAtomicOperator(f, Op::I32AtomicsBinOp, viewType))
return false;
if (!f.encoder().writeFixedU8(uint8_t(op)))
return false;
if (!WriteArrayAccessFlags(f, viewType))
return false;
*type = Type::Int;
@@ -4623,17 +4623,17 @@ CheckAtomicsCompareExchange(FunctionVali
if (!newValueArgType.isIntish())
return f.failf(newValueArg, "%s is not a subtype of intish", newValueArgType.toChars());
Scalar::Type viewType;
if (!CheckSharedArrayAtomicAccess(f, arrayArg, indexArg, &viewType))
return false;
- if (!WriteAtomicOperator(f, Expr::I32AtomicsCompareExchange, viewType))
+ if (!WriteAtomicOperator(f, Op::I32AtomicsCompareExchange, viewType))
return false;
if (!WriteArrayAccessFlags(f, viewType))
return false;
*type = Type::Int;
return true;
}
@@ -4654,17 +4654,17 @@ CheckAtomicsExchange(FunctionValidator&
if (!valueArgType.isIntish())
return f.failf(arrayArg, "%s is not a subtype of intish", valueArgType.toChars());
Scalar::Type viewType;
if (!CheckSharedArrayAtomicAccess(f, arrayArg, indexArg, &viewType))
return false;
- if (!WriteAtomicOperator(f, Expr::I32AtomicsExchange, viewType))
+ if (!WriteAtomicOperator(f, Op::I32AtomicsExchange, viewType))
return false;
if (!WriteArrayAccessFlags(f, viewType))
return false;
*type = Type::Int;
return true;
}
@@ -4787,17 +4787,17 @@ CheckInternalCall(FunctionValidator& f,
return false;
Sig sig(Move(args), ret.canonicalToExprType());
ModuleValidator::Func* callee;
if (!CheckFunctionSignature(f.m(), callNode, Move(sig), calleeName, &callee))
return false;
- if (!f.writeCall(callNode, Expr::Call))
+ if (!f.writeCall(callNode, Op::Call))
return false;
if (!f.encoder().writeVarU32(callee->index()))
return false;
*type = Type::ret(ret);
return true;
}
@@ -4870,17 +4870,17 @@ CheckFuncPtrCall(FunctionValidator& f, P
return false;
Sig sig(Move(args), ret.canonicalToExprType());
uint32_t tableIndex;
if (!CheckFuncPtrTableAgainstExisting(f.m(), tableNode, name, Move(sig), mask, &tableIndex))
return false;
- if (!f.writeCall(callNode, Expr::OldCallIndirect))
+ if (!f.writeCall(callNode, Op::OldCallIndirect))
return false;
// Call signature
if (!f.encoder().writeVarU32(f.m().funcPtrTable(tableIndex).sigIndex()))
return false;
*type = Type::ret(ret);
return true;
@@ -4911,35 +4911,35 @@ CheckFFICall(FunctionValidator& f, Parse
return false;
Sig sig(Move(args), ret.canonicalToExprType());
uint32_t funcIndex;
if (!f.m().declareImport(calleeName, Move(sig), ffiIndex, &funcIndex))
return false;
- if (!f.writeCall(callNode, Expr::Call))
+ if (!f.writeCall(callNode, Op::Call))
return false;
if (!f.encoder().writeVarU32(funcIndex))
return false;
*type = Type::ret(ret);
return true;
}
static bool
CheckFloatCoercionArg(FunctionValidator& f, ParseNode* inputNode, Type inputType)
{
if (inputType.isMaybeDouble())
- return f.encoder().writeExpr(Expr::F32DemoteF64);
+ return f.encoder().writeOp(Op::F32DemoteF64);
if (inputType.isSigned())
- return f.encoder().writeExpr(Expr::F32ConvertSI32);
+ return f.encoder().writeOp(Op::F32ConvertSI32);
if (inputType.isUnsigned())
- return f.encoder().writeExpr(Expr::F32ConvertUI32);
+ return f.encoder().writeOp(Op::F32ConvertUI32);
if (inputType.isFloatish())
return true;
return f.failf(inputNode, "%s is not a subtype of signed, unsigned, double? or floatish",
inputType.toChars());
}
static bool
@@ -4987,38 +4987,38 @@ CheckMathFRound(FunctionValidator& f, Pa
return true;
}
static bool
CheckMathBuiltinCall(FunctionValidator& f, ParseNode* callNode, AsmJSMathBuiltinFunction func,
Type* type)
{
unsigned arity = 0;
- Expr f32;
- Expr f64;
+ Op f32;
+ Op f64;
switch (func) {
case AsmJSMathBuiltin_imul: return CheckMathIMul(f, callNode, type);
case AsmJSMathBuiltin_clz32: return CheckMathClz32(f, callNode, type);
case AsmJSMathBuiltin_abs: return CheckMathAbs(f, callNode, type);
case AsmJSMathBuiltin_sqrt: return CheckMathSqrt(f, callNode, type);
case AsmJSMathBuiltin_fround: return CheckMathFRound(f, callNode, type);
case AsmJSMathBuiltin_min: return CheckMathMinMax(f, callNode, /* isMax = */ false, type);
case AsmJSMathBuiltin_max: return CheckMathMinMax(f, callNode, /* isMax = */ true, type);
- case AsmJSMathBuiltin_ceil: arity = 1; f64 = Expr::F64Ceil; f32 = Expr::F32Ceil; break;
- case AsmJSMathBuiltin_floor: arity = 1; f64 = Expr::F64Floor; f32 = Expr::F32Floor; break;
- case AsmJSMathBuiltin_sin: arity = 1; f64 = Expr::F64Sin; f32 = Expr::Unreachable; break;
- case AsmJSMathBuiltin_cos: arity = 1; f64 = Expr::F64Cos; f32 = Expr::Unreachable; break;
- case AsmJSMathBuiltin_tan: arity = 1; f64 = Expr::F64Tan; f32 = Expr::Unreachable; break;
- case AsmJSMathBuiltin_asin: arity = 1; f64 = Expr::F64Asin; f32 = Expr::Unreachable; break;
- case AsmJSMathBuiltin_acos: arity = 1; f64 = Expr::F64Acos; f32 = Expr::Unreachable; break;
- case AsmJSMathBuiltin_atan: arity = 1; f64 = Expr::F64Atan; f32 = Expr::Unreachable; break;
- case AsmJSMathBuiltin_exp: arity = 1; f64 = Expr::F64Exp; f32 = Expr::Unreachable; break;
- case AsmJSMathBuiltin_log: arity = 1; f64 = Expr::F64Log; f32 = Expr::Unreachable; break;
- case AsmJSMathBuiltin_pow: arity = 2; f64 = Expr::F64Pow; f32 = Expr::Unreachable; break;
- case AsmJSMathBuiltin_atan2: arity = 2; f64 = Expr::F64Atan2; f32 = Expr::Unreachable; break;
+ case AsmJSMathBuiltin_ceil: arity = 1; f64 = Op::F64Ceil; f32 = Op::F32Ceil; break;
+ case AsmJSMathBuiltin_floor: arity = 1; f64 = Op::F64Floor; f32 = Op::F32Floor; break;
+ case AsmJSMathBuiltin_sin: arity = 1; f64 = Op::F64Sin; f32 = Op::Unreachable; break;
+ case AsmJSMathBuiltin_cos: arity = 1; f64 = Op::F64Cos; f32 = Op::Unreachable; break;
+ case AsmJSMathBuiltin_tan: arity = 1; f64 = Op::F64Tan; f32 = Op::Unreachable; break;
+ case AsmJSMathBuiltin_asin: arity = 1; f64 = Op::F64Asin; f32 = Op::Unreachable; break;
+ case AsmJSMathBuiltin_acos: arity = 1; f64 = Op::F64Acos; f32 = Op::Unreachable; break;
+ case AsmJSMathBuiltin_atan: arity = 1; f64 = Op::F64Atan; f32 = Op::Unreachable; break;
+ case AsmJSMathBuiltin_exp: arity = 1; f64 = Op::F64Exp; f32 = Op::Unreachable; break;
+ case AsmJSMathBuiltin_log: arity = 1; f64 = Op::F64Log; f32 = Op::Unreachable; break;
+ case AsmJSMathBuiltin_pow: arity = 2; f64 = Op::F64Pow; f32 = Op::Unreachable; break;
+ case AsmJSMathBuiltin_atan2: arity = 2; f64 = Op::F64Atan2; f32 = Op::Unreachable; break;
default: MOZ_CRASH("unexpected mathBuiltin function");
}
unsigned actualArity = CallArgListLength(callNode);
if (actualArity != arity)
return f.failf(callNode, "call passed %u arguments, expected %u", actualArity, arity);
if (!f.prepareCall(callNode))
@@ -5028,36 +5028,36 @@ CheckMathBuiltinCall(FunctionValidator&
ParseNode* argNode = CallArgList(callNode);
if (!CheckExpr(f, argNode, &firstType))
return false;
if (!firstType.isMaybeFloat() && !firstType.isMaybeDouble())
return f.fail(argNode, "arguments to math call should be a subtype of double? or float?");
bool opIsDouble = firstType.isMaybeDouble();
- if (!opIsDouble && f32 == Expr::Unreachable)
+ if (!opIsDouble && f32 == Op::Unreachable)
return f.fail(callNode, "math builtin cannot be used as float");
if (arity == 2) {
Type secondType;
argNode = NextNode(argNode);
if (!CheckExpr(f, argNode, &secondType))
return false;
if (firstType.isMaybeDouble() && !secondType.isMaybeDouble())
return f.fail(argNode, "both arguments to math builtin call should be the same type");
if (firstType.isMaybeFloat() && !secondType.isMaybeFloat())
return f.fail(argNode, "both arguments to math builtin call should be the same type");
}
if (opIsDouble) {
- if (!f.encoder().writeExpr(f64))
+ if (!f.encoder().writeOp(f64))
return false;
} else {
- if (!f.encoder().writeExpr(f32))
+ if (!f.encoder().writeOp(f32))
return false;
}
*type = opIsDouble ? Type::Double : Type::Floatish;
return true;
}
namespace {
@@ -5142,17 +5142,17 @@ class CheckSimdScalarArgs
// re-emitting them as float32 constants.
if (simdType_ != SimdType::Float32x4 || !actualType.isDoubleLit()) {
return f.failf(arg, "%s is not a subtype of %s%s",
actualType.toChars(), formalType_.toChars(),
simdType_ == SimdType::Float32x4 ? " or doublelit" : "");
}
// We emitted a double literal and actually want a float32.
- return f.encoder().writeExpr(Expr::F32DemoteF64);
+ return f.encoder().writeOp(Op::F32DemoteF64);
}
return true;
}
};
class CheckSimdSelectArgs
{
@@ -5329,17 +5329,17 @@ CheckSimdReplaceLane(FunctionValidator&
arg = NextNode(arg);
// Third argument is the scalar
Type scalarType;
if (!CheckExpr(f, arg, &scalarType))
return false;
if (!(scalarType <= SimdToCoercedScalarType(opType))) {
if (opType == SimdType::Float32x4 && scalarType.isDoubleLit()) {
- if (!f.encoder().writeExpr(Expr::F32DemoteF64))
+ if (!f.encoder().writeOp(Op::F32DemoteF64))
return false;
} else {
return f.failf(arg, "%s is not the correct type to replace an element of %s",
scalarType.toChars(), vecType.toChars());
}
}
if (!f.writeSimdOp(opType, SimdOperation::Fn_replaceLane))
@@ -5722,39 +5722,39 @@ CoerceResult(FunctionValidator& f, Parse
{
MOZ_ASSERT(expected.isCanonical());
// At this point, the bytecode resembles this:
// | the thing we wanted to coerce | current position |>
switch (expected.which()) {
case Type::Void:
if (!actual.isVoid()) {
- if (!f.encoder().writeExpr(Expr::Drop))
+ if (!f.encoder().writeOp(Op::Drop))
return false;
}
break;
case Type::Int:
if (!actual.isIntish())
return f.failf(expr, "%s is not a subtype of intish", actual.toChars());
break;
case Type::Float:
if (!CheckFloatCoercionArg(f, expr, actual))
return false;
break;
case Type::Double:
if (actual.isMaybeDouble()) {
// No conversion necessary.
} else if (actual.isMaybeFloat()) {
- if (!f.encoder().writeExpr(Expr::F64PromoteF32))
+ if (!f.encoder().writeOp(Op::F64PromoteF32))
return false;
} else if (actual.isSigned()) {
- if (!f.encoder().writeExpr(Expr::F64ConvertSI32))
+ if (!f.encoder().writeOp(Op::F64ConvertSI32))
return false;
} else if (actual.isUnsigned()) {
- if (!f.encoder().writeExpr(Expr::F64ConvertUI32))
+ if (!f.encoder().writeOp(Op::F64ConvertUI32))
return false;
} else {
return f.failf(expr, "%s is not a subtype of double?, float?, signed or unsigned", actual.toChars());
}
break;
default:
MOZ_ASSERT(expected.isSimd(), "Incomplete switch");
if (actual != expected)
@@ -5886,42 +5886,42 @@ CheckNot(FunctionValidator& f, ParseNode
Type operandType;
if (!CheckExpr(f, operand, &operandType))
return false;
if (!operandType.isInt())
return f.failf(operand, "%s is not a subtype of int", operandType.toChars());
*type = Type::Int;
- return f.encoder().writeExpr(Expr::I32Eqz);
+ return f.encoder().writeOp(Op::I32Eqz);
}
static bool
CheckNeg(FunctionValidator& f, ParseNode* expr, Type* type)
{
MOZ_ASSERT(expr->isKind(PNK_NEG));
ParseNode* operand = UnaryKid(expr);
Type operandType;
if (!CheckExpr(f, operand, &operandType))
return false;
if (operandType.isInt()) {
*type = Type::Intish;
- return f.encoder().writeExpr(Expr::I32Neg);
+ return f.encoder().writeOp(Op::I32Neg);
}
if (operandType.isMaybeDouble()) {
*type = Type::Double;
- return f.encoder().writeExpr(Expr::F64Neg);
+ return f.encoder().writeOp(Op::F64Neg);
}
if (operandType.isMaybeFloat()) {
*type = Type::Floatish;
- return f.encoder().writeExpr(Expr::F32Neg);
+ return f.encoder().writeOp(Op::F32Neg);
}
return f.failf(operand, "%s is not a subtype of int, float? or double?", operandType.toChars());
}
static bool
CheckCoerceToInt(FunctionValidator& f, ParseNode* expr, Type* type)
{
@@ -5929,18 +5929,18 @@ CheckCoerceToInt(FunctionValidator& f, P
ParseNode* operand = UnaryKid(expr);
Type operandType;
if (!CheckExpr(f, operand, &operandType))
return false;
if (operandType.isMaybeDouble() || operandType.isMaybeFloat()) {
*type = Type::Signed;
- Expr opcode = operandType.isMaybeDouble() ? Expr::I32TruncSF64 : Expr::I32TruncSF32;
- return f.encoder().writeExpr(opcode);
+ Op opcode = operandType.isMaybeDouble() ? Op::I32TruncSF64 : Op::I32TruncSF32;
+ return f.encoder().writeOp(opcode);
}
if (!operandType.isIntish())
return f.failf(operand, "%s is not a subtype of double?, float? or intish", operandType.toChars());
*type = Type::Signed;
return true;
}
@@ -5956,17 +5956,17 @@ CheckBitNot(FunctionValidator& f, ParseN
Type operandType;
if (!CheckExpr(f, operand, &operandType))
return false;
if (!operandType.isIntish())
return f.failf(operand, "%s is not a subtype of intish", operandType.toChars());
- if (!f.encoder().writeExpr(Expr::I32BitNot))
+ if (!f.encoder().writeOp(Op::I32BitNot))
return false;
*type = Type::Signed;
return true;
}
static bool
CheckAsExprStatement(FunctionValidator& f, ParseNode* exprStmt);
@@ -5974,17 +5974,17 @@ CheckAsExprStatement(FunctionValidator&
static bool
CheckComma(FunctionValidator& f, ParseNode* comma, Type* type)
{
MOZ_ASSERT(comma->isKind(PNK_COMMA));
ParseNode* operands = ListHead(comma);
// The block depth isn't taken into account here, because a comma list can't
// contain breaks and continues and nested control flow structures.
- if (!f.encoder().writeExpr(Expr::Block))
+ if (!f.encoder().writeOp(Op::Block))
return false;
size_t typeAt;
if (!f.encoder().writePatchableFixedU7(&typeAt))
return false;
ParseNode* pn = operands;
for (; NextNode(pn); pn = NextNode(pn)) {
@@ -5992,17 +5992,17 @@ CheckComma(FunctionValidator& f, ParseNo
return false;
}
if (!CheckExpr(f, pn, type))
return false;
f.encoder().patchFixedU7(typeAt, uint8_t(type->toWasmBlockSignatureType()));
- return f.encoder().writeExpr(Expr::End);
+ return f.encoder().writeOp(Op::End);
}
static bool
CheckConditional(FunctionValidator& f, ParseNode* ternary, Type* type)
{
MOZ_ASSERT(ternary->isKind(PNK_CONDITIONAL));
ParseNode* cond = TernaryKid1(ternary);
@@ -6098,27 +6098,27 @@ CheckMultiply(FunctionValidator& f, Pars
Type rhsType;
if (!CheckExpr(f, rhs, &rhsType))
return false;
if (lhsType.isInt() && rhsType.isInt()) {
if (!IsValidIntMultiplyConstant(f.m(), lhs) && !IsValidIntMultiplyConstant(f.m(), rhs))
return f.fail(star, "one arg to int multiply must be a small (-2^20, 2^20) int literal");
*type = Type::Intish;
- return f.encoder().writeExpr(Expr::I32Mul);
+ return f.encoder().writeOp(Op::I32Mul);
}
if (lhsType.isMaybeDouble() && rhsType.isMaybeDouble()) {
*type = Type::Double;
- return f.encoder().writeExpr(Expr::F64Mul);
+ return f.encoder().writeOp(Op::F64Mul);
}
if (lhsType.isMaybeFloat() && rhsType.isMaybeFloat()) {
*type = Type::Floatish;
- return f.encoder().writeExpr(Expr::F32Mul);
+ return f.encoder().writeOp(Op::F32Mul);
}
return f.fail(star, "multiply operands must be both int, both double? or both float?");
}
static bool
CheckAddOrSub(FunctionValidator& f, ParseNode* expr, Type* type, unsigned* numAddOrSubOut = nullptr)
{
@@ -6153,25 +6153,25 @@ CheckAddOrSub(FunctionValidator& f, Pars
rhsNumAddOrSub = 0;
}
unsigned numAddOrSub = lhsNumAddOrSub + rhsNumAddOrSub + 1;
if (numAddOrSub > (1<<20))
return f.fail(expr, "too many + or - without intervening coercion");
if (lhsType.isInt() && rhsType.isInt()) {
- if (!f.encoder().writeExpr(expr->isKind(PNK_ADD) ? Expr::I32Add : Expr::I32Sub))
+ if (!f.encoder().writeOp(expr->isKind(PNK_ADD) ? Op::I32Add : Op::I32Sub))
return false;
*type = Type::Intish;
} else if (lhsType.isMaybeDouble() && rhsType.isMaybeDouble()) {
- if (!f.encoder().writeExpr(expr->isKind(PNK_ADD) ? Expr::F64Add : Expr::F64Sub))
+ if (!f.encoder().writeOp(expr->isKind(PNK_ADD) ? Op::F64Add : Op::F64Sub))
return false;
*type = Type::Double;
} else if (lhsType.isMaybeFloat() && rhsType.isMaybeFloat()) {
- if (!f.encoder().writeExpr(expr->isKind(PNK_ADD) ? Expr::F32Add : Expr::F32Sub))
+ if (!f.encoder().writeOp(expr->isKind(PNK_ADD) ? Op::F32Add : Op::F32Sub))
return false;
*type = Type::Floatish;
} else {
return f.failf(expr, "operands to + or - must both be int, float? or double?, got %s and %s",
lhsType.toChars(), rhsType.toChars());
}
if (numAddOrSubOut)
@@ -6190,35 +6190,35 @@ CheckDivOrMod(FunctionValidator& f, Pars
Type lhsType, rhsType;
if (!CheckExpr(f, lhs, &lhsType))
return false;
if (!CheckExpr(f, rhs, &rhsType))
return false;
if (lhsType.isMaybeDouble() && rhsType.isMaybeDouble()) {
*type = Type::Double;
- return f.encoder().writeExpr(expr->isKind(PNK_DIV) ? Expr::F64Div : Expr::F64Mod);
+ return f.encoder().writeOp(expr->isKind(PNK_DIV) ? Op::F64Div : Op::F64Mod);
}
if (lhsType.isMaybeFloat() && rhsType.isMaybeFloat()) {
*type = Type::Floatish;
if (expr->isKind(PNK_DIV))
- return f.encoder().writeExpr(Expr::F32Div);
+ return f.encoder().writeOp(Op::F32Div);
else
return f.fail(expr, "modulo cannot receive float arguments");
}
if (lhsType.isSigned() && rhsType.isSigned()) {
*type = Type::Intish;
- return f.encoder().writeExpr(expr->isKind(PNK_DIV) ? Expr::I32DivS : Expr::I32RemS);
+ return f.encoder().writeOp(expr->isKind(PNK_DIV) ? Op::I32DivS : Op::I32RemS);
}
if (lhsType.isUnsigned() && rhsType.isUnsigned()) {
*type = Type::Intish;
- return f.encoder().writeExpr(expr->isKind(PNK_DIV) ? Expr::I32DivU : Expr::I32RemU);
+ return f.encoder().writeOp(expr->isKind(PNK_DIV) ? Op::I32DivU : Op::I32RemU);
}
return f.failf(expr, "arguments to / or %% must both be double?, float?, signed, or unsigned; "
"%s and %s are given", lhsType.toChars(), rhsType.toChars());
}
static bool
CheckComparison(FunctionValidator& f, ParseNode* comp, Type* type)
@@ -6239,63 +6239,63 @@ CheckComparison(FunctionValidator& f, Pa
!(lhsType.isUnsigned() && rhsType.isUnsigned()) &&
!(lhsType.isDouble() && rhsType.isDouble()) &&
!(lhsType.isFloat() && rhsType.isFloat()))
{
return f.failf(comp, "arguments to a comparison must both be signed, unsigned, floats or doubles; "
"%s and %s are given", lhsType.toChars(), rhsType.toChars());
}
- Expr stmt;
+ Op stmt;
if (lhsType.isSigned() && rhsType.isSigned()) {
switch (comp->getOp()) {
- case JSOP_EQ: stmt = Expr::I32Eq; break;
- case JSOP_NE: stmt = Expr::I32Ne; break;
- case JSOP_LT: stmt = Expr::I32LtS; break;
- case JSOP_LE: stmt = Expr::I32LeS; break;
- case JSOP_GT: stmt = Expr::I32GtS; break;
- case JSOP_GE: stmt = Expr::I32GeS; break;
+ case JSOP_EQ: stmt = Op::I32Eq; break;
+ case JSOP_NE: stmt = Op::I32Ne; break;
+ case JSOP_LT: stmt = Op::I32LtS; break;
+ case JSOP_LE: stmt = Op::I32LeS; break;
+ case JSOP_GT: stmt = Op::I32GtS; break;
+ case JSOP_GE: stmt = Op::I32GeS; break;
default: MOZ_CRASH("unexpected comparison op");
}
} else if (lhsType.isUnsigned() && rhsType.isUnsigned()) {
switch (comp->getOp()) {
- case JSOP_EQ: stmt = Expr::I32Eq; break;
- case JSOP_NE: stmt = Expr::I32Ne; break;
- case JSOP_LT: stmt = Expr::I32LtU; break;
- case JSOP_LE: stmt = Expr::I32LeU; break;
- case JSOP_GT: stmt = Expr::I32GtU; break;
- case JSOP_GE: stmt = Expr::I32GeU; break;
+ case JSOP_EQ: stmt = Op::I32Eq; break;
+ case JSOP_NE: stmt = Op::I32Ne; break;
+ case JSOP_LT: stmt = Op::I32LtU; break;
+ case JSOP_LE: stmt = Op::I32LeU; break;
+ case JSOP_GT: stmt = Op::I32GtU; break;
+ case JSOP_GE: stmt = Op::I32GeU; break;
default: MOZ_CRASH("unexpected comparison op");
}
} else if (lhsType.isDouble()) {
switch (comp->getOp()) {
- case JSOP_EQ: stmt = Expr::F64Eq; break;
- case JSOP_NE: stmt = Expr::F64Ne; break;
- case JSOP_LT: stmt = Expr::F64Lt; break;
- case JSOP_LE: stmt = Expr::F64Le; break;
- case JSOP_GT: stmt = Expr::F64Gt; break;
- case JSOP_GE: stmt = Expr::F64Ge; break;
+ case JSOP_EQ: stmt = Op::F64Eq; break;
+ case JSOP_NE: stmt = Op::F64Ne; break;
+ case JSOP_LT: stmt = Op::F64Lt; break;
+ case JSOP_LE: stmt = Op::F64Le; break;
+ case JSOP_GT: stmt = Op::F64Gt; break;
+ case JSOP_GE: stmt = Op::F64Ge; break;
default: MOZ_CRASH("unexpected comparison op");
}
} else if (lhsType.isFloat()) {
switch (comp->getOp()) {
- case JSOP_EQ: stmt = Expr::F32Eq; break;
- case JSOP_NE: stmt = Expr::F32Ne; break;
- case JSOP_LT: stmt = Expr::F32Lt; break;
- case JSOP_LE: stmt = Expr::F32Le; break;
- case JSOP_GT: stmt = Expr::F32Gt; break;
- case JSOP_GE: stmt = Expr::F32Ge; break;
+ case JSOP_EQ: stmt = Op::F32Eq; break;
+ case JSOP_NE: stmt = Op::F32Ne; break;
+ case JSOP_LT: stmt = Op::F32Lt; break;
+ case JSOP_LE: stmt = Op::F32Le; break;
+ case JSOP_GT: stmt = Op::F32Gt; break;
+ case JSOP_GE: stmt = Op::F32Ge; break;
default: MOZ_CRASH("unexpected comparison op");
}
} else {
MOZ_CRASH("unexpected type");
}
*type = Type::Int;
- return f.encoder().writeExpr(stmt);
+ return f.encoder().writeOp(stmt);
}
static bool
CheckBitwise(FunctionValidator& f, ParseNode* bitwise, Type* type)
{
ParseNode* lhs = BitwiseLeft(bitwise);
ParseNode* rhs = BitwiseRight(bitwise);
@@ -6342,22 +6342,22 @@ CheckBitwise(FunctionValidator& f, Parse
return false;
if (!lhsType.isIntish())
return f.failf(lhs, "%s is not a subtype of intish", lhsType.toChars());
if (!rhsType.isIntish())
return f.failf(rhs, "%s is not a subtype of intish", rhsType.toChars());
switch (bitwise->getKind()) {
- case PNK_BITOR: if (!f.encoder().writeExpr(Expr::I32Or)) return false; break;
- case PNK_BITAND: if (!f.encoder().writeExpr(Expr::I32And)) return false; break;
- case PNK_BITXOR: if (!f.encoder().writeExpr(Expr::I32Xor)) return false; break;
- case PNK_LSH: if (!f.encoder().writeExpr(Expr::I32Shl)) return false; break;
- case PNK_RSH: if (!f.encoder().writeExpr(Expr::I32ShrS)) return false; break;
- case PNK_URSH: if (!f.encoder().writeExpr(Expr::I32ShrU)) return false; break;
+ case PNK_BITOR: if (!f.encoder().writeOp(Op::I32Or)) return false; break;
+ case PNK_BITAND: if (!f.encoder().writeOp(Op::I32And)) return false; break;
+ case PNK_BITXOR: if (!f.encoder().writeOp(Op::I32Xor)) return false; break;
+ case PNK_LSH: if (!f.encoder().writeOp(Op::I32Shl)) return false; break;
+ case PNK_RSH: if (!f.encoder().writeOp(Op::I32ShrS)) return false; break;
+ case PNK_URSH: if (!f.encoder().writeOp(Op::I32ShrU)) return false; break;
default: MOZ_CRASH("not a bitwise op");
}
return true;
}
static bool
CheckExpr(FunctionValidator& f, ParseNode* expr, Type* type)
@@ -6421,17 +6421,17 @@ CheckAsExprStatement(FunctionValidator&
return CheckCoercedCall(f, expr, Type::Void, &ignored);
}
Type resultType;
if (!CheckExpr(f, expr, &resultType))
return false;
if (!resultType.isVoid()) {
- if (!f.encoder().writeExpr(Expr::Drop))
+ if (!f.encoder().writeOp(Op::Drop))
return false;
}
return true;
}
static bool
CheckExprStatement(FunctionValidator& f, ParseNode* exprStmt)
@@ -6455,17 +6455,17 @@ CheckLoopConditionOnEntry(FunctionValida
return false;
if (!condType.isInt())
return f.failf(cond, "%s is not a subtype of int", condType.toChars());
// TODO change this to i32.eqz
// i32.eq 0 $f
if (!f.writeInt32Lit(0))
return false;
- if (!f.encoder().writeExpr(Expr::I32Eq))
+ if (!f.encoder().writeOp(Op::I32Eq))
return false;
// brIf (i32.eq 0 $f) $out
if (!f.writeBreakIf())
return false;
return true;
}
@@ -6828,17 +6828,17 @@ CheckSwitch(FunctionValidator& f, ParseN
return f.fail(switchBody, "switch body may not contain lexical declarations");
switchBody = switchBody->scopeBody();
}
ParseNode* stmt = ListHead(switchBody);
if (!stmt) {
if (!CheckSwitchExpr(f, switchExpr))
return false;
- if (!f.encoder().writeExpr(Expr::Drop))
+ if (!f.encoder().writeOp(Op::Drop))
return false;
return true;
}
if (!CheckDefaultAtEnd(f, stmt))
return false;
int32_t low = 0, high = 0;
@@ -6883,25 +6883,25 @@ CheckSwitch(FunctionValidator& f, ParseN
uint32_t defaultDepth = numCases;
// Subtract lowest case value, so that all the cases start from 0.
if (low) {
if (!CheckSwitchExpr(f, switchExpr))
return false;
if (!f.writeInt32Lit(low))
return false;
- if (!f.encoder().writeExpr(Expr::I32Sub))
+ if (!f.encoder().writeOp(Op::I32Sub))
return false;
} else {
if (!CheckSwitchExpr(f, switchExpr))
return false;
}
// Start the br_table block.
- if (!f.encoder().writeExpr(Expr::BrTable))
+ if (!f.encoder().writeOp(Op::BrTable))
return false;
// Write the number of cases (tableLength - 1 + 1 (default)).
// Write the number of cases (tableLength - 1 + 1 (default)).
if (!f.encoder().writeVarU32(tableLength))
return false;
// Each case value describes the relative depth to the actual block. When
@@ -6970,17 +6970,17 @@ CheckReturn(FunctionValidator& f, ParseN
if (!type.isReturnType())
return f.failf(expr, "%s is not a valid return type", type.toChars());
if (!CheckReturnType(f, expr, Type::canonicalize(type)))
return false;
}
- if (!f.encoder().writeExpr(Expr::Return))
+ if (!f.encoder().writeOp(Op::Return))
return false;
return true;
}
static bool
CheckStatementList(FunctionValidator& f, ParseNode* stmtList, const NameVector* labels /*= nullptr */)
{
--- a/js/src/wasm/WasmAST.h
+++ b/js/src/wasm/WasmAST.h
@@ -369,71 +369,71 @@ class AstTeeLocal : public AstExpr
}
AstExpr& value() const {
return value_;
}
};
class AstBlock : public AstExpr
{
- Expr expr_;
+ Op op_;
AstName name_;
AstExprVector exprs_;
public:
static const AstExprKind Kind = AstExprKind::Block;
- explicit AstBlock(Expr expr, ExprType type, AstName name, AstExprVector&& exprs)
+ explicit AstBlock(Op op, ExprType type, AstName name, AstExprVector&& exprs)
: AstExpr(Kind, type),
- expr_(expr),
+ op_(op),
name_(name),
exprs_(Move(exprs))
{}
- Expr expr() const { return expr_; }
+ Op op() const { return op_; }
AstName name() const { return name_; }
const AstExprVector& exprs() const { return exprs_; }
};
class AstBranch : public AstExpr
{
- Expr expr_;
+ Op op_;
AstExpr* cond_;
AstRef target_;
AstExpr* value_;
public:
static const AstExprKind Kind = AstExprKind::Branch;
- explicit AstBranch(Expr expr, ExprType type,
+ explicit AstBranch(Op op, ExprType type,
AstExpr* cond, AstRef target, AstExpr* value)
: AstExpr(Kind, type),
- expr_(expr),
+ op_(op),
cond_(cond),
target_(target),
value_(value)
{}
- Expr expr() const { return expr_; }
+ Op op() const { return op_; }
AstRef& target() { return target_; }
AstExpr& cond() const { MOZ_ASSERT(cond_); return *cond_; }
AstExpr* maybeValue() const { return value_; }
};
class AstCall : public AstExpr
{
- Expr expr_;
+ Op op_;
AstRef func_;
AstExprVector args_;
public:
static const AstExprKind Kind = AstExprKind::Call;
- AstCall(Expr expr, ExprType type, AstRef func, AstExprVector&& args)
- : AstExpr(Kind, type), expr_(expr), func_(func), args_(Move(args))
+ AstCall(Op op, ExprType type, AstRef func, AstExprVector&& args)
+ : AstExpr(Kind, type), op_(op), func_(func), args_(Move(args))
{}
- Expr expr() const { return expr_; }
+ Op op() const { return op_; }
AstRef& func() { return func_; }
const AstExprVector& args() const { return args_; }
};
class AstCallIndirect : public AstExpr
{
AstRef sig_;
AstExprVector args_;
@@ -502,72 +502,71 @@ class AstLoadStoreAddress
AstExpr& base() const { return *base_; }
int32_t flags() const { return flags_; }
int32_t offset() const { return offset_; }
};
class AstLoad : public AstExpr
{
- Expr expr_;
+ Op op_;
AstLoadStoreAddress address_;
public:
static const AstExprKind Kind = AstExprKind::Load;
- explicit AstLoad(Expr expr, const AstLoadStoreAddress &address)
+ explicit AstLoad(Op op, const AstLoadStoreAddress &address)
: AstExpr(Kind, ExprType::Limit),
- expr_(expr),
+ op_(op),
address_(address)
{}
- Expr expr() const { return expr_; }
+ Op op() const { return op_; }
const AstLoadStoreAddress& address() const { return address_; }
};
class AstStore : public AstExpr
{
- Expr expr_;
+ Op op_;
AstLoadStoreAddress address_;
AstExpr* value_;
public:
static const AstExprKind Kind = AstExprKind::Store;
- explicit AstStore(Expr expr, const AstLoadStoreAddress &address,
- AstExpr* value)
+ explicit AstStore(Op op, const AstLoadStoreAddress &address, AstExpr* value)
: AstExpr(Kind, ExprType::Void),
- expr_(expr),
+ op_(op),
address_(address),
value_(value)
{}
- Expr expr() const { return expr_; }
+ Op op() const { return op_; }
const AstLoadStoreAddress& address() const { return address_; }
AstExpr& value() const { return *value_; }
};
class AstCurrentMemory final : public AstExpr
{
public:
static const AstExprKind Kind = AstExprKind::CurrentMemory;
explicit AstCurrentMemory()
: AstExpr(Kind, ExprType::I32)
{}
};
class AstGrowMemory final : public AstExpr
{
- AstExpr* op_;
+ AstExpr* operand_;
public:
static const AstExprKind Kind = AstExprKind::GrowMemory;
- explicit AstGrowMemory(AstExpr* op)
- : AstExpr(Kind, ExprType::I32), op_(op)
+ explicit AstGrowMemory(AstExpr* operand)
+ : AstExpr(Kind, ExprType::I32), operand_(operand)
{}
- AstExpr* op() const { return op_; }
+ AstExpr* operand() const { return operand_; }
};
class AstBranchTable : public AstExpr
{
AstExpr& index_;
AstRef default_;
AstRefVector table_;
AstExpr* value_;
@@ -912,100 +911,100 @@ class AstModule : public AstNode
}
const AstGlobalVector& globals() const {
return globals_;
}
};
class AstUnaryOperator final : public AstExpr
{
- Expr expr_;
- AstExpr* op_;
+ Op op_;
+ AstExpr* operand_;
public:
static const AstExprKind Kind = AstExprKind::UnaryOperator;
- explicit AstUnaryOperator(Expr expr, AstExpr* op)
+ explicit AstUnaryOperator(Op op, AstExpr* operand)
: AstExpr(Kind, ExprType::Limit),
- expr_(expr), op_(op)
+ op_(op), operand_(operand)
{}
- Expr expr() const { return expr_; }
- AstExpr* op() const { return op_; }
+ Op op() const { return op_; }
+ AstExpr* operand() const { return operand_; }
};
class AstBinaryOperator final : public AstExpr
{
- Expr expr_;
+ Op op_;
AstExpr* lhs_;
AstExpr* rhs_;
public:
static const AstExprKind Kind = AstExprKind::BinaryOperator;
- explicit AstBinaryOperator(Expr expr, AstExpr* lhs, AstExpr* rhs)
+ explicit AstBinaryOperator(Op op, AstExpr* lhs, AstExpr* rhs)
: AstExpr(Kind, ExprType::Limit),
- expr_(expr), lhs_(lhs), rhs_(rhs)
+ op_(op), lhs_(lhs), rhs_(rhs)
{}
- Expr expr() const { return expr_; }
+ Op op() const { return op_; }
AstExpr* lhs() const { return lhs_; }
AstExpr* rhs() const { return rhs_; }
};
class AstTernaryOperator : public AstExpr
{
- Expr expr_;
+ Op op_;
AstExpr* op0_;
AstExpr* op1_;
AstExpr* op2_;
public:
static const AstExprKind Kind = AstExprKind::TernaryOperator;
- AstTernaryOperator(Expr expr, AstExpr* op0, AstExpr* op1, AstExpr* op2)
+ AstTernaryOperator(Op op, AstExpr* op0, AstExpr* op1, AstExpr* op2)
: AstExpr(Kind, ExprType::Limit),
- expr_(expr), op0_(op0), op1_(op1), op2_(op2)
+ op_(op), op0_(op0), op1_(op1), op2_(op2)
{}
- Expr expr() const { return expr_; }
+ Op op() const { return op_; }
AstExpr* op0() const { return op0_; }
AstExpr* op1() const { return op1_; }
AstExpr* op2() const { return op2_; }
};
class AstComparisonOperator final : public AstExpr
{
- Expr expr_;
+ Op op_;
AstExpr* lhs_;
AstExpr* rhs_;
public:
static const AstExprKind Kind = AstExprKind::ComparisonOperator;
- explicit AstComparisonOperator(Expr expr, AstExpr* lhs, AstExpr* rhs)
+ explicit AstComparisonOperator(Op op, AstExpr* lhs, AstExpr* rhs)
: AstExpr(Kind, ExprType::Limit),
- expr_(expr), lhs_(lhs), rhs_(rhs)
+ op_(op), lhs_(lhs), rhs_(rhs)
{}
- Expr expr() const { return expr_; }
+ Op op() const { return op_; }
AstExpr* lhs() const { return lhs_; }
AstExpr* rhs() const { return rhs_; }
};
class AstConversionOperator final : public AstExpr
{
- Expr expr_;
- AstExpr* op_;
+ Op op_;
+ AstExpr* operand_;
public:
static const AstExprKind Kind = AstExprKind::ConversionOperator;
- explicit AstConversionOperator(Expr expr, AstExpr* op)
+ explicit AstConversionOperator(Op op, AstExpr* operand)
: AstExpr(Kind, ExprType::Limit),
- expr_(expr), op_(op)
+ op_(op), operand_(operand)
{}
- Expr expr() const { return expr_; }
- AstExpr* op() const { return op_; }
+ Op op() const { return op_; }
+ AstExpr* operand() const { return operand_; }
};
// This is an artificial AST node which can fill operand slots in an AST
// constructed from parsing or decoding stack-machine code that doesn't have
// an inherent AST structure.
class AstPop final : public AstExpr
{
public:
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -54,17 +54,17 @@
* this reduces register pressure and instruction count.
*
* - (Bug 1286816) Opportunities for cheaply folding in a constant rhs to
* conditionals.
*
* - (Bug 1286816) Boolean evaluation for control can be optimized by pushing a
* bool-generating operation onto the value stack in the same way that we now
* push latent constants and local lookups, or (easier) by remembering the
- * operation in a side location if the next Expr will consume it.
+ * operation in a side location if the next Op will consume it.
*
* - (Bug 1286816) brIf pessimizes by branching over code that performs stack
* cleanup and a branch. If no cleanup is needed we can just branch
* conditionally to the target.
*
* - (Bug 1316804) brTable pessimizes by always dispatching to code that pops
* the stack and then jumps to the code for the target case. If no cleanup is
* needed we could just branch conditionally to the target; if the same amount
@@ -128,33 +128,33 @@ using mozilla::IsPowerOfTwo;
using mozilla::SpecificNaN;
namespace js {
namespace wasm {
using namespace js::jit;
using JS::GenericNaN;
-struct BaseCompilePolicy : ExprIterPolicy
+struct BaseCompilePolicy : OpIterPolicy
{
static const bool Output = true;
// The baseline compiler tracks values on a stack of its own -- it
// needs to scan that stack for spilling -- and thus has no need
// for the values maintained by the iterator.
//
// The baseline compiler tracks control items on a stack of its
// own as well.
//
// TODO / REDUNDANT (Bug 1316814): It would be nice if we could
// make use of the iterator's ControlItems and not require our own
// stack for that.
};
-typedef ExprIter<BaseCompilePolicy> BaseExprIter;
+typedef OpIter<BaseCompilePolicy> BaseOpIter;
typedef bool IsUnsigned;
typedef bool IsSigned;
typedef bool ZeroOnOverflow;
typedef bool IsKnownNotZero;
typedef bool HandleNaNSpecially;
typedef unsigned ByteSize;
typedef unsigned BitSize;
@@ -501,17 +501,17 @@ class BaseCompiler
//
// All other registers must be explicitly saved and restored
// by the OOL code before being used.
virtual void generate(MacroAssembler& masm) = 0;
};
const ModuleGeneratorData& mg_;
- BaseExprIter iter_;
+ BaseOpIter iter_;
const FuncBytes& func_;
size_t lastReadCallSite_;
TempAllocator& alloc_;
const ValTypeVector& locals_; // Types of parameters and locals
int32_t localSize_; // Size of local area in bytes (stable after beginFunction)
int32_t varLow_; // Low byte offset of local area for true locals (not parameters)
int32_t varHigh_; // High byte offset + 1 of local area for true locals
int32_t maxFramePushed_; // Max value of masm.framePushed() observed
@@ -6579,540 +6579,540 @@ BaseCompiler::emitBody()
CHECK(stk_.reserve(stk_.length() + overhead * 2));
}
overhead--;
if (done())
return true;
- Expr expr;
- CHECK(iter_.readExpr(&expr));
-
- switch (expr) {
+ uint16_t op;
+ CHECK(iter_.readOp(&op));
+
+ switch (op) {
// Control opcodes
- case Expr::Nop:
+ case uint16_t(Op::Nop):
CHECK(iter_.readNop());
NEXT();
- case Expr::Drop:
+ case uint16_t(Op::Drop):
CHECK_NEXT(emitDrop());
- case Expr::Block:
+ case uint16_t(Op::Block):
CHECK_NEXT(emitBlock());
- case Expr::Loop:
+ case uint16_t(Op::Loop):
CHECK_NEXT(emitLoop());
- case Expr::If:
+ case uint16_t(Op::If):
CHECK_NEXT(emitIf());
- case Expr::Else:
+ case uint16_t(Op::Else):
CHECK_NEXT(emitElse());
- case Expr::End:
+ case uint16_t(Op::End):
CHECK_NEXT(emitEnd());
- case Expr::Br:
+ case uint16_t(Op::Br):
CHECK_NEXT(emitBr());
- case Expr::BrIf:
+ case uint16_t(Op::BrIf):
CHECK_NEXT(emitBrIf());
- case Expr::BrTable:
+ case uint16_t(Op::BrTable):
CHECK_NEXT(emitBrTable());
- case Expr::Return:
+ case uint16_t(Op::Return):
CHECK_NEXT(emitReturn());
- case Expr::Unreachable:
+ case uint16_t(Op::Unreachable):
CHECK(iter_.readUnreachable());
if (!deadCode_) {
unreachableTrap();
deadCode_ = true;
popValueStackTo(ctl_.back().stackSize);
}
NEXT();
// Calls
- case Expr::Call:
+ case uint16_t(Op::Call):
CHECK_NEXT(emitCall());
- case Expr::CallIndirect:
+ case uint16_t(Op::CallIndirect):
CHECK_NEXT(emitCallIndirect(/* oldStyle = */ false));
- case Expr::OldCallIndirect:
+ case uint16_t(Op::OldCallIndirect):
CHECK_NEXT(emitCallIndirect(/* oldStyle = */ true));
// Locals and globals
- case Expr::GetLocal:
+ case uint16_t(Op::GetLocal):
CHECK_NEXT(emitGetLocal());
- case Expr::SetLocal:
+ case uint16_t(Op::SetLocal):
CHECK_NEXT(emitSetLocal());
- case Expr::TeeLocal:
+ case uint16_t(Op::TeeLocal):
CHECK_NEXT(emitTeeLocal());
- case Expr::GetGlobal:
+ case uint16_t(Op::GetGlobal):
CHECK_NEXT(emitGetGlobal());
- case Expr::SetGlobal:
+ case uint16_t(Op::SetGlobal):
CHECK_NEXT(emitSetGlobal());
- case Expr::TeeGlobal:
+ case uint16_t(Op::TeeGlobal):
CHECK_NEXT(emitTeeGlobal());
// Select
- case Expr::Select:
+ case uint16_t(Op::Select):
CHECK_NEXT(emitSelect());
// I32
- case Expr::I32Const: {
+ case uint16_t(Op::I32Const): {
int32_t i32;
CHECK(iter_.readI32Const(&i32));
if (!deadCode_)
pushI32(i32);
NEXT();
}
- case Expr::I32Add:
+ case uint16_t(Op::I32Add):
CHECK_NEXT(emitBinary(emitAddI32, ValType::I32));
- case Expr::I32Sub:
+ case uint16_t(Op::I32Sub):
CHECK_NEXT(emitBinary(emitSubtractI32, ValType::I32));
- case Expr::I32Mul:
+ case uint16_t(Op::I32Mul):
CHECK_NEXT(emitBinary(emitMultiplyI32, ValType::I32));
- case Expr::I32DivS:
+ case uint16_t(Op::I32DivS):
CHECK_NEXT(emitBinary(emitQuotientI32, ValType::I32));
- case Expr::I32DivU:
+ case uint16_t(Op::I32DivU):
CHECK_NEXT(emitBinary(emitQuotientU32, ValType::I32));
- case Expr::I32RemS:
+ case uint16_t(Op::I32RemS):
CHECK_NEXT(emitBinary(emitRemainderI32, ValType::I32));
- case Expr::I32RemU:
+ case uint16_t(Op::I32RemU):
CHECK_NEXT(emitBinary(emitRemainderU32, ValType::I32));
- case Expr::I32Min:
+ case uint16_t(Op::I32Min):
CHECK_NEXT(emitBinary(emitMinI32, ValType::I32));
- case Expr::I32Max:
+ case uint16_t(Op::I32Max):
CHECK_NEXT(emitBinary(emitMaxI32, ValType::I32));
- case Expr::I32Eqz:
+ case uint16_t(Op::I32Eqz):
CHECK_NEXT(emitConversion(emitEqzI32, ValType::I32, ValType::I32));
- case Expr::I32TruncSF32:
+ case uint16_t(Op::I32TruncSF32):
CHECK_NEXT(emitConversionOOM(emitTruncateF32ToI32<false>, ValType::F32, ValType::I32));
- case Expr::I32TruncUF32:
+ case uint16_t(Op::I32TruncUF32):
CHECK_NEXT(emitConversionOOM(emitTruncateF32ToI32<true>, ValType::F32, ValType::I32));
- case Expr::I32TruncSF64:
+ case uint16_t(Op::I32TruncSF64):
CHECK_NEXT(emitConversionOOM(emitTruncateF64ToI32<false>, ValType::F64, ValType::I32));
- case Expr::I32TruncUF64:
+ case uint16_t(Op::I32TruncUF64):
CHECK_NEXT(emitConversionOOM(emitTruncateF64ToI32<true>, ValType::F64, ValType::I32));
- case Expr::I32WrapI64:
+ case uint16_t(Op::I32WrapI64):
CHECK_NEXT(emitConversion(emitWrapI64ToI32, ValType::I64, ValType::I32));
- case Expr::I32ReinterpretF32:
+ case uint16_t(Op::I32ReinterpretF32):
CHECK_NEXT(emitConversion(emitReinterpretF32AsI32, ValType::F32, ValType::I32));
- case Expr::I32Clz:
+ case uint16_t(Op::I32Clz):
CHECK_NEXT(emitUnary(emitClzI32, ValType::I32));
- case Expr::I32Ctz:
+ case uint16_t(Op::I32Ctz):
CHECK_NEXT(emitUnary(emitCtzI32, ValType::I32));
- case Expr::I32Popcnt:
+ case uint16_t(Op::I32Popcnt):
CHECK_NEXT(emitUnary(emitPopcntI32, ValType::I32));
- case Expr::I32Abs:
+ case uint16_t(Op::I32Abs):
CHECK_NEXT(emitUnary(emitAbsI32, ValType::I32));
- case Expr::I32Neg:
+ case uint16_t(Op::I32Neg):
CHECK_NEXT(emitUnary(emitNegateI32, ValType::I32));
- case Expr::I32Or:
+ case uint16_t(Op::I32Or):
CHECK_NEXT(emitBinary(emitOrI32, ValType::I32));
- case Expr::I32And:
+ case uint16_t(Op::I32And):
CHECK_NEXT(emitBinary(emitAndI32, ValType::I32));
- case Expr::I32Xor:
+ case uint16_t(Op::I32Xor):
CHECK_NEXT(emitBinary(emitXorI32, ValType::I32));
- case Expr::I32Shl:
+ case uint16_t(Op::I32Shl):
CHECK_NEXT(emitBinary(emitShlI32, ValType::I32));
- case Expr::I32ShrS:
+ case uint16_t(Op::I32ShrS):
CHECK_NEXT(emitBinary(emitShrI32, ValType::I32));
- case Expr::I32ShrU:
+ case uint16_t(Op::I32ShrU):
CHECK_NEXT(emitBinary(emitShrU32, ValType::I32));
- case Expr::I32BitNot:
+ case uint16_t(Op::I32BitNot):
CHECK_NEXT(emitUnary(emitBitNotI32, ValType::I32));
- case Expr::I32Load8S:
+ case uint16_t(Op::I32Load8S):
CHECK_NEXT(emitLoad(ValType::I32, Scalar::Int8));
- case Expr::I32Load8U:
+ case uint16_t(Op::I32Load8U):
CHECK_NEXT(emitLoad(ValType::I32, Scalar::Uint8));
- case Expr::I32Load16S:
+ case uint16_t(Op::I32Load16S):
CHECK_NEXT(emitLoad(ValType::I32, Scalar::Int16));
- case Expr::I32Load16U:
+ case uint16_t(Op::I32Load16U):
CHECK_NEXT(emitLoad(ValType::I32, Scalar::Uint16));
- case Expr::I32Load:
+ case uint16_t(Op::I32Load):
CHECK_NEXT(emitLoad(ValType::I32, Scalar::Int32));
- case Expr::I32Store8:
+ case uint16_t(Op::I32Store8):
CHECK_NEXT(emitStore(ValType::I32, Scalar::Int8));
- case Expr::I32TeeStore8:
+ case uint16_t(Op::I32TeeStore8):
CHECK_NEXT(emitTeeStore(ValType::I32, Scalar::Int8));
- case Expr::I32Store16:
+ case uint16_t(Op::I32Store16):
CHECK_NEXT(emitStore(ValType::I32, Scalar::Int16));
- case Expr::I32TeeStore16:
+ case uint16_t(Op::I32TeeStore16):
CHECK_NEXT(emitTeeStore(ValType::I32, Scalar::Int16));
- case Expr::I32Store:
+ case uint16_t(Op::I32Store):
CHECK_NEXT(emitStore(ValType::I32, Scalar::Int32));
- case Expr::I32TeeStore:
+ case uint16_t(Op::I32TeeStore):
CHECK_NEXT(emitTeeStore(ValType::I32, Scalar::Int32));
- case Expr::I32Rotr:
+ case uint16_t(Op::I32Rotr):
CHECK_NEXT(emitBinary(emitRotrI32, ValType::I32));
- case Expr::I32Rotl:
+ case uint16_t(Op::I32Rotl):
CHECK_NEXT(emitBinary(emitRotlI32, ValType::I32));
// I64
- case Expr::I64Const: {
+ case uint16_t(Op::I64Const): {
int64_t i64;
CHECK(iter_.readI64Const(&i64));
if (!deadCode_)
pushI64(i64);
NEXT();
}
- case Expr::I64Add:
+ case uint16_t(Op::I64Add):
CHECK_NEXT(emitBinary(emitAddI64, ValType::I64));
- case Expr::I64Sub:
+ case uint16_t(Op::I64Sub):
CHECK_NEXT(emitBinary(emitSubtractI64, ValType::I64));
- case Expr::I64Mul:
+ case uint16_t(Op::I64Mul):
CHECK_NEXT(emitBinary(emitMultiplyI64, ValType::I64));
- case Expr::I64DivS:
+ case uint16_t(Op::I64DivS):
#ifdef INT_DIV_I64_CALLOUT
CHECK_NEXT(emitDivOrModI64BuiltinCall(SymbolicAddress::DivI64, ValType::I64));
#else
CHECK_NEXT(emitBinary(emitQuotientI64, ValType::I64));
#endif
- case Expr::I64DivU:
+ case uint16_t(Op::I64DivU):
#ifdef INT_DIV_I64_CALLOUT
CHECK_NEXT(emitDivOrModI64BuiltinCall(SymbolicAddress::UDivI64, ValType::I64));
#else
CHECK_NEXT(emitBinary(emitQuotientU64, ValType::I64));
#endif
- case Expr::I64RemS:
+ case uint16_t(Op::I64RemS):
#ifdef INT_DIV_I64_CALLOUT
CHECK_NEXT(emitDivOrModI64BuiltinCall(SymbolicAddress::ModI64, ValType::I64));
#else
CHECK_NEXT(emitBinary(emitRemainderI64, ValType::I64));
#endif
- case Expr::I64RemU:
+ case uint16_t(Op::I64RemU):
#ifdef INT_DIV_I64_CALLOUT
CHECK_NEXT(emitDivOrModI64BuiltinCall(SymbolicAddress::UModI64, ValType::I64));
#else
CHECK_NEXT(emitBinary(emitRemainderU64, ValType::I64));
#endif
- case Expr::I64TruncSF32:
+ case uint16_t(Op::I64TruncSF32):
#ifdef FLOAT_TO_I64_CALLOUT
CHECK_NEXT(emitCalloutConversionOOM(emitConvertFloatingToInt64Callout,
SymbolicAddress::TruncateDoubleToInt64,
ValType::F32, ValType::I64));
#else
CHECK_NEXT(emitConversionOOM(emitTruncateF32ToI64<false>, ValType::F32, ValType::I64));
#endif
- case Expr::I64TruncUF32:
+ case uint16_t(Op::I64TruncUF32):
#ifdef FLOAT_TO_I64_CALLOUT
CHECK_NEXT(emitCalloutConversionOOM(emitConvertFloatingToInt64Callout,
SymbolicAddress::TruncateDoubleToUint64,
ValType::F32, ValType::I64));
#else
CHECK_NEXT(emitConversionOOM(emitTruncateF32ToI64<true>, ValType::F32, ValType::I64));
#endif
- case Expr::I64TruncSF64:
+ case uint16_t(Op::I64TruncSF64):
#ifdef FLOAT_TO_I64_CALLOUT
CHECK_NEXT(emitCalloutConversionOOM(emitConvertFloatingToInt64Callout,
SymbolicAddress::TruncateDoubleToInt64,
ValType::F64, ValType::I64));
#else
CHECK_NEXT(emitConversionOOM(emitTruncateF64ToI64<false>, ValType::F64, ValType::I64));
#endif
- case Expr::I64TruncUF64:
+ case uint16_t(Op::I64TruncUF64):
#ifdef FLOAT_TO_I64_CALLOUT
CHECK_NEXT(emitCalloutConversionOOM(emitConvertFloatingToInt64Callout,
SymbolicAddress::TruncateDoubleToUint64,
ValType::F64, ValType::I64));
#else
CHECK_NEXT(emitConversionOOM(emitTruncateF64ToI64<true>, ValType::F64, ValType::I64));
#endif
- case Expr::I64ExtendSI32:
+ case uint16_t(Op::I64ExtendSI32):
CHECK_NEXT(emitConversion(emitExtendI32ToI64, ValType::I32, ValType::I64));
- case Expr::I64ExtendUI32:
+ case uint16_t(Op::I64ExtendUI32):
CHECK_NEXT(emitConversion(emitExtendU32ToI64, ValType::I32, ValType::I64));
- case Expr::I64ReinterpretF64:
+ case uint16_t(Op::I64ReinterpretF64):
CHECK_NEXT(emitConversion(emitReinterpretF64AsI64, ValType::F64, ValType::I64));
- case Expr::I64Or:
+ case uint16_t(Op::I64Or):
CHECK_NEXT(emitBinary(emitOrI64, ValType::I64));
- case Expr::I64And:
+ case uint16_t(Op::I64And):
CHECK_NEXT(emitBinary(emitAndI64, ValType::I64));
- case Expr::I64Xor:
+ case uint16_t(Op::I64Xor):
CHECK_NEXT(emitBinary(emitXorI64, ValType::I64));
- case Expr::I64Shl:
+ case uint16_t(Op::I64Shl):
CHECK_NEXT(emitBinary(emitShlI64, ValType::I64));
- case Expr::I64ShrS:
+ case uint16_t(Op::I64ShrS):
CHECK_NEXT(emitBinary(emitShrI64, ValType::I64));
- case Expr::I64ShrU:
+ case uint16_t(Op::I64ShrU):
CHECK_NEXT(emitBinary(emitShrU64, ValType::I64));
- case Expr::I64Rotr:
+ case uint16_t(Op::I64Rotr):
CHECK_NEXT(emitBinary(emitRotrI64, ValType::I64));
- case Expr::I64Rotl:
+ case uint16_t(Op::I64Rotl):
CHECK_NEXT(emitBinary(emitRotlI64, ValType::I64));
- case Expr::I64Clz:
+ case uint16_t(Op::I64Clz):
CHECK_NEXT(emitUnary(emitClzI64, ValType::I64));
- case Expr::I64Ctz:
+ case uint16_t(Op::I64Ctz):
CHECK_NEXT(emitUnary(emitCtzI64, ValType::I64));
- case Expr::I64Popcnt:
+ case uint16_t(Op::I64Popcnt):
CHECK_NEXT(emitUnary(emitPopcntI64, ValType::I64));
- case Expr::I64Eqz:
+ case uint16_t(Op::I64Eqz):
CHECK_NEXT(emitConversion(emitEqzI64, ValType::I64, ValType::I32));
- case Expr::I64Load8S:
+ case uint16_t(Op::I64Load8S):
CHECK_NEXT(emitLoad(ValType::I64, Scalar::Int8));
- case Expr::I64Load16S:
+ case uint16_t(Op::I64Load16S):
CHECK_NEXT(emitLoad(ValType::I64, Scalar::Int16));
- case Expr::I64Load32S:
+ case uint16_t(Op::I64Load32S):
CHECK_NEXT(emitLoad(ValType::I64, Scalar::Int32));
- case Expr::I64Load8U:
+ case uint16_t(Op::I64Load8U):
CHECK_NEXT(emitLoad(ValType::I64, Scalar::Uint8));
- case Expr::I64Load16U:
+ case uint16_t(Op::I64Load16U):
CHECK_NEXT(emitLoad(ValType::I64, Scalar::Uint16));
- case Expr::I64Load32U:
+ case uint16_t(Op::I64Load32U):
CHECK_NEXT(emitLoad(ValType::I64, Scalar::Uint32));
- case Expr::I64Load:
+ case uint16_t(Op::I64Load):
CHECK_NEXT(emitLoad(ValType::I64, Scalar::Int64));
- case Expr::I64Store8:
+ case uint16_t(Op::I64Store8):
CHECK_NEXT(emitStore(ValType::I64, Scalar::Int8));
- case Expr::I64TeeStore8:
+ case uint16_t(Op::I64TeeStore8):
CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int8));
- case Expr::I64Store16:
+ case uint16_t(Op::I64Store16):
CHECK_NEXT(emitStore(ValType::I64, Scalar::Int16));
- case Expr::I64TeeStore16:
+ case uint16_t(Op::I64TeeStore16):
CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int16));
- case Expr::I64Store32:
+ case uint16_t(Op::I64Store32):
CHECK_NEXT(emitStore(ValType::I64, Scalar::Int32));
- case Expr::I64TeeStore32:
+ case uint16_t(Op::I64TeeStore32):
CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int32));
- case Expr::I64Store:
+ case uint16_t(Op::I64Store):
CHECK_NEXT(emitStore(ValType::I64, Scalar::Int64));
- case Expr::I64TeeStore:
+ case uint16_t(Op::I64TeeStore):
CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int64));
// F32
- case Expr::F32Const: {
+ case uint16_t(Op::F32Const): {
RawF32 f32;
CHECK(iter_.readF32Const(&f32));
if (!deadCode_)
pushF32(f32);
NEXT();
}
- case Expr::F32Add:
+ case uint16_t(Op::F32Add):
CHECK_NEXT(emitBinary(emitAddF32, ValType::F32));
- case Expr::F32Sub:
+ case uint16_t(Op::F32Sub):
CHECK_NEXT(emitBinary(emitSubtractF32, ValType::F32));
- case Expr::F32Mul:
+ case uint16_t(Op::F32Mul):
CHECK_NEXT(emitBinary(emitMultiplyF32, ValType::F32));
- case Expr::F32Div:
+ case uint16_t(Op::F32Div):
CHECK_NEXT(emitBinary(emitDivideF32, ValType::F32));
- case Expr::F32Min:
+ case uint16_t(Op::F32Min):
CHECK_NEXT(emitBinary(emitMinF32, ValType::F32));
- case Expr::F32Max:
+ case uint16_t(Op::F32Max):
CHECK_NEXT(emitBinary(emitMaxF32, ValType::F32));
- case Expr::F32Neg:
+ case uint16_t(Op::F32Neg):
CHECK_NEXT(emitUnary(emitNegateF32, ValType::F32));
- case Expr::F32Abs:
+ case uint16_t(Op::F32Abs):
CHECK_NEXT(emitUnary(emitAbsF32, ValType::F32));
- case Expr::F32Sqrt:
+ case uint16_t(Op::F32Sqrt):
CHECK_NEXT(emitUnary(emitSqrtF32, ValType::F32));
- case Expr::F32Ceil:
+ case uint16_t(Op::F32Ceil):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::CeilF, ValType::F32));
- case Expr::F32Floor:
+ case uint16_t(Op::F32Floor):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::FloorF, ValType::F32));
- case Expr::F32DemoteF64:
+ case uint16_t(Op::F32DemoteF64):
CHECK_NEXT(emitConversion(emitConvertF64ToF32, ValType::F64, ValType::F32));
- case Expr::F32ConvertSI32:
+ case uint16_t(Op::F32ConvertSI32):
CHECK_NEXT(emitConversion(emitConvertI32ToF32, ValType::I32, ValType::F32));
- case Expr::F32ConvertUI32:
+ case uint16_t(Op::F32ConvertUI32):
CHECK_NEXT(emitConversion(emitConvertU32ToF32, ValType::I32, ValType::F32));
- case Expr::F32ConvertSI64:
+ case uint16_t(Op::F32ConvertSI64):
#ifdef I64_TO_FLOAT_CALLOUT
CHECK_NEXT(emitCalloutConversionOOM(emitConvertInt64ToFloatingCallout,
SymbolicAddress::Int64ToFloatingPoint,
ValType::I64, ValType::F32));
#else
CHECK_NEXT(emitConversion(emitConvertI64ToF32, ValType::I64, ValType::F32));
#endif
- case Expr::F32ConvertUI64:
+ case uint16_t(Op::F32ConvertUI64):
#ifdef I64_TO_FLOAT_CALLOUT
CHECK_NEXT(emitCalloutConversionOOM(emitConvertInt64ToFloatingCallout,
SymbolicAddress::Uint64ToFloatingPoint,
ValType::I64, ValType::F32));
#else
CHECK_NEXT(emitConversion(emitConvertU64ToF32, ValType::I64, ValType::F32));
#endif
- case Expr::F32ReinterpretI32:
+ case uint16_t(Op::F32ReinterpretI32):
CHECK_NEXT(emitConversion(emitReinterpretI32AsF32, ValType::I32, ValType::F32));
- case Expr::F32Load:
+ case uint16_t(Op::F32Load):
CHECK_NEXT(emitLoad(ValType::F32, Scalar::Float32));
- case Expr::F32Store:
+ case uint16_t(Op::F32Store):
CHECK_NEXT(emitStore(ValType::F32, Scalar::Float32));
- case Expr::F32TeeStore:
+ case uint16_t(Op::F32TeeStore):
CHECK_NEXT(emitTeeStore(ValType::F32, Scalar::Float32));
- case Expr::F32TeeStoreF64:
+ case uint16_t(Op::F32TeeStoreF64):
CHECK_NEXT(emitTeeStoreWithCoercion(ValType::F32, Scalar::Float64));
- case Expr::F32CopySign:
+ case uint16_t(Op::F32CopySign):
CHECK_NEXT(emitBinary(emitCopysignF32, ValType::F32));
- case Expr::F32Nearest:
+ case uint16_t(Op::F32Nearest):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::NearbyIntF, ValType::F32));
- case Expr::F32Trunc:
+ case uint16_t(Op::F32Trunc):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::TruncF, ValType::F32));
// F64
- case Expr::F64Const: {
+ case uint16_t(Op::F64Const): {
RawF64 f64;
CHECK(iter_.readF64Const(&f64));
if (!deadCode_)
pushF64(f64);
NEXT();
}
- case Expr::F64Add:
+ case uint16_t(Op::F64Add):
CHECK_NEXT(emitBinary(emitAddF64, ValType::F64));
- case Expr::F64Sub:
+ case uint16_t(Op::F64Sub):
CHECK_NEXT(emitBinary(emitSubtractF64, ValType::F64));
- case Expr::F64Mul:
+ case uint16_t(Op::F64Mul):
CHECK_NEXT(emitBinary(emitMultiplyF64, ValType::F64));
- case Expr::F64Div:
+ case uint16_t(Op::F64Div):
CHECK_NEXT(emitBinary(emitDivideF64, ValType::F64));
- case Expr::F64Mod:
+ case uint16_t(Op::F64Mod):
CHECK_NEXT(emitBinaryMathBuiltinCall(SymbolicAddress::ModD, ValType::F64));
- case Expr::F64Min:
+ case uint16_t(Op::F64Min):
CHECK_NEXT(emitBinary(emitMinF64, ValType::F64));
- case Expr::F64Max:
+ case uint16_t(Op::F64Max):
CHECK_NEXT(emitBinary(emitMaxF64, ValType::F64));
- case Expr::F64Neg:
+ case uint16_t(Op::F64Neg):
CHECK_NEXT(emitUnary(emitNegateF64, ValType::F64));
- case Expr::F64Abs:
+ case uint16_t(Op::F64Abs):
CHECK_NEXT(emitUnary(emitAbsF64, ValType::F64));
- case Expr::F64Sqrt:
+ case uint16_t(Op::F64Sqrt):
CHECK_NEXT(emitUnary(emitSqrtF64, ValType::F64));
- case Expr::F64Ceil:
+ case uint16_t(Op::F64Ceil):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::CeilD, ValType::F64));
- case Expr::F64Floor:
+ case uint16_t(Op::F64Floor):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::FloorD, ValType::F64));
- case Expr::F64Sin:
+ case uint16_t(Op::F64Sin):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::SinD, ValType::F64));
- case Expr::F64Cos:
+ case uint16_t(Op::F64Cos):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::CosD, ValType::F64));
- case Expr::F64Tan:
+ case uint16_t(Op::F64Tan):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::TanD, ValType::F64));
- case Expr::F64Asin:
+ case uint16_t(Op::F64Asin):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::ASinD, ValType::F64));
- case Expr::F64Acos:
+ case uint16_t(Op::F64Acos):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::ACosD, ValType::F64));
- case Expr::F64Atan:
+ case uint16_t(Op::F64Atan):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::ATanD, ValType::F64));
- case Expr::F64Exp:
+ case uint16_t(Op::F64Exp):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::ExpD, ValType::F64));
- case Expr::F64Log:
+ case uint16_t(Op::F64Log):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::LogD, ValType::F64));
- case Expr::F64Pow:
+ case uint16_t(Op::F64Pow):
CHECK_NEXT(emitBinaryMathBuiltinCall(SymbolicAddress::PowD, ValType::F64));
- case Expr::F64Atan2:
+ case uint16_t(Op::F64Atan2):
CHECK_NEXT(emitBinaryMathBuiltinCall(SymbolicAddress::ATan2D, ValType::F64));
- case Expr::F64PromoteF32:
+ case uint16_t(Op::F64PromoteF32):
CHECK_NEXT(emitConversion(emitConvertF32ToF64, ValType::F32, ValType::F64));
- case Expr::F64ConvertSI32:
+ case uint16_t(Op::F64ConvertSI32):
CHECK_NEXT(emitConversion(emitConvertI32ToF64, ValType::I32, ValType::F64));
- case Expr::F64ConvertUI32:
+ case uint16_t(Op::F64ConvertUI32):
CHECK_NEXT(emitConversion(emitConvertU32ToF64, ValType::I32, ValType::F64));
- case Expr::F64ConvertSI64:
+ case uint16_t(Op::F64ConvertSI64):
#ifdef I64_TO_FLOAT_CALLOUT
CHECK_NEXT(emitCalloutConversionOOM(emitConvertInt64ToFloatingCallout,
SymbolicAddress::Int64ToFloatingPoint,
ValType::I64, ValType::F64));
#else
CHECK_NEXT(emitConversion(emitConvertI64ToF64, ValType::I64, ValType::F64));
#endif
- case Expr::F64ConvertUI64:
+ case uint16_t(Op::F64ConvertUI64):
#ifdef I64_TO_FLOAT_CALLOUT
CHECK_NEXT(emitCalloutConversionOOM(emitConvertInt64ToFloatingCallout,
SymbolicAddress::Uint64ToFloatingPoint,
ValType::I64, ValType::F64));
#else
CHECK_NEXT(emitConversion(emitConvertU64ToF64, ValType::I64, ValType::F64));
#endif
- case Expr::F64Load:
+ case uint16_t(Op::F64Load):
CHECK_NEXT(emitLoad(ValType::F64, Scalar::Float64));
- case Expr::F64Store:
+ case uint16_t(Op::F64Store):
CHECK_NEXT(emitStore(ValType::F64, Scalar::Float64));
- case Expr::F64TeeStore:
+ case uint16_t(Op::F64TeeStore):
CHECK_NEXT(emitTeeStore(ValType::F64, Scalar::Float64));
- case Expr::F64TeeStoreF32:
+ case uint16_t(Op::F64TeeStoreF32):
CHECK_NEXT(emitTeeStoreWithCoercion(ValType::F64, Scalar::Float32));
- case Expr::F64ReinterpretI64:
+ case uint16_t(Op::F64ReinterpretI64):
CHECK_NEXT(emitConversion(emitReinterpretI64AsF64, ValType::I64, ValType::F64));
- case Expr::F64CopySign:
+ case uint16_t(Op::F64CopySign):
CHECK_NEXT(emitBinary(emitCopysignF64, ValType::F64));
- case Expr::F64Nearest:
+ case uint16_t(Op::F64Nearest):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::NearbyIntD, ValType::F64));
- case Expr::F64Trunc:
+ case uint16_t(Op::F64Trunc):
CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::TruncD, ValType::F64));
// Comparisons
- case Expr::I32Eq:
+ case uint16_t(Op::I32Eq):
CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_EQ, MCompare::Compare_Int32));
- case Expr::I32Ne:
+ case uint16_t(Op::I32Ne):
CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_NE, MCompare::Compare_Int32));
- case Expr::I32LtS:
+ case uint16_t(Op::I32LtS):
CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LT, MCompare::Compare_Int32));
- case Expr::I32LeS:
+ case uint16_t(Op::I32LeS):
CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LE, MCompare::Compare_Int32));
- case Expr::I32GtS:
+ case uint16_t(Op::I32GtS):
CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GT, MCompare::Compare_Int32));
- case Expr::I32GeS:
+ case uint16_t(Op::I32GeS):
CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GE, MCompare::Compare_Int32));
- case Expr::I32LtU:
+ case uint16_t(Op::I32LtU):
CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LT, MCompare::Compare_UInt32));
- case Expr::I32LeU:
+ case uint16_t(Op::I32LeU):
CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LE, MCompare::Compare_UInt32));
- case Expr::I32GtU:
+ case uint16_t(Op::I32GtU):
CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GT, MCompare::Compare_UInt32));
- case Expr::I32GeU:
+ case uint16_t(Op::I32GeU):
CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GE, MCompare::Compare_UInt32));
- case Expr::I64Eq:
+ case uint16_t(Op::I64Eq):
CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_EQ, MCompare::Compare_Int64));
- case Expr::I64Ne:
+ case uint16_t(Op::I64Ne):
CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_NE, MCompare::Compare_Int64));
- case Expr::I64LtS:
+ case uint16_t(Op::I64LtS):
CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LT, MCompare::Compare_Int64));
- case Expr::I64LeS:
+ case uint16_t(Op::I64LeS):
CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LE, MCompare::Compare_Int64));
- case Expr::I64GtS:
+ case uint16_t(Op::I64GtS):
CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GT, MCompare::Compare_Int64));
- case Expr::I64GeS:
+ case uint16_t(Op::I64GeS):
CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GE, MCompare::Compare_Int64));
- case Expr::I64LtU:
+ case uint16_t(Op::I64LtU):
CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LT, MCompare::Compare_UInt64));
- case Expr::I64LeU:
+ case uint16_t(Op::I64LeU):
CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LE, MCompare::Compare_UInt64));
- case Expr::I64GtU:
+ case uint16_t(Op::I64GtU):
CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GT, MCompare::Compare_UInt64));
- case Expr::I64GeU:
+ case uint16_t(Op::I64GeU):
CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GE, MCompare::Compare_UInt64));
- case Expr::F32Eq:
+ case uint16_t(Op::F32Eq):
CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_EQ, MCompare::Compare_Float32));
- case Expr::F32Ne:
+ case uint16_t(Op::F32Ne):
CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_NE, MCompare::Compare_Float32));
- case Expr::F32Lt:
+ case uint16_t(Op::F32Lt):
CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_LT, MCompare::Compare_Float32));
- case Expr::F32Le:
+ case uint16_t(Op::F32Le):
CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_LE, MCompare::Compare_Float32));
- case Expr::F32Gt:
+ case uint16_t(Op::F32Gt):
CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_GT, MCompare::Compare_Float32));
- case Expr::F32Ge:
+ case uint16_t(Op::F32Ge):
CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_GE, MCompare::Compare_Float32));
- case Expr::F64Eq:
+ case uint16_t(Op::F64Eq):
CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_EQ, MCompare::Compare_Double));
- case Expr::F64Ne:
+ case uint16_t(Op::F64Ne):
CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_NE, MCompare::Compare_Double));
- case Expr::F64Lt:
+ case uint16_t(Op::F64Lt):
CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_LT, MCompare::Compare_Double));
- case Expr::F64Le:
+ case uint16_t(Op::F64Le):
CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_LE, MCompare::Compare_Double));
- case Expr::F64Gt:
+ case uint16_t(Op::F64Gt):
CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_GT, MCompare::Compare_Double));
- case Expr::F64Ge:
+ case uint16_t(Op::F64Ge):
CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_GE, MCompare::Compare_Double));
// SIMD
#define CASE(TYPE, OP, SIGN) \
- case Expr::TYPE##OP: \
+ case uint16_t(Op::TYPE##OP): \
MOZ_CRASH("Unimplemented SIMD");
#define I8x16CASE(OP) CASE(I8x16, OP, SimdSign::Signed)
#define I16x8CASE(OP) CASE(I16x8, OP, SimdSign::Signed)
#define I32x4CASE(OP) CASE(I32x4, OP, SimdSign::Signed)
#define F32x4CASE(OP) CASE(F32x4, OP, SimdSign::NotApplicable)
#define B8x16CASE(OP) CASE(B8x16, OP, SimdSign::NotApplicable)
#define B16x8CASE(OP) CASE(B16x8, OP, SimdSign::NotApplicable)
#define B32x4CASE(OP) CASE(B32x4, OP, SimdSign::NotApplicable)
#define ENUMERATE(TYPE, FORALL, DO) \
- case Expr::TYPE##Constructor: \
+ case uint16_t(Op::TYPE##Constructor): \
FORALL(DO)
ENUMERATE(I8x16, FORALL_INT8X16_ASMJS_OP, I8x16CASE)
ENUMERATE(I16x8, FORALL_INT16X8_ASMJS_OP, I16x8CASE)
ENUMERATE(I32x4, FORALL_INT32X4_ASMJS_OP, I32x4CASE)
ENUMERATE(F32x4, FORALL_FLOAT32X4_ASMJS_OP, F32x4CASE)
ENUMERATE(B8x16, FORALL_BOOL_SIMD_OP, B8x16CASE)
ENUMERATE(B16x8, FORALL_BOOL_SIMD_OP, B16x8CASE)
@@ -7123,62 +7123,60 @@ BaseCompiler::emitBody()
#undef I16x8CASE
#undef I32x4CASE
#undef F32x4CASE
#undef B8x16CASE
#undef B16x8CASE
#undef B32x4CASE
#undef ENUMERATE
- case Expr::I8x16Const:
- case Expr::I16x8Const:
- case Expr::I32x4Const:
- case Expr::F32x4Const:
- case Expr::B8x16Const:
- case Expr::B16x8Const:
- case Expr::B32x4Const:
- case Expr::I32x4shiftRightByScalarU:
- case Expr::I8x16addSaturateU:
- case Expr::I8x16subSaturateU:
- case Expr::I8x16shiftRightByScalarU:
- case Expr::I8x16lessThanU:
- case Expr::I8x16lessThanOrEqualU:
- case Expr::I8x16greaterThanU:
- case Expr::I8x16greaterThanOrEqualU:
- case Expr::I8x16extractLaneU:
- case Expr::I16x8addSaturateU:
- case Expr::I16x8subSaturateU:
- case Expr::I16x8shiftRightByScalarU:
- case Expr::I16x8lessThanU:
- case Expr::I16x8lessThanOrEqualU:
- case Expr::I16x8greaterThanU:
- case Expr::I16x8greaterThanOrEqualU:
- case Expr::I16x8extractLaneU:
- case Expr::I32x4lessThanU:
- case Expr::I32x4lessThanOrEqualU:
- case Expr::I32x4greaterThanU:
- case Expr::I32x4greaterThanOrEqualU:
- case Expr::I32x4fromFloat32x4U:
+ case uint16_t(Op::I8x16Const):
+ case uint16_t(Op::I16x8Const):
+ case uint16_t(Op::I32x4Const):
+ case uint16_t(Op::F32x4Const):
+ case uint16_t(Op::B8x16Const):
+ case uint16_t(Op::B16x8Const):
+ case uint16_t(Op::B32x4Const):
+ case uint16_t(Op::I32x4shiftRightByScalarU):
+ case uint16_t(Op::I8x16addSaturateU):
+ case uint16_t(Op::I8x16subSaturateU):
+ case uint16_t(Op::I8x16shiftRightByScalarU):
+ case uint16_t(Op::I8x16lessThanU):
+ case uint16_t(Op::I8x16lessThanOrEqualU):
+ case uint16_t(Op::I8x16greaterThanU):
+ case uint16_t(Op::I8x16greaterThanOrEqualU):
+ case uint16_t(Op::I8x16extractLaneU):
+ case uint16_t(Op::I16x8addSaturateU):
+ case uint16_t(Op::I16x8subSaturateU):
+ case uint16_t(Op::I16x8shiftRightByScalarU):
+ case uint16_t(Op::I16x8lessThanU):
+ case uint16_t(Op::I16x8lessThanOrEqualU):
+ case uint16_t(Op::I16x8greaterThanU):
+ case uint16_t(Op::I16x8greaterThanOrEqualU):
+ case uint16_t(Op::I16x8extractLaneU):
+ case uint16_t(Op::I32x4lessThanU):
+ case uint16_t(Op::I32x4lessThanOrEqualU):
+ case uint16_t(Op::I32x4greaterThanU):
+ case uint16_t(Op::I32x4greaterThanOrEqualU):
+ case uint16_t(Op::I32x4fromFloat32x4U):
MOZ_CRASH("Unimplemented SIMD");
// Atomics
- case Expr::I32AtomicsLoad:
- case Expr::I32AtomicsStore:
- case Expr::I32AtomicsBinOp:
- case Expr::I32AtomicsCompareExchange:
- case Expr::I32AtomicsExchange:
+ case uint16_t(Op::I32AtomicsLoad):
+ case uint16_t(Op::I32AtomicsStore):
+ case uint16_t(Op::I32AtomicsBinOp):
+ case uint16_t(Op::I32AtomicsCompareExchange):
+ case uint16_t(Op::I32AtomicsExchange):
MOZ_CRASH("Unimplemented Atomics");
// Memory Related
- case Expr::GrowMemory:
+ case uint16_t(Op::GrowMemory):
CHECK_NEXT(emitGrowMemory());
- case Expr::CurrentMemory:
+ case uint16_t(Op::CurrentMemory):
CHECK_NEXT(emitCurrentMemory());
-
- case Expr::Limit:;
}
MOZ_CRASH("unexpected wasm opcode");
#undef CHECK
#undef NEXT
#undef CHECK_NEXT
#undef emitBinary
@@ -7451,17 +7449,17 @@ js::wasm::BaselineCompileFunction(IonCom
Decoder d(func.bytes());
// Build the local types vector.
ValTypeVector locals;
if (!locals.appendAll(func.sig().args()))
return false;
- if (!DecodeLocalEntries(d, &locals))
+ if (!DecodeLocalEntries(d, task->mg().kind, &locals))
return false;
// The MacroAssembler will sometimes access the jitContext.
JitContext jitContext(&results.alloc());
// One-pass baseline compilation.
--- a/js/src/wasm/WasmBinaryConstants.h
+++ b/js/src/wasm/WasmBinaryConstants.h
@@ -64,22 +64,20 @@ enum class TypeCode
AnyFunc = 0x70, // SLEB128(-0x10)
// Type constructor for function types
Func = 0x60, // SLEB128(-0x20)
// Special code representing the block signature ()->()
BlockVoid = 0x40, // SLEB128(-0x40)
- // Type codes currently always fit in a single byte
- Max = 0x7f,
Limit = 0x80
};
-enum class ValType : uint32_t // fix type so we can cast from any u8 in decoder
+enum class ValType
{
I32 = uint8_t(TypeCode::I32),
I64 = uint8_t(TypeCode::I64),
F32 = uint8_t(TypeCode::F32),
F64 = uint8_t(TypeCode::F64),
// ------------------------------------------------------------------------
// The rest of these types are currently only emitted internally when
@@ -110,17 +108,17 @@ enum class GlobalFlags
AllowedMask = 0x1
};
enum class MemoryTableFlags
{
Default = 0x0
};
-enum class Expr : uint32_t // fix type so we can cast from any u16 in decoder
+enum class Op
{
// Control flow operators
Unreachable = 0x00,
Nop = 0x01,
Block = 0x02,
Loop = 0x03,
If = 0x04,
Else = 0x05,
--- a/js/src/wasm/WasmBinaryFormat.cpp
+++ b/js/src/wasm/WasmBinaryFormat.cpp
@@ -38,31 +38,44 @@ wasm::DecodePreamble(Decoder& d)
if (!d.readFixedU32(&u32) || u32 != EncodingVersion)
return d.fail("binary version 0x%" PRIx32 " does not match expected version 0x%" PRIx32,
u32, EncodingVersion);
return true;
}
-bool
-wasm::CheckValType(Decoder& d, ValType type)
+static bool
+DecodeValType(Decoder& d, ModuleKind kind, ValType* type)
{
- switch (type) {
- case ValType::I32:
- case ValType::F32:
- case ValType::F64:
- case ValType::I64:
+ uint8_t unchecked;
+ if (!d.readValType(&unchecked))
+ return false;
+
+ switch (unchecked) {
+ case uint8_t(ValType::I32):
+ case uint8_t(ValType::F32):
+ case uint8_t(ValType::F64):
+ case uint8_t(ValType::I64):
+ *type = ValType(unchecked);
+ return true;
+ case uint8_t(ValType::I8x16):
+ case uint8_t(ValType::I16x8):
+ case uint8_t(ValType::I32x4):
+ case uint8_t(ValType::F32x4):
+ case uint8_t(ValType::B8x16):
+ case uint8_t(ValType::B16x8):
+ case uint8_t(ValType::B32x4):
+ if (kind != ModuleKind::AsmJS)
+ return d.fail("bad type");
+ *type = ValType(unchecked);
return true;
default:
- // Note: it's important not to remove this default since readValType()
- // can return ValType values for which there is no enumerator.
break;
}
-
return d.fail("bad type");
}
bool
wasm::DecodeTypeSection(Decoder& d, SigWithIdVector* sigs)
{
uint32_t sectionStart, sectionSize;
if (!d.startSection(SectionId::Type, §ionStart, §ionSize, "type"))
@@ -92,38 +105,32 @@ wasm::DecodeTypeSection(Decoder& d, SigW
if (numArgs > MaxArgsPerFunc)
return d.fail("too many arguments in signature");
ValTypeVector args;
if (!args.resize(numArgs))
return false;
for (uint32_t i = 0; i < numArgs; i++) {
- if (!d.readValType(&args[i]))
- return d.fail("bad value type");
-
- if (!CheckValType(d, args[i]))
+ if (!DecodeValType(d, ModuleKind::Wasm, &args[i]))
return false;
}
uint32_t numRets;
if (!d.readVarU32(&numRets))
return d.fail("bad number of function returns");
if (numRets > 1)
return d.fail("too many returns in signature");
ExprType result = ExprType::Void;
if (numRets == 1) {
ValType type;
- if (!d.readValType(&type))
- return d.fail("bad expression type");
-
- if (!CheckValType(d, type))
+ if (!DecodeValType(d, ModuleKind::Wasm, &type))
return false;
result = ToExprType(type);
}
(*sigs)[sigIndex] = Sig(Move(args), result);
}
@@ -362,96 +369,96 @@ wasm::EncodeLocalEntries(Encoder& e, con
if (!e.writeValType(prev))
return false;
}
return true;
}
bool
-wasm::DecodeLocalEntries(Decoder& d, ValTypeVector* locals)
+wasm::DecodeLocalEntries(Decoder& d, ModuleKind kind, ValTypeVector* locals)
{
uint32_t numLocalEntries;
if (!d.readVarU32(&numLocalEntries))
- return false;
+ return d.fail("failed to read number of local entries");
for (uint32_t i = 0; i < numLocalEntries; i++) {
uint32_t count;
if (!d.readVarU32(&count))
- return false;
+ return d.fail("failed to read local entry count");
if (MaxLocals - locals->length() < count)
- return false;
+ return d.fail("too many locals");
ValType type;
- if (!d.readValType(&type))
+ if (!DecodeValType(d, kind, &type))
return false;
if (!locals->appendN(type, count))
return false;
}
return true;
}
bool
wasm::DecodeGlobalType(Decoder& d, ValType* type, bool* isMutable)
{
- if (!d.readValType(type))
- return d.fail("bad global type");
+ if (!DecodeValType(d, ModuleKind::Wasm, type))
+ return false;
uint32_t flags;
if (!d.readVarU32(&flags))
return d.fail("expected global flags");
if (flags & ~uint32_t(GlobalFlags::AllowedMask))
return d.fail("unexpected bits set in global flags");
*isMutable = flags & uint32_t(GlobalFlags::IsMutable);
return true;
}
bool
wasm::DecodeInitializerExpression(Decoder& d, const GlobalDescVector& globals, ValType expected,
InitExpr* init)
{
- Expr expr;
- if (!d.readExpr(&expr))
+ uint16_t op;
+ if (!d.readOp(&op))
return d.fail("failed to read initializer type");
- switch (expr) {
- case Expr::I32Const: {
+ switch (op) {
+ case uint16_t(Op::I32Const): {
int32_t i32;
if (!d.readVarS32(&i32))
return d.fail("failed to read initializer i32 expression");
*init = InitExpr(Val(uint32_t(i32)));
break;
}
- case Expr::I64Const: {
+ case uint16_t(Op::I64Const): {
int64_t i64;
if (!d.readVarS64(&i64))
return d.fail("failed to read initializer i64 expression");
*init = InitExpr(Val(uint64_t(i64)));
break;
}
- case Expr::F32Const: {
+ case uint16_t(Op::F32Const): {
RawF32 f32;
if (!d.readFixedF32(&f32))
return d.fail("failed to read initializer f32 expression");
*init = InitExpr(Val(f32));
break;
}
- case Expr::F64Const: {
+ case uint16_t(Op::F64Const): {
RawF64 f64;
if (!d.readFixedF64(&f64))
return d.fail("failed to read initializer f64 expression");
*init = InitExpr(Val(f64));
break;
}
- case Expr::GetGlobal: {
+ case uint16_t(Op::GetGlobal): {
uint32_t i;
if (!d.readVarU32(&i))
return d.fail("failed to read get_global index in initializer expression");
if (i >= globals.length())
return d.fail("global index out of range in initializer expression");
if (!globals[i].isImport() || globals[i].isMutable())
return d.fail("initializer expression must reference a global immutable import");
*init = InitExpr(i, globals[i].type());
@@ -460,18 +467,18 @@ wasm::DecodeInitializerExpression(Decode
default: {
return d.fail("unexpected initializer expression");
}
}
if (expected != init->type())
return d.fail("type mismatch: initializer type and expected type don't match");
- Expr end;
- if (!d.readExpr(&end) || end != Expr::End)
+ uint16_t end;
+ if (!d.readOp(&end) || end != uint16_t(Op::End))
return d.fail("failed to read end of initializer expression");
return true;
}
bool
wasm::DecodeLimits(Decoder& d, Limits* limits)
{
--- a/js/src/wasm/WasmBinaryFormat.h
+++ b/js/src/wasm/WasmBinaryFormat.h
@@ -93,18 +93,16 @@ class Encoder
uint32_t varU32ByteLength(size_t offset) const {
size_t start = offset;
while (bytes_[offset] & 0x80)
offset++;
return offset - start + 1;
}
- static const size_t ExprLimit = 2 * UINT8_MAX - 1;
-
public:
explicit Encoder(Bytes& bytes)
: bytes_(bytes)
{
MOZ_ASSERT(empty());
}
size_t currentOffset() const { return bytes_.length(); }
@@ -152,31 +150,32 @@ class Encoder
}
MOZ_MUST_USE bool writeVarU64(uint64_t i) {
return writeVarU<uint64_t>(i);
}
MOZ_MUST_USE bool writeVarS64(int64_t i) {
return writeVarS<int64_t>(i);
}
MOZ_MUST_USE bool writeValType(ValType type) {
- static_assert(size_t(TypeCode::Max) <= INT8_MAX, "fits");
- MOZ_ASSERT(size_t(type) <= size_t(TypeCode::Max));
+ static_assert(size_t(TypeCode::Limit) <= UINT8_MAX, "fits");
+ MOZ_ASSERT(size_t(type) < size_t(TypeCode::Limit));
return writeFixedU8(uint8_t(type));
}
MOZ_MUST_USE bool writeBlockType(ExprType type) {
- static_assert(size_t(TypeCode::Max) <= INT8_MAX, "fits");
- MOZ_ASSERT(size_t(type) <= size_t(TypeCode::Max));
+ static_assert(size_t(TypeCode::Limit) <= UINT8_MAX, "fits");
+ MOZ_ASSERT(size_t(type) < size_t(TypeCode::Limit));
return writeFixedU8(uint8_t(type));
}
- MOZ_MUST_USE bool writeExpr(Expr expr) {
- static_assert(size_t(Expr::Limit) <= ExprLimit, "fits");
- if (size_t(expr) < UINT8_MAX)
- return writeFixedU8(uint8_t(expr));
+ MOZ_MUST_USE bool writeOp(Op op) {
+ static_assert(size_t(Op::Limit) <= 2 * UINT8_MAX, "fits");
+ MOZ_ASSERT(size_t(op) < size_t(Op::Limit));
+ if (size_t(op) < UINT8_MAX)
+ return writeFixedU8(uint8_t(op));
return writeFixedU8(UINT8_MAX) &&
- writeFixedU8(size_t(expr) - UINT8_MAX);
+ writeFixedU8(size_t(op) - UINT8_MAX);
}
// Fixed-length encodings that allow back-patching.
MOZ_MUST_USE bool writePatchableFixedU7(size_t* offset) {
*offset = bytes_.length();
return writeFixedU8(UINT8_MAX);
}
@@ -303,18 +302,16 @@ class Decoder
return false;
uint8_t mask = 0x7f & (uint8_t(-1) << remainderBits);
if ((byte & mask) != ((byte & (1 << (remainderBits - 1))) ? mask : 0))
return false;
*out = s | SInt(byte) << shift;
return true;
}
- static const size_t ExprLimit = 2 * UINT8_MAX - 1;
-
public:
Decoder(const uint8_t* begin, const uint8_t* end, UniqueChars* error)
: beg_(begin),
end_(end),
cur_(begin),
error_(error)
{
MOZ_ASSERT(begin <= end);
@@ -397,46 +394,36 @@ class Decoder
return readVarS<int32_t>(out);
}
MOZ_MUST_USE bool readVarU64(uint64_t* out) {
return readVarU<uint64_t>(out);
}
MOZ_MUST_USE bool readVarS64(int64_t* out) {
return readVarS<int64_t>(out);
}
- MOZ_MUST_USE bool readValType(ValType* type) {
- static_assert(uint8_t(TypeCode::Max) <= INT8_MAX, "fits");
+ MOZ_MUST_USE bool readValType(uint8_t* type) {
+ static_assert(uint8_t(TypeCode::Limit) <= UINT8_MAX, "fits");
+ return readFixedU8(type);
+ }
+ MOZ_MUST_USE bool readBlockType(uint8_t* type) {
+ static_assert(size_t(TypeCode::Limit) <= UINT8_MAX, "fits");
+ return readFixedU8(type);
+ }
+ MOZ_MUST_USE bool readOp(uint16_t* op) {
+ static_assert(size_t(Op::Limit) <= 2 * UINT8_MAX, "fits");
uint8_t u8;
if (!readFixedU8(&u8))
return false;
- *type = (ValType)u8;
- return true;
- }
- MOZ_MUST_USE bool readBlockType(ExprType* type) {
- static_assert(size_t(TypeCode::Max) <= INT8_MAX, "fits");
- uint8_t u8;
- if (!readFixedU8(&u8))
- return false;
- *type = (ExprType)u8;
- return true;
- }
- MOZ_MUST_USE bool readExpr(Expr* expr) {
- static_assert(size_t(Expr::Limit) <= ExprLimit, "fits");
- uint8_t u8;
- if (!readFixedU8(&u8))
- return false;
- if (u8 != UINT8_MAX) {
- *expr = Expr(u8);
+ if (MOZ_LIKELY(u8 != UINT8_MAX)) {
+ *op = u8;
return true;
}
if (!readFixedU8(&u8))
return false;
- if (u8 == UINT8_MAX)
- return false;
- *expr = Expr(uint16_t(u8) + UINT8_MAX);
+ *op = uint16_t(u8) + UINT8_MAX;
return true;
}
// See writeBytes comment.
MOZ_MUST_USE bool readBytes(uint32_t numBytes, const uint8_t** bytes = nullptr) {
if (bytes)
*bytes = cur_;
@@ -597,22 +584,22 @@ class Decoder
int64_t uncheckedReadVarS64() {
int64_t i64 = 0;
MOZ_ALWAYS_TRUE(readVarS64(&i64));
return i64;
}
ValType uncheckedReadValType() {
return (ValType)uncheckedReadFixedU8();
}
- Expr uncheckedReadExpr() {
- static_assert(size_t(Expr::Limit) <= ExprLimit, "fits");
+ Op uncheckedReadOp() {
+ static_assert(size_t(Op::Limit) <= 2 * UINT8_MAX, "fits");
uint8_t u8 = uncheckedReadFixedU8();
return u8 != UINT8_MAX
- ? Expr(u8)
- : Expr(uncheckedReadFixedU8() + UINT8_MAX);
+ ? Op(u8)
+ : Op(uncheckedReadFixedU8() + UINT8_MAX);
}
void uncheckedReadFixedI8x16(I8x16* i8x16) {
struct T { I8x16 v; };
T t = uncheckedRead<T>();
memcpy(i8x16, &t, sizeof(t));
}
void uncheckedReadFixedI16x8(I16x8* i16x8) {
struct T { I16x8 v; };
@@ -632,33 +619,30 @@ class Decoder
};
// Reusable macro encoding/decoding functions reused by both the two
// encoders (AsmJS/WasmTextToBinary) and all the decoders
// (WasmCompile/WasmIonCompile/WasmBaselineCompile/WasmBinaryToText).
// Misc helpers.
-MOZ_MUST_USE bool
-CheckValType(Decoder& d, ValType type);
-
UniqueChars
DecodeName(Decoder& d);
MOZ_MUST_USE bool
DecodeTableLimits(Decoder& d, TableDescVector* tables);
MOZ_MUST_USE bool
GlobalIsJSCompatible(Decoder& d, ValType type, bool isMutable);
MOZ_MUST_USE bool
EncodeLocalEntries(Encoder& d, const ValTypeVector& locals);
MOZ_MUST_USE bool
-DecodeLocalEntries(Decoder& d, ValTypeVector* locals);
+DecodeLocalEntries(Decoder& d, ModuleKind kind, ValTypeVector* locals);
MOZ_MUST_USE bool
DecodeGlobalType(Decoder& d, ValType* type, bool* isMutable);
MOZ_MUST_USE bool
DecodeInitializerExpression(Decoder& d, const GlobalDescVector& globals, ValType expected,
InitExpr* init);
--- a/js/src/wasm/WasmBinaryIterator.cpp
+++ b/js/src/wasm/WasmBinaryIterator.cpp
@@ -18,481 +18,481 @@
#include "wasm/WasmBinaryIterator.h"
using namespace js;
using namespace js::jit;
using namespace js::wasm;
#ifdef DEBUG
-ExprKind
-wasm::Classify(Expr expr)
+OpKind
+wasm::Classify(Op op)
{
- switch (expr) {
- case Expr::Block:
- return ExprKind::Block;
- case Expr::Loop:
- return ExprKind::Loop;
- case Expr::Unreachable:
- return ExprKind::Unreachable;
- case Expr::Drop:
- return ExprKind::Drop;
- case Expr::I32Const:
- return ExprKind::I32;
- case Expr::I64Const:
- return ExprKind::I64;
- case Expr::F32Const:
- return ExprKind::F32;
- case Expr::F64Const:
- return ExprKind::F64;
- case Expr::I8x16Const:
- return ExprKind::I8x16;
- case Expr::I16x8Const:
- return ExprKind::I16x8;
- case Expr::I32x4Const:
- return ExprKind::I32x4;
- case Expr::B8x16Const:
- return ExprKind::B8x16;
- case Expr::B16x8Const:
- return ExprKind::B16x8;
- case Expr::B32x4Const:
- return ExprKind::B32x4;
- case Expr::F32x4Const:
- return ExprKind::F32x4;
- case Expr::Br:
- return ExprKind::Br;
- case Expr::BrIf:
- return ExprKind::BrIf;
- case Expr::BrTable:
- return ExprKind::BrTable;
- case Expr::Nop:
- return ExprKind::Nop;
- case Expr::I32Clz:
- case Expr::I32Ctz:
- case Expr::I32Popcnt:
- case Expr::I64Clz:
- case Expr::I64Ctz:
- case Expr::I64Popcnt:
- case Expr::F32Abs:
- case Expr::F32Neg:
- case Expr::F32Ceil:
- case Expr::F32Floor:
- case Expr::F32Trunc:
- case Expr::F32Nearest:
- case Expr::F32Sqrt:
- case Expr::F64Abs:
- case Expr::F64Neg:
- case Expr::F64Ceil:
- case Expr::F64Floor:
- case Expr::F64Trunc:
- case Expr::F64Nearest:
- case Expr::F64Sqrt:
- case Expr::I32BitNot:
- case Expr::I32Abs:
- case Expr::F64Sin:
- case Expr::F64Cos:
- case Expr::F64Tan:
- case Expr::F64Asin:
- case Expr::F64Acos:
- case Expr::F64Atan:
- case Expr::F64Exp:
- case Expr::F64Log:
- case Expr::I32Neg:
- case Expr::I8x16neg:
- case Expr::I8x16not:
- case Expr::I16x8neg:
- case Expr::I16x8not:
- case Expr::I32x4neg:
- case Expr::I32x4not:
- case Expr::F32x4neg:
- case Expr::F32x4sqrt:
- case Expr::F32x4abs:
- case Expr::F32x4reciprocalApproximation:
- case Expr::F32x4reciprocalSqrtApproximation:
- case Expr::B8x16not:
- case Expr::B16x8not:
- case Expr::B32x4not:
- return ExprKind::Unary;
- case Expr::I32Add:
- case Expr::I32Sub:
- case Expr::I32Mul:
- case Expr::I32DivS:
- case Expr::I32DivU:
- case Expr::I32RemS:
- case Expr::I32RemU:
- case Expr::I32And:
- case Expr::I32Or:
- case Expr::I32Xor:
- case Expr::I32Shl:
- case Expr::I32ShrS:
- case Expr::I32ShrU:
- case Expr::I32Rotl:
- case Expr::I32Rotr:
- case Expr::I64Add:
- case Expr::I64Sub:
- case Expr::I64Mul:
- case Expr::I64DivS:
- case Expr::I64DivU:
- case Expr::I64RemS:
- case Expr::I64RemU:
- case Expr::I64And:
- case Expr::I64Or:
- case Expr::I64Xor:
- case Expr::I64Shl:
- case Expr::I64ShrS:
- case Expr::I64ShrU:
- case Expr::I64Rotl:
- case Expr::I64Rotr:
- case Expr::F32Add:
- case Expr::F32Sub:
- case Expr::F32Mul:
- case Expr::F32Div:
- case Expr::F32Min:
- case Expr::F32Max:
- case Expr::F32CopySign:
- case Expr::F64Add:
- case Expr::F64Sub:
- case Expr::F64Mul:
- case Expr::F64Div:
- case Expr::F64Min:
- case Expr::F64Max:
- case Expr::F64CopySign:
- case Expr::I32Min:
- case Expr::I32Max:
- case Expr::F64Mod:
- case Expr::F64Pow:
- case Expr::F64Atan2:
- case Expr::I8x16add:
- case Expr::I8x16sub:
- case Expr::I8x16mul:
- case Expr::I8x16addSaturate:
- case Expr::I8x16subSaturate:
- case Expr::I8x16addSaturateU:
- case Expr::I8x16subSaturateU:
- case Expr::I8x16and:
- case Expr::I8x16or:
- case Expr::I8x16xor:
- case Expr::I16x8add:
- case Expr::I16x8sub:
- case Expr::I16x8mul:
- case Expr::I16x8addSaturate:
- case Expr::I16x8subSaturate:
- case Expr::I16x8addSaturateU:
- case Expr::I16x8subSaturateU:
- case Expr::I16x8and:
- case Expr::I16x8or:
- case Expr::I16x8xor:
- case Expr::I32x4add:
- case Expr::I32x4sub:
- case Expr::I32x4mul:
- case Expr::I32x4and:
- case Expr::I32x4or:
- case Expr::I32x4xor:
- case Expr::F32x4add:
- case Expr::F32x4sub:
- case Expr::F32x4mul:
- case Expr::F32x4div:
- case Expr::F32x4min:
- case Expr::F32x4max:
- case Expr::F32x4minNum:
- case Expr::F32x4maxNum:
- case Expr::B8x16and:
- case Expr::B8x16or:
- case Expr::B8x16xor:
- case Expr::B16x8and:
- case Expr::B16x8or:
- case Expr::B16x8xor:
- case Expr::B32x4and:
- case Expr::B32x4or:
- case Expr::B32x4xor:
- return ExprKind::Binary;
- case Expr::I32Eq:
- case Expr::I32Ne:
- case Expr::I32LtS:
- case Expr::I32LtU:
- case Expr::I32LeS:
- case Expr::I32LeU:
- case Expr::I32GtS:
- case Expr::I32GtU:
- case Expr::I32GeS:
- case Expr::I32GeU:
- case Expr::I64Eq:
- case Expr::I64Ne:
- case Expr::I64LtS:
- case Expr::I64LtU:
- case Expr::I64LeS:
- case Expr::I64LeU:
- case Expr::I64GtS:
- case Expr::I64GtU:
- case Expr::I64GeS:
- case Expr::I64GeU:
- case Expr::F32Eq:
- case Expr::F32Ne:
- case Expr::F32Lt:
- case Expr::F32Le:
- case Expr::F32Gt:
- case Expr::F32Ge:
- case Expr::F64Eq:
- case Expr::F64Ne:
- case Expr::F64Lt:
- case Expr::F64Le:
- case Expr::F64Gt:
- case Expr::F64Ge:
- return ExprKind::Comparison;
- case Expr::I32Eqz:
- case Expr::I32WrapI64:
- case Expr::I32TruncSF32:
- case Expr::I32TruncUF32:
- case Expr::I32ReinterpretF32:
- case Expr::I32TruncSF64:
- case Expr::I32TruncUF64:
- case Expr::I64ExtendSI32:
- case Expr::I64ExtendUI32:
- case Expr::I64TruncSF32:
- case Expr::I64TruncUF32:
- case Expr::I64TruncSF64:
- case Expr::I64TruncUF64:
- case Expr::I64ReinterpretF64:
- case Expr::I64Eqz:
- case Expr::F32ConvertSI32:
- case Expr::F32ConvertUI32:
- case Expr::F32ReinterpretI32:
- case Expr::F32ConvertSI64:
- case Expr::F32ConvertUI64:
- case Expr::F32DemoteF64:
- case Expr::F64ConvertSI32:
- case Expr::F64ConvertUI32:
- case Expr::F64ConvertSI64:
- case Expr::F64ConvertUI64:
- case Expr::F64ReinterpretI64:
- case Expr::F64PromoteF32:
- case Expr::I32x4fromFloat32x4:
- case Expr::I32x4fromFloat32x4U:
- case Expr::F32x4fromInt32x4:
- case Expr::F32x4fromUint32x4:
- case Expr::I32x4fromFloat32x4Bits:
- case Expr::I32x4fromInt8x16Bits:
- case Expr::I32x4fromInt16x8Bits:
- case Expr::I16x8fromInt8x16Bits:
- case Expr::I16x8fromInt32x4Bits:
- case Expr::I16x8fromFloat32x4Bits:
- case Expr::I8x16fromInt16x8Bits:
- case Expr::I8x16fromInt32x4Bits:
- case Expr::I8x16fromFloat32x4Bits:
- case Expr::F32x4fromInt8x16Bits:
- case Expr::F32x4fromInt16x8Bits:
- case Expr::F32x4fromInt32x4Bits:
- return ExprKind::Conversion;
- case Expr::I32Load8S:
- case Expr::I32Load8U:
- case Expr::I32Load16S:
- case Expr::I32Load16U:
- case Expr::I64Load8S:
- case Expr::I64Load8U:
- case Expr::I64Load16S:
- case Expr::I64Load16U:
- case Expr::I64Load32S:
- case Expr::I64Load32U:
- case Expr::I32Load:
- case Expr::I64Load:
- case Expr::F32Load:
- case Expr::F64Load:
- case Expr::I8x16load:
- case Expr::I16x8load:
- case Expr::I32x4load:
- case Expr::I32x4load1:
- case Expr::I32x4load2:
- case Expr::I32x4load3:
- case Expr::F32x4load:
- case Expr::F32x4load1:
- case Expr::F32x4load2:
- case Expr::F32x4load3:
- return ExprKind::Load;
- case Expr::I32Store8:
- case Expr::I32Store16:
- case Expr::I64Store8:
- case Expr::I64Store16:
- case Expr::I64Store32:
- case Expr::I32Store:
- case Expr::I64Store:
- case Expr::F32Store:
- case Expr::F64Store:
- return ExprKind::Store;
- case Expr::I32TeeStore8:
- case Expr::I32TeeStore16:
- case Expr::I64TeeStore8:
- case Expr::I64TeeStore16:
- case Expr::I64TeeStore32:
- case Expr::I32TeeStore:
- case Expr::I64TeeStore:
- case Expr::F32TeeStore:
- case Expr::F64TeeStore:
- case Expr::F32TeeStoreF64:
- case Expr::F64TeeStoreF32:
- case Expr::I8x16store:
- case Expr::I16x8store:
- case Expr::I32x4store:
- case Expr::I32x4store1:
- case Expr::I32x4store2:
- case Expr::I32x4store3:
- case Expr::F32x4store:
- case Expr::F32x4store1:
- case Expr::F32x4store2:
- case Expr::F32x4store3:
- return ExprKind::TeeStore;
- case Expr::Select:
- return ExprKind::Select;
- case Expr::GetLocal:
- return ExprKind::GetLocal;
- case Expr::SetLocal:
- return ExprKind::SetLocal;
- case Expr::TeeLocal:
- return ExprKind::TeeLocal;
- case Expr::GetGlobal:
- return ExprKind::GetGlobal;
- case Expr::SetGlobal:
- return ExprKind::SetGlobal;
- case Expr::TeeGlobal:
- return ExprKind::TeeGlobal;
- case Expr::Call:
- return ExprKind::Call;
- case Expr::CallIndirect:
- return ExprKind::CallIndirect;
- case Expr::OldCallIndirect:
- return ExprKind::OldCallIndirect;
- case Expr::Return:
- case Expr::Limit:
+ switch (op) {
+ case Op::Block:
+ return OpKind::Block;
+ case Op::Loop:
+ return OpKind::Loop;
+ case Op::Unreachable:
+ return OpKind::Unreachable;
+ case Op::Drop:
+ return OpKind::Drop;
+ case Op::I32Const:
+ return OpKind::I32;
+ case Op::I64Const:
+ return OpKind::I64;
+ case Op::F32Const:
+ return OpKind::F32;
+ case Op::F64Const:
+ return OpKind::F64;
+ case Op::I8x16Const:
+ return OpKind::I8x16;
+ case Op::I16x8Const:
+ return OpKind::I16x8;
+ case Op::I32x4Const:
+ return OpKind::I32x4;
+ case Op::B8x16Const:
+ return OpKind::B8x16;
+ case Op::B16x8Const:
+ return OpKind::B16x8;
+ case Op::B32x4Const:
+ return OpKind::B32x4;
+ case Op::F32x4Const:
+ return OpKind::F32x4;
+ case Op::Br:
+ return OpKind::Br;
+ case Op::BrIf:
+ return OpKind::BrIf;
+ case Op::BrTable:
+ return OpKind::BrTable;
+ case Op::Nop:
+ return OpKind::Nop;
+ case Op::I32Clz:
+ case Op::I32Ctz:
+ case Op::I32Popcnt:
+ case Op::I64Clz:
+ case Op::I64Ctz:
+ case Op::I64Popcnt:
+ case Op::F32Abs:
+ case Op::F32Neg:
+ case Op::F32Ceil:
+ case Op::F32Floor:
+ case Op::F32Trunc:
+ case Op::F32Nearest:
+ case Op::F32Sqrt:
+ case Op::F64Abs:
+ case Op::F64Neg:
+ case Op::F64Ceil:
+ case Op::F64Floor:
+ case Op::F64Trunc:
+ case Op::F64Nearest:
+ case Op::F64Sqrt:
+ case Op::I32BitNot:
+ case Op::I32Abs:
+ case Op::F64Sin:
+ case Op::F64Cos:
+ case Op::F64Tan:
+ case Op::F64Asin:
+ case Op::F64Acos:
+ case Op::F64Atan:
+ case Op::F64Exp:
+ case Op::F64Log:
+ case Op::I32Neg:
+ case Op::I8x16neg:
+ case Op::I8x16not:
+ case Op::I16x8neg:
+ case Op::I16x8not:
+ case Op::I32x4neg:
+ case Op::I32x4not:
+ case Op::F32x4neg:
+ case Op::F32x4sqrt:
+ case Op::F32x4abs:
+ case Op::F32x4reciprocalApproximation:
+ case Op::F32x4reciprocalSqrtApproximation:
+ case Op::B8x16not:
+ case Op::B16x8not:
+ case Op::B32x4not:
+ return OpKind::Unary;
+ case Op::I32Add:
+ case Op::I32Sub:
+ case Op::I32Mul:
+ case Op::I32DivS:
+ case Op::I32DivU:
+ case Op::I32RemS:
+ case Op::I32RemU:
+ case Op::I32And:
+ case Op::I32Or:
+ case Op::I32Xor:
+ case Op::I32Shl:
+ case Op::I32ShrS:
+ case Op::I32ShrU:
+ case Op::I32Rotl:
+ case Op::I32Rotr:
+ case Op::I64Add:
+ case Op::I64Sub:
+ case Op::I64Mul:
+ case Op::I64DivS:
+ case Op::I64DivU:
+ case Op::I64RemS:
+ case Op::I64RemU:
+ case Op::I64And:
+ case Op::I64Or:
+ case Op::I64Xor:
+ case Op::I64Shl:
+ case Op::I64ShrS:
+ case Op::I64ShrU:
+ case Op::I64Rotl:
+ case Op::I64Rotr:
+ case Op::F32Add:
+ case Op::F32Sub:
+ case Op::F32Mul:
+ case Op::F32Div:
+ case Op::F32Min:
+ case Op::F32Max:
+ case Op::F32CopySign:
+ case Op::F64Add:
+ case Op::F64Sub:
+ case Op::F64Mul:
+ case Op::F64Div:
+ case Op::F64Min:
+ case Op::F64Max:
+ case Op::F64CopySign:
+ case Op::I32Min:
+ case Op::I32Max:
+ case Op::F64Mod:
+ case Op::F64Pow:
+ case Op::F64Atan2:
+ case Op::I8x16add:
+ case Op::I8x16sub:
+ case Op::I8x16mul:
+ case Op::I8x16addSaturate:
+ case Op::I8x16subSaturate:
+ case Op::I8x16addSaturateU:
+ case Op::I8x16subSaturateU:
+ case Op::I8x16and:
+ case Op::I8x16or:
+ case Op::I8x16xor:
+ case Op::I16x8add:
+ case Op::I16x8sub:
+ case Op::I16x8mul:
+ case Op::I16x8addSaturate:
+ case Op::I16x8subSaturate:
+ case Op::I16x8addSaturateU:
+ case Op::I16x8subSaturateU:
+ case Op::I16x8and:
+ case Op::I16x8or:
+ case Op::I16x8xor:
+ case Op::I32x4add:
+ case Op::I32x4sub:
+ case Op::I32x4mul:
+ case Op::I32x4and:
+ case Op::I32x4or:
+ case Op::I32x4xor:
+ case Op::F32x4add:
+ case Op::F32x4sub:
+ case Op::F32x4mul:
+ case Op::F32x4div:
+ case Op::F32x4min:
+ case Op::F32x4max:
+ case Op::F32x4minNum:
+ case Op::F32x4maxNum:
+ case Op::B8x16and:
+ case Op::B8x16or:
+ case Op::B8x16xor:
+ case Op::B16x8and:
+ case Op::B16x8or:
+ case Op::B16x8xor:
+ case Op::B32x4and:
+ case Op::B32x4or:
+ case Op::B32x4xor:
+ return OpKind::Binary;
+ case Op::I32Eq:
+ case Op::I32Ne:
+ case Op::I32LtS:
+ case Op::I32LtU:
+ case Op::I32LeS:
+ case Op::I32LeU:
+ case Op::I32GtS:
+ case Op::I32GtU:
+ case Op::I32GeS:
+ case Op::I32GeU:
+ case Op::I64Eq:
+ case Op::I64Ne:
+ case Op::I64LtS:
+ case Op::I64LtU:
+ case Op::I64LeS:
+ case Op::I64LeU:
+ case Op::I64GtS:
+ case Op::I64GtU:
+ case Op::I64GeS:
+ case Op::I64GeU:
+ case Op::F32Eq:
+ case Op::F32Ne:
+ case Op::F32Lt:
+ case Op::F32Le:
+ case Op::F32Gt:
+ case Op::F32Ge:
+ case Op::F64Eq:
+ case Op::F64Ne:
+ case Op::F64Lt:
+ case Op::F64Le:
+ case Op::F64Gt:
+ case Op::F64Ge:
+ return OpKind::Comparison;
+ case Op::I32Eqz:
+ case Op::I32WrapI64:
+ case Op::I32TruncSF32:
+ case Op::I32TruncUF32:
+ case Op::I32ReinterpretF32:
+ case Op::I32TruncSF64:
+ case Op::I32TruncUF64:
+ case Op::I64ExtendSI32:
+ case Op::I64ExtendUI32:
+ case Op::I64TruncSF32:
+ case Op::I64TruncUF32:
+ case Op::I64TruncSF64:
+ case Op::I64TruncUF64:
+ case Op::I64ReinterpretF64:
+ case Op::I64Eqz:
+ case Op::F32ConvertSI32:
+ case Op::F32ConvertUI32:
+ case Op::F32ReinterpretI32:
+ case Op::F32ConvertSI64:
+ case Op::F32ConvertUI64:
+ case Op::F32DemoteF64:
+ case Op::F64ConvertSI32:
+ case Op::F64ConvertUI32:
+ case Op::F64ConvertSI64:
+ case Op::F64ConvertUI64:
+ case Op::F64ReinterpretI64:
+ case Op::F64PromoteF32:
+ case Op::I32x4fromFloat32x4:
+ case Op::I32x4fromFloat32x4U:
+ case Op::F32x4fromInt32x4:
+ case Op::F32x4fromUint32x4:
+ case Op::I32x4fromFloat32x4Bits:
+ case Op::I32x4fromInt8x16Bits:
+ case Op::I32x4fromInt16x8Bits:
+ case Op::I16x8fromInt8x16Bits:
+ case Op::I16x8fromInt32x4Bits:
+ case Op::I16x8fromFloat32x4Bits:
+ case Op::I8x16fromInt16x8Bits:
+ case Op::I8x16fromInt32x4Bits:
+ case Op::I8x16fromFloat32x4Bits:
+ case Op::F32x4fromInt8x16Bits:
+ case Op::F32x4fromInt16x8Bits:
+ case Op::F32x4fromInt32x4Bits:
+ return OpKind::Conversion;
+ case Op::I32Load8S:
+ case Op::I32Load8U:
+ case Op::I32Load16S:
+ case Op::I32Load16U:
+ case Op::I64Load8S:
+ case Op::I64Load8U:
+ case Op::I64Load16S:
+ case Op::I64Load16U:
+ case Op::I64Load32S:
+ case Op::I64Load32U:
+ case Op::I32Load:
+ case Op::I64Load:
+ case Op::F32Load:
+ case Op::F64Load:
+ case Op::I8x16load:
+ case Op::I16x8load:
+ case Op::I32x4load:
+ case Op::I32x4load1:
+ case Op::I32x4load2:
+ case Op::I32x4load3:
+ case Op::F32x4load:
+ case Op::F32x4load1:
+ case Op::F32x4load2:
+ case Op::F32x4load3:
+ return OpKind::Load;
+ case Op::I32Store8:
+ case Op::I32Store16:
+ case Op::I64Store8:
+ case Op::I64Store16:
+ case Op::I64Store32:
+ case Op::I32Store:
+ case Op::I64Store:
+ case Op::F32Store:
+ case Op::F64Store:
+ return OpKind::Store;
+ case Op::I32TeeStore8:
+ case Op::I32TeeStore16:
+ case Op::I64TeeStore8:
+ case Op::I64TeeStore16:
+ case Op::I64TeeStore32:
+ case Op::I32TeeStore:
+ case Op::I64TeeStore:
+ case Op::F32TeeStore:
+ case Op::F64TeeStore:
+ case Op::F32TeeStoreF64:
+ case Op::F64TeeStoreF32:
+ case Op::I8x16store:
+ case Op::I16x8store:
+ case Op::I32x4store:
+ case Op::I32x4store1:
+ case Op::I32x4store2:
+ case Op::I32x4store3:
+ case Op::F32x4store:
+ case Op::F32x4store1:
+ case Op::F32x4store2:
+ case Op::F32x4store3:
+ return OpKind::TeeStore;
+ case Op::Select:
+ return OpKind::Select;
+ case Op::GetLocal:
+ return OpKind::GetLocal;
+ case Op::SetLocal:
+ return OpKind::SetLocal;
+ case Op::TeeLocal:
+ return OpKind::TeeLocal;
+ case Op::GetGlobal:
+ return OpKind::GetGlobal;
+ case Op::SetGlobal:
+ return OpKind::SetGlobal;
+ case Op::TeeGlobal:
+ return OpKind::TeeGlobal;
+ case Op::Call:
+ return OpKind::Call;
+ case Op::CallIndirect:
+ return OpKind::CallIndirect;
+ case Op::OldCallIndirect:
+ return OpKind::OldCallIndirect;
+ case Op::Return:
+ case Op::Limit:
// Accept Limit, for use in decoding the end of a function after the body.
- return ExprKind::Return;
- case Expr::If:
- return ExprKind::If;
- case Expr::Else:
- return ExprKind::Else;
- case Expr::End:
- return ExprKind::End;
- case Expr::I32AtomicsLoad:
- return ExprKind::AtomicLoad;
- case Expr::I32AtomicsStore:
- return ExprKind::AtomicStore;
- case Expr::I32AtomicsBinOp:
- return ExprKind::AtomicBinOp;
- case Expr::I32AtomicsCompareExchange:
- return ExprKind::AtomicCompareExchange;
- case Expr::I32AtomicsExchange:
- return ExprKind::AtomicExchange;
- case Expr::I8x16extractLane:
- case Expr::I8x16extractLaneU:
- case Expr::I16x8extractLane:
- case Expr::I16x8extractLaneU:
- case Expr::I32x4extractLane:
- case Expr::F32x4extractLane:
- case Expr::B8x16extractLane:
- case Expr::B16x8extractLane:
- case Expr::B32x4extractLane:
- return ExprKind::ExtractLane;
- case Expr::I8x16replaceLane:
- case Expr::I16x8replaceLane:
- case Expr::I32x4replaceLane:
- case Expr::F32x4replaceLane:
- case Expr::B8x16replaceLane:
- case Expr::B16x8replaceLane:
- case Expr::B32x4replaceLane:
- return ExprKind::ReplaceLane;
- case Expr::I8x16swizzle:
- case Expr::I16x8swizzle:
- case Expr::I32x4swizzle:
- case Expr::F32x4swizzle:
- return ExprKind::Swizzle;
- case Expr::I8x16shuffle:
- case Expr::I16x8shuffle:
- case Expr::I32x4shuffle:
- case Expr::F32x4shuffle:
- return ExprKind::Shuffle;
- case Expr::I16x8check:
- case Expr::I16x8splat:
- case Expr::I32x4check:
- case Expr::I32x4splat:
- case Expr::I8x16check:
- case Expr::I8x16splat:
- case Expr::F32x4check:
- case Expr::F32x4splat:
- case Expr::B16x8check:
- case Expr::B16x8splat:
- case Expr::B32x4check:
- case Expr::B32x4splat:
- case Expr::B8x16check:
- case Expr::B8x16splat:
- return ExprKind::Splat;
- case Expr::I8x16select:
- case Expr::I16x8select:
- case Expr::I32x4select:
- case Expr::F32x4select:
- return ExprKind::SimdSelect;
- case Expr::I8x16Constructor:
- case Expr::I16x8Constructor:
- case Expr::I32x4Constructor:
- case Expr::F32x4Constructor:
- case Expr::B8x16Constructor:
- case Expr::B16x8Constructor:
- case Expr::B32x4Constructor:
- return ExprKind::SimdCtor;
- case Expr::B8x16allTrue:
- case Expr::B8x16anyTrue:
- case Expr::B16x8allTrue:
- case Expr::B16x8anyTrue:
- case Expr::B32x4allTrue:
- case Expr::B32x4anyTrue:
- return ExprKind::SimdBooleanReduction;
- case Expr::I8x16shiftLeftByScalar:
- case Expr::I8x16shiftRightByScalar:
- case Expr::I8x16shiftRightByScalarU:
- case Expr::I16x8shiftLeftByScalar:
- case Expr::I16x8shiftRightByScalar:
- case Expr::I16x8shiftRightByScalarU:
- case Expr::I32x4shiftLeftByScalar:
- case Expr::I32x4shiftRightByScalar:
- case Expr::I32x4shiftRightByScalarU:
- return ExprKind::SimdShiftByScalar;
- case Expr::I8x16equal:
- case Expr::I8x16notEqual:
- case Expr::I8x16greaterThan:
- case Expr::I8x16greaterThanOrEqual:
- case Expr::I8x16lessThan:
- case Expr::I8x16lessThanOrEqual:
- case Expr::I8x16greaterThanU:
- case Expr::I8x16greaterThanOrEqualU:
- case Expr::I8x16lessThanU:
- case Expr::I8x16lessThanOrEqualU:
- case Expr::I16x8equal:
- case Expr::I16x8notEqual:
- case Expr::I16x8greaterThan:
- case Expr::I16x8greaterThanOrEqual:
- case Expr::I16x8lessThan:
- case Expr::I16x8lessThanOrEqual:
- case Expr::I16x8greaterThanU:
- case Expr::I16x8greaterThanOrEqualU:
- case Expr::I16x8lessThanU:
- case Expr::I16x8lessThanOrEqualU:
- case Expr::I32x4equal:
- case Expr::I32x4notEqual:
- case Expr::I32x4greaterThan:
- case Expr::I32x4greaterThanOrEqual:
- case Expr::I32x4lessThan:
- case Expr::I32x4lessThanOrEqual:
- case Expr::I32x4greaterThanU:
- case Expr::I32x4greaterThanOrEqualU:
- case Expr::I32x4lessThanU:
- case Expr::I32x4lessThanOrEqualU:
- case Expr::F32x4equal:
- case Expr::F32x4notEqual:
- case Expr::F32x4greaterThan:
- case Expr::F32x4greaterThanOrEqual:
- case Expr::F32x4lessThan:
- case Expr::F32x4lessThanOrEqual:
- return ExprKind::SimdComparison;
- case Expr::CurrentMemory:
- return ExprKind::CurrentMemory;
- case Expr::GrowMemory:
- return ExprKind::GrowMemory;
+ return OpKind::Return;
+ case Op::If:
+ return OpKind::If;
+ case Op::Else:
+ return OpKind::Else;
+ case Op::End:
+ return OpKind::End;
+ case Op::I32AtomicsLoad:
+ return OpKind::AtomicLoad;
+ case Op::I32AtomicsStore:
+ return OpKind::AtomicStore;
+ case Op::I32AtomicsBinOp:
+ return OpKind::AtomicBinOp;
+ case Op::I32AtomicsCompareExchange:
+ return OpKind::AtomicCompareExchange;
+ case Op::I32AtomicsExchange:
+ return OpKind::AtomicExchange;
+ case Op::I8x16extractLane:
+ case Op::I8x16extractLaneU:
+ case Op::I16x8extractLane:
+ case Op::I16x8extractLaneU:
+ case Op::I32x4extractLane:
+ case Op::F32x4extractLane:
+ case Op::B8x16extractLane:
+ case Op::B16x8extractLane:
+ case Op::B32x4extractLane:
+ return OpKind::ExtractLane;
+ case Op::I8x16replaceLane:
+ case Op::I16x8replaceLane:
+ case Op::I32x4replaceLane:
+ case Op::F32x4replaceLane:
+ case Op::B8x16replaceLane:
+ case Op::B16x8replaceLane:
+ case Op::B32x4replaceLane:
+ return OpKind::ReplaceLane;
+ case Op::I8x16swizzle:
+ case Op::I16x8swizzle:
+ case Op::I32x4swizzle:
+ case Op::F32x4swizzle:
+ return OpKind::Swizzle;
+ case Op::I8x16shuffle:
+ case Op::I16x8shuffle:
+ case Op::I32x4shuffle:
+ case Op::F32x4shuffle:
+ return OpKind::Shuffle;
+ case Op::I16x8check:
+ case Op::I16x8splat:
+ case Op::I32x4check:
+ case Op::I32x4splat:
+ case Op::I8x16check:
+ case Op::I8x16splat:
+ case Op::F32x4check:
+ case Op::F32x4splat:
+ case Op::B16x8check:
+ case Op::B16x8splat:
+ case Op::B32x4check:
+ case Op::B32x4splat:
+ case Op::B8x16check:
+ case Op::B8x16splat:
+ return OpKind::Splat;
+ case Op::I8x16select:
+ case Op::I16x8select:
+ case Op::I32x4select:
+ case Op::F32x4select:
+ return OpKind::SimdSelect;
+ case Op::I8x16Constructor:
+ case Op::I16x8Constructor:
+ case Op::I32x4Constructor:
+ case Op::F32x4Constructor:
+ case Op::B8x16Constructor:
+ case Op::B16x8Constructor:
+ case Op::B32x4Constructor:
+ return OpKind::SimdCtor;
+ case Op::B8x16allTrue:
+ case Op::B8x16anyTrue:
+ case Op::B16x8allTrue:
+ case Op::B16x8anyTrue:
+ case Op::B32x4allTrue:
+ case Op::B32x4anyTrue:
+ return OpKind::SimdBooleanReduction;
+ case Op::I8x16shiftLeftByScalar:
+ case Op::I8x16shiftRightByScalar:
+ case Op::I8x16shiftRightByScalarU:
+ case Op::I16x8shiftLeftByScalar:
+ case Op::I16x8shiftRightByScalar:
+ case Op::I16x8shiftRightByScalarU:
+ case Op::I32x4shiftLeftByScalar:
+ case Op::I32x4shiftRightByScalar:
+ case Op::I32x4shiftRightByScalarU:
+ return OpKind::SimdShiftByScalar;
+ case Op::I8x16equal:
+ case Op::I8x16notEqual:
+ case Op::I8x16greaterThan:
+ case Op::I8x16greaterThanOrEqual:
+ case Op::I8x16lessThan:
+ case Op::I8x16lessThanOrEqual:
+ case Op::I8x16greaterThanU:
+ case Op::I8x16greaterThanOrEqualU:
+ case Op::I8x16lessThanU:
+ case Op::I8x16lessThanOrEqualU:
+ case Op::I16x8equal:
+ case Op::I16x8notEqual:
+ case Op::I16x8greaterThan:
+ case Op::I16x8greaterThanOrEqual:
+ case Op::I16x8lessThan:
+ case Op::I16x8lessThanOrEqual:
+ case Op::I16x8greaterThanU:
+ case Op::I16x8greaterThanOrEqualU:
+ case Op::I16x8lessThanU:
+ case Op::I16x8lessThanOrEqualU:
+ case Op::I32x4equal:
+ case Op::I32x4notEqual:
+ case Op::I32x4greaterThan:
+ case Op::I32x4greaterThanOrEqual:
+ case Op::I32x4lessThan:
+ case Op::I32x4lessThanOrEqual:
+ case Op::I32x4greaterThanU:
+ case Op::I32x4greaterThanOrEqualU:
+ case Op::I32x4lessThanU:
+ case Op::I32x4lessThanOrEqualU:
+ case Op::F32x4equal:
+ case Op::F32x4notEqual:
+ case Op::F32x4greaterThan:
+ case Op::F32x4greaterThanOrEqual:
+ case Op::F32x4lessThan:
+ case Op::F32x4lessThanOrEqual:
+ return OpKind::SimdComparison;
+ case Op::CurrentMemory:
+ return OpKind::CurrentMemory;
+ case Op::GrowMemory:
+ return OpKind::GrowMemory;
}
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("unimplemented opcode");
}
#endif
--- a/js/src/wasm/WasmBinaryIterator.h
+++ b/js/src/wasm/WasmBinaryIterator.h
@@ -35,17 +35,17 @@ enum class LabelKind : uint8_t {
Loop,
Then,
UnreachableThen, // like Then, but not reachable
Else
};
#ifdef DEBUG
// Families of opcodes that share a signature and validation logic.
-enum class ExprKind {
+enum class OpKind {
Block,
Loop,
Unreachable,
Drop,
I32,
I64,
F32,
F64,
@@ -96,20 +96,20 @@ enum class ExprKind {
Splat,
SimdSelect,
SimdCtor,
SimdBooleanReduction,
SimdShiftByScalar,
SimdComparison,
};
-// Return the ExprKind for a given Expr. This is used for sanity-checking that
-// API users use the correct read function for a given Expr.
-ExprKind
-Classify(Expr expr);
+// Return the OpKind for a given Op. This is used for sanity-checking that
+// API users use the correct read function for a given Op.
+OpKind
+Classify(Op op);
#endif
// Common fields for linear memory access.
template <typename Value>
struct LinearMemoryAddress
{
Value base;
uint32_t offset;
@@ -225,19 +225,19 @@ class TypeAndValue<Nothing>
: type_(type)
{}
ValType type() const { return type_; }
Nothing value() const { return Nothing(); }
void setValue(Nothing value) {}
};
-// A policy class for configuring ExprIter. Clients can use this as a
+// A policy class for configuring OpIter. Clients can use this as a
// base class, and override the behavior as needed.
-struct ExprIterPolicy
+struct OpIterPolicy
{
// Should the iterator perform validation, such as type checking and
// validity checking?
static const bool Validate = false;
// Should the iterator produce output values?
static const bool Output = false;
@@ -250,31 +250,31 @@ struct ExprIterPolicy
// An iterator over the bytes of a function body. It performs validation
// (if Policy::Validate is true) and unpacks the data into a usable form.
//
// The MOZ_STACK_CLASS attribute here is because of the use of DebugOnly.
// There's otherwise nothing inherent in this class which would require
// it to be used on the stack.
template <typename Policy>
-class MOZ_STACK_CLASS ExprIter : private Policy
+class MOZ_STACK_CLASS OpIter : private Policy
{
static const bool Validate = Policy::Validate;
static const bool Output = Policy::Output;
typedef typename Policy::Value Value;
typedef typename Policy::ControlItem ControlItem;
Decoder& d_;
const size_t offsetInModule_;
- Vector<TypeAndValue<Value>, 0, SystemAllocPolicy> valueStack_;
- Vector<ControlStackEntry<ControlItem>, 0, SystemAllocPolicy> controlStack_;
+ Vector<TypeAndValue<Value>, 8, SystemAllocPolicy> valueStack_;
+ Vector<ControlStackEntry<ControlItem>, 8, SystemAllocPolicy> controlStack_;
bool reachable_;
- DebugOnly<Expr> expr_;
+ DebugOnly<Op> op_;
size_t offsetOfExpr_;
MOZ_MUST_USE bool readFixedU8(uint8_t* out) {
if (Validate)
return d_.readFixedU8(out);
*out = d_.uncheckedReadFixedU8();
return true;
}
@@ -498,48 +498,48 @@ class MOZ_STACK_CLASS ExprIter : private
valueStack_.shrinkTo(controlStack_.back().valueStackStart());
reachable_ = false;
}
bool checkBrValue(uint32_t relativeDepth, ExprType* type, Value* value);
bool checkBrIfValues(uint32_t relativeDepth, Value* condition, ExprType* type, Value* value);
public:
- explicit ExprIter(Decoder& decoder, uint32_t offsetInModule = 0)
+ explicit OpIter(Decoder& decoder, uint32_t offsetInModule = 0)
: d_(decoder), offsetInModule_(offsetInModule), reachable_(true),
- expr_(Expr::Limit), offsetOfExpr_(0)
+ op_(Op::Limit), offsetOfExpr_(0)
{}
// Return the decoding byte offset.
uint32_t currentOffset() const { return d_.currentOffset(); }
- // Returning the offset within the entire module of the last-read Expr.
+ // Returning the offset within the entire module of the last-read Op.
TrapOffset trapOffset() const {
return TrapOffset(offsetInModule_ + offsetOfExpr_);
}
// Test whether the iterator has reached the end of the buffer.
bool done() const { return d_.done(); }
// Report a general failure.
MOZ_MUST_USE bool fail(const char* msg) MOZ_COLD;
// Report an unimplemented feature.
MOZ_MUST_USE bool notYetImplemented(const char* what) MOZ_COLD;
// Report an unrecognized opcode.
- MOZ_MUST_USE bool unrecognizedOpcode(Expr expr) MOZ_COLD;
+ MOZ_MUST_USE bool unrecognizedOpcode(uint32_t expr) MOZ_COLD;
// Test whether the iterator is currently in "reachable" code.
bool inReachableCode() const { return reachable_; }
// ------------------------------------------------------------------------
// Decoding and validation interface.
- MOZ_MUST_USE bool readExpr(Expr* expr);
+ MOZ_MUST_USE bool readOp(uint16_t* op);
MOZ_MUST_USE bool readFunctionStart(ExprType ret);
MOZ_MUST_USE bool readFunctionEnd();
MOZ_MUST_USE bool readReturn(Value* value);
MOZ_MUST_USE bool readBlock();
MOZ_MUST_USE bool readLoop();
MOZ_MUST_USE bool readIf(Value* condition);
MOZ_MUST_USE bool readElse(ExprType* thenType, Value* thenValue);
MOZ_MUST_USE bool readEnd(LabelKind* kind, ExprType* type, Value* value);
@@ -658,92 +658,92 @@ class MOZ_STACK_CLASS ExprIter : private
// end of the function body.
bool controlStackEmpty() const {
return controlStack_.empty();
}
};
template <typename Policy>
bool
-ExprIter<Policy>::typeMismatch(ExprType actual, ExprType expected)
+OpIter<Policy>::typeMismatch(ExprType actual, ExprType expected)
{
MOZ_ASSERT(Validate);
MOZ_ASSERT(reachable_);
UniqueChars error(JS_smprintf("type mismatch: expression has type %s but expected %s",
ToCString(actual), ToCString(expected)));
if (!error)
return false;
return fail(error.get());
}
template <typename Policy>
inline bool
-ExprIter<Policy>::checkType(ValType actual, ValType expected)
+OpIter<Policy>::checkType(ValType actual, ValType expected)
{
return checkType(ToExprType(actual), ToExprType(expected));
}
template <typename Policy>
inline bool
-ExprIter<Policy>::checkType(ExprType actual, ExprType expected)
+OpIter<Policy>::checkType(ExprType actual, ExprType expected)
{
MOZ_ASSERT(reachable_);
if (!Validate) {
MOZ_ASSERT(actual == expected, "type mismatch");
return true;
}
if (MOZ_LIKELY(actual == expected))
return true;
return typeMismatch(actual, expected);
}
template <typename Policy>
bool
-ExprIter<Policy>::notYetImplemented(const char* what)
+OpIter<Policy>::notYetImplemented(const char* what)
{
UniqueChars error(JS_smprintf("not yet implemented: %s", what));
if (!error)
return false;
return fail(error.get());
}
template <typename Policy>
bool
-ExprIter<Policy>::unrecognizedOpcode(Expr expr)
+OpIter<Policy>::unrecognizedOpcode(uint32_t expr)
{
- UniqueChars error(JS_smprintf("unrecognized opcode: %x", uint32_t(expr)));
+ UniqueChars error(JS_smprintf("unrecognized opcode: %x", expr));
if (!error)
return false;
return fail(error.get());
}
template <typename Policy>
bool
-ExprIter<Policy>::fail(const char* msg)
+OpIter<Policy>::fail(const char* msg)
{
return d_.fail("%s", msg);
}
template <typename Policy>
inline bool
-ExprIter<Policy>::pushControl(LabelKind kind, ExprType type, bool reachable)
+OpIter<Policy>::pushControl(LabelKind kind, ExprType type, bool reachable)
{
return controlStack_.emplaceBack(kind, type, reachable, valueStack_.length());
}
template <typename Policy>
inline bool
-ExprIter<Policy>::mergeControl(LabelKind* kind, ExprType* type, Value* value)
+OpIter<Policy>::mergeControl(LabelKind* kind, ExprType* type, Value* value)
{
MOZ_ASSERT(!controlStack_.empty());
ControlStackEntry<ControlItem>& controlItem = controlStack_.back();
*kind = controlItem.kind();
if (reachable_) {
// Unlike branching, exiting a scope via fallthrough does not implicitly
@@ -781,17 +781,17 @@ ExprIter<Policy>::mergeControl(LabelKind
*value = Value();
}
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::popControl(LabelKind* kind, ExprType* type, Value* value)
+OpIter<Policy>::popControl(LabelKind* kind, ExprType* type, Value* value)
{
if (!mergeControl(kind, type, value))
return false;
if (*kind == LabelKind::Then) {
// A reachable If without an Else. Forbid a result value.
if (reachable_) {
if (Validate && !IsVoid(*type))
@@ -805,95 +805,97 @@ ExprIter<Policy>::popControl(LabelKind*
if (!reachable_ && !controlStack_.empty())
valueStack_.shrinkTo(controlStack_.back().valueStackStart());
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readBlockType(ExprType* type)
+OpIter<Policy>::readBlockType(ExprType* type)
{
- if (!d_.readBlockType(type))
+ uint8_t unchecked;
+ if (!d_.readBlockType(&unchecked))
return fail("unable to read block signature");
if (Validate) {
- switch (*type) {
- case ExprType::Void:
- case ExprType::I32:
- case ExprType::I64:
- case ExprType::F32:
- case ExprType::F64:
- case ExprType::I8x16:
- case ExprType::I16x8:
- case ExprType::I32x4:
- case ExprType::F32x4:
- case ExprType::B8x16:
- case ExprType::B16x8:
- case ExprType::B32x4:
+ switch (unchecked) {
+ case uint8_t(ExprType::Void):
+ case uint8_t(ExprType::I32):
+ case uint8_t(ExprType::I64):
+ case uint8_t(ExprType::F32):
+ case uint8_t(ExprType::F64):
+ case uint8_t(ExprType::I8x16):
+ case uint8_t(ExprType::I16x8):
+ case uint8_t(ExprType::I32x4):
+ case uint8_t(ExprType::F32x4):
+ case uint8_t(ExprType::B8x16):
+ case uint8_t(ExprType::B16x8):
+ case uint8_t(ExprType::B32x4):
break;
default:
return fail("invalid inline block type");
}
}
+ *type = ExprType(unchecked);
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readExpr(Expr* expr)
+OpIter<Policy>::readOp(uint16_t* op)
{
offsetOfExpr_ = d_.currentOffset();
if (Validate) {
- if (MOZ_UNLIKELY(!d_.readExpr(expr)))
+ if (MOZ_UNLIKELY(!d_.readOp(op)))
return fail("unable to read opcode");
} else {
- *expr = d_.uncheckedReadExpr();
+ *op = uint16_t(d_.uncheckedReadOp());
}
- expr_ = *expr;
+ op_ = Op(*op); // debug-only
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readFunctionStart(ExprType ret)
+OpIter<Policy>::readFunctionStart(ExprType ret)
{
MOZ_ASSERT(valueStack_.empty());
MOZ_ASSERT(controlStack_.empty());
- MOZ_ASSERT(Expr(expr_) == Expr::Limit);
+ MOZ_ASSERT(Op(op_) == Op::Limit);
MOZ_ASSERT(reachable_);
return pushControl(LabelKind::Block, ret, false);
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readFunctionEnd()
+OpIter<Policy>::readFunctionEnd()
{
if (Validate) {
if (!controlStack_.empty())
return fail("unbalanced function body control flow");
} else {
MOZ_ASSERT(controlStack_.empty());
}
- expr_ = Expr::Limit;
+ op_ = Op::Limit;
valueStack_.clear();
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readReturn(Value* value)
+OpIter<Policy>::readReturn(Value* value)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Return);
+ MOZ_ASSERT(Classify(op_) == OpKind::Return);
if (MOZ_LIKELY(reachable_)) {
ControlStackEntry<ControlItem>& controlItem = controlStack_[0];
MOZ_ASSERT(controlItem.kind() == LabelKind::Block);
controlItem.setReachable();
if (!IsVoid(controlItem.type())) {
@@ -903,45 +905,45 @@ ExprIter<Policy>::readReturn(Value* valu
}
enterUnreachableCode();
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readBlock()
+OpIter<Policy>::readBlock()
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Block);
+ MOZ_ASSERT(Classify(op_) == OpKind::Block);
ExprType type = ExprType::Limit;
if (!readBlockType(&type))
return false;
return pushControl(LabelKind::Block, type, false);
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readLoop()
+OpIter<Policy>::readLoop()
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Loop);
+ MOZ_ASSERT(Classify(op_) == OpKind::Loop);
ExprType type = ExprType::Limit;
if (!readBlockType(&type))
return false;
return pushControl(LabelKind::Loop, type, reachable_);
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readIf(Value* condition)
+OpIter<Policy>::readIf(Value* condition)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::If);
+ MOZ_ASSERT(Classify(op_) == OpKind::If);
ExprType type = ExprType::Limit;
if (!readBlockType(&type))
return false;
if (MOZ_LIKELY(reachable_)) {
if (!popWithType(ValType::I32, condition))
return false;
@@ -949,19 +951,19 @@ ExprIter<Policy>::readIf(Value* conditio
return pushControl(LabelKind::Then, type, false);
}
return pushControl(LabelKind::UnreachableThen, type, false);
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readElse(ExprType* thenType, Value* thenValue)
+OpIter<Policy>::readElse(ExprType* thenType, Value* thenValue)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Else);
+ MOZ_ASSERT(Classify(op_) == OpKind::Else);
// Finish up the then arm.
ExprType type = ExprType::Limit;
LabelKind kind;
if (!mergeControl(&kind, &type, thenValue))
return false;
if (Output)
@@ -981,36 +983,36 @@ ExprIter<Policy>::readElse(ExprType* the
MOZ_ASSERT(valueStack_.length() == controlStack_.back().valueStackStart());
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readEnd(LabelKind* kind, ExprType* type, Value* value)
+OpIter<Policy>::readEnd(LabelKind* kind, ExprType* type, Value* value)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::End);
+ MOZ_ASSERT(Classify(op_) == OpKind::End);
LabelKind validateKind = static_cast<LabelKind>(-1);
ExprType validateType = ExprType::Limit;
if (!popControl(&validateKind, &validateType, value))
return false;
if (Output) {
*kind = validateKind;
*type = validateType;
}
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::checkBrValue(uint32_t relativeDepth, ExprType* type, Value* value)
+OpIter<Policy>::checkBrValue(uint32_t relativeDepth, ExprType* type, Value* value)
{
if (MOZ_LIKELY(reachable_)) {
ControlStackEntry<ControlItem>* controlItem = nullptr;
if (!getControl(relativeDepth, &controlItem))
return false;
if (controlItem->kind() != LabelKind::Loop) {
controlItem->setReachable();
@@ -1029,19 +1031,19 @@ ExprIter<Policy>::checkBrValue(uint32_t
*value = Value();
}
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readBr(uint32_t* relativeDepth, ExprType* type, Value* value)
+OpIter<Policy>::readBr(uint32_t* relativeDepth, ExprType* type, Value* value)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Br);
+ MOZ_ASSERT(Classify(op_) == OpKind::Br);
uint32_t validateRelativeDepth;
if (!readVarU32(&validateRelativeDepth))
return fail("unable to read br depth");
if (!checkBrValue(validateRelativeDepth, type, value))
return false;
@@ -1049,17 +1051,17 @@ ExprIter<Policy>::readBr(uint32_t* relat
*relativeDepth = validateRelativeDepth;
enterUnreachableCode();
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::checkBrIfValues(uint32_t relativeDepth, Value* condition,
+OpIter<Policy>::checkBrIfValues(uint32_t relativeDepth, Value* condition,
ExprType* type, Value* value)
{
if (MOZ_LIKELY(reachable_)) {
if (!popWithType(ValType::I32, condition))
return false;
ControlStackEntry<ControlItem>* controlItem = nullptr;
if (!getControl(relativeDepth, &controlItem))
@@ -1082,39 +1084,39 @@ ExprIter<Policy>::checkBrIfValues(uint32
*value = Value();
}
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readBrIf(uint32_t* relativeDepth, ExprType* type, Value* value, Value* condition)
+OpIter<Policy>::readBrIf(uint32_t* relativeDepth, ExprType* type, Value* value, Value* condition)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::BrIf);
+ MOZ_ASSERT(Classify(op_) == OpKind::BrIf);
uint32_t validateRelativeDepth;
if (!readVarU32(&validateRelativeDepth))
return fail("unable to read br_if depth");
if (!checkBrIfValues(validateRelativeDepth, condition, type, value))
return false;
if (Output)
*relativeDepth = validateRelativeDepth;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readBrTable(uint32_t* tableLength, ExprType* type,
+OpIter<Policy>::readBrTable(uint32_t* tableLength, ExprType* type,
Value* value, Value* index)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::BrTable);
+ MOZ_ASSERT(Classify(op_) == OpKind::BrTable);
if (!readVarU32(tableLength))
return fail("unable to read br_table table length");
if (MOZ_LIKELY(reachable_)) {
if (!popWithType(ValType::I32, index))
return false;
}
@@ -1124,19 +1126,19 @@ ExprIter<Policy>::readBrTable(uint32_t*
if (Output)
*value = Value();
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readBrTableEntry(ExprType* type, Value* value, uint32_t* depth)
+OpIter<Policy>::readBrTableEntry(ExprType* type, Value* value, uint32_t* depth)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::BrTable);
+ MOZ_ASSERT(Classify(op_) == OpKind::BrTable);
if (!readVarU32(depth))
return false;
ExprType knownType = *type;
if (MOZ_LIKELY(reachable_)) {
ControlStackEntry<ControlItem>* controlItem = nullptr;
@@ -1166,114 +1168,114 @@ ExprIter<Policy>::readBrTableEntry(ExprT
*type = ExprType::Void;
if (Output)
*value = Value();
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readBrTableDefault(ExprType* type, Value* value, uint32_t* depth)
+OpIter<Policy>::readBrTableDefault(ExprType* type, Value* value, uint32_t* depth)
{
if (!readBrTableEntry(type, value, depth))
return false;
MOZ_ASSERT(!reachable_ || *type != ExprType::Limit);
enterUnreachableCode();
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readUnreachable()
+OpIter<Policy>::readUnreachable()
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Unreachable);
+ MOZ_ASSERT(Classify(op_) == OpKind::Unreachable);
enterUnreachableCode();
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readDrop()
+OpIter<Policy>::readDrop()
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Drop);
+ MOZ_ASSERT(Classify(op_) == OpKind::Drop);
if (!pop())
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readUnary(ValType operandType, Value* input)
+OpIter<Policy>::readUnary(ValType operandType, Value* input)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Unary);
+ MOZ_ASSERT(Classify(op_) == OpKind::Unary);
if (!popWithType(operandType, input))
return false;
infalliblePush(operandType);
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readConversion(ValType operandType, ValType resultType, Value* input)
+OpIter<Policy>::readConversion(ValType operandType, ValType resultType, Value* input)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Conversion);
+ MOZ_ASSERT(Classify(op_) == OpKind::Conversion);
if (!popWithType(operandType, input))
return false;
infalliblePush(resultType);
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readBinary(ValType operandType, Value* lhs, Value* rhs)
+OpIter<Policy>::readBinary(ValType operandType, Value* lhs, Value* rhs)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Binary);
+ MOZ_ASSERT(Classify(op_) == OpKind::Binary);
if (!popWithType(operandType, rhs))
return false;
if (!popWithType(operandType, lhs))
return false;
infalliblePush(operandType);
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readComparison(ValType operandType, Value* lhs, Value* rhs)
+OpIter<Policy>::readComparison(ValType operandType, Value* lhs, Value* rhs)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Comparison);
+ MOZ_ASSERT(Classify(op_) == OpKind::Comparison);
if (!popWithType(operandType, rhs))
return false;
if (!popWithType(operandType, lhs))
return false;
infalliblePush(ValType::I32);
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readLinearMemoryAddress(uint32_t byteSize, LinearMemoryAddress<Value>* addr)
+OpIter<Policy>::readLinearMemoryAddress(uint32_t byteSize, LinearMemoryAddress<Value>* addr)
{
uint8_t alignLog2;
if (!readFixedU8(&alignLog2))
return fail("unable to read load alignment");
uint32_t unusedOffset;
if (!readVarU32(Output ? &addr->offset : &unusedOffset))
return fail("unable to read load offset");
@@ -1288,96 +1290,95 @@ ExprIter<Policy>::readLinearMemoryAddres
if (Output)
addr->align = uint32_t(1) << alignLog2;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readLoad(ValType resultType, uint32_t byteSize,
- LinearMemoryAddress<Value>* addr)
+OpIter<Policy>::readLoad(ValType resultType, uint32_t byteSize, LinearMemoryAddress<Value>* addr)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Load);
+ MOZ_ASSERT(Classify(op_) == OpKind::Load);
if (!readLinearMemoryAddress(byteSize, addr))
return false;
infalliblePush(resultType);
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readStore(ValType resultType, uint32_t byteSize,
- LinearMemoryAddress<Value>* addr, Value* value)
+OpIter<Policy>::readStore(ValType resultType, uint32_t byteSize, LinearMemoryAddress<Value>* addr,
+ Value* value)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Store);
+ MOZ_ASSERT(Classify(op_) == OpKind::Store);
if (!popWithType(resultType, value))
return false;
if (!readLinearMemoryAddress(byteSize, addr))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readTeeStore(ValType resultType, uint32_t byteSize,
- LinearMemoryAddress<Value>* addr, Value* value)
+OpIter<Policy>::readTeeStore(ValType resultType, uint32_t byteSize, LinearMemoryAddress<Value>* addr,
+ Value* value)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::TeeStore);
+ MOZ_ASSERT(Classify(op_) == OpKind::TeeStore);
if (!popWithType(resultType, value))
return false;
if (!readLinearMemoryAddress(byteSize, addr))
return false;
infalliblePush(TypeAndValue<Value>(resultType, Output ? *value : Value()));
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readNop()
+OpIter<Policy>::readNop()
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Nop);
+ MOZ_ASSERT(Classify(op_) == OpKind::Nop);
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readCurrentMemory()
+OpIter<Policy>::readCurrentMemory()
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::CurrentMemory);
+ MOZ_ASSERT(Classify(op_) == OpKind::CurrentMemory);
uint32_t flags;
if (!readVarU32(&flags))
return false;
if (Validate && flags != uint32_t(MemoryTableFlags::Default))
return fail("unexpected flags");
if (!push(ValType::I32))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readGrowMemory(Value* input)
+OpIter<Policy>::readGrowMemory(Value* input)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::GrowMemory);
+ MOZ_ASSERT(Classify(op_) == OpKind::GrowMemory);
uint32_t flags;
if (!readVarU32(&flags))
return false;
if (Validate && flags != uint32_t(MemoryTableFlags::Default))
return fail("unexpected flags");
@@ -1386,19 +1387,19 @@ ExprIter<Policy>::readGrowMemory(Value*
infalliblePush(ValType::I32);
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readSelect(ValType* type, Value* trueValue, Value* falseValue, Value* condition)
+OpIter<Policy>::readSelect(ValType* type, Value* trueValue, Value* falseValue, Value* condition)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::Select);
+ MOZ_ASSERT(Classify(op_) == OpKind::Select);
if (!popWithType(ValType::I32, condition))
return false;
TypeAndValue<Value> false_;
if (!pop(&false_))
return false;
@@ -1418,19 +1419,19 @@ ExprIter<Policy>::readSelect(ValType* ty
*falseValue = false_.value();
}
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readGetLocal(const ValTypeVector& locals, uint32_t* id)
+OpIter<Policy>::readGetLocal(const ValTypeVector& locals, uint32_t* id)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::GetLocal);
+ MOZ_ASSERT(Classify(op_) == OpKind::GetLocal);
uint32_t validateId;
if (!readVarU32(&validateId))
return false;
if (Validate && validateId >= locals.length())
return fail("get_local index out of range");
@@ -1440,19 +1441,19 @@ ExprIter<Policy>::readGetLocal(const Val
if (Output)
*id = validateId;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readSetLocal(const ValTypeVector& locals, uint32_t* id, Value* value)
+OpIter<Policy>::readSetLocal(const ValTypeVector& locals, uint32_t* id, Value* value)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::SetLocal);
+ MOZ_ASSERT(Classify(op_) == OpKind::SetLocal);
uint32_t validateId;
if (!readVarU32(&validateId))
return false;
if (Validate && validateId >= locals.length())
return fail("set_local index out of range");
@@ -1462,19 +1463,19 @@ ExprIter<Policy>::readSetLocal(const Val
if (Output)
*id = validateId;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readTeeLocal(const ValTypeVector& locals, uint32_t* id, Value* value)
+OpIter<Policy>::readTeeLocal(const ValTypeVector& locals, uint32_t* id, Value* value)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::TeeLocal);
+ MOZ_ASSERT(Classify(op_) == OpKind::TeeLocal);
uint32_t validateId;
if (!readVarU32(&validateId))
return false;
if (Validate && validateId >= locals.length())
return fail("set_local index out of range");
@@ -1484,19 +1485,19 @@ ExprIter<Policy>::readTeeLocal(const Val
if (Output)
*id = validateId;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readGetGlobal(const GlobalDescVector& globals, uint32_t* id)
+OpIter<Policy>::readGetGlobal(const GlobalDescVector& globals, uint32_t* id)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::GetGlobal);
+ MOZ_ASSERT(Classify(op_) == OpKind::GetGlobal);
uint32_t validateId;
if (!readVarU32(&validateId))
return false;
if (Validate && validateId >= globals.length())
return fail("get_global index out of range");
@@ -1506,19 +1507,19 @@ ExprIter<Policy>::readGetGlobal(const Gl
if (Output)
*id = validateId;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readSetGlobal(const GlobalDescVector& globals, uint32_t* id, Value* value)
+OpIter<Policy>::readSetGlobal(const GlobalDescVector& globals, uint32_t* id, Value* value)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::SetGlobal);
+ MOZ_ASSERT(Classify(op_) == OpKind::SetGlobal);
uint32_t validateId;
if (!readVarU32(&validateId))
return false;
if (Validate && validateId >= globals.length())
return fail("set_global index out of range");
@@ -1531,19 +1532,19 @@ ExprIter<Policy>::readSetGlobal(const Gl
if (Output)
*id = validateId;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readTeeGlobal(const GlobalDescVector& globals, uint32_t* id, Value* value)
+OpIter<Policy>::readTeeGlobal(const GlobalDescVector& globals, uint32_t* id, Value* value)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::TeeGlobal);
+ MOZ_ASSERT(Classify(op_) == OpKind::TeeGlobal);
uint32_t validateId;
if (!readVarU32(&validateId))
return false;
if (Validate && validateId >= globals.length())
return fail("set_global index out of range");
@@ -1556,207 +1557,207 @@ ExprIter<Policy>::readTeeGlobal(const Gl
if (Output)
*id = validateId;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readI32Const(int32_t* i32)
+OpIter<Policy>::readI32Const(int32_t* i32)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::I32);
+ MOZ_ASSERT(Classify(op_) == OpKind::I32);
int32_t unused;
if (!readVarS32(Output ? i32 : &unused))
return false;
if (!push(ValType::I32))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readI64Const(int64_t* i64)
+OpIter<Policy>::readI64Const(int64_t* i64)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::I64);
+ MOZ_ASSERT(Classify(op_) == OpKind::I64);
int64_t unused;
if (!readVarS64(Output ? i64 : &unused))
return false;
if (!push(ValType::I64))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readF32Const(RawF32* f32)
+OpIter<Policy>::readF32Const(RawF32* f32)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::F32);
+ MOZ_ASSERT(Classify(op_) == OpKind::F32);
RawF32 unused;
if (!readFixedF32(Output ? f32 : &unused))
return false;
if (!push(ValType::F32))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readF64Const(RawF64* f64)
+OpIter<Policy>::readF64Const(RawF64* f64)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::F64);
+ MOZ_ASSERT(Classify(op_) == OpKind::F64);
RawF64 unused;
if (!readFixedF64(Output ? f64 : &unused))
return false;
if (!push(ValType::F64))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readI8x16Const(I8x16* i8x16)
+OpIter<Policy>::readI8x16Const(I8x16* i8x16)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::I8x16);
+ MOZ_ASSERT(Classify(op_) == OpKind::I8x16);
I8x16 unused;
if (!readFixedI8x16(Output ? i8x16 : &unused))
return false;
if (!push(ValType::I8x16))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readI16x8Const(I16x8* i16x8)
+OpIter<Policy>::readI16x8Const(I16x8* i16x8)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::I16x8);
+ MOZ_ASSERT(Classify(op_) == OpKind::I16x8);
I16x8 unused;
if (!readFixedI16x8(Output ? i16x8 : &unused))
return false;
if (!push(ValType::I16x8))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readI32x4Const(I32x4* i32x4)
+OpIter<Policy>::readI32x4Const(I32x4* i32x4)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::I32x4);
+ MOZ_ASSERT(Classify(op_) == OpKind::I32x4);
I32x4 unused;
if (!readFixedI32x4(Output ? i32x4 : &unused))
return false;
if (!push(ValType::I32x4))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readF32x4Const(F32x4* f32x4)
+OpIter<Policy>::readF32x4Const(F32x4* f32x4)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::F32x4);
+ MOZ_ASSERT(Classify(op_) == OpKind::F32x4);
F32x4 unused;
if (!readFixedF32x4(Output ? f32x4 : &unused))
return false;
if (!push(ValType::F32x4))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readB8x16Const(I8x16* i8x16)
+OpIter<Policy>::readB8x16Const(I8x16* i8x16)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::B8x16);
+ MOZ_ASSERT(Classify(op_) == OpKind::B8x16);
I8x16 unused;
if (!readFixedI8x16(Output ? i8x16 : &unused))
return false;
if (!push(ValType::B8x16))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readB16x8Const(I16x8* i16x8)
+OpIter<Policy>::readB16x8Const(I16x8* i16x8)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::B16x8);
+ MOZ_ASSERT(Classify(op_) == OpKind::B16x8);
I16x8 unused;
if (!readFixedI16x8(Output ? i16x8 : &unused))
return false;
if (!push(ValType::B16x8))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readB32x4Const(I32x4* i32x4)
+OpIter<Policy>::readB32x4Const(I32x4* i32x4)
{
- MOZ_ASSERT(Classify(expr_) == ExprKind::B32x4);
+ MOZ_ASSERT(Classify(op_) == OpKind::B32x4);
I32x4 unused;
if (!readFixedI32x4(Output ? i32x4 : &unused))
return false;
if (!push(ValType::B32x4))
return false;
return true;
}
template <typename Policy>
inline bool
-ExprIter<Policy>::readCall(uint32_t* calleeIndex)
+OpIter<Policy>::readCall(uint32_t* calleeIndex)
{