diff --git a/.mailmap b/.mailmap index 9df203838bf6..f239cdef57c2 100644 --- a/.mailmap +++ b/.mailmap @@ -1 +1,2 @@ +Andreas Tolfsen Nika Layzell Michael Layzell diff --git a/browser/base/content/browser-pageActions.js b/browser/base/content/browser-pageActions.js index bac04157ab25..d6be64e733a5 100644 --- a/browser/base/content/browser-pageActions.js +++ b/browser/base/content/browser-pageActions.js @@ -251,7 +251,7 @@ var BrowserPageActions = { let popupSet = document.getElementById("mainPopupSet"); popupSet.appendChild(panelNode); panelNode.addEventListener("popuphidden", () => { - panelNode.remove(); + PanelMultiView.removePopup(panelNode); }, { once: true }); if (iframeNode) { diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css index 546dcf476e58..eaa1eb254255 100644 --- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -77,18 +77,17 @@ toolbar[customizable="true"] { panelmultiview { -moz-box-align: start; - -moz-binding: url("chrome://browser/content/customizableui/panelUI.xml#panelmultiview"); +} + +panelmultiview[transitioning] { + pointer-events: none; } panelview { -moz-box-orient: vertical; } -panel[hidden] panelmultiview { - -moz-binding: none; -} - -panelview:not([current]):not([in-transition]) { +panelview:not([visible]) { visibility: collapse; } @@ -97,6 +96,26 @@ panelview[mainview] > .panel-header { display: none; } +.panel-viewcontainer { + overflow: hidden; +} + +.panel-viewcontainer[panelopen] { + transition-property: height; + transition-timing-function: var(--animation-easing-function); + transition-duration: var(--panelui-subview-transition-duration); + will-change: height; +} + +.panel-viewcontainer.offscreen { + position: absolute; +} + +.panel-viewstack { + overflow: visible; + transition: height var(--panelui-subview-transition-duration); +} + #navigator-toolbox { -moz-binding: url("chrome://browser/content/tabbrowser.xml#empty"); } diff --git a/browser/base/content/test/performance/browser_appmenu_reflows.js b/browser/base/content/test/performance/browser_appmenu_reflows.js index 7d5343352778..e957b5c9b6f6 100644 --- a/browser/base/content/test/performance/browser_appmenu_reflows.js +++ b/browser/base/content/test/performance/browser_appmenu_reflows.js @@ -100,21 +100,19 @@ add_task(async function() { await BrowserTestUtils.waitForEvent(PanelUI.panel, "ViewShown"); // Workaround until bug 1363756 is fixed, then this can be removed. + let container = PanelUI.multiView.querySelector(".panel-viewcontainer"); await BrowserTestUtils.waitForCondition(() => { - return !PanelUI.multiView.instance._viewContainer.hasAttribute("width"); + return !container.hasAttribute("width"); }); - info("Shown " + PanelUI.multiView.instance._currentSubView.id); - // Unfortunately, I can't find a better accessor to the current - // subview, so I have to reach the PanelMultiView instance - // here. - await openSubViewsRecursively(PanelUI.multiView.instance._currentSubView); + info("Shown " + PanelUI.multiView.current.id); + await openSubViewsRecursively(PanelUI.multiView.current); PanelUI.multiView.goBack(); await BrowserTestUtils.waitForEvent(PanelUI.panel, "ViewShown"); // Workaround until bug 1363756 is fixed, then this can be removed. await BrowserTestUtils.waitForCondition(() => { - return !PanelUI.multiView.instance._viewContainer.hasAttribute("width"); + return !container.hasAttribute("width"); }); } } diff --git a/browser/components/customizableui/PanelMultiView.jsm b/browser/components/customizableui/PanelMultiView.jsm index 8a19fcaeac6b..624f3a284e92 100644 --- a/browser/components/customizableui/PanelMultiView.jsm +++ b/browser/components/customizableui/PanelMultiView.jsm @@ -55,6 +55,20 @@ * When navigating backwards, an open subview will first become invisible and * then will be closed. * + * -- Active or inactive + * + * This indicates whether the view is fully scrolled into the visible area + * and ready to receive mouse and keyboard events. An active view is always + * visible, but a visible view may be inactive. For example, during a scroll + * transition, both views will be inactive. + * + * When a view becomes active, the ViewShown event is fired synchronously. + * For the main view of the panel, this happens during the "popupshown" + * event, which means that other "popupshown" handlers may be called before + * the view is active. However, the main view can already receive mouse and + * keyboard events at this point, only because this allows regression tests + * to use the "popupshown" event to simulate interaction. + * * -- Navigating with the keyboard * * An open view may keep state related to keyboard navigation, even if it is @@ -96,11 +110,14 @@ ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); ChromeUtils.import("resource://gre/modules/Services.jsm"); ChromeUtils.defineModuleGetter(this, "AppConstants", "resource://gre/modules/AppConstants.jsm"); -ChromeUtils.defineModuleGetter(this, "BrowserUtils", - "resource://gre/modules/BrowserUtils.jsm"); ChromeUtils.defineModuleGetter(this, "CustomizableUI", "resource:///modules/CustomizableUI.jsm"); +XPCOMUtils.defineLazyGetter(this, "gBundle", function() { + return Services.strings.createBundle( + "chrome://browser/locale/browser.properties"); +}); + /** * Safety timeout after which asynchronous events will be canceled if any of the * registered blockers does not return. @@ -115,6 +132,7 @@ const TRANSITION_PHASES = Object.freeze({ }); let gNodeToObjectMap = new WeakMap(); +let gWindowsWithUnloadHandler = new WeakSet(); let gMultiLineElementsMap = new WeakMap(); /** @@ -247,7 +265,7 @@ var AssociatedToNode = class { }; /** - * This is associated to elements by the panelUI.xml binding. + * This is associated to elements. */ var PanelMultiView = class extends this.AssociatedToNode { /** @@ -285,6 +303,44 @@ var PanelMultiView = class extends this.AssociatedToNode { } } + /** + * Removes the specified from the document, ensuring that any + * node it contains is destroyed properly. + * + * If the panel does not contain a , it is removed directly. + * This allows consumers like page actions to accept different panel types. + */ + static removePopup(panelNode) { + try { + let panelMultiViewNode = panelNode.querySelector("panelmultiview"); + if (panelMultiViewNode) { + this.forNode(panelMultiViewNode).disconnect(); + } + } finally { + // Make sure to remove the panel element even if disconnecting fails. + panelNode.remove(); + } + } + + /** + * Ensures that when the specified window is closed all the + * node it contains are destroyed properly. + */ + static ensureUnloadHandlerRegistered(window) { + if (gWindowsWithUnloadHandler.has(window)) { + return; + } + + window.addEventListener("unload", () => { + for (let panelMultiViewNode of + window.document.querySelectorAll("panelmultiview")) { + this.forNode(panelMultiViewNode).disconnect(); + } + }, { once: true }); + + gWindowsWithUnloadHandler.add(window); + } + get _panel() { return this.node.parentNode; } @@ -349,28 +405,41 @@ var PanelMultiView = class extends this.AssociatedToNode { connect() { this.connected = true; + + PanelMultiView.ensureUnloadHandlerRegistered(this.window); + + let viewContainer = this._viewContainer = + this.document.createElement("box"); + viewContainer.classList.add("panel-viewcontainer"); + + let viewStack = this._viewStack = this.document.createElement("box"); + viewStack.classList.add("panel-viewstack"); + viewContainer.append(viewStack); + + let offscreenViewContainer = this.document.createElement("box"); + offscreenViewContainer.classList.add("panel-viewcontainer", "offscreen"); + + let offscreenViewStack = this._offscreenViewStack = + this.document.createElement("box"); + offscreenViewStack.classList.add("panel-viewstack"); + offscreenViewContainer.append(offscreenViewStack); + + this.node.prepend(offscreenViewContainer); + this.node.prepend(viewContainer); + this.openViews = []; this.__transitioning = false; - const {document, window} = this; - - this._viewContainer = - document.getAnonymousElementByAttribute(this.node, "anonid", "viewContainer"); - this._viewStack = - document.getAnonymousElementByAttribute(this.node, "anonid", "viewStack"); - this._offscreenViewStack = - document.getAnonymousElementByAttribute(this.node, "anonid", "offscreenViewStack"); - XPCOMUtils.defineLazyGetter(this, "_panelViewCache", () => { let viewCacheId = this.node.getAttribute("viewCacheId"); - return viewCacheId ? document.getElementById(viewCacheId) : null; + return viewCacheId ? this.document.getElementById(viewCacheId) : null; }); this._panel.addEventListener("popupshowing", this); this._panel.addEventListener("popuppositioned", this); this._panel.addEventListener("popuphidden", this); this._panel.addEventListener("popupshown", this); - let cs = window.getComputedStyle(document.documentElement); + let cs = this.window.getComputedStyle(this.document.documentElement); // Set CSS-determined attributes now to prevent a layout flush when we do // it when transitioning between panels. this._dir = cs.direction; @@ -391,9 +460,9 @@ var PanelMultiView = class extends this.AssociatedToNode { }); } - destructor() { + disconnect() { // Guard against re-entrancy. - if (!this.node) + if (!this.node || !this.connected) return; this._cleanupTransitionPhase(); @@ -489,21 +558,8 @@ var PanelMultiView = class extends this.AssociatedToNode { return true; } try { - // Most of the panel elements in the browser window have their display - // turned off for performance reasons, typically by setting the "hidden" - // attribute. If the caller has just turned on the display, the XBL - // binding for the element may still be disconnected. - // In this case, give the layout code a chance to run. if (!this.connected) { - await this.window.promiseDocumentFlushed(() => {}); - - // The XBL binding must be connected at this point. If this is not the - // case, the calling code should be updated to unhide the panel. - if (!this.connected) { - throw new Error("The binding for the panelmultiview element isn't" + - " connected. The containing panel may still have" + - " its display turned off by the hidden attribute."); - } + this.connect(); } // Allow any of the ViewShowing handlers to prevent showing the main view. if (!(await this._showMainView())) { @@ -631,7 +687,7 @@ var PanelMultiView = class extends this.AssociatedToNode { } await this._transitionViews(prevPanelView.node, viewNode, false, anchor); - this._viewShown(nextPanelView); + this._activateView(nextPanelView); } /** @@ -655,7 +711,7 @@ var PanelMultiView = class extends this.AssociatedToNode { this._closeLatestView(); - this._viewShown(nextPanelView); + this._activateView(nextPanelView); } /** @@ -672,6 +728,10 @@ var PanelMultiView = class extends this.AssociatedToNode { let oldPanelMultiViewNode = nextPanelView.node.panelMultiView; if (oldPanelMultiViewNode) { PanelMultiView.forNode(oldPanelMultiViewNode).hidePopup(); + // Wait for a layout flush after hiding the popup, otherwise the view may + // not be displayed correctly for some time after the new panel is opened. + // This is filed as bug 1441015. + await this.window.promiseDocumentFlushed(() => {}); } if (!(await this._openView(nextPanelView))) { @@ -688,7 +748,6 @@ var PanelMultiView = class extends this.AssociatedToNode { nextPanelView.visible = true; nextPanelView.descriptionHeightWorkaround(); - this._viewShown(nextPanelView); return true; } @@ -728,10 +787,12 @@ var PanelMultiView = class extends this.AssociatedToNode { } /** - * Raises the ViewShown event if the specified view is still open. + * Activates the specified view and raises the ViewShown event, unless the + * view was closed in the meantime. */ - _viewShown(panelView) { + _activateView(panelView) { if (panelView.node.panelMultiView == this.node) { + panelView.active = true; panelView.dispatchCustomEvent("ViewShown"); } } @@ -804,10 +865,6 @@ var PanelMultiView = class extends this.AssociatedToNode { if (anchor) anchor.setAttribute("open", "true"); - // Since we're going to show two subview at the same time, don't abuse the - // 'current' attribute, since it's needed for other state-keeping, but use - // a separate 'in-transition' attribute instead. - previousViewNode.setAttribute("in-transition", true); // Set the viewContainer dimensions to make sure only the current view is // visible. let olderView = reverse ? nextPanelView : prevPanelView; @@ -825,7 +882,7 @@ var PanelMultiView = class extends this.AssociatedToNode { // reopening a subview, because its contents may have changed. viewRect = { width: nextPanelView.knownWidth, height: nextPanelView.knownHeight }; - viewNode.setAttribute("in-transition", true); + nextPanelView.visible = true; } else if (viewNode.customRectGetter) { // Can't use Object.assign directly with a DOM Rect object because its properties // aren't enumerable. @@ -836,12 +893,13 @@ var PanelMultiView = class extends this.AssociatedToNode { if (header && header.classList.contains("panel-header")) { viewRect.height += this._dwu.getBoundsWithoutFlushing(header).height; } - viewNode.setAttribute("in-transition", true); + nextPanelView.visible = true; + nextPanelView.descriptionHeightWorkaround(); } else { let oldSibling = viewNode.nextSibling || null; this._offscreenViewStack.style.minHeight = olderView.knownHeight + "px"; this._offscreenViewStack.appendChild(viewNode); - viewNode.setAttribute("in-transition", true); + nextPanelView.visible = true; // Now that the subview is visible, we can check the height of the // description elements it contains. @@ -884,6 +942,10 @@ var PanelMultiView = class extends this.AssociatedToNode { // Use an outline instead of a border so that the size is not affected. deepestNode.style.outline = "1px solid var(--panel-separator-color)"; + // Now that all the elements are in place for the start of the transition, + // give the layout code a chance to set the initial values. + await window.promiseDocumentFlushed(() => {}); + // Now set the viewContainer dimensions to that of the new view, which // kicks of the height animation. this._viewContainer.style.height = viewRect.height + "px"; @@ -894,7 +956,13 @@ var PanelMultiView = class extends this.AssociatedToNode { // sliding animation with smaller views. viewNode.style.width = viewRect.width + "px"; - await window.promiseDocumentFlushed(() => {}); + // For proper bookkeeping, mark the view that is about to scrolled out of + // the visible area as inactive, because it won't be possible to simulate + // mouse events on it properly. In practice this isn't important, because we + // use the separate "transitioning" attribute on the panel to suppress + // pointer events. This allows mouse events to be available for the main + // view in regression tests that wait for the "popupshown" event. + prevPanelView.active = false; // Kick off the transition! details.phase = TRANSITION_PHASES.TRANSITION; @@ -926,8 +994,6 @@ var PanelMultiView = class extends this.AssociatedToNode { // Apply the final visibility, unless the view was closed in the meantime. if (nextPanelView.node.panelMultiView == this.node) { prevPanelView.visible = false; - nextPanelView.visible = true; - nextPanelView.descriptionHeightWorkaround(); } // This will complete the operation by removing any transition properties. @@ -958,9 +1024,6 @@ var PanelMultiView = class extends this.AssociatedToNode { // Do the things we _always_ need to do whenever the transition ends or is // interrupted. - previousViewNode.removeAttribute("in-transition"); - viewNode.removeAttribute("in-transition"); - if (anchor) anchor.removeAttribute("open"); @@ -1060,7 +1123,7 @@ var PanelMultiView = class extends this.AssociatedToNode { this.openViews.forEach(panelView => panelView.clearNavigation()); break; case "popupshowing": { - this.node.setAttribute("panelopen", "true"); + this._viewContainer.setAttribute("panelopen", "true"); if (!this.node.hasAttribute("disablekeynav")) { this.window.addEventListener("keydown", this); this._panel.addEventListener("mousemove", this); @@ -1085,15 +1148,17 @@ var PanelMultiView = class extends this.AssociatedToNode { break; } case "popupshown": + let mainPanelView = PanelView.forNode(this._mainView); // Now that the main view is visible, we can check the height of the // description elements it contains. - PanelView.forNode(this._mainView).descriptionHeightWorkaround(); + mainPanelView.descriptionHeightWorkaround(); + this._activateView(mainPanelView); break; case "popuphidden": { // WebExtensions consumers can hide the popup from viewshowing, or // mid-transition, which disrupts our state: this._transitioning = false; - this.node.removeAttribute("panelopen"); + this._viewContainer.removeAttribute("panelopen"); this._cleanupTransitionPhase(); this.window.removeEventListener("keydown", this); this._panel.removeEventListener("mousemove", this); @@ -1117,6 +1182,16 @@ var PanelMultiView = class extends this.AssociatedToNode { * This is associated to elements. */ var PanelView = class extends this.AssociatedToNode { + constructor(node) { + super(node); + + /** + * Indicates whether the view is active. When this is false, consumers can + * wait for the ViewShown event to know when the view becomes active. + */ + this.active = false; + } + /** * The "mainview" attribute is set before the panel is opened when this view * is displayed as the main view, and is removed before the is @@ -1131,11 +1206,16 @@ var PanelView = class extends this.AssociatedToNode { } } + /** + * Determines whether the view is visible. Setting this to false also resets + * the "active" property. + */ set visible(value) { if (value) { - this.node.setAttribute("current", true); + this.node.setAttribute("visible", true); } else { - this.node.removeAttribute("current"); + this.node.removeAttribute("visible"); + this.active = false; } } @@ -1181,8 +1261,8 @@ var PanelView = class extends this.AssociatedToNode { "subviewbutton subviewbutton-iconic subviewbutton-back"; backButton.setAttribute("closemenu", "none"); backButton.setAttribute("tabindex", "0"); - backButton.setAttribute("tooltip", - this.node.getAttribute("data-subviewbutton-tooltip")); + backButton.setAttribute("aria-label", + gBundle.GetStringFromName("panel.back")); backButton.addEventListener("command", () => { // The panelmultiview element may change if the view is reused. this.node.panelMultiView.goBack(); diff --git a/browser/components/customizableui/content/jar.mn b/browser/components/customizableui/content/jar.mn index 05c0112cd87e..df48d768b76e 100644 --- a/browser/components/customizableui/content/jar.mn +++ b/browser/components/customizableui/content/jar.mn @@ -3,8 +3,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. browser.jar: - content/browser/customizableui/panelUI.css content/browser/customizableui/panelUI.js - content/browser/customizableui/panelUI.xml content/browser/customizableui/toolbar.xml diff --git a/browser/components/customizableui/content/panelUI.css b/browser/components/customizableui/content/panelUI.css deleted file mode 100644 index 0cf1209e2b51..000000000000 --- a/browser/components/customizableui/content/panelUI.css +++ /dev/null @@ -1,27 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -.panel-viewcontainer { - overflow: hidden; -} - -.panel-viewstack { - overflow: visible; - transition: height var(--panelui-subview-transition-duration); -} - -.panel-viewcontainer[panelopen] { - transition-property: height; - transition-timing-function: var(--animation-easing-function); - transition-duration: var(--panelui-subview-transition-duration); - will-change: height; -} - -panelmultiview[transitioning] { - pointer-events: none; -} - -.panel-viewcontainer.offscreen { - position: absolute; -} diff --git a/browser/components/customizableui/content/panelUI.js b/browser/components/customizableui/content/panelUI.js index 0e3c8c3b41be..d07170856e3c 100644 --- a/browser/components/customizableui/content/panelUI.js +++ b/browser/components/customizableui/content/panelUI.js @@ -423,10 +423,7 @@ const PanelUI = { } aAnchor.open = false; - // Ensure we run the destructor: - multiView.instance.destructor(); - - tempPanel.remove(); + PanelMultiView.removePopup(tempPanel); }; if (aAnchor.parentNode.id == "PersonalToolbar") { diff --git a/browser/components/customizableui/content/panelUI.xml b/browser/components/customizableui/content/panelUI.xml deleted file mode 100644 index b06969f21b89..000000000000 --- a/browser/components/customizableui/content/panelUI.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - %browserDTD; -]> - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/browser/components/customizableui/test/browser.ini b/browser/components/customizableui/test/browser.ini index 49a9c428296f..e5dcd68df154 100644 --- a/browser/components/customizableui/test/browser.ini +++ b/browser/components/customizableui/test/browser.ini @@ -141,6 +141,7 @@ skip-if = os == "linux" # linux doesn't get drag space (no tabsintitlebar) [browser_drag_outside_palette.js] [browser_exit_background_customize_mode.js] [browser_insert_before_moved_node.js] +[browser_library_after_appMenu.js] [browser_overflow_use_subviews.js] [browser_panel_keyboard_navigation.js] [browser_panel_toggle.js] @@ -164,3 +165,7 @@ subsuite = clipboard [browser_sidebar_toggle.js] [browser_remote_tabs_button.js] [browser_widget_animation.js] + +# Unit tests for the PanelMultiView module. These are independent from +# CustomizableUI, but are located here together with the module they're testing. +[browser_PanelMultiView.js] diff --git a/browser/components/customizableui/test/browser_947914_button_history.js b/browser/components/customizableui/test/browser_947914_button_history.js index 3ed2e3939678..cd122640d589 100644 --- a/browser/components/customizableui/test/browser_947914_button_history.js +++ b/browser/components/customizableui/test/browser_947914_button_history.js @@ -28,7 +28,7 @@ add_task(async function() { let promise = BrowserTestUtils.waitForEvent(historyPanel, "ViewShown"); historyButton.click(); await promise; - ok(historyPanel.getAttribute("current"), "History Panel is in view"); + ok(historyPanel.getAttribute("visible"), "History Panel is in view"); let browserLoaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser); let panelHiddenPromise = promiseOverflowHidden(window); diff --git a/browser/components/customizableui/test/browser_967000_button_charEncoding.js b/browser/components/customizableui/test/browser_967000_button_charEncoding.js index 9b02be4c7bac..35c51100b4be 100644 --- a/browser/components/customizableui/test/browser_967000_button_charEncoding.js +++ b/browser/components/customizableui/test/browser_967000_button_charEncoding.js @@ -37,7 +37,7 @@ add_task(async function() { charEncodingButton.click(); await subviewShownPromise; - ok(characterEncodingView.hasAttribute("current"), "The Character encoding panel is displayed"); + ok(characterEncodingView.hasAttribute("visible"), "The Character encoding panel is displayed"); let pinnedEncodings = document.getElementById("PanelUI-characterEncodingView-pinned"); let charsetsList = document.getElementById("PanelUI-characterEncodingView-charsets"); diff --git a/browser/components/customizableui/test/browser_981418-widget-onbeforecreated-handler.js b/browser/components/customizableui/test/browser_981418-widget-onbeforecreated-handler.js index 74efd4bc150e..f3ec519b22f7 100644 --- a/browser/components/customizableui/test/browser_981418-widget-onbeforecreated-handler.js +++ b/browser/components/customizableui/test/browser_981418-widget-onbeforecreated-handler.js @@ -31,21 +31,12 @@ add_task(async function testAddOnBeforeCreatedWidget() { ok(widgetNode, "Widget should exist"); ok(viewNode, "Panelview should exist"); - let widgetPanel; - let panelShownPromise; - let viewShownPromise = new Promise(resolve => { - viewNode.addEventListener("ViewShown", () => { - widgetPanel = document.getElementById("customizationui-widget-panel"); - ok(widgetPanel, "Widget panel should exist"); - // Add the popupshown event listener directly inside the ViewShown event - // listener to avoid missing the event. - panelShownPromise = promisePanelElementShown(window, widgetPanel); - resolve(); - }, { once: true }); - }); + let viewShownPromise = BrowserTestUtils.waitForEvent(viewNode, "ViewShown"); widgetNode.click(); await viewShownPromise; - await panelShownPromise; + + let widgetPanel = document.getElementById("customizationui-widget-panel"); + ok(widgetPanel, "Widget panel should exist"); let panelHiddenPromise = promisePanelElementHidden(window, widgetPanel); widgetPanel.hidePopup(); @@ -55,9 +46,9 @@ add_task(async function testAddOnBeforeCreatedWidget() { await waitForOverflowButtonShown(); await document.getElementById("nav-bar").overflowable.show(); + viewShownPromise = BrowserTestUtils.waitForEvent(viewNode, "ViewShown"); widgetNode.click(); - - await BrowserTestUtils.waitForEvent(viewNode, "ViewShown"); + await viewShownPromise; let panelHidden = promiseOverflowHidden(window); PanelUI.overflowPanel.hidePopup(); diff --git a/browser/components/customizableui/test/browser_PanelMultiView.js b/browser/components/customizableui/test/browser_PanelMultiView.js new file mode 100644 index 000000000000..18de3e0e5801 --- /dev/null +++ b/browser/components/customizableui/test/browser_PanelMultiView.js @@ -0,0 +1,478 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Unit tests for the PanelMultiView module. + */ + +ChromeUtils.import("resource:///modules/PanelMultiView.jsm"); + +const PANELS_COUNT = 2; +let gPanelAnchors = []; +let gPanels = []; +let gPanelMultiViews = []; + +const PANELVIEWS_COUNT = 4; +let gPanelViews = []; +let gPanelViewLabels = []; + +const EVENT_TYPES = ["popupshown", "popuphidden", "PanelMultiViewHidden", + "ViewShowing", "ViewShown", "ViewHiding"]; + +/** + * Checks that the element is displayed, including the state of the popup where + * the element is located. This can trigger a synchronous reflow if necessary, + * because even though the code under test is designed to avoid synchronous + * reflows, it can raise completion events while a layout flush is still needed. + * + * In production code, event handlers for ViewShown have to wait for a flush if + * they need to read style or layout information, like other code normally does. + */ +function is_visible(element) { + var style = element.ownerGlobal.getComputedStyle(element); + if (style.display == "none") + return false; + if (style.visibility != "visible") + return false; + if (style.display == "-moz-popup" && element.state != "open") + return false; + + // Hiding a parent element will hide all its children + if (element.parentNode != element.ownerDocument) + return is_visible(element.parentNode); + + return true; +} + +/** + * Checks whether the label in the specified view is visible. + */ +function assertLabelVisible(viewIndex, expectedVisible) { + Assert.equal(is_visible(gPanelViewLabels[viewIndex]), expectedVisible, + `Visibility of label in view ${viewIndex}`); +} + +/** + * Opens the specified view as the main view in the specified panel. + */ +async function openPopup(panelIndex, viewIndex) { + gPanelMultiViews[panelIndex].setAttribute("mainViewId", + gPanelViews[viewIndex].id); + + let promiseShown = BrowserTestUtils.waitForEvent(gPanels[panelIndex], + "popupshown"); + PanelMultiView.openPopup(gPanels[panelIndex], gPanelAnchors[panelIndex], + "bottomcenter topright"); + await promiseShown; + + assertLabelVisible(viewIndex, true); +} + +/** + * Closes the specified panel. + */ +async function hidePopup(panelIndex) { + gPanelMultiViews[panelIndex].setAttribute("mainViewId", + gPanelViews[panelIndex].id); + + let promiseHidden = BrowserTestUtils.waitForEvent(gPanels[panelIndex], + "popuphidden"); + PanelMultiView.hidePopup(gPanels[panelIndex]); + await promiseHidden; +} + +/** + * Opens the specified subview in the specified panel. + */ +async function showSubView(panelIndex, viewIndex) { + let promiseShown = BrowserTestUtils.waitForEvent(gPanelViews[viewIndex], + "ViewShown"); + gPanelMultiViews[panelIndex].showSubView(gPanelViews[viewIndex]); + await promiseShown; + + assertLabelVisible(viewIndex, true); +} + +/** + * Navigates backwards to the specified view, which is displayed as a result. + */ +async function goBack(panelIndex, viewIndex) { + let promiseShown = BrowserTestUtils.waitForEvent(gPanelViews[viewIndex], + "ViewShown"); + gPanelMultiViews[panelIndex].goBack(); + await promiseShown; + + assertLabelVisible(viewIndex, true); +} + +/** + * Records the specified events on an element into the specified array. An + * optional callback can be used to respond to events and trigger nested events. + */ +function recordEvents(element, eventTypes, recordArray, + eventCallback = () => {}) { + let nestedEvents = []; + element.recorders = eventTypes.map(eventType => { + let recorder = { + eventType, + listener(event) { + let eventString = nestedEvents.join("") + + `${event.originalTarget.id}: ${event.type}`; + info(`Event on ${eventString}`); + recordArray.push(eventString); + // Any synchronous event triggered from within the given callback will + // include information about the current event. + nestedEvents.unshift(`${eventString} > `); + eventCallback(event); + nestedEvents.shift(); + }, + }; + element.addEventListener(recorder.eventType, recorder.listener); + return recorder; + }); +} + +/** + * Stops recording events on an element. + */ +function stopRecordingEvents(element) { + for (let recorder of element.recorders) { + element.removeEventListener(recorder.eventType, recorder.listener); + } + delete element.recorders; +} + +/** + * Sets up the elements in the browser window that will be used by all the other + * regression tests. Since the panel and view elements can live anywhere in the + * document, they are simply added to the same toolbar as the panel anchors. + * + * + * -> gPanelAnchors[panelIndex] + * -> gPanels[panelIndex] + * -> gPanelMultiViews[panelIndex] + * + * -> gPanelViews[viewIndex] + * + * + */ +add_task(async function test_setup() { + let navBar = document.getElementById("nav-bar"); + + for (let i = 0; i < PANELS_COUNT; i++) { + gPanelAnchors[i] = document.createElement("toolbarbutton"); + gPanelAnchors[i].classList.add("toolbarbutton-1", + "chromeclass-toolbar-additional"); + navBar.appendChild(gPanelAnchors[i]); + + gPanels[i] = document.createElement("panel"); + gPanels[i].id = "panel-" + i; + gPanels[i].setAttribute("type", "arrow"); + gPanels[i].setAttribute("photon", true); + navBar.appendChild(gPanels[i]); + + gPanelMultiViews[i] = document.createElement("panelmultiview"); + gPanelMultiViews[i].id = "panelmultiview-" + i; + gPanels[i].appendChild(gPanelMultiViews[i]); + } + + for (let i = 0; i < PANELVIEWS_COUNT; i++) { + gPanelViews[i] = document.createElement("panelview"); + gPanelViews[i].id = "panelview-" + i; + navBar.appendChild(gPanelViews[i]); + + gPanelViewLabels[i] = document.createElement("label"); + gPanelViewLabels[i].setAttribute("value", "PanelView " + i); + gPanelViews[i].appendChild(gPanelViewLabels[i]); + } + + registerCleanupFunction(() => { + [...gPanelAnchors, ...gPanels, ...gPanelViews].forEach(e => e.remove()); + }); +}); + +/** + * Shows and hides all views in a panel with this static structure: + * + * - Panel 0 + * - View 0 + * - View 1 + * - View 3 + * - View 2 + */ +add_task(async function test_simple() { + // Show main view 0. + await openPopup(0, 0); + + // Show and hide subview 1. + await showSubView(0, 1); + assertLabelVisible(0, false); + await goBack(0, 0); + assertLabelVisible(1, false); + + // Show subview 3. + await showSubView(0, 3); + assertLabelVisible(0, false); + + // Show and hide subview 2. + await showSubView(0, 2); + assertLabelVisible(3, false); + await goBack(0, 3); + assertLabelVisible(2, false); + + // Hide subview 3. + await goBack(0, 0); + assertLabelVisible(3, false); + + // Hide main view 0. + await hidePopup(0); + assertLabelVisible(0, false); +}); + +/** + * Tests the event sequence in a panel with this static structure: + * + * - Panel 0 + * - View 0 + * - View 1 + * - View 3 + * - View 2 + */ +add_task(async function test_simple_event_sequence() { + let recordArray = []; + recordEvents(gPanels[0], EVENT_TYPES, recordArray); + + await openPopup(0, 0); + await showSubView(0, 1); + await goBack(0, 0); + await showSubView(0, 3); + await showSubView(0, 2); + await goBack(0, 3); + await goBack(0, 0); + await hidePopup(0); + + stopRecordingEvents(gPanels[0]); + + Assert.deepEqual(recordArray, [ + "panelview-0: ViewShowing", + "panelview-0: ViewShown", + "panel-0: popupshown", + "panelview-1: ViewShowing", + "panelview-1: ViewShown", + "panelview-1: ViewHiding", + "panelview-0: ViewShown", + "panelview-3: ViewShowing", + "panelview-3: ViewShown", + "panelview-2: ViewShowing", + "panelview-2: ViewShown", + "panelview-2: ViewHiding", + "panelview-3: ViewShown", + "panelview-3: ViewHiding", + "panelview-0: ViewShown", + "panelview-0: ViewHiding", + "panelmultiview-0: PanelMultiViewHidden", + "panel-0: popuphidden", + ]); +}); + +/** + * Tests reusing views that are already open in another panel. In this test, the + * structure of the first panel will change dynamically: + * + * - Panel 0 + * - View 0 + * - View 1 + * - Panel 1 + * - View 1 + * - View 2 + * - Panel 0 + * - View 1 + * - View 0 + */ +add_task(async function test_switch_event_sequence() { + let recordArray = []; + recordEvents(gPanels[0], EVENT_TYPES, recordArray); + recordEvents(gPanels[1], EVENT_TYPES, recordArray); + + // Show panel 0. + await openPopup(0, 0); + await showSubView(0, 1); + + // Show panel 1 with the view that is already open and visible in panel 0. + // This will close panel 0 automatically. + await openPopup(1, 1); + await showSubView(1, 2); + + // Show panel 0 with a view that is already open but invisible in panel 1. + // This will close panel 1 automatically. + await openPopup(0, 1); + await showSubView(0, 0); + + // Hide panel 0. + await hidePopup(0); + + stopRecordingEvents(gPanels[0]); + stopRecordingEvents(gPanels[1]); + + Assert.deepEqual(recordArray, [ + "panelview-0: ViewShowing", + "panelview-0: ViewShown", + "panel-0: popupshown", + "panelview-1: ViewShowing", + "panelview-1: ViewShown", + "panelview-1: ViewHiding", + "panelview-0: ViewHiding", + "panelmultiview-0: PanelMultiViewHidden", + "panel-0: popuphidden", + "panelview-1: ViewShowing", + "panel-1: popupshown", + "panelview-1: ViewShown", + "panelview-2: ViewShowing", + "panelview-2: ViewShown", + "panel-1: popuphidden", + "panelview-2: ViewHiding", + "panelview-1: ViewHiding", + "panelmultiview-1: PanelMultiViewHidden", + "panelview-1: ViewShowing", + "panelview-1: ViewShown", + "panel-0: popupshown", + "panelview-0: ViewShowing", + "panelview-0: ViewShown", + "panelview-0: ViewHiding", + "panelview-1: ViewHiding", + "panelmultiview-0: PanelMultiViewHidden", + "panel-0: popuphidden", + ]); +}); + +/** + * Tests the event sequence when opening the main view is canceled. + */ +add_task(async function test_cancel_mainview_event_sequence() { + let recordArray = []; + recordEvents(gPanels[0], EVENT_TYPES, recordArray, event => { + if (event.type == "ViewShowing") { + event.preventDefault(); + } + }); + + gPanelMultiViews[0].setAttribute("mainViewId", gPanelViews[0].id); + + let promiseHidden = BrowserTestUtils.waitForEvent(gPanels[0], "popuphidden"); + PanelMultiView.openPopup(gPanels[0], gPanelAnchors[0], + "bottomcenter topright"); + await promiseHidden; + + stopRecordingEvents(gPanels[0]); + + Assert.deepEqual(recordArray, [ + "panelview-0: ViewShowing", + "panelview-0: ViewHiding", + "panelmultiview-0: popuphidden", + ]); +}); + +/** + * Tests the event sequence when opening a subview is canceled. + */ +add_task(async function test_cancel_subview_event_sequence() { + let recordArray = []; + recordEvents(gPanels[0], EVENT_TYPES, recordArray, event => { + if (event.type == "ViewShowing" && + event.originalTarget.id == gPanelViews[1].id) { + event.preventDefault(); + } + }); + + await openPopup(0, 0); + + let promiseHiding = BrowserTestUtils.waitForEvent(gPanelViews[1], + "ViewHiding"); + gPanelMultiViews[0].showSubView(gPanelViews[1]); + await promiseHiding; + + // Only the subview should have received the hidden event at this point. + Assert.deepEqual(recordArray, [ + "panelview-0: ViewShowing", + "panelview-0: ViewShown", + "panel-0: popupshown", + "panelview-1: ViewShowing", + "panelview-1: ViewHiding", + ]); + recordArray.length = 0; + + await hidePopup(0); + + stopRecordingEvents(gPanels[0]); + + Assert.deepEqual(recordArray, [ + "panelview-0: ViewHiding", + "panelmultiview-0: PanelMultiViewHidden", + "panel-0: popuphidden", + ]); +}); + +/** + * Tests the event sequence when closing the panel while opening the main view. + */ +add_task(async function test_close_while_showing_mainview_event_sequence() { + let recordArray = []; + recordEvents(gPanels[0], EVENT_TYPES, recordArray, event => { + if (event.type == "ViewShowing") { + PanelMultiView.hidePopup(gPanels[0]); + } + }); + + gPanelMultiViews[0].setAttribute("mainViewId", gPanelViews[0].id); + + let promiseHidden = BrowserTestUtils.waitForEvent(gPanels[0], "popuphidden"); + let promiseHiding = BrowserTestUtils.waitForEvent(gPanelViews[0], + "ViewHiding"); + PanelMultiView.openPopup(gPanels[0], gPanelAnchors[0], + "bottomcenter topright"); + await promiseHiding; + await promiseHidden; + + stopRecordingEvents(gPanels[0]); + + Assert.deepEqual(recordArray, [ + "panelview-0: ViewShowing", + "panelview-0: ViewShowing > panelmultiview-0: popuphidden", + "panelview-0: ViewShowing > panelview-0: ViewHiding", + ]); +}); + +/** + * Tests the event sequence when closing the panel while opening a subview. + */ +add_task(async function test_close_while_showing_subview_event_sequence() { + let recordArray = []; + recordEvents(gPanels[0], EVENT_TYPES, recordArray, event => { + if (event.type == "ViewShowing" && + event.originalTarget.id == gPanelViews[1].id) { + PanelMultiView.hidePopup(gPanels[0]); + } + }); + + await openPopup(0, 0); + + let promiseHidden = BrowserTestUtils.waitForEvent(gPanels[0], "popuphidden"); + gPanelMultiViews[0].showSubView(gPanelViews[1]); + await promiseHidden; + + stopRecordingEvents(gPanels[0]); + + Assert.deepEqual(recordArray, [ + "panelview-0: ViewShowing", + "panelview-0: ViewShown", + "panel-0: popupshown", + "panelview-1: ViewShowing", + "panelview-1: ViewShowing > panelview-1: ViewHiding", + "panelview-1: ViewShowing > panelview-0: ViewHiding", + "panelview-1: ViewShowing > panelmultiview-0: PanelMultiViewHidden", + "panelview-1: ViewShowing > panel-0: popuphidden", + ]); +}); diff --git a/browser/components/customizableui/test/browser_library_after_appMenu.js b/browser/components/customizableui/test/browser_library_after_appMenu.js new file mode 100644 index 000000000000..130c8bc89ecc --- /dev/null +++ b/browser/components/customizableui/test/browser_library_after_appMenu.js @@ -0,0 +1,37 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Checks that opening the Library view using the default toolbar button works + * also while the view is displayed in the main menu. + */ +add_task(async function test_library_after_appMenu() { + await PanelUI.show(); + + // Show the Library view as a subview of the main menu. + let libraryView = document.getElementById("appMenu-libraryView"); + let promise = BrowserTestUtils.waitForEvent(libraryView, "ViewShown"); + document.getElementById("appMenu-library-button").click(); + await promise; + + // Show the Library view as the main view of the Library panel. + promise = BrowserTestUtils.waitForEvent(libraryView, "ViewShown"); + document.getElementById("library-button").click(); + await promise; + + // Navigate to the History subview. + let historyView = document.getElementById("PanelUI-history"); + promise = BrowserTestUtils.waitForEvent(historyView, "ViewShown"); + document.getElementById("appMenu-library-history-button").click(); + await promise; + + Assert.ok(PanelView.forNode(historyView).active); + + // Close the Library panel. + let historyPanel = historyView.closest("panel"); + promise = BrowserTestUtils.waitForEvent(historyPanel, "popuphidden"); + historyPanel.hidePopup(); + await promise; +}); diff --git a/browser/components/customizableui/test/browser_remote_tabs_button.js b/browser/components/customizableui/test/browser_remote_tabs_button.js index d96b21086a1a..4e3e739d2e76 100644 --- a/browser/components/customizableui/test/browser_remote_tabs_button.js +++ b/browser/components/customizableui/test/browser_remote_tabs_button.js @@ -38,7 +38,7 @@ add_task(async function testSyncRemoteTabsButtonFunctionality() { // click the button - the panel should open. syncRemoteTabsBtn.click(); await viewShown; - ok(remoteTabsPanel.getAttribute("current"), "Sync Panel is in view"); + ok(remoteTabsPanel.getAttribute("visible"), "Sync Panel is in view"); // Find and click the "setup" button. let syncNowButton = document.getElementById("PanelUI-remotetabs-syncnow"); diff --git a/browser/components/customizableui/test/browser_synced_tabs_menu.js b/browser/components/customizableui/test/browser_synced_tabs_menu.js index 30c9eb5fb888..b8073e5892c8 100644 --- a/browser/components/customizableui/test/browser_synced_tabs_menu.js +++ b/browser/components/customizableui/test/browser_synced_tabs_menu.js @@ -86,7 +86,7 @@ async function openPrefsFromMenuPanel(expectedPanelId, entryPoint) { let viewShownPromise = BrowserTestUtils.waitForEvent(syncPanel, "ViewShown"); syncButton.click(); await Promise.all([tabsUpdatedPromise, viewShownPromise]); - ok(syncPanel.getAttribute("current"), "Sync Panel is in view"); + ok(syncPanel.getAttribute("visible"), "Sync Panel is in view"); // Sync is not configured - verify that state is reflected. let subpanel = document.getElementById(expectedPanelId); @@ -187,7 +187,7 @@ add_task(async function() { let syncButton = document.getElementById("sync-button"); syncButton.click(); await Promise.all([tabsUpdatedPromise, viewShownPromise]); - ok(syncPanel.getAttribute("current"), "Sync Panel is in view"); + ok(syncPanel.getAttribute("visible"), "Sync Panel is in view"); let subpanel = document.getElementById("PanelUI-remotetabs-main"); ok(!subpanel.hidden, "main pane is visible"); @@ -352,7 +352,7 @@ add_task(async function() { await Promise.all([tabsUpdatedPromise, viewShownPromise]); // Check pre-conditions - ok(syncPanel.getAttribute("current"), "Sync Panel is in view"); + ok(syncPanel.getAttribute("visible"), "Sync Panel is in view"); let subpanel = document.getElementById("PanelUI-remotetabs-main"); ok(!subpanel.hidden, "main pane is visible"); let deck = document.getElementById("PanelUI-remotetabs-deck"); diff --git a/browser/components/extensions/test/browser/browser-common.ini b/browser/components/extensions/test/browser/browser-common.ini index 8f7aafadba00..f64c9b553b9a 100644 --- a/browser/components/extensions/test/browser/browser-common.ini +++ b/browser/components/extensions/test/browser/browser-common.ini @@ -102,6 +102,7 @@ skip-if = (os == 'win' && ccov) # Bug 1423667 [browser_ext_menus_events.js] [browser_ext_menus_refresh.js] [browser_ext_omnibox.js] +skip-if = debug && (os == 'linux' || os == 'mac') # Bug 1417052 [browser_ext_openPanel.js] [browser_ext_optionsPage_browser_style.js] [browser_ext_optionsPage_modals.js] diff --git a/browser/components/search/test/browser.ini b/browser/components/search/test/browser.ini index 5ac23c75c5ec..c1bfca4055c4 100644 --- a/browser/components/search/test/browser.ini +++ b/browser/components/search/test/browser.ini @@ -35,6 +35,7 @@ skip-if = artifact # bug 1315953 [browser_oneOffContextMenu.js] [browser_oneOffContextMenu_setDefault.js] [browser_oneOffHeader.js] +skip-if = os == "mac" #1421238 [browser_private_search_perwindowpb.js] [browser_yahoo.js] [browser_abouthome_behavior.js] diff --git a/browser/locales/en-US/chrome/browser/browser.properties b/browser/locales/en-US/chrome/browser/browser.properties index 8fecdbbf6454..6a6f4ec5193b 100644 --- a/browser/locales/en-US/chrome/browser/browser.properties +++ b/browser/locales/en-US/chrome/browser/browser.properties @@ -941,3 +941,8 @@ midi.shareWithSite.message = Will you allow %S to access your MIDI Devices? midi.shareSysexWithFile.message = Will you allow this local file to access your MIDI devices and send/receive SysEx messages? # LOCALIZATION NOTE (midi.shareSysexWithFile.message): %S is the name of the site URL (https://...) requesting MIDI access midi.shareSysexWithSite.message = Will you allow %S to access your MIDI devices and send/receive SysEx messages? + +# LOCALIZATION NOTE (panel.back): +# This is used by screen readers to label the "back" button in various browser +# popup panels, including the sliding subviews of the main menu. +panel.back = Back diff --git a/devtools/client/shared/components/AutoCompletePopup.js b/devtools/client/shared/components/AutoCompletePopup.js index 0b2197ee135c..fe4d1a068c60 100644 --- a/devtools/client/shared/components/AutoCompletePopup.js +++ b/devtools/client/shared/components/AutoCompletePopup.js @@ -51,7 +51,7 @@ class AutocompletePopup extends Component { computeState({ autocompleteProvider, filter }) { let list = autocompleteProvider(filter); - let selectedIndex = list.length == 1 ? 0 : -1; + let selectedIndex = list.length > 0 ? 0 : -1; return { list, selectedIndex }; } diff --git a/devtools/client/shared/components/test/mochitest/test_searchbox-with-autocomplete.html b/devtools/client/shared/components/test/mochitest/test_searchbox-with-autocomplete.html index 95a896ff659b..5b6c28937776 100644 --- a/devtools/client/shared/components/test/mochitest/test_searchbox-with-autocomplete.html +++ b/devtools/client/shared/components/test/mochitest/test_searchbox-with-autocomplete.html @@ -26,15 +26,19 @@ window.onload = async function () { * compared with the reference item's value as a test * * @params {Node} - Node to be compared - * @reference {array} - Reference array for comparison + * @reference {array} - Reference array for comparison. The selected index is + * highlighted as a single element array ie. ["[abc]", "ab", "abcPQR"], + * Here the element "abc" is highlighted */ function compareAutocompleteList(list, reference) { - let items = [...list.children].map(el => el.textContent); - for (let i = 0; i < items.length; i++) { - let item = items[i]; - let ref = reference[i]; - is(item, ref, `Item ${i} in list is correct`); - } + const delimiter = " - "; + const observedList = [...list.children].map(el => { + return el.classList.contains("autocomplete-selected") + ? `[${el.textContent}]` + : el.textContent + }); + is(observedList.join(delimiter), reference.join(delimiter), + "Autocomplete items are rendered as expected"); } let React = browserRequire("devtools/client/shared/vendor/react"); @@ -96,7 +100,7 @@ window.onload = async function () { await forceRender(component); compareAutocompleteList($(".devtools-autocomplete-listbox"), [ - "ABC", + "[ABC]", "a1", "a2", "a3", @@ -105,8 +109,6 @@ window.onload = async function () { "abc", ]); - is(refs.autocomplete.state.selectedIndex, -1, "Initialised selectedIndex is -1"); - // Blur event $(".devtools-searchinput").blur(); await forceRender(component); @@ -121,35 +123,84 @@ window.onload = async function () { // ArrowDown synthesizeKey("KEY_ArrowDown"); await forceRender(component); - is(refs.autocomplete.state.selectedIndex, 0, "selectedIndex is 0"); - ok($(".devtools-autocomplete-listbox .autocomplete-item:nth-child(1)") + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "ABC", + "[a1]", + "a2", + "a3", + "a4", + "a5", + "abc", + ]); + ok($(".devtools-autocomplete-listbox .autocomplete-item:nth-child(2)") .className.includes("autocomplete-selected"), "Selection class applied"); - // ArrowUp should roll back to the bottom of the list + // A double ArrowUp should roll back to the bottom of the list + synthesizeKey("KEY_ArrowUp"); synthesizeKey("KEY_ArrowUp"); await forceRender(component); - is(refs.autocomplete.state.selectedIndex, 6, "ArrowUp works"); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "ABC", + "a1", + "a2", + "a3", + "a4", + "a5", + "[abc]", + ]); // PageDown should take -5 places up synthesizeKey("KEY_PageUp"); await forceRender(component); - is(refs.autocomplete.state.selectedIndex, 1, "PageUp works"); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "ABC", + "[a1]", + "a2", + "a3", + "a4", + "a5", + "abc", + ]); // PageDown should take +5 places down synthesizeKey("KEY_PageDown"); await forceRender(component); - is(refs.autocomplete.state.selectedIndex, 6, "PageDown works"); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "ABC", + "a1", + "a2", + "a3", + "a4", + "a5", + "[abc]", + ]); // Home should take to the top of the list synthesizeKey("KEY_Home"); await forceRender(component); - is(refs.autocomplete.state.selectedIndex, 0, "Home works"); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "[ABC]", + "a1", + "a2", + "a3", + "a4", + "a5", + "abc", + ]); // End should take to the bottom of the list synthesizeKey("KEY_End"); await forceRender(component); - is(refs.autocomplete.state.selectedIndex, 6, "End works"); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "ABC", + "a1", + "a2", + "a3", + "a4", + "a5", + "[abc]", + ]); // Key down in existing state should rollover to the top synthesizeKey("KEY_ArrowDown"); @@ -164,7 +215,10 @@ window.onload = async function () { synthesizeKey("KEY_Backspace"); await forceRender(component); ok($(".devtools-autocomplete-popup"), "Popup is up"); - compareAutocompleteList($(".devtools-autocomplete-listbox"), ["ABC", "abc"]); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "[ABC]", + "abc" + ]); // Enter key selection synthesizeKey("KEY_ArrowUp"); @@ -212,7 +266,10 @@ window.onload = async function () { // Test for string "pqr ab" which should show list of ABC, abc sendString(" ab"); await forceRender(component); - compareAutocompleteList($(".devtools-autocomplete-listbox"), ["ABC", "abc"]); + compareAutocompleteList($(".devtools-autocomplete-listbox"), [ + "[ABC]", + "abc" + ]); // Select the first element, value now should be "pqr ABC" synthesizeMouseAtCenter( diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp index 6c5a55f0baf6..7b89365f8681 100644 --- a/dom/animation/Animation.cpp +++ b/dom/animation/Animation.cpp @@ -693,8 +693,10 @@ Animation::Tick() // during the *previous* tick of the refresh driver, it can still be // ahead of the *current* timeline time when we are using the // vsync timer so we need to clamp it to the timeline time. - mPendingReadyTime.SetValue(std::min(mTimeline->GetCurrentTime().Value(), - mPendingReadyTime.Value())); + TimeDuration currentTime = mTimeline->GetCurrentTime().Value(); + if (currentTime < mPendingReadyTime.Value()) { + mPendingReadyTime.SetValue(currentTime); + } FinishPendingAt(mPendingReadyTime.Value()); mPendingReadyTime.SetNull(); } diff --git a/dom/events/test/chrome.ini b/dom/events/test/chrome.ini index 32a808a88d3a..fe4d6d33a414 100644 --- a/dom/events/test/chrome.ini +++ b/dom/events/test/chrome.ini @@ -27,3 +27,4 @@ support-files = [test_bug1412775.xul] [test_eventctors.xul] [test_DataTransferItemList.html] +skip-if = !debug && (os == "linux") #Bug 1421150 diff --git a/dom/ipc/ContentPrefs.cpp b/dom/ipc/ContentPrefs.cpp index 837be4b1a19b..996bff9eac02 100644 --- a/dom/ipc/ContentPrefs.cpp +++ b/dom/ipc/ContentPrefs.cpp @@ -129,6 +129,7 @@ const char* mozilla::dom::ContentPrefs::gEarlyPrefs[] = { "javascript.options.parallel_parsing", "javascript.options.shared_memory", "javascript.options.spectre.index_masking", + "javascript.options.spectre.object_mitigations.barriers", "javascript.options.spectre.string_mitigations", "javascript.options.spectre.value_masking", "javascript.options.streams", diff --git a/dom/media/systemservices/CamerasChild.cpp b/dom/media/systemservices/CamerasChild.cpp index 195f8338f4fb..72ef1cc49ab4 100644 --- a/dom/media/systemservices/CamerasChild.cpp +++ b/dom/media/systemservices/CamerasChild.cpp @@ -292,11 +292,10 @@ CamerasChild::NumberOfCapabilities(CaptureEngine aCapEngine, LOG((__PRETTY_FUNCTION__)); LOG(("NumberOfCapabilities for %s", deviceUniqueIdUTF8)); nsCString unique_id(deviceUniqueIdUTF8); - RefPtr self(this); nsCOMPtr runnable = - mozilla::NewNonOwningRunnableMethod( + mozilla::NewRunnableMethod( "camera::PCamerasChild::SendNumberOfCapabilities", - self, + this, &CamerasChild::SendNumberOfCapabilities, aCapEngine, unique_id); @@ -309,11 +308,10 @@ int CamerasChild::NumberOfCaptureDevices(CaptureEngine aCapEngine) { LOG((__PRETTY_FUNCTION__)); - RefPtr self(this); nsCOMPtr runnable = - mozilla::NewNonOwningRunnableMethod( + mozilla::NewRunnableMethod( "camera::PCamerasChild::SendNumberOfCaptureDevices", - self, + this, &CamerasChild::SendNumberOfCaptureDevices, aCapEngine); LockAndDispatch<> dispatcher(this, __func__, runnable, 0, mReplyInteger); @@ -337,11 +335,10 @@ int CamerasChild::EnsureInitialized(CaptureEngine aCapEngine) { LOG((__PRETTY_FUNCTION__)); - RefPtr self(this); nsCOMPtr runnable = - mozilla::NewNonOwningRunnableMethod( + mozilla::NewRunnableMethod( "camera::PCamerasChild::SendEnsureInitialized", - self, + this, &CamerasChild::SendEnsureInitialized, aCapEngine); LockAndDispatch<> dispatcher(this, __func__, runnable, 0, mReplyInteger); @@ -357,11 +354,10 @@ CamerasChild::GetCaptureCapability(CaptureEngine aCapEngine, { LOG(("GetCaptureCapability: %s %d", unique_idUTF8, capability_number)); nsCString unique_id(unique_idUTF8); - RefPtr self(this); nsCOMPtr runnable = - mozilla::NewNonOwningRunnableMethod( + mozilla::NewRunnableMethod( "camera::PCamerasChild::SendGetCaptureCapability", - self, + this, &CamerasChild::SendGetCaptureCapability, aCapEngine, unique_id, @@ -400,11 +396,10 @@ CamerasChild::GetCaptureDevice(CaptureEngine aCapEngine, bool* scary) { LOG((__PRETTY_FUNCTION__)); - RefPtr self(this); nsCOMPtr runnable = - mozilla::NewNonOwningRunnableMethod( + mozilla::NewRunnableMethod( "camera::PCamerasChild::SendGetCaptureDevice", - self, + this, &CamerasChild::SendGetCaptureDevice, aCapEngine, list_number); @@ -445,13 +440,12 @@ CamerasChild::AllocateCaptureDevice(CaptureEngine aCapEngine, { LOG((__PRETTY_FUNCTION__)); nsCString unique_id(unique_idUTF8); - RefPtr self(this); nsCOMPtr runnable = - mozilla::NewNonOwningRunnableMethod( + mozilla::NewRunnableMethod( "camera::PCamerasChild::SendAllocateCaptureDevice", - self, + this, &CamerasChild::SendAllocateCaptureDevice, aCapEngine, unique_id, @@ -482,11 +476,10 @@ CamerasChild::ReleaseCaptureDevice(CaptureEngine aCapEngine, const int capture_id) { LOG((__PRETTY_FUNCTION__)); - RefPtr self(this); nsCOMPtr runnable = - mozilla::NewNonOwningRunnableMethod( + mozilla::NewRunnableMethod( "camera::PCamerasChild::SendReleaseCaptureDevice", - self, + this, &CamerasChild::SendReleaseCaptureDevice, aCapEngine, capture_id); @@ -534,11 +527,10 @@ CamerasChild::StartCapture(CaptureEngine aCapEngine, webrtcCaps.rawType, webrtcCaps.codecType, webrtcCaps.interlaced); - RefPtr self(this); nsCOMPtr runnable = mozilla:: - NewNonOwningRunnableMethod( + NewRunnableMethod( "camera::PCamerasChild::SendStartCapture", - self, + this, &CamerasChild::SendStartCapture, aCapEngine, capture_id, @@ -551,11 +543,10 @@ int CamerasChild::StopCapture(CaptureEngine aCapEngine, const int capture_id) { LOG((__PRETTY_FUNCTION__)); - RefPtr self(this); nsCOMPtr runnable = - mozilla::NewNonOwningRunnableMethod( + mozilla::NewRunnableMethod( "camera::PCamerasChild::SendStopCapture", - self, + this, &CamerasChild::SendStopCapture, aCapEngine, capture_id); @@ -624,9 +615,8 @@ CamerasChild::ShutdownParent() // Delete the parent actor. // CamerasChild (this) will remain alive and is only deleted by the // IPC layer when SendAllDone returns. - RefPtr self(this); - nsCOMPtr deleteRunnable = mozilla::NewNonOwningRunnableMethod( - "camera::PCamerasChild::SendAllDone", self, &CamerasChild::SendAllDone); + nsCOMPtr deleteRunnable = mozilla::NewRunnableMethod( + "camera::PCamerasChild::SendAllDone", this, &CamerasChild::SendAllDone); CamerasSingleton::Thread()->Dispatch(deleteRunnable, NS_DISPATCH_NORMAL); } else { LOG(("ShutdownParent called without PBackground thread")); diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index 440849377807..28a8938fc23c 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -862,7 +862,7 @@ ModuleObject::functionDeclarations() void ModuleObject::init(HandleScript script) { - initReservedSlot(ScriptSlot, PrivateValue(script)); + initReservedSlot(ScriptSlot, PrivateGCThingValue(script)); initReservedSlot(StatusSlot, Int32Value(MODULE_STATUS_UNINSTANTIATED)); } @@ -973,7 +973,7 @@ ModuleObject::hasScript() const JSScript* ModuleObject::script() const { - return static_cast(getReservedSlot(ScriptSlot).toPrivate()); + return getReservedSlot(ScriptSlot).toGCThing()->as(); } static inline void @@ -1026,11 +1026,6 @@ ModuleObject::enclosingScope() const ModuleObject::trace(JSTracer* trc, JSObject* obj) { ModuleObject& module = obj->as(); - if (module.hasScript()) { - JSScript* script = module.script(); - TraceManuallyBarrieredEdge(trc, &script, "Module script"); - module.setReservedSlot(ScriptSlot, PrivateValue(script)); - } if (module.hasImportBindings()) module.importBindings().trace(trc); diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp index cb0ac5711286..75e18aaf49fa 100644 --- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -903,9 +903,8 @@ IsTrailSurrogateWithLeadSurrogate(HandleLinearString input, int32_t index) * steps 3, 9-14, except 12.a.i, 12.c.i.1. */ static RegExpRunStatus -ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string, - int32_t lastIndex, - MatchPairs* matches, size_t* endIndex, RegExpStaticsUpdate staticsUpdate) +ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string, int32_t lastIndex, + MatchPairs* matches, size_t* endIndex) { /* * WARNING: Despite the presence of spec step comment numbers, this @@ -920,14 +919,9 @@ ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string, if (!re) return RegExpRunStatus_Error; - RegExpStatics* res; - if (staticsUpdate == UpdateRegExpStatics) { - res = GlobalObject::getRegExpStatics(cx, cx->global()); - if (!res) - return RegExpRunStatus_Error; - } else { - res = nullptr; - } + RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global()); + if (!res) + return RegExpRunStatus_Error; RootedLinearString input(cx, string->ensureLinear(cx)); if (!input) @@ -981,15 +975,14 @@ ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string, * steps 3, 9-25, except 12.a.i, 12.c.i.1, 15. */ static bool -RegExpMatcherImpl(JSContext* cx, HandleObject regexp, HandleString string, - int32_t lastIndex, RegExpStaticsUpdate staticsUpdate, MutableHandleValue rval) +RegExpMatcherImpl(JSContext* cx, HandleObject regexp, HandleString string, int32_t lastIndex, + MutableHandleValue rval) { /* Execute regular expression and gather matches. */ ScopedMatchPairs matches(&cx->tempLifoAlloc()); /* Steps 3, 9-14, except 12.a.i, 12.c.i.1. */ - RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, - &matches, nullptr, staticsUpdate); + RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches, nullptr); if (status == RegExpRunStatus_Error) return false; @@ -1023,8 +1016,7 @@ js::RegExpMatcher(JSContext* cx, unsigned argc, Value* vp) MOZ_ALWAYS_TRUE(ToInt32(cx, args[2], &lastIndex)); /* Steps 3, 9-25, except 12.a.i, 12.c.i.1, 15. */ - return RegExpMatcherImpl(cx, regexp, string, lastIndex, - UpdateRegExpStatics, args.rval()); + return RegExpMatcherImpl(cx, regexp, string, lastIndex, args.rval()); } /* @@ -1042,8 +1034,7 @@ js::RegExpMatcherRaw(JSContext* cx, HandleObject regexp, HandleString input, // successful only if the pairs have actually been filled in. if (maybeMatches && maybeMatches->pairsRaw()[0] >= 0) return CreateRegExpMatchResult(cx, input, *maybeMatches, output); - return RegExpMatcherImpl(cx, regexp, input, lastIndex, - UpdateRegExpStatics, output); + return RegExpMatcherImpl(cx, regexp, input, lastIndex, output); } /* @@ -1053,15 +1044,14 @@ js::RegExpMatcherRaw(JSContext* cx, HandleObject regexp, HandleString input, * changes to this code need to get reflected in there too. */ static bool -RegExpSearcherImpl(JSContext* cx, HandleObject regexp, HandleString string, - int32_t lastIndex, RegExpStaticsUpdate staticsUpdate, int32_t* result) +RegExpSearcherImpl(JSContext* cx, HandleObject regexp, HandleString string, int32_t lastIndex, + int32_t* result) { /* Execute regular expression and gather matches. */ ScopedMatchPairs matches(&cx->tempLifoAlloc()); /* Steps 3, 9-14, except 12.a.i, 12.c.i.1. */ - RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, - &matches, nullptr, staticsUpdate); + RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches, nullptr); if (status == RegExpRunStatus_Error) return false; @@ -1097,7 +1087,7 @@ js::RegExpSearcher(JSContext* cx, unsigned argc, Value* vp) /* Steps 3, 9-25, except 12.a.i, 12.c.i.1, 15. */ int32_t result = 0; - if (!RegExpSearcherImpl(cx, regexp, string, lastIndex, UpdateRegExpStatics, &result)) + if (!RegExpSearcherImpl(cx, regexp, string, lastIndex, &result)) return false; args.rval().setInt32(result); @@ -1120,23 +1110,7 @@ js::RegExpSearcherRaw(JSContext* cx, HandleObject regexp, HandleString input, *result = CreateRegExpSearchResult(*maybeMatches); return true; } - return RegExpSearcherImpl(cx, regexp, input, lastIndex, - UpdateRegExpStatics, result); -} - -bool -js::regexp_exec_no_statics(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - MOZ_ASSERT(args.length() == 2); - MOZ_ASSERT(IsRegExpObject(args[0])); - MOZ_ASSERT(args[1].isString()); - - RootedObject regexp(cx, &args[0].toObject()); - RootedString string(cx, args[1].toString()); - - return RegExpMatcherImpl(cx, regexp, string, 0, - DontUpdateRegExpStatics, args.rval()); + return RegExpSearcherImpl(cx, regexp, input, lastIndex, result); } /* @@ -1160,8 +1134,7 @@ js::RegExpTester(JSContext* cx, unsigned argc, Value* vp) /* Steps 3, 9-14, except 12.a.i, 12.c.i.1. */ size_t endIndex = 0; - RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, - nullptr, &endIndex, UpdateRegExpStatics); + RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, nullptr, &endIndex); if (status == RegExpRunStatus_Error) return false; @@ -1186,8 +1159,7 @@ js::RegExpTesterRaw(JSContext* cx, HandleObject regexp, HandleString input, MOZ_ASSERT(lastIndex >= 0); size_t endIndexTmp = 0; - RegExpRunStatus status = ExecuteRegExp(cx, regexp, input, lastIndex, - nullptr, &endIndexTmp, UpdateRegExpStatics); + RegExpRunStatus status = ExecuteRegExp(cx, regexp, input, lastIndex, nullptr, &endIndexTmp); if (status == RegExpRunStatus_Success) { MOZ_ASSERT(endIndexTmp <= INT32_MAX); @@ -1202,24 +1174,6 @@ js::RegExpTesterRaw(JSContext* cx, HandleObject regexp, HandleString input, return false; } -bool -js::regexp_test_no_statics(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - MOZ_ASSERT(args.length() == 2); - MOZ_ASSERT(IsRegExpObject(args[0])); - MOZ_ASSERT(args[1].isString()); - - RootedObject regexp(cx, &args[0].toObject()); - RootedString string(cx, args[1].toString()); - - size_t ignored = 0; - RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, 0, - nullptr, &ignored, DontUpdateRegExpStatics); - args.rval().setBoolean(status == RegExpRunStatus_Success); - return status != RegExpRunStatus_Error; -} - using CapturesVector = GCVector; struct JSSubString diff --git a/js/src/builtin/RegExp.h b/js/src/builtin/RegExp.h index d522cc1af319..72c0fbc69abf 100644 --- a/js/src/builtin/RegExp.h +++ b/js/src/builtin/RegExp.h @@ -19,10 +19,6 @@ namespace js { JSObject* InitRegExpClass(JSContext* cx, HandleObject obj); -// Whether RegExp statics should be updated with the input and results of a -// regular expression execution. -enum RegExpStaticsUpdate { UpdateRegExpStatics, DontUpdateRegExpStatics }; - /* * Legacy behavior of ExecuteRegExp(), which is baked into the JSAPI. * @@ -71,22 +67,6 @@ intrinsic_GetStringDataProperty(JSContext* cx, unsigned argc, Value* vp); * The following functions are for use by self-hosted code. */ -/* - * Behaves like regexp.exec(string), but doesn't set RegExp statics. - * - * Usage: match = regexp_exec_no_statics(regexp, string) - */ -extern MOZ_MUST_USE bool -regexp_exec_no_statics(JSContext* cx, unsigned argc, Value* vp); - -/* - * Behaves like regexp.test(string), but doesn't set RegExp statics. - * - * Usage: does_match = regexp_test_no_statics(regexp, string) - */ -extern MOZ_MUST_USE bool -regexp_test_no_statics(JSContext* cx, unsigned argc, Value* vp); - /* * Behaves like RegExp(source, flags). * |source| must be a valid regular expression pattern, |flags| is a raw diff --git a/js/src/builtin/intl/CommonFunctions.js b/js/src/builtin/intl/CommonFunctions.js index b38da600a899..8fd631e7ff70 100644 --- a/js/src/builtin/intl/CommonFunctions.js +++ b/js/src/builtin/intl/CommonFunctions.js @@ -5,16 +5,7 @@ /* Portions Copyright Norbert Lindenberg 2011-2012. */ /** - * Holder object for encapsulating regexp instances. - * - * Regular expression instances should be created after the initialization of - * self-hosted global. - */ -var internalIntlRegExps = std_Object_create(null); -internalIntlRegExps.unicodeLocaleExtensionSequenceRE = null; - -/** - * Regular expression matching a "Unicode locale extension sequence", which the + * Returns the start index of a "Unicode locale extension sequence", which the * specification defines as: "any substring of a language tag that starts with * a separator '-' and the singleton 'u' and includes the maximum sequence of * following non-singleton subtags and their preceding '-' separators." @@ -25,50 +16,110 @@ internalIntlRegExps.unicodeLocaleExtensionSequenceRE = null; * * Spec: ECMAScript Internationalization API Specification, 6.2.1. */ -function getUnicodeLocaleExtensionSequenceRE() { - return internalIntlRegExps.unicodeLocaleExtensionSequenceRE || - (internalIntlRegExps.unicodeLocaleExtensionSequenceRE = - RegExpCreate("-u(?:-[a-z0-9]{2,8})+")); +function startOfUnicodeExtensions(locale) { + assert(typeof locale === "string", "locale is a string"); + assert(IsStructurallyValidLanguageTag(locale), "locale is a language tag"); + assert(CanonicalizeLanguageTag(locale) === locale, "locale is a canonicalized language tag"); + + #define HYPHEN 0x2D + assert(std_String_fromCharCode(HYPHEN) === "-", + "code unit constant should match the expected character"); + + // A wholly-privateuse or grandfathered locale has no extension sequences. + if (callFunction(std_String_charCodeAt, locale, 1) === HYPHEN) { + assert(locale[0] === "x" || locale[0] === "i", + "locale[1] === '-' implies a privateuse-only or grandfathered locale"); + return -1; + } + + #undef HYPHEN + + // Search for "-u-" marking the start of a Unicode extension sequence. + var start = callFunction(std_String_indexOf, locale, "-u-"); + if (start < 0) + return -1; + + // And search for "-x-" marking the start of any privateuse component to + // handle the case when "-u-" was only found within a privateuse subtag. + var privateExt = callFunction(std_String_indexOf, locale, "-x-"); + if (privateExt >= 0 && privateExt < start) + return -1; + + return start; +} + +/** + * Returns the end index of a Unicode locale extension sequence. + */ +function endOfUnicodeExtensions(locale, start) { + assert(typeof locale === "string", "locale is a string"); + assert(IsStructurallyValidLanguageTag(locale), "locale is a language tag"); + assert(CanonicalizeLanguageTag(locale) === locale, "locale is a canonicalized language tag"); + assert(0 <= start && start < locale.length, "start is an index into locale"); + assert(Substring(locale, start, 3) === "-u-", "start points to Unicode extension sequence"); + + #define HYPHEN 0x2D + assert(std_String_fromCharCode(HYPHEN) === "-", + "code unit constant should match the expected character"); + + // Search for the start of the next singleton or privateuse subtag. + // + // Begin searching after the smallest possible Unicode locale extension + // sequence, namely |"-u-" 2alphanum|. End searching once the remaining + // characters can't fit the smallest possible singleton or privateuse + // subtag, namely |"-x-" alphanum|. Note the reduced end-limit means + // indexing inside the loop is always in-range. + for (var i = start + 5, end = locale.length - 4; i <= end; i++) { + if (callFunction(std_String_charCodeAt, locale, i) !== HYPHEN) + continue; + if (callFunction(std_String_charCodeAt, locale, i + 2) === HYPHEN) + return i; + + // Skip over (i + 1) and (i + 2) because we've just verified they + // aren't "-", so the next possible delimiter can only be at (i + 3). + i += 2; + } + + #undef HYPHEN + + // If no singleton or privateuse subtag was found, the Unicode extension + // sequence extends until the end of the string. + return locale.length; } /** * Removes Unicode locale extension sequences from the given language tag. */ function removeUnicodeExtensions(locale) { - // A wholly-privateuse locale has no extension sequences. - if (callFunction(std_String_startsWith, locale, "x-")) + var start = startOfUnicodeExtensions(locale); + if (start < 0) return locale; - // Otherwise, split on "-x-" marking the start of any privateuse component. - // Replace Unicode locale extension sequences in the left half, and return - // the concatenation. - var pos = callFunction(std_String_indexOf, locale, "-x-"); - if (pos < 0) - pos = locale.length; - - var left = callFunction(String_substring, locale, 0, pos); - var right = callFunction(String_substring, locale, pos); - - var unicodeLocaleExtensionSequenceRE = getUnicodeLocaleExtensionSequenceRE(); - var extensions = regexp_exec_no_statics(unicodeLocaleExtensionSequenceRE, left); - if (extensions !== null) { - left = callFunction(String_substring, left, 0, extensions.index) + - callFunction(String_substring, left, extensions.index + extensions[0].length); - } + var end = endOfUnicodeExtensions(locale, start); + var left = Substring(locale, 0, start); + var right = Substring(locale, end, locale.length - end); var combined = left + right; - assert(IsStructurallyValidLanguageTag(combined), "recombination produced an invalid language tag"); - assert(function() { - var uindex = callFunction(std_String_indexOf, combined, "-u-"); - if (uindex < 0) - return true; - var xindex = callFunction(std_String_indexOf, combined, "-x-"); - return xindex > 0 && xindex < uindex; - }(), "recombination failed to remove all Unicode locale extension sequences"); + + assert(IsStructurallyValidLanguageTag(combined), + "recombination produced an invalid language tag"); + assert(startOfUnicodeExtensions(combined) < 0, + "recombination failed to remove all Unicode locale extension sequences"); return combined; } +/** + * Returns Unicode locale extension sequences from the given language tag. + */ +function getUnicodeExtensions(locale) { + var start = startOfUnicodeExtensions(locale); + assert(start >= 0, "start of Unicode extension sequence not found"); + var end = endOfUnicodeExtensions(locale, start); + + return Substring(locale, start, end - start); +} + /* eslint-disable complexity */ /** * Parser for BCP 47 language tags. @@ -702,23 +753,6 @@ function ValidateAndCanonicalizeLanguageTag(locale) { return CanonicalizeLanguageTagFromObject(localeObj); } -function localeContainsNoUnicodeExtensions(locale) { - // No "-u-", no possible Unicode extension. - if (callFunction(std_String_indexOf, locale, "-u-") === -1) - return true; - - // "-u-" within privateuse also isn't one. - if (callFunction(std_String_indexOf, locale, "-u-") > callFunction(std_String_indexOf, locale, "-x-")) - return true; - - // An entirely-privateuse tag doesn't contain extensions. - if (callFunction(std_String_startsWith, locale, "x-")) - return true; - - // Otherwise, we have a Unicode extension sequence. - return false; -} - // The last-ditch locale is used if none of the available locales satisfies a // request. "en-GB" is used based on the assumptions that English is the most // common second language, that both en-GB and en-US are normally available in @@ -785,7 +819,7 @@ function DefaultLocaleIgnoringAvailableLocales() { assert(IsStructurallyValidLanguageTag(candidate), "the candidate must be structurally valid"); - assert(localeContainsNoUnicodeExtensions(candidate), + assert(startOfUnicodeExtensions(candidate) < 0, "the candidate must not contain a Unicode extension sequence"); return candidate; @@ -825,7 +859,7 @@ function DefaultLocale() { "the computed default locale must be structurally valid"); assert(locale === CanonicalizeLanguageTag(locale), "the computed default locale must be canonical"); - assert(localeContainsNoUnicodeExtensions(locale), + assert(startOfUnicodeExtensions(locale) < 0, "the computed default locale must not contain a Unicode extension sequence"); localeCache.defaultLocale = locale; @@ -917,7 +951,7 @@ function CanonicalizeLocaleList(locales) { function BestAvailableLocaleHelper(availableLocales, locale, considerDefaultLocale) { assert(IsStructurallyValidLanguageTag(locale), "invalid BestAvailableLocale locale structure"); assert(locale === CanonicalizeLanguageTag(locale), "non-canonical BestAvailableLocale locale"); - assert(localeContainsNoUnicodeExtensions(locale), "locale must contain no Unicode extensions"); + assert(startOfUnicodeExtensions(locale) < 0, "locale must contain no Unicode extensions"); // In the spec, [[availableLocales]] is formally a list of all available // locales. But in our implementation, it's an *incomplete* list, not @@ -1009,12 +1043,8 @@ function LookupMatcher(availableLocales, requestedLocales) { result.locale = availableLocale; // Step 2.c.ii. - if (locale !== noExtensionsLocale) { - var unicodeLocaleExtensionSequenceRE = getUnicodeLocaleExtensionSequenceRE(); - var extensionMatch = regexp_exec_no_statics(unicodeLocaleExtensionSequenceRE, - locale); - result.extension = extensionMatch[0]; - } + if (locale !== noExtensionsLocale) + result.extension = getUnicodeExtensions(locale); // Step 2.c.iii. return result; @@ -1049,11 +1079,9 @@ function BestFitMatcher(availableLocales, requestedLocales) { */ function UnicodeExtensionValue(extension, key) { assert(typeof extension === "string", "extension is a string value"); - assert(function() { - var unicodeLocaleExtensionSequenceRE = getUnicodeLocaleExtensionSequenceRE(); - var extensionMatch = regexp_exec_no_statics(unicodeLocaleExtensionSequenceRE, extension); - return extensionMatch !== null && extensionMatch[0] === extension; - }(), "extension is a Unicode extension subtag"); + assert(callFunction(std_String_startsWith, extension, "-u-") && + getUnicodeExtensions("und" + extension) === extension, + "extension is a Unicode extension subtag"); assert(typeof key === "string", "key is a string value"); // Step 1. diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index e516a9a77722..d31be65d6c7c 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -14,6 +14,7 @@ #include "mozilla/EnumeratedRange.h" #include "mozilla/MathAlgorithms.h" #include "mozilla/ScopeExit.h" +#include "mozilla/Unused.h" #include @@ -442,22 +443,25 @@ CodeGenerator::visitValueToDouble(LValueToDouble* lir) ValueOperand operand = ToValue(lir, LValueToDouble::Input); FloatRegister output = ToFloatRegister(lir->output()); - Register tag = masm.splitTagForTest(operand); - Label isDouble, isInt32, isBool, isNull, isUndefined, done; bool hasBoolean = false, hasNull = false, hasUndefined = false; - masm.branchTestDouble(Assembler::Equal, tag, &isDouble); - masm.branchTestInt32(Assembler::Equal, tag, &isInt32); + { + ScratchTagScope tag(masm, operand); + masm.splitTagForTest(operand, tag); - if (mir->conversion() != MToFPInstruction::NumbersOnly) { - masm.branchTestBoolean(Assembler::Equal, tag, &isBool); - masm.branchTestUndefined(Assembler::Equal, tag, &isUndefined); - hasBoolean = true; - hasUndefined = true; - if (mir->conversion() != MToFPInstruction::NonNullNonStringPrimitives) { - masm.branchTestNull(Assembler::Equal, tag, &isNull); - hasNull = true; + masm.branchTestDouble(Assembler::Equal, tag, &isDouble); + masm.branchTestInt32(Assembler::Equal, tag, &isInt32); + + if (mir->conversion() != MToFPInstruction::NumbersOnly) { + masm.branchTestBoolean(Assembler::Equal, tag, &isBool); + masm.branchTestUndefined(Assembler::Equal, tag, &isUndefined); + hasBoolean = true; + hasUndefined = true; + if (mir->conversion() != MToFPInstruction::NonNullNonStringPrimitives) { + masm.branchTestNull(Assembler::Equal, tag, &isNull); + hasNull = true; + } } } @@ -497,22 +501,25 @@ CodeGenerator::visitValueToFloat32(LValueToFloat32* lir) ValueOperand operand = ToValue(lir, LValueToFloat32::Input); FloatRegister output = ToFloatRegister(lir->output()); - Register tag = masm.splitTagForTest(operand); - Label isDouble, isInt32, isBool, isNull, isUndefined, done; bool hasBoolean = false, hasNull = false, hasUndefined = false; - masm.branchTestDouble(Assembler::Equal, tag, &isDouble); - masm.branchTestInt32(Assembler::Equal, tag, &isInt32); + { + ScratchTagScope tag(masm, operand); + masm.splitTagForTest(operand, tag); - if (mir->conversion() != MToFPInstruction::NumbersOnly) { - masm.branchTestBoolean(Assembler::Equal, tag, &isBool); - masm.branchTestUndefined(Assembler::Equal, tag, &isUndefined); - hasBoolean = true; - hasUndefined = true; - if (mir->conversion() != MToFPInstruction::NonNullNonStringPrimitives) { - masm.branchTestNull(Assembler::Equal, tag, &isNull); - hasNull = true; + masm.branchTestDouble(Assembler::Equal, tag, &isDouble); + masm.branchTestInt32(Assembler::Equal, tag, &isInt32); + + if (mir->conversion() != MToFPInstruction::NumbersOnly) { + masm.branchTestBoolean(Assembler::Equal, tag, &isBool); + masm.branchTestUndefined(Assembler::Equal, tag, &isUndefined); + hasBoolean = true; + hasUndefined = true; + if (mir->conversion() != MToFPInstruction::NonNullNonStringPrimitives) { + masm.branchTestNull(Assembler::Equal, tag, &isNull); + hasNull = true; + } } } @@ -751,7 +758,8 @@ CodeGenerator::testValueTruthyKernel(const ValueOperand& value, return; } - Register tag = masm.splitTagForTest(value); + ScratchTagScope tag(masm, value); + masm.splitTagForTest(value, tag); if (mightBeUndefined) { MOZ_ASSERT(tagCount > 1); @@ -770,7 +778,10 @@ CodeGenerator::testValueTruthyKernel(const ValueOperand& value, Label notBoolean; if (tagCount != 1) masm.branchTestBoolean(Assembler::NotEqual, tag, ¬Boolean); - masm.branchTestBooleanTruthy(false, value, ifFalsy); + { + ScratchTagScopeRelease _(&tag); + masm.branchTestBooleanTruthy(false, value, ifFalsy); + } if (tagCount != 1) masm.jump(ifTruthy); // Else just fall through to truthiness. @@ -783,7 +794,10 @@ CodeGenerator::testValueTruthyKernel(const ValueOperand& value, Label notInt32; if (tagCount != 1) masm.branchTestInt32(Assembler::NotEqual, tag, ¬Int32); - masm.branchTestInt32Truthy(false, value, ifFalsy); + { + ScratchTagScopeRelease _(&tag); + masm.branchTestInt32Truthy(false, value, ifFalsy); + } if (tagCount != 1) masm.jump(ifTruthy); // Else just fall through to truthiness. @@ -799,8 +813,11 @@ CodeGenerator::testValueTruthyKernel(const ValueOperand& value, if (tagCount != 1) masm.branchTestObject(Assembler::NotEqual, tag, ¬Object); - Register objreg = masm.extractObject(value, ToRegister(scratch1)); - testObjectEmulatesUndefined(objreg, ifFalsy, ifTruthy, ToRegister(scratch2), ool); + { + ScratchTagScopeRelease _(&tag); + Register objreg = masm.extractObject(value, ToRegister(scratch1)); + testObjectEmulatesUndefined(objreg, ifFalsy, ifTruthy, ToRegister(scratch2), ool); + } masm.bind(¬Object); } else { @@ -822,7 +839,10 @@ CodeGenerator::testValueTruthyKernel(const ValueOperand& value, Label notString; if (tagCount != 1) masm.branchTestString(Assembler::NotEqual, tag, ¬String); - masm.branchTestStringTruthy(false, value, ifFalsy); + { + ScratchTagScopeRelease _(&tag); + masm.branchTestStringTruthy(false, value, ifFalsy); + } if (tagCount != 1) masm.jump(ifTruthy); // Else just fall through to truthiness. @@ -842,8 +862,11 @@ CodeGenerator::testValueTruthyKernel(const ValueOperand& value, if (mightBeDouble) { MOZ_ASSERT(tagCount == 1); // If we reach here the value is a double. - masm.unboxDouble(value, fr); - masm.branchTestDoubleTruthy(false, fr, ifFalsy); + { + ScratchTagScopeRelease _(&tag); + masm.unboxDouble(value, fr); + masm.branchTestDoubleTruthy(false, fr, ifFalsy); + } --tagCount; } @@ -1095,7 +1118,7 @@ CodeGenerator::visitValueToString(LValueToString* lir) StoreRegisterTo(output)); Label done; - Register tag = masm.splitTagForTest(input); + Register tag = masm.extractTag(input, output); const JSAtomState& names = gen->runtime->names(); // String @@ -2148,7 +2171,7 @@ CodeGenerator::visitRegExpMatcher(LRegExpMatcher* lir) MOZ_ASSERT(ToRegister(lir->regexp()) == RegExpMatcherRegExpReg); MOZ_ASSERT(ToRegister(lir->string()) == RegExpMatcherStringReg); MOZ_ASSERT(ToRegister(lir->lastIndex()) == RegExpMatcherLastIndexReg); - MOZ_ASSERT(GetValueOutput(lir) == JSReturnOperand); + MOZ_ASSERT(ToOutValue(lir) == JSReturnOperand); #if defined(JS_NUNBOX32) MOZ_ASSERT(RegExpMatcherRegExpReg != JSReturnReg_Type); @@ -3518,7 +3541,7 @@ void CodeGenerator::visitGetPropertyPolymorphicV(LGetPropertyPolymorphicV* ins) { Register obj = ToRegister(ins->obj()); - ValueOperand output = GetValueOutput(ins); + ValueOperand output = ToOutValue(ins); emitGetPropertyPolymorphic(ins, obj, output.scratchReg(), output); } @@ -3835,9 +3858,13 @@ CodeGenerator::visitTypeBarrierV(LTypeBarrierV* lir) Register unboxScratch = ToTempRegisterOrInvalid(lir->unboxTemp()); Register objScratch = ToTempRegisterOrInvalid(lir->objTemp()); + // guardObjectType may zero the payload/Value register on speculative paths + // (we should have a defineReuseInput allocation in this case). + Register spectreRegToZero = operand.payloadOrValueReg(); + Label miss; masm.guardTypeSet(operand, lir->mir()->resultTypeSet(), lir->mir()->barrierKind(), - unboxScratch, objScratch, &miss); + unboxScratch, objScratch, spectreRegToZero, &miss); bailoutFrom(&miss, lir->snapshot()); } @@ -3859,26 +3886,16 @@ CodeGenerator::visitTypeBarrierO(LTypeBarrierO* lir) if (lir->mir()->barrierKind() != BarrierKind::TypeTagOnly) { masm.comment("Type tag only"); - masm.guardObjectType(obj, lir->mir()->resultTypeSet(), scratch, &miss); + // guardObjectType may zero the object register on speculative paths + // (we should have a defineReuseInput allocation in this case). + Register spectreRegToZero = obj; + masm.guardObjectType(obj, lir->mir()->resultTypeSet(), scratch, spectreRegToZero, &miss); } bailoutFrom(&miss, lir->snapshot()); masm.bind(&ok); } -void -CodeGenerator::visitMonitorTypes(LMonitorTypes* lir) -{ - ValueOperand operand = ToValue(lir, LMonitorTypes::Input); - Register unboxScratch = ToTempRegisterOrInvalid(lir->unboxTemp()); - Register objScratch = ToTempRegisterOrInvalid(lir->objTemp()); - - Label matched, miss; - masm.guardTypeSet(operand, lir->mir()->typeSet(), lir->mir()->barrierKind(), unboxScratch, - objScratch, &miss); - bailoutFrom(&miss, lir->snapshot()); -} - // Out-of-line path to update the store buffer. class OutOfLineCallPostWriteBarrier : public OutOfLineCodeBase { @@ -5103,13 +5120,26 @@ CodeGenerator::generateArgumentsChecks(bool assert) if (!types || types->unknown()) continue; +#ifndef JS_CODEGEN_ARM64 // Calculate the offset on the stack of the argument. // (i - info.startArgSlot()) - Compute index of arg within arg vector. // ... * sizeof(Value) - Scale by value size. // ArgToStackOffset(...) - Compute displacement within arg vector. int32_t offset = ArgToStackOffset((i - info.startArgSlot()) * sizeof(Value)); Address argAddr(masm.getStackPointer(), offset); - masm.guardTypeSet(argAddr, types, BarrierKind::TypeSet, temp1, temp2, &miss); + + // guardObjectType will zero the stack pointer register on speculative + // paths. + Register spectreRegToZero = masm.getStackPointer(); + masm.guardTypeSet(argAddr, types, BarrierKind::TypeSet, temp1, temp2, + spectreRegToZero, &miss); +#else + // On ARM64, the stack pointer situation is more complicated. When we + // enable Ion, we should figure out how to mitigate Spectre there. + mozilla::Unused << temp1; + mozilla::Unused << temp2; + MOZ_CRASH("NYI"); +#endif } if (miss.used()) { @@ -5409,7 +5439,7 @@ CodeGenerator::emitAssertObjectOrStringResult(Register input, MIRType type, cons if (type == MIRType::ObjectOrNull) masm.branchPtr(Assembler::Equal, input, ImmWord(0), &ok); if (typeset->getObjectCount() > 0) - masm.guardObjectType(input, typeset, temp, &miss); + masm.guardObjectType(input, typeset, temp, input, &miss); else masm.jump(&miss); masm.jump(&ok); @@ -5475,7 +5505,8 @@ CodeGenerator::emitAssertResultV(const ValueOperand input, const TemporaryTypeSe if (typeset && !typeset->unknown()) { // We have a result TypeSet, assert this value is in it. Label miss, ok; - masm.guardTypeSet(input, typeset, BarrierKind::TypeSet, temp1, temp2, &miss); + masm.guardTypeSet(input, typeset, BarrierKind::TypeSet, temp1, temp2, + input.payloadOrValueReg(), &miss); masm.jump(&ok); masm.bind(&miss); @@ -5521,8 +5552,10 @@ CodeGenerator::emitObjectOrStringResultChecks(LInstruction* lir, MDefinition* mi return; MOZ_ASSERT(lir->numDefs() == 1); - Register output = ToRegister(lir->getDef(0)); + if (lir->getDef(0)->isBogusTemp()) + return; + Register output = ToRegister(lir->getDef(0)); emitAssertObjectOrStringResult(output, mir->type(), mir->resultTypeSet()); } @@ -7576,22 +7609,28 @@ CodeGenerator::visitIsNullOrLikeUndefinedV(LIsNullOrLikeUndefinedV* lir) notNullOrLikeUndefined = label2.ptr(); } - Register tag = masm.splitTagForTest(value); - MDefinition* input = lir->mir()->lhs(); - if (input->mightBeType(MIRType::Null)) - masm.branchTestNull(Assembler::Equal, tag, nullOrLikeUndefined); - if (input->mightBeType(MIRType::Undefined)) - masm.branchTestUndefined(Assembler::Equal, tag, nullOrLikeUndefined); + { + ScratchTagScope tag(masm, value); + masm.splitTagForTest(value, tag); - if (ool) { - // Check whether it's a truthy object or a falsy object that emulates - // undefined. - masm.branchTestObject(Assembler::NotEqual, tag, notNullOrLikeUndefined); + MDefinition* input = lir->mir()->lhs(); + if (input->mightBeType(MIRType::Null)) + masm.branchTestNull(Assembler::Equal, tag, nullOrLikeUndefined); + if (input->mightBeType(MIRType::Undefined)) + masm.branchTestUndefined(Assembler::Equal, tag, nullOrLikeUndefined); - Register objreg = masm.extractObject(value, ToTempUnboxRegister(lir->tempToUnbox())); - branchTestObjectEmulatesUndefined(objreg, nullOrLikeUndefined, notNullOrLikeUndefined, - ToRegister(lir->temp()), ool); - // fall through + if (ool) { + // Check whether it's a truthy object or a falsy object that emulates + // undefined. + masm.branchTestObject(Assembler::NotEqual, tag, notNullOrLikeUndefined); + + ScratchTagScopeRelease _(&tag); + + Register objreg = masm.extractObject(value, ToTempUnboxRegister(lir->tempToUnbox())); + branchTestObjectEmulatesUndefined(objreg, nullOrLikeUndefined, notNullOrLikeUndefined, + ToRegister(lir->temp()), ool); + // fall through + } } Label done; @@ -7652,28 +7691,33 @@ CodeGenerator::visitIsNullOrLikeUndefinedAndBranchV(LIsNullOrLikeUndefinedAndBra addOutOfLineCode(ool, lir->cmpMir()); } - Register tag = masm.splitTagForTest(value); + { + ScratchTagScope tag(masm, value); + masm.splitTagForTest(value, tag); - Label* ifTrueLabel = getJumpLabelForBranch(ifTrue); - Label* ifFalseLabel = getJumpLabelForBranch(ifFalse); + Label* ifTrueLabel = getJumpLabelForBranch(ifTrue); + Label* ifFalseLabel = getJumpLabelForBranch(ifFalse); - MDefinition* input = lir->cmpMir()->lhs(); - if (input->mightBeType(MIRType::Null)) - masm.branchTestNull(Assembler::Equal, tag, ifTrueLabel); - if (input->mightBeType(MIRType::Undefined)) - masm.branchTestUndefined(Assembler::Equal, tag, ifTrueLabel); + MDefinition* input = lir->cmpMir()->lhs(); + if (input->mightBeType(MIRType::Null)) + masm.branchTestNull(Assembler::Equal, tag, ifTrueLabel); + if (input->mightBeType(MIRType::Undefined)) + masm.branchTestUndefined(Assembler::Equal, tag, ifTrueLabel); - if (ool) { - masm.branchTestObject(Assembler::NotEqual, tag, ifFalseLabel); + if (ool) { + masm.branchTestObject(Assembler::NotEqual, tag, ifFalseLabel); - // Objects that emulate undefined are loosely equal to null/undefined. - Register objreg = masm.extractObject(value, ToTempUnboxRegister(lir->tempToUnbox())); - Register scratch = ToRegister(lir->temp()); - testObjectEmulatesUndefined(objreg, ifTrueLabel, ifFalseLabel, scratch, ool); - } else { - masm.jump(ifFalseLabel); + ScratchTagScopeRelease _(&tag); + + // Objects that emulate undefined are loosely equal to null/undefined. + Register objreg = masm.extractObject(value, ToTempUnboxRegister(lir->tempToUnbox())); + Register scratch = ToRegister(lir->temp()); + testObjectEmulatesUndefined(objreg, ifTrueLabel, ifFalseLabel, scratch, ool); + } else { + masm.jump(ifFalseLabel); + } + return; } - return; } MOZ_ASSERT(op == JSOP_STRICTEQ || op == JSOP_STRICTNE); @@ -9677,7 +9721,7 @@ CodeGenerator::visitArgumentsLength(LArgumentsLength* lir) void CodeGenerator::visitGetFrameArgument(LGetFrameArgument* lir) { - ValueOperand result = GetValueOutput(lir); + ValueOperand result = ToOutValue(lir); const LAllocation* index = lir->index(); size_t argvOffset = frameSize() + JitFrameLayout::offsetOfActualArgs(); @@ -10432,7 +10476,7 @@ CodeGenerator::visitLoadFixedSlotV(LLoadFixedSlotV* ins) { const Register obj = ToRegister(ins->getOperand(0)); size_t slot = ins->mir()->slot(); - ValueOperand result = GetValueOutput(ins); + ValueOperand result = ToOutValue(ins); masm.loadValue(Address(obj, NativeObject::getFixedSlotOffset(slot)), result); } @@ -10526,7 +10570,7 @@ CodeGenerator::visitGetNameCache(LGetNameCache* ins) { LiveRegisterSet liveRegs = ins->safepoint()->liveRegs(); Register envChain = ToRegister(ins->envObj()); - ValueOperand output(GetValueOutput(ins)); + ValueOperand output = ToOutValue(ins); Register temp = ToRegister(ins->temp()); IonGetNameIC ic(liveRegs, envChain, output, temp); @@ -10620,7 +10664,7 @@ CodeGenerator::visitGetPropertyCacheV(LGetPropertyCacheV* ins) TypedOrValueRegister value = toConstantOrRegister(ins, LGetPropertyCacheV::Value, ins->mir()->value()->type()).reg(); ConstantOrRegister id = toConstantOrRegister(ins, LGetPropertyCacheV::Id, ins->mir()->idval()->type()); - TypedOrValueRegister output = TypedOrValueRegister(GetValueOutput(ins)); + TypedOrValueRegister output(ToOutValue(ins)); Register maybeTemp = ins->temp()->isBogusTemp() ? InvalidReg : ToRegister(ins->temp()); addGetPropertyCache(ins, liveRegs, value, id, output, maybeTemp, @@ -10649,7 +10693,7 @@ CodeGenerator::visitGetPropSuperCacheV(LGetPropSuperCacheV* ins) TypedOrValueRegister receiver = toConstantOrRegister(ins, LGetPropSuperCacheV::Receiver, ins->mir()->receiver()->type()).reg(); ConstantOrRegister id = toConstantOrRegister(ins, LGetPropSuperCacheV::Id, ins->mir()->idval()->type()); - TypedOrValueRegister output = TypedOrValueRegister(GetValueOutput(ins)); + TypedOrValueRegister output(ToOutValue(ins)); CacheKind kind = CacheKind::GetElemSuper; if (id.constant() && id.value().isString()) { @@ -10842,7 +10886,7 @@ CodeGenerator::visitTypeOfV(LTypeOfV* lir) { const ValueOperand value = ToValue(lir, LTypeOfV::Input); Register output = ToRegister(lir->output()); - Register tag = masm.splitTagForTest(value); + Register tag = masm.extractTag(value, output); const JSAtomState& names = gen->runtime->names(); Label done; @@ -11050,7 +11094,7 @@ CodeGenerator::visitToIdV(LToIdV* lir) ArgList(ToValue(lir, LToIdV::Input)), StoreValueTo(out)); - Register tag = masm.splitTagForTest(input); + Register tag = masm.extractTag(input, out.scratchReg()); masm.branchTestInt32(Assembler::NotEqual, tag, ¬Int32); masm.moveValue(input, out); @@ -12007,7 +12051,7 @@ CodeGenerator::visitGetDOMMemberV(LGetDOMMemberV* ins) // proxies in IonBuilder. Register object = ToRegister(ins->object()); size_t slot = ins->mir()->domMemberSlotIndex(); - ValueOperand result = GetValueOutput(ins); + ValueOperand result = ToOutValue(ins); masm.loadValue(Address(object, NativeObject::getFixedSlotOffset(slot)), result); } @@ -12622,28 +12666,38 @@ CodeGenerator::visitAssertRangeV(LAssertRangeV* ins) { const Range* r = ins->range(); const ValueOperand value = ToValue(ins, LAssertRangeV::Input); - Register tag = masm.splitTagForTest(value); Label done; { - Label isNotInt32; - masm.branchTestInt32(Assembler::NotEqual, tag, &isNotInt32); - Register unboxInt32 = ToTempUnboxRegister(ins->temp()); - Register input = masm.extractInt32(value, unboxInt32); - emitAssertRangeI(r, input); - masm.jump(&done); - masm.bind(&isNotInt32); - } + ScratchTagScope tag(masm, value); + masm.splitTagForTest(value, tag); - { - Label isNotDouble; - masm.branchTestDouble(Assembler::NotEqual, tag, &isNotDouble); - FloatRegister input = ToFloatRegister(ins->floatTemp1()); - FloatRegister temp = ToFloatRegister(ins->floatTemp2()); - masm.unboxDouble(value, input); - emitAssertRangeD(r, input, temp); - masm.jump(&done); - masm.bind(&isNotDouble); + { + Label isNotInt32; + masm.branchTestInt32(Assembler::NotEqual, tag, &isNotInt32); + { + ScratchTagScopeRelease _(&tag); + Register unboxInt32 = ToTempUnboxRegister(ins->temp()); + Register input = masm.extractInt32(value, unboxInt32); + emitAssertRangeI(r, input); + masm.jump(&done); + } + masm.bind(&isNotInt32); + } + + { + Label isNotDouble; + masm.branchTestDouble(Assembler::NotEqual, tag, &isNotDouble); + { + ScratchTagScopeRelease _(&tag); + FloatRegister input = ToFloatRegister(ins->floatTemp1()); + FloatRegister temp = ToFloatRegister(ins->floatTemp2()); + masm.unboxDouble(value, input); + emitAssertRangeD(r, input, temp); + masm.jump(&done); + } + masm.bind(&isNotDouble); + } } masm.assumeUnreachable("Incorrect range for Value."); @@ -12814,7 +12868,7 @@ CodeGenerator::visitDebugger(LDebugger* ins) void CodeGenerator::visitNewTarget(LNewTarget *ins) { - ValueOperand output = GetValueOutput(ins); + ValueOperand output = ToOutValue(ins); // if (isConstructing) output = argv[Max(numActualArgs, numFormalArgs)] Label notConstructing, done; diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h index 2a0cb1ab2024..d0d0c491fc6e 100644 --- a/js/src/jit/CodeGenerator.h +++ b/js/src/jit/CodeGenerator.h @@ -161,7 +161,6 @@ class CodeGenerator final : public CodeGeneratorSpecific void visitLoadUnboxedExpando(LLoadUnboxedExpando* lir); void visitTypeBarrierV(LTypeBarrierV* lir); void visitTypeBarrierO(LTypeBarrierO* lir); - void visitMonitorTypes(LMonitorTypes* lir); void emitPostWriteBarrier(const LAllocation* obj); void emitPostWriteBarrier(Register objreg); void emitPostWriteBarrierS(Address address, Register prev, Register next); diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp index 310e00c7af80..6fe2a395a098 100644 --- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -3156,7 +3156,10 @@ AutoFlushICache::setRange(uintptr_t start, size_t len) void AutoFlushICache::flush(uintptr_t start, size_t len) { -#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) +#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_NONE) + // Nothing +#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || \ + defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) JSContext* cx = TlsContext.get(); AutoFlushICache* afc = cx ? cx->autoFlushICache() : nullptr; if (!afc) { @@ -3175,6 +3178,8 @@ AutoFlushICache::flush(uintptr_t start, size_t len) JitSpewCont(JitSpew_CacheFlush, afc->inhibit_ ? "x" : "*"); ExecutableAllocator::cacheFlush((void*)start, len); +#else + MOZ_CRASH("Unresolved porting API - AutoFlushICache::flush"); #endif } @@ -3183,12 +3188,17 @@ AutoFlushICache::flush(uintptr_t start, size_t len) void AutoFlushICache::setInhibit() { -#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) +#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_NONE) + // Nothing +#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || \ + defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) AutoFlushICache* afc = TlsContext.get()->autoFlushICache(); MOZ_ASSERT(afc); MOZ_ASSERT(afc->start_); JitSpewCont(JitSpew_CacheFlush, "I"); afc->inhibit_ = true; +#else + MOZ_CRASH("Unresolved porting API - AutoFlushICache::setInhibit"); #endif } diff --git a/js/src/jit/IonCacheIRCompiler.cpp b/js/src/jit/IonCacheIRCompiler.cpp index e0555e46cbd4..3b710395afb1 100644 --- a/js/src/jit/IonCacheIRCompiler.cpp +++ b/js/src/jit/IonCacheIRCompiler.cpp @@ -1439,16 +1439,22 @@ EmitCheckPropertyTypes(MacroAssembler& masm, const PropertyTypeCheckInfo* typeCh masm.Push(obj); Register scratch1 = obj; - // We may also need a scratch register for guardTypeSet. + // We may also need a scratch register for guardTypeSet. Additionally, + // spectreRegToZero is the register that may be zeroed on speculatively + // executed paths. Register objScratch = InvalidReg; + Register spectreRegToZero = InvalidReg; if (propTypes && !propTypes->unknownObject() && propTypes->getObjectCount() > 0) { AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All()); if (!val.constant()) { TypedOrValueRegister valReg = val.reg(); - if (valReg.hasValue()) + if (valReg.hasValue()) { regs.take(valReg.valueReg()); - else if (!valReg.typedReg().isFloat()) + spectreRegToZero = valReg.valueReg().payloadOrValueReg(); + } else if (!valReg.typedReg().isFloat()) { regs.take(valReg.typedReg().gpr()); + spectreRegToZero = valReg.typedReg().gpr(); + } } regs.take(scratch1); objScratch = regs.takeAny(); @@ -1485,7 +1491,7 @@ EmitCheckPropertyTypes(MacroAssembler& masm, const PropertyTypeCheckInfo* typeCh // guardTypeSet can read from type sets without triggering read barriers. TypeSet::readBarrier(propTypes); masm.guardTypeSet(valReg, propTypes, BarrierKind::TypeSet, scratch1, objScratch, - &failedFastPath); + spectreRegToZero, &failedFastPath); masm.jump(&done); } else { masm.jump(&failedFastPath); diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp index 5484d43a7a4c..d4ee59426aa1 100644 --- a/js/src/jit/JitOptions.cpp +++ b/js/src/jit/JitOptions.cpp @@ -235,6 +235,7 @@ DefaultJitOptions::DefaultJitOptions() } SET_DEFAULT(spectreIndexMasking, true); + SET_DEFAULT(spectreObjectMitigationsBarriers, false); SET_DEFAULT(spectreStringMitigations, true); SET_DEFAULT(spectreValueMasking, true); diff --git a/js/src/jit/JitOptions.h b/js/src/jit/JitOptions.h index 503ef05880fa..f75f34a40da4 100644 --- a/js/src/jit/JitOptions.h +++ b/js/src/jit/JitOptions.h @@ -98,6 +98,7 @@ struct DefaultJitOptions // measure the effectiveness of each mitigation with various proof of // concept. bool spectreIndexMasking; + bool spectreObjectMitigationsBarriers; bool spectreStringMitigations; bool spectreValueMasking; diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index 5f61097084a2..bb78da3d47dd 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -2806,16 +2806,23 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier* ins) return; } - bool needObjTemp = !types->unknownObject() && types->getObjectCount() > 0; + bool hasSpecificObjects = !types->unknownObject() && types->getObjectCount() > 0; // Handle typebarrier with Value as input. if (inputType == MIRType::Value) { - LDefinition objTemp = needObjTemp ? temp() : LDefinition::BogusTemp(); - LTypeBarrierV* barrier = new(alloc()) LTypeBarrierV(useBox(ins->input()), tempToUnbox(), - objTemp); - assignSnapshot(barrier, Bailout_TypeBarrierV); - add(barrier, ins); - redefine(ins, ins->input()); + LDefinition objTemp = hasSpecificObjects ? temp() : LDefinition::BogusTemp(); + if (ins->canRedefineInput()) { + LTypeBarrierV* barrier = + new(alloc()) LTypeBarrierV(useBox(ins->input()), tempToUnbox(), objTemp); + assignSnapshot(barrier, Bailout_TypeBarrierV); + add(barrier, ins); + redefine(ins, ins->input()); + } else { + LTypeBarrierV* barrier = + new(alloc()) LTypeBarrierV(useBoxAtStart(ins->input()), tempToUnbox(), objTemp); + assignSnapshot(barrier, Bailout_TypeBarrierV); + defineBoxReuseInput(barrier, ins, 0); + } return; } @@ -2831,11 +2838,19 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier* ins) } if (needsObjectBarrier) { - LDefinition tmp = needObjTemp ? temp() : LDefinition::BogusTemp(); - LTypeBarrierO* barrier = new(alloc()) LTypeBarrierO(useRegister(ins->getOperand(0)), tmp); - assignSnapshot(barrier, Bailout_TypeBarrierO); - add(barrier, ins); - redefine(ins, ins->getOperand(0)); + LDefinition tmp = hasSpecificObjects ? temp() : LDefinition::BogusTemp(); + if (ins->canRedefineInput()) { + LTypeBarrierO* barrier = + new(alloc()) LTypeBarrierO(useRegister(ins->input()), tmp); + assignSnapshot(barrier, Bailout_TypeBarrierO); + add(barrier, ins); + redefine(ins, ins->getOperand(0)); + } else { + LTypeBarrierO* barrier = + new(alloc()) LTypeBarrierO(useRegisterAtStart(ins->input()), tmp); + assignSnapshot(barrier, Bailout_TypeBarrierO); + defineReuseInput(barrier, ins, 0); + } return; } @@ -2843,22 +2858,6 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier* ins) redefine(ins, ins->getOperand(0)); } -void -LIRGenerator::visitMonitorTypes(MMonitorTypes* ins) -{ - // Requesting a non-GC pointer is safe here since we never re-enter C++ - // from inside a type check. - - const TemporaryTypeSet* types = ins->typeSet(); - - bool needObjTemp = !types->unknownObject() && types->getObjectCount() > 0; - LDefinition objTemp = needObjTemp ? temp() : LDefinition::BogusTemp(); - - LMonitorTypes* lir = new(alloc()) LMonitorTypes(useBox(ins->input()), tempToUnbox(), objTemp); - assignSnapshot(lir, Bailout_MonitorTypes); - add(lir, ins); -} - // Returns true iff |def| is a constant that's either not a GC thing or is not // allocated in the nursery. static bool diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h index 64128afbf9a8..e2fe880101bb 100644 --- a/js/src/jit/Lowering.h +++ b/js/src/jit/Lowering.h @@ -216,7 +216,6 @@ class LIRGenerator : public LIRGeneratorSpecific void visitStoreSlot(MStoreSlot* ins) override; void visitFilterTypeSet(MFilterTypeSet* ins) override; void visitTypeBarrier(MTypeBarrier* ins) override; - void visitMonitorTypes(MMonitorTypes* ins) override; void visitPostWriteBarrier(MPostWriteBarrier* ins) override; void visitPostWriteElementBarrier(MPostWriteElementBarrier* ins) override; void visitArrayLength(MArrayLength* ins) override; diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index 3f4d4ba479ad..16adeb45cc7a 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -4340,7 +4340,7 @@ IonBuilder::prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType, // in bounds while the actual index isn't, so we need two bounds checks // here. if (byteLoadSize > 1) { - indexLoadEnd = addBoundsCheck(indexLoadEnd, length, BoundsCheckKind::UnusedIndex); + indexLoadEnd = addBoundsCheck(indexLoadEnd, length, BoundsCheckKind::IsLoad); auto* sub = MSub::New(alloc(), indexLoadEnd, constant(Int32Value(byteLoadSize - 1))); sub->setInt32Specialization(); current->add(sub); diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 58cd916415df..fded16bbf869 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -2361,6 +2361,29 @@ MTypeBarrier::foldsTo(TempAllocator& alloc) return input(); } +bool +MTypeBarrier::canRedefineInput() +{ + // LTypeBarrier does not need its own def usually, because we can use the + // input's allocation (LIRGenerator::redefineInput). However, if Spectre + // mitigations are enabled, guardObjectType may zero the object register on + // speculatively executed paths, so LTypeBarrier needs to have its own def + // then to guarantee all uses will see this potentially-zeroed value. + + if (!JitOptions.spectreObjectMitigationsBarriers) + return true; + + if (barrierKind() == BarrierKind::TypeTagOnly) + return true; + + TemporaryTypeSet* types = resultTypeSet(); + bool hasSpecificObjects = !types->unknownObject() && types->getObjectCount() > 0; + if (!hasSpecificObjects) + return true; + + return false; +} + #ifdef DEBUG void MPhi::assertLoopPhi() const @@ -6636,8 +6659,17 @@ TryAddTypeBarrierForWrite(TempAllocator& alloc, CompilerConstraintList* constrai if ((*pvalue)->resultTypeSet() && (*pvalue)->resultTypeSet()->objectsAreSubset(types)) kind = BarrierKind::TypeTagOnly; - MInstruction* ins = MMonitorTypes::New(alloc, *pvalue, types, kind); + MInstruction* ins = MTypeBarrier::New(alloc, *pvalue, types, kind); current->add(ins); + ins->setNotMovable(); + if (ins->type() == MIRType::Undefined) { + ins = MConstant::New(alloc, UndefinedValue()); + current->add(ins); + } else if (ins->type() == MIRType::Null) { + ins = MConstant::New(alloc, NullValue()); + current->add(ins); + } + *pvalue = ins; return true; } diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 778788280572..f318568dce75 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -13223,6 +13223,8 @@ class MTypeBarrier } MDefinition* foldsTo(TempAllocator& alloc) override; + bool canRedefineInput(); + bool alwaysBails() const { // If mirtype of input doesn't agree with mirtype of barrier, // we will definitely bail. @@ -13243,43 +13245,6 @@ class MTypeBarrier ALLOW_CLONE(MTypeBarrier) }; -// Like MTypeBarrier, guard that the value is in the given type set. This is -// used before property writes to ensure the value being written is represented -// in the property types for the object. -class MMonitorTypes - : public MUnaryInstruction, - public BoxInputsPolicy::Data -{ - const TemporaryTypeSet* typeSet_; - BarrierKind barrierKind_; - - MMonitorTypes(MDefinition* def, const TemporaryTypeSet* types, BarrierKind kind) - : MUnaryInstruction(classOpcode, def), - typeSet_(types), - barrierKind_(kind) - { - MOZ_ASSERT(kind == BarrierKind::TypeTagOnly || kind == BarrierKind::TypeSet); - - setGuard(); - MOZ_ASSERT(!types->unknown()); - } - - public: - INSTRUCTION_HEADER(MonitorTypes) - TRIVIAL_NEW_WRAPPERS - - const TemporaryTypeSet* typeSet() const { - return typeSet_; - } - BarrierKind barrierKind() const { - return barrierKind_; - } - - AliasSet getAliasSet() const override { - return AliasSet::None(); - } -}; - // Given a value being written to another object, update the generational store // buffer if the value is in the nursery and object is in the tenured heap. class MPostWriteBarrier : public MBinaryInstruction, public ObjectPolicy<0>::Data diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h index f0f601cdb285..44b5e9d171b0 100644 --- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -186,7 +186,6 @@ namespace jit { _(HomeObjectSuperBase) \ _(FilterTypeSet) \ _(TypeBarrier) \ - _(MonitorTypes) \ _(PostWriteBarrier) \ _(PostWriteElementBarrier) \ _(GetPropSuperCache) \ diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp index bd578a8e0773..fbd0e3c57bd8 100644 --- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -80,13 +80,17 @@ EmitTypeCheck(MacroAssembler& masm, Assembler::Condition cond, const T& src, Typ template void MacroAssembler::guardTypeSet(const Source& address, const TypeSet* types, BarrierKind kind, - Register unboxScratch, Register objScratch, Label* miss) + Register unboxScratch, Register objScratch, + Register spectreRegToZero, Label* miss) { // unboxScratch may be InvalidReg on 32-bit platforms. It should only be // used for extracting the Value tag or payload. // // objScratch may be InvalidReg if the TypeSet does not contain specific // objects to guard on. It should only be used for guardObjectType. + // + // spectreRegToZero is a register that will be zeroed by guardObjectType on + // speculatively executed paths. MOZ_ASSERT(kind == BarrierKind::TypeTagOnly || kind == BarrierKind::TypeSet); MOZ_ASSERT(!types->unknown()); @@ -154,12 +158,12 @@ MacroAssembler::guardTypeSet(const Source& address, const TypeSet* types, Barrie if (kind != BarrierKind::TypeTagOnly) { Register obj = extractObject(address, unboxScratch); - guardObjectType(obj, types, objScratch, miss); + guardObjectType(obj, types, objScratch, spectreRegToZero, miss); } else { #ifdef DEBUG Label fail; Register obj = extractObject(address, unboxScratch); - guardObjectType(obj, types, objScratch, &fail); + guardObjectType(obj, types, objScratch, spectreRegToZero, &fail); jump(&matched); bind(&fail); @@ -210,8 +214,8 @@ MacroAssembler::guardTypeSetMightBeIncomplete(const TypeSet* types, Register obj #endif void -MacroAssembler::guardObjectType(Register obj, const TypeSet* types, - Register scratch, Label* miss) +MacroAssembler::guardObjectType(Register obj, const TypeSet* types, Register scratch, + Register spectreRegToZero, Label* miss) { MOZ_ASSERT(obj != scratch); MOZ_ASSERT(!types->unknown()); @@ -246,33 +250,66 @@ MacroAssembler::guardObjectType(Register obj, const TypeSet* types, return; } + if (JitOptions.spectreObjectMitigationsBarriers) + move32(Imm32(0), scratch); + if (hasSingletons) { for (unsigned i = 0; i < count; i++) { JSObject* singleton = types->getSingletonNoBarrier(i); if (!singleton) continue; - if (--numBranches > 0) - branchPtr(Equal, obj, ImmGCPtr(singleton), &matched); - else - branchPtr(NotEqual, obj, ImmGCPtr(singleton), miss); + if (JitOptions.spectreObjectMitigationsBarriers) { + if (--numBranches > 0) { + Label next; + branchPtr(NotEqual, obj, ImmGCPtr(singleton), &next); + spectreMovePtr(NotEqual, scratch, spectreRegToZero); + jump(&matched); + bind(&next); + } else { + branchPtr(NotEqual, obj, ImmGCPtr(singleton), miss); + spectreMovePtr(NotEqual, scratch, spectreRegToZero); + } + } else { + if (--numBranches > 0) + branchPtr(Equal, obj, ImmGCPtr(singleton), &matched); + else + branchPtr(NotEqual, obj, ImmGCPtr(singleton), miss); + } } } if (hasObjectGroups) { comment("has object groups"); - loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch); + // If Spectre mitigations are enabled, we use the scratch register as + // zero register. Without mitigations we can use it to store the group. + Address groupAddr(obj, JSObject::offsetOfGroup()); + if (!JitOptions.spectreObjectMitigationsBarriers) + loadPtr(groupAddr, scratch); for (unsigned i = 0; i < count; i++) { ObjectGroup* group = types->getGroupNoBarrier(i); if (!group) continue; - if (--numBranches > 0) - branchPtr(Equal, scratch, ImmGCPtr(group), &matched); - else - branchPtr(NotEqual, scratch, ImmGCPtr(group), miss); + if (JitOptions.spectreObjectMitigationsBarriers) { + if (--numBranches > 0) { + Label next; + branchPtr(NotEqual, groupAddr, ImmGCPtr(group), &next); + spectreMovePtr(NotEqual, scratch, spectreRegToZero); + jump(&matched); + bind(&next); + } else { + branchPtr(NotEqual, groupAddr, ImmGCPtr(group), miss); + spectreMovePtr(NotEqual, scratch, spectreRegToZero); + } + } else { + if (--numBranches > 0) + branchPtr(Equal, scratch, ImmGCPtr(group), &matched); + else + branchPtr(NotEqual, scratch, ImmGCPtr(group), miss); + } } } @@ -283,13 +320,16 @@ MacroAssembler::guardObjectType(Register obj, const TypeSet* types, template void MacroAssembler::guardTypeSet(const Address& address, const TypeSet* types, BarrierKind kind, Register unboxScratch, - Register objScratch, Label* miss); + Register objScratch, Register spectreRegToZero, + Label* miss); template void MacroAssembler::guardTypeSet(const ValueOperand& value, const TypeSet* types, BarrierKind kind, Register unboxScratch, - Register objScratch, Label* miss); + Register objScratch, Register spectreRegToZero, + Label* miss); template void MacroAssembler::guardTypeSet(const TypedOrValueRegister& value, const TypeSet* types, BarrierKind kind, Register unboxScratch, - Register objScratch, Label* miss); + Register objScratch, Register spectreRegToZero, + Label* miss); template static void @@ -2212,15 +2252,18 @@ void MacroAssembler::convertValueToFloatingPoint(ValueOperand value, FloatRegister output, Label* fail, MIRType outputType) { - Register tag = splitTagForTest(value); - Label isDouble, isInt32, isBool, isNull, done; - branchTestDouble(Assembler::Equal, tag, &isDouble); - branchTestInt32(Assembler::Equal, tag, &isInt32); - branchTestBoolean(Assembler::Equal, tag, &isBool); - branchTestNull(Assembler::Equal, tag, &isNull); - branchTestUndefined(Assembler::NotEqual, tag, fail); + { + ScratchTagScope tag(*this, value); + splitTagForTest(value, tag); + + branchTestDouble(Assembler::Equal, tag, &isDouble); + branchTestInt32(Assembler::Equal, tag, &isInt32); + branchTestBoolean(Assembler::Equal, tag, &isBool); + branchTestNull(Assembler::Equal, tag, &isNull); + branchTestUndefined(Assembler::NotEqual, tag, fail); + } // fall-through: undefined loadConstantFloatingPoint(GenericNaN(), float(GenericNaN()), output, outputType); @@ -2428,7 +2471,8 @@ MacroAssembler::convertValueToInt(ValueOperand value, MDefinition* maybeInput, Label* fail, IntConversionBehavior behavior, IntConversionInputKind conversion) { - Register tag = splitTagForTest(value); + Label done, isInt32, isBool, isDouble, isNull, isString; + bool handleStrings = (behavior == IntConversionBehavior::Truncate || behavior == IntConversionBehavior::ClampToUint8) && handleStringEntry && @@ -2436,33 +2480,36 @@ MacroAssembler::convertValueToInt(ValueOperand value, MDefinition* maybeInput, MOZ_ASSERT_IF(handleStrings, conversion == IntConversionInputKind::Any); - Label done, isInt32, isBool, isDouble, isNull, isString; + { + ScratchTagScope tag(*this, value); + splitTagForTest(value, tag); - maybeBranchTestType(MIRType::Int32, maybeInput, tag, &isInt32); - if (conversion == IntConversionInputKind::Any || conversion == IntConversionInputKind::NumbersOrBoolsOnly) - maybeBranchTestType(MIRType::Boolean, maybeInput, tag, &isBool); - maybeBranchTestType(MIRType::Double, maybeInput, tag, &isDouble); + maybeBranchTestType(MIRType::Int32, maybeInput, tag, &isInt32); + if (conversion == IntConversionInputKind::Any || conversion == IntConversionInputKind::NumbersOrBoolsOnly) + maybeBranchTestType(MIRType::Boolean, maybeInput, tag, &isBool); + maybeBranchTestType(MIRType::Double, maybeInput, tag, &isDouble); - if (conversion == IntConversionInputKind::Any) { - // If we are not truncating, we fail for anything that's not - // null. Otherwise we might be able to handle strings and objects. - switch (behavior) { - case IntConversionBehavior::Normal: - case IntConversionBehavior::NegativeZeroCheck: - branchTestNull(Assembler::NotEqual, tag, fail); - break; + if (conversion == IntConversionInputKind::Any) { + // If we are not truncating, we fail for anything that's not + // null. Otherwise we might be able to handle strings and objects. + switch (behavior) { + case IntConversionBehavior::Normal: + case IntConversionBehavior::NegativeZeroCheck: + branchTestNull(Assembler::NotEqual, tag, fail); + break; - case IntConversionBehavior::Truncate: - case IntConversionBehavior::ClampToUint8: - maybeBranchTestType(MIRType::Null, maybeInput, tag, &isNull); - if (handleStrings) - maybeBranchTestType(MIRType::String, maybeInput, tag, &isString); - maybeBranchTestType(MIRType::Object, maybeInput, tag, fail); - branchTestUndefined(Assembler::NotEqual, tag, fail); - break; + case IntConversionBehavior::Truncate: + case IntConversionBehavior::ClampToUint8: + maybeBranchTestType(MIRType::Null, maybeInput, tag, &isNull); + if (handleStrings) + maybeBranchTestType(MIRType::String, maybeInput, tag, &isString); + maybeBranchTestType(MIRType::Object, maybeInput, tag, fail); + branchTestUndefined(Assembler::NotEqual, tag, fail); + break; + } + } else { + jump(fail); } - } else { - jump(fail); } // The value is null or undefined in truncation contexts - just emit 0. @@ -3581,7 +3628,7 @@ namespace jit { #ifdef DEBUG template AutoGenericRegisterScope::AutoGenericRegisterScope(MacroAssembler& masm, RegisterType reg) - : RegisterType(reg), masm_(masm) + : RegisterType(reg), masm_(masm), released_(false) { masm.debugTrackedRegisters_.add(reg); } @@ -3594,12 +3641,39 @@ template AutoGenericRegisterScope::AutoGenericRegisterScope(Macro template AutoGenericRegisterScope::~AutoGenericRegisterScope() { - const RegisterType& reg = *dynamic_cast(this); - masm_.debugTrackedRegisters_.take(reg); + if (!released_) + release(); } template AutoGenericRegisterScope::~AutoGenericRegisterScope(); template AutoGenericRegisterScope::~AutoGenericRegisterScope(); + +template +void +AutoGenericRegisterScope::release() +{ + MOZ_ASSERT(!released_); + released_ = true; + const RegisterType& reg = *dynamic_cast(this); + masm_.debugTrackedRegisters_.take(reg); +} + +template void AutoGenericRegisterScope::release(); +template void AutoGenericRegisterScope::release(); + +template +void +AutoGenericRegisterScope::reacquire() +{ + MOZ_ASSERT(released_); + released_ = false; + const RegisterType& reg = *dynamic_cast(this); + masm_.debugTrackedRegisters_.add(reg); +} + +template void AutoGenericRegisterScope::reacquire(); +template void AutoGenericRegisterScope::reacquire(); + #endif // DEBUG } // namespace jit diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index cfa60ca41c65..00b74fdcdf07 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -1367,6 +1367,10 @@ class MacroAssembler : public MacroAssemblerSpecific Register dest) DEFINED_ON(arm, arm64, mips_shared, x86, x64); + // Conditional move for Spectre mitigations. + inline void spectreMovePtr(Condition cond, Register src, Register dest) + DEFINED_ON(arm, arm64, x86, x64); + // Performs a bounds check and zeroes the index register if out-of-bounds // (to mitigate Spectre). inline void boundsCheck32ForLoad(Register index, Register length, Register scratch, @@ -1485,23 +1489,23 @@ class MacroAssembler : public MacroAssemblerSpecific void wasmStore(const wasm::MemoryAccessDesc& access, AnyRegister value, Operand dstAddr) DEFINED_ON(x86, x64); void wasmStoreI64(const wasm::MemoryAccessDesc& access, Register64 value, Operand dstAddr) DEFINED_ON(x86); - // For all the ARM wasmLoad and wasmStore functions, `ptr` MUST equal - // `ptrScratch`, and that register will be updated based on conditions + // For all the ARM and ARM64 wasmLoad and wasmStore functions, `ptr` MUST + // equal `ptrScratch`, and that register will be updated based on conditions // listed below (where it is only mentioned as `ptr`). // `ptr` will be updated if access.offset() != 0 or access.type() == Scalar::Int64. void wasmLoad(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, Register ptrScratch, AnyRegister output) - DEFINED_ON(arm, mips_shared); + DEFINED_ON(arm, arm64, mips_shared); void wasmLoadI64(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, Register ptrScratch, Register64 output) - DEFINED_ON(arm, mips32, mips64); + DEFINED_ON(arm, arm64, mips32, mips64); void wasmStore(const wasm::MemoryAccessDesc& access, AnyRegister value, Register memoryBase, Register ptr, Register ptrScratch) - DEFINED_ON(arm, mips_shared); + DEFINED_ON(arm, arm64, mips_shared); void wasmStoreI64(const wasm::MemoryAccessDesc& access, Register64 value, Register memoryBase, Register ptr, Register ptrScratch) - DEFINED_ON(arm, mips32, mips64); + DEFINED_ON(arm, arm64, mips32, mips64); // `ptr` will always be updated. void wasmUnalignedLoad(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, @@ -1934,9 +1938,11 @@ class MacroAssembler : public MacroAssemblerSpecific // register is required. template void guardTypeSet(const Source& address, const TypeSet* types, BarrierKind kind, - Register unboxScratch, Register objScratch, Label* miss); + Register unboxScratch, Register objScratch, Register spectreRegToZero, + Label* miss); - void guardObjectType(Register obj, const TypeSet* types, Register scratch, Label* miss); + void guardObjectType(Register obj, const TypeSet* types, Register scratch, + Register spectreRegToZero, Label* miss); #ifdef DEBUG void guardTypeSetMightBeIncomplete(const TypeSet* types, Register obj, Register scratch, diff --git a/js/src/jit/RegisterSets.h b/js/src/jit/RegisterSets.h index 34ca95b7c787..b6436a801b1c 100644 --- a/js/src/jit/RegisterSets.h +++ b/js/src/jit/RegisterSets.h @@ -130,7 +130,7 @@ class ValueOperand bool aliases(Register reg) const { return type_ == reg || payload_ == reg; } - Register scratchReg() const { + Register payloadOrValueReg() const { return payloadReg(); } constexpr bool operator==(const ValueOperand& o) const { @@ -154,7 +154,7 @@ class ValueOperand bool aliases(Register reg) const { return value_ == reg; } - Register scratchReg() const { + Register payloadOrValueReg() const { return valueReg(); } constexpr bool operator==(const ValueOperand& o) const { @@ -165,6 +165,10 @@ class ValueOperand } #endif + Register scratchReg() const { + return payloadOrValueReg(); + } + ValueOperand() = default; }; diff --git a/js/src/jit/Registers.h b/js/src/jit/Registers.h index 572554ffe160..d6d586a12b6a 100644 --- a/js/src/jit/Registers.h +++ b/js/src/jit/Registers.h @@ -345,12 +345,17 @@ struct AutoGenericRegisterScope : public RegisterType #ifdef DEBUG MacroAssembler& masm_; + bool released_; explicit AutoGenericRegisterScope(MacroAssembler& masm, RegisterType reg); ~AutoGenericRegisterScope(); + void release(); + void reacquire(); #else constexpr explicit AutoGenericRegisterScope(MacroAssembler& masm, RegisterType reg) : RegisterType(reg) { } + void release() {} + void reacquire() {} #endif }; diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp index 8eabc5608219..46da6665b547 100644 --- a/js/src/jit/arm/CodeGenerator-arm.cpp +++ b/js/src/jit/arm/CodeGenerator-arm.cpp @@ -1385,14 +1385,6 @@ CodeGeneratorARM::ToValue(LInstruction* ins, size_t pos) return ValueOperand(typeReg, payloadReg); } -ValueOperand -CodeGeneratorARM::ToOutValue(LInstruction* ins) -{ - Register typeReg = ToRegister(ins->getDef(TYPE_INDEX)); - Register payloadReg = ToRegister(ins->getDef(PAYLOAD_INDEX)); - return ValueOperand(typeReg, payloadReg); -} - ValueOperand CodeGeneratorARM::ToTempValue(LInstruction* ins, size_t pos) { @@ -1472,10 +1464,10 @@ CodeGeneratorARM::visitFloat32(LFloat32* ins) masm.loadConstantFloat32(ins->getFloat(), ToFloatRegister(out)); } -Register -CodeGeneratorARM::splitTagForTest(const ValueOperand& value) +void +CodeGeneratorARM::splitTagForTest(const ValueOperand& value, ScratchTagScope& tag) { - return value.typeReg(); + MOZ_ASSERT(value.typeReg() == tag); } void diff --git a/js/src/jit/arm/CodeGenerator-arm.h b/js/src/jit/arm/CodeGenerator-arm.h index bcda27d5ec6e..4c72eefda811 100644 --- a/js/src/jit/arm/CodeGenerator-arm.h +++ b/js/src/jit/arm/CodeGenerator-arm.h @@ -200,13 +200,12 @@ class CodeGeneratorARM : public CodeGeneratorShared protected: ValueOperand ToValue(LInstruction* ins, size_t pos); - ValueOperand ToOutValue(LInstruction* ins); ValueOperand ToTempValue(LInstruction* ins, size_t pos); Register64 ToOperandOrRegister64(const LInt64Allocation input); // Functions for LTestVAndBranch. - Register splitTagForTest(const ValueOperand& value); + void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag); void divICommon(MDiv* mir, Register lhs, Register rhs, Register output, LSnapshot* snapshot, Label& done); diff --git a/js/src/jit/arm/MacroAssembler-arm-inl.h b/js/src/jit/arm/MacroAssembler-arm-inl.h index 038ae5eb9bee..b67636e71e28 100644 --- a/js/src/jit/arm/MacroAssembler-arm-inl.h +++ b/js/src/jit/arm/MacroAssembler-arm-inl.h @@ -2181,6 +2181,12 @@ MacroAssembler::test32MovePtr(Condition cond, const Address& addr, Imm32 mask, R ma_mov(src, dest, LeaveCC, cond); } +void +MacroAssembler::spectreMovePtr(Condition cond, Register src, Register dest) +{ + ma_mov(src, dest, LeaveCC, cond); +} + void MacroAssembler::boundsCheck32ForLoad(Register index, Register length, Register scratch, Label* failure) diff --git a/js/src/jit/arm/MacroAssembler-arm.h b/js/src/jit/arm/MacroAssembler-arm.h index cc769d8b0f98..2cdc68eebab8 100644 --- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -23,6 +23,25 @@ static Register CallReg = ip; static const int defaultShift = 3; JS_STATIC_ASSERT(1 << defaultShift == sizeof(JS::Value)); +// See documentation for ScratchTagScope and ScratchTagScopeRelease in +// MacroAssembler-x64.h. + +class ScratchTagScope +{ + const ValueOperand& v_; + public: + ScratchTagScope(MacroAssembler&, const ValueOperand& v) : v_(v) {} + operator Register() { return v_.typeReg(); } + void release() {} + void reacquire() {} +}; + +class ScratchTagScopeRelease +{ + public: + explicit ScratchTagScopeRelease(ScratchTagScope*) {} +}; + // MacroAssemblerARM is inheriting form Assembler defined in // Assembler-arm.{h,cpp} class MacroAssemblerARM : public Assembler @@ -700,9 +719,8 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM test32(lhs, rhs); } - // Returns the register containing the type tag. - Register splitTagForTest(const ValueOperand& value) { - return value.typeReg(); + void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag) { + MOZ_ASSERT(value.typeReg() == tag); } // Higher level tag testing code. diff --git a/js/src/jit/arm64/Assembler-arm64.cpp b/js/src/jit/arm64/Assembler-arm64.cpp index 00026299e24e..bf3c32991936 100644 --- a/js/src/jit/arm64/Assembler-arm64.cpp +++ b/js/src/jit/arm64/Assembler-arm64.cpp @@ -35,6 +35,7 @@ ABIArgGenerator::next(MIRType type) { switch (type) { case MIRType::Int32: + case MIRType::Int64: case MIRType::Pointer: if (intRegIndex_ == NumIntArgRegs) { current_ = ABIArg(stackOffset_); @@ -87,6 +88,34 @@ Assembler::finish() } } +bool +Assembler::appendRawCode(const uint8_t* code, size_t numBytes) +{ + flush(); + return armbuffer_.appendRawCode(code, numBytes); +} + +bool +Assembler::reserve(size_t size) +{ + // This buffer uses fixed-size chunks so there's no point in reserving + // now vs. on-demand. + return !oom(); +} + +bool +Assembler::swapBuffer(wasm::Bytes& bytes) +{ + // For now, specialize to the one use case. As long as wasm::Bytes is a + // Vector, not a linked-list of chunks, there's not much we can do other + // than copy. + MOZ_ASSERT(bytes.empty()); + if (!bytes.resize(bytesNeeded())) + return false; + armbuffer_.executableCopy(bytes.begin()); + return true; +} + BufferOffset Assembler::emitExtendedJumpTable() { @@ -285,6 +314,19 @@ Assembler::bind(RepatchLabel* label) inst->SetImmPCOffsetTarget(inst + nextOffset().getOffset() - branchOffset); } +void +Assembler::bindLater(Label* label, wasm::OldTrapDesc target) +{ + if (label->used()) { + BufferOffset b(label); + do { + append(wasm::OldTrapSite(target, b.getOffset())); + b = NextLink(b); + } while (b.assigned()); + } + label->reset(); +} + void Assembler::trace(JSTracer* trc) { @@ -381,6 +423,8 @@ Assembler::ToggleToJmp(CodeLocationLabel inst_) MOZ_ASSERT(vixl::is_int19(imm19)); b(i, imm19, Always); + + AutoFlushICache::flush(uintptr_t(i), 4); } void @@ -405,6 +449,8 @@ Assembler::ToggleToCmp(CodeLocationLabel inst_) // From the above, there is a safe 19-bit contiguous region from 5:23. Emit(i, vixl::ThirtyTwoBits | vixl::AddSubImmediateFixed | vixl::SUB | Flags(vixl::SetFlags) | Rd(vixl::xzr) | (imm19 << vixl::Rn_offset)); + + AutoFlushICache::flush(uintptr_t(i), 4); } void @@ -431,7 +477,7 @@ Assembler::ToggleCall(CodeLocationLabel inst_, bool enabled) return; if (call->IsBLR()) { - // If the second instruction is blr(), then wehave: + // If the second instruction is blr(), then we have: // ldr x17, [pc, offset] // blr x17 MOZ_ASSERT(load->IsLDR()); @@ -455,6 +501,9 @@ Assembler::ToggleCall(CodeLocationLabel inst_, bool enabled) ldr(load, ScratchReg2_64, int32_t(offset)); blr(call, ScratchReg2_64); } + + AutoFlushICache::flush(uintptr_t(first), 4); + AutoFlushICache::flush(uintptr_t(call), 8); } class RelocationIterator diff --git a/js/src/jit/arm64/Assembler-arm64.h b/js/src/jit/arm64/Assembler-arm64.h index ab425f1614dc..6304e57afdfd 100644 --- a/js/src/jit/arm64/Assembler-arm64.h +++ b/js/src/jit/arm64/Assembler-arm64.h @@ -192,15 +192,9 @@ class Assembler : public vixl::Assembler typedef vixl::Condition Condition; void finish(); - bool appendRawCode(const uint8_t* code, size_t numBytes) { - MOZ_CRASH("NYI"); - } - bool reserve(size_t size) { - MOZ_CRASH("NYI"); - } - bool swapBuffer(wasm::Bytes& bytes) { - MOZ_CRASH("NYI"); - } + bool appendRawCode(const uint8_t* code, size_t numBytes); + bool reserve(size_t size); + bool swapBuffer(wasm::Bytes& bytes); void trace(JSTracer* trc); // Emit the jump table, returning the BufferOffset to the first entry in the table. @@ -220,9 +214,7 @@ class Assembler : public vixl::Assembler void bind(Label* label) { bind(label, nextOffset()); } void bind(Label* label, BufferOffset boff); void bind(RepatchLabel* label); - void bindLater(Label* label, wasm::OldTrapDesc target) { - MOZ_CRASH("NYI"); - } + void bindLater(Label* label, wasm::OldTrapDesc target); bool oom() const { return AssemblerShared::oom() || @@ -473,8 +465,8 @@ static constexpr Register ABINonArgReturnVolatileReg = lr; // TLS pointer argument register for WebAssembly functions. This must not alias // any other register used for passing function arguments or return values. -// Preserved by WebAssembly functions. -static constexpr Register WasmTlsReg { Registers::x17 }; +// Preserved by WebAssembly functions. Must be nonvolatile. +static constexpr Register WasmTlsReg { Registers::x23 }; // Registers used for wasm table calls. These registers must be disjoint // from the ABI argument registers, WasmTlsReg and each other. diff --git a/js/src/jit/arm64/CodeGenerator-arm64.cpp b/js/src/jit/arm64/CodeGenerator-arm64.cpp index e36888156680..65497d44f3db 100644 --- a/js/src/jit/arm64/CodeGenerator-arm64.cpp +++ b/js/src/jit/arm64/CodeGenerator-arm64.cpp @@ -401,13 +401,6 @@ CodeGeneratorARM64::ToValue(LInstruction* ins, size_t pos) return ValueOperand(ToRegister(ins->getOperand(pos))); } -ValueOperand -CodeGeneratorARM64::ToOutValue(LInstruction* ins) -{ - Register payloadReg = ToRegister(ins->getDef(0)); - return ValueOperand(payloadReg); -} - ValueOperand CodeGeneratorARM64::ToTempValue(LInstruction* ins, size_t pos) { @@ -444,8 +437,8 @@ CodeGeneratorARM64::visitFloat32(LFloat32* ins) MOZ_CRASH("visitFloat32"); } -Register -CodeGeneratorARM64::splitTagForTest(const ValueOperand& value) +void +CodeGeneratorARM64::splitTagForTest(const ValueOperand& value, ScratchTagScope& tag) { MOZ_CRASH("splitTagForTest"); } diff --git a/js/src/jit/arm64/CodeGenerator-arm64.h b/js/src/jit/arm64/CodeGenerator-arm64.h index e3f2755a4f68..975e82ee51d7 100644 --- a/js/src/jit/arm64/CodeGenerator-arm64.h +++ b/js/src/jit/arm64/CodeGenerator-arm64.h @@ -158,11 +158,10 @@ class CodeGeneratorARM64 : public CodeGeneratorShared protected: ValueOperand ToValue(LInstruction* ins, size_t pos); - ValueOperand ToOutValue(LInstruction* ins); ValueOperand ToTempValue(LInstruction* ins, size_t pos); // Functions for LTestVAndBranch. - Register splitTagForTest(const ValueOperand& value); + void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag); void storeElementTyped(const LAllocation* value, MIRType valueType, MIRType elementType, Register elements, const LAllocation* index); diff --git a/js/src/jit/arm64/MacroAssembler-arm64-inl.h b/js/src/jit/arm64/MacroAssembler-arm64-inl.h index 981cbe3b3b14..1fac1c456aca 100644 --- a/js/src/jit/arm64/MacroAssembler-arm64-inl.h +++ b/js/src/jit/arm64/MacroAssembler-arm64-inl.h @@ -17,79 +17,79 @@ namespace jit { void MacroAssembler::move64(Register64 src, Register64 dest) { - movePtr(src.reg, dest.reg); + Mov(ARMRegister(dest.reg, 64), ARMRegister(src.reg, 64)); } void MacroAssembler::move64(Imm64 imm, Register64 dest) { - movePtr(ImmWord(imm.value), dest.reg); + Mov(ARMRegister(dest.reg, 64), imm.value); } void MacroAssembler::moveFloat32ToGPR(FloatRegister src, Register dest) { - MOZ_CRASH("NYI: moveFloat32ToGPR"); + Fmov(ARMRegister(dest, 32), ARMFPRegister(src, 32)); } void MacroAssembler::moveGPRToFloat32(Register src, FloatRegister dest) { - MOZ_CRASH("NYI: moveGPRToFloat32"); + Fmov(ARMFPRegister(dest, 32), ARMRegister(src, 32)); } void MacroAssembler::move8SignExtend(Register src, Register dest) { - MOZ_CRASH("NYI: move8SignExtend"); + Sxtb(ARMRegister(dest, 32), ARMRegister(src, 32)); } void MacroAssembler::move16SignExtend(Register src, Register dest) { - MOZ_CRASH("NYI: move16SignExtend"); + Sxth(ARMRegister(dest, 32), ARMRegister(src, 32)); } void MacroAssembler::moveDoubleToGPR64(FloatRegister src, Register64 dest) { - MOZ_CRASH("NYI: moveDoubleToGPR64"); + Fmov(ARMRegister(dest.reg, 64), ARMFPRegister(src, 64)); } void MacroAssembler::moveGPR64ToDouble(Register64 src, FloatRegister dest) { - MOZ_CRASH("NYI: moveGPR64ToDouble"); + Fmov(ARMFPRegister(dest, 64), ARMRegister(src.reg, 64)); } void MacroAssembler::move64To32(Register64 src, Register dest) { - MOZ_CRASH("NYI: move64To32"); + Mov(ARMRegister(dest, 32), ARMRegister(src.reg, 32)); } void MacroAssembler::move32To64ZeroExtend(Register src, Register64 dest) { - MOZ_CRASH("NYI: move32To64ZeroExtend"); + Mov(ARMRegister(dest.reg, 32), ARMRegister(src, 32)); } void MacroAssembler::move8To64SignExtend(Register src, Register64 dest) { - MOZ_CRASH("NYI: move8To64SignExtend"); + Sxtb(ARMRegister(dest.reg, 64), ARMRegister(src, 32)); } void MacroAssembler::move16To64SignExtend(Register src, Register64 dest) { - MOZ_CRASH("NYI: move16To64SignExtend"); + Sxth(ARMRegister(dest.reg, 64), ARMRegister(src, 32)); } void MacroAssembler::move32To64SignExtend(Register src, Register64 dest) { - MOZ_CRASH("NYI: move32To64SignExtend"); + Sxtw(ARMRegister(dest.reg, 64), ARMRegister(src, 32)); } // =============================================================== @@ -164,7 +164,7 @@ MacroAssembler::and64(Imm64 imm, Register64 dest) void MacroAssembler::and64(Register64 src, Register64 dest) { - MOZ_CRASH("NYI: and64"); + And(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), ARMRegister(src.reg, 64)); } void @@ -357,13 +357,25 @@ MacroAssembler::add64(Imm64 imm, Register64 dest) CodeOffset MacroAssembler::sub32FromStackPtrWithPatch(Register dest) { - MOZ_CRASH("NYI - sub32FromStackPtrWithPatch"); + vixl::UseScratchRegisterScope temps(this); + const ARMRegister scratch = temps.AcquireX(); + CodeOffset offs = CodeOffset(currentOffset()); + movz(scratch, 0, 0); + movk(scratch, 0, 16); + Sub(ARMRegister(dest, 64), sp, scratch); + return offs; } void MacroAssembler::patchSub32FromStackPtr(CodeOffset offset, Imm32 imm) { - MOZ_CRASH("NYI - patchSub32FromStackPtr"); + Instruction* i1 = getInstructionAt(BufferOffset(offset.offset())); + MOZ_ASSERT(i1->IsMovz()); + i1->SetInstructionBits(i1->InstructionBits() | ImmMoveWide(uint16_t(imm.value))); + + Instruction* i2 = getInstructionAt(BufferOffset(offset.offset() + 4)); + MOZ_ASSERT(i2->IsMovk()); + i2->SetInstructionBits(i2->InstructionBits() | ImmMoveWide(uint16_t(imm.value >> 16))); } void @@ -438,13 +450,13 @@ MacroAssembler::subPtr(const Address& addr, Register dest) void MacroAssembler::sub64(Register64 src, Register64 dest) { - MOZ_CRASH("NYI: sub64"); + Sub(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), ARMRegister(src.reg, 64)); } void MacroAssembler::sub64(Imm64 imm, Register64 dest) { - MOZ_CRASH("NYI: sub64"); + Sub(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), Operand(imm.value)); } void @@ -462,7 +474,7 @@ MacroAssembler::subFloat32(FloatRegister src, FloatRegister dest) void MacroAssembler::mul32(Register rhs, Register srcDest) { - MOZ_CRASH("NYI - mul32"); + mul32(srcDest, rhs, srcDest, nullptr, nullptr); } void @@ -493,7 +505,8 @@ MacroAssembler::mul64(Imm64 imm, const Register64& dest) void MacroAssembler::mul64(const Register64& src, const Register64& dest, const Register temp) { - MOZ_CRASH("NYI: mul64"); + MOZ_ASSERT(temp == Register::Invalid()); + Mul(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), ARMRegister(src.reg, 64)); } void @@ -531,13 +544,26 @@ MacroAssembler::mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest) void MacroAssembler::quotient32(Register rhs, Register srcDest, bool isUnsigned) { - MOZ_CRASH("NYI - quotient32"); + if (isUnsigned) + Udiv(ARMRegister(srcDest, 32), ARMRegister(srcDest, 32), ARMRegister(rhs, 32)); + else + Sdiv(ARMRegister(srcDest, 32), ARMRegister(srcDest, 32), ARMRegister(rhs, 32)); } +// This does not deal with x % 0 or INT_MIN % -1, the caller needs to filter +// those cases when they may occur. + void MacroAssembler::remainder32(Register rhs, Register srcDest, bool isUnsigned) { - MOZ_CRASH("NYI - remainder32"); + vixl::UseScratchRegisterScope temps(this); + ARMRegister scratch = temps.AcquireW(); + if (isUnsigned) + Udiv(scratch, ARMRegister(srcDest, 32), ARMRegister(rhs, 32)); + else + Sdiv(scratch, ARMRegister(srcDest, 32), ARMRegister(rhs, 32)); + Mul(scratch, scratch, ARMRegister(rhs, 32)); + Sub(ARMRegister(srcDest, 32), ARMRegister(srcDest, 32), scratch); } void @@ -586,49 +612,53 @@ MacroAssembler::negateDouble(FloatRegister reg) void MacroAssembler::absFloat32(FloatRegister src, FloatRegister dest) { - MOZ_CRASH("NYI - absFloat32"); + fabs(ARMFPRegister(dest, 32), ARMFPRegister(src, 32)); } void MacroAssembler::absDouble(FloatRegister src, FloatRegister dest) { - MOZ_CRASH("NYI - absDouble"); + fabs(ARMFPRegister(dest, 64), ARMFPRegister(src, 64)); } void MacroAssembler::sqrtFloat32(FloatRegister src, FloatRegister dest) { - MOZ_CRASH("NYI - sqrtFloat32"); + fsqrt(ARMFPRegister(dest, 32), ARMFPRegister(src, 32)); } void MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister dest) { - MOZ_CRASH("NYI - sqrtDouble"); + fsqrt(ARMFPRegister(dest, 64), ARMFPRegister(src, 64)); } void MacroAssembler::minFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN) { - MOZ_CRASH("NYI - minFloat32"); + MOZ_ASSERT(handleNaN); // Always true for wasm + fmin(ARMFPRegister(srcDest, 32), ARMFPRegister(srcDest, 32), ARMFPRegister(other, 32)); } void MacroAssembler::minDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN) { - MOZ_CRASH("NYI - minDouble"); + MOZ_ASSERT(handleNaN); // Always true for wasm + fmin(ARMFPRegister(srcDest, 64), ARMFPRegister(srcDest, 64), ARMFPRegister(other, 64)); } void MacroAssembler::maxFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN) { - MOZ_CRASH("NYI - maxFloat32"); + MOZ_ASSERT(handleNaN); // Always true for wasm + fmax(ARMFPRegister(srcDest, 32), ARMFPRegister(srcDest, 32), ARMFPRegister(other, 32)); } void MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN) { - MOZ_CRASH("NYI - maxDouble"); + MOZ_ASSERT(handleNaN); // Always true for wasm + fmax(ARMFPRegister(srcDest, 64), ARMFPRegister(srcDest, 64), ARMFPRegister(other, 64)); } // =============================================================== @@ -651,7 +681,7 @@ MacroAssembler::lshift64(Imm32 imm, Register64 dest) void MacroAssembler::lshift64(Register shift, Register64 srcDest) { - MOZ_CRASH("NYI: lshift64"); + Lsl(ARMRegister(srcDest.reg, 64), ARMRegister(srcDest.reg, 64), ARMRegister(shift, 64)); } void @@ -724,19 +754,19 @@ MacroAssembler::rshift64(Imm32 imm, Register64 dest) void MacroAssembler::rshift64(Register shift, Register64 srcDest) { - MOZ_CRASH("NYI: rshift64"); + Lsr(ARMRegister(srcDest.reg, 64), ARMRegister(srcDest.reg, 64), ARMRegister(shift, 64)); } void MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest) { - MOZ_CRASH("NYI: rshift64Arithmetic"); + Asr(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), imm.value); } void MacroAssembler::rshift64Arithmetic(Register shift, Register64 srcDest) { - MOZ_CRASH("NYI: rshift64Arithmetic"); + Asr(ARMRegister(srcDest.reg, 64), ARMRegister(srcDest.reg, 64), ARMRegister(shift, 64)); } // =============================================================== @@ -764,49 +794,65 @@ MacroAssembler::cmpPtrSet(Condition cond, T1 lhs, T2 rhs, Register dest) void MacroAssembler::rotateLeft(Imm32 count, Register input, Register dest) { - MOZ_CRASH("NYI: rotateLeft by immediate"); + Ror(ARMRegister(dest, 32), ARMRegister(input, 32), (32 - count.value) & 31); } void MacroAssembler::rotateLeft(Register count, Register input, Register dest) { - MOZ_CRASH("NYI: rotateLeft by register"); + vixl::UseScratchRegisterScope temps(this); + const ARMRegister scratch = temps.AcquireW(); + // Really 32 - count, but the upper bits of the result are ignored. + Neg(scratch, ARMRegister(count, 32)); + Ror(ARMRegister(dest, 32), ARMRegister(input, 32), scratch); } void MacroAssembler::rotateRight(Imm32 count, Register input, Register dest) { - MOZ_CRASH("NYI: rotateRight by immediate"); + Ror(ARMRegister(dest, 32), ARMRegister(input, 32), count.value & 31); } void MacroAssembler::rotateRight(Register count, Register input, Register dest) { - MOZ_CRASH("NYI: rotateRight by register"); + Ror(ARMRegister(dest, 32), ARMRegister(input, 32), ARMRegister(count, 32)); } void MacroAssembler::rotateLeft64(Register count, Register64 input, Register64 dest, Register temp) { - MOZ_CRASH("NYI: rotateLeft64"); + MOZ_ASSERT(temp == Register::Invalid()); + + vixl::UseScratchRegisterScope temps(this); + const ARMRegister scratch = temps.AcquireX(); + // Really 64 - count, but the upper bits of the result are ignored. + Neg(scratch, ARMRegister(count, 64)); + Ror(ARMRegister(dest.reg, 64), ARMRegister(input.reg, 64), scratch); } void MacroAssembler::rotateLeft64(Imm32 count, Register64 input, Register64 dest, Register temp) { - MOZ_CRASH("NYI: rotateLeft64"); + MOZ_ASSERT(temp == Register::Invalid()); + + Ror(ARMRegister(dest.reg, 64), ARMRegister(input.reg, 64), (64 - count.value) & 63); } void MacroAssembler::rotateRight64(Register count, Register64 input, Register64 dest, Register temp) { - MOZ_CRASH("NYI: rotateRight64"); + MOZ_ASSERT(temp == Register::Invalid()); + + Ror(ARMRegister(dest.reg, 64), ARMRegister(input.reg, 64), ARMRegister(count, 64)); } void MacroAssembler::rotateRight64(Imm32 count, Register64 input, Register64 dest, Register temp) { - MOZ_CRASH("NYI: rotateRight64"); + MOZ_ASSERT(temp == Register::Invalid()); + + Ror(ARMRegister(dest.reg, 64), ARMRegister(input.reg, 64), count.value & 63); } // =============================================================== @@ -815,37 +861,84 @@ MacroAssembler::rotateRight64(Imm32 count, Register64 input, Register64 dest, Re void MacroAssembler::clz32(Register src, Register dest, bool knownNotZero) { - MOZ_CRASH("NYI: clz32"); + Clz(ARMRegister(dest, 32), ARMRegister(src, 32)); } void MacroAssembler::ctz32(Register src, Register dest, bool knownNotZero) { - MOZ_CRASH("NYI: ctz32"); + Rbit(ARMRegister(dest, 32), ARMRegister(src, 32)); + Clz(ARMRegister(dest, 32), ARMRegister(dest, 32)); } void MacroAssembler::clz64(Register64 src, Register dest) { - MOZ_CRASH("NYI: clz64"); + Clz(ARMRegister(dest, 64), ARMRegister(src.reg, 64)); } void MacroAssembler::ctz64(Register64 src, Register dest) { - MOZ_CRASH("NYI: ctz64"); + Rbit(ARMRegister(dest, 64), ARMRegister(src.reg, 64)); + Clz(ARMRegister(dest, 64), ARMRegister(dest, 64)); } void -MacroAssembler::popcnt32(Register src, Register dest, Register temp) +MacroAssembler::popcnt32(Register src_, Register dest_, Register tmp_) { - MOZ_CRASH("NYI: popcnt32"); + MOZ_ASSERT(tmp_ != Register::Invalid()); + + // Equivalent to mozilla::CountPopulation32(). + + ARMRegister src(src_, 32); + ARMRegister dest(dest_, 32); + ARMRegister tmp(tmp_, 32); + + Mov(tmp, src); + if (src_ != dest_) + Mov(dest, src); + Lsr(dest, dest, 1); + And(dest, dest, 0x55555555); + Sub(dest, tmp, dest); + Lsr(tmp, dest, 2); + And(tmp, tmp, 0x33333333); + And(dest, dest, 0x33333333); + Add(dest, tmp, dest); + Add(dest, dest, Operand(dest, vixl::LSR, 4)); + And(dest, dest, 0x0F0F0F0F); + Add(dest, dest, Operand(dest, vixl::LSL, 8)); + Add(dest, dest, Operand(dest, vixl::LSL, 16)); + Lsr(dest, dest, 24); } void -MacroAssembler::popcnt64(Register64 src, Register64 dest, Register temp) +MacroAssembler::popcnt64(Register64 src_, Register64 dest_, Register tmp_) { - MOZ_CRASH("NYI: popcnt64"); + MOZ_ASSERT(tmp_ != Register::Invalid()); + + // Equivalent to mozilla::CountPopulation64(), though likely more efficient. + + ARMRegister src(src_.reg, 64); + ARMRegister dest(dest_.reg, 64); + ARMRegister tmp(tmp_, 64); + + Mov(tmp, src); + if (src_ != dest_) + Mov(dest, src); + Lsr(dest, dest, 1); + And(dest, dest, 0x5555555555555555); + Sub(dest, tmp, dest); + Lsr(tmp, dest, 2); + And(tmp, tmp, 0x3333333333333333); + And(dest, dest, 0x3333333333333333); + Add(dest, tmp, dest); + Add(dest, dest, Operand(dest, vixl::LSR, 4)); + And(dest, dest, 0x0F0F0F0F0F0F0F0F); + Add(dest, dest, Operand(dest, vixl::LSL, 8)); + Add(dest, dest, Operand(dest, vixl::LSL, 16)); + Add(dest, dest, Operand(dest, vixl::LSL, 32)); + Lsr(dest, dest, 56); } // =============================================================== @@ -929,13 +1022,19 @@ MacroAssembler::branch32(Condition cond, wasm::SymbolicAddress lhs, Imm32 rhs, L void MacroAssembler::branch64(Condition cond, Register64 lhs, Imm64 val, Label* success, Label* fail) { - MOZ_CRASH("NYI: branch64 reg-imm"); + Cmp(ARMRegister(lhs.reg, 64), val.value); + B(success, cond); + if (fail) + B(fail); } void MacroAssembler::branch64(Condition cond, Register64 lhs, Register64 rhs, Label* success, Label* fail) { - MOZ_CRASH("NYI: branch64 reg-reg"); + Cmp(ARMRegister(lhs.reg, 64), ARMRegister(rhs.reg, 64)); + B(success, cond); + if (fail) + B(fail); } void @@ -1707,7 +1806,8 @@ MacroAssembler::branchTestMagic(Condition cond, const Address& valaddr, JSWhyMag void MacroAssembler::branchToComputedAddress(const BaseIndex& addr) { - MOZ_CRASH("branchToComputedAddress"); + // Not used by Rabaldr. + MOZ_CRASH("NYI - branchToComputedAddress"); } void @@ -1760,6 +1860,12 @@ MacroAssembler::test32MovePtr(Condition cond, const Address& addr, Imm32 mask, R Csel(ARMRegister(dest, 64), ARMRegister(src, 64), ARMRegister(dest, 64), cond); } +void +MacroAssembler::spectreMovePtr(Condition cond, Register src, Register dest) +{ + Csel(ARMRegister(dest, 64), ARMRegister(src, 64), ARMRegister(dest, 64), cond); +} + void MacroAssembler::boundsCheck32ForLoad(Register index, Register length, Register scratch, Label* failure) @@ -1826,7 +1932,12 @@ MacroAssembler::storeFloat32x3(FloatRegister src, const BaseIndex& dest) void MacroAssembler::memoryBarrier(MemoryBarrierBits barrier) { - MOZ_CRASH("NYI"); + if (barrier == MembarStoreStore) + Dmb(vixl::InnerShareable, vixl::BarrierWrites); + else if (barrier == MembarLoadLoad) + Dmb(vixl::InnerShareable, vixl::BarrierReads); + else if (barrier) + Dmb(vixl::InnerShareable, vixl::BarrierAll); } // =============================================================== @@ -1853,14 +1964,16 @@ template void MacroAssembler::wasmBoundsCheck(Condition cond, Register index, Register boundsCheckLimit, L label) { - MOZ_CRASH("NYI"); + // Not used on ARM64, we rely on signal handling instead + MOZ_CRASH("NYI - wasmBoundsCheck"); } template void MacroAssembler::wasmBoundsCheck(Condition cond, Register index, Address boundsCheckLimit, L label) { - MOZ_CRASH("NYI"); + // Not used on ARM64, we rely on signal handling instead + MOZ_CRASH("NYI - wasmBoundsCheck"); } //}}} check_macroassembler_style @@ -1950,14 +2063,29 @@ MacroAssemblerCompat::moveStackPtrTo(Register dest) void MacroAssemblerCompat::loadStackPtr(const Address& src) { - Ldr(GetStackPointer64(), toMemOperand(src)); - syncStackPtr(); + if (sp.Is(GetStackPointer64())) { + vixl::UseScratchRegisterScope temps(this); + const ARMRegister scratch = temps.AcquireX(); + Ldr(scratch, toMemOperand(src)); + Mov(sp, scratch); + // syncStackPtr() not needed since our SP is the real SP. + } else { + Ldr(GetStackPointer64(), toMemOperand(src)); + syncStackPtr(); + } } void MacroAssemblerCompat::storeStackPtr(const Address& dest) { - Str(GetStackPointer64(), toMemOperand(dest)); + if (sp.Is(GetStackPointer64())) { + vixl::UseScratchRegisterScope temps(this); + const ARMRegister scratch = temps.AcquireX(); + Mov(scratch, sp); + Str(scratch, toMemOperand(dest)); + } else { + Str(GetStackPointer64(), toMemOperand(dest)); + } } void @@ -2009,12 +2137,9 @@ MacroAssemblerCompat::ensureDouble(const ValueOperand& source, FloatRegister des { Label isDouble, done; - // TODO: splitTagForTest really should not leak a scratch register. - Register tag = splitTagForTest(source); { - vixl::UseScratchRegisterScope temps(this); - temps.Exclude(ARMRegister(tag, 64)); - + ScratchTagScope tag(asMasm(), source); + splitTagForTest(source, tag); asMasm().branchTestDouble(Assembler::Equal, tag, &isDouble); asMasm().branchTestInt32(Assembler::NotEqual, tag, failure); } diff --git a/js/src/jit/arm64/MacroAssembler-arm64.cpp b/js/src/jit/arm64/MacroAssembler-arm64.cpp index a12d224d3a66..ce4e2feaa2b2 100644 --- a/js/src/jit/arm64/MacroAssembler-arm64.cpp +++ b/js/src/jit/arm64/MacroAssembler-arm64.cpp @@ -72,6 +72,17 @@ MacroAssemblerCompat::asVIXL() const return *static_cast(this); } +void +MacroAssemblerCompat::B(wasm::OldTrapDesc target, Condition cond) +{ + Label l; + if (cond == Always) + B(&l); + else + B(&l, cond); + bindLater(&l, target); +} + BufferOffset MacroAssemblerCompat::movePatchablePtr(ImmPtr ptr, Register dest) { @@ -152,6 +163,7 @@ MacroAssemblerCompat::handleFailureWithHandlerTail(void* handler, Label* profile Label finally; Label return_; Label bailout; + Label wasm; MOZ_ASSERT(GetStackPointer64().Is(x28)); // Lets the code below be a little cleaner. @@ -163,6 +175,7 @@ MacroAssemblerCompat::handleFailureWithHandlerTail(void* handler, Label* profile asMasm().branch32(Assembler::Equal, r0, Imm32(ResumeFromException::RESUME_FORCED_RETURN), &return_); asMasm().branch32(Assembler::Equal, r0, Imm32(ResumeFromException::RESUME_BAILOUT), &bailout); + asMasm().branch32(Assembler::Equal, r0, Imm32(ResumeFromException::RESUME_WASM), &wasm); breakpoint(); // Invalid kind. @@ -215,6 +228,15 @@ MacroAssemblerCompat::handleFailureWithHandlerTail(void* handler, Label* profile Ldr(x1, MemOperand(GetStackPointer64(), offsetof(ResumeFromException, target))); Mov(x0, BAILOUT_RETURN_OK); Br(x1); + + // If we are throwing and the innermost frame was a wasm frame, reset SP and + // FP; SP is pointing to the unwound return address to the wasm entry, so + // we can just ret(). + bind(&wasm); + Ldr(x29, MemOperand(GetStackPointer64(), offsetof(ResumeFromException, framePointer))); + Ldr(x28, MemOperand(GetStackPointer64(), offsetof(ResumeFromException, stackPointer))); + syncStackPtr(); + ret(); } void @@ -242,6 +264,147 @@ MacroAssemblerCompat::breakpoint() Brk((code++) & 0xffff); } +// Either `any` is valid or `sixtyfour` is valid. Return a 32-bit ARMRegister +// in the first case and an ARMRegister of the desired size in the latter case. + +static inline ARMRegister +SelectGPReg(AnyRegister any, Register64 sixtyfour, unsigned size = 64) +{ + MOZ_ASSERT(any.isValid() != (sixtyfour != Register64::Invalid())); + + if (sixtyfour == Register64::Invalid()) + return ARMRegister(any.gpr(), 32); + + return ARMRegister(sixtyfour.reg, size); +} + +// Assert that `sixtyfour` is invalid and then return an FP register from `any` +// of the desired size. + +static inline ARMFPRegister +SelectFPReg(AnyRegister any, Register64 sixtyfour, unsigned size) +{ + MOZ_ASSERT(sixtyfour == Register64::Invalid()); + return ARMFPRegister(any.fpu(), size); +} + +void +MacroAssemblerCompat::wasmLoadImpl(const wasm::MemoryAccessDesc& access, Register memoryBase_, + Register ptr_, Register ptrScratch_, AnyRegister outany, + Register64 out64) +{ + uint32_t offset = access.offset(); + MOZ_ASSERT(offset < wasm::OffsetGuardLimit); + + MOZ_ASSERT(ptr_ == ptrScratch_); + + ARMRegister memoryBase(memoryBase_, 64); + ARMRegister ptr(ptr_, 64); + if (offset) + Add(ptr, ptr, Operand(offset)); + + asMasm().memoryBarrierBefore(access.sync()); + + MemOperand srcAddr(memoryBase, ptr); + size_t loadOffset = asMasm().currentOffset(); + switch (access.type()) { + case Scalar::Int8: + Ldrsb(SelectGPReg(outany, out64), srcAddr); + break; + case Scalar::Uint8: + Ldrb(SelectGPReg(outany, out64), srcAddr); + break; + case Scalar::Int16: + Ldrsh(SelectGPReg(outany, out64), srcAddr); + break; + case Scalar::Uint16: + Ldrh(SelectGPReg(outany, out64), srcAddr); + break; + case Scalar::Int32: + if (out64 != Register64::Invalid()) + Ldrsw(SelectGPReg(outany, out64), srcAddr); + else + Ldr(SelectGPReg(outany, out64, 32), srcAddr); + break; + case Scalar::Uint32: + Ldr(SelectGPReg(outany, out64, 32), srcAddr); + break; + case Scalar::Int64: + Ldr(SelectGPReg(outany, out64), srcAddr); + break; + case Scalar::Float32: + Ldr(SelectFPReg(outany, out64, 32), srcAddr); + break; + case Scalar::Float64: + Ldr(SelectFPReg(outany, out64, 64), srcAddr); + break; + case Scalar::Uint8Clamped: + case Scalar::MaxTypedArrayViewType: + case Scalar::Float32x4: + case Scalar::Int32x4: + case Scalar::Int8x16: + case Scalar::Int16x8: + MOZ_CRASH("unexpected array type"); + } + append(access, loadOffset, framePushed()); + + asMasm().memoryBarrierAfter(access.sync()); +} + +void +MacroAssemblerCompat::wasmStoreImpl(const wasm::MemoryAccessDesc& access, AnyRegister valany, + Register64 val64, Register memoryBase_, Register ptr_, + Register ptrScratch_) +{ + uint32_t offset = access.offset(); + MOZ_ASSERT(offset < wasm::OffsetGuardLimit); + + MOZ_ASSERT(ptr_ == ptrScratch_); + + ARMRegister memoryBase(memoryBase_, 64); + ARMRegister ptr(ptr_, 64); + if (offset) + Add(ptr, ptr, Operand(offset)); + + asMasm().memoryBarrierBefore(access.sync()); + + MemOperand dstAddr(memoryBase, ptr); + size_t storeOffset = asMasm().currentOffset(); + switch (access.type()) { + case Scalar::Int8: + case Scalar::Uint8: + Strb(SelectGPReg(valany, val64), dstAddr); + break; + case Scalar::Int16: + case Scalar::Uint16: + Strh(SelectGPReg(valany, val64), dstAddr); + break; + case Scalar::Int32: + case Scalar::Uint32: + Str(SelectGPReg(valany, val64), dstAddr); + break; + case Scalar::Int64: + Str(SelectGPReg(valany, val64), dstAddr); + break; + case Scalar::Float32: + Str(SelectFPReg(valany, val64, 32), dstAddr); + break; + case Scalar::Float64: + Str(SelectFPReg(valany, val64, 64), dstAddr); + break; + case Scalar::Float32x4: + case Scalar::Int32x4: + case Scalar::Int8x16: + case Scalar::Int16x8: + case Scalar::Uint8Clamped: + case Scalar::MaxTypedArrayViewType: + MOZ_CRASH("unexpected array type"); + } + append(access, storeOffset, framePushed()); + + asMasm().memoryBarrierAfter(access.sync()); +} + void MacroAssembler::reserveStack(uint32_t amount) { @@ -503,79 +666,126 @@ MacroAssembler::call(JitCode* c) CodeOffset MacroAssembler::callWithPatch() { - MOZ_CRASH("NYI"); - return CodeOffset(); + bl(0, LabelDoc()); + return CodeOffset(currentOffset()); } void MacroAssembler::patchCall(uint32_t callerOffset, uint32_t calleeOffset) { - MOZ_CRASH("NYI"); + Instruction* inst = getInstructionAt(BufferOffset(callerOffset - 4)); + MOZ_ASSERT(inst->IsBL()); + bl(inst, ((int)calleeOffset - ((int)callerOffset - 4)) >> 2); } CodeOffset MacroAssembler::farJumpWithPatch() { - MOZ_CRASH("NYI"); + vixl::UseScratchRegisterScope temps(this); + const ARMRegister scratch = temps.AcquireX(); + const ARMRegister scratch2 = temps.AcquireX(); + + AutoForbidPools afp(this, /* max number of instructions in scope = */ 7); + + mozilla::DebugOnly before = currentOffset(); + + align(8); // At most one nop + + Label branch; + adr(scratch2, &branch); + ldr(scratch, vixl::MemOperand(scratch2, 4)); + add(scratch2, scratch2, scratch); + CodeOffset offs(currentOffset()); + bind(&branch); + br(scratch2); + Emit(UINT32_MAX); + Emit(UINT32_MAX); + + mozilla::DebugOnly after = currentOffset(); + + MOZ_ASSERT(after - before == 24 || after - before == 28); + + return offs; } void MacroAssembler::patchFarJump(CodeOffset farJump, uint32_t targetOffset) { - MOZ_CRASH("NYI"); + Instruction* inst1 = getInstructionAt(BufferOffset(farJump.offset() + 4)); + Instruction* inst2 = getInstructionAt(BufferOffset(farJump.offset() + 8)); + + int64_t distance = (int64_t)targetOffset - (int64_t)farJump.offset(); + + MOZ_ASSERT(inst1->InstructionBits() == UINT32_MAX); + MOZ_ASSERT(inst2->InstructionBits() == UINT32_MAX); + + inst1->SetInstructionBits((uint32_t)distance); + inst2->SetInstructionBits((uint32_t)(distance >> 32)); } void MacroAssembler::repatchFarJump(uint8_t* code, uint32_t farJumpOffset, uint32_t targetOffset) { - MOZ_CRASH("NYI"); + MOZ_CRASH("Unimplemented - never used"); } CodeOffset MacroAssembler::nopPatchableToNearJump() { - MOZ_CRASH("NYI"); + MOZ_CRASH("Unimplemented - never used"); } void MacroAssembler::patchNopToNearJump(uint8_t* jump, uint8_t* target) { - MOZ_CRASH("NYI"); + MOZ_CRASH("Unimplemented - never used"); } void MacroAssembler::patchNearJumpToNop(uint8_t* jump) { - MOZ_CRASH("NYI"); + MOZ_CRASH("Unimplemented - never used"); } CodeOffset MacroAssembler::nopPatchableToCall(const wasm::CallSiteDesc& desc) { - MOZ_CRASH("NYI"); - return CodeOffset(); + CodeOffset offset(currentOffset()); + Nop(); + append(desc, CodeOffset(currentOffset())); + return offset; } void MacroAssembler::patchNopToCall(uint8_t* call, uint8_t* target) { - MOZ_CRASH("NYI"); + uint8_t* inst = call - 4; + Instruction* instr = reinterpret_cast(inst); + MOZ_ASSERT(instr->IsBL() || instr->IsNOP()); + bl(instr, (target - inst) >> 2); + AutoFlushICache::flush(uintptr_t(inst), 4); } void MacroAssembler::patchCallToNop(uint8_t* call) { - MOZ_CRASH("NYI"); + uint8_t* inst = call - 4; + Instruction* instr = reinterpret_cast(inst); + MOZ_ASSERT(instr->IsBL() || instr->IsNOP()); + nop(instr); + AutoFlushICache::flush(uintptr_t(inst), 4); } void MacroAssembler::pushReturnAddress() { + MOZ_RELEASE_ASSERT(!sp.Is(GetStackPointer64()), "Not valid"); push(lr); } void MacroAssembler::popReturnAddress() { + MOZ_RELEASE_ASSERT(!sp.Is(GetStackPointer64()), "Not valid"); pop(lr); } @@ -909,81 +1119,203 @@ MacroAssembler::comment(const char* msg) CodeOffset MacroAssembler::wasmTrapInstruction() { - MOZ_CRASH("NYI"); + CodeOffset offs(currentOffset()); + Unreachable(); + return offs; } +// FCVTZU behaves as follows: +// +// on NaN it produces zero +// on too large it produces UINT_MAX (for appropriate type) +// on too small it produces zero +// +// FCVTZS behaves as follows: +// +// on NaN it produces zero +// on too large it produces INT_MAX (for appropriate type) +// on too small it produces INT_MIN (ditto) + void -MacroAssembler::wasmTruncateDoubleToUInt32(FloatRegister input, Register output, +MacroAssembler::wasmTruncateDoubleToUInt32(FloatRegister input_, Register output_, bool isSaturating, Label* oolEntry) { - MOZ_CRASH("NYI"); + ARMRegister output(output_, 32); + ARMFPRegister input(input_, 64); + Fcvtzu(output, input); + if (!isSaturating) { + Cmp(output, 0); + Ccmp(output, -1, vixl::ZFlag, Assembler::NotEqual); + B(oolEntry, Assembler::Equal); + } } void -MacroAssembler::wasmTruncateDoubleToInt32(FloatRegister input, Register output, - bool isSaturating, Label* oolEntry) -{ - MOZ_CRASH("NYI"); -} - -void -MacroAssembler::wasmTruncateFloat32ToUInt32(FloatRegister input, Register output, +MacroAssembler::wasmTruncateFloat32ToUInt32(FloatRegister input_, Register output_, bool isSaturating, Label* oolEntry) { - MOZ_CRASH("NYI"); + ARMRegister output(output_, 32); + ARMFPRegister input(input_, 32); + Fcvtzu(output, input); + if (!isSaturating) { + Cmp(output, 0); + Ccmp(output, -1, vixl::ZFlag, Assembler::NotEqual); + B(oolEntry, Assembler::Equal); + } } void -MacroAssembler::wasmTruncateFloat32ToInt32(FloatRegister input, Register output, +MacroAssembler::wasmTruncateDoubleToInt32(FloatRegister input_, Register output_, + bool isSaturating, Label* oolEntry) +{ + ARMRegister output(output_, 32); + ARMFPRegister input(input_, 64); + Fcvtzs(output, input); + if (!isSaturating) { + Cmp(output, 0); + Ccmp(output, INT32_MAX, vixl::ZFlag, Assembler::NotEqual); + Ccmp(output, INT32_MIN, vixl::ZFlag, Assembler::NotEqual); + B(oolEntry, Assembler::Equal); + } +} + +void +MacroAssembler::wasmTruncateFloat32ToInt32(FloatRegister input_, Register output_, bool isSaturating, Label* oolEntry) { - MOZ_CRASH("NYI"); + ARMRegister output(output_, 32); + ARMFPRegister input(input_, 32); + Fcvtzs(output, input); + if (!isSaturating) { + Cmp(output, 0); + Ccmp(output, INT32_MAX, vixl::ZFlag, Assembler::NotEqual); + Ccmp(output, INT32_MIN, vixl::ZFlag, Assembler::NotEqual); + B(oolEntry, Assembler::Equal); + } } void -MacroAssembler::wasmTruncateDoubleToInt64(FloatRegister input, Register64 output, - bool isSaturating, Label* oolEntry, - Label* oolRejoin, FloatRegister tempDouble) -{ - MOZ_CRASH("NYI"); -} - -void -MacroAssembler::wasmTruncateDoubleToUInt64(FloatRegister input, Register64 output, +MacroAssembler::wasmTruncateDoubleToUInt64(FloatRegister input_, Register64 output_, bool isSaturating, Label* oolEntry, Label* oolRejoin, FloatRegister tempDouble) { - MOZ_CRASH("NYI"); + MOZ_ASSERT(tempDouble == InvalidFloatReg); + + ARMRegister output(output_.reg, 64); + ARMFPRegister input(input_, 64); + Fcvtzu(output, input); + if (!isSaturating) { + Cmp(output, 0); + Ccmp(output, -1, vixl::ZFlag, Assembler::NotEqual); + B(oolEntry, Assembler::Equal); + bind(oolRejoin); + } } void -MacroAssembler::wasmTruncateFloat32ToInt64(FloatRegister input, Register64 output, - bool isSaturating, Label* oolEntry, - Label* oolRejoin, FloatRegister tempDouble) -{ - MOZ_CRASH("NYI"); -} - -void -MacroAssembler::wasmTruncateFloat32ToUInt64(FloatRegister input, Register64 output, +MacroAssembler::wasmTruncateFloat32ToUInt64(FloatRegister input_, Register64 output_, bool isSaturating, Label* oolEntry, Label* oolRejoin, FloatRegister tempDouble) { - MOZ_CRASH("NYI"); + MOZ_ASSERT(tempDouble == InvalidFloatReg); + + ARMRegister output(output_.reg, 64); + ARMFPRegister input(input_, 32); + Fcvtzu(output, input); + if (!isSaturating) { + Cmp(output, 0); + Ccmp(output, -1, vixl::ZFlag, Assembler::NotEqual); + B(oolEntry, Assembler::Equal); + bind(oolRejoin); + } +} + +void +MacroAssembler::wasmTruncateDoubleToInt64(FloatRegister input_, Register64 output_, + bool isSaturating, Label* oolEntry, + Label* oolRejoin, FloatRegister tempDouble) +{ + MOZ_ASSERT(tempDouble == InvalidFloatReg); + + ARMRegister output(output_.reg, 64); + ARMFPRegister input(input_, 64); + Fcvtzs(output, input); + if (!isSaturating) { + Cmp(output, 0); + Ccmp(output, INT64_MAX, vixl::ZFlag, Assembler::NotEqual); + Ccmp(output, INT64_MIN, vixl::ZFlag, Assembler::NotEqual); + B(oolEntry, Assembler::Equal); + bind(oolRejoin); + } +} + +void +MacroAssembler::wasmTruncateFloat32ToInt64(FloatRegister input_, Register64 output_, + bool isSaturating, Label* oolEntry, + Label* oolRejoin, FloatRegister tempDouble) +{ + ARMRegister output(output_.reg, 64); + ARMFPRegister input(input_, 32); + Fcvtzs(output, input); + if (!isSaturating) { + Cmp(output, 0); + Ccmp(output, INT64_MAX, vixl::ZFlag, Assembler::NotEqual); + Ccmp(output, INT64_MIN, vixl::ZFlag, Assembler::NotEqual); + B(oolEntry, Assembler::Equal); + bind(oolRejoin); + } } void MacroAssembler::oolWasmTruncateCheckF32ToI32(FloatRegister input, Register output, TruncFlags flags, wasm::BytecodeOffset off, Label* rejoin) { - MOZ_CRASH("NYI"); + Label notNaN; + branchFloat(Assembler::DoubleOrdered, input, input, ¬NaN); + wasmTrap(wasm::Trap::InvalidConversionToInteger, off); + bind(¬NaN); + + Label isOverflow; + const float two_31 = -float(INT32_MIN); + if (flags & TRUNC_UNSIGNED) { + loadConstantFloat32(two_31 * 2, ScratchFloat32Reg); + branchFloat(Assembler::DoubleGreaterThanOrEqual, input, ScratchFloat32Reg, &isOverflow); + loadConstantFloat32(-1.0f, ScratchFloat32Reg); + branchFloat(Assembler::DoubleGreaterThan, input, ScratchFloat32Reg, rejoin); + } else { + loadConstantFloat32(two_31, ScratchFloat32Reg); + branchFloat(Assembler::DoubleGreaterThanOrEqual, input, ScratchFloat32Reg, &isOverflow); + loadConstantFloat32(-two_31, ScratchFloat32Reg); + branchFloat(Assembler::DoubleGreaterThanOrEqual, input, ScratchFloat32Reg, rejoin); + } + bind(&isOverflow); + wasmTrap(wasm::Trap::IntegerOverflow, off); } void MacroAssembler::oolWasmTruncateCheckF64ToI32(FloatRegister input, Register output, TruncFlags flags, wasm::BytecodeOffset off, Label* rejoin) { - MOZ_CRASH("NYI"); + Label notNaN; + branchDouble(Assembler::DoubleOrdered, input, input, ¬NaN); + wasmTrap(wasm::Trap::InvalidConversionToInteger, off); + bind(¬NaN); + + Label isOverflow; + const double two_31 = -double(INT32_MIN); + if (flags & TRUNC_UNSIGNED) { + loadConstantDouble(two_31 * 2, ScratchDoubleReg); + branchDouble(Assembler::DoubleGreaterThanOrEqual, input, ScratchDoubleReg, &isOverflow); + loadConstantDouble(-1.0, ScratchDoubleReg); + branchDouble(Assembler::DoubleGreaterThan, input, ScratchDoubleReg, rejoin); + } else { + loadConstantDouble(two_31, ScratchDoubleReg); + branchDouble(Assembler::DoubleGreaterThanOrEqual, input, ScratchDoubleReg, &isOverflow); + loadConstantDouble(-two_31 - 1, ScratchDoubleReg); + branchDouble(Assembler::DoubleGreaterThan, input, ScratchDoubleReg, rejoin); + } + bind(&isOverflow); + wasmTrap(wasm::Trap::IntegerOverflow, off); } void @@ -991,7 +1323,26 @@ MacroAssembler::oolWasmTruncateCheckF32ToI64(FloatRegister input, Register64 out TruncFlags flags, wasm::BytecodeOffset off, Label* rejoin) { - MOZ_CRASH("NYI"); + Label notNaN; + branchFloat(Assembler::DoubleOrdered, input, input, ¬NaN); + wasmTrap(wasm::Trap::InvalidConversionToInteger, off); + bind(¬NaN); + + Label isOverflow; + const float two_63 = -float(INT64_MIN); + if (flags & TRUNC_UNSIGNED) { + loadConstantFloat32(two_63 * 2, ScratchFloat32Reg); + branchFloat(Assembler::DoubleGreaterThanOrEqual, input, ScratchFloat32Reg, &isOverflow); + loadConstantFloat32(-1.0f, ScratchFloat32Reg); + branchFloat(Assembler::DoubleGreaterThan, input, ScratchFloat32Reg, rejoin); + } else { + loadConstantFloat32(two_63, ScratchFloat32Reg); + branchFloat(Assembler::DoubleGreaterThanOrEqual, input, ScratchFloat32Reg, &isOverflow); + loadConstantFloat32(-two_63, ScratchFloat32Reg); + branchFloat(Assembler::DoubleGreaterThanOrEqual, input, ScratchFloat32Reg, rejoin); + } + bind(&isOverflow); + wasmTrap(wasm::Trap::IntegerOverflow, off); } void @@ -999,7 +1350,54 @@ MacroAssembler::oolWasmTruncateCheckF64ToI64(FloatRegister input, Register64 out TruncFlags flags, wasm::BytecodeOffset off, Label* rejoin) { - MOZ_CRASH("NYI"); + Label notNaN; + branchDouble(Assembler::DoubleOrdered, input, input, ¬NaN); + wasmTrap(wasm::Trap::InvalidConversionToInteger, off); + bind(¬NaN); + + Label isOverflow; + const double two_63 = -double(INT64_MIN); + if (flags & TRUNC_UNSIGNED) { + loadConstantDouble(two_63 * 2, ScratchDoubleReg); + branchDouble(Assembler::DoubleGreaterThanOrEqual, input, ScratchDoubleReg, &isOverflow); + loadConstantDouble(-1.0, ScratchDoubleReg); + branchDouble(Assembler::DoubleGreaterThan, input, ScratchDoubleReg, rejoin); + } else { + loadConstantDouble(two_63, ScratchDoubleReg); + branchDouble(Assembler::DoubleGreaterThanOrEqual, input, ScratchDoubleReg, &isOverflow); + loadConstantDouble(-two_63, ScratchDoubleReg); + branchDouble(Assembler::DoubleGreaterThanOrEqual, input, ScratchDoubleReg, rejoin); + } + bind(&isOverflow); + wasmTrap(wasm::Trap::IntegerOverflow, off); +} + +void +MacroAssembler::wasmLoad(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, + Register ptrScratch, AnyRegister output) +{ + wasmLoadImpl(access, memoryBase, ptr, ptrScratch, output, Register64::Invalid()); +} + +void +MacroAssembler::wasmLoadI64(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, + Register ptrScratch, Register64 output) +{ + wasmLoadImpl(access, memoryBase, ptr, ptrScratch, AnyRegister(), output); +} + +void +MacroAssembler::wasmStore(const wasm::MemoryAccessDesc& access, AnyRegister value, + Register memoryBase, Register ptr, Register ptrScratch) +{ + wasmStoreImpl(access, value, Register64::Invalid(), memoryBase, ptr, ptrScratch); +} + +void +MacroAssembler::wasmStoreI64(const wasm::MemoryAccessDesc& access, Register64 value, + Register memoryBase, Register ptr, Register ptrScratch) +{ + wasmStoreImpl(access, AnyRegister(), value, memoryBase, ptr, ptrScratch); } // ======================================================================== @@ -1040,100 +1438,335 @@ MacroAssembler::convertInt64ToFloat32(Register64 src, FloatRegister dest) // ======================================================================== // Primitive atomic operations. +// The computed MemOperand must be Reg+0 because the load/store exclusive +// instructions only take a single pointer register. + +enum class Width { + _32 = 32, + _64 = 64 +}; + +static inline ARMRegister +X(Register r) { + return ARMRegister(r, 64); +} + +static inline ARMRegister +X(MacroAssembler& masm, RegisterOrSP r) { + return masm.toARMRegister(r, 64); +} + +static inline ARMRegister +W(Register r) { + return ARMRegister(r, 32); +} + +static inline ARMRegister +R(Register r, Width w) { + return ARMRegister(r, unsigned(w)); +} + +static MemOperand +ComputePointerForAtomic(MacroAssembler& masm, const Address& address, Register scratch) +{ + if (address.offset == 0) + return MemOperand(X(masm, address.base), 0); + + masm.Add(X(scratch), X(masm, address.base), address.offset); + return MemOperand(X(scratch), 0); +} + +static MemOperand +ComputePointerForAtomic(MacroAssembler& masm, const BaseIndex& address, Register scratch) +{ + masm.Add(X(scratch), X(masm, address.base), Operand(X(address.index), vixl::LSL, address.scale)); + if (address.offset) + masm.Add(X(scratch), X(scratch), address.offset); + return MemOperand(X(scratch), 0); +} + +// This sign extends to targetWidth and leaves any higher bits zero. + +static void +SignOrZeroExtend(MacroAssembler& masm, Scalar::Type srcType, Width targetWidth, Register src, + Register dest) +{ + bool signExtend = Scalar::isSignedIntType(srcType); + + switch (Scalar::byteSize(srcType)) { + case 1: + if (signExtend) + masm.Sbfm(R(dest, targetWidth), R(src, targetWidth), 0, 7); + else + masm.Ubfm(R(dest, targetWidth), R(src, targetWidth), 0, 7); + break; + case 2: + if (signExtend) + masm.Sbfm(R(dest, targetWidth), R(src, targetWidth), 0, 15); + else + masm.Ubfm(R(dest, targetWidth), R(src, targetWidth), 0, 15); + break; + case 4: + if (targetWidth == Width::_64) { + if (signExtend) + masm.Sbfm(X(dest), X(src), 0, 31); + else + masm.Ubfm(X(dest), X(src), 0, 31); + } else if (src != dest) { + masm.Mov(R(dest, targetWidth), R(src, targetWidth)); + } + break; + case 8: + if (src != dest) + masm.Mov(R(dest, targetWidth), R(src, targetWidth)); + break; + default: + MOZ_CRASH(); + } +} + +// Exclusive-loads zero-extend their values to the full width of the X register. +// +// Note, we've promised to leave the high bits of the 64-bit register clear if +// the targetWidth is 32. + +static void +LoadExclusive(MacroAssembler& masm, Scalar::Type srcType, Width targetWidth, MemOperand ptr, + Register dest) +{ + bool signExtend = Scalar::isSignedIntType(srcType); + + switch (Scalar::byteSize(srcType)) { + case 1: + masm.Ldxrb(W(dest), ptr); + if (signExtend) + masm.Sbfm(R(dest, targetWidth), R(dest, targetWidth), 0, 7); + break; + case 2: + masm.Ldxrh(W(dest), ptr); + if (signExtend) + masm.Sbfm(R(dest, targetWidth), R(dest, targetWidth), 0, 15); + break; + case 4: + masm.Ldxr(W(dest), ptr); + if (targetWidth == Width::_64 && signExtend) + masm.Sbfm(X(dest), X(dest), 0, 31); + break; + case 8: + masm.Ldxr(X(dest), ptr); + break; + default: + MOZ_CRASH(); + } +} + +static void +StoreExclusive(MacroAssembler& masm, Scalar::Type type, Register status, Register src, + MemOperand ptr) +{ + switch (Scalar::byteSize(type)) { + case 1: + masm.Stxrb(W(status), W(src), ptr); + break; + case 2: + masm.Stxrh(W(status), W(src), ptr); + break; + case 4: + masm.Stxr(W(status), W(src), ptr); + break; + case 8: + masm.Stxr(W(status), X(src), ptr); + break; + } +} + +template +static void +CompareExchange(MacroAssembler& masm, Scalar::Type type, Width targetWidth, + const Synchronization& sync, const T& mem, Register oldval, + Register newval, Register output) +{ + Label again; + Label done; + + vixl::UseScratchRegisterScope temps(&masm); + + Register scratch2 = temps.AcquireX().asUnsized(); + MemOperand ptr = ComputePointerForAtomic(masm, mem, scratch2); + + masm.memoryBarrierBefore(sync); + + Register scratch = temps.AcquireX().asUnsized(); + + masm.bind(&again); + SignOrZeroExtend(masm, type, targetWidth, oldval, scratch); + LoadExclusive(masm, type, targetWidth, ptr, output); + masm.Cmp(R(output, targetWidth), R(scratch, targetWidth)); + masm.B(&done, MacroAssembler::NotEqual); + StoreExclusive(masm, type, scratch, newval, ptr); + masm.Cbnz(W(scratch), &again); + masm.bind(&done); + + masm.memoryBarrierAfter(sync); +} + +template +static void +AtomicExchange(MacroAssembler& masm, Scalar::Type type, Width targetWidth, + const Synchronization& sync, const T& mem, Register value, + Register output) +{ + Label again; + + vixl::UseScratchRegisterScope temps(&masm); + + Register scratch2 = temps.AcquireX().asUnsized(); + MemOperand ptr = ComputePointerForAtomic(masm, mem, scratch2); + + masm.memoryBarrierBefore(sync); + + Register scratch = temps.AcquireX().asUnsized(); + + masm.bind(&again); + LoadExclusive(masm, type, targetWidth, ptr, output); + StoreExclusive(masm, type, scratch, value, ptr); + masm.Cbnz(W(scratch), &again); + + masm.memoryBarrierAfter(sync); +} + +template +static void +AtomicFetchOp(MacroAssembler& masm, Scalar::Type type, Width targetWidth, + const Synchronization& sync, AtomicOp op, const T& mem, + Register value, Register temp, Register output) +{ + Label again; + + vixl::UseScratchRegisterScope temps(&masm); + + Register scratch2 = temps.AcquireX().asUnsized(); + MemOperand ptr = ComputePointerForAtomic(masm, mem, scratch2); + + masm.memoryBarrierBefore(sync); + + Register scratch = temps.AcquireX().asUnsized(); + + masm.bind(&again); + LoadExclusive(masm, type, targetWidth, ptr, output); + switch (op) { + case AtomicFetchAddOp: masm.Add(X(temp), X(output), X(value)); break; + case AtomicFetchSubOp: masm.Sub(X(temp), X(output), X(value)); break; + case AtomicFetchAndOp: masm.And(X(temp), X(output), X(value)); break; + case AtomicFetchOrOp: masm.Orr(X(temp), X(output), X(value)); break; + case AtomicFetchXorOp: masm.Eor(X(temp), X(output), X(value)); break; + } + StoreExclusive(masm, type, scratch, temp, ptr); + masm.Cbnz(W(scratch), &again); + if (wantResult) + SignOrZeroExtend(masm, type, targetWidth, output, output); + + masm.memoryBarrierAfter(sync); +} + void MacroAssembler::compareExchange(Scalar::Type type, const Synchronization& sync, const Address& mem, Register oldval, Register newval, Register output) { - MOZ_CRASH("NYI"); + CompareExchange(*this, type, Width::_32, sync, mem, oldval, newval, output); } void MacroAssembler::compareExchange(Scalar::Type type, const Synchronization& sync, const BaseIndex& mem, Register oldval, Register newval, Register output) { - MOZ_CRASH("NYI"); + CompareExchange(*this, type, Width::_32, sync, mem, oldval, newval, output); } void MacroAssembler::atomicExchange(Scalar::Type type, const Synchronization& sync, const Address& mem, Register value, Register output) { - MOZ_CRASH("NYI"); + AtomicExchange(*this, type, Width::_32, sync, mem, value, output); } void MacroAssembler::atomicExchange(Scalar::Type type, const Synchronization& sync, const BaseIndex& mem, Register value, Register output) { - MOZ_CRASH("NYI"); + AtomicExchange(*this, type, Width::_32, sync, mem, value, output); } void MacroAssembler::atomicFetchOp(Scalar::Type type, const Synchronization& sync, AtomicOp op, Register value, const Address& mem, Register temp, Register output) { - MOZ_CRASH("NYI"); + AtomicFetchOp(*this, type, Width::_32, sync, op, mem, value, temp, output); } void MacroAssembler::atomicFetchOp(Scalar::Type type, const Synchronization& sync, AtomicOp op, Register value, const BaseIndex& mem, Register temp, Register output) { - MOZ_CRASH("NYI"); + AtomicFetchOp(*this, type, Width::_32, sync, op, mem, value, temp, output); } void MacroAssembler::atomicEffectOp(Scalar::Type type, const Synchronization& sync, AtomicOp op, Register value, const Address& mem, Register temp) { - MOZ_CRASH("NYI"); + AtomicFetchOp(*this, type, Width::_32, sync, op, mem, value, temp, temp); } void MacroAssembler::atomicEffectOp(Scalar::Type type, const Synchronization& sync, AtomicOp op, Register value, const BaseIndex& mem, Register temp) { - MOZ_CRASH("NYI"); + AtomicFetchOp(*this, type, Width::_32, sync, op, mem, value, temp, temp); } void MacroAssembler::compareExchange64(const Synchronization& sync, const Address& mem, Register64 expect, Register64 replace, Register64 output) { - MOZ_CRASH("NYI"); + CompareExchange(*this, Scalar::Int64, Width::_64, sync, mem, expect.reg, replace.reg, output.reg); } void MacroAssembler::compareExchange64(const Synchronization& sync, const BaseIndex& mem, Register64 expect, Register64 replace, Register64 output) { - MOZ_CRASH("NYI"); + CompareExchange(*this, Scalar::Int64, Width::_64, sync, mem, expect.reg, replace.reg, output.reg); } void -MacroAssembler::atomicExchange64(const Synchronization& sync, const Address& mem, Register64 value, Register64 output) +MacroAssembler::atomicExchange64(const Synchronization& sync, const Address& mem, Register64 value, + Register64 output) { - MOZ_CRASH("NYI"); + AtomicExchange(*this, Scalar::Int64, Width::_64, sync, mem, value.reg, output.reg); } void -MacroAssembler::atomicExchange64(const Synchronization& sync, const BaseIndex& mem, Register64 value, Register64 output) +MacroAssembler::atomicExchange64(const Synchronization& sync, const BaseIndex& mem, Register64 value, + Register64 output) { - MOZ_CRASH("NYI"); + AtomicExchange(*this, Scalar::Int64, Width::_64, sync, mem, value.reg, output.reg); } void -MacroAssembler::atomicFetchOp64(const Synchronization& sync, AtomicOp op, Register64 value, const Address& mem, - Register64 temp, Register64 output) +MacroAssembler::atomicFetchOp64(const Synchronization& sync, AtomicOp op, Register64 value, + const Address& mem, Register64 temp, Register64 output) { - MOZ_CRASH("NYI"); + AtomicFetchOp(*this, Scalar::Int64, Width::_64, sync, op, mem, value.reg, temp.reg, + output.reg); } void -MacroAssembler::atomicFetchOp64(const Synchronization& sync, AtomicOp op, Register64 value, const BaseIndex& mem, - Register64 temp, Register64 output) +MacroAssembler::atomicFetchOp64(const Synchronization& sync, AtomicOp op, Register64 value, + const BaseIndex& mem, Register64 temp, Register64 output) { - MOZ_CRASH("NYI"); + AtomicFetchOp(*this, Scalar::Int64, Width::_64, sync, op, mem, value.reg, temp.reg, + output.reg); } // ======================================================================== diff --git a/js/src/jit/arm64/MacroAssembler-arm64.h b/js/src/jit/arm64/MacroAssembler-arm64.h index 3f0d4c4c73af..8fe51e9c73e5 100644 --- a/js/src/jit/arm64/MacroAssembler-arm64.h +++ b/js/src/jit/arm64/MacroAssembler-arm64.h @@ -40,6 +40,8 @@ struct ImmTag : public Imm32 { } }; +class ScratchTagScope; + class MacroAssemblerCompat : public vixl::MacroAssembler { public: @@ -516,12 +518,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler } using vixl::MacroAssembler::B; - void B(wasm::OldTrapDesc) { - MOZ_CRASH("NYI"); - } - void B(wasm::OldTrapDesc, Condition cond) { - MOZ_CRASH("NYI"); - } + void B(wasm::OldTrapDesc, Condition cond = Always); void convertDoubleToInt32(FloatRegister src, Register dest, Label* fail, bool negativeZeroCheck = true) @@ -697,7 +694,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler Br(vixl::ip0); } void jump(wasm::OldTrapDesc target) { - MOZ_CRASH("NYI"); + B(target); } void align(int alignment) { @@ -710,7 +707,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler armbuffer_.align(alignment); } void nopAlign(int alignment) { - MOZ_CRASH("NYI"); + armbuffer_.align(alignment); } void movePtr(Register src, Register dest) { @@ -1183,14 +1180,8 @@ class MacroAssemblerCompat : public vixl::MacroAssembler splitTag(dest, dest); } - // Extracts the tag of a value and places it in ScratchReg. - Register splitTagForTest(const ValueOperand& value) { - vixl::UseScratchRegisterScope temps(this); - const ARMRegister scratch64 = temps.AcquireX(); - MOZ_ASSERT(scratch64.asUnsized() != value.valueReg()); - Lsr(scratch64, ARMRegister(value.valueReg(), 64), JSVAL_TAG_SHIFT); - return scratch64.asUnsized(); // FIXME: Surely we can make a better interface. - } + // Extracts the tag of a value and places it in tag + inline void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag); void cmpTag(const ValueOperand& operand, ImmTag tag) { MOZ_CRASH("cmpTag"); } @@ -1400,7 +1391,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler } void unboxPrivate(const ValueOperand& src, Register dest) { - ubfx(ARMRegister(dest, 64), ARMRegister(src.valueReg(), 64), 1, JSVAL_TAG_SHIFT - 1); + Lsl(ARMRegister(dest, 64), ARMRegister(src.valueReg(), 64), 1); } void notBoolean(const ValueOperand& val) { @@ -1930,6 +1921,13 @@ class MacroAssemblerCompat : public vixl::MacroAssembler return value; } + void wasmLoadImpl(const wasm::MemoryAccessDesc& access, Register memoryBase, + Register ptr, Register ptrScratch, AnyRegister outany, + Register64 out64); + void wasmStoreImpl(const wasm::MemoryAccessDesc& access, AnyRegister valany, + Register64 val64, Register memoryBase, Register ptr, + Register ptrScratch); + // Emit a BLR or NOP instruction. ToggleCall can be used to patch // this instruction. CodeOffset toggledCall(JitCode* target, bool enabled) { @@ -2101,6 +2099,64 @@ class MacroAssemblerCompat : public vixl::MacroAssembler } }; +// See documentation for ScratchTagScope and ScratchTagScopeRelease in +// MacroAssembler-x64.h. + +class ScratchTagScope +{ + vixl::UseScratchRegisterScope temps_; + ARMRegister scratch64_; + bool owned_; + mozilla::DebugOnly released_; + + public: + ScratchTagScope(MacroAssemblerCompat& masm, const ValueOperand&) + : temps_(&masm), + owned_(true), + released_(false) + { + scratch64_ = temps_.AcquireX(); + } + + operator Register() { + MOZ_ASSERT(!released_); + return scratch64_.asUnsized(); + } + + void release() { + MOZ_ASSERT(!released_); + released_ = true; + if (owned_) { + temps_.Release(scratch64_); + owned_ = false; + } + } + + void reacquire() { + MOZ_ASSERT(released_); + released_ = false; + } +}; + +class ScratchTagScopeRelease +{ + ScratchTagScope* ts_; + + public: + explicit ScratchTagScopeRelease(ScratchTagScope* ts) : ts_(ts) { + ts_->release(); + } + ~ScratchTagScopeRelease() { + ts_->reacquire(); + } +}; + +inline void +MacroAssemblerCompat::splitTagForTest(const ValueOperand& value, ScratchTagScope& tag) +{ + splitTag(value, tag); +} + typedef MacroAssemblerCompat MacroAssemblerSpecific; } // namespace jit diff --git a/js/src/jit/arm64/vixl/Assembler-vixl.h b/js/src/jit/arm64/vixl/Assembler-vixl.h index 3f1d659f83aa..21e0c34ba599 100644 --- a/js/src/jit/arm64/vixl/Assembler-vixl.h +++ b/js/src/jit/arm64/vixl/Assembler-vixl.h @@ -951,7 +951,38 @@ class Assembler : public MozBaseAssembler { } static inline DoubleCondition InvertCondition(DoubleCondition cond) { - MOZ_CRASH("Not yet implemented: InvertCondition(DoubleCondition)"); + switch (cond) { + case DoubleOrdered: + return DoubleUnordered; + case DoubleEqual: + return DoubleNotEqualOrUnordered; + case DoubleNotEqual: + return DoubleEqualOrUnordered; + case DoubleGreaterThan: + return DoubleLessThanOrEqualOrUnordered; + case DoubleGreaterThanOrEqual: + return DoubleLessThanOrUnordered; + case DoubleLessThan: + return DoubleGreaterThanOrEqualOrUnordered; + case DoubleLessThanOrEqual: + return DoubleGreaterThanOrUnordered; + case DoubleUnordered: + return DoubleOrdered; + case DoubleEqualOrUnordered: + return DoubleNotEqual; + case DoubleNotEqualOrUnordered: + return DoubleEqual; + case DoubleGreaterThanOrUnordered: + return DoubleLessThanOrEqual; + case DoubleGreaterThanOrEqualOrUnordered: + return DoubleLessThan; + case DoubleLessThanOrUnordered: + return DoubleGreaterThanOrEqual; + case DoubleLessThanOrEqualOrUnordered: + return DoubleGreaterThan; + default: + MOZ_CRASH("Bad condition"); + } } static inline Condition ConditionFromDoubleCondition(DoubleCondition cond) { diff --git a/js/src/jit/arm64/vixl/Instructions-vixl.h b/js/src/jit/arm64/vixl/Instructions-vixl.h index d55b6d75d057..b3664fd19dd5 100644 --- a/js/src/jit/arm64/vixl/Instructions-vixl.h +++ b/js/src/jit/arm64/vixl/Instructions-vixl.h @@ -311,6 +311,8 @@ class Instruction { bool IsNOP() const; bool IsADR() const; bool IsADRP() const; + bool IsMovz() const; + bool IsMovk() const; bool IsBranchLinkImm() const; bool IsTargetReachable(Instruction* target) const; ptrdiff_t ImmPCRawOffset() const; diff --git a/js/src/jit/arm64/vixl/MacroAssembler-vixl.h b/js/src/jit/arm64/vixl/MacroAssembler-vixl.h index b27a7102c42f..b3735e5ee9f3 100644 --- a/js/src/jit/arm64/vixl/MacroAssembler-vixl.h +++ b/js/src/jit/arm64/vixl/MacroAssembler-vixl.h @@ -1480,9 +1480,25 @@ class MacroAssembler : public js::jit::Assembler { #ifdef JS_SIMULATOR_ARM64 hlt(kUnreachableOpcode); #else - // Branch to 0 to generate a segfault. - // lr - kInstructionSize is the address of the offending instruction. - blr(xzr); + // A couple of strategies we can use here. There are no unencoded + // instructions in the instruction set that are guaranteed to remain that + // way. However there are some currently (as of 2018) unencoded + // instructions that are good candidates. + // + // Ideally, unencoded instructions should be non-destructive to the register + // state, and should be unencoded at all exception levels. + // + // At the trap the pc will hold the address of the offending instruction. + + // Some candidates for unencoded instructions: + // + // 0xd4a00000 (essentially dcps0, a good one since it is nonsensical and may + // remain unencoded in the future for that reason) + // 0x33000000 (bfm variant) + // 0xd67f0000 (br variant) + // 0x5ac00c00 (rbit variant) + + Emit(0xd4a00000); // "dcps0", also has 16-bit payload if needed #endif } void Uxtb(const Register& rd, const Register& rn) { diff --git a/js/src/jit/arm64/vixl/MozAssembler-vixl.cpp b/js/src/jit/arm64/vixl/MozAssembler-vixl.cpp index 790dda197323..6b4c54bcb42d 100644 --- a/js/src/jit/arm64/vixl/MozAssembler-vixl.cpp +++ b/js/src/jit/arm64/vixl/MozAssembler-vixl.cpp @@ -389,12 +389,12 @@ void Assembler::ldr(Instruction* at, const CPURegister& rt, int imm19) { BufferOffset Assembler::hint(SystemHint code) { - return Emit(HINT | ImmHint(code) | Rt(xzr)); + return Emit(HINT | ImmHint(code)); } void Assembler::hint(Instruction* at, SystemHint code) { - Emit(at, HINT | ImmHint(code) | Rt(xzr)); + Emit(at, HINT | ImmHint(code)); } diff --git a/js/src/jit/arm64/vixl/MozBaseAssembler-vixl.h b/js/src/jit/arm64/vixl/MozBaseAssembler-vixl.h index 3289e4b37093..0b14c057d985 100644 --- a/js/src/jit/arm64/vixl/MozBaseAssembler-vixl.h +++ b/js/src/jit/arm64/vixl/MozBaseAssembler-vixl.h @@ -59,8 +59,8 @@ class MozBaseAssembler : public js::jit::AssemblerShared { static const size_t BufferCodeAlignment = 8; static const size_t BufferMaxPoolOffset = 1024; static const unsigned BufferPCBias = 0; - static const uint32_t BufferAlignmentFillInstruction = BRK | (0xdead << ImmException_offset); - static const uint32_t BufferNopFillInstruction = HINT | (31 << Rt_offset); + static const uint32_t BufferAlignmentFillInstruction = HINT | (NOP << ImmHint_offset); + static const uint32_t BufferNopFillInstruction = HINT | (NOP << ImmHint_offset); static const unsigned BufferNumDebugNopsToInsert = 0; #ifdef JS_DISASM_ARM64 diff --git a/js/src/jit/arm64/vixl/MozInstructions-vixl.cpp b/js/src/jit/arm64/vixl/MozInstructions-vixl.cpp index fcae1ba47fb1..8547341bf8af 100644 --- a/js/src/jit/arm64/vixl/MozInstructions-vixl.cpp +++ b/js/src/jit/arm64/vixl/MozInstructions-vixl.cpp @@ -95,6 +95,17 @@ bool Instruction::IsADRP() const { } +bool Instruction::IsMovz() const { + return (Mask(MoveWideImmediateMask) == MOVZ_x) || + (Mask(MoveWideImmediateMask) == MOVZ_w); +} + + +bool Instruction::IsMovk() const { + return (Mask(MoveWideImmediateMask) == MOVK_x) || + (Mask(MoveWideImmediateMask) == MOVK_w); +} + bool Instruction::IsBranchLinkImm() const { return Mask(UnconditionalBranchFMask) == (UnconditionalBranchFixed | BL); } diff --git a/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp b/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp index cb93d7111530..219f1cb9b049 100644 --- a/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp +++ b/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp @@ -33,15 +33,16 @@ #include "threading/LockGuard.h" #include "vm/Runtime.h" #include "wasm/WasmInstance.h" +#include "wasm/WasmProcess.h" #include "wasm/WasmSignalHandlers.h" js::jit::SimulatorProcess* js::jit::SimulatorProcess::singleton_ = nullptr; namespace vixl { - using mozilla::DebugOnly; using js::jit::ABIFunctionType; +using js::jit::JitActivation; using js::jit::SimulatorProcess; Simulator::Simulator(JSContext* cx, Decoder* decoder, FILE* stream) @@ -218,13 +219,13 @@ uintptr_t* Simulator::addressOfStackLimit() { bool Simulator::overRecursed(uintptr_t newsp) const { if (newsp) - newsp = xreg(31, Reg31IsStackPointer); + newsp = get_sp(); return newsp <= stackLimit(); } bool Simulator::overRecursedWithExtra(uint32_t extra) const { - uintptr_t newsp = xreg(31, Reg31IsStackPointer) - extra; + uintptr_t newsp = get_sp() - extra; return newsp <= stackLimit(); } @@ -235,31 +236,91 @@ void Simulator::trigger_wasm_interrupt() { } +static inline JitActivation* +GetJitActivation(JSContext* cx) +{ + if (!js::wasm::CodeExists) + return nullptr; + if (!cx->activation() || !cx->activation()->isJit()) + return nullptr; + return cx->activation()->asJit(); +} + +JS::ProfilingFrameIterator::RegisterState +Simulator::registerState() +{ + JS::ProfilingFrameIterator::RegisterState state; + state.pc = (uint8_t*) get_pc(); + state.fp = (uint8_t*) get_fp(); + state.lr = (uint8_t*) get_lr(); + state.sp = (uint8_t*) get_sp(); + return state; +} + // The signal handler only redirects the PC to the interrupt stub when the PC is // in function code. However, this guard is racy for the ARM simulator since the // signal handler samples PC in the middle of simulating an instruction and thus // the current PC may have advanced once since the signal handler's guard. So we // re-check here. -void Simulator::handle_wasm_interrupt() { +void Simulator::handle_wasm_interrupt() +{ + if (!js::wasm::CodeExists) + return; + uint8_t* pc = (uint8_t*)get_pc(); - uint8_t* fp = (uint8_t*)xreg(30); const js::wasm::ModuleSegment* ms = nullptr; if (!js::wasm::InInterruptibleCode(cx_, pc, &ms)) return; - JS::ProfilingFrameIterator::RegisterState state; - state.pc = pc; - state.fp = fp; - state.lr = (uint8_t*) xreg(30); - state.sp = (uint8_t*) xreg(31); + JitActivation* act = GetJitActivation(cx_); + if (!act) + return; - if (!cx_->activation_->asJit()->startWasmInterrupt(state)) + if (!act->startWasmInterrupt(registerState())) return; set_pc((Instruction*)ms->interruptCode()); } +bool +Simulator::handle_wasm_seg_fault(uintptr_t addr, unsigned numBytes) +{ + JitActivation* act = GetJitActivation(cx_); + if (!act) + return false; + + uint8_t* pc = (uint8_t*)get_pc(); + uint8_t* fp = (uint8_t*)get_fp(); + + const js::wasm::CodeSegment* segment = js::wasm::LookupCodeSegment(pc); + if (!segment) + return false; + const js::wasm::ModuleSegment* moduleSegment = segment->asModule(); + + js::wasm::Instance* instance = js::wasm::LookupFaultingInstance(*moduleSegment, pc, fp); + if (!instance) + return false; + + MOZ_RELEASE_ASSERT(&instance->code() == &moduleSegment->code()); + + if (!instance->memoryAccessInGuardRegion((uint8_t*)addr, numBytes)) + return false; + + const js::wasm::MemoryAccess* memoryAccess = instance->code().lookupMemoryAccess(pc); + if (!memoryAccess) { + if (!act->startWasmInterrupt(registerState())) + MOZ_CRASH("Cannot start interrupt"); + if (!instance->code().containsCodePC(pc)) + MOZ_CRASH("Cannot map PC to trap handler"); + set_pc((Instruction*)moduleSegment->outOfBoundsCode()); + return true; + } + + MOZ_ASSERT(memoryAccess->hasTrapOutOfLineCode()); + set_pc((Instruction*)memoryAccess->trapOutOfLineCode(moduleSegment->base())); + return true; +} int64_t Simulator::call(uint8_t* entry, int argument_count, ...) { va_list parameters; @@ -303,12 +364,12 @@ int64_t Simulator::call(uint8_t* entry, int argument_count, ...) { va_end(parameters); // Call must transition back to native code on exit. - VIXL_ASSERT(xreg(30) == int64_t(kEndOfSimAddress)); + VIXL_ASSERT(get_lr() == int64_t(kEndOfSimAddress)); // Execute the simulation. - DebugOnly entryStack = xreg(31, Reg31IsStackPointer); + DebugOnly entryStack = get_sp(); RunFrom((Instruction*)entry); - DebugOnly exitStack = xreg(31, Reg31IsStackPointer); + DebugOnly exitStack = get_sp(); VIXL_ASSERT(entryStack == exitStack); int64_t result = xreg(0); @@ -403,6 +464,29 @@ void* Simulator::RedirectNativeFunction(void* nativeFunction, ABIFunctionType ty return redirection->addressOfSvcInstruction(); } +bool +Simulator::handle_wasm_ill_fault() +{ + JitActivation* act = GetJitActivation(cx_); + if (!act) + return false; + + uint8_t* pc = (uint8_t*)get_pc(); + + const js::wasm::CodeSegment* segment = js::wasm::LookupCodeSegment(pc); + if (!segment || !segment->isModule()) + return false; + const js::wasm::ModuleSegment* moduleSegment = segment->asModule(); + + js::wasm::Trap trap; + js::wasm::BytecodeOffset bytecode; + if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode)) + return false; + + act->startWasmTrap(trap, bytecode.offset, registerState()); + set_pc((Instruction*)moduleSegment->trapCode()); + return true; +} void Simulator::VisitException(const Instruction* instr) { switch (instr->Mask(ExceptionMask)) { @@ -415,7 +499,8 @@ void Simulator::VisitException(const Instruction* instr) { case HLT: switch (instr->ImmException()) { case kUnreachableOpcode: - DoUnreachable(instr); + if (!handle_wasm_ill_fault()) + DoUnreachable(instr); return; case kTraceOpcode: DoTrace(instr); @@ -439,12 +524,12 @@ void Simulator::VisitException(const Instruction* instr) { return; case kMarkStackPointer: { js::AutoEnterOOMUnsafeRegion oomUnsafe; - if (!spStack_.append(xreg(31, Reg31IsStackPointer))) + if (!spStack_.append(get_sp())) oomUnsafe.crash("tracking stack for ARM64 simulator"); return; } case kCheckStackPointer: { - int64_t current = xreg(31, Reg31IsStackPointer); + int64_t current = get_sp(); int64_t expected = spStack_.popCopy(); VIXL_ASSERT(current == expected); return; @@ -492,6 +577,10 @@ typedef int64_t (*Prototype_General7)(int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg4, int64_t arg5, int64_t arg6); typedef int64_t (*Prototype_General8)(int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3, int64_t arg4, int64_t arg5, int64_t arg6, int64_t arg7); +typedef int64_t (*Prototype_GeneralGeneralGeneralInt64)(int64_t arg0, int32_t arg1, int32_t arg2, + int64_t arg3); +typedef int64_t (*Prototype_GeneralGeneralInt64Int64)(int64_t arg0, int32_t arg1, int64_t arg2, + int64_t arg3); typedef int64_t (*Prototype_Int_Double)(double arg0); typedef int64_t (*Prototype_Int_IntDouble)(int32_t arg0, double arg1); @@ -500,6 +589,7 @@ typedef int64_t (*Prototype_Int_IntDoubleIntInt)(uint64_t arg0, double arg1, uint64_t arg2, uint64_t arg3); typedef float (*Prototype_Float32_Float32)(float arg0); +typedef float (*Prototype_Float32_Float32Float32)(float arg0, float arg1); typedef double (*Prototype_Double_None)(); typedef double (*Prototype_Double_Double)(double arg0); @@ -538,7 +628,7 @@ Simulator::VisitCallRedirection(const Instruction* instr) DebugOnly x27 = xreg(27); DebugOnly x28 = xreg(28); DebugOnly x29 = xreg(29); - DebugOnly savedSP = xreg(31, Reg31IsStackPointer); + DebugOnly savedSP = get_sp(); // Remember LR for returning from the "call". int64_t savedLR = xreg(30); @@ -561,6 +651,7 @@ Simulator::VisitCallRedirection(const Instruction* instr) double d2 = dreg(2); double d3 = dreg(3); float s0 = sreg(0); + float s1 = sreg(1); // Dispatch the call and set the return value. switch (redir->type()) { @@ -610,6 +701,16 @@ Simulator::VisitCallRedirection(const Instruction* instr) setGPR64Result(ret); break; } + case js::jit::Args_Int_GeneralGeneralGeneralInt64: { + int64_t ret = reinterpret_cast(nativeFn)(x0, x1, x2, x3); + setGPR64Result(ret); + break; + } + case js::jit::Args_Int_GeneralGeneralInt64Int64: { + int64_t ret = reinterpret_cast(nativeFn)(x0, x1, x2, x3); + setGPR64Result(ret); + break; + } // Cases with GPR return type. This can be int32 or int64, but int64 is a safer assumption. case js::jit::Args_Int_Double: { @@ -641,6 +742,11 @@ Simulator::VisitCallRedirection(const Instruction* instr) setFP32Result(ret); break; } + case js::jit::Args_Float32_Float32Float32: { + float ret = reinterpret_cast(nativeFn)(s0, s1); + setFP32Result(ret); + break; + } // Cases with double return type. case js::jit::Args_Double_None: { @@ -705,7 +811,7 @@ Simulator::VisitCallRedirection(const Instruction* instr) VIXL_ASSERT(xreg(29) == x29); // Assert that the stack is unchanged. - VIXL_ASSERT(savedSP == xreg(31, Reg31IsStackPointer)); + VIXL_ASSERT(savedSP == get_sp()); // Simulate a return. set_lr(savedLR); diff --git a/js/src/jit/arm64/vixl/Simulator-vixl.cpp b/js/src/jit/arm64/vixl/Simulator-vixl.cpp index 9d95a2bb4b81..ea2031e3bc32 100644 --- a/js/src/jit/arm64/vixl/Simulator-vixl.cpp +++ b/js/src/jit/arm64/vixl/Simulator-vixl.cpp @@ -1012,7 +1012,38 @@ void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) { LoadStoreHelper(instr, offset, Offset); } +template +static T Faulted() { + return ~0; +} +template<> +Simulator::qreg_t Faulted() { + static_assert(kQRegSizeInBytes == 16, "Known constraint"); + static Simulator::qreg_t dummy = { { + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255 + } }; + return dummy; +} + +template T +Simulator::Read(uintptr_t address) +{ + address = Memory::AddressUntag(address); + if (handle_wasm_seg_fault(address, sizeof(T))) + return Faulted(); + return Memory::Read(address); +} + +template void +Simulator::Write(uintptr_t address, T value) +{ + address = Memory::AddressUntag(address); + if (handle_wasm_seg_fault(address, sizeof(T))) + return; + Memory::Write(address, value); +} void Simulator::LoadStoreHelper(const Instruction* instr, int64_t offset, @@ -1023,43 +1054,43 @@ void Simulator::LoadStoreHelper(const Instruction* instr, LoadStoreOp op = static_cast(instr->Mask(LoadStoreMask)); switch (op) { case LDRB_w: - set_wreg(srcdst, Memory::Read(address), NoRegLog); break; + set_wreg(srcdst, Read(address), NoRegLog); break; case LDRH_w: - set_wreg(srcdst, Memory::Read(address), NoRegLog); break; + set_wreg(srcdst, Read(address), NoRegLog); break; case LDR_w: - set_wreg(srcdst, Memory::Read(address), NoRegLog); break; + set_wreg(srcdst, Read(address), NoRegLog); break; case LDR_x: - set_xreg(srcdst, Memory::Read(address), NoRegLog); break; + set_xreg(srcdst, Read(address), NoRegLog); break; case LDRSB_w: - set_wreg(srcdst, Memory::Read(address), NoRegLog); break; + set_wreg(srcdst, Read(address), NoRegLog); break; case LDRSH_w: - set_wreg(srcdst, Memory::Read(address), NoRegLog); break; + set_wreg(srcdst, Read(address), NoRegLog); break; case LDRSB_x: - set_xreg(srcdst, Memory::Read(address), NoRegLog); break; + set_xreg(srcdst, Read(address), NoRegLog); break; case LDRSH_x: - set_xreg(srcdst, Memory::Read(address), NoRegLog); break; + set_xreg(srcdst, Read(address), NoRegLog); break; case LDRSW_x: - set_xreg(srcdst, Memory::Read(address), NoRegLog); break; + set_xreg(srcdst, Read(address), NoRegLog); break; case LDR_b: - set_breg(srcdst, Memory::Read(address), NoRegLog); break; + set_breg(srcdst, Read(address), NoRegLog); break; case LDR_h: - set_hreg(srcdst, Memory::Read(address), NoRegLog); break; + set_hreg(srcdst, Read(address), NoRegLog); break; case LDR_s: - set_sreg(srcdst, Memory::Read(address), NoRegLog); break; + set_sreg(srcdst, Read(address), NoRegLog); break; case LDR_d: - set_dreg(srcdst, Memory::Read(address), NoRegLog); break; + set_dreg(srcdst, Read(address), NoRegLog); break; case LDR_q: - set_qreg(srcdst, Memory::Read(address), NoRegLog); break; + set_qreg(srcdst, Read(address), NoRegLog); break; - case STRB_w: Memory::Write(address, wreg(srcdst)); break; - case STRH_w: Memory::Write(address, wreg(srcdst)); break; - case STR_w: Memory::Write(address, wreg(srcdst)); break; - case STR_x: Memory::Write(address, xreg(srcdst)); break; - case STR_b: Memory::Write(address, breg(srcdst)); break; - case STR_h: Memory::Write(address, hreg(srcdst)); break; - case STR_s: Memory::Write(address, sreg(srcdst)); break; - case STR_d: Memory::Write(address, dreg(srcdst)); break; - case STR_q: Memory::Write(address, qreg(srcdst)); break; + case STRB_w: Write(address, wreg(srcdst)); break; + case STRH_w: Write(address, wreg(srcdst)); break; + case STR_w: Write(address, wreg(srcdst)); break; + case STR_x: Write(address, xreg(srcdst)); break; + case STR_b: Write(address, breg(srcdst)); break; + case STR_h: Write(address, hreg(srcdst)); break; + case STR_s: Write(address, sreg(srcdst)); break; + case STR_d: Write(address, dreg(srcdst)); break; + case STR_q: Write(address, qreg(srcdst)); break; // Ignore prfm hint instructions. case PRFM: break; @@ -1129,58 +1160,58 @@ void Simulator::LoadStorePairHelper(const Instruction* instr, // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We // will print a more detailed log. case LDP_w: { - set_wreg(rt, Memory::Read(address), NoRegLog); - set_wreg(rt2, Memory::Read(address2), NoRegLog); + set_wreg(rt, Read(address), NoRegLog); + set_wreg(rt2, Read(address2), NoRegLog); break; } case LDP_s: { - set_sreg(rt, Memory::Read(address), NoRegLog); - set_sreg(rt2, Memory::Read(address2), NoRegLog); + set_sreg(rt, Read(address), NoRegLog); + set_sreg(rt2, Read(address2), NoRegLog); break; } case LDP_x: { - set_xreg(rt, Memory::Read(address), NoRegLog); - set_xreg(rt2, Memory::Read(address2), NoRegLog); + set_xreg(rt, Read(address), NoRegLog); + set_xreg(rt2, Read(address2), NoRegLog); break; } case LDP_d: { - set_dreg(rt, Memory::Read(address), NoRegLog); - set_dreg(rt2, Memory::Read(address2), NoRegLog); + set_dreg(rt, Read(address), NoRegLog); + set_dreg(rt2, Read(address2), NoRegLog); break; } case LDP_q: { - set_qreg(rt, Memory::Read(address), NoRegLog); - set_qreg(rt2, Memory::Read(address2), NoRegLog); + set_qreg(rt, Read(address), NoRegLog); + set_qreg(rt2, Read(address2), NoRegLog); break; } case LDPSW_x: { - set_xreg(rt, Memory::Read(address), NoRegLog); - set_xreg(rt2, Memory::Read(address2), NoRegLog); + set_xreg(rt, Read(address), NoRegLog); + set_xreg(rt2, Read(address2), NoRegLog); break; } case STP_w: { - Memory::Write(address, wreg(rt)); - Memory::Write(address2, wreg(rt2)); + Write(address, wreg(rt)); + Write(address2, wreg(rt2)); break; } case STP_s: { - Memory::Write(address, sreg(rt)); - Memory::Write(address2, sreg(rt2)); + Write(address, sreg(rt)); + Write(address2, sreg(rt2)); break; } case STP_x: { - Memory::Write(address, xreg(rt)); - Memory::Write(address2, xreg(rt2)); + Write(address, xreg(rt)); + Write(address2, xreg(rt2)); break; } case STP_d: { - Memory::Write(address, dreg(rt)); - Memory::Write(address2, dreg(rt2)); + Write(address, dreg(rt)); + Write(address2, dreg(rt2)); break; } case STP_q: { - Memory::Write(address, qreg(rt)); - Memory::Write(address2, qreg(rt2)); + Write(address, qreg(rt)); + Write(address2, qreg(rt2)); break; } default: VIXL_UNREACHABLE(); @@ -1276,32 +1307,32 @@ void Simulator::VisitLoadStoreExclusive(const Instruction* instr) { case LDXRB_w: case LDAXRB_w: case LDARB_w: - set_wreg(rt, Memory::Read(address), NoRegLog); + set_wreg(rt, Read(address), NoRegLog); break; case LDXRH_w: case LDAXRH_w: case LDARH_w: - set_wreg(rt, Memory::Read(address), NoRegLog); + set_wreg(rt, Read(address), NoRegLog); break; case LDXR_w: case LDAXR_w: case LDAR_w: - set_wreg(rt, Memory::Read(address), NoRegLog); + set_wreg(rt, Read(address), NoRegLog); break; case LDXR_x: case LDAXR_x: case LDAR_x: - set_xreg(rt, Memory::Read(address), NoRegLog); + set_xreg(rt, Read(address), NoRegLog); break; case LDXP_w: case LDAXP_w: - set_wreg(rt, Memory::Read(address), NoRegLog); - set_wreg(rt2, Memory::Read(address + element_size), NoRegLog); + set_wreg(rt, Read(address), NoRegLog); + set_wreg(rt2, Read(address + element_size), NoRegLog); break; case LDXP_x: case LDAXP_x: - set_xreg(rt, Memory::Read(address), NoRegLog); - set_xreg(rt2, Memory::Read(address + element_size), NoRegLog); + set_xreg(rt, Read(address), NoRegLog); + set_xreg(rt2, Read(address + element_size), NoRegLog); break; default: VIXL_UNREACHABLE(); @@ -1341,32 +1372,32 @@ void Simulator::VisitLoadStoreExclusive(const Instruction* instr) { case STXRB_w: case STLXRB_w: case STLRB_w: - Memory::Write(address, wreg(rt)); + Write(address, wreg(rt)); break; case STXRH_w: case STLXRH_w: case STLRH_w: - Memory::Write(address, wreg(rt)); + Write(address, wreg(rt)); break; case STXR_w: case STLXR_w: case STLR_w: - Memory::Write(address, wreg(rt)); + Write(address, wreg(rt)); break; case STXR_x: case STLXR_x: case STLR_x: - Memory::Write(address, xreg(rt)); + Write(address, xreg(rt)); break; case STXP_w: case STLXP_w: - Memory::Write(address, wreg(rt)); - Memory::Write(address + element_size, wreg(rt2)); + Write(address, wreg(rt)); + Write(address + element_size, wreg(rt2)); break; case STXP_x: case STLXP_x: - Memory::Write(address, xreg(rt)); - Memory::Write(address + element_size, xreg(rt2)); + Write(address, xreg(rt)); + Write(address + element_size, xreg(rt2)); break; default: VIXL_UNREACHABLE(); @@ -1393,27 +1424,27 @@ void Simulator::VisitLoadLiteral(const Instruction* instr) { // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then // print a more detailed log. case LDR_w_lit: - set_wreg(rt, Memory::Read(address), NoRegLog); + set_wreg(rt, Read(address), NoRegLog); LogRead(address, rt, kPrintWReg); break; case LDR_x_lit: - set_xreg(rt, Memory::Read(address), NoRegLog); + set_xreg(rt, Read(address), NoRegLog); LogRead(address, rt, kPrintXReg); break; case LDR_s_lit: - set_sreg(rt, Memory::Read(address), NoRegLog); + set_sreg(rt, Read(address), NoRegLog); LogVRead(address, rt, kPrintSReg); break; case LDR_d_lit: - set_dreg(rt, Memory::Read(address), NoRegLog); + set_dreg(rt, Read(address), NoRegLog); LogVRead(address, rt, kPrintDReg); break; case LDR_q_lit: - set_qreg(rt, Memory::Read(address), NoRegLog); + set_qreg(rt, Read(address), NoRegLog); LogVRead(address, rt, kPrintReg1Q); break; case LDRSW_x_lit: - set_xreg(rt, Memory::Read(address), NoRegLog); + set_xreg(rt, Read(address), NoRegLog); LogRead(address, rt, kPrintWReg); break; @@ -2242,7 +2273,7 @@ void Simulator::SysOp_W(int op, int64_t val) { case CIVAC: { // Perform a dummy memory access to ensure that we have read access // to the specified address. - volatile uint8_t y = Memory::Read(val); + volatile uint8_t y = Read(val); USE(y); // TODO: Implement "case ZVA:". break; diff --git a/js/src/jit/arm64/vixl/Simulator-vixl.h b/js/src/jit/arm64/vixl/Simulator-vixl.h index 07956733ea04..4a58419ed93c 100644 --- a/js/src/jit/arm64/vixl/Simulator-vixl.h +++ b/js/src/jit/arm64/vixl/Simulator-vixl.h @@ -721,6 +721,9 @@ class Simulator : public DecoderVisitor { static bool supportsAtomics() { return true; } + template T Read(uintptr_t address); + template void Write(uintptr_t address_, T value); + JS::ProfilingFrameIterator::RegisterState registerState(); void ResetState(); @@ -731,6 +734,9 @@ class Simulator : public DecoderVisitor { // Simulation helpers. const Instruction* pc() const { return pc_; } const Instruction* get_pc() const { return pc_; } + int64_t get_sp() const { return xreg(31, Reg31IsStackPointer); } + int64_t get_lr() const { return xreg(30); } + int64_t get_fp() const { return xreg(29); } template T get_pc_as() const { return reinterpret_cast(const_cast(pc())); } @@ -742,6 +748,8 @@ class Simulator : public DecoderVisitor { void trigger_wasm_interrupt(); void handle_wasm_interrupt(); + bool handle_wasm_ill_fault(); + bool handle_wasm_seg_fault(uintptr_t addr, unsigned numBytes); void increment_pc() { if (!pc_modified_) { diff --git a/js/src/jit/mips-shared/Assembler-mips-shared.cpp b/js/src/jit/mips-shared/Assembler-mips-shared.cpp index fff5fd00675b..44265664c8c2 100644 --- a/js/src/jit/mips-shared/Assembler-mips-shared.cpp +++ b/js/src/jit/mips-shared/Assembler-mips-shared.cpp @@ -1217,35 +1217,35 @@ AssemblerMIPSShared::as_dextu(Register rt, Register rs, uint16_t pos, uint16_t s // FP instructions BufferOffset -AssemblerMIPSShared::as_ld(FloatRegister fd, Register base, int32_t off) +AssemblerMIPSShared::as_ldc1(FloatRegister ft, Register base, int32_t off) { MOZ_ASSERT(Imm16::IsInSignedRange(off)); - spew("ldc1 %3s, (0x%x)%2s", fd.name(), off, base.name()); - return writeInst(InstImm(op_ldc1, base, fd, Imm16(off)).encode()); + spew("ldc1 %3s, (0x%x)%2s", ft.name(), off, base.name()); + return writeInst(InstImm(op_ldc1, base, ft, Imm16(off)).encode()); } BufferOffset -AssemblerMIPSShared::as_sd(FloatRegister fd, Register base, int32_t off) +AssemblerMIPSShared::as_sdc1(FloatRegister ft, Register base, int32_t off) { MOZ_ASSERT(Imm16::IsInSignedRange(off)); - spew("sdc1 %3s, (0x%x)%2s", fd.name(), off, base.name()); - return writeInst(InstImm(op_sdc1, base, fd, Imm16(off)).encode()); + spew("sdc1 %3s, (0x%x)%2s", ft.name(), off, base.name()); + return writeInst(InstImm(op_sdc1, base, ft, Imm16(off)).encode()); } BufferOffset -AssemblerMIPSShared::as_ls(FloatRegister fd, Register base, int32_t off) +AssemblerMIPSShared::as_lwc1(FloatRegister ft, Register base, int32_t off) { MOZ_ASSERT(Imm16::IsInSignedRange(off)); - spew("lwc1 %3s, (0x%x)%2s", fd.name(), off, base.name()); - return writeInst(InstImm(op_lwc1, base, fd, Imm16(off)).encode()); + spew("lwc1 %3s, (0x%x)%2s", ft.name(), off, base.name()); + return writeInst(InstImm(op_lwc1, base, ft, Imm16(off)).encode()); } BufferOffset -AssemblerMIPSShared::as_ss(FloatRegister fd, Register base, int32_t off) +AssemblerMIPSShared::as_swc1(FloatRegister ft, Register base, int32_t off) { MOZ_ASSERT(Imm16::IsInSignedRange(off)); - spew("swc1 %3s, (0x%x)%2s", fd.name(), off, base.name()); - return writeInst(InstImm(op_swc1, base, fd, Imm16(off)).encode()); + spew("swc1 %3s, (0x%x)%2s", ft.name(), off, base.name()); + return writeInst(InstImm(op_swc1, base, ft, Imm16(off)).encode()); } BufferOffset diff --git a/js/src/jit/mips-shared/Assembler-mips-shared.h b/js/src/jit/mips-shared/Assembler-mips-shared.h index f96b7d81eddc..510b659cbf8d 100644 --- a/js/src/jit/mips-shared/Assembler-mips-shared.h +++ b/js/src/jit/mips-shared/Assembler-mips-shared.h @@ -1139,13 +1139,11 @@ class AssemblerMIPSShared : public AssemblerShared // FP instructions - // Use these two functions only when you are sure address is aligned. - // Otherwise, use ma_ld and ma_sd. - BufferOffset as_ld(FloatRegister fd, Register base, int32_t off); - BufferOffset as_sd(FloatRegister fd, Register base, int32_t off); + BufferOffset as_ldc1(FloatRegister ft, Register base, int32_t off); + BufferOffset as_sdc1(FloatRegister ft, Register base, int32_t off); - BufferOffset as_ls(FloatRegister fd, Register base, int32_t off); - BufferOffset as_ss(FloatRegister fd, Register base, int32_t off); + BufferOffset as_lwc1(FloatRegister ft, Register base, int32_t off); + BufferOffset as_swc1(FloatRegister ft, Register base, int32_t off); // Loongson-specific FP load and store instructions BufferOffset as_gsldl(FloatRegister fd, Register base, int32_t off); diff --git a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp index 60df38984ea5..5f4ef36fba14 100644 --- a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp +++ b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp @@ -1592,7 +1592,7 @@ CodeGeneratorMIPSShared::visitCopySignD(LCopySignD* ins) void CodeGeneratorMIPSShared::visitValue(LValue* value) { - const ValueOperand out = GetValueOutput(value); + const ValueOperand out = ToOutValue(value); masm.moveValue(value->value(), out); } diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h b/js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h index 6a54ec1747e2..1fea3cb56b3b 100644 --- a/js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h +++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h @@ -1037,6 +1037,28 @@ MacroAssembler::storeFloat32x3(FloatRegister src, const BaseIndex& dest) MOZ_CRASH("NYI"); } +void +MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const Address& addr) +{ + ma_sd(src, addr); +} +void +MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const BaseIndex& addr) +{ + ma_sd(src, addr); +} + +void +MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const Address& addr) +{ + ma_ss(src, addr); +} +void +MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const BaseIndex& addr) +{ + ma_ss(src, addr); +} + void MacroAssembler::memoryBarrier(MemoryBarrierBits barrier) { diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp index 3e1de14502e8..7fded8e040a6 100644 --- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp +++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp @@ -1118,14 +1118,6 @@ MacroAssemblerMIPSShared::ma_lis(FloatRegister dest, float value) } } -void -MacroAssemblerMIPSShared::ma_liNegZero(FloatRegister dest) -{ - moveToDoubleLo(zero, dest); - ma_li(ScratchRegister, Imm32(INT_MIN)); - asMasm().moveToDoubleHi(ScratchRegister, dest); -} - void MacroAssemblerMIPSShared::ma_sd(FloatRegister ft, BaseIndex address) { @@ -1178,6 +1170,20 @@ MacroAssemblerMIPSShared::ma_ss(FloatRegister ft, BaseIndex address) asMasm().ma_ss(ft, Address(SecondScratchReg, address.offset)); } +void +MacroAssemblerMIPSShared::ma_ld(FloatRegister ft, const BaseIndex& src) +{ + asMasm().computeScaledAddress(src, SecondScratchReg); + asMasm().ma_ld(ft, Address(SecondScratchReg, src.offset)); +} + +void +MacroAssemblerMIPSShared::ma_ls(FloatRegister ft, const BaseIndex& src) +{ + asMasm().computeScaledAddress(src, SecondScratchReg); + asMasm().ma_ls(ft, Address(SecondScratchReg, src.offset)); +} + void MacroAssemblerMIPSShared::ma_bc1s(FloatRegister lhs, FloatRegister rhs, Label* label, DoubleCondition c, JumpKind jumpKind, FPConditionBit fcc) @@ -1290,6 +1296,44 @@ MacroAssemblerMIPSShared::minMaxFloat32(FloatRegister srcDest, FloatRegister sec bind(&done); } +void +MacroAssemblerMIPSShared::loadDouble(const Address& address, FloatRegister dest) +{ + asMasm().ma_ld(dest, address); +} + +void +MacroAssemblerMIPSShared::loadDouble(const BaseIndex& src, FloatRegister dest) +{ + asMasm().ma_ld(dest, src); +} + +void +MacroAssemblerMIPSShared::loadFloatAsDouble(const Address& address, FloatRegister dest) +{ + asMasm().ma_ls(dest, address); + as_cvtds(dest, dest); +} + +void +MacroAssemblerMIPSShared::loadFloatAsDouble(const BaseIndex& src, FloatRegister dest) +{ + asMasm().loadFloat32(src, dest); + as_cvtds(dest, dest); +} + +void +MacroAssemblerMIPSShared::loadFloat32(const Address& address, FloatRegister dest) +{ + asMasm().ma_ls(dest, address); +} + +void +MacroAssemblerMIPSShared::loadFloat32(const BaseIndex& src, FloatRegister dest) +{ + asMasm().ma_ls(dest, src); +} + void MacroAssemblerMIPSShared::ma_call(ImmPtr dest) { @@ -1371,7 +1415,7 @@ void MacroAssembler::Push(FloatRegister f) { ma_push(f); - adjustFrame(int32_t(sizeof(double))); + adjustFrame(int32_t(f.pushSize())); } void @@ -1385,21 +1429,21 @@ void MacroAssembler::Pop(FloatRegister f) { ma_pop(f); - adjustFrame(-int32_t(sizeof(double))); + adjustFrame(-int32_t(f.pushSize())); } void MacroAssembler::Pop(const ValueOperand& val) { popValue(val); - framePushed_ -= sizeof(Value); + adjustFrame(-int32_t(sizeof(Value))); } void MacroAssembler::PopStackPtr() { loadPtr(Address(StackPointer, 0), StackPointer); - framePushed_ -= sizeof(intptr_t); + adjustFrame(-int32_t(sizeof(intptr_t))); } @@ -1972,12 +2016,10 @@ MacroAssemblerMIPSShared::wasmLoadImpl(const wasm::MemoryAccessDesc& access, Reg asMasm().memoryBarrierBefore(access.sync()); if (isFloat) { - if (byteSize == 4) { - asMasm().loadFloat32(address, output.fpu()); - } else { - asMasm().computeScaledAddress(address, SecondScratchReg); - asMasm().as_ld(output.fpu(), SecondScratchReg, 0); - } + if (byteSize == 4) + asMasm().ma_ls(output.fpu(), address); + else + asMasm().ma_ld(output.fpu(), address); } else { asMasm().ma_load(output.gpr(), address, static_cast(8 * byteSize), isSigned ? SignExtend : ZeroExtend); @@ -2036,15 +2078,10 @@ MacroAssemblerMIPSShared::wasmStoreImpl(const wasm::MemoryAccessDesc& access, An asMasm().memoryBarrierBefore(access.sync()); if (isFloat) { - if (byteSize == 4) { - asMasm().storeFloat32(value.fpu(), address); - } else { - //asMasm().storeDouble(value.fpu(), address); - // For time being storeDouble for mips32 uses two store instructions, - // so we emit only one to get correct behavior in case of OOB access. - asMasm().computeScaledAddress(address, SecondScratchReg); - asMasm().as_sd(value.fpu(), SecondScratchReg, 0); - } + if (byteSize == 4) + asMasm().ma_ss(value.fpu(), address); + else + asMasm().ma_sd(value.fpu(), address); } else { asMasm().ma_store(value.gpr(), address, static_cast(8 * byteSize), diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h index b88695d54827..857ba5768f47 100644 --- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h +++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h @@ -172,10 +172,12 @@ class MacroAssemblerMIPSShared : public Assembler // fp instructions void ma_lis(FloatRegister dest, float value); - void ma_liNegZero(FloatRegister dest); - void ma_sd(FloatRegister fd, BaseIndex address); - void ma_ss(FloatRegister fd, BaseIndex address); + void ma_sd(FloatRegister src, BaseIndex address); + void ma_ss(FloatRegister src, BaseIndex address); + + void ma_ld(FloatRegister dest, const BaseIndex& src); + void ma_ls(FloatRegister dest, const BaseIndex& src); //FP branches void ma_bc1s(FloatRegister lhs, FloatRegister rhs, Label* label, DoubleCondition c, @@ -192,12 +194,6 @@ class MacroAssemblerMIPSShared : public Assembler void ma_cmp_set_double(Register dst, FloatRegister lhs, FloatRegister rhs, DoubleCondition c); void ma_cmp_set_float32(Register dst, FloatRegister lhs, FloatRegister rhs, DoubleCondition c); - BufferOffset ma_BoundsCheck(Register bounded) { - BufferOffset bo = m_buffer.nextOffset(); - ma_liPatchable(bounded, Imm32(0)); - return bo; - } - void moveToDoubleLo(Register src, FloatRegister dest) { as_mtc1(src, dest); } @@ -217,6 +213,16 @@ class MacroAssemblerMIPSShared : public Assembler void minMaxDouble(FloatRegister srcDest, FloatRegister other, bool handleNaN, bool isMax); void minMaxFloat32(FloatRegister srcDest, FloatRegister other, bool handleNaN, bool isMax); + void loadDouble(const Address& addr, FloatRegister dest); + void loadDouble(const BaseIndex& src, FloatRegister dest); + + // Load a float value into a register, then expand it to a double. + void loadFloatAsDouble(const Address& addr, FloatRegister dest); + void loadFloatAsDouble(const BaseIndex& src, FloatRegister dest); + + void loadFloat32(const Address& addr, FloatRegister dest); + void loadFloat32(const BaseIndex& src, FloatRegister dest); + void outOfLineWasmTruncateToInt32Check(FloatRegister input, Register output, MIRType fromType, TruncFlags flags, Label* rejoin, wasm::BytecodeOffset trapOffset); diff --git a/js/src/jit/mips32/Architecture-mips32.h b/js/src/jit/mips32/Architecture-mips32.h index 8bbec8fc1d9d..e653caed0387 100644 --- a/js/src/jit/mips32/Architecture-mips32.h +++ b/js/src/jit/mips32/Architecture-mips32.h @@ -131,6 +131,7 @@ class FloatRegister : public FloatRegisterMIPSShared } bool equiv(const FloatRegister& other) const { return other.kind_ == kind_; } size_t size() const { return (kind_ == Double) ? 8 : 4; } + size_t pushSize() const { return size(); } bool isInvalid() const { return code_ == FloatRegisters::invalid_freg; } diff --git a/js/src/jit/mips32/CodeGenerator-mips32.cpp b/js/src/jit/mips32/CodeGenerator-mips32.cpp index 87afa2a8e44e..f197dd203064 100644 --- a/js/src/jit/mips32/CodeGenerator-mips32.cpp +++ b/js/src/jit/mips32/CodeGenerator-mips32.cpp @@ -108,14 +108,6 @@ CodeGeneratorMIPS::ToValue(LInstruction* ins, size_t pos) return ValueOperand(typeReg, payloadReg); } -ValueOperand -CodeGeneratorMIPS::ToOutValue(LInstruction* ins) -{ - Register typeReg = ToRegister(ins->getDef(TYPE_INDEX)); - Register payloadReg = ToRegister(ins->getDef(PAYLOAD_INDEX)); - return ValueOperand(typeReg, payloadReg); -} - ValueOperand CodeGeneratorMIPS::ToTempValue(LInstruction* ins, size_t pos) { @@ -160,8 +152,8 @@ CodeGeneratorMIPS::visitUnbox(LUnbox* unbox) } } -Register -CodeGeneratorMIPS::splitTagForTest(const ValueOperand& value) +void +CodeGeneratorMIPS::splitTagForTest(const ValueOperand& value, ScratchTagScope& tag) { return value.typeReg(); } diff --git a/js/src/jit/mips32/CodeGenerator-mips32.h b/js/src/jit/mips32/CodeGenerator-mips32.h index cc455b0ad15d..7b76856c4260 100644 --- a/js/src/jit/mips32/CodeGenerator-mips32.h +++ b/js/src/jit/mips32/CodeGenerator-mips32.h @@ -69,11 +69,10 @@ class CodeGeneratorMIPS : public CodeGeneratorMIPSShared void visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool); protected: ValueOperand ToValue(LInstruction* ins, size_t pos); - ValueOperand ToOutValue(LInstruction* ins); ValueOperand ToTempValue(LInstruction* ins, size_t pos); // Functions for LTestVAndBranch. - Register splitTagForTest(const ValueOperand& value); + void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag); public: CodeGeneratorMIPS(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm) diff --git a/js/src/jit/mips32/MacroAssembler-mips32-inl.h b/js/src/jit/mips32/MacroAssembler-mips32-inl.h index 4007703aab1d..78e63b48eb3e 100644 --- a/js/src/jit/mips32/MacroAssembler-mips32-inl.h +++ b/js/src/jit/mips32/MacroAssembler-mips32-inl.h @@ -1016,32 +1016,6 @@ MacroAssembler::branchTruncateFloat32MaybeModUint32(FloatRegister src, Register ma_b(ScratchRegister, Imm32(0), fail, Assembler::NotEqual); } -// ======================================================================== -// Memory access primitives. -void -MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const Address& addr) -{ - ma_sd(src, addr); -} -void -MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const BaseIndex& addr) -{ - MOZ_ASSERT(addr.offset == 0); - ma_sd(src, addr); -} - -void -MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const Address& addr) -{ - ma_ss(src, addr); -} -void -MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const BaseIndex& addr) -{ - MOZ_ASSERT(addr.offset == 0); - ma_ss(src, addr); -} - // ======================================================================== // wasm support diff --git a/js/src/jit/mips32/MacroAssembler-mips32.cpp b/js/src/jit/mips32/MacroAssembler-mips32.cpp index cee7b0cefa69..e7a7b9db4fc4 100644 --- a/js/src/jit/mips32/MacroAssembler-mips32.cpp +++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp @@ -870,7 +870,7 @@ void MacroAssemblerMIPS::ma_ls(FloatRegister ft, Address address) { if (Imm16::IsInSignedRange(address.offset)) { - as_ls(ft, address.base, address.offset); + as_lwc1(ft, address.base, address.offset); } else { MOZ_ASSERT(address.base != ScratchRegister); ma_li(ScratchRegister, Imm32(address.offset)); @@ -878,7 +878,7 @@ MacroAssemblerMIPS::ma_ls(FloatRegister ft, Address address) as_gslsx(ft, address.base, ScratchRegister, 0); } else { as_addu(ScratchRegister, address.base, ScratchRegister); - as_ls(ft, ScratchRegister, 0); + as_lwc1(ft, ScratchRegister, 0); } } } @@ -886,37 +886,34 @@ MacroAssemblerMIPS::ma_ls(FloatRegister ft, Address address) void MacroAssemblerMIPS::ma_ld(FloatRegister ft, Address address) { - // Use single precision load instructions so we don't have to worry about - // alignment. - - int32_t off = address.offset + PAYLOAD_OFFSET; - int32_t off2 = address.offset + TAG_OFFSET; - if (Imm16::IsInSignedRange(off) && Imm16::IsInSignedRange(off2)) { - as_ls(ft, address.base, off); - as_ls(getOddPair(ft), address.base, off2); + if (Imm16::IsInSignedRange(address.offset)) { + as_ldc1(ft, address.base, address.offset); } else { MOZ_ASSERT(address.base != ScratchRegister); - ma_li(ScratchRegister, Imm32(off)); - as_addu(ScratchRegister, address.base, ScratchRegister); - as_ls(ft, ScratchRegister, PAYLOAD_OFFSET); - as_ls(getOddPair(ft), ScratchRegister, TAG_OFFSET); + ma_li(ScratchRegister, Imm32(address.offset)); + if (isLoongson()) { + as_gsldx(ft, address.base, ScratchRegister, 0); + } else { + as_addu(ScratchRegister, address.base, ScratchRegister); + as_ldc1(ft, ScratchRegister, 0); + } } } void MacroAssemblerMIPS::ma_sd(FloatRegister ft, Address address) { - int32_t off = address.offset + PAYLOAD_OFFSET; - int32_t off2 = address.offset + TAG_OFFSET; - if (Imm16::IsInSignedRange(off) && Imm16::IsInSignedRange(off2)) { - as_ss(ft, address.base, off); - as_ss(getOddPair(ft), address.base, off2); + if (Imm16::IsInSignedRange(address.offset)) { + as_sdc1(ft, address.base, address.offset); } else { MOZ_ASSERT(address.base != ScratchRegister); - ma_li(ScratchRegister, Imm32(off)); - as_addu(ScratchRegister, address.base, ScratchRegister); - as_ss(ft, ScratchRegister, PAYLOAD_OFFSET); - as_ss(getOddPair(ft), ScratchRegister, TAG_OFFSET); + ma_li(ScratchRegister, Imm32(address.offset)); + if (isLoongson()) { + as_gssdx(ft, address.base, ScratchRegister, 0); + } else { + as_addu(ScratchRegister, address.base, ScratchRegister); + as_sdc1(ft, ScratchRegister, 0); + } } } @@ -924,7 +921,7 @@ void MacroAssemblerMIPS::ma_ss(FloatRegister ft, Address address) { if (Imm16::IsInSignedRange(address.offset)) { - as_ss(ft, address.base, address.offset); + as_swc1(ft, address.base, address.offset); } else { MOZ_ASSERT(address.base != ScratchRegister); ma_li(ScratchRegister, Imm32(address.offset)); @@ -932,23 +929,51 @@ MacroAssemblerMIPS::ma_ss(FloatRegister ft, Address address) as_gsssx(ft, address.base, ScratchRegister, 0); } else { as_addu(ScratchRegister, address.base, ScratchRegister); - as_ss(ft, ScratchRegister, 0); + as_swc1(ft, ScratchRegister, 0); } } } void -MacroAssemblerMIPS::ma_pop(FloatRegister fs) +MacroAssemblerMIPS::ma_ldc1WordAligned(FloatRegister ft, Register base, int32_t off) { - ma_ld(fs.doubleOverlay(), Address(StackPointer, 0)); - as_addiu(StackPointer, StackPointer, sizeof(double)); + MOZ_ASSERT(Imm16::IsInSignedRange(off + PAYLOAD_OFFSET) && + Imm16::IsInSignedRange(off + TAG_OFFSET)); + + as_lwc1(ft, base, off + PAYLOAD_OFFSET); + as_lwc1(getOddPair(ft), base, off + TAG_OFFSET); } void -MacroAssemblerMIPS::ma_push(FloatRegister fs) +MacroAssemblerMIPS::ma_sdc1WordAligned(FloatRegister ft, Register base, int32_t off) { - as_addiu(StackPointer, StackPointer, -sizeof(double)); - ma_sd(fs.doubleOverlay(), Address(StackPointer, 0)); + MOZ_ASSERT(Imm16::IsInSignedRange(off + PAYLOAD_OFFSET) && + Imm16::IsInSignedRange(off + TAG_OFFSET)); + + as_swc1(ft, base, off + PAYLOAD_OFFSET); + as_swc1(getOddPair(ft), base, off + TAG_OFFSET); +} + +void +MacroAssemblerMIPS::ma_pop(FloatRegister f) +{ + if (f.isDouble()) + ma_ldc1WordAligned(f, StackPointer, 0); + else + as_lwc1(f, StackPointer, 0); + + as_addiu(StackPointer, StackPointer, f.size()); +} + +void +MacroAssemblerMIPS::ma_push(FloatRegister f) +{ + as_addiu(StackPointer, StackPointer, -f.size()); + + if(f.isDouble()) + ma_sdc1WordAligned(f, StackPointer, 0); + else + as_swc1(f, StackPointer, 0); } bool @@ -1110,19 +1135,6 @@ MacroAssemblerMIPSCompat::loadPrivate(const Address& address, Register dest) ma_lw(dest, Address(address.base, address.offset + PAYLOAD_OFFSET)); } -void -MacroAssemblerMIPSCompat::loadDouble(const Address& address, FloatRegister dest) -{ - ma_ld(dest, address); -} - -void -MacroAssemblerMIPSCompat::loadDouble(const BaseIndex& src, FloatRegister dest) -{ - computeScaledAddress(src, SecondScratchReg); - ma_ld(dest, Address(SecondScratchReg, src.offset)); -} - void MacroAssemblerMIPSCompat::loadUnalignedDouble(const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp, FloatRegister dest) @@ -1155,33 +1167,6 @@ MacroAssemblerMIPSCompat::loadUnalignedDouble(const wasm::MemoryAccessDesc& acce } } -void -MacroAssemblerMIPSCompat::loadFloatAsDouble(const Address& address, FloatRegister dest) -{ - ma_ls(dest, address); - as_cvtds(dest, dest); -} - -void -MacroAssemblerMIPSCompat::loadFloatAsDouble(const BaseIndex& src, FloatRegister dest) -{ - loadFloat32(src, dest); - as_cvtds(dest, dest); -} - -void -MacroAssemblerMIPSCompat::loadFloat32(const Address& address, FloatRegister dest) -{ - ma_ls(dest, address); -} - -void -MacroAssemblerMIPSCompat::loadFloat32(const BaseIndex& src, FloatRegister dest) -{ - computeScaledAddress(src, SecondScratchReg); - ma_ls(dest, Address(SecondScratchReg, src.offset)); -} - void MacroAssemblerMIPSCompat::loadUnalignedFloat32(const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp, FloatRegister dest) @@ -2190,7 +2175,7 @@ MacroAssembler::PushRegsInMask(LiveRegisterSet set) diffF -= sizeof(double); for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) { - as_sd(*iter, SecondScratchReg, -diffF); + as_sdc1(*iter, SecondScratchReg, -diffF); diffF -= sizeof(double); } @@ -2216,7 +2201,7 @@ MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore) LiveFloatRegisterSet fpignore(ignore.fpus().reduceSetForPush()); for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) { if (!ignore.has(*iter)) - as_ld(*iter, SecondScratchReg, -diffF); + as_ldc1(*iter, SecondScratchReg, -diffF); diffF -= sizeof(double); } freeStack(reservedF); @@ -2256,7 +2241,7 @@ MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register scra diffF -= sizeof(double); for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) { - as_sd(*iter, scratch, -diffF); + as_sdc1(*iter, scratch, -diffF); diffF -= sizeof(double); } MOZ_ASSERT(diffF == 0); diff --git a/js/src/jit/mips32/MacroAssembler-mips32.h b/js/src/jit/mips32/MacroAssembler-mips32.h index b75d8362e59a..9f1841b118c3 100644 --- a/js/src/jit/mips32/MacroAssembler-mips32.h +++ b/js/src/jit/mips32/MacroAssembler-mips32.h @@ -46,6 +46,25 @@ static const int32_t LOW_32_OFFSET = 4; static const int32_t HIGH_32_OFFSET = 0; #endif +// See documentation for ScratchTagScope and ScratchTagScopeRelease in +// MacroAssembler-x64.h. + +class ScratchTagScope +{ + const ValueOperand& v_; + public: + ScratchTagScope(MacroAssembler&, const ValueOperand& v) : v_(v) {} + operator Register() { return v_.typeReg(); } + void release() {} + void reacquire() {} +}; + +class ScratchTagScopeRelease +{ + public: + explicit ScratchTagScopeRelease(ScratchTagScope*) {} +}; + class MacroAssemblerMIPS : public MacroAssemblerMIPSShared { public: @@ -53,6 +72,8 @@ class MacroAssemblerMIPS : public MacroAssemblerMIPSShared using MacroAssemblerMIPSShared::ma_li; using MacroAssemblerMIPSShared::ma_ss; using MacroAssemblerMIPSShared::ma_sd; + using MacroAssemblerMIPSShared::ma_ls; + using MacroAssemblerMIPSShared::ma_ld; using MacroAssemblerMIPSShared::ma_load; using MacroAssemblerMIPSShared::ma_store; using MacroAssemblerMIPSShared::ma_cmp_set; @@ -122,13 +143,16 @@ class MacroAssemblerMIPS : public MacroAssemblerMIPSShared void ma_mv(FloatRegister src, ValueOperand dest); void ma_mv(ValueOperand src, FloatRegister dest); - void ma_ls(FloatRegister fd, Address address); - void ma_ld(FloatRegister fd, Address address); - void ma_sd(FloatRegister fd, Address address); - void ma_ss(FloatRegister fd, Address address); + void ma_ls(FloatRegister ft, Address address); + void ma_ld(FloatRegister ft, Address address); + void ma_sd(FloatRegister ft, Address address); + void ma_ss(FloatRegister ft, Address address); - void ma_pop(FloatRegister fs); - void ma_push(FloatRegister fs); + void ma_ldc1WordAligned(FloatRegister ft, Register base, int32_t off); + void ma_sdc1WordAligned(FloatRegister ft, Register base, int32_t off); + + void ma_pop(FloatRegister f); + void ma_push(FloatRegister f); void ma_cmp_set(Register dst, Register lhs, ImmPtr imm, Condition c) { ma_cmp_set(dst, lhs, Imm32(uint32_t(imm.value)), c); @@ -328,9 +352,8 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS ma_negu(reg, reg); } - // Returns the register containing the type tag. - Register splitTagForTest(const ValueOperand& value) { - return value.typeReg(); + void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag) { + MOZ_ASSERT(value.typeReg() == tag); } // unboxing code @@ -636,17 +659,9 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS void storeUnalignedSimd128Float(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); } void storeUnalignedSimd128Float(FloatRegister src, BaseIndex addr) { MOZ_CRASH("NYI"); } - void loadDouble(const Address& addr, FloatRegister dest); - void loadDouble(const BaseIndex& src, FloatRegister dest); void loadUnalignedDouble(const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp, FloatRegister dest); - // Load a float value into a register, then expand it to a double. - void loadFloatAsDouble(const Address& addr, FloatRegister dest); - void loadFloatAsDouble(const BaseIndex& src, FloatRegister dest); - - void loadFloat32(const Address& addr, FloatRegister dest); - void loadFloat32(const BaseIndex& src, FloatRegister dest); void loadUnalignedFloat32(const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp, FloatRegister dest); diff --git a/js/src/jit/mips32/Trampoline-mips32.cpp b/js/src/jit/mips32/Trampoline-mips32.cpp index b80957f943c1..21fb68ff9631 100644 --- a/js/src/jit/mips32/Trampoline-mips32.cpp +++ b/js/src/jit/mips32/Trampoline-mips32.cpp @@ -70,24 +70,24 @@ GenerateReturn(MacroAssembler& masm, int returnCode) MOZ_ASSERT(masm.framePushed() == sizeof(EnterJITRegs)); // Restore non-volatile registers - masm.loadPtr(Address(StackPointer, offsetof(EnterJITRegs, s0)), s0); - masm.loadPtr(Address(StackPointer, offsetof(EnterJITRegs, s1)), s1); - masm.loadPtr(Address(StackPointer, offsetof(EnterJITRegs, s2)), s2); - masm.loadPtr(Address(StackPointer, offsetof(EnterJITRegs, s3)), s3); - masm.loadPtr(Address(StackPointer, offsetof(EnterJITRegs, s4)), s4); - masm.loadPtr(Address(StackPointer, offsetof(EnterJITRegs, s5)), s5); - masm.loadPtr(Address(StackPointer, offsetof(EnterJITRegs, s6)), s6); - masm.loadPtr(Address(StackPointer, offsetof(EnterJITRegs, s7)), s7); - masm.loadPtr(Address(StackPointer, offsetof(EnterJITRegs, fp)), fp); - masm.loadPtr(Address(StackPointer, offsetof(EnterJITRegs, ra)), ra); + masm.as_lw(s0, StackPointer, offsetof(EnterJITRegs, s0)); + masm.as_lw(s1, StackPointer, offsetof(EnterJITRegs, s1)); + masm.as_lw(s2, StackPointer, offsetof(EnterJITRegs, s2)); + masm.as_lw(s3, StackPointer, offsetof(EnterJITRegs, s3)); + masm.as_lw(s4, StackPointer, offsetof(EnterJITRegs, s4)); + masm.as_lw(s5, StackPointer, offsetof(EnterJITRegs, s5)); + masm.as_lw(s6, StackPointer, offsetof(EnterJITRegs, s6)); + masm.as_lw(s7, StackPointer, offsetof(EnterJITRegs, s7)); + masm.as_lw(fp, StackPointer, offsetof(EnterJITRegs, fp)); + masm.as_lw(ra, StackPointer, offsetof(EnterJITRegs, ra)); // Restore non-volatile floating point registers - masm.loadDouble(Address(StackPointer, offsetof(EnterJITRegs, f20)), f20); - masm.loadDouble(Address(StackPointer, offsetof(EnterJITRegs, f22)), f22); - masm.loadDouble(Address(StackPointer, offsetof(EnterJITRegs, f24)), f24); - masm.loadDouble(Address(StackPointer, offsetof(EnterJITRegs, f26)), f26); - masm.loadDouble(Address(StackPointer, offsetof(EnterJITRegs, f28)), f28); - masm.loadDouble(Address(StackPointer, offsetof(EnterJITRegs, f30)), f30); + masm.as_ldc1(f20, StackPointer, offsetof(EnterJITRegs, f20)); + masm.as_ldc1(f22, StackPointer, offsetof(EnterJITRegs, f22)); + masm.as_ldc1(f24, StackPointer, offsetof(EnterJITRegs, f24)); + masm.as_ldc1(f26, StackPointer, offsetof(EnterJITRegs, f26)); + masm.as_ldc1(f28, StackPointer, offsetof(EnterJITRegs, f28)); + masm.as_ldc1(f30, StackPointer, offsetof(EnterJITRegs, f30)); masm.freeStack(sizeof(EnterJITRegs)); @@ -101,23 +101,23 @@ GeneratePrologue(MacroAssembler& masm) // rather than the JIT'd code, because they are scanned by the conservative // scanner. masm.reserveStack(sizeof(EnterJITRegs)); - masm.storePtr(s0, Address(StackPointer, offsetof(EnterJITRegs, s0))); - masm.storePtr(s1, Address(StackPointer, offsetof(EnterJITRegs, s1))); - masm.storePtr(s2, Address(StackPointer, offsetof(EnterJITRegs, s2))); - masm.storePtr(s3, Address(StackPointer, offsetof(EnterJITRegs, s3))); - masm.storePtr(s4, Address(StackPointer, offsetof(EnterJITRegs, s4))); - masm.storePtr(s5, Address(StackPointer, offsetof(EnterJITRegs, s5))); - masm.storePtr(s6, Address(StackPointer, offsetof(EnterJITRegs, s6))); - masm.storePtr(s7, Address(StackPointer, offsetof(EnterJITRegs, s7))); - masm.storePtr(fp, Address(StackPointer, offsetof(EnterJITRegs, fp))); - masm.storePtr(ra, Address(StackPointer, offsetof(EnterJITRegs, ra))); + masm.as_sw(s0, StackPointer, offsetof(EnterJITRegs, s0)); + masm.as_sw(s1, StackPointer, offsetof(EnterJITRegs, s1)); + masm.as_sw(s2, StackPointer, offsetof(EnterJITRegs, s2)); + masm.as_sw(s3, StackPointer, offsetof(EnterJITRegs, s3)); + masm.as_sw(s4, StackPointer, offsetof(EnterJITRegs, s4)); + masm.as_sw(s5, StackPointer, offsetof(EnterJITRegs, s5)); + masm.as_sw(s6, StackPointer, offsetof(EnterJITRegs, s6)); + masm.as_sw(s7, StackPointer, offsetof(EnterJITRegs, s7)); + masm.as_sw(fp, StackPointer, offsetof(EnterJITRegs, fp)); + masm.as_sw(ra, StackPointer, offsetof(EnterJITRegs, ra)); - masm.as_sd(f20, StackPointer, offsetof(EnterJITRegs, f20)); - masm.as_sd(f22, StackPointer, offsetof(EnterJITRegs, f22)); - masm.as_sd(f24, StackPointer, offsetof(EnterJITRegs, f24)); - masm.as_sd(f26, StackPointer, offsetof(EnterJITRegs, f26)); - masm.as_sd(f28, StackPointer, offsetof(EnterJITRegs, f28)); - masm.as_sd(f30, StackPointer, offsetof(EnterJITRegs, f30)); + masm.as_sdc1(f20, StackPointer, offsetof(EnterJITRegs, f20)); + masm.as_sdc1(f22, StackPointer, offsetof(EnterJITRegs, f22)); + masm.as_sdc1(f24, StackPointer, offsetof(EnterJITRegs, f24)); + masm.as_sdc1(f26, StackPointer, offsetof(EnterJITRegs, f26)); + masm.as_sdc1(f28, StackPointer, offsetof(EnterJITRegs, f28)); + masm.as_sdc1(f30, StackPointer, offsetof(EnterJITRegs, f30)); } @@ -364,9 +364,10 @@ JitRuntime::generateInvalidator(MacroAssembler& masm, Label* bailoutTail) // Save floating point registers // We can use as_sd because stack is alligned. - for (uint32_t i = 0; i < FloatRegisters::TotalDouble; i ++) - masm.as_sd(FloatRegister::FromIndex(i, FloatRegister::Double), StackPointer, - InvalidationBailoutStack::offsetOfFpRegs() + i * sizeof(double)); + for (uint32_t i = 0; i < FloatRegisters::TotalDouble; i ++) { + masm.as_sdc1(FloatRegister::FromIndex(i, FloatRegister::Double), StackPointer, + InvalidationBailoutStack::offsetOfFpRegs() + i * sizeof(double)); + } // Pass pointer to InvalidationBailoutStack structure. masm.movePtr(StackPointer, a0); @@ -576,10 +577,11 @@ PushBailoutFrame(MacroAssembler& masm, uint32_t frameClass, Register spArg) } // Save floating point registers - // We can use as_sd because stack is alligned. - for (uint32_t i = 0; i < FloatRegisters::TotalDouble; i++) - masm.as_sd(FloatRegister::FromIndex(i, FloatRegister::Double), StackPointer, - BailoutStack::offsetOfFpRegs() + i * sizeof(double)); + // We can use as_sdc1 because stack is alligned. + for (uint32_t i = 0; i < FloatRegisters::TotalDouble; i++) { + masm.as_sdc1(FloatRegister::FromIndex(i, FloatRegister::Double), StackPointer, + BailoutStack::offsetOfFpRegs() + i * sizeof(double)); + } // Store the frameSize_ or tableOffset_ stored in ra // See: JitRuntime::generateBailoutTable() @@ -775,8 +777,8 @@ JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm, const VMFunct break; case VMFunction::DoubleByRef: // Copy double sized argument to aligned place. - masm.ma_ld(ScratchDoubleReg, Address(argsBase, argDisp)); - masm.as_sd(ScratchDoubleReg, doubleArgs, doubleArgDisp); + masm.ma_ldc1WordAligned(ScratchDoubleReg, argsBase, argDisp); + masm.as_sdc1(ScratchDoubleReg, doubleArgs, doubleArgDisp); masm.passABIArg(MoveOperand(doubleArgs, doubleArgDisp, MoveOperand::EFFECTIVE_ADDRESS), MoveOp::GENERAL); doubleArgDisp += sizeof(double); @@ -841,7 +843,7 @@ JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm, const VMFunct case Type_Double: if (cx->runtime()->jitSupportsFloatingPoint) { - masm.as_ld(ReturnDoubleReg, StackPointer, 0); + masm.as_ldc1(ReturnDoubleReg, StackPointer, 0); } else { masm.assumeUnreachable("Unable to load into float reg, with no FP support."); } diff --git a/js/src/jit/mips64/Architecture-mips64.h b/js/src/jit/mips64/Architecture-mips64.h index 87a52fd00601..e25730e8b888 100644 --- a/js/src/jit/mips64/Architecture-mips64.h +++ b/js/src/jit/mips64/Architecture-mips64.h @@ -122,6 +122,8 @@ class FloatRegister : public FloatRegisterMIPSShared } bool equiv(const FloatRegister& other) const { return other.kind_ == kind_; } size_t size() const { return (kind_ == Codes::Double) ? sizeof(double) : sizeof (float); } + // Always push doubles to maintain 8-byte stack alignment. + size_t pushSize() const { return sizeof(double); } bool isInvalid() const { return reg_ == FloatRegisters::invalid_freg; } diff --git a/js/src/jit/mips64/CodeGenerator-mips64.cpp b/js/src/jit/mips64/CodeGenerator-mips64.cpp index 7311a9b338d3..70aaf2d9a49f 100644 --- a/js/src/jit/mips64/CodeGenerator-mips64.cpp +++ b/js/src/jit/mips64/CodeGenerator-mips64.cpp @@ -109,12 +109,6 @@ CodeGeneratorMIPS64::ToValue(LInstruction* ins, size_t pos) return ValueOperand(ToRegister(ins->getOperand(pos))); } -ValueOperand -CodeGeneratorMIPS64::ToOutValue(LInstruction* ins) -{ - return ValueOperand(ToRegister(ins->getDef(0))); -} - ValueOperand CodeGeneratorMIPS64::ToTempValue(LInstruction* ins, size_t pos) { @@ -199,12 +193,10 @@ CodeGeneratorMIPS64::visitUnbox(LUnbox* unbox) } } -Register -CodeGeneratorMIPS64::splitTagForTest(const ValueOperand& value) +void +CodeGeneratorMIPS64::splitTagForTest(const ValueOperand& value, ScratchTagScope& Tag) { - MOZ_ASSERT(value.valueReg() != SecondScratchReg); - masm.splitTag(value.valueReg(), SecondScratchReg); - return SecondScratchReg; + masm.splitTag(value.valueReg(), tag); } void diff --git a/js/src/jit/mips64/CodeGenerator-mips64.h b/js/src/jit/mips64/CodeGenerator-mips64.h index c84456764350..06d8a0f35eea 100644 --- a/js/src/jit/mips64/CodeGenerator-mips64.h +++ b/js/src/jit/mips64/CodeGenerator-mips64.h @@ -75,11 +75,10 @@ class CodeGeneratorMIPS64 : public CodeGeneratorMIPSShared void visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool); protected: ValueOperand ToValue(LInstruction* ins, size_t pos); - ValueOperand ToOutValue(LInstruction* ins); ValueOperand ToTempValue(LInstruction* ins, size_t pos); // Functions for LTestVAndBranch. - Register splitTagForTest(const ValueOperand& value); + void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag); public: CodeGeneratorMIPS64(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm) diff --git a/js/src/jit/mips64/MacroAssembler-mips64-inl.h b/js/src/jit/mips64/MacroAssembler-mips64-inl.h index 3efdf7a78d4a..c7d5d14908d4 100644 --- a/js/src/jit/mips64/MacroAssembler-mips64-inl.h +++ b/js/src/jit/mips64/MacroAssembler-mips64-inl.h @@ -768,32 +768,6 @@ MacroAssembler::branchTruncateFloat32MaybeModUint32(FloatRegister src, Register as_sll(dest, dest, 0); } -// ======================================================================== -// Memory access primitives. -void -MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const Address& addr) -{ - ma_sd(src, addr); -} -void -MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const BaseIndex& addr) -{ - MOZ_ASSERT(addr.offset == 0); - ma_sd(src, addr); -} - -void -MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const Address& addr) -{ - ma_ss(src, addr); -} -void -MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const BaseIndex& addr) -{ - MOZ_ASSERT(addr.offset == 0); - ma_ss(src, addr); -} - // ======================================================================== // wasm support @@ -809,7 +783,7 @@ void MacroAssembler::wasmBoundsCheck(Condition cond, Register index, Address boundsCheckLimit, L label) { SecondScratchRegisterScope scratch2(*this); - load32(boundsCheckLimit,SecondScratchReg); + load32(boundsCheckLimit, SecondScratchReg); ma_b(index, SecondScratchReg, label, cond); } diff --git a/js/src/jit/mips64/MacroAssembler-mips64.cpp b/js/src/jit/mips64/MacroAssembler-mips64.cpp index 2163752733d0..3c92a299f702 100644 --- a/js/src/jit/mips64/MacroAssembler-mips64.cpp +++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp @@ -850,7 +850,7 @@ void MacroAssemblerMIPS64::ma_ls(FloatRegister ft, Address address) { if (Imm16::IsInSignedRange(address.offset)) { - as_ls(ft, address.base, address.offset); + as_lwc1(ft, address.base, address.offset); } else { MOZ_ASSERT(address.base != ScratchRegister); ma_li(ScratchRegister, Imm32(address.offset)); @@ -858,7 +858,7 @@ MacroAssemblerMIPS64::ma_ls(FloatRegister ft, Address address) as_gslsx(ft, address.base, ScratchRegister, 0); } else { as_daddu(ScratchRegister, address.base, ScratchRegister); - as_ls(ft, ScratchRegister, 0); + as_lwc1(ft, ScratchRegister, 0); } } } @@ -867,7 +867,7 @@ void MacroAssemblerMIPS64::ma_ld(FloatRegister ft, Address address) { if (Imm16::IsInSignedRange(address.offset)) { - as_ld(ft, address.base, address.offset); + as_ldc1(ft, address.base, address.offset); } else { MOZ_ASSERT(address.base != ScratchRegister); ma_li(ScratchRegister, Imm32(address.offset)); @@ -875,7 +875,7 @@ MacroAssemblerMIPS64::ma_ld(FloatRegister ft, Address address) as_gsldx(ft, address.base, ScratchRegister, 0); } else { as_daddu(ScratchRegister, address.base, ScratchRegister); - as_ld(ft, ScratchRegister, 0); + as_ldc1(ft, ScratchRegister, 0); } } } @@ -884,7 +884,7 @@ void MacroAssemblerMIPS64::ma_sd(FloatRegister ft, Address address) { if (Imm16::IsInSignedRange(address.offset)) { - as_sd(ft, address.base, address.offset); + as_sdc1(ft, address.base, address.offset); } else { MOZ_ASSERT(address.base != ScratchRegister); ma_li(ScratchRegister, Imm32(address.offset)); @@ -892,7 +892,7 @@ MacroAssemblerMIPS64::ma_sd(FloatRegister ft, Address address) as_gssdx(ft, address.base, ScratchRegister, 0); } else { as_daddu(ScratchRegister, address.base, ScratchRegister); - as_sd(ft, ScratchRegister, 0); + as_sdc1(ft, ScratchRegister, 0); } } } @@ -901,7 +901,7 @@ void MacroAssemblerMIPS64::ma_ss(FloatRegister ft, Address address) { if (Imm16::IsInSignedRange(address.offset)) { - as_ss(ft, address.base, address.offset); + as_swc1(ft, address.base, address.offset); } else { MOZ_ASSERT(address.base != ScratchRegister); ma_li(ScratchRegister, Imm32(address.offset)); @@ -909,23 +909,23 @@ MacroAssemblerMIPS64::ma_ss(FloatRegister ft, Address address) as_gsssx(ft, address.base, ScratchRegister, 0); } else { as_daddu(ScratchRegister, address.base, ScratchRegister); - as_ss(ft, ScratchRegister, 0); + as_swc1(ft, ScratchRegister, 0); } } } void -MacroAssemblerMIPS64::ma_pop(FloatRegister fs) +MacroAssemblerMIPS64::ma_pop(FloatRegister f) { - ma_ld(fs, Address(StackPointer, 0)); + as_ldc1(f, StackPointer, 0); as_daddiu(StackPointer, StackPointer, sizeof(double)); } void -MacroAssemblerMIPS64::ma_push(FloatRegister fs) +MacroAssemblerMIPS64::ma_push(FloatRegister f) { as_daddiu(StackPointer, StackPointer, (int32_t)-sizeof(double)); - ma_sd(fs, Address(StackPointer, 0)); + as_sdc1(f, StackPointer, 0); } bool @@ -1088,19 +1088,6 @@ MacroAssemblerMIPS64Compat::loadPrivate(const Address& address, Register dest) ma_dsll(dest, dest, Imm32(1)); } -void -MacroAssemblerMIPS64Compat::loadDouble(const Address& address, FloatRegister dest) -{ - ma_ld(dest, address); -} - -void -MacroAssemblerMIPS64Compat::loadDouble(const BaseIndex& src, FloatRegister dest) -{ - computeScaledAddress(src, SecondScratchReg); - ma_ld(dest, Address(SecondScratchReg, src.offset)); -} - void MacroAssemblerMIPS64Compat::loadUnalignedDouble(const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp, FloatRegister dest) @@ -1120,33 +1107,6 @@ MacroAssemblerMIPS64Compat::loadUnalignedDouble(const wasm::MemoryAccessDesc& ac moveToDouble(temp, dest); } -void -MacroAssemblerMIPS64Compat::loadFloatAsDouble(const Address& address, FloatRegister dest) -{ - ma_ls(dest, address); - as_cvtds(dest, dest); -} - -void -MacroAssemblerMIPS64Compat::loadFloatAsDouble(const BaseIndex& src, FloatRegister dest) -{ - loadFloat32(src, dest); - as_cvtds(dest, dest); -} - -void -MacroAssemblerMIPS64Compat::loadFloat32(const Address& address, FloatRegister dest) -{ - ma_ls(dest, address); -} - -void -MacroAssemblerMIPS64Compat::loadFloat32(const BaseIndex& src, FloatRegister dest) -{ - computeScaledAddress(src, SecondScratchReg); - ma_ls(dest, Address(SecondScratchReg, src.offset)); -} - void MacroAssemblerMIPS64Compat::loadUnalignedFloat32(const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp, FloatRegister dest) @@ -1847,9 +1807,12 @@ MacroAssemblerMIPS64Compat::ensureDouble(const ValueOperand& source, FloatRegist Label* failure) { Label isDouble, done; - Register tag = splitTagForTest(source); - asMasm().branchTestDouble(Assembler::Equal, tag, &isDouble); - asMasm().branchTestInt32(Assembler::NotEqual, tag, failure); + { + ScratchTagScope tag(this, source); + splitTagForTest(source, tag); + asMasm().branchTestDouble(Assembler::Equal, tag, &isDouble); + asMasm().branchTestInt32(Assembler::NotEqual, tag, failure); + } unboxInt32(source, ScratchRegister); convertInt32ToDouble(ScratchRegister, dest); diff --git a/js/src/jit/mips64/MacroAssembler-mips64.h b/js/src/jit/mips64/MacroAssembler-mips64.h index d23fe144e98e..bd56e0ce834d 100644 --- a/js/src/jit/mips64/MacroAssembler-mips64.h +++ b/js/src/jit/mips64/MacroAssembler-mips64.h @@ -44,6 +44,29 @@ static constexpr ValueOperand JSReturnOperand{JSReturnReg}; static const int defaultShift = 3; static_assert(1 << defaultShift == sizeof(JS::Value), "The defaultShift is wrong"); +// See documentation for ScratchTagScope and ScratchTagScopeRelease in +// MacroAssembler-x64.h. + +class ScratchTagScope : public SecondScratchRegisterScope +{ + public: + ScratchTagScope(MacroAssembler& masm, const ValueOperand&) + : SecondScratchRegisterScope(masm) + {} +}; + +class ScratchTagScopeRelease +{ + ScratchTagScope* ts_; + public: + explicit ScratchTagScopeRelease(ScratchTagScope* ts) : ts_(ts) { + ts_->release(); + } + ~ScratchTagScopeRelease() { + ts_->reacquire(); + } +}; + class MacroAssemblerMIPS64 : public MacroAssemblerMIPSShared { public: @@ -51,6 +74,8 @@ class MacroAssemblerMIPS64 : public MacroAssemblerMIPSShared using MacroAssemblerMIPSShared::ma_li; using MacroAssemblerMIPSShared::ma_ss; using MacroAssemblerMIPSShared::ma_sd; + using MacroAssemblerMIPSShared::ma_ls; + using MacroAssemblerMIPSShared::ma_ld; using MacroAssemblerMIPSShared::ma_load; using MacroAssemblerMIPSShared::ma_store; using MacroAssemblerMIPSShared::ma_cmp_set; @@ -133,13 +158,13 @@ class MacroAssemblerMIPS64 : public MacroAssemblerMIPSShared void ma_mv(FloatRegister src, ValueOperand dest); void ma_mv(ValueOperand src, FloatRegister dest); - void ma_ls(FloatRegister fd, Address address); - void ma_ld(FloatRegister fd, Address address); - void ma_sd(FloatRegister fd, Address address); - void ma_ss(FloatRegister fd, Address address); + void ma_ls(FloatRegister ft, Address address); + void ma_ld(FloatRegister ft, Address address); + void ma_sd(FloatRegister ft, Address address); + void ma_ss(FloatRegister ft, Address address); - void ma_pop(FloatRegister fs); - void ma_push(FloatRegister fs); + void ma_pop(FloatRegister f); + void ma_push(FloatRegister f); void ma_cmp_set(Register dst, Register lhs, ImmWord imm, Condition c); void ma_cmp_set(Register dst, Register lhs, ImmPtr imm, Condition c); @@ -354,10 +379,8 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64 splitTag(operand.valueReg(), dest); } - // Returns the register containing the type tag. - Register splitTagForTest(const ValueOperand& value) { - splitTag(value, SecondScratchReg); - return SecondScratchReg; + void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag) { + splitTag(value, tag); } // unboxing code @@ -660,17 +683,8 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64 void storeUnalignedSimd128Float(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); } void storeUnalignedSimd128Float(FloatRegister src, BaseIndex addr) { MOZ_CRASH("NYI"); } - void loadDouble(const Address& addr, FloatRegister dest); - void loadDouble(const BaseIndex& src, FloatRegister dest); void loadUnalignedDouble(const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp, FloatRegister dest); - - // Load a float value into a register, then expand it to a double. - void loadFloatAsDouble(const Address& addr, FloatRegister dest); - void loadFloatAsDouble(const BaseIndex& src, FloatRegister dest); - - void loadFloat32(const Address& addr, FloatRegister dest); - void loadFloat32(const BaseIndex& src, FloatRegister dest); void loadUnalignedFloat32(const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp, FloatRegister dest); diff --git a/js/src/jit/mips64/Trampoline-mips64.cpp b/js/src/jit/mips64/Trampoline-mips64.cpp index a6dda19acf92..2c5899e0c445 100644 --- a/js/src/jit/mips64/Trampoline-mips64.cpp +++ b/js/src/jit/mips64/Trampoline-mips64.cpp @@ -64,6 +64,8 @@ struct EnterJITRegs static void GenerateReturn(MacroAssembler& masm, int returnCode) { + MOZ_ASSERT(masm.framePushed() == sizeof(EnterJITRegs)); + if (isLoongson()) { // Restore non-volatile registers masm.as_ld(s0, StackPointer, offsetof(EnterJITRegs, s0)); @@ -92,14 +94,14 @@ GenerateReturn(MacroAssembler& masm, int returnCode) masm.as_ld(ra, StackPointer, offsetof(EnterJITRegs, ra)); // Restore non-volatile floating point registers - masm.as_ld(f24, StackPointer, offsetof(EnterJITRegs, f24)); - masm.as_ld(f25, StackPointer, offsetof(EnterJITRegs, f25)); - masm.as_ld(f26, StackPointer, offsetof(EnterJITRegs, f26)); - masm.as_ld(f27, StackPointer, offsetof(EnterJITRegs, f27)); - masm.as_ld(f28, StackPointer, offsetof(EnterJITRegs, f28)); - masm.as_ld(f29, StackPointer, offsetof(EnterJITRegs, f29)); - masm.as_ld(f30, StackPointer, offsetof(EnterJITRegs, f30)); - masm.as_ld(f31, StackPointer, offsetof(EnterJITRegs, f31)); + masm.as_ldc1(f24, StackPointer, offsetof(EnterJITRegs, f24)); + masm.as_ldc1(f25, StackPointer, offsetof(EnterJITRegs, f25)); + masm.as_ldc1(f26, StackPointer, offsetof(EnterJITRegs, f26)); + masm.as_ldc1(f27, StackPointer, offsetof(EnterJITRegs, f27)); + masm.as_ldc1(f28, StackPointer, offsetof(EnterJITRegs, f28)); + masm.as_ldc1(f29, StackPointer, offsetof(EnterJITRegs, f29)); + masm.as_ldc1(f30, StackPointer, offsetof(EnterJITRegs, f30)); + masm.as_ldc1(f31, StackPointer, offsetof(EnterJITRegs, f31)); } masm.freeStack(sizeof(EnterJITRegs)); @@ -139,14 +141,14 @@ GeneratePrologue(MacroAssembler& masm) masm.as_sd(ra, StackPointer, offsetof(EnterJITRegs, ra)); masm.as_sd(a7, StackPointer, offsetof(EnterJITRegs, a7)); - masm.as_sd(f24, StackPointer, offsetof(EnterJITRegs, f24)); - masm.as_sd(f25, StackPointer, offsetof(EnterJITRegs, f25)); - masm.as_sd(f26, StackPointer, offsetof(EnterJITRegs, f26)); - masm.as_sd(f27, StackPointer, offsetof(EnterJITRegs, f27)); - masm.as_sd(f28, StackPointer, offsetof(EnterJITRegs, f28)); - masm.as_sd(f29, StackPointer, offsetof(EnterJITRegs, f29)); - masm.as_sd(f30, StackPointer, offsetof(EnterJITRegs, f30)); - masm.as_sd(f31, StackPointer, offsetof(EnterJITRegs, f31)); + masm.as_sdc1(f24, StackPointer, offsetof(EnterJITRegs, f24)); + masm.as_sdc1(f25, StackPointer, offsetof(EnterJITRegs, f25)); + masm.as_sdc1(f26, StackPointer, offsetof(EnterJITRegs, f26)); + masm.as_sdc1(f27, StackPointer, offsetof(EnterJITRegs, f27)); + masm.as_sdc1(f28, StackPointer, offsetof(EnterJITRegs, f28)); + masm.as_sdc1(f29, StackPointer, offsetof(EnterJITRegs, f29)); + masm.as_sdc1(f30, StackPointer, offsetof(EnterJITRegs, f30)); + masm.as_sdc1(f31, StackPointer, offsetof(EnterJITRegs, f31)); } @@ -796,7 +798,7 @@ JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm, const VMFunct case Type_Double: if (cx->runtime()->jitSupportsFloatingPoint) { - masm.as_ld(ReturnDoubleReg, StackPointer, 0); + masm.as_ldc1(ReturnDoubleReg, StackPointer, 0); } else { masm.assumeUnreachable("Unable to load into float reg, with no FP support."); } diff --git a/js/src/jit/none/CodeGenerator-none.h b/js/src/jit/none/CodeGenerator-none.h index ad62ea452b2a..af2b151cd557 100644 --- a/js/src/jit/none/CodeGenerator-none.h +++ b/js/src/jit/none/CodeGenerator-none.h @@ -48,7 +48,6 @@ class CodeGeneratorNone : public CodeGeneratorShared } void emitTableSwitchDispatch(MTableSwitch*, Register, Register) { MOZ_CRASH(); } ValueOperand ToValue(LInstruction*, size_t) { MOZ_CRASH(); } - ValueOperand ToOutValue(LInstruction*) { MOZ_CRASH(); } ValueOperand ToTempValue(LInstruction*, size_t) { MOZ_CRASH(); } void generateInvalidateEpilogue() { MOZ_CRASH(); } void setReturnDoubleRegs(LiveRegisterSet* regs) { MOZ_CRASH(); } diff --git a/js/src/jit/none/MacroAssembler-none.h b/js/src/jit/none/MacroAssembler-none.h index da2b332ca25f..d721e4e11c28 100644 --- a/js/src/jit/none/MacroAssembler-none.h +++ b/js/src/jit/none/MacroAssembler-none.h @@ -176,6 +176,21 @@ class Operand Operand (Register, int32_t ) { MOZ_CRASH(); } }; +class ScratchTagScope +{ + public: + ScratchTagScope(MacroAssembler&, const ValueOperand) {} + operator Register() { MOZ_CRASH(); } + void release() { MOZ_CRASH(); } + void reacquire() { MOZ_CRASH(); } +}; + +class ScratchTagScopeRelease +{ + public: + explicit ScratchTagScopeRelease(ScratchTagScope*) {} +}; + class MacroAssemblerNone : public Assembler { public: @@ -313,7 +328,7 @@ class MacroAssemblerNone : public Assembler template void computeEffectiveAddress(T, Register) { MOZ_CRASH(); } - Register splitTagForTest(ValueOperand) { MOZ_CRASH(); } + void splitTagForTest(ValueOperand, ScratchTagScope&) { MOZ_CRASH(); } void boxDouble(FloatRegister, ValueOperand, FloatRegister) { MOZ_CRASH(); } void boxNonDouble(JSValueType, Register, ValueOperand) { MOZ_CRASH(); } diff --git a/js/src/jit/shared/CodeGenerator-shared-inl.h b/js/src/jit/shared/CodeGenerator-shared-inl.h index 45a1359e2641..07b4f9fa78ae 100644 --- a/js/src/jit/shared/CodeGenerator-shared-inl.h +++ b/js/src/jit/shared/CodeGenerator-shared-inl.h @@ -193,7 +193,7 @@ ToRegisterOrInt32Constant(const LAllocation* a) } static inline ValueOperand -GetValueOutput(LInstruction* ins) +ToOutValue(LInstruction* ins) { #if defined(JS_NUNBOX32) return ValueOperand(ToRegister(ins->getDef(TYPE_INDEX)), diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h index 02240d31a620..bd33bd99bd63 100644 --- a/js/src/jit/shared/LIR-shared.h +++ b/js/src/jit/shared/LIR-shared.h @@ -7788,7 +7788,7 @@ class LLoadUnboxedExpando : public LInstructionHelper<1, 1, 0> }; // Guard that a value is in a TypeSet. -class LTypeBarrierV : public LInstructionHelper<0, BOX_PIECES, 2> +class LTypeBarrierV : public LInstructionHelper { public: LIR_HEADER(TypeBarrierV) @@ -7814,7 +7814,7 @@ class LTypeBarrierV : public LInstructionHelper<0, BOX_PIECES, 2> }; // Guard that a object is in a TypeSet. -class LTypeBarrierO : public LInstructionHelper<0, 1, 1> +class LTypeBarrierO : public LInstructionHelper<1, 1, 1> { public: LIR_HEADER(TypeBarrierO) @@ -7834,32 +7834,6 @@ class LTypeBarrierO : public LInstructionHelper<0, 1, 1> } }; -// Guard that a value is in a TypeSet. -class LMonitorTypes : public LInstructionHelper<0, BOX_PIECES, 2> -{ - public: - LIR_HEADER(MonitorTypes) - - LMonitorTypes(const LBoxAllocation& input, const LDefinition& unboxTemp, - const LDefinition& objTemp) { - setBoxOperand(Input, input); - setTemp(0, unboxTemp); - setTemp(1, objTemp); - } - - static const size_t Input = 0; - - const MMonitorTypes* mir() const { - return mir_->toMonitorTypes(); - } - const LDefinition* unboxTemp() { - return getTemp(0); - } - const LDefinition* objTemp() { - return getTemp(1); - } -}; - // Generational write barrier used when writing an object to another object. class LPostWriteBarrierO : public LInstructionHelper<0, 2, 1> { diff --git a/js/src/jit/shared/LOpcodes-shared.h b/js/src/jit/shared/LOpcodes-shared.h index edac14985537..2d0fc83bab6e 100644 --- a/js/src/jit/shared/LOpcodes-shared.h +++ b/js/src/jit/shared/LOpcodes-shared.h @@ -270,7 +270,6 @@ _(LoadUnboxedExpando) \ _(TypeBarrierV) \ _(TypeBarrierO) \ - _(MonitorTypes) \ _(PostWriteBarrierO) \ _(PostWriteBarrierS) \ _(PostWriteBarrierV) \ diff --git a/js/src/jit/shared/Lowering-shared-inl.h b/js/src/jit/shared/Lowering-shared-inl.h index 021fab88ba46..2b97ffdd1916 100644 --- a/js/src/jit/shared/Lowering-shared-inl.h +++ b/js/src/jit/shared/Lowering-shared-inl.h @@ -159,6 +159,46 @@ LIRGeneratorShared::defineInt64ReuseInput(LInstructionHelper void +LIRGeneratorShared::defineBoxReuseInput(LInstructionHelper* lir, + MDefinition* mir, uint32_t operand) +{ + // The input should be used at the start of the instruction, to avoid moves. + MOZ_ASSERT(lir->getOperand(operand)->toUse()->usedAtStart()); +#ifdef JS_NUNBOX32 + MOZ_ASSERT(lir->getOperand(operand + 1)->toUse()->usedAtStart()); +#endif + MOZ_ASSERT(!lir->isCall()); + MOZ_ASSERT(mir->type() == MIRType::Value); + + uint32_t vreg = getVirtualRegister(); + +#ifdef JS_NUNBOX32 + static_assert(VREG_TYPE_OFFSET == 0, "Code below assumes VREG_TYPE_OFFSET == 0"); + static_assert(VREG_DATA_OFFSET == 1, "Code below assumes VREG_DATA_OFFSET == 1"); + + LDefinition def1(LDefinition::TYPE, LDefinition::MUST_REUSE_INPUT); + def1.setReusedInput(operand); + def1.setVirtualRegister(vreg); + lir->setDef(0, def1); + + getVirtualRegister(); + LDefinition def2(LDefinition::PAYLOAD, LDefinition::MUST_REUSE_INPUT); + def2.setReusedInput(operand + 1); + def2.setVirtualRegister(vreg + 1); + lir->setDef(1, def2); +#else + LDefinition def(LDefinition::BOX, LDefinition::MUST_REUSE_INPUT); + def.setReusedInput(operand); + def.setVirtualRegister(vreg); + lir->setDef(0, def); +#endif + + lir->setMir(mir); + mir->setVirtualRegister(vreg); + add(lir); +} + template void LIRGeneratorShared::defineBox(details::LInstructionFixedDefsTempsHelper* lir, MDefinition* mir, LDefinition::Policy policy) @@ -679,8 +719,8 @@ VirtualRegisterOfPayload(MDefinition* mir) if (!inner->isConstant() && inner->type() != MIRType::Double && inner->type() != MIRType::Float32) return inner->virtualRegister(); } - if (mir->isTypeBarrier()) - return VirtualRegisterOfPayload(mir->getOperand(0)); + if (mir->isTypeBarrier() && mir->toTypeBarrier()->canRedefineInput()) + return VirtualRegisterOfPayload(mir->toTypeBarrier()->input()); return mir->virtualRegister() + VREG_DATA_OFFSET; } diff --git a/js/src/jit/shared/Lowering-shared.h b/js/src/jit/shared/Lowering-shared.h index a4f14c68d5bc..e0de2e25a87b 100644 --- a/js/src/jit/shared/Lowering-shared.h +++ b/js/src/jit/shared/Lowering-shared.h @@ -187,6 +187,10 @@ class LIRGeneratorShared : public MDefinitionVisitor inline void defineReuseInput(LInstructionHelper<1, Ops, Temps>* lir, MDefinition* mir, uint32_t operand); + template + inline void defineBoxReuseInput(LInstructionHelper* lir, + MDefinition* mir, uint32_t operand); + template inline void defineInt64ReuseInput(LInstructionHelper* lir, MDefinition* mir, uint32_t operand); diff --git a/js/src/jit/x64/CodeGenerator-x64.cpp b/js/src/jit/x64/CodeGenerator-x64.cpp index cd84513b015a..2a52b0d24438 100644 --- a/js/src/jit/x64/CodeGenerator-x64.cpp +++ b/js/src/jit/x64/CodeGenerator-x64.cpp @@ -30,12 +30,6 @@ CodeGeneratorX64::ToValue(LInstruction* ins, size_t pos) return ValueOperand(ToRegister(ins->getOperand(pos))); } -ValueOperand -CodeGeneratorX64::ToOutValue(LInstruction* ins) -{ - return ValueOperand(ToRegister(ins->getDef(0))); -} - ValueOperand CodeGeneratorX64::ToTempValue(LInstruction* ins, size_t pos) { @@ -73,7 +67,7 @@ FrameSizeClass::frameSize() const void CodeGeneratorX64::visitValue(LValue* value) { - ValueOperand result = GetValueOutput(value); + ValueOperand result = ToOutValue(value); masm.moveValue(value->value(), result); } @@ -81,7 +75,7 @@ void CodeGeneratorX64::visitBox(LBox* box) { const LAllocation* in = box->getOperand(0); - ValueOperand result = GetValueOutput(box); + ValueOperand result = ToOutValue(box); masm.moveValue(TypedOrValueRegister(box->type(), ToAnyRegister(in)), result); } diff --git a/js/src/jit/x64/CodeGenerator-x64.h b/js/src/jit/x64/CodeGenerator-x64.h index e9da6c3e4cd7..16e501c5f91b 100644 --- a/js/src/jit/x64/CodeGenerator-x64.h +++ b/js/src/jit/x64/CodeGenerator-x64.h @@ -21,7 +21,6 @@ class CodeGeneratorX64 : public CodeGeneratorX86Shared protected: Operand ToOperand64(const LInt64Allocation& a); ValueOperand ToValue(LInstruction* ins, size_t pos); - ValueOperand ToOutValue(LInstruction* ins); ValueOperand ToTempValue(LInstruction* ins, size_t pos); void storeUnboxedValue(const LAllocation* value, MIRType valueType, diff --git a/js/src/jit/x64/MacroAssembler-x64-inl.h b/js/src/jit/x64/MacroAssembler-x64-inl.h index c678625fb8c7..cf59a82c11b8 100644 --- a/js/src/jit/x64/MacroAssembler-x64-inl.h +++ b/js/src/jit/x64/MacroAssembler-x64-inl.h @@ -846,6 +846,12 @@ MacroAssembler::test32MovePtr(Condition cond, const Address& addr, Imm32 mask, R cmovCCq(cond, Operand(src), dest); } +void +MacroAssembler::spectreMovePtr(Condition cond, Register src, Register dest) +{ + cmovCCq(cond, Operand(src), dest); +} + // ======================================================================== // Truncate floating point. @@ -949,9 +955,12 @@ void MacroAssemblerX64::ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure) { Label isDouble, done; - Register tag = splitTagForTest(source); - asMasm().branchTestDouble(Assembler::Equal, tag, &isDouble); - asMasm().branchTestInt32(Assembler::NotEqual, tag, failure); + { + ScratchTagScope tag(asMasm(), source); + splitTagForTest(source, tag); + asMasm().branchTestDouble(Assembler::Equal, tag, &isDouble); + asMasm().branchTestInt32(Assembler::NotEqual, tag, failure); + } ScratchRegisterScope scratch(asMasm()); unboxInt32(source, scratch); diff --git a/js/src/jit/x64/MacroAssembler-x64.h b/js/src/jit/x64/MacroAssembler-x64.h index f00c1de9993b..17e204a0eed6 100644 --- a/js/src/jit/x64/MacroAssembler-x64.h +++ b/js/src/jit/x64/MacroAssembler-x64.h @@ -32,6 +32,44 @@ struct ImmTag : public Imm32 { } }; +// ScratchTagScope and ScratchTagScopeRelease are used to manage the tag +// register for splitTagForTest(), which has different register management on +// different platforms. On 64-bit platforms it requires a scratch register that +// does not interfere with other operations; on 32-bit platforms it uses a +// register that is already part of the Value. +// +// The ScratchTagScope RAII type acquires the appropriate register; a reference +// to a variable of this type is then passed to splitTagForTest(). +// +// On 64-bit platforms ScratchTagScopeRelease makes the owned scratch register +// available in a dynamic scope during compilation. However it is important to +// remember that that does not preserve the register value in any way, so this +// RAII type should only be used along paths that eventually branch past further +// uses of the extracted tag value. +// +// On 32-bit platforms ScratchTagScopeRelease has no effect, since it does not +// manage a register, it only aliases a register in the ValueOperand. + +class ScratchTagScope : public ScratchRegisterScope +{ + public: + ScratchTagScope(MacroAssembler& masm, const ValueOperand&) + : ScratchRegisterScope(masm) + {} +}; + +class ScratchTagScopeRelease +{ + ScratchTagScope* ts_; + public: + explicit ScratchTagScopeRelease(ScratchTagScope* ts) : ts_(ts) { + ts_->release(); + } + ~ScratchTagScopeRelease() { + ts_->reacquire(); + } +}; + class MacroAssemblerX64 : public MacroAssemblerX86Shared { private: @@ -662,19 +700,19 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared splitTag(Operand(operand), dest); } - // Extracts the tag of a value and places it in ScratchReg. - Register splitTagForTest(const ValueOperand& value) { - splitTag(value, ScratchReg); - return ScratchReg; + // Extracts the tag of a value and places it in tag. + void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag) { + splitTag(value, tag); } void cmpTag(const ValueOperand& operand, ImmTag tag) { - Register reg = splitTagForTest(operand); + ScratchTagScope reg(asMasm(), operand); + splitTagForTest(operand, reg); cmp32(reg, tag); } Condition testMagic(Condition cond, const ValueOperand& src) { - ScratchRegisterScope scratch(asMasm()); - splitTag(src, scratch); + ScratchTagScope scratch(asMasm(), src); + splitTagForTest(src, scratch); return testMagic(cond, scratch); } Condition testError(Condition cond, const ValueOperand& src) { diff --git a/js/src/jit/x86/CodeGenerator-x86.cpp b/js/src/jit/x86/CodeGenerator-x86.cpp index c4262c1259ee..2abe2220c380 100644 --- a/js/src/jit/x86/CodeGenerator-x86.cpp +++ b/js/src/jit/x86/CodeGenerator-x86.cpp @@ -70,14 +70,6 @@ CodeGeneratorX86::ToValue(LInstruction* ins, size_t pos) return ValueOperand(typeReg, payloadReg); } -ValueOperand -CodeGeneratorX86::ToOutValue(LInstruction* ins) -{ - Register typeReg = ToRegister(ins->getDef(TYPE_INDEX)); - Register payloadReg = ToRegister(ins->getDef(PAYLOAD_INDEX)); - return ValueOperand(typeReg, payloadReg); -} - ValueOperand CodeGeneratorX86::ToTempValue(LInstruction* ins, size_t pos) { diff --git a/js/src/jit/x86/CodeGenerator-x86.h b/js/src/jit/x86/CodeGenerator-x86.h index 741c15ac7faa..e8fa6a0d517c 100644 --- a/js/src/jit/x86/CodeGenerator-x86.h +++ b/js/src/jit/x86/CodeGenerator-x86.h @@ -25,7 +25,6 @@ class CodeGeneratorX86 : public CodeGeneratorX86Shared protected: ValueOperand ToValue(LInstruction* ins, size_t pos); - ValueOperand ToOutValue(LInstruction* ins); ValueOperand ToTempValue(LInstruction* ins, size_t pos); template void emitWasmLoad(T* ins); diff --git a/js/src/jit/x86/MacroAssembler-x86-inl.h b/js/src/jit/x86/MacroAssembler-x86-inl.h index d0a6d0322964..43e5df690faf 100644 --- a/js/src/jit/x86/MacroAssembler-x86-inl.h +++ b/js/src/jit/x86/MacroAssembler-x86-inl.h @@ -1035,6 +1035,12 @@ MacroAssembler::test32MovePtr(Condition cond, const Address& addr, Imm32 mask, R cmovCCl(cond, Operand(src), dest); } +void +MacroAssembler::spectreMovePtr(Condition cond, Register src, Register dest) +{ + cmovCCl(cond, Operand(src), dest); +} + // ======================================================================== // Truncate floating point. diff --git a/js/src/jit/x86/MacroAssembler-x86.h b/js/src/jit/x86/MacroAssembler-x86.h index ea3bc4c09234..0f4c9c755b97 100644 --- a/js/src/jit/x86/MacroAssembler-x86.h +++ b/js/src/jit/x86/MacroAssembler-x86.h @@ -15,6 +15,25 @@ namespace js { namespace jit { +// See documentation for ScratchTagScope and ScratchTagScopeRelease in +// MacroAssembler-x64.h. + +class ScratchTagScope +{ + const ValueOperand& v_; + public: + ScratchTagScope(MacroAssembler&, const ValueOperand& v) : v_(v) {} + operator Register() { return v_.typeReg(); } + void release() {} + void reacquire() {} +}; + +class ScratchTagScopeRelease +{ + public: + explicit ScratchTagScopeRelease(ScratchTagScope*) {} +}; + class MacroAssemblerX86 : public MacroAssemblerX86Shared { private: @@ -247,9 +266,8 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared movl(src, dest); } - // Returns the register containing the type tag. - Register splitTagForTest(const ValueOperand& value) { - return value.typeReg(); + void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag) { + MOZ_ASSERT(value.typeReg() == tag); } Condition testUndefined(Condition cond, Register tag) { diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 6f28cbfeb981..41be31996cfd 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -7265,6 +7265,9 @@ JS_SetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t v case JSJITCOMPILER_SPECTRE_INDEX_MASKING: jit::JitOptions.spectreIndexMasking = !!value; break; + case JSJITCOMPILER_SPECTRE_OBJECT_MITIGATIONS_BARRIERS: + jit::JitOptions.spectreObjectMitigationsBarriers = !!value; + break; case JSJITCOMPILER_SPECTRE_STRING_MITIGATIONS: jit::JitOptions.spectreStringMitigations = !!value; break; diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 9eb023346f32..d7b8a5b3ab51 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -5924,6 +5924,7 @@ JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled); Register(JUMP_THRESHOLD, "jump-threshold") \ Register(SIMULATOR_ALWAYS_INTERRUPT, "simulator.always-interrupt") \ Register(SPECTRE_INDEX_MASKING, "spectre.index-masking") \ + Register(SPECTRE_OBJECT_MITIGATIONS_BARRIERS, "spectre.object-mitigations.barriers") \ Register(SPECTRE_STRING_MITIGATIONS, "spectre.string-mitigations") \ Register(SPECTRE_VALUE_MASKING, "spectre.value-masking") \ Register(ASMJS_ATOMICS_ENABLE, "asmjs.atomics.enable") \ diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index befa547a2756..ff09bc9dd1b5 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -8469,10 +8469,12 @@ SetContextOptions(JSContext* cx, const OptionParser& op) if (const char* str = op.getStringOption("spectre-mitigations")) { if (strcmp(str, "on") == 0) { jit::JitOptions.spectreIndexMasking = true; + jit::JitOptions.spectreObjectMitigationsBarriers = true; jit::JitOptions.spectreStringMitigations = true; jit::JitOptions.spectreValueMasking = true; } else if (strcmp(str, "off") == 0) { jit::JitOptions.spectreIndexMasking = false; + jit::JitOptions.spectreObjectMitigationsBarriers = false; jit::JitOptions.spectreStringMitigations = false; jit::JitOptions.spectreValueMasking = false; } else { diff --git a/js/src/tests/non262/Intl/extensions/unicode-extension-sequences.js b/js/src/tests/non262/Intl/extensions/unicode-extension-sequences.js new file mode 100644 index 000000000000..25173f70c93f --- /dev/null +++ b/js/src/tests/non262/Intl/extensions/unicode-extension-sequences.js @@ -0,0 +1,79 @@ +// |reftest| skip-if(!this.getSelfHostedValue) + +const startOfUnicodeExtensions = getSelfHostedValue("startOfUnicodeExtensions"); +const endOfUnicodeExtensions = getSelfHostedValue("endOfUnicodeExtensions"); + +const testcases = [ + // Language tag without Unicode extension. + { locale: "en", start: -1, end: 0 }, + { locale: "en-Latn", start: -1, end: 0 }, + { locale: "en-x-y", start: -1, end: 0 }, + { locale: "en-x-yz", start: -1, end: 0 }, + { locale: "en-x-u-kf", start: -1, end: 0 }, + + // Irregular grandfathered language tag without Unicode extension. + { locale: "i-default", start: -1, end: 0 }, + + // Privateuse only language tag. + { locale: "x-only", start: -1, end: 0 }, + { locale: "x-only-u", start: -1, end: 0 }, + { locale: "x-only-u-kf", start: -1, end: 0 }, + + // Unicode extension sequence starts with key subtag. + // - no suceeding key or type subtags. + { locale: "en-u-ab", start: 2, end: 7 }, + { locale: "en-u-ab-x-y", start: 2, end: 7 }, + { locale: "en-u-ab-x-yz", start: 2, end: 7 }, + { locale: "en-u-ab-x-u-kn", start: 2, end: 7 }, + // - followed by key subtag. + { locale: "en-u-ab-cd", start: 2, end: 10 }, + { locale: "en-u-ab-cd-x-y", start: 2, end: 10 }, + { locale: "en-u-ab-cd-x-yz", start: 2, end: 10 }, + { locale: "en-u-ab-cd-x-u-kn", start: 2, end: 10 }, + // - followed by type subtag. + { locale: "en-u-ab-cdef", start: 2, end: 12 }, + { locale: "en-u-ab-cdef-x-y", start: 2, end: 12 }, + { locale: "en-u-ab-cdef-x-yz", start: 2, end: 12 }, + { locale: "en-u-ab-cdef-x-y-u-kn", start: 2, end: 12 }, + + // Unicode extension sequence starts with attribute subtag. + // - no suceeding attribute or key subtags. + { locale: "en-u-abc", start: 2, end: 8 }, + { locale: "en-u-abc-x-y", start: 2, end: 8 }, + { locale: "en-u-abc-x-yz", start: 2, end: 8 }, + { locale: "en-u-abc-x-y-u-kn", start: 2, end: 8 }, + // - followed by attribute subtag. + { locale: "en-u-abc-def", start: 2, end: 12 }, + { locale: "en-u-abc-def-x-y", start: 2, end: 12 }, + { locale: "en-u-abc-def-x-yz", start: 2, end: 12 }, + { locale: "en-u-abc-def-x-y-u-kn", start: 2, end: 12 }, + // - followed by key subtag. + { locale: "en-u-abc-de", start: 2, end: 11 }, + { locale: "en-u-abc-de-x-y", start: 2, end: 11 }, + { locale: "en-u-abc-de-x-yz", start: 2, end: 11 }, + { locale: "en-u-abc-de-x-y-u-kn", start: 2, end: 11 }, + // - followed by two key subtags. + { locale: "en-u-abc-de-fg", start: 2, end: 14 }, + { locale: "en-u-abc-de-fg-x-y", start: 2, end: 14 }, + { locale: "en-u-abc-de-fg-x-yz", start: 2, end: 14 }, + { locale: "en-u-abc-de-fg-x-y-u-kn", start: 2, end: 14 }, + // - followed by key and type subtag. + { locale: "en-u-abc-de-fgh", start: 2, end: 15 }, + { locale: "en-u-abc-de-fgh-x-y", start: 2, end: 15 }, + { locale: "en-u-abc-de-fgh-x-yz", start: 2, end: 15 }, + { locale: "en-u-abc-de-fgh-x-y-u-kn", start: 2, end: 15 }, + + // Also test when the Unicode extension doesn't start at index 2. + { locale: "en-Latn-u-kf", start: 7, end: 12 }, + { locale: "und-u-kf", start: 3, end: 8 }, +]; + +for (const {locale, start, end} of testcases) { + assertEq(startOfUnicodeExtensions(locale), start); + + if (start >= 0) + assertEq(endOfUnicodeExtensions(locale, start), end); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/vm/JSScript.cpp b/js/src/vm/JSScript.cpp index f31a899bf4d7..93097af23f53 100644 --- a/js/src/vm/JSScript.cpp +++ b/js/src/vm/JSScript.cpp @@ -1398,21 +1398,6 @@ JSScript::hasScriptName() return p.found(); } -void -ScriptSourceObject::trace(JSTracer* trc, JSObject* obj) -{ - ScriptSourceObject* sso = static_cast(obj); - - // Don't trip over the poison 'not yet initialized' values. - if (!sso->getReservedSlot(INTRODUCTION_SCRIPT_SLOT).isMagic(JS_GENERIC_MAGIC)) { - JSScript* script = sso->introductionScript(); - if (script) { - TraceManuallyBarrieredEdge(trc, &script, "ScriptSourceObject introductionScript"); - sso->setReservedSlot(INTRODUCTION_SCRIPT_SLOT, PrivateValue(script)); - } - } -} - void ScriptSourceObject::finalize(FreeOp* fop, JSObject* obj) { @@ -1433,7 +1418,7 @@ static const ClassOps ScriptSourceObjectClassOps = { nullptr, /* call */ nullptr, /* hasInstance */ nullptr, /* construct */ - ScriptSourceObject::trace + nullptr /* trace */ }; const Class ScriptSourceObject::class_ = { @@ -1483,13 +1468,13 @@ ScriptSourceObject::initFromOptions(JSContext* cx, HandleScriptSource source, // we would be creating a cross-compartment script reference, which is // forbidden. In that case, simply don't bother to retain the introduction // script. + Value introductionScript = UndefinedValue(); if (options.introductionScript() && options.introductionScript()->compartment() == cx->compartment()) { - source->setReservedSlot(INTRODUCTION_SCRIPT_SLOT, PrivateValue(options.introductionScript())); - } else { - source->setReservedSlot(INTRODUCTION_SCRIPT_SLOT, UndefinedValue()); + introductionScript.setPrivateGCThing(options.introductionScript()); } + source->setReservedSlot(INTRODUCTION_SCRIPT_SLOT, introductionScript); return true; } diff --git a/js/src/vm/JSScript.h b/js/src/vm/JSScript.h index 7b303a6b6c49..8a82667a1f3d 100644 --- a/js/src/vm/JSScript.h +++ b/js/src/vm/JSScript.h @@ -742,11 +742,10 @@ class ScriptSourceObject : public NativeObject return getReservedSlot(ELEMENT_PROPERTY_SLOT); } JSScript* introductionScript() const { - if (getReservedSlot(INTRODUCTION_SCRIPT_SLOT).isUndefined()) + Value value = getReservedSlot(INTRODUCTION_SCRIPT_SLOT); + if (value.isUndefined()) return nullptr; - void* untyped = getReservedSlot(INTRODUCTION_SCRIPT_SLOT).toPrivate(); - MOZ_ASSERT(untyped); - return static_cast(untyped); + return value.toGCThing()->as(); } private: diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 3236e30f7a48..bcb633fdfb83 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -2561,8 +2561,6 @@ static const JSFunctionSpec intrinsic_functions[] = { JS_FN("ThrowArgTypeNotObject", intrinsic_ThrowArgTypeNotObject, 2, 0), // See builtin/RegExp.h for descriptions of the regexp_* functions. - JS_FN("regexp_exec_no_statics", regexp_exec_no_statics, 2,0), - JS_FN("regexp_test_no_statics", regexp_test_no_statics, 2,0), JS_FN("regexp_construct_raw_flags", regexp_construct_raw_flags, 2,0), JS_FN("IsModule", intrinsic_IsInstanceOfBuiltin, 1, 0), diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp index 1a5b3b3eb5d6..8e0419c21a3d 100644 --- a/js/src/vm/UnboxedObject.cpp +++ b/js/src/vm/UnboxedObject.cpp @@ -201,7 +201,7 @@ UnboxedLayout::makeConstructorCode(JSContext* cx, HandleObjectGroup group) if (!types->hasType(TypeSet::AnyObjectType())) { Register scratch = (payloadReg == scratch1) ? scratch2 : scratch1; - masm.guardObjectType(payloadReg, types, scratch, &failureStoreObject); + masm.guardObjectType(payloadReg, types, scratch, payloadReg, &failureStoreObject); } masm.storeUnboxedProperty(targetAddress, JSVAL_TYPE_OBJECT, diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp index 7cd106e90588..d13e0953480f 100644 --- a/js/src/wasm/AsmJS.cpp +++ b/js/src/wasm/AsmJS.cpp @@ -42,6 +42,7 @@ #include "wasm/WasmCompile.h" #include "wasm/WasmGenerator.h" #include "wasm/WasmInstance.h" +#include "wasm/WasmIonCompile.h" #include "wasm/WasmJS.h" #include "wasm/WasmSerialize.h" #include "wasm/WasmValidate.h" @@ -8726,7 +8727,8 @@ TypeFailureWarning(AsmJSParser& parser, const char* str) static bool EstablishPreconditions(JSContext* cx, AsmJSParser& parser) { - if (!HasCompilerSupport(cx)) + // asm.js requires Ion. + if (!HasCompilerSupport(cx) || !IonCanCompile()) return TypeFailureWarning(parser, "Disabled by lack of compiler support"); switch (parser.options().asmJSOption) { @@ -8908,7 +8910,7 @@ js::IsAsmJSCompilationAvailable(JSContext* cx, unsigned argc, Value* vp) CallArgs args = CallArgsFromVp(argc, vp); // See EstablishPreconditions. - bool available = HasCompilerSupport(cx) && cx->options().asmJS(); + bool available = HasCompilerSupport(cx) && IonCanCompile() && cx->options().asmJS(); args.rval().set(BooleanValue(available)); return true; diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp index b3bc9841b455..ddcdd45b8012 100644 --- a/js/src/wasm/WasmBaselineCompile.cpp +++ b/js/src/wasm/WasmBaselineCompile.cpp @@ -1191,7 +1191,7 @@ class BaseStackFrame static const size_t StackSizeOfPtr = sizeof(intptr_t); static const size_t StackSizeOfInt64 = sizeof(int64_t); -#ifdef JS_CODEGEN_ARM +#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) static const size_t StackSizeOfFloat = sizeof(float); #else static const size_t StackSizeOfFloat = sizeof(double); @@ -3750,12 +3750,13 @@ class BaseCompiler final : public BaseCompilerInterface if (!ool) return false; bool isSaturating = flags & TRUNC_SATURATING; - if (flags & TRUNC_UNSIGNED) + if (flags & TRUNC_UNSIGNED) { masm.wasmTruncateFloat32ToUInt64(src, dest, isSaturating, ool->entry(), ool->rejoin(), temp); - else + } else { masm.wasmTruncateFloat32ToInt64(src, dest, isSaturating, ool->entry(), ool->rejoin(), temp); + } return true; } @@ -3768,12 +3769,13 @@ class BaseCompiler final : public BaseCompilerInterface if (!ool) return false; bool isSaturating = flags & TRUNC_SATURATING; - if (flags & TRUNC_UNSIGNED) + if (flags & TRUNC_UNSIGNED) { masm.wasmTruncateDoubleToUInt64(src, dest, isSaturating, ool->entry(), ool->rejoin(), temp); - else + } else { masm.wasmTruncateDoubleToInt64(src, dest, isSaturating, ool->entry(), ool->rejoin(), temp); + } return true; } #endif // RABALDR_FLOAT_TO_I64_CALLOUT diff --git a/js/src/wasm/WasmCompile.cpp b/js/src/wasm/WasmCompile.cpp index e24b0b292c5c..396af8b68a3c 100644 --- a/js/src/wasm/WasmCompile.cpp +++ b/js/src/wasm/WasmCompile.cpp @@ -25,6 +25,7 @@ #include "wasm/WasmBaselineCompile.h" #include "wasm/WasmBinaryIterator.h" #include "wasm/WasmGenerator.h" +#include "wasm/WasmIonCompile.h" #include "wasm/WasmSignalHandlers.h" #include "wasm/WasmValidate.h" @@ -392,9 +393,13 @@ InitialCompileFlags(const CompileArgs& args, Decoder& d, CompileMode* mode, Tier if (StartsCodeSection(d.begin(), d.end(), &range)) codeSectionSize = range.size; + // Attempt to default to ion if baseline is disabled. bool baselineEnabled = BaselineCanCompile() && (args.baselineEnabled || args.testTiering); bool debugEnabled = BaselineCanCompile() && args.debugEnabled; - bool ionEnabled = args.ionEnabled || !baselineEnabled || args.testTiering; + bool ionEnabled = IonCanCompile() && (args.ionEnabled || !baselineEnabled || args.testTiering); + + // HasCompilerSupport() should prevent failure here + MOZ_RELEASE_ASSERT(baselineEnabled || ionEnabled); if (baselineEnabled && ionEnabled && !debugEnabled && (TieringBeneficial(codeSectionSize) || args.testTiering)) diff --git a/js/src/wasm/WasmIonCompile.cpp b/js/src/wasm/WasmIonCompile.cpp index 428d91699c5c..baf00251f0cf 100644 --- a/js/src/wasm/WasmIonCompile.cpp +++ b/js/src/wasm/WasmIonCompile.cpp @@ -4442,3 +4442,13 @@ wasm::IonCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo, return code->swap(masm); } + +bool +js::wasm::IonCanCompile() +{ +#if !defined(JS_CODEGEN_NONE) && !defined(JS_CODEGEN_ARM64) + return true; +#else + return false; +#endif +} diff --git a/js/src/wasm/WasmIonCompile.h b/js/src/wasm/WasmIonCompile.h index 81d53a0fd263..c164ca73926d 100644 --- a/js/src/wasm/WasmIonCompile.h +++ b/js/src/wasm/WasmIonCompile.h @@ -26,6 +26,10 @@ namespace js { namespace wasm { +// Return whether IonCompileFunction() can generate code on the current device. +bool +IonCanCompile(); + // Generates very fast code at the expense of compilation time. MOZ_MUST_USE bool IonCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo, diff --git a/js/src/wasm/WasmJS.cpp b/js/src/wasm/WasmJS.cpp index 9bd3be0d9477..19d2f8092f6c 100644 --- a/js/src/wasm/WasmJS.cpp +++ b/js/src/wasm/WasmJS.cpp @@ -31,8 +31,10 @@ #include "vm/Interpreter.h" #include "vm/String.h" #include "vm/StringBuffer.h" +#include "wasm/WasmBaselineCompile.h" #include "wasm/WasmCompile.h" #include "wasm/WasmInstance.h" +#include "wasm/WasmIonCompile.h" #include "wasm/WasmModule.h" #include "wasm/WasmSignalHandlers.h" #include "wasm/WasmStubs.h" @@ -85,7 +87,8 @@ wasm::HasCompilerSupport(JSContext* cx) #if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64) return false; #else - return true; + return (cx->options().wasmBaseline() && BaselineCanCompile()) || + (cx->options().wasmIon() && IonCanCompile()); #endif } diff --git a/js/src/wasm/WasmStubs.cpp b/js/src/wasm/WasmStubs.cpp index 940c0aca8620..19124a3f06fa 100644 --- a/js/src/wasm/WasmStubs.cpp +++ b/js/src/wasm/WasmStubs.cpp @@ -473,7 +473,8 @@ GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, const FuncExport& Label next; switch (fe.sig().args()[i]) { case ValType::I32: { - Register tag = masm.splitTagForTest(scratchV); + ScratchTagScope tag(masm, scratchV); + masm.splitTagForTest(scratchV, tag); // For int32 inputs, just skip. masm.branchTestInt32(Assembler::Equal, tag, &next); @@ -481,9 +482,12 @@ GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, const FuncExport& // For double inputs, unbox, truncate and store back. Label storeBack, notDouble; masm.branchTestDouble(Assembler::NotEqual, tag, ¬Double); - masm.unboxDouble(scratchV, scratchF); - masm.branchTruncateDoubleMaybeModUint32(scratchF, scratchG, &oolCall); - masm.jump(&storeBack); + { + ScratchTagScopeRelease _(&tag); + masm.unboxDouble(scratchV, scratchF); + masm.branchTruncateDoubleMaybeModUint32(scratchF, scratchG, &oolCall); + masm.jump(&storeBack); + } masm.bind(¬Double); // For null or undefined, store 0. @@ -491,7 +495,10 @@ GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, const FuncExport& masm.branchTestUndefined(Assembler::Equal, tag, &nullOrUndefined); masm.branchTestNull(Assembler::NotEqual, tag, ¬NullOrUndefined); masm.bind(&nullOrUndefined); - masm.storeValue(Int32Value(0), jitArgAddr); + { + ScratchTagScopeRelease _(&tag); + masm.storeValue(Int32Value(0), jitArgAddr); + } masm.jump(&next); masm.bind(¬NullOrUndefined); @@ -502,7 +509,10 @@ GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, const FuncExport& // fallthrough: masm.bind(&storeBack); - masm.storeValue(JSVAL_TYPE_INT32, scratchG, jitArgAddr); + { + ScratchTagScopeRelease _(&tag); + masm.storeValue(JSVAL_TYPE_INT32, scratchG, jitArgAddr); + } break; } case ValType::F32: @@ -510,29 +520,39 @@ GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, const FuncExport& // Note we can reuse the same code for f32/f64 here, since for the // case of f32, the conversion of f64 to f32 will happen in the // second loop. - Register tag = masm.splitTagForTest(scratchV); + ScratchTagScope tag(masm, scratchV); + masm.splitTagForTest(scratchV, tag); // For double inputs, just skip. masm.branchTestDouble(Assembler::Equal, tag, &next); // For int32 inputs, convert and rebox. Label storeBack, notInt32; - masm.branchTestInt32(Assembler::NotEqual, scratchV, ¬Int32); - masm.int32ValueToDouble(scratchV, scratchF); - masm.jump(&storeBack); + { + ScratchTagScopeRelease _(&tag); + masm.branchTestInt32(Assembler::NotEqual, scratchV, ¬Int32); + masm.int32ValueToDouble(scratchV, scratchF); + masm.jump(&storeBack); + } masm.bind(¬Int32); // For undefined (missing argument), store NaN. Label notUndefined; masm.branchTestUndefined(Assembler::NotEqual, tag, ¬Undefined); - masm.storeValue(DoubleValue(JS::GenericNaN()), jitArgAddr); - masm.jump(&next); + { + ScratchTagScopeRelease _(&tag); + masm.storeValue(DoubleValue(JS::GenericNaN()), jitArgAddr); + masm.jump(&next); + } masm.bind(¬Undefined); // +null is 0. Label notNull; masm.branchTestNull(Assembler::NotEqual, tag, ¬Null); - masm.storeValue(DoubleValue(0.), jitArgAddr); + { + ScratchTagScopeRelease _(&tag); + masm.storeValue(DoubleValue(0.), jitArgAddr); + } masm.jump(&next); masm.bind(¬Null); diff --git a/js/xpconnect/src/XPCJSContext.cpp b/js/xpconnect/src/XPCJSContext.cpp index 0fe8f6c018a3..864bf6c6a4d7 100644 --- a/js/xpconnect/src/XPCJSContext.cpp +++ b/js/xpconnect/src/XPCJSContext.cpp @@ -808,6 +808,8 @@ ReloadPrefsCallback(const char* pref, void* data) bool streams = Preferences::GetBool(JS_OPTIONS_DOT_STR "streams"); bool spectreIndexMasking = Preferences::GetBool(JS_OPTIONS_DOT_STR "spectre.index_masking"); + bool spectreObjectMitigationsBarriers = + Preferences::GetBool(JS_OPTIONS_DOT_STR "spectre.object_mitigations.barriers"); bool spectreStringMitigations = Preferences::GetBool(JS_OPTIONS_DOT_STR "spectre.string_mitigations"); bool spectreValueMasking = Preferences::GetBool(JS_OPTIONS_DOT_STR "spectre.value_masking"); @@ -873,6 +875,8 @@ ReloadPrefsCallback(const char* pref, void* data) #endif JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_SPECTRE_INDEX_MASKING, spectreIndexMasking); + JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_SPECTRE_OBJECT_MITIGATIONS_BARRIERS, + spectreObjectMitigationsBarriers); JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_SPECTRE_STRING_MITIGATIONS, spectreStringMitigations); JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_SPECTRE_VALUE_MASKING, spectreValueMasking); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 293b95c51a03..21edf6e72e78 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1561,6 +1561,7 @@ pref("javascript.options.dump_stack_on_debuggee_would_run", false); // Spectre security vulnerability mitigations. pref("javascript.options.spectre.index_masking", true); +pref("javascript.options.spectre.object_mitigations.barriers", false); pref("javascript.options.spectre.string_mitigations", true); pref("javascript.options.spectre.value_masking", true); diff --git a/security/manager/ssl/StaticHPKPins.h b/security/manager/ssl/StaticHPKPins.h index 5bd58f099224..7b26adc04adb 100644 --- a/security/manager/ssl/StaticHPKPins.h +++ b/security/manager/ssl/StaticHPKPins.h @@ -1162,4 +1162,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = { static const int32_t kUnknownId = -1; -static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1528055426806000); +static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1528144877030000); diff --git a/security/manager/ssl/nsSTSPreloadList.errors b/security/manager/ssl/nsSTSPreloadList.errors index c89ee9ef5d95..26cf13356f57 100644 --- a/security/manager/ssl/nsSTSPreloadList.errors +++ b/security/manager/ssl/nsSTSPreloadList.errors @@ -8,6 +8,7 @@ 0vi.org: could not connect to host 0x52.org: could not connect to host 0xdc.io: could not connect to host +1001.best: could not connect to host 100onrainkajino.com: could not connect to host 10gb.io: could not connect to host 135vv.com: could not connect to host @@ -18,7 +19,6 @@ 1gsoft.com: could not connect to host 1nian.vip: could not connect to host 1q365a.com: could not connect to host -247healthshop.com: could not connect to host 24ip.fr: could not connect to host 2b3b.com: could not connect to host 2bitout.com: could not connect to host @@ -41,6 +41,7 @@ 4mm.org: could not connect to host 4web-hosting.com: could not connect to host 5000yz.com: could not connect to host +517vpn.cn: could not connect to host 52kb1.com: could not connect to host 52neptune.com: could not connect to host 5ece.de: could not connect to host @@ -59,10 +60,8 @@ 91-freedom.com: could not connect to host 99buffets.com: could not connect to host 9ss6.com: could not connect to host -a-little-linux-box.at: could not connect to host a-starbouncycastles.co.uk: could not connect to host aaron.xin: could not connect to host -abandonedmines.gov: could not connect to host abi-fvs.de: could not connect to host abloop.com: could not connect to host abolition.co: could not connect to host @@ -87,6 +86,7 @@ adult.properties: could not connect to host advaithnikhi.ml: could not connect to host advaithnikhi.tk: could not connect to host advanced-online.eu: could not connect to host +aestore.by: could not connect to host aevpn.org: could not connect to host affiliateroyale.com: could not connect to host affily.io: could not connect to host @@ -102,9 +102,9 @@ aikenorganics.com: could not connect to host aim-consultants.com: could not connect to host airclass.com: could not connect to host ajetaci.cz: could not connect to host -akdusekbudil.cz: could not connect to host akiba-server.info: could not connect to host akita-stream.com: could not connect to host +akoch.net: could not connect to host akoww.de: could not connect to host akul.co.in: could not connect to host al-f.net: could not connect to host @@ -122,12 +122,11 @@ alilialili.ga: could not connect to host alldm.ru: could not connect to host alloutatl.com: could not connect to host allscammers.exposed: could not connect to host -allsync.com: could not connect to host -allsync.nl: could not connect to host alltheducks.com: could not connect to host alocato.com: could not connect to host alohapartyevents.co.uk: could not connect to host alphabrock.cn: could not connect to host +alroniks.com: could not connect to host altahrim.net: could not connect to host alza.at: could not connect to host alza.co.uk: could not connect to host @@ -144,6 +143,7 @@ anadoluefessk.org: could not connect to host analyzemyfriends.com: could not connect to host anastasia-shamara.ru: could not connect to host andiplusben.com: could not connect to host +andisadhdspot.com: could not connect to host andreamcnett.com: could not connect to host andreas-kluge.eu: could not connect to host andreaskluge.eu: could not connect to host @@ -169,6 +169,7 @@ apple.ax: could not connect to host apponline.com: could not connect to host apps4all.sytes.net: could not connect to host appzoojoo.be: could not connect to host +aquaundine.net: could not connect to host aranycsillag.net: could not connect to host area3.org: could not connect to host arent.kz: could not connect to host @@ -177,7 +178,6 @@ argh.io: could not connect to host arknodejs.com: could not connect to host arksan.com.tr: could not connect to host armenians.online: could not connect to host -arne-petersen.net: could not connect to host arresttracker.com: could not connect to host arsenal.ru: could not connect to host artea.ga: could not connect to host @@ -190,6 +190,10 @@ as200753.net: could not connect to host ashleyadum.com: could not connect to host askmagicconch.com: could not connect to host asphaltfruehling.de: could not connect to host +asr.cloud: could not connect to host +asr.li: could not connect to host +asr.rocks: could not connect to host +asr.solar: could not connect to host asral7.com: could not connect to host assdecoeur.org: could not connect to host assindia.nl: could not connect to host @@ -221,10 +225,10 @@ awan.tech: could not connect to host awei.pub: could not connect to host awf0.xyz: could not connect to host axel-fischer.science: could not connect to host -az-vinyl-boden.de: could not connect to host b9winner.com: could not connect to host babelfisch.eu: could not connect to host bacimg.com: could not connect to host +badbee.cc: could not connect to host bailbondsaffordable.com: could not connect to host balonmano.co: could not connect to host bandally.net: could not connect to host @@ -233,7 +237,6 @@ bannisbierblog.de: could not connect to host bardiharborow.com: could not connect to host bardiharborow.tk: could not connect to host barracuda.blog: could not connect to host -barreaudenice.com: could not connect to host bashc.at: could not connect to host basnieuwenhuizen.nl: could not connect to host batfoundry.com: could not connect to host @@ -275,7 +278,6 @@ bfi.wien: could not connect to host bfrailwayclub.cf: could not connect to host bianinapiccanovias.com: could not connect to host bigerbio.com: could not connect to host -billaud.eu.org: could not connect to host billigpoker.dk: could not connect to host billpro.com.au: could not connect to host binam.center: could not connect to host @@ -289,7 +291,6 @@ biswas.me: could not connect to host bitcoin-class.com: could not connect to host bitcoin-daijin.com: could not connect to host bitcoinjpn.com: could not connect to host -bitfasching.de: could not connect to host bitmain.com.ua: could not connect to host bitmaincare.com.ua: could not connect to host bitmaincare.ru: could not connect to host @@ -304,6 +305,7 @@ blantik.net: could not connect to host blazeit.io: could not connect to host blessedearth.com.au: could not connect to host blindaryproduction.tk: could not connect to host +blink-security.com: could not connect to host blinkenlight.co.uk: could not connect to host blinkenlight.com.au: could not connect to host blog.gparent.org: could not connect to host @@ -320,7 +322,6 @@ bombsquad.studio: could not connect to host bonesserver.com: could not connect to host bonobo.cz: could not connect to host bookreport.ga: could not connect to host -booter.es: could not connect to host borchers-media.de: could not connect to host borisbesemer.com: could not connect to host bosabosa.org: could not connect to host @@ -334,6 +335,7 @@ brandontaylor-black.com: could not connect to host bratteng.me: could not connect to host bratteng.xyz: could not connect to host breathingblanket.com: could not connect to host +breeyn.com: could not connect to host brettabel.com: could not connect to host brianmwaters.net: could not connect to host brideandgroomdirect.ie: could not connect to host @@ -346,6 +348,7 @@ bsalyzer.com: could not connect to host bsktweetup.info: could not connect to host bslim-e-boutique.com: could not connect to host bsuess.de: could not connect to host +btcycle.org: could not connect to host buck.com: could not connect to host buenotour.ru: could not connect to host bugsmashed.com: could not connect to host @@ -390,7 +393,6 @@ carlovanwyk.com: could not connect to host carlsbouncycastlesandhottubs.co.uk: could not connect to host carrando.de: could not connect to host casinoreal.com: could not connect to host -catchers.cc: could not connect to host catcontent.cloud: could not connect to host catsmagic.pp.ua: could not connect to host caughtredhanded.co.nz: could not connect to host @@ -398,7 +400,6 @@ ccayearbook.com: could not connect to host ccl-sti.ch: could not connect to host ccprwebsite.org: could not connect to host cctld.com: could not connect to host -cdlcenter.com: could not connect to host cdmon.tech: could not connect to host cdnk39.com: could not connect to host cee.io: could not connect to host @@ -414,6 +415,7 @@ championnat-romand-cuisiniers-amateurs.ch: could not connect to host channellife.asia: could not connect to host chaouby.com: could not connect to host charmyadesara.com: could not connect to host +chazay.net: could not connect to host cheesefusion.com: could not connect to host chez-janine.de: could not connect to host childrendeservebetter.org: could not connect to host @@ -422,6 +424,7 @@ chinternet.xyz: could not connect to host chiropracticwpb.com: could not connect to host chloe.re: could not connect to host chocolat-suisse.ch: could not connect to host +chrisebert.net: could not connect to host christianhoffmann.info: could not connect to host christiansayswords.com: could not connect to host chromaryu.net: could not connect to host @@ -432,7 +435,6 @@ cisy.me: could not connect to host citywalkr.com: could not connect to host ciuciucadou.ro: could not connect to host cjey.me: could not connect to host -cjr.host: could not connect to host cjtkfan.club: could not connect to host ckcameron.net: could not connect to host clashersrepublic.com: could not connect to host @@ -457,7 +459,6 @@ cnwage.com: could not connect to host cnwarn.com: could not connect to host co-yutaka.com: could not connect to host cobaltlp.com: could not connect to host -coccolebenessere.it: could not connect to host codenlife.xyz: could not connect to host codercross.com: could not connect to host coderhangout.com: could not connect to host @@ -479,24 +480,23 @@ conception.sk: could not connect to host connectum.eu: could not connect to host conniesacademy.com: could not connect to host conrad.am: could not connect to host -consejosdenutricion.com: could not connect to host constructive.men: could not connect to host conve.eu: could not connect to host coreapm.com: could not connect to host coreapm.org: could not connect to host corecdn.org: could not connect to host corinnanese.de: could not connect to host -corrbee.com: could not connect to host correct.horse: could not connect to host cosmeticosdelivery.com.br: could not connect to host cosmiatria.pe: could not connect to host cosplayer.com: could not connect to host +cotta.dk: could not connect to host coumoul.fr: could not connect to host cpaneltips.com: could not connect to host crackslut.eu: could not connect to host crashsec.com: could not connect to host +creato.top: could not connect to host credential.eu: could not connect to host -crestasantos.com: could not connect to host cristianhares.com: could not connect to host criticalaim.com: could not connect to host crow.tw: could not connect to host @@ -529,7 +529,6 @@ daltonedwards.me: could not connect to host dam74.com.ar: could not connect to host damedrogy.cz: could not connect to host daniel-stahl.net: could not connect to host -dannyrohde.de: could not connect to host darkdestiny.ch: could not connect to host darlo.co.uk: could not connect to host darrienworth.com: could not connect to host @@ -554,7 +553,6 @@ ddmeportal.com: could not connect to host de-servers.de: could not connect to host decoyrouting.com: could not connect to host dedietrich-asia.com: could not connect to host -deep.club: could not connect to host deepcreampie.com: could not connect to host deeps.cat: could not connect to host deloittequant.com: could not connect to host @@ -571,9 +569,7 @@ developersclub.website: could not connect to host devh.net: could not connect to host deviltraxxx.de: could not connect to host devops.moe: could not connect to host -devpsy.info: could not connect to host dezintranet.com: could not connect to host -dfixit.com: could not connect to host dhl-smart.ch: could not connect to host dhub.xyz: could not connect to host dhxxls.com: could not connect to host @@ -587,7 +583,7 @@ digihyp.ch: could not connect to host digioccumss.ddns.net: could not connect to host digitalhurricane.io: could not connect to host digitalrxcloud.com: could not connect to host -digiworks.se: could not connect to host +digitalwasteland.net: could not connect to host diguass.us: could not connect to host dijks.com: could not connect to host dingcc.com: could not connect to host @@ -612,6 +608,7 @@ dmdre.com: could not connect to host dna.li: could not connect to host dndtools.net: could not connect to host dnfc.rocks: could not connect to host +dnshallinta.fi: could not connect to host dobrisan.ro: could not connect to host doctafit.com: could not connect to host docubox.info: could not connect to host @@ -632,12 +629,12 @@ doyoulyft.com: could not connect to host doze-cloud.tech: could not connect to host dragonwork.me: could not connect to host dranderle.com: could not connect to host +dranek.com: could not connect to host dreaming.solutions: could not connect to host dreizwosechs.de: could not connect to host driving-lessons.co.uk: could not connect to host drivinghorror.com: could not connect to host drixn.cn: could not connect to host -drixn.com: could not connect to host drixn.info: could not connect to host drixn.net: could not connect to host drizz.com.br: could not connect to host @@ -650,7 +647,6 @@ drunkscifi.com: could not connect to host dubrovskiy.net: could not connect to host dubrovskiy.pro: could not connect to host duch.cloud: could not connect to host -duckyubuntu.tk: could not connect to host duelsow.eu: could not connect to host dujsq.com: could not connect to host dujsq.top: could not connect to host @@ -660,7 +656,6 @@ durangoenergyllc.com: could not connect to host dwnld.me: could not connect to host dynts.pro: could not connect to host dzyabchenko.com: could not connect to host -dzytdl.com: could not connect to host e-mak.eu: could not connect to host e-wishlist.net: could not connect to host eagletechz.com.br: could not connect to host @@ -688,6 +683,7 @@ electricalcontrolpanels.co.uk: could not connect to host elektronring.com: could not connect to host elenorsmadness.org: could not connect to host elevateandprosper.com: could not connect to host +elia.cloud: could not connect to host elitesensual.com.br: could not connect to host elonbase.com: could not connect to host elsword.moe: could not connect to host @@ -713,6 +709,7 @@ es888999.com: could not connect to host esoterik.link: could not connect to host esseriumani.com: could not connect to host ethiobaba.com: could not connect to host +etincelle.ml: could not connect to host euexia.fr: could not connect to host eung.ga: could not connect to host eurostrategy.vn.ua: could not connect to host @@ -724,6 +721,7 @@ eworksmedia.com: could not connect to host exceptionalservices.us: could not connect to host exo.do: could not connect to host exteriorservices.io: could not connect to host +extreme-players.com: could not connect to host eytosh.net: could not connect to host f1bigpicture.com: could not connect to host f8842.com: could not connect to host @@ -782,10 +780,10 @@ fixmyglitch.com: could not connect to host fixthetimeline.com: could not connect to host fixthetimeline.org: could not connect to host flamingcow.tv: could not connect to host +flexinvesting.fi: could not connect to host floth.at: could not connect to host flow.su: could not connect to host flugplatz-edvc.de: could not connect to host -flygpost.com: could not connect to host flyingdoggy.net: could not connect to host focalforest.com: could not connect to host fojing.com: could not connect to host @@ -808,6 +806,7 @@ fredliang.cn: could not connect to host fredtec.ru: could not connect to host free8.xyz: could not connect to host freeassangenow.org: could not connect to host +freeboson.org: could not connect to host freejidi.com: could not connect to host freelansir.com: could not connect to host freeshkre.li: could not connect to host @@ -816,7 +815,7 @@ freshcode.nl: could not connect to host freshmaza.com: could not connect to host frickenate.com: could not connect to host friedhelm-wolf.de: could not connect to host -frodriguez.xyz: could not connect to host +friller.com.au: could not connect to host frolov.net: could not connect to host fromlemaytoz.com: could not connect to host frosty-gaming.xyz: could not connect to host @@ -830,7 +829,6 @@ fugle.de: could not connect to host fuitedeau.ch: could not connect to host fukuko.biz: could not connect to host fukuko.xyz: could not connect to host -fukuoka-cityliner.jp: could not connect to host fun9.cc: could not connect to host fun99.cc: could not connect to host funksteckdosen24.de: could not connect to host @@ -854,7 +852,6 @@ gameswitchers.uk: could not connect to host gametium.com: could not connect to host gametium.es: could not connect to host gamhealth.net: could not connect to host -gar-nich.net: could not connect to host garage-door.pro: could not connect to host gasbarkenora.com: could not connect to host gasnews.net: could not connect to host @@ -924,6 +921,8 @@ gratisonlinesex.com: could not connect to host greenitpark.net: could not connect to host greggsfoundation.org.uk: could not connect to host gregmartyn.com: could not connect to host +gregmilton.com: could not connect to host +gregmilton.org: could not connect to host greuel.online: could not connect to host greyhash.se: could not connect to host gritte.net: could not connect to host @@ -933,6 +932,7 @@ gruelang.org: could not connect to host grusenmeyer.be: could not connect to host gugaltika-ipb.org: could not connect to host guinea-pig.co: could not connect to host +gumannp.de: could not connect to host gunhunter.com: could not connect to host gus.moe: could not connect to host gutuia.blue: could not connect to host @@ -941,9 +941,7 @@ gxgx.org: could not connect to host gzpblog.com: could not connect to host h3artbl33d.nl: could not connect to host habeo.si: could not connect to host -hack.club: could not connect to host hackbubble.me: could not connect to host -hacker.club: could not connect to host hackingsafe.com: could not connect to host hackmeplz.com: could not connect to host haktec.de: could not connect to host @@ -977,16 +975,15 @@ heavenlysmokenc.com: could not connect to host heisenberg.co: could not connect to host hejsupport.se: could not connect to host hellofilters.com: could not connect to host -hellomouse.cf: could not connect to host hellomouse.tk: could not connect to host helpantiaging.com: could not connect to host helpekwendenihospital.com: could not connect to host helsingfors.guide: could not connect to host -hendyisaac.com: could not connect to host henhenlu.com: could not connect to host henriknoerr.com: could not connect to host hentai.design: could not connect to host hentaimaster.net: could not connect to host +heptner24.de: could not connect to host here.ml: could not connect to host heribe-maruo.com: could not connect to host hermes-servizi.it: could not connect to host @@ -1009,7 +1006,6 @@ hondenoppasfraneker.nl: could not connect to host honeytracks.com: could not connect to host hoodoo.io: could not connect to host hoodoo.tech: could not connect to host -hoorr.com: could not connect to host hopglass.eu: could not connect to host hopglass.net: could not connect to host horvathd.eu: could not connect to host @@ -1036,6 +1032,7 @@ hypotheques24.ch: could not connect to host i-stats.net: could not connect to host i95.me: could not connect to host iadttaveras.com: could not connect to host +iamwoodbeard.com: could not connect to host ibron.co: could not connect to host ibsafrica.co.za: could not connect to host ibsglobal.co.za: could not connect to host @@ -1071,6 +1068,7 @@ imperdintechnologies.com: could not connect to host imperiumnova.info: could not connect to host imrejonk.nl: could not connect to host increasetestosteronelevels.org: could not connect to host +inderagamono.net: could not connect to host industreiler.com: could not connect to host industreiler.com.br: could not connect to host inexpensivecomputers.net: could not connect to host @@ -1092,7 +1090,6 @@ intracom.com: could not connect to host invenio.software: could not connect to host investingdiary.cn: could not connect to host investorloanshub.com: could not connect to host -investpay.ru: could not connect to host iodu.re: could not connect to host ip.or.at: could not connect to host iphonechina.net: could not connect to host @@ -1103,7 +1100,6 @@ irinkeby.nu: could not connect to host isamiok.com: could not connect to host isisfighters.info: could not connect to host iskkk.com: could not connect to host -isopres.de: could not connect to host isscouncil.com: could not connect to host isthefieldcontrolsystemdown.com: could not connect to host istherrienstillcoach.com: could not connect to host @@ -1127,6 +1123,7 @@ jaksel.id: could not connect to host jaksi.io: could not connect to host jamesachambers.com: could not connect to host jamesheald.com: could not connect to host +jan-bucher.ch: could not connect to host janheidler.dynv6.net: could not connect to host janssen.fm: could not connect to host japan4you.org: could not connect to host @@ -1170,8 +1167,8 @@ just-pools.co.za: could not connect to host justinharrison.ca: could not connect to host justzz.xyz: could not connect to host juventusmania1897.com: could not connect to host -k258059.net: could not connect to host k33k00.com: could not connect to host +kabus.org: could not connect to host kaika-facilitymanagement.de: could not connect to host kainz.be: could not connect to host kaiusaltd.com: could not connect to host @@ -1208,17 +1205,19 @@ kigmbh.com: could not connect to host kikuzuki.org: could not connect to host kinepolis-studio.ga: could not connect to host kingclass.cn: could not connect to host -kingdomcrc.org: could not connect to host kirill.ws: could not connect to host kj1396.net: could not connect to host kjoglum.me: could not connect to host kleinblogje.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 116" data: no] +klimchuk.by: could not connect to host +klimchuk.com: could not connect to host klingeletest.de: could not connect to host knep.me: could not connect to host kngk-azs.ru: could not connect to host kngkng.com: could not connect to host knightsweep.com: could not connect to host knownsec.cf: could not connect to host +koenen-bau.de: could not connect to host koez-mangal.ch: could not connect to host koezmangal.ch: could not connect to host koketteriet.se: could not connect to host @@ -1263,7 +1262,6 @@ lathamlabs.net: could not connect to host lathamlabs.org: could not connect to host lazulu.com: could not connect to host lbarrios.es: could not connect to host -lbls.me: could not connect to host lbrls.tk: could not connect to host lcti.biz: could not connect to host ldc.com.br: could not connect to host @@ -1275,11 +1273,11 @@ lebal.se: could not connect to host leebiblestudycentre.net: could not connect to host leebiblestudycentre.org: could not connect to host leefindlow.com: could not connect to host +leelou.wedding: could not connect to host legal.farm: could not connect to host legaltip.eu: could not connect to host leolana.com: could not connect to host leonardcamacho.me: could not connect to host -leonhooijer.nl: could not connect to host lerlivros.online: could not connect to host lescomptoirsdepierrot.com: could not connect to host lesdouceursdeliyana.com: could not connect to host @@ -1293,7 +1291,9 @@ lhsj68.com: could not connect to host lhsj78.com: could not connect to host liaozheqi.cn: could not connect to host libertas-tech.com: could not connect to host +librebox.de: could not connect to host libscode.com: could not connect to host +liceserv.com: could not connect to host likenosis.com: could not connect to host lincdavis.com: could not connect to host lingting.vip: could not connect to host @@ -1331,7 +1331,6 @@ lovingearth.co: could not connect to host lowt.us: could not connect to host loyaltech.ch: could not connect to host lstma.com: could not connect to host -lswim.com: could not connect to host lszj.com: could not connect to host ltransferts.com: could not connect to host luav.org: could not connect to host @@ -1363,13 +1362,14 @@ makeit-so.de: could not connect to host malamutedoalasca.com.br: could not connect to host malesbdsm.com: could not connect to host malgraph.net: could not connect to host -maly.io: could not connect to host mamastore.eu: could not connect to host marcelmarnitz.com: could not connect to host marche-nordic-jorat.ch: could not connect to host mardelcupon.com: could not connect to host mare92.cz: could not connect to host +mariposah.ch: could not connect to host mariusschulte.de: could not connect to host +mark-armstrong-gaming.com: could not connect to host marketingdesignu.cz: could not connect to host markllego.com: could not connect to host marko-fenster24.de: could not connect to host @@ -1381,14 +1381,12 @@ mashek.net: could not connect to host mastodon.expert: could not connect to host mastodon.my: could not connect to host matarrosabierzo.com: could not connect to host -matcha-iga.jp: could not connect to host mathijskingma.nl: could not connect to host matrix.ac: could not connect to host matthewtester.com: could not connect to host matthey.nl: could not connect to host mattia98.org: could not connect to host mattli.us: could not connect to host -mattwb65.com: could not connect to host matze.co: could not connect to host max-moeglich.de: could not connect to host maybeul.com: could not connect to host @@ -1396,7 +1394,6 @@ maynardnetworks.com: could not connect to host mazternet.ru: could not connect to host mb-is.info: could not connect to host mbdrogenbos-usedcars.be: could not connect to host -mble.mg: could not connect to host mbsec.net: could not connect to host mbwemmel-usedcars.be: could not connect to host mcdanieldevelopmentservices.com: could not connect to host @@ -1444,7 +1441,6 @@ mingy.ddns.net: could not connect to host mingyueli.com: could not connect to host minimaliston.com: could not connect to host minitruckin.net: could not connect to host -misconfigured.io: could not connect to host mkcert.org: could not connect to host mkfs.fr: could not connect to host mkhsoft.eu: could not connect to host @@ -1460,6 +1456,7 @@ mobmp4.co: could not connect to host mobmp4.com: could not connect to host mobmp4.info: could not connect to host mochoko.com: could not connect to host +modcasts.video: could not connect to host modded-minecraft-server-list.com: could not connect to host modelcase.co.jp: could not connect to host modernibytovytextil.cz: could not connect to host @@ -1467,7 +1464,6 @@ moderntld.net: could not connect to host moe-max.jp: could not connect to host moefi.xyz: could not connect to host moeyi.xyz: could not connect to host -moin.jp: could not connect to host mongla168.net: could not connect to host mongla88.net: could not connect to host monitori.ng: could not connect to host @@ -1505,7 +1501,6 @@ multivpn.fr: could not connect to host munduch.cz: could not connect to host murraycolin.org: could not connect to host murz.tv: could not connect to host -mushman.tk: could not connect to host muslimbanter.co.za: could not connect to host mxawei.cn: could not connect to host mxlife.org: could not connect to host @@ -1524,6 +1519,7 @@ mytravelblog.de: could not connect to host mziulu.me: could not connect to host mzlog.win: could not connect to host n0099.cf: could not connect to host +n3twork.net: could not connect to host naano.org: could not connect to host nadyaolcer.fr: could not connect to host namaleaks.com: could not connect to host @@ -1537,6 +1533,7 @@ ndtblog.com: could not connect to host necesitodinero.org: could not connect to host neer.io: could not connect to host nephy.jp: could not connect to host +nerdjokes.de: could not connect to host nerfroute.com: could not connect to host nestone.ru: could not connect to host net4visions.at: could not connect to host @@ -1572,13 +1569,13 @@ nolimits.net.nz: could not connect to host nonemu.ninja: could not connect to host norad.sytes.net: could not connect to host northwoodsfish.com: could not connect to host +nos-oignons.net: could not connect to host nosbenevolesontdutalent.com: could not connect to host not-a.link: could not connect to host notabug.org: could not connect to host note7forever.com: could not connect to host notesforpebble.com: could not connect to host notevencode.com: could not connect to host -notificami.com: could not connect to host novfishing.ru: could not connect to host nowremindme.com: could not connect to host nsbfalconacademy.org: could not connect to host @@ -1589,6 +1586,7 @@ numis.tech: could not connect to host nyanpasu.tv: could not connect to host nyip.co.uk: could not connect to host nyip.edu: could not connect to host +oaksbloom.com: could not connect to host obdolbacca.ru: could not connect to host oberam.de: could not connect to host oberhof.co: could not connect to host @@ -1601,19 +1599,22 @@ oinky.ddns.net: could not connect to host okusiassociates.com: could not connect to host oldtimer-trifft-flugplatz.de: could not connect to host oliverspringer.eu: could not connect to host +ollies.cloud: could not connect to host +olliespage.com: could not connect to host +olliespage.net: could not connect to host +olliespage.uk: could not connect to host omnibot.tv: could not connect to host oneazcu.com: could not connect to host onewebdev.info: could not connect to host onsite4u.de: could not connect to host onstud.com: could not connect to host +onviga.de: could not connect to host onwie.fr: could not connect to host ooeste.com: could not connect to host open-desk.org: could not connect to host open-future.be: could not connect to host openconnect.com.au: could not connect to host opinion8td.com: could not connect to host -orangecomputers.com: could not connect to host -oranges.tokyo: could not connect to host oricejoc.com: could not connect to host oscarmashauri.com: could not connect to host oscsdp.cz: could not connect to host @@ -1655,6 +1656,7 @@ patrickbusch.net: could not connect to host patrickneuro.de: could not connect to host paulshir.com: could not connect to host paulshir.is: could not connect to host +pavelstriz.cz: could not connect to host pay.ubuntu.com: could not connect to host payload.tech: could not connect to host paymon.tj: could not connect to host @@ -1708,7 +1710,6 @@ pnsc.is: could not connect to host pogs.us: could not connect to host pointagri.com: could not connect to host polit.im: could not connect to host -ponteencima.com: could not connect to host pookl.com: could not connect to host poolinstallers.co.za: could not connect to host popkins.cf: could not connect to host @@ -1777,7 +1778,6 @@ pwdgen.net: could not connect to host pyjiaoyi.cf: could not connect to host pythia.nz: could not connect to host python-hyper.org: could not connect to host -qcmakeupacademy.com: could not connect to host qforum.org: could not connect to host qikan.net: could not connect to host qirinus.com: could not connect to host @@ -1852,6 +1852,7 @@ ronghexx.com: could not connect to host roolevoi.ru: could not connect to host rootbsd.at: could not connect to host rospa100.com: could not connect to host +roten.email: could not connect to host rotterdamjazz.info: could not connect to host royzez.com: could not connect to host rozalynne-dawn.ga: could not connect to host @@ -1883,7 +1884,6 @@ sanael.net: could not connect to host sanatrans.com: could not connect to host sanmuding.com: could not connect to host santanderideas.com: could not connect to host -santojuken.co.jp: could not connect to host sarahlicity.me.uk: could not connect to host sarindia.com: could not connect to host sarindia.de: could not connect to host @@ -1893,6 +1893,7 @@ savethedogfishfoundation.org: could not connect to host savingbytes.com: could not connect to host sbm.cloud: could not connect to host schaafenstrasse.koeln: could not connect to host +scheuchenstuel.at: could not connect to host schmidttulskie.de: could not connect to host schnapke.name: could not connect to host schul-bar.de: could not connect to host @@ -1912,6 +1913,7 @@ sectest.ml: could not connect to host secure-automotive-cloud.com: could not connect to host secure-automotive-cloud.org: could not connect to host secureindia.co: could not connect to host +securetronic.ch: could not connect to host security.xn--q9jyb4c: could not connect to host securitymap.wiki: could not connect to host securitysoapbox.com: could not connect to host @@ -1924,7 +1926,6 @@ seleondar.ru: could not connect to host selfserverx.com: could not connect to host sellmoretires.com: could not connect to host seoscribe.net: could not connect to host -seproco.com: could not connect to host serverlauget.no: could not connect to host servfefe.com: could not connect to host seryovpn.com: could not connect to host @@ -1938,6 +1939,7 @@ shanxiapark.com: could not connect to host shareoine.com: could not connect to host sharvey.ca: could not connect to host shavingks.com: could not connect to host +shellday.cc: could not connect to host shentengtu.idv.tw: could not connect to host sheying.tm: could not connect to host shh.sh: could not connect to host @@ -1984,13 +1986,13 @@ smith.is: could not connect to host sml.lc: could not connect to host smuhelper.cn: could not connect to host snapserv.net: could not connect to host +sneed.company: could not connect to host snerith.com: could not connect to host sniderman.pro: could not connect to host sniderman.us: could not connect to host snowdy.eu: could not connect to host soboleva-pr.com.ua: could not connect to host soc.net: could not connect to host -socialdevelop.biz: could not connect to host socialworkout.com: could not connect to host socialworkout.net: could not connect to host socialworkout.org: could not connect to host @@ -1998,19 +2000,16 @@ socialworkout.tv: could not connect to host socketize.com: could not connect to host sogravatas.net.br: could not connect to host sojingle.net: could not connect to host -sol-computers.es: could not connect to host solymar.co: could not connect to host sonafe.info: could not connect to host sonja-kowa.de: could not connect to host soontm.de: could not connect to host sorenam.com: could not connect to host -sorincocorada.ro: could not connect to host sorn.service.gov.uk: could not connect to host sortaweird.net: could not connect to host sourcecode.love: could not connect to host sowingseasons.com: could not connect to host sowncloud.de: could not connect to host -sozon.ca: could not connect to host sp.rw: could not connect to host spam.lol: could not connect to host spamdrain.com: could not connect to host @@ -2019,7 +2018,6 @@ sparkbase.cn: could not connect to host spawn.cz: could not connect to host sphinx.network: could not connect to host spicywombat.com: could not connect to host -spidernet.tk: could not connect to host spinner.dnshome.de: could not connect to host split.is: could not connect to host sportflash.info: could not connect to host @@ -2032,9 +2030,9 @@ srvonfire.com: could not connect to host sss3s.com: could not connect to host stadionmanager.com: could not connect to host stadtgartenla.com: could not connect to host -stameystreet.com: could not connect to host starplatinum.jp: could not connect to host startup.melbourne: could not connect to host +startuppeople.co.uk: could not connect to host startupum.ru: could not connect to host statgram.me: could not connect to host static-assets.io: could not connect to host @@ -2051,7 +2049,6 @@ stonemanbrasil.com.br: could not connect to host stpip.com: could not connect to host streams.dyndns.org: could not connect to host stressfreehousehold.com: could not connect to host -strom.family: could not connect to host struxureon.com: could not connect to host stylle.me: could not connect to host subrain.com: could not connect to host @@ -2083,6 +2080,7 @@ swissentreprises.ch: could not connect to host swuosa.org: could not connect to host syhost.at: could not connect to host syhost.de: could not connect to host +syncaddict.net: could not connect to host syncmylife.net: could not connect to host synergisticsoccer.com: could not connect to host sysert.tv: could not connect to host @@ -2091,6 +2089,7 @@ szunia.com: could not connect to host t3rror.net: could not connect to host tab.watch: could not connect to host tacoma-games.com: could not connect to host +tadu.de: could not connect to host taidu.news: could not connect to host takusan.ru: could not connect to host tangyue.date: could not connect to host @@ -2144,7 +2143,6 @@ thesehighsandlows.com: could not connect to host theserver201.tk: could not connect to host thetapirsmouth.com: could not connect to host thevoid.one: could not connect to host -theyear199x.org: could not connect to host thinkcash.nl: could not connect to host thismumdoesntknowbest.com: could not connect to host thoughtsynth.com: could not connect to host @@ -2156,6 +2154,7 @@ tianxicaipiao.com: could not connect to host tianxicaipiao.win: could not connect to host tianxicp.com: could not connect to host tibovanheule.site: could not connect to host +ticfleet.com: could not connect to host tiernanx.com: could not connect to host tigit.co.nz: could not connect to host timer.fit: could not connect to host @@ -2169,9 +2168,10 @@ tofa-koeln.de: could not connect to host tokoindo.top: could not connect to host tollsjekk.no: could not connect to host tomharris.tech: could not connect to host -tomli.blog: could not connect to host tomm.yt: could not connect to host tomo.gr: could not connect to host +tonsit.com: could not connect to host +tonsit.org: could not connect to host tooolroc.org: could not connect to host top10mountainbikes.info: could not connect to host topanlage.de: could not connect to host @@ -2188,7 +2188,6 @@ toxicip.com: could not connect to host tpblist.xyz: could not connect to host tpolemis.com: could not connect to host track.plus: could not connect to host -tradingrooms.com: could not connect to host traforet.win: could not connect to host trainhornforums.com: could not connect to host trainline.io: could not connect to host @@ -2233,7 +2232,6 @@ udo-luetkemeier.de: could not connect to host ueba1085.jp: could not connect to host ueu.me: could not connect to host ulalau.com: could not connect to host -ulti.gq: could not connect to host unefuite.ch: could not connect to host unhu.fr: could not connect to host uni2share.com: could not connect to host @@ -2241,6 +2239,7 @@ unicorn.li: could not connect to host uniformespousoalegre.com.br: could not connect to host uploadbro.com: could not connect to host upmchealthsecurity.us: could not connect to host +upr.com.ua: could not connect to host urbanwildlifealliance.org: could not connect to host urcentral.org: could not connect to host uscp8.com: could not connect to host @@ -2280,7 +2279,6 @@ vicenage.com: could not connect to host viciousviscosity.xyz: could not connect to host videorullen.se: could not connect to host vieaw.com: could not connect to host -vieux.pro: could not connect to host vikasbabyworld.de: could not connect to host vilaydin.com: could not connect to host villainsclothing.com.au: could not connect to host @@ -2296,13 +2294,13 @@ visiontree-beta.eu: could not connect to host visiontree.eu: could not connect to host vleij.family: could not connect to host vlogge.com: could not connect to host +vlvvl.com: could not connect to host vocab.guru: could not connect to host voeux.io: could not connect to host vogt.tech: could not connect to host volcain.io: could not connect to host vorderklier.de: could not connect to host vorlif.org: could not connect to host -vorodevops.com: could not connect to host votresiteweb.ch: could not connect to host vow.vn: could not connect to host vranjske.co.rs: could not connect to host @@ -2329,7 +2327,6 @@ watchweasel.com: could not connect to host waxdramatic.com: could not connect to host we.serveftp.net: could not connect to host weareincognito.org: could not connect to host -web-wave.jp: could not connect to host webambacht.nl: could not connect to host webart-factory.de: could not connect to host webbson.net: could not connect to host @@ -2345,10 +2342,10 @@ wecobble.com: could not connect to host weebsr.us: could not connect to host weiji.ga: could not connect to host weiler.xyz: could not connect to host +weizenke.im: could not connect to host wejumall.com: could not connect to host wekibe.de: could not connect to host welby.cat: could not connect to host -wellacapability.com: could not connect to host wendigo.pl: could not connect to host werbik.at: could not connect to host wereldplanner.nl: could not connect to host @@ -2395,12 +2392,10 @@ wumbo.kiwi: could not connect to host wundi.net: could not connect to host www-68277.com: could not connect to host www-8887999.com: could not connect to host -www.torproject.org: could not connect to host wxrlab.com: could not connect to host wyeworks.com: could not connect to host xatr0z.org: could not connect to host xbc.nz: could not connect to host -xboxdownloadthat.com: could not connect to host xeonlab.com: could not connect to host xeonlab.de: could not connect to host xia100.xyz: could not connect to host @@ -2408,13 +2403,16 @@ xianguocy.com: could not connect to host xilegames.com: could not connect to host xing.ml: could not connect to host xiqi.us: could not connect to host +xlboo.com: could not connect to host xmiui.com: could not connect to host xn--6x6a.life: could not connect to host xn--80aocgsfei.xn--p1ai: could not connect to host xn--8mr166hf6s.xn--fiqs8s: could not connect to host xn--c5w27q.ml: could not connect to host +xn--rdiger-kuhlmann-zvb.de: could not connect to host xn--srenpind-54a.dk: could not connect to host xn--t8j2a3042d.xyz: could not connect to host +xn--tda.ml: could not connect to host xn--vck8crc010pu14e.biz: could not connect to host xn--yj8h0m.ws: could not connect to host xn--ykrp42k.com: could not connect to host @@ -2428,7 +2426,6 @@ yabrt.cn: could not connect to host yahoo.ax: could not connect to host yarchives.jp: could not connect to host yaucy.win: could not connect to host -ybresson.com: could not connect to host yd.io: could not connect to host yellowcar.website: could not connect to host yemalu.com: could not connect to host @@ -2437,7 +2434,6 @@ yepbitcoin.com: could not connect to host yesfone.com.br: could not connect to host yggdar.ga: could not connect to host yhori.xyz: could not connect to host -yhwj.top: could not connect to host yibin0831.com: could not connect to host ying299.com: could not connect to host ying299.net: could not connect to host @@ -2452,18 +2448,17 @@ yourznc.com: could not connect to host yousite.by: could not connect to host yude.ml: could not connect to host yum.beer: could not connect to host -yurimoens.be: could not connect to host yux.fr: could not connect to host yveshield.com: could not connect to host z0rro.net: could not connect to host zachbolinger.com: could not connect to host +zalohovaniburian.cz: could not connect to host zaoext.com: could not connect to host zbchen.com: could not connect to host zbp.at: could not connect to host zeitzer-turngala.de: could not connect to host zeloz.xyz: could not connect to host zenghx.tk: could not connect to host -zenics.co.uk: could not connect to host zero-x-baadf00d.com: could not connect to host zerosource.net: could not connect to host zeug.co: could not connect to host @@ -2484,8 +2479,8 @@ zorz.info: could not connect to host zrn.in: could not connect to host zudomc.me: could not connect to host zuehlcke.de: could not connect to host +zulu7.com: could not connect to host zuviel.space: could not connect to host -zwerimex.com: could not connect to host zwy.me: could not connect to host zypr.pw: could not connect to host zyx.im: could not connect to host @@ -2496,7 +2491,7 @@ zzw.ca: could not connect to host 0005aa.com: could not connect to host 007sascha.de: did not receive HSTS header 020wifi.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 116" data: no] -0222aa.com: could not connect to host +0222aa.com: did not receive HSTS header 040fit.nl: did not receive HSTS header 048.ag: could not connect to host 050508.com: could not connect to host @@ -2862,7 +2857,6 @@ alfa24.pro: could not connect to host alfredxing.com: did not receive HSTS header alistairpialek.com: max-age too low: 86400 alittlebitcheeky.com: did not receive HSTS header -aljaspod.net: could not connect to host aljmz.com: could not connect to host alkami.com: max-age too low: 0 alkamitech.com: max-age too low: 0 @@ -2872,6 +2866,7 @@ all4os.com: did not receive HSTS header alldaymonitoring.com: could not connect to host allegro-inc.com: did not receive HSTS header allgrass.es: did not receive HSTS header +alliance-compacts.com: did not receive HSTS header allinnote.com: could not connect to host allkindzabeats.com: did not receive HSTS header allmbw.com: could not connect to host @@ -3054,11 +3049,11 @@ arboineuropa.nl: did not receive HSTS header arboleda-hurtado.com: could not connect to host arbu.eu: max-age too low: 2419200 arcbit.io: did not receive HSTS header -archii.ca: could not connect to host +archii.ca: did not receive HSTS header architecte-interieur.be: did not receive HSTS header ardao.me: could not connect to host ardorlabs.se: could not connect to host -arewedubstepyet.com: could not connect to host +arewedubstepyet.com: did not receive HSTS header areyouever.me: did not receive HSTS header argennon.xyz: could not connect to host arguggi.co.uk: could not connect to host @@ -3073,8 +3068,9 @@ armored.ninja: did not receive HSTS header armory.consulting: could not connect to host armory.supplies: could not connect to host armsday.com: could not connect to host -armyofbane.com: did not receive HSTS header +armyofbane.com: could not connect to host armytricka.cz: did not receive HSTS header +arne-petersen.net: did not receive HSTS header aromaclub.nl: did not receive HSTS header aroundme.org: did not receive HSTS header arpa.ph: did not receive HSTS header @@ -3117,7 +3113,6 @@ ass.org.au: could not connect to host assekuranzjobs.de: could not connect to host asset-alive.com: did not receive HSTS header asset-alive.net: did not receive HSTS header -assetict.com: did not receive HSTS header assurancesmons.be: did not receive HSTS header astraalivankila.net: did not receive HSTS header astral.gq: did not receive HSTS header @@ -3278,13 +3273,14 @@ baobeiglass.com: did not receive HSTS header baptiste-destombes.fr: did not receive HSTS header barcel.com.mx: max-age too low: 86400 barely.sexy: could not connect to host +barreaudenice.com: max-age too low: 0 barrelhead.org: could not connect to host barrut.me: did not receive HSTS header barshout.co.uk: could not connect to host bartbania.com: did not receive HSTS header barunisystems.com: could not connect to host bashcode.ninja: could not connect to host -basicsolutionsus.com: could not connect to host +basicsolutionsus.com: did not receive HSTS header basilisk.io: could not connect to host basketsbymaurice.com: did not receive HSTS header baskettemple.com: did not receive HSTS header @@ -3371,6 +3367,7 @@ besixdouze.world: could not connect to host besola.de: did not receive HSTS header bestattorney.com: did not receive HSTS header bestbeards.ca: could not connect to host +bestcellular.com: did not receive HSTS header besthost.cz: did not receive HSTS header bestmodels.su: did not receive HSTS header bestof1001.de: could not connect to host @@ -3395,6 +3392,7 @@ beyond-edge.com: could not connect to host beyuna.co.uk: did not receive HSTS header beyuna.eu: did not receive HSTS header beyuna.nl: did not receive HSTS header +bezemkast.nl: did not receive HSTS header bezorg.ninja: could not connect to host bezprawnik.pl: did not receive HSTS header bf.am: max-age too low: 0 @@ -3515,7 +3513,7 @@ blue17.co.uk: did not receive HSTS header bluebill.net: did not receive HSTS header bluecon.eu: did not receive HSTS header bluefrag.com: did not receive HSTS header -blueglobalmedia.com: did not receive HSTS header +blueglobalmedia.com: could not connect to host blueliv.com: did not receive HSTS header bluescloud.xyz: could not connect to host bluetenmeer.com: did not receive HSTS header @@ -3618,7 +3616,7 @@ brookechase.com: did not receive HSTS header brownlawoffice.us: did not receive HSTS header browserid.org: could not connect to host brrd.io: did not receive HSTS header -brunix.net: could not connect to host +brunix.net: did not receive HSTS header brunohenc.from.hr: did not receive HSTS header brunoonline.co.uk: could not connect to host bryanshearer.accountant: did not receive HSTS header @@ -3896,7 +3894,7 @@ cheesetart.my: could not connect to host cheetah85.de: could not connect to host chefgalles.com.br: could not connect to host chejianer.cn: could not connect to host -chelema.xyz: could not connect to host +chelema.xyz: did not receive HSTS header chenfengyi.com: could not connect to host chensir.net: could not connect to host chepaofen.com: did not receive HSTS header @@ -4017,6 +4015,7 @@ clovissantos.com: did not receive HSTS header clowde.in: could not connect to host clownaroundbouncycastles.co.uk: did not receive HSTS header club-adulti.ro: did not receive HSTS header +club103.ch: did not receive HSTS header clubalfa.it: max-age too low: 3600 clubcall.com: did not receive HSTS header clubmix.co.kr: could not connect to host @@ -4034,6 +4033,7 @@ co-driversphoto.se: could not connect to host coach-sportif.paris: did not receive HSTS header coachingconsultancy.com: did not receive HSTS header cobrax.net: could not connect to host +coccolebenessere.it: did not receive HSTS header cocker.cc: max-age too low: 7776000 cocktailfuture.fr: could not connect to host cocolovesdaddy.com: could not connect to host @@ -4151,7 +4151,6 @@ core.mx: could not connect to host core4system.de: could not connect to host corenetworking.de: could not connect to host corex.io: could not connect to host -coreyjmahler.com: did not receive HSTS header corgicloud.com: could not connect to host corkyoga.site: could not connect to host cormactagging.ie: could not connect to host @@ -4252,7 +4251,7 @@ ct-status.org: could not connect to host ct-watches.dk: did not receive HSTS header cthulhuden.com: could not connect to host ctrl.blog: did not receive HSTS header -cuanhua3s.com: could not connect to host +cuanhua3s.com: did not receive HSTS header cubecart-demo.co.uk: did not receive HSTS header cubecart-hosting.co.uk: did not receive HSTS header cubecart.net: did not receive HSTS header @@ -4438,6 +4437,7 @@ demo.swedbank.se: did not receive HSTS header demomanca.com: did not receive HSTS header demotops.com: could not connect to host dempsters.ca: max-age too low: 86400 +denardbrewing.com: did not receive HSTS header denh.am: did not receive HSTS header denisjean.fr: could not connect to host dentaldomain.org: did not receive HSTS header @@ -4521,6 +4521,7 @@ digitalnonplus.com: could not connect to host digitalquery.com: did not receive HSTS header digitalriver.tk: did not receive HSTS header digitalskillswap.com: could not connect to host +digiworks.se: did not receive HSTS header dikshant.net: did not receive HSTS header diletec.com.br: did not receive HSTS header dim.lighting: could not connect to host @@ -4706,7 +4707,6 @@ dunea.nl: did not receive HSTS header duole30.com: did not receive HSTS header duongpho.com: did not receive HSTS header duskopy.top: could not connect to host -dutchessuganda.com: did not receive HSTS header dutchrank.com: did not receive HSTS header duuu.ch: could not connect to host duyao.de: max-age too low: 86400 @@ -4824,7 +4824,6 @@ eidolonhost.com: did not receive HSTS header eifelindex.de: did not receive HSTS header eigo.work: could not connect to host eimanavicius.lt: did not receive HSTS header -einhorn.space: could not connect to host ekbanden.nl: could not connect to host eksik.com: did not receive HSTS header el-soul.com: did not receive HSTS header @@ -4850,6 +4849,7 @@ elenoon.ir: did not receive HSTS header elgacien.de: could not connect to host elglobo.com.mx: max-age too low: 86400 elimdengelen.com: did not receive HSTS header +elite-porno.ru: did not receive HSTS header elitecovering.fr: did not receive HSTS header elitefishtank.com: could not connect to host elmar-kraamzorg.nl: did not receive HSTS header @@ -4960,6 +4960,7 @@ escalate.eu: could not connect to host escolaengenharia.com.br: did not receive HSTS header escortshotsexy.com: max-age too low: 2592000 escotour.com: could not connect to host +escueladewordpress.com: did not receive HSTS header esec.rs: did not receive HSTS header esko.bar: could not connect to host esln.org: did not receive HSTS header @@ -5187,6 +5188,7 @@ findigo.fish: could not connect to host findingmyname.com: did not receive HSTS header findtutorsnearme.com: did not receive HSTS header finer04.pw: did not receive HSTS header +finflix.net: did not receive HSTS header fingent.com: did not receive HSTS header finiteheap.com: did not receive HSTS header finn.io: did not receive HSTS header @@ -5267,6 +5269,7 @@ flurrybridge.com: did not receive HSTS header flushstudios.com: did not receive HSTS header flyaces.com: could not connect to host flybunnyfly.dk: did not receive HSTS header +flygpost.com: did not receive HSTS header fm83.nl: could not connect to host fm992.com: did not receive HSTS header fmi.gov: did not receive HSTS header @@ -5303,6 +5306,7 @@ formazioneopen.it: could not connect to host formersessalaries.com: did not receive HSTS header formula.cf: could not connect to host forplanetsake.com: could not connect to host +fortran.io: did not receive HSTS header forty2.eu: did not receive HSTS header forus.be: could not connect to host fossewaygardencentre.co.uk: did not receive HSTS header @@ -5316,7 +5320,6 @@ fourchin.net: could not connect to host fourwheelpartloanssimple.com: did not receive HSTS header foxdev.io: did not receive HSTS header foxelbox.com: did not receive HSTS header -foxing.club: did not receive HSTS header foxley-farm.co.uk: did not receive HSTS header foxley-seeds.co.uk: did not receive HSTS header foxleyseeds.co.uk: could not connect to host @@ -5438,7 +5441,7 @@ gallery44.org: did not receive HSTS header galletasgabi.com.mx: max-age too low: 86400 galoisvpn.xyz: could not connect to host gambitcloud.net: could not connect to host -game.yt: could not connect to host +game.yt: did not receive HSTS header gamecave.de: could not connect to host gamechasm.com: could not connect to host gameclue.jp: did not receive HSTS header @@ -5582,6 +5585,7 @@ glbg.eu: did not receive HSTS header glentakahashi.com: could not connect to host glittersjabloon.nl: did not receive HSTS header glitzmirror.com: could not connect to host +global-adult-webcams.com: did not receive HSTS header globalado.com: could not connect to host globalbridge-japan.com: did not receive HSTS header globalexpert.co.nz: could not connect to host @@ -5638,7 +5642,7 @@ gorillow.com: could not connect to host goshop.cz: did not receive HSTS header gostream.asia: could not connect to host gotgenes.com: could not connect to host -goto.msk.ru: could not connect to host +goto.msk.ru: did not receive HSTS header gotobrno.cz: did not receive HSTS header gotocloud.ru: did not receive HSTS header gotowned.org: max-age too low: 0 @@ -5696,7 +5700,7 @@ gresb.com: did not receive HSTS header gretchelizartistry.com: did not receive HSTS header grevesgarten.de: could not connect to host greyline.se: could not connect to host -grian-bam.at: could not connect to host +grian-bam.at: did not receive HSTS header gribani.com: could not connect to host grid2osm.org: could not connect to host grigalanzsoftware.com: could not connect to host @@ -5778,7 +5782,6 @@ hacker8.cn: did not receive HSTS header hackercat.ninja: did not receive HSTS header hackerforever.com: could not connect to host hackerone-ext-adroll.com: could not connect to host -hackerpoints.com: did not receive HSTS header hackerspace-ntnu.no: did not receive HSTS header hackest.org: did not receive HSTS header hackit.im: could not connect to host @@ -6065,6 +6068,7 @@ hup.blue: could not connect to host huskybutt.dog: could not connect to host huzu.com: did not receive HSTS header hwcine.com: did not receive HSTS header +hwpkasse.de: max-age too low: 2592000 hyakumachi.com: did not receive HSTS header hyatt.com: could not connect to host hydra.ws: could not connect to host @@ -6314,7 +6318,6 @@ iprice.vn: did not receive HSTS header ipricethailand.com: did not receive HSTS header iprody.com: max-age too low: 7889238 iptel.ro: could not connect to host -ipuservicedesign.com: could not connect to host ipv6.watch: did not receive HSTS header ipv6cloud.club: could not connect to host ipv6only.network: could not connect to host @@ -6409,7 +6412,7 @@ jacobparry.ca: did not receive HSTS header jacobsenarquitetura.com: max-age too low: 5184000 jagido.de: did not receive HSTS header jahliveradio.com: could not connect to host -jakeguild.com: could not connect to host +jakeguild.com: did not receive HSTS header jamanji.com.ng: could not connect to host james-parker.com: did not receive HSTS header james.je: could not connect to host @@ -6568,7 +6571,7 @@ jonsno.ws: could not connect to host joostbovee.nl: could not connect to host jordanstrustcompany.cn: could not connect to host jordanstrustcompany.ru: could not connect to host -jordikroon.nl: did not receive HSTS header +jordikroon.nl: could not connect to host joretapo.fr: could not connect to host jorgemesa.me: could not connect to host josahrens.me: could not connect to host @@ -6628,7 +6631,7 @@ jvwdev.nl: did not receive HSTS header jwilsson.me: could not connect to host jxm.in: could not connect to host jym.fit: did not receive HSTS header -jysperm.me: could not connect to host +jysperm.me: did not receive HSTS header jznet.org: could not connect to host k-dev.de: could not connect to host k-rickroll-g.pw: could not connect to host @@ -6696,6 +6699,7 @@ keepassa.co: could not connect to host keepclean.me: could not connect to host keepcoalintheground.org: could not connect to host kefaloniatoday.com: did not receive HSTS header +ken-electric.com.br: did not receive HSTS header kenkoelectric.com: did not receive HSTS header kentacademiestrust.org.uk: did not receive HSTS header kerangalam.com: could not connect to host @@ -6995,6 +6999,7 @@ lenovogaming.com: could not connect to host lentri.com: did not receive HSTS header leob.in: could not connect to host leon-jaekel.com: could not connect to host +leondenard.com: did not receive HSTS header leonmahler.consulting: did not receive HSTS header leopold.email: could not connect to host leopotamgroup.com: could not connect to host @@ -7129,6 +7134,7 @@ lodgesdureynou.fr: did not receive HSTS header loftboard.eu: could not connect to host log2n.uk: could not connect to host logario.com.br: could not connect to host +logfile.ch: did not receive HSTS header logicaladvertising.com: could not connect to host login.persona.org: could not connect to host loginseite.com: could not connect to host @@ -7184,7 +7190,7 @@ lrhsclubs.com: could not connect to host ls-a.org: did not receive HSTS header ls-reallife.de: did not receive HSTS header ls-rp.es: did not receive HSTS header -lsky.cn: could not connect to host +lsky.cn: did not receive HSTS header lsp-sports.de: did not receive HSTS header lsvih.com: did not receive HSTS header ltbytes.com: could not connect to host @@ -7334,7 +7340,7 @@ maosi.xin: did not receive HSTS header maple5.com: could not connect to host maplenorth.co: could not connect to host mapresidentielle.fr: could not connect to host -marcdorka.de: did not receive HSTS header +marcdorka.de: max-age too low: 0 marcelparra.com: could not connect to host marchagen.nl: did not receive HSTS header marco01809.net: could not connect to host @@ -7463,6 +7469,7 @@ mediafinancelab.org: did not receive HSTS header mediamag.am: max-age too low: 0 mediawikicn.org: could not connect to host medienservice-fritz.de: did not receive HSTS header +medifab.online: did not receive HSTS header medirich.co: could not connect to host meditek-dv.ru: could not connect to host mediterenopmaandag.nl: did not receive HSTS header @@ -7517,7 +7524,6 @@ metadistribution.com: did not receive HSTS header metagrader.com: could not connect to host metasyntactic.xyz: could not connect to host metebalci.com: did not receive HSTS header -meteosherbrooke.com: did not receive HSTS header meteosky.net: could not connect to host meter.md: could not connect to host metin2blog.de: did not receive HSTS header @@ -7751,6 +7757,7 @@ motherbase.io: could not connect to host motionfreight.com: could not connect to host motionpicturesolutions.com: did not receive HSTS header motorcheck.ie: did not receive HSTS header +motorsportdiesel.com: did not receive HSTS header mottvd.com: could not connect to host moudicat.com: max-age too low: 6307200 moula.com.au: did not receive HSTS header @@ -7776,8 +7783,9 @@ mrettich.org: did not receive HSTS header mrhee.com: did not receive HSTS header mrning.com: did not receive HSTS header mrnonz.com: max-age too low: 0 +mrparker.pw: did not receive HSTS header mrpopat.in: did not receive HSTS header -mrs-shop.com: could not connect to host +mrs-shop.com: did not receive HSTS header mrsbairds.com: max-age too low: 86400 msc-seereisen.net: max-age too low: 0 mstd.tokyo: did not receive HSTS header @@ -7871,7 +7879,6 @@ mysecretrewards.com: could not connect to host myspa.asia: did not receive HSTS header mystery-science-theater-3000.de: did not receive HSTS header mysteryblog.de: did not receive HSTS header -mysterysear.ch: did not receive HSTS header mythlogic.com: did not receive HSTS header mythslegendscollection.com: did not receive HSTS header myweb360.de: did not receive HSTS header @@ -7956,7 +7963,7 @@ nemovement.org: could not connect to host neoani.me: did not receive HSTS header neofelhz.space: could not connect to host neonisi.com: could not connect to host -neonnuke.tech: did not receive HSTS header +neonnuke.tech: could not connect to host neosolution.ca: did not receive HSTS header nepustil.net: could not connect to host nerd42.de: could not connect to host @@ -8023,12 +8030,14 @@ nhus.de: max-age too low: 172800 nibiisclaim.com: could not connect to host nicesco.re: did not receive HSTS header nicestresser.fr: could not connect to host +nicholaspruss.com: did not receive HSTS header nicky.io: did not receive HSTS header nico.one: could not connect to host nicoborghuis.nl: could not connect to host nicolaelmer.ch: did not receive HSTS header nicolasbettag.me: did not receive HSTS header nicolasdutour.com: did not receive HSTS header +nicolasklotz.de: did not receive HSTS header niconiconi.xyz: could not connect to host niconode.com: could not connect to host nidux.com: did not receive HSTS header @@ -8053,7 +8062,7 @@ nirna.io: did not receive HSTS header nitropur.de: max-age too low: 0 nixien.fr: could not connect to host nixmag.net: could not connect to host -nkautoservice.nl: did not receive HSTS header +nkautoservice.nl: could not connect to host nkb.in.th: could not connect to host nll.fi: could not connect to host nmadda.com: could not connect to host @@ -8211,6 +8220,7 @@ ohsocool.org: did not receive HSTS header oiepoie.nl: could not connect to host oishioffice.com: did not receive HSTS header ojls.co: could not connect to host +ojomovies.com: did not receive HSTS header okane.love: could not connect to host okok-rent.com: could not connect to host okok.rent: could not connect to host @@ -8240,7 +8250,6 @@ onefour.co: could not connect to host onehourloan.com: could not connect to host onehourloan.sg: did not receive HSTS header oneiros.cc: could not connect to host -oneminute.io: could not connect to host oneminutefilm.tv: could not connect to host onepathnetwork.com: max-age too low: 7776000 onepluscamps.com: did not receive HSTS header @@ -8352,7 +8361,7 @@ otrsdemo.hu: did not receive HSTS header ottospora.nl: could not connect to host ourbank.com: max-age too low: 2592000 outdooradventures.pro: did not receive HSTS header -outdoorproducts.com: could not connect to host +outdoorproducts.com: did not receive HSTS header outreachbuddy.com: could not connect to host outsider.im: could not connect to host outurnate.com: did not receive HSTS header @@ -8403,7 +8412,7 @@ panaceallc.net: could not connect to host panama-gbs.com: did not receive HSTS header panamaequity.com: did not receive HSTS header panamateakforestry.com: did not receive HSTS header -panelomix.net: did not receive HSTS header +panelomix.net: could not connect to host panicparts.com: max-age too low: 10540800 panni.me: could not connect to host panoranordic.net: could not connect to host @@ -8691,6 +8700,7 @@ polycrypt.us: could not connect to host polypho.nyc: could not connect to host pompefunebrilariviera.it: could not connect to host pompompoes.com: could not connect to host +ponteencima.com: did not receive HSTS header pontokay.com.br: could not connect to host pontualcomp.com: could not connect to host pony.today: could not connect to host @@ -8699,6 +8709,7 @@ poolsandstuff.com: did not receive HSTS header poon.tech: could not connect to host popi.se: did not receive HSTS header popkins.ml: could not connect to host +popupsoftplay.com: did not receive HSTS header poris.web.id: could not connect to host pornstars.me: did not receive HSTS header portalm.tk: could not connect to host @@ -9082,7 +9093,7 @@ reporturl.com: did not receive HSTS header reporturl.io: did not receive HSTS header reprolife.co.uk: could not connect to host res-rheingau.de: did not receive HSTS header -res42.com: could not connect to host +res42.com: did not receive HSTS header reserve-online.net: did not receive HSTS header residentsinsurance.co.uk: did not receive HSTS header resl20.servehttp.com: could not connect to host @@ -9161,6 +9172,7 @@ rodneybrooksjr.com: did not receive HSTS header rodosto.com: did not receive HSTS header roeper.party: could not connect to host roesemann.email: could not connect to host +roffe.nu: did not receive HSTS header roguelikecenter.fr: did not receive HSTS header rohlik.cz: did not receive HSTS header roketix.co.uk: could not connect to host @@ -9178,6 +9190,7 @@ ronanrbr.com: did not receive HSTS header rondoniatec.com.br: did not receive HSTS header ronvandordt.info: could not connect to host ronwo.de: max-age too low: 1 +roo.ie: did not receive HSTS header rootforum.org: did not receive HSTS header rootservice.org: did not receive HSTS header rootwpn.com: could not connect to host @@ -9253,7 +9266,7 @@ safetyrisk.net: did not receive HSTS header safewings-nh.nl: could not connect to host safing.me: did not receive HSTS header sagarhandicraft.com: could not connect to host -sageth.com: max-age too low: 0 +sageth.com: could not connect to host sah3.net: could not connect to host saharalondon.com: max-age too low: 0 saigonstar.de: did not receive HSTS header @@ -9459,7 +9472,7 @@ semps.de: did not receive HSTS header sendash.com: could not connect to host sendmeback.de: did not receive HSTS header senedirect.com: could not connect to host -sens2lavie.com: could not connect to host +sens2lavie.com: did not receive HSTS header senseofnumber.co.uk: did not receive HSTS header sensiblemn.org: could not connect to host sensibus.com: did not receive HSTS header @@ -9474,7 +9487,7 @@ serbien.guide: could not connect to host serenitycreams.com: did not receive HSTS header serfdom.io: did not receive HSTS header serized.pw: could not connect to host -serverangels.co.uk: could not connect to host +serverangels.co.uk: did not receive HSTS header servercode.ca: did not receive HSTS header serverdensity.io: did not receive HSTS header servergno.me: did not receive HSTS header @@ -9744,7 +9757,6 @@ socomponents.co.uk: could not connect to host sodacore.com: could not connect to host softballsavings.com: did not receive HSTS header sogeek.me: could not connect to host -sokietech.com: did not receive HSTS header sokolka.tv: did not receive HSTS header sol-3.de: did not receive HSTS header sol.works: did not receive HSTS header @@ -9799,7 +9811,7 @@ spacehq.org: could not connect to host spacemo.com: did not receive HSTS header spacountryexplorer.org.au: did not receive HSTS header spaggel.nl: did not receive HSTS header -spamloco.net: could not connect to host +spamloco.net: did not receive HSTS header spangehlassociates.com: did not receive HSTS header sparelib.com: max-age too low: 3650 spark.team: could not connect to host @@ -9976,7 +9988,7 @@ studydrive.net: did not receive HSTS header studyhub.cf: did not receive HSTS header stuffie.org: did not receive HSTS header stugb.de: did not receive HSTS header -sturbock.me: did not receive HSTS header +sturbock.me: could not connect to host sturdio.com.br: could not connect to host stylenda.com: could not connect to host stytt.com: did not receive HSTS header @@ -10057,7 +10069,6 @@ swisstranslate.fr: did not receive HSTS header swite.com: did not receive HSTS header swmd5c.org: could not connect to host swu.party: could not connect to host -sx3.no: did not receive HSTS header sxbk.pw: could not connect to host syam.cc: could not connect to host sydgrabber.tk: could not connect to host @@ -10137,7 +10148,7 @@ tasmansecurity.com: could not connect to host tassup.com: could not connect to host tasta.ro: did not receive HSTS header tastyyy.co: could not connect to host -tatilbus.com: could not connect to host +tatilbus.com: did not receive HSTS header tatt.io: could not connect to host tattvaayoga.com: did not receive HSTS header tauchkater.de: could not connect to host @@ -10402,7 +10413,7 @@ tikutiku.pl: could not connect to host tildebot.com: could not connect to host tilient.eu: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 116" data: no] tilikum.io: did not receive HSTS header -tilkah.com.au: did not receive HSTS header +tilkah.com.au: could not connect to host tillcraft.com: could not connect to host timbeilby.com: could not connect to host timbuktutimber.com: did not receive HSTS header @@ -10471,7 +10482,6 @@ tobyx.org: could not connect to host todesschaf.org: could not connect to host todo.is: did not receive HSTS header todobazar.es: could not connect to host -todoscomciro.com: did not receive HSTS header tofu.im: could not connect to host togelonlinecommunity.com: did not receive HSTS header toka.sg: did not receive HSTS header @@ -10586,7 +10596,6 @@ trinityaffirmations.com: max-age too low: 0 trinitycore.org: max-age too low: 2592000 trinitytechdev.com: did not receive HSTS header tripdelta.com: did not receive HSTS header -tripinsider.club: could not connect to host trixies-wish.nz: could not connect to host trixy.com.br: could not connect to host troi.de: did not receive HSTS header @@ -10685,7 +10694,7 @@ uadp.pw: could not connect to host uatgootax.ru: did not receive HSTS header uber.com.au: did not receive HSTS header uberfunction.com: did not receive HSTS header -ubicloud.de: did not receive HSTS header +ubicloud.de: could not connect to host ublox.com: did not receive HSTS header ubuntuhot.com: did not receive HSTS header uefeng.com: did not receive HSTS header @@ -10754,7 +10763,6 @@ unikitty-on-tour.com: could not connect to host unionstationapp.com: could not connect to host unison.com: did not receive HSTS header unisyssecurity.com: did not receive HSTS header -uniteasia.org: did not receive HSTS header unitlabs.net: could not connect to host unitrade-425.co.za: did not receive HSTS header university4industry.com: did not receive HSTS header @@ -10871,7 +10879,7 @@ vechkasov.ru: did not receive HSTS header vedatkamer.com: did not receive HSTS header vega-motor.com.ua: did not receive HSTS header vega.dyndns.info: could not connect to host -vegalengd.com: could not connect to host +vegalengd.com: did not receive HSTS header veganosonline.com: could not connect to host veggiefasting.com: could not connect to host veggiesbourg.fr: did not receive HSTS header @@ -11037,7 +11045,7 @@ w4xzr.top: could not connect to host w4xzr.xyz: could not connect to host w9rld.com: did not receive HSTS header wachtwoordencheck.nl: could not connect to host -wahhoi.net: could not connect to host +wahhoi.net: did not receive HSTS header wait.moe: could not connect to host waixingrenfuli7.vip: could not connect to host wakapp.de: could not connect to host @@ -11073,6 +11081,7 @@ waterforlife.net.au: did not receive HSTS header waterpoint.com.br: could not connect to host watersportmarkt.net: did not receive HSTS header watsonhall.uk: could not connect to host +wattechweb.com: did not receive HSTS header wavefloatrooms.com: did not receive HSTS header wavefrontsystemstech.com: could not connect to host waylee.net: did not receive HSTS header @@ -11276,6 +11285,7 @@ wpturnedup.com: did not receive HSTS header wpunpacked.com: could not connect to host wpyecom.es: did not receive HSTS header wpzhiku.com: did not receive HSTS header +wql.zj.cn: did not receive HSTS header wrbunderwriting.com: did not receive HSTS header wrightdoumawedding.com: could not connect to host writeapp.me: did not receive HSTS header @@ -11619,7 +11629,6 @@ zoommailing.com: did not receive HSTS header zoorigin.com: did not receive HSTS header zorasvobodova.cz: did not receive HSTS header zortium.report: could not connect to host -zotero.org: did not receive HSTS header zoznamrealit.sk: did not receive HSTS header zqhong.com: could not connect to host zqjs.tk: could not connect to host @@ -11632,8 +11641,6 @@ zunftmarke.de: did not receive HSTS header zuram.net: max-age too low: 1 zvncloud.com: did not receive HSTS header zwollemagazine.nl: did not receive HSTS header -zx6rninja.de: did not receive HSTS header -zx7r.de: did not receive HSTS header zyf.pw: could not connect to host zymbit.com: did not receive HSTS header zync.ca: did not receive HSTS header diff --git a/security/manager/ssl/nsSTSPreloadList.inc b/security/manager/ssl/nsSTSPreloadList.inc index a3c868ee2144..7aa4a5bbbc54 100644 --- a/security/manager/ssl/nsSTSPreloadList.inc +++ b/security/manager/ssl/nsSTSPreloadList.inc @@ -8,7 +8,7 @@ /*****************************************************************************/ #include -const PRTime gPreloadListExpirationTime = INT64_C(1530474614818000); +const PRTime gPreloadListExpirationTime = INT64_C(1530564062624000); %% 0-1.party, 1 0.me.uk, 1 @@ -1452,6 +1452,7 @@ alize-theatre.ch, 1 aljammaz.holdings, 1 aljaspod.com, 1 aljaspod.hu, 1 +aljaspod.net, 1 aljweb.com, 1 alkel.info, 1 all-connect.net, 0 @@ -1489,7 +1490,6 @@ allforyou.at, 1 allfreelancers.su, 1 allgrass.net, 1 allgreenturf.com.au, 1 -alliance-compacts.com, 1 alliances-faq.de, 1 alliances-globalsolutions.com, 1 alliedfrozenstorage.com, 1 @@ -2333,7 +2333,6 @@ armyprodej.cz, 1 arnaudb.net, 1 arnaudfeld.de, 1 arnaudminable.net, 1 -arne-petersen.net, 1 arnesolutions.com, 1 arniescastles.co.uk, 1 arnoldkontz-occasions.lu, 1 @@ -2506,6 +2505,7 @@ assemble-together.org, 1 assempsaibiza.com, 1 assertion.de, 1 assessoriati.com.br, 1 +assetict.com, 1 assetsupervision.com, 1 assetvault.co.za, 1 assguidesporrentruy.ch, 1 @@ -3234,7 +3234,6 @@ barprive.com, 1 barqo.co, 1 barracuda.blog, 1 barracuda.com.tr, 1 -barreaudenice.com, 1 barrera.io, 1 barrett.ag, 1 barriofut.com, 1 @@ -3688,7 +3687,6 @@ bestbonuses.co.uk, 1 bestbrakes.com, 1 bestbridal.top, 1 bestbyte.com.br, 1 -bestcellular.com, 0 bestellipticalmachinereview.info, 1 bestesb.com, 1 bestesb.net, 1 @@ -3788,7 +3786,6 @@ beyondweb.net, 1 beyonic.com, 1 beyours.be, 1 bez-energie.de, 1 -bezemkast.nl, 1 bezoomnyville.com, 1 bezpecnostsiti.cf, 1 bfam.tv, 1 @@ -6574,7 +6571,6 @@ clu-in.org, 1 club-duomo.com, 1 club-is.ru, 1 club-reduc.com, 1 -club103.ch, 1 clubdeslecteurs.net, 1 clubedalutashop.com, 1 clubempleos.com, 1 @@ -6656,7 +6652,6 @@ cocalc.com, 1 coccinellaskitchen.com, 1 coccinellaskitchen.de, 1 coccinellaskitchen.it, 1 -coccolebenessere.it, 1 cocinoyo.com, 1 cock.li, 1 cockedey.in, 1 @@ -7122,6 +7117,7 @@ corepartners.com.ua, 1 coresolutions.ca, 1 coresos.com, 1 coreum.ca, 1 +coreyjmahler.com, 1 corgi.party, 1 coribi.com, 1 corinnanese.de, 1 @@ -8322,7 +8318,6 @@ demuzere.net, 1 demuzere.org, 1 denabot.pw, 1 denaehula.com, 1 -denardbrewing.com, 1 dengchangdong.com, 1 dengode.eu, 1 denimio.com, 1 @@ -8698,7 +8693,6 @@ digitaltechnologies.ltd.uk, 1 digitalunite.de, 1 digitalwasteland.net, 1 digitkon.com, 1 -digiworks.se, 1 digminecraft.com, 1 diguass.us, 1 digwp.com, 1 @@ -9463,6 +9457,7 @@ dustygroove.com, 1 dustyspokesbnb.ca, 1 dutch.desi, 1 dutch1.nl, 1 +dutchessuganda.com, 1 dutchrank.nl, 1 dutchwanderers.nl, 1 dutchweballiance.nl, 1 @@ -9879,6 +9874,7 @@ einfachbahn.de, 1 einfachmaldiefressehalten.de, 1 einheft.info, 1 einheizpreis.de, 1 +einhorn.space, 1 einmonolog.de, 1 einrichtwerk.de, 1 einrichtwerk.shop, 1 @@ -10026,7 +10022,6 @@ elisabethkostecki.de, 1 elistor6100.xyz, 0 elite-box.com, 1 elite-box.org, 1 -elite-porno.ru, 1 elite12.de, 1 elitebouncingfun.com, 1 elitegameservers.net, 1 @@ -10604,7 +10599,6 @@ escort-byuro.net, 1 escortdisplay.com, 1 escortmantra.com, 1 escritoriodearte.com, 1 -escueladewordpress.com, 1 escxtra.com, 1 escyr.top, 1 esdenera.com, 1 @@ -11537,7 +11531,6 @@ finelovedolls.com, 1 finenet.com.tw, 1 finewineonline.com, 1 finfev.de, 1 -finflix.net, 1 finform.ch, 1 fingerscrossed.style, 1 fini-de-jouer.ch, 1 @@ -11780,7 +11773,6 @@ fly.moe, 1 flyawayantennas.com, 1 flyboyfpv.com, 1 flygon.pink, 1 -flygpost.com, 1 flyingdoggy.net, 1 flyinglocksmiths.com, 0 flyingpackets.net, 1 @@ -11928,7 +11920,6 @@ forsyththeatre.com, 1 forteggz.nl, 1 fortesanshop.it, 1 fortnine.ca, 1 -fortran.io, 1 fortress.no, 1 fortress.sk, 1 fortricks.in, 1 @@ -11991,6 +11982,7 @@ foxbnc.co.uk, 1 foxdev.co, 1 foxes.no, 1 foxhound.com.br, 1 +foxing.club, 1 foxmay.co.uk, 1 foxontheinter.net, 1 foxphotography.ch, 1 @@ -12822,7 +12814,7 @@ gers-authentique.com, 1 gerum.dynv6.net, 1 gerwinvanderkamp.nl, 1 ges-bo.de, 1 -geschenkly.de, 0 +geschenkly.de, 1 geschmacksache.online, 1 geschmackspiloten.de, 1 geschwinder.net, 1 @@ -13074,7 +13066,6 @@ glidingshop.de, 1 glidingshop.eu, 1 glloq.org, 1 glob-coin.com, 1 -global-adult-webcams.com, 1 global-lights.ma, 1 global-office.com, 1 global-village.koeln, 1 @@ -13755,6 +13746,7 @@ hackerone-ext-content.com, 1 hackerone-user-content.com, 1 hackerone.com, 1 hackerone.net, 1 +hackerpoints.com, 1 hackerstxt.org, 1 hackgins.com, 1 hackingand.coffee, 1 @@ -14931,7 +14923,6 @@ hvtuananh.com, 1 hwaddress.com, 1 hwag-pb.de, 1 hwinfo.com, 1 -hwpkasse.de, 0 hx53.de, 1 hxying.com, 1 hybridiyhdistys.fi, 1 @@ -15856,6 +15847,7 @@ ipstream.it, 1 ipswitch.com.tw, 1 ipty.de, 1 ipura.ch, 1 +ipuservicedesign.com, 1 ipv4.cf, 1 ipv4.gr, 1 ipv6-adresse.dk, 1 @@ -16311,7 +16303,7 @@ janverlaan.nl, 1 jaot.info, 1 japan4you.org, 1 japaneseemoticons.org, 1 -japanesenames.biz, 1 +japanesenames.biz, 0 japaniac.de, 0 japanphilosophy.com, 1 japanwatches.xyz, 1 @@ -17334,7 +17326,6 @@ kempkens.io, 1 kemptown.co.uk, 1 kemptown.com, 1 kemptown.net, 1 -ken-electric.com.br, 1 ken.fm, 1 kenalsworld.com, 1 kenbonny.net, 1 @@ -18621,7 +18612,6 @@ leonard.io, 0 leonardcamacho.me, 1 leonauto.de, 1 leonax.net, 1 -leondenard.com, 1 leonhooijer.nl, 0 leonklingele.de, 1 leopoldina.net, 1 @@ -19163,7 +19153,6 @@ logement.com, 1 logentries.com, 0 logexplorer.net, 1 logfile.at, 1 -logfile.ch, 1 logic8.ml, 1 logicchen.com, 1 logiciel-entreprise-seurann.fr, 1 @@ -19966,7 +19955,7 @@ marjoriecarvalho.com.br, 1 mark-a-hydrant.com, 1 mark-armstrong-gaming.com, 1 mark-semmler.de, 1 -markaconnor.com, 0 +markaconnor.com, 1 markepps.com, 1 market.android.com, 1 marketgot.com, 1 @@ -20407,7 +20396,6 @@ medicinia.com.br, 1 medicinskavranje.edu.rs, 1 medicocompetente.it, 1 medicoresponde.com.br, 1 -medifab.online, 1 medifi.com, 1 medinside.ch, 1 medinside.li, 1 @@ -20642,6 +20630,7 @@ meteobox.mx, 1 meteobox.pl, 1 meteobox.sk, 1 meteorapp.space, 1 +meteosherbrooke.com, 1 meteosmit.it, 1 meterhost.com, 1 methamphetamine.co.uk, 1 @@ -21392,7 +21381,6 @@ motoroilinfo.com, 1 motorpointarenacardiff.co.uk, 1 motorring.ru, 1 motorsplus.com, 0 -motorsportdiesel.com, 1 motoryachtclub-radolfzell.de, 1 motosikletevi.com, 1 motostorie.blog, 0 @@ -21493,7 +21481,6 @@ mrliu.me, 1 mrmoregame.de, 1 mrnh.de, 1 mrnh.tk, 1 -mrparker.pw, 1 mrpropop.com, 1 mrs-labo.jp, 1 mrserge.lv, 1 @@ -21913,6 +21900,7 @@ myssl.com, 1 mystatus24.com, 1 mysteriouscode.io, 1 mysterymind.ch, 1 +mysterysear.ch, 1 mystic-welten.de, 1 mystickphysick.com, 1 mysticplumes.com, 1 @@ -22583,7 +22571,6 @@ niceb5y.net, 0 niceguyit.biz, 1 nicestudio.co.il, 0 nichijou.com, 1 -nicholaspruss.com, 1 nicholasquigley.com, 1 nicholaswilliams.net, 1 nichteinschalten.de, 0 @@ -22611,7 +22598,6 @@ nicolas-hoffmann.net, 1 nicolas-hoizey.com, 1 nicolas-simond.com, 1 nicolasiung.me, 1 -nicolasklotz.de, 1 nicolaszambetti.ch, 1 nicolaw.uk, 1 nicoleoquendo.com, 1 @@ -23253,7 +23239,6 @@ oisd.nl, 1 oita-homes.com, 1 ojaioliveoil.com, 1 ojdip.net, 1 -ojomovies.com, 1 ojp.gov, 1 okad-center.de, 1 okad.de, 1 @@ -23385,6 +23370,7 @@ onefour.ga, 0 oneidentity.me, 1 onelawsuit.com, 1 onemid.net, 1 +oneminute.io, 0 onemoonmedia.de, 1 oneononeonone.de, 1 oneononeonone.tv, 1 @@ -25064,7 +25050,6 @@ pondof.fish, 1 poneypourtous.com, 1 poneytelecom.org, 1 ponga.se, 1 -ponteencima.com, 1 ponteus.com, 1 pontodogame.com.br, 1 pony-cl.co.jp, 1 @@ -25093,7 +25078,6 @@ popoway.cloud, 1 popoway.me, 1 poppetsphere.de, 1 population-ethics.com, 1 -popupsoftplay.com, 1 poquvi.net, 1 porg.es, 1 pork.org.uk, 1 @@ -25824,7 +25808,7 @@ qikan.net, 1 qiliang.wang, 1 qimiao.io, 1 qingpat.com, 1 -qingpei.me, 0 +qingpei.me, 1 qionouu.cn, 1 qirinus.com, 1 qitarabutrans.com, 1 @@ -26899,7 +26883,6 @@ roelsworld.eu, 1 roemhild.de, 1 roerstaafjes.nl, 1 roessner-network-solutions.com, 0 -roffe.nu, 1 rofl.com.ua, 1 roflcopter.fr, 1 rofrank.space, 1 @@ -26957,7 +26940,6 @@ rondreis-planner.nl, 1 ronghexx.com, 1 roninf.ch, 1 ronomon.com, 1 -roo.ie, 1 roof.ai, 1 roofingomaha.com, 1 roofsandbasements.com, 1 @@ -28029,7 +28011,7 @@ securon.io, 1 securoswiss.ch, 1 secutrans.com, 1 secuvera.de, 0 -secwall.me, 0 +secwall.me, 1 secwise.nl, 1 sedeusquiser.net, 1 sedussa.ro, 1 @@ -29286,6 +29268,7 @@ soinvett.com, 1 sojingle.net, 1 soju.fi, 1 sokche.com, 1 +sokietech.com, 1 sokkenhoek.nl, 1 sokolkarvina.cz, 1 sokouchousa.net, 1 @@ -30461,6 +30444,7 @@ swordfighting.net, 1 swuosa.org, 1 swvaux.com, 1 swyn.net, 1 +sx3.no, 1 sxistolithos.gr, 1 sy-anduril.de, 1 sy24.ru, 1 @@ -31805,6 +31789,7 @@ todocracy.com, 1 todoescine.com, 1 todoist.com, 1 todon.fr, 1 +todoscomciro.com, 1 todosrv.com, 1 toeglhofer.at, 1 toeightycountries.com, 1 @@ -32311,6 +32296,7 @@ trio.online, 1 triop.se, 1 trior.net, 1 tripcombi.com, 1 +tripinsider.club, 0 triple-mmm.de, 1 tripseats.com, 1 tripsinc.com, 1 @@ -32819,6 +32805,7 @@ unirenter.ru, 1 unit7jazz.com, 1 unit7jazz.org, 1 unite-ka.de, 1 +uniteasia.org, 1 united-schools.net, 1 united.com, 0 unitedadmins.com, 1 @@ -33662,7 +33649,7 @@ vorodevops.com, 1 vos-fleurs.ch, 1 vos-fleurs.com, 1 vosgym.jp, 1 -voshod.org, 0 +voshod.org, 1 vosjesweb.nl, 1 vosky.fr, 1 vostronet.com, 1 @@ -33903,7 +33890,6 @@ watertrails.io, 1 waterworkscondos.com, 1 watoo.tech, 1 watsonwork.me, 1 -wattechweb.com, 1 wave-ola.es, 1 wave.is, 1 wavesboardshop.com, 1 @@ -34772,7 +34758,6 @@ wpsono.com, 1 wpthaiuser.com, 1 wptotal.com, 1 wpvulndb.com, 1 -wql.zj.cn, 1 wr.su, 1 wrapitup.co.uk, 1 wrara.org, 1 @@ -35921,6 +35906,7 @@ zorium.org, 1 zorki.nl, 1 zorntt.fr, 1 zorz.info, 1 +zotero.org, 1 zouk.info, 1 zouyaoji.top, 1 zravypapir.cz, 1 @@ -35977,6 +35963,8 @@ zwk.de, 1 zwollemag.nl, 1 zwy.ch, 1 zwy.me, 0 +zx6rninja.de, 1 +zx7r.de, 1 zxity.co.uk, 1 zxity.ltd, 1 zxity.uk, 1 diff --git a/testing/geckodriver/doc/Releasing.md b/testing/geckodriver/doc/Releasing.md index cd3376f1450d..f1f3a51a2900 100644 --- a/testing/geckodriver/doc/Releasing.md +++ b/testing/geckodriver/doc/Releasing.md @@ -19,25 +19,35 @@ In any case, the steps to release geckodriver are as follows: [Mozilla’s CI infrastructure]: https://treeherder.mozilla.org/ -Release new webdriver crate ---------------------------- +Release new in-tree dependency crates +------------------------------------- -geckodriver depends on the [webdriver] crate, also hosted in -mozilla-central, by pointing to its in-tree relative path: +geckodriver depends on a number of Rust crates that also live in +central by using relative paths: - [dependencies] - webdriver = { path = "../webdriver" } + [dependencies] + … + mozprofile = { path = "../mozbase/rust/mozprofile" } + mozrunner = { path = "../mozbase/rust/mozrunner" } + mozversion = { path = "../mozbase/rust/mozversion" } + … + webdriver = { path = "../webdriver" } -Because we need to export the geckodriver source code to the old GitHub -repository in order to release, we need to publish any changes that -have been made to webdriver in the interim. If no changes have been -made, you can skip these steps: +Because we need to export the geckodriver source code to the old +GitHub repository when we release, we first need to publish these +crates if they have had any changes in the interim since the last +release. If they have receieved no changes, you can skip them: - 1. Bump the version number in testing/webdriver/Cargo.toml + - `testing/mozbase/rust/mozprofile` + - `testing/mozbase/rust/mozrunner` + - `testing/mozbase/rust/mozversion` + - `testing/webdriver` + +For each crate: + + 1. Bump the version number in Cargo.toml 2. `cargo publish` -[webdriver]: ../webdriver - Update the change log --------------------- @@ -63,8 +73,7 @@ mention of this. Lines are optimally formatted at roughly 72 columns to make the file readable in a text editor as well as rendered HTML. fmt(1) does a splendid job at text formatting. -[CHANGES.md]: ../CHANGES.md -[webdriver]: ../../webdriver +[CHANGES.md]: https://searchfox.org/mozilla-central/source/testing/geckodriver/CHANGES.md [rust-mozrunner]: https://github.com/jgraham/rust_mozrunner @@ -77,15 +86,15 @@ Make relevant changes to [Cargo.toml] to upgrade dependencies, then run % ./mach build testing/geckodriver to pull down and vendor the upgraded libraries. Remember to check -in the [Cargo.lock] file, since unlike we want geckodriver builds to -be reproducible. +in the [Cargo.lock] file since we want reproducible builds for +geckodriver, uninfluenced by dependency variations. -Updating dependencies should always be made as a separate commit to -not confuse reviewers because vendoring involves checking in a lot -of extra code reviewed downstream. +The updates to dependencies should always be made as a separate +commit to not confuse reviewers, because vendoring involves checking +in a lot of extra code already reviewed downstream. -[Cargo.toml]: ../Cargo.toml -[Cargo.lock]: ../Cargo.lock +[Cargo.toml]: https://searchfox.org/mozilla-central/source/testing/geckodriver/Cargo.toml +[Cargo.lock]: https://searchfox.org/mozilla-central/source/testing/geckodriver/Cargo.lock Bump the version number @@ -123,24 +132,24 @@ of [testing/geckodriver] to the latter branch: % git clean -fxd % cp -r $SRC/gecko/testing/geckodriver/* . -[README]: ../README.md -[testing/geckodriver]: ../ +[README.md]: https://searchfox.org/mozilla-central/source/testing/geckodriver/README.md +[testing/geckodriver]: https://searchfox.org/mozilla-central/source/testing/geckodriver -Manually change `webdriver` dependency --------------------------------------- +Manually change in-tree path dependencies +------------------------------------------ -After the source code has been imported we need to change the -dependency information for the [webdriver] crate. As explained -previously geckodriver depends on a relative path in in the -mozilla-central repository to build with the latest unreleased -source code. +After the source code has been imported we need to change the dependency +information for the `mozrunner`, `mozprofile`, `mozversion`, and +`webdriver` crates. As explained previously geckodriver depends +on a relative path in in the mozilla-central repository to build +with the latest unreleased source code. -This relative path does not exist in the GitHub repository and the -build will fail unless we change it to the latest [webdriver] crate -version from crates.io. That version will either be the crate you -published earlier, or the latest version available if no changes have -been made to it since the last geckodriver release. +This relative paths do not exist in the GitHub repository and the +build will fail unless we change it to the latest crate versions +from crates.io. That version will either be the crate you published +earlier, or the latest version available if no changes have been +made to it since the last geckodriver release. Commit local changes diff --git a/testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/browser/toolbars.py b/testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/browser/toolbars.py index c8abbf6ec068..dede6f311114 100644 --- a/testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/browser/toolbars.py +++ b/testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/browser/toolbars.py @@ -500,7 +500,7 @@ class IdentityPopupView(UIBaseLib): :return: `True` if the view is selected. """ - return self.element.get_attribute('current') == 'true' + return self.element.get_attribute('visible') == 'true' class IdentityPopupMainView(IdentityPopupView): diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 6e31365d7f78..30d93696c850 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -2398,7 +2398,7 @@ }, "HTTP_AUTH_DIALOG_STATS_3": { "record_in_processes": ["main", "content"], - "expires_in_version": "61", + "expires_in_version": "65", "alert_emails": ["necko@mozilla.com", "ddamjanovic@mozilla.com"], "bug_numbers": [1357835], "kind": "enumerated", @@ -2427,7 +2427,7 @@ }, "TCP_FAST_OPEN_3": { "record_in_processes": ["main"], - "expires_in_version": "61", + "expires_in_version": "65", "kind": "enumerated", "n_values": 32, "description": "When a http connection is closed, track whether or not TCP Fast Open was used: 0=TFO_NOT_SET, 1=TFO_UNKNOWN, 2=TFO_DISABLED, 3=TFO_DISABLED_CONNECT, 4=TFO_NOT_TRIED, 5=TFO_TRIED, 6=TFO_DATA_SENT, 7=TFO_DATA_COOKIE_NOT_ACCEPTED, 8=TFO_FAILED_CONNECTION_REFUSED, 9=TFO_FAILED_NET_TIMEOUT, 10=TFO_FAILED_UNKNOW_ERROR, 11=TFO_FAILED_BACKUP_CONNECTION_TFO_NOT_TRIED, 12=TFO_FAILED_BACKUP_CONNECTION_TFO_TRIED, 13=TFO_FAILED_BACKUP_CONNECTION_TFO_DATA_SENT, 14=TFO_FAILED_BACKUP_CONNECTION_TFO_DATA_COOKIE_NOT_ACCEPTED, 15=TFO_FAILED_CONNECTION_REFUSED_NO_TFO_FAILED_TOO, 16=TFO_FAILED_NET_TIMEOUT__NO_TFO_FAILED_TOO, 17=TFO_FAILED_UNKNOW_ERROR_NO_TFO_FAILED_TOO, 18=TFO_FAILED_BACKUP_CONNECTION_NO_TFO_FAILED_TOO, 19=TFO_BACKUP_CONN. Please look at netwerk/base/TCPFastOpenLayer.h for more info", @@ -2436,7 +2436,7 @@ }, "TCP_FAST_OPEN_STATUS": { "record_in_processes": ["main", "content"], - "expires_in_version": "61", + "expires_in_version": "65", "kind": "enumerated", "n_values": 8, "description": "TCP Fast Open was: 0=enabled during the session, 1=not available or disabled in the os, 2=disabled by the pref, 3=disabled based on the too many connection failures, 4=disable based on too many http transaction stalls after a connection was idle.", diff --git a/widget/windows/PDFiumEngineShim.cpp b/widget/windows/PDFiumEngineShim.cpp index 43ead7a94bf9..13a3ee3eeac3 100644 --- a/widget/windows/PDFiumEngineShim.cpp +++ b/widget/windows/PDFiumEngineShim.cpp @@ -65,7 +65,7 @@ PDFiumEngineShim::GetInstanceOrNull() RefPtr inst = sPDFiumEngineShim; if (!inst) { inst = new PDFiumEngineShim(); - if (!inst->Init(nsCString("pdfium.dll"))) { + if (!inst->Init(NS_LITERAL_STRING("pdfium.dll"))) { inst = nullptr; } sPDFiumEngineShim = inst.get(); @@ -76,7 +76,7 @@ PDFiumEngineShim::GetInstanceOrNull() /* static */ already_AddRefed -PDFiumEngineShim::GetInstanceOrNull(const nsCString& aLibrary) +PDFiumEngineShim::GetInstanceOrNull(const nsString& aLibrary) { RefPtr shim = new PDFiumEngineShim(); if (!shim->Init(aLibrary)) { @@ -107,13 +107,16 @@ PDFiumEngineShim::~PDFiumEngineShim() } bool -PDFiumEngineShim::Init(const nsCString& aLibrary) +PDFiumEngineShim::Init(const nsString& aLibrary) { if (mInitialized) { return true; } - mPRLibrary = PR_LoadLibrary(aLibrary.get()); + PRLibSpec libSpec; + libSpec.type = PR_LibSpec_PathnameU; + libSpec.value.pathname_u = aLibrary.get(); + mPRLibrary = PR_LoadLibraryWithFlags(libSpec, 0); NS_ENSURE_TRUE(mPRLibrary, false); mTable->mFPDF_InitLibrary = diff --git a/widget/windows/PDFiumEngineShim.h b/widget/windows/PDFiumEngineShim.h index bfdfa18bab1b..8df1205e38ec 100644 --- a/widget/windows/PDFiumEngineShim.h +++ b/widget/windows/PDFiumEngineShim.h @@ -33,7 +33,7 @@ public: // This function is used for testing purpose only, do not call it in regular // code. static already_AddRefed - GetInstanceOrNull(const nsCString& aLibrary); + GetInstanceOrNull(const nsString& aLibrary); FPDF_DOCUMENT LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING aPassword); @@ -54,7 +54,7 @@ public: private: PDFiumEngineShim(); ~PDFiumEngineShim(); - bool Init(const nsCString& aLibrary); + bool Init(const nsString& aLibrary); UniquePtr mTable; bool mInitialized ; diff --git a/widget/windows/PDFiumProcessChild.cpp b/widget/windows/PDFiumProcessChild.cpp index 014b6e289db7..dd6f2ae85411 100644 --- a/widget/windows/PDFiumProcessChild.cpp +++ b/widget/windows/PDFiumProcessChild.cpp @@ -46,7 +46,10 @@ PDFiumProcessChild::Init(int aArgc, char* aArgv[]) // an unknown reason, "pdfium.dll" can not be loaded correctly after // StartSandbox() been called. Temporary preload this library until we fix // bug 1417000. - mPDFium = PR_LoadLibrary("pdfium.dll"); + PRLibSpec libSpec; + libSpec.type = PR_LibSpec_PathnameU; + libSpec.value.pathname_u = char16ptr_t(u"pdfium.dll"); + mPDFium = PR_LoadLibraryWithFlags(libSpec, 0); mozilla::SandboxTarget::Instance()->StartSandbox(); #endif diff --git a/widget/windows/gtest/TestEMFConversion.cpp b/widget/windows/gtest/TestEMFConversion.cpp index 2cbd8133b1fa..970dbd5fd7a0 100755 --- a/widget/windows/gtest/TestEMFConversion.cpp +++ b/widget/windows/gtest/TestEMFConversion.cpp @@ -134,8 +134,7 @@ protected: NS_OS_CURRENT_WORKING_DIR, PDFIUM_FILENAME, pdfiumPath))); - const NS_ConvertUTF16toUTF8 externalDll(pdfiumPath); - mPDFiumEngine = PDFiumEngineShim::GetInstanceOrNull(externalDll); + mPDFiumEngine = PDFiumEngineShim::GetInstanceOrNull(pdfiumPath); MOZ_RELEASE_ASSERT(mPDFiumEngine); }