Merge inbound to mozilla-central. a=merge

This commit is contained in:
Csoregi Natalia 2018-07-27 00:58:11 +03:00
commit 3708e71462
480 changed files with 12099 additions and 45114 deletions

17
Cargo.lock generated
View file

@ -181,11 +181,11 @@ dependencies = [
[[package]]
name = "binjs_meta"
version = "0.3.6"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"Inflector 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"webidl 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -194,7 +194,7 @@ dependencies = [
name = "binsource"
version = "0.1.0"
dependencies = [
"binjs_meta 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"binjs_meta 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -947,14 +947,6 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itertools"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itertools"
version = "0.7.6"
@ -2551,7 +2543,7 @@ dependencies = [
"checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
"checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0"
"checksum bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1b25ab82877ea8fe6ce1ce1f8ac54361f0218bad900af9eb11803994bf67c221"
"checksum binjs_meta 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9fcfc86eecb125147e907529a5f1ac7978f6f26d20a52b82a7e053da5faefbc3"
"checksum binjs_meta 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fd7ca5635f1c6f94aaef7de76cb834c5920578355ce41dbcaf731b7ebe348518"
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
@ -2627,7 +2619,6 @@ dependencies = [
"checksum ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9826188e666f2ed92071d2dadef6edc430b11b158b5b2b3f4babbcc891eaaa"
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
"checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be"
"checksum itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3f2be4da1690a039e9ae5fd575f706a63ad5a2120f161b1d653c9da3930dd21"
"checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394"
"checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"

View file

@ -70,10 +70,7 @@ pref("extensions.geckoProfiler.getSymbolRules", "localBreakpad,dump_syms.exe");
pref("extensions.webextensions.base-content-security-policy", "script-src 'self' https://* moz-extension: blob: filesystem: 'unsafe-eval' 'unsafe-inline'; object-src 'self' https://* moz-extension: blob: filesystem:;");
pref("extensions.webextensions.default-content-security-policy", "script-src 'self'; object-src 'self';");
#if defined(XP_WIN) || defined(XP_MACOSX)
pref("extensions.webextensions.remote", true);
#endif
pref("extensions.webextensions.background-delayed-startup", true);
// Extensions that should not be flagged as legacy in about:addons

View file

@ -1023,7 +1023,7 @@ var gIdentityHandler = {
let block = document.createElement("vbox");
block.setAttribute("id", "identity-popup-popup-container");
menulist.setAttribute("sizetopopup", "none");
menulist.setAttribute("class", "identity-popup-popup-menulist subviewkeynav");
menulist.setAttribute("class", "identity-popup-popup-menulist");
menulist.setAttribute("id", "identity-popup-popup-menulist");
for (let state of SitePermissions.getAvailableStates(aPermission.id)) {
@ -1090,7 +1090,7 @@ var gIdentityHandler = {
}
let button = document.createElement("button");
button.setAttribute("class", "identity-popup-permission-remove-button subviewkeynav");
button.setAttribute("class", "identity-popup-permission-remove-button");
let tooltiptext = gNavigatorBundle.getString("permissions.remove.tooltip");
button.setAttribute("tooltiptext", tooltiptext);
button.addEventListener("command", () => {
@ -1146,7 +1146,7 @@ var gIdentityHandler = {
let text = document.createElement("label");
text.setAttribute("flex", "1");
text.setAttribute("class", "identity-popup-permission-label text-link subviewkeynav");
text.setAttribute("class", "identity-popup-permission-label text-link");
let popupCount = gBrowser.selectedBrowser.blockedPopups.length;
let messageBase = gNavigatorBundle.getString("popupShowBlockedPopupsIndicatorText");

View file

@ -47,7 +47,7 @@
</vbox>
</vbox>
<button id="identity-popup-security-expander"
class="identity-popup-expander subviewkeynav"
class="identity-popup-expander"
when-connection="not-secure secure secure-ev secure-cert-user-overridden"
oncommand="gIdentityHandler.showSecuritySubView();"/>
</hbox>
@ -84,22 +84,22 @@
crop="end">&trackingProtection.reloadRequired2;</description>
<button id="tracking-action-reload"
class="tracking-protection-button subviewkeynav"
class="tracking-protection-button"
label="&trackingProtection.reload2.label;"
accesskey="&trackingProtection.reload2.accesskey;"
oncommand="TrackingProtection.hideIdentityPopupAndReload();" />
<button id="tracking-action-unblock"
class="tracking-protection-button subviewkeynav"
class="tracking-protection-button"
label="&trackingProtection.unblock3.label;"
accesskey="&trackingProtection.unblock3.accesskey;"
oncommand="TrackingProtection.disableForCurrentPage();" />
<button id="tracking-action-unblock-private"
class="tracking-protection-button subviewkeynav"
class="tracking-protection-button"
label="&trackingProtection.unblockPrivate3.label;"
accesskey="&trackingProtection.unblockPrivate3.accesskey;"
oncommand="TrackingProtection.disableForCurrentPage();" />
<button id="tracking-action-block"
class="tracking-protection-button subviewkeynav"
class="tracking-protection-button"
label="&trackingProtection.block4.label;"
accesskey="&trackingProtection.block4.accesskey;"
oncommand="TrackingProtection.enableForCurrentPage();" />
@ -131,8 +131,7 @@
<vbox hidden="true"
id="identity-popup-clear-sitedata-footer"
class="identity-popup-footer">
<button class="subviewkeynav"
id="identity-popup-clear-sitedata-button"
<button id="identity-popup-clear-sitedata-button"
label="&identity.clearSiteData;"
oncommand="gIdentityHandler.clearSiteData(event);"/>
</vbox>
@ -167,7 +166,6 @@
<!-- Remove Certificate Exception -->
<button when-connection="secure-cert-user-overridden"
class="subviewkeynav"
label="&identity.removeCertException.label;"
accesskey="&identity.removeCertException.accesskey;"
oncommand="gIdentityHandler.removeCertException()"/>
@ -209,11 +207,11 @@
and-when-loginforms="insecure">&identity.description.activeLoaded; <label observes="identity-popup-mcb-learn-more"/></description>
<!-- Buttons to enable/disable mixed content blocking. -->
<button when-mixedcontent="active-blocked" class="subviewkeynav"
<button when-mixedcontent="active-blocked"
label="&identity.disableMixedContentBlocking.label;"
accesskey="&identity.disableMixedContentBlocking.accesskey;"
oncommand="gIdentityHandler.disableMixedContentProtection()"/>
<button when-mixedcontent="active-loaded" class="subviewkeynav"
<button when-mixedcontent="active-loaded"
label="&identity.enableMixedContentBlocking.label;"
accesskey="&identity.enableMixedContentBlocking.accesskey;"
oncommand="gIdentityHandler.enableMixedContentProtection()"/>
@ -221,7 +219,7 @@
<vbox id="identity-popup-more-info-footer" class="identity-popup-footer">
<!-- More Security Information -->
<button id="identity-popup-more-info" class="subviewkeynav"
<button id="identity-popup-more-info"
label="&identity.moreInfoLinkText2;"
oncommand="gIdentityHandler.handleMoreInfoClick(event);"/>
</vbox>

View file

@ -1357,17 +1357,29 @@ var PanelView = class extends AssociatedToNode {
}
/**
* Retrieves the button elements that can be used for navigation using the
* keyboard, that is all enabled buttons including the back button if visible.
* Array of enabled elements that can be selected with the keyboard. This
* means all buttons, menulists, and text links including the back button.
*
* @return {Array}
* This list is cached until the view is closed, so elements that become
* enabled later may not be navigable.
*/
_getNavigableElements() {
let buttons = Array.from(this.node.querySelectorAll(
".subviewbutton:not([disabled]), .subviewkeynav:not([disabled])"));
get _navigableElements() {
if (this.__navigableElements) {
return this.__navigableElements;
}
let navigableElements = Array.from(this.node.querySelectorAll(
":-moz-any(button,toolbarbutton,menulist,.text-link):not([disabled])"));
let dwu = this._dwu;
return buttons.filter(button => {
let bounds = dwu.getBoundsWithoutFlushing(button);
return this.__navigableElements = navigableElements.filter(element => {
// Set the "tabindex" attribute to make sure the element is focusable.
if (!element.hasAttribute("tabindex")) {
element.setAttribute("tabindex", "0");
}
if (element.hasAttribute("disabled")) {
return false;
}
let bounds = dwu.getBoundsWithoutFlushing(element);
return bounds.width > 0 && bounds.height > 0;
});
}
@ -1377,8 +1389,7 @@ var PanelView = class extends AssociatedToNode {
* is selected. Since the reference is held weakly, it can become null or
* undefined at any time.
*
* The element is usually, but not necessarily, in the "buttons" property
* which in turn is initialized from the _getNavigableElements list.
* The element is usually, but not necessarily, among the _navigableElements.
*/
get selectedElement() {
return this._selectedElement && this._selectedElement.get();
@ -1396,19 +1407,19 @@ var PanelView = class extends AssociatedToNode {
* This is a no-op if there are no navigable elements.
*/
focusFirstNavigableElement() {
this.selectedElement = this._getNavigableElements()[0];
this.selectedElement = this._navigableElements[0];
this.focusSelectedElement();
}
/**
* Based on going up or down, select the previous or next focusable button.
* Based on going up or down, select the previous or next focusable element.
*
* @param {Boolean} isDown whether we're going down (true) or up (false).
*
* @return {DOMNode} the button we selected.
* @return {DOMNode} the element we selected.
*/
moveSelection(isDown) {
let buttons = this.buttons;
let buttons = this._navigableElements;
let lastSelected = this.selectedElement;
let newButton = null;
let maxIdx = buttons.length - 1;
@ -1478,19 +1489,10 @@ var PanelView = class extends AssociatedToNode {
return;
}
let buttons = this.buttons;
if (!buttons || !buttons.length) {
buttons = this.buttons = this._getNavigableElements();
// Set the 'tabindex' attribute on the buttons to make sure they're focussable.
for (let button of buttons) {
if (!button.classList.contains("subviewbutton-back") &&
!button.hasAttribute("tabindex")) {
button.setAttribute("tabindex", 0);
}
}
}
if (!buttons.length)
let buttons = this._navigableElements;
if (!buttons.length) {
return;
}
let stop = () => {
event.stopPropagation();
@ -1559,7 +1561,7 @@ var PanelView = class extends AssociatedToNode {
* Clear all traces of keyboard navigation happening right now.
*/
clearNavigation() {
delete this.buttons;
delete this.__navigableElements;
let selected = this.selectedElement;
if (selected) {
selected.blur();

View file

@ -217,7 +217,6 @@
label="&trackingProtection.title;"/>
<toolbarseparator orient="vertical"/>
<toolbarbutton id="appMenu-tp-toggle"
class="subviewkeynav"
enabled="false"
oncommand="TrackingProtection.onGlobalToggleCommand();" />
</toolbaritem>

View file

@ -7,10 +7,19 @@
const {PanelView} = ChromeUtils.import("resource:///modules/PanelMultiView.jsm", {});
const kHelpButtonId = "appMenu-help-button";
function getEnabledNavigableElementsForView(panelView) {
return Array.from(panelView.querySelectorAll(
"button,toolbarbutton,menulist,.text-link"
)).filter(element => {
let bounds = element.getBoundingClientRect();
return !element.disabled && (bounds.width > 0 && bounds.height > 0);
});
}
add_task(async function testUpDownKeys() {
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView)._getNavigableElements();
let buttons = getEnabledNavigableElementsForView(PanelUI.mainView);
for (let button of buttons) {
if (button.disabled)
@ -39,7 +48,7 @@ add_task(async function testUpDownKeys() {
add_task(async function testEnterKeyBehaviors() {
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView)._getNavigableElements();
let buttons = getEnabledNavigableElementsForView(PanelUI.mainView);
// Navigate to the 'Help' button, which points to a subview.
EventUtils.synthesizeKey("KEY_ArrowUp");
@ -56,7 +65,7 @@ add_task(async function testEnterKeyBehaviors() {
EventUtils.synthesizeKey("KEY_Enter");
await promise;
let helpButtons = PanelView.forNode(PanelUI.helpView)._getNavigableElements();
let helpButtons = getEnabledNavigableElementsForView(PanelUI.helpView);
Assert.ok(helpButtons[0].classList.contains("subviewbutton-back"),
"First button in help view should be a back button");
@ -132,7 +141,7 @@ add_task(async function testLeftRightKeys() {
add_task(async function testTabKey() {
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView)._getNavigableElements();
let buttons = getEnabledNavigableElementsForView(PanelUI.mainView);
for (let button of buttons) {
if (button.disabled)
@ -165,7 +174,7 @@ add_task(async function testTabKey() {
add_task(async function testInterleavedTabAndArrowKeys() {
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView)._getNavigableElements();
let buttons = getEnabledNavigableElementsForView(PanelUI.mainView);
let tab = false;
for (let button of buttons) {
@ -188,7 +197,7 @@ add_task(async function testInterleavedTabAndArrowKeys() {
add_task(async function testSpaceDownAfterTabNavigation() {
await gCUITestUtils.openMainMenu();
let buttons = PanelView.forNode(PanelUI.mainView)._getNavigableElements();
let buttons = getEnabledNavigableElementsForView(PanelUI.mainView);
let button;
for (button of buttons) {

View file

@ -202,10 +202,12 @@ add_task(async function testBrowserActionTabPopulation() {
let widget = getBrowserActionWidget(extension).forWindow(win);
EventUtils.synthesizeMouseAtCenter(widget.node, {type: "mousedown", button: 0}, win);
await extension.awaitMessage("tabTitle");
await new Promise(resolve => setTimeout(resolve, 100));
EventUtils.synthesizeMouseAtCenter(widget.node, {type: "mouseup", button: 0}, win);
await extension.awaitMessage("tabTitle");
await extension.unload();
await BrowserTestUtils.closeWindow(win);
});

View file

@ -213,14 +213,6 @@
%include ../shared/toolbarbutton-icons.inc.css
%include ../shared/menupanel.inc.css
/* Override OSX-specific toolkit findbar button styles */
.findbar-button {
background: none;
box-shadow: none;
border: none;
color: inherit;
}
/* On Mac, native buttons keep their full opacity when they become disabled
* and only the glyph or text on top of them becomes less opaque. */
:root:not([customizing]) #back-button[disabled="true"] {

View file

@ -91,12 +91,6 @@ toolbar[brighttext] {
background-color: Highlight;
}
.findbar-button {
-moz-appearance: none;
padding: 0;
color: inherit;
}
toolbar .toolbarbutton-1 {
-moz-appearance: none;
margin: 0;

View file

@ -1346,3 +1346,20 @@ if CONFIG['MOZ_WAYLAND']:
'wayland-client.h',
'wayland-egl.h',
]
if CONFIG['MOZ_LIB_SECRET']:
system_headers += [
'libsecret/secret.h',
'libsecret/secret-attributes.h',
'libsecret/secret-collection.h',
'libsecret/secret-enum-types.h',
'libsecret/secret-item.h',
'libsecret/secret-password.h',
'libsecret/secret-paths.h',
'libsecret/secret-prompt.h',
'libsecret/secret-schema.h',
'libsecret/secret-schemas.h',
'libsecret/secret-types.h',
'libsecret/secret-value.h',
'libsecret/secret-service.h',
]

View file

@ -1,9 +1,9 @@
This is the debugger.html project output.
See https://github.com/devtools-html/debugger.html
Version 74
Version 75
Comparison: https://github.com/devtools-html/debugger.html/compare/release-73...release-74
Comparison: https://github.com/devtools-html/debugger.html/compare/release-74...release-75
Packages:
- babel-plugin-transform-es2015-modules-commonjs @6.26.2

View file

@ -55,8 +55,6 @@
.shortcuts-content {
padding: 15px;
-moz-column-width: 250px;
-webkit-column-width: 250px;
column-width: 250px;
cursor: default;
}

View file

@ -23171,8 +23171,9 @@ function buildMetaBindings(sourceId, node, ancestors, parentIndex = ancestors.le
};
}
// Consider "Object(foo)" to be equivalent to "foo"
if (t.isCallExpression(parent) && t.isIdentifier(parent.callee, { name: "Object" }) && parent.arguments.length === 1 && parent.arguments[0] === node) {
// Consider "Object(foo)", and "__webpack_require__.i(foo)" to be
// equivalent to "foo" since they are essentially identity functions.
if (t.isCallExpression(parent) && (t.isIdentifier(parent.callee, { name: "Object" }) || t.isMemberExpression(parent.callee, { computed: false }) && t.isIdentifier(parent.callee.object, { name: "__webpack_require__" }) && t.isIdentifier(parent.callee.property, { name: "i" })) && parent.arguments.length === 1 && parent.arguments[0] === node) {
return {
type: "inherit",
start: fromBabelLocation(parent.loc.start, sourceId),

View file

@ -44,11 +44,11 @@ function makeMarker(isDisabled) {
return bp;
}
class Breakpoint extends _react.Component {
constructor() {
super();
class Breakpoint extends _react.PureComponent {
constructor(...args) {
var _temp;
this.addBreakpoint = () => {
return _temp = super(...args), this.addBreakpoint = () => {
const {
breakpoint,
editor,
@ -75,7 +75,7 @@ class Breakpoint extends _react.Component {
} else {
editor.codeMirror.removeLineClass(line, "line", "has-condition");
}
};
}, _temp;
}
componentDidMount() {

View file

@ -168,7 +168,7 @@ class Editor extends _react.PureComponent {
continueToHere
} = this.props; // ignore right clicks in the gutter
if (ev.ctrlKey && ev.button === 0 || ev.which === 3 || selectedSource && selectedSource.isBlackBoxed || !selectedSource) {
if (ev.ctrlKey && ev.button === 0 || ev.button === 2 || selectedSource && selectedSource.isBlackBoxed || !selectedSource) {
return;
}
@ -343,6 +343,11 @@ class Editor extends _react.PureComponent {
const {
selectedSource
} = this.props;
if (!selectedSource) {
return;
}
const line = (0, _editor.getCursorLine)(codeMirror);
return (0, _editor.toSourceLine)(selectedSource.id, line);
}
@ -382,8 +387,9 @@ class Editor extends _react.PureComponent {
const {
setContextMenu
} = this.props;
const target = event.target;
if (event.target.classList.contains("CodeMirror-linenumber")) {
if (target.classList.contains("CodeMirror-linenumber")) {
return setContextMenu("Gutter", event);
}
@ -396,7 +402,7 @@ class Editor extends _react.PureComponent {
jumpToMappedLocation
} = this.props;
if (e.metaKey && e.altKey) {
if (selectedLocation && e.metaKey && e.altKey) {
const sourceLocation = (0, _editor.getSourceLocationFromMouseEvent)(this.state.editor, selectedLocation, e);
jumpToMappedLocation(sourceLocation);
}
@ -411,7 +417,7 @@ class Editor extends _react.PureComponent {
editor
} = this.state;
if (!editor || !nextProps.selectedSource || !nextProps.selectedLocation || !(0, _source.isLoaded)(nextProps.selectedSource)) {
if (!editor || !nextProps.selectedSource || !nextProps.selectedLocation || !nextProps.selectedLocation.line || !(0, _source.isLoaded)(nextProps.selectedSource)) {
return false;
}
@ -424,15 +430,19 @@ class Editor extends _react.PureComponent {
const {
editor
} = this.state;
const {
selectedLocation,
selectedSource
} = nextProps;
if (this.shouldScrollToLocation(nextProps)) {
if (selectedLocation && this.shouldScrollToLocation(nextProps)) {
let {
line,
column
} = (0, _editor.toEditorPosition)(nextProps.selectedLocation);
} = (0, _editor.toEditorPosition)(selectedLocation);
if ((0, _editor.hasDocument)(nextProps.selectedSource.id)) {
const doc = (0, _editor.getDocument)(nextProps.selectedSource.id);
if (selectedSource && (0, _editor.hasDocument)(selectedSource.id)) {
const doc = (0, _editor.getDocument)(selectedSource.id);
const lineText = doc.getLine(line);
column = Math.max(column, (0, _indentation.getIndentation)(lineText));
}

View file

@ -149,11 +149,11 @@ class CommandBar extends _react.Component {
canRewind
} = this.props;
if (canRewind) {
return;
}
if (isPaused) {
if (canRewind) {
return null;
}
return (0, _CommandBarButton.debugBtn)(() => this.resume(), "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume")));
}
@ -179,7 +179,7 @@ class CommandBar extends _react.Component {
}
const isDisabled = !isPaused;
return [(0, _CommandBarButton.debugBtn)(this.props.rewind, "rewind", "active", "Rewind Execution"), (0, _CommandBarButton.debugBtn)(() => this.props.resume, "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume"))), _react2.default.createElement("div", {
return [(0, _CommandBarButton.debugBtn)(this.props.rewind, "rewind", "active", "Rewind Execution"), (0, _CommandBarButton.debugBtn)(this.props.resume, "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume"))), _react2.default.createElement("div", {
key: "divider-1",
className: "divider"
}), (0, _CommandBarButton.debugBtn)(this.props.reverseStepOver, "reverseStepOver", "active", "Reverse step over"), (0, _CommandBarButton.debugBtn)(this.props.stepOver, "stepOver", "active", L10N.getFormatStr("stepOverTooltip", formatKey("stepOver")), isDisabled), _react2.default.createElement("div", {

View file

@ -68,10 +68,6 @@ var _FrameworkComponent = require("./FrameworkComponent");
var _FrameworkComponent2 = _interopRequireDefault(_FrameworkComponent);
var _ReactComponentStack = require("./ReactComponentStack");
var _ReactComponentStack2 = _interopRequireDefault(_ReactComponentStack);
var _Scopes = require("./Scopes");
var _Scopes2 = _interopRequireDefault(_Scopes);
@ -181,17 +177,6 @@ class SecondaryPanes extends _react.Component {
};
}
getComponentStackItem() {
return {
header: L10N.getStr("components.header"),
component: _react2.default.createElement(_ReactComponentStack2.default, null),
opened: _prefs.prefs.componentStackVisible,
onToggle: opened => {
_prefs.prefs.componentStackVisible = opened;
}
};
}
getComponentItem() {
const {
extra: {
@ -292,11 +277,7 @@ class SecondaryPanes extends _react.Component {
items.push(this.getCallStackItem());
if (this.props.horizontal) {
if (extra && extra.react) {
if (_prefs.features.componentStack && extra.react.componentStack.length > 1) {
items.push(this.getComponentStackItem());
}
if (_prefs.features.componentPane && extra && extra.react) {
items.push(this.getComponentItem());
}
@ -338,7 +319,7 @@ class SecondaryPanes extends _react.Component {
items.push(this.getWatchItem());
if (extra && extra.react) {
if (_prefs.features.componentPane && extra && extra.react) {
items.push(this.getComponentItem());
}

View file

@ -14,7 +14,6 @@ DevToolsModules(
'Expressions.js',
'FrameworkComponent.js',
'index.js',
'ReactComponentStack.js',
'Scopes.js',
'UtilsBar.js',
'Workers.js',

View file

@ -32,6 +32,7 @@ class Accordion extends _react.Component {
}, _react2.default.createElement("h2", {
className: "_header",
tabIndex: "0",
onKeyDown: e => this.onHandleHeaderKeyDown(e, i),
onClick: () => this.handleHeaderClick(i)
}, _react2.default.createElement(_Svg2.default, {
name: "arrow",
@ -64,6 +65,12 @@ class Accordion extends _react.Component {
this.forceUpdate();
}
onHandleHeaderKeyDown(e, i) {
if (e && (e.key === " " || e.key === "Enter")) {
this.handleHeaderClick(i);
}
}
render() {
return _react2.default.createElement("ul", {
role: "list",

View file

@ -160,7 +160,7 @@ function showSourceText(editor, source, symbols) {
const mode = (0, _source.getMode)(source, symbols);
const currentMode = editor.codeMirror.getOption("mode");
if (currentMode.name !== mode.name) {
if (currentMode.name != mode.name) {
editor.setMode(mode);
}

View file

@ -14,7 +14,13 @@ function getIndentation(line) {
return 0;
}
return line.match(/^\s*/)[0].length;
const lineMatch = line.match(/^\s*/);
if (!lineMatch) {
return 0;
}
return lineMatch[0].length;
}
function getMaxIndentation(lines) {

View file

@ -196,7 +196,12 @@ async function mapImportReferenceToDescriptor({
// ^^^ // binding
// vs
//
// Object(foo.bar)() // Webpack
// __webpack_require__.i(foo.bar)() // Webpack 2
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // mapping
// ^^^ // binding
// vs
//
// Object(foo.bar)() // Webpack >= 3
// ^^^^^^^^^^^^^^^ // mapping
// ^^^ // binding
//
@ -211,6 +216,13 @@ async function mapImportReferenceToDescriptor({
if (!(0, _mappingContains.mappingContains)(range, binding.loc)) {
return null;
} // Webpack 2's import declarations wrap calls with an identity fn, so we
// need to make sure to skip that binding because it is mapped to the
// location of the original binding usage.
if (binding.name === "__webpack_require__" && binding.loc.meta && binding.loc.meta.type === "member" && binding.loc.meta.property === "i") {
return null;
}
let expression = binding.name;

View file

@ -48,10 +48,8 @@ function formatPausePoints(text, pausePoints) {
break: breakPoint,
step
} = node.types;
const num = nodes.length - index;
const types = `${breakPoint ? "b" : ""}${step ? "s" : ""}`;
const spacer = breakPoint || step ? " " : "";
lines[line - 1] = insertStrtAt(lines[line - 1], column, `/*${types}${spacer}${num}*/`);
lines[line - 1] = insertStrtAt(lines[line - 1], column, `/*${types}*/`);
});
return lines.join("\n");
}

View file

@ -29,7 +29,6 @@ if (isDevelopment()) {
pref("devtools.debugger.call-stack-visible", true);
pref("devtools.debugger.scopes-visible", true);
pref("devtools.debugger.component-visible", true);
pref("devtools.debugger.component-stack-visible", false);
pref("devtools.debugger.workers-visible", true);
pref("devtools.debugger.expressions-visible", true);
pref("devtools.debugger.breakpoints-visible", true);
@ -62,9 +61,8 @@ if (isDevelopment()) {
pref("devtools.debugger.features.column-breakpoints", true);
pref("devtools.debugger.features.replay", true);
pref("devtools.debugger.features.pause-points", true);
pref("devtools.debugger.features.skip-pausing", false);
pref("devtools.debugger.features.component-pane", false);
pref("devtools.debugger.features.skip-pausing", true);
pref("devtools.debugger.features.component-pane", false);
pref("devtools.debugger.features.autocomplete-expressions", false);
pref("devtools.debugger.features.map-expression-bindings", true);
}
@ -79,7 +77,6 @@ const prefs = exports.prefs = new PrefsHelper("devtools", {
callStackVisible: ["Bool", "debugger.call-stack-visible"],
scopesVisible: ["Bool", "debugger.scopes-visible"],
componentVisible: ["Bool", "debugger.component-visible"],
componentStackVisible: ["Bool", "debugger.component-stack-visible"],
workersVisible: ["Bool", "debugger.workers-visible"],
breakpointsVisible: ["Bool", "debugger.breakpoints-visible"],
expressionsVisible: ["Bool", "debugger.expressions-visible"],
@ -115,7 +112,8 @@ const features = exports.features = new PrefsHelper("devtools.debugger.features"
pausePoints: ["Bool", "pause-points"],
skipPausing: ["Bool", "skip-pausing"],
autocompleteExpression: ["Bool", "autocomplete-expressions"],
mapExpressionBindings: ["Bool", "map-expression-bindings"]
mapExpressionBindings: ["Bool", "map-expression-bindings"],
componentPane: ["Bool", "component-pane"]
});
if (prefs.debuggerPrefsSchemaVersion !== prefsSchemaVersion) {

View file

@ -29,7 +29,6 @@ pref("devtools.debugger.ui.variables-only-enum-visible", false);
pref("devtools.debugger.ui.variables-searchbox-visible", false);
pref("devtools.debugger.ui.framework-grouping-on", true);
pref("devtools.debugger.call-stack-visible", true);
pref("devtools.debugger.component-stack-visible", true);
pref("devtools.debugger.scopes-visible", true);
pref("devtools.debugger.component-visible", true);
pref("devtools.debugger.workers-visible", true);
@ -62,7 +61,7 @@ pref("devtools.debugger.features.code-folding", false);
pref("devtools.debugger.features.outline", true);
pref("devtools.debugger.features.replay", false);
pref("devtools.debugger.features.pause-points", true);
pref("devtools.debugger.features.component-stack", false);
pref("devtools.debugger.features.component-pane", false);
pref("devtools.debugger.features.async-stepping", true);
pref("devtools.debugger.features.skip-pausing", true);
pref("devtools.debugger.features.autocomplete-expressions", false);

View file

@ -325,7 +325,7 @@ define(function(require, exports, module) {
// Display the menu only if there is not enough horizontal
// space for all tabs (and overflow happened).
const allTabsMenu = this.state.overflow ? (
dom.div({
dom.button({
className: "all-tabs-menu",
onClick: this.props.onAllTabsMenuClick,
})

View file

@ -755,12 +755,24 @@ checkbox:-moz-focusring {
width: 15px;
height: 100%;
padding: 0;
border: none;
border-inline-start: 1px solid var(--theme-splitter-color);
background: var(--theme-tab-toolbar-background);
background-image: url("chrome://devtools/skin/images/dropmarker.svg");
background-repeat: no-repeat;
background-position: center;
-moz-context-properties: fill;
fill: var(--theme-toolbar-photon-icon-color);
}
.all-tabs-menu:hover {
background-color: var(--theme-toolbar-hover);
}
.all-tabs-menu:hover:active {
background-color: var(--theme-toolbar-hover-active);
}
.devtools-tab-line {
@ -770,7 +782,7 @@ checkbox:-moz-focusring {
width: 100%;
height: 2px;
background: transparent;
transition: transform 250ms var(--animation-easing-function), opacity 250ms var(--animation-easing-function);
transition: transform 250ms var(--animation-curve), opacity 250ms var(--animation-curve);
opacity: 0;
transform: scaleX(0);
}

View file

@ -1,6 +1,6 @@
<!-- 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/. -->
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="4" viewBox="0 0 8 4">
<polygon points="0,0 4,4 8,0" fill="#b6babf"/>
</svg>
<!-- 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/. -->
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="4" viewBox="0 0 8 4">
<polygon points="0,0 4,4 8,0" fill="context-fill #b6babf"/>
</svg>

Before

Width:  |  Height:  |  Size: 354 B

After

Width:  |  Height:  |  Size: 361 B

View file

@ -930,13 +930,6 @@ exports.AnimationsActor = protocol.ActorClassWithSpec(animationsSpec, {
* @param {Object} player
*/
pauseSync(player) {
// Gecko includes an optimization that means that if the animation is play-pending
// and we set the startTime to null, the change will be ignored and the animation
// will continue to be play-pending. This violates the spec but until the spec is
// clarified[1] on this point we work around this by ensuring the animation's
// startTime is set to something non-null before setting it to null.
// [1] https://github.com/w3c/csswg-drafts/issues/2691
this.playSync(player);
player.startTime = null;
},

View file

@ -45,7 +45,6 @@ const FLEXBOX_CONTAINER_PATTERN_HEIGHT = 14; // px
const FLEXBOX_JUSTIFY_CONTENT_PATTERN_WIDTH = 7; // px
const FLEXBOX_JUSTIFY_CONTENT_PATTERN_HEIGHT = 7; // px
const FLEXBOX_CONTAINER_PATTERN_LINE_DISH = [5, 3]; // px
const BASIS_FILL_COLOR = "rgb(109, 184, 255, 0.4)";
/**
* Cached used by `FlexboxHighlighter.getFlexContainerPattern`.
@ -66,9 +65,6 @@ const JUSTIFY_CONTENT = "justify-content";
* - showAlignment(isShown)
* @param {Boolean} isShown
* Shows the alignment in the flexbox highlighter.
* - showFlexBasis(isShown)
* @param {Boolean} isShown
* Shows the flex basis in the flexbox highlighter.
*/
class FlexboxHighlighter extends AutoRefreshHighlighter {
constructor(highlighterEnv) {
@ -296,10 +292,6 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
this.alignItemsValue = this.computedStyle.alignItems;
const newAlignItems = this.alignItemsValue;
const oldFlexBasis = this.flexBasis;
this.flexBasis = this.computedStyle.flexBasis;
const newFlexBasis = this.flexBasis;
const oldFlexDirection = this.flexDirection;
this.flexDirection = this.computedStyle.flexDirection;
const newFlexDirection = this.flexDirection;
@ -315,7 +307,6 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
return hasMoved ||
hasFlexDataChanged ||
oldAlignItems !== newAlignItems ||
oldFlexBasis !== newFlexBasis ||
oldFlexDirection !== newFlexDirection ||
oldFlexWrap !== newFlexWrap ||
oldJustifyContent !== newJustifyContent;
@ -324,7 +315,6 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
_hide() {
this.alignItemsValue = null;
this.computedStyle = null;
this.flexBasis = null;
this.flexData = null;
this.flexDirection = null;
this.flexWrap = null;
@ -542,28 +532,6 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
this.ctx.restore();
}
/**
* Renders the flex basis for a given flex item.
*/
renderFlexItemBasis(flexItem, left, top, right, bottom, boundsWidth) {
if (!this.options.showFlexBasis || !this.computedStyle) {
return;
}
let basis = this.flexBasis;
if (basis.endsWith("px")) {
right = Math.round(left + parseFloat(basis));
} else if (basis.endsWith("%")) {
basis = parseFloat(basis) / 100 * boundsWidth;
right = Math.round(left + basis);
}
this.ctx.fillStyle = BASIS_FILL_COLOR;
drawRect(this.ctx, left, top, right, bottom, this.currentMatrix);
this.ctx.fill();
}
renderFlexItems() {
if (!this.flexData || !this.currentQuads.content || !this.currentQuads.content[0]) {
return;
@ -600,8 +568,6 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
clearRect(this.ctx, left, top, right, bottom, this.currentMatrix);
drawRect(this.ctx, left, top, right, bottom, this.currentMatrix);
this.ctx.stroke();
this.renderFlexItemBasis(flexItem.node, left, top, right, bottom, bounds.width);
}
}

View file

@ -677,6 +677,7 @@ nsDocShell::LoadURI(nsIURI* aURI,
nsCOMPtr<nsIURI> referrer;
nsCOMPtr<nsIURI> originalURI;
Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
bool keepResultPrincipalURIIfSet = false;
bool loadReplace = false;
nsCOMPtr<nsIInputStream> postStream;
nsCOMPtr<nsIInputStream> headersStream;
@ -708,6 +709,7 @@ nsDocShell::LoadURI(nsIURI* aURI,
referrer = aLoadInfo->Referrer();
originalURI = aLoadInfo->OriginalURI();
aLoadInfo->GetMaybeResultPrincipalURI(resultPrincipalURI);
keepResultPrincipalURIIfSet = aLoadInfo->KeepResultPrincipalURIIfSet();
loadReplace = aLoadInfo->LoadReplace();
// Get the appropriate loadType from nsIDocShellLoadInfo type
loadType = aLoadInfo->LoadType();
@ -1001,6 +1003,7 @@ nsDocShell::LoadURI(nsIURI* aURI,
return InternalLoad(aURI,
originalURI,
resultPrincipalURI,
keepResultPrincipalURIIfSet,
loadReplace,
referrer,
referrerPolicy,
@ -4798,7 +4801,7 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
NS_ENSURE_SUCCESS(rv, rv);
return InternalLoad(errorPageURI, nullptr, Nothing(), false, nullptr, RP_Unset,
return InternalLoad(errorPageURI, nullptr, Nothing(), false, false, nullptr, RP_Unset,
nsContentUtils::GetSystemPrincipal(), nullptr,
INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
nullptr, VoidString(), nullptr, nullptr,
@ -4893,6 +4896,7 @@ nsDocShell::Reload(uint32_t aReloadFlags)
rv = InternalLoad(currentURI,
originalURI,
emplacedResultPrincipalURI,
false,
loadReplace,
referrerURI,
referrerPolicy,
@ -6184,6 +6188,11 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, int32_t aDel
*/
loadInfo->SetReferrer(mCurrentURI);
loadInfo->SetOriginalURI(mCurrentURI);
loadInfo->SetResultPrincipalURI(aURI);
loadInfo->SetResultPrincipalURIIsSome(true);
loadInfo->SetKeepResultPrincipalURIIfSet(true);
// Set the triggering pricipal to aPrincipal if available, or current
// document's principal otherwise.
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
@ -9003,6 +9012,7 @@ public:
nsIURI* aURI,
nsIURI* aOriginalURI,
Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
bool aKeepResultPrincipalURIIfSet,
bool aLoadReplace,
nsIURI* aReferrer, uint32_t aReferrerPolicy,
nsIPrincipal* aTriggeringPrincipal,
@ -9023,6 +9033,7 @@ public:
, mURI(aURI)
, mOriginalURI(aOriginalURI)
, mResultPrincipalURI(aResultPrincipalURI)
, mKeepResultPrincipalURIIfSet(aKeepResultPrincipalURIIfSet)
, mLoadReplace(aLoadReplace)
, mReferrer(aReferrer)
, mReferrerPolicy(aReferrerPolicy)
@ -9049,6 +9060,7 @@ public:
Run() override
{
return mDocShell->InternalLoad(mURI, mOriginalURI, mResultPrincipalURI,
mKeepResultPrincipalURIIfSet,
mLoadReplace,
mReferrer,
mReferrerPolicy,
@ -9071,6 +9083,7 @@ private:
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mOriginalURI;
Maybe<nsCOMPtr<nsIURI>> mResultPrincipalURI;
bool mKeepResultPrincipalURIIfSet;
bool mLoadReplace;
nsCOMPtr<nsIURI> mReferrer;
uint32_t mReferrerPolicy;
@ -9117,6 +9130,7 @@ NS_IMETHODIMP
nsDocShell::InternalLoad(nsIURI* aURI,
nsIURI* aOriginalURI,
Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
bool aKeepResultPrincipalURIIfSet,
bool aLoadReplace,
nsIURI* aReferrer,
uint32_t aReferrerPolicy,
@ -9415,6 +9429,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER));
loadInfo->SetOriginalURI(aOriginalURI);
loadInfo->SetMaybeResultPrincipalURI(aResultPrincipalURI);
loadInfo->SetKeepResultPrincipalURIIfSet(aKeepResultPrincipalURIIfSet);
loadInfo->SetLoadReplace(aLoadReplace);
loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
loadInfo->SetInheritPrincipal(
@ -9464,6 +9479,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
rv = targetDocShell->InternalLoad(aURI,
aOriginalURI,
aResultPrincipalURI,
aKeepResultPrincipalURIIfSet,
aLoadReplace,
aReferrer,
aReferrerPolicy,
@ -9562,6 +9578,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
// Do this asynchronously
nsCOMPtr<nsIRunnable> ev =
new InternalLoadEvent(this, aURI, aOriginalURI, aResultPrincipalURI,
aKeepResultPrincipalURIIfSet,
aLoadReplace, aReferrer, aReferrerPolicy,
aTriggeringPrincipal, principalToInherit,
aFlags, aTypeHint, aPostData,
@ -10079,7 +10096,8 @@ nsDocShell::InternalLoad(nsIURI* aURI,
nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
nsCOMPtr<nsIRequest> req;
rv = DoURILoad(aURI, aOriginalURI, aResultPrincipalURI, aLoadReplace,
rv = DoURILoad(aURI, aOriginalURI, aResultPrincipalURI,
aKeepResultPrincipalURIIfSet, aLoadReplace,
loadFromExternal,
(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI),
(aFlags & INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC),
@ -10219,6 +10237,7 @@ nsresult
nsDocShell::DoURILoad(nsIURI* aURI,
nsIURI* aOriginalURI,
Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
bool aKeepResultPrincipalURIIfSet,
bool aLoadReplace,
bool aLoadFromExternal,
bool aForceAllowDataURI,
@ -10568,7 +10587,10 @@ nsDocShell::DoURILoad(nsIURI* aURI,
channel->SetOriginalURI(aURI);
}
if (aResultPrincipalURI) {
nsCOMPtr<nsIURI> rpURI;
loadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
if (aResultPrincipalURI &&
(!aKeepResultPrincipalURIIfSet || !rpURI)) {
// Unconditionally override, we want the replay to be equal to what has
// been captured.
loadInfo->SetResultPrincipalURI(aResultPrincipalURI.ref());
@ -12145,6 +12167,7 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
rv = InternalLoad(uri,
originalURI,
emplacedResultPrincipalURI,
false,
loadReplace,
referrerURI,
referrerPolicy,
@ -13424,6 +13447,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
nsresult rv = InternalLoad(aURI, // New URI
nullptr, // Original URI
Nothing(), // Let the protocol handler assign it
false,
false, // LoadReplace
referer, // Referer URI
refererPolicy, // Referer policy

View file

@ -520,6 +520,7 @@ private: // member functions
nsresult DoURILoad(nsIURI* aURI,
nsIURI* aOriginalURI,
mozilla::Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
bool aKeepResultPrincipalURIIfSet,
bool aLoadReplace,
bool aLoadFromExternal,
bool aForceAllowDataURI,

View file

@ -20,6 +20,7 @@ namespace mozilla {
nsDocShellLoadInfo::nsDocShellLoadInfo()
: mResultPrincipalURIIsSome(false)
, mKeepResultPrincipalURIIfSet(false)
, mLoadReplace(false)
, mInheritPrincipal(false)
, mPrincipalIsExplicit(false)
@ -84,6 +85,18 @@ nsDocShellLoadInfo::SetResultPrincipalURIIsSome(bool aIsSome)
mResultPrincipalURIIsSome = aIsSome;
}
bool
nsDocShellLoadInfo::KeepResultPrincipalURIIfSet() const
{
return mKeepResultPrincipalURIIfSet;
}
void
nsDocShellLoadInfo::SetKeepResultPrincipalURIIfSet(bool aKeep)
{
mKeepResultPrincipalURIIfSet = aKeep;
}
bool
nsDocShellLoadInfo::LoadReplace() const
{

View file

@ -45,6 +45,10 @@ public:
void SetResultPrincipalURIIsSome(bool aIsSome);
bool KeepResultPrincipalURIIfSet() const;
void SetKeepResultPrincipalURIIfSet(bool aKeep);
bool LoadReplace() const;
void SetLoadReplace(bool aLoadReplace);
@ -140,6 +144,10 @@ protected:
// will be identical.
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
// if http-equiv="refresh" cause reload we do not want to replace
// ResultPrinicpalURI if it was already set.
bool mKeepResultPrincipalURIIfSet;
// loadReplace flag to be passed to nsIDocShell.internalLoad.
bool mLoadReplace;

View file

@ -132,6 +132,13 @@ interface nsIDocShell : nsIDocShellTreeItem
* When Nothing, there will be no change
* When Some, the principal URI will overwrite even
* with a null value.
* @param aKeepResultPrincipalURIIfSet - If a refresh is caused by
* http-equiv="refresh" we want to set
* aResultPrincipalURI, but we do not want
* to overwrite the channel's
* ResultPrincipalURI, if it has already
* been set on the channel by a protocol
* handler.
* @param aLoadReplace - If set LOAD_REPLACE flag will be set on the
* channel. aOriginalURI is null, this argument is
* ignored.
@ -180,6 +187,7 @@ interface nsIDocShell : nsIDocShellTreeItem
[noscript]void internalLoad(in nsIURI aURI,
in nsIURI aOriginalURI,
[const] in MaybeURI aResultPrincipalURI,
in bool aKeepResultPrincipalURIIfSet,
in boolean aLoadReplace,
in nsIURI aReferrer,
in unsigned long aReferrerPolicy,

View file

@ -227,7 +227,11 @@ Animation::SetTimelineNoUpdate(AnimationTimeline* aTimeline)
void
Animation::SetStartTime(const Nullable<TimeDuration>& aNewStartTime)
{
if (aNewStartTime == mStartTime) {
// Return early if the start time will not change. However, if we
// are pending, then setting the start time to any value
// including the current value has the effect of aborting
// pending tasks so we should not return early in that case.
if (!Pending() && aNewStartTime == mStartTime) {
return;
}

View file

@ -26,6 +26,7 @@
#include "nsTextNode.h"
#include "mozAutoDocUpdate.h"
#include "nsWrapperCacheInlines.h"
#include "NodeUbiReporting.h"
namespace mozilla {
namespace dom {
@ -308,5 +309,11 @@ Attr::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
return Attr_Binding::Wrap(aCx, this, aGivenProto);
}
void
Attr::ConstructUbiNode(void* storage)
{
JS::ubi::Concrete<Attr>::construct(storage, this);
}
} // namespace dom
} // namespace mozilla

View file

@ -51,6 +51,8 @@ public:
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
void ConstructUbiNode(void* storage) override;
nsDOMAttributeMap* GetMap()
{
return mAttrMap;

View file

@ -125,6 +125,8 @@
#include "nsChildContentList.h"
#include "mozilla/BloomFilter.h"
#include "NodeUbiReporting.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -445,6 +447,12 @@ nsIContent::GetURLDataForStyleAttr(nsIPrincipal* aSubjectPrincipal) const
return do_AddRef(OwnerDoc()->DefaultStyleAttrURLData());
}
void
nsIContent::ConstructUbiNode(void* storage)
{
JS::ubi::Concrete<nsIContent>::construct(storage, this);
}
//----------------------------------------------------------------------
static inline JSObject*

View file

@ -30,6 +30,7 @@
#include "nsContentUtils.h"
#include "nsUnicharUtils.h"
#include "mozilla/Preferences.h"
#include "mozilla/StaticPrefs.h"
#include "mozilla/Telemetry.h"
#include "BatteryManager.h"
#include "mozilla/dom/CredentialsContainer.h"
@ -519,9 +520,8 @@ Navigator::Storage()
bool
Navigator::CookieEnabled()
{
bool cookieEnabled =
(Preferences::GetInt("network.cookie.cookieBehavior",
COOKIE_BEHAVIOR_REJECT) != COOKIE_BEHAVIOR_REJECT);
bool cookieEnabled = (StaticPrefs::network_cookie_cookieBehavior() !=
COOKIE_BEHAVIOR_REJECT);
// Check whether an exception overrides the global cookie behavior
// Note that the code for getting the URI here matches that in

View file

@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "NodeUbiReporting.h"
#include "js/UbiNodeUtils.h"
#include "nsWindowSizes.h"
using JS::ubi::SimpleEdgeRange;
using JS::ubi::EdgeRange;
const char16_t JS::ubi::Concrete<nsIDocument>::concreteTypeName[] = u"nsIDocument";
const char16_t JS::ubi::Concrete<nsIContent>::concreteTypeName[] = u"nsIContent";
const char16_t JS::ubi::Concrete<Attr>::concreteTypeName[] = u"Attr";
void
JS::ubi::Concrete<nsINode>::construct(void* storage, nsINode* ptr)
{
// nsINode is abstract, and all of its inherited instances have
// an overridden function with instructions to construct ubi::Nodes.
// We actually want to call that function and construct from those instances.
ptr->ConstructUbiNode(storage);
}
js::UniquePtr<EdgeRange>
JS::ubi::Concrete<nsINode>::edges(JSContext* cx, bool wantNames) const
{
AutoSuppressGCAnalysis suppress;
auto range = js::MakeUnique<SimpleEdgeRange>();
if (!range) {
return nullptr;
}
if (get().GetParent()) {
char16_t* edgeName = nullptr;
if (wantNames) {
edgeName = NS_strdup(u"Parent Node");
}
if (!range->addEdge(JS::ubi::Edge(edgeName, get().GetParent()))) {
return nullptr;
}
}
for (auto curr = get().GetFirstChild(); curr; curr = curr->GetNextSibling()) {
char16_t* edgeName = nullptr;
if (wantNames) {
edgeName = NS_strdup(u"Child Node");
}
if (!range->addEdge(JS::ubi::Edge(edgeName, curr))) {
return nullptr;
}
}
return range;
}
JS::ubi::Node::Size
JS::ubi::Concrete<nsINode>::size(mozilla::MallocSizeOf mallocSizeOf) const
{
AutoSuppressGCAnalysis suppress;
mozilla::SizeOfState sz(mallocSizeOf);
nsWindowSizes wn(sz);
size_t n = 0;
get().AddSizeOfIncludingThis(wn, &n);
return n;
}
JS::ubi::Node::Size
JS::ubi::Concrete<nsIDocument>::size(mozilla::MallocSizeOf mallocSizeOf) const
{
AutoSuppressGCAnalysis suppress;
mozilla::SizeOfState sz(mallocSizeOf);
nsWindowSizes wn(sz);
getDoc().DocAddSizeOfIncludingThis(wn);
return wn.getTotalSize();
}

View file

@ -0,0 +1,84 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef dom_NodeUbiReporting_h
#define dom_NodeUbiReporting_h
#include "nsINode.h"
#include "js/UbiNode.h"
/*
* This file defines specializations of JS::ubi::Concrete for DOM nodes
* so that the JS memory tools, which operate on the UbiNode graph, can
* define subclasses of JS::ubi::Base that represent DOM nodes and
* yield the outgoing edges in a DOM node graph for reporting.
*/
using mozilla::dom::Attr;
namespace JS {
namespace ubi {
// The DOM node base class.
// This is an abstract class and therefore does not require a concreteTypeName.
template<>
class Concrete<nsINode> : public Base
{
protected:
explicit Concrete(nsINode *ptr) : Base(ptr) { }
public:
static void construct(void *storage, nsINode *ptr);
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
nsINode& get() const { return *static_cast<nsINode*>(ptr); }
CoarseType coarseType() const final { return CoarseType::Other; }
};
template<>
class Concrete<nsIContent> : public Concrete<nsINode>
{
protected:
explicit Concrete(nsIContent *ptr) : Concrete<nsINode>(ptr) { }
public:
static void construct(void *storage, nsIContent *ptr) { new (storage) Concrete(ptr); }
const char16_t* typeName() const override { return concreteTypeName; };
static const char16_t concreteTypeName[];
};
template<>
class Concrete<nsIDocument> : public Concrete<nsINode>
{
protected:
explicit Concrete(nsIDocument *ptr) : Concrete<nsINode>(ptr) { }
public:
static void construct(void *storage, nsIDocument *ptr) { new (storage) Concrete(ptr); }
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
nsIDocument& getDoc() const { return *static_cast<nsIDocument*>(ptr); }
const char16_t* typeName() const override { return concreteTypeName; };
static const char16_t concreteTypeName[];
};
template<>
class Concrete<Attr> : public Concrete<nsINode>
{
protected:
explicit Concrete(Attr *ptr) : Concrete<nsINode>(ptr) { }
public:
static void construct(void *storage, Attr *ptr) { new (storage) Concrete(ptr); }
const char16_t* typeName() const override { return concreteTypeName; };
static const char16_t concreteTypeName[];
};
} //namespace ubi
} //namespace JS
#endif

View file

@ -9,6 +9,7 @@
#include "nsCycleCollectionParticipant.h"
#include "nsISupportsImpl.h"
#include "nsWrapperCache.h"
class nsScreen;

View file

@ -38,6 +38,7 @@ EXPORTS += [
'HTMLSplitOnSpacesTokenizer.h',
'IframeSandboxKeywordList.h',
'mozAutoDocUpdate.h',
'NodeUbiReporting.h',
'nsAttrAndChildArray.h',
'nsAttrName.h',
'nsAttrValue.h',
@ -287,6 +288,7 @@ UNIFIED_SOURCES += [
'Navigator.cpp',
'NodeInfo.cpp',
'NodeIterator.cpp',
'NodeUbiReporting.cpp',
'nsAttrAndChildArray.cpp',
'nsAttrValue.cpp',
'nsAttrValueOrString.cpp',

View file

@ -326,7 +326,6 @@ nsContentUtils::sUserInteractionObserver = nullptr;
uint32_t nsContentUtils::sHandlingInputTimeout = 1000;
uint32_t nsContentUtils::sCookiesLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
uint32_t nsContentUtils::sCookiesBehavior = nsICookieService::BEHAVIOR_ACCEPT;
nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
nsIParser* nsContentUtils::sXMLFragmentParser = nullptr;
@ -689,10 +688,6 @@ nsContentUtils::Init()
"network.cookie.lifetimePolicy",
nsICookieService::ACCEPT_NORMALLY);
Preferences::AddUintVarCache(&sCookiesBehavior,
"network.cookie.cookieBehavior",
nsICookieService::BEHAVIOR_ACCEPT);
Preferences::AddBoolVarCache(&sDoNotTrackEnabled,
"privacy.donottrackheader.enabled", false);
@ -8783,7 +8778,7 @@ nsContentUtils::GetCookieBehaviorForPrincipal(nsIPrincipal* aPrincipal,
uint32_t* aBehavior)
{
*aLifetimePolicy = sCookiesLifetimePolicy;
*aBehavior = sCookiesBehavior;
*aBehavior = StaticPrefs::network_cookie_cookieBehavior();
// Any permissions set for the given principal will override our default
// settings from preferences.

View file

@ -3426,7 +3426,6 @@ private:
static bool sIsBytecodeCacheEnabled;
static int32_t sBytecodeCacheStrategy;
static uint32_t sCookiesLifetimePolicy;
static uint32_t sCookiesBehavior;
static bool sShortcutsCustomized;
static int32_t sPrivacyMaxInnerWidth;

View file

@ -275,6 +275,7 @@
#include "mozilla/RestyleManager.h"
#include "mozilla/ClearOnShutdown.h"
#include "nsHTMLTags.h"
#include "NodeUbiReporting.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -1576,6 +1577,13 @@ nsIDocument::IsAboutPage() const
return isAboutScheme;
}
void
nsIDocument::ConstructUbiNode(void* storage)
{
JS::ubi::Concrete<nsIDocument>::construct(storage, this);
}
nsDocument::~nsDocument()
{
MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug, ("DOCUMENT %p destroyed", this));

View file

@ -55,6 +55,8 @@ class nsIContent : public nsINode {
public:
typedef mozilla::widget::IMEState IMEState;
void ConstructUbiNode(void* storage) override;
#ifdef MOZILLA_INTERNAL_API
// If you're using the external API, the only thing you can know about
// nsIContent is that it exists with an IID

View file

@ -3042,6 +3042,8 @@ public:
// declaration of nsINode::SizeOfIncludingThis.
virtual void DocAddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const;
void ConstructUbiNode(void* storage) override;
bool MayHaveDOMMutationObservers()
{
return mMayHaveDOMMutationObservers;

View file

@ -455,6 +455,12 @@ public:
virtual JSObject* WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
/**
* Hook for constructing JS::ubi::Concrete specializations for memory reporting.
* Specializations are defined in NodeUbiReporting.h.
*/
virtual void ConstructUbiNode(void* storage) = 0;
/**
* returns true if we are in priviliged code or
* layout.css.getBoxQuads.enabled == true.

View file

@ -601,7 +601,7 @@ FetchUtil::StreamResponseToJS(JSContext* aCx,
return ThrowException(aCx, JSMSG_ERROR_CONSUMING_RESPONSE);
}
nsIGlobalObject* global = xpc::NativeGlobal(aObj);
nsIGlobalObject* global = xpc::NativeGlobal(js::UncheckedUnwrap(aObj));
if (!JSStreamConsumer::Start(body, aConsumer, global, aMaybeWorker)) {
return ThrowException(aCx, JSMSG_OUT_OF_MEMORY);

View file

@ -19,6 +19,8 @@
#include "nsINode.h"
#include "nsIPrincipal.h"
#include "js/Wrapper.h"
using namespace mozilla::dom;
namespace mozilla {
@ -184,6 +186,7 @@ nsBrowserElement::Download(const nsAString& aUrl,
RefPtr<DOMRequest> req;
nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(mBrowserElementAPI);
MOZ_ASSERT(wrappedObj, "Failed to get wrapped JS from XPCOM component.");
MOZ_RELEASE_ASSERT(!js::IsWrapper(wrappedObj->GetJSObject()));
AutoJSAPI jsapi;
if (!jsapi.Init(wrappedObj->GetJSObject())) {
aRv.Throw(NS_ERROR_UNEXPECTED);
@ -403,6 +406,7 @@ nsBrowserElement::ExecuteScript(const nsAString& aScript,
RefPtr<DOMRequest> req;
nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(mBrowserElementAPI);
MOZ_ASSERT(wrappedObj, "Failed to get wrapped JS from XPCOM component.");
MOZ_RELEASE_ASSERT(!js::IsWrapper(wrappedObj->GetJSObject()));
AutoJSAPI jsapi;
if (!jsapi.Init(wrappedObj->GetJSObject())) {
aRv.Throw(NS_ERROR_UNEXPECTED);

View file

@ -490,6 +490,7 @@ AutoJSAPI::Init(nsIGlobalObject* aGlobalObject)
bool
AutoJSAPI::Init(JSObject* aObject)
{
MOZ_ASSERT(!js::IsCrossCompartmentWrapper(aObject));
return Init(xpc::NativeGlobal(aObject));
}

View file

@ -228,7 +228,8 @@ public:
MOZ_MUST_USE bool Init(nsIGlobalObject* aGlobalObject);
// This is a helper that grabs the native global associated with aObject and
// invokes the above Init() with that.
// invokes the above Init() with that. aObject must not be a cross-compartment
// wrapper: CCWs are not associated with a single global.
MOZ_MUST_USE bool Init(JSObject* aObject);
// Unsurprisingly, this uses aCx and enters the compartment of aGlobalObject.

View file

@ -41,26 +41,21 @@ namespace serviceWorkerScriptCache {
namespace {
// XXX A sandbox nsIGlobalObject does not preserve its reflector, so |aSandbox|
// must be kept alive as long as the CacheStorage if you want to ensure that
// the CacheStorage will continue to work. Failures will manifest as errors
// like "JavaScript error: , line 0: TypeError: The expression cannot be
// converted to return the specified type."
already_AddRefed<CacheStorage>
CreateCacheStorage(JSContext* aCx, nsIPrincipal* aPrincipal, ErrorResult& aRv,
JS::MutableHandle<JSObject*> aSandbox)
CreateCacheStorage(JSContext* aCx, nsIPrincipal* aPrincipal, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
nsIXPConnect* xpc = nsContentUtils::XPConnect();
MOZ_ASSERT(xpc, "This should never be null!");
aRv = xpc->CreateSandbox(aCx, aPrincipal, aSandbox.address());
JS::Rooted<JSObject*> sandbox(aCx);
aRv = xpc->CreateSandbox(aCx, aPrincipal, sandbox.address());
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
nsCOMPtr<nsIGlobalObject> sandboxGlobalObject = xpc::NativeGlobal(aSandbox);
nsCOMPtr<nsIGlobalObject> sandboxGlobalObject = xpc::NativeGlobal(sandbox);
if (!sandboxGlobalObject) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
@ -666,7 +661,6 @@ private:
RefPtr<ServiceWorkerRegistrationInfo> mRegistration;
RefPtr<CompareCallback> mCallback;
JS::PersistentRooted<JSObject*> mSandbox;
RefPtr<CacheStorage> mCacheStorage;
nsTArray<RefPtr<CompareNetwork>> mCNList;
@ -1286,8 +1280,7 @@ CompareManager::Initialize(nsIPrincipal* aPrincipal,
AutoJSAPI jsapi;
jsapi.Init();
ErrorResult result;
mSandbox.init(jsapi.cx());
mCacheStorage = CreateCacheStorage(jsapi.cx(), aPrincipal, result, &mSandbox);
mCacheStorage = CreateCacheStorage(jsapi.cx(), aPrincipal, result);
if (NS_WARN_IF(result.Failed())) {
MOZ_ASSERT(!result.IsErrorWithMessage());
return result.StealNSResult();
@ -1429,8 +1422,7 @@ PurgeCache(nsIPrincipal* aPrincipal, const nsAString& aCacheName)
AutoJSAPI jsapi;
jsapi.Init();
ErrorResult rv;
JS::Rooted<JSObject*> sandboxObject(jsapi.cx());
RefPtr<CacheStorage> cacheStorage = CreateCacheStorage(jsapi.cx(), aPrincipal, rv, &sandboxObject);
RefPtr<CacheStorage> cacheStorage = CreateCacheStorage(jsapi.cx(), aPrincipal, rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}

View file

@ -57,7 +57,6 @@ var ecmaGlobals =
"RegExp",
"Set",
{name: "SharedArrayBuffer", disabled: true},
{name: "SIMD", nightly: true},
"String",
"Symbol",
"SyntaxError",

View file

@ -282,6 +282,10 @@ SVGAnimationElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
}
}
if (!IsInComposedDoc()) {
return rv;
}
if (!((aNamespaceID == kNameSpaceID_None ||
aNamespaceID == kNameSpaceID_XLink) &&
aName == nsGkAtoms::href)) {
@ -305,8 +309,7 @@ SVGAnimationElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
AnimationTargetChanged();
} // else: we unset xlink:href, but we still have href attribute, so keep
// mHrefTarget linking to href.
} else if (IsInComposedDoc() &&
!(aNamespaceID == kNameSpaceID_XLink &&
} else if (!(aNamespaceID == kNameSpaceID_XLink &&
HasAttr(kNameSpaceID_None, nsGkAtoms::href))) {
// Note: "href" takes priority over xlink:href. So if "xlink:href" is being
// set here, we only let that update our target if "href" is *unset*.

View file

@ -78,7 +78,6 @@ var ecmaGlobals =
{name: "RegExp", insecureContext: true},
{name: "Set", insecureContext: true},
{name: "SharedArrayBuffer", insecureContext: true, disabled: true},
{name: "SIMD", insecureContext: true, nightly: true},
{name: "String", insecureContext: true},
{name: "Symbol", insecureContext: true},
{name: "SyntaxError", insecureContext: true},

View file

@ -63,7 +63,6 @@ var ecmaGlobals =
{name: "RegExp", insecureContext: true},
{name: "Set", insecureContext: true},
{name: "SharedArrayBuffer", insecureContext: true, disabled: true},
{name: "SIMD", insecureContext: true, nightly: true},
{name: "String", insecureContext: true},
{name: "Symbol", insecureContext: true},
{name: "SyntaxError", insecureContext: true},

View file

@ -892,7 +892,8 @@ GetOrCreateMapEntryForPrototype(JSContext *cx, JS::Handle<JSObject*> proto)
// Now, enter the XBL scope, since that's where we need to operate, and wrap
// the proto accordingly. We hang the map off of the content XBL scope for
// content, and the Window for chrome (whether add-ons are involved or not).
JS::Rooted<JSObject*> scope(cx, xpc::GetXBLScopeOrGlobal(cx, proto));
JS::Rooted<JSObject*> scope(cx,
xpc::GetXBLScopeOrGlobal(cx, JS::CurrentGlobalOrNull(cx)));
NS_ENSURE_TRUE(scope, nullptr);
MOZ_ASSERT(JS_IsGlobalObject(scope));
@ -958,7 +959,10 @@ nsXBLBinding::DoInitJSClass(JSContext *cx,
// and defining it as a property on the XBL scope's global. This works fine,
// but we need to make sure never to assume that the the reflector and
// prototype are same-compartment with the bound document.
JS::Rooted<JSObject*> global(cx, js::GetGlobalForObjectCrossCompartment(obj));
JS::Rooted<JSObject*> global(cx, JS::GetNonCCWObjectGlobal(obj));
// We must be in obj's realm.
MOZ_ASSERT(JS::CurrentGlobalOrNull(cx) == global);
// We never store class objects in add-on scopes.
JS::Rooted<JSObject*> xblScope(cx, xpc::GetXBLScopeOrGlobal(cx, global));
@ -1115,7 +1119,7 @@ nsXBLBinding::LookupMember(JSContext* aCx, JS::Handle<jsid> aId,
// This code is only called for content XBL, so we don't have to worry about
// add-on scopes here.
JS::Rooted<JSObject*> boundScope(aCx,
js::GetGlobalForObjectCrossCompartment(mBoundElement->GetWrapper()));
JS::GetNonCCWObjectGlobal(mBoundElement->GetWrapper()));
MOZ_RELEASE_ASSERT(!xpc::IsInContentXBLScope(boundScope));
JS::Rooted<JSObject*> xblScope(aCx, xpc::GetXBLScope(aCx, boundScope));
NS_ENSURE_TRUE(xblScope, false);

View file

@ -22,7 +22,6 @@
using namespace mozilla;
using namespace mozilla::dom;
using js::GetGlobalForObjectCrossCompartment;
using js::AssertSameCompartment;
nsresult
@ -82,7 +81,7 @@ nsXBLProtoImpl::InstallImplementation(nsXBLPrototypeBinding* aPrototypeBinding,
// First, start by entering the realm of the XBL scope. This may or may
// not be the same realm as globalObject.
JS::Rooted<JSObject*> globalObject(cx,
GetGlobalForObjectCrossCompartment(targetClassObject));
JS::GetNonCCWObjectGlobal(targetClassObject));
JS::Rooted<JSObject*> scopeObject(cx, xpc::GetXBLScopeOrGlobal(cx, globalObject));
NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
MOZ_ASSERT(JS_IsGlobalObject(scopeObject));
@ -218,6 +217,10 @@ nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding,
JS::Rooted<JSObject*> value(cx, &v.toObject());
JSAutoRealm ar2(cx, value);
// We passed aAllowWrapping = false to nsContentUtils::WrapNative so we
// should not have a wrapper.
MOZ_ASSERT(!js::IsWrapper(value));
// All of the above code was just obtaining the bound element's script object and its immediate
// concrete base class. We need to alter the object so that our concrete class is interposed
// between the object and its base class. We become the new base class of the object, and the

View file

@ -0,0 +1,26 @@
# v2
0x41324230="A2B0"
0x42324130="B2A0"
0x47524159="GRAY"
0x4C616220="Lab "
0x52474220="RGB "
0x58595a20="XYZ "
0x62545243="bTRC"
0x6258595a="bXYZ"
0x63686164="chad"
0x63757276="curv"
0x67545243="gTRC"
0x6758595a="gXYZ"
0x6D667431="mft1"
0x6D667432="mft2"
0x6b545243="kTRC"
0x6d6e7472="mntr"
0x72545243="rTRC"
0x7258595a="rXYZ"
0x73636e72="scnr"
0x73663332="sf32"
# v4
0x6D414220="mAB "
0x6D424120="mBA "
0x70617261="para"

View file

@ -305,18 +305,14 @@ SkScalerContext_DW::SkScalerContext_DW(sk_sp<DWriteFontTypeface> typefaceRef,
fTextSizeMeasure = realTextSize;
fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
IDWriteFactory* factory = sk_get_dwrite_factory();
if (factory != nullptr) {
HRVM(factory->CreateRenderingParams(&fDefaultRenderingParams),
"Could not create default rendering params");
}
IDWriteRenderingParams* params = sk_get_dwrite_default_rendering_params();
DWriteFontTypeface* typeface = static_cast<DWriteFontTypeface*>(getTypeface());
if (!SUCCEEDED(typeface->fDWriteFontFace->GetRecommendedRenderingMode(
if (params &&
!SUCCEEDED(typeface->fDWriteFontFace->GetRecommendedRenderingMode(
fTextSizeRender,
1.0f,
fMeasuringMode,
fDefaultRenderingParams.get(),
params,
&fRenderingMode))) {
fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
}

View file

@ -70,7 +70,6 @@ private:
DWRITE_MEASURING_MODE fMeasuringMode;
DWRITE_TEXT_ANTIALIAS_MODE fAntiAliasMode;
DWRITE_GRID_FIT_MODE fGridFitMode;
SkTScopedComPtr<IDWriteRenderingParams> fDefaultRenderingParams;
bool fIsColorFont;
};

View file

@ -49,6 +49,30 @@ IDWriteFactory* sk_get_dwrite_factory() {
return gDWriteFactory;
}
static IDWriteRenderingParams* gDWriteRenderingParams = nullptr;
static void release_dwrite_rendering_params() {
if (gDWriteRenderingParams) {
gDWriteRenderingParams->Release();
}
}
static void create_dwrite_rendering_params(IDWriteRenderingParams** params) {
IDWriteFactory* factory = sk_get_dwrite_factory();
if (!factory) {
return;
}
HRVM(factory->CreateRenderingParams(params),
"Could not create DWrite default rendering params");
atexit(release_dwrite_rendering_params);
}
IDWriteRenderingParams* sk_get_dwrite_default_rendering_params() {
static SkOnce once;
once(create_dwrite_rendering_params, &gDWriteRenderingParams);
return gDWriteRenderingParams;
}
////////////////////////////////////////////////////////////////////////////////
// String conversion

View file

@ -20,6 +20,7 @@ class SkString;
// Factory
IDWriteFactory* sk_get_dwrite_factory();
IDWriteRenderingParams* sk_get_dwrite_default_rendering_params();
////////////////////////////////////////////////////////////////////////////////
// String conversion

View file

@ -35,7 +35,6 @@ EXPORTS += [
'nsRegion.h',
'nsRegionFwd.h',
'nsSize.h',
'nsThemeConstants.h',
'nsTransform2D.h',
'RegionBuilder.h',
'X11UndefineNone.h'

View file

@ -25,6 +25,7 @@ class nsIWidget;
namespace mozilla {
class ComputedStyle;
enum class StyleAppearance : uint8_t;
namespace layers {
class StackingContextHelper;
class WebRenderLayerManager;
@ -58,6 +59,7 @@ class IpcResourceUpdateQueue;
class nsITheme: public nsISupports {
protected:
using LayoutDeviceIntMargin = mozilla::LayoutDeviceIntMargin;
using WidgetType = mozilla::StyleAppearance;
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITHEME_IID)
@ -72,7 +74,7 @@ public:
*/
NS_IMETHOD DrawWidgetBackground(gfxContext* aContext,
nsIFrame* aFrame,
uint8_t aWidgetType,
WidgetType aWidgetType,
const nsRect& aRect,
const nsRect& aDirtyRect) = 0;
@ -81,7 +83,7 @@ public:
* It's currently only used for scrollbar-*-color properties.
*/
virtual nscolor GetWidgetAutoColor(mozilla::ComputedStyle* aStyle,
uint8_t aWidgetType)
WidgetType aWidgetType)
{ return NS_RGB(0, 0, 0); }
/**
@ -95,7 +97,7 @@ public:
const mozilla::layers::StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsIFrame* aFrame,
uint8_t aWidgetType,
WidgetType aWidgetType,
const nsRect& aRect) { return false; }
/**
@ -103,7 +105,7 @@ public:
*/
virtual MOZ_MUST_USE LayoutDeviceIntMargin GetWidgetBorder(nsDeviceContext* aContext,
nsIFrame* aFrame,
uint8_t aWidgetType) = 0;
WidgetType aWidgetType) = 0;
/**
* This method can return false to indicate that the CSS padding
@ -115,9 +117,9 @@ public:
* the computed padding and potentially the size.
*/
virtual bool GetWidgetPadding(nsDeviceContext* aContext,
nsIFrame* aFrame,
uint8_t aWidgetType,
LayoutDeviceIntMargin* aResult) = 0;
nsIFrame* aFrame,
WidgetType aWidgetType,
LayoutDeviceIntMargin* aResult) = 0;
/**
* On entry, *aResult is positioned at 0,0 and sized to the new size
@ -134,9 +136,9 @@ public:
* scrollable overflow.)
*/
virtual bool GetWidgetOverflow(nsDeviceContext* aContext,
nsIFrame* aFrame,
uint8_t aWidgetType,
/*INOUT*/ nsRect* aOverflowRect)
nsIFrame* aFrame,
WidgetType aWidgetType,
/*INOUT*/ nsRect* aOverflowRect)
{ return false; }
/**
@ -147,7 +149,7 @@ public:
*/
NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext,
nsIFrame* aFrame,
uint8_t aWidgetType,
WidgetType aWidgetType,
mozilla::LayoutDeviceIntSize* aResult,
bool* aIsOverridable)=0;
@ -161,7 +163,7 @@ public:
/**
* Returns what we know about the transparency of the widget.
*/
virtual Transparency GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType)
virtual Transparency GetWidgetTransparency(nsIFrame* aFrame, WidgetType aWidgetType)
{ return eUnknownTransparency; }
/**
@ -169,17 +171,16 @@ public:
* change should trigger a repaint. Call with null |aAttribute| (and
* null |aOldValue|) for content state changes.
*/
NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType,
NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, WidgetType aWidgetType,
nsAtom* aAttribute, bool* aShouldRepaint,
const nsAttrValue* aOldValue)=0;
NS_IMETHOD ThemeChanged()=0;
virtual bool WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType)
virtual bool WidgetAppearanceDependsOnWindowFocus(WidgetType aWidgetType)
{ return false; }
virtual bool NeedToClearBackgroundBehindWidget(nsIFrame* aFrame,
uint8_t aWidgetType)
virtual bool NeedToClearBackgroundBehindWidget(nsIFrame* aFrame, WidgetType aWidgetType)
{ return false; }
/**
@ -206,27 +207,27 @@ public:
* not be included in the ThemeGeometry array.
*/
virtual ThemeGeometryType ThemeGeometryTypeForWidget(nsIFrame* aFrame,
uint8_t aWidgetType)
WidgetType aWidgetType)
{ return eThemeGeometryTypeUnknown; }
/**
* Can the nsITheme implementation handle this widget?
*/
virtual bool ThemeSupportsWidget(nsPresContext* aPresContext,
nsIFrame* aFrame,
uint8_t aWidgetType)=0;
nsIFrame* aFrame,
WidgetType aWidgetType) = 0;
virtual bool WidgetIsContainer(uint8_t aWidgetType)=0;
virtual bool WidgetIsContainer(WidgetType aWidgetType) = 0;
/**
* Does the nsITheme implementation draw its own focus ring for this widget?
*/
virtual bool ThemeDrawsFocusForWidget(uint8_t aWidgetType)=0;
virtual bool ThemeDrawsFocusForWidget(WidgetType aWidgetType) = 0;
/**
* Should we insert a dropmarker inside of combobox button?
*/
virtual bool ThemeNeedsComboboxDropmarker()=0;
virtual bool ThemeNeedsComboboxDropmarker() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsITheme, NS_ITHEME_IID)

View file

@ -1,316 +0,0 @@
/* -*- 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/. */
#ifndef nsThemeConstants_h_
#define nsThemeConstants_h_
enum ThemeWidgetType : uint8_t {
// No appearance at all.
NS_THEME_NONE,
// A typical dialog button.
NS_THEME_BUTTON,
// A radio element within a radio group.
NS_THEME_RADIO,
// A checkbox element.
NS_THEME_CHECKBOX,
// A rectangular button that contains complex content
// like images (e.g. HTML <button> elements)
NS_THEME_BUTTON_BEVEL,
// A themed focus outline (for outline:auto)
NS_THEME_FOCUS_OUTLINE,
// The toolbox that contains the toolbars.
NS_THEME_TOOLBOX,
// A toolbar in an application window.
NS_THEME_TOOLBAR,
// A single toolbar button (with no associated dropdown)
NS_THEME_TOOLBARBUTTON,
// A dual toolbar button (e.g., a Back button with a dropdown)
NS_THEME_DUALBUTTON,
// The dropdown portion of a toolbar button
NS_THEME_TOOLBARBUTTON_DROPDOWN,
// Various arrows that go in buttons
NS_THEME_BUTTON_ARROW_UP,
NS_THEME_BUTTON_ARROW_DOWN,
NS_THEME_BUTTON_ARROW_NEXT,
NS_THEME_BUTTON_ARROW_PREVIOUS,
// A separator. Can be horizontal or vertical.
NS_THEME_SEPARATOR,
// The gripper for a toolbar.
NS_THEME_TOOLBARGRIPPER,
// A splitter. Can be horizontal or vertical.
NS_THEME_SPLITTER,
// A status bar in a main application window.
NS_THEME_STATUSBAR,
// A single pane of a status bar.
NS_THEME_STATUSBARPANEL,
// The resizer background area in a status bar
// for the resizer widget in the corner of a window.
NS_THEME_RESIZERPANEL,
// The resizer itself.
NS_THEME_RESIZER,
// List boxes
NS_THEME_LISTBOX,
// A listbox item
NS_THEME_LISTITEM,
// A tree widget
NS_THEME_TREEVIEW,
// A tree item
NS_THEME_TREEITEM,
// A tree widget twisty
NS_THEME_TREETWISTY,
// A tree widget branch line
NS_THEME_TREELINE,
// A listbox or tree widget header
NS_THEME_TREEHEADER,
// An individual header cell
NS_THEME_TREEHEADERCELL,
// The sort arrow for a header.
NS_THEME_TREEHEADERSORTARROW,
// Open tree widget twisty
NS_THEME_TREETWISTYOPEN,
// A horizontal progress bar.
NS_THEME_PROGRESSBAR,
// The progress bar's progress indicator
NS_THEME_PROGRESSCHUNK,
// A vertical progress bar.
NS_THEME_PROGRESSBAR_VERTICAL,
// A vertical progress chunk
NS_THEME_PROGRESSCHUNK_VERTICAL,
// A horizontal meter bar.
NS_THEME_METERBAR,
// The meter bar's meter indicator
NS_THEME_METERCHUNK,
// A single tab in a tab widget.
NS_THEME_TAB,
// A single pane (inside the tabpanels container)
NS_THEME_TABPANEL,
// The tab panels container.
NS_THEME_TABPANELS,
// The tabs scroll arrows (left/right)
NS_THEME_TAB_SCROLL_ARROW_BACK,
NS_THEME_TAB_SCROLL_ARROW_FORWARD,
// A tooltip
NS_THEME_TOOLTIP,
// A inner-spin control
NS_THEME_INNER_SPIN_BUTTON,
// A spin control (up/down control for time/date pickers)
NS_THEME_SPINNER,
// The up button of a spin control
NS_THEME_SPINNER_UPBUTTON,
// The down button of a spin control
NS_THEME_SPINNER_DOWNBUTTON,
// The textfield of a spin control
NS_THEME_SPINNER_TEXTFIELD,
// For HTML's <input type=number>
NS_THEME_NUMBER_INPUT,
// A scrollbar.
NS_THEME_SCROLLBAR,
// A small scrollbar.
NS_THEME_SCROLLBAR_SMALL,
// The scrollbar slider
NS_THEME_SCROLLBAR_HORIZONTAL,
NS_THEME_SCROLLBAR_VERTICAL,
// A scrollbar button (up/down/left/right)
NS_THEME_SCROLLBARBUTTON_UP,
NS_THEME_SCROLLBARBUTTON_DOWN,
NS_THEME_SCROLLBARBUTTON_LEFT,
NS_THEME_SCROLLBARBUTTON_RIGHT,
// The scrollbar track
NS_THEME_SCROLLBARTRACK_HORIZONTAL,
NS_THEME_SCROLLBARTRACK_VERTICAL,
// The scrollbar thumb
NS_THEME_SCROLLBARTHUMB_HORIZONTAL,
NS_THEME_SCROLLBARTHUMB_VERTICAL,
// A non-disappearing scrollbar.
NS_THEME_SCROLLBAR_NON_DISAPPEARING,
// The scroll corner
NS_THEME_SCROLLCORNER,
// A textfield or text area
NS_THEME_TEXTFIELD,
// The caret of a text area
NS_THEME_CARET,
// A multiline text field
NS_THEME_TEXTFIELD_MULTILINE,
// A searchfield
NS_THEME_SEARCHFIELD,
// A dropdown list.
NS_THEME_MENULIST,
// The dropdown button(s) that open up a dropdown list.
NS_THEME_MENULIST_BUTTON,
// The text part of a dropdown list, to left of button
NS_THEME_MENULIST_TEXT,
// An editable textfield with a dropdown list (a combobox)
NS_THEME_MENULIST_TEXTFIELD,
// A slider
NS_THEME_SCALE_HORIZONTAL,
NS_THEME_SCALE_VERTICAL,
// A slider's thumb
NS_THEME_SCALETHUMB_HORIZONTAL,
NS_THEME_SCALETHUMB_VERTICAL,
// If the platform supports it, the left/right chunks
// of the slider thumb
NS_THEME_SCALETHUMBSTART,
NS_THEME_SCALETHUMBEND,
// The ticks for a slider.
NS_THEME_SCALETHUMBTICK,
// nsRangeFrame and its subparts
NS_THEME_RANGE,
NS_THEME_RANGE_THUMB,
// A groupbox
NS_THEME_GROUPBOX,
// A generic container that always repaints on state
// changes. This is a hack to make checkboxes and
// radio buttons work.
NS_THEME_CHECKBOX_CONTAINER,
NS_THEME_RADIO_CONTAINER,
// The label part of a checkbox or radio button, used for painting
// a focus outline.
NS_THEME_CHECKBOX_LABEL,
NS_THEME_RADIO_LABEL,
// The focus outline box inside of a button
NS_THEME_BUTTON_FOCUS,
// Window and dialog backgrounds
NS_THEME_WINDOW,
NS_THEME_DIALOG,
// Menu Bar background
NS_THEME_MENUBAR,
// Menu Popup background
NS_THEME_MENUPOPUP,
// <menu> and <menuitem> appearances
NS_THEME_MENUITEM,
NS_THEME_CHECKMENUITEM,
NS_THEME_RADIOMENUITEM,
// menu checkbox/radio appearances
NS_THEME_MENUCHECKBOX,
NS_THEME_MENURADIO,
NS_THEME_MENUSEPARATOR,
NS_THEME_MENUARROW,
// An image in the menu gutter, like in bookmarks or history
NS_THEME_MENUIMAGE,
// For text on non-iconic menuitems only
NS_THEME_MENUITEMTEXT,
// Vista Rebars
NS_THEME_WIN_COMMUNICATIONS_TOOLBOX,
NS_THEME_WIN_MEDIA_TOOLBOX,
NS_THEME_WIN_BROWSERTABBAR_TOOLBOX,
// Titlebar elements on the Mac
NS_THEME_MAC_FULLSCREEN_BUTTON,
// Mac help button
NS_THEME_MAC_HELP_BUTTON,
// Vista glass
NS_THEME_WIN_BORDERLESS_GLASS,
NS_THEME_WIN_GLASS,
// Windows themed window frame elements
NS_THEME_WINDOW_TITLEBAR,
NS_THEME_WINDOW_TITLEBAR_MAXIMIZED,
NS_THEME_WINDOW_FRAME_LEFT,
NS_THEME_WINDOW_FRAME_RIGHT,
NS_THEME_WINDOW_FRAME_BOTTOM,
NS_THEME_WINDOW_BUTTON_CLOSE,
NS_THEME_WINDOW_BUTTON_MINIMIZE,
NS_THEME_WINDOW_BUTTON_MAXIMIZE,
NS_THEME_WINDOW_BUTTON_RESTORE,
NS_THEME_WINDOW_BUTTON_BOX,
NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED,
// moz-apperance style used in setting proper glass margins
NS_THEME_WIN_EXCLUDE_GLASS,
NS_THEME_MAC_VIBRANCY_LIGHT,
NS_THEME_MAC_VIBRANCY_DARK,
NS_THEME_MAC_VIBRANT_TITLEBAR_LIGHT,
NS_THEME_MAC_VIBRANT_TITLEBAR_DARK,
NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN,
NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED,
NS_THEME_GTK_INFO_BAR,
NS_THEME_MAC_SOURCE_LIST,
NS_THEME_MAC_SOURCE_LIST_SELECTION,
NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION,
ThemeWidgetType_COUNT
};
#endif // nsThemeConstants_h_

View file

@ -48,12 +48,6 @@
#define IF_BDATA(real,imaginary) imaginary
#endif
#ifdef ENABLE_SIMD
# define IF_SIMD(real,imaginary) real
#else
# define IF_SIMD(real,imaginary) imaginary
#endif
#ifdef ENABLE_SHARED_ARRAY_BUFFER
#define IF_SAB(real,imaginary) real
#else
@ -106,7 +100,6 @@ IF_SAB(real,imaginary)(SharedArrayBuffer, InitViaClassSpec, OCLASP(SharedA
IF_INTL(real,imaginary) (Intl, InitIntlClass, CLASP(Intl)) \
IF_BDATA(real,imaginary)(TypedObject, InitTypedObjectModuleObject, OCLASP(TypedObjectModule)) \
real(Reflect, InitReflect, nullptr) \
IF_SIMD(real,imaginary)(SIMD, InitSimdClass, OCLASP(Simd)) \
real(WeakSet, InitWeakSetClass, OCLASP(WeakSet)) \
real(TypedArray, InitViaClassSpec, &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \
IF_SAB(real,imaginary)(Atomics, InitAtomicsClass, OCLASP(Atomics)) \

View file

@ -37,13 +37,7 @@ struct JS_PUBLIC_API(WorkBudget)
*/
class JS_PUBLIC_API(SliceBudget)
{
const mozilla::TimeStamp &UnlimitedDeadline() const {
mozilla::recordreplay::AutoPassThroughThreadEvents pt;
static const mozilla::TimeStamp unlimitedDeadline =
mozilla::TimeStamp::Now() + mozilla::TimeDuration::Forever();
return unlimitedDeadline;
}
static mozilla::TimeStamp unlimitedDeadline;
static const intptr_t unlimitedStartCounter = INTPTR_MAX;
bool checkOverBudget();
@ -75,7 +69,8 @@ class JS_PUBLIC_API(SliceBudget)
explicit SliceBudget(WorkBudget work);
void makeUnlimited() {
deadline = UnlimitedDeadline();
MOZ_ASSERT(unlimitedDeadline);
deadline = unlimitedDeadline;
counter = unlimitedStartCounter;
}
@ -91,9 +86,11 @@ class JS_PUBLIC_API(SliceBudget)
bool isWorkBudget() const { return deadline.IsNull(); }
bool isTimeBudget() const { return !deadline.IsNull() && !isUnlimited(); }
bool isUnlimited() const { return deadline == UnlimitedDeadline(); }
bool isUnlimited() const { return deadline == unlimitedDeadline; }
int describe(char* buffer, size_t maxlen) const;
static void Init();
};
} // namespace js

View file

@ -1110,9 +1110,7 @@ class JS_PUBLIC_API(Concrete<JSObject>) : public TracerConcrete<JSObject> {
explicit Concrete(JSObject* ptr) : TracerConcrete<JSObject>(ptr) { }
public:
static void construct(void* storage, JSObject* ptr) {
new (storage) Concrete(ptr);
}
static void construct(void* storage, JSObject* ptr);
JS::Compartment* compartment() const override;
JS::Realm* realm() const override;
@ -1165,6 +1163,15 @@ class JS_PUBLIC_API(Concrete<void>) : public Base {
static void construct(void* storage, void* ptr) { new (storage) Concrete(ptr); }
};
// The |callback| callback is much like the |Concrete<T>::construct| method: a call to
// |callback| should construct an instance of the most appropriate JS::ubi::Base subclass
// for |obj| in |storage|. The callback may assume that
// |obj->getClass()->isDOMClass()|, and that |storage| refers to the
// sizeof(JS::ubi::Base) bytes of space that all ubi::Base implementations should
// require.
// Set |cx|'s runtime hook for constructing ubi::Nodes for DOM classes to |callback|.
void SetConstructUbiNodeForDOMObjectCallback(JSContext* cx, void (*callback)(void*, JSObject*));
} // namespace ubi
} // namespace JS

View file

@ -35,7 +35,7 @@ class SimpleEdgeRange : public EdgeRange {
bool addTracerEdges(JSRuntime* rt, void* thing, JS::TraceKind kind, bool wantNames);
bool addEdge(Edge edge) {
if (!edge.name || !edges.append(std::move(edge)))
if(!edges.append(std::move(edge)))
return false;
settle();
return true;

File diff suppressed because it is too large Load diff

View file

@ -1,298 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef builtin_SIMD_h
#define builtin_SIMD_h
#include "jsapi.h"
#include "NamespaceImports.h"
#include "builtin/SIMDConstants.h"
#include "jit/IonTypes.h"
#include "js/Conversions.h"
/*
* JS SIMD functions.
* Spec matching polyfill:
* https://github.com/tc39/ecmascript_simd/blob/master/src/ecmascript_simd.js
*/
namespace js {
class GlobalObject;
// These classes implement the concept containing the following constraints:
// - requires typename Elem: this is the scalar lane type, stored in each lane
// of the SIMD vector.
// - requires static const unsigned lanes: this is the number of lanes (length)
// of the SIMD vector.
// - requires static const SimdType type: this is the SimdType enum value
// corresponding to the SIMD type.
// - requires static bool Cast(JSContext*, JS::HandleValue, Elem*): casts a
// given Value to the current scalar lane type and saves it in the Elem
// out-param.
// - requires static Value ToValue(Elem): returns a Value of the right type
// containing the given value.
//
// This concept is used in the templates above to define the functions
// associated to a given type and in their implementations, to avoid code
// redundancy.
struct Float32x4 {
typedef float Elem;
static const unsigned lanes = 4;
static const SimdType type = SimdType::Float32x4;
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
double d;
if (!ToNumber(cx, v, &d))
return false;
*out = float(d);
return true;
}
static Value ToValue(Elem value) {
return DoubleValue(JS::CanonicalizeNaN(value));
}
};
struct Float64x2 {
typedef double Elem;
static const unsigned lanes = 2;
static const SimdType type = SimdType::Float64x2;
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
return ToNumber(cx, v, out);
}
static Value ToValue(Elem value) {
return DoubleValue(JS::CanonicalizeNaN(value));
}
};
struct Int8x16 {
typedef int8_t Elem;
static const unsigned lanes = 16;
static const SimdType type = SimdType::Int8x16;
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
return ToInt8(cx, v, out);
}
static Value ToValue(Elem value) {
return NumberValue(value);
}
};
struct Int16x8 {
typedef int16_t Elem;
static const unsigned lanes = 8;
static const SimdType type = SimdType::Int16x8;
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
return ToInt16(cx, v, out);
}
static Value ToValue(Elem value) {
return NumberValue(value);
}
};
struct Int32x4 {
typedef int32_t Elem;
static const unsigned lanes = 4;
static const SimdType type = SimdType::Int32x4;
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
return ToInt32(cx, v, out);
}
static Value ToValue(Elem value) {
return NumberValue(value);
}
};
struct Uint8x16 {
typedef uint8_t Elem;
static const unsigned lanes = 16;
static const SimdType type = SimdType::Uint8x16;
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
return ToUint8(cx, v, out);
}
static Value ToValue(Elem value) {
return NumberValue(value);
}
};
struct Uint16x8 {
typedef uint16_t Elem;
static const unsigned lanes = 8;
static const SimdType type = SimdType::Uint16x8;
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
return ToUint16(cx, v, out);
}
static Value ToValue(Elem value) {
return NumberValue(value);
}
};
struct Uint32x4 {
typedef uint32_t Elem;
static const unsigned lanes = 4;
static const SimdType type = SimdType::Uint32x4;
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
return ToUint32(cx, v, out);
}
static Value ToValue(Elem value) {
return NumberValue(value);
}
};
struct Bool8x16 {
typedef int8_t Elem;
static const unsigned lanes = 16;
static const SimdType type = SimdType::Bool8x16;
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
*out = ToBoolean(v) ? -1 : 0;
return true;
}
static Value ToValue(Elem value) {
return BooleanValue(value);
}
};
struct Bool16x8 {
typedef int16_t Elem;
static const unsigned lanes = 8;
static const SimdType type = SimdType::Bool16x8;
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
*out = ToBoolean(v) ? -1 : 0;
return true;
}
static Value ToValue(Elem value) {
return BooleanValue(value);
}
};
struct Bool32x4 {
typedef int32_t Elem;
static const unsigned lanes = 4;
static const SimdType type = SimdType::Bool32x4;
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
*out = ToBoolean(v) ? -1 : 0;
return true;
}
static Value ToValue(Elem value) {
return BooleanValue(value);
}
};
struct Bool64x2 {
typedef int64_t Elem;
static const unsigned lanes = 2;
static const SimdType type = SimdType::Bool64x2;
static MOZ_MUST_USE bool Cast(JSContext* cx, JS::HandleValue v, Elem* out) {
*out = ToBoolean(v) ? -1 : 0;
return true;
}
static Value ToValue(Elem value) {
return BooleanValue(value);
}
};
// Get the well known name of the SIMD.* object corresponding to type.
PropertyName* SimdTypeToName(const JSAtomState& atoms, SimdType type);
// Check if name is the well known name of a SIMD type.
// Returns true and sets *type iff name is known.
bool IsSimdTypeName(const JSAtomState& atoms, const PropertyName* name, SimdType* type);
const char* SimdTypeToString(SimdType type);
template<typename V>
JSObject* CreateSimd(JSContext* cx, const typename V::Elem* data);
template<typename V>
bool IsVectorObject(HandleValue v);
template<typename V>
MOZ_MUST_USE bool ToSimdConstant(JSContext* cx, HandleValue v, jit::SimdConstant* out);
JSObject*
InitSimdClass(JSContext* cx, Handle<GlobalObject*> global);
namespace jit {
extern const JSJitInfo JitInfo_SimdInt32x4_extractLane;
extern const JSJitInfo JitInfo_SimdFloat32x4_extractLane;
} // namespace jit
#define DECLARE_SIMD_FLOAT32X4_FUNCTION(Name, Func, Operands) \
extern MOZ_MUST_USE bool \
simd_float32x4_##Name(JSContext* cx, unsigned argc, Value* vp);
FLOAT32X4_FUNCTION_LIST(DECLARE_SIMD_FLOAT32X4_FUNCTION)
#undef DECLARE_SIMD_FLOAT32X4_FUNCTION
#define DECLARE_SIMD_FLOAT64X2_FUNCTION(Name, Func, Operands) \
extern MOZ_MUST_USE bool \
simd_float64x2_##Name(JSContext* cx, unsigned argc, Value* vp);
FLOAT64X2_FUNCTION_LIST(DECLARE_SIMD_FLOAT64X2_FUNCTION)
#undef DECLARE_SIMD_FLOAT64X2_FUNCTION
#define DECLARE_SIMD_INT8X16_FUNCTION(Name, Func, Operands) \
extern MOZ_MUST_USE bool \
simd_int8x16_##Name(JSContext* cx, unsigned argc, Value* vp);
INT8X16_FUNCTION_LIST(DECLARE_SIMD_INT8X16_FUNCTION)
#undef DECLARE_SIMD_INT8X16_FUNCTION
#define DECLARE_SIMD_INT16X8_FUNCTION(Name, Func, Operands) \
extern MOZ_MUST_USE bool \
simd_int16x8_##Name(JSContext* cx, unsigned argc, Value* vp);
INT16X8_FUNCTION_LIST(DECLARE_SIMD_INT16X8_FUNCTION)
#undef DECLARE_SIMD_INT16X8_FUNCTION
#define DECLARE_SIMD_INT32X4_FUNCTION(Name, Func, Operands) \
extern MOZ_MUST_USE bool \
simd_int32x4_##Name(JSContext* cx, unsigned argc, Value* vp);
INT32X4_FUNCTION_LIST(DECLARE_SIMD_INT32X4_FUNCTION)
#undef DECLARE_SIMD_INT32X4_FUNCTION
#define DECLARE_SIMD_UINT8X16_FUNCTION(Name, Func, Operands) \
extern MOZ_MUST_USE bool \
simd_uint8x16_##Name(JSContext* cx, unsigned argc, Value* vp);
UINT8X16_FUNCTION_LIST(DECLARE_SIMD_UINT8X16_FUNCTION)
#undef DECLARE_SIMD_UINT8X16_FUNCTION
#define DECLARE_SIMD_UINT16X8_FUNCTION(Name, Func, Operands) \
extern MOZ_MUST_USE bool \
simd_uint16x8_##Name(JSContext* cx, unsigned argc, Value* vp);
UINT16X8_FUNCTION_LIST(DECLARE_SIMD_UINT16X8_FUNCTION)
#undef DECLARE_SIMD_UINT16X8_FUNCTION
#define DECLARE_SIMD_UINT32X4_FUNCTION(Name, Func, Operands) \
extern MOZ_MUST_USE bool \
simd_uint32x4_##Name(JSContext* cx, unsigned argc, Value* vp);
UINT32X4_FUNCTION_LIST(DECLARE_SIMD_UINT32X4_FUNCTION)
#undef DECLARE_SIMD_UINT32X4_FUNCTION
#define DECLARE_SIMD_BOOL8X16_FUNCTION(Name, Func, Operands) \
extern MOZ_MUST_USE bool \
simd_bool8x16_##Name(JSContext* cx, unsigned argc, Value* vp);
BOOL8X16_FUNCTION_LIST(DECLARE_SIMD_BOOL8X16_FUNCTION)
#undef DECLARE_SIMD_BOOL8X16_FUNCTION
#define DECLARE_SIMD_BOOL16X8_FUNCTION(Name, Func, Operands) \
extern MOZ_MUST_USE bool \
simd_bool16x8_##Name(JSContext* cx, unsigned argc, Value* vp);
BOOL16X8_FUNCTION_LIST(DECLARE_SIMD_BOOL16X8_FUNCTION)
#undef DECLARE_SIMD_BOOL16X8_FUNCTION
#define DECLARE_SIMD_BOOL32X4_FUNCTION(Name, Func, Operands) \
extern MOZ_MUST_USE bool \
simd_bool32x4_##Name(JSContext* cx, unsigned argc, Value* vp);
BOOL32X4_FUNCTION_LIST(DECLARE_SIMD_BOOL32X4_FUNCTION)
#undef DECLARE_SIMD_BOOL32X4_FUNCTION
#define DECLARE_SIMD_BOOL64X2_FUNCTION(Name, Func, Operands) \
extern MOZ_MUST_USE bool \
simd_bool64x2_##Name(JSContext* cx, unsigned argc, Value* vp);
BOOL64X2_FUNCTION_LIST(DECLARE_SIMD_BOOL64X2_FUNCTION)
#undef DECLARE_SIMD_BOOL64X2_FUNCTION
} /* namespace js */
#endif /* builtin_SIMD_h */

View file

@ -1,941 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef builtin_SIMDConstants_h
#define builtin_SIMDConstants_h
#include "mozilla/Assertions.h"
#include "builtin/TypedObjectConstants.h"
// Bool8x16.
#define BOOL8X16_UNARY_FUNCTION_LIST(V) \
V(not, (UnaryFunc<Bool8x16, LogicalNot, Bool8x16>), 1) \
V(check, (UnaryFunc<Bool8x16, Identity, Bool8x16>), 1) \
V(splat, (FuncSplat<Bool8x16>), 1) \
V(allTrue, (AllTrue<Bool8x16>), 1) \
V(anyTrue, (AnyTrue<Bool8x16>), 1)
#define BOOL8X16_BINARY_FUNCTION_LIST(V) \
V(extractLane, (ExtractLane<Bool8x16>), 2) \
V(and, (BinaryFunc<Bool8x16, And, Bool8x16>), 2) \
V(or, (BinaryFunc<Bool8x16, Or, Bool8x16>), 2) \
V(xor, (BinaryFunc<Bool8x16, Xor, Bool8x16>), 2) \
#define BOOL8X16_TERNARY_FUNCTION_LIST(V) \
V(replaceLane, (ReplaceLane<Bool8x16>), 3)
#define BOOL8X16_FUNCTION_LIST(V) \
BOOL8X16_UNARY_FUNCTION_LIST(V) \
BOOL8X16_BINARY_FUNCTION_LIST(V) \
BOOL8X16_TERNARY_FUNCTION_LIST(V)
// Bool 16x8.
#define BOOL16X8_UNARY_FUNCTION_LIST(V) \
V(not, (UnaryFunc<Bool16x8, LogicalNot, Bool16x8>), 1) \
V(check, (UnaryFunc<Bool16x8, Identity, Bool16x8>), 1) \
V(splat, (FuncSplat<Bool16x8>), 1) \
V(allTrue, (AllTrue<Bool16x8>), 1) \
V(anyTrue, (AnyTrue<Bool16x8>), 1)
#define BOOL16X8_BINARY_FUNCTION_LIST(V) \
V(extractLane, (ExtractLane<Bool16x8>), 2) \
V(and, (BinaryFunc<Bool16x8, And, Bool16x8>), 2) \
V(or, (BinaryFunc<Bool16x8, Or, Bool16x8>), 2) \
V(xor, (BinaryFunc<Bool16x8, Xor, Bool16x8>), 2) \
#define BOOL16X8_TERNARY_FUNCTION_LIST(V) \
V(replaceLane, (ReplaceLane<Bool16x8>), 3)
#define BOOL16X8_FUNCTION_LIST(V) \
BOOL16X8_UNARY_FUNCTION_LIST(V) \
BOOL16X8_BINARY_FUNCTION_LIST(V) \
BOOL16X8_TERNARY_FUNCTION_LIST(V)
// Bool32x4.
#define BOOL32X4_UNARY_FUNCTION_LIST(V) \
V(not, (UnaryFunc<Bool32x4, LogicalNot, Bool32x4>), 1) \
V(check, (UnaryFunc<Bool32x4, Identity, Bool32x4>), 1) \
V(splat, (FuncSplat<Bool32x4>), 1) \
V(allTrue, (AllTrue<Bool32x4>), 1) \
V(anyTrue, (AnyTrue<Bool32x4>), 1)
#define BOOL32X4_BINARY_FUNCTION_LIST(V) \
V(extractLane, (ExtractLane<Bool32x4>), 2) \
V(and, (BinaryFunc<Bool32x4, And, Bool32x4>), 2) \
V(or, (BinaryFunc<Bool32x4, Or, Bool32x4>), 2) \
V(xor, (BinaryFunc<Bool32x4, Xor, Bool32x4>), 2) \
#define BOOL32X4_TERNARY_FUNCTION_LIST(V) \
V(replaceLane, (ReplaceLane<Bool32x4>), 3)
#define BOOL32X4_FUNCTION_LIST(V) \
BOOL32X4_UNARY_FUNCTION_LIST(V) \
BOOL32X4_BINARY_FUNCTION_LIST(V) \
BOOL32X4_TERNARY_FUNCTION_LIST(V)
// Bool64x2.
#define BOOL64X2_UNARY_FUNCTION_LIST(V) \
V(not, (UnaryFunc<Bool64x2, LogicalNot, Bool64x2>), 1) \
V(check, (UnaryFunc<Bool64x2, Identity, Bool64x2>), 1) \
V(splat, (FuncSplat<Bool64x2>), 1) \
V(allTrue, (AllTrue<Bool64x2>), 1) \
V(anyTrue, (AnyTrue<Bool64x2>), 1)
#define BOOL64X2_BINARY_FUNCTION_LIST(V) \
V(extractLane, (ExtractLane<Bool64x2>), 2) \
V(and, (BinaryFunc<Bool64x2, And, Bool64x2>), 2) \
V(or, (BinaryFunc<Bool64x2, Or, Bool64x2>), 2) \
V(xor, (BinaryFunc<Bool64x2, Xor, Bool64x2>), 2) \
#define BOOL64X2_TERNARY_FUNCTION_LIST(V) \
V(replaceLane, (ReplaceLane<Bool64x2>), 3)
#define BOOL64X2_FUNCTION_LIST(V) \
BOOL64X2_UNARY_FUNCTION_LIST(V) \
BOOL64X2_BINARY_FUNCTION_LIST(V) \
BOOL64X2_TERNARY_FUNCTION_LIST(V)
// Float32x4.
#define FLOAT32X4_UNARY_FUNCTION_LIST(V) \
V(abs, (UnaryFunc<Float32x4, Abs, Float32x4>), 1) \
V(check, (UnaryFunc<Float32x4, Identity, Float32x4>), 1) \
V(fromFloat64x2Bits, (FuncConvertBits<Float64x2, Float32x4>), 1) \
V(fromInt8x16Bits, (FuncConvertBits<Int8x16, Float32x4>), 1) \
V(fromInt16x8Bits, (FuncConvertBits<Int16x8, Float32x4>), 1) \
V(fromInt32x4, (FuncConvert<Int32x4, Float32x4>), 1) \
V(fromInt32x4Bits, (FuncConvertBits<Int32x4, Float32x4>), 1) \
V(fromUint8x16Bits, (FuncConvertBits<Uint8x16, Float32x4>), 1) \
V(fromUint16x8Bits, (FuncConvertBits<Uint16x8, Float32x4>), 1) \
V(fromUint32x4, (FuncConvert<Uint32x4, Float32x4>), 1) \
V(fromUint32x4Bits, (FuncConvertBits<Uint32x4, Float32x4>), 1) \
V(neg, (UnaryFunc<Float32x4, Neg, Float32x4>), 1) \
V(reciprocalApproximation, (UnaryFunc<Float32x4, RecApprox, Float32x4>), 1) \
V(reciprocalSqrtApproximation, (UnaryFunc<Float32x4, RecSqrtApprox, Float32x4>), 1) \
V(splat, (FuncSplat<Float32x4>), 1) \
V(sqrt, (UnaryFunc<Float32x4, Sqrt, Float32x4>), 1)
#define FLOAT32X4_BINARY_FUNCTION_LIST(V) \
V(add, (BinaryFunc<Float32x4, Add, Float32x4>), 2) \
V(div, (BinaryFunc<Float32x4, Div, Float32x4>), 2) \
V(equal, (CompareFunc<Float32x4, Equal, Bool32x4>), 2) \
V(extractLane, (ExtractLane<Float32x4>), 2) \
V(greaterThan, (CompareFunc<Float32x4, GreaterThan, Bool32x4>), 2) \
V(greaterThanOrEqual, (CompareFunc<Float32x4, GreaterThanOrEqual, Bool32x4>), 2) \
V(lessThan, (CompareFunc<Float32x4, LessThan, Bool32x4>), 2) \
V(lessThanOrEqual, (CompareFunc<Float32x4, LessThanOrEqual, Bool32x4>), 2) \
V(load, (Load<Float32x4, 4>), 2) \
V(load3, (Load<Float32x4, 3>), 2) \
V(load2, (Load<Float32x4, 2>), 2) \
V(load1, (Load<Float32x4, 1>), 2) \
V(max, (BinaryFunc<Float32x4, Maximum, Float32x4>), 2) \
V(maxNum, (BinaryFunc<Float32x4, MaxNum, Float32x4>), 2) \
V(min, (BinaryFunc<Float32x4, Minimum, Float32x4>), 2) \
V(minNum, (BinaryFunc<Float32x4, MinNum, Float32x4>), 2) \
V(mul, (BinaryFunc<Float32x4, Mul, Float32x4>), 2) \
V(notEqual, (CompareFunc<Float32x4, NotEqual, Bool32x4>), 2) \
V(sub, (BinaryFunc<Float32x4, Sub, Float32x4>), 2)
#define FLOAT32X4_TERNARY_FUNCTION_LIST(V) \
V(replaceLane, (ReplaceLane<Float32x4>), 3) \
V(select, (Select<Float32x4, Bool32x4>), 3) \
V(store, (Store<Float32x4, 4>), 3) \
V(store3, (Store<Float32x4, 3>), 3) \
V(store2, (Store<Float32x4, 2>), 3) \
V(store1, (Store<Float32x4, 1>), 3)
#define FLOAT32X4_SHUFFLE_FUNCTION_LIST(V) \
V(swizzle, Swizzle<Float32x4>, 5) \
V(shuffle, Shuffle<Float32x4>, 6)
#define FLOAT32X4_FUNCTION_LIST(V) \
FLOAT32X4_UNARY_FUNCTION_LIST(V) \
FLOAT32X4_BINARY_FUNCTION_LIST(V) \
FLOAT32X4_TERNARY_FUNCTION_LIST(V) \
FLOAT32X4_SHUFFLE_FUNCTION_LIST(V)
// Float64x2.
#define FLOAT64X2_UNARY_FUNCTION_LIST(V) \
V(abs, (UnaryFunc<Float64x2, Abs, Float64x2>), 1) \
V(check, (UnaryFunc<Float64x2, Identity, Float64x2>), 1) \
V(fromFloat32x4Bits, (FuncConvertBits<Float32x4, Float64x2>), 1) \
V(fromInt8x16Bits, (FuncConvertBits<Int8x16, Float64x2>), 1) \
V(fromInt16x8Bits, (FuncConvertBits<Int16x8, Float64x2>), 1) \
V(fromInt32x4Bits, (FuncConvertBits<Int32x4, Float64x2>), 1) \
V(fromUint8x16Bits, (FuncConvertBits<Uint8x16, Float64x2>), 1) \
V(fromUint16x8Bits, (FuncConvertBits<Uint16x8, Float64x2>), 1) \
V(fromUint32x4Bits, (FuncConvertBits<Uint32x4, Float64x2>), 1) \
V(neg, (UnaryFunc<Float64x2, Neg, Float64x2>), 1) \
V(reciprocalApproximation, (UnaryFunc<Float64x2, RecApprox, Float64x2>), 1) \
V(reciprocalSqrtApproximation, (UnaryFunc<Float64x2, RecSqrtApprox, Float64x2>), 1) \
V(splat, (FuncSplat<Float64x2>), 1) \
V(sqrt, (UnaryFunc<Float64x2, Sqrt, Float64x2>), 1)
#define FLOAT64X2_BINARY_FUNCTION_LIST(V) \
V(add, (BinaryFunc<Float64x2, Add, Float64x2>), 2) \
V(div, (BinaryFunc<Float64x2, Div, Float64x2>), 2) \
V(equal, (CompareFunc<Float64x2, Equal, Bool64x2>), 2) \
V(extractLane, (ExtractLane<Float64x2>), 2) \
V(greaterThan, (CompareFunc<Float64x2, GreaterThan, Bool64x2>), 2) \
V(greaterThanOrEqual, (CompareFunc<Float64x2, GreaterThanOrEqual, Bool64x2>), 2) \
V(lessThan, (CompareFunc<Float64x2, LessThan, Bool64x2>), 2) \
V(lessThanOrEqual, (CompareFunc<Float64x2, LessThanOrEqual, Bool64x2>), 2) \
V(load, (Load<Float64x2, 2>), 2) \
V(load1, (Load<Float64x2, 1>), 2) \
V(max, (BinaryFunc<Float64x2, Maximum, Float64x2>), 2) \
V(maxNum, (BinaryFunc<Float64x2, MaxNum, Float64x2>), 2) \
V(min, (BinaryFunc<Float64x2, Minimum, Float64x2>), 2) \
V(minNum, (BinaryFunc<Float64x2, MinNum, Float64x2>), 2) \
V(mul, (BinaryFunc<Float64x2, Mul, Float64x2>), 2) \
V(notEqual, (CompareFunc<Float64x2, NotEqual, Bool64x2>), 2) \
V(sub, (BinaryFunc<Float64x2, Sub, Float64x2>), 2)
#define FLOAT64X2_TERNARY_FUNCTION_LIST(V) \
V(replaceLane, (ReplaceLane<Float64x2>), 3) \
V(select, (Select<Float64x2, Bool64x2>), 3) \
V(store, (Store<Float64x2, 2>), 3) \
V(store1, (Store<Float64x2, 1>), 3)
#define FLOAT64X2_SHUFFLE_FUNCTION_LIST(V) \
V(swizzle, Swizzle<Float64x2>, 3) \
V(shuffle, Shuffle<Float64x2>, 4)
#define FLOAT64X2_FUNCTION_LIST(V) \
FLOAT64X2_UNARY_FUNCTION_LIST(V) \
FLOAT64X2_BINARY_FUNCTION_LIST(V) \
FLOAT64X2_TERNARY_FUNCTION_LIST(V) \
FLOAT64X2_SHUFFLE_FUNCTION_LIST(V)
// Int8x16.
#define INT8X16_UNARY_FUNCTION_LIST(V) \
V(check, (UnaryFunc<Int8x16, Identity, Int8x16>), 1) \
V(fromFloat32x4Bits, (FuncConvertBits<Float32x4, Int8x16>), 1) \
V(fromFloat64x2Bits, (FuncConvertBits<Float64x2, Int8x16>), 1) \
V(fromInt16x8Bits, (FuncConvertBits<Int16x8, Int8x16>), 1) \
V(fromInt32x4Bits, (FuncConvertBits<Int32x4, Int8x16>), 1) \
V(fromUint8x16Bits, (FuncConvertBits<Uint8x16, Int8x16>), 1) \
V(fromUint16x8Bits, (FuncConvertBits<Uint16x8, Int8x16>), 1) \
V(fromUint32x4Bits, (FuncConvertBits<Uint32x4, Int8x16>), 1) \
V(neg, (UnaryFunc<Int8x16, Neg, Int8x16>), 1) \
V(not, (UnaryFunc<Int8x16, Not, Int8x16>), 1) \
V(splat, (FuncSplat<Int8x16>), 1)
#define INT8X16_BINARY_FUNCTION_LIST(V) \
V(add, (BinaryFunc<Int8x16, Add, Int8x16>), 2) \
V(addSaturate, (BinaryFunc<Int8x16, AddSaturate, Int8x16>), 2) \
V(and, (BinaryFunc<Int8x16, And, Int8x16>), 2) \
V(equal, (CompareFunc<Int8x16, Equal, Bool8x16>), 2) \
V(extractLane, (ExtractLane<Int8x16>), 2) \
V(greaterThan, (CompareFunc<Int8x16, GreaterThan, Bool8x16>), 2) \
V(greaterThanOrEqual, (CompareFunc<Int8x16, GreaterThanOrEqual, Bool8x16>), 2) \
V(lessThan, (CompareFunc<Int8x16, LessThan, Bool8x16>), 2) \
V(lessThanOrEqual, (CompareFunc<Int8x16, LessThanOrEqual, Bool8x16>), 2) \
V(load, (Load<Int8x16, 16>), 2) \
V(mul, (BinaryFunc<Int8x16, Mul, Int8x16>), 2) \
V(notEqual, (CompareFunc<Int8x16, NotEqual, Bool8x16>), 2) \
V(or, (BinaryFunc<Int8x16, Or, Int8x16>), 2) \
V(sub, (BinaryFunc<Int8x16, Sub, Int8x16>), 2) \
V(subSaturate, (BinaryFunc<Int8x16, SubSaturate, Int8x16>), 2) \
V(shiftLeftByScalar, (BinaryScalar<Int8x16, ShiftLeft>), 2) \
V(shiftRightByScalar, (BinaryScalar<Int8x16, ShiftRightArithmetic>), 2) \
V(xor, (BinaryFunc<Int8x16, Xor, Int8x16>), 2)
#define INT8X16_TERNARY_FUNCTION_LIST(V) \
V(replaceLane, (ReplaceLane<Int8x16>), 3) \
V(select, (Select<Int8x16, Bool8x16>), 3) \
V(store, (Store<Int8x16, 16>), 3)
#define INT8X16_SHUFFLE_FUNCTION_LIST(V) \
V(swizzle, Swizzle<Int8x16>, 17) \
V(shuffle, Shuffle<Int8x16>, 18)
#define INT8X16_FUNCTION_LIST(V) \
INT8X16_UNARY_FUNCTION_LIST(V) \
INT8X16_BINARY_FUNCTION_LIST(V) \
INT8X16_TERNARY_FUNCTION_LIST(V) \
INT8X16_SHUFFLE_FUNCTION_LIST(V)
// Uint8x16.
#define UINT8X16_UNARY_FUNCTION_LIST(V) \
V(check, (UnaryFunc<Uint8x16, Identity, Uint8x16>), 1) \
V(fromFloat32x4Bits, (FuncConvertBits<Float32x4, Uint8x16>), 1) \
V(fromFloat64x2Bits, (FuncConvertBits<Float64x2, Uint8x16>), 1) \
V(fromInt8x16Bits, (FuncConvertBits<Int8x16, Uint8x16>), 1) \
V(fromInt16x8Bits, (FuncConvertBits<Int16x8, Uint8x16>), 1) \
V(fromInt32x4Bits, (FuncConvertBits<Int32x4, Uint8x16>), 1) \
V(fromUint16x8Bits, (FuncConvertBits<Uint16x8, Uint8x16>), 1) \
V(fromUint32x4Bits, (FuncConvertBits<Uint32x4, Uint8x16>), 1) \
V(neg, (UnaryFunc<Uint8x16, Neg, Uint8x16>), 1) \
V(not, (UnaryFunc<Uint8x16, Not, Uint8x16>), 1) \
V(splat, (FuncSplat<Uint8x16>), 1)
#define UINT8X16_BINARY_FUNCTION_LIST(V) \
V(add, (BinaryFunc<Uint8x16, Add, Uint8x16>), 2) \
V(addSaturate, (BinaryFunc<Uint8x16, AddSaturate, Uint8x16>), 2) \
V(and, (BinaryFunc<Uint8x16, And, Uint8x16>), 2) \
V(equal, (CompareFunc<Uint8x16, Equal, Bool8x16>), 2) \
V(extractLane, (ExtractLane<Uint8x16>), 2) \
V(greaterThan, (CompareFunc<Uint8x16, GreaterThan, Bool8x16>), 2) \
V(greaterThanOrEqual, (CompareFunc<Uint8x16, GreaterThanOrEqual, Bool8x16>), 2) \
V(lessThan, (CompareFunc<Uint8x16, LessThan, Bool8x16>), 2) \
V(lessThanOrEqual, (CompareFunc<Uint8x16, LessThanOrEqual, Bool8x16>), 2) \
V(load, (Load<Uint8x16, 16>), 2) \
V(mul, (BinaryFunc<Uint8x16, Mul, Uint8x16>), 2) \
V(notEqual, (CompareFunc<Uint8x16, NotEqual, Bool8x16>), 2) \
V(or, (BinaryFunc<Uint8x16, Or, Uint8x16>), 2) \
V(sub, (BinaryFunc<Uint8x16, Sub, Uint8x16>), 2) \
V(subSaturate, (BinaryFunc<Uint8x16, SubSaturate, Uint8x16>), 2) \
V(shiftLeftByScalar, (BinaryScalar<Uint8x16, ShiftLeft>), 2) \
V(shiftRightByScalar, (BinaryScalar<Uint8x16, ShiftRightLogical>), 2) \
V(xor, (BinaryFunc<Uint8x16, Xor, Uint8x16>), 2)
#define UINT8X16_TERNARY_FUNCTION_LIST(V) \
V(replaceLane, (ReplaceLane<Uint8x16>), 3) \
V(select, (Select<Uint8x16, Bool8x16>), 3) \
V(store, (Store<Uint8x16, 16>), 3)
#define UINT8X16_SHUFFLE_FUNCTION_LIST(V) \
V(swizzle, Swizzle<Uint8x16>, 17) \
V(shuffle, Shuffle<Uint8x16>, 18)
#define UINT8X16_FUNCTION_LIST(V) \
UINT8X16_UNARY_FUNCTION_LIST(V) \
UINT8X16_BINARY_FUNCTION_LIST(V) \
UINT8X16_TERNARY_FUNCTION_LIST(V) \
UINT8X16_SHUFFLE_FUNCTION_LIST(V)
// Int16x8.
#define INT16X8_UNARY_FUNCTION_LIST(V) \
V(check, (UnaryFunc<Int16x8, Identity, Int16x8>), 1) \
V(fromFloat32x4Bits, (FuncConvertBits<Float32x4, Int16x8>), 1) \
V(fromFloat64x2Bits, (FuncConvertBits<Float64x2, Int16x8>), 1) \
V(fromInt8x16Bits, (FuncConvertBits<Int8x16, Int16x8>), 1) \
V(fromInt32x4Bits, (FuncConvertBits<Int32x4, Int16x8>), 1) \
V(fromUint8x16Bits, (FuncConvertBits<Uint8x16, Int16x8>), 1) \
V(fromUint16x8Bits, (FuncConvertBits<Uint16x8, Int16x8>), 1) \
V(fromUint32x4Bits, (FuncConvertBits<Uint32x4, Int16x8>), 1) \
V(neg, (UnaryFunc<Int16x8, Neg, Int16x8>), 1) \
V(not, (UnaryFunc<Int16x8, Not, Int16x8>), 1) \
V(splat, (FuncSplat<Int16x8>), 1)
#define INT16X8_BINARY_FUNCTION_LIST(V) \
V(add, (BinaryFunc<Int16x8, Add, Int16x8>), 2) \
V(addSaturate, (BinaryFunc<Int16x8, AddSaturate, Int16x8>), 2) \
V(and, (BinaryFunc<Int16x8, And, Int16x8>), 2) \
V(equal, (CompareFunc<Int16x8, Equal, Bool16x8>), 2) \
V(extractLane, (ExtractLane<Int16x8>), 2) \
V(greaterThan, (CompareFunc<Int16x8, GreaterThan, Bool16x8>), 2) \
V(greaterThanOrEqual, (CompareFunc<Int16x8, GreaterThanOrEqual, Bool16x8>), 2) \
V(lessThan, (CompareFunc<Int16x8, LessThan, Bool16x8>), 2) \
V(lessThanOrEqual, (CompareFunc<Int16x8, LessThanOrEqual, Bool16x8>), 2) \
V(load, (Load<Int16x8, 8>), 2) \
V(mul, (BinaryFunc<Int16x8, Mul, Int16x8>), 2) \
V(notEqual, (CompareFunc<Int16x8, NotEqual, Bool16x8>), 2) \
V(or, (BinaryFunc<Int16x8, Or, Int16x8>), 2) \
V(sub, (BinaryFunc<Int16x8, Sub, Int16x8>), 2) \
V(subSaturate, (BinaryFunc<Int16x8, SubSaturate, Int16x8>), 2) \
V(shiftLeftByScalar, (BinaryScalar<Int16x8, ShiftLeft>), 2) \
V(shiftRightByScalar, (BinaryScalar<Int16x8, ShiftRightArithmetic>), 2) \
V(xor, (BinaryFunc<Int16x8, Xor, Int16x8>), 2)
#define INT16X8_TERNARY_FUNCTION_LIST(V) \
V(replaceLane, (ReplaceLane<Int16x8>), 3) \
V(select, (Select<Int16x8, Bool16x8>), 3) \
V(store, (Store<Int16x8, 8>), 3)
#define INT16X8_SHUFFLE_FUNCTION_LIST(V) \
V(swizzle, Swizzle<Int16x8>, 9) \
V(shuffle, Shuffle<Int16x8>, 10)
#define INT16X8_FUNCTION_LIST(V) \
INT16X8_UNARY_FUNCTION_LIST(V) \
INT16X8_BINARY_FUNCTION_LIST(V) \
INT16X8_TERNARY_FUNCTION_LIST(V) \
INT16X8_SHUFFLE_FUNCTION_LIST(V)
// Uint16x8.
#define UINT16X8_UNARY_FUNCTION_LIST(V) \
V(check, (UnaryFunc<Uint16x8, Identity, Uint16x8>), 1) \
V(fromFloat32x4Bits, (FuncConvertBits<Float32x4, Uint16x8>), 1) \
V(fromFloat64x2Bits, (FuncConvertBits<Float64x2, Uint16x8>), 1) \
V(fromInt8x16Bits, (FuncConvertBits<Int8x16, Uint16x8>), 1) \
V(fromInt16x8Bits, (FuncConvertBits<Int16x8, Uint16x8>), 1) \
V(fromInt32x4Bits, (FuncConvertBits<Int32x4, Uint16x8>), 1) \
V(fromUint8x16Bits, (FuncConvertBits<Uint8x16, Uint16x8>), 1) \
V(fromUint32x4Bits, (FuncConvertBits<Uint32x4, Uint16x8>), 1) \
V(neg, (UnaryFunc<Uint16x8, Neg, Uint16x8>), 1) \
V(not, (UnaryFunc<Uint16x8, Not, Uint16x8>), 1) \
V(splat, (FuncSplat<Uint16x8>), 1)
#define UINT16X8_BINARY_FUNCTION_LIST(V) \
V(add, (BinaryFunc<Uint16x8, Add, Uint16x8>), 2) \
V(addSaturate, (BinaryFunc<Uint16x8, AddSaturate, Uint16x8>), 2) \
V(and, (BinaryFunc<Uint16x8, And, Uint16x8>), 2) \
V(equal, (CompareFunc<Uint16x8, Equal, Bool16x8>), 2) \
V(extractLane, (ExtractLane<Uint16x8>), 2) \
V(greaterThan, (CompareFunc<Uint16x8, GreaterThan, Bool16x8>), 2) \
V(greaterThanOrEqual, (CompareFunc<Uint16x8, GreaterThanOrEqual, Bool16x8>), 2) \
V(lessThan, (CompareFunc<Uint16x8, LessThan, Bool16x8>), 2) \
V(lessThanOrEqual, (CompareFunc<Uint16x8, LessThanOrEqual, Bool16x8>), 2) \
V(load, (Load<Uint16x8, 8>), 2) \
V(mul, (BinaryFunc<Uint16x8, Mul, Uint16x8>), 2) \
V(notEqual, (CompareFunc<Uint16x8, NotEqual, Bool16x8>), 2) \
V(or, (BinaryFunc<Uint16x8, Or, Uint16x8>), 2) \
V(sub, (BinaryFunc<Uint16x8, Sub, Uint16x8>), 2) \
V(subSaturate, (BinaryFunc<Uint16x8, SubSaturate, Uint16x8>), 2) \
V(shiftLeftByScalar, (BinaryScalar<Uint16x8, ShiftLeft>), 2) \
V(shiftRightByScalar, (BinaryScalar<Uint16x8, ShiftRightLogical>), 2) \
V(xor, (BinaryFunc<Uint16x8, Xor, Uint16x8>), 2)
#define UINT16X8_TERNARY_FUNCTION_LIST(V) \
V(replaceLane, (ReplaceLane<Uint16x8>), 3) \
V(select, (Select<Uint16x8, Bool16x8>), 3) \
V(store, (Store<Uint16x8, 8>), 3)
#define UINT16X8_SHUFFLE_FUNCTION_LIST(V) \
V(swizzle, Swizzle<Uint16x8>, 9) \
V(shuffle, Shuffle<Uint16x8>, 10)
#define UINT16X8_FUNCTION_LIST(V) \
UINT16X8_UNARY_FUNCTION_LIST(V) \
UINT16X8_BINARY_FUNCTION_LIST(V) \
UINT16X8_TERNARY_FUNCTION_LIST(V) \
UINT16X8_SHUFFLE_FUNCTION_LIST(V)
// Int32x4.
#define INT32X4_UNARY_FUNCTION_LIST(V) \
V(check, (UnaryFunc<Int32x4, Identity, Int32x4>), 1) \
V(fromFloat32x4, (FuncConvert<Float32x4, Int32x4>), 1) \
V(fromFloat32x4Bits, (FuncConvertBits<Float32x4, Int32x4>), 1) \
V(fromFloat64x2Bits, (FuncConvertBits<Float64x2, Int32x4>), 1) \
V(fromInt8x16Bits, (FuncConvertBits<Int8x16, Int32x4>), 1) \
V(fromInt16x8Bits, (FuncConvertBits<Int16x8, Int32x4>), 1) \
V(fromUint8x16Bits, (FuncConvertBits<Uint8x16, Int32x4>), 1) \
V(fromUint16x8Bits, (FuncConvertBits<Uint16x8, Int32x4>), 1) \
V(fromUint32x4Bits, (FuncConvertBits<Uint32x4, Int32x4>), 1) \
V(neg, (UnaryFunc<Int32x4, Neg, Int32x4>), 1) \
V(not, (UnaryFunc<Int32x4, Not, Int32x4>), 1) \
V(splat, (FuncSplat<Int32x4>), 0)
#define INT32X4_BINARY_FUNCTION_LIST(V) \
V(add, (BinaryFunc<Int32x4, Add, Int32x4>), 2) \
V(and, (BinaryFunc<Int32x4, And, Int32x4>), 2) \
V(equal, (CompareFunc<Int32x4, Equal, Bool32x4>), 2) \
V(extractLane, (ExtractLane<Int32x4>), 2) \
V(greaterThan, (CompareFunc<Int32x4, GreaterThan, Bool32x4>), 2) \
V(greaterThanOrEqual, (CompareFunc<Int32x4, GreaterThanOrEqual, Bool32x4>), 2) \
V(lessThan, (CompareFunc<Int32x4, LessThan, Bool32x4>), 2) \
V(lessThanOrEqual, (CompareFunc<Int32x4, LessThanOrEqual, Bool32x4>), 2) \
V(load, (Load<Int32x4, 4>), 2) \
V(load3, (Load<Int32x4, 3>), 2) \
V(load2, (Load<Int32x4, 2>), 2) \
V(load1, (Load<Int32x4, 1>), 2) \
V(mul, (BinaryFunc<Int32x4, Mul, Int32x4>), 2) \
V(notEqual, (CompareFunc<Int32x4, NotEqual, Bool32x4>), 2) \
V(or, (BinaryFunc<Int32x4, Or, Int32x4>), 2) \
V(sub, (BinaryFunc<Int32x4, Sub, Int32x4>), 2) \
V(shiftLeftByScalar, (BinaryScalar<Int32x4, ShiftLeft>), 2) \
V(shiftRightByScalar, (BinaryScalar<Int32x4, ShiftRightArithmetic>), 2) \
V(xor, (BinaryFunc<Int32x4, Xor, Int32x4>), 2)
#define INT32X4_TERNARY_FUNCTION_LIST(V) \
V(replaceLane, (ReplaceLane<Int32x4>), 3) \
V(select, (Select<Int32x4, Bool32x4>), 3) \
V(store, (Store<Int32x4, 4>), 3) \
V(store3, (Store<Int32x4, 3>), 3) \
V(store2, (Store<Int32x4, 2>), 3) \
V(store1, (Store<Int32x4, 1>), 3)
#define INT32X4_SHUFFLE_FUNCTION_LIST(V) \
V(swizzle, Swizzle<Int32x4>, 5) \
V(shuffle, Shuffle<Int32x4>, 6)
#define INT32X4_FUNCTION_LIST(V) \
INT32X4_UNARY_FUNCTION_LIST(V) \
INT32X4_BINARY_FUNCTION_LIST(V) \
INT32X4_TERNARY_FUNCTION_LIST(V) \
INT32X4_SHUFFLE_FUNCTION_LIST(V)
// Uint32x4.
#define UINT32X4_UNARY_FUNCTION_LIST(V) \
V(check, (UnaryFunc<Uint32x4, Identity, Uint32x4>), 1) \
V(fromFloat32x4, (FuncConvert<Float32x4, Uint32x4>), 1) \
V(fromFloat32x4Bits, (FuncConvertBits<Float32x4, Uint32x4>), 1) \
V(fromFloat64x2Bits, (FuncConvertBits<Float64x2, Uint32x4>), 1) \
V(fromInt8x16Bits, (FuncConvertBits<Int8x16, Uint32x4>), 1) \
V(fromInt16x8Bits, (FuncConvertBits<Int16x8, Uint32x4>), 1) \
V(fromInt32x4Bits, (FuncConvertBits<Int32x4, Uint32x4>), 1) \
V(fromUint8x16Bits, (FuncConvertBits<Uint8x16, Uint32x4>), 1) \
V(fromUint16x8Bits, (FuncConvertBits<Uint16x8, Uint32x4>), 1) \
V(neg, (UnaryFunc<Uint32x4, Neg, Uint32x4>), 1) \
V(not, (UnaryFunc<Uint32x4, Not, Uint32x4>), 1) \
V(splat, (FuncSplat<Uint32x4>), 0)
#define UINT32X4_BINARY_FUNCTION_LIST(V) \
V(add, (BinaryFunc<Uint32x4, Add, Uint32x4>), 2) \
V(and, (BinaryFunc<Uint32x4, And, Uint32x4>), 2) \
V(equal, (CompareFunc<Uint32x4, Equal, Bool32x4>), 2) \
V(extractLane, (ExtractLane<Uint32x4>), 2) \
V(greaterThan, (CompareFunc<Uint32x4, GreaterThan, Bool32x4>), 2) \
V(greaterThanOrEqual, (CompareFunc<Uint32x4, GreaterThanOrEqual, Bool32x4>), 2) \
V(lessThan, (CompareFunc<Uint32x4, LessThan, Bool32x4>), 2) \
V(lessThanOrEqual, (CompareFunc<Uint32x4, LessThanOrEqual, Bool32x4>), 2) \
V(load, (Load<Uint32x4, 4>), 2) \
V(load3, (Load<Uint32x4, 3>), 2) \
V(load2, (Load<Uint32x4, 2>), 2) \
V(load1, (Load<Uint32x4, 1>), 2) \
V(mul, (BinaryFunc<Uint32x4, Mul, Uint32x4>), 2) \
V(notEqual, (CompareFunc<Uint32x4, NotEqual, Bool32x4>), 2) \
V(or, (BinaryFunc<Uint32x4, Or, Uint32x4>), 2) \
V(sub, (BinaryFunc<Uint32x4, Sub, Uint32x4>), 2) \
V(shiftLeftByScalar, (BinaryScalar<Uint32x4, ShiftLeft>), 2) \
V(shiftRightByScalar, (BinaryScalar<Uint32x4, ShiftRightLogical>), 2) \
V(xor, (BinaryFunc<Uint32x4, Xor, Uint32x4>), 2)
#define UINT32X4_TERNARY_FUNCTION_LIST(V) \
V(replaceLane, (ReplaceLane<Uint32x4>), 3) \
V(select, (Select<Uint32x4, Bool32x4>), 3) \
V(store, (Store<Uint32x4, 4>), 3) \
V(store3, (Store<Uint32x4, 3>), 3) \
V(store2, (Store<Uint32x4, 2>), 3) \
V(store1, (Store<Uint32x4, 1>), 3)
#define UINT32X4_SHUFFLE_FUNCTION_LIST(V) \
V(swizzle, Swizzle<Uint32x4>, 5) \
V(shuffle, Shuffle<Uint32x4>, 6)
#define UINT32X4_FUNCTION_LIST(V) \
UINT32X4_UNARY_FUNCTION_LIST(V) \
UINT32X4_BINARY_FUNCTION_LIST(V) \
UINT32X4_TERNARY_FUNCTION_LIST(V) \
UINT32X4_SHUFFLE_FUNCTION_LIST(V)
/*
* The FOREACH macros below partition all of the SIMD operations into disjoint
* sets.
*/
// Operations available on all SIMD types. Mixed arity.
#define FOREACH_COMMON_SIMD_OP(_) \
_(extractLane) \
_(replaceLane) \
_(check) \
_(splat)
// Lanewise operations available on numeric SIMD types.
// Include lane-wise select here since it is not arithmetic and defined on
// numeric types too.
#define FOREACH_LANE_SIMD_OP(_) \
_(select) \
_(swizzle) \
_(shuffle)
// Memory operations available on numeric SIMD types.
#define FOREACH_MEMORY_SIMD_OP(_) \
_(load) \
_(store)
// Memory operations available on numeric X4 SIMD types.
#define FOREACH_MEMORY_X4_SIMD_OP(_) \
_(load1) \
_(load2) \
_(load3) \
_(store1) \
_(store2) \
_(store3)
// Unary operations on Bool vectors.
#define FOREACH_BOOL_SIMD_UNOP(_) \
_(allTrue) \
_(anyTrue)
// Unary bitwise SIMD operators defined on all integer and boolean SIMD types.
#define FOREACH_BITWISE_SIMD_UNOP(_) \
_(not)
// Binary bitwise SIMD operators defined on all integer and boolean SIMD types.
#define FOREACH_BITWISE_SIMD_BINOP(_) \
_(and) \
_(or) \
_(xor)
// Bitwise shifts defined on integer SIMD types.
#define FOREACH_SHIFT_SIMD_OP(_) \
_(shiftLeftByScalar) \
_(shiftRightByScalar)
// Unary arithmetic operators defined on numeric SIMD types.
#define FOREACH_NUMERIC_SIMD_UNOP(_) \
_(neg)
// Binary arithmetic operators defined on numeric SIMD types.
#define FOREACH_NUMERIC_SIMD_BINOP(_) \
_(add) \
_(sub) \
_(mul)
// Unary arithmetic operators defined on floating point SIMD types.
#define FOREACH_FLOAT_SIMD_UNOP(_) \
_(abs) \
_(sqrt) \
_(reciprocalApproximation) \
_(reciprocalSqrtApproximation)
// Binary arithmetic operators defined on floating point SIMD types.
#define FOREACH_FLOAT_SIMD_BINOP(_) \
_(div) \
_(max) \
_(min) \
_(maxNum) \
_(minNum)
// Binary operations on small integer (< 32 bits) vectors.
#define FOREACH_SMINT_SIMD_BINOP(_) \
_(addSaturate) \
_(subSaturate)
// Comparison operators defined on numeric SIMD types.
#define FOREACH_COMP_SIMD_OP(_) \
_(lessThan) \
_(lessThanOrEqual) \
_(equal) \
_(notEqual) \
_(greaterThan) \
_(greaterThanOrEqual)
/*
* All SIMD operations, excluding casts.
*/
#define FORALL_SIMD_NONCAST_OP(_) \
FOREACH_COMMON_SIMD_OP(_) \
FOREACH_LANE_SIMD_OP(_) \
FOREACH_MEMORY_SIMD_OP(_) \
FOREACH_MEMORY_X4_SIMD_OP(_) \
FOREACH_BOOL_SIMD_UNOP(_) \
FOREACH_BITWISE_SIMD_UNOP(_) \
FOREACH_BITWISE_SIMD_BINOP(_) \
FOREACH_SHIFT_SIMD_OP(_) \
FOREACH_NUMERIC_SIMD_UNOP(_) \
FOREACH_NUMERIC_SIMD_BINOP(_) \
FOREACH_FLOAT_SIMD_UNOP(_) \
FOREACH_FLOAT_SIMD_BINOP(_) \
FOREACH_SMINT_SIMD_BINOP(_) \
FOREACH_COMP_SIMD_OP(_)
/*
* All operations on integer SIMD types, excluding casts and
* FOREACH_MEMORY_X4_OP.
*/
#define FORALL_INT_SIMD_OP(_) \
FOREACH_COMMON_SIMD_OP(_) \
FOREACH_LANE_SIMD_OP(_) \
FOREACH_MEMORY_SIMD_OP(_) \
FOREACH_BITWISE_SIMD_UNOP(_) \
FOREACH_BITWISE_SIMD_BINOP(_) \
FOREACH_SHIFT_SIMD_OP(_) \
FOREACH_NUMERIC_SIMD_UNOP(_) \
FOREACH_NUMERIC_SIMD_BINOP(_) \
FOREACH_COMP_SIMD_OP(_)
/*
* All operations on floating point SIMD types, excluding casts and
* FOREACH_MEMORY_X4_OP.
*/
#define FORALL_FLOAT_SIMD_OP(_) \
FOREACH_COMMON_SIMD_OP(_) \
FOREACH_LANE_SIMD_OP(_) \
FOREACH_MEMORY_SIMD_OP(_) \
FOREACH_NUMERIC_SIMD_UNOP(_) \
FOREACH_NUMERIC_SIMD_BINOP(_) \
FOREACH_FLOAT_SIMD_UNOP(_) \
FOREACH_FLOAT_SIMD_BINOP(_) \
FOREACH_COMP_SIMD_OP(_)
/*
* All operations on Bool SIMD types.
*
* These types don't have casts, so no need to specialize.
*/
#define FORALL_BOOL_SIMD_OP(_) \
FOREACH_COMMON_SIMD_OP(_) \
FOREACH_BOOL_SIMD_UNOP(_) \
FOREACH_BITWISE_SIMD_UNOP(_) \
FOREACH_BITWISE_SIMD_BINOP(_)
/*
* The sets of cast operations are listed per type below.
*
* These sets are not disjoint.
*/
#define FOREACH_INT8X16_SIMD_CAST(_) \
_(fromFloat32x4Bits) \
_(fromFloat64x2Bits) \
_(fromInt16x8Bits) \
_(fromInt32x4Bits)
#define FOREACH_INT16X8_SIMD_CAST(_) \
_(fromFloat32x4Bits) \
_(fromFloat64x2Bits) \
_(fromInt8x16Bits) \
_(fromInt32x4Bits)
#define FOREACH_INT32X4_SIMD_CAST(_) \
_(fromFloat32x4) \
_(fromFloat32x4Bits) \
_(fromFloat64x2Bits) \
_(fromInt8x16Bits) \
_(fromInt16x8Bits)
#define FOREACH_FLOAT32X4_SIMD_CAST(_)\
_(fromFloat64x2Bits) \
_(fromInt8x16Bits) \
_(fromInt16x8Bits) \
_(fromInt32x4) \
_(fromInt32x4Bits)
#define FOREACH_FLOAT64X2_SIMD_CAST(_)\
_(fromFloat32x4Bits) \
_(fromInt8x16Bits) \
_(fromInt16x8Bits) \
_(fromInt32x4Bits)
// All operations on Int32x4.
#define FORALL_INT32X4_SIMD_OP(_) \
FORALL_INT_SIMD_OP(_) \
FOREACH_MEMORY_X4_SIMD_OP(_) \
FOREACH_INT32X4_SIMD_CAST(_)
// All operations on Float32X4
#define FORALL_FLOAT32X4_SIMD_OP(_) \
FORALL_FLOAT_SIMD_OP(_) \
FOREACH_MEMORY_X4_SIMD_OP(_) \
FOREACH_FLOAT32X4_SIMD_CAST(_)
/*
* All SIMD operations assuming only 32x4 types exist.
* This is used in the current asm.js impl.
*/
#define FORALL_SIMD_ASMJS_OP(_) \
FORALL_SIMD_NONCAST_OP(_) \
_(fromFloat32x4) \
_(fromFloat32x4Bits) \
_(fromInt8x16Bits) \
_(fromInt16x8Bits) \
_(fromInt32x4) \
_(fromInt32x4Bits) \
_(fromUint8x16Bits) \
_(fromUint16x8Bits) \
_(fromUint32x4) \
_(fromUint32x4Bits)
// All operations on Int8x16 or Uint8x16 in the asm.js world.
// Note: this does not include conversions and casts to/from Uint8x16 because
// this list is shared between Int8x16 and Uint8x16.
#define FORALL_INT8X16_ASMJS_OP(_) \
FORALL_INT_SIMD_OP(_) \
FOREACH_SMINT_SIMD_BINOP(_) \
_(fromInt16x8Bits) \
_(fromInt32x4Bits) \
_(fromFloat32x4Bits)
// All operations on Int16x8 or Uint16x8 in the asm.js world.
// Note: this does not include conversions and casts to/from Uint16x8 because
// this list is shared between Int16x8 and Uint16x8.
#define FORALL_INT16X8_ASMJS_OP(_) \
FORALL_INT_SIMD_OP(_) \
FOREACH_SMINT_SIMD_BINOP(_) \
_(fromInt8x16Bits) \
_(fromInt32x4Bits) \
_(fromFloat32x4Bits)
// All operations on Int32x4 or Uint32x4 in the asm.js world.
// Note: this does not include conversions and casts to/from Uint32x4 because
// this list is shared between Int32x4 and Uint32x4.
#define FORALL_INT32X4_ASMJS_OP(_) \
FORALL_INT_SIMD_OP(_) \
FOREACH_MEMORY_X4_SIMD_OP(_) \
_(fromInt8x16Bits) \
_(fromInt16x8Bits) \
_(fromFloat32x4) \
_(fromFloat32x4Bits)
// All operations on Float32X4 in the asm.js world.
#define FORALL_FLOAT32X4_ASMJS_OP(_) \
FORALL_FLOAT_SIMD_OP(_) \
FOREACH_MEMORY_X4_SIMD_OP(_) \
_(fromInt8x16Bits) \
_(fromInt16x8Bits) \
_(fromInt32x4Bits) \
_(fromInt32x4) \
_(fromUint32x4)
namespace js {
// Complete set of SIMD types.
// It must be kept in sync with the enumeration of values in
// TypedObjectConstants.h; in particular we need to ensure that Count is
// appropriately set with respect to the number of actual types.
enum class SimdType {
Int8x16 = JS_SIMDTYPEREPR_INT8X16,
Int16x8 = JS_SIMDTYPEREPR_INT16X8,
Int32x4 = JS_SIMDTYPEREPR_INT32X4,
Uint8x16 = JS_SIMDTYPEREPR_UINT8X16,
Uint16x8 = JS_SIMDTYPEREPR_UINT16X8,
Uint32x4 = JS_SIMDTYPEREPR_UINT32X4,
Float32x4 = JS_SIMDTYPEREPR_FLOAT32X4,
Float64x2 = JS_SIMDTYPEREPR_FLOAT64X2,
Bool8x16 = JS_SIMDTYPEREPR_BOOL8X16,
Bool16x8 = JS_SIMDTYPEREPR_BOOL16X8,
Bool32x4 = JS_SIMDTYPEREPR_BOOL32X4,
Bool64x2 = JS_SIMDTYPEREPR_BOOL64X2,
Count
};
// The integer SIMD types have a lot of operations that do the exact same thing
// for signed and unsigned integer types. Sometimes it is simpler to treat
// signed and unsigned integer SIMD types as the same type, using a SimdSign to
// distinguish the few cases where there is a difference.
enum class SimdSign {
// Signedness is not applicable to this type. (i.e., Float or Bool).
NotApplicable,
// Treat as an unsigned integer with a range 0 .. 2^N-1.
Unsigned,
// Treat as a signed integer in two's complement encoding.
Signed,
};
// Get the signedness of a SIMD type.
inline SimdSign
GetSimdSign(SimdType t)
{
switch(t) {
case SimdType::Int8x16:
case SimdType::Int16x8:
case SimdType::Int32x4:
return SimdSign::Signed;
case SimdType::Uint8x16:
case SimdType::Uint16x8:
case SimdType::Uint32x4:
return SimdSign::Unsigned;
default:
return SimdSign::NotApplicable;
}
}
inline bool
IsSignedIntSimdType(SimdType type)
{
return GetSimdSign(type) == SimdSign::Signed;
}
// Get the boolean SIMD type with the same shape as t.
//
// This is the result type of a comparison operation, and it can also be used to
// identify the geometry of a SIMD type.
inline SimdType
GetBooleanSimdType(SimdType t)
{
switch(t) {
case SimdType::Int8x16:
case SimdType::Uint8x16:
case SimdType::Bool8x16:
return SimdType::Bool8x16;
case SimdType::Int16x8:
case SimdType::Uint16x8:
case SimdType::Bool16x8:
return SimdType::Bool16x8;
case SimdType::Int32x4:
case SimdType::Uint32x4:
case SimdType::Float32x4:
case SimdType::Bool32x4:
return SimdType::Bool32x4;
case SimdType::Float64x2:
case SimdType::Bool64x2:
return SimdType::Bool64x2;
case SimdType::Count:
break;
}
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Bad SIMD type");
}
// Get the number of lanes in a SIMD type.
inline unsigned
GetSimdLanes(SimdType t)
{
switch(t) {
case SimdType::Int8x16:
case SimdType::Uint8x16:
case SimdType::Bool8x16:
return 16;
case SimdType::Int16x8:
case SimdType::Uint16x8:
case SimdType::Bool16x8:
return 8;
case SimdType::Int32x4:
case SimdType::Uint32x4:
case SimdType::Float32x4:
case SimdType::Bool32x4:
return 4;
case SimdType::Float64x2:
case SimdType::Bool64x2:
return 2;
case SimdType::Count:
break;
}
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Bad SIMD type");
}
// Complete set of SIMD operations.
//
// No SIMD types implement all of these operations.
//
// C++ defines keywords and/or/xor/not, so prepend Fn_ to all named functions to
// avoid clashes.
//
// Note: because of a gcc < v4.8's compiler bug, uint8_t can't be used as the
// storage class here. See bug 1243810. See also
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64037 .
enum class SimdOperation {
// The constructor call. No Fn_ prefix here.
Constructor,
// All the operations, except for casts.
#define DEFOP(x) Fn_##x,
FORALL_SIMD_NONCAST_OP(DEFOP)
#undef DEFOP
// Int <-> Float conversions.
Fn_fromInt32x4,
Fn_fromUint32x4,
Fn_fromFloat32x4,
// Bitcasts. One for each type with a memory representation.
Fn_fromInt8x16Bits,
Fn_fromInt16x8Bits,
Fn_fromInt32x4Bits,
Fn_fromUint8x16Bits,
Fn_fromUint16x8Bits,
Fn_fromUint32x4Bits,
Fn_fromFloat32x4Bits,
Fn_fromFloat64x2Bits,
Last = Fn_fromFloat64x2Bits
};
} // namespace js
#endif /* builtin_SIMDConstants_h */

View file

@ -3980,12 +3980,7 @@ static bool
IsSimdAvailable(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
#if defined(JS_CODEGEN_NONE) || !defined(ENABLE_SIMD)
bool available = false;
#else
bool available = cx->jitSupportsSimd();
#endif
args.rval().set(BooleanValue(available));
args.rval().set(BooleanValue(cx->jitSupportsSimd()));
return true;
}

View file

@ -11,7 +11,6 @@
#include "jsutil.h"
#include "builtin/SIMDConstants.h"
#include "gc/Marking.h"
#include "js/Vector.h"
#include "util/StringBuffer.h"
@ -244,10 +243,6 @@ ScalarTypeDescr::typeName(Type type)
JS_FOR_EACH_SCALAR_TYPE_REPR(NUMERIC_TYPE_TO_STRING)
#undef NUMERIC_TYPE_TO_STRING
case Scalar::Int64:
case Scalar::Float32x4:
case Scalar::Int8x16:
case Scalar::Int16x8:
case Scalar::Int32x4:
case Scalar::MaxTypedArrayViewType:
break;
}
@ -285,10 +280,6 @@ ScalarTypeDescr::call(JSContext* cx, unsigned argc, Value* vp)
JS_FOR_EACH_SCALAR_TYPE_REPR(SCALARTYPE_CALL)
#undef SCALARTYPE_CALL
case Scalar::Int64:
case Scalar::Float32x4:
case Scalar::Int8x16:
case Scalar::Int16x8:
case Scalar::Int32x4:
case Scalar::MaxTypedArrayViewType:
MOZ_CRASH();
}
@ -401,50 +392,6 @@ js::ReferenceTypeDescr::call(JSContext* cx, unsigned argc, Value* vp)
MOZ_CRASH("Unhandled Reference type");
}
/***************************************************************************
* SIMD type objects
*
* Note: these are partially defined in SIMD.cpp
*/
SimdType
SimdTypeDescr::type() const {
uint32_t t = uint32_t(getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32());
MOZ_ASSERT(t < uint32_t(SimdType::Count));
return SimdType(t);
}
uint32_t
SimdTypeDescr::size(SimdType t)
{
MOZ_ASSERT(unsigned(t) < unsigned(SimdType::Count));
switch (t) {
case SimdType::Int8x16:
case SimdType::Int16x8:
case SimdType::Int32x4:
case SimdType::Uint8x16:
case SimdType::Uint16x8:
case SimdType::Uint32x4:
case SimdType::Float32x4:
case SimdType::Float64x2:
case SimdType::Bool8x16:
case SimdType::Bool16x8:
case SimdType::Bool32x4:
case SimdType::Bool64x2:
return 16;
case SimdType::Count:
break;
}
MOZ_CRASH("unexpected SIMD type");
}
uint32_t
SimdTypeDescr::alignment(SimdType t)
{
MOZ_ASSERT(unsigned(t) < unsigned(SimdType::Count));
return size(t);
}
/***************************************************************************
* ArrayMetaTypeDescr class
*/
@ -1666,7 +1613,6 @@ TypeDescr::hasProperty(const JSAtomState& names, jsid id)
switch (kind()) {
case type::Scalar:
case type::Reference:
case type::Simd:
return false;
case type::Array:
@ -1739,7 +1685,6 @@ TypedObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool*
switch (typedObj->typeDescr().kind()) {
case type::Scalar:
case type::Reference:
case type::Simd:
break;
case type::Array: {
@ -1791,9 +1736,6 @@ TypedObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiv
case type::Reference:
break;
case type::Simd:
break;
case type::Array:
if (JSID_IS_ATOM(id, cx->names().length)) {
if (!typedObj->isAttached()) {
@ -1840,7 +1782,6 @@ TypedObject::obj_getElement(JSContext* cx, HandleObject obj, HandleValue receive
switch (descr->kind()) {
case type::Scalar:
case type::Reference:
case type::Simd:
case type::Struct:
break;
@ -1886,9 +1827,6 @@ TypedObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleId id, Handl
case type::Reference:
break;
case type::Simd:
break;
case type::Array: {
if (JSID_IS_ATOM(id, cx->names().length)) {
if (receiver.isObject() && obj == &receiver.toObject()) {
@ -1956,7 +1894,6 @@ TypedObject::obj_getOwnPropertyDescriptor(JSContext* cx, HandleObject obj, Handl
switch (descr->kind()) {
case type::Scalar:
case type::Reference:
case type::Simd:
break;
case type::Array:
@ -2010,7 +1947,6 @@ IsOwnId(JSContext* cx, HandleObject obj, HandleId id)
switch (typedObj->typeDescr().kind()) {
case type::Scalar:
case type::Reference:
case type::Simd:
return false;
case type::Array:
@ -2049,8 +1985,7 @@ TypedObject::obj_newEnumerate(JSContext* cx, HandleObject obj, AutoIdVector& pro
RootedId id(cx);
switch (descr->kind()) {
case type::Scalar:
case type::Reference:
case type::Simd: {
case type::Reference: {
// Nothing to enumerate.
break;
}
@ -2535,22 +2470,6 @@ js::GetTypedObjectModule(JSContext* cx, unsigned argc, Value* vp)
return true;
}
bool
js::GetSimdTypeDescr(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
MOZ_ASSERT(args[0].isInt32());
// One of the JS_SIMDTYPEREPR_* constants / a SimdType enum value.
// getOrCreateSimdTypeDescr() will do the range check.
int32_t simdTypeRepr = args[0].toInt32();
Rooted<GlobalObject*> global(cx, cx->global());
MOZ_ASSERT(global);
auto* obj = GlobalObject::getOrCreateSimdTypeDescr(cx, global, SimdType(simdTypeRepr));
args.rval().setObject(*obj);
return true;
}
#define JS_STORE_SCALAR_CLASS_IMPL(_constant, T, _name) \
bool \
js::StoreScalar##T::Func(JSContext* cx, unsigned argc, Value* vp) \
@ -2741,7 +2660,6 @@ visitReferences(TypeDescr& descr,
switch (descr.kind()) {
case type::Scalar:
case type::Simd:
return;
case type::Reference:

View file

@ -121,7 +121,6 @@ namespace type {
enum Kind {
Scalar = JS_TYPEREPR_SCALAR_KIND,
Reference = JS_TYPEREPR_REFERENCE_KIND,
Simd = JS_TYPEREPR_SIMD_KIND,
Struct = JS_TYPEREPR_STRUCT_KIND,
Array = JS_TYPEREPR_ARRAY_KIND
};
@ -133,7 +132,6 @@ enum Kind {
class SimpleTypeDescr;
class ComplexTypeDescr;
class SimdTypeDescr;
class StructTypeDescr;
class TypedProto;
@ -255,14 +253,6 @@ class ScalarTypeDescr : public SimpleTypeDescr
"TypedObjectConstants.h must be consistent with Scalar::Type");
static_assert(Scalar::Uint8Clamped == JS_SCALARTYPEREPR_UINT8_CLAMPED,
"TypedObjectConstants.h must be consistent with Scalar::Type");
static_assert(Scalar::Float32x4 == JS_SCALARTYPEREPR_FLOAT32X4,
"TypedObjectConstants.h must be consistent with Scalar::Type");
static_assert(Scalar::Int8x16 == JS_SCALARTYPEREPR_INT8X16,
"TypedObjectConstants.h must be consistent with Scalar::Type");
static_assert(Scalar::Int16x8 == JS_SCALARTYPEREPR_INT16X8,
"TypedObjectConstants.h must be consistent with Scalar::Type");
static_assert(Scalar::Int32x4 == JS_SCALARTYPEREPR_INT32X4,
"TypedObjectConstants.h must be consistent with Scalar::Type");
return Type(getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32());
}
@ -340,25 +330,6 @@ class ComplexTypeDescr : public TypeDescr
}
};
enum class SimdType;
/*
* SIMD Type descriptors.
*/
class SimdTypeDescr : public ComplexTypeDescr
{
public:
static const type::Kind Kind = type::Simd;
static const bool Opaque = false;
static const Class class_;
static uint32_t size(SimdType t);
static uint32_t alignment(SimdType t);
static MOZ_MUST_USE bool call(JSContext* cx, unsigned argc, Value* vp);
static bool is(const Value& v);
SimdType type() const;
};
bool IsTypedObjectClass(const Class* clasp); // Defined below
bool IsTypedObjectArray(JSObject& obj);
@ -794,16 +765,6 @@ class InlineOpaqueTypedObject : public InlineTypedObject
static const Class class_;
};
// Class for the global SIMD object.
class SimdObject : public NativeObject
{
public:
static const Class class_;
static MOZ_MUST_USE bool toString(JSContext* cx, unsigned int argc, Value* vp);
static MOZ_MUST_USE bool resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId,
bool* resolved);
};
/*
* Usage: NewOpaqueTypedObject(typeObj)
*
@ -901,16 +862,6 @@ MOZ_MUST_USE bool ClampToUint8(JSContext* cx, unsigned argc, Value* vp);
*/
MOZ_MUST_USE bool GetTypedObjectModule(JSContext* cx, unsigned argc, Value* vp);
/*
* Usage: GetSimdTypeDescr(simdTypeRepr)
*
* Returns one of the SIMD type objects, identified by `simdTypeRepr` which must
* be one of the JS_SIMDTYPEREPR_* constants.
*
* The SIMD pseudo-module must have been initialized for this to be safe.
*/
MOZ_MUST_USE bool GetSimdTypeDescr(JSContext* cx, unsigned argc, Value* vp);
/*
* Usage: Store_int8(targetDatum, targetOffset, value)
* ...
@ -1045,8 +996,7 @@ inline bool
IsComplexTypeDescrClass(const Class* clasp)
{
return clasp == &StructTypeDescr::class_ ||
clasp == &ArrayTypeDescr::class_ ||
clasp == &SimdTypeDescr::class_;
clasp == &ArrayTypeDescr::class_;
}
inline bool

View file

@ -53,9 +53,6 @@ function TypedObjectGet(descr, typedObj, offset) {
case JS_TYPEREPR_REFERENCE_KIND:
return TypedObjectGetReference(descr, typedObj, offset);
case JS_TYPEREPR_SIMD_KIND:
return TypedObjectGetSimd(descr, typedObj, offset);
case JS_TYPEREPR_ARRAY_KIND:
case JS_TYPEREPR_STRUCT_KIND:
return TypedObjectGetDerived(descr, typedObj, offset);
@ -137,144 +134,6 @@ function TypedObjectGetReference(descr, typedObj, offset) {
return undefined;
}
function TypedObjectGetSimd(descr, typedObj, offset) {
var type = DESCR_TYPE(descr);
var simdTypeDescr = GetSimdTypeDescr(type);
switch (type) {
case JS_SIMDTYPEREPR_FLOAT32X4:
var x = Load_float32(typedObj, offset + 0);
var y = Load_float32(typedObj, offset + 4);
var z = Load_float32(typedObj, offset + 8);
var w = Load_float32(typedObj, offset + 12);
return simdTypeDescr(x, y, z, w);
case JS_SIMDTYPEREPR_FLOAT64X2:
var x = Load_float64(typedObj, offset + 0);
var y = Load_float64(typedObj, offset + 8);
return simdTypeDescr(x, y);
case JS_SIMDTYPEREPR_INT8X16:
var s0 = Load_int8(typedObj, offset + 0);
var s1 = Load_int8(typedObj, offset + 1);
var s2 = Load_int8(typedObj, offset + 2);
var s3 = Load_int8(typedObj, offset + 3);
var s4 = Load_int8(typedObj, offset + 4);
var s5 = Load_int8(typedObj, offset + 5);
var s6 = Load_int8(typedObj, offset + 6);
var s7 = Load_int8(typedObj, offset + 7);
var s8 = Load_int8(typedObj, offset + 8);
var s9 = Load_int8(typedObj, offset + 9);
var s10 = Load_int8(typedObj, offset + 10);
var s11 = Load_int8(typedObj, offset + 11);
var s12 = Load_int8(typedObj, offset + 12);
var s13 = Load_int8(typedObj, offset + 13);
var s14 = Load_int8(typedObj, offset + 14);
var s15 = Load_int8(typedObj, offset + 15);
return simdTypeDescr(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15);
case JS_SIMDTYPEREPR_INT16X8:
var s0 = Load_int16(typedObj, offset + 0);
var s1 = Load_int16(typedObj, offset + 2);
var s2 = Load_int16(typedObj, offset + 4);
var s3 = Load_int16(typedObj, offset + 6);
var s4 = Load_int16(typedObj, offset + 8);
var s5 = Load_int16(typedObj, offset + 10);
var s6 = Load_int16(typedObj, offset + 12);
var s7 = Load_int16(typedObj, offset + 14);
return simdTypeDescr(s0, s1, s2, s3, s4, s5, s6, s7);
case JS_SIMDTYPEREPR_INT32X4:
var x = Load_int32(typedObj, offset + 0);
var y = Load_int32(typedObj, offset + 4);
var z = Load_int32(typedObj, offset + 8);
var w = Load_int32(typedObj, offset + 12);
return simdTypeDescr(x, y, z, w);
case JS_SIMDTYPEREPR_UINT8X16:
var s0 = Load_uint8(typedObj, offset + 0);
var s1 = Load_uint8(typedObj, offset + 1);
var s2 = Load_uint8(typedObj, offset + 2);
var s3 = Load_uint8(typedObj, offset + 3);
var s4 = Load_uint8(typedObj, offset + 4);
var s5 = Load_uint8(typedObj, offset + 5);
var s6 = Load_uint8(typedObj, offset + 6);
var s7 = Load_uint8(typedObj, offset + 7);
var s8 = Load_uint8(typedObj, offset + 8);
var s9 = Load_uint8(typedObj, offset + 9);
var s10 = Load_uint8(typedObj, offset + 10);
var s11 = Load_uint8(typedObj, offset + 11);
var s12 = Load_uint8(typedObj, offset + 12);
var s13 = Load_uint8(typedObj, offset + 13);
var s14 = Load_uint8(typedObj, offset + 14);
var s15 = Load_uint8(typedObj, offset + 15);
return simdTypeDescr(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15);
case JS_SIMDTYPEREPR_UINT16X8:
var s0 = Load_uint16(typedObj, offset + 0);
var s1 = Load_uint16(typedObj, offset + 2);
var s2 = Load_uint16(typedObj, offset + 4);
var s3 = Load_uint16(typedObj, offset + 6);
var s4 = Load_uint16(typedObj, offset + 8);
var s5 = Load_uint16(typedObj, offset + 10);
var s6 = Load_uint16(typedObj, offset + 12);
var s7 = Load_uint16(typedObj, offset + 14);
return simdTypeDescr(s0, s1, s2, s3, s4, s5, s6, s7);
case JS_SIMDTYPEREPR_UINT32X4:
var x = Load_uint32(typedObj, offset + 0);
var y = Load_uint32(typedObj, offset + 4);
var z = Load_uint32(typedObj, offset + 8);
var w = Load_uint32(typedObj, offset + 12);
return simdTypeDescr(x, y, z, w);
case JS_SIMDTYPEREPR_BOOL8X16:
var s0 = Load_int8(typedObj, offset + 0);
var s1 = Load_int8(typedObj, offset + 1);
var s2 = Load_int8(typedObj, offset + 2);
var s3 = Load_int8(typedObj, offset + 3);
var s4 = Load_int8(typedObj, offset + 4);
var s5 = Load_int8(typedObj, offset + 5);
var s6 = Load_int8(typedObj, offset + 6);
var s7 = Load_int8(typedObj, offset + 7);
var s8 = Load_int8(typedObj, offset + 8);
var s9 = Load_int8(typedObj, offset + 9);
var s10 = Load_int8(typedObj, offset + 10);
var s11 = Load_int8(typedObj, offset + 11);
var s12 = Load_int8(typedObj, offset + 12);
var s13 = Load_int8(typedObj, offset + 13);
var s14 = Load_int8(typedObj, offset + 14);
var s15 = Load_int8(typedObj, offset + 15);
return simdTypeDescr(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15);
case JS_SIMDTYPEREPR_BOOL16X8:
var s0 = Load_int16(typedObj, offset + 0);
var s1 = Load_int16(typedObj, offset + 2);
var s2 = Load_int16(typedObj, offset + 4);
var s3 = Load_int16(typedObj, offset + 6);
var s4 = Load_int16(typedObj, offset + 8);
var s5 = Load_int16(typedObj, offset + 10);
var s6 = Load_int16(typedObj, offset + 12);
var s7 = Load_int16(typedObj, offset + 14);
return simdTypeDescr(s0, s1, s2, s3, s4, s5, s6, s7);
case JS_SIMDTYPEREPR_BOOL32X4:
var x = Load_int32(typedObj, offset + 0);
var y = Load_int32(typedObj, offset + 4);
var z = Load_int32(typedObj, offset + 8);
var w = Load_int32(typedObj, offset + 12);
return simdTypeDescr(x, y, z, w);
case JS_SIMDTYPEREPR_BOOL64X2:
var x = Load_int32(typedObj, offset + 0);
var y = Load_int32(typedObj, offset + 8);
return simdTypeDescr(x, y);
}
assert(false, "Unhandled SIMD type: " + type);
return undefined;
}
///////////////////////////////////////////////////////////////////////////
// Setting values
//
@ -296,10 +155,6 @@ function TypedObjectSet(descr, typedObj, offset, name, fromValue) {
TypedObjectSetReference(descr, typedObj, offset, name, fromValue);
return;
case JS_TYPEREPR_SIMD_KIND:
TypedObjectSetSimd(descr, typedObj, offset, fromValue);
return;
case JS_TYPEREPR_ARRAY_KIND:
var length = DESCR_ARRAY_LENGTH(descr);
if (TypedObjectSetArray(descr, length, typedObj, offset, fromValue))
@ -414,106 +269,6 @@ function TypedObjectSetReference(descr, typedObj, offset, name, fromValue) {
}
// Sets `fromValue` to `this` assuming that `this` is a scalar type.
function TypedObjectSetSimd(descr, typedObj, offset, fromValue) {
if (!IsObject(fromValue) || !ObjectIsTypedObject(fromValue))
ThrowTypeError(JSMSG_CANT_CONVERT_TO,
typeof(fromValue),
DESCR_STRING_REPR(descr));
if (!DescrsEquiv(descr, TypedObjectTypeDescr(fromValue)))
ThrowTypeError(JSMSG_CANT_CONVERT_TO,
typeof(fromValue),
DESCR_STRING_REPR(descr));
var type = DESCR_TYPE(descr);
switch (type) {
case JS_SIMDTYPEREPR_FLOAT32X4:
Store_float32(typedObj, offset + 0, Load_float32(fromValue, 0));
Store_float32(typedObj, offset + 4, Load_float32(fromValue, 4));
Store_float32(typedObj, offset + 8, Load_float32(fromValue, 8));
Store_float32(typedObj, offset + 12, Load_float32(fromValue, 12));
break;
case JS_SIMDTYPEREPR_FLOAT64X2:
Store_float64(typedObj, offset + 0, Load_float64(fromValue, 0));
Store_float64(typedObj, offset + 8, Load_float64(fromValue, 8));
break;
case JS_SIMDTYPEREPR_INT8X16:
case JS_SIMDTYPEREPR_BOOL8X16:
Store_int8(typedObj, offset + 0, Load_int8(fromValue, 0));
Store_int8(typedObj, offset + 1, Load_int8(fromValue, 1));
Store_int8(typedObj, offset + 2, Load_int8(fromValue, 2));
Store_int8(typedObj, offset + 3, Load_int8(fromValue, 3));
Store_int8(typedObj, offset + 4, Load_int8(fromValue, 4));
Store_int8(typedObj, offset + 5, Load_int8(fromValue, 5));
Store_int8(typedObj, offset + 6, Load_int8(fromValue, 6));
Store_int8(typedObj, offset + 7, Load_int8(fromValue, 7));
Store_int8(typedObj, offset + 8, Load_int8(fromValue, 8));
Store_int8(typedObj, offset + 9, Load_int8(fromValue, 9));
Store_int8(typedObj, offset + 10, Load_int8(fromValue, 10));
Store_int8(typedObj, offset + 11, Load_int8(fromValue, 11));
Store_int8(typedObj, offset + 12, Load_int8(fromValue, 12));
Store_int8(typedObj, offset + 13, Load_int8(fromValue, 13));
Store_int8(typedObj, offset + 14, Load_int8(fromValue, 14));
Store_int8(typedObj, offset + 15, Load_int8(fromValue, 15));
break;
case JS_SIMDTYPEREPR_INT16X8:
case JS_SIMDTYPEREPR_BOOL16X8:
Store_int16(typedObj, offset + 0, Load_int16(fromValue, 0));
Store_int16(typedObj, offset + 2, Load_int16(fromValue, 2));
Store_int16(typedObj, offset + 4, Load_int16(fromValue, 4));
Store_int16(typedObj, offset + 6, Load_int16(fromValue, 6));
Store_int16(typedObj, offset + 8, Load_int16(fromValue, 8));
Store_int16(typedObj, offset + 10, Load_int16(fromValue, 10));
Store_int16(typedObj, offset + 12, Load_int16(fromValue, 12));
Store_int16(typedObj, offset + 14, Load_int16(fromValue, 14));
break;
case JS_SIMDTYPEREPR_INT32X4:
case JS_SIMDTYPEREPR_BOOL32X4:
case JS_SIMDTYPEREPR_BOOL64X2:
Store_int32(typedObj, offset + 0, Load_int32(fromValue, 0));
Store_int32(typedObj, offset + 4, Load_int32(fromValue, 4));
Store_int32(typedObj, offset + 8, Load_int32(fromValue, 8));
Store_int32(typedObj, offset + 12, Load_int32(fromValue, 12));
break;
case JS_SIMDTYPEREPR_UINT8X16:
Store_uint8(typedObj, offset + 0, Load_uint8(fromValue, 0));
Store_uint8(typedObj, offset + 1, Load_uint8(fromValue, 1));
Store_uint8(typedObj, offset + 2, Load_uint8(fromValue, 2));
Store_uint8(typedObj, offset + 3, Load_uint8(fromValue, 3));
Store_uint8(typedObj, offset + 4, Load_uint8(fromValue, 4));
Store_uint8(typedObj, offset + 5, Load_uint8(fromValue, 5));
Store_uint8(typedObj, offset + 6, Load_uint8(fromValue, 6));
Store_uint8(typedObj, offset + 7, Load_uint8(fromValue, 7));
Store_uint8(typedObj, offset + 8, Load_uint8(fromValue, 8));
Store_uint8(typedObj, offset + 9, Load_uint8(fromValue, 9));
Store_uint8(typedObj, offset + 10, Load_uint8(fromValue, 10));
Store_uint8(typedObj, offset + 11, Load_uint8(fromValue, 11));
Store_uint8(typedObj, offset + 12, Load_uint8(fromValue, 12));
Store_uint8(typedObj, offset + 13, Load_uint8(fromValue, 13));
Store_uint8(typedObj, offset + 14, Load_uint8(fromValue, 14));
Store_uint8(typedObj, offset + 15, Load_uint8(fromValue, 15));
break;
case JS_SIMDTYPEREPR_UINT16X8:
Store_uint16(typedObj, offset + 0, Load_uint16(fromValue, 0));
Store_uint16(typedObj, offset + 2, Load_uint16(fromValue, 2));
Store_uint16(typedObj, offset + 4, Load_uint16(fromValue, 4));
Store_uint16(typedObj, offset + 6, Load_uint16(fromValue, 6));
Store_uint16(typedObj, offset + 8, Load_uint16(fromValue, 8));
Store_uint16(typedObj, offset + 10, Load_uint16(fromValue, 10));
Store_uint16(typedObj, offset + 12, Load_uint16(fromValue, 12));
Store_uint16(typedObj, offset + 14, Load_uint16(fromValue, 14));
break;
case JS_SIMDTYPEREPR_UINT32X4:
Store_uint32(typedObj, offset + 0, Load_uint32(fromValue, 0));
Store_uint32(typedObj, offset + 4, Load_uint32(fromValue, 4));
Store_uint32(typedObj, offset + 8, Load_uint32(fromValue, 8));
Store_uint32(typedObj, offset + 12, Load_uint32(fromValue, 12));
break;
default:
assert(false, "Unhandled Simd type: " + type);
}
}
///////////////////////////////////////////////////////////////////////////
// C++ Wrappers
//
@ -629,241 +384,6 @@ function TypedObjectArrayRedimension(newArrayType) {
return NewDerivedTypedObject(newArrayType, this, 0);
}
///////////////////////////////////////////////////////////////////////////
// SIMD
function SimdProtoString(type) {
switch (type) {
case JS_SIMDTYPEREPR_INT8X16:
return "Int8x16";
case JS_SIMDTYPEREPR_INT16X8:
return "Int16x8";
case JS_SIMDTYPEREPR_INT32X4:
return "Int32x4";
case JS_SIMDTYPEREPR_UINT8X16:
return "Uint8x16";
case JS_SIMDTYPEREPR_UINT16X8:
return "Uint16x8";
case JS_SIMDTYPEREPR_UINT32X4:
return "Uint32x4";
case JS_SIMDTYPEREPR_FLOAT32X4:
return "Float32x4";
case JS_SIMDTYPEREPR_FLOAT64X2:
return "Float64x2";
case JS_SIMDTYPEREPR_BOOL8X16:
return "Bool8x16";
case JS_SIMDTYPEREPR_BOOL16X8:
return "Bool16x8";
case JS_SIMDTYPEREPR_BOOL32X4:
return "Bool32x4";
case JS_SIMDTYPEREPR_BOOL64X2:
return "Bool64x2";
}
assert(false, "Unhandled type constant");
return undefined;
}
function SimdTypeToLength(type) {
switch (type) {
case JS_SIMDTYPEREPR_INT8X16:
case JS_SIMDTYPEREPR_BOOL8X16:
return 16;
case JS_SIMDTYPEREPR_INT16X8:
case JS_SIMDTYPEREPR_BOOL16X8:
return 8;
case JS_SIMDTYPEREPR_INT32X4:
case JS_SIMDTYPEREPR_FLOAT32X4:
case JS_SIMDTYPEREPR_BOOL32X4:
return 4;
case JS_SIMDTYPEREPR_FLOAT64X2:
case JS_SIMDTYPEREPR_BOOL64X2:
return 2;
}
assert(false, "Unhandled type constant");
return undefined;
}
// This implements SIMD.*.prototype.valueOf().
// Once we have proper value semantics for SIMD types, this function should just
// perform a type check and return this.
// For now, throw a TypeError unconditionally since valueOf() was probably
// called from ToNumber() which is supposed to throw when attempting to convert
// a SIMD value to a number.
function SimdValueOf() {
if (!IsObject(this) || !ObjectIsTypedObject(this))
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "SIMD", "valueOf", typeof this);
var descr = TypedObjectTypeDescr(this);
if (DESCR_KIND(descr) != JS_TYPEREPR_SIMD_KIND)
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "SIMD", "valueOf", typeof this);
ThrowTypeError(JSMSG_SIMD_TO_NUMBER);
}
function SimdToSource() {
if (!IsObject(this) || !ObjectIsTypedObject(this))
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "SIMD.*", "toSource", typeof this);
var descr = TypedObjectTypeDescr(this);
if (DESCR_KIND(descr) != JS_TYPEREPR_SIMD_KIND)
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "SIMD.*", "toSource", typeof this);
return SimdFormatString(descr, this);
}
function SimdToString() {
if (!IsObject(this) || !ObjectIsTypedObject(this))
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "SIMD.*", "toString", typeof this);
var descr = TypedObjectTypeDescr(this);
if (DESCR_KIND(descr) != JS_TYPEREPR_SIMD_KIND)
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "SIMD.*", "toString", typeof this);
return SimdFormatString(descr, this);
}
function SimdFormatString(descr, typedObj) {
var typerepr = DESCR_TYPE(descr);
var protoString = SimdProtoString(typerepr);
switch (typerepr) {
case JS_SIMDTYPEREPR_INT8X16: {
var s1 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 0);
var s2 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 1);
var s3 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 2);
var s4 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 3);
var s5 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 4);
var s6 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 5);
var s7 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 6);
var s8 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 7);
var s9 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 8);
var s10 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 9);
var s11 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 10);
var s12 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 11);
var s13 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 12);
var s14 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 13);
var s15 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 14);
var s16 = callFunction(std_SIMD_Int8x16_extractLane, null, typedObj, 15);
return `SIMD.${protoString}(${s1}, ${s2}, ${s3}, ${s4}, ${s5}, ${s6}, ${s7}, ${s8}, ${s9}, ${s10}, ${s11}, ${s12}, ${s13}, ${s14}, ${s15}, ${s16})`;
}
case JS_SIMDTYPEREPR_INT16X8: {
var s1 = callFunction(std_SIMD_Int16x8_extractLane, null, typedObj, 0);
var s2 = callFunction(std_SIMD_Int16x8_extractLane, null, typedObj, 1);
var s3 = callFunction(std_SIMD_Int16x8_extractLane, null, typedObj, 2);
var s4 = callFunction(std_SIMD_Int16x8_extractLane, null, typedObj, 3);
var s5 = callFunction(std_SIMD_Int16x8_extractLane, null, typedObj, 4);
var s6 = callFunction(std_SIMD_Int16x8_extractLane, null, typedObj, 5);
var s7 = callFunction(std_SIMD_Int16x8_extractLane, null, typedObj, 6);
var s8 = callFunction(std_SIMD_Int16x8_extractLane, null, typedObj, 7);
return `SIMD.${protoString}(${s1}, ${s2}, ${s3}, ${s4}, ${s5}, ${s6}, ${s7}, ${s8})`;
}
case JS_SIMDTYPEREPR_INT32X4: {
var x = callFunction(std_SIMD_Int32x4_extractLane, null, typedObj, 0);
var y = callFunction(std_SIMD_Int32x4_extractLane, null, typedObj, 1);
var z = callFunction(std_SIMD_Int32x4_extractLane, null, typedObj, 2);
var w = callFunction(std_SIMD_Int32x4_extractLane, null, typedObj, 3);
return `SIMD.${protoString}(${x}, ${y}, ${z}, ${w})`;
}
case JS_SIMDTYPEREPR_UINT8X16: {
var s1 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 0);
var s2 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 1);
var s3 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 2);
var s4 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 3);
var s5 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 4);
var s6 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 5);
var s7 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 6);
var s8 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 7);
var s9 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 8);
var s10 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 9);
var s11 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 10);
var s12 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 11);
var s13 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 12);
var s14 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 13);
var s15 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 14);
var s16 = callFunction(std_SIMD_Uint8x16_extractLane, null, typedObj, 15);
return `SIMD.${protoString}(${s1}, ${s2}, ${s3}, ${s4}, ${s5}, ${s6}, ${s7}, ${s8}, ${s9}, ${s10}, ${s11}, ${s12}, ${s13}, ${s14}, ${s15}, ${s16})`;
}
case JS_SIMDTYPEREPR_UINT16X8: {
var s1 = callFunction(std_SIMD_Uint16x8_extractLane, null, typedObj, 0);
var s2 = callFunction(std_SIMD_Uint16x8_extractLane, null, typedObj, 1);
var s3 = callFunction(std_SIMD_Uint16x8_extractLane, null, typedObj, 2);
var s4 = callFunction(std_SIMD_Uint16x8_extractLane, null, typedObj, 3);
var s5 = callFunction(std_SIMD_Uint16x8_extractLane, null, typedObj, 4);
var s6 = callFunction(std_SIMD_Uint16x8_extractLane, null, typedObj, 5);
var s7 = callFunction(std_SIMD_Uint16x8_extractLane, null, typedObj, 6);
var s8 = callFunction(std_SIMD_Uint16x8_extractLane, null, typedObj, 7);
return `SIMD.${protoString}(${s1}, ${s2}, ${s3}, ${s4}, ${s5}, ${s6}, ${s7}, ${s8})`;
}
case JS_SIMDTYPEREPR_UINT32X4: {
var x = callFunction(std_SIMD_Uint32x4_extractLane, null, typedObj, 0);
var y = callFunction(std_SIMD_Uint32x4_extractLane, null, typedObj, 1);
var z = callFunction(std_SIMD_Uint32x4_extractLane, null, typedObj, 2);
var w = callFunction(std_SIMD_Uint32x4_extractLane, null, typedObj, 3);
return `SIMD.${protoString}(${x}, ${y}, ${z}, ${w})`;
}
case JS_SIMDTYPEREPR_FLOAT32X4: {
var x = callFunction(std_SIMD_Float32x4_extractLane, null, typedObj, 0);
var y = callFunction(std_SIMD_Float32x4_extractLane, null, typedObj, 1);
var z = callFunction(std_SIMD_Float32x4_extractLane, null, typedObj, 2);
var w = callFunction(std_SIMD_Float32x4_extractLane, null, typedObj, 3);
return `SIMD.${protoString}(${x}, ${y}, ${z}, ${w})`;
}
case JS_SIMDTYPEREPR_FLOAT64X2: {
var x = callFunction(std_SIMD_Float64x2_extractLane, null, typedObj, 0);
var y = callFunction(std_SIMD_Float64x2_extractLane, null, typedObj, 1);
return `SIMD.${protoString}(${x}, ${y})`;
}
case JS_SIMDTYPEREPR_BOOL8X16: {
var s1 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 0);
var s2 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 1);
var s3 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 2);
var s4 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 3);
var s5 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 4);
var s6 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 5);
var s7 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 6);
var s8 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 7);
var s9 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 8);
var s10 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 9);
var s11 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 10);
var s12 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 11);
var s13 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 12);
var s14 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 13);
var s15 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 14);
var s16 = callFunction(std_SIMD_Bool8x16_extractLane, null, typedObj, 15);
return `SIMD.${protoString}(${s1}, ${s2}, ${s3}, ${s4}, ${s5}, ${s6}, ${s7}, ${s8}, ${s9}, ${s10}, ${s11}, ${s12}, ${s13}, ${s14}, ${s15}, ${s16})`;
}
case JS_SIMDTYPEREPR_BOOL16X8: {
var s1 = callFunction(std_SIMD_Bool16x8_extractLane, null, typedObj, 0);
var s2 = callFunction(std_SIMD_Bool16x8_extractLane, null, typedObj, 1);
var s3 = callFunction(std_SIMD_Bool16x8_extractLane, null, typedObj, 2);
var s4 = callFunction(std_SIMD_Bool16x8_extractLane, null, typedObj, 3);
var s5 = callFunction(std_SIMD_Bool16x8_extractLane, null, typedObj, 4);
var s6 = callFunction(std_SIMD_Bool16x8_extractLane, null, typedObj, 5);
var s7 = callFunction(std_SIMD_Bool16x8_extractLane, null, typedObj, 6);
var s8 = callFunction(std_SIMD_Bool16x8_extractLane, null, typedObj, 7);
return `SIMD.${protoString}(${s1}, ${s2}, ${s3}, ${s4}, ${s5}, ${s6}, ${s7}, ${s8})`;
}
case JS_SIMDTYPEREPR_BOOL32X4: {
var x = callFunction(std_SIMD_Bool32x4_extractLane, null, typedObj, 0);
var y = callFunction(std_SIMD_Bool32x4_extractLane, null, typedObj, 1);
var z = callFunction(std_SIMD_Bool32x4_extractLane, null, typedObj, 2);
var w = callFunction(std_SIMD_Bool32x4_extractLane, null, typedObj, 3);
return `SIMD.${protoString}(${x}, ${y}, ${z}, ${w})`;
}
case JS_SIMDTYPEREPR_BOOL64X2: {
var x = callFunction(std_SIMD_Bool64x2_extractLane, null, typedObj, 0);
var y = callFunction(std_SIMD_Bool64x2_extractLane, null, typedObj, 1);
return `SIMD.${protoString}(${x}, ${y})`;
}
}
assert(false, "unexpected SIMD kind");
return "?";
}
///////////////////////////////////////////////////////////////////////////
// Miscellaneous

View file

@ -53,7 +53,7 @@
#define JS_DESCR_SLOT_ARRAYPROTO 6 // Lazily created prototype for arrays
#define JS_DESCR_SLOT_TRACE_LIST 7 // List of references for use in tracing
// Slots on scalars, references, and SIMD objects
// Slots on scalars, references
#define JS_DESCR_SLOT_TYPE 8 // Type code
// Slots on array descriptors
@ -75,7 +75,6 @@
#define JS_TYPEREPR_REFERENCE_KIND 2
#define JS_TYPEREPR_STRUCT_KIND 3
#define JS_TYPEREPR_ARRAY_KIND 4
#define JS_TYPEREPR_SIMD_KIND 5
// These constants are for use exclusively in JS code. In C++ code,
// prefer Scalar::Int8 etc, which allows you to write a switch which will
@ -89,10 +88,6 @@
#define JS_SCALARTYPEREPR_FLOAT32 6
#define JS_SCALARTYPEREPR_FLOAT64 7
#define JS_SCALARTYPEREPR_UINT8_CLAMPED 8
#define JS_SCALARTYPEREPR_FLOAT32X4 11
#define JS_SCALARTYPEREPR_INT8X16 12
#define JS_SCALARTYPEREPR_INT16X8 13
#define JS_SCALARTYPEREPR_INT32X4 14
// These constants are for use exclusively in JS code. In C++ code,
// prefer ReferenceTypeRepresentation::TYPE_ANY etc, which allows
@ -102,20 +97,4 @@
#define JS_REFERENCETYPEREPR_OBJECT 1
#define JS_REFERENCETYPEREPR_STRING 2
// These constants are for use exclusively in JS code. In C++ code, prefer
// SimdType::Int32x4 etc, since that allows you to write a switch which will
// receive a warning if you omit a case.
#define JS_SIMDTYPEREPR_INT8X16 0
#define JS_SIMDTYPEREPR_INT16X8 1
#define JS_SIMDTYPEREPR_INT32X4 2
#define JS_SIMDTYPEREPR_UINT8X16 3
#define JS_SIMDTYPEREPR_UINT16X8 4
#define JS_SIMDTYPEREPR_UINT32X4 5
#define JS_SIMDTYPEREPR_FLOAT32X4 6
#define JS_SIMDTYPEREPR_FLOAT64X2 7
#define JS_SIMDTYPEREPR_BOOL8X16 8
#define JS_SIMDTYPEREPR_BOOL16X8 9
#define JS_SIMDTYPEREPR_BOOL32X4 10
#define JS_SIMDTYPEREPR_BOOL64X2 11
#endif

View file

@ -1,4 +1,3 @@
SIMD/nursery-overflow.js
asm.js/testBug1117235.js
asm.js/testParallelCompile.js
auto-regress/bug653395.js

View file

@ -152,11 +152,6 @@ Failed to do range check of element access on a typed object.
### AccessNotDense
### AccessNotSimdObject
The observed type of the target of the property access doesn't guarantee
that it is a SIMD object.
### AccessNotTypedObject
The observed type of the target of the property access doesn't guarantee
@ -222,15 +217,6 @@ the keys have never been observed to be a String, Symbol, or Int32.
IonMonkey only generates inline caches for element accesses which are
either on dense objects (e.g. dense Arrays), or Typed Arrays.
### NoSimdJitSupport
Optimization failed because SIMD JIT support was not enabled.
### SimdTypeNotOptimized
The type observed as being retrieved from this property access did not
match an optimizable type.
### HasCommonInliningPath
Inlining was abandoned because the inlining call path was repeated. A

View file

@ -274,7 +274,7 @@ const size_t BINKIND_LIMIT = 183;
* (sorted by alphabetical order)
*/
#define FOR_EACH_BIN_FIELD(F) \
F(Offset, "_offset") \
F(Skip, "_skip") \
F(Alternate, "alternate") \
F(Arguments, "arguments") \
F(Binding, "binding") \

View file

@ -12,14 +12,17 @@
#include "mozilla/Attributes.h"
#include "mozilla/IntegerTypeTraits.h"
#include "mozilla/Likely.h"
#include "mozilla/Maybe.h"
#include "mozilla/MemoryChecking.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/Span.h"
#include "mozilla/TextUtils.h"
#include "mozilla/Utf8.h"
#include <algorithm>
#include <ctype.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <utility>
@ -41,10 +44,14 @@
using mozilla::ArrayLength;
using mozilla::AssertedCast;
using mozilla::DecodeOneUtf8CodePoint;
using mozilla::IsAscii;
using mozilla::IsAsciiAlpha;
using mozilla::IsAsciiDigit;
using mozilla::IsTrailingUnit;
using mozilla::MakeScopeExit;
using mozilla::MakeSpan;
using mozilla::Maybe;
using mozilla::PointerRangeSize;
using mozilla::Utf8Unit;
@ -464,6 +471,41 @@ TokenStreamCharsBase<char16_t>::fillCharBufferFromSourceNormalizingAsciiLineBrea
return true;
}
template<>
MOZ_MUST_USE bool
TokenStreamCharsBase<Utf8Unit>::fillCharBufferFromSourceNormalizingAsciiLineBreaks(const Utf8Unit* cur,
const Utf8Unit* end)
{
MOZ_ASSERT(this->charBuffer.length() == 0);
while (cur < end) {
Utf8Unit unit = *cur++;
if (MOZ_LIKELY(IsAscii(unit))) {
char16_t ch = unit.toUint8();
if (ch == '\r') {
ch = '\n';
if (cur < end && *cur == Utf8Unit('\n'))
cur++;
}
if (!this->charBuffer.append(ch))
return false;
continue;
}
Maybe<char32_t> ch = DecodeOneUtf8CodePoint(unit, &cur, end);
MOZ_ASSERT(ch.isSome(),
"provided source text should already have been validated");
if (!appendCodePointToCharBuffer(ch.value()))
return false;
}
MOZ_ASSERT(cur == end);
return true;
}
template<typename CharT, class AnyCharsAccess>
TokenStreamSpecific<CharT, AnyCharsAccess>::TokenStreamSpecific(JSContext* cx,
const ReadOnlyCompileOptions& options,
@ -511,41 +553,241 @@ TokenStreamAnyChars::undoInternalUpdateLineInfoForEOL()
lineno--;
}
template<class AnyCharsAccess>
bool
TokenStreamChars<char16_t, AnyCharsAccess>::getCodePoint(int32_t* cp)
{
TokenStreamAnyChars& anyChars = anyCharsAccess();
#ifdef DEBUG
if (MOZ_UNLIKELY(this->sourceUnits.atEnd())) {
anyChars.flags.isEOF = true;
*cp = EOF;
return true;
template<>
inline void
SourceUnits<char16_t>::assertNextCodePoint(const PeekedCodePoint<char16_t>& peeked)
{
char32_t c = peeked.codePoint();
if (c < unicode::NonBMPMin) {
MOZ_ASSERT(peeked.lengthInUnits() == 1);
MOZ_ASSERT(ptr[0] == c);
} else {
MOZ_ASSERT(peeked.lengthInUnits() == 2);
char16_t lead, trail;
unicode::UTF16Encode(c, &lead, &trail);
MOZ_ASSERT(ptr[0] == lead);
MOZ_ASSERT(ptr[1] == trail);
}
}
template<>
inline void
SourceUnits<Utf8Unit>::assertNextCodePoint(const PeekedCodePoint<Utf8Unit>& peeked)
{
char32_t c = peeked.codePoint();
// This is all roughly indulgence of paranoia only for assertions, so the
// reimplementation of UTF-8 encoding a code point is (we think) a virtue.
uint8_t expectedUnits[4] = {};
if (c < 0x80) {
expectedUnits[0] = AssertedCast<uint8_t>(c);
} else if (c < 0x800) {
expectedUnits[0] = 0b1100'0000 | (c >> 6);
expectedUnits[1] = 0b1000'0000 | (c & 0b11'1111);
} else if (c < 0x10000) {
expectedUnits[0] = 0b1110'0000 | (c >> 12);
expectedUnits[1] = 0b1000'0000 | ((c >> 6) & 0b11'1111);
expectedUnits[2] = 0b1000'0000 | (c & 0b11'1111);
} else {
expectedUnits[0] = 0b1110'0000 | (c >> 18);
expectedUnits[2] = 0b1000'0000 | ((c >> 12) & 0b11'1111);
expectedUnits[2] = 0b1000'0000 | ((c >> 6) & 0b11'1111);
expectedUnits[3] = 0b1000'0000 | (c & 0b11'1111);
}
int32_t c = this->sourceUnits.getCodeUnit();
MOZ_ASSERT(peeked.lengthInUnits() <= 4);
for (uint8_t i = 0; i < peeked.lengthInUnits(); i++)
MOZ_ASSERT(expectedUnits[i] == ptr[i].toUint8());
}
#endif // DEBUG
template<class AnyCharsAccess>
MOZ_COLD void
TokenStreamChars<Utf8Unit, AnyCharsAccess>::internalEncodingError(uint8_t relevantUnits,
unsigned errorNumber, ...)
{
va_list args;
va_start(args, errorNumber);
do {
// Normalize the char16_t if it was a newline.
if (MOZ_UNLIKELY(c == '\n'))
break;
size_t offset = this->sourceUnits.offset();
if (MOZ_UNLIKELY(c == '\r')) {
matchLineTerminator('\n');
ErrorMetadata err;
TokenStreamAnyChars& anyChars = anyCharsAccess();
if (bool hasLineOfContext = anyChars.fillExcludingContext(&err, offset)) {
if (!internalComputeLineOfContext(&err, offset))
break;
// As this is an encoding error, the computed window-end must be
// identical to the location of the error -- any further on and the
// window would contain invalid Unicode.
MOZ_ASSERT_IF(err.lineOfContext != nullptr,
err.lineLength == err.tokenOffset);
}
auto notes = MakeUnique<JSErrorNotes>();
if (!notes) {
ReportOutOfMemory(anyChars.cx);
break;
}
if (MOZ_UNLIKELY(c == unicode::LINE_SEPARATOR || c == unicode::PARA_SEPARATOR))
break;
// The largest encoding of a UTF-8 code point is 4 units. (Encoding an
// obsolete 5- or 6-byte code point will complain only about a bad lead
// code unit.)
constexpr size_t MaxWidth = sizeof("0xHH 0xHH 0xHH 0xHH");
*cp = c;
return true;
MOZ_ASSERT(relevantUnits > 0);
char badUnitsStr[MaxWidth];
char* ptr = badUnitsStr;
while (relevantUnits > 0) {
byteToString(this->sourceUnits.getCodeUnit().toUint8(), ptr);
ptr[4] = ' ';
ptr += 5;
relevantUnits--;
}
ptr[-1] = '\0';
uint32_t line, column;
anyChars.srcCoords.lineNumAndColumnIndex(offset, &line, &column);
if (!notes->addNoteASCII(anyChars.cx, anyChars.getFilename(), line, column,
GetErrorMessage, nullptr, JSMSG_BAD_CODE_UNITS, badUnitsStr))
{
break;
}
ReportCompileError(anyChars.cx, std::move(err), std::move(notes), JSREPORT_ERROR,
errorNumber, args);
} while (false);
if (!updateLineInfoForEOL())
va_end(args);
}
template<class AnyCharsAccess>
MOZ_COLD void
TokenStreamChars<Utf8Unit, AnyCharsAccess>::badLeadUnit(Utf8Unit lead)
{
uint8_t leadValue = lead.toUint8();
char leadByteStr[5];
byteToTerminatedString(leadValue, leadByteStr);
internalEncodingError(1, JSMSG_BAD_LEADING_UTF8_UNIT, leadByteStr);
}
template<class AnyCharsAccess>
MOZ_COLD void
TokenStreamChars<Utf8Unit, AnyCharsAccess>::notEnoughUnits(Utf8Unit lead,
uint8_t remaining, uint8_t required)
{
uint8_t leadValue = lead.toUint8();
MOZ_ASSERT(required == 2 || required == 3 || required == 4);
MOZ_ASSERT(remaining < 4);
MOZ_ASSERT(remaining < required);
char leadByteStr[5];
byteToTerminatedString(leadValue, leadByteStr);
// |toHexChar| produces the desired decimal numbers for values < 4.
const char expectedStr[] = { toHexChar(required - 1), '\0' };
const char actualStr[] = { toHexChar(remaining - 1), '\0' };
internalEncodingError(remaining, JSMSG_NOT_ENOUGH_CODE_UNITS,
leadByteStr, expectedStr, actualStr, remaining == 2 ? " was" : "s were");
}
template<class AnyCharsAccess>
MOZ_COLD void
TokenStreamChars<Utf8Unit, AnyCharsAccess>::badTrailingUnit(Utf8Unit badUnit,
uint8_t unitsObserved)
{
char badByteStr[5];
byteToTerminatedString(badUnit.toUint8(), badByteStr);
internalEncodingError(unitsObserved, JSMSG_BAD_TRAILING_UTF8_UNIT, badByteStr);
}
template<class AnyCharsAccess>
MOZ_COLD void
TokenStreamChars<Utf8Unit, AnyCharsAccess>::badStructurallyValidCodePoint(uint32_t codePoint,
uint8_t codePointLength,
const char* reason)
{
// Construct a string like "0x203D" (including null terminator) to include
// in the error message. Write the string end-to-start from end to start
// of an adequately sized |char| array, shifting least significant nibbles
// off the number and writing the corresponding hex digits until done, then
// prefixing with "0x". |codePointStr| points at the incrementally
// computed string, within |codePointCharsArray|'s bounds.
// 0x1F'FFFF is the maximum value that can fit in 3+6+6+6 unconstrained
// bits in a four-byte UTF-8 code unit sequence.
constexpr size_t MaxHexSize = sizeof("0x1F" "FFFF"); // including '\0'
char codePointCharsArray[MaxHexSize];
char* codePointStr = codePointCharsArray + ArrayLength(codePointCharsArray);
*--codePointStr = '\0';
uint32_t copy = codePoint;
while (copy) {
MOZ_ASSERT(codePointCharsArray < codePointStr);
*--codePointStr = toHexChar(copy & 0xF);
copy >>= 4;
}
MOZ_ASSERT(codePointCharsArray + 2 <= codePointStr);
*--codePointStr = 'x';
*--codePointStr = '0';
internalEncodingError(codePointLength, JSMSG_FORBIDDEN_UTF8_CODE_POINT, codePointStr, reason);
}
template<class AnyCharsAccess>
MOZ_MUST_USE bool
TokenStreamChars<Utf8Unit, AnyCharsAccess>::getNonAsciiCodePointDontNormalize(Utf8Unit lead,
char32_t* codePoint)
{
auto onBadLeadUnit = [this, &lead]() {
this->badLeadUnit(lead);
};
auto onNotEnoughUnits = [this, &lead](uint8_t remaining, uint8_t required) {
this->notEnoughUnits(lead, remaining, required);
};
auto onBadTrailingUnit = [this, &lead](uint8_t unitsObserved) {
this->badTrailingUnit(lead, unitsObserved);
};
auto onBadCodePoint = [this](char32_t badCodePoint, uint8_t unitsObserved) {
this->badCodePoint(badCodePoint, unitsObserved);
};
auto onNotShortestForm = [this](char32_t badCodePoint, uint8_t unitsObserved) {
this->notShortestForm(badCodePoint, unitsObserved);
};
// If a valid code point is decoded, this function call consumes its code
// units. If not, it ungets the lead code unit and invokes the right error
// handler, so on failure we must immediately return false.
SourceUnitsIterator iter(this->sourceUnits);
Maybe<char32_t> maybeCodePoint =
DecodeOneUtf8CodePointInline(lead, &iter, SourceUnitsEnd(),
onBadLeadUnit, onNotEnoughUnits, onBadTrailingUnit,
onBadCodePoint, onNotShortestForm);
if (maybeCodePoint.isNothing())
return false;
*cp = '\n';
*codePoint = maybeCodePoint.value();
return true;
}
@ -603,25 +845,88 @@ TokenStreamChars<char16_t, AnyCharsAccess>::getNonAsciiCodePoint(int32_t lead, i
return true;
}
template<class AnyCharsAccess>
void
TokenStreamChars<char16_t, AnyCharsAccess>::ungetCodePointIgnoreEOL(uint32_t codePoint)
template<typename CharT, class AnyCharsAccess>
bool
TokenStreamSpecific<CharT, AnyCharsAccess>::getCodePoint(int32_t* cp)
{
MOZ_ASSERT(!this->sourceUnits.atStart());
int32_t unit = getCodeUnit();
if (unit == EOF) {
MOZ_ASSERT(anyCharsAccess().flags.isEOF,
"flags.isEOF should have been set by getCodeUnit()");
*cp = EOF;
return true;
}
unsigned numUnits = 0;
char16_t units[2];
unicode::UTF16Encode(codePoint, units, &numUnits);
if (isAsciiCodePoint(unit))
return getFullAsciiCodePoint(unit, cp);
MOZ_ASSERT(numUnits == 1 || numUnits == 2);
return getNonAsciiCodePoint(unit, cp);
}
while (numUnits-- > 0)
ungetCodeUnit(units[numUnits]);
template<class AnyCharsAccess>
bool
TokenStreamChars<Utf8Unit, AnyCharsAccess>::getNonAsciiCodePoint(int32_t unit, int32_t* codePoint)
{
MOZ_ASSERT(unit != EOF);
MOZ_ASSERT(!isAsciiCodePoint(unit),
"ASCII code unit/point must be handled separately");
Utf8Unit lead = Utf8Unit(static_cast<unsigned char>(unit));
MOZ_ASSERT(lead == this->sourceUnits.previousCodeUnit(),
"getNonAsciiCodePoint called incorrectly");
auto onBadLeadUnit = [this, &lead]() {
this->badLeadUnit(lead);
};
auto onNotEnoughUnits = [this, &lead](uint_fast8_t remaining, uint_fast8_t required) {
this->notEnoughUnits(lead, remaining, required);
};
auto onBadTrailingUnit = [this, &lead](uint_fast8_t unitsObserved) {
this->badTrailingUnit(lead, unitsObserved);
};
auto onBadCodePoint = [this](char32_t badCodePoint, uint_fast8_t unitsObserved) {
this->badCodePoint(badCodePoint, unitsObserved);
};
auto onNotShortestForm = [this](char32_t badCodePoint, uint_fast8_t unitsObserved) {
this->notShortestForm(badCodePoint, unitsObserved);
};
// This consumes the full, valid code point or ungets |lead| and calls the
// appropriate error functor on failure.
SourceUnitsIterator iter(this->sourceUnits);
Maybe<char32_t> maybeCodePoint =
DecodeOneUtf8CodePoint(lead, &iter, SourceUnitsEnd(),
onBadLeadUnit, onNotEnoughUnits, onBadTrailingUnit, onBadCodePoint,
onNotShortestForm);
if (maybeCodePoint.isNothing())
return false;
char32_t cp = maybeCodePoint.value();
if (MOZ_UNLIKELY(cp == unicode::LINE_SEPARATOR || cp == unicode::PARA_SEPARATOR)) {
if (!updateLineInfoForEOL()) {
#ifdef DEBUG
*codePoint = EOF; // sentinel value to hopefully cause errors
#endif
MOZ_MAKE_MEM_UNDEFINED(codePoint, sizeof(*codePoint));
return false;
}
*codePoint = '\n';
} else {
MOZ_ASSERT(!IsLineTerminator(cp));
*codePoint = AssertedCast<int32_t>(cp);
}
return true;
}
template<>
size_t
SourceUnits<char16_t>::findWindowStart(size_t offset)
SourceUnits<char16_t>::findWindowStart(size_t offset) const
{
// This is JS's understanding of UTF-16 that allows lone surrogates, so
// we have to exclude lone surrogates from [windowStart, offset) ourselves.
@ -679,7 +984,70 @@ SourceUnits<char16_t>::findWindowStart(size_t offset)
template<>
size_t
SourceUnits<char16_t>::findWindowEnd(size_t offset)
SourceUnits<Utf8Unit>::findWindowStart(size_t offset) const
{
// |offset| must be the location of the error or somewhere before it, so we
// know preceding data is valid UTF-8.
const Utf8Unit* const earliestPossibleStart = codeUnitPtrAt(startOffset_);
const Utf8Unit* const initial = codeUnitPtrAt(offset);
const Utf8Unit* p = initial;
auto HalfWindowSize = [&p, &initial]() { return PointerRangeSize(p, initial); };
while (true) {
MOZ_ASSERT(earliestPossibleStart <= p);
MOZ_ASSERT(HalfWindowSize() <= WindowRadius);
if (p <= earliestPossibleStart || HalfWindowSize() >= WindowRadius)
break;
// Peek backward for a line break, and only decrement if there is none.
uint8_t prev = p[-1].toUint8();
// First check for the ASCII LineTerminators.
if (prev == '\r' || prev == '\n')
break;
// Now check for the non-ASCII LineTerminators U+2028 LINE SEPARATOR
// (0xE2 0x80 0xA8) and U+2029 PARAGRAPH (0xE2 0x80 0xA9). If there
// aren't three code units available, some comparison here will fail
// before we'd underflow.
if (MOZ_UNLIKELY((prev == 0xA8 || prev == 0xA9) &&
p[-2].toUint8() == 0x80 &&
p[-3].toUint8() == 0xE2))
{
break;
}
// Rewind over the non-LineTerminator. This can't underflow
// |earliestPossibleStart| because it begins a code point.
while (IsTrailingUnit(*--p))
continue;
MOZ_ASSERT(earliestPossibleStart <= p);
// But if we underflowed |WindowRadius|, adjust forward and stop.
if (HalfWindowSize() > WindowRadius) {
static_assert(WindowRadius > 3,
"skipping over non-lead code units below must not "
"advance past |offset|");
while (IsTrailingUnit(*++p))
continue;
MOZ_ASSERT(HalfWindowSize() < WindowRadius);
break;
}
}
MOZ_ASSERT(HalfWindowSize() <= WindowRadius);
return offset - HalfWindowSize();
}
template<>
size_t
SourceUnits<char16_t>::findWindowEnd(size_t offset) const
{
const char16_t* const initial = codeUnitPtrAt(offset);
const char16_t* p = initial;
@ -730,6 +1098,55 @@ SourceUnits<char16_t>::findWindowEnd(size_t offset)
return offset + HalfWindowSize();
}
template<>
size_t
SourceUnits<Utf8Unit>::findWindowEnd(size_t offset) const
{
const Utf8Unit* const initial = codeUnitPtrAt(offset);
const Utf8Unit* p = initial;
auto HalfWindowSize = [&initial, &p]() { return PointerRangeSize(initial, p); };
while (true) {
MOZ_ASSERT(p <= limit_);
MOZ_ASSERT(HalfWindowSize() <= WindowRadius);
if (p >= limit_ || HalfWindowSize() >= WindowRadius)
break;
// A non-encoding error might be followed by an encoding error within
// |maxEnd|, so we must validate as we go to not include invalid UTF-8
// in the computed window. What joy!
Utf8Unit lead = *p;
if (mozilla::IsAscii(lead)) {
if (IsSingleUnitLineTerminator(lead))
break;
p++;
continue;
}
PeekedCodePoint<Utf8Unit> peeked = PeekCodePoint(p, limit_);
if (peeked.isNone())
break; // encoding error
char32_t c = peeked.codePoint();
if (MOZ_UNLIKELY(c == unicode::LINE_SEPARATOR || c == unicode::PARA_SEPARATOR))
break;
MOZ_ASSERT(!IsLineTerminator(c));
uint8_t len = peeked.lengthInUnits();
if (HalfWindowSize() + len > WindowRadius)
break;
p += len;
}
MOZ_ASSERT(HalfWindowSize() <= WindowRadius);
return offset + HalfWindowSize();
}
template<typename CharT, class AnyCharsAccess>
bool
TokenStreamSpecific<CharT, AnyCharsAccess>::advance(size_t position)
@ -876,23 +1293,10 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::currentLineAndColumn(uint32_t* line,
anyChars.srcCoords.lineNumAndColumnIndex(offset, line, column);
}
template<>
template<typename CharT>
bool
TokenStreamCharsBase<Utf8Unit>::addLineOfContext(ErrorMetadata* err, uint32_t offset)
TokenStreamCharsBase<CharT>::addLineOfContext(ErrorMetadata* err, uint32_t offset)
{
// The specialization below is 100% usable if tweaked to be a definition
// for any CharT, but it demands SourceUnits::findWindow{Start,End} and
// TokenStreamCharsBase::fillCharBufferFromSourceNormalizingAsciiLineBreaks
// for UTF-8 that haven't been defined yet. Use a placeholder definition
// til those are place.
return true;
}
template<>
bool
TokenStreamCharsBase<char16_t>::addLineOfContext(ErrorMetadata* err, uint32_t offset)
{
using CharT = char16_t;
size_t windowStart = sourceUnits.findWindowStart(offset);
size_t windowEnd = sourceUnits.findWindowEnd(offset);
@ -1271,16 +1675,18 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getDirective(bool isMultiline,
continue;
}
int32_t codePoint;
if (!getCodePoint(&codePoint))
return false;
if (unicode::IsSpaceOrBOM2(codePoint)) {
ungetNonAsciiNormalizedCodePoint(codePoint);
// This ignores encoding errors: subsequent caller-side code to
// handle the remaining source text in the comment will do so.
PeekedCodePoint<CharT> peeked = this->sourceUnits.peekCodePoint();
if (peeked.isNone() || unicode::IsSpaceOrBOM2(peeked.codePoint()))
break;
}
if (!appendCodePointToCharBuffer(codePoint))
MOZ_ASSERT(!IsLineTerminator(peeked.codePoint()),
"!IsSpaceOrBOM2 must imply !IsLineTerminator or else we'll "
"fail to maintain line-info/flags for EOL");
this->sourceUnits.consumeKnownCodePoint(peeked);
if (!appendCodePointToCharBuffer(peeked.codePoint()))
return false;
} while (true);
@ -1455,11 +1861,13 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::identifierName(TokenStart start,
// code points in the loop below.
int32_t unit;
while (true) {
unit = getCodeUnit();
unit = peekCodeUnit();
if (unit == EOF)
break;
if (MOZ_LIKELY(isAsciiCodePoint(unit))) {
consumeKnownCodeUnit(unit);
if (MOZ_UNLIKELY(!unicode::IsIdentifierPart(static_cast<char16_t>(unit)))) {
// Handle a Unicode escape -- otherwise it's not part of the
// identifier.
@ -1472,14 +1880,17 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::identifierName(TokenStart start,
escaping = IdentifierEscapes::SawUnicodeEscape;
}
} else {
int32_t codePoint;
if (!getNonAsciiCodePoint(unit, &codePoint))
return false;
if (!unicode::IsIdentifierPart(uint32_t(codePoint))) {
ungetNonAsciiNormalizedCodePoint(codePoint);
// This ignores encoding errors: subsequent caller-side code to
// handle source text after the IdentifierName will do so.
PeekedCodePoint<CharT> peeked = this->sourceUnits.peekCodePoint();
if (peeked.isNone() || !unicode::IsIdentifierPart(peeked.codePoint()))
break;
}
MOZ_ASSERT(!IsLineTerminator(peeked.codePoint()),
"IdentifierPart must guarantee !IsLineTerminator or "
"else we'll fail to maintain line-info/flags for EOL");
this->sourceUnits.consumeKnownCodePoint(peeked);
}
}
@ -1503,7 +1914,7 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::identifierName(TokenStart start,
return true;
}
atom = atomizeSourceChars(anyCharsAccess().cx, chars, length);
atom = atomizeSourceChars(anyCharsAccess().cx, MakeSpan(chars, length));
}
if (!atom)
return false;
@ -1596,15 +2007,42 @@ static const uint8_t firstCharKinds[] = {
static_assert(LastCharKind < (1 << (sizeof(firstCharKinds[0]) * 8)),
"Elements of firstCharKinds[] are too small");
template<>
void
SpecializedTokenStreamCharsBase<char16_t>::infallibleConsumeRestOfSingleLineComment()
SourceUnits<char16_t>::consumeRestOfSingleLineComment()
{
while (MOZ_LIKELY(!this->sourceUnits.atEnd())) {
char16_t unit = this->sourceUnits.peekCodeUnit();
while (MOZ_LIKELY(!atEnd())) {
char16_t unit = peekCodeUnit();
if (IsLineTerminator(unit))
return;
this->sourceUnits.consumeKnownCodeUnit(unit);
consumeKnownCodeUnit(unit);
}
}
template<>
void
SourceUnits<Utf8Unit>::consumeRestOfSingleLineComment()
{
while (MOZ_LIKELY(!atEnd())) {
const Utf8Unit unit = peekCodeUnit();
if (IsSingleUnitLineTerminator(unit))
return;
if (MOZ_LIKELY(IsAscii(unit))) {
consumeKnownCodeUnit(unit);
continue;
}
PeekedCodePoint<Utf8Unit> peeked = peekCodePoint();
if (peeked.isNone())
return;
char32_t c = peeked.codePoint();
if (MOZ_UNLIKELY(c == unicode::LINE_SEPARATOR || c == unicode::PARA_SEPARATOR))
return;
consumeKnownCodePoint(peeked);
}
}
@ -1686,13 +2124,10 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::decimalNumber(int32_t unit, TokenSta
return false;
}
} else {
int32_t codePoint;
if (!getCodePoint(&codePoint))
return false;
ungetNonAsciiNormalizedCodePoint(codePoint);
if (unicode::IsIdentifierStart(uint32_t(codePoint))) {
// This ignores encoding errors: subsequent caller-side code to
// handle source text after the number will do so.
PeekedCodePoint<CharT> peeked = this->sourceUnits.peekCodePoint();
if (!peeked.isNone() && unicode::IsIdentifierStart(peeked.codePoint())) {
error(JSMSG_IDSTART_AFTER_NUMBER);
return false;
}
@ -1843,7 +2278,7 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* const tt
// This loop runs more than once only when whitespace or comments are
// encountered.
do {
int32_t unit = getCodeUnit();
int32_t unit = peekCodeUnit();
if (MOZ_UNLIKELY(unit == EOF)) {
MOZ_ASSERT(this->sourceUnits.atEnd());
anyCharsAccess().flags.isEOF = true;
@ -1859,16 +2294,25 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* const tt
// a variable number of code points, it's easier to assume it's an
// identifier and maybe do a little wasted work, than to unget and
// compute and reget if whitespace.
TokenStart start(this->sourceUnits, -1);
const CharT* identStart = this->sourceUnits.addressOfNextCodeUnit() - 1;
TokenStart start(this->sourceUnits, 0);
const CharT* identStart = this->sourceUnits.addressOfNextCodeUnit();
int32_t codePoint;
if (!getNonAsciiCodePoint(unit, &codePoint))
PeekedCodePoint<CharT> peeked = this->sourceUnits.peekCodePoint();
if (peeked.isNone()) {
int32_t bad;
MOZ_ALWAYS_FALSE(getCodePoint(&bad));
return badToken();
}
char32_t cp = peeked.codePoint();
if (unicode::IsSpaceOrBOM2(cp)) {
this->sourceUnits.consumeKnownCodePoint(peeked);
if (IsLineTerminator(cp)) {
if (!updateLineInfoForEOL())
return badToken();
if (unicode::IsSpaceOrBOM2(codePoint)) {
if (codePoint == '\n')
anyCharsAccess().updateFlagsForEOL();
}
continue;
}
@ -1882,14 +2326,22 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* const tt
"!IsUnicodeIDStart('_'), ensure that '_' is never "
"handled here");
if (unicode::IsUnicodeIDStart(uint32_t(codePoint)))
return identifierName(start, identStart, IdentifierEscapes::None, modifier, ttp);
if (MOZ_LIKELY(unicode::IsUnicodeIDStart(cp))) {
this->sourceUnits.consumeKnownCodePoint(peeked);
MOZ_ASSERT(!IsLineTerminator(cp),
"IdentifierStart must guarantee !IsLineTerminator "
"or else we'll fail to maintain line-info/flags "
"for EOL here");
return identifierName(start, identStart, IdentifierEscapes::None, modifier, ttp);
}
ungetCodePointIgnoreEOL(codePoint);
error(JSMSG_ILLEGAL_CHARACTER);
return badToken();
} // !isAsciiCodePoint(unit)
consumeKnownCodeUnit(unit);
// Get the token kind, based on the first char. The ordering of c1kind
// comparison is based on the frequency of tokens in real code:
// Parsemark (which represents typical JS code on the web) and the
@ -2047,29 +2499,21 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* const tt
return decimalNumber(unit, start, numStart, modifier, ttp);
}
// Check for an identifier-start code point immediately after the
// number. This must be an error, and somewhat surprisingly, if
// a check doesn't happen here, it never will.
if (MOZ_UNLIKELY(unit == EOF)) {
// Technically this isn't necessary -- ungetting EOF does
// nothing -- but it's conceptually nicer if we consider all
// gets requiring an unget to revert them.
ungetCodeUnit(unit);
} else if (MOZ_LIKELY(isAsciiCodePoint(unit))) {
ungetCodeUnit(unit);
ungetCodeUnit(unit);
// Error if an identifier-start code point appears immediately
// after the number. Somewhat surprisingly, if we don't check
// here, we'll never check at all.
if (MOZ_LIKELY(isAsciiCodePoint(unit))) {
if (unicode::IsIdentifierStart(char16_t(unit))) {
error(JSMSG_IDSTART_AFTER_NUMBER);
return badToken();
}
} else {
int32_t codePoint;
if (!getNonAsciiCodePoint(unit, &codePoint))
return badToken();
ungetNonAsciiNormalizedCodePoint(codePoint);
if (unicode::IsIdentifierStart(uint32_t(codePoint))) {
} else if (MOZ_LIKELY(unit != EOF)) {
// This ignores encoding errors: subsequent caller-side code to
// handle source text after the number will do so.
PeekedCodePoint<CharT> peeked = this->sourceUnits.peekCodePoint();
if (!peeked.isNone() && unicode::IsIdentifierStart(peeked.codePoint())) {
error(JSMSG_IDSTART_AFTER_NUMBER);
return badToken();
}
@ -2189,9 +2633,7 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* const tt
if (matchCodeUnit('!')) {
if (matchCodeUnit('-')) {
if (matchCodeUnit('-')) {
if (!consumeRestOfSingleLineComment())
return false;
this->sourceUnits.consumeRestOfSingleLineComment();
continue;
}
ungetCodeUnit('-');
@ -2236,9 +2678,7 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* const tt
ungetCodeUnit(unit);
}
if (!consumeRestOfSingleLineComment())
return false;
this->sourceUnits.consumeRestOfSingleLineComment();
continue;
}
@ -2295,9 +2735,7 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* const tt
!anyCharsAccess().flags.isDirtyLine)
{
if (matchCodeUnit('>')) {
if (!consumeRestOfSingleLineComment())
return false;
this->sourceUnits.consumeRestOfSingleLineComment();
continue;
}
}
@ -2715,6 +3153,10 @@ template class TokenStreamCharsBase<char16_t>;
template class TokenStreamChars<char16_t, TokenStreamAnyCharsAccess>;
template class TokenStreamSpecific<char16_t, TokenStreamAnyCharsAccess>;
template class
TokenStreamChars<Utf8Unit, ParserAnyCharsAccess<GeneralParser<FullParseHandler, Utf8Unit>>>;
template class
TokenStreamChars<Utf8Unit, ParserAnyCharsAccess<GeneralParser<SyntaxParseHandler, Utf8Unit>>>;
template class
TokenStreamChars<char16_t, ParserAnyCharsAccess<GeneralParser<FullParseHandler, char16_t>>>;
template class

View file

@ -185,8 +185,10 @@
#include "mozilla/Attributes.h"
#include "mozilla/Casting.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Maybe.h"
#include "mozilla/MemoryChecking.h"
#include "mozilla/PodOperations.h"
#include "mozilla/Span.h"
#include "mozilla/TextUtils.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Unused.h"
@ -195,6 +197,7 @@
#include <algorithm>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "jspubtd.h"
@ -969,6 +972,156 @@ IsLineTerminator(char16_t unit)
return IsLineTerminator(static_cast<char32_t>(unit));
}
template<typename CharT>
struct SourceUnitTraits;
template<>
struct SourceUnitTraits<char16_t>
{
public:
static constexpr uint8_t maxUnitsLength = 2;
static constexpr size_t lengthInUnits(char32_t codePoint) {
return codePoint < unicode::NonBMPMin ? 1 : 2;
}
};
template<>
struct SourceUnitTraits<mozilla::Utf8Unit>
{
public:
static constexpr uint8_t maxUnitsLength = 4;
static constexpr size_t lengthInUnits(char32_t codePoint) {
return codePoint < 0x80
? 1
: codePoint < 0x800
? 2
: codePoint < 0x10000
? 3
: 4;
}
};
/**
* PeekedCodePoint represents the result of peeking ahead in some source text
* to determine the next validly-encoded code point.
*
* If there isn't a valid code point, then |isNone()|.
*
* But if there *is* a valid code point, then |!isNone()|, the code point has
* value |codePoint()| and its length in code units is |lengthInUnits()|.
*
* Conceptually, this class is |Maybe<struct { char32_t v; uint8_t len; }>|.
*/
template<typename CharT>
class PeekedCodePoint final
{
char32_t codePoint_ = 0;
uint8_t lengthInUnits_ = 0;
private:
using SourceUnitTraits = frontend::SourceUnitTraits<CharT>;
PeekedCodePoint() = default;
public:
/**
* Create a peeked code point with the given value and length in code
* units.
*
* While the latter value is computable from the former for both UTF-8 and
* JS's version of UTF-16, the caller likely computed a length in units in
* the course of determining the peeked value. Passing both here avoids
* recomputation and lets us do a consistency-checking assertion.
*/
PeekedCodePoint(char32_t codePoint, uint8_t lengthInUnits)
: codePoint_(codePoint),
lengthInUnits_(lengthInUnits)
{
MOZ_ASSERT(codePoint <= unicode::NonBMPMax);
MOZ_ASSERT(lengthInUnits != 0, "bad code point length");
MOZ_ASSERT(lengthInUnits == SourceUnitTraits::lengthInUnits(codePoint));
}
/** Create a PeekedCodeUnit that represents no valid code point. */
static PeekedCodePoint none() {
return PeekedCodePoint();
}
/** True if no code point was found, false otherwise. */
bool isNone() const {
return lengthInUnits_ == 0;
}
/** If a code point was found, its value. */
char32_t codePoint() const {
MOZ_ASSERT(!isNone());
return codePoint_;
}
/** If a code point was found, its length in code units. */
uint8_t lengthInUnits() const {
MOZ_ASSERT(!isNone());
return lengthInUnits_;
}
};
inline PeekedCodePoint<char16_t>
PeekCodePoint(const char16_t* const ptr, const char16_t* const end)
{
if (MOZ_UNLIKELY(ptr >= end))
return PeekedCodePoint<char16_t>::none();
char16_t lead = ptr[0];
char32_t c;
uint8_t len;
if (MOZ_LIKELY(!unicode::IsLeadSurrogate(lead)) ||
MOZ_UNLIKELY(ptr + 1 >= end ||
!unicode::IsTrailSurrogate(ptr[1])))
{
c = lead;
len = 1;
} else {
c = unicode::UTF16Decode(lead, ptr[1]);
len = 2;
}
return PeekedCodePoint<char16_t>(c, len);
}
inline PeekedCodePoint<mozilla::Utf8Unit>
PeekCodePoint(const mozilla::Utf8Unit* const ptr, const mozilla::Utf8Unit* const end)
{
if (MOZ_UNLIKELY(ptr >= end))
return PeekedCodePoint<mozilla::Utf8Unit>::none();
const mozilla::Utf8Unit lead = ptr[0];
if (mozilla::IsAscii(lead))
return PeekedCodePoint<mozilla::Utf8Unit>(lead.toUint8(), 1);
const mozilla::Utf8Unit* afterLead = ptr + 1;
mozilla::Maybe<char32_t> codePoint = mozilla::DecodeOneUtf8CodePoint(lead, &afterLead, end);
if (codePoint.isNothing())
return PeekedCodePoint<mozilla::Utf8Unit>::none();
auto len = mozilla::AssertedCast<uint8_t>(mozilla::PointerRangeSize(ptr, afterLead));
MOZ_ASSERT(len <= 4);
return PeekedCodePoint<mozilla::Utf8Unit>(codePoint.value(), len);
}
inline bool
IsSingleUnitLineTerminator(mozilla::Utf8Unit unit)
{
// BEWARE: The Unicode line/paragraph separators don't fit in a single
// UTF-8 code unit, so this test is exact for Utf8Unit but inexact
// for UTF-8 as a whole. Users must handle |unit| as start of a
// Unicode LineTerminator themselves!
return unit == mozilla::Utf8Unit('\n') || unit == mozilla::Utf8Unit('\r');
}
// This is the low-level interface to the JS source code buffer. It just gets
// raw Unicode code units -- 16-bit char16_t units of source text that are not
// (always) full code points, and 8-bit units of UTF-8 source text soon.
@ -1021,6 +1174,10 @@ class SourceUnits
return base_ + (offset - startOffset_);
}
const CharT* current() const {
return ptr;
}
const CharT* limit() const {
return limit_;
}
@ -1039,6 +1196,47 @@ class SourceUnits
return *ptr; // this will nullptr-crash if poisoned
}
/**
* Determine the next code point in source text. The code point is not
* normalized: '\r', '\n', '\u2028', and '\u2029' are returned literally.
* If there is no next code point because |atEnd()|, or if an encoding
* error is encountered, return a |PeekedCodePoint| that |isNone()|.
*
* This function does not report errors: code that attempts to get the next
* code point must report any error.
*
* If a next code point is found, it may be consumed by passing it to
* |consumeKnownCodePoint|.
*/
PeekedCodePoint<CharT> peekCodePoint() const {
return PeekCodePoint(ptr, limit_);
}
private:
#ifdef DEBUG
void assertNextCodePoint(const PeekedCodePoint<CharT>& peeked);
#endif
public:
/**
* Consume a peeked code point that |!isNone()|.
*
* This call DOES NOT UPDATE LINE-STATUS. You may need to call
* |updateLineInfoForEOL()| and |updateFlagsForEOL()| if this consumes a
* LineTerminator. Note that if this consumes '\r', you also must consume
* an optional '\n' (i.e. a full LineTerminatorSequence) before doing so.
*/
void consumeKnownCodePoint(const PeekedCodePoint<CharT>& peeked) {
MOZ_ASSERT(!peeked.isNone());
MOZ_ASSERT(peeked.lengthInUnits() <= remaining());
#ifdef DEBUG
assertNextCodePoint(peeked);
#endif
ptr += peeked.lengthInUnits();
}
/** Match |n| hexadecimal digits and store their value in |*out|. */
bool matchHexDigits(uint8_t n, char16_t* out) {
MOZ_ASSERT(ptr, "shouldn't peek into poisoned SourceUnits");
@ -1152,6 +1350,28 @@ class SourceUnits
#endif
}
/**
* Consume the rest of a single-line comment (but not the EOL/EOF that
* terminates it).
*
* If an encoding error is encountered -- possible only for UTF-8 because
* JavaScript's conception of UTF-16 encompasses any sequence of 16-bit
* code units -- valid code points prior to the encoding error are consumed
* and subsequent invalid code units are not consumed. For example, given
* these UTF-8 code units:
*
* 'B' 'A' 'D' ':' <bad code unit sequence>
* 0x42 0x41 0x44 0x3A 0xD0 0x00 ...
*
* the first four code units are consumed, but 0xD0 and 0x00 are not
* consumed because 0xD0 encodes a two-byte lead unit but 0x00 is not a
* valid trailing code unit.
*
* It is expected that the caller will report such an encoding error when
* it attempts to consume the next code point.
*/
void consumeRestOfSingleLineComment();
/**
* The maximum radius of code around the location of an error that should
* be included in a syntax error message -- this many code units to either
@ -1170,7 +1390,7 @@ class SourceUnits
* away from |offset|, such that all code points from that offset to
* |offset| are valid, non-LineTerminator code points.
*/
size_t findWindowStart(size_t offset);
size_t findWindowStart(size_t offset) const;
/**
* From absolute offset |offset|, find an absolute offset within source
@ -1178,7 +1398,7 @@ class SourceUnits
* that all code units from |offset| to that offset are valid,
* non-LineTerminator code points.
*/
size_t findWindowEnd(size_t offset);
size_t findWindowEnd(size_t offset) const;
private:
/** Base of buffer. */
@ -1265,6 +1485,26 @@ class TokenStreamCharsShared
CharBuffer& getCharBuffer() { return charBuffer; }
};
inline mozilla::Span<const char>
ToCharSpan(mozilla::Span<const mozilla::Utf8Unit> codeUnits)
{
static_assert(alignof(char) == alignof(mozilla::Utf8Unit),
"must have equal alignment to reinterpret_cast<>");
static_assert(sizeof(char) == sizeof(mozilla::Utf8Unit),
"must have equal size to reinterpret_cast<>");
// This cast is safe for two reasons.
//
// First, per C++11 [basic.lval]p10 it is permitted to access any object's
// memory through |char|.
//
// Second, Utf8Unit *contains* a |char|. Examining that memory as |char|
// is simply, per C++11 [basic.lval]p10, to access the memory according to
// the dynamic type of the object: essentially trivially safe.
return mozilla::MakeSpan(reinterpret_cast<const char*>(codeUnits.data()),
codeUnits.size());
}
template<typename CharT>
class TokenStreamCharsBase
: public TokenStreamCharsShared
@ -1286,7 +1526,7 @@ class TokenStreamCharsBase
}
static MOZ_ALWAYS_INLINE JSAtom*
atomizeSourceChars(JSContext* cx, const CharT* chars, size_t length);
atomizeSourceChars(JSContext* cx, mozilla::Span<const CharT> units);
using SourceUnits = frontend::SourceUnits<CharT>;
@ -1379,10 +1619,19 @@ TokenStreamCharsBase<CharT>::consumeKnownCodeUnit(int32_t unit)
template<>
/* static */ MOZ_ALWAYS_INLINE JSAtom*
TokenStreamCharsBase<char16_t>::atomizeSourceChars(JSContext* cx, const char16_t* chars,
size_t length)
TokenStreamCharsBase<char16_t>::atomizeSourceChars(JSContext* cx,
mozilla::Span<const char16_t> units)
{
return AtomizeChars(cx, chars, length);
return AtomizeChars(cx, units.data(), units.size());
}
template<>
/* static */ MOZ_ALWAYS_INLINE JSAtom*
TokenStreamCharsBase<mozilla::Utf8Unit>::atomizeSourceChars(JSContext* cx,
mozilla::Span<const mozilla::Utf8Unit> units)
{
auto chars = ToCharSpan(units);
return AtomizeUTF8Chars(cx, chars.data(), chars.size());
}
template<typename CharT>
@ -1403,13 +1652,6 @@ class SpecializedTokenStreamCharsBase<char16_t>
protected:
// These APIs are only usable by UTF-16-specific code.
/**
* Consume the rest of a single-line comment (but not the EOL/EOF that
* terminates it) -- infallibly because no 16-bit code unit sequence in a
* comment is an error.
*/
void infallibleConsumeRestOfSingleLineComment();
/**
* Given |lead| already consumed, consume and return the code point encoded
* starting from it. Infallible because lone surrogates in JS encode a
@ -1451,6 +1693,88 @@ class SpecializedTokenStreamCharsBase<mozilla::Utf8Unit>
protected:
// These APIs are only usable by UTF-8-specific code.
using typename CharsBase::SourceUnits;
/**
* A mutable iterator-wrapper around |SourceUnits| that translates
* operators to calls to |SourceUnits::getCodeUnit()| and similar.
*
* This class is expected to be used in concert with |SourceUnitsEnd|.
*/
class SourceUnitsIterator
{
SourceUnits& sourceUnits_;
#ifdef DEBUG
// In iterator copies created by the post-increment operator, a pointer
// at the next source text code unit when the post-increment operator
// was called, cleared when the iterator is dereferenced.
mutable mozilla::Maybe<const mozilla::Utf8Unit*> currentBeforePostIncrement_;
#endif
public:
explicit SourceUnitsIterator(SourceUnits& sourceUnits)
: sourceUnits_(sourceUnits)
{}
mozilla::Utf8Unit operator*() const {
// operator* is expected to get the *next* value from an iterator
// not pointing at the end of the underlying range. However, the
// sole use of this is in the context of an expression of the form
// |*iter++|, that performed the |sourceUnits_.getCodeUnit()| in
// the |operator++(int)| below -- so dereferencing acts on a
// |sourceUnits_| already advanced. Therefore the correct unit to
// return is the previous one.
MOZ_ASSERT(currentBeforePostIncrement_.value() + 1 == sourceUnits_.current());
#ifdef DEBUG
currentBeforePostIncrement_.reset();
#endif
return sourceUnits_.previousCodeUnit();
}
SourceUnitsIterator operator++(int) {
MOZ_ASSERT(currentBeforePostIncrement_.isNothing(),
"the only valid operation on a post-incremented "
"iterator is dereferencing a single time");
SourceUnitsIterator copy = *this;
#ifdef DEBUG
copy.currentBeforePostIncrement_.emplace(sourceUnits_.current());
#endif
sourceUnits_.getCodeUnit();
return copy;
}
void operator-=(size_t n) {
MOZ_ASSERT(currentBeforePostIncrement_.isNothing(),
"the only valid operation on a post-incremented "
"iterator is dereferencing a single time");
sourceUnits_.unskipCodeUnits(n);
}
mozilla::Utf8Unit operator[](ptrdiff_t index) {
MOZ_ASSERT(currentBeforePostIncrement_.isNothing(),
"the only valid operation on a post-incremented "
"iterator is dereferencing a single time");
MOZ_ASSERT(index == -1,
"must only be called to verify the value of the "
"previous code unit");
return sourceUnits_.previousCodeUnit();
}
size_t remaining() const {
MOZ_ASSERT(currentBeforePostIncrement_.isNothing(),
"the only valid operation on a post-incremented "
"iterator is dereferencing a single time");
return sourceUnits_.remaining();
}
};
/** A sentinel representing the end of |SourceUnits| data. */
class SourceUnitsEnd {};
friend inline size_t operator-(const SourceUnitsEnd& aEnd, const SourceUnitsIterator& aIter);
protected:
// These APIs are in both SpecializedTokenStreamCharsBase specializations
// and so are usable in subclasses no matter what CharT is.
@ -1458,6 +1782,13 @@ class SpecializedTokenStreamCharsBase<mozilla::Utf8Unit>
using CharsBase::CharsBase;
};
inline size_t
operator-(const SpecializedTokenStreamCharsBase<mozilla::Utf8Unit>::SourceUnitsEnd& aEnd,
const SpecializedTokenStreamCharsBase<mozilla::Utf8Unit>::SourceUnitsIterator& aIter)
{
return aIter.remaining();
}
/** A small class encapsulating computation of the start-offset of a Token. */
class TokenStart
{
@ -1710,7 +2041,6 @@ class TokenStreamChars<char16_t, AnyCharsAccess>
protected:
using GeneralCharsBase::anyCharsAccess;
using GeneralCharsBase::getCodeUnit;
using SpecializedCharsBase::infallibleConsumeRestOfSingleLineComment;
using SpecializedCharsBase::infallibleGetNonAsciiCodePointDontNormalize;
using TokenStreamCharsShared::isAsciiCodePoint;
using CharsBase::matchLineTerminator;
@ -1718,8 +2048,6 @@ class TokenStreamChars<char16_t, AnyCharsAccess>
using GeneralCharsBase::ungetCodeUnit;
using GeneralCharsBase::updateLineInfoForEOL;
using typename GeneralCharsBase::SourceUnits;
protected:
using GeneralCharsBase::GeneralCharsBase;
@ -1735,14 +2063,6 @@ class TokenStreamChars<char16_t, AnyCharsAccess>
return true;
}
/**
* Get the next code point, converting LineTerminatorSequences to '\n' and
* updating internal line-counter state if needed. Return true on success
* and store the code point in |*c|. Return false and leave |*c| undefined
* on failure.
*/
MOZ_MUST_USE bool getCodePoint(int32_t* cp);
/**
* Given a just-consumed non-ASCII code unit |lead| (which may also be a
* full code point, for UTF-16), consume a full code point or
@ -1755,47 +2075,6 @@ class TokenStreamChars<char16_t, AnyCharsAccess>
* This may change the current |sourceUnits| offset.
*/
MOZ_MUST_USE bool getNonAsciiCodePoint(int32_t lead, int32_t* codePoint);
/**
* Unget a full code point (ASCII or not) without altering line/column
* state. If line/column state must be updated, this must happen manually.
* This method ungets a single code point, not a LineTerminatorSequence
* that is multiple code points. (Generally you shouldn't be in a state
* where you've just consumed "\r\n" and want to unget that full sequence.)
*
* This function ordinarily should be used to unget code points that have
* been consumed *without* line/column state having been updated.
*/
void ungetCodePointIgnoreEOL(uint32_t codePoint);
/**
* Unget an originally non-ASCII, normalized code point, including undoing
* line/column updates that were performed for it. Don't use this if the
* code point was gotten *without* line/column state being updated!
*/
void ungetNonAsciiNormalizedCodePoint(int32_t codePoint) {
MOZ_ASSERT_IF(isAsciiCodePoint(codePoint),
codePoint == '\n');
MOZ_ASSERT(codePoint != unicode::LINE_SEPARATOR,
"should not be ungetting un-normalized code points");
MOZ_ASSERT(codePoint != unicode::PARA_SEPARATOR,
"should not be ungetting un-normalized code points");
ungetCodePointIgnoreEOL(codePoint);
if (codePoint == '\n')
anyCharsAccess().undoInternalUpdateLineInfoForEOL();
}
/**
* Consume code points til EOL/EOF following the start of a single-line
* comment, without consuming the EOL/EOF.
*/
MOZ_MUST_USE bool consumeRestOfSingleLineComment() {
// This operation is infallible for UTF-16 -- and this implementation
// approach lets the compiler boil away call-side fallibility handling.
infallibleConsumeRestOfSingleLineComment();
return true;
}
};
template<class AnyCharsAccess>
@ -1807,11 +2086,135 @@ class TokenStreamChars<mozilla::Utf8Unit, AnyCharsAccess>
using GeneralCharsBase = GeneralTokenStreamChars<mozilla::Utf8Unit, AnyCharsAccess>;
using Self = TokenStreamChars<mozilla::Utf8Unit, AnyCharsAccess>;
using typename SpecializedCharsBase::SourceUnitsEnd;
using typename SpecializedCharsBase::SourceUnitsIterator;
protected:
using GeneralCharsBase::anyCharsAccess;
using GeneralCharsBase::internalComputeLineOfContext;
using TokenStreamCharsShared::isAsciiCodePoint;
// Deliberately don't |using| |sourceUnits| because of bug 1472569. :-(
using GeneralCharsBase::updateLineInfoForEOL;
private:
static char toHexChar(uint8_t nibble) {
MOZ_ASSERT(nibble < 16);
return "0123456789ABCDEF"[nibble];
}
static void byteToString(uint8_t n, char* str) {
str[0] = '0';
str[1] = 'x';
str[2] = toHexChar(n >> 4);
str[3] = toHexChar(n & 0xF);
}
static void byteToTerminatedString(uint8_t n, char* str) {
byteToString(n, str);
str[4] = '\0';
}
/**
* Report a UTF-8 encoding-related error for a code point starting AT THE
* CURRENT OFFSET.
*
* |relevantUnits| indicates how many code units from the current offset
* are potentially relevant to the reported error, such that they may be
* included in the error message. For example, if at the current offset we
* have
*
* 0b1111'1111 ...
*
* a code unit never allowed in UTF-8, then |relevantUnits| might be 1
* because only that unit is relevant. Or if we have
*
* 0b1111'0111 0b1011'0101 0b0000'0000 ...
*
* where the first two code units are a valid prefix to a four-unit code
* point but the third unit *isn't* a valid trailing code unit, then
* |relevantUnits| might be 3.
*/
MOZ_COLD void internalEncodingError(uint8_t relevantUnits, unsigned errorNumber, ...);
// Don't use |internalEncodingError|! Use one of the elaborated functions
// that calls it, below -- all of which should be used to indicate an error
// in a code point starting AT THE CURRENT OFFSET as with
// |internalEncodingError|.
/** Report an error for an invalid lead code unit |lead|. */
MOZ_COLD void badLeadUnit(mozilla::Utf8Unit lead);
/**
* Report an error when there aren't enough code units remaining to
* constitute a full code point after |lead|: only |remaining| code units
* were available for a code point starting with |lead|, when at least
* |required| code units were required.
*/
MOZ_COLD void notEnoughUnits(mozilla::Utf8Unit lead, uint8_t remaining, uint8_t required);
/**
* Report an error for a bad trailing UTF-8 code unit, where the bad
* trailing unit was the last of |unitsObserved| units examined from the
* current offset.
*/
MOZ_COLD void badTrailingUnit(mozilla::Utf8Unit badUnit, uint8_t unitsObserved);
// Helper used for both |badCodePoint| and |notShortestForm| for code units
// that have all the requisite high bits set/unset in a manner that *could*
// encode a valid code point, but the remaining bits encoding its actual
// value do not define a permitted value.
MOZ_COLD void badStructurallyValidCodePoint(uint32_t codePoint, uint8_t codePointLength,
const char* reason);
/**
* Report an error for UTF-8 that encodes a UTF-16 surrogate or a number
* outside the Unicode range.
*/
MOZ_COLD void badCodePoint(uint32_t codePoint, uint8_t codePointLength) {
MOZ_ASSERT(unicode::IsSurrogate(codePoint) || codePoint > unicode::NonBMPMax);
badStructurallyValidCodePoint(codePoint, codePointLength,
unicode::IsSurrogate(codePoint)
? "it's a UTF-16 surrogate"
: "the maximum code point is U+10FFFF");
}
/**
* Report an error for UTF-8 that encodes a code point not in its shortest
* form.
*/
MOZ_COLD void notShortestForm(uint32_t codePoint, uint8_t codePointLength) {
MOZ_ASSERT(!unicode::IsSurrogate(codePoint));
MOZ_ASSERT(codePoint <= unicode::NonBMPMax);
badStructurallyValidCodePoint(codePoint, codePointLength,
"it wasn't encoded in shortest possible form");
}
protected:
using GeneralCharsBase::GeneralCharsBase;
/**
* Given the non-ASCII |lead| code unit just consumed, consume the rest of
* a non-ASCII code point. The code point is not normalized: on success
* |*codePoint| may be U+2028 LINE SEPARATOR or U+2029 PARAGRAPH SEPARATOR.
*
* Report an error if an invalid code point is encountered.
*/
MOZ_MUST_USE bool
getNonAsciiCodePointDontNormalize(mozilla::Utf8Unit lead, char32_t* codePoint);
/**
* Given a just-consumed non-ASCII code unit |lead|, consume a full code
* point or LineTerminatorSequence (normalizing it to '\n') and store it in
* |*codePoint|. Return true on success, otherwise return false and leave
* |*codePoint| undefined on failure.
*
* If a LineTerminatorSequence was consumed, also update line/column info.
*
* This function will change the current |sourceUnits| offset.
*/
MOZ_MUST_USE bool getNonAsciiCodePoint(int32_t lead, int32_t* codePoint);
};
// TokenStream is the lexical scanner for JavaScript source text.
@ -1892,11 +2295,9 @@ class MOZ_STACK_CLASS TokenStreamSpecific
using GeneralCharsBase::badToken;
// Deliberately don't |using| |charBuffer| because of bug 1472569. :-(
using CharsBase::consumeKnownCodeUnit;
using SpecializedChars::consumeRestOfSingleLineComment;
using TokenStreamCharsShared::copyCharBufferTo;
using TokenStreamCharsShared::drainCharBufferIntoAtom;
using CharsBase::fillCharBufferFromSourceNormalizingAsciiLineBreaks;
using SpecializedChars::getCodePoint;
using GeneralCharsBase::getCodeUnit;
using GeneralCharsBase::getFullAsciiCodePoint;
using SpecializedChars::getNonAsciiCodePoint;
@ -1914,9 +2315,7 @@ class MOZ_STACK_CLASS TokenStreamSpecific
using GeneralCharsBase::newSimpleToken;
using CharsBase::peekCodeUnit;
// Deliberately don't |using| |sourceUnits| because of bug 1472569. :-(
using SpecializedChars::ungetCodePointIgnoreEOL;
using GeneralCharsBase::ungetCodeUnit;
using SpecializedChars::ungetNonAsciiNormalizedCodePoint;
using GeneralCharsBase::updateLineInfoForEOL;
template<typename CharU> friend class TokenStreamPosition;
@ -1925,6 +2324,14 @@ class MOZ_STACK_CLASS TokenStreamSpecific
TokenStreamSpecific(JSContext* cx, const ReadOnlyCompileOptions& options,
const CharT* base, size_t length);
/**
* Get the next code point, converting LineTerminatorSequences to '\n' and
* updating internal line-counter state if needed. Return true on success
* and store the code point in |*cp|. Return false and leave |*cp|
* undefined on failure.
*/
MOZ_MUST_USE bool getCodePoint(int32_t* cp);
// If there is an invalid escape in a template, report it and return false,
// otherwise return true.
bool checkForInvalidTemplateEscapeError() {

View file

@ -4,7 +4,7 @@ version = "0.1.0"
authors = ["David Teller <D.O.Teller@gmail.com>"]
[dependencies]
binjs_meta = "^0.3.6"
binjs_meta = "^0.3.8"
clap = "^2"
env_logger = "^0.5.6"
itertools = "^0.7.6"

View file

@ -21,22 +21,6 @@ use clap::{ App, Arg };
use itertools::Itertools;
/// A string or string-like construction that can be appended newline.
trait NewLineIfNotEmpty {
/// Append newline if the string is not empty.
fn newline_if_not_empty(&self) -> String;
}
impl<T> NewLineIfNotEmpty for T where T: ToStr {
fn newline_if_not_empty(&self) -> String {
let str = self.to_str();
if str.len() == 0 {
"".to_string()
} else {
format!("{}\n", str)
}
}
}
/// Rules for generating the code for parsing a single field
/// of a node.
///

View file

@ -221,6 +221,7 @@ template struct JS_PUBLIC_API(MovableCellHasher<SavedFrame*>);
template struct JS_PUBLIC_API(MovableCellHasher<EnvironmentObject*>);
template struct JS_PUBLIC_API(MovableCellHasher<WasmInstanceObject*>);
template struct JS_PUBLIC_API(MovableCellHasher<JSScript*>);
template struct JS_PUBLIC_API(MovableCellHasher<LazyScript*>);
#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
#pragma GCC diagnostic pop

View file

@ -263,6 +263,7 @@ using mozilla::ArrayLength;
using mozilla::Maybe;
using mozilla::Swap;
using mozilla::TimeStamp;
using mozilla::TimeDuration;
using JS::AutoGCRooter;
@ -1415,7 +1416,7 @@ GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value, const AutoL
gcMaxNurseryBytes_ = value;
break;
case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
highFrequencyThreshold_ = mozilla::TimeDuration::FromMilliseconds(value);
highFrequencyThreshold_ = TimeDuration::FromMilliseconds(value);
break;
case JSGC_HIGH_FREQUENCY_LOW_LIMIT: {
uint64_t newLimit = (uint64_t)value * 1024 * 1024;
@ -1571,7 +1572,7 @@ GCSchedulingTunables::GCSchedulingTunables()
allocThresholdFactorAvoidInterrupt_(TuningDefaults::AllocThresholdFactorAvoidInterrupt),
zoneAllocDelayBytes_(TuningDefaults::ZoneAllocDelayBytes),
dynamicHeapGrowthEnabled_(TuningDefaults::DynamicHeapGrowthEnabled),
highFrequencyThreshold_(mozilla::TimeDuration::FromSeconds(TuningDefaults::HighFrequencyThreshold)),
highFrequencyThreshold_(TimeDuration::FromSeconds(TuningDefaults::HighFrequencyThreshold)),
highFrequencyLowLimitBytes_(TuningDefaults::HighFrequencyLowLimitBytes),
highFrequencyHighLimitBytes_(TuningDefaults::HighFrequencyHighLimitBytes),
highFrequencyHeapGrowthMax_(TuningDefaults::HighFrequencyHeapGrowthMax),
@ -1623,7 +1624,7 @@ GCSchedulingTunables::resetParameter(JSGCParamKey key, const AutoLockGC& lock)
break;
case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
highFrequencyThreshold_ =
mozilla::TimeDuration::FromSeconds(TuningDefaults::HighFrequencyThreshold);
TimeDuration::FromSeconds(TuningDefaults::HighFrequencyThreshold);
break;
case JSGC_HIGH_FREQUENCY_LOW_LIMIT:
setHighFrequencyLowLimit(TuningDefaults::HighFrequencyLowLimitBytes);
@ -2124,7 +2125,7 @@ GCRuntime::shouldCompact()
// if we are currently animating, unless the user is inactive or we're
// responding to memory pressure.
static const auto oneSecond = mozilla::TimeDuration::FromSeconds(1);
static const auto oneSecond = TimeDuration::FromSeconds(1);
if (invocationKind != GC_SHRINK || !isCompactingGCEnabled())
return false;
@ -2138,7 +2139,7 @@ GCRuntime::shouldCompact()
const auto &lastAnimationTime = rt->lastAnimationTime.ref();
return !isIncremental
|| lastAnimationTime.IsNull()
|| lastAnimationTime + oneSecond < mozilla::TimeStamp::Now();
|| lastAnimationTime + oneSecond < TimeStamp::Now();
}
bool
@ -3234,6 +3235,16 @@ ArenaLists::queueForegroundThingsForSweep()
gcScriptArenasToUpdate = arenaListsToSweep(AllocKind::SCRIPT);
}
TimeStamp SliceBudget::unlimitedDeadline;
void
SliceBudget::Init()
{
MOZ_ASSERT(!unlimitedDeadline);
uint64_t oneYearsInSeconds = 365 * 24 * 60 * 60;
unlimitedDeadline = ReallyNow() + TimeDuration::FromSeconds(100 * oneYearsInSeconds);
}
SliceBudget::SliceBudget()
: timeBudget(UnlimitedTimeBudget), workBudget(UnlimitedWorkBudget)
{
@ -3247,7 +3258,7 @@ SliceBudget::SliceBudget(TimeBudget time)
makeUnlimited();
} else {
// Note: TimeBudget(0) is equivalent to WorkBudget(CounterReset).
deadline = ReallyNow() + mozilla::TimeDuration::FromMilliseconds(time.budget);
deadline = ReallyNow() + TimeDuration::FromMilliseconds(time.budget);
counter = CounterReset;
}
}
@ -3258,7 +3269,7 @@ SliceBudget::SliceBudget(WorkBudget work)
if (work.budget < 0) {
makeUnlimited();
} else {
deadline = mozilla::TimeStamp();
deadline = TimeStamp();
counter = work.budget;
}
}
@ -4046,10 +4057,10 @@ GCRuntime::purgeRuntime()
}
bool
GCRuntime::shouldPreserveJITCode(Realm* realm, const mozilla::TimeStamp &currentTime,
GCRuntime::shouldPreserveJITCode(Realm* realm, const TimeStamp &currentTime,
JS::gcreason::Reason reason, bool canAllocateMoreCode)
{
static const auto oneSecond = mozilla::TimeDuration::FromSeconds(1);
static const auto oneSecond = TimeDuration::FromSeconds(1);
if (cleanUpEverything)
return false;

View file

@ -112,6 +112,8 @@ IterateChunks(JSContext* cx, void* data, IterateChunkCallback chunkCallback);
typedef void (*IterateScriptCallback)(JSRuntime* rt, void* data, JSScript* script,
const JS::AutoRequireNoGC& nogc);
typedef void (*IterateLazyScriptCallback)(JSRuntime* rt, void* data, LazyScript* lazyScript,
const JS::AutoRequireNoGC& nogc);
/*
* Invoke scriptCallback on every in-use script for the given realm or for all
@ -119,6 +121,9 @@ typedef void (*IterateScriptCallback)(JSRuntime* rt, void* data, JSScript* scrip
*/
extern void
IterateScripts(JSContext* cx, JS::Realm* realm, void* data, IterateScriptCallback scriptCallback);
extern void
IterateLazyScripts(JSContext* cx, JS::Realm* realm, void* data,
IterateLazyScriptCallback lazyScriptCallback);
JS::Realm*
NewRealm(JSContext* cx, JSPrincipals* principals, const JS::RealmOptions& options);

View file

@ -92,6 +92,7 @@ class MarkStack
Cell* ptr() const;
public:
TaggedPtr() {}
TaggedPtr(Tag tag, Cell* ptr);
Tag tag() const;
template <typename T> T* as() const;
@ -99,11 +100,14 @@ class MarkStack
JSObject* asValueArrayObject() const;
JSObject* asSavedValueArrayObject() const;
JSRope* asTempRope() const;
void assertValid() const;
};
struct ValueArray
{
ValueArray(JSObject* obj, HeapSlot* start, HeapSlot* end);
void assertValid() const;
HeapSlot* end;
HeapSlot* start;
@ -113,6 +117,7 @@ class MarkStack
struct SavedValueArray
{
SavedValueArray(JSObject* obj, size_t index, HeapSlot::Kind kind);
void assertValid() const;
uintptr_t kind;
uintptr_t index;
@ -124,19 +129,16 @@ class MarkStack
static const size_t DefaultCapacity = SIZE_MAX;
size_t capacity() { return end_ - stack_; }
size_t capacity() { return stack().length(); }
size_t position() const {
auto result = tos_ - stack_;
MOZ_ASSERT(result >= 0);
return size_t(result);
return topIndex_;
}
void setStack(TaggedPtr* stack, size_t tosIndex, size_t capacity);
MOZ_MUST_USE bool init(JSGCMode gcMode);
void setBaseCapacity(JSGCMode mode);
MOZ_MUST_USE bool setCapacityForMode(JSGCMode mode);
size_t maxCapacity() const { return maxCapacity_; }
void setMaxCapacity(size_t maxCapacity);
@ -152,7 +154,7 @@ class MarkStack
MOZ_MUST_USE bool pushTempRope(JSRope* ptr);
bool isEmpty() const {
return tos_ == stack_;
return topIndex_ == 0;
}
Tag peekTag() const;
@ -160,29 +162,42 @@ class MarkStack
ValueArray popValueArray();
SavedValueArray popSavedValueArray();
void reset();
void clear() {
topIndex_ = 0;
}
void setGCMode(JSGCMode gcMode);
void poisonUnused();
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:
using StackVector = Vector<TaggedPtr, 0, SystemAllocPolicy>;
const StackVector& stack() const { return stack_.ref(); }
StackVector& stack() { return stack_.ref(); }
MOZ_MUST_USE bool ensureSpace(size_t count);
/* Grow the stack, ensuring there is space for at least count elements. */
MOZ_MUST_USE bool enlarge(size_t count);
MOZ_MUST_USE bool resize(size_t newCapacity);
TaggedPtr* topPtr();
const TaggedPtr& peekPtr() const;
MOZ_MUST_USE bool pushTaggedPtr(Tag tag, Cell* ptr);
MainThreadData<TaggedPtr*> stack_;
MainThreadData<TaggedPtr*> tos_;
MainThreadData<TaggedPtr*> end_;
// Index of the top of the stack.
MainThreadData<size_t> topIndex_;
// The capacity we start with and reset() to.
MainThreadData<size_t> baseCapacity_;
// The maximum stack capacity to grow to.
MainThreadData<size_t> maxCapacity_;
// Vector containing allocated stack memory. Unused beyond topIndex_.
MainThreadData<StackVector> stack_;
#ifdef DEBUG
mutable size_t iteratorCount_;
#endif
@ -192,11 +207,11 @@ class MarkStack
class MarkStackIter
{
const MarkStack& stack_;
MarkStack::TaggedPtr* pos_;
MarkStack& stack_;
size_t pos_;
public:
explicit MarkStackIter(const MarkStack& stack);
explicit MarkStackIter(MarkStack& stack);
~MarkStackIter();
bool done() const;
@ -208,7 +223,7 @@ class MarkStackIter
void nextArray();
// Mutate the current ValueArray to a SavedValueArray.
void saveValueArray(NativeObject* obj, uintptr_t index, HeapSlot::Kind kind);
void saveValueArray(const MarkStack::SavedValueArray& savedArray);
private:
size_t position() const;
@ -287,7 +302,7 @@ class GCMarker : public JSTracer
bool shouldCheckCompartments() { return strictCompartmentChecking; }
JS::Zone* stackContainsCrossZonePointerTo(const gc::Cell* cell) const;
JS::Zone* stackContainsCrossZonePointerTo(const gc::Cell* cell);
#endif
@ -342,7 +357,11 @@ class GCMarker : public JSTracer
MOZ_MUST_USE bool restoreValueArray(const gc::MarkStack::SavedValueArray& array,
HeapSlot** vpp, HeapSlot** endp);
gc::MarkStack::ValueArray restoreValueArray(const gc::MarkStack::SavedValueArray& savedArray);
void saveValueRanges();
gc::MarkStack::SavedValueArray saveValueRange(const gc::MarkStack::ValueArray& array);
inline void processMarkStackTop(SliceBudget& budget);
/* The mark stack. Pointers in this stack are "gray" in the GC sense. */

View file

@ -460,6 +460,8 @@ template void js::TraceManuallyBarrieredCrossCompartmentEdge<JSObject*>(JSTracer
JSObject**, const char*);
template void js::TraceManuallyBarrieredCrossCompartmentEdge<JSScript*>(JSTracer*, JSObject*,
JSScript**, const char*);
template void js::TraceManuallyBarrieredCrossCompartmentEdge<LazyScript*>(JSTracer*, JSObject*,
LazyScript**, const char*);
void
js::TraceCrossCompartmentEdge(JSTracer* trc, JSObject* src, WriteBarrieredBase<Value>* dst,
@ -1795,6 +1797,7 @@ GCMarker::processMarkStackTop(SliceBudget& budget)
* pointers are replaced with slot indexes, and slot array end pointers are
* replaced with the kind of index (properties vs. elements).
*/
void
GCMarker::saveValueRanges()
{
@ -1802,37 +1805,9 @@ GCMarker::saveValueRanges()
while (!iter.done()) {
auto tag = iter.peekTag();
if (tag == MarkStack::ValueArrayTag) {
auto array = iter.peekValueArray();
NativeObject* obj = &array.ptr.asValueArrayObject()->as<NativeObject>();
MOZ_ASSERT(obj->isNative());
uintptr_t index;
HeapSlot::Kind kind;
HeapSlot* vp = obj->getDenseElementsAllowCopyOnWrite();
if (array.end == vp + obj->getDenseInitializedLength()) {
MOZ_ASSERT(array.start >= vp);
// Add the number of shifted elements here (and subtract in
// restoreValueArray) to ensure shift() calls on the array
// are handled correctly.
index = obj->unshiftedIndex(array.start - vp);
kind = HeapSlot::Element;
} else {
HeapSlot* vp = obj->fixedSlots();
unsigned nfixed = obj->numFixedSlots();
if (array.start == array.end) {
index = obj->slotSpan();
} else if (array.start >= vp && array.start < vp + nfixed) {
MOZ_ASSERT(array.end == vp + Min(nfixed, obj->slotSpan()));
index = array.start - vp;
} else {
MOZ_ASSERT(array.start >= obj->slots_ &&
array.end == obj->slots_ + obj->slotSpan() - nfixed);
index = (array.start - obj->slots_) + nfixed;
}
kind = HeapSlot::Slot;
}
iter.saveValueArray(obj, index, kind);
const auto& array = iter.peekValueArray();
auto savedArray = saveValueRange(array);
iter.saveValueArray(savedArray);
iter.nextArray();
} else if (tag == MarkStack::SavedValueArrayTag) {
iter.nextArray();
@ -1840,54 +1815,103 @@ GCMarker::saveValueRanges()
iter.nextPtr();
}
}
// This is also a convenient point to poison unused stack memory.
stack.poisonUnused();
}
bool
GCMarker::restoreValueArray(const MarkStack::SavedValueArray& array,
GCMarker::restoreValueArray(const MarkStack::SavedValueArray& savedArray,
HeapSlot** vpp, HeapSlot** endp)
{
JSObject* objArg = array.ptr.asSavedValueArrayObject();
JSObject* objArg = savedArray.ptr.asSavedValueArrayObject();
if (!objArg->isNative())
return false;
NativeObject* obj = &objArg->as<NativeObject>();
uintptr_t start = array.index;
if (array.kind == HeapSlot::Element) {
auto array = restoreValueArray(savedArray);
*vpp = array.start;
*endp = array.end;
return true;
}
MarkStack::SavedValueArray
GCMarker::saveValueRange(const MarkStack::ValueArray& array)
{
NativeObject* obj = &array.ptr.asValueArrayObject()->as<NativeObject>();
MOZ_ASSERT(obj->isNative());
uintptr_t index;
HeapSlot::Kind kind;
HeapSlot* vp = obj->getDenseElementsAllowCopyOnWrite();
if (array.end == vp + obj->getDenseInitializedLength()) {
MOZ_ASSERT(array.start >= vp);
// Add the number of shifted elements here (and subtract in
// restoreValueArray) to ensure shift() calls on the array
// are handled correctly.
index = obj->unshiftedIndex(array.start - vp);
kind = HeapSlot::Element;
} else {
HeapSlot* vp = obj->fixedSlots();
unsigned nfixed = obj->numFixedSlots();
if (array.start == array.end) {
index = obj->slotSpan();
} else if (array.start >= vp && array.start < vp + nfixed) {
MOZ_ASSERT(array.end == vp + Min(nfixed, obj->slotSpan()));
index = array.start - vp;
} else {
MOZ_ASSERT(array.start >= obj->slots_ &&
array.end == obj->slots_ + obj->slotSpan() - nfixed);
index = (array.start - obj->slots_) + nfixed;
}
kind = HeapSlot::Slot;
}
return MarkStack::SavedValueArray(obj, index, kind);
}
MarkStack::ValueArray
GCMarker::restoreValueArray(const MarkStack::SavedValueArray& savedArray)
{
NativeObject* obj = &savedArray.ptr.asSavedValueArrayObject()->as<NativeObject>();
HeapSlot* start = nullptr;
HeapSlot* end = nullptr;
uintptr_t index = savedArray.index;
if (savedArray.kind == HeapSlot::Element) {
uint32_t initlen = obj->getDenseInitializedLength();
// Account for shifted elements.
uint32_t numShifted = obj->getElementsHeader()->numShiftedElements();
start = (numShifted < start) ? start - numShifted : 0;
index = (numShifted < index) ? index - numShifted : 0;
HeapSlot* vp = obj->getDenseElementsAllowCopyOnWrite();
if (start < initlen) {
*vpp = vp + start;
*endp = vp + initlen;
if (index < initlen) {
start = vp + index;
end = vp + initlen;
} else {
/* The object shrunk, in which case no scanning is needed. */
*vpp = *endp = vp;
start = end = vp;
}
} else {
MOZ_ASSERT(array.kind == HeapSlot::Slot);
MOZ_ASSERT(savedArray.kind == HeapSlot::Slot);
HeapSlot* vp = obj->fixedSlots();
unsigned nfixed = obj->numFixedSlots();
unsigned nslots = obj->slotSpan();
if (start < nslots) {
if (start < nfixed) {
*vpp = vp + start;
*endp = vp + Min(nfixed, nslots);
if (index < nslots) {
if (index < nfixed) {
start = vp + index;
end = vp + Min(nfixed, nslots);
} else {
*vpp = obj->slots_ + start - nfixed;
*endp = obj->slots_ + nslots - nfixed;
start = obj->slots_ + index - nfixed;
end = obj->slots_ + nslots - nfixed;
}
} else {
/* The object shrunk, in which case no scanning is needed. */
*vpp = *endp = vp;
start = end = vp;
}
}
MOZ_ASSERT(*vpp <= *endp);
return true;
return MarkStack::ValueArray(obj, start, end);
}
@ -1919,27 +1943,11 @@ TagIsArrayTag(MarkStack::Tag tag)
return tag == MarkStack::ValueArrayTag || tag == MarkStack::SavedValueArrayTag;
}
static inline void
CheckValueArray(const MarkStack::ValueArray& array)
{
MOZ_ASSERT(array.ptr.tag() == MarkStack::ValueArrayTag);
MOZ_ASSERT(uintptr_t(array.start) <= uintptr_t(array.end));
MOZ_ASSERT((uintptr_t(array.end) - uintptr_t(array.start)) % sizeof(Value) == 0);
}
static inline void
CheckSavedValueArray(const MarkStack::SavedValueArray& array)
{
MOZ_ASSERT(array.ptr.tag() == MarkStack::SavedValueArrayTag);
MOZ_ASSERT(array.kind == HeapSlot::Slot || array.kind == HeapSlot::Element);
}
inline
MarkStack::TaggedPtr::TaggedPtr(Tag tag, Cell* ptr)
: bits(tag | uintptr_t(ptr))
{
MOZ_ASSERT(tag <= LastTag);
MOZ_ASSERT((uintptr_t(ptr) & CellAlignMask) == 0);
assertValid();
}
inline MarkStack::Tag
@ -1956,6 +1964,13 @@ MarkStack::TaggedPtr::ptr() const
return reinterpret_cast<Cell*>(bits & ~TagMask);
}
inline void
MarkStack::TaggedPtr::assertValid() const
{
mozilla::Unused << tag();
MOZ_ASSERT(IsCellPointerValid(ptr()));
}
template <typename T>
inline T*
MarkStack::TaggedPtr::as() const
@ -1995,18 +2010,38 @@ MarkStack::TaggedPtr::asTempRope() const
inline
MarkStack::ValueArray::ValueArray(JSObject* obj, HeapSlot* startArg, HeapSlot* endArg)
: end(endArg), start(startArg), ptr(ValueArrayTag, obj)
{}
{
assertValid();
}
inline void
MarkStack::ValueArray::assertValid() const
{
ptr.assertValid();
MOZ_ASSERT(ptr.tag() == MarkStack::ValueArrayTag);
MOZ_ASSERT(start);
MOZ_ASSERT(end);
MOZ_ASSERT(uintptr_t(start) <= uintptr_t(end));
MOZ_ASSERT((uintptr_t(end) - uintptr_t(start)) % sizeof(Value) == 0);
}
inline
MarkStack::SavedValueArray::SavedValueArray(JSObject* obj, size_t indexArg, HeapSlot::Kind kindArg)
: kind(kindArg), index(indexArg), ptr(SavedValueArrayTag, obj)
{}
{
assertValid();
}
inline void
MarkStack::SavedValueArray::assertValid() const
{
ptr.assertValid();
MOZ_ASSERT(ptr.tag() == MarkStack::SavedValueArrayTag);
MOZ_ASSERT(kind == HeapSlot::Slot || kind == HeapSlot::Element);
}
MarkStack::MarkStack(size_t maxCapacity)
: stack_(nullptr)
, tos_(nullptr)
, end_(nullptr)
, baseCapacity_(0)
: topIndex_(0)
, maxCapacity_(maxCapacity)
#ifdef DEBUG
, iteratorCount_(0)
@ -2015,50 +2050,46 @@ MarkStack::MarkStack(size_t maxCapacity)
MarkStack::~MarkStack()
{
MOZ_ASSERT(isEmpty());
MOZ_ASSERT(iteratorCount_ == 0);
js_free(stack_);
}
bool
MarkStack::init(JSGCMode gcMode)
{
setBaseCapacity(gcMode);
MOZ_ASSERT(isEmpty());
MOZ_ASSERT(!stack_);
auto newStack = js_pod_malloc<TaggedPtr>(baseCapacity_);
if (!newStack)
return false;
setStack(newStack, 0, baseCapacity_);
return true;
}
inline void
MarkStack::setStack(TaggedPtr* stack, size_t tosIndex, size_t capacity)
{
MOZ_ASSERT(iteratorCount_ == 0);
stack_ = stack;
tos_ = stack + tosIndex;
end_ = stack + capacity;
return setCapacityForMode(gcMode);
}
void
MarkStack::setBaseCapacity(JSGCMode mode)
MarkStack::setGCMode(JSGCMode gcMode)
{
// Ignore failure to resize the stack and keep using the existing stack.
mozilla::Unused << setCapacityForMode(gcMode);
}
bool
MarkStack::setCapacityForMode(JSGCMode mode)
{
size_t capacity;
switch (mode) {
case JSGC_MODE_GLOBAL:
case JSGC_MODE_ZONE:
baseCapacity_ = NON_INCREMENTAL_MARK_STACK_BASE_CAPACITY;
capacity = NON_INCREMENTAL_MARK_STACK_BASE_CAPACITY;
break;
case JSGC_MODE_INCREMENTAL:
baseCapacity_ = INCREMENTAL_MARK_STACK_BASE_CAPACITY;
capacity = INCREMENTAL_MARK_STACK_BASE_CAPACITY;
break;
default:
MOZ_CRASH("bad gc mode");
}
if (baseCapacity_ > maxCapacity_)
baseCapacity_ = maxCapacity_;
if (capacity > maxCapacity_)
capacity = maxCapacity_;
return resize(capacity);
}
void
@ -2066,11 +2097,19 @@ MarkStack::setMaxCapacity(size_t maxCapacity)
{
MOZ_ASSERT(maxCapacity != 0);
MOZ_ASSERT(isEmpty());
maxCapacity_ = maxCapacity;
if (baseCapacity_ > maxCapacity_)
baseCapacity_ = maxCapacity_;
reset();
maxCapacity_ = maxCapacity;
if (capacity() > maxCapacity_) {
// If the realloc fails, just keep using the existing stack; it's
// not ideal but better than failing.
mozilla::Unused << resize(maxCapacity_);
}
}
inline MarkStack::TaggedPtr*
MarkStack::topPtr()
{
return &stack()[topIndex_];
}
inline bool
@ -2079,8 +2118,8 @@ MarkStack::pushTaggedPtr(Tag tag, Cell* ptr)
if (!ensureSpace(1))
return false;
MOZ_ASSERT(tos_ < end_);
*tos_++ = TaggedPtr(tag, ptr);
*topPtr() = TaggedPtr(tag, ptr);
topIndex_++;
return true;
}
@ -2106,14 +2145,14 @@ MarkStack::push(JSObject* obj, HeapSlot* start, HeapSlot* end)
inline bool
MarkStack::push(const ValueArray& array)
{
CheckValueArray(array);
array.assertValid();
if (!ensureSpace(ValueArrayWords))
return false;
*reinterpret_cast<ValueArray*>(tos_.ref()) = array;
tos_ += ValueArrayWords;
MOZ_ASSERT(tos_ <= end_);
*reinterpret_cast<ValueArray*>(topPtr()) = array;
topIndex_ += ValueArrayWords;
MOZ_ASSERT(position() <= capacity());
MOZ_ASSERT(peekTag() == ValueArrayTag);
return true;
}
@ -2121,14 +2160,14 @@ MarkStack::push(const ValueArray& array)
inline bool
MarkStack::push(const SavedValueArray& array)
{
CheckSavedValueArray(array);
array.assertValid();
if (!ensureSpace(ValueArrayWords))
return false;
*reinterpret_cast<SavedValueArray*>(tos_.ref()) = array;
tos_ += ValueArrayWords;
MOZ_ASSERT(tos_ <= end_);
*reinterpret_cast<SavedValueArray*>(topPtr()) = array;
topIndex_ += ValueArrayWords;
MOZ_ASSERT(position() <= capacity());
MOZ_ASSERT(peekTag() == SavedValueArrayTag);
return true;
}
@ -2136,8 +2175,7 @@ MarkStack::push(const SavedValueArray& array)
inline const MarkStack::TaggedPtr&
MarkStack::peekPtr() const
{
MOZ_ASSERT(!isEmpty());
return tos_[-1];
return stack()[topIndex_ - 1];
}
inline MarkStack::Tag
@ -2151,8 +2189,9 @@ MarkStack::popPtr()
{
MOZ_ASSERT(!isEmpty());
MOZ_ASSERT(!TagIsArrayTag(peekTag()));
tos_--;
return *tos_;
peekPtr().assertValid();
topIndex_--;
return *topPtr();
}
inline MarkStack::ValueArray
@ -2161,9 +2200,9 @@ MarkStack::popValueArray()
MOZ_ASSERT(peekTag() == ValueArrayTag);
MOZ_ASSERT(position() >= ValueArrayWords);
tos_ -= ValueArrayWords;
const auto& array = *reinterpret_cast<ValueArray*>(tos_.ref());
CheckValueArray(array);
topIndex_ -= ValueArrayWords;
const auto& array = *reinterpret_cast<ValueArray*>(topPtr());
array.assertValid();
return array;
}
@ -2173,36 +2212,16 @@ MarkStack::popSavedValueArray()
MOZ_ASSERT(peekTag() == SavedValueArrayTag);
MOZ_ASSERT(position() >= ValueArrayWords);
tos_ -= ValueArrayWords;
const auto& array = *reinterpret_cast<SavedValueArray*>(tos_.ref());
CheckSavedValueArray(array);
topIndex_ -= ValueArrayWords;
const auto& array = *reinterpret_cast<SavedValueArray*>(topPtr());
array.assertValid();
return array;
}
void
MarkStack::reset()
{
if (capacity() == baseCapacity_) {
// No size change; keep the current stack.
setStack(stack_, 0, baseCapacity_);
return;
}
MOZ_ASSERT(baseCapacity_ != 0);
auto newStack = js_pod_realloc<TaggedPtr>(stack_, capacity(), baseCapacity_);
if (!newStack) {
// If the realloc fails, just keep using the existing stack; it's
// not ideal but better than failing.
newStack = stack_;
baseCapacity_ = capacity();
}
setStack(newStack, 0, baseCapacity_);
}
inline bool
MarkStack::ensureSpace(size_t count)
{
if ((tos_ + count) <= end_)
if ((topIndex_ + count) <= capacity())
return !js::oom::ShouldFailWithOOM();
return enlarge(count);
@ -2215,34 +2234,41 @@ MarkStack::enlarge(size_t count)
if (newCapacity < capacity() + count)
return false;
size_t tosIndex = position();
return resize(newCapacity);
}
bool
MarkStack::resize(size_t newCapacity)
{
MOZ_ASSERT(newCapacity != 0);
auto newStack = js_pod_realloc<TaggedPtr>(stack_, capacity(), newCapacity);
if (!newStack)
if (!stack().resize(newCapacity))
return false;
setStack(newStack, tosIndex, newCapacity);
poisonUnused();
return true;
}
void
MarkStack::setGCMode(JSGCMode gcMode)
inline void
MarkStack::poisonUnused()
{
// The mark stack won't be resized until the next call to reset(), but
// that will happen at the end of the next GC.
setBaseCapacity(gcMode);
static_assert((JS_FRESH_MARK_STACK_PATTERN & TagMask) > LastTag,
"The mark stack poison pattern must not look like a valid tagged pointer");
JS_POISON(&stack()[topIndex_],
JS_FRESH_MARK_STACK_PATTERN,
stack().capacity() - topIndex_,
MemCheckKind::MakeUndefined);
}
size_t
MarkStack::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
return mallocSizeOf(stack_);
return stack().sizeOfExcludingThis(mallocSizeOf);
}
MarkStackIter::MarkStackIter(const MarkStack& stack)
MarkStackIter::MarkStackIter(MarkStack& stack)
: stack_(stack),
pos_(stack.tos_)
pos_(stack.position())
{
#ifdef DEBUG
stack.iteratorCount_++;
@ -2260,7 +2286,7 @@ MarkStackIter::~MarkStackIter()
inline size_t
MarkStackIter::position() const
{
return pos_ - stack_.stack_;
return pos_;
}
inline bool
@ -2273,7 +2299,7 @@ inline MarkStack::TaggedPtr
MarkStackIter::peekPtr() const
{
MOZ_ASSERT(!done());
return pos_[-1];
return stack_.stack()[pos_ - 1];
}
inline MarkStack::Tag
@ -2288,8 +2314,9 @@ MarkStackIter::peekValueArray() const
MOZ_ASSERT(peekTag() == MarkStack::ValueArrayTag);
MOZ_ASSERT(position() >= ValueArrayWords);
const auto& array = *reinterpret_cast<MarkStack::ValueArray*>(pos_ - ValueArrayWords);
CheckValueArray(array);
const MarkStack::TaggedPtr* ptr = &stack_.stack()[pos_ - ValueArrayWords];
const auto& array = *reinterpret_cast<const MarkStack::ValueArray*>(ptr);
array.assertValid();
return array;
}
@ -2319,15 +2346,15 @@ MarkStackIter::nextArray()
}
void
MarkStackIter::saveValueArray(NativeObject* obj, uintptr_t index, HeapSlot::Kind kind)
MarkStackIter::saveValueArray(const MarkStack::SavedValueArray& savedArray)
{
MOZ_ASSERT(peekTag() == MarkStack::ValueArrayTag);
MOZ_ASSERT(peekPtr().asValueArrayObject() == obj);
MOZ_ASSERT(peekPtr().asValueArrayObject() == savedArray.ptr.asSavedValueArrayObject());
MOZ_ASSERT(position() >= ValueArrayWords);
auto& array = *reinterpret_cast<MarkStack::SavedValueArray*>(pos_ - ValueArrayWords);
array = MarkStack::SavedValueArray(obj, index, kind);
CheckSavedValueArray(array);
MarkStack::TaggedPtr* ptr = &stack_.stack()[pos_ - ValueArrayWords];
auto dest = reinterpret_cast<MarkStack::SavedValueArray*>(ptr);
*dest = savedArray;
MOZ_ASSERT(peekTag() == MarkStack::SavedValueArrayTag);
}
@ -2387,7 +2414,7 @@ GCMarker::stop()
#endif
/* Free non-ballast stack memory. */
stack.reset();
stack.clear();
AutoEnterOOMUnsafeRegion oomUnsafe;
for (GCZonesIter zone(runtime()); !zone.done(); zone.next()) {
if (!zone->gcWeakKeys().clear())
@ -2400,7 +2427,7 @@ GCMarker::reset()
{
color = MarkColor::Black;
stack.reset();
stack.clear();
MOZ_ASSERT(isMarkStackEmpty());
while (unmarkedArenaStackTop) {
@ -2433,6 +2460,10 @@ void
GCMarker::pushValueArray(JSObject* obj, HeapSlot* start, HeapSlot* end)
{
checkZone(obj);
if (start == end)
return;
if (!stack.push(obj, start, end))
delayMarkingChildren(obj);
}
@ -2581,7 +2612,7 @@ GCMarker::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
#ifdef DEBUG
Zone*
GCMarker::stackContainsCrossZonePointerTo(const Cell* target) const
GCMarker::stackContainsCrossZonePointerTo(const Cell* target)
{
MOZ_ASSERT(!JS::RuntimeHeapIsCollecting());

View file

@ -84,8 +84,69 @@ js::IterateChunks(JSContext* cx, void* data, IterateChunkCallback chunkCallback)
chunkCallback(cx->runtime(), data, chunk);
}
void
js::IterateScripts(JSContext* cx, Realm* realm, void* data, IterateScriptCallback scriptCallback)
static void
TraverseInnerLazyScriptsForLazyScript(JSContext* cx, void* data, LazyScript* enclosingLazyScript,
IterateLazyScriptCallback lazyScriptCallback,
const JS::AutoRequireNoGC& nogc)
{
GCPtrFunction* innerFunctions = enclosingLazyScript->innerFunctions();
for (size_t i = 0, len = enclosingLazyScript->numInnerFunctions(); i < len; i++) {
JSFunction* fun = innerFunctions[i];
// LazyScript::CreateForXDR temporarily initializes innerFunctions with
// its own function, but it should be overwritten with correct
// inner functions before getting inserted into parent's innerFunctions.
MOZ_ASSERT(fun != enclosingLazyScript->functionNonDelazifying());
if (!fun->isInterpretedLazy())
return;
LazyScript* lazyScript = fun->lazyScript();
MOZ_ASSERT(lazyScript->hasEnclosingScope() || lazyScript->hasEnclosingLazyScript());
MOZ_ASSERT_IF(lazyScript->hasEnclosingLazyScript(),
lazyScript->enclosingLazyScript() == enclosingLazyScript);
lazyScriptCallback(cx->runtime(), data, lazyScript, nogc);
TraverseInnerLazyScriptsForLazyScript(cx, data, lazyScript, lazyScriptCallback, nogc);
}
}
static inline void
DoScriptCallback(JSContext* cx, void* data, LazyScript* lazyScript,
IterateLazyScriptCallback lazyScriptCallback,
const JS::AutoRequireNoGC& nogc)
{
// We call the callback only for the LazyScript that:
// (a) its enclosing script has ever been fully compiled and
// itself is delazifyable (handled in this function)
// (b) it is contained in the (a)'s inner function tree
// (handled in TraverseInnerLazyScriptsForLazyScript)
if (!lazyScript->enclosingScriptHasEverBeenCompiled())
return;
lazyScriptCallback(cx->runtime(), data, lazyScript, nogc);
TraverseInnerLazyScriptsForLazyScript(cx, data, lazyScript, lazyScriptCallback, nogc);
}
static inline void
DoScriptCallback(JSContext* cx, void* data, JSScript* script,
IterateScriptCallback scriptCallback,
const JS::AutoRequireNoGC& nogc)
{
// We check for presence of script->isUncompleted() because it is
// possible that the script was created and thus exposed to GC, but *not*
// fully initialized from fullyInit{FromEmitter,Trivial} due to errors.
if (script->isUncompleted())
return;
scriptCallback(cx->runtime(), data, script, nogc);
}
template <typename T, typename Callback>
static void
IterateScriptsImpl(JSContext* cx, Realm* realm, void* data, Callback scriptCallback)
{
MOZ_ASSERT(!cx->suppressGC);
AutoEmptyNursery empty(cx);
@ -94,18 +155,31 @@ js::IterateScripts(JSContext* cx, Realm* realm, void* data, IterateScriptCallbac
if (realm) {
Zone* zone = realm->zone();
for (auto script = zone->cellIter<JSScript>(empty); !script.done(); script.next()) {
for (auto script = zone->cellIter<T>(empty); !script.done(); script.next()) {
if (script->realm() == realm)
scriptCallback(cx->runtime(), data, script, nogc);
DoScriptCallback(cx, data, script, scriptCallback, nogc);
}
} else {
for (ZonesIter zone(cx->runtime(), SkipAtoms); !zone.done(); zone.next()) {
for (auto script = zone->cellIter<JSScript>(empty); !script.done(); script.next())
scriptCallback(cx->runtime(), data, script, nogc);
for (auto script = zone->cellIter<T>(empty); !script.done(); script.next())
DoScriptCallback(cx, data, script, scriptCallback, nogc);
}
}
}
void
js::IterateScripts(JSContext* cx, Realm* realm, void* data, IterateScriptCallback scriptCallback)
{
IterateScriptsImpl<JSScript>(cx, realm, data, scriptCallback);
}
void
js::IterateLazyScripts(JSContext* cx, Realm* realm, void* data,
IterateLazyScriptCallback scriptCallback)
{
IterateScriptsImpl<LazyScript>(cx, realm, data, scriptCallback);
}
static void
IterateGrayObjects(Zone* zone, GCThingCallback cellCallback, void* data)
{

View file

@ -445,6 +445,13 @@ JS_GetTraceThingInfo(char* buf, size_t bufsize, JSTracer* trc, void* thing,
break;
}
case JS::TraceKind::LazyScript:
{
LazyScript* script = static_cast<LazyScript*>(thing);
snprintf(buf, bufsize, " %s:%u", script->filename(), script->lineno());
break;
}
case JS::TraceKind::String:
{
*buf++ = ' ';

View file

@ -298,6 +298,9 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, ZoneAllocPolicy>,
JSObject* getDelegate(JSScript* script) const {
return nullptr;
}
JSObject* getDelegate(LazyScript* script) const {
return nullptr;
}
private:
void exposeGCThingToActiveJS(const JS::Value& v) const { JS::ExposeValueToActiveJS(v); }
@ -315,6 +318,9 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, ZoneAllocPolicy>,
bool keyNeedsMark(JSScript* script) const {
return false;
}
bool keyNeedsMark(LazyScript* script) const {
return false;
}
bool findZoneEdges() override {
// This is overridden by ObjectValueMap.

View file

@ -253,9 +253,6 @@ def main(argv):
# This part is equivalent to:
# skip-if = coverage
if os.getenv('GCOV_PREFIX') is not None:
# GCOV errors.
options.exclude += [os.path.join('asm.js', 'testSIMD.js')] # Bug 1347245
# JSVM errors.
options.exclude += [os.path.join('basic', 'functionnames.js')] # Bug 1369783
options.exclude += [os.path.join('debug', 'Debugger-findScripts-23.js')]

View file

@ -1,109 +0,0 @@
if (!this.hasOwnProperty("SIMD"))
quit();
function booleanBinaryX4(op, v, w) {
var arr = [];
var [varr, warr] = [simdToArray(v), simdToArray(w)];
for (var i = 0; i < 4; i++)
arr[i] = op(varr[i], warr[i]);
return arr;
}
function binaryX(op, v, w) {
var arr = [];
var [varr, warr] = [simdToArray(v), simdToArray(w)];
[varr, warr] = [varr.map(Math.fround), warr.map(Math.fround)];
for (var i = 0; i < varr.length; i++)
arr[i] = op(varr[i], warr[i]);
return arr.map(Math.fround);
}
function unaryX4(op, v, coerceFunc) {
var arr = [];
var varr = simdToArray(v).map(coerceFunc);
for (var i = 0; i < 4; i++)
arr[i] = op(varr[i]);
return arr.map(coerceFunc);
}
function assertNear(a, b) {
assertEq((a != a && b != b) || Math.abs(a - b) < 0.001, true);
}
function GetType(v) {
var pt = Object.getPrototypeOf(v);
switch (pt) {
case SIMD.Int8x16.prototype: return SIMD.Int8x16;
case SIMD.Int16x8.prototype: return SIMD.Int16x8;
case SIMD.Int32x4.prototype: return SIMD.Int32x4;
case SIMD.Uint8x16.prototype: return SIMD.Uint8x16;
case SIMD.Uint16x8.prototype: return SIMD.Uint16x8;
case SIMD.Uint32x4.prototype: return SIMD.Uint32x4;
case SIMD.Float32x4.prototype: return SIMD.Float32x4;
case SIMD.Bool8x16.prototype: return SIMD.Bool8x16;
case SIMD.Bool16x8.prototype: return SIMD.Bool16x8;
case SIMD.Bool32x4.prototype: return SIMD.Bool32x4;
}
throw "unexpected SIMD type";
}
function GetLength(t) {
switch (t) {
case SIMD.Int8x16: return 16;
case SIMD.Int16x8: return 8;
case SIMD.Int32x4: return 4;
case SIMD.Uint8x16: return 16;
case SIMD.Uint16x8: return 8;
case SIMD.Uint32x4: return 4;
case SIMD.Float32x4: return 4;
case SIMD.Bool8x16: return 16;
case SIMD.Bool16x8: return 8;
case SIMD.Bool32x4: return 4;
}
throw "unexpected SIMD type";
}
function assertEqVec(v, w) {
var typeV = GetType(v);
var lengthV = GetLength(typeV);
var ext = typeV.extractLane;
assertEq(GetType(w), typeV);
for (var i = 0; i < lengthV; i++)
assertEq(ext(v, i), ext(w, i));
}
function assertEqVecArr(v, w) {
var typeV = GetType(v);
var lengthV = GetLength(typeV);
var ext = typeV.extractLane;
assertEq(w.length, lengthV);
for (var i = 0; i < lengthV; i++)
assertEq(ext(v, i), w[i]);
}
function assertEqX4(vec, arr, ...opts) {
var assertFunc;
if (opts.length == 1 && typeof opts[0] !== 'undefined') {
assertFunc = opts[0];
} else {
assertFunc = assertEq;
}
var Type = GetType(vec);
assertFunc(Type.extractLane(vec, 0), arr[0]);
assertFunc(Type.extractLane(vec, 1), arr[1]);
assertFunc(Type.extractLane(vec, 2), arr[2]);
assertFunc(Type.extractLane(vec, 3), arr[3]);
}
function simdToArray(vec) {
var Type = GetType(vec);
var Length = GetLength(Type);
var a = [];
for (var i = 0; i < Length; i++)
a.push(Type.extractLane(vec, i));
return a;
}

View file

@ -1,38 +0,0 @@
load(libdir + 'simd.js');
setJitCompilerOption("ion.warmup.trigger", 50);
function all(B, n) {
var a = B.splat(true);
for (var i = 0; i < n; i++) {
var b = B.replaceLane(a, i, false);
assertEq(B.allTrue(b), false);
var c = B.replaceLane(b, i, true);
assertEq(B.allTrue(c), true);
}
}
function any(B, n) {
var a = B.splat(false);
for (var i = 0; i < n; i++) {
var b = B.replaceLane(a, i, true);
assertEq(B.anyTrue(b), true);
var c = B.replaceLane(b, i, false);
assertEq(B.anyTrue(c), false);
}
}
function f() {
for (var j = 0; j < 200; j++) {
all(SIMD.Bool64x2, 2)
any(SIMD.Bool64x2, 2)
all(SIMD.Bool32x4, 4)
any(SIMD.Bool32x4, 4)
all(SIMD.Bool16x8, 8)
any(SIMD.Bool16x8, 8)
all(SIMD.Bool8x16, 16)
any(SIMD.Bool8x16, 16)
}
}
f()

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