author | Cosmin Sabou <csabou@mozilla.com> |
Sat, 27 Oct 2018 01:50:33 +0300 | |
changeset 443224 | b5e9f8e954d67e039597495016dc8a54fc38452f |
parent 443223 | 230a5cf2a4b45352217919b185831e767ce1f193 (current diff) |
parent 443192 | 3dc7cdbb2b5fe3cbbe34b19fc32b3562b6ff6ff9 (diff) |
child 443225 | 3f6d3c425b42d0b916cc6b05514bde45faf46753 |
push id | 34944 |
push user | ncsoregi@mozilla.com |
push date | Sat, 27 Oct 2018 09:49:55 +0000 |
treeherder | mozilla-central@49d47a692ca4 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 65.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1192,16 +1192,18 @@ pref("services.sync.prefs.sync.privacy.c pref("services.sync.prefs.sync.privacy.clearOnShutdown.cookies", true); pref("services.sync.prefs.sync.privacy.clearOnShutdown.downloads", true); pref("services.sync.prefs.sync.privacy.clearOnShutdown.formdata", true); pref("services.sync.prefs.sync.privacy.clearOnShutdown.history", true); pref("services.sync.prefs.sync.privacy.clearOnShutdown.offlineApps", true); pref("services.sync.prefs.sync.privacy.clearOnShutdown.sessions", true); pref("services.sync.prefs.sync.privacy.clearOnShutdown.siteSettings", true); pref("services.sync.prefs.sync.privacy.donottrackheader.enabled", true); +pref("services.sync.prefs.sync.privacy.fuzzyfox.enabled", true); +pref("services.sync.prefs.sync.privacy.fuzzyfox.clockgrainus", true); pref("services.sync.prefs.sync.privacy.sanitize.sanitizeOnShutdown", true); pref("services.sync.prefs.sync.privacy.trackingprotection.enabled", true); pref("services.sync.prefs.sync.privacy.trackingprotection.pbmode.enabled", true); pref("services.sync.prefs.sync.privacy.resistFingerprinting", true); pref("services.sync.prefs.sync.privacy.reduceTimerPrecision", true); pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.microseconds", true); pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.jitter", true); pref("services.sync.prefs.sync.security.OCSP.enabled", true);
--- a/browser/config/mozconfigs/linux64/code-coverage-debug +++ b/browser/config/mozconfigs/linux64/code-coverage-debug @@ -1,3 +1,5 @@ . "$topsrcdir/browser/config/mozconfigs/linux64/code-coverage" ac_add_options --enable-debug=-g1 +# We enable Rust tests on the debug build only, as the opt build is currently only used for fuzzing. +ac_add_options --enable-rust-tests
--- a/browser/config/mozconfigs/win64/code-coverage +++ b/browser/config/mozconfigs/win64/code-coverage @@ -3,16 +3,17 @@ MOZ_AUTOMATION_L10N_CHECK=0 . "$topsrcdir/browser/config/mozconfigs/common" . "$topsrcdir/browser/config/mozconfigs/win64/common-win64" ac_add_options --enable-optimize ac_add_options --enable-debug ac_add_options --disable-sandbox ac_add_options --disable-warnings-as-errors ac_add_options --enable-coverage +ac_add_options --enable-rust-tests # Needed to enable breakpad in application.ini export MOZILLA_OFFICIAL=1 # Enable Telemetry export MOZ_TELEMETRY_REPORTING=1 . $topsrcdir/build/win64/mozconfig.vs-latest
--- 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.936 +Current extension version is: 2.0.943 -Taken from upstream commit: d2189293 +Taken from upstream commit: dc98bf76
--- a/browser/extensions/pdfjs/content/build/pdf.js +++ b/browser/extensions/pdfjs/content/build/pdf.js @@ -118,18 +118,18 @@ return /******/ (function(modules) { // /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; -var pdfjsVersion = '2.0.936'; -var pdfjsBuild = 'd2189293'; +var pdfjsVersion = '2.0.943'; +var pdfjsBuild = 'dc98bf76'; var pdfjsSharedUtil = __w_pdfjs_require__(1); var pdfjsDisplayAPI = __w_pdfjs_require__(7); var pdfjsDisplayTextLayer = __w_pdfjs_require__(19); var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(20); var pdfjsDisplayDOMUtils = __w_pdfjs_require__(8); var pdfjsDisplaySVG = __w_pdfjs_require__(21); let pdfjsDisplayWorkerOptions = __w_pdfjs_require__(13); let pdfjsDisplayAPICompatibility = __w_pdfjs_require__(10); @@ -4221,17 +4221,17 @@ function _fetchDocument(worker, source, return Promise.reject(new Error('Worker was destroyed')); } if (pdfDataRangeTransport) { source.length = pdfDataRangeTransport.length; source.initialData = pdfDataRangeTransport.initialData; } return worker.messageHandler.sendWithPromise('GetDocRequest', { docId, - apiVersion: '2.0.936', + apiVersion: '2.0.943', source: { data: source.data, url: source.url, password: source.password, disableAutoFetch: source.disableAutoFetch, rangeChunkSize: source.rangeChunkSize, length: source.length }, @@ -4278,67 +4278,61 @@ var PDFDocumentLoadingTask = function PD }); }, then: function PDFDocumentLoadingTask_then(onFulfilled, onRejected) { return this.promise.then.apply(this.promise, arguments); } }; return PDFDocumentLoadingTask; }(); -var PDFDataRangeTransport = function pdfDataRangeTransportClosure() { - function PDFDataRangeTransport(length, initialData) { +class PDFDataRangeTransport { + constructor(length, initialData) { this.length = length; this.initialData = initialData; this._rangeListeners = []; this._progressListeners = []; this._progressiveReadListeners = []; this._readyCapability = (0, _util.createPromiseCapability)(); } - PDFDataRangeTransport.prototype = { - addRangeListener: function PDFDataRangeTransport_addRangeListener(listener) { - this._rangeListeners.push(listener); - }, - addProgressListener: function PDFDataRangeTransport_addProgressListener(listener) { - this._progressListeners.push(listener); - }, - addProgressiveReadListener: function PDFDataRangeTransport_addProgressiveReadListener(listener) { - this._progressiveReadListeners.push(listener); - }, - onDataRange: function PDFDataRangeTransport_onDataRange(begin, chunk) { - var listeners = this._rangeListeners; - for (var i = 0, n = listeners.length; i < n; ++i) { - listeners[i](begin, chunk); - } - }, - onDataProgress: function PDFDataRangeTransport_onDataProgress(loaded) { - this._readyCapability.promise.then(() => { - var listeners = this._progressListeners; - for (var i = 0, n = listeners.length; i < n; ++i) { - listeners[i](loaded); - } - }); - }, - onDataProgressiveRead: function PDFDataRangeTransport_onDataProgress(chunk) { - this._readyCapability.promise.then(() => { - var listeners = this._progressiveReadListeners; - for (var i = 0, n = listeners.length; i < n; ++i) { - listeners[i](chunk); - } - }); - }, - transportReady: function PDFDataRangeTransport_transportReady() { - this._readyCapability.resolve(); - }, - requestDataRange: function PDFDataRangeTransport_requestDataRange(begin, end) { - (0, _util.unreachable)('Abstract method PDFDataRangeTransport.requestDataRange'); - }, - abort: function PDFDataRangeTransport_abort() {} - }; - return PDFDataRangeTransport; -}(); + addRangeListener(listener) { + this._rangeListeners.push(listener); + } + addProgressListener(listener) { + this._progressListeners.push(listener); + } + addProgressiveReadListener(listener) { + this._progressiveReadListeners.push(listener); + } + onDataRange(begin, chunk) { + for (const listener of this._rangeListeners) { + listener(begin, chunk); + } + } + onDataProgress(loaded) { + this._readyCapability.promise.then(() => { + for (const listener of this._progressListeners) { + listener(loaded); + } + }); + } + onDataProgressiveRead(chunk) { + this._readyCapability.promise.then(() => { + for (const listener of this._progressiveReadListeners) { + listener(chunk); + } + }); + } + transportReady() { + this._readyCapability.resolve(); + } + requestDataRange(begin, end) { + (0, _util.unreachable)('Abstract method PDFDataRangeTransport.requestDataRange'); + } + abort() {} +} class PDFDocumentProxy { constructor(pdfInfo, transport, loadingTask) { this.loadingTask = loadingTask; this._pdfInfo = pdfInfo; this._transport = transport; } get numPages() { return this._pdfInfo.numPages; @@ -5556,18 +5550,18 @@ var InternalRenderTask = function Intern } }); } }; return InternalRenderTask; }(); var version, build; { - exports.version = version = '2.0.936'; - exports.build = build = 'd2189293'; + exports.version = version = '2.0.943'; + exports.build = build = 'dc98bf76'; } exports.getDocument = getDocument; exports.LoopbackPort = LoopbackPort; exports.PDFDataRangeTransport = PDFDataRangeTransport; exports.PDFWorker = PDFWorker; exports.PDFDocumentProxy = PDFDocumentProxy; exports.PDFPageProxy = PDFPageProxy; exports.setPDFNetworkStreamFactory = setPDFNetworkStreamFactory;
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js +++ b/browser/extensions/pdfjs/content/build/pdf.worker.js @@ -118,18 +118,18 @@ return /******/ (function(modules) { // /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; -var pdfjsVersion = '2.0.936'; -var pdfjsBuild = 'd2189293'; +var pdfjsVersion = '2.0.943'; +var pdfjsBuild = 'dc98bf76'; var pdfjsCoreWorker = __w_pdfjs_require__(1); exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler; /***/ }), /* 1 */ /***/ (function(module, exports, __w_pdfjs_require__) { "use strict"; @@ -322,17 +322,17 @@ var WorkerMessageHandler = { }); }, createDocumentHandler(docParams, port) { var pdfManager; var terminated = false; var cancelXHRs = null; var WorkerTasks = []; let apiVersion = docParams.apiVersion; - let workerVersion = '2.0.936'; + let workerVersion = '2.0.943'; if (apiVersion !== workerVersion) { throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`); } var docId = docParams.docId; var docBaseUrl = docParams.docBaseUrl; var workerHandlerName = docParams.docId + '_worker'; var handler = new _message_handler.MessageHandler(workerHandlerName, docId, port); handler.postMessageTransfers = docParams.postMessageTransfers;
--- a/browser/extensions/pdfjs/content/web/viewer.js +++ b/browser/extensions/pdfjs/content/web/viewer.js @@ -9008,29 +9008,27 @@ class MozL10n { highlightAll: !!detail.highlightAll, findPrevious: !!detail.findPrevious }); }; for (let event of events) { window.addEventListener(event, handleEvent); } })(); -function FirefoxComDataRangeTransport(length, initialData) { - _pdfjsLib.PDFDataRangeTransport.call(this, length, initialData); -} -FirefoxComDataRangeTransport.prototype = Object.create(_pdfjsLib.PDFDataRangeTransport.prototype); -FirefoxComDataRangeTransport.prototype.requestDataRange = function FirefoxComDataRangeTransport_requestDataRange(begin, end) { - FirefoxCom.request('requestDataRange', { - begin, - end - }); -}; -FirefoxComDataRangeTransport.prototype.abort = function FirefoxComDataRangeTransport_abort() { - FirefoxCom.requestSync('abortLoading', null); -}; +class FirefoxComDataRangeTransport extends _pdfjsLib.PDFDataRangeTransport { + requestDataRange(begin, end) { + FirefoxCom.request('requestDataRange', { + begin, + end + }); + } + abort() { + FirefoxCom.requestSync('abortLoading', null); + } +} _app.PDFViewerApplication.externalServices = { updateFindControlState(data) { FirefoxCom.request('updateFindControlState', data); }, updateFindMatchesCount(data) { FirefoxCom.request('updateFindMatchesCount', data); }, initPassiveLoading(callbacks) {
--- a/browser/extensions/pdfjs/moz.yaml +++ b/browser/extensions/pdfjs/moz.yaml @@ -15,15 +15,15 @@ origin: description: Portable Document Format (PDF) viewer that is built with HTML5 # Full URL for the package's homepage/etc # Usually different from repository url url: https://github.com/mozilla/pdf.js # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: version 2.0.936 + release: version 2.0.943 # The package's license, where possible using the mnemonic from # https://spdx.org/licenses/ # Multiple licenses can be specified (as a YAML list) # A "LICENSE" file must exist containing the full license text license: Apache-2.0
--- a/config/external/ffi/moz.build +++ b/config/external/ffi/moz.build @@ -72,16 +72,18 @@ else: # Per-platform sources and flags. ffi_srcs = () if CONFIG['FFI_TARGET'] == 'ARM': ffi_srcs = ('sysv.S', 'ffi.c') if CONFIG['CC_TYPE'] == 'clang': ASFLAGS += ['-no-integrated-as'] elif CONFIG['FFI_TARGET'] == 'AARCH64': ffi_srcs = ('sysv.S', 'ffi.c') + elif CONFIG['FFI_TARGET'] == 'ARM64_WIN64': + ffi_srcs = ('win64.asm', 'ffi.c') elif CONFIG['FFI_TARGET'] == 'X86': ffi_srcs = ('ffi.c', 'sysv.S', 'win32.S') elif CONFIG['FFI_TARGET'] == 'X86_64': ffi_srcs = ('ffi64.c', 'unix64.S', 'ffi.c', 'sysv.S') elif CONFIG['FFI_TARGET'] == 'X86_WIN32': ffi_srcs = ['ffi.c'] # MinGW Build for 32 bit if CONFIG['CC_TYPE'] in ('gcc', 'clang'):
--- a/dom/base/nsDeprecatedOperationList.h +++ b/dom/base/nsDeprecatedOperationList.h @@ -44,8 +44,9 @@ DEPRECATED_OPERATION(MixedDisplayObjectS DEPRECATED_OPERATION(MotionEvent) DEPRECATED_OPERATION(OrientationEvent) DEPRECATED_OPERATION(ProximityEvent) DEPRECATED_OPERATION(AmbientLightEvent) DEPRECATED_OPERATION(IDBOpenDBOptions_StorageType) DEPRECATED_OPERATION(DOMAttrModifiedEvent) DEPRECATED_OPERATION(MozBoxOrInlineBoxDisplay) DEPRECATED_OPERATION(DOMQuadBoundsAttr) +DEPRECATED_OPERATION(CreateImageBitmapCanvasRenderingContext2D)
--- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -10709,18 +10709,22 @@ public: { public: explicit Iterator(nsIDocument* aDoc, IteratorOption aOption) : mCurrent(PendingFullscreenChangeList::sList.getFirst()) , mRootShellForIteration(aDoc->GetDocShell()) { if (mCurrent) { if (mRootShellForIteration && aOption == eDocumentsWithSameRoot) { + // Use a temporary to avoid undefined behavior from passing + // mRootShellForIteration. + nsCOMPtr<nsIDocShellTreeItem> root; mRootShellForIteration-> - GetRootTreeItem(getter_AddRefs(mRootShellForIteration)); + GetRootTreeItem(getter_AddRefs(root)); + mRootShellForIteration = root.forget(); } SkipToNextMatch(); } } UniquePtr<T> TakeAndNext() { auto thisChange = TakeAndNextInternal(); @@ -10746,17 +10750,19 @@ public: if (!docShell) { // Always automatically drop fullscreen changes which are // from a document detached from the doc shell. UniquePtr<T> change = TakeAndNextInternal(); change->MayRejectPromise(); continue; } while (docShell && docShell != mRootShellForIteration) { - docShell->GetParent(getter_AddRefs(docShell)); + nsCOMPtr<nsIDocShellTreeItem> parent; + docShell->GetParent(getter_AddRefs(parent)); + docShell = parent.forget(); } if (docShell) { break; } } // The current one either don't have matched type, or isn't // inside the given subtree, so skip this item. mCurrent = mCurrent->getNext();
--- a/dom/canvas/ImageBitmap.cpp +++ b/dom/canvas/ImageBitmap.cpp @@ -1056,16 +1056,25 @@ ImageBitmap::CreateInternal(nsIGlobalObj return ret.forget(); } /* static */ already_AddRefed<ImageBitmap> ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, CanvasRenderingContext2D& aCanvasCtx, const Maybe<IntRect>& aCropRect, ErrorResult& aRv) { + nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aGlobal); + nsGlobalWindowInner* window = nsGlobalWindowInner::Cast(win); + if (NS_WARN_IF(!window) || !window->GetExtantDoc()) { + aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); + return nullptr; + } + + window->GetExtantDoc()->WarnOnceAbout(nsIDocument::eCreateImageBitmapCanvasRenderingContext2D); + // Check origin-clean. if (aCanvasCtx.GetCanvas()->IsWriteOnly()) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return nullptr; } RefPtr<SourceSurface> surface = aCanvasCtx.GetSurfaceSnapshot();
--- a/dom/canvas/WebGLContext.cpp +++ b/dom/canvas/WebGLContext.cpp @@ -596,26 +596,18 @@ WebGLContext::CreateAndInitGL(bool force // -- typedef decltype(gl::GLContextProviderEGL::CreateOffscreen) fnCreateOffscreenT; const auto fnCreate = [&](fnCreateOffscreenT* const pfnCreateOffscreen, const char* const info) { const gfx::IntSize dummySize(1, 1); nsCString failureId; - RefPtr<GLContext> gl = pfnCreateOffscreen(dummySize, surfaceCaps, flags, - &failureId); - if (gl && gl->IsCoreProfile() && - !(flags & gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE) && - !gl->IsSupported(gl::GLFeature::gpu_shader5)) - { - // See comment on "constant-index-expression" in WebGLShaderValidator.cpp. - const auto compatFlags = flags | gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE; - gl = pfnCreateOffscreen(dummySize, surfaceCaps, compatFlags, &failureId); - } + const RefPtr<GLContext> gl = pfnCreateOffscreen(dummySize, surfaceCaps, flags, + &failureId); if (!gl) { out_failReasons->push_back(WebGLContext::FailureReason(failureId, info)); } return gl; }; const auto newGL = [&]() -> RefPtr<gl::GLContext> { if (tryNativeGL) {
--- a/dom/canvas/WebGLContextValidate.cpp +++ b/dom/canvas/WebGLContextValidate.cpp @@ -300,32 +300,33 @@ WebGLContext::ValidateUniformMatrixArray return true; } bool WebGLContext::InitAndValidateGL(FailureReason* const out_failReason) { MOZ_RELEASE_ASSERT(gl, "GFX: GL not initialized"); - if (!gl->MakeCurrent(true)) { - MOZ_ASSERT(false); - *out_failReason = { "FEATURE_FAILURE_WEBGL_MAKECURRENT", - "Failed to MakeCurrent for init." }; - return false; - } - // Unconditionally create a new format usage authority. This is // important when restoring contexts and extensions need to add // formats back into the authority. mFormatUsage = CreateFormatUsage(gl); - MOZ_RELEASE_ASSERT(mFormatUsage); + if (!mFormatUsage) { + *out_failReason = { "FEATURE_FAILURE_WEBGL_FORMAT", + "Failed to create mFormatUsage." }; + return false; + } - { - const auto error = gl->fGetError(); - MOZ_ALWAYS_TRUE(!error); + GLenum error = gl->fGetError(); + if (error != LOCAL_GL_NO_ERROR) { + const nsPrintfCString reason("GL error 0x%x occurred during OpenGL context" + " initialization, before WebGL initialization!", + error); + *out_failReason = { "FEATURE_FAILURE_WEBGL_GLERR_1", reason }; + return false; } mDisableExtensions = gfxPrefs::WebGLDisableExtensions(); mLoseContextOnMemoryPressure = gfxPrefs::WebGLLoseContextOnMemoryPressure(); mCanLoseContextInForeground = gfxPrefs::WebGLCanLoseContextInForeground(); mRestoreWhenVisible = gfxPrefs::WebGLRestoreWhenVisible(); // These are the default values, see 6.2 State tables in the @@ -598,19 +599,23 @@ WebGLContext::InitAndValidateGL(FailureR // Mesa can only be detected with the GL_VERSION string, of the form // "2.1 Mesa 7.11.0" const char* versionStr = (const char*)(gl->fGetString(LOCAL_GL_VERSION)); mIsMesa = strstr(versionStr, "Mesa"); // Notice that the point of calling fGetError here is not only to check for // errors, but also to reset the error flags so that a subsequent WebGL // getError call will give the correct result. - { - const auto error = gl->fGetError(); - MOZ_ALWAYS_TRUE(!error); + error = gl->fGetError(); + if (error != LOCAL_GL_NO_ERROR) { + const nsPrintfCString reason("GL error 0x%x occurred during WebGL context" + " initialization!", + error); + *out_failReason = { "FEATURE_FAILURE_WEBGL_GLERR_2", reason }; + return false; } if (IsWebGL2() && !InitWebGL2(out_failReason)) { // Todo: Bug 898404: Only allow WebGL2 on GL>=3.0 on desktop GL. return false; }
--- a/dom/canvas/WebGLShaderValidator.cpp +++ b/dom/canvas/WebGLShaderValidator.cpp @@ -1,16 +1,15 @@ /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WebGLShaderValidator.h" -#include <algorithm> #include "gfxPrefs.h" #include "GLContext.h" #include "mozilla/gfx/Logging.h" #include "mozilla/Preferences.h" #include "MurmurHash3.h" #include "nsPrintfCString.h" #include <string> #include <vector> @@ -97,32 +96,22 @@ ChooseValidatorCompileOptions(const ShBu return options; } } // namespace webgl //////////////////////////////////////// static ShShaderOutput -ShaderOutput(gl::GLContext* const gl) +ShaderOutput(gl::GLContext* gl) { if (gl->IsGLES()) { return SH_ESSL_OUTPUT; } else { uint32_t version = gl->ShadingLanguageVersion(); - - // Version 130 starts to require integral constant expressions for loop indices, - // instead of "constant-index-expression". - // Both version 400 and gpu_shader5 remove this restrictions. - // gpu_shader5 went core in 400, so we can just check for the GLFeature. - // If we're compiling for webglsl1, even for webgl2, we need gpu_shader5, or GLSL_COMPAT. - if (!gl->IsSupported(gl::GLFeature::gpu_shader5)) { - version = std::min<uint32_t>(version, 120); - } - switch (version) { case 100: return SH_GLSL_COMPATIBILITY_OUTPUT; case 120: return SH_GLSL_COMPATIBILITY_OUTPUT; case 130: return SH_GLSL_130_OUTPUT; case 140: return SH_GLSL_140_OUTPUT; case 150: return SH_GLSL_150_CORE_OUTPUT; case 330: return SH_GLSL_330_CORE_OUTPUT; case 400: return SH_GLSL_400_CORE_OUTPUT;
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini +++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini @@ -11112,16 +11112,17 @@ subsuite = webgl1-ext subsuite = webgl1-ext skip-if = (os == 'android') [generated/test_conformance__glsl__bugs__qualcomm-loop-with-continue-crash.html] subsuite = webgl1-ext [generated/test_conformance__glsl__bugs__sampler-array-struct-function-arg.html] subsuite = webgl1-ext [generated/test_conformance__glsl__bugs__sampler-array-using-loop-index.html] subsuite = webgl1-ext +fail-if = (os == 'linux') [generated/test_conformance__glsl__bugs__sampler-struct-function-arg.html] subsuite = webgl1-ext skip-if = (os == 'linux') || (os == 'android') [generated/test_conformance__glsl__bugs__sequence-operator-evaluation-order.html] subsuite = webgl1-ext skip-if = (os == 'android') [generated/test_conformance__glsl__bugs__sketchfab-lighting-shader-crash.html] subsuite = webgl1-ext @@ -11407,17 +11408,17 @@ subsuite = webgl1-ext [generated/test_conformance__glsl__misc__empty-declaration.html] subsuite = webgl1-ext [generated/test_conformance__glsl__misc__empty_main.vert.html] subsuite = webgl1-ext [generated/test_conformance__glsl__misc__expression-list-in-declarator-initializer.html] subsuite = webgl1-ext [generated/test_conformance__glsl__misc__fragcolor-fragdata-invariant.html] subsuite = webgl1-ext -fail-if = (os == 'linux') || (os == 'mac') +fail-if = (os == 'mac') [generated/test_conformance__glsl__misc__gl_position_unset.vert.html] subsuite = webgl1-ext [generated/test_conformance__glsl__misc__global-variable-init.html] subsuite = webgl1-ext [generated/test_conformance__glsl__misc__glsl-function-nodes.html] subsuite = webgl1-ext [generated/test_conformance__glsl__misc__glsl-long-variable-names.html] subsuite = webgl1-ext @@ -11587,17 +11588,16 @@ subsuite = webgl1-ext [generated/test_conformance__glsl__misc__shader-with-while-loop.html] subsuite = webgl1-ext [generated/test_conformance__glsl__misc__shader-without-precision.frag.html] subsuite = webgl1-ext [generated/test_conformance__glsl__misc__shaders-with-constant-expression-loop-conditions.html] subsuite = webgl1-ext [generated/test_conformance__glsl__misc__shaders-with-invariance.html] subsuite = webgl1-ext -fail-if = (os == 'linux') [generated/test_conformance__glsl__misc__shaders-with-mis-matching-uniforms.html] subsuite = webgl1-ext [generated/test_conformance__glsl__misc__shaders-with-mis-matching-varyings.html] subsuite = webgl1-ext [generated/test_conformance__glsl__misc__shaders-with-missing-varyings.html] subsuite = webgl1-ext [generated/test_conformance__glsl__misc__shaders-with-name-conflicts.html] subsuite = webgl1-ext
--- a/dom/canvas/test/webgl-conf/mochitest-errata.ini +++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini @@ -188,17 +188,19 @@ skip-if = (os == 'linux') || (os == 'mac [generated/test_conformance__glsl__constructors__glsl-construct-ivec4.html] # Assume crashes like ivec3 skip-if = (os == 'linux') || (os == 'mac') [generated/test_conformance__glsl__constructors__glsl-construct-mat2.html] # Crashes on Linux ASAN skip-if = ((os == 'linux') && asan) -[generated/test_conformance__glsl__misc__shaders-with-invariance.html] +[generated/test_conformance__glsl__bugs__sampler-array-using-loop-index.html] +# Testfail on Linux after removing SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX. +# Only happen on tryserver fail-if = (os == 'linux') [generated/test_conformance__misc__type-conversion-test.html] fail-if = (os == 'linux') # Resets device on Android 2.3. # Crashes on desktop Linux. skip-if = (os == 'android') || (os == 'linux') @@ -353,17 +355,17 @@ fail-if = (os == 'mac') || (verify && de skip-if = (os == 'win') [generated/test_2_conformance__rendering__rendering-stencil-large-viewport.html] # same as webgl1 test fail-if = (os == 'mac') skip-if = (os == 'win') [generated/test_conformance__glsl__misc__fragcolor-fragdata-invariant.html] # [unexpected fragment shader compile status] (expected: true) Declaring both gl_FragColor and gl_FragData invariant should succeed. -fail-if = (os == 'linux') || (os == 'mac') +fail-if = (os == 'mac') ######################################################################## # "tst-linux{32,64}-spot-NNN" Slaves: # Android 2.3 and Linux. # Android: os == 'android'. (Not enough info to separate out 2.3) # Linux: os == 'linux'. [generated/test_conformance__glsl__bugs__temp-expressions-should-not-crash.html] # Coincidentally enough, crashes on Linux and Android 4.0.
--- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -353,8 +353,10 @@ MixedDisplayObjectSubrequestWarning=Load MotionEventWarning=Use of the motion sensor is deprecated. OrientationEventWarning=Use of the orientation sensor is deprecated. ProximityEventWarning=Use of the proximity sensor is deprecated. AmbientLightEventWarning=Use of the ambient light sensor is deprecated. # LOCALIZATION NOTE: Do not translate "storage", "indexedDB.open" and "navigator.storage.persist()". IDBOpenDBOptions_StorageTypeWarning=The ‘storage’ attribute in options passed to indexedDB.open is deprecated and will soon be removed. To get persistent storage, please use navigator.storage.persist() instead. DOMQuadBoundsAttrWarning=DOMQuad.bounds is deprecated in favor of DOMQuad.getBounds() UnsupportedEntryTypesIgnored=Ignoring unsupported entryTypes: %S. +# LOCALIZATION NOTE (CreateImageBitmapCanvasRenderingContext2DWarning): Do not translate CanvasRenderingContext2D and createImageBitmap. +CreateImageBitmapCanvasRenderingContext2DWarning=Use of CanvasRenderingContext2D in createImageBitmap is deprecated.
--- a/dom/performance/Performance.cpp +++ b/dom/performance/Performance.cpp @@ -104,17 +104,17 @@ Performance::Now() const double maxResolutionMs = 0.020; DOMHighResTimeStamp minimallyClamped = floor(rawTime / maxResolutionMs) * maxResolutionMs; return nsRFPService::ReduceTimePrecisionAsMSecs(minimallyClamped, GetRandomTimelineSeed()); } DOMHighResTimeStamp Performance::NowUnclamped() const { - TimeDuration duration = TimeStamp::Now() - CreationTimeStamp(); + TimeDuration duration = TimeStamp::NowUnfuzzed() - CreationTimeStamp(); return duration.ToMilliseconds(); } DOMHighResTimeStamp Performance::TimeOrigin() { if (!mPerformanceService) { mPerformanceService = PerformanceService::GetOrCreate();
--- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -92,17 +92,16 @@ static const char* const sExtensionNames "GL_ARB_compatibility", "GL_ARB_copy_buffer", "GL_ARB_depth_texture", "GL_ARB_draw_buffers", "GL_ARB_draw_instanced", "GL_ARB_framebuffer_object", "GL_ARB_framebuffer_sRGB", "GL_ARB_geometry_shader4", - "GL_ARB_gpu_shader5", "GL_ARB_half_float_pixel", "GL_ARB_instanced_arrays", "GL_ARB_internalformat_query", "GL_ARB_invalidate_subdata", "GL_ARB_map_buffer_range", "GL_ARB_occlusion_query2", "GL_ARB_pixel_buffer_object", "GL_ARB_robust_buffer_access_behavior", @@ -135,17 +134,16 @@ static const char* const sExtensionNames "GL_EXT_draw_instanced", "GL_EXT_draw_range_elements", "GL_EXT_frag_depth", "GL_EXT_framebuffer_blit", "GL_EXT_framebuffer_multisample", "GL_EXT_framebuffer_object", "GL_EXT_framebuffer_sRGB", "GL_EXT_gpu_shader4", - "GL_EXT_gpu_shader5", "GL_EXT_multisampled_render_to_texture", "GL_EXT_occlusion_query_boolean", "GL_EXT_packed_depth_stencil", "GL_EXT_read_format_bgra", "GL_EXT_robustness", "GL_EXT_sRGB", "GL_EXT_sRGB_write_control", "GL_EXT_shader_texture_lod", @@ -169,17 +167,16 @@ static const char* const sExtensionNames "GL_KHR_robust_buffer_access_behavior", "GL_KHR_robustness", "GL_KHR_texture_compression_astc_hdr", "GL_KHR_texture_compression_astc_ldr", "GL_NV_draw_instanced", "GL_NV_fence", "GL_NV_framebuffer_blit", "GL_NV_geometry_program4", - "GL_NV_gpu_shader5", "GL_NV_half_float", "GL_NV_instanced_arrays", "GL_NV_primitive_restart", "GL_NV_texture_barrier", "GL_NV_transform_feedback", "GL_NV_transform_feedback2", "GL_OES_EGL_image", "GL_OES_EGL_image_external", @@ -376,20 +373,16 @@ GLContext::LoadFeatureSymbols(const char return false; } return true; }; bool GLContext::InitWithPrefixImpl(const char* prefix, bool trygl) { - // see bug 929506 comment 29. wglGetProcAddress requires a current context. - if (!MakeCurrent(true)) - return false; - mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs(); const SymLoadStruct coreSymbols[] = { { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } }, { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } }, { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } }, { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } }, { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } }, @@ -516,16 +509,20 @@ GLContext::InitWithPrefixImpl(const char END_SYMBOLS }; if (!LoadGLSymbols(this, prefix, trygl, coreSymbols, "GL")) return false; //////////////// + if (!MakeCurrent()) { + return false; + } + const std::string versionStr = (const char*)fGetString(LOCAL_GL_VERSION); if (versionStr.find("OpenGL ES") == 0) { mProfile = ContextProfile::OpenGLES; } uint32_t majorVer, minorVer; if (!ParseVersion(versionStr, &majorVer, &minorVer)) { MOZ_ASSERT(false, "Failed to parse GL_VERSION"); @@ -2049,19 +2046,21 @@ GLContext::MarkDestroyed() return; // Null these before they're naturally nulled after dtor, as we want GLContext to // still be alive in *their* dtors. mScreen = nullptr; mBlitHelper = nullptr; mReadTexImageHelper = nullptr; - mIsDestroyed = true; + if (!MakeCurrent()) { + NS_WARNING("MakeCurrent() failed during MarkDestroyed! Skipping GL object teardown."); + } + mSymbols = {}; - (void)MakeCurrent(true); // Clear current context. } #ifdef MOZ_GL_DEBUG /* static */ void GLContext::AssertNotPassingStackBufferToTheGL(const void* ptr) { int somethingOnTheStack; const void* someStackPtr = &somethingOnTheStack; @@ -2937,36 +2936,36 @@ GetBytesPerTexel(GLenum format, GLenum t return 2; } gfxCriticalError() << "Unknown texture type " << type << " or format " << format; return 0; } bool -GLContext::MakeCurrent(const bool aForce) const +GLContext::MakeCurrent(bool aForce) const { - if (MOZ_LIKELY( !aForce & !IsDestroyed() )) { - bool isCurrent = false; + if (MOZ_UNLIKELY( IsDestroyed() )) + return false; + + if (MOZ_LIKELY( !aForce )) { + bool isCurrent; if (mUseTLSIsCurrent) { isCurrent = (sCurrentContext.get() == reinterpret_cast<uintptr_t>(this)); - } - if (MOZ_UNLIKELY( !isCurrent )) { + } else { isCurrent = IsCurrentImpl(); } if (MOZ_LIKELY( isCurrent )) { MOZ_ASSERT(IsCurrentImpl()); return true; } } - if (MOZ_UNLIKELY( !MakeCurrentImpl() )) { - ClearGetCurrentContextTLS(); + if (!MakeCurrentImpl()) return false; - } sCurrentContext.set(reinterpret_cast<uintptr_t>(this)); return true; } void GLContext::ResetSyncCallCount(const char* resetReason) const {
--- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -98,17 +98,16 @@ enum class GLFeature { framebuffer_multisample, framebuffer_object, framebuffer_object_EXT_OES, get_integer_indexed, get_integer64_indexed, get_query_object_i64v, get_query_object_iv, gpu_shader4, - gpu_shader5, instanced_arrays, instanced_non_arrays, internalformat_query, invalidate_framebuffer, map_buffer_range, occlusion_query, occlusion_query_boolean, occlusion_query2, @@ -196,20 +195,16 @@ class GLContext : public GLLibraryLoader , public GenericAtomicRefCounted , public SupportsWeakPtr<GLContext> { public: MOZ_DECLARE_WEAKREFERENCE_TYPENAME(GLContext) static MOZ_THREAD_LOCAL(uintptr_t) sCurrentContext; - static void ClearGetCurrentContextTLS() { - sCurrentContext.set(0); - } - bool mImplicitMakeCurrent = false; bool mUseTLSIsCurrent; class TlsScope final { const WeakPtr<GLContext> mGL; const bool mWasTlsOk; public: explicit TlsScope(GLContext* const gl) @@ -341,17 +336,16 @@ public: */ virtual GLuint GetDefaultFramebuffer() { return 0; } protected: bool mIsOffscreen; mutable bool mContextLost = false; - bool mIsDestroyed = false; /** * mVersion store the OpenGL's version, multiplied by 100. For example, if * the context is an OpenGL 2.1 context, mVersion value will be 210. */ uint32_t mVersion = 0; ContextProfile mProfile = ContextProfile::Unknown; @@ -399,17 +393,16 @@ public: ARB_compatibility, ARB_copy_buffer, ARB_depth_texture, ARB_draw_buffers, ARB_draw_instanced, ARB_framebuffer_object, ARB_framebuffer_sRGB, ARB_geometry_shader4, - ARB_gpu_shader5, ARB_half_float_pixel, ARB_instanced_arrays, ARB_internalformat_query, ARB_invalidate_subdata, ARB_map_buffer_range, ARB_occlusion_query2, ARB_pixel_buffer_object, ARB_robust_buffer_access_behavior, @@ -442,17 +435,16 @@ public: EXT_draw_instanced, EXT_draw_range_elements, EXT_frag_depth, EXT_framebuffer_blit, EXT_framebuffer_multisample, EXT_framebuffer_object, EXT_framebuffer_sRGB, EXT_gpu_shader4, - EXT_gpu_shader5, EXT_multisampled_render_to_texture, EXT_occlusion_query_boolean, EXT_packed_depth_stencil, EXT_read_format_bgra, EXT_robustness, EXT_sRGB, EXT_sRGB_write_control, EXT_shader_texture_lod, @@ -476,17 +468,16 @@ public: KHR_robust_buffer_access_behavior, KHR_robustness, KHR_texture_compression_astc_hdr, KHR_texture_compression_astc_ldr, NV_draw_instanced, NV_fence, NV_framebuffer_blit, NV_geometry_program4, - NV_gpu_shader5, NV_half_float, NV_instanced_arrays, NV_primitive_restart, NV_texture_barrier, NV_transform_feedback, NV_transform_feedback2, OES_EGL_image, OES_EGL_image_external, @@ -3378,17 +3369,18 @@ protected: public: virtual bool Init() = 0; virtual bool SetupLookupFunction() = 0; virtual void ReleaseSurface() {} bool IsDestroyed() const { - return mIsDestroyed; + // MarkDestroyed will mark all these as null. + return mSymbols.fUseProgram == nullptr; } GLContext* GetSharedContext() { return mSharedContext; } /** * Returns true if the thread on which this context was created is the currently * executing thread. */
--- a/gfx/gl/GLContextCGL.h +++ b/gfx/gl/GLContextCGL.h @@ -19,17 +19,17 @@ typedef void NSOpenGLContext; namespace mozilla { namespace gl { class GLContextCGL : public GLContext { friend class GLContextProviderCGL; - NSOpenGLContext* const mContext; + NSOpenGLContext* mContext; public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextCGL, override) GLContextCGL(CreateContextFlags flags, const SurfaceCaps& caps, NSOpenGLContext* context, bool isOffscreen); ~GLContextCGL();
--- a/gfx/gl/GLContextFeatures.cpp +++ b/gfx/gl/GLContextFeatures.cpp @@ -317,28 +317,16 @@ static const FeatureInfo sFeatureInfoArr GLESVersion::ES3, GLContext::Extension_None, { GLContext::EXT_gpu_shader4, GLContext::Extensions_End } }, { - "gpu_shader5", - GLVersion::GL4, - GLESVersion::NONE, - GLContext::Extension_None, - { - GLContext::ARB_gpu_shader5, - GLContext::EXT_gpu_shader5, - GLContext::NV_gpu_shader5, - GLContext::Extensions_End - } - }, - { "instanced_arrays", GLVersion::GL3_3, GLESVersion::ES3, GLContext::Extension_None, { GLContext::ARB_instanced_arrays, GLContext::NV_instanced_arrays, GLContext::ANGLE_instanced_arrays,
--- a/gfx/gl/GLContextGLX.h +++ b/gfx/gl/GLContextGLX.h @@ -82,17 +82,16 @@ private: GLXContext aContext, bool aDeleteDrawable, bool aDoubleBuffered, gfxXlibSurface* aPixmap); GLXContext mContext; Display* mDisplay; GLXDrawable mDrawable; - Maybe<GLXDrawable> mOverrideDrawable; bool mDeleteDrawable; bool mDoubleBuffered; GLXLibrary* mGLX; RefPtr<gfxXlibSurface> mPixmap; bool mOwnsContext = true; };
--- a/gfx/gl/GLContextProviderCGL.mm +++ b/gfx/gl/GLContextProviderCGL.mm @@ -71,39 +71,46 @@ GLContextCGL::GLContextCGL(CreateContext : GLContext(flags, caps, nullptr, isOffscreen) , mContext(context) { } GLContextCGL::~GLContextCGL() { MarkDestroyed(); - [mContext release]; + + if (mContext) { + if ([NSOpenGLContext currentContext] == mContext) { + // Clear the current context before releasing. If we don't do + // this, the next time we call [NSOpenGLContext currentContext], + // "invalid context" will be printed to the console. + [NSOpenGLContext clearCurrentContext]; + } + [mContext release]; + } } bool GLContextCGL::Init() { - return InitWithPrefix("gl", true); + if (!InitWithPrefix("gl", true)) + return false; + + return true; } CGLContextObj GLContextCGL::GetCGLContext() const { return static_cast<CGLContextObj>([mContext CGLContextObj]); } bool GLContextCGL::MakeCurrentImpl() const { - if (IsDestroyed()) { - [NSOpenGLContext clearCurrentContext]; - return false; - } - if (mContext) { [mContext makeCurrentContext]; MOZ_ASSERT(IsCurrentImpl()); // Use non-blocking swap in "ASAP mode". // ASAP mode means that rendering is iterated as fast as possible. // ASAP mode is entered when layout.frame_rate=0 (requires restart). // If swapInt is 1, then glSwapBuffers will block and wait for a vblank signal. // When we're iterating as fast as possible, however, we want a non-blocking
--- a/gfx/gl/GLContextProviderEAGL.mm +++ b/gfx/gl/GLContextProviderEAGL.mm @@ -27,36 +27,45 @@ GLContextEAGL::GLContextEAGL(CreateConte bool isOffscreen) : GLContext(flags, caps, sharedContext, isOffscreen) , mContext(context) { } GLContextEAGL::~GLContextEAGL() { - if (MakeCurrent()) { - if (mBackbufferFB) { - fDeleteFramebuffers(1, &mBackbufferFB); - } + MakeCurrent(); - if (mBackbufferRB) { - fDeleteRenderbuffers(1, &mBackbufferRB); - } + if (mBackbufferFB) { + fDeleteFramebuffers(1, &mBackbufferFB); + } + + if (mBackbufferRB) { + fDeleteRenderbuffers(1, &mBackbufferRB); } - mLayer = nil; + MarkDestroyed(); - MarkDestroyed(); - [mContext release]; + if (mLayer) { + mLayer = nil; + } + + if (mContext) { + [EAGLContext setCurrentContext:nil]; + [mContext release]; + } } bool GLContextEAGL::Init() { - return InitWithPrefix("gl", true); + if (!InitWithPrefix("gl", true)) + return false; + + return true; } bool GLContextEAGL::AttachToWindow(nsIWidget* aWidget) { // This should only be called once MOZ_ASSERT(!mBackbufferFB && !mBackbufferRB); @@ -98,21 +107,22 @@ GLContextEAGL::RecreateRB() LOCAL_GL_RENDERBUFFER, mBackbufferRB); return LOCAL_GL_FRAMEBUFFER_COMPLETE == fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); } bool GLContextEAGL::MakeCurrentImpl() const { - if (IsDestroyed()) { - [EAGLContext setCurrentContext:nil]; - return false; + if (mContext) { + if(![EAGLContext setCurrentContext:mContext]) { + return false; + } } - return [EAGLContext setCurrentContext:mContext]; + return true; } bool GLContextEAGL::IsCurrentImpl() const { return [EAGLContext currentContext] == mContext; }
--- a/gfx/gl/GLContextProviderEGL.cpp +++ b/gfx/gl/GLContextProviderEGL.cpp @@ -153,28 +153,29 @@ is_power_of_two(int v) if (v == 0) return true; return (v & (v-1)) == 0; } static void -DestroySurface(const EGLSurface surf) -{ - if (!surf) - return; +DestroySurface(EGLSurface oldSurface) { + auto* egl = gl::GLLibraryEGL::Get(); - const auto& egl = gl::GLLibraryEGL::Get(); - - // TODO: This breaks TLS MakeCurrent caching. - MOZ_ALWAYS_TRUE( egl->fDestroySurface(EGL_DISPLAY(), surf) ); + if (oldSurface != EGL_NO_SURFACE) { + // TODO: This breaks TLS MakeCurrent caching. + egl->fMakeCurrent(EGL_DISPLAY(), + EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + egl->fDestroySurface(EGL_DISPLAY(), oldSurface); #if defined(MOZ_WAYLAND) - DeleteWaylandGLSurface(surf); + DeleteWaylandGLSurface(oldSurface); #endif + } } static EGLSurface CreateFallbackSurface(const EGLConfig& config) { nsCString discardFailureId; if (!GLLibraryEGL::EnsureInitialized(false, &discardFailureId)) { gfxCriticalNote << "Failed to load EGL library 3!"; @@ -278,17 +279,17 @@ GLContextEGLFactory::Create(EGLNativeWin if (aWebRender) { flags |= CreateContextFlags::PREFER_ES3; } SurfaceCaps caps = SurfaceCaps::Any(); RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(flags, caps, false, config, surface, &discardFailureId); if (!gl) { gfxCriticalNote << "Failed to create EGLContext!"; - DestroySurface(surface); + mozilla::gl::DestroySurface(surface); return nullptr; } gl->MakeCurrent(); gl->SetIsDoubleBuffered(doubleBuffered); if (aWebRender && egl->IsANGLE()) { MOZ_ASSERT(doubleBuffered); egl->fSwapInterval(EGL_DISPLAY(), 0); @@ -320,19 +321,19 @@ GLContextEGL::~GLContextEGL() return; } #ifdef DEBUG printf_stderr("Destroying context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY()); #endif mEgl->fDestroyContext(EGL_DISPLAY(), mContext); - DestroySurface(mSurface); - MOZ_ASSERT(!mFallbackSurface || mFallbackSurface != mSurface); - DestroySurface(mFallbackSurface); + + mozilla::gl::DestroySurface(mSurface); + mozilla::gl::DestroySurface(mFallbackSurface); } bool GLContextEGL::Init() { #if defined(ANDROID) // We can't use LoadApitraceLibrary here because the GLContext // expects its own handle to the GL library @@ -345,17 +346,23 @@ GLContextEGL::Init() return false; } #endif } SetupLookupFunction(); if (!InitWithPrefix("gl", true)) return false; - MOZ_ASSERT(IsCurrent()); + + bool current = MakeCurrent(); + if (!current) { + gfx::LogFailure(NS_LITERAL_CSTRING( + "Couldn't get device attachments for device.")); + return false; + } static_assert(sizeof(GLint) >= sizeof(int32_t), "GLint is smaller than int32_t"); mMaxTextureImageSize = INT32_MAX; mShareWithEGLImage = mEgl->HasKHRImageBase() && mEgl->HasKHRImageTexture2D() && IsExtensionSupported(OES_EGL_image); @@ -396,45 +403,36 @@ GLContextEGL::ReleaseTexImage() if (success == LOCAL_EGL_FALSE) return false; mBound = false; return true; } void -GLContextEGL::SetEGLSurfaceOverride(const EGLSurface surf) -{ - MOZ_ASSERT(!surf || surf != mSurface); - +GLContextEGL::SetEGLSurfaceOverride(EGLSurface surf) { if (Screen()) { /* Blit `draw` to `read` if we need to, before we potentially juggle * `read` around. If we don't, we might attach a different `read`, * and *then* hit AssureBlitted, which will blit a dirty `draw` onto * the wrong `read`! */ Screen()->AssureBlitted(); } mSurfaceOverride = surf; - MOZ_ALWAYS_TRUE( MakeCurrent(true) ); + DebugOnly<bool> ok = MakeCurrent(true); + MOZ_ASSERT(ok); } bool GLContextEGL::MakeCurrentImpl() const { - if (IsDestroyed()) { - MOZ_ALWAYS_TRUE( mEgl->fMakeCurrent(EGL_DISPLAY(), nullptr, nullptr, nullptr) ); - return false; - } - - auto surface = mSurface; - if (mSurfaceOverride) { - surface = mSurfaceOverride; - } + EGLSurface surface = (mSurfaceOverride != EGL_NO_SURFACE) ? mSurfaceOverride + : mSurface; if (!surface) { surface = mFallbackSurface; } const bool succeeded = mEgl->fMakeCurrent(EGL_DISPLAY(), surface, surface, mContext); if (!succeeded) { const auto eglError = mEgl->fGetError(); @@ -454,18 +452,17 @@ GLContextEGL::MakeCurrentImpl() const bool GLContextEGL::IsCurrentImpl() const { return mEgl->fGetCurrentContext() == mContext; } bool -GLContextEGL::RenewSurface(CompositorWidget* const aWidget) -{ +GLContextEGL::RenewSurface(CompositorWidget* aWidget) { if (!mOwnsContext) { return false; } // unconditionally release the surface and create a new one. Don't try to optimize this away. // If we get here, then by definition we know that we want to get a new surface. ReleaseSurface(); MOZ_ASSERT(aWidget); @@ -477,23 +474,24 @@ GLContextEGL::RenewSurface(CompositorWid return false; } } return MakeCurrent(true); } void -GLContextEGL::ReleaseSurface() -{ - if (!mOwnsContext) - return; - - DestroySurface(mSurface); - mSurface = nullptr; +GLContextEGL::ReleaseSurface() { + if (mOwnsContext) { + mozilla::gl::DestroySurface(mSurface); + } + if (mSurface == mSurfaceOverride) { + mSurfaceOverride = EGL_NO_SURFACE; + } + mSurface = EGL_NO_SURFACE; } bool GLContextEGL::SetupLookupFunction() { mLookupFunc = mEgl->GetLookupFunction(); return true; }
--- a/gfx/gl/GLContextProviderGLX.cpp +++ b/gfx/gl/GLContextProviderGLX.cpp @@ -582,22 +582,30 @@ GLContextGLX::~GLContextGLX() { MarkDestroyed(); // Wrapped context should not destroy glxContext/Surface if (!mOwnsContext) { return; } + // see bug 659842 comment 76 +#ifdef DEBUG + bool success = +#endif + mGLX->fMakeCurrent(mDisplay, X11None, nullptr); + MOZ_ASSERT(success, + "glXMakeCurrent failed to release GL context before we call " + "glXDestroyContext!"); + mGLX->fDestroyContext(mDisplay, mContext); if (mDeleteDrawable) { mGLX->fDestroyPixmap(mDisplay, mDrawable); } - MOZ_ASSERT(!mOverrideDrawable); } bool GLContextGLX::Init() { SetupLookupFunction(); if (!InitWithPrefix("gl", true)) { @@ -616,26 +624,17 @@ bool GLContextGLX::MakeCurrentImpl() const { if (mGLX->IsMesa()) { // Read into the event queue to ensure that Mesa receives a // DRI2InvalidateBuffers event before drawing. See bug 1280653. Unused << XPending(mDisplay); } - if (IsDestroyed()) { - MOZ_ALWAYS_TRUE( mGLX->fMakeCurrent(mDisplay, X11None, nullptr) ); - return false; // Did not MakeCurrent mContext, but that's what we wanted! - } - - auto drawable = mDrawable; - if (mOverrideDrawable) { - drawable = mOverrideDrawable.ref(); - } - const bool succeeded = mGLX->fMakeCurrent(mDisplay, drawable, mContext); + const bool succeeded = mGLX->fMakeCurrent(mDisplay, mDrawable, mContext); NS_ASSERTION(succeeded, "Failed to make GL context current!"); if (!IsOffscreen() && mGLX->SupportsSwapControl()) { // Many GLX implementations default to blocking until the next // VBlank when calling glXSwapBuffers. We want to run unthrottled // in ASAP mode. See bug 1280744. const bool isASAP = (gfxPrefs::LayoutFrameRate() == 0); mGLX->fSwapInterval(mDisplay, mDrawable, isASAP ? 0 : 1); @@ -690,28 +689,26 @@ GLContextGLX::GetWSIInfo(nsCString* cons out->AppendLiteral("\nExtensions: "); out->Append(sGLXLibrary.fQueryExtensionsString(display, screen)); } bool GLContextGLX::OverrideDrawable(GLXDrawable drawable) { - if (Screen()) { + if (Screen()) Screen()->AssureBlitted(); - } - mOverrideDrawable = Some(drawable); - return MakeCurrent(true); + Bool result = mGLX->fMakeCurrent(mDisplay, drawable, mContext); + return result; } bool GLContextGLX::RestoreDrawable() { - mOverrideDrawable = Nothing(); - return MakeCurrent(true); + return mGLX->fMakeCurrent(mDisplay, mDrawable, mContext); } GLContextGLX::GLContextGLX( CreateContextFlags flags, const SurfaceCaps& caps, bool isOffscreen, Display* aDisplay, GLXDrawable aDrawable,
--- a/gfx/gl/GLContextProviderWGL.cpp +++ b/gfx/gl/GLContextProviderWGL.cpp @@ -158,16 +158,17 @@ WGLLibrary::EnsureInitialized() // create rendering context mDummyGlrc = mSymbols.fCreateContext(mRootDc); if (!mDummyGlrc) return false; const auto curCtx = mSymbols.fGetCurrentContext(); const auto curDC = mSymbols.fGetCurrentDC(); + if (!mSymbols.fMakeCurrent(mRootDc, mDummyGlrc)) { NS_WARNING("wglMakeCurrent failed"); return false; } const auto resetContext = MakeScopeExit([&]() { mSymbols.fMakeCurrent(curDC, curCtx); }); @@ -293,16 +294,17 @@ GLContextWGL::GLContextWGL(CreateContext mPBuffer(aPbuffer), mPixelFormat(aPixelFormat) { } GLContextWGL::~GLContextWGL() { MarkDestroyed(); + (void)sWGLLib.mSymbols.fDeleteContext(mContext); if (mPBuffer) { (void)sWGLLib.mSymbols.fReleasePbufferDC(mPBuffer, mDC); (void)sWGLLib.mSymbols.fDestroyPbuffer(mPBuffer); } if (mWnd) { (void)ReleaseDC(mWnd, mDC); @@ -311,28 +313,30 @@ GLContextWGL::~GLContextWGL() } bool GLContextWGL::Init() { if (!mDC || !mContext) return false; + // see bug 929506 comment 29. wglGetProcAddress requires a current context. + if (!sWGLLib.mSymbols.fMakeCurrent(mDC, mContext)) + return false; + SetupLookupFunction(); - return InitWithPrefix("gl", true); + if (!InitWithPrefix("gl", true)) + return false; + + return true; } bool GLContextWGL::MakeCurrentImpl() const { - if (IsDestroyed()) { - MOZ_ALWAYS_TRUE( sWGLLib.mSymbols.fMakeCurrent(0, 0) ); - return false; - } - const bool succeeded = sWGLLib.mSymbols.fMakeCurrent(mDC, mContext); NS_ASSERTION(succeeded, "Failed to make GL context current!"); return succeeded; } bool GLContextWGL::IsCurrentImpl() const {
--- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -822,25 +822,53 @@ struct ParamTraits<mozilla::TimeStamp> template<> struct ParamTraits<mozilla::TimeStampValue> { typedef mozilla::TimeStampValue paramType; static void Write(Message* aMsg, const paramType& aParam) { WriteParam(aMsg, aParam.mGTC); WriteParam(aMsg, aParam.mQPC); + WriteParam(aMsg, aParam.mUsedCanonicalNow); + WriteParam(aMsg, aParam.mIsNull); WriteParam(aMsg, aParam.mHasQPC); - WriteParam(aMsg, aParam.mIsNull); } static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) { return (ReadParam(aMsg, aIter, &aResult->mGTC) && ReadParam(aMsg, aIter, &aResult->mQPC) && - ReadParam(aMsg, aIter, &aResult->mHasQPC) && - ReadParam(aMsg, aIter, &aResult->mIsNull)); + ReadParam(aMsg, aIter, &aResult->mUsedCanonicalNow) && + ReadParam(aMsg, aIter, &aResult->mIsNull) && + ReadParam(aMsg, aIter, &aResult->mHasQPC)); + } +}; + +#else + +template<> +struct ParamTraits<mozilla::TimeStamp63Bit> +{ + typedef mozilla::TimeStamp63Bit paramType; + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.mUsedCanonicalNow); + WriteParam(aMsg, aParam.mTimeStamp); + } + static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) + { + bool success = true; + uint64_t result; + + success &= ReadParam(aMsg, aIter, &result); + aResult->mUsedCanonicalNow = result & 0x01; + + success &= ReadParam(aMsg, aIter, &result); + aResult->mTimeStamp = result & 0x7FFFFFFFFFFFFFFF; + + return success; } }; #endif template <> struct ParamTraits<mozilla::dom::ipc::StructuredCloneData> {
--- a/js/ffi.configure +++ b/js/ffi.configure @@ -28,21 +28,21 @@ add_old_configure_assignment('MOZ_SYSTEM # Target selection, based on ffi/configure.ac. @depends(target, when=building_ffi) def ffi_target(target): if target.cpu not in ('x86', 'x86_64', 'arm', 'aarch64'): die('Building libffi from the tree is not supported on this platform. ' 'Use --with-system-ffi instead.') if target.os == 'WINNT': - target_dir = 'x86' - if target.cpu == 'x86_64': - target_name = 'X86_WIN64' - else: - target_name = 'X86_WIN32' + target_dir, target_name = { + 'x86_64': ('x86', 'X86_WIN64'), + 'x86': ('x86', 'X86_WIN32'), + 'aarch64': ('aarch64', 'ARM64_WIN64'), + }[target.cpu] elif target.os == 'OSX': target_dir = 'x86' target_name = 'X86_DARWIN' elif target.cpu == 'arm': target_dir = 'arm' target_name = 'ARM' elif target.cpu == 'aarch64': target_dir = 'aarch64'
--- a/js/src/builtin/intl/DateTimeFormat.js +++ b/js/src/builtin/intl/DateTimeFormat.js @@ -875,59 +875,42 @@ function Intl_DateTimeFormat_resolvedOpt } resolveICUPattern(internals.pattern, result); // Step 6. return result; } -// Table mapping ICU pattern characters back to the corresponding date-time -// components of DateTimeFormat. See -// http://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table -var icuPatternCharToComponent = { - E: "weekday", - G: "era", - y: "year", - M: "month", - L: "month", - d: "day", - h: "hour", - H: "hour", - k: "hour", - K: "hour", - m: "minute", - s: "second", - z: "timeZoneName", - v: "timeZoneName", - V: "timeZoneName", -}; - +/* eslint-disable complexity */ /** * Maps an ICU pattern string to a corresponding set of date-time components * and their values, and adds properties for these components to the result * object, which will be returned by the resolvedOptions method. For the * interpretation of ICU pattern characters, see * http://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table */ function resolveICUPattern(pattern, result) { assert(IsObject(result), "resolveICUPattern"); + + var hourCycle, weekday, era, year, month, day, hour, minute, second, timeZoneName; var i = 0; while (i < pattern.length) { var c = pattern[i++]; if (c === "'") { while (i < pattern.length && pattern[i] !== "'") i++; i++; } else { var count = 1; while (i < pattern.length && pattern[i] === c) { i++; count++; } + var value; switch (c) { // "text" cases case "G": case "E": case "z": case "v": case "V": @@ -964,31 +947,93 @@ function resolveICUPattern(pattern, resu else if (count === 4) value = "long"; else value = "narrow"; break; default: // skip other pattern characters and literal text } - if (hasOwn(c, icuPatternCharToComponent)) - _DefineDataProperty(result, icuPatternCharToComponent[c], value); + + // Map ICU pattern characters back to the corresponding date-time + // components of DateTimeFormat. See + // http://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table switch (c) { + case "E": + weekday = value; + break; + case "G": + era = value; + break; + case "y": + year = value; + break; + case "M": + case "L": + month = value; + break; + case "d": + day = value; + break; case "h": - _DefineDataProperty(result, "hourCycle", "h12"); - _DefineDataProperty(result, "hour12", true); + hourCycle = "h12"; + hour = value; + break; + case "H": + hourCycle = "h23"; + hour = value; + break; + case "k": + hourCycle = "h24"; + hour = value; break; case "K": - _DefineDataProperty(result, "hourCycle", "h11"); - _DefineDataProperty(result, "hour12", true); + hourCycle = "h11"; + hour = value; + break; + case "m": + minute = value; break; - case "H": - _DefineDataProperty(result, "hourCycle", "h23"); - _DefineDataProperty(result, "hour12", false); + case "s": + second = value; break; - case "k": - _DefineDataProperty(result, "hourCycle", "h24"); - _DefineDataProperty(result, "hour12", false); + case "z": + case "v": + case "V": + timeZoneName = value; break; } } } + + if (hourCycle) { + _DefineDataProperty(result, "hourCycle", hourCycle); + _DefineDataProperty(result, "hour12", hourCycle === "h11" || hourCycle === "h12"); + } + if (weekday) { + _DefineDataProperty(result, "weekday", weekday); + } + if (era) { + _DefineDataProperty(result, "era", era); + } + if (year) { + _DefineDataProperty(result, "year", year); + } + if (month) { + _DefineDataProperty(result, "month", month); + } + if (day) { + _DefineDataProperty(result, "day", day); + } + if (hour) { + _DefineDataProperty(result, "hour", hour); + } + if (minute) { + _DefineDataProperty(result, "minute", minute); + } + if (second) { + _DefineDataProperty(result, "second", second); + } + if (timeZoneName) { + _DefineDataProperty(result, "timeZoneName", timeZoneName); + } } +/* eslint-enable complexity */
--- a/js/src/builtin/intl/NumberFormat.js +++ b/js/src/builtin/intl/NumberFormat.js @@ -475,40 +475,42 @@ function Intl_NumberFormat_resolvedOptio var internals = getNumberFormatInternals(nf); // Steps 4-5. var result = { locale: internals.locale, numberingSystem: internals.numberingSystem, style: internals.style, - minimumIntegerDigits: internals.minimumIntegerDigits, - minimumFractionDigits: internals.minimumFractionDigits, - maximumFractionDigits: internals.maximumFractionDigits, - useGrouping: internals.useGrouping, }; // currency and currencyDisplay are only present for currency formatters. assert(hasOwn("currency", internals) === (internals.style === "currency"), "currency is present iff style is 'currency'"); assert(hasOwn("currencyDisplay", internals) === (internals.style === "currency"), "currencyDisplay is present iff style is 'currency'"); if (hasOwn("currency", internals)) { _DefineDataProperty(result, "currency", internals.currency); _DefineDataProperty(result, "currencyDisplay", internals.currencyDisplay); } + _DefineDataProperty(result, "minimumIntegerDigits", internals.minimumIntegerDigits); + _DefineDataProperty(result, "minimumFractionDigits", internals.minimumFractionDigits); + _DefineDataProperty(result, "maximumFractionDigits", internals.maximumFractionDigits); + // Min/Max significant digits are either both present or not at all. assert(hasOwn("minimumSignificantDigits", internals) === hasOwn("maximumSignificantDigits", internals), "minimumSignificantDigits is present iff maximumSignificantDigits is present"); if (hasOwn("minimumSignificantDigits", internals)) { _DefineDataProperty(result, "minimumSignificantDigits", internals.minimumSignificantDigits); _DefineDataProperty(result, "maximumSignificantDigits", internals.maximumSignificantDigits); } + _DefineDataProperty(result, "useGrouping", internals.useGrouping); + // Step 6. return result; }
--- a/js/src/builtin/intl/PluralRules.js +++ b/js/src/builtin/intl/PluralRules.js @@ -221,34 +221,20 @@ function Intl_PluralRules_resolvedOption // Steps 2-3. if (!IsObject(pluralRules) || (pluralRules = GuardToPluralRules(pluralRules)) === null) { ThrowTypeError(JSMSG_INTL_OBJECT_NOT_INITED, "PluralRules", "resolvedOptions", "PluralRules"); } var internals = getPluralRulesInternals(pluralRules); - var internalsPluralCategories = internals.pluralCategories; - if (internalsPluralCategories === null) { - internalsPluralCategories = intl_GetPluralCategories(pluralRules); - internals.pluralCategories = internalsPluralCategories; - } - - // TODO: The current spec actually requires to return the internal array - // object and not a copy of it. - // <https://github.com/tc39/proposal-intl-plural-rules/issues/28#issuecomment-341557030> - var pluralCategories = []; - for (var i = 0; i < internalsPluralCategories.length; i++) - _DefineDataProperty(pluralCategories, i, internalsPluralCategories[i]); - // Steps 4-5. var result = { locale: internals.locale, type: internals.type, - pluralCategories, minimumIntegerDigits: internals.minimumIntegerDigits, minimumFractionDigits: internals.minimumFractionDigits, maximumFractionDigits: internals.maximumFractionDigits, }; // Min/Max significant digits are either both present or not at all. assert(hasOwn("minimumSignificantDigits", internals) === hasOwn("maximumSignificantDigits", internals), @@ -257,10 +243,24 @@ function Intl_PluralRules_resolvedOption if (hasOwn("minimumSignificantDigits", internals)) { _DefineDataProperty(result, "minimumSignificantDigits", internals.minimumSignificantDigits); _DefineDataProperty(result, "maximumSignificantDigits", internals.maximumSignificantDigits); } // Step 6. + var internalsPluralCategories = internals.pluralCategories; + if (internalsPluralCategories === null) { + internalsPluralCategories = intl_GetPluralCategories(pluralRules); + internals.pluralCategories = internalsPluralCategories; + } + + var pluralCategories = []; + for (var i = 0; i < internalsPluralCategories.length; i++) + _DefineDataProperty(pluralCategories, i, internalsPluralCategories[i]); + + // Step 7. + _DefineDataProperty(result, "pluralCategories", pluralCategories); + + // Step 8. return result; }
--- a/js/src/builtin/intl/RelativeTimeFormat.js +++ b/js/src/builtin/intl/RelativeTimeFormat.js @@ -214,17 +214,17 @@ function Intl_RelativeTimeFormat_format( ThrowRangeError(JSMSG_INVALID_OPTION_VALUE, "unit", u); } // Step 5. return intl_FormatRelativeTime(relativeTimeFormat, t, u, internals.numeric); } /** - * Returns the resolved options for a PluralRules object. + * Returns the resolved options for a RelativeTimeFormat object. * * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.4.4. */ function Intl_RelativeTimeFormat_resolvedOptions() { var relativeTimeFormat; // Check "this RelativeTimeFormat object" per introduction of section 1.4. if (!IsObject(this) || (relativeTimeFormat = GuardToRelativeTimeFormat(this)) === null) { ThrowTypeError(JSMSG_INTL_OBJECT_NOT_INITED, "RelativeTimeFormat", "resolvedOptions",
--- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -6803,33 +6803,45 @@ GetABI(JSContext* cx, HandleValue abiTyp // given platform. ABI_DEFAULT specifies the default // C calling convention (cdecl) on each platform. switch (abi) { case ABI_DEFAULT: *result = FFI_DEFAULT_ABI; return true; case ABI_THISCALL: #if defined(_WIN64) +#if defined(_M_X64) *result = FFI_WIN64; +#elif defined(_M_ARM64) + *result = FFI_SYSV; +#else +#error unknown 64-bit Windows platform +#endif return true; #elif defined(_WIN32) *result = FFI_THISCALL; return true; #else break; #endif case ABI_STDCALL: case ABI_WINAPI: #if (defined(_WIN32) && !defined(_WIN64)) || defined(_OS2) *result = FFI_STDCALL; return true; #elif (defined(_WIN64)) // We'd like the same code to work across Win32 and Win64, so stdcall_api // and winapi_abi become aliases to the lone Win64 ABI. +#if defined(_M_X64) *result = FFI_WIN64; +#elif defined(_M_ARM64) + *result = FFI_SYSV; +#else +#error unknown 64-bit Windows platform +#endif return true; #endif case INVALID_ABI: break; } return false; }
--- a/js/src/ctypes/libffi/src/aarch64/ffi.c +++ b/js/src/ctypes/libffi/src/aarch64/ffi.c @@ -21,16 +21,23 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN #include <stdio.h> #include <ffi.h> #include <ffi_common.h> #include <stdlib.h> +#if defined(_WIN32) +#if !defined(WIN32_LEAN_AND_MEAN) +#define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> +#endif + /* Stack alignment requirement in bytes */ #if defined (__APPLE__) #define AARCH64_STACK_ALIGN 1 #else #define AARCH64_STACK_ALIGN 16 #endif #define N_X_ARG_REG 8 @@ -60,16 +67,19 @@ sys_icache_invalidate (void *start, size static inline void ffi_clear_cache (void *start, void *end) { #if defined (__clang__) && defined (__APPLE__) sys_icache_invalidate (start, (char *)end - (char *)start); #elif defined (__GNUC__) __builtin___clear_cache (start, end); +#elif defined (_WIN32) + FlushInstructionCache (GetCurrentProcess (), start, + (char*)end - (char*)start); #else #error "Missing builtin to flush instruction cache" #endif } static void * get_x_addr (struct call_context *context, unsigned n) { @@ -214,16 +224,20 @@ get_basic_type_size (unsigned short type return sizeof (SINT64); default: FFI_ASSERT (0); return 0; } } +// XXX The Win64 and the SYSV ABI are very close, differing only in their +// calling of varargs functions. Since we don't care about calling varargs +// functions in our use of libffi, we just hack our way through and use the +// SYSV-designated functions everywhere. extern void ffi_call_SYSV (unsigned (*)(struct call_context *context, unsigned char *, extended_cif *), struct call_context *context, extended_cif *, size_t, void (*fn)(void)); @@ -486,17 +500,17 @@ allocate_to_stack (struct arg_state *sta state->nsaa = ALIGN (state->nsaa, alignment); #if defined (__APPLE__) if (state->allocating_variadic) state->nsaa = ALIGN (state->nsaa, 8); #else state->nsaa = ALIGN (state->nsaa, 8); #endif - allocation = stack + state->nsaa; + allocation = (char*)stack + state->nsaa; state->nsaa += size; return allocation; } static void copy_basic_type (void *dest, void *source, unsigned short type) { @@ -570,17 +584,17 @@ copy_hfa_to_reg_or_stack (void *memory, else { int i; unsigned short type = get_homogeneous_type (ty); for (i = 0; i < elems; i++) { void *reg = allocate_to_v (context, state); copy_basic_type (reg, memory, type); - memory += get_basic_type_size (type); + memory = (char*)memory + get_basic_type_size (type); } } } /* Either allocate an appropriate register for the argument type, or if none are available, allocate a stack slot and return a pointer to the allocated space. */ @@ -854,17 +868,17 @@ ffi_call (ffi_cif *cif, void (*fn)(void) { int j; unsigned short type = get_homogeneous_type (cif->rtype); unsigned elems = element_count (cif->rtype); for (j = 0; j < elems; j++) { void *reg = get_basic_type_addr (type, &context, j); copy_basic_type (rvalue, reg, type); - rvalue += get_basic_type_size (type); + rvalue = (char*)rvalue + get_basic_type_size (type); } } else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG) { size_t size = ALIGN (cif->rtype->size, sizeof (UINT64)); memcpy (rvalue, get_x_addr (&context, 0), size); } else @@ -897,26 +911,27 @@ static unsigned char trampoline [] = { 0x70, 0x00, 0x00, 0x58, /* ldr x16, 1f */ 0x91, 0x00, 0x00, 0x10, /* adr x17, 2f */ 0x00, 0x02, 0x1f, 0xd6 /* br x16 */ }; /* Build a trampoline. */ #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,FLAGS) \ - ({unsigned char *__tramp = (unsigned char*)(TRAMP); \ + do { \ + unsigned char *__tramp = (unsigned char*)(TRAMP); \ UINT64 __fun = (UINT64)(FUN); \ UINT64 __ctx = (UINT64)(CTX); \ UINT64 __flags = (UINT64)(FLAGS); \ memcpy (__tramp, trampoline, sizeof (trampoline)); \ memcpy (__tramp + 12, &__fun, sizeof (__fun)); \ memcpy (__tramp + 20, &__ctx, sizeof (__ctx)); \ memcpy (__tramp + 28, &__flags, sizeof (__flags)); \ ffi_clear_cache(__tramp, __tramp + FFI_TRAMPOLINE_SIZE); \ - }) + } while(0) ffi_status ffi_prep_closure_loc (ffi_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data, void *codeloc) { @@ -1136,17 +1151,17 @@ ffi_closure_SYSV_inner (ffi_closure *clo { int j; unsigned short type = get_homogeneous_type (cif->rtype); unsigned elems = element_count (cif->rtype); for (j = 0; j < elems; j++) { void *reg = get_basic_type_addr (type, context, j); copy_basic_type (reg, rvalue, type); - rvalue += get_basic_type_size (type); + rvalue = (char*)rvalue + get_basic_type_size (type); } } else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG) { size_t size = ALIGN (cif->rtype->size, sizeof (UINT64)) ; memcpy (get_x_addr (context, 0), rvalue, size); } else
new file mode 100644 --- /dev/null +++ b/js/src/ctypes/libffi/src/aarch64/win64.asm @@ -0,0 +1,272 @@ +;; Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd. + +;; Permission is hereby granted, free of charge, to any person obtaining +;; a copy of this software and associated documentation files (the +;; ``Software''), to deal in the Software without restriction, including +;; without limitation the rights to use, copy, modify, merge, publish, +;; distribute, sublicense, and/or sell copies of the Software, and to +;; permit persons to whom the Software is furnished to do so, subject to +;; the following conditions: + +;; The above copyright notice and this permission notice shall be +;; included in all copies or substantial portions of the Software. + +;; THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +;; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +;; CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +;; Hand-converted from the sysv.S file in this directory. + + AREA |.text|, CODE, ARM64 + + ;; ffi_call_SYSV() + + ;; Create a stack frame, setup an argument context, call the callee + ;; and extract the result. + + ;; The maximum required argument stack size is provided, + ;; ffi_call_SYSV() allocates that stack space then calls the + ;; prepare_fn to populate register context and stack. The + ;; argument passing registers are loaded from the register + ;; context and the callee called, on return the register passing + ;; register are saved back to the context. Our caller will + ;; extract the return value from the final state of the saved + ;; register context. + + ;; Prototype: + + ;; extern unsigned + ;; ffi_call_SYSV (void (*)(struct call_context *context, unsigned char *, + ;; extended_cif *), + ;; struct call_context *context, + ;; extended_cif *, + ;; size_t required_stack_size, + ;; void (*fn)(void)); + + ;; Therefore on entry we have: + + ;; x0 prepare_fn + ;; x1 &context + ;; x2 &ecif + ;; x3 bytes + ;; x4 fn + + ;; This function uses the following stack frame layout: + + ;; == + ;; saved x30(lr) + ;; x29(fp)-> saved x29(fp) + ;; saved x24 + ;; saved x23 + ;; saved x22 + ;; sp' -> saved x21 + ;; ... + ;; sp -> (constructed callee stack arguments) + ;; == + + ;; Voila! + + EXPORT |ffi_call_SYSV| + +|ffi_call_SYSV| PROC +;#define ffi_call_SYSV_FS (8 * 4) + + stp x29, x30, [sp, #-16]! + + mov x29, sp + sub sp, sp, #32 ; ffi_call_SYSV_FS + + stp x21, x22, [sp, #0] + stp x23, x24, [sp, #16] + + mov x21, x1 + mov x22, x2 + mov x24, x4 + + ; Allocate the stack space for the actual arguments, many + ; arguments will be passed in registers, but we assume + ; worst case and allocate sufficient stack for ALL of + ; the arguments. + sub sp, sp, x3 + + ; unsigned (*prepare_fn) (struct call_context *context, + ; unsigned char *stack, extended_cif *ecif); + + mov x23, x0 + mov x0, x1 + mov x1, sp + ; x2 already in place + blr x23 + + ; Preserve the flags returned. + mov x23, x0 + + ; Figure out if we should touch the vector registers. + tbz x23, #0, noload_call + + ; Load the vector argument passing registers. + ldp q0, q1, [x21, #8*32 + 0] + ldp q2, q3, [x21, #8*32 + 32] + ldp q4, q5, [x21, #8*32 + 64] + ldp q6, q7, [x21, #8*32 + 96] + +noload_call + ; Load the core argument passing registers. + ldp x0, x1, [x21, #0] + ldp x2, x3, [x21, #16] + ldp x4, x5, [x21, #32] + ldp x6, x7, [x21, #48] + + ; Don't forget x8 which may be holding the address of a return buffer. + ldr x8, [x21, #8*8] + + blr x24 + + ; Save the core argument passing registers. + stp x0, x1, [x21, #0] + stp x2, x3, [x21, #16] + stp x4, x5, [x21, #32] + stp x6, x7, [x21, #48] + + ; Note nothing useful ever comes back in x8! + + ; Figure out if we should touch the vector registers. + tbz x23, #0, nosave_call ; AARCH64_FFI_WITH_V_BIT + + ; Save the vector argument passing registers. + stp q0, q1, [x21, #8*32 + 0] + stp q2, q3, [x21, #8*32 + 32] + stp q4, q5, [x21, #8*32 + 64] + stp q6, q7, [x21, #8*32 + 96] + +nosave_call + ; All done, unwind our stack frame. + ldp x21, x22, [x29, # - 32] ; ffi_call_SYSV_FS + + ldp x23, x24, [x29, # - 32 + 16] ; ffi_call_SYSV_FS + + mov sp, x29 + + ldp x29, x30, [sp], #16 + + ret + + ENDP + +; #define ffi_closure_SYSV_FS (8 * 2 + AARCH64_CALL_CONTEXT_SIZE) + + ;; ffi_closure_SYSV + + ;; Closure invocation glue. This is the low level code invoked directly by + ;; the closure trampoline to setup and call a closure. + + ;; On entry x17 points to a struct trampoline_data, x16 has been clobbered + ;; all other registers are preserved. + + ;; We allocate a call context and save the argument passing registers, + ;; then invoked the generic C ffi_closure_SYSV_inner() function to do all + ;; the real work, on return we load the result passing registers back from + ;; the call context. + + ;; On entry + + ;; extern void + ;; ffi_closure_SYSV (struct trampoline_data *); + + ;; struct trampoline_data + ;; { + ;; UINT64 *ffi_closure; + ;; UINT64 flags; + ;; }; + + ;; This function uses the following stack frame layout: + + ;; == + ;; saved x30(lr) + ;; x29(fp)-> saved x29(fp) + ;; saved x22 + ;; saved x21 + ;; ... + ;; sp -> call_context + ;; == + + ;; Voila! + + IMPORT |ffi_closure_SYSV_inner| + EXPORT |ffi_closure_SYSV| + +|ffi_closure_SYSV| PROC + stp x29, x30, [sp, #-16]! + + mov x29, sp + + sub sp, sp, #256+512+16 + + stp x21, x22, [x29, #-16] + + ; Load x21 with &call_context. + mov x21, sp + ; Preserve our struct trampoline_data + mov x22, x17 + + ; Save the rest of the argument passing registers. + stp x0, x1, [x21, #0] + stp x2, x3, [x21, #16] + stp x4, x5, [x21, #32] + stp x6, x7, [x21, #48] + ; Don't forget we may have been given a result scratch pad address. + str x8, [x21, #64] + + ; Figure out if we should touch the vector registers. + ldr x0, [x22, #8] + tbz x0, #0, nosave_closure ; AARCH64_FFI_WITH_V_BIT + + ; Save the argument passing vector registers. + stp q0, q1, [x21, #8*32 + 0] + stp q2, q3, [x21, #8*32 + 32] + stp q4, q5, [x21, #8*32 + 64] + stp q6, q7, [x21, #8*32 + 96] + +nosave_closure + ; Load &ffi_closure.. + ldr x0, [x22, #0] + mov x1, x21 + ; Compute the location of the stack at the point that the + ; trampoline was called. + add x2, x29, #16 + + bl ffi_closure_SYSV_inner + + ; Figure out if we should touch the vector registers. + ldr x0, [x22, #8] + tbz x0, #0, noload_closure ; AARCH64_FFI_WITH_V_BIT + + ; Load the result passing vector registers. + ldp q0, q1, [x21, #8*32 + 0] + ldp q2, q3, [x21, #8*32 + 32] + ldp q4, q5, [x21, #8*32 + 64] + ldp q6, q7, [x21, #8*32 + 96] + +noload_closure + ; Load the result passing core registers. + ldp x0, x1, [x21, #0] + ldp x2, x3, [x21, #16] + ldp x4, x5, [x21, #32] + ldp x6, x7, [x21, #48] + ; Note nothing useful is returned in x8. + + ; We are done, unwind our frame. + ldp x21, x22, [x29, #-16] + + mov sp, x29 + + ldp x29, x30, [sp], #16 + + ret + + ENDP + END
--- a/js/src/jit-test/jit_test.py +++ b/js/src/jit-test/jit_test.py @@ -370,19 +370,23 @@ def main(argv): elif options.debugger == 'lldb': debug_cmd = ['lldb', '--'] elif options.debugger == 'rr': debug_cmd = ['rr', 'record'] else: debug_cmd = options.debugger.split() with change_env(test_environment): - subprocess.call(debug_cmd + tc.command(prefix, jittests.LIB_DIR, jittests.MODULE_DIR)) if options.debugger == 'rr': - subprocess.call(['rr', 'replay']) + subprocess.call(debug_cmd + + tc.command(prefix, jittests.LIB_DIR, jittests.MODULE_DIR)) + os.execvp('rr', ['rr', 'replay']) + else: + os.execvp(debug_cmd[0], debug_cmd + + tc.command(prefix, jittests.LIB_DIR, jittests.MODULE_DIR)) sys.exit() try: ok = None if options.remote: ok = jittests.run_tests(job_list, job_count, prefix, options, remote=True) else: with change_env(test_environment):
--- a/js/src/jit/JitRealm.h +++ b/js/src/jit/JitRealm.h @@ -633,44 +633,40 @@ const unsigned WINDOWS_BIG_FRAME_TOUCH_I // AutoWritableJitCodeFallible may only fail to make code writable; it cannot fail to // make JIT code executable (because the creating code has no chance to // recover from a failed destructor). class MOZ_RAII AutoWritableJitCodeFallible { JSRuntime* rt_; void* addr_; size_t size_; - bool madeWritable_; public: AutoWritableJitCodeFallible(JSRuntime* rt, void* addr, size_t size) - : rt_(rt), addr_(addr), size_(size), madeWritable_(false) + : rt_(rt), addr_(addr), size_(size) { rt_->toggleAutoWritableJitCodeActive(true); } AutoWritableJitCodeFallible(void* addr, size_t size) : AutoWritableJitCodeFallible(TlsContext.get()->runtime(), addr, size) { } explicit AutoWritableJitCodeFallible(JitCode* code) : AutoWritableJitCodeFallible(code->runtimeFromMainThread(), code->raw(), code->bufferSize()) {} MOZ_MUST_USE bool makeWritable() { - madeWritable_ = ExecutableAllocator::makeWritable(addr_, size_); - return madeWritable_; + return ExecutableAllocator::makeWritable(addr_, size_); } ~AutoWritableJitCodeFallible() { - if (madeWritable_) { - if (!ExecutableAllocator::makeExecutable(addr_, size_)) { - MOZ_CRASH(); - } + if (!ExecutableAllocator::makeExecutable(addr_, size_)) { + MOZ_CRASH(); } rt_->toggleAutoWritableJitCodeActive(false); } }; // Infallible variant of AutoWritableJitCodeFallible, ensures writable during construction class MOZ_RAII AutoWritableJitCode : private AutoWritableJitCodeFallible
new file mode 100644 --- /dev/null +++ b/js/src/jit/moz.build @@ -0,0 +1,239 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +FINAL_LIBRARY = 'js' + +FILES_PER_UNIFIED_FILE = 6 + +# Includes should be relative to parent path +LOCAL_INCLUDES += [ + '!..', + '..' +] + +include('../js-config.mozbuild') +include('../js-cxxflags.mozbuild') + + +# Generate jit/MOpcodes.h from jit/MIR.h +GENERATED_FILES += ['MOpcodes.h'] +MOpcodesGenerated = GENERATED_FILES['MOpcodes.h'] +MOpcodesGenerated.script = 'GenerateOpcodeFiles.py:generate_mir_header' +MOpcodesGenerated.inputs = ['MIR.h'] + +# Generate jit/LOpcodes.h from jit/LIR.h, jit/shared/LIR-shared.h, and +# platform-specific LIR files. +GENERATED_FILES += ['LOpcodes.h'] +LOpcodesGenerated = GENERATED_FILES['LOpcodes.h'] +LOpcodesGenerated.script = 'GenerateOpcodeFiles.py:generate_lir_header' +LOpcodesGenerated.inputs = ['LIR.h', 'shared/LIR-shared.h'] + + +UNIFIED_SOURCES += [ + 'AliasAnalysis.cpp', + 'AlignmentMaskAnalysis.cpp', + 'BacktrackingAllocator.cpp', + 'Bailouts.cpp', + 'BaselineBailouts.cpp', + 'BaselineCacheIRCompiler.cpp', + 'BaselineCompiler.cpp', + 'BaselineDebugModeOSR.cpp', + 'BaselineFrame.cpp', + 'BaselineFrameInfo.cpp', + 'BaselineIC.cpp', + 'BaselineInspector.cpp', + 'BaselineJIT.cpp', + 'BitSet.cpp', + 'BytecodeAnalysis.cpp', + 'CacheIR.cpp', + 'CacheIRCompiler.cpp', + 'CacheIRSpewer.cpp', + 'CodeGenerator.cpp', + 'CompileWrappers.cpp', + 'EdgeCaseAnalysis.cpp', + 'EffectiveAddressAnalysis.cpp', + 'ExecutableAllocator.cpp', + 'FoldLinearArithConstants.cpp', + 'InstructionReordering.cpp', + 'Ion.cpp', + 'IonAnalysis.cpp', + 'IonBuilder.cpp', + 'IonCacheIRCompiler.cpp', + 'IonControlFlow.cpp', + 'IonIC.cpp', + 'IonOptimizationLevels.cpp', + 'Jit.cpp', + 'JitcodeMap.cpp', + 'JitFrames.cpp', + 'JitOptions.cpp', + 'JitSpewer.cpp', + 'JSJitFrameIter.cpp', + 'JSONSpewer.cpp', + 'LICM.cpp', + 'Linker.cpp', + 'LIR.cpp', + 'LoopUnroller.cpp', + 'Lowering.cpp', + 'MacroAssembler.cpp', + 'MCallOptimize.cpp', + 'MIR.cpp', + 'MIRGraph.cpp', + 'MoveResolver.cpp', + 'OptimizationTracking.cpp', + 'PerfSpewer.cpp', + 'ProcessExecutableMemory.cpp', + 'RangeAnalysis.cpp', + 'Recover.cpp', + 'RegisterAllocator.cpp', + 'RematerializedFrame.cpp', + 'Safepoints.cpp', + 'ScalarReplacement.cpp', + 'shared/Assembler-shared.cpp', + 'shared/CodeGenerator-shared.cpp', + 'shared/Disassembler-shared.cpp', + 'shared/Lowering-shared.cpp', + 'Sink.cpp', + 'Snapshots.cpp', + 'StupidAllocator.cpp', + 'TypedObjectPrediction.cpp', + 'TypePolicy.cpp', + 'ValueNumbering.cpp', + 'VMFunctions.cpp', + 'WasmBCE.cpp', +] + +if not CONFIG['ENABLE_ION']: + LOpcodesGenerated.inputs += ['none/LIR-none.h'] + UNIFIED_SOURCES += [ + 'none/Trampoline-none.cpp' + ] +elif CONFIG['JS_CODEGEN_X86'] or CONFIG['JS_CODEGEN_X64']: + LOpcodesGenerated.inputs += ['x86-shared/LIR-x86-shared.h'] + UNIFIED_SOURCES += [ + 'x86-shared/Architecture-x86-shared.cpp', + 'x86-shared/Assembler-x86-shared.cpp', + 'x86-shared/AssemblerBuffer-x86-shared.cpp', + 'x86-shared/CodeGenerator-x86-shared.cpp', + 'x86-shared/Lowering-x86-shared.cpp', + 'x86-shared/MacroAssembler-x86-shared-SIMD.cpp', + 'x86-shared/MacroAssembler-x86-shared.cpp', + 'x86-shared/MoveEmitter-x86-shared.cpp', + ] + if CONFIG['JS_CODEGEN_X64']: + LOpcodesGenerated.inputs += ['x64/LIR-x64.h'] + UNIFIED_SOURCES += [ + 'x64/Assembler-x64.cpp', + 'x64/Bailouts-x64.cpp', + 'x64/CodeGenerator-x64.cpp', + 'x64/Lowering-x64.cpp', + 'x64/MacroAssembler-x64.cpp', + 'x64/Trampoline-x64.cpp', + ] + else: + LOpcodesGenerated.inputs += ['x86/LIR-x86.h'] + UNIFIED_SOURCES += [ + 'x86/Assembler-x86.cpp', + 'x86/Bailouts-x86.cpp', + 'x86/CodeGenerator-x86.cpp', + 'x86/Lowering-x86.cpp', + 'x86/MacroAssembler-x86.cpp', + 'x86/Trampoline-x86.cpp', + ] +elif CONFIG['JS_CODEGEN_ARM']: + LOpcodesGenerated.inputs += ['arm/LIR-arm.h'] + UNIFIED_SOURCES += [ + 'arm/Architecture-arm.cpp', + 'arm/Assembler-arm.cpp', + 'arm/Bailouts-arm.cpp', + 'arm/CodeGenerator-arm.cpp', + 'arm/disasm/Constants-arm.cpp', + 'arm/disasm/Disasm-arm.cpp', + 'arm/Lowering-arm.cpp', + 'arm/MacroAssembler-arm.cpp', + 'arm/MoveEmitter-arm.cpp', + 'arm/Trampoline-arm.cpp', + ] + if CONFIG['JS_SIMULATOR_ARM']: + UNIFIED_SOURCES += [ + 'arm/Simulator-arm.cpp' + ] + elif CONFIG['OS_ARCH'] == 'Darwin': + SOURCES += [ + 'arm/llvm-compiler-rt/arm/aeabi_idivmod.S', + 'arm/llvm-compiler-rt/arm/aeabi_uidivmod.S', + ] +elif CONFIG['JS_CODEGEN_ARM64']: + LOpcodesGenerated.inputs += ['arm64/LIR-arm64.h'] + UNIFIED_SOURCES += [ + 'arm64/Architecture-arm64.cpp', + 'arm64/Assembler-arm64.cpp', + 'arm64/Bailouts-arm64.cpp', + 'arm64/CodeGenerator-arm64.cpp', + 'arm64/Lowering-arm64.cpp', + 'arm64/MacroAssembler-arm64.cpp', + 'arm64/MoveEmitter-arm64.cpp', + 'arm64/Trampoline-arm64.cpp', + 'arm64/vixl/Assembler-vixl.cpp', + 'arm64/vixl/Cpu-vixl.cpp', + 'arm64/vixl/Decoder-vixl.cpp', + 'arm64/vixl/Disasm-vixl.cpp', + 'arm64/vixl/Instructions-vixl.cpp', + 'arm64/vixl/Instrument-vixl.cpp', + 'arm64/vixl/MacroAssembler-vixl.cpp', + 'arm64/vixl/MozAssembler-vixl.cpp', + 'arm64/vixl/MozInstructions-vixl.cpp', + 'arm64/vixl/Utils-vixl.cpp' + ] + if CONFIG['JS_SIMULATOR_ARM64']: + UNIFIED_SOURCES += [ + 'arm64/vixl/Debugger-vixl.cpp', + 'arm64/vixl/Logic-vixl.cpp', + 'arm64/vixl/MozSimulator-vixl.cpp', + 'arm64/vixl/Simulator-vixl.cpp' + ] +elif CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']: + LOpcodesGenerated.inputs += ['mips-shared/LIR-mips-shared.h'] + UNIFIED_SOURCES += [ + 'mips-shared/Architecture-mips-shared.cpp', + 'mips-shared/Assembler-mips-shared.cpp', + 'mips-shared/Bailouts-mips-shared.cpp', + 'mips-shared/CodeGenerator-mips-shared.cpp', + 'mips-shared/Lowering-mips-shared.cpp', + 'mips-shared/MacroAssembler-mips-shared.cpp', + 'mips-shared/MoveEmitter-mips-shared.cpp', + ] + if CONFIG['JS_CODEGEN_MIPS32']: + LOpcodesGenerated.inputs += ['mips32/LIR-mips32.h'] + UNIFIED_SOURCES += [ + 'mips32/Architecture-mips32.cpp', + 'mips32/Assembler-mips32.cpp', + 'mips32/Bailouts-mips32.cpp', + 'mips32/CodeGenerator-mips32.cpp', + 'mips32/Lowering-mips32.cpp', + 'mips32/MacroAssembler-mips32.cpp', + 'mips32/MoveEmitter-mips32.cpp', + 'mips32/Trampoline-mips32.cpp', + ] + if CONFIG['JS_SIMULATOR_MIPS32']: + UNIFIED_SOURCES += [ + 'mips32/Simulator-mips32.cpp' + ] + elif CONFIG['JS_CODEGEN_MIPS64']: + LOpcodesGenerated.inputs += ['mips64/LIR-mips64.h'] + UNIFIED_SOURCES += [ + 'mips64/Architecture-mips64.cpp', + 'mips64/Assembler-mips64.cpp', + 'mips64/Bailouts-mips64.cpp', + 'mips64/CodeGenerator-mips64.cpp', + 'mips64/Lowering-mips64.cpp', + 'mips64/MacroAssembler-mips64.cpp', + 'mips64/MoveEmitter-mips64.cpp', + 'mips64/Trampoline-mips64.cpp', + ] + if CONFIG['JS_SIMULATOR_MIPS64']: + UNIFIED_SOURCES += [ + 'mips64/Simulator-mips64.cpp' + ] \ No newline at end of file
--- a/js/src/jsapi-tests/moz.build +++ b/js/src/jsapi-tests/moz.build @@ -136,16 +136,17 @@ if CONFIG['ENABLE_ION']: 'testJitRegisterSet.cpp', 'testJitRValueAlloc.cpp', ] if CONFIG['NIGHTLY_BUILD']: # The Error interceptor only exists on Nightly. UNIFIED_SOURCES += [ 'testErrorInterceptor.cpp', + 'testErrorInterceptorGC.cpp', ] if CONFIG['JS_BUILD_BINAST'] and CONFIG['JS_STANDALONE'] and not CONFIG['FUZZING']: # Standalone builds leave the source directory untouched, # which lets us run tests with the data files intact. # Otherwise, in the current state of the build system, # we can't have data files in js/src tests. # Also, fuzzing builds modify the const matching in the
--- a/js/src/jsapi-tests/testErrorInterceptor.cpp +++ b/js/src/jsapi-tests/testErrorInterceptor.cpp @@ -7,17 +7,17 @@ // Tests for JS_GetErrorInterceptorCallback and JS_SetErrorInterceptorCallback. namespace { static JS::PersistentRootedString gLatestMessage; // An interceptor that stores the error in `gLatestMessage`. struct SimpleInterceptor: JSErrorInterceptor { - virtual void interceptError(JSContext* cx, const JS::Value& val) override { + virtual void interceptError(JSContext* cx, JS::HandleValue val) override { js::StringBuffer buffer(cx); if (!ValueToStringBuffer(cx, val, buffer)) { MOZ_CRASH("Could not convert to string buffer"); } gLatestMessage = buffer.finishString(); if (!gLatestMessage) { MOZ_CRASH("Could not convert to string"); }
new file mode 100644 --- /dev/null +++ b/js/src/jsapi-tests/testErrorInterceptorGC.cpp @@ -0,0 +1,34 @@ +#include "jsapi.h" + +#include "jsapi-tests/tests.h" + +namespace { + +// An interceptor that triggers GC: +struct ErrorInterceptorWithGC : JSErrorInterceptor { + void interceptError(JSContext* cx, JS::HandleValue val) override { + JS::PrepareForFullGC(cx); + JS::NonIncrementalGC(cx, GC_SHRINK, JS::gcreason::DEBUG_GC); + } +}; + +} + +BEGIN_TEST(testErrorInterceptorGC) +{ + JSErrorInterceptor* original = JS_GetErrorInterceptorCallback(cx->runtime()); + + ErrorInterceptorWithGC interceptor; + JS_SetErrorInterceptorCallback(cx->runtime(), &interceptor); + + CHECK(!execDontReport("0 = 0;", __FILE__, __LINE__)); + + CHECK(JS_IsExceptionPending(cx)); + JS_ClearPendingException(cx); + + // Restore the original error interceptor. + JS_SetErrorInterceptorCallback(cx->runtime(), original); + + return true; +} +END_TEST(testErrorInterceptorGC)
--- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -257,17 +257,17 @@ using JSExternalStringSizeofCallback = * Callback used to intercept JavaScript errors. */ struct JSErrorInterceptor { /** * This method is called whenever an error has been raised from JS code. * * This method MUST be infallible. */ - virtual void interceptError(JSContext* cx, const JS::Value& error) = 0; + virtual void interceptError(JSContext* cx, JS::HandleValue error) = 0; }; /************************************************************************/ static MOZ_ALWAYS_INLINE JS::Value JS_NumberValue(double d) { int32_t i;
--- a/js/src/moz.build +++ b/js/src/moz.build @@ -93,29 +93,16 @@ CONFIGURE_DEFINE_FILES += [ 'js-config.h', ] if CONFIG['HAVE_DTRACE']: GENERATED_FILES += ['javascript-trace.h'] EXPORTS += ['!javascript-trace.h'] -# Generate jit/MOpcodes.h from jit/MIR.h -GENERATED_FILES += ['jit/MOpcodes.h'] -MOpcodesGenerated = GENERATED_FILES['jit/MOpcodes.h'] -MOpcodesGenerated.script = 'jit/GenerateOpcodeFiles.py:generate_mir_header' -MOpcodesGenerated.inputs = ['jit/MIR.h'] - -# Generate jit/LOpcodes.h from jit/LIR.h, jit/shared/LIR-shared.h, and -# platform-specific LIR files. -GENERATED_FILES += ['jit/LOpcodes.h'] -LOpcodesGenerated = GENERATED_FILES['jit/LOpcodes.h'] -LOpcodesGenerated.script = 'jit/GenerateOpcodeFiles.py:generate_lir_header' -LOpcodesGenerated.inputs = ['jit/LIR.h', 'jit/shared/LIR-shared.h'] - # Changes to internal header files, used externally, massively slow down # browser builds. Don't add new files here unless you know what you're # doing! EXPORTS += [ '!js-config.h', 'js.msg', 'jsapi.h', 'jsfriendapi.h', @@ -266,86 +253,16 @@ UNIFIED_SOURCES += [ 'irregexp/NativeRegExpMacroAssembler.cpp', 'irregexp/RegExpAST.cpp', 'irregexp/RegExpCharacters.cpp', 'irregexp/RegExpEngine.cpp', 'irregexp/RegExpInterpreter.cpp', 'irregexp/RegExpMacroAssembler.cpp', 'irregexp/RegExpParser.cpp', 'irregexp/RegExpStack.cpp', - 'jit/AliasAnalysis.cpp', - 'jit/AlignmentMaskAnalysis.cpp', - 'jit/BacktrackingAllocator.cpp', - 'jit/Bailouts.cpp', - 'jit/BaselineBailouts.cpp', - 'jit/BaselineCacheIRCompiler.cpp', - 'jit/BaselineCompiler.cpp', - 'jit/BaselineDebugModeOSR.cpp', - 'jit/BaselineFrame.cpp', - 'jit/BaselineFrameInfo.cpp', - 'jit/BaselineIC.cpp', - 'jit/BaselineInspector.cpp', - 'jit/BaselineJIT.cpp', - 'jit/BitSet.cpp', - 'jit/BytecodeAnalysis.cpp', - 'jit/CacheIR.cpp', - 'jit/CacheIRCompiler.cpp', - 'jit/CacheIRSpewer.cpp', - 'jit/CodeGenerator.cpp', - 'jit/CompileWrappers.cpp', - 'jit/EdgeCaseAnalysis.cpp', - 'jit/EffectiveAddressAnalysis.cpp', - 'jit/ExecutableAllocator.cpp', - 'jit/FoldLinearArithConstants.cpp', - 'jit/InstructionReordering.cpp', - 'jit/Ion.cpp', - 'jit/IonAnalysis.cpp', - 'jit/IonBuilder.cpp', - 'jit/IonCacheIRCompiler.cpp', - 'jit/IonControlFlow.cpp', - 'jit/IonIC.cpp', - 'jit/IonOptimizationLevels.cpp', - 'jit/Jit.cpp', - 'jit/JitcodeMap.cpp', - 'jit/JitFrames.cpp', - 'jit/JitOptions.cpp', - 'jit/JitSpewer.cpp', - 'jit/JSJitFrameIter.cpp', - 'jit/JSONSpewer.cpp', - 'jit/LICM.cpp', - 'jit/Linker.cpp', - 'jit/LIR.cpp', - 'jit/LoopUnroller.cpp', - 'jit/Lowering.cpp', - 'jit/MacroAssembler.cpp', - 'jit/MCallOptimize.cpp', - 'jit/MIR.cpp', - 'jit/MIRGraph.cpp', - 'jit/MoveResolver.cpp', - 'jit/OptimizationTracking.cpp', - 'jit/PerfSpewer.cpp', - 'jit/ProcessExecutableMemory.cpp', - 'jit/RangeAnalysis.cpp', - 'jit/Recover.cpp', - 'jit/RegisterAllocator.cpp', - 'jit/RematerializedFrame.cpp', - 'jit/Safepoints.cpp', - 'jit/ScalarReplacement.cpp', - 'jit/shared/Assembler-shared.cpp', - 'jit/shared/CodeGenerator-shared.cpp', - 'jit/shared/Disassembler-shared.cpp', - 'jit/shared/Lowering-shared.cpp', - 'jit/Sink.cpp', - 'jit/Snapshots.cpp', - 'jit/StupidAllocator.cpp', - 'jit/TypedObjectPrediction.cpp', - 'jit/TypePolicy.cpp', - 'jit/ValueNumbering.cpp', - 'jit/VMFunctions.cpp', - 'jit/WasmBCE.cpp', 'jsapi.cpp', 'jsdate.cpp', 'jsexn.cpp', 'jsfriendapi.cpp', 'jsnum.cpp', 'perf/jsperf.cpp', 'proxy/BaseProxyHandler.cpp', 'proxy/CrossCompartmentWrapper.cpp', @@ -501,149 +418,16 @@ if CONFIG['MOZ_INSTRUMENTS']: if CONFIG['ENABLE_TRACE_LOGGING']: SOURCES += [ 'vm/TraceLogging.cpp', 'vm/TraceLoggingGraph.cpp', 'vm/TraceLoggingTypes.cpp', ] -if not CONFIG['ENABLE_ION']: - LOpcodesGenerated.inputs += ['jit/none/LIR-none.h'] - UNIFIED_SOURCES += [ - 'jit/none/Trampoline-none.cpp' - ] -elif CONFIG['JS_CODEGEN_X86'] or CONFIG['JS_CODEGEN_X64']: - LOpcodesGenerated.inputs += ['jit/x86-shared/LIR-x86-shared.h'] - UNIFIED_SOURCES += [ - 'jit/x86-shared/Architecture-x86-shared.cpp', - 'jit/x86-shared/Assembler-x86-shared.cpp', - 'jit/x86-shared/AssemblerBuffer-x86-shared.cpp', - 'jit/x86-shared/CodeGenerator-x86-shared.cpp', - 'jit/x86-shared/Lowering-x86-shared.cpp', - 'jit/x86-shared/MacroAssembler-x86-shared-SIMD.cpp', - 'jit/x86-shared/MacroAssembler-x86-shared.cpp', - 'jit/x86-shared/MoveEmitter-x86-shared.cpp', - ] - if CONFIG['JS_CODEGEN_X64']: - LOpcodesGenerated.inputs += ['jit/x64/LIR-x64.h'] - UNIFIED_SOURCES += [ - 'jit/x64/Assembler-x64.cpp', - 'jit/x64/Bailouts-x64.cpp', - 'jit/x64/CodeGenerator-x64.cpp', - 'jit/x64/Lowering-x64.cpp', - 'jit/x64/MacroAssembler-x64.cpp', - 'jit/x64/Trampoline-x64.cpp', - ] - else: - LOpcodesGenerated.inputs += ['jit/x86/LIR-x86.h'] - UNIFIED_SOURCES += [ - 'jit/x86/Assembler-x86.cpp', - 'jit/x86/Bailouts-x86.cpp', - 'jit/x86/CodeGenerator-x86.cpp', - 'jit/x86/Lowering-x86.cpp', - 'jit/x86/MacroAssembler-x86.cpp', - 'jit/x86/Trampoline-x86.cpp', - ] -elif CONFIG['JS_CODEGEN_ARM']: - LOpcodesGenerated.inputs += ['jit/arm/LIR-arm.h'] - UNIFIED_SOURCES += [ - 'jit/arm/Architecture-arm.cpp', - 'jit/arm/Assembler-arm.cpp', - 'jit/arm/Bailouts-arm.cpp', - 'jit/arm/CodeGenerator-arm.cpp', - 'jit/arm/disasm/Constants-arm.cpp', - 'jit/arm/disasm/Disasm-arm.cpp', - 'jit/arm/Lowering-arm.cpp', - 'jit/arm/MacroAssembler-arm.cpp', - 'jit/arm/MoveEmitter-arm.cpp', - 'jit/arm/Trampoline-arm.cpp', - ] - if CONFIG['JS_SIMULATOR_ARM']: - UNIFIED_SOURCES += [ - 'jit/arm/Simulator-arm.cpp' - ] - elif CONFIG['OS_ARCH'] == 'Darwin': - SOURCES += [ - 'jit/arm/llvm-compiler-rt/arm/aeabi_idivmod.S', - 'jit/arm/llvm-compiler-rt/arm/aeabi_uidivmod.S', - ] -elif CONFIG['JS_CODEGEN_ARM64']: - LOpcodesGenerated.inputs += ['jit/arm64/LIR-arm64.h'] - UNIFIED_SOURCES += [ - 'jit/arm64/Architecture-arm64.cpp', - 'jit/arm64/Assembler-arm64.cpp', - 'jit/arm64/Bailouts-arm64.cpp', - 'jit/arm64/CodeGenerator-arm64.cpp', - 'jit/arm64/Lowering-arm64.cpp', - 'jit/arm64/MacroAssembler-arm64.cpp', - 'jit/arm64/MoveEmitter-arm64.cpp', - 'jit/arm64/Trampoline-arm64.cpp', - 'jit/arm64/vixl/Assembler-vixl.cpp', - 'jit/arm64/vixl/Cpu-vixl.cpp', - 'jit/arm64/vixl/Decoder-vixl.cpp', - 'jit/arm64/vixl/Disasm-vixl.cpp', - 'jit/arm64/vixl/Instructions-vixl.cpp', - 'jit/arm64/vixl/Instrument-vixl.cpp', - 'jit/arm64/vixl/MacroAssembler-vixl.cpp', - 'jit/arm64/vixl/MozAssembler-vixl.cpp', - 'jit/arm64/vixl/MozInstructions-vixl.cpp', - 'jit/arm64/vixl/Utils-vixl.cpp' - ] - if CONFIG['JS_SIMULATOR_ARM64']: - UNIFIED_SOURCES += [ - 'jit/arm64/vixl/Debugger-vixl.cpp', - 'jit/arm64/vixl/Logic-vixl.cpp', - 'jit/arm64/vixl/MozSimulator-vixl.cpp', - 'jit/arm64/vixl/Simulator-vixl.cpp' - ] -elif CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']: - LOpcodesGenerated.inputs += ['jit/mips-shared/LIR-mips-shared.h'] - UNIFIED_SOURCES += [ - 'jit/mips-shared/Architecture-mips-shared.cpp', - 'jit/mips-shared/Assembler-mips-shared.cpp', - 'jit/mips-shared/Bailouts-mips-shared.cpp', - 'jit/mips-shared/CodeGenerator-mips-shared.cpp', - 'jit/mips-shared/Lowering-mips-shared.cpp', - 'jit/mips-shared/MacroAssembler-mips-shared.cpp', - 'jit/mips-shared/MoveEmitter-mips-shared.cpp', - ] - if CONFIG['JS_CODEGEN_MIPS32']: - LOpcodesGenerated.inputs += ['jit/mips32/LIR-mips32.h'] - UNIFIED_SOURCES += [ - 'jit/mips32/Architecture-mips32.cpp', - 'jit/mips32/Assembler-mips32.cpp', - 'jit/mips32/Bailouts-mips32.cpp', - 'jit/mips32/CodeGenerator-mips32.cpp', - 'jit/mips32/Lowering-mips32.cpp', - 'jit/mips32/MacroAssembler-mips32.cpp', - 'jit/mips32/MoveEmitter-mips32.cpp', - 'jit/mips32/Trampoline-mips32.cpp', - ] - if CONFIG['JS_SIMULATOR_MIPS32']: - UNIFIED_SOURCES += [ - 'jit/mips32/Simulator-mips32.cpp' - ] - elif CONFIG['JS_CODEGEN_MIPS64']: - LOpcodesGenerated.inputs += ['jit/mips64/LIR-mips64.h'] - UNIFIED_SOURCES += [ - 'jit/mips64/Architecture-mips64.cpp', - 'jit/mips64/Assembler-mips64.cpp', - 'jit/mips64/Bailouts-mips64.cpp', - 'jit/mips64/CodeGenerator-mips64.cpp', - 'jit/mips64/Lowering-mips64.cpp', - 'jit/mips64/MacroAssembler-mips64.cpp', - 'jit/mips64/MoveEmitter-mips64.cpp', - 'jit/mips64/Trampoline-mips64.cpp', - ] - if CONFIG['JS_SIMULATOR_MIPS64']: - UNIFIED_SOURCES += [ - 'jit/mips64/Simulator-mips64.cpp' - ] - if CONFIG['OS_ARCH'] == 'WINNT': UNIFIED_SOURCES += [ 'threading/windows/CpuCount.cpp', 'threading/windows/Thread.cpp', ] else: UNIFIED_SOURCES += [ 'threading/posix/CpuCount.cpp', @@ -685,16 +469,17 @@ GENERATED_FILES += ['frontend/ReservedWo ReservedWordsGenerated = GENERATED_FILES['frontend/ReservedWordsGenerated.h'] ReservedWordsGenerated.script = 'frontend/GenerateReservedWords.py' ReservedWordsGenerated.inputs += [ 'frontend/ReservedWords.h' ] DIRS += [ 'build', + 'jit', ] FINAL_LIBRARY = 'js' if CONFIG['ENABLE_WASM_CRANELIFT']: DIRS += ['rust'] UNIFIED_SOURCES += [ 'wasm/WasmCraneliftCompile.cpp',
--- a/js/src/tests/jstests.list +++ b/js/src/tests/jstests.list @@ -5,16 +5,26 @@ skip include test/jstests.list skip script non262/String/normalize-generateddata-input.js # input data for other test # Timeouts on arm and cgc builds. slow script test262/built-ins/decodeURI/S15.1.3.1_A2.5_T1.js slow script test262/built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1.js +# Fields are not fully implemented yet +# https://bugzilla.mozilla.org/show_bug.cgi?id=1499448 +skip script non262/fields/access.js +skip script non262/fields/basic.js +skip script non262/fields/error.js +skip script non262/fields/field_types.js +skip script non262/fields/literal.js +skip script non262/fields/mixed_methods.js +skip script non262/fields/quirks.js + ################################################################# # Tests disabled due to intentional alternative implementations # ################################################################# # Legacy "caller" and "arguments" implemented as accessor properties on Function.prototype. skip script test262/built-ins/Function/prototype/restricted-property-arguments.js skip script test262/built-ins/Function/prototype/restricted-property-caller.js @@ -438,29 +448,16 @@ skip script test262/intl402/RelativeTime skip script test262/intl402/RelativeTimeFormat/prototype/format/en-us-style-short.js skip script test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-long.js skip script test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-narrow.js skip script test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-short.js # https://bugzilla.mozilla.org/show_bug.cgi?id=1473588 skip script test262/intl402/RelativeTimeFormat/prototype/format/unit-plural.js -# https://bugzilla.mozilla.org/show_bug.cgi?id=1499933 -skip script test262/intl402/DateTimeFormat/prototype/resolvedOptions/order.js -skip script test262/intl402/PluralRules/prototype/resolvedOptions/order.js -skip script test262/intl402/NumberFormat/prototype/resolvedOptions/order.js - -# Fields are not fully implemented yet -skip script non262/fields/access.js -skip script non262/fields/basic.js -skip script non262/fields/error.js -skip script non262/fields/field_types.js -skip script non262/fields/literal.js -skip script non262/fields/mixed_methods.js -skip script non262/fields/quirks.js ########################################################### # Tests disabled due to issues in test262 importer script # ########################################################### # test262 importer merges all includes in a per directory shell.js file, breaking this harness test case. skip script test262/harness/detachArrayBuffer.js
--- a/js/src/vm/Time.cpp +++ b/js/src/vm/Time.cpp @@ -38,20 +38,36 @@ extern int gettimeofday(struct timeval* #endif #include <sys/time.h> #endif /* XP_UNIX */ using mozilla::DebugOnly; -#if defined(XP_UNIX) +// Forward declare the function +static int64_t PRMJ_NowImpl(); + int64_t PRMJ_Now() { + if (mozilla::TimeStamp::GetFuzzyfoxEnabled()) { + return mozilla::TimeStamp::NowFuzzyTime(); + } + + int64_t now = PRMJ_NowImpl(); + // We check the FuzzyFox clock in case it was recently disabled, to prevent time + // from going backwards. + return mozilla::TimeStamp::NowFuzzyTime() > now ? mozilla::TimeStamp::NowFuzzyTime() : now; +} + +#if defined(XP_UNIX) +static int64_t +PRMJ_NowImpl() +{ struct timeval tv; #ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris <sys/types.h> */ gettimeofday(&tv); #else gettimeofday(&tv, 0); #endif /* _SVID_GETTOD */ @@ -145,24 +161,27 @@ PRMJ_NowShutdown() DeleteCriticalSection(&calibration.data_lock); } #define MUTEX_LOCK(m) EnterCriticalSection(m) #define MUTEX_UNLOCK(m) LeaveCriticalSection(m) #define MUTEX_SETSPINCOUNT(m, c) SetCriticalSectionSpinCount((m),(c)) // Please see bug 363258 for why the win32 timing code is so complex. -int64_t -PRMJ_Now() +static int64_t +PRMJ_NowImpl() { if (pGetSystemTimePreciseAsFileTime) { // Windows 8 has a new API function that does all the work. FILETIME ft; pGetSystemTimePreciseAsFileTime(&ft); - return int64_t(FileTimeToUnixMicroseconds(ft)); + int64_t now = int64_t(FileTimeToUnixMicroseconds(ft)); + // We check the FuzzyFox clock in case it was recently disabled, to prevent time + // from going backwards. + return mozilla::TimeStamp::NowFuzzyTime() > now ? mozilla::TimeStamp::NowFuzzyTime() : now; } bool calibrated = false; bool needsCalibration = !calibration.calibrated; double cachedOffset = 0.0; while (true) { if (needsCalibration) { MUTEX_LOCK(&calibration.data_lock);
--- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -25,16 +25,17 @@ // to manually include it #include <mmsystem.h> #include "WinUtils.h" #endif #include "mozilla/AnimationEventDispatcher.h" #include "mozilla/ArrayUtils.h" #include "mozilla/AutoRestore.h" +#include "mozilla/DebugOnly.h" #include "mozilla/IntegerRange.h" #include "mozilla/dom/FontTableURIProtocolHandler.h" #include "nsITimer.h" #include "nsLayoutUtils.h" #include "nsPresContext.h" #include "nsComponentManagerUtils.h" #include "mozilla/Logging.h" #include "nsAutoPtr.h" @@ -657,17 +658,20 @@ private: MonitorAutoLock lock(mRefreshTickLock); aVsyncTimestamp = mRecentVsync; mProcessedVsync = true; } else { mLastChildTick = TimeStamp::Now(); mLastProcessedTickInChildProcess = aVsyncTimestamp; } - MOZ_ASSERT(aVsyncTimestamp <= TimeStamp::Now()); + + // Do not compare timestamps unless they are both canonical or fuzzy + DebugOnly<TimeStamp> rightnow = TimeStamp::Now(); + MOZ_ASSERT_IF((*&rightnow).UsedCanonicalNow() == aVsyncTimestamp.UsedCanonicalNow(), aVsyncTimestamp <= *&rightnow); // We might have a problem that we call ~VsyncRefreshDriverTimer() before // the scheduled TickRefreshDriver() runs. Check mVsyncRefreshDriverTimer // before use. if (mVsyncRefreshDriverTimer) { RefPtr<VsyncRefreshDriverTimer> timer = mVsyncRefreshDriverTimer; timer->RunRefreshDrivers(aVsyncTimestamp); // Note: mVsyncRefreshDriverTimer might be null now.
--- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -97,16 +97,17 @@ #include "mozilla/dom/CustomElementRegistry.h" #include "mozilla/EventDispatcher.h" #include "mozilla/IMEStateManager.h" #include "mozilla/dom/HTMLVideoElement.h" #include "TouchManager.h" #include "DecoderDoctorLogger.h" #include "MediaDecoder.h" #include "mozilla/ClearSiteData.h" +#include "mozilla/Fuzzyfox.h" #include "mozilla/ServoBindings.h" #include "mozilla/StaticPresData.h" #include "mozilla/dom/WebIDLGlobalNameHash.h" #include "mozilla/dom/ipc/IPCBlobInputStreamStorage.h" #include "mozilla/dom/U2FTokenManager.h" #include "mozilla/dom/PointerEventHandler.h" #include "mozilla/dom/BlobURLProtocolHandler.h" #include "nsThreadManager.h" @@ -279,16 +280,18 @@ nsLayoutStatics::Initialize() if (XRE_IsParentProcess()) { // On content process we initialize DOMPrefs when PContentChild is fully // initialized. mozilla::dom::DOMPrefs::Initialize(); } nsThreadManager::InitializeShutdownObserver(); + mozilla::Fuzzyfox::Start(); + ClearSiteData::Initialize(); return NS_OK; } void nsLayoutStatics::Shutdown() {
--- a/mozglue/misc/TimeStamp.cpp +++ b/mozglue/misc/TimeStamp.cpp @@ -3,16 +3,17 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Implementation of the OS-independent methods of the TimeStamp class */ +#include "mozilla/Atomics.h" #include "mozilla/TimeStamp.h" #include <stdio.h> #include <string.h> #include <stdlib.h> namespace mozilla { /** @@ -40,16 +41,45 @@ struct TimeStampInitialization }; ~TimeStampInitialization() { TimeStamp::Shutdown(); }; }; +static bool sFuzzyfoxEnabled; + +/* static */ bool +TimeStamp::GetFuzzyfoxEnabled() +{ + return sFuzzyfoxEnabled; +} + +/* static */ void +TimeStamp::SetFuzzyfoxEnabled(bool aValue) +{ + sFuzzyfoxEnabled = aValue; +} + +// These variables store the frozen time (as a TimeStamp) for FuzzyFox that +// will be reported if FuzzyFox is enabled. +// We overload the top bit of sCanonicalNow and sCanonicalGTC to +// indicate if a Timestamp is a fuzzed timestamp (bit set) or not +// (bit unset). +#ifdef XP_WIN +static Atomic<uint64_t> sCanonicalGTC; +static Atomic<uint64_t> sCanonicalQPC; +static Atomic<bool> sCanonicalHasQPC; +#else +static Atomic<uint64_t> sCanonicalNowTimeStamp; +#endif +static Atomic<int64_t> sCanonicalNowTime; +// This variable stores the frozen time (as ms since the epoch) for FuzzyFox +// to report if FuzzyFox is enabled. static TimeStampInitialization sInitOnce; MFBT_API TimeStamp TimeStamp::ProcessCreation(bool* aIsInconsistent) { if (aIsInconsistent) { *aIsInconsistent = false; } @@ -89,9 +119,56 @@ TimeStamp::ProcessCreation(bool* aIsInco } void TimeStamp::RecordProcessRestart() { sInitOnce.mProcessCreation = TimeStamp(); } +MFBT_API TimeStamp +TimeStamp::NowFuzzy(TimeStampValue aValue) +{ +#ifdef XP_WIN + TimeStampValue canonicalNow = TimeStampValue(sCanonicalGTC, sCanonicalQPC, sCanonicalHasQPC, true); +#else + TimeStampValue canonicalNow = TimeStampValue(sCanonicalNowTimeStamp); +#endif + + if (TimeStamp::GetFuzzyfoxEnabled()) { + if(MOZ_LIKELY(!canonicalNow.IsNull())) { + return TimeStamp(canonicalNow); + } + } + // When we disable Fuzzyfox, time may goes backwards, so we need to make sure + // we don't do that. + else if (MOZ_UNLIKELY(canonicalNow > aValue)) { + return TimeStamp(canonicalNow); + } + + return TimeStamp(aValue); +} + +MFBT_API void +TimeStamp::UpdateFuzzyTimeStamp(TimeStamp aValue) +{ +#ifdef XP_WIN + sCanonicalGTC = aValue.mValue.mGTC; + sCanonicalQPC = aValue.mValue.mQPC; + sCanonicalHasQPC = aValue.mValue.mHasQPC; +#else + sCanonicalNowTimeStamp = aValue.mValue.mTimeStamp; +#endif +} + +MFBT_API int64_t +TimeStamp::NowFuzzyTime() +{ + return sCanonicalNowTime; +} + +MFBT_API void +TimeStamp::UpdateFuzzyTime(int64_t aValue) +{ + sCanonicalNowTime = aValue; +} + } // namespace mozilla
--- a/mozglue/misc/TimeStamp.h +++ b/mozglue/misc/TimeStamp.h @@ -24,17 +24,63 @@ template<typename T> struct ParamTraits; // defines TimeStampValue as a complex value keeping both // GetTickCount and QueryPerformanceCounter values #include "TimeStamp_windows.h" #endif namespace mozilla { #ifndef XP_WIN -typedef uint64_t TimeStampValue; +struct TimeStamp63Bit +{ + uint64_t mUsedCanonicalNow : 1; + uint64_t mTimeStamp : 63; + + constexpr TimeStamp63Bit() + : mUsedCanonicalNow(0) + , mTimeStamp(0) { } + + MOZ_IMPLICIT constexpr TimeStamp63Bit(const uint64_t aValue) + : mUsedCanonicalNow(0) + , mTimeStamp(aValue) { } + + constexpr TimeStamp63Bit(const bool aUsedCanonicalNow, const int64_t aTimeStamp) + : mUsedCanonicalNow(aUsedCanonicalNow ? 1 : 0) + , mTimeStamp(aTimeStamp) { } + + bool operator==(const TimeStamp63Bit aOther) const + { + uint64_t here, there; + memcpy(&here, this, sizeof(TimeStamp63Bit)); + memcpy(&there, &aOther, sizeof(TimeStamp63Bit)); + return here == there; + } + + operator uint64_t () const + { + return mTimeStamp; + } + + bool IsNull() const + { + return mTimeStamp == 0; + } + + bool UsedCanonicalNow() const + { + return mUsedCanonicalNow; + } + + void SetCanonicalNow() + { + mUsedCanonicalNow = 1; + } +}; + +typedef TimeStamp63Bit TimeStampValue; #endif class TimeStamp; /** * Platform-specific implementation details of BaseTimeDuration. */ class BaseTimeDurationPlatformUtils @@ -408,17 +454,17 @@ typedef BaseTimeDuration<TimeDurationVal * unless there is a specific reason not to do so. */ class TimeStamp { public: /** * Initialize to the "null" moment */ - constexpr TimeStamp() : mValue(0) {} + constexpr TimeStamp() : mValue() {} // Default copy-constructor and assignment are OK /** * The system timestamps are the same as the TimeStamp * retrieved by mozilla::TimeStamp. Since we need this for * vsync timestamps, we enable the creation of mozilla::TimeStamps * on platforms that support vsync aligned refresh drivers / compositors * Verified true as of Jan 31, 2015: B2G and OS X @@ -429,50 +475,59 @@ public: * compositors. * UNTESTED ON OTHER PLATFORMS */ #if defined(XP_DARWIN) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK) static TimeStamp FromSystemTime(int64_t aSystemTime) { static_assert(sizeof(aSystemTime) == sizeof(TimeStampValue), "System timestamp should be same units as TimeStampValue"); - return TimeStamp(aSystemTime); + return TimeStamp(TimeStampValue(false, aSystemTime)); } #endif /** * Return true if this is the "null" moment */ - bool IsNull() const { return mValue == 0; } + bool IsNull() const { return mValue.IsNull(); } /** * Return true if this is not the "null" moment, may be used in tests, e.g.: * |if (timestamp) { ... }| */ explicit operator bool() const { - return mValue != 0; + return !IsNull(); } + bool UsedCanonicalNow() const + { + return mValue.UsedCanonicalNow(); + } + static MFBT_API bool GetFuzzyfoxEnabled(); + static MFBT_API void SetFuzzyfoxEnabled(bool aValue); + /** * Return a timestamp reflecting the current elapsed system time. This * is monotonically increasing (i.e., does not decrease) over the * lifetime of this process' XPCOM session. * * Now() is trying to ensure the best possible precision on each platform, * at least one millisecond. * * NowLoRes() has been introduced to workaround performance problems of * QueryPerformanceCounter on the Windows platform. NowLoRes() is giving * lower precision, usually 15.6 ms, but with very good performance benefit. * Use it for measurements of longer times, like >200ms timeouts. */ static TimeStamp Now() { return Now(true); } static TimeStamp NowLoRes() { return Now(false); } + static TimeStamp NowUnfuzzed() { return NowUnfuzzed(true); } + static MFBT_API int64_t NowFuzzyTime(); /** * Return a timestamp representing the time when the current process was * created which will be comparable with other timestamps taken with this * class. If the actual process creation time is detected to be inconsistent * the @a aIsInconsistent parameter will be set to true, the returned * timestamp however will still be valid though inaccurate. * * @param aIsInconsistent If non-null, set to true if an inconsistency was @@ -526,30 +581,36 @@ public: TimeStamp& operator+=(const TimeDuration& aOther) { MOZ_ASSERT(!IsNull(), "Cannot compute with a null value"); TimeStampValue value = mValue + aOther.mValue; // Check for underflow. // (We don't check for overflow because it's not obvious what the error // behavior should be in that case.) if (aOther.mValue < 0 && value > mValue) { - value = 0; + value = TimeStampValue(); + } + if (mValue.UsedCanonicalNow()) { + value.SetCanonicalNow(); } mValue = value; return *this; } TimeStamp& operator-=(const TimeDuration& aOther) { MOZ_ASSERT(!IsNull(), "Cannot compute with a null value"); TimeStampValue value = mValue - aOther.mValue; // Check for underflow. // (We don't check for overflow because it's not obvious what the error // behavior should be in that case.) if (aOther.mValue > 0 && value > mValue) { - value = 0; + value = TimeStampValue(); + } + if (mValue.UsedCanonicalNow()) { + value.SetCanonicalNow(); } mValue = value; return *this; } bool operator<(const TimeStamp& aOther) const { MOZ_ASSERT(!IsNull(), "Cannot compute with a null value"); @@ -593,16 +654,21 @@ public: static MFBT_API void Shutdown(); private: friend struct IPC::ParamTraits<mozilla::TimeStamp>; MOZ_IMPLICIT TimeStamp(TimeStampValue aValue) : mValue(aValue) {} static MFBT_API TimeStamp Now(bool aHighResolution); + static MFBT_API TimeStamp NowUnfuzzed(bool aHighResolution); + static MFBT_API TimeStamp NowFuzzy(TimeStampValue aValue); + + static MFBT_API void UpdateFuzzyTime(int64_t aValue); + static MFBT_API void UpdateFuzzyTimeStamp(TimeStamp aValue); /** * Computes the uptime of the current process in microseconds. The result * is platform-dependent and needs to be checked against existing timestamps * for consistency. * * @returns The number of microseconds since the calling process was started * or 0 if an error was encountered while computing the uptime @@ -618,13 +684,15 @@ private: * * PR_INTERVAL_MAX is set at 100,000 ticks per second. So the minimum * time to wrap around is about 2^64/100000 seconds, i.e. about * 5,849,424 years. * * When using a system clock, a value is system dependent. */ TimeStampValue mValue; + + friend class Fuzzyfox; }; } // namespace mozilla #endif /* mozilla_TimeStamp_h */
--- a/mozglue/misc/TimeStamp_darwin.cpp +++ b/mozglue/misc/TimeStamp_darwin.cpp @@ -154,22 +154,27 @@ TimeStamp::Startup() void TimeStamp::Shutdown() { } TimeStamp TimeStamp::Now(bool aHighResolution) { - return TimeStamp(ClockTime()); + return TimeStamp::NowFuzzy(TimeStampValue(false, ClockTime())); +} + +TimeStamp +TimeStamp::NowUnfuzzed(bool aHighResolution) +{ + return TimeStamp(TimeStampValue(false, ClockTime())); } // Computes and returns the process uptime in microseconds. // Returns 0 if an error was encountered. - uint64_t TimeStamp::ComputeProcessUptime() { struct timeval tv; int rv = gettimeofday(&tv, nullptr); if (rv == -1) { return 0;
--- a/mozglue/misc/TimeStamp_posix.cpp +++ b/mozglue/misc/TimeStamp_posix.cpp @@ -197,17 +197,23 @@ TimeStamp::Startup() void TimeStamp::Shutdown() { } TimeStamp TimeStamp::Now(bool aHighResolution) { - return TimeStamp(ClockTimeNs()); + return TimeStamp::NowFuzzy(TimeStampValue(false, ClockTimeNs())); +} + +TimeStamp +TimeStamp::NowUnfuzzed(bool aHighResolution) +{ + return TimeStamp(TimeStampValue(false, ClockTimeNs())); } #if defined(XP_LINUX) || defined(ANDROID) // Calculates the amount of jiffies that have elapsed since boot and up to the // starttime value of a specific process as found in its /proc/*/stat file. // Returns 0 if an error occurred.
--- a/mozglue/misc/TimeStamp_windows.cpp +++ b/mozglue/misc/TimeStamp_windows.cpp @@ -58,36 +58,30 @@ static const uint32_t kFailureThreshold // If we are not able to get the value of GTC time increment, use this value // which is the most usual increment. static const DWORD kDefaultTimeIncrement = 156001; // ---------------------------------------------------------------------------- // Global variables, not changing at runtime // ---------------------------------------------------------------------------- -/** - * The [mt] unit: - * - * Many values are kept in ticks of the Performance Coutner x 1000, - * further just referred as [mt], meaning milli-ticks. - * - * This is needed to preserve maximum precision of the performance frequency - * representation. GetTickCount64 values in milliseconds are multiplied with - * frequency per second. Therefor we need to multiply QPC value by 1000 to - * have the same units to allow simple arithmentic with both QPC and GTC. - */ - -#define ms2mt(x) ((x) * sFrequencyPerSec) -#define mt2ms(x) ((x) / sFrequencyPerSec) -#define mt2ms_f(x) (double(x) / sFrequencyPerSec) - // Result of QueryPerformanceFrequency // We use default of 1 for the case we can't use QueryPerformanceCounter // to make mt/ms conversions work despite that. -static LONGLONG sFrequencyPerSec = 1; +static uint64_t sFrequencyPerSec = 1; + +namespace mozilla { + +MFBT_API uint64_t +GetQueryPerformanceFrequencyPerSec() +{ + return sFrequencyPerSec; +} + +} // How much we are tolerant to GTC occasional loose of resoltion. // This number says how many multiples of the minimal GTC resolution // detected on the system are acceptable. This number is empirical. static const LONGLONG kGTCTickLeapTolerance = 4; // Base tolerance (more: "inability of detection" range) threshold is calculated // dynamically, and kept in sGTCResolutionThreshold. @@ -270,22 +264,23 @@ InitResolution() sResolutionSigDigs = sigDigs; } // ---------------------------------------------------------------------------- // TimeStampValue implementation // ---------------------------------------------------------------------------- MFBT_API -TimeStampValue::TimeStampValue(ULONGLONG aGTC, ULONGLONG aQPC, bool aHasQPC) +TimeStampValue::TimeStampValue(ULONGLONG aGTC, ULONGLONG aQPC, bool aHasQPC, bool aUsedCanonicalNow) : mGTC(aGTC) , mQPC(aQPC) + , mUsedCanonicalNow(aUsedCanonicalNow) , mHasQPC(aHasQPC) - , mIsNull(false) { + mIsNull = aGTC == 0 && aQPC == 0; } MFBT_API TimeStampValue& TimeStampValue::operator+=(const int64_t aOther) { mGTC += aOther; mQPC += aOther; return *this; @@ -373,17 +368,17 @@ TimeStampValue::CheckQPC(const TimeStamp } return deltaGTC; } MFBT_API uint64_t TimeStampValue::operator-(const TimeStampValue& aOther) const { - if (mIsNull && aOther.mIsNull) { + if (IsNull() && aOther.IsNull()) { return uint64_t(0); } return CheckQPC(aOther); } // ---------------------------------------------------------------------------- // TimeDuration and TimeStamp implementation @@ -524,26 +519,39 @@ TimeStamp::Startup() } MFBT_API void TimeStamp::Shutdown() { DeleteCriticalSection(&sTimeStampLock); } -MFBT_API TimeStamp -TimeStamp::Now(bool aHighResolution) + +TimeStampValue +NowInternal(bool aHighResolution) { // sUseQPC is volatile bool useQPC = (aHighResolution && sUseQPC); // Both values are in [mt] units. ULONGLONG QPC = useQPC ? PerformanceCounter() : uint64_t(0); ULONGLONG GTC = ms2mt(GetTickCount64()); - return TimeStamp(TimeStampValue(GTC, QPC, useQPC)); + return TimeStampValue(GTC, QPC, useQPC, false); +} + +MFBT_API TimeStamp +TimeStamp::Now(bool aHighResolution) +{ + return TimeStamp::NowFuzzy(NowInternal(aHighResolution)); +} + +MFBT_API TimeStamp +TimeStamp::NowUnfuzzed(bool aHighResolution) +{ + return TimeStamp(NowInternal(aHighResolution)); } // Computes and returns the process uptime in microseconds. // Returns 0 if an error was encountered. MFBT_API uint64_t TimeStamp::ComputeProcessUptime() {
--- a/mozglue/misc/TimeStamp_windows.h +++ b/mozglue/misc/TimeStamp_windows.h @@ -6,52 +6,80 @@ #ifndef mozilla_TimeStamp_windows_h #define mozilla_TimeStamp_windows_h #include "mozilla/Types.h" namespace mozilla { +/** + * The [mt] unit: + * + * Many values are kept in ticks of the Performance Counter x 1000, + * further just referred as [mt], meaning milli-ticks. + * + * This is needed to preserve maximum precision of the performance frequency + * representation. GetTickCount64 values in milliseconds are multiplied with + * frequency per second. Therefore we need to multiply QPC value by 1000 to + * have the same units to allow simple arithmentic with both QPC and GTC. + */ +#define ms2mt(x) ((x) * mozilla::GetQueryPerformanceFrequencyPerSec()) +#define mt2ms(x) ((x) / mozilla::GetQueryPerformanceFrequencyPerSec()) +#define mt2ms_f(x) (double(x) / mozilla::GetQueryPerformanceFrequencyPerSec()) + +MFBT_API uint64_t +GetQueryPerformanceFrequencyPerSec(); + class TimeStamp; +class TimeStampValue; + +TimeStampValue +NowInternal(bool aHighResolution); + class TimeStampValue { + friend TimeStampValue NowInternal(bool); + friend bool IsCanonicalTimeStamp(TimeStampValue); friend struct IPC::ParamTraits<mozilla::TimeStampValue>; friend class TimeStamp; + friend class Fuzzyfox; // Both QPC and GTC are kept in [mt] units. uint64_t mGTC; uint64_t mQPC; - bool mHasQPC; + + bool mUsedCanonicalNow; bool mIsNull; + bool mHasQPC; - MFBT_API TimeStampValue(uint64_t aGTC, uint64_t aQPC, bool aHasQPC); + MFBT_API TimeStampValue(uint64_t aGTC, uint64_t aQPC, bool aHasQPC, bool aUsedCanonicalNow); MFBT_API uint64_t CheckQPC(const TimeStampValue& aOther) const; - struct _SomethingVeryRandomHere; - constexpr MOZ_IMPLICIT TimeStampValue(_SomethingVeryRandomHere* aNullValue) + constexpr MOZ_IMPLICIT TimeStampValue() : mGTC(0) , mQPC(0) + , mUsedCanonicalNow(false) + , mIsNull(true) , mHasQPC(false) - , mIsNull(true) { } public: MFBT_API uint64_t operator-(const TimeStampValue& aOther) const; TimeStampValue operator+(const int64_t aOther) const { - return TimeStampValue(mGTC + aOther, mQPC + aOther, mHasQPC); + return TimeStampValue(mGTC + aOther, mQPC + aOther, mHasQPC, mUsedCanonicalNow); } TimeStampValue operator-(const int64_t aOther) const { - return TimeStampValue(mGTC - aOther, mQPC - aOther, mHasQPC); + return TimeStampValue(mGTC - aOther, mQPC - aOther, mHasQPC, mUsedCanonicalNow); } MFBT_API TimeStampValue& operator+=(const int64_t aOther); MFBT_API TimeStampValue& operator-=(const int64_t aOther); bool operator<(const TimeStampValue& aOther) const { return int64_t(*this - aOther) < 0; } @@ -70,13 +98,25 @@ public: bool operator==(const TimeStampValue& aOther) const { return int64_t(*this - aOther) == 0; } bool operator!=(const TimeStampValue& aOther) const { return int64_t(*this - aOther) != 0; } + bool UsedCanonicalNow() const + { + return mUsedCanonicalNow; + } + void SetCanonicalNow() + { + mUsedCanonicalNow = true; + } + bool IsNull() const + { + return mIsNull; + } }; } #endif /* mozilla_TimeStamp_h */
new file mode 100644 --- /dev/null +++ b/netwerk/protocol/http/DelayHttpChannelQueue.cpp @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set et cin ts=4 sw=4 sts=4: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DelayHttpChannelQueue.h" +#include "mozilla/Services.h" +#include "mozilla/StaticPtr.h" + +using namespace mozilla; +using namespace mozilla::net; + +namespace { +StaticRefPtr<DelayHttpChannelQueue> sDelayHttpChannelQueue; +} + +bool +DelayHttpChannelQueue::AttemptQueueChannel(nsHttpChannel* aChannel) +{ + MOZ_ASSERT(aChannel); + MOZ_ASSERT(NS_IsMainThread()); + + if (!TimeStamp::GetFuzzyfoxEnabled()) { + return false; + } + + if (!sDelayHttpChannelQueue) { + RefPtr<DelayHttpChannelQueue> queue = new DelayHttpChannelQueue(); + if (!queue->Initialize()) { + return false; + } + + sDelayHttpChannelQueue = queue; + } + + if (NS_WARN_IF(!sDelayHttpChannelQueue->mQueue.AppendElement(aChannel, fallible))) { + return false; + } + + return true; +} + +DelayHttpChannelQueue::DelayHttpChannelQueue() +{ + MOZ_ASSERT(NS_IsMainThread()); +} + +DelayHttpChannelQueue::~DelayHttpChannelQueue() +{ + MOZ_ASSERT(NS_IsMainThread()); +} + +bool +DelayHttpChannelQueue::Initialize() +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + if (NS_WARN_IF(!obs)) { + return false; + } + + nsresult rv = obs->AddObserver(this, "fuzzyfox-fire-outbound", false); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + + rv = obs->AddObserver(this, "xpcom-shutdown", false); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + + return true; +} + +NS_IMETHODIMP +DelayHttpChannelQueue::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (!strcmp(aTopic, "fuzzyfox-fire-outbound")) { + FireQueue(); + return NS_OK; + } + + MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown")); + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + if (NS_WARN_IF(!obs)) { + return NS_OK; + } + + obs->RemoveObserver(this, "fuzzyfox-fire-outbound"); + obs->RemoveObserver(this, "xpcom-shutdown"); + + return NS_OK; +} + +void +DelayHttpChannelQueue::FireQueue() +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (mQueue.IsEmpty()) { + return; + } + + //TODO: get this from the DOM clock? + TimeStamp ts = TimeStamp::Now(); + + FallibleTArray<RefPtr<nsHttpChannel>> queue; + queue.SwapElements(mQueue); + + for (RefPtr<nsHttpChannel>& channel : queue) { + channel->AsyncOpenFinal(ts); + } +} + +NS_INTERFACE_MAP_BEGIN(DelayHttpChannelQueue) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver) + NS_INTERFACE_MAP_ENTRY(nsIObserver) +NS_INTERFACE_MAP_END + +NS_IMPL_ADDREF(DelayHttpChannelQueue) +NS_IMPL_RELEASE(DelayHttpChannelQueue)
new file mode 100644 --- /dev/null +++ b/netwerk/protocol/http/DelayHttpChannelQueue.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set et cin ts=4 sw=4 sts=4: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_net_DelayHttpChannelQueue_h +#define mozilla_net_DelayHttpChannelQueue_h + +#include "nsIObserver.h" +#include "nsTArray.h" + +namespace mozilla { +namespace net { + +class nsHttpChannel; + +/** + * DelayHttpChannelQueue stores a set of nsHttpChannels that + * are ready to fire out onto the network. However, with FuzzyFox, + * we can only fire those events at a specific interval, so we + * delay them here, in an instance of this class, until we observe + * the topic notificaion that we can send them outbound. + */ +class DelayHttpChannelQueue final : public nsIObserver +{ +public: + static bool + AttemptQueueChannel(nsHttpChannel* aChannel); + + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + +private: + DelayHttpChannelQueue(); + ~DelayHttpChannelQueue(); + + bool + Initialize(); + + void + FireQueue(); + + FallibleTArray<RefPtr<nsHttpChannel>> mQueue; +}; + +} // net namespace +} // mozilla namespace + +#endif // mozilla_net_DelayHttpChannelQueue_h
--- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -25,16 +25,17 @@ #include "AltDataOutputStreamChild.h" #include "CookieServiceChild.h" #include "HttpBackgroundChannelChild.h" #include "nsCOMPtr.h" #include "nsISupportsPrimitives.h" #include "nsChannelClassifier.h" #include "nsContentPolicyUtils.h" +#include "nsDOMNavigationTiming.h" #include "nsGlobalWindow.h" #include "nsStringStream.h" #include "nsHttpChannel.h" #include "nsHttpHandler.h" #include "nsNetUtil.h" #include "nsSerializationHelper.h" #include "mozilla/Attributes.h" #include "mozilla/dom/PerformanceStorage.h"
--- a/netwerk/protocol/http/moz.build +++ b/netwerk/protocol/http/moz.build @@ -64,16 +64,17 @@ SOURCES += [ UNIFIED_SOURCES += [ 'AltDataOutputStreamChild.cpp', 'AltDataOutputStreamParent.cpp', 'AlternateServices.cpp', 'ASpdySession.cpp', 'BackgroundChannelRegistrar.cpp', 'CacheControlParser.cpp', 'ConnectionDiagnostics.cpp', + 'DelayHttpChannelQueue.cpp', 'Http2Compression.cpp', 'Http2Push.cpp', 'Http2Session.cpp', 'Http2Stream.cpp', 'HttpAuthUtils.cpp', 'HttpBackgroundChannelChild.cpp', 'HttpBackgroundChannelParent.cpp', 'HttpBaseChannel.cpp',
--- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -6416,25 +6416,40 @@ nsHttpChannel::AsyncOpen(nsIStreamListen } mIsPending = true; mWasOpened = true; mListener = listener; mListenerContext = context; + // PauseTask/DelayHttpChannel queuing + if (!DelayHttpChannelQueue::AttemptQueueChannel(this)) { + // If fuzzyfox is disabled; or adding to the queue failed, the channel must continue. + AsyncOpenFinal(TimeStamp::Now()); + } + + return NS_OK; +} + +nsresult +nsHttpChannel::AsyncOpenFinal(TimeStamp aTimeStamp) +{ + // Added due to PauseTask/DelayHttpChannel + nsresult rv; + if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr); // record asyncopen time unconditionally and clear it if we // don't want it after OnModifyRequest() weighs in. But waiting for // that to complete would mean we don't include proxy resolution in the // timing. if (!mAsyncOpenTimeOverriden) { - mAsyncOpenTime = TimeStamp::Now(); + mAsyncOpenTime = aTimeStamp; } // Remember we have Authorization header set here. We need to check on it // just once and early, AsyncOpen is the best place. mCustomAuthHeader = mRequestHead.HasHeader(nsHttp::Authorization); // The common case for HTTP channels is to begin proxy resolution and return // at this point. The only time we know mProxyInfo already is if we're
--- a/netwerk/protocol/http/nsHttpChannel.h +++ b/netwerk/protocol/http/nsHttpChannel.h @@ -2,16 +2,17 @@ /* vim:set et cin ts=4 sw=4 sts=4: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsHttpChannel_h__ #define nsHttpChannel_h__ +#include "DelayHttpChannelQueue.h" #include "HttpBaseChannel.h" #include "nsTArray.h" #include "nsICachingChannel.h" #include "nsICacheEntry.h" #include "nsICacheEntryOpenCallback.h" #include "nsIDNSListener.h" #include "nsIApplicationCacheChannel.h" #include "nsIChannelWithDivertableParentListener.h" @@ -200,16 +201,18 @@ public: HttpChannelSecurityWarningReporter* GetWarningReporter(); public: /* internal necko use only */ uint32_t GetRequestTime() const { return mRequestTime; } + nsresult AsyncOpenFinal(TimeStamp aTimeStamp); + MOZ_MUST_USE nsresult OpenCacheEntry(bool usingSSL); MOZ_MUST_USE nsresult OpenCacheEntryInternal(bool isHttps, nsIApplicationCache *applicationCache, bool noAppCache); MOZ_MUST_USE nsresult ContinueConnect(); MOZ_MUST_USE nsresult StartRedirectChannelToURI(nsIURI *, uint32_t);
--- a/taskcluster/ci/build/linux.yml +++ b/taskcluster/ci/build/linux.yml @@ -977,16 +977,19 @@ linux64-ccov/debug: need-xvfb: true toolchains: - linux64-clang-7 - linux64-rust-nightly - linux64-gcc - linux64-cbindgen - linux64-sccache - linux64-node + fetches: + toolchain: + - linux64-grcov linux64-ccov/opt: description: "Linux64-CCov Opt" index: product: firefox job-name: linux64-ccov-opt treeherder: platform: linux64-ccov/opt
--- a/taskcluster/ci/build/windows.yml +++ b/taskcluster/ci/build/windows.yml @@ -587,16 +587,19 @@ win64-ccov/debug: run-on-projects: ['mozilla-central', 'try'] toolchains: - win64-clang-cl - win64-rust-nightly - win64-rust-size - win64-cbindgen - win64-sccache - win64-node + fetches: + toolchain: + - win64-grcov win64-asan/debug: description: "Win64 Debug ASAN" index: product: firefox job-name: win64-asan-debug treeherder: platform: windows2012-64/asan
--- a/testing/marionette/harness/requirements.txt +++ b/testing/marionette/harness/requirements.txt @@ -1,13 +1,13 @@ browsermob-proxy >= 0.6.0 manifestparser >= 1.1 marionette-driver >= 2.7.0 mozcrash >= 0.5 -mozdevice >= 1.0.0 +mozdevice >= 1.1.5 mozinfo >= 0.8 mozlog >= 3.0 moznetwork >= 0.21 mozprocess >= 0.9 mozprofile >= 0.7 mozrunner >= 7.0.1 moztest >= 0.8 mozversion >= 1.1
--- a/testing/mozbase/mozdevice/mozdevice/adb.py +++ b/testing/mozbase/mozdevice/mozdevice/adb.py @@ -640,26 +640,26 @@ class ADBDevice(ADBCommand): except ADBError: self._logger.debug("Check for su 0 failed") self._mkdir_p = None # Force the use of /system/bin/ls or /system/xbin/ls in case # there is /sbin/ls which embeds ansi escape codes to colorize # the output. Detect if we are using busybox ls. We want each # entry on a single line and we don't want . or .. - system_dir = "/system" + ls_dir = "/sdcard" - if self.shell_bool("/system/bin/ls {}".format(system_dir), timeout=timeout): + if self.shell_bool("/system/bin/ls {}".format(ls_dir), timeout=timeout): self._ls = "/system/bin/ls" - elif self.shell_bool("/system/xbin/ls {}".format(system_dir), timeout=timeout): + elif self.shell_bool("/system/xbin/ls {}".format(ls_dir), timeout=timeout): self._ls = "/system/xbin/ls" else: raise ADBError("ADBDevice.__init__: ls could not be found") try: - self.shell_output("%s -1A {}".format(system_dir) % self._ls, timeout=timeout) + self.shell_output("%s -1A {}".format(ls_dir) % self._ls, timeout=timeout) self._ls += " -1A" except ADBError: self._ls += " -a" self._logger.info("%s supported" % self._ls) # Do we have cp? self._have_cp = self.shell_bool("type cp", timeout=timeout)
--- a/testing/mozbase/mozdevice/setup.py +++ b/testing/mozbase/mozdevice/setup.py @@ -3,17 +3,17 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. from __future__ import absolute_import from setuptools import setup PACKAGE_NAME = 'mozdevice' -PACKAGE_VERSION = '1.1.3' +PACKAGE_VERSION = '1.1.5' deps = ['mozfile >= 1.0', 'mozlog >= 3.0', 'moznetwork >= 0.24', 'mozprocess >= 0.19', ] setup(name=PACKAGE_NAME,
--- a/testing/mozbase/mozrunner/setup.py +++ b/testing/mozbase/mozrunner/setup.py @@ -7,17 +7,17 @@ from __future__ import absolute_import from setuptools import setup, find_packages PACKAGE_NAME = 'mozrunner' PACKAGE_VERSION = '7.2.0' desc = """Reliable start/stop/configuration of Mozilla Applications (Firefox, Thunderbird, etc.)""" deps = [ - 'mozdevice>=1.*', + 'mozdevice>=1.1.5', 'mozfile>=1.2', 'mozinfo>=0.7,<2', 'mozlog==3.*', 'mozprocess>=0.23,<1', 'mozprofile~=2.1', 'six>=1.10.0,<2', ]
--- a/testing/raptor/requirements.txt +++ b/testing/raptor/requirements.txt @@ -1,5 +1,5 @@ mozrunner ~= 7.0 mozprofile ~= 2.1 manifestparser >= 1.1 wptserve ~= 1.4.0 -mozdevice >= 1.1.1 \ No newline at end of file +mozdevice >= 1.1.5
--- a/testing/web-platform/meta/svg/idlharness.window.js.ini +++ b/testing/web-platform/meta/svg/idlharness.window.js.ini @@ -462,19 +462,16 @@ expected: FAIL [SVGElement interface: objects.script must inherit property "correspondingElement" with the proper type] expected: FAIL [SVGElement interface: objects.script must inherit property "correspondingUseElement" with the proper type] expected: FAIL - [SVGAElement interface: attribute relList] - expected: FAIL - [SVGElement interface: objects.a must inherit property "correspondingElement" with the proper type] expected: FAIL [SVGElement interface: objects.a must inherit property "correspondingUseElement" with the proper type] expected: FAIL [SVGElement interface: objects.view must inherit property "correspondingElement" with the proper type] expected: FAIL
--- a/testing/web-platform/tests/interfaces/SVG.idl +++ b/testing/web-platform/tests/interfaces/SVG.idl @@ -671,17 +671,17 @@ interface SVGScriptElement : SVGElement SVGScriptElement includes SVGURIReference; [Exposed=Window] interface SVGAElement : SVGGraphicsElement { [SameObject] readonly attribute SVGAnimatedString target; attribute DOMString download; attribute USVString ping; attribute DOMString rel; - [SameObject, PutsForward=value] readonly attribute DOMTokenList relList; + [SameObject, PutForwards=value] readonly attribute DOMTokenList relList; attribute DOMString hreflang; attribute DOMString type; attribute DOMString text; attribute DOMString referrerPolicy; };
new file mode 100644 --- /dev/null +++ b/toolkit/components/fuzzyfox/Fuzzyfox.cpp @@ -0,0 +1,383 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "Fuzzyfox.h" +#include "mozilla/Logging.h" +#include "mozilla/Preferences.h" +#include "mozilla/Services.h" +#include "mozilla/SystemGroup.h" +#include "mozilla/TimeStamp.h" +#include "nsComponentManagerUtils.h" +#include "nsIPrefBranch.h" +#include "nsIPrefService.h" +#include "nsServiceManagerUtils.h" +#include "prrng.h" +#include "prtime.h" + +// For usleep/Sleep & QueryPerformanceFrequency +#ifdef XP_WIN +#include <windows.h> +#else +#include <unistd.h> +#endif + +using namespace mozilla; + +static LazyLogModule sFuzzyfoxLog("Fuzzyfox"); + +#define US_TO_NS(x) ((x)*1000) +#define NS_TO_US(x) ((x)/1000) + +#ifdef LOG +#undef LOG +#endif + +#define LOG(level, args) MOZ_LOG(sFuzzyfoxLog, mozilla::LogLevel::level, args) + +#define FUZZYFOX_ENABLED_PREF "privacy.fuzzyfox.enabled" +#define FUZZYFOX_ENABLED_PREF_DEFAULT false +#define FUZZYFOX_CLOCKGRAIN_PREF "privacy.fuzzyfox.clockgrainus" +#define FUZZYFOX_CLOCKGRAIN_PREF_DEFAULT 100 + +Atomic<uint32_t, Relaxed> Fuzzyfox::sFuzzyfoxClockGrain; + +NS_IMPL_ISUPPORTS_INHERITED(Fuzzyfox, Runnable, nsIObserver) + +/* static */ void +Fuzzyfox::Start() +{ + MOZ_ASSERT(NS_IsMainThread()); + + RefPtr<Fuzzyfox> r = new Fuzzyfox(); + SystemGroup::Dispatch(TaskCategory::Other, r.forget()); +} + +Fuzzyfox::Fuzzyfox() + : Runnable("Fuzzyfox") + , mSanityCheck(false) + , mStartTime(0) + , mDuration(PickDuration()) + , mTickType(eUptick) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // [[ I originally ran this after observing profile-after-change, but + // it turned out that this contructor was getting called _after_ that + // event had already fired. ]] + Preferences::AddAtomicUintVarCache(&sFuzzyfoxClockGrain, + FUZZYFOX_CLOCKGRAIN_PREF, + FUZZYFOX_CLOCKGRAIN_PREF_DEFAULT); + + bool fuzzyfoxEnabled = + Preferences::GetBool(FUZZYFOX_ENABLED_PREF, FUZZYFOX_ENABLED_PREF_DEFAULT); + + LOG(Info, ("PT(%p) Created Fuzzyfox, FuzzyFox is now %s \n", + this, (fuzzyfoxEnabled ? "enabled" : "disabled"))); + + TimeStamp::SetFuzzyfoxEnabled(fuzzyfoxEnabled); + + // Should I see if these fail? And do what? + nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); + prefs->AddObserver(FUZZYFOX_ENABLED_PREF, this, false); + prefs->AddObserver(FUZZYFOX_CLOCKGRAIN_PREF, this, false); +} + +Fuzzyfox::~Fuzzyfox() = default; + +/* + * Fuzzyfox::Run is the core of FuzzyFox. Every so often we pop into this method, and pick + * a new point in the future to hold time constant until. If we have not reached the _previous_ + * point in time we had picked, we sleep until we do so. + * Then we round the current time downwards to a configurable grain value, fix it in place so + * time does not advance, and let execution continue. + */ +NS_IMETHODIMP +Fuzzyfox::Observe(nsISupports* aObject, const char* aTopic, + const char16_t* aMessage) +{ + if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) { + NS_ConvertUTF16toUTF8 pref(aMessage); + + if (pref.EqualsLiteral(FUZZYFOX_ENABLED_PREF)) { + bool fuzzyfoxEnabled = + Preferences::GetBool(FUZZYFOX_ENABLED_PREF, FUZZYFOX_ENABLED_PREF_DEFAULT); + + LOG(Info, ("PT(%p) Observed a pref change, FuzzyFox is now %s \n", + this, (fuzzyfoxEnabled ? "enabled" : "disabled"))); + + + TimeStamp::SetFuzzyfoxEnabled(fuzzyfoxEnabled); + + + if (TimeStamp::GetFuzzyfoxEnabled()) { + // Queue a runnable + nsCOMPtr<nsIRunnable> r = this; + SystemGroup::Dispatch(TaskCategory::Other, r.forget()); + } else { + mStartTime = 0; + mTickType = eUptick; + mSanityCheck = false; + } + } + } + return NS_OK; +} + +#define DISPATCH_AND_RETURN() \ + nsCOMPtr<nsIRunnable> r = this; \ + SystemGroup::Dispatch(TaskCategory::Other, r.forget()); \ + return NS_OK + +NS_IMETHODIMP +Fuzzyfox::Run() +{ + MOZ_ASSERT(NS_IsMainThread()); + if (!TimeStamp::GetFuzzyfoxEnabled()) { + LOG(Info, ("[FuzzyfoxEvent] PT(%p) Fuzzyfox is shut down, doing nothing \n", this)); + return NS_OK; + } + + if (mStartTime == 0) { + // This is the first time we are running afer enabling FuzzyFox. We need + // to prevent time from going backwards, so for the first run we round the time up + // to the next grain. + mStartTime = CeilToGrain(ActualTime()); + MOZ_ASSERT(mStartTime != 0); + TimeStamp newTimeStamp = CeilToGrain(TimeStamp::NowUnfuzzed()); + Fuzzyfox::UpdateClocks(mStartTime, newTimeStamp); + + mSanityCheck = true; + LOG(Info, ("[FuzzyfoxEvent] PT(%p) Going to start Fuzzyfox, queuing up the job \n", + this)); + + DISPATCH_AND_RETURN(); + } + + // We need to check how long its been since we ran + uint64_t endTime = ActualTime(); + + uint64_t remaining = 0; + + // Pick the amount to sleep + if (endTime < mStartTime) { + // This can only happen if we just enabled FuzzyFox, rounded up, and then re-ran the + // runnable before we advanced to the next grain. + // If that happens, then repeat the current time. + // We use mSanityCheck just to be sure (and will eventually remove it.) + MOZ_ASSERT(mSanityCheck); + LOG(Debug, ("[FuzzyfoxEvent] PT(%p) endTime < mStartTime mStartTime %" PRIu64 " endTime %" PRIu64 " \n", + this, mStartTime, endTime)); + + mSanityCheck = true; + DISPATCH_AND_RETURN(); + } + + uint64_t actualRunDuration = endTime - mStartTime; + if (actualRunDuration > mDuration) { + // We ran over our budget! + uint64_t over = actualRunDuration - mDuration; + LOG(Verbose, ("[FuzzyfoxEvent] PT(%p) Overran budget of %" PRIu32 " by %" PRIu64 " \n", + this, mDuration, over)); + + uint64_t nextDuration = PickDuration(); + while (over > nextDuration) { + over -= nextDuration; + nextDuration = PickDuration(); + mTickType = mTickType == eUptick ? eDowntick : eUptick; + } + + remaining = nextDuration - over; + } else { + // Didn't go over budget + remaining = mDuration - actualRunDuration; + LOG(Verbose, ("[FuzzyfoxEvent] PT(%p) Finishing budget of %" PRIu32 " with %" PRIu64 " \n", + this, mDuration, remaining)); + } + mSanityCheck = false; + + // Sleep for now +#ifdef XP_WIN + Sleep(remaining); +#else + usleep(remaining); +#endif + + /* + * Update clocks (and fire pending events etc) + * + * Note: Anytime we round the current time to the grain, and then round the 'real' + * time to the grain, we are introducing the risk that we split the grain. That is, + * the time advances enough after the first rounding that the second rounding causes + * us to move to a different grain. + * + * In theory, such an occurance breaks the security of FuzzyFox, and if an + * attacker can influence the event to occur reliably, and then measure against it + * they can attack FuzzyFox. But such an attack is so difficult that it will + * never be acheived until you read this comment in a future Academic Publication + * that demonstrates it. And at that point the paper would surely never be accepted + * into any _respectable_ journal unless the authors had also presented a solution + * for the issue that was usable and incorporated into Firefox! + */ + uint64_t newTime = FloorToGrain(ActualTime()); + TimeStamp newTimeStamp = FloorToGrain(TimeStamp::NowUnfuzzed()); + UpdateClocks(newTime, newTimeStamp); + + // Reset values + mTickType = mTickType == eUptick ? eDowntick : eUptick; + mStartTime = ActualTime(); + mDuration = PickDuration(); + + DISPATCH_AND_RETURN(); +} + +/* + * ActualTime returns the unfuzzed/unrounded time in microseconds since the epoch + */ +uint64_t +Fuzzyfox::ActualTime() +{ + return PR_Now(); +} + +/* + * Calculate a duration we will wait until we allow time to advance again + */ +uint64_t +Fuzzyfox::PickDuration() +{ + // TODO: Bug 1484298 - use a real RNG + long int rval = rand(); + + // Avoid divide by zero errors and overflow errors + uint32_t duration = sFuzzyfoxClockGrain <= 0 ? 1 : sFuzzyfoxClockGrain; + duration = duration >= (UINT32_MAX / 2) ? (UINT32_MAX / 2) : duration; + + // We want uniform distribution from 1->duration*2 + // so that the mean is duration + return 1 + (rval % (duration * 2)); +} + +/* + * Update the TimeStamp's class value for the current (constant) time and dispatch + * the new (constant) timestamp so observers can register to receive it to update + * their own time code. + */ +void +Fuzzyfox::UpdateClocks(uint64_t aNewTime, TimeStamp aNewTimeStamp) +{ + // newTime is the new canonical time for this scope! + #ifndef XP_WIN + LOG(Verbose, ("[Time] New time is %" PRIu64 " (compare to %" PRIu64 ") and timestamp is %" PRIu64 " (compare to %" PRIu64 ")\n", + aNewTime, ActualTime(), aNewTimeStamp.mValue.mTimeStamp, TimeStamp::NowUnfuzzed().mValue.mTimeStamp)); + #else + LOG(Verbose, ("[Time] New time is %" PRIu64 " (compare to %" PRIu64 ") \n", aNewTime, ActualTime())); + #endif + + // Fire notifications + if (MOZ_UNLIKELY(!mObs)) { + mObs = services::GetObserverService(); + if (NS_WARN_IF(!mObs)) { + return; + } + } + + // Event firings on occur on downticks and have no data + if (mTickType == eDowntick) { + mObs->NotifyObservers(nullptr, FUZZYFOX_FIREOUTBOUND_OBSERVER_TOPIC, nullptr); + } + + if (!mTimeUpdateWrapper) { + mTimeUpdateWrapper = do_CreateInstance(NS_SUPPORTS_PRINT64_CONTRACTID); + if (NS_WARN_IF(!mTimeUpdateWrapper)) { + return; + } + } + + mTimeUpdateWrapper->SetData(aNewTime); + + // Clocks get the new official (frozen) time. This happens on all ticks + mObs->NotifyObservers(mTimeUpdateWrapper, FUZZYFOX_UPDATECLOCK_OBSERVER_TOPIC, nullptr); + + // Update the timestamp's canonicaltimes + TimeStamp::UpdateFuzzyTime(aNewTime); + TimeStamp::UpdateFuzzyTimeStamp(aNewTimeStamp); +} + +uint64_t +Fuzzyfox::GetClockGrain() +{ + return sFuzzyfoxClockGrain; +} + + +/* + * FloorToGrain accepts a timestamp in microsecond precision + * and returns it in microseconds, rounded down to the nearest + * ClockGrain value. + */ +uint64_t +Fuzzyfox::FloorToGrain(uint64_t aValue) +{ + return aValue - (aValue % GetClockGrain()); +} + + +/* + * FloorToGrain accepts a timestamp and returns it, rounded down + * to the nearest ClockGrain value. + */ +TimeStamp +Fuzzyfox::FloorToGrain(TimeStamp aValue) +{ +#ifdef XP_WIN + // grain is in us + uint64_t grain = GetClockGrain(); + // GTC and QPS are stored in |mt| and need to be converted to + uint64_t GTC = mt2ms(aValue.mValue.mGTC) * 1000; + uint64_t QPC = mt2ms(aValue.mValue.mQPC) * 1000; + + return TimeStamp(TimeStampValue( + ms2mt((GTC - (GTC % grain)) / 1000), + ms2mt((QPC - (QPC % grain)) / 1000), + aValue.mValue.mHasQPC, true)); +#else + return TimeStamp(TimeStampValue(true, US_TO_NS(FloorToGrain(NS_TO_US(aValue.mValue.mTimeStamp))))); +#endif +} + +/* + * CeilToGrain accepts a timestamp in microsecond precision + * and returns it in microseconds, rounded up to the nearest + * ClockGrain value. + */ +uint64_t +Fuzzyfox::CeilToGrain(uint64_t aValue) +{ + return (aValue / GetClockGrain()) * GetClockGrain(); +} + +/* + * CeilToGrain accepts a timestamp and returns it, rounded up + * to the nearest ClockGrain value. + */ +TimeStamp +Fuzzyfox::CeilToGrain(TimeStamp aValue) +{ +#ifdef XP_WIN + // grain is in us + uint64_t grain = GetClockGrain(); + // GTC and QPS are stored in |mt| and need to be converted + uint64_t GTC = mt2ms(aValue.mValue.mGTC) * 1000; + uint64_t QPC = mt2ms(aValue.mValue.mQPC) * 1000; + + return TimeStamp(TimeStampValue( + ms2mt(((GTC / grain) * grain) / 1000), + ms2mt(((QPC / grain) * grain) / 1000), + aValue.mValue.mHasQPC, true)); +#else + return TimeStamp(TimeStampValue(true, US_TO_NS(CeilToGrain(NS_TO_US(aValue.mValue.mTimeStamp))))); +#endif +} \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/toolkit/components/fuzzyfox/Fuzzyfox.h @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_Fuzzyfox_h +#define mozilla_Fuzzyfox_h + +#include "nsIObserver.h" +#include "nsIObserverService.h" +#include "nsISupportsPrimitives.h" +#include "nsThreadUtils.h" +#include "mozilla/TimeStamp.h" + + +/* + * This topic publishes the new canonical time according to Fuzzyfox, + * in microseconds since the epoch. If code needs to know the current time, + * it should listen for this topic and keep track of the 'current' time, + * so as to respect Fuzzyfox and be in sync with the rest of the browser's + * timekeeping. + */ +#define FUZZYFOX_UPDATECLOCK_OBSERVER_TOPIC "fuzzyfox-update-clocks" + +/* + * For Fuzzyfox's security guarentees to hold, the browser must not execute + * actions while it should be paused. We currently only pause the main thread, + * so actions that occur on other threads should be queued until the browser + * unpaused (and moreso than unpauses: until it reaches a downtick.) + * This topic indicates when any queued outbound events should be delivered. + * TODO: Bug 1484300 and 1484299 would apply this to other communication channels + */ +#define FUZZYFOX_FIREOUTBOUND_OBSERVER_TOPIC "fuzzyfox-fire-outbound" + +namespace mozilla { + + +/* + * Fuzzyfox is an implementation of the Fermata concept presented in + * Trusted Browsers for Uncertain Times. + * + * Web Browsers expose explicit (performance.now()) and implicit + * (WebVTT, Video Frames) timers that, when combined with algorithmic + * improvements such as edge thresholding, produce extremely high + * resolution clocks. + * + * High Resolution clocks can be used to time network accesses, browser + * cache reads, web page rendering, access to the CPU cache, and other + * operations - and the time these operations take to perform can yield + * detailed information about user information we want to keep private. + * + * Fuzzyfox limits the information disclosure by limiting an attacker's + * ability to create a high resolution clock. It does this by introducing + * a concept called 'fuzzy time' that degrades all clocks (explicit and + * implicit). This is done through a combination of holding time constant + * during program execution and pausing program execution. + * + * @InProceedings{KS16, + * author = {David Kohlbrenner and Hovav Shacham}, + * title = {Trusted Browsers for Uncertain Times}, + * booktitle = {Proceedings of USENIX Security 2016}, + * pages = {463-80}, + * year = 2016, + * editor = {Thorsten Holz and Stefan Savage}, + * month = aug, + * organization = {USENIX} + * } + * https://www.usenix.org/system/files/conference/usenixsecurity16/sec16_paper_kohlbrenner.pdf + * + * Fuzzyfox is an adaptation of + * W.-M. Hu, “Reducing timing channels with fuzzy time,” in + * Proceedings of IEEE Security and Privacy (“Oakland”) + * 1991, T. F. Lunt and J. McLean, Eds. IEEE Computer + * Society, May 1991, pp. 8–20. + */ +class Fuzzyfox final : public Runnable, public nsIObserver +{ +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIOBSERVER + + static void + Start(); + + NS_IMETHOD + Run() override; + +private: + Fuzzyfox(); + ~Fuzzyfox(); + + uint64_t + ActualTime(); + + uint64_t + PickDuration(); + + void + UpdateClocks(uint64_t aNewTime, TimeStamp aNewTimeStamp); + + uint64_t + GetClockGrain(); + + uint64_t + FloorToGrain(uint64_t aValue); + + TimeStamp + FloorToGrain(TimeStamp aValue); + + uint64_t + CeilToGrain(uint64_t aValue); + + TimeStamp + CeilToGrain(TimeStamp aValue); + + bool mSanityCheck; + uint64_t mStartTime; + uint32_t mDuration; + + enum Tick { + eUptick, + eDowntick, + }; + + Tick mTickType; + + nsCOMPtr<nsIObserverService> mObs = nullptr; + nsCOMPtr<nsISupportsPRInt64> mTimeUpdateWrapper = nullptr; + + static Atomic<bool, Relaxed> sFuzzyfoxEnabledPrefMapped; + static Atomic<uint32_t, Relaxed> sFuzzyfoxClockGrain; +}; + +} // mozilla namespace + +#endif /* mozilla_Fuzzyfox_h */
new file mode 100644 --- /dev/null +++ b/toolkit/components/fuzzyfox/moz.build @@ -0,0 +1,15 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +SOURCES += [ + 'Fuzzyfox.cpp', +] + +EXPORTS.mozilla += [ + 'Fuzzyfox.h' +] + +FINAL_LIBRARY = 'xul'
--- a/toolkit/components/moz.build +++ b/toolkit/components/moz.build @@ -31,16 +31,17 @@ DIRS += [ 'crashes', 'crashmonitor', 'downloads', 'enterprisepolicies', 'extensions', 'filewatcher', 'finalizationwitness', 'find', + 'fuzzyfox', 'jsoncpp/src/lib_json', 'lz4', 'mediasniffer', 'microformats', 'mozintl', 'mozprotocol', 'osfile', 'parentalcontrols',
--- a/toolkit/components/telemetry/app/TelemetryEnvironment.jsm +++ b/toolkit/components/telemetry/app/TelemetryEnvironment.jsm @@ -248,16 +248,17 @@ const DEFAULT_ENVIRONMENT_PREFS = new Ma ["layout.css.devPixelsPerPx", {what: RECORD_PREF_VALUE}], ["marionette.enabled", {what: RECORD_PREF_VALUE}], ["network.proxy.autoconfig_url", {what: RECORD_PREF_STATE}], ["network.proxy.http", {what: RECORD_PREF_STATE}], ["network.proxy.ssl", {what: RECORD_PREF_STATE}], ["pdfjs.disabled", {what: RECORD_PREF_VALUE}], ["places.history.enabled", {what: RECORD_PREF_VALUE}], ["plugins.show_infobar", {what: RECORD_PREF_VALUE}], + ["privacy.fuzzyfox.enabled", {what: RECORD_PREF_VALUE}], ["privacy.trackingprotection.enabled", {what: RECORD_PREF_VALUE}], ["privacy.donottrackheader.enabled", {what: RECORD_PREF_VALUE}], ["security.mixed_content.block_active_content", {what: RECORD_PREF_VALUE}], ["security.mixed_content.block_display_content", {what: RECORD_PREF_VALUE}], ["xpinstall.signatures.required", {what: RECORD_PREF_VALUE}], ]); const LOGGER_NAME = "Toolkit.Telemetry";
--- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -1594,17 +1594,17 @@ extern void DumpValue(const JS::Value& v void CycleCollectedJSRuntime::ErrorInterceptor::Shutdown(JSRuntime* rt) { JS_SetErrorInterceptorCallback(rt, nullptr); mThrownError.reset(); } /* virtual */ void -CycleCollectedJSRuntime::ErrorInterceptor::interceptError(JSContext* cx, const JS::Value& exn) +CycleCollectedJSRuntime::ErrorInterceptor::interceptError(JSContext* cx, JS::HandleValue exn) { if (mThrownError) { // We already have an error, we don't need anything more. return; } if (!nsContentUtils::ThreadsafeIsSystemCaller(cx)) { // We are only interested in chrome code. @@ -1626,26 +1626,25 @@ CycleCollectedJSRuntime::ErrorIntercepto // Not one of the errors we are interested in. return; } // Now copy the details of the exception locally. // While copying the details of an exception could be expensive, in most runs, // this will be done at most once during the execution of the process, so the // total cost should be reasonable. - JS::RootedValue value(cx, exn); ErrorDetails details; details.mType = *type; // If `exn` isn't an exception object, `ExtractErrorValues` could end up calling // `toString()`, which could in turn end up throwing an error. While this should // work, we want to avoid that complex use case. // Fortunately, we have already checked above that `exn` is an exception object, // so nothing such should happen. - nsContentUtils::ExtractErrorValues(cx, value, details.mFilename, &details.mLine, &details.mColumn, details.mMessage); + nsContentUtils::ExtractErrorValues(cx, exn, details.mFilename, &details.mLine, &details.mColumn, details.mMessage); JS::UniqueChars buf = JS::FormatStackDump(cx, /* showArgs = */ false, /* showLocals = */ false, /* showThisProps = */ false); CopyUTF8toUTF16(mozilla::MakeStringSpan(buf.get()), details.mStack); mThrownError.emplace(std::move(details)); } void
--- a/xpcom/base/CycleCollectedJSRuntime.h +++ b/xpcom/base/CycleCollectedJSRuntime.h @@ -378,17 +378,17 @@ private: bool mShutdownCalled; #endif #ifdef NIGHTLY_BUILD // Implementation of the error interceptor. // Built on nightly only to avoid any possible performance impact on release struct ErrorInterceptor final : public JSErrorInterceptor { - virtual void interceptError(JSContext* cx, const JS::Value& val) override; + virtual void interceptError(JSContext* cx, JS::HandleValue exn) override; void Shutdown(JSRuntime* rt); // Copy of the details of the exception. // We store this rather than the exception itself to avoid dealing with complicated // garbage-collection scenarios, e.g. a JSContext being killed while we still hold // onto an exception thrown from it. struct ErrorDetails { nsString mFilename;