forked from mirrors/gecko-dev
Merge inbound to mozilla-central. a=merge
This commit is contained in:
commit
3708e71462
480 changed files with 12099 additions and 45114 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -217,7 +217,6 @@
|
|||
label="&trackingProtection.title;"/>
|
||||
<toolbarseparator orient="vertical"/>
|
||||
<toolbarbutton id="appMenu-tp-toggle"
|
||||
class="subviewkeynav"
|
||||
enabled="false"
|
||||
oncommand="TrackingProtection.onGlobalToggleCommand();" />
|
||||
</toolbaritem>
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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"] {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -55,8 +55,6 @@
|
|||
|
||||
.shortcuts-content {
|
||||
padding: 15px;
|
||||
-moz-column-width: 250px;
|
||||
-webkit-column-width: 250px;
|
||||
column-width: 250px;
|
||||
cursor: default;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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", {
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ DevToolsModules(
|
|||
'Expressions.js',
|
||||
'FrameworkComponent.js',
|
||||
'index.js',
|
||||
'ReactComponentStack.js',
|
||||
'Scopes.js',
|
||||
'UtilsBar.js',
|
||||
'Workers.js',
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 |
|
|
@ -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;
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ public:
|
|||
|
||||
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
||||
|
||||
void ConstructUbiNode(void* storage) override;
|
||||
|
||||
nsDOMAttributeMap* GetMap()
|
||||
{
|
||||
return mAttrMap;
|
||||
|
|
|
|||
|
|
@ -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*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
75
dom/base/NodeUbiReporting.cpp
Normal file
75
dom/base/NodeUbiReporting.cpp
Normal 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();
|
||||
}
|
||||
84
dom/base/NodeUbiReporting.h
Normal file
84
dom/base/NodeUbiReporting.h
Normal 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
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsScreen;
|
||||
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -3042,6 +3042,8 @@ public:
|
|||
// declaration of nsINode::SizeOfIncludingThis.
|
||||
virtual void DocAddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const;
|
||||
|
||||
void ConstructUbiNode(void* storage) override;
|
||||
|
||||
bool MayHaveDOMMutationObservers()
|
||||
{
|
||||
return mMayHaveDOMMutationObservers;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -490,6 +490,7 @@ AutoJSAPI::Init(nsIGlobalObject* aGlobalObject)
|
|||
bool
|
||||
AutoJSAPI::Init(JSObject* aObject)
|
||||
{
|
||||
MOZ_ASSERT(!js::IsCrossCompartmentWrapper(aObject));
|
||||
return Init(xpc::NativeGlobal(aObject));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ var ecmaGlobals =
|
|||
"RegExp",
|
||||
"Set",
|
||||
{name: "SharedArrayBuffer", disabled: true},
|
||||
{name: "SIMD", nightly: true},
|
||||
"String",
|
||||
"Symbol",
|
||||
"SyntaxError",
|
||||
|
|
|
|||
|
|
@ -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*.
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
26
gfx/qcms/fuzztest/qcms_fuzzer.dict
Normal file
26
gfx/qcms/fuzztest/qcms_fuzzer.dict
Normal 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"
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ private:
|
|||
DWRITE_MEASURING_MODE fMeasuringMode;
|
||||
DWRITE_TEXT_ANTIALIAS_MODE fAntiAliasMode;
|
||||
DWRITE_GRID_FIT_MODE fGridFitMode;
|
||||
SkTScopedComPtr<IDWriteRenderingParams> fDefaultRenderingParams;
|
||||
bool fIsColorFont;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ class SkString;
|
|||
// Factory
|
||||
|
||||
IDWriteFactory* sk_get_dwrite_factory();
|
||||
IDWriteRenderingParams* sk_get_dwrite_default_rendering_params();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// String conversion
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ EXPORTS += [
|
|||
'nsRegion.h',
|
||||
'nsRegionFwd.h',
|
||||
'nsSize.h',
|
||||
'nsThemeConstants.h',
|
||||
'nsTransform2D.h',
|
||||
'RegionBuilder.h',
|
||||
'X11UndefineNone.h'
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
@ -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)) \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
SIMD/nursery-overflow.js
|
||||
asm.js/testBug1117235.js
|
||||
asm.js/testParallelCompile.js
|
||||
auto-regress/bug653395.js
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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") \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ¤tTime,
|
||||
GCRuntime::shouldPreserveJITCode(Realm* realm, const TimeStamp ¤tTime,
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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++ = ' ';
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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')]
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
Loading…
Reference in a new issue