diff --git a/browser/components/translation/BingTranslator.jsm b/browser/components/translation/BingTranslator.jsm index fa433fc98e29..7349e56ad1a8 100644 --- a/browser/components/translation/BingTranslator.jsm +++ b/browser/components/translation/BingTranslator.jsm @@ -9,7 +9,7 @@ this.EXPORTED_SYMBOLS = [ "BingTranslator" ]; ChromeUtils.import("resource://gre/modules/Services.jsm"); ChromeUtils.import("resource://gre/modules/Log.jsm"); ChromeUtils.import("resource://gre/modules/PromiseUtils.jsm"); -ChromeUtils.import("resource://services-common/utils.js"); +ChromeUtils.import("resource://services-common/async.js"); ChromeUtils.import("resource://gre/modules/Http.jsm"); Cu.importGlobalProperties(["XMLHttpRequest"]); @@ -69,7 +69,7 @@ this.BingTranslator.prototype = { // let's take the opportunity of the chunkification process to // allow for the event loop to attend other pending events // before we continue. - await CommonUtils.laterTickResolvingPromise(); + await Async.promiseYield(); // Determine the data for the next request. let request = this._generateNextTranslationRequest(currentIndex); diff --git a/browser/components/translation/TranslationDocument.jsm b/browser/components/translation/TranslationDocument.jsm index 1d87b18a3520..5f4997d0e55d 100644 --- a/browser/components/translation/TranslationDocument.jsm +++ b/browser/components/translation/TranslationDocument.jsm @@ -8,7 +8,7 @@ this.EXPORTED_SYMBOLS = [ "TranslationDocument" ]; const TEXT_NODE = Ci.nsIDOMNode.TEXT_NODE; -ChromeUtils.import("resource://services-common/utils.js"); +ChromeUtils.import("resource://services-common/async.js"); /** * This class represents a document that is being translated, @@ -208,14 +208,10 @@ this.TranslationDocument.prototype = { // Let the event loop breath on every 100 nodes // that are replaced. const YIELD_INTERVAL = 100; - let count = YIELD_INTERVAL; - + let maybeYield = Async.jankYielder(YIELD_INTERVAL); for (let root of this.roots) { root.swapText(target); - if (count-- == 0) { - count = YIELD_INTERVAL; - await CommonUtils.laterTickResolvingPromise(); - } + await maybeYield(); } })(); } diff --git a/browser/components/translation/YandexTranslator.jsm b/browser/components/translation/YandexTranslator.jsm index 3476e84ec05d..81e56ad6d8e5 100644 --- a/browser/components/translation/YandexTranslator.jsm +++ b/browser/components/translation/YandexTranslator.jsm @@ -9,7 +9,7 @@ this.EXPORTED_SYMBOLS = [ "YandexTranslator" ]; ChromeUtils.import("resource://gre/modules/Services.jsm"); ChromeUtils.import("resource://gre/modules/Log.jsm"); ChromeUtils.import("resource://gre/modules/PromiseUtils.jsm"); -ChromeUtils.import("resource://services-common/utils.js"); +ChromeUtils.import("resource://services-common/async.js"); ChromeUtils.import("resource://gre/modules/Http.jsm"); Cu.importGlobalProperties(["XMLHttpRequest"]); @@ -87,7 +87,7 @@ this.YandexTranslator.prototype = { // let's take the opportunity of the chunkification process to // allow for the event loop to attend other pending events // before we continue. - await CommonUtils.laterTickResolvingPromise(); + await Async.promiseYield(); // Determine the data for the next request. let request = this._generateNextTranslationRequest(currentIndex); diff --git a/browser/extensions/pdfjs/README.mozilla b/browser/extensions/pdfjs/README.mozilla index 0c622545d09d..43adcc332743 100644 --- a/browser/extensions/pdfjs/README.mozilla +++ b/browser/extensions/pdfjs/README.mozilla @@ -1,5 +1,5 @@ This is the PDF.js project output, https://github.com/mozilla/pdf.js -Current extension version is: 2.0.332 +Current extension version is: 2.0.385 -Taken from upstream commit: 6b7e2cbc +Taken from upstream commit: 99060e24 diff --git a/browser/extensions/pdfjs/content/PdfJs.jsm b/browser/extensions/pdfjs/content/PdfJs.jsm index 18f8f0766a81..1a3ef5a1267b 100644 --- a/browser/extensions/pdfjs/content/PdfJs.jsm +++ b/browser/extensions/pdfjs/content/PdfJs.jsm @@ -81,7 +81,6 @@ function initializeDefaultPreferences() { "showPreviousViewOnLoad": true, "defaultZoomValue": "", "sidebarViewOnLoad": 0, - "enableHandToolOnLoad": false, "cursorToolOnLoad": 0, "enableWebGL": false, "pdfBugEnabled": false, @@ -89,10 +88,9 @@ function initializeDefaultPreferences() { "disableStream": false, "disableAutoFetch": false, "disableFontFace": false, - "disableTextLayer": false, + "textLayerMode": 1, "useOnlyCssZoom": false, "externalLinkTarget": 0, - "enhanceTextSelection": false, "renderer": "canvas", "renderInteractiveForms": false, "enablePrintAutoRotate": false, diff --git a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm index 6457466a1f2e..8a10fe0677e0 100644 --- a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm +++ b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm @@ -108,7 +108,7 @@ function getDOMWindow(aChannel) { var requestor = aChannel.notificationCallbacks ? aChannel.notificationCallbacks : aChannel.loadGroup.notificationCallbacks; - var win = requestor.getInterface(Components.interfaces.nsIDOMWindow); + var win = requestor.getInterface(Ci.nsIDOMWindow); return win; } diff --git a/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm b/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm index aebfc418a7d3..264a9031b0db 100644 --- a/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm +++ b/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm @@ -34,7 +34,6 @@ var DEFAULT_PREFERENCES = "showPreviousViewOnLoad": true, "defaultZoomValue": "", "sidebarViewOnLoad": 0, - "enableHandToolOnLoad": false, "cursorToolOnLoad": 0, "enableWebGL": false, "pdfBugEnabled": false, @@ -42,10 +41,9 @@ var DEFAULT_PREFERENCES = "disableStream": false, "disableAutoFetch": false, "disableFontFace": false, - "disableTextLayer": false, + "textLayerMode": 1, "useOnlyCssZoom": false, "externalLinkTarget": 0, - "enhanceTextSelection": false, "renderer": "canvas", "renderInteractiveForms": false, "enablePrintAutoRotate": false, diff --git a/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm b/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm index 6250eebee91f..71c797fd2289 100644 --- a/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm +++ b/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm @@ -17,7 +17,6 @@ var EXPORTED_SYMBOLS = ["PdfjsContentUtils"]; -ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); ChromeUtils.import("resource://gre/modules/Services.jsm"); var PdfjsContentUtils = { diff --git a/browser/extensions/pdfjs/content/build/pdf.js b/browser/extensions/pdfjs/content/build/pdf.js index 760eb62a19e4..b6097a619b53 100644 --- a/browser/extensions/pdfjs/content/build/pdf.js +++ b/browser/extensions/pdfjs/content/build/pdf.js @@ -92,7 +92,7 @@ return /******/ (function(modules) { // webpackBootstrap /******/ __w_pdfjs_require__.p = ""; /******/ /******/ // Load entry module and return exports -/******/ return __w_pdfjs_require__(__w_pdfjs_require__.s = 8); +/******/ return __w_pdfjs_require__(__w_pdfjs_require__.s = 9); /******/ }) /************************************************************************/ /******/ ([ @@ -105,11 +105,11 @@ return /******/ (function(modules) { // webpackBootstrap Object.defineProperty(exports, "__esModule", { value: true }); -exports.unreachable = exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.ReadableStream = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.loadJpegStream = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isSpace = exports.isString = exports.isNum = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.info = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.createBlob = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.FormatError = exports.XRefParseException = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PasswordResponses = exports.PasswordException = exports.PageViewport = exports.NotImplementedException = exports.NativeImageDecoding = exports.MissingPDFException = exports.MissingDataException = exports.MessageHandler = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VERBOSITY_LEVELS = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined; +exports.unreachable = exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.ReadableStream = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isSpace = exports.isString = exports.isNum = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.info = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.createBlob = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.FormatError = exports.XRefParseException = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PasswordResponses = exports.PasswordException = exports.PageViewport = exports.NotImplementedException = exports.NativeImageDecoding = exports.MissingPDFException = exports.MissingDataException = exports.MessageHandler = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VerbosityLevel = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined; -__w_pdfjs_require__(9); +__w_pdfjs_require__(10); -var _streams_polyfill = __w_pdfjs_require__(10); +var _streams_polyfill = __w_pdfjs_require__(11); var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; const NativeImageDecoding = { @@ -227,10 +227,10 @@ var FontType = { TYPE0: 9, MMTYPE1: 10 }; -var VERBOSITY_LEVELS = { - errors: 0, - warnings: 1, - infos: 5 +const VerbosityLevel = { + ERRORS: 0, + WARNINGS: 1, + INFOS: 5 }; var CMapCompressionType = { NONE: 0, @@ -330,20 +330,22 @@ var OPS = { paintSolidColorImageMask: 90, constructPath: 91 }; -var verbosity = VERBOSITY_LEVELS.warnings; +let verbosity = VerbosityLevel.WARNINGS; function setVerbosityLevel(level) { - verbosity = level; + if (Number.isInteger(level)) { + verbosity = level; + } } function getVerbosityLevel() { return verbosity; } function info(msg) { - if (verbosity >= VERBOSITY_LEVELS.infos) { + if (verbosity >= VerbosityLevel.INFOS) { console.log('Info: ' + msg); } } function warn(msg) { - if (verbosity >= VERBOSITY_LEVELS.warnings) { + if (verbosity >= VerbosityLevel.WARNINGS) { console.log('Warning: ' + msg); } } @@ -1310,21 +1312,10 @@ MessageHandler.prototype = { this.comObj.removeEventListener('message', this._onComObjOnMessage); } }; -function loadJpegStream(id, imageUrl, objs) { - var img = new Image(); - img.onload = function loadJpegStream_onloadClosure() { - objs.resolve(id, img); - }; - img.onerror = function loadJpegStream_onerrorClosure() { - objs.resolve(id, null); - warn('Error during JPEG image loading'); - }; - img.src = imageUrl; -} exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX; exports.IDENTITY_MATRIX = IDENTITY_MATRIX; exports.OPS = OPS; -exports.VERBOSITY_LEVELS = VERBOSITY_LEVELS; +exports.VerbosityLevel = VerbosityLevel; exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES; exports.AnnotationBorderStyleType = AnnotationBorderStyleType; exports.AnnotationFieldFlag = AnnotationFieldFlag; @@ -1371,7 +1362,6 @@ exports.isSameOrigin = isSameOrigin; exports.createValidAbsoluteUrl = createValidAbsoluteUrl; exports.isLittleEndian = isLittleEndian; exports.isEvalSupported = isEvalSupported; -exports.loadJpegStream = loadJpegStream; exports.log2 = log2; exports.readInt8 = readInt8; exports.readUint16 = readUint16; @@ -1398,7 +1388,7 @@ exports.unreachable = unreachable; Object.defineProperty(exports, "__esModule", { value: true }); -exports.DummyStatTimer = exports.StatTimer = exports.SimpleXMLParser = exports.DOMSVGFactory = exports.DOMCMapReaderFactory = exports.DOMCanvasFactory = exports.DEFAULT_LINK_REL = exports.getDefaultSetting = exports.LinkTarget = exports.getFilenameFromUrl = exports.isExternalLinkTargetSet = exports.addLinkAttributes = exports.RenderingCancelledException = undefined; +exports.DummyStatTimer = exports.StatTimer = exports.SimpleXMLParser = exports.DOMSVGFactory = exports.DOMCMapReaderFactory = exports.DOMCanvasFactory = exports.DEFAULT_LINK_REL = exports.getDefaultSetting = exports.LinkTarget = exports.getFilenameFromUrl = exports.addLinkAttributes = exports.RenderingCancelledException = undefined; var _util = __w_pdfjs_require__(0); @@ -1615,28 +1605,21 @@ var RenderingCancelledException = function RenderingCancelledException() { RenderingCancelledException.constructor = RenderingCancelledException; return RenderingCancelledException; }(); -var LinkTarget = { +const LinkTarget = { NONE: 0, SELF: 1, BLANK: 2, PARENT: 3, TOP: 4 }; -var LinkTargetStringMap = ['', '_self', '_blank', '_parent', '_top']; -function addLinkAttributes(link, params) { - var url = params && params.url; +const LinkTargetStringMap = ['', '_self', '_blank', '_parent', '_top']; +function addLinkAttributes(link, { url, target, rel } = {}) { link.href = link.title = url ? (0, _util.removeNullCharacters)(url) : ''; if (url) { - var target = params.target; - if (typeof target === 'undefined') { - target = getDefaultSetting('externalLinkTarget'); - } - link.target = LinkTargetStringMap[target]; - var rel = params.rel; - if (typeof rel === 'undefined') { - rel = getDefaultSetting('externalLinkRel'); - } - link.rel = rel; + const LinkTargetValues = Object.values(LinkTarget); + let targetIndex = LinkTargetValues.includes(target) ? target : LinkTarget.NONE; + link.target = LinkTargetStringMap[targetIndex]; + link.rel = typeof rel === 'string' ? rel : DEFAULT_LINK_REL; } } function getFilenameFromUrl(url) { @@ -1660,59 +1643,18 @@ function getDefaultSetting(id) { return globalSettings ? globalSettings.disableFontFace : false; case 'disableCreateObjectURL': return globalSettings ? globalSettings.disableCreateObjectURL : false; - case 'disableWebGL': - return globalSettings ? globalSettings.disableWebGL : true; case 'cMapUrl': return globalSettings ? globalSettings.cMapUrl : null; case 'cMapPacked': return globalSettings ? globalSettings.cMapPacked : false; - case 'postMessageTransfers': - return globalSettings ? globalSettings.postMessageTransfers : true; - case 'workerPort': - return globalSettings ? globalSettings.workerPort : null; - case 'workerSrc': - return globalSettings ? globalSettings.workerSrc : null; case 'maxImageSize': return globalSettings ? globalSettings.maxImageSize : -1; - case 'imageResourcesPath': - return globalSettings ? globalSettings.imageResourcesPath : ''; case 'isEvalSupported': return globalSettings ? globalSettings.isEvalSupported : true; - case 'externalLinkTarget': - if (!globalSettings) { - return LinkTarget.NONE; - } - switch (globalSettings.externalLinkTarget) { - case LinkTarget.NONE: - case LinkTarget.SELF: - case LinkTarget.BLANK: - case LinkTarget.PARENT: - case LinkTarget.TOP: - return globalSettings.externalLinkTarget; - } - (0, _util.warn)('PDFJS.externalLinkTarget is invalid: ' + globalSettings.externalLinkTarget); - globalSettings.externalLinkTarget = LinkTarget.NONE; - return LinkTarget.NONE; - case 'externalLinkRel': - return globalSettings ? globalSettings.externalLinkRel : DEFAULT_LINK_REL; - case 'enableStats': - return !!(globalSettings && globalSettings.enableStats); default: throw new Error('Unknown default setting: ' + id); } } -function isExternalLinkTargetSet() { - var externalLinkTarget = getDefaultSetting('externalLinkTarget'); - switch (externalLinkTarget) { - case LinkTarget.NONE: - return false; - case LinkTarget.SELF: - case LinkTarget.BLANK: - case LinkTarget.PARENT: - case LinkTarget.TOP: - return true; - } -} class StatTimer { constructor(enable = true) { this.enabled = !!enable; @@ -1772,7 +1714,6 @@ class DummyStatTimer { } exports.RenderingCancelledException = RenderingCancelledException; exports.addLinkAttributes = addLinkAttributes; -exports.isExternalLinkTargetSet = isExternalLinkTargetSet; exports.getFilenameFromUrl = getFilenameFromUrl; exports.LinkTarget = LinkTarget; exports.getDefaultSetting = getDefaultSetting; @@ -1800,6 +1741,21 @@ module.exports = typeof window !== 'undefined' && window.Math === Math ? window "use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +const GlobalWorkerOptions = Object.create(null); +GlobalWorkerOptions.workerPort = GlobalWorkerOptions.workerPort === undefined ? null : GlobalWorkerOptions.workerPort; +GlobalWorkerOptions.workerSrc = GlobalWorkerOptions.workerSrc === undefined ? '' : GlobalWorkerOptions.workerSrc; +exports.GlobalWorkerOptions = GlobalWorkerOptions; + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __w_pdfjs_require__) { + +"use strict"; + + Object.defineProperty(exports, "__esModule", { value: true }); @@ -1809,27 +1765,28 @@ var _util = __w_pdfjs_require__(0); var _dom_utils = __w_pdfjs_require__(1); -var _font_loader = __w_pdfjs_require__(13); +var _font_loader = __w_pdfjs_require__(14); -var _canvas = __w_pdfjs_require__(14); +var _canvas = __w_pdfjs_require__(15); var _global_scope = __w_pdfjs_require__(2); var _global_scope2 = _interopRequireDefault(_global_scope); -var _metadata = __w_pdfjs_require__(4); +var _worker_options = __w_pdfjs_require__(3); -var _transport_stream = __w_pdfjs_require__(16); +var _metadata = __w_pdfjs_require__(5); -var _webgl = __w_pdfjs_require__(17); +var _transport_stream = __w_pdfjs_require__(17); + +var _webgl = __w_pdfjs_require__(18); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var DEFAULT_RANGE_CHUNK_SIZE = 65536; -var isWorkerDisabled = false; -var workerSrc; -var isPostMessageTransfersDisabled = false; -var pdfjsFilePath = null; +let isWorkerDisabled = false; +let workerSrc; +const pdfjsFilePath = null; var fakeWorkerFilesLoader = null; var useRequireEnsure = false; ; @@ -1857,7 +1814,7 @@ function getDocument(src) { } var params = {}; var rangeTransport = null; - var worker = null; + let worker = null; var CMapReaderFactory = _dom_utils.DOMCMapReaderFactory; for (var key in source) { if (key === 'url' && typeof window !== 'undefined') { @@ -1893,9 +1850,19 @@ function getDocument(src) { if (params.nativeImageDecoderSupport === undefined || !nativeImageDecoderValues.includes(params.nativeImageDecoderSupport)) { params.nativeImageDecoderSupport = _util.NativeImageDecoding.DECODE; } + (0, _util.setVerbosityLevel)(params.verbosity); if (!worker) { - var workerPort = (0, _dom_utils.getDefaultSetting)('workerPort'); - worker = workerPort ? PDFWorker.fromPort(workerPort) : new PDFWorker(); + const workerParams = { + postMessageTransfers: params.postMessageTransfers, + verbosity: params.verbosity + }; + let workerPort = _worker_options.GlobalWorkerOptions.workerPort; + if (workerPort) { + workerParams.port = workerPort; + worker = PDFWorker.fromPort(workerParams); + } else { + worker = new PDFWorker(workerParams); + } task._worker = worker; } var docId = task.docId; @@ -1926,7 +1893,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { if (worker.destroyed) { return Promise.reject(new Error('Worker was destroyed')); } - let apiVersion = '2.0.332'; + let apiVersion = '2.0.385'; source.disableRange = (0, _dom_utils.getDefaultSetting)('disableRange'); source.disableAutoFetch = (0, _dom_utils.getDefaultSetting)('disableAutoFetch'); source.disableStream = (0, _dom_utils.getDefaultSetting)('disableStream'); @@ -1948,7 +1915,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { maxImageSize: (0, _dom_utils.getDefaultSetting)('maxImageSize'), disableFontFace: (0, _dom_utils.getDefaultSetting)('disableFontFace'), disableCreateObjectURL: (0, _dom_utils.getDefaultSetting)('disableCreateObjectURL'), - postMessageTransfers: (0, _dom_utils.getDefaultSetting)('postMessageTransfers') && !isPostMessageTransfersDisabled, + postMessageTransfers: worker.postMessageTransfers, docBaseUrl: source.docBaseUrl, nativeImageDecoderSupport: source.nativeImageDecoderSupport, ignoreErrors: source.ignoreErrors, @@ -2110,7 +2077,7 @@ var PDFPageProxy = function PDFPageProxyClosure() { this.pageIndex = pageIndex; this.pageInfo = pageInfo; this.transport = transport; - this._stats = (0, _dom_utils.getDefaultSetting)('enableStats') ? new _dom_utils.StatTimer() : _dom_utils.DummyStatTimer; + this._stats = (0, _dom_utils.getDefaultSetting)('pdfBug') ? new _dom_utils.StatTimer() : _dom_utils.DummyStatTimer; this.commonObjs = transport.commonObjs; this.objs = new PDFObjects(); this.cleanupAfterRender = false; @@ -2151,7 +2118,7 @@ var PDFPageProxy = function PDFPageProxyClosure() { this.pendingCleanup = false; var renderingIntent = params.intent === 'print' ? 'print' : 'display'; var canvasFactory = params.canvasFactory || new _dom_utils.DOMCanvasFactory(); - let webGLContext = new _webgl.WebGLContext({ enable: !(0, _dom_utils.getDefaultSetting)('disableWebGL') }); + let webGLContext = new _webgl.WebGLContext({ enable: params.enableWebGL }); if (!this.intentStates[renderingIntent]) { this.intentStates[renderingIntent] = Object.create(null); } @@ -2417,13 +2384,13 @@ class LoopbackPort { var PDFWorker = function PDFWorkerClosure() { let nextFakeWorkerId = 0; function getWorkerSrc() { + if (_worker_options.GlobalWorkerOptions.workerSrc) { + return _worker_options.GlobalWorkerOptions.workerSrc; + } if (typeof workerSrc !== 'undefined') { return workerSrc; } - if ((0, _dom_utils.getDefaultSetting)('workerSrc')) { - return (0, _dom_utils.getDefaultSetting)('workerSrc'); - } - throw new Error('No PDFJS.workerSrc specified'); + throw new Error('No "GlobalWorkerOptions.workerSrc" specified.'); } function getMainThreadWorkerMessageHandler() { if (typeof window === 'undefined') { @@ -2455,13 +2422,14 @@ var PDFWorker = function PDFWorkerClosure() { return URL.createObjectURL(new Blob([wrapper])); } let pdfWorkerPorts = new WeakMap(); - function PDFWorker(name, port) { + function PDFWorker({ name = null, port = null, postMessageTransfers = true, verbosity = null } = {}) { if (port && pdfWorkerPorts.has(port)) { throw new Error('Cannot use more than one PDFWorker per port'); } this.name = name; this.destroyed = false; - this.postMessageTransfers = true; + this.postMessageTransfers = postMessageTransfers !== false; + this.verbosity = (0, _util.isNum)(verbosity) ? verbosity : (0, _util.getVerbosityLevel)(); this._readyCapability = (0, _util.createPromiseCapability)(); this._port = null; this._webWorker = null; @@ -2524,10 +2492,9 @@ var PDFWorker = function PDFWorkerClosure() { this._webWorker = worker; if (!data.supportTransfers) { this.postMessageTransfers = false; - isPostMessageTransfersDisabled = true; } this._readyCapability.resolve(); - messageHandler.send('configure', { verbosity: (0, _util.getVerbosityLevel)() }); + messageHandler.send('configure', { verbosity: this.verbosity }); } else { this._setupFakeWorker(); messageHandler.destroy(); @@ -2546,9 +2513,8 @@ var PDFWorker = function PDFWorkerClosure() { this._setupFakeWorker(); } }); - var sendTest = function () { - var postMessageTransfers = (0, _dom_utils.getDefaultSetting)('postMessageTransfers') && !isPostMessageTransfersDisabled; - var testObj = new Uint8Array([postMessageTransfers ? 255 : 0]); + const sendTest = () => { + let testObj = new Uint8Array([this.postMessageTransfers ? 255 : 0]); try { messageHandler.send('test', testObj, [testObj.buffer]); } catch (ex) { @@ -2600,11 +2566,11 @@ var PDFWorker = function PDFWorkerClosure() { } } }; - PDFWorker.fromPort = function (port) { - if (pdfWorkerPorts.has(port)) { - return pdfWorkerPorts.get(port); + PDFWorker.fromPort = function (params) { + if (pdfWorkerPorts.has(params.port)) { + return pdfWorkerPorts.get(params.port); } - return new PDFWorker(null, port); + return new PDFWorker(params); }; PDFWorker.getWorkerSrc = function () { return getWorkerSrc(); @@ -2852,8 +2818,18 @@ var WorkerTransport = function WorkerTransportClosure() { switch (type) { case 'JpegStream': imageData = data[3]; - (0, _util.loadJpegStream)(id, imageData, pageProxy.objs); - break; + return new Promise((resolve, reject) => { + const img = new Image(); + img.onload = function () { + resolve(img); + }; + img.onerror = function () { + reject(new Error('Error during JPEG image loading')); + }; + img.src = imageData; + }).then(img => { + pageProxy.objs.resolve(id, img); + }); case 'Image': imageData = data[3]; pageProxy.objs.resolve(id, imageData); @@ -3234,8 +3210,8 @@ var InternalRenderTask = function InternalRenderTaskClosure() { }(); var version, build; { - exports.version = version = '2.0.332'; - exports.build = build = '6b7e2cbc'; + exports.version = version = '2.0.385'; + exports.build = build = '99060e24'; } exports.getDocument = getDocument; exports.LoopbackPort = LoopbackPort; @@ -3248,7 +3224,7 @@ exports.version = version; exports.build = build; /***/ }), -/* 4 */ +/* 5 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -3343,7 +3319,7 @@ class Metadata { exports.Metadata = Metadata; /***/ }), -/* 5 */ +/* 6 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -3511,16 +3487,18 @@ class LinkAnnotationElement extends AnnotationElement { } render() { this.container.className = 'linkAnnotation'; + let { data, linkService } = this; let link = document.createElement('a'); (0, _dom_utils.addLinkAttributes)(link, { - url: this.data.url, - target: this.data.newWindow ? _dom_utils.LinkTarget.BLANK : undefined + url: data.url, + target: data.newWindow ? _dom_utils.LinkTarget.BLANK : linkService.externalLinkTarget, + rel: linkService.externalLinkRel }); - if (!this.data.url) { - if (this.data.action) { - this._bindNamedAction(link, this.data.action); + if (!data.url) { + if (data.action) { + this._bindNamedAction(link, data.action); } else { - this._bindLink(link, this.data.dest); + this._bindLink(link, data.dest); } } this.container.appendChild(link); @@ -4033,7 +4011,7 @@ class AnnotationLayer { viewport: parameters.viewport, linkService: parameters.linkService, downloadManager: parameters.downloadManager, - imageResourcesPath: parameters.imageResourcesPath || (0, _dom_utils.getDefaultSetting)('imageResourcesPath'), + imageResourcesPath: parameters.imageResourcesPath || '', renderInteractiveForms: parameters.renderInteractiveForms || false, svgFactory: new _dom_utils.DOMSVGFactory() }); @@ -4056,7 +4034,7 @@ class AnnotationLayer { exports.AnnotationLayer = AnnotationLayer; /***/ }), -/* 6 */ +/* 7 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -4594,7 +4572,7 @@ var renderTextLayer = function renderTextLayerClosure() { exports.renderTextLayer = renderTextLayer; /***/ }), -/* 7 */ +/* 8 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -4609,7 +4587,7 @@ var _util = __w_pdfjs_require__(0); var _dom_utils = __w_pdfjs_require__(1); -var _is_node = __w_pdfjs_require__(18); +var _is_node = __w_pdfjs_require__(19); var _is_node2 = _interopRequireDefault(_is_node); @@ -4622,21 +4600,22 @@ var SVGGraphics = function () { exports.SVGGraphics = SVGGraphics; /***/ }), -/* 8 */ +/* 9 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; -var pdfjsVersion = '2.0.332'; -var pdfjsBuild = '6b7e2cbc'; +var pdfjsVersion = '2.0.385'; +var pdfjsBuild = '99060e24'; var pdfjsSharedUtil = __w_pdfjs_require__(0); -var pdfjsDisplayGlobal = __w_pdfjs_require__(12); -var pdfjsDisplayAPI = __w_pdfjs_require__(3); -var pdfjsDisplayTextLayer = __w_pdfjs_require__(6); -var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(5); +var pdfjsDisplayGlobal = __w_pdfjs_require__(13); +var pdfjsDisplayAPI = __w_pdfjs_require__(4); +var pdfjsDisplayTextLayer = __w_pdfjs_require__(7); +var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(6); var pdfjsDisplayDOMUtils = __w_pdfjs_require__(1); -var pdfjsDisplaySVG = __w_pdfjs_require__(7); +var pdfjsDisplaySVG = __w_pdfjs_require__(8); +let pdfjsDisplayWorkerOptions = __w_pdfjs_require__(3); ; exports.PDFJS = pdfjsDisplayGlobal.PDFJS; exports.build = pdfjsDisplayAPI.build; @@ -4655,6 +4634,7 @@ exports.SVGGraphics = pdfjsDisplaySVG.SVGGraphics; exports.NativeImageDecoding = pdfjsSharedUtil.NativeImageDecoding; exports.UnexpectedResponseException = pdfjsSharedUtil.UnexpectedResponseException; exports.OPS = pdfjsSharedUtil.OPS; +exports.VerbosityLevel = pdfjsSharedUtil.VerbosityLevel; exports.UNSUPPORTED_FEATURES = pdfjsSharedUtil.UNSUPPORTED_FEATURES; exports.createValidAbsoluteUrl = pdfjsSharedUtil.createValidAbsoluteUrl; exports.createObjectURL = pdfjsSharedUtil.createObjectURL; @@ -4663,10 +4643,12 @@ exports.shadow = pdfjsSharedUtil.shadow; exports.createBlob = pdfjsSharedUtil.createBlob; exports.RenderingCancelledException = pdfjsDisplayDOMUtils.RenderingCancelledException; exports.getFilenameFromUrl = pdfjsDisplayDOMUtils.getFilenameFromUrl; +exports.LinkTarget = pdfjsDisplayDOMUtils.LinkTarget; exports.addLinkAttributes = pdfjsDisplayDOMUtils.addLinkAttributes; +exports.GlobalWorkerOptions = pdfjsDisplayWorkerOptions.GlobalWorkerOptions; /***/ }), -/* 9 */ +/* 10 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -4675,7 +4657,7 @@ exports.addLinkAttributes = pdfjsDisplayDOMUtils.addLinkAttributes; ; /***/ }), -/* 10 */ +/* 11 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -4695,11 +4677,11 @@ if (typeof ReadableStream !== 'undefined') { if (isReadableStreamSupported) { exports.ReadableStream = ReadableStream; } else { - exports.ReadableStream = __w_pdfjs_require__(11).ReadableStream; + exports.ReadableStream = __w_pdfjs_require__(12).ReadableStream; } /***/ }), -/* 11 */ +/* 12 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -7715,7 +7697,7 @@ if (isReadableStreamSupported) { }])); /***/ }), -/* 12 */ +/* 13 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -7726,23 +7708,25 @@ Object.defineProperty(exports, "__esModule", { }); exports.PDFJS = exports.globalScope = undefined; -var _dom_utils = __w_pdfjs_require__(1); - var _util = __w_pdfjs_require__(0); -var _api = __w_pdfjs_require__(3); +var _dom_utils = __w_pdfjs_require__(1); -var _annotation_layer = __w_pdfjs_require__(5); +var _api = __w_pdfjs_require__(4); + +var _annotation_layer = __w_pdfjs_require__(6); var _global_scope = __w_pdfjs_require__(2); var _global_scope2 = _interopRequireDefault(_global_scope); -var _metadata = __w_pdfjs_require__(4); +var _worker_options = __w_pdfjs_require__(3); -var _text_layer = __w_pdfjs_require__(6); +var _metadata = __w_pdfjs_require__(5); -var _svg = __w_pdfjs_require__(7); +var _text_layer = __w_pdfjs_require__(7); + +var _svg = __w_pdfjs_require__(8); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -7750,29 +7734,9 @@ if (!_global_scope2.default.PDFJS) { _global_scope2.default.PDFJS = {}; } var PDFJS = _global_scope2.default.PDFJS; -{ - PDFJS.version = '2.0.332'; - PDFJS.build = '6b7e2cbc'; -} PDFJS.pdfBug = false; -if (PDFJS.verbosity !== undefined) { - (0, _util.setVerbosityLevel)(PDFJS.verbosity); -} -delete PDFJS.verbosity; -Object.defineProperty(PDFJS, 'verbosity', { - get() { - return (0, _util.getVerbosityLevel)(); - }, - set(level) { - (0, _util.setVerbosityLevel)(level); - }, - enumerable: true, - configurable: true -}); -PDFJS.VERBOSITY_LEVELS = _util.VERBOSITY_LEVELS; PDFJS.OPS = _util.OPS; PDFJS.UNSUPPORTED_FEATURES = _util.UNSUPPORTED_FEATURES; -PDFJS.isValidUrl = _dom_utils.isValidUrl; PDFJS.shadow = _util.shadow; PDFJS.createBlob = _util.createBlob; PDFJS.createObjectURL = function PDFJS_createObjectURL(data, contentType) { @@ -7798,16 +7762,11 @@ PDFJS.maxImageSize = PDFJS.maxImageSize === undefined ? -1 : PDFJS.maxImageSize; PDFJS.cMapUrl = PDFJS.cMapUrl === undefined ? null : PDFJS.cMapUrl; PDFJS.cMapPacked = PDFJS.cMapPacked === undefined ? false : PDFJS.cMapPacked; PDFJS.disableFontFace = PDFJS.disableFontFace === undefined ? false : PDFJS.disableFontFace; -PDFJS.imageResourcesPath = PDFJS.imageResourcesPath === undefined ? '' : PDFJS.imageResourcesPath; -PDFJS.workerSrc = PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc; -PDFJS.workerPort = PDFJS.workerPort === undefined ? null : PDFJS.workerPort; PDFJS.disableRange = PDFJS.disableRange === undefined ? false : PDFJS.disableRange; PDFJS.disableStream = PDFJS.disableStream === undefined ? false : PDFJS.disableStream; PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ? false : PDFJS.disableAutoFetch; PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug; -PDFJS.postMessageTransfers = PDFJS.postMessageTransfers === undefined ? true : PDFJS.postMessageTransfers; PDFJS.disableCreateObjectURL = PDFJS.disableCreateObjectURL === undefined ? false : PDFJS.disableCreateObjectURL; -PDFJS.disableWebGL = PDFJS.disableWebGL === undefined ? true : PDFJS.disableWebGL; PDFJS.externalLinkTarget = PDFJS.externalLinkTarget === undefined ? _dom_utils.LinkTarget.NONE : PDFJS.externalLinkTarget; PDFJS.externalLinkRel = PDFJS.externalLinkRel === undefined ? _dom_utils.DEFAULT_LINK_REL : PDFJS.externalLinkRel; PDFJS.isEvalSupported = PDFJS.isEvalSupported === undefined ? true : PDFJS.isEvalSupported; @@ -7815,10 +7774,8 @@ PDFJS.getDocument = _api.getDocument; PDFJS.LoopbackPort = _api.LoopbackPort; PDFJS.PDFDataRangeTransport = _api.PDFDataRangeTransport; PDFJS.PDFWorker = _api.PDFWorker; -PDFJS.LinkTarget = _dom_utils.LinkTarget; -PDFJS.addLinkAttributes = _dom_utils.addLinkAttributes; +PDFJS.GlobalWorkerOptions = _worker_options.GlobalWorkerOptions; PDFJS.getFilenameFromUrl = _dom_utils.getFilenameFromUrl; -PDFJS.isExternalLinkTargetSet = _dom_utils.isExternalLinkTargetSet; PDFJS.AnnotationLayer = _annotation_layer.AnnotationLayer; PDFJS.renderTextLayer = _text_layer.renderTextLayer; PDFJS.Metadata = _metadata.Metadata; @@ -7827,7 +7784,7 @@ exports.globalScope = _global_scope2.default; exports.PDFJS = PDFJS; /***/ }), -/* 13 */ +/* 14 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -7952,7 +7909,7 @@ exports.FontFaceObject = FontFaceObject; exports.FontLoader = FontLoader; /***/ }), -/* 14 */ +/* 15 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -7965,7 +7922,7 @@ exports.CanvasGraphics = undefined; var _util = __w_pdfjs_require__(0); -var _pattern_helper = __w_pdfjs_require__(15); +var _pattern_helper = __w_pdfjs_require__(16); var MIN_FONT_SIZE = 16; var MAX_FONT_SIZE = 100; @@ -9693,7 +9650,7 @@ var CanvasGraphics = function CanvasGraphicsClosure() { exports.CanvasGraphics = CanvasGraphics; /***/ }), -/* 15 */ +/* 16 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -10075,7 +10032,7 @@ exports.getShadingPatternFromIR = getShadingPatternFromIR; exports.TilingPattern = TilingPattern; /***/ }), -/* 16 */ +/* 17 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -10098,8 +10055,8 @@ var PDFDataTransportStream = function PDFDataTransportStreamClosure() { this._queuedChunks.push(buffer); } this._pdfDataRangeTransport = pdfDataRangeTransport; - this._isRangeSupported = !params.disableRange; this._isStreamingSupported = !params.disableStream; + this._isRangeSupported = !params.disableRange; this._contentLength = params.length; this._fullRequestReader = null; this._rangeReaders = []; @@ -10315,7 +10272,7 @@ var PDFDataTransportStream = function PDFDataTransportStreamClosure() { exports.PDFDataTransportStream = PDFDataTransportStream; /***/ }), -/* 17 */ +/* 18 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -10698,7 +10655,7 @@ var WebGLUtils = function WebGLUtilsClosure() { exports.WebGLContext = WebGLContext; /***/ }), -/* 18 */ +/* 19 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; diff --git a/browser/extensions/pdfjs/content/build/pdf.worker.js b/browser/extensions/pdfjs/content/build/pdf.worker.js index 44bbf13efa64..4f8c414370e3 100644 --- a/browser/extensions/pdfjs/content/build/pdf.worker.js +++ b/browser/extensions/pdfjs/content/build/pdf.worker.js @@ -105,7 +105,7 @@ return /******/ (function(modules) { // webpackBootstrap Object.defineProperty(exports, "__esModule", { value: true }); -exports.unreachable = exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.ReadableStream = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.loadJpegStream = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isSpace = exports.isString = exports.isNum = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.info = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.createBlob = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.FormatError = exports.XRefParseException = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PasswordResponses = exports.PasswordException = exports.PageViewport = exports.NotImplementedException = exports.NativeImageDecoding = exports.MissingPDFException = exports.MissingDataException = exports.MessageHandler = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VERBOSITY_LEVELS = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined; +exports.unreachable = exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.ReadableStream = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isSpace = exports.isString = exports.isNum = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.info = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.createBlob = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.FormatError = exports.XRefParseException = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PasswordResponses = exports.PasswordException = exports.PageViewport = exports.NotImplementedException = exports.NativeImageDecoding = exports.MissingPDFException = exports.MissingDataException = exports.MessageHandler = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VerbosityLevel = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined; __w_pdfjs_require__(21); @@ -227,10 +227,10 @@ var FontType = { TYPE0: 9, MMTYPE1: 10 }; -var VERBOSITY_LEVELS = { - errors: 0, - warnings: 1, - infos: 5 +const VerbosityLevel = { + ERRORS: 0, + WARNINGS: 1, + INFOS: 5 }; var CMapCompressionType = { NONE: 0, @@ -330,20 +330,22 @@ var OPS = { paintSolidColorImageMask: 90, constructPath: 91 }; -var verbosity = VERBOSITY_LEVELS.warnings; +let verbosity = VerbosityLevel.WARNINGS; function setVerbosityLevel(level) { - verbosity = level; + if (Number.isInteger(level)) { + verbosity = level; + } } function getVerbosityLevel() { return verbosity; } function info(msg) { - if (verbosity >= VERBOSITY_LEVELS.infos) { + if (verbosity >= VerbosityLevel.INFOS) { console.log('Info: ' + msg); } } function warn(msg) { - if (verbosity >= VERBOSITY_LEVELS.warnings) { + if (verbosity >= VerbosityLevel.WARNINGS) { console.log('Warning: ' + msg); } } @@ -1310,21 +1312,10 @@ MessageHandler.prototype = { this.comObj.removeEventListener('message', this._onComObjOnMessage); } }; -function loadJpegStream(id, imageUrl, objs) { - var img = new Image(); - img.onload = function loadJpegStream_onloadClosure() { - objs.resolve(id, img); - }; - img.onerror = function loadJpegStream_onerrorClosure() { - objs.resolve(id, null); - warn('Error during JPEG image loading'); - }; - img.src = imageUrl; -} exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX; exports.IDENTITY_MATRIX = IDENTITY_MATRIX; exports.OPS = OPS; -exports.VERBOSITY_LEVELS = VERBOSITY_LEVELS; +exports.VerbosityLevel = VerbosityLevel; exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES; exports.AnnotationBorderStyleType = AnnotationBorderStyleType; exports.AnnotationFieldFlag = AnnotationFieldFlag; @@ -1371,7 +1362,6 @@ exports.isSameOrigin = isSameOrigin; exports.createValidAbsoluteUrl = createValidAbsoluteUrl; exports.isLittleEndian = isLittleEndian; exports.isEvalSupported = isEvalSupported; -exports.loadJpegStream = loadJpegStream; exports.log2 = log2; exports.readInt8 = readInt8; exports.readUint16 = readUint16; @@ -3624,7 +3614,21 @@ var _jpeg_stream = __w_pdfjs_require__(6); var _jpx_stream = __w_pdfjs_require__(30); -var MAX_LENGTH_TO_CACHE = 1000; +const MAX_LENGTH_TO_CACHE = 1000; +const MAX_ADLER32_LENGTH = 5552; +function computeAdler32(bytes) { + let bytesLength = bytes.length; + if (bytesLength >= MAX_ADLER32_LENGTH) { + throw new Error('computeAdler32: The input is too large.'); + } + let a = 1, + b = 0; + for (let i = 0; i < bytesLength; ++i) { + a += bytes[i] & 0xFF; + b += a; + } + return b % 65521 << 16 | a % 65521; +} var Parser = function ParserClosure() { function Parser(lexer, allowStreams, xref, recoveryMode) { this.lexer = lexer; @@ -3913,7 +3917,8 @@ var Parser = function ParserClosure() { makeInlineImage: function Parser_makeInlineImage(cipherTransform) { var lexer = this.lexer; var stream = lexer.stream; - var dict = new _primitives.Dict(this.xref); + let dict = new _primitives.Dict(this.xref), + dictLength; while (!(0, _primitives.isCmd)(this.buf1, 'ID') && !(0, _primitives.isEOF)(this.buf1)) { if (!(0, _primitives.isName)(this.buf1)) { throw new _util.FormatError('Dictionary key must be a name object'); @@ -3925,6 +3930,9 @@ var Parser = function ParserClosure() { } dict.set(key, this.getObj(cipherTransform)); } + if (lexer.beginInlineImagePos !== -1) { + dictLength = stream.pos - lexer.beginInlineImagePos; + } var filter = dict.get('Filter', 'F'), filterName; if ((0, _primitives.isName)(filter)) { @@ -3935,10 +3943,8 @@ var Parser = function ParserClosure() { filterName = filterZero.name; } } - var startPos = stream.pos, - length, - i, - ii; + let startPos = stream.pos, + length; if (filterName === 'DCTDecode' || filterName === 'DCT') { length = this.findDCTDecodeInlineStreamEnd(stream); } else if (filterName === 'ASCII85Decode' || filterName === 'A85') { @@ -3949,18 +3955,16 @@ var Parser = function ParserClosure() { length = this.findDefaultInlineStreamEnd(stream); } var imageStream = stream.makeSubStream(startPos, length, dict); - var adler32; - if (length < MAX_LENGTH_TO_CACHE) { + let cacheKey; + if (length < MAX_LENGTH_TO_CACHE && dictLength < MAX_ADLER32_LENGTH) { var imageBytes = imageStream.getBytes(); imageStream.reset(); - var a = 1; - var b = 0; - for (i = 0, ii = imageBytes.length; i < ii; ++i) { - a += imageBytes[i] & 0xff; - b += a; - } - adler32 = b % 65521 << 16 | a % 65521; - let cacheEntry = this.imageCache[adler32]; + const initialStreamPos = stream.pos; + stream.pos = lexer.beginInlineImagePos; + let dictBytes = stream.getBytes(dictLength); + stream.pos = initialStreamPos; + cacheKey = computeAdler32(imageBytes) + '_' + computeAdler32(dictBytes); + let cacheEntry = this.imageCache[cacheKey]; if (cacheEntry !== undefined) { this.buf2 = _primitives.Cmd.get('EI'); this.shift(); @@ -3973,9 +3977,9 @@ var Parser = function ParserClosure() { } imageStream = this.filter(imageStream, dict, length); imageStream.dict = dict; - if (adler32 !== undefined) { - imageStream.cacheKey = 'inline_' + length + '_' + adler32; - this.imageCache[adler32] = imageStream; + if (cacheKey !== undefined) { + imageStream.cacheKey = 'inline_' + length + '_' + cacheKey; + this.imageCache[cacheKey] = imageStream; } this.buf2 = _primitives.Cmd.get('EI'); this.shift(); @@ -4148,6 +4152,7 @@ var Lexer = function LexerClosure() { this.nextChar(); this.strBuf = []; this.knownCommands = knownCommands; + this.beginInlineImagePos = -1; } var specialChars = [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; function toHexDigit(ch) { @@ -4502,6 +4507,9 @@ var Lexer = function LexerClosure() { if (str === 'null') { return null; } + if (str === 'BI') { + this.beginInlineImagePos = this.stream.pos; + } return _primitives.Cmd.get(str); }, skipToNextLine: function Lexer_skipToNextLine() { @@ -21065,8 +21073,8 @@ exports.PostScriptCompiler = PostScriptCompiler; "use strict"; -var pdfjsVersion = '2.0.332'; -var pdfjsBuild = '6b7e2cbc'; +var pdfjsVersion = '2.0.385'; +var pdfjsBuild = '99060e24'; var pdfjsCoreWorker = __w_pdfjs_require__(20); exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler; @@ -21267,7 +21275,7 @@ var WorkerMessageHandler = { var cancelXHRs = null; var WorkerTasks = []; let apiVersion = docParams.apiVersion; - let workerVersion = '2.0.332'; + let workerVersion = '2.0.385'; if (apiVersion !== null && apiVersion !== workerVersion) { throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`); } @@ -27326,6 +27334,16 @@ let JpegError = function JpegErrorClosure() { JpegError.constructor = JpegError; return JpegError; }(); +let DNLMarkerError = function DNLMarkerErrorClosure() { + function DNLMarkerError(message, scanLines) { + this.message = message; + this.scanLines = scanLines; + } + DNLMarkerError.prototype = new Error(); + DNLMarkerError.prototype.name = 'DNLMarkerError'; + DNLMarkerError.constructor = DNLMarkerError; + return DNLMarkerError; +}(); var JpegImage = function JpegImageClosure() { var dctZigZag = new Uint8Array([0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63]); var dctCos1 = 4017; @@ -27388,7 +27406,7 @@ var JpegImage = function JpegImageClosure() { function getBlockBufferOffset(component, row, col) { return 64 * ((component.blocksPerLine + 1) * row + col); } - function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive) { + function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive, parseDNLMarker = false) { var mcusPerLine = frame.mcusPerLine; var progressive = frame.progressive; var startOffset = offset, @@ -27403,6 +27421,13 @@ var JpegImage = function JpegImageClosure() { if (bitsData === 0xFF) { var nextByte = data[offset++]; if (nextByte) { + if (nextByte === 0xDC && parseDNLMarker) { + offset += 2; + const scanLines = data[offset++] << 8 | data[offset++]; + if (scanLines > 0 && scanLines !== frame.scanLines) { + throw new DNLMarkerError('Found DNL marker (0xFFDC) while parsing scan data', scanLines); + } + } throw new JpegError(`unexpected marker ${(bitsData << 8 | nextByte).toString(16)}`); } } @@ -27838,7 +27863,9 @@ var JpegImage = function JpegImageClosure() { }; } JpegImage.prototype = { - parse: function parse(data) { + parse(data, { + dnlScanLines = null + } = {}) { function readUint16() { var value = data[offset] << 8 | data[offset + 1]; offset += 2; @@ -27877,6 +27904,7 @@ var JpegImage = function JpegImageClosure() { var jfif = null; var adobe = null; var frame, resetInterval; + let numSOSMarkers = 0; var quantizationTables = []; var huffmanTablesAC = [], huffmanTablesDC = []; @@ -27967,7 +27995,8 @@ var JpegImage = function JpegImageClosure() { frame.extended = fileMarker === 0xFFC1; frame.progressive = fileMarker === 0xFFC2; frame.precision = data[offset++]; - frame.scanLines = readUint16(); + const sofScanLines = readUint16(); + frame.scanLines = dnlScanLines || sofScanLines; frame.samplesPerLine = readUint16(); frame.components = []; frame.componentIds = {}; @@ -28021,6 +28050,7 @@ var JpegImage = function JpegImageClosure() { resetInterval = readUint16(); break; case 0xFFDA: + const parseDNLMarker = ++numSOSMarkers === 1 && !dnlScanLines; readUint16(); var selectorsCount = data[offset++]; var components = [], @@ -28036,8 +28066,19 @@ var JpegImage = function JpegImageClosure() { var spectralStart = data[offset++]; var spectralEnd = data[offset++]; var successiveApproximation = data[offset++]; - var processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15); - offset += processed; + try { + var processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15, parseDNLMarker); + offset += processed; + } catch (ex) { + if (ex instanceof DNLMarkerError) { + (0, _util.warn)('Attempting to re-parse JPEG image using "scanLines" ' + 'parameter found in DNL marker (0xFFDC) segment.'); + return this.parse(data, { dnlScanLines: ex.scanLines }); + } + throw ex; + } + break; + case 0xFFDC: + offset += 4; break; case 0xFFFF: if (data[offset] !== 0xFF) { @@ -28162,7 +28203,7 @@ var JpegImage = function JpegImageClosure() { data[offset++] = 107.268039397724 + Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + 0.000659397001245577 * Y + 0.000426105652938837 * k - 0.176491792462875) + Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + 0.000770482631801132 * k - 0.151051492775562) + Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + 0.25802910206845) + k * (-0.000318913117588328 * k - 0.213742400323665); data[offset++] = -20.810012546947 + Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + 0.0020741088115012 * Y - 0.00288260236853442 * k + 0.814272968359295) + Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + 0.000560833691242812 * k - 0.195152027534049) + Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + 0.116935020465145) + k * (-0.000343531996510555 * k + 0.24165260232407); } - return data; + return data.subarray(0, offset); }, _convertYcckToCmyk: function convertYcckToCmyk(data) { var Y, Cb, Cr; @@ -28189,7 +28230,7 @@ var JpegImage = function JpegImageClosure() { data[offset++] = 255 + c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k - 79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) - k * (20.737325471181034 * k + 187.80453709719578); data[offset++] = 255 + c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k - 14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k - 193.58209356861505) - k * (22.33816807309886 * k + 180.12613974708367); } - return data; + return data.subarray(0, offset); }, getData: function getData(width, height, forceRGBoutput) { if (this.numComponents > 4) { @@ -29045,10 +29086,7 @@ var PartialEvaluator = function PartialEvaluatorClosure() { var dict = image.dict; var colorSpace = dict.get('ColorSpace', 'CS'); colorSpace = _colorspace.ColorSpace.parse(colorSpace, this.xref, this.resources, this.pdfFunctionFactory); - var numComps = colorSpace.numComps; - var decodePromise = this.handler.sendWithPromise('JpegDecode', [image.getIR(this.forceDataSchema), numComps]); - return decodePromise.then(function (message) { - var data = message.data; + return this.handler.sendWithPromise('JpegDecode', [image.getIR(this.forceDataSchema), colorSpace.numComps]).then(function ({ data, width, height }) { return new _stream.Stream(data, 0, data.length, image.dict); }); } @@ -29262,18 +29300,18 @@ var PartialEvaluator = function PartialEvaluatorClosure() { } }); }, - buildPaintImageXObject: function PartialEvaluator_buildPaintImageXObject(resources, image, inline, operatorList, cacheKey, imageCache) { + buildPaintImageXObject({ resources, image, isInline = false, operatorList, cacheKey, imageCache, forceDisableNativeImageDecoder = false }) { var dict = image.dict; var w = dict.get('Width', 'W'); var h = dict.get('Height', 'H'); if (!(w && (0, _util.isNum)(w)) || !(h && (0, _util.isNum)(h))) { (0, _util.warn)('Image dimensions are missing, or not numbers.'); - return; + return Promise.resolve(); } var maxImageSize = this.options.maxImageSize; if (maxImageSize !== -1 && w * h > maxImageSize) { (0, _util.warn)('Image exceeded maximum allowed size and was removed.'); - return; + return Promise.resolve(); } var imageMask = dict.get('ImageMask', 'IM') || false; var imgData, args; @@ -29299,37 +29337,48 @@ var PartialEvaluator = function PartialEvaluatorClosure() { args }; } - return; + return Promise.resolve(); } var softMask = dict.get('SMask', 'SM') || false; var mask = dict.get('Mask') || false; var SMALL_IMAGE_DIMENSIONS = 200; - if (inline && !softMask && !mask && !(image instanceof _jpeg_stream.JpegStream) && w + h < SMALL_IMAGE_DIMENSIONS) { + if (isInline && !softMask && !mask && !(image instanceof _jpeg_stream.JpegStream) && w + h < SMALL_IMAGE_DIMENSIONS) { let imageObj = new _image.PDFImage({ xref: this.xref, res: resources, image, - isInline: inline, + isInline, pdfFunctionFactory: this.pdfFunctionFactory }); imgData = imageObj.createImageData(true); operatorList.addOp(_util.OPS.paintInlineImageXObject, [imgData]); - return; + return Promise.resolve(); } - var nativeImageDecoderSupport = this.options.nativeImageDecoderSupport; + const nativeImageDecoderSupport = forceDisableNativeImageDecoder ? _util.NativeImageDecoding.NONE : this.options.nativeImageDecoderSupport; var objId = 'img_' + this.idFactory.createObjId(); - operatorList.addDependency(objId); - args = [objId, w, h]; if (nativeImageDecoderSupport !== _util.NativeImageDecoding.NONE && !softMask && !mask && image instanceof _jpeg_stream.JpegStream && NativeImageDecoder.isSupported(image, this.xref, resources, this.pdfFunctionFactory)) { - operatorList.addOp(_util.OPS.paintJpegXObject, args); - this.handler.send('obj', [objId, this.pageIndex, 'JpegStream', image.getIR(this.options.forceDataSchema)]); - if (cacheKey) { - imageCache[cacheKey] = { - fn: _util.OPS.paintJpegXObject, - args - }; - } - return; + return this.handler.sendWithPromise('obj', [objId, this.pageIndex, 'JpegStream', image.getIR(this.options.forceDataSchema)]).then(function () { + operatorList.addDependency(objId); + args = [objId, w, h]; + operatorList.addOp(_util.OPS.paintJpegXObject, args); + if (cacheKey) { + imageCache[cacheKey] = { + fn: _util.OPS.paintJpegXObject, + args + }; + } + }, reason => { + (0, _util.warn)('Native JPEG decoding failed -- trying to recover: ' + (reason && reason.message)); + return this.buildPaintImageXObject({ + resources, + image, + isInline, + operatorList, + cacheKey, + imageCache, + forceDisableNativeImageDecoder: true + }); + }); } var nativeImageDecoder = null; if (nativeImageDecoderSupport === _util.NativeImageDecoding.DECODE && (image instanceof _jpeg_stream.JpegStream || mask instanceof _jpeg_stream.JpegStream || softMask instanceof _jpeg_stream.JpegStream)) { @@ -29341,12 +29390,14 @@ var PartialEvaluator = function PartialEvaluatorClosure() { pdfFunctionFactory: this.pdfFunctionFactory }); } + operatorList.addDependency(objId); + args = [objId, w, h]; _image.PDFImage.buildImage({ handler: this.handler, xref: this.xref, res: resources, image, - isInline: inline, + isInline, nativeDecoder: nativeImageDecoder, pdfFunctionFactory: this.pdfFunctionFactory }).then(imageObj => { @@ -29363,6 +29414,7 @@ var PartialEvaluator = function PartialEvaluatorClosure() { args }; } + return Promise.resolve(); }, handleSMask: function PartialEvaluator_handleSmask(smask, resources, operatorList, task, stateManager) { var smaskContent = smask.get('G'); @@ -29736,7 +29788,14 @@ var PartialEvaluator = function PartialEvaluatorClosure() { }, rejectXObject); return; } else if (type.name === 'Image') { - self.buildPaintImageXObject(resources, xobj, false, operatorList, name, imageCache); + self.buildPaintImageXObject({ + resources, + image: xobj, + operatorList, + cacheKey: name, + imageCache + }).then(resolveXObject, rejectXObject); + return; } else if (type.name === 'PS') { (0, _util.info)('Ignored XObject subtype PS'); } else { @@ -29769,9 +29828,15 @@ var PartialEvaluator = function PartialEvaluatorClosure() { continue; } } - self.buildPaintImageXObject(resources, args[0], true, operatorList, cacheKey, imageCache); - args = null; - continue; + next(self.buildPaintImageXObject({ + resources, + image: args[0], + isInline: true, + operatorList, + cacheKey, + imageCache + })); + return; case _util.OPS.showText: args[0] = self.handleText(args[0], stateManager.state); break; @@ -34108,7 +34173,7 @@ var Font = function FontClosure() { } font.pos += 4; maxFunctionDefs = font.getUint16(); - font.pos += 6; + font.pos += 4; maxSizeOfInstructions = font.getUint16(); } var dupFirstEntry = false; @@ -40561,7 +40626,10 @@ var _jpx = __w_pdfjs_require__(13); var PDFImage = function PDFImageClosure() { function handleImageData(image, nativeDecoder) { if (nativeDecoder && nativeDecoder.canDecode(image)) { - return nativeDecoder.decode(image); + return nativeDecoder.decode(image).catch(reason => { + (0, _util.warn)('Native image decoding failed -- trying to recover: ' + (reason && reason.message)); + return image; + }); } return Promise.resolve(image); } diff --git a/browser/extensions/pdfjs/content/web/debugger.js b/browser/extensions/pdfjs/content/web/debugger.js index 72e9e1e058c7..57a4ed4e4cf6 100644 --- a/browser/extensions/pdfjs/content/web/debugger.js +++ b/browser/extensions/pdfjs/content/web/debugger.js @@ -338,7 +338,7 @@ var Stepper = (function StepperClosure() { line.className = 'line'; line.dataset.idx = i; chunk.appendChild(line); - var checked = this.breakPoints.indexOf(i) !== -1; + var checked = this.breakPoints.includes(i); var args = operatorList.argsArray[i] || []; var breakCell = c('td'); @@ -462,7 +462,6 @@ var Stats = (function Stats() { manager: null, init(pdfjsLib) { this.panel.setAttribute('style', 'padding: 5px;'); - pdfjsLib.PDFJS.enableStats = true; }, enabled: false, active: false, @@ -521,7 +520,7 @@ window.PDFBug = (function PDFBugClosure() { } for (var i = 0; i < tools.length; ++i) { var tool = tools[i]; - if (all || ids.indexOf(tool.id) !== -1) { + if (all || ids.includes(tool.id)) { tool.enabled = true; } } diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-selectTool@2x.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-selectTool@2x.png index 1104cbc2ec4b..a58aaef4fbee 100644 Binary files a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-selectTool@2x.png and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-selectTool@2x.png differ diff --git a/browser/extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail@2x.png b/browser/extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail@2x.png index 958afad13342..a0208b41377f 100644 Binary files a/browser/extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail@2x.png and b/browser/extensions/pdfjs/content/web/images/toolbarButton-viewThumbnail@2x.png differ diff --git a/browser/extensions/pdfjs/content/web/images/treeitem-collapsed-rtl@2x.png b/browser/extensions/pdfjs/content/web/images/treeitem-collapsed-rtl@2x.png index 4fa5937b5de9..6ad9ebcdf5df 100644 Binary files a/browser/extensions/pdfjs/content/web/images/treeitem-collapsed-rtl@2x.png and b/browser/extensions/pdfjs/content/web/images/treeitem-collapsed-rtl@2x.png differ diff --git a/browser/extensions/pdfjs/content/web/viewer.js b/browser/extensions/pdfjs/content/web/viewer.js index 231d54880cb6..dc6a73685031 100644 --- a/browser/extensions/pdfjs/content/web/viewer.js +++ b/browser/extensions/pdfjs/content/web/viewer.js @@ -82,7 +82,7 @@ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 8); +/******/ return __webpack_require__(__webpack_require__.s = 9); /******/ }) /************************************************************************/ /******/ ([ @@ -95,7 +95,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.waitOnEventOrTimeout = exports.WaitOnType = exports.localized = exports.animationStarted = exports.normalizeWheelEventDelta = exports.binarySearchFirstItem = exports.watchScroll = exports.scrollIntoView = exports.getOutputScale = exports.approximateFraction = exports.roundToDivide = exports.getVisibleElements = exports.parseQueryString = exports.noContextMenuHandler = exports.getPDFFileNameFromURL = exports.ProgressBar = exports.EventBus = exports.NullL10n = exports.mozL10n = exports.RendererType = exports.PresentationModeState = exports.cloneObj = exports.isFileSchema = exports.isValidRotation = exports.VERTICAL_PADDING = exports.SCROLLBAR_PADDING = exports.MAX_AUTO_SCALE = exports.UNKNOWN_SCALE = exports.MAX_SCALE = exports.MIN_SCALE = exports.DEFAULT_SCALE = exports.DEFAULT_SCALE_VALUE = exports.CSS_UNITS = undefined; +exports.waitOnEventOrTimeout = exports.WaitOnType = exports.localized = exports.animationStarted = exports.normalizeWheelEventDelta = exports.binarySearchFirstItem = exports.watchScroll = exports.scrollIntoView = exports.getOutputScale = exports.approximateFraction = exports.roundToDivide = exports.getVisibleElements = exports.parseQueryString = exports.noContextMenuHandler = exports.getPDFFileNameFromURL = exports.ProgressBar = exports.EventBus = exports.NullL10n = exports.mozL10n = exports.TextLayerMode = exports.RendererType = exports.PresentationModeState = exports.cloneObj = exports.isFileSchema = exports.isValidRotation = exports.VERTICAL_PADDING = exports.SCROLLBAR_PADDING = exports.MAX_AUTO_SCALE = exports.UNKNOWN_SCALE = exports.MAX_SCALE = exports.MIN_SCALE = exports.DEFAULT_SCALE = exports.DEFAULT_SCALE_VALUE = exports.CSS_UNITS = undefined; var _pdfjsLib = __webpack_require__(1); @@ -118,6 +118,11 @@ const RendererType = { CANVAS: 'canvas', SVG: 'svg' }; +const TextLayerMode = { + DISABLE: 0, + ENABLE: 1, + ENABLE_ENHANCE: 2 +}; function formatL10nValue(text, args) { if (!args) { return text; @@ -137,11 +142,9 @@ let NullL10n = { return Promise.resolve(); } }; -_pdfjsLib.PDFJS.disableFullscreen = _pdfjsLib.PDFJS.disableFullscreen === undefined ? false : _pdfjsLib.PDFJS.disableFullscreen; _pdfjsLib.PDFJS.useOnlyCssZoom = _pdfjsLib.PDFJS.useOnlyCssZoom === undefined ? false : _pdfjsLib.PDFJS.useOnlyCssZoom; _pdfjsLib.PDFJS.maxCanvasPixels = _pdfjsLib.PDFJS.maxCanvasPixels === undefined ? 16777216 : _pdfjsLib.PDFJS.maxCanvasPixels; _pdfjsLib.PDFJS.disableHistory = _pdfjsLib.PDFJS.disableHistory === undefined ? false : _pdfjsLib.PDFJS.disableHistory; -_pdfjsLib.PDFJS.disableTextLayer = _pdfjsLib.PDFJS.disableTextLayer === undefined ? false : _pdfjsLib.PDFJS.disableTextLayer; ; function getOutputScale(ctx) { let devicePixelRatio = window.devicePixelRatio || 1; @@ -368,7 +371,7 @@ function getPDFFileNameFromURL(url, defaultFilename = 'document.pdf') { let suggestedFilename = reFilename.exec(splitURI[1]) || reFilename.exec(splitURI[2]) || reFilename.exec(splitURI[3]); if (suggestedFilename) { suggestedFilename = suggestedFilename[0]; - if (suggestedFilename.indexOf('%') !== -1) { + if (suggestedFilename.includes('%')) { try { suggestedFilename = reFilename.exec(decodeURIComponent(suggestedFilename))[0]; } catch (ex) {} @@ -544,6 +547,7 @@ exports.isFileSchema = isFileSchema; exports.cloneObj = cloneObj; exports.PresentationModeState = PresentationModeState; exports.RendererType = RendererType; +exports.TextLayerMode = TextLayerMode; exports.mozL10n = mozL10n; exports.NullL10n = NullL10n; exports.EventBus = EventBus; @@ -830,47 +834,49 @@ var _pdf_cursor_tools = __webpack_require__(6); var _pdf_rendering_queue = __webpack_require__(3); -var _pdf_sidebar = __webpack_require__(10); +var _pdf_sidebar = __webpack_require__(11); var _dom_events = __webpack_require__(2); -var _overlay_manager = __webpack_require__(11); +var _overlay_manager = __webpack_require__(12); -var _password_prompt = __webpack_require__(12); +var _password_prompt = __webpack_require__(13); -var _pdf_attachment_viewer = __webpack_require__(13); +var _pdf_attachment_viewer = __webpack_require__(14); -var _pdf_document_properties = __webpack_require__(14); +var _pdf_document_properties = __webpack_require__(15); -var _pdf_find_bar = __webpack_require__(15); +var _pdf_find_bar = __webpack_require__(16); var _pdf_find_controller = __webpack_require__(7); -var _pdf_history = __webpack_require__(16); +var _pdf_history = __webpack_require__(17); var _pdf_link_service = __webpack_require__(5); -var _pdf_outline_viewer = __webpack_require__(17); +var _pdf_outline_viewer = __webpack_require__(18); -var _pdf_presentation_mode = __webpack_require__(18); +var _pdf_presentation_mode = __webpack_require__(19); -var _pdf_sidebar_resizer = __webpack_require__(19); +var _pdf_sidebar_resizer = __webpack_require__(20); -var _pdf_thumbnail_viewer = __webpack_require__(20); +var _pdf_thumbnail_viewer = __webpack_require__(21); -var _pdf_viewer = __webpack_require__(22); +var _pdf_viewer = __webpack_require__(23); -var _secondary_toolbar = __webpack_require__(27); +var _secondary_toolbar = __webpack_require__(28); -var _toolbar = __webpack_require__(28); +var _toolbar = __webpack_require__(29); -var _view_history = __webpack_require__(29); +var _viewer_compatibility = __webpack_require__(8); + +var _view_history = __webpack_require__(30); const DEFAULT_SCALE_DELTA = 1.1; const DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000; function configure(PDFJS) { PDFJS.imageResourcesPath = './images/'; - PDFJS.workerSrc = '../build/pdf.worker.js'; + _pdfjsLib.GlobalWorkerOptions.workerSrc = '../build/pdf.worker.js'; PDFJS.cMapUrl = '../web/cmaps/'; PDFJS.cMapPacked = true; } @@ -927,6 +933,7 @@ let PDFViewerApplication = { isInitialViewSet: false, downloadComplete: false, viewerPrefs: { + enableWebGL: false, sidebarViewOnLoad: _pdf_sidebar.SidebarView.NONE, pdfBugEnabled: false, showPreviousViewOnLoad: true, @@ -934,7 +941,7 @@ let PDFViewerApplication = { disablePageMode: false, disablePageLabels: false, renderer: 'canvas', - enhanceTextSelection: false, + textLayerMode: _ui_utils.TextLayerMode.ENABLE, renderInteractiveForms: false, enablePrintAutoRotate: false }, @@ -961,8 +968,8 @@ let PDFViewerApplication = { this.l10n.translate(appContainer).then(() => { this.eventBus.dispatch('localized'); }); - if (this.isViewerEmbedded && !_pdfjsLib.PDFJS.isExternalLinkTargetSet()) { - _pdfjsLib.PDFJS.externalLinkTarget = _pdfjsLib.PDFJS.LinkTarget.TOP; + if (this.isViewerEmbedded && _pdfjsLib.PDFJS.externalLinkTarget === _pdfjsLib.LinkTarget.NONE) { + _pdfjsLib.PDFJS.externalLinkTarget = _pdfjsLib.LinkTarget.TOP; } this.initialized = true; }); @@ -970,7 +977,7 @@ let PDFViewerApplication = { _readPreferences() { let { preferences, viewerPrefs } = this; return Promise.all([preferences.get('enableWebGL').then(function resolved(value) { - _pdfjsLib.PDFJS.disableWebGL = !value; + viewerPrefs['enableWebGL'] = value; }), preferences.get('sidebarViewOnLoad').then(function resolved(value) { viewerPrefs['sidebarViewOnLoad'] = value; }), preferences.get('pdfBugEnabled').then(function resolved(value) { @@ -979,13 +986,11 @@ let PDFViewerApplication = { viewerPrefs['showPreviousViewOnLoad'] = value; }), preferences.get('defaultZoomValue').then(function resolved(value) { viewerPrefs['defaultZoomValue'] = value; - }), preferences.get('enhanceTextSelection').then(function resolved(value) { - viewerPrefs['enhanceTextSelection'] = value; - }), preferences.get('disableTextLayer').then(function resolved(value) { - if (_pdfjsLib.PDFJS.disableTextLayer === true) { + }), preferences.get('textLayerMode').then(function resolved(value) { + if (viewerPrefs['textLayerMode'] === _ui_utils.TextLayerMode.DISABLE) { return; } - _pdfjsLib.PDFJS.disableTextLayer = value; + viewerPrefs['textLayerMode'] = value; }), preferences.get('disableRange').then(function resolved(value) { if (_pdfjsLib.PDFJS.disableRange === true) { return; @@ -1006,7 +1011,7 @@ let PDFViewerApplication = { }), preferences.get('useOnlyCssZoom').then(function resolved(value) { _pdfjsLib.PDFJS.useOnlyCssZoom = value; }), preferences.get('externalLinkTarget').then(function resolved(value) { - if (_pdfjsLib.PDFJS.isExternalLinkTargetSet()) { + if (_pdfjsLib.PDFJS.externalLinkTarget !== _pdfjsLib.LinkTarget.NONE) { return; } _pdfjsLib.PDFJS.externalLinkTarget = value; @@ -1047,7 +1052,7 @@ let PDFViewerApplication = { _pdfjsLib.PDFJS.disableHistory = hashParams['disablehistory'] === 'true'; } if ('webgl' in hashParams) { - _pdfjsLib.PDFJS.disableWebGL = hashParams['webgl'] !== 'true'; + viewerPrefs['enableWebGL'] = hashParams['webgl'] === 'true'; } if ('useonlycsszoom' in hashParams) { _pdfjsLib.PDFJS.useOnlyCssZoom = hashParams['useonlycsszoom'] === 'true'; @@ -1058,7 +1063,7 @@ let PDFViewerApplication = { if ('textlayer' in hashParams) { switch (hashParams['textlayer']) { case 'off': - _pdfjsLib.PDFJS.disableTextLayer = true; + viewerPrefs['textLayerMode'] = _ui_utils.TextLayerMode.DISABLE; break; case 'visible': case 'shadow': @@ -1070,15 +1075,14 @@ let PDFViewerApplication = { } if ('pdfbug' in hashParams) { _pdfjsLib.PDFJS.pdfBug = true; - let pdfBug = hashParams['pdfbug']; - let enabled = pdfBug.split(','); + let enabled = hashParams['pdfbug'].split(','); waitOn.push(loadAndEnablePDFBug(enabled)); } } return Promise.all(waitOn); }, _initializeL10n() { - this.l10n = this.externalServices.createL10n(); + this.l10n = this.externalServices.createL10n({ locale: _pdfjsLib.PDFJS.locale }); return this.l10n.getDirection().then(dir => { document.getElementsByTagName('html')[0].dir = dir; }); @@ -1092,7 +1096,11 @@ let PDFViewerApplication = { let pdfRenderingQueue = new _pdf_rendering_queue.PDFRenderingQueue(); pdfRenderingQueue.onIdle = this.cleanup.bind(this); this.pdfRenderingQueue = pdfRenderingQueue; - let pdfLinkService = new _pdf_link_service.PDFLinkService({ eventBus }); + let pdfLinkService = new _pdf_link_service.PDFLinkService({ + eventBus, + externalLinkTarget: _pdfjsLib.PDFJS.externalLinkTarget, + externalLinkRel: _pdfjsLib.PDFJS.externalLinkRel + }); this.pdfLinkService = pdfLinkService; let downloadManager = this.externalServices.createDownloadManager(); this.downloadManager = downloadManager; @@ -1106,10 +1114,14 @@ let PDFViewerApplication = { linkService: pdfLinkService, downloadManager, renderer: viewerPrefs['renderer'], + enableWebGL: viewerPrefs['enableWebGL'], l10n: this.l10n, - enhanceTextSelection: viewerPrefs['enhanceTextSelection'], + textLayerMode: viewerPrefs['textLayerMode'], + imageResourcesPath: _pdfjsLib.PDFJS.imageResourcesPath, renderInteractiveForms: viewerPrefs['renderInteractiveForms'], - enablePrintAutoRotate: viewerPrefs['enablePrintAutoRotate'] + enablePrintAutoRotate: viewerPrefs['enablePrintAutoRotate'], + useOnlyCssZoom: _pdfjsLib.PDFJS.useOnlyCssZoom, + maxCanvasPixels: _pdfjsLib.PDFJS.maxCanvasPixels }); pdfRenderingQueue.setViewer(this.pdfViewer); pdfLinkService.setViewer(this.pdfViewer); @@ -1226,7 +1238,7 @@ let PDFViewerApplication = { get supportsFullscreen() { let support; support = document.fullscreenEnabled === true || document.mozFullScreenEnabled === true; - if (support && _pdfjsLib.PDFJS.disableFullscreen === true) { + if (support && _viewer_compatibility.viewerCompatibilityParams['disableFullscreen'] === true) { support = false; } return (0, _pdfjsLib.shadow)(this, 'supportsFullscreen', support); @@ -1352,6 +1364,7 @@ let PDFViewerApplication = { parameters.url = file.url; } parameters.docBaseUrl = this.baseUrl; + parameters.verbosity = _pdfjsLib.PDFJS.verbosity; if (args) { for (let prop in args) { if (prop === 'length') { @@ -1626,7 +1639,7 @@ let PDFViewerApplication = { this.documentInfo = info; this.metadata = metadata; this.contentDispositionFilename = contentDispositionFilename; - console.log('PDF ' + pdfDocument.fingerprint + ' [' + info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() + ' / ' + (info.Creator || '-').trim() + ']' + ' (PDF.js: ' + (_pdfjsLib.version || '-') + (!_pdfjsLib.PDFJS.disableWebGL ? ' [WebGL]' : '') + ')'); + console.log('PDF ' + pdfDocument.fingerprint + ' [' + info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() + ' / ' + (info.Creator || '-').trim() + ']' + ' (PDF.js: ' + (_pdfjsLib.version || '-') + (this.viewerPrefs['enableWebGL'] ? ' [WebGL]' : '') + ')'); let pdfTitle; if (metadata && metadata.has('dc:title')) { let title = metadata.get('dc:title'); @@ -1651,7 +1664,7 @@ let PDFViewerApplication = { const KNOWN_GENERATORS = ['acrobat distiller', 'acrobat pdfwriter', 'adobe livecycle', 'adobe pdf library', 'adobe photoshop', 'ghostscript', 'tcpdf', 'cairo', 'dvipdfm', 'dvips', 'pdftex', 'pdfkit', 'itext', 'prince', 'quarkxpress', 'mac os x', 'microsoft', 'openoffice', 'oracle', 'luradocument', 'pdf-xchange', 'antenna house', 'aspose.cells', 'fpdf']; if (info.Producer) { KNOWN_GENERATORS.some(function (generator, s, i) { - if (generator.indexOf(s) < 0) { + if (!generator.includes(s)) { return false; } generatorId = i + 1; @@ -1880,10 +1893,7 @@ function loadAndEnablePDFBug(enabledTabs) { script.src = appConfig.debuggerScriptPath; script.onload = function () { PDFBug.enable(enabledTabs); - PDFBug.init({ - PDFJS: _pdfjsLib.PDFJS, - OPS: _pdfjsLib.OPS - }, appConfig.mainContainer); + PDFBug.init({ OPS: _pdfjsLib.OPS }, appConfig.mainContainer); resolve(); }; script.onerror = function () { @@ -1952,7 +1962,7 @@ function webViewerPageRendered(evt) { let thumbnailView = PDFViewerApplication.pdfThumbnailViewer.getThumbnail(pageIndex); thumbnailView.setImage(pageView); } - if (_pdfjsLib.PDFJS.pdfBug && typeof Stats !== 'undefined' && Stats.enabled && pageView.stats) { + if (typeof Stats !== 'undefined' && Stats.enabled && pageView.stats) { Stats.add(pageNumber, pageView.stats); } if (pageView.error) { @@ -2152,7 +2162,7 @@ function webViewerPageChanging(evt) { if (PDFViewerApplication.pdfSidebar.isThumbnailViewVisible) { PDFViewerApplication.pdfThumbnailViewer.scrollThumbnailIntoView(page); } - if (_pdfjsLib.PDFJS.pdfBug && typeof Stats !== 'undefined' && Stats.enabled) { + if (typeof Stats !== 'undefined' && Stats.enabled) { let pageView = PDFViewerApplication.pdfViewer.getPageView(page - 1); if (pageView && pageView.stats) { Stats.add(page, pageView.stats); @@ -2454,8 +2464,10 @@ var _dom_events = __webpack_require__(2); var _ui_utils = __webpack_require__(0); class PDFLinkService { - constructor({ eventBus } = {}) { + constructor({ eventBus, externalLinkTarget = null, externalLinkRel = null } = {}) { this.eventBus = eventBus || (0, _dom_events.getGlobalEventBus)(); + this.externalLinkTarget = externalLinkTarget; + this.externalLinkRel = externalLinkRel; this.baseUrl = null; this.pdfDocument = null; this.pdfViewer = null; @@ -2566,7 +2578,7 @@ class PDFLinkService { } setHash(hash) { let pageNumber, dest; - if (hash.indexOf('=') >= 0) { + if (hash.includes('=')) { let params = (0, _ui_utils.parseQueryString)(hash); if ('search' in params) { this.eventBus.dispatch('findfromurlhash', { @@ -2586,7 +2598,7 @@ class PDFLinkService { let zoomArgs = params.zoom.split(','); let zoomArg = zoomArgs[0]; let zoomArgNumber = parseFloat(zoomArg); - if (zoomArg.indexOf('Fit') === -1) { + if (!zoomArg.includes('Fit')) { dest = [null, { name: 'XYZ' }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null, zoomArgs.length > 2 ? zoomArgs[2] | 0 : null, zoomArgNumber ? zoomArgNumber / 100 : zoomArg]; } else { if (zoomArg === 'Fit' || zoomArg === 'FitB') { @@ -2739,6 +2751,10 @@ function isValidExplicitDestination(dest) { return true; } class SimpleLinkService { + constructor() { + this.externalLinkTarget = null; + this.externalLinkRel = null; + } get page() { return 0; } @@ -2774,7 +2790,7 @@ Object.defineProperty(exports, "__esModule", { }); exports.PDFCursorTools = exports.CursorTool = undefined; -var _grab_to_pan = __webpack_require__(9); +var _grab_to_pan = __webpack_require__(10); const CursorTool = { SELECT: 0, @@ -2932,7 +2948,32 @@ class PDFFindController { this.resolveFirstPage = resolve; }); } - normalize(text) { + executeCommand(cmd, state) { + if (this.state === null || cmd !== 'findagain') { + this.dirtyMatch = true; + } + this.state = state; + this._updateUIState(FindState.PENDING); + this._firstPagePromise.then(() => { + this._extractText(); + clearTimeout(this.findTimeout); + if (cmd === 'find') { + this.findTimeout = setTimeout(this._nextMatch.bind(this), FIND_TIMEOUT); + } else { + this._nextMatch(); + } + }); + } + updateMatchPosition(pageIndex, matchIndex, elements, beginIdx) { + if (this.selected.matchIdx === matchIndex && this.selected.pageIdx === pageIndex) { + let spot = { + top: FIND_SCROLL_OFFSET_TOP, + left: FIND_SCROLL_OFFSET_LEFT + }; + (0, _ui_utils.scrollIntoView)(elements[beginIdx], spot, true); + } + } + _normalize(text) { return text.replace(this.normalizationRegex, function (ch) { return CHARACTERS_TO_NORMALIZE[ch]; }); @@ -2971,7 +3012,7 @@ class PDFFindController { matchesLength.push(matchesWithLength[i].matchLength); } } - calcFindPhraseMatch(query, pageIndex, pageContent) { + _calculatePhraseMatch(query, pageIndex, pageContent) { let matches = []; let queryLen = query.length; let matchIdx = -queryLen; @@ -2984,7 +3025,7 @@ class PDFFindController { } this.pageMatches[pageIndex] = matches; } - calcFindWordMatch(query, pageIndex, pageContent) { + _calculateWordMatch(query, pageIndex, pageContent) { let matchesWithLength = []; let queryArray = query.match(/\S+/g); for (let i = 0, len = queryArray.length; i < len; i++) { @@ -3010,9 +3051,9 @@ class PDFFindController { this.pageMatches[pageIndex] = []; this._prepareMatches(matchesWithLength, this.pageMatches[pageIndex], this.pageMatchesLength[pageIndex]); } - calcFindMatch(pageIndex) { - let pageContent = this.normalize(this.pageContents[pageIndex]); - let query = this.normalize(this.state.query); + _calculateMatch(pageIndex) { + let pageContent = this._normalize(this.pageContents[pageIndex]); + let query = this._normalize(this.state.query); let caseSensitive = this.state.caseSensitive; let phraseSearch = this.state.phraseSearch; let queryLen = query.length; @@ -3024,21 +3065,21 @@ class PDFFindController { query = query.toLowerCase(); } if (phraseSearch) { - this.calcFindPhraseMatch(query, pageIndex, pageContent); + this._calculatePhraseMatch(query, pageIndex, pageContent); } else { - this.calcFindWordMatch(query, pageIndex, pageContent); + this._calculateWordMatch(query, pageIndex, pageContent); } - this.updatePage(pageIndex); + this._updatePage(pageIndex); if (this.resumePageIdx === pageIndex) { this.resumePageIdx = null; - this.nextPageMatch(); + this._nextPageMatch(); } if (this.pageMatches[pageIndex].length > 0) { this.matchCount += this.pageMatches[pageIndex].length; - this.updateUIResultsCount(); + this._updateUIResultsCount(); } } - extractText() { + _extractText() { if (this.startedTextExtraction) { return; } @@ -3065,23 +3106,7 @@ class PDFFindController { }); } } - executeCommand(cmd, state) { - if (this.state === null || cmd !== 'findagain') { - this.dirtyMatch = true; - } - this.state = state; - this.updateUIState(FindState.PENDING); - this._firstPagePromise.then(() => { - this.extractText(); - clearTimeout(this.findTimeout); - if (cmd === 'find') { - this.findTimeout = setTimeout(this.nextMatch.bind(this), FIND_TIMEOUT); - } else { - this.nextMatch(); - } - }); - } - updatePage(index) { + _updatePage(index) { if (this.selected.pageIdx === index) { this.pdfViewer.currentPageNumber = index + 1; } @@ -3090,7 +3115,7 @@ class PDFFindController { page.textLayer.updateMatches(); } } - nextMatch() { + _nextMatch() { let previous = this.state.findPrevious; let currentPageIndex = this.pdfViewer.currentPageNumber - 1; let numPages = this.pdfViewer.pagesCount; @@ -3106,18 +3131,18 @@ class PDFFindController { this.matchCount = 0; this.pageMatchesLength = null; for (let i = 0; i < numPages; i++) { - this.updatePage(i); + this._updatePage(i); if (!(i in this.pendingFindMatches)) { this.pendingFindMatches[i] = true; this.extractTextPromises[i].then(pageIdx => { delete this.pendingFindMatches[pageIdx]; - this.calcFindMatch(pageIdx); + this._calculateMatch(pageIdx); }); } } } if (this.state.query === '') { - this.updateUIState(FindState.FOUND); + this._updateUIState(FindState.FOUND); return; } if (this.resumePageIdx) { @@ -3130,43 +3155,34 @@ class PDFFindController { if (!previous && offset.matchIdx + 1 < numPageMatches || previous && offset.matchIdx > 0) { this.hadMatch = true; offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1; - this.updateMatch(true); + this._updateMatch(true); return; } - this.advanceOffsetPage(previous); + this._advanceOffsetPage(previous); } - this.nextPageMatch(); + this._nextPageMatch(); } - matchesReady(matches) { + _matchesReady(matches) { let offset = this.offset; let numMatches = matches.length; let previous = this.state.findPrevious; if (numMatches) { this.hadMatch = true; offset.matchIdx = previous ? numMatches - 1 : 0; - this.updateMatch(true); + this._updateMatch(true); return true; } - this.advanceOffsetPage(previous); + this._advanceOffsetPage(previous); if (offset.wrapped) { offset.matchIdx = null; if (this.pagesToSearch < 0) { - this.updateMatch(false); + this._updateMatch(false); return true; } } return false; } - updateMatchPosition(pageIndex, matchIndex, elements, beginIdx) { - if (this.selected.matchIdx === matchIndex && this.selected.pageIdx === pageIndex) { - let spot = { - top: FIND_SCROLL_OFFSET_TOP, - left: FIND_SCROLL_OFFSET_LEFT - }; - (0, _ui_utils.scrollIntoView)(elements[beginIdx], spot, true); - } - } - nextPageMatch() { + _nextPageMatch() { if (this.resumePageIdx !== null) { console.error('There can only be one pending page.'); } @@ -3178,9 +3194,9 @@ class PDFFindController { this.resumePageIdx = pageIdx; break; } - } while (!this.matchesReady(matches)); + } while (!this._matchesReady(matches)); } - advanceOffsetPage(previous) { + _advanceOffsetPage(previous) { let offset = this.offset; let numPages = this.extractTextPromises.length; offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1; @@ -3191,7 +3207,7 @@ class PDFFindController { offset.wrapped = true; } } - updateMatch(found = false) { + _updateMatch(found = false) { let state = FindState.NOT_FOUND; let wrapped = this.offset.wrapped; this.offset.wrapped = false; @@ -3201,20 +3217,20 @@ class PDFFindController { this.selected.matchIdx = this.offset.matchIdx; state = wrapped ? FindState.WRAPPED : FindState.FOUND; if (previousPage !== -1 && previousPage !== this.selected.pageIdx) { - this.updatePage(previousPage); + this._updatePage(previousPage); } } - this.updateUIState(state, this.state.findPrevious); + this._updateUIState(state, this.state.findPrevious); if (this.selected.pageIdx !== -1) { - this.updatePage(this.selected.pageIdx); + this._updatePage(this.selected.pageIdx); } } - updateUIResultsCount() { + _updateUIResultsCount() { if (this.onUpdateResultsCount) { this.onUpdateResultsCount(this.matchCount); } } - updateUIState(state, previous) { + _updateUIState(state, previous) { if (this.onUpdateState) { this.onUpdateState(state, previous, this.matchCount); } @@ -3230,6 +3246,21 @@ exports.PDFFindController = PDFFindController; "use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +let compatibilityParams = Object.create(null); +; +const viewerCompatibilityParams = Object.freeze(compatibilityParams); +exports.viewerCompatibilityParams = viewerCompatibilityParams; + +/***/ }), +/* 9 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + let DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf'; ; let pdfjsWebApp; @@ -3237,8 +3268,8 @@ let pdfjsWebApp; pdfjsWebApp = __webpack_require__(4); } { - __webpack_require__(30); - __webpack_require__(33); + __webpack_require__(31); + __webpack_require__(34); } ; ; @@ -3370,7 +3401,7 @@ if (document.readyState === 'interactive' || document.readyState === 'complete') } /***/ }), -/* 9 */ +/* 10 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -3511,7 +3542,7 @@ function isLeftMouseReleased(event) { exports.GrabToPan = GrabToPan; /***/ }), -/* 10 */ +/* 11 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -3812,7 +3843,7 @@ exports.SidebarView = SidebarView; exports.PDFSidebar = PDFSidebar; /***/ }), -/* 11 */ +/* 12 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -3912,7 +3943,7 @@ class OverlayManager { exports.OverlayManager = OverlayManager; /***/ }), -/* 12 */ +/* 13 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -3982,7 +4013,7 @@ class PasswordPrompt { exports.PasswordPrompt = PasswordPrompt; /***/ }), -/* 13 */ +/* 14 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -4095,7 +4126,7 @@ class PDFAttachmentViewer { exports.PDFAttachmentViewer = PDFAttachmentViewer; /***/ }), -/* 14 */ +/* 15 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -4260,7 +4291,7 @@ class PDFDocumentProperties { exports.PDFDocumentProperties = PDFDocumentProperties; /***/ }), -/* 15 */ +/* 16 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -4428,7 +4459,7 @@ class PDFFindBar { exports.PDFFindBar = PDFFindBar; /***/ }), -/* 16 */ +/* 17 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -4805,7 +4836,7 @@ exports.isDestHashesEqual = isDestHashesEqual; exports.isDestArraysEqual = isDestArraysEqual; /***/ }), -/* 17 */ +/* 18 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -4838,29 +4869,30 @@ class PDFOutlineViewer { outlineCount }); } - _bindLink(element, item) { - if (item.url) { + _bindLink(element, { url, newWindow, dest }) { + let { linkService } = this; + if (url) { (0, _pdfjsLib.addLinkAttributes)(element, { - url: item.url, - target: item.newWindow ? _pdfjsLib.PDFJS.LinkTarget.BLANK : undefined + url, + target: newWindow ? _pdfjsLib.LinkTarget.BLANK : linkService.externalLinkTarget, + rel: linkService.externalLinkRel }); return; } - let destination = item.dest; - element.href = this.linkService.getDestinationHash(destination); + element.href = this.linkService.getDestinationHash(dest); element.onclick = () => { - if (destination) { - this.linkService.navigateTo(destination); + if (dest) { + this.linkService.navigateTo(dest); } return false; }; } - _setStyles(element, item) { + _setStyles(element, { bold, italic }) { let styleStr = ''; - if (item.bold) { + if (bold) { styleStr += 'font-weight: bold;'; } - if (item.italic) { + if (italic) { styleStr += 'font-style: italic;'; } if (styleStr) { @@ -4945,7 +4977,7 @@ class PDFOutlineViewer { exports.PDFOutlineViewer = PDFOutlineViewer; /***/ }), -/* 18 */ +/* 19 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5262,7 +5294,7 @@ class PDFPresentationMode { exports.PDFPresentationMode = PDFPresentationMode; /***/ }), -/* 19 */ +/* 20 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5382,7 +5414,7 @@ class PDFSidebarResizer { exports.PDFSidebarResizer = PDFSidebarResizer; /***/ }), -/* 20 */ +/* 21 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5395,9 +5427,10 @@ exports.PDFThumbnailViewer = undefined; var _ui_utils = __webpack_require__(0); -var _pdf_thumbnail_view = __webpack_require__(21); +var _pdf_thumbnail_view = __webpack_require__(22); const THUMBNAIL_SCROLL_MARGIN = -19; +const THUMBNAIL_SELECTED_CLASS = 'selected'; class PDFThumbnailViewer { constructor({ container, linkService, renderingQueue, l10n = _ui_utils.NullL10n }) { this.container = container; @@ -5416,14 +5449,19 @@ class PDFThumbnailViewer { _getVisibleThumbs() { return (0, _ui_utils.getVisibleElements)(this.container, this._thumbnails); } - scrollThumbnailIntoView(page) { - let selected = document.querySelector('.thumbnail.selected'); - if (selected) { - selected.classList.remove('selected'); + scrollThumbnailIntoView(pageNumber) { + if (!this.pdfDocument) { + return; } - let thumbnail = document.querySelector('div.thumbnail[data-page-number="' + page + '"]'); - if (thumbnail) { - thumbnail.classList.add('selected'); + const thumbnailView = this._thumbnails[pageNumber - 1]; + if (!thumbnailView) { + console.error('scrollThumbnailIntoView: Invalid "pageNumber" parameter.'); + return; + } + if (pageNumber !== this._currentPageNumber) { + const prevThumbnailView = this._thumbnails[this._currentPageNumber - 1]; + prevThumbnailView.div.classList.remove(THUMBNAIL_SELECTED_CLASS); + thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS); } let visibleThumbs = this._getVisibleThumbs(); let numVisibleThumbs = visibleThumbs.views.length; @@ -5431,11 +5469,11 @@ class PDFThumbnailViewer { let first = visibleThumbs.first.id; let last = numVisibleThumbs > 1 ? visibleThumbs.last.id : first; let shouldScroll = false; - if (page <= first || page >= last) { + if (pageNumber <= first || pageNumber >= last) { shouldScroll = true; } else { visibleThumbs.views.some(function (view) { - if (view.id !== page) { + if (view.id !== pageNumber) { return false; } shouldScroll = view.percent < 100; @@ -5443,9 +5481,10 @@ class PDFThumbnailViewer { }); } if (shouldScroll) { - (0, _ui_utils.scrollIntoView)(thumbnail, { top: THUMBNAIL_SCROLL_MARGIN }); + (0, _ui_utils.scrollIntoView)(thumbnailView.div, { top: THUMBNAIL_SCROLL_MARGIN }); } } + this._currentPageNumber = pageNumber; } get pagesRotation() { return this._pagesRotation; @@ -5470,6 +5509,7 @@ class PDFThumbnailViewer { } _resetView() { this._thumbnails = []; + this._currentPageNumber = 1; this._pageLabels = null; this._pagesRotation = 0; this._pagesRequests = []; @@ -5499,6 +5539,8 @@ class PDFThumbnailViewer { }); this._thumbnails.push(thumbnail); } + const thumbnailView = this._thumbnails[this._currentPageNumber - 1]; + thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS); }).catch(reason => { console.error('Unable to initialize thumbnail viewer', reason); }); @@ -5561,7 +5603,7 @@ class PDFThumbnailViewer { exports.PDFThumbnailViewer = PDFThumbnailViewer; /***/ }), -/* 21 */ +/* 22 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5646,9 +5688,6 @@ class PDFThumbnailView { div.className = 'thumbnail'; div.setAttribute('data-page-number', this.id); this.div = div; - if (id === 1) { - div.classList.add('selected'); - } let ring = document.createElement('div'); ring.className = 'thumbnailSelectionRing'; let borderAdjustment = 2 * THUMBNAIL_CANVAS_BORDER_WIDTH; @@ -5872,7 +5911,7 @@ class PDFThumbnailView { exports.PDFThumbnailView = PDFThumbnailView; /***/ }), -/* 22 */ +/* 23 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5885,7 +5924,7 @@ exports.PDFViewer = undefined; var _ui_utils = __webpack_require__(0); -var _base_viewer = __webpack_require__(23); +var _base_viewer = __webpack_require__(24); var _pdfjsLib = __webpack_require__(1); @@ -5948,7 +5987,7 @@ class PDFViewer extends _base_viewer.BaseViewer { exports.PDFViewer = PDFViewer; /***/ }), -/* 23 */ +/* 24 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5965,15 +6004,15 @@ var _ui_utils = __webpack_require__(0); var _pdf_rendering_queue = __webpack_require__(3); -var _annotation_layer_builder = __webpack_require__(24); +var _annotation_layer_builder = __webpack_require__(25); var _dom_events = __webpack_require__(2); -var _pdf_page_view = __webpack_require__(25); +var _pdf_page_view = __webpack_require__(26); var _pdf_link_service = __webpack_require__(5); -var _text_layer_builder = __webpack_require__(26); +var _text_layer_builder = __webpack_require__(27); const DEFAULT_CACHE_SIZE = 10; function PDFPageViewBuffer(size) { @@ -6019,10 +6058,15 @@ class BaseViewer { this.linkService = options.linkService || new _pdf_link_service.SimpleLinkService(); this.downloadManager = options.downloadManager || null; this.removePageBorders = options.removePageBorders || false; + this.textLayerMode = Number.isInteger(options.textLayerMode) ? options.textLayerMode : _ui_utils.TextLayerMode.ENABLE; this.enhanceTextSelection = options.enhanceTextSelection || false; + this.imageResourcesPath = options.imageResourcesPath || ''; this.renderInteractiveForms = options.renderInteractiveForms || false; this.enablePrintAutoRotate = options.enablePrintAutoRotate || false; this.renderer = options.renderer || _ui_utils.RendererType.CANVAS; + this.enableWebGL = options.enableWebGL || false; + this.useOnlyCssZoom = options.useOnlyCssZoom || false; + this.maxCanvasPixels = options.maxCanvasPixels; this.l10n = options.l10n || _ui_utils.NullL10n; this.defaultRenderingQueue = !options.renderingQueue; if (this.defaultRenderingQueue) { @@ -6190,7 +6234,7 @@ class BaseViewer { let viewport = pdfPage.getViewport(scale * _ui_utils.CSS_UNITS); for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { let textLayerFactory = null; - if (!_pdfjsLib.PDFJS.disableTextLayer) { + if (this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE) { textLayerFactory = this; } let pageView = new _pdf_page_view.PDFPageView({ @@ -6201,10 +6245,14 @@ class BaseViewer { defaultViewport: viewport.clone(), renderingQueue: this.renderingQueue, textLayerFactory, + textLayerMode: this.textLayerMode, annotationLayerFactory: this, - enhanceTextSelection: this.enhanceTextSelection, + imageResourcesPath: this.imageResourcesPath, renderInteractiveForms: this.renderInteractiveForms, renderer: this.renderer, + enableWebGL: this.enableWebGL, + useOnlyCssZoom: this.useOnlyCssZoom, + maxCanvasPixels: this.maxCanvasPixels, l10n: this.l10n }); bindOnAfterAndBeforeDraw(pageView); @@ -6574,10 +6622,11 @@ class BaseViewer { enhanceTextSelection: this.isInPresentationMode ? false : enhanceTextSelection }); } - createAnnotationLayerBuilder(pageDiv, pdfPage, renderInteractiveForms = false, l10n = _ui_utils.NullL10n) { + createAnnotationLayerBuilder(pageDiv, pdfPage, imageResourcesPath = '', renderInteractiveForms = false, l10n = _ui_utils.NullL10n) { return new _annotation_layer_builder.AnnotationLayerBuilder({ pageDiv, pdfPage, + imageResourcesPath, renderInteractiveForms, linkService: this.linkService, downloadManager: this.downloadManager, @@ -6625,7 +6674,7 @@ class BaseViewer { exports.BaseViewer = BaseViewer; /***/ }), -/* 24 */ +/* 25 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6643,11 +6692,12 @@ var _ui_utils = __webpack_require__(0); var _pdf_link_service = __webpack_require__(5); class AnnotationLayerBuilder { - constructor({ pageDiv, pdfPage, linkService, downloadManager, renderInteractiveForms = false, l10n = _ui_utils.NullL10n }) { + constructor({ pageDiv, pdfPage, linkService, downloadManager, imageResourcesPath = '', renderInteractiveForms = false, l10n = _ui_utils.NullL10n }) { this.pageDiv = pageDiv; this.pdfPage = pdfPage; this.linkService = linkService; this.downloadManager = downloadManager; + this.imageResourcesPath = imageResourcesPath; this.renderInteractiveForms = renderInteractiveForms; this.l10n = l10n; this.div = null; @@ -6663,6 +6713,7 @@ class AnnotationLayerBuilder { div: this.div, annotations, page: this.pdfPage, + imageResourcesPath: this.imageResourcesPath, renderInteractiveForms: this.renderInteractiveForms, linkService: this.linkService, downloadManager: this.downloadManager @@ -6693,10 +6744,11 @@ class AnnotationLayerBuilder { } } class DefaultAnnotationLayerFactory { - createAnnotationLayerBuilder(pageDiv, pdfPage, renderInteractiveForms = false, l10n = _ui_utils.NullL10n) { + createAnnotationLayerBuilder(pageDiv, pdfPage, imageResourcesPath = '', renderInteractiveForms = false, l10n = _ui_utils.NullL10n) { return new AnnotationLayerBuilder({ pageDiv, pdfPage, + imageResourcesPath, renderInteractiveForms, linkService: new _pdf_link_service.SimpleLinkService(), l10n @@ -6707,7 +6759,7 @@ exports.AnnotationLayerBuilder = AnnotationLayerBuilder; exports.DefaultAnnotationLayerFactory = DefaultAnnotationLayerFactory; /***/ }), -/* 25 */ +/* 26 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6726,6 +6778,9 @@ var _dom_events = __webpack_require__(2); var _pdf_rendering_queue = __webpack_require__(3); +var _viewer_compatibility = __webpack_require__(8); + +const MAX_CANVAS_PIXELS = _viewer_compatibility.viewerCompatibilityParams.maxCanvasPixels || 16777216; class PDFPageView { constructor(options) { let container = options.container; @@ -6739,13 +6794,17 @@ class PDFPageView { this.viewport = defaultViewport; this.pdfPageRotate = defaultViewport.rotation; this.hasRestrictedScaling = false; - this.enhanceTextSelection = options.enhanceTextSelection || false; + this.textLayerMode = Number.isInteger(options.textLayerMode) ? options.textLayerMode : _ui_utils.TextLayerMode.ENABLE; + this.imageResourcesPath = options.imageResourcesPath || ''; this.renderInteractiveForms = options.renderInteractiveForms || false; + this.useOnlyCssZoom = options.useOnlyCssZoom || false; + this.maxCanvasPixels = options.maxCanvasPixels || MAX_CANVAS_PIXELS; this.eventBus = options.eventBus || (0, _dom_events.getGlobalEventBus)(); this.renderingQueue = options.renderingQueue; this.textLayerFactory = options.textLayerFactory; this.annotationLayerFactory = options.annotationLayerFactory; this.renderer = options.renderer || _ui_utils.RendererType.CANVAS; + this.enableWebGL = options.enableWebGL || false; this.l10n = options.l10n || _ui_utils.NullL10n; this.paintTask = null; this.paintedViewportMap = new WeakMap(); @@ -6851,14 +6910,14 @@ class PDFPageView { return; } let isScalingRestricted = false; - if (this.canvas && _pdfjsLib.PDFJS.maxCanvasPixels > 0) { + if (this.canvas && this.maxCanvasPixels > 0) { let outputScale = this.outputScale; - if ((Math.floor(this.viewport.width) * outputScale.sx | 0) * (Math.floor(this.viewport.height) * outputScale.sy | 0) > _pdfjsLib.PDFJS.maxCanvasPixels) { + if ((Math.floor(this.viewport.width) * outputScale.sx | 0) * (Math.floor(this.viewport.height) * outputScale.sy | 0) > this.maxCanvasPixels) { isScalingRestricted = true; } } if (this.canvas) { - if (_pdfjsLib.PDFJS.useOnlyCssZoom || this.hasRestrictedScaling && isScalingRestricted) { + if (this.useOnlyCssZoom || this.hasRestrictedScaling && isScalingRestricted) { this.cssTransform(this.canvas, true); this.eventBus.dispatch('pagerendered', { source: this, @@ -6977,7 +7036,7 @@ class PDFPageView { div.appendChild(canvasWrapper); } let textLayer = null; - if (this.textLayerFactory) { + if (this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE && this.textLayerFactory) { let textLayerDiv = document.createElement('div'); textLayerDiv.className = 'textLayer'; textLayerDiv.style.width = canvasWrapper.style.width; @@ -6987,7 +7046,7 @@ class PDFPageView { } else { div.appendChild(textLayerDiv); } - textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.enhanceTextSelection); + textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.textLayerMode === _ui_utils.TextLayerMode.ENABLE_ENHANCE); } this.textLayer = textLayer; let renderContinueCallback = null; @@ -7049,7 +7108,7 @@ class PDFPageView { }); if (this.annotationLayerFactory) { if (!this.annotationLayer) { - this.annotationLayer = this.annotationLayerFactory.createAnnotationLayerBuilder(div, pdfPage, this.renderInteractiveForms, this.l10n); + this.annotationLayer = this.annotationLayerFactory.createAnnotationLayerBuilder(div, pdfPage, this.imageResourcesPath, this.renderInteractiveForms, this.l10n); } this.annotationLayer.render(this.viewport, 'display'); } @@ -7087,15 +7146,15 @@ class PDFPageView { let ctx = canvas.getContext('2d', { alpha: false }); let outputScale = (0, _ui_utils.getOutputScale)(ctx); this.outputScale = outputScale; - if (_pdfjsLib.PDFJS.useOnlyCssZoom) { + if (this.useOnlyCssZoom) { let actualSizeViewport = viewport.clone({ scale: _ui_utils.CSS_UNITS }); outputScale.sx *= actualSizeViewport.width / viewport.width; outputScale.sy *= actualSizeViewport.height / viewport.height; outputScale.scaled = true; } - if (_pdfjsLib.PDFJS.maxCanvasPixels > 0) { + if (this.maxCanvasPixels > 0) { let pixelsInViewport = viewport.width * viewport.height; - let maxScale = Math.sqrt(_pdfjsLib.PDFJS.maxCanvasPixels / pixelsInViewport); + let maxScale = Math.sqrt(this.maxCanvasPixels / pixelsInViewport); if (outputScale.sx > maxScale || outputScale.sy > maxScale) { outputScale.sx = maxScale; outputScale.sy = maxScale; @@ -7117,6 +7176,7 @@ class PDFPageView { canvasContext: ctx, transform, viewport: this.viewport, + enableWebGL: this.enableWebGL, renderInteractiveForms: this.renderInteractiveForms }; let renderTask = this.pdfPage.render(renderContext); @@ -7156,7 +7216,7 @@ class PDFPageView { exports.PDFPageView = PDFPageView; /***/ }), -/* 26 */ +/* 27 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -7425,7 +7485,7 @@ exports.TextLayerBuilder = TextLayerBuilder; exports.DefaultTextLayerFactory = DefaultTextLayerFactory; /***/ }), -/* 27 */ +/* 28 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -7605,7 +7665,7 @@ class SecondaryToolbar { exports.SecondaryToolbar = SecondaryToolbar; /***/ }), -/* 28 */ +/* 29 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -7790,7 +7850,7 @@ class Toolbar { exports.Toolbar = Toolbar; /***/ }), -/* 29 */ +/* 30 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -7873,7 +7933,7 @@ class ViewHistory { exports.ViewHistory = ViewHistory; /***/ }), -/* 30 */ +/* 31 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -7884,11 +7944,11 @@ Object.defineProperty(exports, "__esModule", { }); exports.FirefoxCom = exports.DownloadManager = undefined; -__webpack_require__(31); +__webpack_require__(32); var _pdfjsLib = __webpack_require__(1); -var _preferences = __webpack_require__(32); +var _preferences = __webpack_require__(33); var _app = __webpack_require__(4); @@ -8081,7 +8141,7 @@ _app.PDFViewerApplication.externalServices = { createPreferences() { return new FirefoxPreferences(); }, - createL10n() { + createL10n(options) { let mozL10n = document.mozL10n; return new MozL10n(mozL10n); }, @@ -8114,7 +8174,7 @@ exports.DownloadManager = DownloadManager; exports.FirefoxCom = FirefoxCom; /***/ }), -/* 31 */ +/* 32 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8197,7 +8257,7 @@ exports.FirefoxCom = FirefoxCom; getDirection() { var rtlList = ["ar", "he", "fa", "ps", "ur"]; var shortCode = gLanguage.split("-")[0]; - return rtlList.indexOf(shortCode) >= 0 ? "rtl" : "ltr"; + return rtlList.includes(shortCode) ? "rtl" : "ltr"; }, getReadyState() { return gReadyState; @@ -8212,7 +8272,7 @@ exports.FirefoxCom = FirefoxCom; })(undefined); /***/ }), -/* 32 */ +/* 33 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8232,7 +8292,6 @@ function getDefaultPreferences() { "showPreviousViewOnLoad": true, "defaultZoomValue": "", "sidebarViewOnLoad": 0, - "enableHandToolOnLoad": false, "cursorToolOnLoad": 0, "enableWebGL": false, "pdfBugEnabled": false, @@ -8240,10 +8299,9 @@ function getDefaultPreferences() { "disableStream": false, "disableAutoFetch": false, "disableFontFace": false, - "disableTextLayer": false, + "textLayerMode": 1, "useOnlyCssZoom": false, "externalLinkTarget": 0, - "enhanceTextSelection": false, "renderer": "canvas", "renderInteractiveForms": false, "enablePrintAutoRotate": false, @@ -8337,7 +8395,7 @@ class BasePreferences { exports.BasePreferences = BasePreferences; /***/ }), -/* 33 */ +/* 34 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; diff --git a/browser/modules/ThemeVariableMap.jsm b/browser/modules/ThemeVariableMap.jsm index 27dda917deb7..70df1d59bfd6 100644 --- a/browser/modules/ThemeVariableMap.jsm +++ b/browser/modules/ThemeVariableMap.jsm @@ -23,4 +23,7 @@ const ThemeVariableMap = [ ["--lwt-toolbarbutton-icon-fill-attention", "icon_attention_color"], ["--lwt-toolbarbutton-hover-background", "button_background_hover"], ["--lwt-toolbarbutton-active-background", "button_background_active"], + ["--arrowpanel-background", "popup"], + ["--arrowpanel-color", "popup_text"], + ["--arrowpanel-border-color", "popup_border"], ]; diff --git a/browser/themes/shared/customizableui/panelUI.inc.css b/browser/themes/shared/customizableui/panelUI.inc.css index 92e65927bf1e..e08184625e52 100644 --- a/browser/themes/shared/customizableui/panelUI.inc.css +++ b/browser/themes/shared/customizableui/panelUI.inc.css @@ -951,6 +951,18 @@ panelmultiview .toolbaritem-combined-buttons > spacer.after-label { /* Unset the min-height constraint, because that works better for a text-only button. */ #appMenu-zoomReset-button { min-height: unset; + border: 1px solid var(--panel-separator-color); + border-radius: 10000px; + padding: 1px 8px; + background-color: var(--arrowpanel-dimmed); +} + +#appMenu-zoomReset-button@buttonStateHover@ { + background-color: var(--arrowpanel-dimmed-further); +} + +#appMenu-zoomReset-button@buttonStateActive@ { + background-color: var(--arrowpanel-dimmed-even-further); } #appMenu-zoomReset-button > .toolbarbutton-text { @@ -968,14 +980,6 @@ panelmultiview .toolbaritem-combined-buttons > spacer.after-label { display: none; } -/* Using this selector, because this way the hover and active selectors will apply properly. */ -.PanelUI-subView .toolbaritem-combined-buttons > .subviewbutton:not(.subviewbutton-iconic) { - background-color: #f9f9f9; - border: 1px solid #e1e1e1; - border-radius: 10000px; - padding: 1px 8px; -} - .toolbaritem-combined-buttons > .subviewbutton:not(.subviewbutton-iconic) > .toolbarbutton-text { font-size: 1em; padding-inline-start: 0; diff --git a/build/autoconf/clang-plugin.m4 b/build/autoconf/clang-plugin.m4 index 76929920d47d..ecc4e26165a6 100644 --- a/build/autoconf/clang-plugin.m4 +++ b/build/autoconf/clang-plugin.m4 @@ -57,7 +57,7 @@ if test -n "$ENABLE_CLANG_PLUGIN"; then dnl version that what our build machines have installed. LLVM_LDFLAGS=`echo "$LLVM_LDFLAGS" | sed -E 's/-L[[^ ]]+\/clang\/lib//'` elif test "${HOST_OS_ARCH}" = "WINNT"; then - CLANG_LDFLAGS="clang.lib" + CLANG_LDFLAGS="clang.lib clangASTMatchers.lib" else CLANG_LDFLAGS="-lclangASTMatchers" fi diff --git a/devtools/client/debugger/new/README.mozilla b/devtools/client/debugger/new/README.mozilla index 05e369153865..b47806140226 100644 --- a/devtools/client/debugger/new/README.mozilla +++ b/devtools/client/debugger/new/README.mozilla @@ -1,8 +1,8 @@ This is the debugger.html project output. See https://github.com/devtools-html/debugger.html -Version 16.0 -Comparison: https://github.com/devtools-html/debugger.html/compare/release-15...release-16 +Version 17.0 +Comparison: https://github.com/devtools-html/debugger.html/compare/release-16...release-17 Packages: - babel-plugin-transform-es2015-modules-commonjs @6.26.0 diff --git a/devtools/client/debugger/new/debugger.css b/devtools/client/debugger/new/debugger.css index 822a84ca87bb..388a32edcc47 100644 --- a/devtools/client/debugger/new/debugger.css +++ b/devtools/client/debugger/new/debugger.css @@ -1054,10 +1054,6 @@ html .arrow.expanded svg { vertical-align: sub; } -.theme-dark .webpack { - opacity: 0.5; -} - .function svg { height: 10px; width: 15px; @@ -1075,13 +1071,19 @@ html .arrow.expanded svg { vertical-align: sub; } -.source-icon svg { - fill: var(--theme-body-color); +.angular, +.webpack { + opacity: 0.8; } -.theme-dark .angular { +.theme-dark .angular, +.theme-dark .webpack { opacity: 0.5; } + +.source-icon svg { + fill: var(--theme-comment); +} /* 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 . */ @@ -1440,8 +1442,10 @@ html[dir="rtl"] .arrow svg, .project-text-search .no-result-msg { color: var(--theme-body-color-inactive); font-size: 24px; - padding: 4px; - word-break: break-all; + padding: 4px 15px; + max-width: 100%; + overflow-wrap: break-word; + hyphens: auto; } .project-text-search .file-result { @@ -1637,7 +1641,7 @@ html[dir="rtl"] .arrow svg, } .theme-dark .sources-list .managed-tree .tree .node:not(.focused) img.blackBox { - background-color: var(--theme-content-color3); + background-color: var(--theme-comment); } .theme-dark .sources-list .managed-tree .tree .node img.blackBox { @@ -2448,7 +2452,7 @@ html .toggle-button.end.vertical svg { } .theme-dark .popover .preview-popup .arrow svg { - fill: var(--theme-content-color3); + fill: var(--theme-comment); } .tooltip { @@ -2504,7 +2508,7 @@ html .toggle-button.end.vertical svg { .add-to-expression-bar .expression-to-save-button { font-size: 14px; - color: var(--theme-content-color3); + color: var(--theme-comment); } /* 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 @@ -2575,7 +2579,6 @@ html .toggle-button.end.vertical svg { background: var(--theme-toolbar-background); border-top: 1px solid var(--theme-splitter-color); border-bottom: 1px solid var(--theme-splitter-color); - padding-right: 16px; } .conditional-breakpoint-panel .prompt { @@ -2622,10 +2625,10 @@ html .toggle-button.end.vertical svg { .editor-wrapper .CodeMirror-linewidget { margin-right: -7px; - overflow: visible; + overflow: hidden; } -.editor-wrapper .CodeMirror-sizer { +.editor-wrapper { min-width: 0 !important; } @@ -2759,7 +2762,7 @@ html[dir="rtl"] .editor-mount { } .theme-dark .editor-wrapper .CodeMirror-line .cm-comment { - color: var(--theme-content-color3); + color: var(--theme-comment); } .debug-expression { @@ -2811,7 +2814,7 @@ debug-expression-error { @keyframes fade-highlight-out-dark { 0% { - background-color: var(--theme-content-color3); + background-color: var(--theme-comment); } 100% { background-color: transparent; @@ -2901,7 +2904,7 @@ html .breakpoints-list .breakpoint.paused { } .breakpoints-list .breakpoint.disabled .breakpoint-label { - color: var(--theme-content-color3); + color: var(--theme-comment); transition: color 0.5s linear; } @@ -3233,12 +3236,18 @@ html .breakpoints-list .breakpoint.paused { color: white; } +.show-more-container { + display: flex; +} + .show-more { text-align: center; padding: 8px 0px; margin: 7px 10px 7px 7px; border: 1px solid var(--theme-splitter-color); background-color: var(--theme-tab-toolbar-background); + width: 100%; + font-size: inherit; } .show-more:hover { @@ -3585,7 +3594,7 @@ html[dir="rtl"] .dropdown { } .dropdown-button { - color: var(--theme-content-color3); + color: var(--theme-comment); background: none; border: none; padding: 0; @@ -3702,6 +3711,14 @@ img.ignore-exceptions { opacity: 0.6; } +.object-node { + padding-left: 4px; +} + +html[dir="rtl"] .object-node { + padding-right: 4px; +} + .object-label { color: var(--theme-highlight-blue); } @@ -3725,10 +3742,6 @@ img.ignore-exceptions { overflow: auto; } -.scopes-list { - padding-inline-start: 4px; -} - .scopes-list .tree:focus { outline: none; } @@ -3891,7 +3904,7 @@ html .welcomebox .toggle-button-end.collapsed { padding: 4px; margin-top: 4px; margin-left: 2px; - fill: var(--theme-content-color3); + fill: var(--theme-comment); transition: 0.1s ease; align-self: center; } diff --git a/devtools/client/debugger/new/debugger.js b/devtools/client/debugger/new/debugger.js index b6e5bdfe50f3..ff90ac5f52a3 100644 --- a/devtools/client/debugger/new/debugger.js +++ b/devtools/client/debugger/new/debugger.js @@ -319,13 +319,7 @@ module.exports = isObjectLike; /***/ }), -/* 15 */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = __webpack_require__(168); - - -/***/ }), +/* 15 */, /* 16 */, /* 17 */, /* 18 */, @@ -387,8 +381,7 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_22__; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ActionTypes; }); /* harmony export (immutable) */ __webpack_exports__["b"] = createStore; /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_es_isPlainObject__ = __webpack_require__(33); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_symbol_observable__ = __webpack_require__(15); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_symbol_observable___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_symbol_observable__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_symbol_observable__ = __webpack_require__(2287); @@ -620,7 +613,7 @@ var ActionTypes = { var unsubscribe = outerSubscribe(observeState); return { unsubscribe: unsubscribe }; } - }, _ref[__WEBPACK_IMPORTED_MODULE_1_symbol_observable___default.a] = function () { + }, _ref[__WEBPACK_IMPORTED_MODULE_1_symbol_observable__["a" /* default */]] = function () { return this; }, _ref; } @@ -635,7 +628,7 @@ var ActionTypes = { subscribe: subscribe, getState: getState, replaceReducer: replaceReducer - }, _ref2[__WEBPACK_IMPORTED_MODULE_1_symbol_observable___default.a] = observable, _ref2; + }, _ref2[__WEBPACK_IMPORTED_MODULE_1_symbol_observable__["a" /* default */]] = observable, _ref2; } /***/ }), @@ -1047,8 +1040,7 @@ module.exports = isSymbol; var memoizeCapped = __webpack_require__(74); /** Used to match property names within property paths. */ -var reLeadingDot = /^\./, - rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; +var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; @@ -1062,11 +1054,11 @@ var reEscapeChar = /\\(\\)?/g; */ var stringToPath = memoizeCapped(function(string) { var result = []; - if (reLeadingDot.test(string)) { + if (string.charCodeAt(0) === 46 /* . */) { result.push(''); } - string.replace(rePropName, function(match, number, quote, string) { - result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); + string.replace(rePropName, function(match, number, quote, subString) { + result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match)); }); return result; }); @@ -2410,10 +2402,13 @@ var reIsUint = /^(?:0|[1-9]\d*)$/; * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. */ function isIndex(value, length) { + var type = typeof value; length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && - (typeof value == 'number' || reIsUint.test(value)) && - (value > -1 && value % 1 == 0 && value < length); + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); } module.exports = isIndex; @@ -9483,71 +9478,8 @@ module.exports = invariant; /***/ }), /* 167 */, -/* 168 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/* WEBPACK VAR INJECTION */(function(global, module) { - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _ponyfill = __webpack_require__(169); - -var _ponyfill2 = _interopRequireDefault(_ponyfill); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -var root; /* global window */ - - -if (typeof self !== 'undefined') { - root = self; -} else if (typeof window !== 'undefined') { - root = window; -} else if (typeof global !== 'undefined') { - root = global; -} else if (true) { - root = module; -} else { - root = Function('return this')(); -} - -var result = (0, _ponyfill2['default'])(root); -exports['default'] = result; -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(792), __webpack_require__(793)(module))) - -/***/ }), -/* 169 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports['default'] = symbolObservablePonyfill; -function symbolObservablePonyfill(root) { - var result; - var _Symbol = root.Symbol; - - if (typeof _Symbol === 'function') { - if (_Symbol.observable) { - result = _Symbol.observable; - } else { - result = _Symbol('observable'); - _Symbol.observable = result; - } - } else { - result = '@@observable'; - } - - return result; -}; - -/***/ }), +/* 168 */, +/* 169 */, /* 170 */, /* 171 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { @@ -13927,7 +13859,7 @@ module.exports = "` line comment - this.skipLineComment(3); - this.skipSpace(); - return this.nextToken(); - } - return this.finishOp(types.incDec, 2); - } - - if (next === 61) { - return this.finishOp(types.assign, 2); - } else { - return this.finishOp(types.plusMin, 1); - } - }; - - Tokenizer.prototype.readToken_lt_gt = function readToken_lt_gt(code) { - // '<>' - var next = this.input.charCodeAt(this.state.pos + 1); - var size = 1; - - if (next === code) { - size = code === 62 && this.input.charCodeAt(this.state.pos + 2) === 62 ? 3 : 2; - if (this.input.charCodeAt(this.state.pos + size) === 61) return this.finishOp(types.assign, size + 1); - return this.finishOp(types.bitShift, size); - } - - if (next === 33 && code === 60 && this.input.charCodeAt(this.state.pos + 2) === 45 && this.input.charCodeAt(this.state.pos + 3) === 45) { - if (this.inModule) this.unexpected(); - // `` line comment + this.skipLineComment(3); + this.skipSpace(); + this.nextToken(); + return; } - this.parseImport(_bodyNode); + this.finishOp(types.incDec, 2); + return; + } + + if (next === 61) { + this.finishOp(types.assign, 2); } else { - this.expectContextual("declare", "Only declares and type imports are allowed inside declare module"); + this.finishOp(types.plusMin, 1); + } + }; - _bodyNode = this.flowParseDeclare(_bodyNode, true); + _proto.readToken_lt_gt = function readToken_lt_gt(code) { + // '<>' + var next = this.input.charCodeAt(this.state.pos + 1); + var size = 1; + + if (next === code) { + size = code === 62 && this.input.charCodeAt(this.state.pos + 2) === 62 ? 3 : 2; + + if (this.input.charCodeAt(this.state.pos + size) === 61) { + this.finishOp(types.assign, size + 1); + return; + } + + this.finishOp(types.bitShift, size); + return; } - body.push(_bodyNode); - } - this.expect(types.braceR); + if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.state.pos + 2) === 45 && this.input.charCodeAt(this.state.pos + 3) === 45) { + // ` diff --git a/devtools/client/debugger/new/test/mochitest/head.js b/devtools/client/debugger/new/test/mochitest/head.js index ae02a04f64f9..cae2a2d39e76 100644 --- a/devtools/client/debugger/new/test/mochitest/head.js +++ b/devtools/client/debugger/new/test/mochitest/head.js @@ -943,7 +943,7 @@ const selectors = { editorFooter: ".editor-pane .source-footer", sourceNode: i => `.sources-list .tree-node:nth-child(${i}) .node`, sourceNodes: ".sources-list .tree-node", - sourceArrow: i => `.sources-list .tree-node:nth-child(${i}) .arrow`, + sourceDirectoryLabel: i => `.sources-list .tree-node:nth-child(${i}) .label`, resultItems: ".result-list .result-item", fileMatch: ".managed-tree .result", popup: ".popover", diff --git a/devtools/client/locales/en-US/debugger.properties b/devtools/client/locales/en-US/debugger.properties index 424e5146ee1b..fb26f29444e2 100644 --- a/devtools/client/locales/en-US/debugger.properties +++ b/devtools/client/locales/en-US/debugger.properties @@ -48,6 +48,10 @@ copyStackTrace.accesskey=c # that expands the left and right panes in the debugger UI. expandPanes=Expand panes +# LOCALIZATION NOTE (evaluateInConsole.label): Editor right-click menu item +# to execute selected text in browser console. +evaluateInConsole.label=Evaluate in console + # LOCALIZATION NOTE (pauseButtonTooltip): The tooltip that is displayed for the pause # button when the debugger is in a running state. pauseButtonTooltip=Pause %S diff --git a/devtools/client/shared/vendor/WASMPARSER_UPGRADING b/devtools/client/shared/vendor/WASMPARSER_UPGRADING index 043ed4377cac..f7168833bbc1 100644 --- a/devtools/client/shared/vendor/WASMPARSER_UPGRADING +++ b/devtools/client/shared/vendor/WASMPARSER_UPGRADING @@ -1,13 +1,13 @@ # wasmparser version -Current vesion is: 0.5.2 +Current vesion is: 0.5.3 # Upgrade process 1. Pull latest release from npm and extract WasmDis.js and WasmParser.js, e.g. ``` -curl https://registry.npmjs.org/wasmparser/-/wasmparser-0.5.2.tgz | tar -x --strip-components 2 package/dist/{WasmDis,WasmParser}.js +curl https://registry.npmjs.org/wasmparser/-/wasmparser-0.5.3.tgz | tar -x --strip-components 2 package/dist/{WasmDis,WasmParser}.js ``` 2. Remove reference to source maps (last line) diff --git a/devtools/client/shared/vendor/WasmDis.js b/devtools/client/shared/vendor/WasmDis.js index b34526ceaff9..fbb528f50f99 100644 --- a/devtools/client/shared/vendor/WasmDis.js +++ b/devtools/client/shared/vendor/WasmDis.js @@ -201,7 +201,7 @@ function getOperatorName(code) { } return operatorCodeNamesCache[code]; } -var DefaultNameResolver = (function () { +var DefaultNameResolver = /** @class */ (function () { function DefaultNameResolver() { } DefaultNameResolver.prototype.getTypeName = function (index, isRef) { @@ -229,7 +229,7 @@ var DefaultNameResolver = (function () { return DefaultNameResolver; }()); exports.DefaultNameResolver = DefaultNameResolver; -var NumericNameResolver = (function () { +var NumericNameResolver = /** @class */ (function () { function NumericNameResolver() { } NumericNameResolver.prototype.getTypeName = function (index, isRef) { @@ -256,7 +256,7 @@ var NumericNameResolver = (function () { return NumericNameResolver; }()); exports.NumericNameResolver = NumericNameResolver; -var LineBuffer = (function () { +var LineBuffer = /** @class */ (function () { function LineBuffer() { this._firstPart = ''; this._secondPart = ''; @@ -325,7 +325,7 @@ var LabelMode; LabelMode[LabelMode["WhenUsed"] = 1] = "WhenUsed"; LabelMode[LabelMode["Always"] = 2] = "Always"; })(LabelMode = exports.LabelMode || (exports.LabelMode = {})); -var WasmDisassembler = (function () { +var WasmDisassembler = /** @class */ (function () { function WasmDisassembler() { this._lines = []; this._offsets = []; @@ -421,7 +421,7 @@ var WasmDisassembler = (function () { for (var i = 0; i < b.length; i++) { var byte = b[i]; if (byte < 0x20 || byte >= 0x7F || - byte == 0x22 || byte == 0x5c) { + byte == /* " */ 0x22 || byte == /* \ */ 0x5c) { this.appendBuffer('\\' + (byte >> 4).toString(16) + (byte & 15).toString(16)); } else { @@ -450,7 +450,7 @@ var WasmDisassembler = (function () { return backrefLabel.label || '' + depth; }; WasmDisassembler.prototype.printOperator = function (operator) { - var code = operator.code | 0; + var code = operator.code; this.appendBuffer(getOperatorName(code)); switch (code) { case 2 /* block */: diff --git a/devtools/client/shared/vendor/WasmParser.js b/devtools/client/shared/vendor/WasmParser.js index 9f24c097a4ec..5852ede7c4b2 100644 --- a/devtools/client/shared/vendor/WasmParser.js +++ b/devtools/client/shared/vendor/WasmParser.js @@ -381,7 +381,7 @@ var BinaryReaderState; BinaryReaderState[BinaryReaderState["RELOC_SECTION_ENTRY"] = 42] = "RELOC_SECTION_ENTRY"; BinaryReaderState[BinaryReaderState["SOURCE_MAPPING_URL"] = 43] = "SOURCE_MAPPING_URL"; })(BinaryReaderState = exports.BinaryReaderState || (exports.BinaryReaderState = {})); -var DataRange = (function () { +var DataRange = /** @class */ (function () { function DataRange(start, end) { this.start = start; this.end = end; @@ -392,7 +392,7 @@ var DataRange = (function () { }; return DataRange; }()); -var Int64 = (function () { +var Int64 = /** @class */ (function () { function Int64(data) { this._data = data || new Uint8Array(8); } @@ -424,7 +424,7 @@ var Int64 = (function () { return Int64; }()); exports.Int64 = Int64; -var BinaryReader = (function () { +var BinaryReader = /** @class */ (function () { function BinaryReader() { this._data = null; this._pos = 0; @@ -1138,7 +1138,7 @@ var BinaryReader = (function () { if (!this._eof && pos + MAX_CODE_OPERATOR_SIZE > this._length) { return false; } - var code = this._data[this._pos++] | 0; + var code = this._data[this._pos++]; var blockType, brDepth, brTable, funcIndex, typeIndex, localIndex, globalIndex, memoryAddress, literal, reserved; switch (code) { case 2 /* block */: diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index 813bbfaa7396..6130b4efc8f9 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -284,9 +284,6 @@ MediaDecoder::Shutdown() DiscardOngoingSeekIfExists(); -#ifdef NIGHTLY_BUILD - DUMP("[DEBUG SHUTDOWN] %s: decoder=%p state machine=%p", __func__, this, mDecoderStateMachine.get()); -#endif // This changes the decoder state to SHUTDOWN and does other things // necessary to unblock the state machine thread if it's blocked, so // the asynchronous shutdown in nsDestroyStateMachine won't deadlock. diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 03b0e8157520..d73bfdbea90b 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -86,12 +86,6 @@ using namespace mozilla::media; #define SLOGW(x, ...) NS_WARNING(nsPrintfCString(SFMT(x, ##__VA_ARGS__)).get()) #define SLOGE(x, ...) NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString(SFMT(x, ##__VA_ARGS__)).get(), nullptr, __FILE__, __LINE__) -#ifdef NIGHTLY_BUILD -#define DEBUG_SHUTDOWN(fmt, ...) printf_stderr("[DEBUG SHUTDOWN] %s: " fmt "\n", __func__, ##__VA_ARGS__) -#else -#define DEBUG_SHUTDOWN(...) do { } while (0) -#endif - // Certain constants get stored as member variables and then adjusted by various // scale factors on a per-decoder basis. We want to make sure to avoid using these // constants directly, so we put them in a namespace. @@ -2663,8 +2657,6 @@ ShutdownState::Enter() // Shut down the watch manager to stop further notifications. master->mWatchManager.Shutdown(); - DEBUG_SHUTDOWN("state machine=%p reader=%p", this, Reader()); - return Reader()->Shutdown()->Then( OwnerThread(), __func__, master, &MediaDecoderStateMachine::FinishShutdown, @@ -3499,7 +3491,6 @@ MediaDecoderStateMachine::FinishShutdown() { MOZ_ASSERT(OnTaskQueue()); LOG("Shutting down state machine task queue"); - DEBUG_SHUTDOWN("state machine=%p", this); return OwnerThread()->BeginShutdown(); } diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index dd0b483fe40b..47f40b5f68e3 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -46,12 +46,6 @@ mozilla::LazyLogModule gMediaDemuxerLog("MediaDemuxer"); #define NS_DispatchToMainThread(...) CompileError_UseAbstractMainThreadInstead -#ifdef NIGHTLY_BUILD -#define DEBUG_SHUTDOWN(fmt, ...) printf_stderr("[DEBUG SHUTDOWN] %s: " fmt "\n", __func__, ##__VA_ARGS__) -#else -#define DEBUG_SHUTDOWN(...) do { } while (0) -#endif - namespace mozilla { @@ -455,7 +449,6 @@ MediaFormatReader::ShutdownPromisePool::Shutdown() { MOZ_DIAGNOSTIC_ASSERT(!mShutdown); mShutdown = true; - DEBUG_SHUTDOWN("pool=%p count=%d", this, mPromises.Count()); if (mPromises.Count() == 0) { mOnShutdownComplete->Resolve(true, __func__); } @@ -473,7 +466,6 @@ MediaFormatReader::ShutdownPromisePool::Track(RefPtr aPromise) [aPromise, this]() { MOZ_DIAGNOSTIC_ASSERT(mPromises.Contains(aPromise)); mPromises.RemoveEntry(aPromise); - DEBUG_SHUTDOWN("pool=%p shutdown=%s count=%d", this, mShutdown ? "true" : "false", mPromises.Count()); if (mShutdown && mPromises.Count() == 0) { mOnShutdownComplete->Resolve(true, __func__); } @@ -490,7 +482,6 @@ MediaFormatReader::DecoderData::ShutdownDecoder() return; } - DEBUG_SHUTDOWN("decoder: '%s' (%p) flush:%d", mDecoder->GetDescriptionName().get(), mDecoder.get(), mFlushing); if (mFlushing) { // Flush is is in action. Shutdown will be initiated after flush completes. MOZ_DIAGNOSTIC_ASSERT(mShutdownPromise); @@ -1391,7 +1382,6 @@ MediaFormatReader::Shutdown() ShutdownDecoder(TrackInfo::kVideoTrack); } - DEBUG_SHUTDOWN("reader=%p shutdown demuxer=%p", this, mDemuxer.get()); mShutdownPromisePool->Track(mDemuxer->Shutdown()); mDemuxer = nullptr; @@ -1426,13 +1416,11 @@ MediaFormatReader::TearDownDecoders() mAudio.mTaskQueue->BeginShutdown(); mAudio.mTaskQueue->AwaitShutdownAndIdle(); mAudio.mTaskQueue = nullptr; - DEBUG_SHUTDOWN("reader=%p shut down audio task queue", this); } if (mVideo.mTaskQueue) { mVideo.mTaskQueue->BeginShutdown(); mVideo.mTaskQueue->AwaitShutdownAndIdle(); mVideo.mTaskQueue = nullptr; - DEBUG_SHUTDOWN("reader=%p shut down video task queue", this); } mDecoderFactory = nullptr; diff --git a/dom/media/MediaShutdownManager.cpp b/dom/media/MediaShutdownManager.cpp index ba3569c62a98..829589504d7c 100644 --- a/dom/media/MediaShutdownManager.cpp +++ b/dom/media/MediaShutdownManager.cpp @@ -19,12 +19,6 @@ extern LazyLogModule gMediaDecoderLog; #define DECODER_LOG(type, msg) MOZ_LOG(gMediaDecoderLog, type, msg) #define LOGW(...) NS_WARNING(nsPrintfCString(__VA_ARGS__).get()) -#ifdef NIGHTLY_BUILD -#define DEBUG_SHUTDOWN(fmt, ...) printf_stderr("[DEBUG SHUTDOWN] %s: " fmt "\n", __func__, ##__VA_ARGS__) -#else -#define DEBUG_SHUTDOWN(...) do { } while (0) -#endif - NS_IMPL_ISUPPORTS(MediaShutdownManager, nsIAsyncShutdownBlocker) MediaShutdownManager::MediaShutdownManager() @@ -124,7 +118,6 @@ MediaShutdownManager::Register(MediaDecoder* aDecoder) // that's not going to work. MOZ_ASSERT(!mDecoders.Contains(aDecoder)); mDecoders.PutEntry(aDecoder); - DEBUG_SHUTDOWN("decoder=%p, count=%d", aDecoder, mDecoders.Count()); MOZ_ASSERT(mDecoders.Contains(aDecoder)); MOZ_ASSERT(mDecoders.Count() > 0); return NS_OK; @@ -138,7 +131,6 @@ MediaShutdownManager::Unregister(MediaDecoder* aDecoder) return; } mDecoders.RemoveEntry(aDecoder); - DEBUG_SHUTDOWN("decoder=%p, count=%d", aDecoder, mDecoders.Count()); if (sInitPhase == XPCOMShutdownStarted && mDecoders.Count() == 0) { RemoveBlocker(); } diff --git a/dom/media/platforms/android/RemoteDataDecoder.cpp b/dom/media/platforms/android/RemoteDataDecoder.cpp index fa546207af64..0855183aeba3 100644 --- a/dom/media/platforms/android/RemoteDataDecoder.cpp +++ b/dom/media/platforms/android/RemoteDataDecoder.cpp @@ -19,12 +19,6 @@ #include -#ifdef NIGHTLY_BUILD -#define DEBUG_SHUTDOWN(fmt, ...) printf_stderr("[DEBUG SHUTDOWN] %s: " fmt "\n", __func__, ##__VA_ARGS__) -#else -#define DEBUG_SHUTDOWN(...) do { } while (0) -#endif - #undef LOG #define LOG(arg, ...) \ MOZ_LOG(sAndroidDecoderModuleLog, \ @@ -542,7 +536,6 @@ RemoteDataDecoder::ProcessShutdown() mFormat = nullptr; - DEBUG_SHUTDOWN("decoder=%p mime=%s", this, mMimeType.get()); return ShutdownPromise::CreateAndResolve(true, __func__); } diff --git a/dom/media/test/reftest/reftest.list b/dom/media/test/reftest/reftest.list index 4e0b4446e39d..b76aa5d3c147 100644 --- a/dom/media/test/reftest/reftest.list +++ b/dom/media/test/reftest/reftest.list @@ -1,4 +1,4 @@ skip-if(Android) fuzzy-if(OSX,22,49977) skip-if(winWidget) fuzzy-if(gtkWidget&&layersGPUAccelerated,70,600) HTTP(..) == short.mp4.firstframe.html short.mp4.firstframe-ref.html skip-if(Android) fuzzy-if(OSX,23,51392) fuzzy-if(winWidget,59,76797) fuzzy-if(gtkWidget&&layersGPUAccelerated,60,1800) HTTP(..) == short.mp4.lastframe.html short.mp4.lastframe-ref.html skip-if(Android) skip-if(winWidget) fuzzy-if(gtkWidget&&layersGPUAccelerated,55,4281) fuzzy-if(OSX,3,111852) HTTP(..) == bipbop_300_215kbps.mp4.lastframe.html bipbop_300_215kbps.mp4.lastframe-ref.html -skip-if(Android) fuzzy-if(OSX,25,175921) fuzzy-if(winWidget,64,179198) HTTP(..) == gizmo.mp4.seek.html gizmo.mp4.55thframe-ref.html +skip-if(Android) fuzzy-if(OSX,25,175921) fuzzy-if(winWidget,71,179198) HTTP(..) == gizmo.mp4.seek.html gizmo.mp4.55thframe-ref.html diff --git a/js/src/jit-test/tests/wasm/profiling.js b/js/src/jit-test/tests/wasm/profiling.js index 73a8a52878b8..c37964600966 100644 --- a/js/src/jit-test/tests/wasm/profiling.js +++ b/js/src/jit-test/tests/wasm/profiling.js @@ -151,10 +151,7 @@ for (let type of ['f32', 'f64']) { (export "" $foo) )`, WebAssembly.RuntimeError, - // Technically we have this one *one-instruction* interval where - // the caller is lost (the stack with "1,>"). It's annoying to fix and shouldn't - // mess up profiles in practice so we ignore it. - ["", ">", "0,>", "1,0,>", "1,>", "trap handling,0,>", "", ">", ""]); + ["", ">", "0,>", "1,0,>", ">", "", ">", ""]); })(); (function() { diff --git a/js/src/jit-test/tests/wasm/regress/debug-clone-segment.js b/js/src/jit-test/tests/wasm/regress/debug-clone-segment.js new file mode 100644 index 000000000000..adf779210921 --- /dev/null +++ b/js/src/jit-test/tests/wasm/regress/debug-clone-segment.js @@ -0,0 +1,34 @@ +var mod = new WebAssembly.Module(wasmTextToBinary(` + (module + (func (export "func_0") (result i32) + call 0 + ) + ) +`)); + +var g = newGlobal(); +g.parent = this; +g.eval("(" + function() { + var dbg = Debugger(parent); + dbg.onEnterFrame = function(frame) {} +} + ")()"); + +processModule(mod); +processModule(mod); +processModule(mod); +processModule(mod); + +mod = new WebAssembly.Module(wasmTextToBinary(` +(module (export "func_0" $func1) (func $func1)) +`)); + +processModule(mod); +processModule(mod); +processModule(mod); +processModule(mod); + +function processModule(module) { + try { + new WebAssembly.Instance(module).exports.func_0(); + } catch(ex) {} +} diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 5040869a4c0a..f3da08596ac0 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -5075,11 +5075,8 @@ CodeGenerator::visitCallDirectEval(LCallDirectEval* lir) } void -CodeGenerator::generateArgumentsChecks(bool bailout) +CodeGenerator::generateArgumentsChecks(bool assert) { - // Registers safe for use before generatePrologue(). - static const uint32_t EntryTempMask = Registers::TempMask & ~(1 << OsrFrameReg.code()); - // This function can be used the normal way to check the argument types, // before entering the function and bailout when arguments don't match. // For debug purpose, this is can also be used to force/check that the @@ -5089,7 +5086,7 @@ CodeGenerator::generateArgumentsChecks(bool bailout) MResumePoint* rp = mir.entryResumePoint(); // No registers are allocated yet, so it's safe to grab anything. - Register temp = AllocatableGeneralRegisterSet(EntryTempMask).getAny(); + Register temp = AllocatableGeneralRegisterSet(GeneralRegisterSet::All()).getAny(); const CompileInfo& info = gen->info(); @@ -5110,9 +5107,8 @@ CodeGenerator::generateArgumentsChecks(bool bailout) } if (miss.used()) { - if (bailout) { - bailoutFrom(&miss, graph.entrySnapshot()); - } else { + if (assert) { +#ifdef DEBUG Label success; masm.jump(&success); masm.bind(&miss); @@ -5135,6 +5131,11 @@ CodeGenerator::generateArgumentsChecks(bool bailout) masm.assumeUnreachable("Argument check fail."); masm.bind(&success); +#else + MOZ_CRASH("Shouldn't get here in opt builds"); +#endif + } else { + bailoutFrom(&miss, graph.entrySnapshot()); } } } @@ -5376,6 +5377,7 @@ CodeGenerator::branchIfInvalidated(Register temp, Label* invalidated) invalidated); } +#ifdef DEBUG void CodeGenerator::emitAssertObjectOrStringResult(Register input, MIRType type, const TemporaryTypeSet* typeset) { @@ -5506,7 +5508,6 @@ CodeGenerator::emitAssertResultV(const ValueOperand input, const TemporaryTypeSe masm.pop(temp1); } -#ifdef DEBUG void CodeGenerator::emitObjectOrStringResultChecks(LInstruction* lir, MDefinition* mir) { @@ -9891,7 +9892,7 @@ CodeGenerator::generate() #ifdef DEBUG // Assert that the argument types are correct. - generateArgumentsChecks(/* bailout = */ false); + generateArgumentsChecks(/* assert = */ true); #endif // Reset native => bytecode map table with top-level script and startPc. @@ -12558,17 +12559,24 @@ CodeGenerator::emitAssertRangeD(const Range* r, FloatRegister input, FloatRegist void CodeGenerator::visitAssertResultV(LAssertResultV* ins) { +#ifdef DEBUG const ValueOperand value = ToValue(ins, LAssertResultV::Input); emitAssertResultV(value, ins->mirRaw()->resultTypeSet()); +#else + MOZ_CRASH("LAssertResultV is debug only"); +#endif } void CodeGenerator::visitAssertResultT(LAssertResultT* ins) { +#ifdef DEBUG Register input = ToRegister(ins->input()); MDefinition* mir = ins->mirRaw(); - emitAssertObjectOrStringResult(input, mir->type(), mir->resultTypeSet()); +#else + MOZ_CRASH("LAssertResultT is debug only"); +#endif } void diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h index 41ead42ff4d3..2a0cb1ab2024 100644 --- a/js/src/jit/CodeGenerator.h +++ b/js/src/jit/CodeGenerator.h @@ -63,7 +63,7 @@ class OutOfLineNaNToZero; class CodeGenerator final : public CodeGeneratorSpecific { - void generateArgumentsChecks(bool bailout = true); + void generateArgumentsChecks(bool assert = false); MOZ_MUST_USE bool generateBody(); ConstantOrRegister toConstantOrRegister(LInstruction* lir, size_t n, MIRType type); @@ -455,8 +455,11 @@ class CodeGenerator final : public CodeGeneratorSpecific void visitAssertResultV(LAssertResultV* ins); void visitAssertResultT(LAssertResultT* ins); + +#ifdef DEBUG void emitAssertResultV(const ValueOperand output, const TemporaryTypeSet* typeset); void emitAssertObjectOrStringResult(Register input, MIRType type, const TemporaryTypeSet* typeset); +#endif void visitInterruptCheck(LInterruptCheck* lir); void visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit* ins); diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index fd8ece73c963..502fe19011fc 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -4658,18 +4658,30 @@ LIRGenerator::visitWasmStackArg(MWasmStackArg* ins) } } -void -LIRGenerator::visitWasmCall(MWasmCall* ins) +template +LInstruction* +LIRGenerator::lowerWasmCall(MWasmCall* ins, bool needsBoundsCheck) { - LAllocation* args = gen->allocate(ins->numOperands()); - if (!args) { + auto* lir = new(alloc()) LClass(ins->numOperands(), needsBoundsCheck); + if (!lir->init(alloc())) { abort(AbortReason::Alloc, "Couldn't allocate for MWasmCall"); - return; + return nullptr; } for (unsigned i = 0; i < ins->numArgs(); i++) - args[i] = useFixedAtStart(ins->getOperand(i), ins->registerForArg(i)); + lir->setOperand(i, useFixedAtStart(ins->getOperand(i), ins->registerForArg(i))); + if (ins->callee().isTable()) { + MDefinition* index = ins->getOperand(ins->numArgs()); + lir->setOperand(ins->numArgs(), useFixedAtStart(index, WasmTableCallIndexReg)); + } + + return lir; +} + +void +LIRGenerator::visitWasmCall(MWasmCall* ins) +{ bool needsBoundsCheck = true; if (ins->callee().isTable()) { MDefinition* index = ins->getOperand(ins->numArgs()); @@ -4678,17 +4690,17 @@ LIRGenerator::visitWasmCall(MWasmCall* ins) if (uint32_t(index->toConstant()->toInt32()) < ins->callee().wasmTableMinLength()) needsBoundsCheck = false; } - - args[ins->numArgs()] = useFixedAtStart(index, WasmTableCallIndexReg); } LInstruction* lir; if (ins->type() == MIRType::Int64) - lir = new(alloc()) LWasmCallI64(args, ins->numOperands(), needsBoundsCheck); + lir = lowerWasmCall(ins, needsBoundsCheck); else if (ins->type() == MIRType::None) - lir = new(alloc()) LWasmCallVoid(args, ins->numOperands(), needsBoundsCheck); + lir = lowerWasmCall(ins, needsBoundsCheck); else - lir = new(alloc()) LWasmCall(args, ins->numOperands(), needsBoundsCheck); + lir = lowerWasmCall(ins, needsBoundsCheck); + if (!lir) + return; if (ins->type() == MIRType::None) add(lir, ins); diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h index 54b649a4f129..64128afbf9a8 100644 --- a/js/src/jit/Lowering.h +++ b/js/src/jit/Lowering.h @@ -63,6 +63,9 @@ class LIRGenerator : public LIRGeneratorSpecific MOZ_MUST_USE bool lowerCallArguments(MCall* call); + template + LInstruction* lowerWasmCall(MWasmCall* ins, bool needsBoundsCheck); + public: MOZ_MUST_USE bool visitInstruction(MInstruction* ins); MOZ_MUST_USE bool visitBlock(MBasicBlock* block); diff --git a/js/src/jit/MacroAssembler-inl.h b/js/src/jit/MacroAssembler-inl.h index 4425afeb074d..0a00dbc35f03 100644 --- a/js/src/jit/MacroAssembler-inl.h +++ b/js/src/jit/MacroAssembler-inl.h @@ -548,27 +548,6 @@ MacroAssembler::branchTestProxyHandlerFamily(Condition cond, Register proxy, Reg branchPtr(cond, familyAddr, ImmPtr(handlerp), label); } -template -void -MacroAssembler::branchTestMIRType(Condition cond, const Value& val, MIRType type, Label* label) -{ - switch (type) { - case MIRType::Null: return branchTestNull(cond, val, label); - case MIRType::Undefined: return branchTestUndefined(cond, val, label); - case MIRType::Boolean: return branchTestBoolean(cond, val, label); - case MIRType::Int32: return branchTestInt32(cond, val, label); - case MIRType::String: return branchTestString(cond, val, label); - case MIRType::Symbol: return branchTestSymbol(cond, val, label); - case MIRType::Object: return branchTestObject(cond, val, label); - case MIRType::Double: return branchTestDouble(cond, val, label); - case MIRType::MagicOptimizedArguments: // Fall through. - case MIRType::MagicIsConstructing: - case MIRType::MagicHole: return branchTestMagic(cond, val, label); - default: - MOZ_CRASH("Bad MIRType"); - } -} - void MacroAssembler::branchTestNeedsIncrementalBarrier(Condition cond, Label* label) { diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp index 56441c8a704f..475fd4934744 100644 --- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -38,6 +38,46 @@ using JS::ToInt32; using mozilla::CheckedUint32; +template +static void +EmitTypeCheck(MacroAssembler& masm, Assembler::Condition cond, const T& src, TypeSet::Type type, + Label* label) +{ + if (type.isAnyObject()) { + masm.branchTestObject(cond, src, label); + return; + } + switch (type.primitive()) { + case JSVAL_TYPE_DOUBLE: + // TI double type includes int32. + masm.branchTestNumber(cond, src, label); + break; + case JSVAL_TYPE_INT32: + masm.branchTestInt32(cond, src, label); + break; + case JSVAL_TYPE_BOOLEAN: + masm.branchTestBoolean(cond, src, label); + break; + case JSVAL_TYPE_STRING: + masm.branchTestString(cond, src, label); + break; + case JSVAL_TYPE_SYMBOL: + masm.branchTestSymbol(cond, src, label); + break; + case JSVAL_TYPE_NULL: + masm.branchTestNull(cond, src, label); + break; + case JSVAL_TYPE_UNDEFINED: + masm.branchTestUndefined(cond, src, label); + break; + case JSVAL_TYPE_MAGIC: + masm.branchTestMagic(cond, src, label); + break; + default: + MOZ_CRASH("Unexpected type"); + } +} + template void MacroAssembler::guardTypeSet(const Source& address, const TypeSet* types, BarrierKind kind, Register scratch, Label* miss) @@ -64,40 +104,47 @@ MacroAssembler::guardTypeSet(const Source& address, const TypeSet* types, Barrie tests[0] = TypeSet::DoubleType(); } + unsigned numBranches = 0; + for (size_t i = 0; i < mozilla::ArrayLength(tests); i++) { + if (types->hasType(tests[i])) + numBranches++; + } + + if (!types->unknownObject() && types->getObjectCount() > 0) + numBranches++; + + if (numBranches == 0) { + MOZ_ASSERT(types->empty()); + jump(miss); + return; + } + Register tag = extractTag(address, scratch); // Emit all typed tests. - BranchType lastBranch; for (size_t i = 0; i < mozilla::ArrayLength(tests); i++) { if (!types->hasType(tests[i])) continue; - if (lastBranch.isInitialized()) - lastBranch.emit(*this); - lastBranch = BranchType(Equal, tag, tests[i], &matched); + if (--numBranches > 0) + EmitTypeCheck(*this, Equal, tag, tests[i], &matched); + else + EmitTypeCheck(*this, NotEqual, tag, tests[i], miss); } - // If this is the last check, invert the last branch. - if (types->hasType(TypeSet::AnyObjectType()) || !types->getObjectCount()) { - if (!lastBranch.isInitialized()) { - jump(miss); - return; - } - - lastBranch.invertCondition(); - lastBranch.relink(miss); - lastBranch.emit(*this); - + // If we don't have specific objects to check for, we're done. + if (numBranches == 0) { + MOZ_ASSERT(types->unknownObject() || types->getObjectCount() == 0); bind(&matched); return; } - if (lastBranch.isInitialized()) - lastBranch.emit(*this); - // Test specific objects. MOZ_ASSERT(scratch != InvalidReg); + + MOZ_ASSERT(numBranches == 1); branchTestObject(NotEqual, tag, miss); + if (kind != BarrierKind::TypeTagOnly) { Register obj = extractObject(address, scratch); guardObjectType(obj, types, scratch, miss); @@ -120,9 +167,12 @@ MacroAssembler::guardTypeSet(const Source& address, const TypeSet* types, Barrie bind(&matched); } -template +#ifdef DEBUG +// guardTypeSetMightBeIncomplete is only used in DEBUG builds. If this ever +// changes, we need to make sure it's Spectre-safe. void -MacroAssembler::guardTypeSetMightBeIncomplete(TypeSet* types, Register obj, Register scratch, Label* label) +MacroAssembler::guardTypeSetMightBeIncomplete(const TypeSet* types, Register obj, + Register scratch, Label* label) { // Type set guards might miss when an object's group changes. In this case // either its old group's properties will become unknown, or it will change @@ -153,6 +203,7 @@ MacroAssembler::guardTypeSetMightBeIncomplete(TypeSet* types, Register obj, Regi Imm32(OBJECT_FLAG_UNKNOWN_PROPERTIES), label); } } +#endif void MacroAssembler::guardObjectType(Register obj, const TypeSet* types, @@ -170,59 +221,59 @@ MacroAssembler::guardObjectType(Register obj, const TypeSet* types, // to trigger the barrier on the contents of type sets passed in here. Label matched; - BranchGCPtr lastBranch; - MOZ_ASSERT(!lastBranch.isInitialized()); + bool hasSingletons = false; bool hasObjectGroups = false; + unsigned numBranches = 0; + unsigned count = types->getObjectCount(); for (unsigned i = 0; i < count; i++) { - if (!types->getSingletonNoBarrier(i)) { - hasObjectGroups = hasObjectGroups || types->getGroupNoBarrier(i); - continue; + if (types->getGroupNoBarrier(i)) { + hasObjectGroups = true; + numBranches++; + } else if (types->getSingletonNoBarrier(i)) { + hasSingletons = true; + numBranches++; } + } - if (lastBranch.isInitialized()) { - comment("emit GC pointer checks"); - lastBranch.emit(*this); + if (numBranches == 0) { + jump(miss); + return; + } + + 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); } - - JSObject* object = types->getSingletonNoBarrier(i); - lastBranch = BranchGCPtr(Equal, obj, ImmGCPtr(object), &matched); } if (hasObjectGroups) { comment("has object groups"); - // We are possibly going to overwrite the obj register. So already - // emit the branch, since branch depends on previous value of obj - // register and there is definitely a branch following. So no need - // to invert the condition. - if (lastBranch.isInitialized()) - lastBranch.emit(*this); - lastBranch = BranchGCPtr(); // Note: Some platforms give the same register for obj and scratch. // Make sure when writing to scratch, the obj register isn't used anymore! loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch); for (unsigned i = 0; i < count; i++) { - if (!types->getGroupNoBarrier(i)) + ObjectGroup* group = types->getGroupNoBarrier(i); + if (!group) continue; - if (lastBranch.isInitialized()) - lastBranch.emit(*this); - - ObjectGroup* group = types->getGroupNoBarrier(i); - lastBranch = BranchGCPtr(Equal, scratch, ImmGCPtr(group), &matched); + if (--numBranches > 0) + branchPtr(Equal, scratch, ImmGCPtr(group), &matched); + else + branchPtr(NotEqual, scratch, ImmGCPtr(group), miss); } } - if (!lastBranch.isInitialized()) { - jump(miss); - return; - } - - lastBranch.invertCondition(); - lastBranch.relink(miss); - lastBranch.emit(*this); + MOZ_ASSERT(numBranches == 0); bind(&matched); } @@ -234,10 +285,6 @@ template void MacroAssembler::guardTypeSet(const ValueOperand& value, const Type template void MacroAssembler::guardTypeSet(const TypedOrValueRegister& value, const TypeSet* types, BarrierKind kind, Register scratch, Label* miss); -template void MacroAssembler::guardTypeSetMightBeIncomplete(const TemporaryTypeSet* types, - Register obj, Register scratch, - Label* label); - template static void StoreToTypedFloatArray(MacroAssembler& masm, int arrayType, const S& value, const T& dest, @@ -3292,47 +3339,34 @@ MacroAssembler::wasmEmitOldTrapOutOfLineCode() } } - if (site.trap == wasm::Trap::IndirectCallBadSig) { - // The indirect call bad-signature trap is a special case for two - // reasons: - // - the check happens in the very first instructions of the - // prologue, before the stack frame has been set up which messes - // up everything (stack depth computations, unwinding) - // - the check happens in the callee while the trap should be - // reported at the caller's call_indirect - // To solve both problems at once, the out-of-line path (far) jumps - // directly to the trap exit stub. This takes advantage of the fact - // that there is already a CallSite for call_indirect and the - // current pre-prologue stack/register state. - append(wasm::OldTrapFarJump(site.trap, farJumpWithPatch())); - } else { - // Inherit the frame depth of the trap site. This value is captured - // by the wasm::CallSite to allow unwinding this frame. - setFramePushed(site.framePushed); + MOZ_ASSERT(site.trap != wasm::Trap::IndirectCallBadSig); - // Align the stack for a nullary call. - size_t alreadyPushed = sizeof(wasm::Frame) + framePushed(); - size_t toPush = ABIArgGenerator().stackBytesConsumedSoFar(); - if (size_t dec = StackDecrementForCall(ABIStackAlignment, alreadyPushed, toPush)) - reserveStack(dec); + // Inherit the frame depth of the trap site. This value is captured + // by the wasm::CallSite to allow unwinding this frame. + setFramePushed(site.framePushed); - // To call the trap handler function, we must have the WasmTlsReg - // filled since this is the normal calling ABI. To avoid requiring - // every trapping operation to have the TLS register filled for the - // rare case that it takes a trap, we restore it from the frame on - // the out-of-line path. However, there are millions of out-of-line - // paths (viz. for loads/stores), so the load is factored out into - // the shared FarJumpIsland generated by patchCallSites. + // Align the stack for a nullary call. + size_t alreadyPushed = sizeof(wasm::Frame) + framePushed(); + size_t toPush = ABIArgGenerator().stackBytesConsumedSoFar(); + if (size_t dec = StackDecrementForCall(ABIStackAlignment, alreadyPushed, toPush)) + reserveStack(dec); - // Call the trap's exit, using the bytecode offset of the trap site. - // Note that this code is inside the same CodeRange::Function as the - // trap site so it's as if the trapping instruction called the - // trap-handling function. The frame iterator knows to skip the trap - // exit's frame so that unwinding begins at the frame and offset of - // the trapping instruction. - wasm::CallSiteDesc desc(site.offset, wasm::CallSiteDesc::OldTrapExit); - call(desc, site.trap); - } + // To call the trap handler function, we must have the WasmTlsReg + // filled since this is the normal calling ABI. To avoid requiring + // every trapping operation to have the TLS register filled for the + // rare case that it takes a trap, we restore it from the frame on + // the out-of-line path. However, there are millions of out-of-line + // paths (viz. for loads/stores), so the load is factored out into + // the shared FarJumpIsland generated by patchCallSites. + + // Call the trap's exit, using the bytecode offset of the trap site. + // Note that this code is inside the same CodeRange::Function as the + // trap site so it's as if the trapping instruction called the + // trap-handling function. The frame iterator knows to skip the trap + // exit's frame so that unwinding begins at the frame and offset of + // the trapping instruction. + wasm::CallSiteDesc desc(site.offset, wasm::CallSiteDesc::OldTrapExit); + call(desc, site.trap); #ifdef DEBUG // Traps do not return, so no need to freeStack(). @@ -3482,29 +3516,6 @@ MacroAssembler::loadWasmTlsRegFromFrame(Register dest) loadPtr(Address(getStackPointer(), framePushed() + offsetof(wasm::Frame, tls)), dest); } -void -MacroAssembler::BranchType::emit(MacroAssembler& masm) -{ - MOZ_ASSERT(isInitialized()); - MIRType mirType = MIRType::None; - - if (type_.isPrimitive()) { - if (type_.isMagicArguments()) - mirType = MIRType::MagicOptimizedArguments; - else - mirType = MIRTypeFromValueType(type_.primitive()); - } else if (type_.isAnyObject()) { - mirType = MIRType::Object; - } else { - MOZ_CRASH("Unknown conversion to mirtype"); - } - - if (mirType == MIRType::Double) - masm.branchTestNumber(cond(), reg(), jump()); - else - masm.branchTestMIRType(cond(), reg(), mirType, jump()); -} - void MacroAssembler::BranchGCPtr::emit(MacroAssembler& masm) { diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index c3341af1e8ff..3339c71617d8 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -303,30 +303,6 @@ class MacroAssembler : public MacroAssemblerSpecific void relink(Label* jump) { jump_ = jump; } - - virtual void emit(MacroAssembler& masm) = 0; - }; - - /* - * Creates a branch based on a specific TypeSet::Type. - * Note: emits number test (int/double) for TypeSet::DoubleType() - */ - class BranchType : public Branch - { - TypeSet::Type type_; - - public: - BranchType() - : Branch(), - type_(TypeSet::UnknownType()) - { } - - BranchType(Condition cond, Register reg, TypeSet::Type type, Label* jump) - : Branch(cond, reg, jump), - type_(type) - { } - - void emit(MacroAssembler& masm) override; }; /* @@ -347,7 +323,7 @@ class MacroAssembler : public MacroAssemblerSpecific ptr_(ptr) { } - void emit(MacroAssembler& masm) override; + void emit(MacroAssembler& masm); }; mozilla::Maybe autoRooter_; @@ -1208,9 +1184,6 @@ class MacroAssembler : public MacroAssemblerSpecific inline void branchTestProxyHandlerFamily(Condition cond, Register proxy, Register scratch, const void* handlerp, Label* label); - template - inline void branchTestMIRType(Condition cond, const Value& val, MIRType type, Label* label); - // Emit type case branch on tag matching if the type tag in the definition // might actually be that type. void maybeBranchTestType(MIRType type, MDefinition* maybeDef, Register tag, Label* label); @@ -1512,50 +1485,52 @@ class MacroAssembler : public MacroAssemblerSpecific // `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); + DEFINED_ON(arm, mips_shared); void wasmLoadI64(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, Register ptrScratch, Register64 output) - DEFINED_ON(arm); + DEFINED_ON(arm, mips32, mips64); void wasmStore(const wasm::MemoryAccessDesc& access, AnyRegister value, Register memoryBase, Register ptr, Register ptrScratch) - DEFINED_ON(arm); + DEFINED_ON(arm, mips_shared); void wasmStoreI64(const wasm::MemoryAccessDesc& access, Register64 value, Register memoryBase, Register ptr, Register ptrScratch) - DEFINED_ON(arm); + DEFINED_ON(arm, mips32, mips64); // `ptr` will always be updated. void wasmUnalignedLoad(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, Register ptrScratch, Register output, Register tmp) - DEFINED_ON(arm); + DEFINED_ON(arm, mips32, mips64); - // `ptr` will always be updated and `tmp1` is always needed. `tmp2` is + // ARM: `ptr` will always be updated and `tmp1` is always needed. `tmp2` is // needed for Float32; `tmp2` and `tmp3` are needed for Float64. Temps must // be Invalid when they are not needed. + // MIPS: `ptr` will always be updated. void wasmUnalignedLoadFP(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, Register ptrScratch, FloatRegister output, Register tmp1, Register tmp2, Register tmp3) - DEFINED_ON(arm); + DEFINED_ON(arm, mips32, mips64); // `ptr` will always be updated. void wasmUnalignedLoadI64(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, Register ptrScratch, Register64 output, Register tmp) - DEFINED_ON(arm); + DEFINED_ON(arm, mips32, mips64); - // `ptr` and `value` will always be updated. + // ARM: `ptr` and `value` will always be updated. 'tmp' must be Invalid. + // MIPS: `ptr` will always be updated. void wasmUnalignedStore(const wasm::MemoryAccessDesc& access, Register value, Register memoryBase, - Register ptr, Register ptrScratch) - DEFINED_ON(arm); + Register ptr, Register ptrScratch, Register tmp) + DEFINED_ON(arm, mips32, mips64); // `ptr` will always be updated. void wasmUnalignedStoreFP(const wasm::MemoryAccessDesc& access, FloatRegister floatValue, Register memoryBase, Register ptr, Register ptrScratch, Register tmp) - DEFINED_ON(arm); + DEFINED_ON(arm, mips32, mips64); // `ptr` will always be updated. void wasmUnalignedStoreI64(const wasm::MemoryAccessDesc& access, Register64 value, Register memoryBase, Register ptr, Register ptrScratch, Register tmp) - DEFINED_ON(arm); + DEFINED_ON(arm, mips32, mips64); // wasm specific methods, used in both the wasm baseline compiler and ion. @@ -1567,7 +1542,7 @@ class MacroAssembler : public MacroAssemblerSpecific Label* oolEntry) PER_SHARED_ARCH; void oolWasmTruncateCheckF64ToI32(FloatRegister input, Register output, TruncFlags flags, wasm::BytecodeOffset off, Label* rejoin) - DEFINED_ON(arm, arm64, x86_shared); + DEFINED_ON(arm, arm64, x86_shared, mips_shared); void wasmTruncateFloat32ToUInt32(FloatRegister input, Register output, bool isSaturating, Label* oolEntry) PER_ARCH; @@ -1575,29 +1550,29 @@ class MacroAssembler : public MacroAssemblerSpecific Label* oolEntry) PER_SHARED_ARCH; void oolWasmTruncateCheckF32ToI32(FloatRegister input, Register output, TruncFlags flags, wasm::BytecodeOffset off, Label* rejoin) - DEFINED_ON(arm, arm64, x86_shared); + DEFINED_ON(arm, arm64, x86_shared, mips_shared); // The truncate-to-int64 methods will always bind the `oolRejoin` label // after the last emitted instruction. void wasmTruncateDoubleToInt64(FloatRegister input, Register64 output, bool isSaturating, Label* oolEntry, Label* oolRejoin, FloatRegister tempDouble) - DEFINED_ON(arm64, x86, x64); + DEFINED_ON(arm64, x86, x64, mips64); void wasmTruncateDoubleToUInt64(FloatRegister input, Register64 output, bool isSaturating, Label* oolEntry, Label* oolRejoin, FloatRegister tempDouble) - DEFINED_ON(arm64, x86, x64); + DEFINED_ON(arm64, x86, x64, mips64); void oolWasmTruncateCheckF64ToI64(FloatRegister input, Register64 output, TruncFlags flags, wasm::BytecodeOffset off, Label* rejoin) - DEFINED_ON(arm, arm64, x86_shared); + DEFINED_ON(arm, arm64, x86_shared, mips_shared); void wasmTruncateFloat32ToInt64(FloatRegister input, Register64 output, bool isSaturating, Label* oolEntry, Label* oolRejoin, FloatRegister tempDouble) - DEFINED_ON(arm64, x86, x64); + DEFINED_ON(arm64, x86, x64, mips64); void wasmTruncateFloat32ToUInt64(FloatRegister input, Register64 output, bool isSaturating, Label* oolEntry, Label* oolRejoin, FloatRegister tempDouble) - DEFINED_ON(arm64, x86, x64); + DEFINED_ON(arm64, x86, x64, mips64); void oolWasmTruncateCheckF32ToI64(FloatRegister input, Register64 output, TruncFlags flags, wasm::BytecodeOffset off, Label* rejoin) - DEFINED_ON(arm, arm64, x86_shared); + DEFINED_ON(arm, arm64, x86_shared, mips_shared); // This function takes care of loading the callee's TLS and pinned regs but // it is the caller's responsibility to save/restore TLS or pinned regs. @@ -1955,8 +1930,10 @@ class MacroAssembler : public MacroAssemblerSpecific void guardObjectType(Register obj, const TypeSet* types, Register scratch, Label* miss); - template - void guardTypeSetMightBeIncomplete(TypeSet* types, Register obj, Register scratch, Label* label); +#ifdef DEBUG + void guardTypeSetMightBeIncomplete(const TypeSet* types, Register obj, Register scratch, + Label* label); +#endif void loadObjShape(Register objReg, Register dest) { loadPtr(Address(objReg, ShapedObject::offsetOfShape()), dest); diff --git a/js/src/jit/arm/Architecture-arm.h b/js/src/jit/arm/Architecture-arm.h index 969557a1760b..1dc8184761b5 100644 --- a/js/src/jit/arm/Architecture-arm.h +++ b/js/src/jit/arm/Architecture-arm.h @@ -151,9 +151,6 @@ class Registers (1 << Registers::lr) | (1 << Registers::pc); - // Registers that can be allocated without being saved, generally. - static const SetType TempMask = VolatileMask & ~NonAllocatableMask; - // Registers returned from a JS -> JS call. static const SetType JSCallMask = (1 << Registers::r2) | @@ -362,9 +359,6 @@ class FloatRegisters (1ULL << s30) | (1ULL << s31); - // Registers that can be allocated without being saved, generally. - static const SetType TempMask = VolatileMask & ~NonAllocatableMask; - static const SetType AllocatableMask = AllMask & ~NonAllocatableMask; }; diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp index 222dd714f265..8eabc5608219 100644 --- a/js/src/jit/arm/CodeGenerator-arm.cpp +++ b/js/src/jit/arm/CodeGenerator-arm.cpp @@ -2185,7 +2185,7 @@ CodeGeneratorARM::emitWasmUnalignedStore(T* lir) FloatRegister value = ToFloatRegister(lir->getOperand(LWasmUnalignedStore::ValueIndex)); masm.wasmUnalignedStoreFP(mir->access(), value, HeapReg, ptr, ptr, valOrTmp); } else { - masm.wasmUnalignedStore(mir->access(), valOrTmp, HeapReg, ptr, ptr); + masm.wasmUnalignedStore(mir->access(), valOrTmp, HeapReg, ptr, ptr, Register::Invalid()); } } diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp index 9a1734d40f36..4134a760a30b 100644 --- a/js/src/jit/arm/MacroAssembler-arm.cpp +++ b/js/src/jit/arm/MacroAssembler-arm.cpp @@ -5044,8 +5044,10 @@ MacroAssembler::wasmUnalignedLoadI64(const wasm::MemoryAccessDesc& access, Regis void MacroAssembler::wasmUnalignedStore(const wasm::MemoryAccessDesc& access, Register value, - Register memoryBase, Register ptr, Register ptrScratch) + Register memoryBase, Register ptr, Register ptrScratch, + Register tmp) { + MOZ_ASSERT(tmp == Register::Invalid()); wasmUnalignedStoreImpl(access, FloatRegister(), Register64::Invalid(), memoryBase, ptr, ptrScratch, value); } diff --git a/js/src/jit/arm/Simulator-arm.cpp b/js/src/jit/arm/Simulator-arm.cpp index 9feca8f36d00..0ac901f0ef84 100644 --- a/js/src/jit/arm/Simulator-arm.cpp +++ b/js/src/jit/arm/Simulator-arm.cpp @@ -1580,15 +1580,15 @@ Simulator::exclusiveMonitorClear() exclusiveMonitorHeld_ = false; } -bool -Simulator::startWasmInterrupt(JitActivation* activation) +JS::ProfilingFrameIterator::RegisterState +Simulator::registerState() { - JS::ProfilingFrameIterator::RegisterState state; + wasm::RegisterState state; state.pc = (void*) get_pc(); state.fp = (void*) get_register(fp); state.sp = (void*) get_register(sp); state.lr = (void*) get_register(lr); - return activation->startWasmInterrupt(state); + return state; } // The signal handler only redirects the PC to the interrupt stub when the PC is @@ -1608,7 +1608,7 @@ Simulator::handleWasmInterrupt() if (!wasm::InInterruptibleCode(cx_, pc, &ms)) return; - if (!startWasmInterrupt(cx_->activation()->asJit())) + if (!cx_->activation()->asJit()->startWasmInterrupt(registerState())) return; set_pc(int32_t(ms->interruptCode())); @@ -1646,12 +1646,17 @@ Simulator::handleWasmSegFault(int32_t addr, unsigned numBytes) const wasm::ModuleSegment* moduleSegment = segment->asModule(); wasm::Instance* instance = wasm::LookupFaultingInstance(*moduleSegment, pc, fp); - if (!instance || !instance->memoryAccessInGuardRegion((uint8_t*)addr, numBytes)) + if (!instance) + return false; + + MOZ_RELEASE_ASSERT(&instance->code() == &moduleSegment->code()); + + if (!instance->memoryAccessInGuardRegion((uint8_t*)addr, numBytes)) return false; const wasm::MemoryAccess* memoryAccess = instance->code().lookupMemoryAccess(pc); if (!memoryAccess) { - MOZ_ALWAYS_TRUE(startWasmInterrupt(act)); + MOZ_ALWAYS_TRUE(act->asJit()->startWasmInterrupt(registerState())); if (!instance->code().containsCodePC(pc)) MOZ_CRASH("Cannot map PC to trap handler"); set_pc(int32_t(moduleSegment->outOfBoundsCode())); @@ -1671,7 +1676,6 @@ Simulator::handleWasmIllFault() return false; void* pc = reinterpret_cast(get_pc()); - uint8_t* fp = reinterpret_cast(get_register(r11)); const wasm::CodeSegment* segment = wasm::LookupCodeSegment(pc); if (!segment || !segment->isModule()) @@ -1683,7 +1687,7 @@ Simulator::handleWasmIllFault() if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode)) return false; - act->startWasmTrap(trap, bytecode.offset, pc, fp); + act->startWasmTrap(trap, bytecode.offset, registerState()); set_pc(int32_t(moduleSegment->trapCode())); return true; } diff --git a/js/src/jit/arm/Simulator-arm.h b/js/src/jit/arm/Simulator-arm.h index f6a4a293848e..b8a33e679ee6 100644 --- a/js/src/jit/arm/Simulator-arm.h +++ b/js/src/jit/arm/Simulator-arm.h @@ -36,6 +36,7 @@ #include "jit/arm/Architecture-arm.h" #include "jit/arm/disasm/Disasm-arm.h" #include "jit/IonTypes.h" +#include "js/ProfilingFrameIterator.h" #include "threading/Thread.h" #include "vm/MutexIDs.h" #include "wasm/WasmCode.h" @@ -293,7 +294,7 @@ class Simulator // Handle a wasm interrupt triggered by an async signal handler. void handleWasmInterrupt(); - bool startWasmInterrupt(JitActivation* act); + JS::ProfilingFrameIterator::RegisterState registerState(); // Handle any wasm faults, returning true if the fault was handled. bool handleWasmSegFault(int32_t addr, unsigned numBytes); diff --git a/js/src/jit/arm64/Architecture-arm64.h b/js/src/jit/arm64/Architecture-arm64.h index 05e72b54fcd8..007315eedd09 100644 --- a/js/src/jit/arm64/Architecture-arm64.h +++ b/js/src/jit/arm64/Architecture-arm64.h @@ -171,9 +171,6 @@ class Registers { (1 << Registers::lr) | (1 << Registers::sp); - // Registers that can be allocated without being saved, generally. - static const SetType TempMask = VolatileMask & ~NonAllocatableMask; - static const SetType WrapperMask = VolatileMask; // Registers returned from a JS -> JS call. @@ -283,9 +280,6 @@ class FloatRegisters // d31 is the ScratchFloatReg. static const SetType NonAllocatableMask = (SetType(1) << FloatRegisters::d31) * SpreadCoefficient; - // Registers that can be allocated without being saved, generally. - static const SetType TempMask = VolatileMask & ~NonAllocatableMask; - static const SetType AllocatableMask = AllMask & ~NonAllocatableMask; union RegisterContent { float s; diff --git a/js/src/jit/mips-shared/Architecture-mips-shared.h b/js/src/jit/mips-shared/Architecture-mips-shared.h index 8c41cf23c384..76e033dd4d49 100644 --- a/js/src/jit/mips-shared/Architecture-mips-shared.h +++ b/js/src/jit/mips-shared/Architecture-mips-shared.h @@ -201,9 +201,6 @@ class Registers (1 << Registers::sp) | (1 << Registers::ra); - // Registers that can be allocated without being saved, generally. - static const SetType TempMask = VolatileMask & ~NonAllocatableMask; - // Registers returned from a JS -> JS call. static const SetType JSCallMask; diff --git a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp index af77ee1f7945..227f94bea3d6 100644 --- a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp +++ b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp @@ -1498,79 +1498,9 @@ CodeGeneratorMIPSShared::visitWasmTruncateToInt32(LWasmTruncateToInt32* lir) void CodeGeneratorMIPSShared::visitOutOfLineWasmTruncateCheck(OutOfLineWasmTruncateCheck* ool) { - FloatRegister input = ool->input(); - MIRType fromType = ool->fromType(); - MIRType toType = ool->toType(); - bool isUnsigned = ool->isUnsigned(); - // Eagerly take care of NaNs. - Label inputIsNaN; - if (fromType == MIRType::Double) - masm.branchDouble(Assembler::DoubleUnordered, input, input, &inputIsNaN); - else if (fromType == MIRType::Float32) - masm.branchFloat(Assembler::DoubleUnordered, input, input, &inputIsNaN); - else - MOZ_CRASH("unexpected type in visitOutOfLineWasmTruncateCheck"); - - // By default test for the following inputs and bail: - // signed: ] -Inf, INTXX_MIN - 1.0 ] and [ INTXX_MAX + 1.0 : +Inf [ - // unsigned: ] -Inf, -1.0 ] and [ UINTXX_MAX + 1.0 : +Inf [ - // Note: we cannot always represent those exact values. As a result - // this changes the actual comparison a bit. - double minValue, maxValue; - Assembler::DoubleCondition minCond = Assembler::DoubleLessThanOrEqual; - Assembler::DoubleCondition maxCond = Assembler::DoubleGreaterThanOrEqual; - if (toType == MIRType::Int64) { - if (isUnsigned) { - minValue = -1; - maxValue = double(UINT64_MAX) + 1.0; - } else { - // In the float32/double range there exists no value between - // INT64_MIN and INT64_MIN - 1.0. Making INT64_MIN the lower-bound. - minValue = double(INT64_MIN); - minCond = Assembler::DoubleLessThan; - maxValue = double(INT64_MAX) + 1.0; - } - } else { - if (isUnsigned) { - minValue = -1; - maxValue = double(UINT32_MAX) + 1.0; - } else { - if (fromType == MIRType::Float32) { - // In the float32 range there exists no value between - // INT32_MIN and INT32_MIN - 1.0. Making INT32_MIN the lower-bound. - minValue = double(INT32_MIN); - minCond = Assembler::DoubleLessThan; - } else { - minValue = double(INT32_MIN) - 1.0; - } - maxValue = double(INT32_MAX) + 1.0; - } - } - - Label fail; - - if (fromType == MIRType::Double) { - masm.loadConstantDouble(minValue, ScratchDoubleReg); - masm.branchDouble(minCond, input, ScratchDoubleReg, &fail); - - masm.loadConstantDouble(maxValue, ScratchDoubleReg); - masm.branchDouble(maxCond, input, ScratchDoubleReg, &fail); - } else { - masm.loadConstantFloat32(float(minValue), ScratchFloat32Reg); - masm.branchFloat(minCond, input, ScratchFloat32Reg, &fail); - - masm.loadConstantFloat32(float(maxValue), ScratchFloat32Reg); - masm.branchFloat(maxCond, input, ScratchFloat32Reg, &fail); - } - - masm.jump(ool->rejoin()); - - // Handle errors. - masm.bind(&fail); - masm.wasmTrap(wasm::Trap::IntegerOverflow, ool->bytecodeOffset()); - - masm.bind(&inputIsNaN); - masm.wasmTrap(wasm::Trap::InvalidConversionToInteger, ool->bytecodeOffset()); + masm.outOfLineWasmTruncateToIntCheck(ool->input(), ool->fromType(), ool->toType(), + ool->isUnsigned(), ool->rejoin(), + ool->bytecodeOffset()); } void @@ -1877,77 +1807,24 @@ CodeGeneratorMIPSShared::emitWasmLoad(T* lir) { const MWasmLoad* mir = lir->mir(); - uint32_t offset = mir->access().offset(); - MOZ_ASSERT(offset <= INT32_MAX); - - Register ptr = ToRegister(lir->ptr()); - - // Maybe add the offset. - if (offset) { - Register ptrPlusOffset = ToRegister(lir->ptrCopy()); - masm.addPtr(Imm32(offset), ptrPlusOffset); - ptr = ptrPlusOffset; - } else { - MOZ_ASSERT(lir->ptrCopy()->isBogusTemp()); + Register ptrScratch = InvalidReg; + if(!lir->ptrCopy()->isBogusTemp()){ + ptrScratch = ToRegister(lir->ptrCopy()); } - unsigned byteSize = mir->access().byteSize(); - bool isSigned; - bool isFloat = false; - - switch (mir->access().type()) { - case Scalar::Int8: isSigned = true; break; - case Scalar::Uint8: isSigned = false; break; - case Scalar::Int16: isSigned = true; break; - case Scalar::Uint16: isSigned = false; break; - case Scalar::Int32: isSigned = true; break; - case Scalar::Uint32: isSigned = false; break; - case Scalar::Float64: isFloat = true; break; - case Scalar::Float32: isFloat = true; break; - default: MOZ_CRASH("unexpected array type"); - } - - masm.memoryBarrierBefore(mir->access().sync()); - - BaseIndex address(HeapReg, ptr, TimesOne); - if (IsUnaligned(mir->access())) { - Register temp = ToRegister(lir->getTemp(1)); - - if (isFloat) { - FloatRegister output = ToFloatRegister(lir->output()); - - if (byteSize == 4) - masm.loadUnalignedFloat32(mir->access(), address, temp, output); - else - masm.loadUnalignedDouble(mir->access(), address, temp, output); + if (IsFloatingPointType(mir->type())) { + masm.wasmUnalignedLoadFP(mir->access(), HeapReg, ToRegister(lir->ptr()), ptrScratch, + ToFloatRegister(lir->output()), ToRegister(lir->getTemp(1)), + InvalidReg, InvalidReg); } else { - masm.ma_load_unaligned(mir->access(), ToRegister(lir->output()), address, temp, - static_cast(8 * byteSize), - isSigned ? SignExtend : ZeroExtend); - } - - masm.memoryBarrierAfter(mir->access().sync()); - return; - } - - if (isFloat) { - FloatRegister output = ToFloatRegister(lir->output()); - - if (byteSize == 4) { - masm.loadFloat32(address, output); - } else { - masm.computeScaledAddress(address, SecondScratchReg); - masm.as_ld(output, SecondScratchReg, 0); + masm.wasmUnalignedLoad(mir->access(), HeapReg, ToRegister(lir->ptr()), + ptrScratch, ToRegister(lir->output()), ToRegister(lir->getTemp(1))); } } else { - masm.ma_load(ToRegister(lir->output()), address, - static_cast(8 * byteSize), - isSigned ? SignExtend : ZeroExtend); + masm.wasmLoad(mir->access(), HeapReg, ToRegister(lir->ptr()), ptrScratch, + ToAnyRegister(lir->output())); } - masm.append(mir->access(), masm.size() - 4, masm.framePushed()); - - masm.memoryBarrierAfter(mir->access().sync()); } void @@ -1968,81 +1845,26 @@ CodeGeneratorMIPSShared::emitWasmStore(T* lir) { const MWasmStore* mir = lir->mir(); - uint32_t offset = mir->access().offset(); - MOZ_ASSERT(offset <= INT32_MAX); - - Register ptr = ToRegister(lir->ptr()); - - // Maybe add the offset. - if (offset) { - Register ptrPlusOffset = ToRegister(lir->ptrCopy()); - masm.addPtr(Imm32(offset), ptrPlusOffset); - ptr = ptrPlusOffset; - } else { - MOZ_ASSERT(lir->ptrCopy()->isBogusTemp()); + Register ptrScratch = InvalidReg; + if(!lir->ptrCopy()->isBogusTemp()){ + ptrScratch = ToRegister(lir->ptrCopy()); } - unsigned byteSize = mir->access().byteSize(); - bool isSigned; - bool isFloat = false; - - switch (mir->access().type()) { - case Scalar::Int8: isSigned = true; break; - case Scalar::Uint8: isSigned = false; break; - case Scalar::Int16: isSigned = true; break; - case Scalar::Uint16: isSigned = false; break; - case Scalar::Int32: isSigned = true; break; - case Scalar::Uint32: isSigned = false; break; - case Scalar::Int64: isSigned = true; break; - case Scalar::Float64: isFloat = true; break; - case Scalar::Float32: isFloat = true; break; - default: MOZ_CRASH("unexpected array type"); - } - - masm.memoryBarrierBefore(mir->access().sync()); - - BaseIndex address(HeapReg, ptr, TimesOne); - if (IsUnaligned(mir->access())) { - Register temp = ToRegister(lir->getTemp(1)); - - if (isFloat) { - FloatRegister value = ToFloatRegister(lir->value()); - - if (byteSize == 4) - masm.storeUnalignedFloat32(mir->access(), value, temp, address); - else - masm.storeUnalignedDouble(mir->access(), value, temp, address); + if (mir->access().type() == Scalar::Float32 || + mir->access().type() == Scalar::Float64) { + masm.wasmUnalignedStoreFP(mir->access(), ToFloatRegister(lir->value()), + HeapReg, ToRegister(lir->ptr()), ptrScratch, + ToRegister(lir->getTemp(1))); } else { - masm.ma_store_unaligned(mir->access(), ToRegister(lir->value()), address, temp, - static_cast(8 * byteSize), - isSigned ? SignExtend : ZeroExtend); - } - - masm.memoryBarrierAfter(mir->access().sync()); - return; - } - - if (isFloat) { - FloatRegister value = ToFloatRegister(lir->value()); - - if (byteSize == 4) { - masm.storeFloat32(value, address); - } else { - // For time being storeDouble for mips32 uses two store instructions, - // so we emit only one to get correct behavior in case of OOB access. - masm.computeScaledAddress(address, SecondScratchReg); - masm.as_sd(value, SecondScratchReg, 0); + masm.wasmUnalignedStore(mir->access(), ToRegister(lir->value()), HeapReg, + ToRegister(lir->ptr()), ptrScratch, + ToRegister(lir->getTemp(1))); } } else { - masm.ma_store(ToRegister(lir->value()), address, - static_cast(8 * byteSize), - isSigned ? SignExtend : ZeroExtend); + masm.wasmStore(mir->access(), ToAnyRegister(lir->value()), HeapReg, + ToRegister(lir->ptr()), ptrScratch); } - // Only the last emitted instruction is a memory access. - masm.append(mir->access(), masm.size() - 4, masm.framePushed()); - - masm.memoryBarrierAfter(mir->access().sync()); } void diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp index bf817c43681f..d29b05b0b76b 100644 --- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp +++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp @@ -328,16 +328,10 @@ template void MacroAssemblerMIPSShared::ma_addTestCarry(Register rd, Register rs, Register rt, L overflow) { - if (rd != rs) { - as_addu(rd, rs, rt); - as_sltu(SecondScratchReg, rd, rs); - ma_b(SecondScratchReg, SecondScratchReg, overflow, Assembler::NonZero); - } else { - ma_move(SecondScratchReg, rs); - as_addu(rd, rs, rt); - as_sltu(SecondScratchReg, rd, SecondScratchReg); - ma_b(SecondScratchReg, SecondScratchReg, overflow, Assembler::NonZero); - } + MOZ_ASSERT_IF(rd == rs, rt != rd); + as_addu(rd, rs, rt); + as_sltu(SecondScratchReg, rd, rd == rs? rt : rs); + ma_b(SecondScratchReg, SecondScratchReg, overflow, Assembler::NonZero); } template void @@ -709,7 +703,8 @@ MacroAssemblerMIPSShared::ma_store(Imm32 imm, const BaseIndex& dest, } void -MacroAssemblerMIPSShared::ma_store_unaligned(const wasm::MemoryAccessDesc& access, Register data, const BaseIndex& dest, Register temp, +MacroAssemblerMIPSShared::ma_store_unaligned(const wasm::MemoryAccessDesc& access, Register data, + const BaseIndex& dest, Register temp, LoadStoreSize size, LoadStoreExtension extension) { MOZ_ASSERT(MOZ_LITTLE_ENDIAN, "Wasm-only; wasm is disabled on big-endian."); @@ -1543,20 +1538,51 @@ MacroAssembler::call(JitCode* c) CodeOffset MacroAssembler::nopPatchableToCall(const wasm::CallSiteDesc& desc) { - MOZ_CRASH("NYI"); - return CodeOffset(); + CodeOffset offset(currentOffset()); + // MIPS32 //MIPS64 + as_nop(); // lui // lui + as_nop(); // ori // ori + as_nop(); // jalr // drotr32 + as_nop(); // ori +#ifdef JS_CODEGEN_MIPS64 + as_nop(); //jalr + as_nop(); +#endif + append(desc, CodeOffset(currentOffset())); + return offset; } void MacroAssembler::patchNopToCall(uint8_t* call, uint8_t* target) { - MOZ_CRASH("NYI"); +#ifdef JS_CODEGEN_MIPS64 + Instruction* inst = (Instruction*) call - 6 /* six nops */; + Assembler::WriteLoad64Instructions(inst, ScratchRegister, (uint64_t) target); + inst[4] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr); +#else + Instruction* inst = (Instruction*) call - 4 /* four nops */; + Assembler::WriteLuiOriInstructions(inst, &inst[1], ScratchRegister, (uint32_t) target); + inst[2] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr); +#endif } void MacroAssembler::patchCallToNop(uint8_t* call) { - MOZ_CRASH("NYI"); +#ifdef JS_CODEGEN_MIPS64 + Instruction* inst = (Instruction*) call - 6 /* six nops */; +#else + Instruction* inst = (Instruction*) call - 4 /* four nops */; +#endif + + inst[0].makeNop(); + inst[1].makeNop(); + inst[2].makeNop(); + inst[3].makeNop(); +#ifdef JS_CODEGEN_MIPS64 + inst[4].makeNop(); + inst[5].makeNop(); +#endif } void @@ -1642,6 +1668,293 @@ MacroAssembler::wasmTruncateFloat32ToInt32(FloatRegister input, Register output, ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual); } +void +MacroAssembler::oolWasmTruncateCheckF32ToI32(FloatRegister input, Register, TruncFlags flags, + wasm::BytecodeOffset off, Label* rejoin) +{ + outOfLineWasmTruncateToIntCheck(input, MIRType::Float32, MIRType::Int32, flags & TRUNC_UNSIGNED, + rejoin, off); +} + +void +MacroAssembler::oolWasmTruncateCheckF64ToI32(FloatRegister input, Register, TruncFlags flags, + wasm::BytecodeOffset off, Label* rejoin) +{ + outOfLineWasmTruncateToIntCheck(input, MIRType::Double, MIRType::Int32, flags & TRUNC_UNSIGNED, + rejoin, off); +} + +void +MacroAssembler::oolWasmTruncateCheckF32ToI64(FloatRegister input, Register64, TruncFlags flags, + wasm::BytecodeOffset off, Label* rejoin) +{ + outOfLineWasmTruncateToIntCheck(input, MIRType::Float32, MIRType::Int64, flags & TRUNC_UNSIGNED, + rejoin, off); +} + +void +MacroAssembler::oolWasmTruncateCheckF64ToI64(FloatRegister input, Register64, TruncFlags flags, + wasm::BytecodeOffset off, Label* rejoin) +{ + outOfLineWasmTruncateToIntCheck(input, MIRType::Double, MIRType::Int64, flags & TRUNC_UNSIGNED, + rejoin, off); +} + +void +MacroAssemblerMIPSShared::outOfLineWasmTruncateToIntCheck(FloatRegister input, MIRType fromType, + MIRType toType, bool isUnsigned, + Label* rejoin, + wasm::BytecodeOffset trapOffset) +{ + // Eagerly take care of NaNs. + Label inputIsNaN; + if (fromType == MIRType::Double) + asMasm().branchDouble(Assembler::DoubleUnordered, input, input, &inputIsNaN); + else if (fromType == MIRType::Float32) + asMasm().branchFloat(Assembler::DoubleUnordered, input, input, &inputIsNaN); + else + MOZ_CRASH("unexpected type in visitOutOfLineWasmTruncateCheck"); + + // By default test for the following inputs and bail: + // signed: ] -Inf, INTXX_MIN - 1.0 ] and [ INTXX_MAX + 1.0 : +Inf [ + // unsigned: ] -Inf, -1.0 ] and [ UINTXX_MAX + 1.0 : +Inf [ + // Note: we cannot always represent those exact values. As a result + // this changes the actual comparison a bit. + double minValue, maxValue; + Assembler::DoubleCondition minCond = Assembler::DoubleLessThanOrEqual; + Assembler::DoubleCondition maxCond = Assembler::DoubleGreaterThanOrEqual; + if (toType == MIRType::Int64) { + if (isUnsigned) { + minValue = -1; + maxValue = double(UINT64_MAX) + 1.0; + } else { + // In the float32/double range there exists no value between + // INT64_MIN and INT64_MIN - 1.0. Making INT64_MIN the lower-bound. + minValue = double(INT64_MIN); + minCond = Assembler::DoubleLessThan; + maxValue = double(INT64_MAX) + 1.0; + } + } else { + if (isUnsigned) { + minValue = -1; + maxValue = double(UINT32_MAX) + 1.0; + } else { + if (fromType == MIRType::Float32) { + // In the float32 range there exists no value between + // INT32_MIN and INT32_MIN - 1.0. Making INT32_MIN the lower-bound. + minValue = double(INT32_MIN); + minCond = Assembler::DoubleLessThan; + } else { + minValue = double(INT32_MIN) - 1.0; + } + maxValue = double(INT32_MAX) + 1.0; + } + } + + Label fail; + + if (fromType == MIRType::Double) { + asMasm().loadConstantDouble(minValue, ScratchDoubleReg); + asMasm().branchDouble(minCond, input, ScratchDoubleReg, &fail); + + asMasm().loadConstantDouble(maxValue, ScratchDoubleReg); + asMasm().branchDouble(maxCond, input, ScratchDoubleReg, &fail); + } else { + asMasm().loadConstantFloat32(float(minValue), ScratchFloat32Reg); + asMasm().branchFloat(minCond, input, ScratchFloat32Reg, &fail); + + asMasm().loadConstantFloat32(float(maxValue), ScratchFloat32Reg); + asMasm().branchFloat(maxCond, input, ScratchFloat32Reg, &fail); + } + + asMasm().jump(rejoin); + + // Handle errors. + asMasm().bind(&fail); + asMasm().wasmTrap(wasm::Trap::IntegerOverflow, trapOffset); + asMasm().bind(&inputIsNaN); + asMasm().wasmTrap(wasm::Trap::InvalidConversionToInteger, trapOffset); +} + +void +MacroAssembler::wasmLoad(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, + Register ptrScratch, AnyRegister output) +{ + wasmLoadImpl(access, memoryBase, ptr, ptrScratch, output, InvalidReg); +} + +void +MacroAssembler::wasmUnalignedLoad(const wasm::MemoryAccessDesc& access, Register memoryBase, + Register ptr, Register ptrScratch, Register output, Register tmp) +{ + wasmLoadImpl(access, memoryBase, ptr, ptrScratch, AnyRegister(output), tmp); +} + +void +MacroAssembler::wasmUnalignedLoadFP(const wasm::MemoryAccessDesc& access, Register memoryBase, + Register ptr, Register ptrScratch, FloatRegister output, + Register tmp1, Register tmp2, Register tmp3) +{ + MOZ_ASSERT(tmp2 == InvalidReg); + MOZ_ASSERT(tmp3 == InvalidReg); + wasmLoadImpl(access, memoryBase, ptr, ptrScratch, AnyRegister(output), tmp1); +} + +void +MacroAssembler::wasmStore(const wasm::MemoryAccessDesc& access, AnyRegister value, + Register memoryBase, Register ptr, Register ptrScratch) +{ + wasmStoreImpl(access, value, memoryBase, ptr, ptrScratch, InvalidReg); +} + +void +MacroAssembler::wasmUnalignedStore(const wasm::MemoryAccessDesc& access, Register value, + Register memoryBase, Register ptr, Register ptrScratch, + Register tmp) +{ + wasmStoreImpl(access, AnyRegister(value), memoryBase, ptr, ptrScratch, tmp); +} + +void +MacroAssembler::wasmUnalignedStoreFP(const wasm::MemoryAccessDesc& access, FloatRegister floatValue, + Register memoryBase, Register ptr, Register ptrScratch, + Register tmp) +{ + wasmStoreImpl(access, AnyRegister(floatValue), memoryBase, ptr, ptrScratch, tmp); +} + +void +MacroAssemblerMIPSShared::wasmLoadImpl(const wasm::MemoryAccessDesc& access, Register memoryBase, + Register ptr, Register ptrScratch, AnyRegister output, + Register tmp) +{ + uint32_t offset = access.offset(); + MOZ_ASSERT(offset < wasm::OffsetGuardLimit); + MOZ_ASSERT_IF(offset, ptrScratch != InvalidReg); + + // Maybe add the offset. + if (offset) { + asMasm().addPtr(Imm32(offset), ptrScratch); + ptr = ptrScratch; + } + + unsigned byteSize = access.byteSize(); + bool isSigned; + bool isFloat = false; + + switch (access.type()) { + case Scalar::Int8: isSigned = true; break; + case Scalar::Uint8: isSigned = false; break; + case Scalar::Int16: isSigned = true; break; + case Scalar::Uint16: isSigned = false; break; + case Scalar::Int32: isSigned = true; break; + case Scalar::Uint32: isSigned = false; break; + case Scalar::Float64: isFloat = true; break; + case Scalar::Float32: isFloat = true; break; + default: MOZ_CRASH("unexpected array type"); + } + + BaseIndex address(memoryBase, ptr, TimesOne); + if (IsUnaligned(access)) { + MOZ_ASSERT(tmp != InvalidReg); + if (isFloat) { + if (byteSize == 4) + asMasm().loadUnalignedFloat32(access, address, tmp, output.fpu()); + else + asMasm().loadUnalignedDouble(access, address, tmp, output.fpu()); + } else { + asMasm().ma_load_unaligned(access, output.gpr(), address, tmp, + static_cast(8 * byteSize), + isSigned ? SignExtend : ZeroExtend); + } + return; + } + + 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); + } + } else { + asMasm().ma_load(output.gpr(), address, static_cast(8 * byteSize), + isSigned ? SignExtend : ZeroExtend); + } + asMasm().append(access, asMasm().size() - 4, asMasm().framePushed()); + asMasm().memoryBarrierAfter(access.sync()); +} + +void +MacroAssemblerMIPSShared::wasmStoreImpl(const wasm::MemoryAccessDesc& access, AnyRegister value, + Register memoryBase, Register ptr, Register ptrScratch, + Register tmp) +{ + uint32_t offset = access.offset(); + MOZ_ASSERT(offset < wasm::OffsetGuardLimit); + MOZ_ASSERT_IF(offset, ptrScratch != InvalidReg); + + // Maybe add the offset. + if (offset) { + asMasm().addPtr(Imm32(offset), ptrScratch); + ptr = ptrScratch; + } + + unsigned byteSize = access.byteSize(); + bool isSigned; + bool isFloat = false; + + switch (access.type()) { + case Scalar::Int8: isSigned = true; break; + case Scalar::Uint8: isSigned = false; break; + case Scalar::Int16: isSigned = true; break; + case Scalar::Uint16: isSigned = false; break; + case Scalar::Int32: isSigned = true; break; + case Scalar::Uint32: isSigned = false; break; + case Scalar::Int64: isSigned = true; break; + case Scalar::Float64: isFloat = true; break; + case Scalar::Float32: isFloat = true; break; + default: MOZ_CRASH("unexpected array type"); + } + + BaseIndex address(memoryBase, ptr, TimesOne); + if (IsUnaligned(access)) { + MOZ_ASSERT(tmp != InvalidReg); + if (isFloat) { + if (byteSize == 4) + asMasm().storeUnalignedFloat32(access, value.fpu(), tmp, address); + else + asMasm().storeUnalignedDouble(access, value.fpu(), tmp, address); + } else { + asMasm().ma_store_unaligned(access, value.gpr(), address, tmp, + static_cast(8 * byteSize), + isSigned ? SignExtend : ZeroExtend); + } + return; + } + + 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); + } + } else { + asMasm().ma_store(value.gpr(), address, + static_cast(8 * byteSize), + isSigned ? SignExtend : ZeroExtend); + } + // Only the last emitted instruction is a memory access. + asMasm().append(access, asMasm().size() - 4, asMasm().framePushed()); + asMasm().memoryBarrierAfter(access.sync()); +} + // ======================================================================== // Primitive atomic operations. diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h index 4bf0db3c9c18..8d115f0cc6ef 100644 --- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h +++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h @@ -216,6 +216,16 @@ class MacroAssemblerMIPSShared : public Assembler // Handle NaN specially if handleNaN is true. void minMaxDouble(FloatRegister srcDest, FloatRegister other, bool handleNaN, bool isMax); void minMaxFloat32(FloatRegister srcDest, FloatRegister other, bool handleNaN, bool isMax); + + void outOfLineWasmTruncateToIntCheck(FloatRegister input, MIRType fromType, + MIRType toType, bool isUnsigned, Label* rejoin, + wasm::BytecodeOffset trapOffset); + + protected: + void wasmLoadImpl(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, + Register ptrScratch, AnyRegister output, Register tmp); + void wasmStoreImpl(const wasm::MemoryAccessDesc& access, AnyRegister value, Register memoryBase, + Register ptr, Register ptrScratch, Register tmp); }; } // namespace jit diff --git a/js/src/jit/mips32/Architecture-mips32.h b/js/src/jit/mips32/Architecture-mips32.h index 85a9c8058d25..54009d57aa63 100644 --- a/js/src/jit/mips32/Architecture-mips32.h +++ b/js/src/jit/mips32/Architecture-mips32.h @@ -97,9 +97,6 @@ class FloatRegisters : public FloatRegistersMIPSShared ((SetType(1) << (FloatRegisters::f16 >> 1)) | (SetType(1) << (FloatRegisters::f18 >> 1))) * ((1 << TotalSingle) + 1); - // Registers that can be allocated without being saved, generally. - static const SetType TempMask = VolatileMask & ~NonAllocatableMask; - static const SetType AllocatableMask = AllMask & ~NonAllocatableMask; }; diff --git a/js/src/jit/mips32/Assembler-mips32.cpp b/js/src/jit/mips32/Assembler-mips32.cpp index f84aa8fda93d..589da426ad68 100644 --- a/js/src/jit/mips32/Assembler-mips32.cpp +++ b/js/src/jit/mips32/Assembler-mips32.cpp @@ -392,7 +392,9 @@ Assembler::bind(RepatchLabel* label) MOZ_ASSERT(inst[0].extractOpcode() == (uint32_t(op_beq) >> OpcodeShift) || inst[0].extractOpcode() == (uint32_t(op_bne) >> OpcodeShift) || inst[0].extractOpcode() == (uint32_t(op_blez) >> OpcodeShift) || - inst[0].extractOpcode() == (uint32_t(op_bgtz) >> OpcodeShift)); + inst[0].extractOpcode() == (uint32_t(op_bgtz) >> OpcodeShift) || + (inst[0].extractOpcode() == (uint32_t(op_regimm) >> OpcodeShift) && + inst[0].extractRT() == (uint32_t(rt_bltz) >> RTShift))); inst[0].setBOffImm16(BOffImm16(offset)); } else if (inst[0].encode() == inst_beq.encode()) { // Handle open long unconditional jumps created by diff --git a/js/src/jit/mips32/Assembler-mips32.h b/js/src/jit/mips32/Assembler-mips32.h index c78f9ce0ff48..7941744a7296 100644 --- a/js/src/jit/mips32/Assembler-mips32.h +++ b/js/src/jit/mips32/Assembler-mips32.h @@ -86,6 +86,13 @@ static constexpr FloatRegister ScratchDoubleReg = { FloatRegisters::f18, FloatRe static constexpr FloatRegister SecondScratchFloat32Reg = { FloatRegisters::f16, FloatRegister::Single }; static constexpr FloatRegister SecondScratchDoubleReg = { FloatRegisters::f16, FloatRegister::Double }; +struct ScratchFloat32Scope : public AutoFloatRegisterScope +{ + explicit ScratchFloat32Scope(MacroAssembler& masm) + : AutoFloatRegisterScope(masm, ScratchFloat32Reg) + { } +}; + struct ScratchDoubleScope : public AutoFloatRegisterScope { explicit ScratchDoubleScope(MacroAssembler& masm) diff --git a/js/src/jit/mips32/CodeGenerator-mips32.cpp b/js/src/jit/mips32/CodeGenerator-mips32.cpp index e7c1b1a09af2..3dc37c15cf92 100644 --- a/js/src/jit/mips32/CodeGenerator-mips32.cpp +++ b/js/src/jit/mips32/CodeGenerator-mips32.cpp @@ -461,73 +461,19 @@ void CodeGeneratorMIPS::emitWasmLoadI64(T* lir) { const MWasmLoad* mir = lir->mir(); - Register64 output = ToOutRegister64(lir); - uint32_t offset = mir->access().offset(); - MOZ_ASSERT(offset < wasm::OffsetGuardLimit); - - Register ptr = ToRegister(lir->ptr()); - - if (offset) { - Register ptrPlusOffset = ToRegister(lir->ptrCopy()); - masm.addPtr(Imm32(offset), ptrPlusOffset); - ptr = ptrPlusOffset; - } else { - MOZ_ASSERT(lir->ptrCopy()->isBogusTemp()); + Register ptrScratch = InvalidReg; + if(!lir->ptrCopy()->isBogusTemp()){ + ptrScratch = ToRegister(lir->ptrCopy()); } - unsigned byteSize = mir->access().byteSize(); - bool isSigned; - switch (mir->access().type()) { - case Scalar::Int8: isSigned = true; break; - case Scalar::Uint8: isSigned = false; break; - case Scalar::Int16: isSigned = true; break; - case Scalar::Uint16: isSigned = false; break; - case Scalar::Int32: isSigned = true; break; - case Scalar::Uint32: isSigned = false; break; - case Scalar::Int64: isSigned = true; break; - default: MOZ_CRASH("unexpected array type"); - } - - masm.memoryBarrierBefore(mir->access().sync()); - - MOZ_ASSERT(INT64LOW_OFFSET == 0); if (IsUnaligned(mir->access())) { - Register temp = ToRegister(lir->getTemp(1)); - - if (byteSize <= 4) { - masm.ma_load_unaligned(mir->access(), output.low, BaseIndex(HeapReg, ptr, TimesOne), - temp, static_cast(8 * byteSize), - isSigned ? SignExtend : ZeroExtend); - if (!isSigned) - masm.move32(Imm32(0), output.high); - else - masm.ma_sra(output.high, output.low, Imm32(31)); - } else { - MOZ_ASSERT(output.low != ptr); - masm.ma_load_unaligned(mir->access(), output.low, - BaseIndex(HeapReg, ptr, TimesOne), temp, SizeWord, ZeroExtend); - masm.ma_load_unaligned(mir->access(), output.high, - BaseIndex(HeapReg, ptr, TimesOne, INT64HIGH_OFFSET), temp, - SizeWord, SignExtend); - } - } else if (byteSize <= 4) { - masm.ma_load(output.low, BaseIndex(HeapReg, ptr, TimesOne), - static_cast(8 * byteSize), isSigned ? SignExtend : ZeroExtend); - masm.append(mir->access(), masm.size() - 4 , masm.framePushed()); - if (!isSigned) - masm.move32(Imm32(0), output.high); - else - masm.ma_sra(output.high, output.low, Imm32(31)); + masm.wasmUnalignedLoadI64(mir->access(), HeapReg, ToRegister(lir->ptr()), + ptrScratch, ToOutRegister64(lir), ToRegister(lir->getTemp(1))); } else { - MOZ_ASSERT(output.low != ptr); - masm.ma_load(output.low, BaseIndex(HeapReg, ptr, TimesOne), SizeWord); - masm.append(mir->access(), masm.size() - 4 , masm.framePushed()); - masm.ma_load(output.high, BaseIndex(HeapReg, ptr, TimesOne, INT64HIGH_OFFSET), SizeWord); - masm.append(mir->access(), masm.size() - 4 , masm.framePushed()); + masm.wasmLoadI64(mir->access(), HeapReg, ToRegister(lir->ptr()), ptrScratch, + ToOutRegister64(lir)); } - - masm.memoryBarrierAfter(mir->access().sync()); } void @@ -547,63 +493,19 @@ void CodeGeneratorMIPS::emitWasmStoreI64(T* lir) { const MWasmStore* mir = lir->mir(); - Register64 value = ToRegister64(lir->getInt64Operand(lir->ValueIndex)); - uint32_t offset = mir->access().offset(); - MOZ_ASSERT(offset < wasm::OffsetGuardLimit); - - Register ptr = ToRegister(lir->ptr()); - - if (offset) { - Register ptrPlusOffset = ToRegister(lir->ptrCopy()); - masm.addPtr(Imm32(offset), ptrPlusOffset); - ptr = ptrPlusOffset; - } else { - MOZ_ASSERT(lir->ptrCopy()->isBogusTemp()); + Register ptrScratch = InvalidReg; + if(!lir->ptrCopy()->isBogusTemp()){ + ptrScratch = ToRegister(lir->ptrCopy()); } - unsigned byteSize = mir->access().byteSize(); - bool isSigned; - switch (mir->access().type()) { - case Scalar::Int8: isSigned = true; break; - case Scalar::Uint8: isSigned = false; break; - case Scalar::Int16: isSigned = true; break; - case Scalar::Uint16: isSigned = false; break; - case Scalar::Int32: isSigned = true; break; - case Scalar::Uint32: isSigned = false; break; - case Scalar::Int64: isSigned = true; break; - default: MOZ_CRASH("unexpected array type"); - } - - masm.memoryBarrierBefore(mir->access().sync()); - - MOZ_ASSERT(INT64LOW_OFFSET == 0); if (IsUnaligned(mir->access())) { - Register temp = ToRegister(lir->getTemp(1)); - - if (byteSize <= 4) { - masm.ma_store_unaligned(mir->access(), value.low, BaseIndex(HeapReg, ptr, TimesOne), - temp, static_cast(8 * byteSize), - isSigned ? SignExtend : ZeroExtend); - } else { - masm.ma_store_unaligned(mir->access(), value.high, - BaseIndex(HeapReg, ptr, TimesOne, INT64HIGH_OFFSET), temp, - SizeWord, SignExtend); - masm.ma_store_unaligned(mir->access(), value.low, BaseIndex(HeapReg, ptr, TimesOne), - temp, SizeWord, ZeroExtend); - } - } else if (byteSize <= 4) { - masm.ma_store(value.low, BaseIndex(HeapReg, ptr, TimesOne), - static_cast(8 * byteSize)); - masm.append(mir->access(), masm.size() - 4, masm.framePushed()); - + masm.wasmUnalignedStoreI64(mir->access(), ToRegister64(lir->value()), HeapReg, + ToRegister(lir->ptr()), ptrScratch, ToRegister(lir->getTemp(1))); } else { - masm.ma_store(value.high, BaseIndex(HeapReg, ptr, TimesOne, INT64HIGH_OFFSET), SizeWord); - masm.append(mir->access(), masm.size() - 4, masm.framePushed()); - masm.ma_store(value.low, BaseIndex(HeapReg, ptr, TimesOne), SizeWord); + masm.wasmStoreI64(mir->access(), ToRegister64(lir->value()), HeapReg, + ToRegister(lir->ptr()), ptrScratch); } - - masm.memoryBarrierAfter(mir->access().sync()); } void diff --git a/js/src/jit/mips32/MacroAssembler-mips32-inl.h b/js/src/jit/mips32/MacroAssembler-mips32-inl.h index c774a76d6dd7..a810a8609a56 100644 --- a/js/src/jit/mips32/MacroAssembler-mips32-inl.h +++ b/js/src/jit/mips32/MacroAssembler-mips32-inl.h @@ -33,43 +33,52 @@ MacroAssembler::move64(Imm64 imm, Register64 dest) void MacroAssembler::moveDoubleToGPR64(FloatRegister src, Register64 dest) { - MOZ_CRASH("NYI: moveDoubleToGPR64"); + moveFromDoubleHi(src, dest.high); + moveFromDoubleLo(src, dest.low); } void MacroAssembler::moveGPR64ToDouble(Register64 src, FloatRegister dest) { - MOZ_CRASH("NYI: moveGPR64ToDouble"); + moveToDoubleHi(src.high, dest); + moveToDoubleLo(src.low, dest); } void MacroAssembler::move64To32(Register64 src, Register dest) { - MOZ_CRASH("NYI: move64To32"); + if (src.low != dest) + move32(src.low, dest); } void MacroAssembler::move32To64ZeroExtend(Register src, Register64 dest) { - MOZ_CRASH("NYI: move32To64ZeroExtend"); + if (src != dest.low) + move32(src, dest.low); + move32(Imm32(0), dest.high); } void MacroAssembler::move8To64SignExtend(Register src, Register64 dest) { - MOZ_CRASH("NYI: move8To64SignExtend"); + move8SignExtend(src, dest.low); + move32To64SignExtend(dest.low, dest); } void MacroAssembler::move16To64SignExtend(Register src, Register64 dest) { - MOZ_CRASH("NYI: move16To64SignExtend"); + move16SignExtend(src, dest.low); + move32To64SignExtend(dest.low, dest); } void MacroAssembler::move32To64SignExtend(Register src, Register64 dest) { - MOZ_CRASH("NYI: move32To64SignExtend"); + if (src != dest.low) + move32(src, dest.low); + ma_sra(dest.high, dest.low, Imm32(31)); } // =============================================================== @@ -210,13 +219,20 @@ MacroAssembler::add64(Imm64 imm, Register64 dest) CodeOffset MacroAssembler::sub32FromStackPtrWithPatch(Register dest) { - MOZ_CRASH("NYI - sub32FromStackPtrWithPatch"); + CodeOffset offset = CodeOffset(currentOffset()); + ma_liPatchable(dest, Imm32(0)); + as_subu(dest, StackPointer, dest); + return offset; } void MacroAssembler::patchSub32FromStackPtr(CodeOffset offset, Imm32 imm) { - MOZ_CRASH("NYI - patchSub32FromStackPtr"); + Instruction* lui = (Instruction*) m_buffer.getInst(BufferOffset(offset.offset())); + MOZ_ASSERT(lui->extractOpcode() == ((uint32_t)op_lui >> OpcodeShift)); + MOZ_ASSERT(lui->next()->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift)); + + UpdateLuiOriValue(lui, lui->next(), imm.value); } void @@ -405,7 +421,7 @@ MacroAssembler::lshift64(Imm32 imm, Register64 dest) return; } else if (imm.value < 32) { as_sll(dest.high, dest.high, imm.value); - as_srl(scratch, dest.low, 32 - imm.value); + as_srl(scratch, dest.low, (32 - imm.value)%32); as_or(dest.high, dest.high, scratch); as_sll(dest.low, dest.low, imm.value); } else { @@ -464,7 +480,7 @@ MacroAssembler::rshift64(Imm32 imm, Register64 dest) if (imm.value < 32) { as_srl(dest.low, dest.low, imm.value); - as_sll(scratch, dest.high, 32 - imm.value); + as_sll(scratch, dest.high, (32 - imm.value)%32); as_or(dest.low, dest.low, scratch); as_srl(dest.high, dest.high, imm.value); } else if (imm.value == 32) { @@ -512,7 +528,7 @@ MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest) if (imm.value < 32) { as_srl(dest.low, dest.low, imm.value); - as_sll(scratch, dest.high, 32 - imm.value); + as_sll(scratch, dest.high, (32 - imm.value)%32); as_or(dest.low, dest.low, scratch); as_sra(dest.high, dest.high, imm.value); } else if (imm.value == 32) { @@ -593,26 +609,26 @@ MacroAssembler::rotateLeft64(Register shift, Register64 src, Register64 dest, Re MOZ_ASSERT(temp != src.low && temp != src.high); MOZ_ASSERT(shift != src.low && shift != src.high); MOZ_ASSERT(temp != InvalidReg); - MOZ_ASSERT(src != dest); ScratchRegisterScope shift_value(*this); Label high, swap, done, zero; - ma_and(temp, shift, Imm32(0x3f)); - ma_b(temp, Imm32(32), &swap, Equal); - ma_b(temp, Imm32(32), &high, GreaterThan); + ma_and(shift, shift, Imm32(0x3f)); + ma_b(shift, Imm32(32), &swap, Equal); + ma_b(shift, Imm32(32), &high, GreaterThan); // high = high << shift | low >> 32 - shift // low = low << shift | high >> 32 - shift - ma_sll(dest.high, src.high, temp); - ma_b(temp, Imm32(0), &zero, Equal); + ma_move(temp, src.high); + ma_sll(dest.high, src.high, shift); + ma_b(shift, Imm32(0), &zero, Equal); ma_li(SecondScratchReg, Imm32(32)); - as_subu(shift_value, SecondScratchReg, temp); + as_subu(shift_value, SecondScratchReg, shift); ma_srl(SecondScratchReg, src.low, shift_value); as_or(dest.high, dest.high, SecondScratchReg); - ma_sll(dest.low, src.low, temp); - ma_srl(SecondScratchReg, src.high, shift_value); + ma_sll(dest.low, src.low, shift); + ma_srl(SecondScratchReg, temp, shift_value); as_or(dest.low, dest.low, SecondScratchReg); ma_b(&done); @@ -620,6 +636,7 @@ MacroAssembler::rotateLeft64(Register shift, Register64 src, Register64 dest, Re ma_move(dest.low, src.low); ma_move(dest.high, src.high); ma_b(&done); + bind(&swap); ma_move(SecondScratchReg, src.low); ma_move(dest.low, src.high); @@ -627,19 +644,21 @@ MacroAssembler::rotateLeft64(Register shift, Register64 src, Register64 dest, Re ma_b(&done); // A 32 - 64 shift is a 0 - 32 shift in the other direction. bind(&high); - ma_and(shift, shift, Imm32(0x3f)); ma_li(SecondScratchReg, Imm32(64)); - as_subu(temp, SecondScratchReg, shift); + as_subu(shift_value, SecondScratchReg, shift); - ma_srl(dest.high, src.high, temp); + ma_move(temp, src.high); + ma_srl(dest.high, src.high, shift_value); ma_li(SecondScratchReg, Imm32(32)); - as_subu(shift_value, SecondScratchReg, temp); + as_subu(shift_value, SecondScratchReg, shift_value); ma_sll(SecondScratchReg, src.low, shift_value); as_or(dest.high, dest.high, SecondScratchReg); - ma_srl(dest.low, src.low, temp); - ma_sll(SecondScratchReg, src.high, shift_value); - as_or(dest.low, dest.low, SecondScratchReg); + ma_sll(temp, temp, shift_value); + ma_li(SecondScratchReg, Imm32(64)); + as_subu(shift_value, SecondScratchReg, shift); + ma_srl(dest.low, src.low, shift_value); + as_or(dest.low, dest.low, temp); bind(&done); } @@ -681,30 +700,30 @@ MacroAssembler::rotateRight64(Register shift, Register64 src, Register64 dest, R MOZ_ASSERT(temp != src.low && temp != src.high); MOZ_ASSERT(shift != src.low && shift != src.high); MOZ_ASSERT(temp != InvalidReg); - MOZ_ASSERT(src != dest); ScratchRegisterScope shift_value(*this); Label high, swap, done, zero; - ma_and(temp, shift, Imm32(0x3f)); - ma_b(temp, Imm32(32), &swap, Equal); - ma_b(temp, Imm32(32), &high, GreaterThan); + ma_and(shift, shift, Imm32(0x3f)); + ma_b(shift, Imm32(32), &swap, Equal); + ma_b(shift, Imm32(32), &high, GreaterThan); // high = high >> shift | low << 32 - shift // low = low >> shift | high << 32 - shift - ma_srl(dest.high, src.high, temp); - ma_b(temp, Imm32(0), &zero, Equal); + ma_move(temp, src.high); + ma_srl(dest.high, src.high, shift); + ma_b(shift, Imm32(0), &zero, Equal); ma_li(SecondScratchReg, Imm32(32)); - as_subu(shift_value, SecondScratchReg, temp); + as_subu(shift_value, SecondScratchReg, shift); ma_sll(SecondScratchReg, src.low, shift_value); as_or(dest.high, dest.high, SecondScratchReg); - ma_srl(dest.low, src.low, temp); + ma_srl(dest.low, src.low, shift); //ma_li(SecondScratchReg, Imm32(32)); //as_subu(shift_value, SecondScratchReg, shift_value); - ma_sll(SecondScratchReg, src.high, shift_value); + ma_sll(SecondScratchReg, temp, shift_value); as_or(dest.low, dest.low, SecondScratchReg); ma_b(&done); @@ -713,6 +732,7 @@ MacroAssembler::rotateRight64(Register shift, Register64 src, Register64 dest, R ma_move(dest.low, src.low); ma_move(dest.high, src.high); ma_b(&done); + bind(&swap); ma_move(SecondScratchReg, src.low); ma_move(dest.low, src.high); @@ -720,20 +740,21 @@ MacroAssembler::rotateRight64(Register shift, Register64 src, Register64 dest, R ma_b(&done); // A 32 - 64 shift is a 0 - 32 shift in the other direction. bind(&high); - ma_and(shift, shift, Imm32(0x3f)); ma_li(SecondScratchReg, Imm32(64)); - as_subu(temp, SecondScratchReg, shift); + as_subu(shift_value, SecondScratchReg, shift); - ma_sll(dest.high, src.high, temp); + ma_move(temp, src.high); + ma_sll(dest.high, src.high, shift_value); ma_li(SecondScratchReg, Imm32(32)); - as_subu(shift_value, SecondScratchReg, temp); - + as_subu(shift_value, SecondScratchReg, shift_value); ma_srl(SecondScratchReg, src.low, shift_value); as_or(dest.high, dest.high, SecondScratchReg); - ma_sll(dest.low, src.low, temp); - ma_srl(SecondScratchReg, src.high, shift_value); - as_or(dest.low, dest.low, SecondScratchReg); + ma_srl(temp, temp, shift_value); + ma_li(SecondScratchReg, Imm32(64)); + as_subu(shift_value, SecondScratchReg, shift); + ma_sll(dest.low, src.low, shift_value); + as_or(dest.low, dest.low, temp); bind(&done); } diff --git a/js/src/jit/mips32/MacroAssembler-mips32.cpp b/js/src/jit/mips32/MacroAssembler-mips32.cpp index 9c226ce7f98b..2da8478dd5e7 100644 --- a/js/src/jit/mips32/MacroAssembler-mips32.cpp +++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp @@ -2403,6 +2403,164 @@ MacroAssembler::wasmTruncateFloat32ToUInt32(FloatRegister input, Register output bind(&done); } +void +MacroAssembler::wasmLoadI64(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, + Register ptrScratch, Register64 output) +{ + wasmLoadI64Impl(access, memoryBase, ptr, ptrScratch, output, InvalidReg); +} + +void +MacroAssembler::wasmUnalignedLoadI64(const wasm::MemoryAccessDesc& access, Register memoryBase, + Register ptr, Register ptrScratch, Register64 output, + Register tmp) +{ + wasmLoadI64Impl(access, memoryBase, ptr, ptrScratch, output, tmp); +} + +void +MacroAssembler::wasmStoreI64(const wasm::MemoryAccessDesc& access, Register64 value, + Register memoryBase, Register ptr, Register ptrScratch) +{ + wasmStoreI64Impl(access, value, memoryBase, ptr, ptrScratch, InvalidReg); +} + +void +MacroAssembler::wasmUnalignedStoreI64(const wasm::MemoryAccessDesc& access, Register64 value, + Register memoryBase, Register ptr, Register ptrScratch, + Register tmp) +{ + wasmStoreI64Impl(access, value, memoryBase, ptr, ptrScratch, tmp); +} + +void +MacroAssemblerMIPSCompat::wasmLoadI64Impl(const wasm::MemoryAccessDesc& access, Register memoryBase, + Register ptr, Register ptrScratch, Register64 output, + Register tmp) +{ + uint32_t offset = access.offset(); + MOZ_ASSERT_IF(offset, ptrScratch != InvalidReg); + + // Maybe add the offset. + if (offset) { + asMasm().movePtr(ptr, ptrScratch); + asMasm().addPtr(Imm32(offset), ptrScratch); + ptr = ptrScratch; + } + + unsigned byteSize = access.byteSize(); + bool isSigned; + + switch (access.type()) { + case Scalar::Int8: isSigned = true; break; + case Scalar::Uint8: isSigned = false; break; + case Scalar::Int16: isSigned = true; break; + case Scalar::Uint16: isSigned = false; break; + case Scalar::Int32: isSigned = true; break; + case Scalar::Uint32: isSigned = false; break; + case Scalar::Int64: isSigned = true; break; + default: MOZ_CRASH("unexpected array type"); + } + + BaseIndex address(memoryBase, ptr, TimesOne); + MOZ_ASSERT(INT64LOW_OFFSET == 0); + if (IsUnaligned(access)) { + MOZ_ASSERT(tmp != InvalidReg); + if (byteSize <= 4) { + asMasm().ma_load_unaligned(access, output.low, address, tmp, + static_cast(8 * byteSize), + isSigned ? SignExtend : ZeroExtend); + if (!isSigned) + asMasm().move32(Imm32(0), output.high); + else + asMasm().ma_sra(output.high, output.low, Imm32(31)); + } else { + MOZ_ASSERT(output.low != ptr); + asMasm().ma_load_unaligned(access, output.low, address, tmp, SizeWord, ZeroExtend); + asMasm().ma_load_unaligned(access, output.high, + BaseIndex(HeapReg, ptr, TimesOne, INT64HIGH_OFFSET), + tmp, SizeWord, SignExtend); + } + return; + } + + asMasm().memoryBarrierBefore(access.sync()); + if (byteSize <= 4) { + asMasm().ma_load(output.low, address, static_cast(8 * byteSize), + isSigned ? SignExtend : ZeroExtend); + asMasm().append(access, asMasm().size() - 4 , asMasm().framePushed()); + if (!isSigned) + asMasm().move32(Imm32(0), output.high); + else + asMasm().ma_sra(output.high, output.low, Imm32(31)); + } else { + MOZ_ASSERT(output.low != ptr); + asMasm().ma_load(output.low, BaseIndex(HeapReg, ptr, TimesOne), SizeWord); + asMasm().append(access, asMasm().size() - 4 , asMasm().framePushed()); + asMasm().ma_load(output.high, BaseIndex(HeapReg, ptr, TimesOne, INT64HIGH_OFFSET), SizeWord); + asMasm().append(access, asMasm().size() - 4 , asMasm().framePushed()); + } + asMasm().memoryBarrierAfter(access.sync()); +} + +void +MacroAssemblerMIPSCompat::wasmStoreI64Impl(const wasm::MemoryAccessDesc& access, Register64 value, + Register memoryBase, Register ptr, Register ptrScratch, + Register tmp) +{ + uint32_t offset = access.offset(); + MOZ_ASSERT(offset < wasm::OffsetGuardLimit); + MOZ_ASSERT_IF(offset, ptrScratch != InvalidReg); + + // Maybe add the offset. + if (offset) { + asMasm().addPtr(Imm32(offset), ptrScratch); + ptr = ptrScratch; + } + + unsigned byteSize = access.byteSize(); + bool isSigned; + switch (access.type()) { + case Scalar::Int8: isSigned = true; break; + case Scalar::Uint8: isSigned = false; break; + case Scalar::Int16: isSigned = true; break; + case Scalar::Uint16: isSigned = false; break; + case Scalar::Int32: isSigned = true; break; + case Scalar::Uint32: isSigned = false; break; + case Scalar::Int64: isSigned = true; break; + default: MOZ_CRASH("unexpected array type"); + } + + MOZ_ASSERT(INT64LOW_OFFSET == 0); + BaseIndex address(memoryBase, ptr, TimesOne); + if (IsUnaligned(access)) { + MOZ_ASSERT(tmp != InvalidReg); + if (byteSize <= 4) { + asMasm().ma_store_unaligned(access, value.low, address, tmp, + static_cast(8 * byteSize), + isSigned ? SignExtend : ZeroExtend); + } else { + asMasm().ma_store_unaligned(access, value.high, + BaseIndex(HeapReg, ptr, TimesOne, INT64HIGH_OFFSET), + tmp, SizeWord, SignExtend); + asMasm().ma_store_unaligned(access, value.low, address, tmp, SizeWord, ZeroExtend); + } + return; + } + + asMasm().memoryBarrierBefore(access.sync()); + if (byteSize <= 4) { + asMasm().ma_store(value.low, address, static_cast(8 * byteSize)); + asMasm().append(access, asMasm().size() - 4, asMasm().framePushed()); + } else { + asMasm().ma_store(value.high, BaseIndex(HeapReg, ptr, TimesOne, INT64HIGH_OFFSET), + SizeWord); + asMasm().append(access, asMasm().size() - 4, asMasm().framePushed()); + asMasm().ma_store(value.low, address, SizeWord); + } + asMasm().memoryBarrierAfter(access.sync()); +} + static void EnterAtomic64Region(MacroAssembler& masm, Register addr, Register spinlock, Register scratch) { @@ -2611,6 +2769,7 @@ MacroAssembler::atomicFetchOp64(const Synchronization&, AtomicOp op, Register64 { AtomicFetchOp64(*this, op, value, mem, temp, output); } + // ======================================================================== // Convert floating point. @@ -2634,4 +2793,3 @@ MacroAssembler::convertUInt64ToDouble(Register64 src, FloatRegister dest, Regist } //}}} check_macroassembler_style - diff --git a/js/src/jit/mips32/MacroAssembler-mips32.h b/js/src/jit/mips32/MacroAssembler-mips32.h index dade88ae3689..50f27c3820b7 100644 --- a/js/src/jit/mips32/MacroAssembler-mips32.h +++ b/js/src/jit/mips32/MacroAssembler-mips32.h @@ -718,6 +718,10 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS void enterAtomic64Region(Register addr, Register spinlock, Register tmp); void exitAtomic64Region(Register spinlock); + void wasmLoadI64Impl(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, + Register ptrScratch, Register64 output, Register tmp); + void wasmStoreI64Impl(const wasm::MemoryAccessDesc& access, Register64 value, Register memoryBase, + Register ptr, Register ptrScratch, Register tmp); public: CodeOffset labelForPatch() { diff --git a/js/src/jit/mips64/Architecture-mips64.h b/js/src/jit/mips64/Architecture-mips64.h index e6a092263ad9..0b816553eb74 100644 --- a/js/src/jit/mips64/Architecture-mips64.h +++ b/js/src/jit/mips64/Architecture-mips64.h @@ -84,9 +84,6 @@ class FloatRegisters : public FloatRegistersMIPSShared (1U << FloatRegisters::f23) ) * Spread; - // Registers that can be allocated without being saved, generally. - static const SetType TempMask = VolatileMask & ~NonAllocatableMask; - static const SetType AllocatableMask = AllMask & ~NonAllocatableMask; }; diff --git a/js/src/jit/mips64/Assembler-mips64.cpp b/js/src/jit/mips64/Assembler-mips64.cpp index a468bcc35326..1eb2dc5ad940 100644 --- a/js/src/jit/mips64/Assembler-mips64.cpp +++ b/js/src/jit/mips64/Assembler-mips64.cpp @@ -323,7 +323,9 @@ Assembler::bind(RepatchLabel* label) MOZ_ASSERT(inst[0].extractOpcode() == (uint32_t(op_beq) >> OpcodeShift) || inst[0].extractOpcode() == (uint32_t(op_bne) >> OpcodeShift) || inst[0].extractOpcode() == (uint32_t(op_blez) >> OpcodeShift) || - inst[0].extractOpcode() == (uint32_t(op_bgtz) >> OpcodeShift)); + inst[0].extractOpcode() == (uint32_t(op_bgtz) >> OpcodeShift) || + (inst[0].extractOpcode() == (uint32_t(op_regimm) >> OpcodeShift) && + inst[0].extractRT() == (uint32_t(rt_bltz) >> RTShift))); inst[0].setBOffImm16(BOffImm16(offset)); } else if (inst[0].encode() == inst_beq.encode()) { // Handle open long unconditional jumps created by diff --git a/js/src/jit/mips64/Assembler-mips64.h b/js/src/jit/mips64/Assembler-mips64.h index 029a7005aebf..8a4e9551024b 100644 --- a/js/src/jit/mips64/Assembler-mips64.h +++ b/js/src/jit/mips64/Assembler-mips64.h @@ -80,6 +80,20 @@ static constexpr FloatRegister ScratchDoubleReg = { FloatRegisters::f23, FloatRe static constexpr FloatRegister SecondScratchFloat32Reg = { FloatRegisters::f21, FloatRegisters::Single }; static constexpr FloatRegister SecondScratchDoubleReg = { FloatRegisters::f21, FloatRegisters::Double }; +struct ScratchFloat32Scope : public AutoFloatRegisterScope +{ + explicit ScratchFloat32Scope(MacroAssembler& masm) + : AutoFloatRegisterScope(masm, ScratchFloat32Reg) + { } +}; + +struct ScratchDoubleScope : public AutoFloatRegisterScope +{ + explicit ScratchDoubleScope(MacroAssembler& masm) + : AutoFloatRegisterScope(masm, ScratchDoubleReg) + { } +}; + // Registers used in the GenerateFFIIonExit Disable Activation block. // None of these may be the second scratch register (t8). static constexpr Register WasmIonExitRegReturnData = JSReturnReg_Data; diff --git a/js/src/jit/mips64/CodeGenerator-mips64.cpp b/js/src/jit/mips64/CodeGenerator-mips64.cpp index afe53ea34d91..7f7bbe6dba6f 100644 --- a/js/src/jit/mips64/CodeGenerator-mips64.cpp +++ b/js/src/jit/mips64/CodeGenerator-mips64.cpp @@ -424,51 +424,18 @@ CodeGeneratorMIPS64::emitWasmLoadI64(T* lir) { const MWasmLoad* mir = lir->mir(); - MOZ_ASSERT(lir->mir()->type() == MIRType::Int64); - - uint32_t offset = mir->access().offset(); - MOZ_ASSERT(offset < wasm::OffsetGuardLimit); - - Register ptr = ToRegister(lir->ptr()); - - // Maybe add the offset. - if (offset) { - Register ptrPlusOffset = ToRegister(lir->ptrCopy()); - masm.addPtr(Imm32(offset), ptrPlusOffset); - ptr = ptrPlusOffset; - } else { - MOZ_ASSERT(lir->ptrCopy()->isBogusTemp()); + Register ptrScratch = InvalidReg; + if(!lir->ptrCopy()->isBogusTemp()){ + ptrScratch = ToRegister(lir->ptrCopy()); } - unsigned byteSize = mir->access().byteSize(); - bool isSigned; - - switch (mir->access().type()) { - case Scalar::Int8: isSigned = true; break; - case Scalar::Uint8: isSigned = false; break; - case Scalar::Int16: isSigned = true; break; - case Scalar::Uint16: isSigned = false; break; - case Scalar::Int32: isSigned = true; break; - case Scalar::Uint32: isSigned = false; break; - case Scalar::Int64: isSigned = true; break; - default: MOZ_CRASH("unexpected array type"); - } - - masm.memoryBarrierBefore(mir->access().sync()); - if (IsUnaligned(mir->access())) { - Register temp = ToRegister(lir->getTemp(1)); - - masm.ma_load_unaligned(mir->access(), ToOutRegister64(lir).reg, BaseIndex(HeapReg, ptr, TimesOne), - temp, static_cast(8 * byteSize), - isSigned ? SignExtend : ZeroExtend); + masm.wasmUnalignedLoadI64(mir->access(), HeapReg, ToRegister(lir->ptr()), + ptrScratch, ToOutRegister64(lir), ToRegister(lir->getTemp(1))); } else { - masm.ma_load(ToOutRegister64(lir).reg, BaseIndex(HeapReg, ptr, TimesOne), - static_cast(8 * byteSize), isSigned ? SignExtend : ZeroExtend); - masm.append(mir->access(), masm.size() - 4, masm.framePushed()); + masm.wasmLoadI64(mir->access(), HeapReg, ToRegister(lir->ptr()), ptrScratch, + ToOutRegister64(lir)); } - - masm.memoryBarrierAfter(mir->access().sync()); } void @@ -489,49 +456,18 @@ CodeGeneratorMIPS64::emitWasmStoreI64(T* lir) { const MWasmStore* mir = lir->mir(); - uint32_t offset = mir->access().offset(); - MOZ_ASSERT(offset < wasm::OffsetGuardLimit); - - Register ptr = ToRegister(lir->ptr()); - - // Maybe add the offset. - if (offset) { - Register ptrPlusOffset = ToRegister(lir->ptrCopy()); - masm.addPtr(Imm32(offset), ptrPlusOffset); - ptr = ptrPlusOffset; - } else { - MOZ_ASSERT(lir->ptrCopy()->isBogusTemp()); + Register ptrScratch = InvalidReg; + if(!lir->ptrCopy()->isBogusTemp()){ + ptrScratch = ToRegister(lir->ptrCopy()); } - unsigned byteSize = mir->access().byteSize(); - bool isSigned; - - switch (mir->access().type()) { - case Scalar::Int8: isSigned = true; break; - case Scalar::Uint8: isSigned = false; break; - case Scalar::Int16: isSigned = true; break; - case Scalar::Uint16: isSigned = false; break; - case Scalar::Int32: isSigned = true; break; - case Scalar::Uint32: isSigned = false; break; - case Scalar::Int64: isSigned = true; break; - default: MOZ_CRASH("unexpected array type"); - } - - masm.memoryBarrierBefore(mir->access().sync()); - if (IsUnaligned(mir->access())) { - Register temp = ToRegister(lir->getTemp(1)); - - masm.ma_store_unaligned(mir->access(), ToRegister64(lir->value()).reg, BaseIndex(HeapReg, ptr, TimesOne), - temp, static_cast(8 * byteSize), - isSigned ? SignExtend : ZeroExtend); + masm.wasmUnalignedStoreI64(mir->access(), ToRegister64(lir->value()), HeapReg, + ToRegister(lir->ptr()), ptrScratch, ToRegister(lir->getTemp(1))); } else { - masm.ma_store(ToRegister64(lir->value()).reg, BaseIndex(HeapReg, ptr, TimesOne), - static_cast(8 * byteSize), isSigned ? SignExtend : ZeroExtend); - masm.append(mir->access(), masm.size() - 4, masm.framePushed()); + masm.wasmStoreI64(mir->access(), ToRegister64(lir->value()), HeapReg, + ToRegister(lir->ptr()), ptrScratch); } - - masm.memoryBarrierAfter(mir->access().sync()); } void @@ -668,79 +604,14 @@ CodeGeneratorMIPS64::visitWasmTruncateToInt64(LWasmTruncateToInt64* lir) auto* ool = new (alloc()) OutOfLineWasmTruncateCheck(mir, input); addOutOfLineCode(ool, mir); - if (mir->isUnsigned()) { - Label isLarge, done; - - if (fromType == MIRType::Double) { - masm.loadConstantDouble(double(INT64_MAX), ScratchDoubleReg); - masm.ma_bc1d(ScratchDoubleReg, input, &isLarge, - Assembler::DoubleLessThanOrEqual, ShortJump); - - masm.as_truncld(ScratchDoubleReg, input); - } else { - masm.loadConstantFloat32(float(INT64_MAX), ScratchFloat32Reg); - masm.ma_bc1s(ScratchFloat32Reg, input, &isLarge, - Assembler::DoubleLessThanOrEqual, ShortJump); - - masm.as_truncls(ScratchDoubleReg, input); - } - - // Check that the result is in the uint64_t range. - masm.moveFromDouble(ScratchDoubleReg, output); - masm.as_cfc1(ScratchRegister, Assembler::FCSR); - // extract invalid operation flag (bit 6) from FCSR - masm.ma_ext(ScratchRegister, ScratchRegister, 6, 1); - masm.ma_dsrl(SecondScratchReg, output, Imm32(63)); - masm.ma_or(SecondScratchReg, ScratchRegister); - masm.ma_b(SecondScratchReg, Imm32(0), ool->entry(), Assembler::NotEqual); - - masm.ma_b(&done, ShortJump); - - // The input is greater than double(INT64_MAX). - masm.bind(&isLarge); - if (fromType == MIRType::Double) { - masm.as_subd(ScratchDoubleReg, input, ScratchDoubleReg); - masm.as_truncld(ScratchDoubleReg, ScratchDoubleReg); - } else { - masm.as_subs(ScratchDoubleReg, input, ScratchDoubleReg); - masm.as_truncls(ScratchDoubleReg, ScratchDoubleReg); - } - - // Check that the result is in the uint64_t range. - masm.moveFromDouble(ScratchDoubleReg, output); - masm.as_cfc1(ScratchRegister, Assembler::FCSR); - masm.ma_ext(ScratchRegister, ScratchRegister, 6, 1); - masm.ma_dsrl(SecondScratchReg, output, Imm32(63)); - masm.ma_or(SecondScratchReg, ScratchRegister); - masm.ma_b(SecondScratchReg, Imm32(0), ool->entry(), Assembler::NotEqual); - - masm.ma_li(ScratchRegister, Imm32(1)); - masm.ma_dins(output, ScratchRegister, Imm32(63), Imm32(1)); - - masm.bind(&done); - return; - } - - // When the input value is Infinity, NaN, or rounds to an integer outside the - // range [INT64_MIN; INT64_MAX + 1[, the Invalid Operation flag is set in the FCSR. - if (fromType == MIRType::Double) - masm.as_truncld(ScratchDoubleReg, input); - else - masm.as_truncls(ScratchDoubleReg, input); - - // Check that the result is in the int64_t range. - masm.as_cfc1(output, Assembler::FCSR); - masm.ma_ext(output, output, 6, 1); - masm.ma_b(output, Imm32(0), ool->entry(), Assembler::NotEqual); - - masm.bind(ool->rejoin()); - masm.moveFromDouble(ScratchDoubleReg, output); + masm.wasmTruncateToI64(input, output, fromType, mir->isUnsigned(), + ool->entry(), ool->rejoin()); } void CodeGeneratorMIPS64::visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir) { - Register input = ToRegister(lir->input()); + Register64 input = ToRegister64(lir->getInt64Operand(0)); FloatRegister output = ToFloatRegister(lir->output()); MIRType outputType = lir->mir()->type(); diff --git a/js/src/jit/mips64/MacroAssembler-mips64-inl.h b/js/src/jit/mips64/MacroAssembler-mips64-inl.h index 674fb50ac439..4127eadbb1cd 100644 --- a/js/src/jit/mips64/MacroAssembler-mips64-inl.h +++ b/js/src/jit/mips64/MacroAssembler-mips64-inl.h @@ -31,43 +31,43 @@ MacroAssembler::move64(Imm64 imm, Register64 dest) void MacroAssembler::moveDoubleToGPR64(FloatRegister src, Register64 dest) { - MOZ_CRASH("NYI: moveDoubleToGPR64"); + moveFromDouble(src, dest.reg); } void MacroAssembler::moveGPR64ToDouble(Register64 src, FloatRegister dest) { - MOZ_CRASH("NYI: moveGPR64ToDouble"); + moveToDouble(src.reg, dest); } void MacroAssembler::move64To32(Register64 src, Register dest) { - MOZ_CRASH("NYI: move64To32"); + ma_sll(dest, src.reg, Imm32(0)); } void MacroAssembler::move32To64ZeroExtend(Register src, Register64 dest) { - MOZ_CRASH("NYI: move32To64ZeroExtend"); + ma_dext(dest.reg, src, Imm32(0), Imm32(32)); } void MacroAssembler::move8To64SignExtend(Register src, Register64 dest) { - MOZ_CRASH("NYI: move8To64SignExtend"); + move8SignExtend(src, dest.reg); } void MacroAssembler::move16To64SignExtend(Register src, Register64 dest) { - MOZ_CRASH("NYI: move16To64SignExtend"); + move16SignExtend(src, dest.reg); } void MacroAssembler::move32To64SignExtend(Register src, Register64 dest) { - MOZ_CRASH("NYI: move32To64SignExtend"); + ma_sll(dest.reg, src, Imm32(0)); } // =============================================================== @@ -245,13 +245,20 @@ MacroAssembler::add64(Imm64 imm, Register64 dest) CodeOffset MacroAssembler::sub32FromStackPtrWithPatch(Register dest) { - MOZ_CRASH("NYI - sub32FromStackPtrWithPatch"); + CodeOffset offset = CodeOffset(currentOffset()); + MacroAssemblerMIPSShared::ma_liPatchable(dest, Imm32(0)); + as_dsubu(dest, StackPointer, dest); + return offset; } void MacroAssembler::patchSub32FromStackPtr(CodeOffset offset, Imm32 imm) { - MOZ_CRASH("NYI - patchSub32FromStackPtr"); + Instruction* lui = (Instruction*) m_buffer.getInst(BufferOffset(offset.offset())); + MOZ_ASSERT(lui->extractOpcode() == ((uint32_t)op_lui >> OpcodeShift)); + MOZ_ASSERT(lui->next()->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift)); + + MacroAssemblerMIPSShared::UpdateLuiOriValue(lui, lui->next(), imm.value); } void diff --git a/js/src/jit/mips64/MacroAssembler-mips64.cpp b/js/src/jit/mips64/MacroAssembler-mips64.cpp index 94472e1befbe..2649795c1fc7 100644 --- a/js/src/jit/mips64/MacroAssembler-mips64.cpp +++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp @@ -2470,6 +2470,236 @@ MacroAssembler::wasmTruncateFloat32ToUInt32(FloatRegister input, Register output } +void +MacroAssembler::wasmLoadI64(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, + Register ptrScratch, Register64 output) +{ + wasmLoadI64Impl(access, memoryBase, ptr, ptrScratch, output, InvalidReg); +} + +void +MacroAssembler::wasmUnalignedLoadI64(const wasm::MemoryAccessDesc& access, Register memoryBase, + Register ptr, Register ptrScratch, Register64 output, + Register tmp) +{ + wasmLoadI64Impl(access, memoryBase, ptr, ptrScratch, output, tmp); +} + +void +MacroAssembler::wasmStoreI64(const wasm::MemoryAccessDesc& access, Register64 value, + Register memoryBase, Register ptr, Register ptrScratch) +{ + wasmStoreI64Impl(access, value, memoryBase, ptr, ptrScratch, InvalidReg); +} + +void +MacroAssembler::wasmUnalignedStoreI64(const wasm::MemoryAccessDesc& access, Register64 value, + Register memoryBase, Register ptr, Register ptrScratch, + Register tmp) +{ + wasmStoreI64Impl(access, value, memoryBase, ptr, ptrScratch, tmp); +} + +void +MacroAssembler::wasmTruncateDoubleToInt64(FloatRegister input, Register64 output, bool, + Label* oolEntry, Label* oolRejoin, + FloatRegister tempDouble) +{ + MOZ_ASSERT(tempDouble.isInvalid()); + wasmTruncateToI64(input, output.reg, MIRType::Double, false, oolEntry, oolRejoin); +} + +void +MacroAssembler::wasmTruncateDoubleToUInt64(FloatRegister input, Register64 output, bool, + Label* oolEntry, Label* oolRejoin, + FloatRegister tempDouble) +{ + MOZ_ASSERT(tempDouble.isInvalid()); + wasmTruncateToI64(input, output.reg, MIRType::Double, true, oolEntry, oolRejoin); +} + +void +MacroAssembler::wasmTruncateFloat32ToInt64(FloatRegister input, Register64 output, bool, + Label* oolEntry, Label* oolRejoin, + FloatRegister tempFloat) +{ + MOZ_ASSERT(tempFloat.isInvalid()); + wasmTruncateToI64(input, output.reg, MIRType::Float32, false, oolEntry, oolRejoin); +} + +void +MacroAssembler::wasmTruncateFloat32ToUInt64(FloatRegister input, Register64 output, bool, + Label* oolEntry, Label* oolRejoin, + FloatRegister tempFloat) +{ + MOZ_ASSERT(tempFloat.isInvalid()); + wasmTruncateToI64(input, output.reg, MIRType::Float32, true, oolEntry, oolRejoin); +} + +void +MacroAssemblerMIPS64Compat::wasmTruncateToI64(FloatRegister input, Register output, MIRType fromType, + bool isUnsigned, Label* oolEntry, Label* oolRejoin) +{ + if (isUnsigned) { + Label isLarge, done; + + if (fromType == MIRType::Double) { + asMasm().loadConstantDouble(double(INT64_MAX), ScratchDoubleReg); + asMasm().ma_bc1d(ScratchDoubleReg, input, &isLarge, + Assembler::DoubleLessThanOrEqual, ShortJump); + + asMasm().as_truncld(ScratchDoubleReg, input); + } else { + asMasm().loadConstantFloat32(float(INT64_MAX), ScratchFloat32Reg); + asMasm().ma_bc1s(ScratchFloat32Reg, input, &isLarge, + Assembler::DoubleLessThanOrEqual, ShortJump); + + asMasm().as_truncls(ScratchDoubleReg, input); + } + + // Check that the result is in the uint64_t range. + asMasm().moveFromDouble(ScratchDoubleReg, output); + asMasm().as_cfc1(ScratchRegister, Assembler::FCSR); + // extract invalid operation flag (bit 6) from FCSR + asMasm().ma_ext(ScratchRegister, ScratchRegister, 16, 1); + asMasm().ma_dsrl(SecondScratchReg, output, Imm32(63)); + asMasm().ma_or(SecondScratchReg, ScratchRegister); + asMasm().ma_b(SecondScratchReg, Imm32(0), oolEntry, Assembler::NotEqual); + + asMasm().ma_b(&done, ShortJump); + + // The input is greater than double(INT64_MAX). + asMasm().bind(&isLarge); + if (fromType == MIRType::Double) { + asMasm().as_subd(ScratchDoubleReg, input, ScratchDoubleReg); + asMasm().as_truncld(ScratchDoubleReg, ScratchDoubleReg); + } else { + asMasm().as_subs(ScratchDoubleReg, input, ScratchDoubleReg); + asMasm().as_truncls(ScratchDoubleReg, ScratchDoubleReg); + } + + // Check that the result is in the uint64_t range. + asMasm().moveFromDouble(ScratchDoubleReg, output); + asMasm().as_cfc1(ScratchRegister, Assembler::FCSR); + asMasm().ma_ext(ScratchRegister, ScratchRegister, 16, 1); + asMasm().ma_dsrl(SecondScratchReg, output, Imm32(63)); + asMasm().ma_or(SecondScratchReg, ScratchRegister); + asMasm().ma_b(SecondScratchReg, Imm32(0), oolEntry, Assembler::NotEqual); + + asMasm().ma_li(ScratchRegister, Imm32(1)); + asMasm().ma_dins(output, ScratchRegister, Imm32(63), Imm32(1)); + + asMasm().bind(&done); + asMasm().bind(oolRejoin); + return; + } + + // When the input value is Infinity, NaN, or rounds to an integer outside the + // range [INT64_MIN; INT64_MAX + 1[, the Invalid Operation flag is set in the FCSR. + if (fromType == MIRType::Double) + asMasm().as_truncld(ScratchDoubleReg, input); + else + asMasm().as_truncls(ScratchDoubleReg, input); + + // Check that the result is in the int64_t range. + asMasm().as_cfc1(output, Assembler::FCSR); + asMasm().ma_ext(output, output, 16, 1); + asMasm().ma_b(output, Imm32(0), oolEntry, Assembler::NotEqual); + + asMasm().bind(oolRejoin); + asMasm().moveFromDouble(ScratchDoubleReg, output); +} + +void +MacroAssemblerMIPS64Compat::wasmLoadI64Impl(const wasm::MemoryAccessDesc& access, + Register memoryBase, Register ptr, Register ptrScratch, + Register64 output, Register tmp) +{ + uint32_t offset = access.offset(); + MOZ_ASSERT(offset < wasm::OffsetGuardLimit); + MOZ_ASSERT_IF(offset, ptrScratch != InvalidReg); + + // Maybe add the offset. + if (offset) { + asMasm().addPtr(Imm32(offset), ptrScratch); + ptr = ptrScratch; + } + + unsigned byteSize = access.byteSize(); + bool isSigned; + + switch (access.type()) { + case Scalar::Int8: isSigned = true; break; + case Scalar::Uint8: isSigned = false; break; + case Scalar::Int16: isSigned = true; break; + case Scalar::Uint16: isSigned = false; break; + case Scalar::Int32: isSigned = true; break; + case Scalar::Uint32: isSigned = false; break; + case Scalar::Int64: isSigned = true; break; + default: MOZ_CRASH("unexpected array type"); + } + + BaseIndex address(memoryBase, ptr, TimesOne); + if (IsUnaligned(access)) { + MOZ_ASSERT(tmp != InvalidReg); + asMasm().ma_load_unaligned(access, output.reg, address, tmp, + static_cast(8 * byteSize), + isSigned ? SignExtend : ZeroExtend); + return; + } + + asMasm().memoryBarrierBefore(access.sync()); + asMasm().ma_load(output.reg, address, static_cast(8 * byteSize), + isSigned ? SignExtend : ZeroExtend); + asMasm().append(access, asMasm().size() - 4, asMasm().framePushed()); + asMasm().memoryBarrierAfter(access.sync()); +} + +void +MacroAssemblerMIPS64Compat::wasmStoreI64Impl(const wasm::MemoryAccessDesc& access, Register64 value, + Register memoryBase, Register ptr, Register ptrScratch, + Register tmp) +{ + uint32_t offset = access.offset(); + MOZ_ASSERT(offset < wasm::OffsetGuardLimit); + MOZ_ASSERT_IF(offset, ptrScratch != InvalidReg); + + // Maybe add the offset. + if (offset) { + asMasm().addPtr(Imm32(offset), ptrScratch); + ptr = ptrScratch; + } + + unsigned byteSize = access.byteSize(); + bool isSigned; + switch (access.type()) { + case Scalar::Int8: isSigned = true; break; + case Scalar::Uint8: isSigned = false; break; + case Scalar::Int16: isSigned = true; break; + case Scalar::Uint16: isSigned = false; break; + case Scalar::Int32: isSigned = true; break; + case Scalar::Uint32: isSigned = false; break; + case Scalar::Int64: isSigned = true; break; + default: MOZ_CRASH("unexpected array type"); + } + + BaseIndex address(memoryBase, ptr, TimesOne); + + if (IsUnaligned(access)) { + MOZ_ASSERT(tmp != InvalidReg); + asMasm().ma_store_unaligned(access, value.reg, address, tmp, + static_cast(8 * byteSize), + isSigned ? SignExtend : ZeroExtend); + return; + } + + asMasm().memoryBarrierBefore(access.sync()); + asMasm().ma_store(value.reg, address, static_cast(8 * byteSize), + isSigned ? SignExtend : ZeroExtend); + asMasm().append(access, asMasm().size() - 4, asMasm().framePushed()); + asMasm().memoryBarrierAfter(access.sync()); +} + template static void CompareExchange64(MacroAssembler& masm, const Synchronization& sync, const T& mem, diff --git a/js/src/jit/mips64/MacroAssembler-mips64.h b/js/src/jit/mips64/MacroAssembler-mips64.h index 892c332b5d07..39e4cb28a4fe 100644 --- a/js/src/jit/mips64/MacroAssembler-mips64.h +++ b/js/src/jit/mips64/MacroAssembler-mips64.h @@ -733,6 +733,9 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64 void convertUInt64ToDouble(Register src, FloatRegister dest); + void wasmTruncateToI64(FloatRegister input, Register output, MIRType fromType, + bool isUnsigned, Label* oolEntry, Label* oolRejoin); + void breakpoint(); void checkStackAlignment(); @@ -756,6 +759,11 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64 protected: bool buildOOLFakeExitFrame(void* fakeReturnAddr); + void wasmLoadI64Impl(const wasm::MemoryAccessDesc& access, Register memoryBase, Register ptr, + Register ptrScratch, Register64 output, Register tmp); + void wasmStoreI64Impl(const wasm::MemoryAccessDesc& access, Register64 value, Register memoryBase, + Register ptr, Register ptrScratch, Register tmp); + public: CodeOffset labelForPatch() { return CodeOffset(nextOffset().getOffset()); diff --git a/js/src/jit/none/Architecture-none.h b/js/src/jit/none/Architecture-none.h index 5e85156021c2..4d80963747c7 100644 --- a/js/src/jit/none/Architecture-none.h +++ b/js/src/jit/none/Architecture-none.h @@ -60,7 +60,6 @@ class Registers static const SetType NonVolatileMask = 0; static const SetType NonAllocatableMask = 0; static const SetType AllocatableMask = 0; - static const SetType TempMask = 0; static const SetType JSCallMask = 0; static const SetType CallMask = 0; }; diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h index 212645226928..4693dc4a9a28 100644 --- a/js/src/jit/shared/LIR-shared.h +++ b/js/src/jit/shared/LIR-shared.h @@ -9080,17 +9080,15 @@ class LWasmStackArgI64 : public LInstructionHelper<0, INT64_PIECES, 0> }; template -class LWasmCallBase : public details::LInstructionFixedDefsTempsHelper +class LWasmCallBase : public LVariadicInstruction { - using Base = details::LInstructionFixedDefsTempsHelper; + using Base = LVariadicInstruction; - LAllocation* operands_; - uint32_t needsBoundsCheck_; + bool needsBoundsCheck_; public: - LWasmCallBase(LAllocation* operands, uint32_t numOperands, bool needsBoundsCheck) + LWasmCallBase(uint32_t numOperands, bool needsBoundsCheck) : Base(numOperands), - operands_(operands), needsBoundsCheck_(needsBoundsCheck) { this->setIsCall(); @@ -9109,15 +9107,6 @@ class LWasmCallBase : public details::LInstructionFixedDefsTempsHelper return !reg.isFloat() && reg.gpr() == WasmTlsReg; } - // LInstruction interface - LAllocation* getOperand(size_t index) override { - MOZ_ASSERT(index < this->numOperands()); - return &operands_[index]; - } - void setOperand(size_t index, const LAllocation& a) override { - MOZ_ASSERT(index < this->numOperands()); - operands_[index] = a; - } bool needsBoundsCheck() const { return needsBoundsCheck_; } @@ -9128,8 +9117,8 @@ class LWasmCall : public LWasmCallBase<1> public: LIR_HEADER(WasmCall); - LWasmCall(LAllocation* operands, uint32_t numOperands, bool needsBoundsCheck) - : LWasmCallBase(operands, numOperands, needsBoundsCheck) + LWasmCall(uint32_t numOperands, bool needsBoundsCheck) + : LWasmCallBase(numOperands, needsBoundsCheck) { } }; @@ -9139,8 +9128,8 @@ class LWasmCallVoid : public LWasmCallBase<0> public: LIR_HEADER(WasmCallVoid); - LWasmCallVoid(LAllocation* operands, uint32_t numOperands, bool needsBoundsCheck) - : LWasmCallBase(operands, numOperands, needsBoundsCheck) + LWasmCallVoid(uint32_t numOperands, bool needsBoundsCheck) + : LWasmCallBase(numOperands, needsBoundsCheck) { } }; @@ -9150,8 +9139,8 @@ class LWasmCallI64 : public LWasmCallBase public: LIR_HEADER(WasmCallI64); - LWasmCallI64(LAllocation* operands, uint32_t numOperands, bool needsBoundsCheck) - : LWasmCallBase(operands, numOperands, needsBoundsCheck) + LWasmCallI64(uint32_t numOperands, bool needsBoundsCheck) + : LWasmCallBase(numOperands, needsBoundsCheck) { } }; diff --git a/js/src/jit/x86-shared/Architecture-x86-shared.h b/js/src/jit/x86-shared/Architecture-x86-shared.h index 2faf28f41294..afbb1bce12c7 100644 --- a/js/src/jit/x86-shared/Architecture-x86-shared.h +++ b/js/src/jit/x86-shared/Architecture-x86-shared.h @@ -193,9 +193,6 @@ class Registers { AllMask & ~VolatileMask & ~(1 << X86Encoding::rsp); static const SetType AllocatableMask = AllMask & ~NonAllocatableMask; - - // Registers that can be allocated without being saved, generally. - static const SetType TempMask = VolatileMask & ~NonAllocatableMask; }; typedef Registers::SetType PackedRegisterMask; diff --git a/js/src/vm/HelperThreads.cpp b/js/src/vm/HelperThreads.cpp index e9b5658c9e5f..dadb1839f8cc 100644 --- a/js/src/vm/HelperThreads.cpp +++ b/js/src/vm/HelperThreads.cpp @@ -389,40 +389,12 @@ static const JSClass parseTaskGlobalClass = { &parseTaskGlobalClassOps }; -ParseTask::ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal, - const char16_t* chars, size_t length, +ParseTask::ParseTask(ParseTaskKind kind, JSContext* cx, JS::OffThreadCompileCallback callback, void* callbackData) - : kind(kind), options(cx), data(AsVariant(TwoByteChars(chars, length))), + : kind(kind), + options(cx), alloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), - parseGlobal(parseGlobal), - callback(callback), callbackData(callbackData), - scripts(cx), sourceObjects(cx), - overRecursed(false), outOfMemory(false) -{ - MOZ_ALWAYS_TRUE(scripts.reserve(scripts.capacity())); - MOZ_ALWAYS_TRUE(sourceObjects.reserve(sourceObjects.capacity())); -} - -ParseTask::ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal, - const JS::TranscodeRange& range, - JS::OffThreadCompileCallback callback, void* callbackData) - : kind(kind), options(cx), data(AsVariant(range)), - alloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), - parseGlobal(parseGlobal), - callback(callback), callbackData(callbackData), - scripts(cx), sourceObjects(cx), - overRecursed(false), outOfMemory(false) -{ - MOZ_ALWAYS_TRUE(scripts.reserve(scripts.capacity())); - MOZ_ALWAYS_TRUE(sourceObjects.reserve(sourceObjects.capacity())); -} - -ParseTask::ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal, - JS::TranscodeSources& sources, - JS::OffThreadCompileCallback callback, void* callbackData) - : kind(kind), options(cx), data(AsVariant(&sources)), - alloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), - parseGlobal(parseGlobal), + parseGlobal(nullptr), callback(callback), callbackData(callbackData), scripts(cx), sourceObjects(cx), overRecursed(false), outOfMemory(false) @@ -432,11 +404,12 @@ ParseTask::ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal, } bool -ParseTask::init(JSContext* cx, const ReadOnlyCompileOptions& options) +ParseTask::init(JSContext* cx, const ReadOnlyCompileOptions& options, JSObject* global) { if (!this->options.copy(cx, options)) return false; + parseGlobal = global; return true; } @@ -483,19 +456,16 @@ ParseTask::trace(JSTracer* trc) sourceObjects.trace(trc); } -ScriptParseTask::ScriptParseTask(JSContext* cx, JSObject* parseGlobal, - const char16_t* chars, size_t length, +ScriptParseTask::ScriptParseTask(JSContext* cx, const char16_t* chars, size_t length, JS::OffThreadCompileCallback callback, void* callbackData) - : ParseTask(ParseTaskKind::Script, cx, parseGlobal, chars, length, callback, - callbackData) -{ -} + : ParseTask(ParseTaskKind::Script, cx, callback, callbackData), + data(TwoByteChars(chars, length)) +{} void ScriptParseTask::parse(JSContext* cx) { - auto& range = data.as(); - SourceBufferHolder srcBuf(range.begin().get(), range.length(), SourceBufferHolder::NoOwnership); + SourceBufferHolder srcBuf(data.begin().get(), data.length(), SourceBufferHolder::NoOwnership); Rooted sourceObject(cx); ScopeKind scopeKind = options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global; @@ -509,19 +479,16 @@ ScriptParseTask::parse(JSContext* cx) sourceObjects.infallibleAppend(sourceObject); } -ModuleParseTask::ModuleParseTask(JSContext* cx, JSObject* parseGlobal, - const char16_t* chars, size_t length, +ModuleParseTask::ModuleParseTask(JSContext* cx, const char16_t* chars, size_t length, JS::OffThreadCompileCallback callback, void* callbackData) - : ParseTask(ParseTaskKind::Module, cx, parseGlobal, chars, length, callback, - callbackData) -{ -} + : ParseTask(ParseTaskKind::Module, cx, callback, callbackData), + data(TwoByteChars(chars, length)) +{} void ModuleParseTask::parse(JSContext* cx) { - auto& range = data.as(); - SourceBufferHolder srcBuf(range.begin().get(), range.length(), SourceBufferHolder::NoOwnership); + SourceBufferHolder srcBuf(data.begin().get(), data.length(), SourceBufferHolder::NoOwnership); Rooted sourceObject(cx); ModuleObject* module = frontend::CompileModule(cx, options, srcBuf, alloc, &sourceObject.get()); @@ -532,13 +499,11 @@ ModuleParseTask::parse(JSContext* cx) } } -ScriptDecodeTask::ScriptDecodeTask(JSContext* cx, JSObject* parseGlobal, - const JS::TranscodeRange& range, +ScriptDecodeTask::ScriptDecodeTask(JSContext* cx, const JS::TranscodeRange& range, JS::OffThreadCompileCallback callback, void* callbackData) - : ParseTask(ParseTaskKind::ScriptDecode, cx, parseGlobal, - range, callback, callbackData) -{ -} + : ParseTask(ParseTaskKind::ScriptDecode, cx, callback, callbackData), + range(range) +{} void ScriptDecodeTask::parse(JSContext* cx) @@ -547,7 +512,7 @@ ScriptDecodeTask::parse(JSContext* cx) Rooted sourceObject(cx); XDROffThreadDecoder decoder(cx, alloc, &options, /* sourceObjectOut = */ &sourceObject.get(), - data.as()); + range); decoder.codeScript(&resultScript); MOZ_ASSERT(bool(resultScript) == (decoder.resultCode() == JS::TranscodeResult_Ok)); if (decoder.resultCode() == JS::TranscodeResult_Ok) { @@ -557,19 +522,16 @@ ScriptDecodeTask::parse(JSContext* cx) } } -MultiScriptsDecodeTask::MultiScriptsDecodeTask(JSContext* cx, JSObject* parseGlobal, - JS::TranscodeSources& sources, - JS::OffThreadCompileCallback callback, void* callbackData) - : ParseTask(ParseTaskKind::MultiScriptsDecode, cx, parseGlobal, - sources, callback, callbackData) -{ -} +MultiScriptsDecodeTask::MultiScriptsDecodeTask(JSContext* cx, JS::TranscodeSources& sources, + JS::OffThreadCompileCallback callback, + void* callbackData) + : ParseTask(ParseTaskKind::MultiScriptsDecode, cx, callback, callbackData), + sources(&sources) +{} void MultiScriptsDecodeTask::parse(JSContext* cx) { - auto sources = data.as(); - if (!scripts.reserve(sources->length()) || !sourceObjects.reserve(sources->length())) { @@ -780,10 +742,8 @@ QueueOffThreadParseTask(JSContext* cx, ParseTask* task) return true; } -template bool -StartOffThreadParseTask(JSContext* cx, const ReadOnlyCompileOptions& options, - ParseTaskKind kind, TaskFunctor& taskFunctor) +StartOffThreadParseTask(JSContext* cx, ParseTask* task, const ReadOnlyCompileOptions& options) { // Suppress GC so that calls below do not trigger a new incremental GC // which could require barriers on the atoms compartment. @@ -791,7 +751,7 @@ StartOffThreadParseTask(JSContext* cx, const ReadOnlyCompileOptions& options, gc::AutoSuppressNurseryCellAlloc noNurseryAlloc(cx); AutoSuppressAllocationMetadataBuilder suppressMetadata(cx); - JSObject* global = CreateGlobalForOffThreadParse(cx, kind, nogc); + JSObject* global = CreateGlobalForOffThreadParse(cx, task->kind, nogc); if (!global) return false; @@ -801,14 +761,12 @@ StartOffThreadParseTask(JSContext* cx, const ReadOnlyCompileOptions& options, // this state is cleared automatically. AutoSetCreatedForHelperThread createdForHelper(global); - ScopedJSDeletePtr task(taskFunctor(global)); - if (!task || !task->init(cx, options)) + if (!task->init(cx, options, global)) return false; if (!QueueOffThreadParseTask(cx, task)) return false; - task.forget(); createdForHelper.forget(); return true; } @@ -818,11 +776,13 @@ js::StartOffThreadParseScript(JSContext* cx, const ReadOnlyCompileOptions& optio const char16_t* chars, size_t length, JS::OffThreadCompileCallback callback, void* callbackData) { - auto functor = [&](JSObject* global) -> ScriptParseTask* { - return cx->new_(cx, global, chars, length, - callback, callbackData); - }; - return StartOffThreadParseTask(cx, options, ParseTaskKind::Script, functor); + ScopedJSDeletePtr task; + task = cx->new_(cx, chars, length, callback, callbackData); + if (!task || !StartOffThreadParseTask(cx, task, options)) + return false; + + task.forget(); + return true; } bool @@ -830,11 +790,13 @@ js::StartOffThreadParseModule(JSContext* cx, const ReadOnlyCompileOptions& optio const char16_t* chars, size_t length, JS::OffThreadCompileCallback callback, void* callbackData) { - auto functor = [&](JSObject* global) -> ModuleParseTask* { - return cx->new_(cx, global, chars, length, - callback, callbackData); - }; - return StartOffThreadParseTask(cx, options, ParseTaskKind::Module, functor); + ScopedJSDeletePtr task; + task = cx->new_(cx, chars, length, callback, callbackData); + if (!task || !StartOffThreadParseTask(cx, task, options)) + return false; + + task.forget(); + return true; } bool @@ -842,10 +804,13 @@ js::StartOffThreadDecodeScript(JSContext* cx, const ReadOnlyCompileOptions& opti const JS::TranscodeRange& range, JS::OffThreadCompileCallback callback, void* callbackData) { - auto functor = [&](JSObject* global) -> ScriptDecodeTask* { - return cx->new_(cx, global, range, callback, callbackData); - }; - return StartOffThreadParseTask(cx, options, ParseTaskKind::ScriptDecode, functor); + ScopedJSDeletePtr task; + task = cx->new_(cx, range, callback, callbackData); + if (!task || !StartOffThreadParseTask(cx, task, options)) + return false; + + task.forget(); + return true; } bool @@ -853,10 +818,13 @@ js::StartOffThreadDecodeMultiScripts(JSContext* cx, const ReadOnlyCompileOptions JS::TranscodeSources& sources, JS::OffThreadCompileCallback callback, void* callbackData) { - auto functor = [&](JSObject* global) -> MultiScriptsDecodeTask* { - return cx->new_(cx, global, sources, callback, callbackData); - }; - return StartOffThreadParseTask(cx, options, ParseTaskKind::MultiScriptsDecode, functor); + ScopedJSDeletePtr task; + task = cx->new_(cx, sources, callback, callbackData); + if (!task || !StartOffThreadParseTask(cx, task, options)) + return false; + + task.forget(); + return true; } void @@ -1206,6 +1174,18 @@ GlobalHelperThreadState::maxGCParallelThreads() const return threadCount; } +bool +GlobalHelperThreadState::canStartWasmTier1Compile(const AutoLockHelperThreadState& lock) +{ + return canStartWasmCompile(lock, wasm::CompileMode::Tier1); +} + +bool +GlobalHelperThreadState::canStartWasmTier2Compile(const AutoLockHelperThreadState& lock) +{ + return canStartWasmCompile(lock, wasm::CompileMode::Tier2); +} + bool GlobalHelperThreadState::canStartWasmCompile(const AutoLockHelperThreadState& lock, wasm::CompileMode mode) @@ -1622,12 +1602,15 @@ GlobalHelperThreadState::finishParseTask(JSContext* cx, ParseTaskKind kind, void size_t expectedLength = 0; bool ok = finishParseTask(cx, kind, token, [&scripts, &expectedLength] (ParseTask* parseTask) { - expectedLength = parseTask->data.as()->length(); + MOZ_ASSERT(parseTask->kind == ParseTaskKind::MultiScriptsDecode); + auto task = static_cast(parseTask); - if (!scripts.reserve(parseTask->scripts.length())) + expectedLength = task->sources->length(); + + if (!scripts.reserve(task->scripts.length())) return false; - for (auto& script : parseTask->scripts) + for (auto& script : task->scripts) scripts.infallibleAppend(script); return true; }); @@ -1743,6 +1726,18 @@ HelperThread::ThreadMain(void* arg) Mutex::ShutDown(); } +void +HelperThread::handleWasmTier1Workload(AutoLockHelperThreadState& locked) +{ + handleWasmWorkload(locked, wasm::CompileMode::Tier1); +} + +void +HelperThread::handleWasmTier2Workload(AutoLockHelperThreadState& locked) +{ + handleWasmWorkload(locked, wasm::CompileMode::Tier2); +} + void HelperThread::handleWasmWorkload(AutoLockHelperThreadState& locked, wasm::CompileMode mode) { @@ -2157,6 +2152,62 @@ JSContext::setHelperThread(HelperThread* thread) nurserySuppressions_++; } +// Definition of helper thread tasks. +// +// Priority is determined by the order they're listed here. +const HelperThread::TaskSpec HelperThread::taskSpecs[] = { + { + THREAD_TYPE_GCPARALLEL, + &GlobalHelperThreadState::canStartGCParallelTask, + &HelperThread::handleGCParallelWorkload + }, + { + THREAD_TYPE_GCHELPER, + &GlobalHelperThreadState::canStartGCHelperTask, + &HelperThread::handleGCHelperWorkload + }, + { + THREAD_TYPE_ION, + &GlobalHelperThreadState::canStartIonCompile, + &HelperThread::handleIonWorkload + }, + { + THREAD_TYPE_WASM, + &GlobalHelperThreadState::canStartWasmTier1Compile, + &HelperThread::handleWasmTier1Workload + }, + { + THREAD_TYPE_PROMISE_TASK, + &GlobalHelperThreadState::canStartPromiseHelperTask, + &HelperThread::handlePromiseHelperTaskWorkload + }, + { + THREAD_TYPE_PARSE, + &GlobalHelperThreadState::canStartParseTask, + &HelperThread::handleParseWorkload + }, + { + THREAD_TYPE_COMPRESS, + &GlobalHelperThreadState::canStartCompressionTask, + &HelperThread::handleCompressionWorkload + }, + { + THREAD_TYPE_ION_FREE, + &GlobalHelperThreadState::canStartIonFreeTask, + &HelperThread::handleIonFreeWorkload + }, + { + THREAD_TYPE_WASM, + &GlobalHelperThreadState::canStartWasmTier2Compile, + &HelperThread::handleWasmTier2Workload + }, + { + THREAD_TYPE_WASM_TIER2, + &GlobalHelperThreadState::canStartWasmTier2Generator, + &HelperThread::handleWasmTier2GeneratorWorkload + } +}; + void HelperThread::threadLoop() { @@ -2174,88 +2225,36 @@ HelperThread::threadLoop() cx.setHelperThread(this); JS_SetNativeStackQuota(&cx, HELPER_STACK_QUOTA); - while (true) { + while (!terminate) { MOZ_ASSERT(idle()); - wasm::CompileMode tier; - js::ThreadType task; - while (true) { - if (terminate) - return; - - // Select the task type to run. Task priority is determined - // exclusively here. - // - // The selectors may depend on the HelperThreadState not changing - // between task selection and task execution, in particular, on new - // tasks not being added (because of the lifo structure of the work - // lists). Unlocking the HelperThreadState between task selection - // and execution is not well-defined. - - if (HelperThreadState().canStartGCParallelTask(lock)) { - task = js::THREAD_TYPE_GCPARALLEL; - } else if (HelperThreadState().canStartGCHelperTask(lock)) { - task = js::THREAD_TYPE_GCHELPER; - } else if (HelperThreadState().canStartIonCompile(lock)) { - task = js::THREAD_TYPE_ION; - } else if (HelperThreadState().canStartWasmCompile(lock, wasm::CompileMode::Tier1)) { - task = js::THREAD_TYPE_WASM; - tier = wasm::CompileMode::Tier1; - } else if (HelperThreadState().canStartPromiseHelperTask(lock)) { - task = js::THREAD_TYPE_PROMISE_TASK; - } else if (HelperThreadState().canStartParseTask(lock)) { - task = js::THREAD_TYPE_PARSE; - } else if (HelperThreadState().canStartCompressionTask(lock)) { - task = js::THREAD_TYPE_COMPRESS; - } else if (HelperThreadState().canStartIonFreeTask(lock)) { - task = js::THREAD_TYPE_ION_FREE; - } else if (HelperThreadState().canStartWasmCompile(lock, wasm::CompileMode::Tier2)) { - task = js::THREAD_TYPE_WASM; - tier = wasm::CompileMode::Tier2; - } else if (HelperThreadState().canStartWasmTier2Generator(lock)) { - task = js::THREAD_TYPE_WASM_TIER2; - } else { - task = js::THREAD_TYPE_NONE; - } - - if (task != js::THREAD_TYPE_NONE) - break; + // The selectors may depend on the HelperThreadState not changing + // between task selection and task execution, in particular, on new + // tasks not being added (because of the lifo structure of the work + // lists). Unlocking the HelperThreadState between task selection and + // execution is not well-defined. + const TaskSpec* task = findHighestPriorityTask(lock); + if (!task) { HelperThreadState().wait(lock, GlobalHelperThreadState::PRODUCER); + continue; } - js::oom::SetThreadType(task); - switch (task) { - case js::THREAD_TYPE_GCPARALLEL: - handleGCParallelWorkload(lock); - break; - case js::THREAD_TYPE_GCHELPER: - handleGCHelperWorkload(lock); - break; - case js::THREAD_TYPE_ION: - handleIonWorkload(lock); - break; - case js::THREAD_TYPE_WASM: - handleWasmWorkload(lock, tier); - break; - case js::THREAD_TYPE_PROMISE_TASK: - handlePromiseHelperTaskWorkload(lock); - break; - case js::THREAD_TYPE_PARSE: - handleParseWorkload(lock); - break; - case js::THREAD_TYPE_COMPRESS: - handleCompressionWorkload(lock); - break; - case js::THREAD_TYPE_ION_FREE: - handleIonFreeWorkload(lock); - break; - case js::THREAD_TYPE_WASM_TIER2: - handleWasmTier2GeneratorWorkload(lock); - break; - default: - MOZ_CRASH("No task to perform"); - } + js::oom::SetThreadType(task->type); + (this->*(task->handleWorkload))(lock); js::oom::SetThreadType(js::THREAD_TYPE_NONE); } } + +const HelperThread::TaskSpec* +HelperThread::findHighestPriorityTask(const AutoLockHelperThreadState& locked) +{ + // Return the highest priority task that is ready to start, or nullptr. + + for (const auto& task : taskSpecs) { + if ((HelperThreadState().*(task.canStart))(locked)) + return &task; + } + + return nullptr; +} diff --git a/js/src/vm/HelperThreads.h b/js/src/vm/HelperThreads.h index cb8d712d7a8b..6f630b8ec57f 100644 --- a/js/src/vm/HelperThreads.h +++ b/js/src/vm/HelperThreads.h @@ -258,6 +258,9 @@ class GlobalHelperThreadState } bool canStartWasmCompile(const AutoLockHelperThreadState& lock, wasm::CompileMode mode); + + bool canStartWasmTier1Compile(const AutoLockHelperThreadState& lock); + bool canStartWasmTier2Compile(const AutoLockHelperThreadState& lock); bool canStartWasmTier2Generator(const AutoLockHelperThreadState& lock); bool canStartPromiseHelperTask(const AutoLockHelperThreadState& lock); bool canStartIonCompile(const AutoLockHelperThreadState& lock); @@ -406,6 +409,20 @@ struct HelperThread void threadLoop(); private: + struct TaskSpec + { + using Selector = bool(GlobalHelperThreadState::*)(const AutoLockHelperThreadState&); + using Handler = void(HelperThread::*)(AutoLockHelperThreadState&); + + js::ThreadType type; + Selector canStart; + Handler handleWorkload; + }; + + static const TaskSpec taskSpecs[]; + + const TaskSpec* findHighestPriorityTask(const AutoLockHelperThreadState& locked); + template T maybeCurrentTaskAs() { if (currentTask.isSome() && currentTask->is()) @@ -415,6 +432,9 @@ struct HelperThread } void handleWasmWorkload(AutoLockHelperThreadState& locked, wasm::CompileMode mode); + + void handleWasmTier1Workload(AutoLockHelperThreadState& locked); + void handleWasmTier2Workload(AutoLockHelperThreadState& locked); void handleWasmTier2GeneratorWorkload(AutoLockHelperThreadState& locked); void handlePromiseHelperTaskWorkload(AutoLockHelperThreadState& locked); void handleIonWorkload(AutoLockHelperThreadState& locked); @@ -630,10 +650,6 @@ struct ParseTask ParseTaskKind kind; OwningCompileOptions options; - mozilla::Variant data; - LifoAlloc alloc; // The global object to use while parsing. @@ -657,16 +673,11 @@ struct ParseTask bool overRecursed; bool outOfMemory; - ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal, - const char16_t* chars, size_t length, + ParseTask(ParseTaskKind kind, JSContext* cx, JS::OffThreadCompileCallback callback, void* callbackData); - ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal, - const JS::TranscodeRange& range, - JS::OffThreadCompileCallback callback, void* callbackData); - ParseTask(ParseTaskKind kind, JSContext* cx, JSObject* parseGlobal, - JS::TranscodeSources& sources, - JS::OffThreadCompileCallback callback, void* callbackData); - bool init(JSContext* cx, const ReadOnlyCompileOptions& options); + virtual ~ParseTask(); + + bool init(JSContext* cx, const ReadOnlyCompileOptions& options, JSObject* global); void activate(JSRuntime* rt); virtual void parse(JSContext* cx) = 0; @@ -676,39 +687,41 @@ struct ParseTask return parseGlobal->runtimeFromAnyThread() == rt; } - virtual ~ParseTask(); - void trace(JSTracer* trc); }; struct ScriptParseTask : public ParseTask { - ScriptParseTask(JSContext* cx, JSObject* parseGlobal, - const char16_t* chars, size_t length, + JS::TwoByteChars data; + + ScriptParseTask(JSContext* cx, const char16_t* chars, size_t length, JS::OffThreadCompileCallback callback, void* callbackData); void parse(JSContext* cx) override; }; struct ModuleParseTask : public ParseTask { - ModuleParseTask(JSContext* cx, JSObject* parseGlobal, - const char16_t* chars, size_t length, + JS::TwoByteChars data; + + ModuleParseTask(JSContext* cx, const char16_t* chars, size_t length, JS::OffThreadCompileCallback callback, void* callbackData); void parse(JSContext* cx) override; }; struct ScriptDecodeTask : public ParseTask { - ScriptDecodeTask(JSContext* cx, JSObject* parseGlobal, - const JS::TranscodeRange& range, + const JS::TranscodeRange range; + + ScriptDecodeTask(JSContext* cx, const JS::TranscodeRange& range, JS::OffThreadCompileCallback callback, void* callbackData); void parse(JSContext* cx) override; }; struct MultiScriptsDecodeTask : public ParseTask { - MultiScriptsDecodeTask(JSContext* cx, JSObject* parseGlobal, - JS::TranscodeSources& sources, + JS::TranscodeSources* sources; + + MultiScriptsDecodeTask(JSContext* cx, JS::TranscodeSources& sources, JS::OffThreadCompileCallback callback, void* callbackData); void parse(JSContext* cx) override; }; diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 6853367a7753..28e995fc8d50 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -1823,13 +1823,27 @@ jit::JitActivation::wasmInterruptResumePC() const } void -jit::JitActivation::startWasmTrap(wasm::Trap trap, uint32_t bytecodeOffset, void* pc, void* fp) +jit::JitActivation::startWasmTrap(wasm::Trap trap, uint32_t bytecodeOffset, + const wasm::RegisterState& state) { - MOZ_ASSERT(pc); - MOZ_ASSERT(fp); + bool unwound; + wasm::UnwindState unwindState; + MOZ_ALWAYS_TRUE(wasm::StartUnwinding(state, &unwindState, &unwound)); + MOZ_ASSERT(unwound == (trap == wasm::Trap::IndirectCallBadSig)); + + void* pc = unwindState.pc; + wasm::Frame* fp = unwindState.fp; + + const wasm::Code& code = fp->tls->instance->code(); + MOZ_RELEASE_ASSERT(&code == wasm::LookupCode(pc)); + + // If the frame was unwound, the bytecodeOffset must be recovered from the + // callsite so that it is accurate. + if (unwound) + bytecodeOffset = code.lookupCallSite(pc)->lineOrBytecode(); cx_->runtime()->wasmUnwindData.ref().construct(pc, trap, bytecodeOffset); - setWasmExitFP((wasm::Frame*)fp); + setWasmExitFP(fp); } void diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index 29afbff01e2f..c7fa3b36fbca 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -1667,13 +1667,13 @@ class JitActivation : public Activation // when the interrupt is handled. // Returns true iff we've entered interrupted state. - bool startWasmInterrupt(const JS::ProfilingFrameIterator::RegisterState& state); + bool startWasmInterrupt(const wasm::RegisterState& state); void finishWasmInterrupt(); bool isWasmInterrupted() const; void* wasmInterruptUnwindPC() const; void* wasmInterruptResumePC() const; - void startWasmTrap(wasm::Trap trap, uint32_t bytecodeOffset, void* pc, void* fp); + void startWasmTrap(wasm::Trap trap, uint32_t bytecodeOffset, const wasm::RegisterState& state); void finishWasmTrap(); bool isWasmTrapping() const; void* wasmTrapPC() const; diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp index ecc89e10e19d..d3da150848bd 100644 --- a/js/src/wasm/WasmBaselineCompile.cpp +++ b/js/src/wasm/WasmBaselineCompile.cpp @@ -126,6 +126,14 @@ # include "jit/x86-shared/Architecture-x86-shared.h" # include "jit/x86-shared/Assembler-x86-shared.h" #endif +#if defined(JS_CODEGEN_MIPS32) +# include "jit/mips-shared/Assembler-mips-shared.h" +# include "jit/mips32/Assembler-mips32.h" +#endif +#if defined(JS_CODEGEN_MIPS64) +# include "jit/mips-shared/Assembler-mips-shared.h" +# include "jit/mips64/Assembler-mips64.h" +#endif #include "wasm/WasmBinaryIterator.h" #include "wasm/WasmGenerator.h" @@ -175,8 +183,7 @@ typedef unsigned BitSize; enum class UseABI { Wasm, System }; enum class InterModule { False = false, True = true }; -#if defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_NONE) || \ - defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) +#if defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_NONE) # define RABALDR_SCRATCH_I32 # define RABALDR_SCRATCH_F32 # define RABALDR_SCRATCH_F64 @@ -217,6 +224,20 @@ static const Register RabaldrScratchI32 = CallTempReg2; # define RABALDR_FLOAT_TO_I64_CALLOUT #endif +#ifdef JS_CODEGEN_MIPS32 +# define RABALDR_SCRATCH_I32 +static const Register RabaldrScratchI32 = CallTempReg2; + +# define RABALDR_INT_DIV_I64_CALLOUT +# define RABALDR_I64_TO_FLOAT_CALLOUT +# define RABALDR_FLOAT_TO_I64_CALLOUT +#endif + +#ifdef JS_CODEGEN_MIPS64 +# define RABALDR_SCRATCH_I32 +static const Register RabaldrScratchI32 = CallTempReg2; +#endif + template struct RegTypeOf { static_assert(t == MIRType::Float32 || t == MIRType::Double, "Float mask type"); @@ -371,6 +392,17 @@ struct SpecificRegs : abiReturnRegI64(ReturnReg64) {} }; +#elif defined(JS_CODEGEN_MIPS32) +struct SpecificRegs +{ + RegI64 abiReturnRegI64; + + SpecificRegs() + : abiReturnRegI64(ReturnReg64) + {} +}; +#elif defined(JS_CODEGEN_MIPS64) +struct SpecificRegs {}; #else struct SpecificRegs { @@ -3083,6 +3115,8 @@ class BaseCompiler final : public BaseCompilerInterface call.hardFP = false; # endif call.abi.setUseHardFp(call.hardFP); +#elif defined(JS_CODEGEN_MIPS32) + call.abi.enforceO32ABI(); #endif } @@ -3198,11 +3232,18 @@ class BaseCompiler final : public BaseCompilerInterface } #if defined(JS_CODEGEN_REGISTER_PAIR) case ABIArg::GPR_PAIR: { -# ifdef JS_CODEGEN_ARM +# if defined(JS_CODEGEN_ARM) ScratchF64 scratch(*this); loadF64(arg, scratch); masm.ma_vxfer(scratch, argLoc.evenGpr(), argLoc.oddGpr()); break; +# elif defined(JS_CODEGEN_MIPS32) + ScratchF64 scratch(*this); + loadF64(arg, scratch); + MOZ_ASSERT(MOZ_LITTLE_ENDIAN); + masm.moveFromDoubleLo(scratch, argLoc.evenGpr()); + masm.moveFromDoubleHi(scratch, argLoc.oddGpr()); + break; # else MOZ_CRASH("BaseCompiler platform hook: passArg F64 pair"); # endif @@ -3311,10 +3352,11 @@ class BaseCompiler final : public BaseCompilerInterface // Sundry low-level code generators. // The compiler depends on moveImm32() clearing the high bits of a 64-bit - // register on 64-bit systems. + // register on 64-bit systems except MIPS64 where high bits are sign extended + // from lower bits. void moveImm32(int32_t v, RegI32 dest) { - masm.mov(ImmWord(uint32_t(v)), dest); + masm.move32(Imm32(v), dest); } void moveImm64(int64_t v, RegI64 dest) { @@ -3389,6 +3431,22 @@ class BaseCompiler final : public BaseCompilerInterface // Jump indirect via table element. masm.ma_ldr(DTRAddr(scratch, DtrRegImmShift(switchValue, LSL, 2)), pc, Offset, Assembler::Always); +#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + ScratchI32 scratch(*this); + CodeLabel tableCl; + + masm.ma_li(scratch, tableCl.patchAt()); +# ifdef JS_CODEGEN_MIPS32 + masm.lshiftPtr(Imm32(4), switchValue); +# else + masm.ma_mul(switchValue, switchValue, Imm32(6 * 4)); +# endif + masm.addPtr(switchValue, scratch); + + tableCl.target()->bind(theTable->offset()); + masm.addCodeLabel(tableCl); + + masm.branch(scratch); #else MOZ_CRASH("BaseCompiler platform hook: tableSwitch"); #endif @@ -3501,6 +3559,12 @@ class BaseCompiler final : public BaseCompilerInterface masm.cqo(); masm.idivq(rhs.reg); } +# elif defined(JS_CODEGEN_MIPS64) + if (isUnsigned) + masm.as_ddivu(srcDest.reg, rhs.reg); + else + masm.as_ddiv(srcDest.reg, rhs.reg); + masm.as_mflo(srcDest.reg); # else MOZ_CRASH("BaseCompiler platform hook: quotientI64"); # endif @@ -3531,6 +3595,12 @@ class BaseCompiler final : public BaseCompilerInterface masm.idivq(rhs.reg); } masm.movq(rdx, rax); +# elif defined(JS_CODEGEN_MIPS64) + if (isUnsigned) + masm.as_ddivu(srcDest.reg, rhs.reg); + else + masm.as_ddiv(srcDest.reg, rhs.reg); + masm.as_mfhi(srcDest.reg); # else MOZ_CRASH("BaseCompiler platform hook: remainderI64"); # endif @@ -3541,7 +3611,8 @@ class BaseCompiler final : public BaseCompilerInterface RegI32 needRotate64Temp() { #if defined(JS_CODEGEN_X86) return needI32(); -#elif defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_ARM) +#elif defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_ARM) || \ + defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) return RegI32::Invalid(); #else MOZ_CRASH("BaseCompiler platform hook: needRotate64Temp"); @@ -3557,7 +3628,7 @@ class BaseCompiler final : public BaseCompilerInterface RegI32 needPopcnt32Temp() { #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) return AssemblerX86Shared::HasPOPCNT() ? RegI32::Invalid() : needI32(); -#elif defined(JS_CODEGEN_ARM) +#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) return needI32(); #else MOZ_CRASH("BaseCompiler platform hook: needPopcnt32Temp"); @@ -3567,7 +3638,7 @@ class BaseCompiler final : public BaseCompilerInterface RegI32 needPopcnt64Temp() { #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) return AssemblerX86Shared::HasPOPCNT() ? RegI32::Invalid() : needI32(); -#elif defined(JS_CODEGEN_ARM) +#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) return needI32(); #else MOZ_CRASH("BaseCompiler platform hook: needPopcnt64Temp"); @@ -3921,7 +3992,8 @@ class BaseCompiler final : public BaseCompilerInterface #endif } -#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_ARM) +#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_ARM) || \ + defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) BaseIndex prepareAtomicMemoryAccess(MemoryAccessDesc* access, AccessCheck* check, RegI32 tls, RegI32 ptr) { @@ -3966,11 +4038,13 @@ class BaseCompiler final : public BaseCompilerInterface break; } } +#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + *temp1 = needI32(); #endif } MOZ_MUST_USE bool needTlsForAccess(const AccessCheck& check) { -#if defined(JS_CODEGEN_ARM) +#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) return !check.omitBoundsCheck; #elif defined(JS_CODEGEN_X86) return true; @@ -4010,7 +4084,7 @@ class BaseCompiler final : public BaseCompilerInterface if (byteRegConflict) masm.mov(scratch, dest.i32()); } -#elif defined(JS_CODEGEN_ARM) +#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) if (IsUnaligned(*access)) { switch (dest.tag) { case AnyReg::I64: @@ -4045,6 +4119,8 @@ class BaseCompiler final : public BaseCompilerInterface #if defined(JS_CODEGEN_ARM) if (IsUnaligned(access) && srcType != ValType::I32) return needI32(); +#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + return needI32(); #endif return RegI32::Invalid(); } @@ -4102,7 +4178,7 @@ class BaseCompiler final : public BaseCompilerInterface break; default: MOZ_ASSERT(temp.isInvalid()); - masm.wasmUnalignedStore(*access, src.i32(), HeapReg, ptr, ptr); + masm.wasmUnalignedStore(*access, src.i32(), HeapReg, ptr, ptr, temp); break; } } else { @@ -4114,6 +4190,28 @@ class BaseCompiler final : public BaseCompilerInterface else masm.wasmStore(*access, src.any(), HeapReg, ptr, ptr); } +#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + if (IsUnaligned(*access)) { + switch (src.tag) { + case AnyReg::I64: + masm.wasmUnalignedStoreI64(*access, src.i64(), HeapReg, ptr, ptr, temp); + break; + case AnyReg::F32: + masm.wasmUnalignedStoreFP(*access, src.f32(), HeapReg, ptr, ptr, temp); + break; + case AnyReg::F64: + masm.wasmUnalignedStoreFP(*access, src.f64(), HeapReg, ptr, ptr, temp); + break; + default: + masm.wasmUnalignedStore(*access, src.i32(), HeapReg, ptr, ptr, temp); + break; + } + } else { + if (src.tag == AnyReg::I64) + masm.wasmStoreI64(*access, src.i64(), HeapReg, ptr, ptr); + else + masm.wasmStore(*access, src.any(), HeapReg, ptr, ptr); + } #else MOZ_CRASH("BaseCompiler platform hook: store"); #endif @@ -4121,26 +4219,54 @@ class BaseCompiler final : public BaseCompilerInterface return true; } + template + struct Atomic32Temps : mozilla::Array { + + // Allocate all temp registers if 'allocate' is not specified. + void allocate(BaseCompiler* bc, size_t allocate = Count) { + MOZ_ASSERT(Count != 0); + for (size_t i = 0; i < allocate; ++i) + this->operator[](i) = bc->needI32(); + } + void maybeFree(BaseCompiler* bc){ + for (size_t i = 0; i < Count; ++i) + bc->maybeFreeI32(this->operator[](i)); + } + }; + +#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + typedef Atomic32Temps<3> AtomicRMW32Temps; +#else + typedef Atomic32Temps<1> AtomicRMW32Temps; +#endif + template - void atomicRMW32(T srcAddr, Scalar::Type viewType, AtomicOp op, RegI32 rv, RegI32 rd, RegI32 temp) + void atomicRMW32(T srcAddr, Scalar::Type viewType, AtomicOp op, RegI32 rv, RegI32 rd, + const AtomicRMW32Temps& temps) { Synchronization sync = Synchronization::Full(); switch (viewType) { - case Scalar::Uint8: { + case Scalar::Uint8: #ifdef JS_CODEGEN_X86 + { + RegI32 temp = temps[0]; // The temp, if used, must be a byte register. MOZ_ASSERT(temp.isInvalid()); ScratchI8 scratch(*this); if (op != AtomicFetchAddOp && op != AtomicFetchSubOp) temp = scratch; -#endif masm.atomicFetchOp(viewType, sync, op, rv, srcAddr, temp, rd); break; } +#endif case Scalar::Uint16: case Scalar::Int32: case Scalar::Uint32: - masm.atomicFetchOp(viewType, sync, op, rv, srcAddr, temp, rd); +#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + masm.atomicFetchOp(viewType, sync, op, rv, srcAddr, temps[0], temps[1], temps[2], rd); +#else + masm.atomicFetchOp(viewType, sync, op, rv, srcAddr, temps[0], rd); +#endif break; default: { MOZ_CRASH("Bad type for atomic operation"); @@ -4156,13 +4282,21 @@ class BaseCompiler final : public BaseCompilerInterface masm.atomicFetchOp64(Synchronization::Full(), op, value, srcAddr, temp, rd); } +#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + typedef Atomic32Temps<3> AtomicCmpXchg32Temps; +#else + typedef Atomic32Temps<0> AtomicCmpXchg32Temps; +#endif + template - void atomicCmpXchg32(T srcAddr, Scalar::Type viewType, RegI32 rexpect, RegI32 rnew, RegI32 rd) + void atomicCmpXchg32(T srcAddr, Scalar::Type viewType, RegI32 rexpect, RegI32 rnew, RegI32 rd, + const AtomicCmpXchg32Temps& temps) { Synchronization sync = Synchronization::Full(); switch (viewType) { - case Scalar::Uint8: { + case Scalar::Uint8: #if defined(JS_CODEGEN_X86) + { ScratchI8 scratch(*this); MOZ_ASSERT(rd == specific.eax); if (!ra.isSingleByteI32(rnew)) { @@ -4170,22 +4304,34 @@ class BaseCompiler final : public BaseCompilerInterface masm.movl(rnew, scratch); rnew = scratch; } -#endif masm.compareExchange(viewType, sync, srcAddr, rexpect, rnew, rd); break; } +#endif case Scalar::Uint16: case Scalar::Int32: case Scalar::Uint32: +#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + masm.compareExchange(viewType, sync, srcAddr, rexpect, rnew, temps[0], temps[1], + temps[2], rd); +#else masm.compareExchange(viewType, sync, srcAddr, rexpect, rnew, rd); +#endif break; default: MOZ_CRASH("Bad type for atomic operation"); } } +#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + typedef Atomic32Temps<3> AtomicXchg32Temps; +#else + typedef Atomic32Temps<0> AtomicXchg32Temps; +#endif + template - void atomicXchg32(T srcAddr, Scalar::Type viewType, RegI32 rv, RegI32 rd) + void atomicXchg32(T srcAddr, Scalar::Type viewType, RegI32 rv, RegI32 rd, + const AtomicXchg32Temps& temps) { Synchronization sync = Synchronization::Full(); switch (viewType) { @@ -4206,7 +4352,11 @@ class BaseCompiler final : public BaseCompilerInterface case Scalar::Uint16: case Scalar::Int32: case Scalar::Uint32: +#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + masm.atomicExchange(viewType, sync, srcAddr, rv, temps[0], temps[1], temps[2], rd); +#else masm.atomicExchange(viewType, sync, srcAddr, rv, rd); +#endif break; default: MOZ_CRASH("Bad type for atomic operation"); @@ -4257,6 +4407,8 @@ class BaseCompiler final : public BaseCompilerInterface *r1 = popI64(); *r0 = popI64ToSpecific(specific.edx_eax); *temp = needI32(); +#elif defined(JS_CODEGEN_MIPS64) + pop2xI64(r0, r1); #else pop2xI64(r0, r1); *temp = needI32(); @@ -4362,10 +4514,11 @@ class BaseCompiler final : public BaseCompilerInterface { using Base = PopBase; RegI32 rexpect, rnew; + AtomicCmpXchg32Temps temps; public: #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) - explicit PopAtomicCmpXchg32Regs(BaseCompiler* bc, ValType type) : Base(bc) { + explicit PopAtomicCmpXchg32Regs(BaseCompiler* bc, ValType type, Scalar::Type viewType) : Base(bc) { // For cmpxchg, the expected value and the result are both in eax. bc->needI32(bc->specific.eax); if (type == ValType::I64) { @@ -4381,7 +4534,7 @@ class BaseCompiler final : public BaseCompilerInterface bc->freeI32(rnew); } #elif defined(JS_CODEGEN_ARM) - explicit PopAtomicCmpXchg32Regs(BaseCompiler* bc, ValType type) : Base(bc) { + explicit PopAtomicCmpXchg32Regs(BaseCompiler* bc, ValType type, Scalar::Type viewType) : Base(bc) { if (type == ValType::I64) { rnew = bc->popI64ToI32(); rexpect = bc->popI64ToI32(); @@ -4395,15 +4548,33 @@ class BaseCompiler final : public BaseCompilerInterface bc->freeI32(rnew); bc->freeI32(rexpect); } +#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + explicit PopAtomicCmpXchg32Regs(BaseCompiler* bc, ValType type, Scalar::Type viewType) : Base(bc) { + if (type == ValType::I64) { + rnew = bc->popI64ToI32(); + rexpect = bc->popI64ToI32(); + } else { + rnew = bc->popI32(); + rexpect = bc->popI32(); + } + if (Scalar::byteSize(viewType) < 4) + temps.allocate(bc); + setRd(bc->needI32()); + } + ~PopAtomicCmpXchg32Regs() { + bc->freeI32(rnew); + bc->freeI32(rexpect); + temps.maybeFree(bc); + } #else - explicit PopAtomicCmpXchg32Regs(BaseCompiler* bc, ValType type) : Base(bc) { + explicit PopAtomicCmpXchg32Regs(BaseCompiler* bc, ValType type, Scalar::Type viewType) : Base(bc) { MOZ_CRASH("BaseCompiler porting interface: PopAtomicCmpXchg32Regs"); } #endif template void atomicCmpXchg32(T srcAddr, Scalar::Type viewType) { - bc->atomicCmpXchg32(srcAddr, viewType, rexpect, rnew, getRd()); + bc->atomicCmpXchg32(srcAddr, viewType, rexpect, rnew, getRd(), temps); } }; @@ -4452,6 +4623,16 @@ class BaseCompiler final : public BaseCompilerInterface bc->freeI64(rexpect); bc->freeI64(rnew); } +#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + explicit PopAtomicCmpXchg64Regs(BaseCompiler* bc) : Base(bc) { + rnew = bc->popI64(); + rexpect = bc->popI64(); + setRd(bc->needI64()); + } + ~PopAtomicCmpXchg64Regs() { + bc->freeI64(rexpect); + bc->freeI64(rnew); + } #else explicit PopAtomicCmpXchg64Regs(BaseCompiler* bc) : Base(bc) { MOZ_CRASH("BaseCompiler porting interface: PopAtomicCmpXchg64Regs"); @@ -4496,6 +4677,10 @@ class BaseCompiler final : public BaseCompilerInterface explicit PopAtomicLoad64Regs(BaseCompiler* bc) : Base(bc) { setRd(bc->needI64Pair()); } +#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + explicit PopAtomicLoad64Regs(BaseCompiler* bc) : Base(bc) { + setRd(bc->needI64()); + } # else explicit PopAtomicLoad64Regs(BaseCompiler* bc) : Base(bc) { MOZ_CRASH("BaseCompiler porting interface: PopAtomicLoad64Regs"); @@ -4521,7 +4706,8 @@ class BaseCompiler final : public BaseCompilerInterface class PopAtomicRMW32Regs : public PopBase { using Base = PopBase; - RegI32 rv, temp; + RegI32 rv; + AtomicRMW32Temps temps; public: #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) @@ -4552,16 +4738,16 @@ class BaseCompiler final : public BaseCompilerInterface // Single-byte is a special case handled very locally with // ScratchReg, see atomicRMW32 above. if (Scalar::byteSize(viewType) > 1) - temp = bc->needI32(); + temps.allocate(bc); # else - temp = bc->needI32(); + temps.allocate(bc); # endif } } ~PopAtomicRMW32Regs() { if (rv != bc->specific.eax) bc->freeI32(rv); - bc->maybeFreeI32(temp); + temps.maybeFree(bc); } #elif defined(JS_CODEGEN_ARM) explicit PopAtomicRMW32Regs(BaseCompiler* bc, ValType type, Scalar::Type viewType, @@ -4569,12 +4755,27 @@ class BaseCompiler final : public BaseCompilerInterface : Base(bc) { rv = type == ValType::I64 ? bc->popI64ToI32() : bc->popI32(); - temp = bc->needI32(); + temps.allocate(bc); setRd(bc->needI32()); } ~PopAtomicRMW32Regs() { bc->freeI32(rv); - bc->freeI32(temp); + temps.maybeFree(bc); + } +#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + explicit PopAtomicRMW32Regs(BaseCompiler* bc, ValType type, Scalar::Type viewType, + AtomicOp op) + : Base(bc) + { + rv = type == ValType::I64 ? bc->popI64ToI32() : bc->popI32(); + if (Scalar::byteSize(viewType) < 4) + temps.allocate(bc); + + setRd(bc->needI32()); + } + ~PopAtomicRMW32Regs() { + bc->freeI32(rv); + temps.maybeFree(bc); } #else explicit PopAtomicRMW32Regs(BaseCompiler* bc, ValType type, Scalar::Type viewType, @@ -4587,7 +4788,7 @@ class BaseCompiler final : public BaseCompilerInterface template void atomicRMW32(T srcAddr, Scalar::Type viewType, AtomicOp op) { - bc->atomicRMW32(srcAddr, viewType, op, rv, getRd(), temp); + bc->atomicRMW32(srcAddr, viewType, op, rv, getRd(), temps); } }; @@ -4650,6 +4851,16 @@ class BaseCompiler final : public BaseCompilerInterface bc->freeI64(rv); bc->freeI64(temp); } +#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + explicit PopAtomicRMW64Regs(BaseCompiler* bc, AtomicOp) : Base(bc) { + rv = bc->popI64(); + temp = bc->needI64(); + setRd(bc->needI64()); + } + ~PopAtomicRMW64Regs() { + bc->freeI64(rv); + bc->freeI64(temp); + } #else explicit PopAtomicRMW64Regs(BaseCompiler* bc, AtomicOp) : Base(bc) { MOZ_CRASH("BaseCompiler porting interface: PopAtomicRMW64Regs"); @@ -4675,31 +4886,43 @@ class BaseCompiler final : public BaseCompilerInterface { using Base = PopBase; RegI32 rv; + AtomicXchg32Temps temps; public: #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) - explicit PopAtomicXchg32Regs(BaseCompiler* bc, ValType type) : Base(bc) { + explicit PopAtomicXchg32Regs(BaseCompiler* bc, ValType type, Scalar::Type viewType) : Base(bc) { // The xchg instruction reuses rv as rd. rv = (type == ValType::I64) ? bc->popI64ToI32() : bc->popI32(); setRd(rv); } #elif defined(JS_CODEGEN_ARM) - explicit PopAtomicXchg32Regs(BaseCompiler* bc, ValType type) : Base(bc) { + explicit PopAtomicXchg32Regs(BaseCompiler* bc, ValType type, Scalar::Type viewType) : Base(bc) { rv = (type == ValType::I64) ? bc->popI64ToI32() : bc->popI32(); setRd(bc->needI32()); } ~PopAtomicXchg32Regs() { bc->freeI32(rv); } +#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + explicit PopAtomicXchg32Regs(BaseCompiler* bc, ValType type, Scalar::Type viewType) : Base(bc) { + rv = (type == ValType::I64) ? bc->popI64ToI32() : bc->popI32(); + if (Scalar::byteSize(viewType) < 4) + temps.allocate(bc); + setRd(bc->needI32()); + } + ~PopAtomicXchg32Regs() { + temps.maybeFree(bc); + bc->freeI32(rv); + } #else - explicit PopAtomicXchg32Regs(BaseCompiler* bc, ValType type) : Base(bc) { + explicit PopAtomicXchg32Regs(BaseCompiler* bc, ValType type, Scalar::Type viewType) : Base(bc) { MOZ_CRASH("BaseCompiler porting interface: PopAtomicXchg32Regs"); } #endif template void atomicXchg32(T srcAddr, Scalar::Type viewType) { - bc->atomicXchg32(srcAddr, viewType, rv, getRd()); + bc->atomicXchg32(srcAddr, viewType, rv, getRd(), temps); } }; @@ -4740,6 +4963,14 @@ class BaseCompiler final : public BaseCompilerInterface ~PopAtomicXchg64Regs() { bc->freeI64(rv); } +#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) + explicit PopAtomicXchg64Regs(BaseCompiler* bc) : Base(bc) { + rv = bc->popI64ToSpecific(bc->needI64()); + setRd(bc->needI64()); + } + ~PopAtomicXchg64Regs() { + bc->freeI64(rv); + } #else explicit PopAtomicXchg64Regs(BaseCompiler* bc) : Base(bc) { MOZ_CRASH("BaseCompiler porting interface: xchg64"); @@ -8094,7 +8325,7 @@ BaseCompiler::emitAtomicCmpXchg(ValType type, Scalar::Type viewType) /*numSimdExprs=*/ 0, Synchronization::Full()); if (Scalar::byteSize(viewType) <= 4) { - PopAtomicCmpXchg32Regs regs(this, type); + PopAtomicCmpXchg32Regs regs(this, type, viewType); AccessCheck check; RegI32 rp = popMemoryAccess(&access, &check); @@ -8285,7 +8516,7 @@ BaseCompiler::emitAtomicXchg(ValType type, Scalar::Type viewType) /*numSimdElems=*/ 0, Synchronization::Full()); if (Scalar::byteSize(viewType) <= 4) { - PopAtomicXchg32Regs regs(this, type); + PopAtomicXchg32Regs regs(this, type, viewType); RegI32 rp = popMemoryAccess(&access, &check); RegI32 tls = maybeLoadTlsForAccess(check); @@ -9299,7 +9530,8 @@ js::wasm::BaselineCanCompile() return false; #endif -#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) +#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) || \ + defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) return true; #else return false; diff --git a/js/src/wasm/WasmFrameIter.cpp b/js/src/wasm/WasmFrameIter.cpp index 05209f4eb115..2f5c82c8f292 100644 --- a/js/src/wasm/WasmFrameIter.cpp +++ b/js/src/wasm/WasmFrameIter.cpp @@ -459,18 +459,26 @@ wasm::GenerateFunctionPrologue(MacroAssembler& masm, uint32_t framePushed, IsLea masm.flushBuffer(); masm.haltingAlign(CodeAlignment); - // Generate table entry: + // The table entry falls through into the normal entry after it has checked + // the signature. + Label normalEntry; + + // Generate table entry. The BytecodeOffset of the trap is fixed up to be + // the bytecode offset of the callsite by JitActivation::startWasmTrap. offsets->begin = masm.currentOffset(); - OldTrapDesc trap(trapOffset, Trap::IndirectCallBadSig, 0); switch (sigId.kind()) { case SigIdDesc::Kind::Global: { Register scratch = WasmTableCallScratchReg; masm.loadWasmGlobalPtr(sigId.globalDataOffset(), scratch); - masm.branchPtr(Assembler::Condition::NotEqual, WasmTableCallSigReg, scratch, trap); + masm.branchPtr(Assembler::Condition::Equal, WasmTableCallSigReg, scratch, + &normalEntry); + masm.wasmTrap(Trap::IndirectCallBadSig, BytecodeOffset(0)); break; } case SigIdDesc::Kind::Immediate: { - masm.branch32(Assembler::Condition::NotEqual, WasmTableCallSigReg, Imm32(sigId.immediate()), trap); + masm.branch32(Assembler::Condition::Equal, WasmTableCallSigReg, Imm32(sigId.immediate()), + &normalEntry); + masm.wasmTrap(Trap::IndirectCallBadSig, BytecodeOffset(0)); break; } case SigIdDesc::Kind::None: @@ -483,6 +491,7 @@ wasm::GenerateFunctionPrologue(MacroAssembler& masm, uint32_t framePushed, IsLea // Generate normal entry: masm.nopAlign(CodeAlignment); + masm.bind(&normalEntry); GenerateCallablePrologue(masm, &offsets->normalEntry); // Tiering works as follows. The Code owns a jumpTable, which has one @@ -1272,20 +1281,21 @@ wasm::LookupFaultingInstance(const ModuleSegment& codeSegment, void* pc, void* f return nullptr; size_t offsetInModule = ((uint8_t*)pc) - codeSegment.base(); - if (offsetInModule < codeRange->funcNormalEntry() + SetFP) - return nullptr; - if (offsetInModule >= codeRange->ret() - PoppedFP && offsetInModule <= codeRange->ret()) + if ((offsetInModule >= codeRange->funcNormalEntry() && + offsetInModule < codeRange->funcNormalEntry() + SetFP) || + (offsetInModule >= codeRange->ret() - PoppedFP && + offsetInModule <= codeRange->ret())) + { return nullptr; + } Instance* instance = reinterpret_cast(fp)->tls->instance; - // TODO: when Trap::IndirectCallBadSig is converted away from being an - // OldTrap, this could become a release assert again. The reason for the - // check is the out-of-line trap stub for the table entry's signature check, - // which executes before fp has been updated. + // TODO: In the special case of a cross-instance indirect call bad-signature + // fault, fp can point to the caller frame which is in a different + // instance/module than pc. This special case should go away when old-style + // traps go away and signal handling is reworked. //MOZ_RELEASE_ASSERT(&instance->code() == &codeSegment.code()); - if (&instance->code() != &codeSegment.code()) - return nullptr; return instance; } diff --git a/js/src/wasm/WasmModule.cpp b/js/src/wasm/WasmModule.cpp index 20199504c90e..1320c9750755 100644 --- a/js/src/wasm/WasmModule.cpp +++ b/js/src/wasm/WasmModule.cpp @@ -1145,7 +1145,7 @@ Module::instantiate(JSContext* cx, return false; JumpTables jumpTables; - if (!jumpTables.init(CompileMode::Once, moduleSegment(tier), metadata(tier).codeRanges)) + if (!jumpTables.init(CompileMode::Once, codeTier->segment(), metadata(tier).codeRanges)) return false; code = js_new(Move(codeTier), metadata(), Move(jumpTables)); diff --git a/js/src/wasm/WasmSignalHandlers.cpp b/js/src/wasm/WasmSignalHandlers.cpp index 87b0e7fac3cd..f528ed524766 100644 --- a/js/src/wasm/WasmSignalHandlers.cpp +++ b/js/src/wasm/WasmSignalHandlers.cpp @@ -1039,11 +1039,13 @@ HandleFault(PEXCEPTION_POINTERS exception) if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode)) return false; - activation->startWasmTrap(trap, bytecode.offset, pc, ContextToFP(context)); + activation->startWasmTrap(trap, bytecode.offset, ToRegisterState(context)); *ppc = moduleSegment->trapCode(); return true; } + MOZ_RELEASE_ASSERT(&instance->code() == &moduleSegment->code()); + if (record->NumberParameters < 2) return false; @@ -1170,9 +1172,11 @@ HandleMachException(JSContext* cx, const ExceptionRequest& request) if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode)) return false; - activation->startWasmTrap(trap, bytecode.offset, pc, ContextToFP(&context)); + activation->startWasmTrap(trap, bytecode.offset, ToRegisterState(&context)); *ppc = moduleSegment->trapCode(); } else { + MOZ_RELEASE_ASSERT(&instance->code() == &moduleSegment->code()); + MOZ_ASSERT(request.body.exception == EXC_BAD_ACCESS); if (request.body.codeCnt != 2) return false; @@ -1394,11 +1398,13 @@ HandleFault(int signum, siginfo_t* info, void* ctx) if (!moduleSegment->code().lookupTrap(pc, &trap, &bytecode)) return false; - activation->startWasmTrap(trap, bytecode.offset, pc, ContextToFP(context)); + activation->startWasmTrap(trap, bytecode.offset, ToRegisterState(context)); *ppc = moduleSegment->trapCode(); return true; } + MOZ_RELEASE_ASSERT(&instance->code() == &moduleSegment->code()); + uint8_t* faultingAddress = reinterpret_cast(info->si_addr); // Although it's not strictly necessary, to make sure we're not covering up diff --git a/js/src/wasm/WasmStubs.cpp b/js/src/wasm/WasmStubs.cpp index 98edaf10bc88..deb298645e57 100644 --- a/js/src/wasm/WasmStubs.cpp +++ b/js/src/wasm/WasmStubs.cpp @@ -1730,14 +1730,14 @@ wasm::GenerateStubs(const ModuleEnvironment& env, const FuncImportVector& import case Trap::InvalidConversionToInteger: case Trap::IntegerDivideByZero: case Trap::IndirectCallToNull: + case Trap::IndirectCallBadSig: case Trap::ImpreciseSimdConversion: case Trap::StackOverflow: case Trap::ThrowReported: break; // The TODO list of "old" traps to convert to new traps: case Trap::OutOfBounds: - case Trap::UnalignedAccess: - case Trap::IndirectCallBadSig: { + case Trap::UnalignedAccess: { CallableOffsets offsets; if (!GenerateOldTrapExit(masm, trap, &throwLabel, &offsets)) return false; diff --git a/layout/printing/ipc/RemotePrintJobChild.cpp b/layout/printing/ipc/RemotePrintJobChild.cpp index 1f7586796436..2451d190ac5c 100644 --- a/layout/printing/ipc/RemotePrintJobChild.cpp +++ b/layout/printing/ipc/RemotePrintJobChild.cpp @@ -154,7 +154,7 @@ RemotePrintJobChild::OnStatusChange(nsIWebProgress* aProgress, nsIRequest* aRequest, nsresult aStatus, const char16_t* aMessage) { - if (!mDestroyed) { + if (NS_SUCCEEDED(mInitializationResult) && !mDestroyed) { Unused << SendStatusChange(aStatus); } diff --git a/layout/reftests/w3c-css/submitted/shapes1/reftest.list b/layout/reftests/w3c-css/submitted/shapes1/reftest.list index b0893c312ec9..6b6e08efbea0 100644 --- a/layout/reftests/w3c-css/submitted/shapes1/reftest.list +++ b/layout/reftests/w3c-css/submitted/shapes1/reftest.list @@ -38,7 +38,7 @@ fails == shape-outside-border-box-border-radius-004.html shape-outside-border-bo # Basic shape: circle() == shape-outside-circle-032.html shape-outside-circle-032-ref.html -== shape-outside-circle-033.html shape-outside-circle-033-ref.html +fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),7,6) == shape-outside-circle-033.html shape-outside-circle-033-ref.html == shape-outside-circle-034.html shape-outside-circle-034-ref.html == shape-outside-circle-035.html shape-outside-circle-035-ref.html == shape-outside-circle-036.html shape-outside-circle-036-ref.html @@ -59,8 +59,8 @@ fails == shape-outside-border-box-border-radius-004.html shape-outside-border-bo == shape-outside-circle-051.html shape-outside-circle-051-ref.html == shape-outside-circle-052.html shape-outside-circle-052-ref.html == shape-outside-circle-053.html shape-outside-circle-053-ref.html -== shape-outside-circle-054.html shape-outside-circle-054-ref.html -== shape-outside-circle-055.html shape-outside-circle-055-ref.html +fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),16,4) == shape-outside-circle-054.html shape-outside-circle-054-ref.html +fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),16,4) == shape-outside-circle-055.html shape-outside-circle-055-ref.html # Basic shape: ellipse() == shape-outside-ellipse-032.html shape-outside-ellipse-032-ref.html diff --git a/services/common/utils.js b/services/common/utils.js index c17161a23f99..aecc8723fa77 100644 --- a/services/common/utils.js +++ b/services/common/utils.js @@ -133,19 +133,6 @@ this.CommonUtils = { Services.tm.dispatchToMainThread(callback); }, - /** - * Return a promise resolving on some later tick. - * - * This a wrapper around Promise.resolve() that prevents stack - * accumulation and prevents callers from accidentally relying on - * same-tick promise resolution. - */ - laterTickResolvingPromise(value) { - return new Promise(resolve => { - this.nextTick(() => resolve(value)); - }); - }, - /** * Return a timer that is scheduled to call the callback after waiting the * provided time or as soon as possible. The timer will be set as a property diff --git a/taskcluster/taskgraph/transforms/repackage_signing.py b/taskcluster/taskgraph/transforms/repackage_signing.py index fc2010e4eb74..01acc43eefbd 100644 --- a/taskcluster/taskgraph/transforms/repackage_signing.py +++ b/taskcluster/taskgraph/transforms/repackage_signing.py @@ -11,6 +11,7 @@ from taskgraph.transforms.base import TransformSequence from taskgraph.util.attributes import copy_attributes_from_dependent_job from taskgraph.util.schema import validate_schema, Schema from taskgraph.util.scriptworker import ( + add_scope_prefix, get_signing_cert_scope_per_platform, get_worker_type_for_scope, ) @@ -89,7 +90,7 @@ def make_repackage_signing_description(config, jobs): signing_cert_scope = get_signing_cert_scope_per_platform( build_platform, is_nightly, config ) - scopes = [signing_cert_scope, 'project:releng:signing:format:mar_sha384'] + scopes = [signing_cert_scope, add_scope_prefix(config, 'signing:format:mar_sha384')] upstream_artifacts = [{ "taskId": {"task-reference": ""}, @@ -108,7 +109,7 @@ def make_repackage_signing_description(config, jobs): ], "formats": ["sha2signcode"] }) - scopes.append("project:releng:signing:format:sha2signcode") + scopes.append(add_scope_prefix(config, "signing:format:sha2signcode")) # Stub installer is only generated on win32 if '32' in build_platform: @@ -120,7 +121,7 @@ def make_repackage_signing_description(config, jobs): ], "formats": ["sha2signcodestub"] }) - scopes.append("project:releng:signing:format:sha2signcodestub") + scopes.append(add_scope_prefix(config, "signing:format:sha2signcodestub")) task = { 'label': label, diff --git a/taskcluster/taskgraph/transforms/task.py b/taskcluster/taskgraph/transforms/task.py index 883433221888..02d368c1229b 100644 --- a/taskcluster/taskgraph/transforms/task.py +++ b/taskcluster/taskgraph/transforms/task.py @@ -962,7 +962,10 @@ def build_generic_worker_payload(config, task, task_def): 'osGroups': worker.get('os-groups', []), } - # needs-sccache is handled in mozharness_on_windows + if task.get('needs-sccache'): + worker['env']['USE_SCCACHE'] = '1' + else: + worker['env']['SCCACHE_DISABLE'] = '1' # currently only support one feature (chain of trust) but this will likely grow features = {} diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/background/border-image-repeat-round-2.html.ini~ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/background/border-image-repeat-round-2.html.ini~ deleted file mode 100644 index 83323cb6e91e..000000000000 --- a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/background/border-image-repeat-round-2.html.ini~ +++ /dev/null @@ -1,4 +0,0 @@ -[border-image-repeat-round-1.html] - expected: - if webrender : FAIL - PASS diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-circle-039.html.ini~ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-circle-039.html.ini~ deleted file mode 100644 index 6743792bf6aa..000000000000 --- a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-circle-039.html.ini~ +++ /dev/null @@ -1,4 +0,0 @@ -[clip-path-ellipse-001.html] - expected: - if webrender : FAIL - PASS diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-circle-040.html.ini~ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-circle-040.html.ini~ deleted file mode 100644 index d9994efb57a7..000000000000 --- a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-circle-040.html.ini~ +++ /dev/null @@ -1,4 +0,0 @@ -[shape-outside-circle-039.html] - expected: - if webrender : FAIL - PASS diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-circle-045.html.ini~ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-circle-045.html.ini~ deleted file mode 100644 index a1d11be64bbb..000000000000 --- a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-circle-045.html.ini~ +++ /dev/null @@ -1,4 +0,0 @@ -[shape-outside-circle-040.html] - expected: - if webrender : FAIL - PASS diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-circle-046.html.ini~ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-circle-046.html.ini~ deleted file mode 100644 index 27031836171f..000000000000 --- a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-circle-046.html.ini~ +++ /dev/null @@ -1,4 +0,0 @@ -[shape-outside-circle-045.html] - expected: - if webrender : FAIL - PASS diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-ellipse-040.html.ini~ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-ellipse-040.html.ini~ deleted file mode 100644 index 5e54b77ef1a3..000000000000 --- a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-ellipse-040.html.ini~ +++ /dev/null @@ -1,4 +0,0 @@ -[shape-outside-circle-046.html] - expected: - if webrender : FAIL - PASS diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-ellipse-041.html.ini~ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-ellipse-041.html.ini~ deleted file mode 100644 index 13bcd8fb74b4..000000000000 --- a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-ellipse-041.html.ini~ +++ /dev/null @@ -1,4 +0,0 @@ -[shape-outside-ellipse-040.html] - expected: - if webrender : FAIL - PASS diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-ellipse-042.html.ini~ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-ellipse-042.html.ini~ deleted file mode 100644 index 2062dd27a4fc..000000000000 --- a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-ellipse-042.html.ini~ +++ /dev/null @@ -1,4 +0,0 @@ -[shape-outside-ellipse-041.html] - expected: - if webrender : FAIL - PASS diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-ellipse-043.html.ini~ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-ellipse-043.html.ini~ deleted file mode 100644 index 24d3ab7e704f..000000000000 --- a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-ellipse-043.html.ini~ +++ /dev/null @@ -1,4 +0,0 @@ -[shape-outside-ellipse-042.html] - expected: - if webrender : FAIL - PASS diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-inset-018.html.ini~ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-inset-018.html.ini~ deleted file mode 100644 index 5a184d477464..000000000000 --- a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-inset-018.html.ini~ +++ /dev/null @@ -1,4 +0,0 @@ -[shape-outside-ellipse-043.html] - expected: - if webrender : FAIL - PASS diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-inset-019.html.ini~ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-inset-019.html.ini~ deleted file mode 100644 index 2fafc37ff540..000000000000 --- a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-inset-019.html.ini~ +++ /dev/null @@ -1,4 +0,0 @@ -[shape-outside-inset-018.html] - expected: - if webrender : FAIL - PASS diff --git a/toolkit/components/extensions/ext-theme.js b/toolkit/components/extensions/ext-theme.js index aee44d9219e9..6c9e7244e4bb 100644 --- a/toolkit/components/extensions/ext-theme.js +++ b/toolkit/components/extensions/ext-theme.js @@ -159,6 +159,9 @@ class Theme { case "toolbar_vertical_separator": case "button_background_hover": case "button_background_active": + case "popup": + case "popup_text": + case "popup_border": this.lwtStyles[color] = cssColor; break; } diff --git a/toolkit/components/extensions/schemas/theme.json b/toolkit/components/extensions/schemas/theme.json index 9dd62506aa0a..d4854b7abc4b 100644 --- a/toolkit/components/extensions/schemas/theme.json +++ b/toolkit/components/extensions/schemas/theme.json @@ -152,6 +152,18 @@ "button_background_active": { "$ref": "ThemeColor", "optional": true + }, + "popup": { + "$ref": "ThemeColor", + "optional": true + }, + "popup_text": { + "$ref": "ThemeColor", + "optional": true + }, + "popup_border": { + "$ref": "ThemeColor", + "optional": true } }, "additionalProperties": { "$ref": "UnrecognizedProperty" } diff --git a/toolkit/components/extensions/test/browser/browser.ini b/toolkit/components/extensions/test/browser/browser.ini index b0a47cb3d6cc..112d7b12ddcb 100644 --- a/toolkit/components/extensions/test/browser/browser.ini +++ b/toolkit/components/extensions/test/browser/browser.ini @@ -20,3 +20,4 @@ support-files = [browser_ext_themes_toolbars.js] [browser_ext_themes_toolbarbutton_icons.js] [browser_ext_themes_toolbarbutton_colors.js] +[browser_ext_themes_arrowpanels.js] diff --git a/toolkit/components/extensions/test/browser/browser_ext_themes_arrowpanels.js b/toolkit/components/extensions/test/browser/browser_ext_themes_arrowpanels.js new file mode 100644 index 000000000000..67a154df0038 --- /dev/null +++ b/toolkit/components/extensions/test/browser/browser_ext_themes_arrowpanels.js @@ -0,0 +1,79 @@ +"use strict"; + +function openIdentityPopup() { + let promise = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popupshown"); + gIdentityHandler._identityBox.click(); + return promise; +} + +function closeIdentityPopup() { + let promise = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popuphidden"); + gIdentityHandler._identityPopup.hidePopup(); + return promise; +} + +// This test checks applied WebExtension themes that attempt to change +// popup properties + +add_task(async function test_popup_styling(browser, accDoc) { + const POPUP_BACKGROUND_COLOR = "#FF0000"; + const POPUP_TEXT_COLOR = "#008000"; + const POPUP_BORDER_COLOR = "#0000FF"; + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + "theme": { + "images": { + "headerURL": "image1.png", + }, + "colors": { + "accentcolor": ACCENT_COLOR, + "textcolor": TEXT_COLOR, + "popup": POPUP_BACKGROUND_COLOR, + "popup_text": POPUP_TEXT_COLOR, + "popup_border": POPUP_BORDER_COLOR, + }, + }, + }, + files: { + "image1.png": BACKGROUND, + }, + }); + + + await BrowserTestUtils.withNewTab({gBrowser, url: "https://example.com"}, async function(browser) { + await extension.startup(); + + // Open the information arrow panel + await openIdentityPopup(); + + let arrowContent = document.getAnonymousElementByAttribute(gIdentityHandler._identityPopup, "class", "panel-arrowcontent"); + let arrowContentComputedStyle = window.getComputedStyle(arrowContent); + // Ensure popup background color was set properly + Assert.equal( + arrowContentComputedStyle.getPropertyValue("background-color"), + `rgb(${hexToRGB(POPUP_BACKGROUND_COLOR).join(", ")})`, + "Popup background color should have been themed" + ); + + // Ensure popup text color was set properly + Assert.equal( + arrowContentComputedStyle.getPropertyValue("color"), + `rgb(${hexToRGB(POPUP_TEXT_COLOR).join(", ")})`, + "Popup text color should have been themed" + ); + + // Ensure popup border color was set properly + if (AppConstants.platform == "macosx") { + Assert.ok( + arrowContentComputedStyle.getPropertyValue("box-shadow").includes(`rgb(${hexToRGB(POPUP_BORDER_COLOR).join(", ")})`), + "Popup border color should be set" + ); + } else { + testBorderColor(arrowContent, POPUP_BORDER_COLOR); + } + + await closeIdentityPopup(); + await extension.unload(); + }); +}); diff --git a/toolkit/components/extensions/test/browser/browser_ext_themes_toolbar_fields.js b/toolkit/components/extensions/test/browser/browser_ext_themes_toolbar_fields.js index 782896350919..a44a89bec68c 100644 --- a/toolkit/components/extensions/test/browser/browser_ext_themes_toolbar_fields.js +++ b/toolkit/components/extensions/test/browser/browser_ext_themes_toolbar_fields.js @@ -10,21 +10,6 @@ add_task(async function setup() { ]}); }); -function testBorderColor(element, expected) { - Assert.equal(window.getComputedStyle(element).borderLeftColor, - hexToCSS(expected), - "Field left border color should be set."); - Assert.equal(window.getComputedStyle(element).borderRightColor, - hexToCSS(expected), - "Field right border color should be set."); - Assert.equal(window.getComputedStyle(element).borderTopColor, - hexToCSS(expected), - "Field top border color should be set."); - Assert.equal(window.getComputedStyle(element).borderBottomColor, - hexToCSS(expected), - "Field bottom border color should be set."); -} - add_task(async function test_support_toolbar_field_properties() { const TOOLBAR_FIELD_BACKGROUND = "#ff00ff"; const TOOLBAR_FIELD_COLOR = "#00ff00"; diff --git a/toolkit/components/extensions/test/browser/head.js b/toolkit/components/extensions/test/browser/head.js index 4101bebb12c5..fa9169af8c2d 100644 --- a/toolkit/components/extensions/test/browser/head.js +++ b/toolkit/components/extensions/test/browser/head.js @@ -1,5 +1,5 @@ /* exported ACCENT_COLOR, BACKGROUND, ENCODED_IMAGE_DATA, FRAME_COLOR, TAB_TEXT_COLOR, - TEXT_COLOR, BACKGROUND_TAB_TEXT_COLOR, imageBufferFromDataURI, hexToCSS, hexToRGB */ + TEXT_COLOR, BACKGROUND_TAB_TEXT_COLOR, imageBufferFromDataURI, hexToCSS, hexToRGB, testBorderColor */ "use strict"; @@ -53,3 +53,19 @@ function imageBufferFromDataURI(encodedImageData) { let decodedImageData = atob(encodedImageData); return Uint8Array.from(decodedImageData, byte => byte.charCodeAt(0)).buffer; } + +function testBorderColor(element, expected) { + let computedStyle = window.getComputedStyle(element); + Assert.equal(computedStyle.borderLeftColor, + hexToCSS(expected), + "Element left border color should be set."); + Assert.equal(computedStyle.borderRightColor, + hexToCSS(expected), + "Element right border color should be set."); + Assert.equal(computedStyle.borderTopColor, + hexToCSS(expected), + "Element top border color should be set."); + Assert.equal(computedStyle.borderBottomColor, + hexToCSS(expected), + "Element bottom border color should be set."); +} diff --git a/widget/nsDeviceContextSpecProxy.cpp b/widget/nsDeviceContextSpecProxy.cpp index 8312dae325b9..012bc0d2c22e 100644 --- a/widget/nsDeviceContextSpecProxy.cpp +++ b/widget/nsDeviceContextSpecProxy.cpp @@ -139,22 +139,34 @@ nsDeviceContextSpecProxy::BeginDocument(const nsAString& aTitle, int32_t aStartPage, int32_t aEndPage) { mRecorder = new mozilla::layout::DrawEventRecorderPRFileDesc(); - return mRemotePrintJob->InitializePrint(nsString(aTitle), - nsString(aPrintToFileName), - aStartPage, aEndPage); + nsresult rv = mRemotePrintJob->InitializePrint(nsString(aTitle), + nsString(aPrintToFileName), + aStartPage, aEndPage); + if (NS_FAILED(rv)) { + // The parent process will send a 'delete' message to tell this process to + // delete our RemotePrintJobChild. As soon as we return to the event loop + // and evaluate that message we will crash if we try to access + // mRemotePrintJob. We must not try to use it again. + mRemotePrintJob = nullptr; + } + return rv; } NS_IMETHODIMP nsDeviceContextSpecProxy::EndDocument() { - Unused << mRemotePrintJob->SendFinalizePrint(); + if (mRemotePrintJob) { + Unused << mRemotePrintJob->SendFinalizePrint(); + } return NS_OK; } NS_IMETHODIMP nsDeviceContextSpecProxy::AbortDocument() { - Unused << mRemotePrintJob->SendAbortPrint(NS_OK); + if (mRemotePrintJob) { + Unused << mRemotePrintJob->SendAbortPrint(NS_OK); + } return NS_OK; }