diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 49db6f945e..42fc5a9ee8 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -966,7 +966,6 @@ pref("apz.allow_zooming", true); // Gaia relies heavily on scroll events for now, so lets fire them // more often than the default value (100). -pref("apz.asyncscroll.throttle", 40); pref("apz.pan_repaint_interval", 16); // APZ physics settings, tuned by UX designers diff --git a/browser/components/about/moz.build b/browser/components/about/moz.build index 95a8451baf..808084f60e 100644 --- a/browser/components/about/moz.build +++ b/browser/components/about/moz.build @@ -17,3 +17,6 @@ FINAL_LIBRARY = 'browsercomps' LOCAL_INCLUDES += [ '../build', ] + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wshadow'] diff --git a/browser/components/build/moz.build b/browser/components/build/moz.build index 8e678c55a6..dd758a0823 100644 --- a/browser/components/build/moz.build +++ b/browser/components/build/moz.build @@ -39,3 +39,6 @@ if CONFIG['OS_ARCH'] == 'WINNT': # GTK2: Need to link with glib for GNOME shell service if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'gtk2', 'gtk3'): OS_LIBS += CONFIG['TK_LIBS'] + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wshadow'] diff --git a/browser/components/dirprovider/moz.build b/browser/components/dirprovider/moz.build index e51e634494..570ff8728f 100644 --- a/browser/components/dirprovider/moz.build +++ b/browser/components/dirprovider/moz.build @@ -12,8 +12,15 @@ SOURCES += [ 'DirectoryProvider.cpp', ] +XPCSHELL_TESTS_MANIFESTS += [ + 'tests/unit/xpcshell.ini', +] + FINAL_LIBRARY = 'browsercomps' LOCAL_INCLUDES += [ '../build' ] + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wshadow'] diff --git a/browser/components/dirprovider/tests/unit/head_dirprovider.js b/browser/components/dirprovider/tests/unit/head_dirprovider.js new file mode 100644 index 0000000000..b80f8ed6bb --- /dev/null +++ b/browser/components/dirprovider/tests/unit/head_dirprovider.js @@ -0,0 +1,20 @@ +/* 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/. */ + +var Cc = Components.classes; +var Ci = Components.interfaces; + +var gProfD = do_get_profile(); +var gDirSvc = Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIProperties); +var gPrefSvc = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + +function writeTestFile(aParent, aName) { + let file = aParent.clone(); + file.append(aName); + file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0644); + return file; +} + diff --git a/browser/components/dirprovider/tests/unit/test_bookmark_pref.js b/browser/components/dirprovider/tests/unit/test_bookmark_pref.js new file mode 100644 index 0000000000..576fd801fc --- /dev/null +++ b/browser/components/dirprovider/tests/unit/test_bookmark_pref.js @@ -0,0 +1,14 @@ +/* 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/. */ + +// We need to run this test separately since DirectoryProvider persists BMarks + +function run_test() { + let dir = gProfD.clone(); + let tfile = writeTestFile(dir, "bookmarkfile.test"); + gPrefSvc.setCharPref("browser.bookmarks.file", tfile.path); + + let bmarks = gDirSvc.get("BMarks", Ci.nsIFile); + do_check_true(tfile.equals(bmarks)); +} diff --git a/browser/components/dirprovider/tests/unit/test_keys.js b/browser/components/dirprovider/tests/unit/test_keys.js new file mode 100644 index 0000000000..8f0773b27c --- /dev/null +++ b/browser/components/dirprovider/tests/unit/test_keys.js @@ -0,0 +1,21 @@ +/* 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/. */ + +function test_bookmarkhtml() { + let bmarks = gProfD.clone(); + bmarks.append("bookmarks.html"); + + let tbmarks = gDirSvc.get("BMarks", Ci.nsIFile); + do_check_true(bmarks.equals(tbmarks)); +} + +function run_test() { + [test_bookmarkhtml + ].forEach(function(f) { + do_test_pending(); + print("Running test: " + f.name); + f(); + do_test_finished(); + }); +} diff --git a/browser/components/dirprovider/tests/unit/xpcshell.ini b/browser/components/dirprovider/tests/unit/xpcshell.ini new file mode 100644 index 0000000000..e1504bb70d --- /dev/null +++ b/browser/components/dirprovider/tests/unit/xpcshell.ini @@ -0,0 +1,8 @@ +[DEFAULT] +head = head_dirprovider.js +tail = +firefox-appdir = browser +skip-if = toolkit == 'android' || toolkit == 'gonk' + +[test_bookmark_pref.js] +[test_keys.js] diff --git a/dom/base/DOMException.cpp b/dom/base/DOMException.cpp index acf9781440..8e2b2ffc0e 100644 --- a/dom/base/DOMException.cpp +++ b/dom/base/DOMException.cpp @@ -435,9 +435,6 @@ Exception::ToString(nsACString& _retval) return NS_OK; } -/* void initialize (in AUTF8String aMessage, in nsresult aResult, - * in AUTF8String aName, in nsIStackFrame aLocation, - * in nsISupports aData, in nsIException aInner); */ NS_IMETHODIMP Exception::Initialize(const nsACString& aMessage, nsresult aResult, const nsACString& aName, nsIStackFrame *aLocation, diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 556b7664f8..8e06e089bd 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -7525,7 +7525,6 @@ nsIDocument::GetDocumentURIObject() const } -// readonly attribute DOMString compatMode; // Returns "BackCompat" if we are in quirks mode, "CSS1Compat" if we are // in almost standards or full standards mode. See bug 105640. This was // implemented to match MSIE's compatMode property. diff --git a/dom/browser-element/BrowserElementParent.cpp b/dom/browser-element/BrowserElementParent.cpp index d41ca73a5f..744769f819 100644 --- a/dom/browser-element/BrowserElementParent.cpp +++ b/dom/browser-element/BrowserElementParent.cpp @@ -117,7 +117,7 @@ DispatchCustomDOMEvent(Element* aFrameElement, const nsAString& aEventName, } event->SetTrusted(true); // Dispatch the event. - *aStatus = nsEventStatus_eConsumeNoDefault; + // We don't initialize aStatus here, as our callers have already done so. nsresult rv = EventDispatcher::DispatchDOMEvent(aFrameElement, nullptr, static_cast(event), @@ -177,7 +177,7 @@ BrowserElementParent::DispatchOpenWindowEvent(Element* aOpenerFrameElement, return BrowserElementParent::OPEN_WINDOW_CANCELLED; } - nsEventStatus status; + nsEventStatus status = nsEventStatus_eIgnore; bool dispatchSucceeded = DispatchCustomDOMEvent(aOpenerFrameElement, NS_LITERAL_STRING("mozbrowseropenwindow"), @@ -299,79 +299,4 @@ BrowserElementParent::OpenWindowInProcess(nsIDOMWindow* aOpenerWindow, return !!*aReturnWindow ? opened : BrowserElementParent::OPEN_WINDOW_CANCELLED; } -class DispatchAsyncScrollEventRunnable : public nsRunnable -{ -public: - DispatchAsyncScrollEventRunnable(TabParent* aTabParent, - const CSSRect& aContentRect, - const CSSSize& aContentSize) - : mTabParent(aTabParent) - , mContentRect(aContentRect) - , mContentSize(aContentSize) - {} - - NS_IMETHOD Run(); - -private: - RefPtr mTabParent; - const CSSRect mContentRect; - const CSSSize mContentSize; -}; - -NS_IMETHODIMP DispatchAsyncScrollEventRunnable::Run() -{ - nsCOMPtr frameElement = mTabParent->GetOwnerElement(); - NS_ENSURE_STATE(frameElement); - nsIDocument *doc = frameElement->OwnerDoc(); - nsCOMPtr globalObject = doc->GetScopeObject(); - NS_ENSURE_TRUE(globalObject, NS_ERROR_UNEXPECTED); - - // Create the event's detail object. - AsyncScrollEventDetail detail; - detail.mLeft = mContentRect.x; - detail.mTop = mContentRect.y; - detail.mWidth = mContentRect.width; - detail.mHeight = mContentRect.height; - detail.mScrollWidth = mContentRect.width; - detail.mScrollHeight = mContentRect.height; - - AutoSafeJSContext cx; - JS::Rooted globalJSObject(cx, globalObject->GetGlobalJSObject()); - NS_ENSURE_TRUE(globalJSObject, NS_ERROR_UNEXPECTED); - - JSAutoCompartment ac(cx, globalJSObject); - JS::Rooted val(cx); - - if (!ToJSValue(cx, detail, &val)) { - MOZ_CRASH("Failed to convert dictionary to JS::Value due to OOM."); - return NS_ERROR_FAILURE; - } - - nsEventStatus status = nsEventStatus_eIgnore; - DispatchCustomDOMEvent(frameElement, - NS_LITERAL_STRING("mozbrowserasyncscroll"), - cx, - val, &status); - return NS_OK; -} - -bool -BrowserElementParent::DispatchAsyncScrollEvent(TabParent* aTabParent, - const CSSRect& aContentRect, - const CSSSize& aContentSize) -{ - // Do not dispatch a mozbrowserasyncscroll event of a widget to its embedder - nsCOMPtr frameElement = aTabParent->GetOwnerElement(); - NS_ENSURE_TRUE(frameElement, false); - nsCOMPtr browserFrame = do_QueryInterface(frameElement); - if (browserFrame && browserFrame->GetReallyIsWidget()) { - return true; - } - - RefPtr runnable = - new DispatchAsyncScrollEventRunnable(aTabParent, aContentRect, - aContentSize); - return NS_SUCCEEDED(NS_DispatchToMainThread(runnable)); -} - } // namespace mozilla diff --git a/dom/browser-element/BrowserElementParent.h b/dom/browser-element/BrowserElementParent.h index f8c28c8318..d67481cff9 100644 --- a/dom/browser-element/BrowserElementParent.h +++ b/dom/browser-element/BrowserElementParent.h @@ -109,26 +109,6 @@ public: const nsACString& aFeatures, nsIDOMWindow** aReturnWindow); - /** - * Fire a mozbrowserasyncscroll CustomEvent on the given TabParent's frame element. - * This event's detail is an AsyncScrollEventDetail dictionary. - * - * @param aContentRect: The portion of the page which is currently visible - * onscreen in CSS pixels. - * - * @param aContentSize: The content width/height in CSS pixels. - * - * aContentRect.top + aContentRect.height may be larger than aContentSize.height. - * This indicates that the content is over-scrolled, which occurs when the - * page "rubber-bands" after being scrolled all the way to the bottom. - * Similarly, aContentRect.left + aContentRect.width may be greater than - * contentSize.width, and both left and top may be negative. - */ - static bool - DispatchAsyncScrollEvent(dom::TabParent* aTabParent, - const CSSRect& aContentRect, - const CSSSize& aContentSize); - private: static OpenWindowResult DispatchOpenWindowEvent(dom::Element* aOpenerFrameElement, diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 071a11f262..d147d5ae6f 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -5322,9 +5322,6 @@ CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx, JS::ToInt32(dirtyHeight)); } -// void putImageData (in ImageData d, in float x, in float y); -// void putImageData (in ImageData d, in double x, in double y, in double dirtyX, in double dirtyY, in double dirtyWidth, in double dirtyHeight); - nsresult CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h, dom::Uint8ClampedArray* aArray, diff --git a/dom/gamepad/GamepadServiceTest.cpp b/dom/gamepad/GamepadServiceTest.cpp index 56a43cec38..393f382396 100644 --- a/dom/gamepad/GamepadServiceTest.cpp +++ b/dom/gamepad/GamepadServiceTest.cpp @@ -59,8 +59,6 @@ NS_IMETHODIMP GamepadServiceTest::RemoveGamepad(uint32_t aIndex) return NS_OK; } -/* void newButtonEvent (in uint32_t index, in uint32_t button, - in boolean pressed); */ NS_IMETHODIMP GamepadServiceTest::NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed) @@ -69,8 +67,6 @@ NS_IMETHODIMP GamepadServiceTest::NewButtonEvent(uint32_t aIndex, return NS_OK; } -/* void newButtonEvent (in uint32_t index, in uint32_t button, - in boolean pressed, double value); */ NS_IMETHODIMP GamepadServiceTest::NewButtonValueEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, @@ -80,8 +76,6 @@ NS_IMETHODIMP GamepadServiceTest::NewButtonValueEvent(uint32_t aIndex, return NS_OK; } -/* void newAxisMoveEvent (in uint32_t index, in uint32_t axis, - in double value); */ NS_IMETHODIMP GamepadServiceTest::NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, double aValue) diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp index 63424cb86e..17a83e4fc4 100644 --- a/dom/html/nsHTMLDocument.cpp +++ b/dom/html/nsHTMLDocument.cpp @@ -3199,8 +3199,6 @@ ConvertToMidasInternalCommand(const nsAString & inCommandID, } /* TODO: don't let this call do anything if the page is not done loading */ -/* boolean execCommand(in DOMString commandID, in boolean doShowUI, - in DOMString value); */ NS_IMETHODIMP nsHTMLDocument::ExecCommand(const nsAString& commandID, bool doShowUI, diff --git a/dom/svg/DOMSVGPathSeg.cpp b/dom/svg/DOMSVGPathSeg.cpp index 521420e8f4..95be3521e2 100644 --- a/dom/svg/DOMSVGPathSeg.cpp +++ b/dom/svg/DOMSVGPathSeg.cpp @@ -156,7 +156,6 @@ DOMSVGPathSeg::IndexIsValid() // Implementation of DOMSVGPathSeg sub-classes below this point #define IMPL_PROP_WITH_TYPE(segName, propName, index, type) \ - /* attribute type propName; */ \ type \ DOMSVGPathSeg##segName::propName() \ { \ diff --git a/dom/system/gonk/mozstumbler/MozStumbler.cpp b/dom/system/gonk/mozstumbler/MozStumbler.cpp index 93a67c2176..e597be7188 100644 --- a/dom/system/gonk/mozstumbler/MozStumbler.cpp +++ b/dom/system/gonk/mozstumbler/MozStumbler.cpp @@ -233,7 +233,6 @@ StumblerInfo::DumpStumblerInfo() target->Dispatch(event, NS_DISPATCH_NORMAL); } -/* void notifyGetCellInfoList (in uint32_t count, [array, size_is (count)] in nsICellInfo result); */ NS_IMETHODIMP StumblerInfo::NotifyGetCellInfoList(uint32_t count, nsICellInfo** aCellInfos) { @@ -248,7 +247,6 @@ StumblerInfo::NotifyGetCellInfoList(uint32_t count, nsICellInfo** aCellInfos) return NS_OK; } -/* void notifyGetCellInfoListFailed (in DOMString error); */ NS_IMETHODIMP StumblerInfo::NotifyGetCellInfoListFailed(const nsAString& error) { MOZ_ASSERT(NS_IsMainThread()); diff --git a/dom/webidl/BrowserElementDictionaries.webidl b/dom/webidl/BrowserElementDictionaries.webidl index a259c7df86..400e402532 100644 --- a/dom/webidl/BrowserElementDictionaries.webidl +++ b/dom/webidl/BrowserElementDictionaries.webidl @@ -7,15 +7,6 @@ * liability, trademark and document use rules apply. */ -dictionary AsyncScrollEventDetail { - float top = 0; - float left = 0; - float width = 0; - float height = 0; - float scrollWidth = 0; - float scrollHeight = 0; -}; - dictionary OpenWindowEventDetail { DOMString url = ""; DOMString name = ""; diff --git a/editor/txmgr/nsTransactionList.cpp b/editor/txmgr/nsTransactionList.cpp index d4567c98e3..b414d26713 100644 --- a/editor/txmgr/nsTransactionList.cpp +++ b/editor/txmgr/nsTransactionList.cpp @@ -85,10 +85,6 @@ NS_IMETHODIMP nsTransactionList::ItemIsBatch(int32_t aIndex, bool *aIsBatch) return item->GetIsBatch(aIsBatch); } -/* void getData (in long aIndex, - [optional] out unsigned long aLength, - [array, size_is (aLength), retval] - out nsISupports aData); */ NS_IMETHODIMP nsTransactionList::GetData(int32_t aIndex, uint32_t *aLength, nsISupports ***aData) diff --git a/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp b/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp index 02dccbd728..5c061adeb2 100644 --- a/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp +++ b/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp @@ -327,9 +327,6 @@ NS_IMETHODIMP nsWebBrowserPersist::SetProgressListener( return NS_OK; } -/* void saveURI (in nsIURI aURI, in nsISupports aCacheKey, in nsIURI aReferrer, - in nsIInputStream aPostData, in wstring aExtraHeaders, - in nsISupports aFile, in nsILoadContext aPrivayContext); */ NS_IMETHODIMP nsWebBrowserPersist::SaveURI( nsIURI *aURI, nsISupports *aCacheKey, nsIURI *aReferrer, uint32_t aReferrerPolicy, @@ -905,8 +902,6 @@ nsWebBrowserPersist::OnDataAvailable( // nsWebBrowserPersist::nsIProgressEventSink //***************************************************************************** -/* void onProgress (in nsIRequest request, in nsISupports ctxt, - in long long aProgress, in long long aProgressMax); */ NS_IMETHODIMP nsWebBrowserPersist::OnProgress( nsIRequest *request, nsISupports *ctxt, int64_t aProgress, int64_t aProgressMax) @@ -958,8 +953,6 @@ NS_IMETHODIMP nsWebBrowserPersist::OnProgress( return NS_OK; } -/* void onStatus (in nsIRequest request, in nsISupports ctxt, - in nsresult status, in wstring statusArg); */ NS_IMETHODIMP nsWebBrowserPersist::OnStatus( nsIRequest *request, nsISupports *ctxt, nsresult status, const char16_t *statusArg) diff --git a/gfx/gl/GLConsts.h b/gfx/gl/GLConsts.h index fb43c745af..ad6175e163 100644 --- a/gfx/gl/GLConsts.h +++ b/gfx/gl/GLConsts.h @@ -5668,7 +5668,6 @@ #define LOCAL_GLX_X_VISUAL_TYPE_EXT 0x22 #define LOCAL_GLX_Y_INVERTED_EXT 0x20D4 - // WGL #define LOCAL_WGL_ACCELERATION_ARB 0x2003 #define LOCAL_WGL_ACCELERATION_EXT 0x2003 @@ -5949,6 +5948,4 @@ #define LOCAL_WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB #define LOCAL_WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC - - #endif // GLCONSTS_H_ diff --git a/gfx/gl/GLContextProviderWGL.cpp b/gfx/gl/GLContextProviderWGL.cpp index 0a7fd79a5c..a8b59b0403 100644 --- a/gfx/gl/GLContextProviderWGL.cpp +++ b/gfx/gl/GLContextProviderWGL.cpp @@ -141,9 +141,11 @@ WGLLibrary::EnsureInitialized() return false; } + const GLLibraryLoader::PlatformLookupFunction lookupFunc = + (GLLibraryLoader::PlatformLookupFunction) fGetProcAddress; + // Now we can grab all the other symbols that we couldn't without having // a context current. - GLLibraryLoader::SymLoadStruct pbufferSymbols[] = { { (PRFuncPtr*) &fCreatePbuffer, { "wglCreatePbufferARB", "wglCreatePbufferEXT", nullptr } }, { (PRFuncPtr*) &fDestroyPbuffer, { "wglDestroyPbufferARB", "wglDestroyPbufferEXT", nullptr } }, @@ -159,16 +161,12 @@ WGLLibrary::EnsureInitialized() { nullptr, { nullptr } } }; - if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pbufferSymbols[0], - (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) - { + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pbufferSymbols[0], lookupFunc)) { // this isn't an error, just means that pbuffers aren't supported fCreatePbuffer = nullptr; } - if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pixFmtSymbols[0], - (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) - { + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pixFmtSymbols[0], lookupFunc)) { // this isn't an error, just means that we don't have the pixel format extension fChoosePixelFormat = nullptr; } @@ -183,14 +181,49 @@ WGLLibrary::EnsureInitialized() { nullptr, { nullptr } } }; - if (GLLibraryLoader::LoadSymbols(mOGLLibrary, &extensionsSymbols[0], - (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress)) { - const char *wglExts = fGetExtensionsString(mWindowDC); - if (wglExts && HasExtension(wglExts, "WGL_ARB_create_context")) { - GLLibraryLoader::LoadSymbols(mOGLLibrary, &robustnessSymbols[0], - (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress); - if (HasExtension(wglExts, "WGL_ARB_create_context_robustness")) { - mHasRobustness = true; + GLLibraryLoader::SymLoadStruct dxInteropSymbols[] = { + { (PRFuncPtr *)&fDXSetResourceShareHandle,{ "wglDXSetResourceShareHandleNV", nullptr } }, + { (PRFuncPtr *)&fDXOpenDevice, { "wglDXOpenDeviceNV", nullptr } }, + { (PRFuncPtr *)&fDXCloseDevice, { "wglDXCloseDeviceNV", nullptr } }, + { (PRFuncPtr *)&fDXRegisterObject, { "wglDXRegisterObjectNV", nullptr } }, + { (PRFuncPtr *)&fDXUnregisterObject, { "wglDXUnregisterObjectNV", nullptr } }, + { (PRFuncPtr *)&fDXObjectAccess, { "wglDXObjectAccessNV", nullptr } }, + { (PRFuncPtr *)&fDXLockObjects, { "wglDXLockObjectsNV", nullptr } }, + { (PRFuncPtr *)&fDXUnlockObjects, { "wglDXUnlockObjectsNV", nullptr } }, + { nullptr, { nullptr } } + }; + + if (GLLibraryLoader::LoadSymbols(mOGLLibrary, &extensionsSymbols[0], lookupFunc)) + { + const char* extString = fGetExtensionsString(mWindowDC); + MOZ_ASSERT(extString); + MOZ_ASSERT(HasExtension(extString, "WGL_ARB_extensions_string")); + + if (HasExtension(extString, "WGL_ARB_context_create")) { + if (GLLibraryLoader::LoadSymbols(mOGLLibrary, &robustnessSymbols[0], lookupFunc)) { + if (HasExtension(extString, "WGL_ARB_create_context_robustness")) { + mHasRobustness = true; + } + } else { + NS_ERROR("WGL supports ARB_create_context without supplying its functions."); + fCreateContextAttribs = nullptr; + } + } + + if (HasExtension(extString, "WGL_NV_DX_interop")) { + if (GLLibraryLoader::LoadSymbols(mOGLLibrary, &dxInteropSymbols[0], lookupFunc)) { + mHasDXInterop = true; + mHasDXInterop2 = HasExtension(extString, "WGL_NV_DX_interop2"); + } else { + NS_ERROR("WGL supports NV_DX_interop without supplying its functions."); + fDXSetResourceShareHandle = nullptr; + fDXOpenDevice = nullptr; + fDXCloseDevice = nullptr; + fDXRegisterObject = nullptr; + fDXUnregisterObject = nullptr; + fDXObjectAccess = nullptr; + fDXLockObjects = nullptr; + fDXUnlockObjects = nullptr; } } } diff --git a/gfx/gl/GLDefs.h b/gfx/gl/GLDefs.h index 18faa79416..73d5dd20bf 100644 --- a/gfx/gl/GLDefs.h +++ b/gfx/gl/GLDefs.h @@ -70,4 +70,9 @@ #define LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2) #define LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3) +// WGL_NV_DX_interop +#define LOCAL_WGL_ACCESS_READ_ONLY 0x0000 +#define LOCAL_WGL_ACCESS_READ_WRITE 0x0001 +#define LOCAL_WGL_ACCESS_WRITE_DISCARD 0x0002 + #endif diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp index 997edd20db..27ecc644b9 100755 --- a/gfx/gl/GLScreenBuffer.cpp +++ b/gfx/gl/GLScreenBuffer.cpp @@ -19,7 +19,8 @@ #include "mozilla/layers/TextureClientSharedSurface.h" #ifdef XP_WIN -#include "SharedSurfaceANGLE.h" // for SurfaceFactory_ANGLEShareHandle +#include "SharedSurfaceANGLE.h" // for SurfaceFactory_ANGLEShareHandle +#include "SharedSurfaceD3D11Interop.h" // for SurfaceFactory_D3D11Interop #include "gfxWindowsPlatform.h" #endif @@ -82,6 +83,8 @@ GLScreenBuffer::CreateFactory(GLContext* gl, #elif defined(GL_PROVIDER_GLX) if (sGLXLibrary.UseSurfaceSharing()) factory = SurfaceFactory_GLXDrawable::Create(gl, caps, forwarder, flags); +#elif defined(MOZ_WIDGET_UIKIT) + factory = MakeUnique(mGLContext, caps, forwarder, mFlags); #else if (gl->GetContextType() == GLContextType::EGL) { if (XRE_IsParentProcess()) { @@ -101,6 +104,10 @@ GLScreenBuffer::CreateFactory(GLContext* gl, { factory = SurfaceFactory_ANGLEShareHandle::Create(gl, caps, forwarder, flags); } + + if (!factory && gfxPrefs::WebGLDXGLEnabled()) { + factory = SurfaceFactory_D3D11Interop::Create(gl, caps, forwarder, flags); + } #endif break; } @@ -525,6 +532,12 @@ GLScreenBuffer::Swap(const gfx::IntSize& size) if (!newBack) return false; + // In the case of DXGL interop, the new surface needs to be acquired before + // it is attached so that the interop surface is locked, which populates + // the GL renderbuffer. This results in the renderbuffer being ready and + // attachment to framebuffer succeeds in Attach() call. + newBack->Surf()->ProducerAcquire(); + if (!Attach(newBack->Surf(), size)) return false; // Attach was successful. @@ -532,10 +545,6 @@ GLScreenBuffer::Swap(const gfx::IntSize& size) mFront = mBack; mBack = newBack; - if (mBack) { - mBack->Surf()->ProducerAcquire(); - } - if (ShouldPreserveBuffer() && mFront && mBack && diff --git a/gfx/gl/SharedSurfaceD3D11Interop.cpp b/gfx/gl/SharedSurfaceD3D11Interop.cpp new file mode 100644 index 0000000000..045610e700 --- /dev/null +++ b/gfx/gl/SharedSurfaceD3D11Interop.cpp @@ -0,0 +1,509 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "SharedSurfaceD3D11Interop.h" + +#include +#include "GLContext.h" +#include "WGLLibrary.h" + +namespace mozilla { +namespace gl { + +/* +Sample Code for WGL_NV_DX_interop2: +Example: Render to Direct3D 11 backbuffer with openGL: + +// create D3D11 device, context and swap chain. +ID3D11Device *device; +ID3D11DeviceContext *devCtx; +IDXGISwapChain *swapChain; + +DXGI_SWAP_CHAIN_DESC scd; + + + +hr = D3D11CreateDeviceAndSwapChain(NULL, // pAdapter + D3D_DRIVER_TYPE_HARDWARE, // DriverType + NULL, // Software + 0, // Flags (Do not set D3D11_CREATE_DEVICE_SINGLETHREADED) + NULL, // pFeatureLevels + 0, // FeatureLevels + D3D11_SDK_VERSION, // SDKVersion + &scd, // pSwapChainDesc + &swapChain, // ppSwapChain + &device, // ppDevice + NULL, // pFeatureLevel + &devCtx); // ppImmediateContext + +// Fetch the swapchain backbuffer +ID3D11Texture2D *dxColorbuffer; +swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID *)&dxColorbuffer); + +// Create depth stencil texture +ID3D11Texture2D *dxDepthBuffer; +D3D11_TEXTURE2D_DESC depthDesc; +depthDesc.Usage = D3D11_USAGE_DEFAULT; + + +// Create Views +ID3D11RenderTargetView *colorBufferView; +D3D11_RENDER_TARGET_VIEW_DESC rtd; + +device->CreateRenderTargetView(dxColorbuffer, &rtd, &colorBufferView); + +ID3D11DepthStencilView *depthBufferView; +D3D11_DEPTH_STENCIL_VIEW_DESC dsd; + +device->CreateDepthStencilView(dxDepthBuffer, &dsd, &depthBufferView); + +// Attach back buffer and depth texture to redertarget for the device. +devCtx->OMSetRenderTargets(1, &colorBufferView, depthBufferView); + +// Register D3D11 device with GL +HANDLE gl_handleD3D; +gl_handleD3D = wglDXOpenDeviceNV(device); + +// register the Direct3D color and depth/stencil buffers as +// renderbuffers in opengl +GLuint gl_names[2]; +HANDLE gl_handles[2]; + +glGenRenderbuffers(2, gl_names); + +gl_handles[0] = wglDXRegisterObjectNV(gl_handleD3D, dxColorBuffer, + gl_names[0], + GL_RENDERBUFFER, + WGL_ACCESS_READ_WRITE_NV); + +gl_handles[1] = wglDXRegisterObjectNV(gl_handleD3D, dxDepthBuffer, + gl_names[1], + GL_RENDERBUFFER, + WGL_ACCESS_READ_WRITE_NV); + +// attach the Direct3D buffers to an FBO +glBindFramebuffer(GL_FRAMEBUFFER, fbo); +glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, gl_names[0]); +glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, gl_names[1]); +glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, gl_names[1]); + +while (!done) { + + + // lock the render targets for GL access + wglDXLockObjectsNVX(gl_handleD3D, 2, gl_handles); + + + + // unlock the render targets + wglDXUnlockObjectsNVX(gl_handleD3D, 2, gl_handles); + + +} +*/ + +//////////////////////////////////////////////////////////////////////////////// +// DXGL Device + +class DXGLDevice : public RefCounted +{ +public: + MOZ_DECLARE_REFCOUNTED_TYPENAME(DXGLDevice) + + WGLLibrary* const mWGL; + const RefPtr mD3D; // Only needed for lifetime guarantee. + const HANDLE mDXGLDeviceHandle; + + static already_AddRefed Open(WGLLibrary* wgl) + { + MOZ_ASSERT(wgl->HasDXInterop2()); + gfxWindowsPlatform* plat = gfxWindowsPlatform::GetPlatform(); + + RefPtr d3d = plat->GetD3D11ContentDevice(); + if (!d3d) { + NS_WARNING("Failed to create D3D11 device."); + return nullptr; + } + + HANDLE dxglDeviceHandle = wgl->fDXOpenDevice(d3d); + if (!dxglDeviceHandle) { + NS_WARNING("Failed to open D3D device for use by WGL."); + return nullptr; + } + + return MakeAndAddRef(wgl, d3d, dxglDeviceHandle); + } + + DXGLDevice(WGLLibrary* wgl, const RefPtr& d3d, HANDLE dxglDeviceHandle) + : mWGL(wgl) + , mD3D(d3d) + , mDXGLDeviceHandle(dxglDeviceHandle) + { } + + ~DXGLDevice() { + if (!mWGL->fDXCloseDevice(mDXGLDeviceHandle)) { +#ifdef DEBUG + uint32_t error = GetLastError(); + printf_stderr("wglDXCloseDevice(0x%x) failed: GetLastError(): 0x%x\n", + mDXGLDeviceHandle, error); +#endif + MOZ_CRASH(); + } + } + + HANDLE RegisterObject(void* dxObject, GLuint name, GLenum type, GLenum access) const { + HANDLE ret = mWGL->fDXRegisterObject(mDXGLDeviceHandle, dxObject, name, type, + access); + if (!ret) { +#ifdef DEBUG + uint32_t error = GetLastError(); + printf_stderr("wglDXRegisterObject(0x%x, 0x%x, %u, 0x%x, 0x%x) failed:" + " GetLastError(): 0x%x\n", mDXGLDeviceHandle, dxObject, name, + type, access, error); +#endif + MOZ_CRASH(); + } + return ret; + } + + bool UnregisterObject(HANDLE hObject) const { + bool ret = mWGL->fDXUnregisterObject(mDXGLDeviceHandle, hObject); + if (!ret) { +#ifdef DEBUG + uint32_t error = GetLastError(); + printf_stderr("wglDXUnregisterObject(0x%x, 0x%x) failed: GetLastError():" + " 0x%x\n", mDXGLDeviceHandle, hObject, error); +#endif + MOZ_CRASH(); + } + return ret; + } + + bool LockObject(HANDLE hObject) const { + bool ret = mWGL->fDXLockObjects(mDXGLDeviceHandle, 1, &hObject); + if (!ret) { +#ifdef DEBUG + uint32_t error = GetLastError(); + printf_stderr("wglDXLockObjects(0x%x, 1, {0x%x}) failed: GetLastError():" + " 0x%x\n", mDXGLDeviceHandle, hObject, error); +#endif + MOZ_CRASH(); + } + return ret; + } + + bool UnlockObject(HANDLE hObject) const { + bool ret = mWGL->fDXUnlockObjects(mDXGLDeviceHandle, 1, &hObject); + if (!ret) { +#ifdef DEBUG + uint32_t error = GetLastError(); + printf_stderr("wglDXUnlockObjects(0x%x, 1, {0x%x}) failed: GetLastError():" + " 0x%x\n", mDXGLDeviceHandle, hObject, error); +#endif + MOZ_CRASH(); + } + return ret; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Shared Surface + +/*static*/ UniquePtr +SharedSurface_D3D11Interop::Create(const RefPtr& dxgl, + GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha) +{ + auto& d3d = *dxgl->mD3D; + + // Create a texture in case we need to readback. + DXGI_FORMAT format = hasAlpha ? DXGI_FORMAT_B8G8R8A8_UNORM + : DXGI_FORMAT_B8G8R8X8_UNORM; + CD3D11_TEXTURE2D_DESC desc(format, size.width, size.height, 1, 1); + desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; + + RefPtr textureD3D; + HRESULT hr = d3d.CreateTexture2D(&desc, nullptr, getter_AddRefs(textureD3D)); + if (FAILED(hr)) { + NS_WARNING("Failed to create texture for CanvasLayer!"); + return nullptr; + } + + RefPtr textureDXGI; + hr = textureD3D->QueryInterface(__uuidof(IDXGIResource), getter_AddRefs(textureDXGI)); + if (FAILED(hr)) { + NS_WARNING("Failed to open texture for sharing!"); + return nullptr; + } + + RefPtr keyedMutex; + hr = textureD3D->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(keyedMutex)); + if (FAILED(hr)) { + NS_WARNING("Failed to obtained keyed mutex from texture!"); + return nullptr; + } + + HANDLE sharedHandle; + textureDXGI->GetSharedHandle(&sharedHandle); + + GLuint renderbufferGL = 0; + gl->MakeCurrent(); + gl->fGenRenderbuffers(1, &renderbufferGL); + HANDLE objectWGL = dxgl->RegisterObject(textureD3D, renderbufferGL, + LOCAL_GL_RENDERBUFFER, + LOCAL_WGL_ACCESS_WRITE_DISCARD_NV); + if (!objectWGL) { + NS_WARNING("Failed to register D3D object with WGL."); + return nullptr; + } + + GLuint fence = 0; + if (gl->IsExtensionSupported(GLContext::NV_fence)) { + gl->MakeCurrent(); + gl->fGenFences(1, &fence); + } + + typedef SharedSurface_D3D11Interop ptrT; + UniquePtr ret ( new ptrT(gl, size, hasAlpha, renderbufferGL, dxgl, objectWGL, + textureD3D, sharedHandle, keyedMutex, fence) ); + return Move(ret); +} + +SharedSurface_D3D11Interop::SharedSurface_D3D11Interop(GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha, + GLuint renderbufferGL, + const RefPtr& dxgl, + HANDLE objectWGL, + const RefPtr& textureD3D, + HANDLE sharedHandle, + const RefPtr& keyedMutex, + GLuint fence) + : SharedSurface(SharedSurfaceType::DXGLInterop2, + AttachmentType::GLRenderbuffer, + gl, + size, + hasAlpha, + true) + , mProdRB(renderbufferGL) + , mDXGL(dxgl) + , mObjectWGL(objectWGL) + , mTextureD3D(textureD3D) + , mSharedHandle(sharedHandle) + , mKeyedMutex(keyedMutex) + , mFence(fence) + , mLockedForGL(false) +{ } + +SharedSurface_D3D11Interop::~SharedSurface_D3D11Interop() +{ + MOZ_ASSERT(!mLockedForGL); + + mGL->fDeleteRenderbuffers(1, &mProdRB); + + if (!mDXGL->UnregisterObject(mObjectWGL)) { + NS_WARNING("Failed to release a DXGL object, possibly leaking it."); + } + + if (mFence) { + mGL->MakeCurrent(); + mGL->fDeleteFences(1, &mFence); + } + + // mDXGL is closed when it runs out of refs. +} + +void +SharedSurface_D3D11Interop::LockProdImpl() +{ } + +void +SharedSurface_D3D11Interop::UnlockProdImpl() +{ } + +void +SharedSurface_D3D11Interop::Fence() +{ + // TODO fence properly. This kills performance. + mGL->fFinish(); +} + +bool +SharedSurface_D3D11Interop::WaitSync() +{ + return true; +} + +bool +SharedSurface_D3D11Interop::PollSync() +{ + return true; +} + +void +SharedSurface_D3D11Interop::ProducerAcquireImpl() +{ + MOZ_ASSERT(!mLockedForGL); + + if (mKeyedMutex) { + const uint64_t keyValue = 0; + const DWORD timeoutMs = 10000; + HRESULT hr = mKeyedMutex->AcquireSync(keyValue, timeoutMs); + if (hr == WAIT_TIMEOUT) { + // Doubt we should do this? Maybe Wait for ever? + MOZ_CRASH("d3d11Interop timeout"); + } + } + + // Now we have the mutex, we can lock for GL. + MOZ_ALWAYS_TRUE(mDXGL->LockObject(mObjectWGL)); + + mLockedForGL = true; +} + +void +SharedSurface_D3D11Interop::ProducerReleaseImpl() +{ + MOZ_ASSERT(mLockedForGL); + + mGL->fFlush(); + MOZ_ALWAYS_TRUE(mDXGL->UnlockObject(mObjectWGL)); + + mLockedForGL = false; + + // Now we have unlocked for GL, we can release to consumer. + if (mKeyedMutex) { + mKeyedMutex->ReleaseSync(0); + } + Fence(); +} + +void +SharedSurface_D3D11Interop::ConsumerAcquireImpl() +{ + if (!mConsumerTexture) { + RefPtr tex; + RefPtr device = gfxWindowsPlatform::GetPlatform()->GetD3D11Device(); + HRESULT hr = device->OpenSharedResource(mSharedHandle, + __uuidof(ID3D11Texture2D), + (void**)(ID3D11Texture2D**) getter_AddRefs(tex)); + if (SUCCEEDED(hr)) { + mConsumerTexture = tex; + RefPtr mutex; + hr = tex->QueryInterface((IDXGIKeyedMutex**) getter_AddRefs(mutex)); + + if (SUCCEEDED(hr)) { + mConsumerKeyedMutex = mutex; + } + } + } + + if (mConsumerKeyedMutex) { + const uint64_t keyValue = 0; + const DWORD timeoutMs = 10000; + HRESULT hr = mConsumerKeyedMutex->AcquireSync(keyValue, timeoutMs); + if (hr == WAIT_TIMEOUT) { + MOZ_CRASH(); + } + } +} + +void +SharedSurface_D3D11Interop::ConsumerReleaseImpl() +{ + if (mConsumerKeyedMutex) { + mConsumerKeyedMutex->ReleaseSync(0); + } +} + +void +SharedSurface_D3D11Interop::Fence_ContentThread_Impl() +{ + if (mFence) { + MOZ_ASSERT(mGL->IsExtensionSupported(GLContext::NV_fence)); + mGL->fSetFence(mFence, LOCAL_GL_ALL_COMPLETED_NV); + mGL->fFlush(); + return; + } + + Fence(); +} + +bool +SharedSurface_D3D11Interop::WaitSync_ContentThread_Impl() +{ + if (mFence) { + mGL->MakeCurrent(); + mGL->fFinishFence(mFence); + return true; + } + + return WaitSync(); +} + +bool +SharedSurface_D3D11Interop::PollSync_ContentThread_Impl() +{ + if (mFence) { + mGL->MakeCurrent(); + return mGL->fTestFence(mFence); + } + + return PollSync(); +} + +bool +SharedSurface_D3D11Interop::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) +{ + gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8 + : gfx::SurfaceFormat::B8G8R8X8; + *out_descriptor = layers::SurfaceDescriptorD3D10((WindowsHandle)GetSharedHandle(), + format, mSize); + return true; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// Factory + +/*static*/ UniquePtr +SurfaceFactory_D3D11Interop::Create(GLContext* gl, const SurfaceCaps& caps, + const RefPtr& allocator, + const layers::TextureFlags& flags) +{ + WGLLibrary* wgl = &sWGLLib; + if (!wgl || !wgl->HasDXInterop2()) + return nullptr; + + RefPtr dxgl = DXGLDevice::Open(wgl); + if (!dxgl) { + NS_WARNING("Failed to open D3D device for use by WGL."); + return nullptr; + } + + typedef SurfaceFactory_D3D11Interop ptrT; + UniquePtr ret(new ptrT(gl, caps, allocator, flags, dxgl)); + + return Move(ret); +} + +SurfaceFactory_D3D11Interop::SurfaceFactory_D3D11Interop(GLContext* gl, + const SurfaceCaps& caps, + const RefPtr& allocator, + const layers::TextureFlags& flags, + const RefPtr& dxgl) + : SurfaceFactory(SharedSurfaceType::DXGLInterop2, gl, caps, allocator, flags) + , mDXGL(dxgl) +{ } + +SurfaceFactory_D3D11Interop::~SurfaceFactory_D3D11Interop() +{ } + +} // namespace gl +} // namespace mozilla diff --git a/gfx/gl/SharedSurfaceD3D11Interop.h b/gfx/gl/SharedSurfaceD3D11Interop.h new file mode 100644 index 0000000000..28e5bd41ce --- /dev/null +++ b/gfx/gl/SharedSurfaceD3D11Interop.h @@ -0,0 +1,123 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 SHARED_SURFACE_D3D11_INTEROP_H_ +#define SHARED_SURFACE_D3D11_INTEROP_H_ + +#include +#include "SharedSurface.h" + +struct ID3D11Device; +struct ID3D11ShaderResourceView; + +namespace mozilla { +namespace gl { + +class DXGLDevice; +class GLContext; +class WGLLibrary; + +class SharedSurface_D3D11Interop + : public SharedSurface +{ + const GLuint mProdRB; + const RefPtr mDXGL; + const HANDLE mObjectWGL; + const HANDLE mSharedHandle; + const RefPtr mTextureD3D; + RefPtr mKeyedMutex; + RefPtr mConsumerKeyedMutex; + RefPtr mConsumerTexture; + const GLuint mFence; + +protected: + bool mLockedForGL; + +public: + static UniquePtr Create(const RefPtr& dxgl, + GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha); + + static SharedSurface_D3D11Interop* Cast(SharedSurface* surf) { + MOZ_ASSERT(surf->mType == SharedSurfaceType::DXGLInterop2); + + return (SharedSurface_D3D11Interop*)surf; + } + +protected: + SharedSurface_D3D11Interop(GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha, + GLuint renderbufferGL, + const RefPtr& dxgl, + HANDLE objectWGL, + const RefPtr& textureD3D, + HANDLE sharedHandle, + const RefPtr& keyedMutex, + GLuint fence); + +public: + virtual ~SharedSurface_D3D11Interop(); + + virtual void LockProdImpl() override; + virtual void UnlockProdImpl() override; + + virtual void Fence() override; + virtual void ProducerAcquireImpl() override; + virtual void ProducerReleaseImpl() override; + virtual void ConsumerAcquireImpl() override; + virtual void ConsumerReleaseImpl() override; + virtual bool WaitSync() override; + virtual bool PollSync() override; + + virtual void Fence_ContentThread_Impl() override; + virtual bool WaitSync_ContentThread_Impl() override; + virtual bool PollSync_ContentThread_Impl() override; + + virtual GLuint ProdRenderbuffer() override { + return mProdRB; + } + + virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override; + + // Implementation-specific functions below: + HANDLE GetSharedHandle() const { + return mSharedHandle; + } +}; + + +class SurfaceFactory_D3D11Interop + : public SurfaceFactory +{ +public: + const RefPtr mDXGL; + + static UniquePtr Create(GLContext* gl, + const SurfaceCaps& caps, + const RefPtr& allocator, + const layers::TextureFlags& flags); + +protected: + SurfaceFactory_D3D11Interop(GLContext* gl, const SurfaceCaps& caps, + const RefPtr& allocator, + const layers::TextureFlags& flags, + const RefPtr& dxgl); + +public: + virtual ~SurfaceFactory_D3D11Interop(); + +protected: + virtual UniquePtr CreateShared(const gfx::IntSize& size) override { + bool hasAlpha = mReadCaps.alpha; + return SharedSurface_D3D11Interop::Create(mDXGL, mGL, size, hasAlpha); + } +}; + +} /* namespace gl */ +} /* namespace mozilla */ + +#endif /* SHARED_SURFACE_D3D11_INTEROP_H_ */ diff --git a/gfx/gl/SharedSurfaceGL.cpp b/gfx/gl/SharedSurfaceGL.cpp index 5aa7d2cb3b..7969686dfe 100644 --- a/gfx/gl/SharedSurfaceGL.cpp +++ b/gfx/gl/SharedSurfaceGL.cpp @@ -95,6 +95,7 @@ SharedSurface_Basic::~SharedSurface_Basic() mGL->fDeleteTextures(1, &mTex); } + //////////////////////////////////////////////////////////////////////// SurfaceFactory_Basic::SurfaceFactory_Basic(GLContext* gl, const SurfaceCaps& caps, @@ -102,6 +103,88 @@ SurfaceFactory_Basic::SurfaceFactory_Basic(GLContext* gl, const SurfaceCaps& cap : SurfaceFactory(SharedSurfaceType::Basic, gl, caps, nullptr, flags) { } + +//////////////////////////////////////////////////////////////////////// +// SharedSurface_GLTexture + +/*static*/ UniquePtr +SharedSurface_GLTexture::Create(GLContext* prodGL, + const GLFormats& formats, + const IntSize& size, + bool hasAlpha) +{ + MOZ_ASSERT(prodGL); + + prodGL->MakeCurrent(); + + UniquePtr ret; + GLContext::LocalErrorScope localError(*prodGL); + + GLuint tex = CreateTextureForOffscreen(prodGL, formats, size); + + GLenum err = localError.GetError(); + MOZ_ASSERT_IF(err, err == LOCAL_GL_OUT_OF_MEMORY); + if (err) { + prodGL->fDeleteTextures(1, &tex); + return Move(ret); + } + + ret.reset(new SharedSurface_GLTexture(prodGL, size, + hasAlpha, tex)); + return Move(ret); +} + +SharedSurface_GLTexture::~SharedSurface_GLTexture() +{ + if (!mGL->MakeCurrent()) + return; + + if (mTex) { + mGL->fDeleteTextures(1, &mTex); + } + + if (mSync) { + mGL->fDeleteSync(mSync); + } +} + +void +SharedSurface_GLTexture::ProducerReleaseImpl() +{ + mGL->MakeCurrent(); + + if (mGL->IsExtensionSupported(GLContext::ARB_sync)) { + if (mSync) { + mGL->fDeleteSync(mSync); + mSync = 0; + } + + mSync = mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + if (mSync) { + mGL->fFlush(); + return; + } + } + MOZ_ASSERT(!mSync); + + mGL->fFinish(); +} + +bool +SharedSurface_GLTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) +{ + *out_descriptor = layers::SurfaceDescriptorSharedGLTexture(ProdTexture(), + ProdTextureTarget(), + (uintptr_t)mSync, + mSize, + mHasAlpha); + + // Transfer ownership of the fence to the host + mSync = nullptr; + return true; +} + + } // namespace gl } /* namespace mozilla */ diff --git a/gfx/gl/SharedSurfaceGL.h b/gfx/gl/SharedSurfaceGL.h index be3ccecfb5..eb13d141cb 100644 --- a/gfx/gl/SharedSurfaceGL.h +++ b/gfx/gl/SharedSurfaceGL.h @@ -93,6 +93,78 @@ public: } }; + +// Using shared GL textures: +class SharedSurface_GLTexture + : public SharedSurface +{ +public: + static UniquePtr Create(GLContext* prodGL, + const GLFormats& formats, + const gfx::IntSize& size, + bool hasAlpha); + + static SharedSurface_GLTexture* Cast(SharedSurface* surf) { + MOZ_ASSERT(surf->mType == SharedSurfaceType::SharedGLTexture); + + return (SharedSurface_GLTexture*)surf; + } + +protected: + const GLuint mTex; + GLsync mSync; + + SharedSurface_GLTexture(GLContext* prodGL, + const gfx::IntSize& size, + bool hasAlpha, + GLuint tex) + : SharedSurface(SharedSurfaceType::SharedGLTexture, + AttachmentType::GLTexture, + prodGL, + size, + hasAlpha, true) + , mTex(tex) + , mSync(0) + { + } + +public: + virtual ~SharedSurface_GLTexture(); + + virtual void LockProdImpl() override {} + virtual void UnlockProdImpl() override {} + + virtual void ProducerReleaseImpl() override; + + virtual void Fence() override {} + virtual bool WaitSync() override { MOZ_CRASH("should not be called"); } + virtual bool PollSync() override { MOZ_CRASH("should not be called"); } + + virtual GLuint ProdTexture() override { + return mTex; + } + + virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override; +}; + +class SurfaceFactory_GLTexture + : public SurfaceFactory +{ +public: + SurfaceFactory_GLTexture(GLContext* prodGL, + const SurfaceCaps& caps, + const RefPtr& allocator, + const layers::TextureFlags& flags) + : SurfaceFactory(SharedSurfaceType::SharedGLTexture, prodGL, caps, allocator, flags) + { + } + + virtual UniquePtr CreateShared(const gfx::IntSize& size) override { + bool hasAlpha = mReadCaps.alpha; + return SharedSurface_GLTexture::Create(mGL, mFormats, size, hasAlpha); + } +}; + } // namespace gl } /* namespace mozilla */ diff --git a/gfx/gl/SharedSurfaceIO.cpp b/gfx/gl/SharedSurfaceIO.cpp index 41c84ef1d7..2154327daf 100644 --- a/gfx/gl/SharedSurfaceIO.cpp +++ b/gfx/gl/SharedSurfaceIO.cpp @@ -55,6 +55,16 @@ SharedSurface_IOSurface::CopyTexImage2D(GLenum target, GLint level, GLenum inter if (width == 0 || height == 0) return false; + switch (internalformat) { + case LOCAL_GL_ALPHA: + case LOCAL_GL_LUMINANCE: + case LOCAL_GL_LUMINANCE_ALPHA: + break; + + default: + return false; + } + MOZ_ASSERT(mGL->IsCurrent()); ScopedTexture destTex(mGL); @@ -90,23 +100,22 @@ SharedSurface_IOSurface::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei hei // from that. MOZ_ASSERT(mGL->IsCurrent()); - ScopedTexture destTex(mGL); { ScopedFramebufferForTexture srcFB(mGL, ProdTexture(), ProdTextureTarget()); ScopedBindFramebuffer bindFB(mGL, srcFB.FB()); ScopedBindTexture bindTex(mGL, destTex.Texture()); - mGL->fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, - mHasAlpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB, - x, y, - width, height, 0); + mGL->raw_fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, + mHasAlpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB, + x, y, + width, height, 0); } ScopedFramebufferForTexture destFB(mGL, destTex.Texture()); ScopedBindFramebuffer bindFB(mGL, destFB.FB()); - mGL->fReadPixels(0, 0, width, height, format, type, pixels); + mGL->raw_fReadPixels(0, 0, width, height, format, type, pixels); return true; } diff --git a/gfx/gl/SurfaceTypes.h b/gfx/gl/SurfaceTypes.h index f4507291cd..b3b9a127ac 100644 --- a/gfx/gl/SurfaceTypes.h +++ b/gfx/gl/SurfaceTypes.h @@ -77,6 +77,7 @@ enum class SharedSurfaceType : uint8_t { Gralloc, IOSurface, GLXDrawable, + SharedGLTexture, Max }; diff --git a/gfx/gl/WGLLibrary.h b/gfx/gl/WGLLibrary.h index f26e57d50a..fb8ed73140 100644 --- a/gfx/gl/WGLLibrary.h +++ b/gfx/gl/WGLLibrary.h @@ -14,14 +14,16 @@ namespace gl { class WGLLibrary { public: - WGLLibrary() - : mInitialized(false), - mOGLLibrary(nullptr), - mHasRobustness(false), - mWindow (0), - mWindowDC(0), - mWindowGLContext(0), - mWindowPixelFormat (0) + WGLLibrary() + : mInitialized(false) + , mOGLLibrary(nullptr) + , mHasRobustness(false) + , mHasDXInterop(false) + , mHasDXInterop2(false) + , mWindow (0) + , mWindowDC(0) + , mWindowGLContext(0) + , mWindowPixelFormat(0) {} typedef HGLRC (GLAPIENTRY * PFNWGLCREATECONTEXTPROC) (HDC); @@ -62,10 +64,45 @@ public: typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSPROC) (HDC hdc, HGLRC hShareContext, const int *attribList); PFNWGLCREATECONTEXTATTRIBSPROC fCreateContextAttribs; + // WGL_NV_DX_interop: + // BOOL wglDXSetResourceShareHandleNV(void *dxObject, HANDLE shareHandle); + typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLEPROC) (void* dxObject, HANDLE shareHandle); + PFNWGLDXSETRESOURCESHAREHANDLEPROC fDXSetResourceShareHandle; + + // HANDLE wglDXOpenDeviceNV(void *dxDevice); + typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICEPROC) (void* dxDevice); + PFNWGLDXOPENDEVICEPROC fDXOpenDevice; + + // BOOL wglDXCloseDeviceNV(HANDLE hDevice); + typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICEPROC) (HANDLE hDevice); + PFNWGLDXCLOSEDEVICEPROC fDXCloseDevice; + + // HANDLE wglDXRegisterObjectNV(HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access); + typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTPROC) (HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access); + PFNWGLDXREGISTEROBJECTPROC fDXRegisterObject; + + // BOOL wglDXUnregisterObjectNV(HANDLE hDevice, HANDLE hObject); + typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECT) (HANDLE hDevice, HANDLE hObject); + PFNWGLDXUNREGISTEROBJECT fDXUnregisterObject; + + // BOOL wglDXObjectAccessNV(HANDLE hObject, GLenum access); + typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSPROC) (HANDLE hObject, GLenum access); + PFNWGLDXOBJECTACCESSPROC fDXObjectAccess; + + // BOOL wglDXLockObjectsNV(HANDLE hDevice, GLint count, HANDLE *hObjects); + typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects); + PFNWGLDXLOCKOBJECTSPROC fDXLockObjects; + + // BOOL wglDXUnlockObjectsNV(HANDLE hDevice, GLint count, HANDLE *hObjects); + typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects); + PFNWGLDXUNLOCKOBJECTSPROC fDXUnlockObjects; + bool EnsureInitialized(); HWND CreateDummyWindow(HDC *aWindowDC = nullptr); bool HasRobustness() const { return mHasRobustness; } + bool HasDXInterop() const { return mHasDXInterop; } + bool HasDXInterop2() const { return mHasDXInterop2; } bool IsInitialized() const { return mInitialized; } HWND GetWindow() const { return mWindow; } HDC GetWindowDC() const {return mWindowDC; } @@ -77,6 +114,8 @@ private: bool mInitialized; PRLibrary *mOGLLibrary; bool mHasRobustness; + bool mHasDXInterop; + bool mHasDXInterop2; HWND mWindow; HDC mWindowDC; @@ -86,8 +125,7 @@ private: }; // a global WGLLibrary instance -extern WGLLibrary sWGLLibrary; +extern WGLLibrary sWGLLib; } /* namespace gl */ } /* namespace mozilla */ - diff --git a/gfx/gl/moz.build b/gfx/gl/moz.build index 6461d5d741..1378f4e483 100644 --- a/gfx/gl/moz.build +++ b/gfx/gl/moz.build @@ -68,11 +68,13 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': EXPORTS += [ 'GLContextWGL.h', 'SharedSurfaceANGLE.h', # Needs for `HANDLE`. + 'SharedSurfaceD3D11Interop.h', 'WGLLibrary.h', ] UNIFIED_SOURCES += [ 'GLContextProviderWGL.cpp', 'SharedSurfaceANGLE.cpp', + 'SharedSurfaceD3D11Interop.cpp', ] if CONFIG['MOZ_ENABLE_SKIA_GPU']: EXPORTS += ['SkiaGLGlue.h'] diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h index 534518beb9..af1ba71fbf 100644 --- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -891,51 +891,6 @@ struct ParamTraits } }; -struct MessageAndAttributeMap -{ - Message* msg; - const mozilla::gfx::AttributeMap& map; -}; - -static bool -WriteAttribute(mozilla::gfx::AttributeName aName, - mozilla::gfx::AttributeType aType, - void* aUserData) -{ - MessageAndAttributeMap* msgAndMap = - static_cast(aUserData); - - WriteParam(msgAndMap->msg, aType); - WriteParam(msgAndMap->msg, aName); - - switch (aType) { - -#define HANDLE_TYPE(typeName) \ - case mozilla::gfx::AttributeType::e##typeName: \ - WriteParam(msgAndMap->msg, msgAndMap->map.Get##typeName(aName)); \ - break; - - HANDLE_TYPE(Bool) - HANDLE_TYPE(Uint) - HANDLE_TYPE(Float) - HANDLE_TYPE(Size) - HANDLE_TYPE(IntSize) - HANDLE_TYPE(IntPoint) - HANDLE_TYPE(Matrix) - HANDLE_TYPE(Matrix5x4) - HANDLE_TYPE(Point3D) - HANDLE_TYPE(Color) - HANDLE_TYPE(AttributeMap) - HANDLE_TYPE(Floats) - -#undef HANDLE_TYPE - - default: - MOZ_CRASH("unhandled attribute type"); - } - return true; -} - template <> struct ParamTraits { @@ -944,8 +899,41 @@ struct ParamTraits static void Write(Message* aMsg, const paramType& aParam) { WriteParam(aMsg, aParam.Count()); - MessageAndAttributeMap msgAndMap = { aMsg, aParam }; - aParam.EnumerateRead(WriteAttribute, &msgAndMap); + for (auto iter = aParam.ConstIter(); !iter.Done(); iter.Next()) { + mozilla::gfx::AttributeName name = + mozilla::gfx::AttributeName(iter.Key()); + mozilla::gfx::AttributeType type = + mozilla::gfx::AttributeMap::GetType(iter.UserData()); + + WriteParam(aMsg, type); + WriteParam(aMsg, name); + + switch (type) { + +#define CASE_TYPE(typeName) \ + case mozilla::gfx::AttributeType::e##typeName: \ + WriteParam(aMsg, aParam.Get##typeName(name)); \ + break; + + CASE_TYPE(Bool) + CASE_TYPE(Uint) + CASE_TYPE(Float) + CASE_TYPE(Size) + CASE_TYPE(IntSize) + CASE_TYPE(IntPoint) + CASE_TYPE(Matrix) + CASE_TYPE(Matrix5x4) + CASE_TYPE(Point3D) + CASE_TYPE(Color) + CASE_TYPE(AttributeMap) + CASE_TYPE(Floats) + +#undef CASE_TYPE + + default: + MOZ_CRASH("unhandled attribute type"); + } + } } static bool Read(const Message* aMsg, void** aIter, paramType* aResult) @@ -973,6 +961,7 @@ struct ParamTraits return false; \ } \ aResult->Set(name, value); \ + break; \ } HANDLE_TYPE(bool, Bool) diff --git a/gfx/layers/apz/public/GeckoContentController.h b/gfx/layers/apz/public/GeckoContentController.h index 25c4ec50ab..169c3731c4 100644 --- a/gfx/layers/apz/public/GeckoContentController.h +++ b/gfx/layers/apz/public/GeckoContentController.h @@ -74,15 +74,6 @@ public: const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) = 0; - /** - * Requests sending a mozbrowserasyncscroll domevent to embedder. - * |aContentRect| is in CSS pixels, relative to the current cssPage. - * |aScrollableSize| is the current content width/height in CSS pixels. - */ - virtual void SendAsyncScrollDOMEvent(bool aIsRootContent, - const CSSRect &aContentRect, - const CSSSize &aScrollableSize) = 0; - /** * Schedules a runnable to run on the controller/UI thread at some time * in the future. diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 66853ab04d..78d0d92ebf 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -104,14 +104,6 @@ using mozilla::gfx::PointTyped; * \li\b apz.allow_checkerboarding * Pref that allows or disallows checkerboarding * - * \li\b apz.asyncscroll.throttle - * The time period that throttles mozbrowserasyncscroll event.\n - * Units: milliseconds - * - * \li\b apz.asyncscroll.timeout - * The timeout for mAsyncScrollTimeoutTask delay task.\n - * Units: milliseconds - * * \li\b apz.axis_lock.mode * The preferred axis locking style. See AxisLockMode for possible values. * @@ -824,10 +816,6 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId, mPanDirRestricted(false), mZoomConstraints(false, false, MIN_ZOOM, MAX_ZOOM), mLastSampleTime(GetFrameTime()), - mLastAsyncScrollTime(GetFrameTime()), - mLastAsyncScrollOffset(0, 0), - mCurrentAsyncScrollOffset(0, 0), - mAsyncScrollTimeoutTask(nullptr), mState(NOTHING), mNotificationBlockers(0), mInputQueue(aInputQueue), @@ -1285,7 +1273,6 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) // events. if (mState != NOTHING) { ReentrantMonitorAutoEnter lock(mMonitor); - SendAsyncScrollEvent(); } switch (mState) { @@ -2711,7 +2698,6 @@ void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics, return; } - SendAsyncScrollEvent(); if (aThrottled) { mPaintThrottler->PostTask( FROM_HERE, @@ -2755,16 +2741,6 @@ AsyncPanZoomController::DispatchRepaintRequest(const FrameMetrics& aFrameMetrics } } -void -AsyncPanZoomController::FireAsyncScrollOnTimeout() -{ - if (mCurrentAsyncScrollOffset != mLastAsyncScrollOffset) { - ReentrantMonitorAutoEnter lock(mMonitor); - SendAsyncScrollEvent(); - } - mAsyncScrollTimeoutTask = nullptr; -} - bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime, Vector* aOutDeferredTasks) { @@ -2791,7 +2767,6 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime, } else { mAnimation = nullptr; SetState(NOTHING); - SendAsyncScrollEvent(); RequestContentRepaint(); } UpdateSharedCompositorFrameMetrics(); @@ -2870,8 +2845,6 @@ bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime) LogRendertraceRect(GetGuid(), "viewport", "red", CSSRect(mFrameMetrics.GetScrollOffset(), mFrameMetrics.CalculateCompositedSizeInCssPixels())); - - mCurrentAsyncScrollOffset = mFrameMetrics.GetScrollOffset(); } // Execute any deferred tasks queued up by mAnimation's Sample() (called by @@ -2887,32 +2860,6 @@ bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime) // we want to ask the compositor to schedule a new composite. requestAnimationFrame |= (mAnimation != nullptr); - // Cancel the mAsyncScrollTimeoutTask because we will fire a - // mozbrowserasyncscroll event or renew the mAsyncScrollTimeoutTask again. - if (mAsyncScrollTimeoutTask) { - mAsyncScrollTimeoutTask->Cancel(); - mAsyncScrollTimeoutTask = nullptr; - } - // Fire the mozbrowserasyncscroll event immediately if it's been - // sAsyncScrollThrottleTime ms since the last time we fired the event and the - // current scroll offset is different than the mLastAsyncScrollOffset we sent - // with the last event. - // Otherwise, start a timer to fire the event sAsyncScrollTimeout ms from now. - TimeDuration delta = aSampleTime - mLastAsyncScrollTime; - if (delta.ToMilliseconds() > gfxPrefs::APZAsyncScrollThrottleTime() && - mCurrentAsyncScrollOffset != mLastAsyncScrollOffset) { - ReentrantMonitorAutoEnter lock(mMonitor); - mLastAsyncScrollTime = aSampleTime; - mLastAsyncScrollOffset = mCurrentAsyncScrollOffset; - SendAsyncScrollEvent(); - } else { - mAsyncScrollTimeoutTask = - NewRunnableMethod(this, &AsyncPanZoomController::FireAsyncScrollOnTimeout); - MessageLoop::current()->PostDelayedTask(FROM_HERE, - mAsyncScrollTimeoutTask, - gfxPrefs::APZAsyncScrollTimeout()); - } - return requestAnimationFrame; } @@ -3408,27 +3355,6 @@ void AsyncPanZoomController::PostDelayedTask(Task* aTask, int aDelayMs) { } } -void AsyncPanZoomController::SendAsyncScrollEvent() { - RefPtr controller = GetGeckoContentController(); - if (!controller) { - return; - } - - bool isRootContent; - CSSRect contentRect; - CSSSize scrollableSize; - { - ReentrantMonitorAutoEnter lock(mMonitor); - - isRootContent = mFrameMetrics.IsRootContent(); - scrollableSize = mFrameMetrics.GetScrollableRect().Size(); - contentRect = mFrameMetrics.CalculateCompositedRectInCssPixels(); - contentRect.MoveTo(mCurrentAsyncScrollOffset); - } - - controller->SendAsyncScrollDOMEvent(isRootContent, contentRect, scrollableSize); -} - bool AsyncPanZoomController::Matches(const ScrollableLayerGuid& aGuid) { return aGuid == GetGuid(); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index c36db4e124..506898dd35 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -261,12 +261,6 @@ public: const ParentLayerPoint& aVelocity, double aEstimatedPaintDuration); - /** - * Send an mozbrowserasyncscroll event. - * *** The monitor must be held while calling this. - */ - void SendAsyncScrollEvent(); - nsEventStatus HandleDragEvent(const MouseInput& aEvent, const AsyncDragMetrics& aDragMetrics); @@ -617,14 +611,6 @@ protected: */ const RefPtr& GetInputQueue() const; - /** - * Timeout function for mozbrowserasyncscroll event. Because we throttle - * mozbrowserasyncscroll events in some conditions, this function ensures - * that the last mozbrowserasyncscroll event will be fired after a period of - * time. - */ - void FireAsyncScrollOnTimeout(); - /** * Convert ScreenPoint relative to the screen to CSSPoint relative * to the parent document. This excludes the transient compositor transform. @@ -731,19 +717,6 @@ private: // to allow panning by moving multiple fingers (thus moving the focus point). ParentLayerPoint mLastZoomFocus; - // The last time and offset we fire the mozbrowserasyncscroll event when - // compositor has sampled the content transform for this frame. - TimeStamp mLastAsyncScrollTime; - CSSPoint mLastAsyncScrollOffset; - - // The current offset drawn on the screen, it may not be sent since we have - // throttling policy for mozbrowserasyncscroll event. - CSSPoint mCurrentAsyncScrollOffset; - - // The delay task triggered by the throttling mozbrowserasyncscroll event - // ensures the last mozbrowserasyncscroll event is always been fired. - CancelableTask* mAsyncScrollTimeoutTask; - RefPtr mAnimation; friend class Axis; diff --git a/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp b/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp index 5aebf306cf..1071da8a9e 100644 --- a/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp @@ -67,7 +67,6 @@ public: MOCK_METHOD3(HandleDoubleTap, void(const CSSPoint&, Modifiers, const ScrollableLayerGuid&)); MOCK_METHOD3(HandleSingleTap, void(const CSSPoint&, Modifiers, const ScrollableLayerGuid&)); MOCK_METHOD4(HandleLongTap, void(const CSSPoint&, Modifiers, const ScrollableLayerGuid&, uint64_t)); - MOCK_METHOD3(SendAsyncScrollDOMEvent, void(bool aIsRoot, const CSSRect &aContentRect, const CSSSize &aScrollableSize)); MOCK_METHOD2(PostDelayedTask, void(Task* aTask, int aDelayMs)); MOCK_METHOD3(NotifyAPZStateChange, void(const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg)); MOCK_METHOD0(NotifyFlushComplete, void()); @@ -791,10 +790,8 @@ protected: MakeApzcZoomable(); if (aShouldTriggerPinch) { - EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1)); EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); } else { - EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtMost(2)); EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0); } @@ -927,7 +924,6 @@ TEST_F(APZCBasicTester, Overzoom) { MakeApzcZoomable(); - EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1)); EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); PinchWithPinchInputAndCheckStatus(apzc, 50, 50, 0.5, true); @@ -1056,10 +1052,8 @@ protected: void DoPanTest(bool aShouldTriggerScroll, bool aShouldBeConsumed, uint32_t aBehavior) { if (aShouldTriggerScroll) { - EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1)); EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); } else { - EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(0); EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0); } @@ -1169,7 +1163,6 @@ TEST_F(APZCPanningTester, PanWithPreventDefault) { } TEST_F(APZCBasicTester, Fling) { - EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1)); EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); int touchStart = 50; @@ -1591,7 +1584,6 @@ protected: void DoLongPressPreventDefaultTest(uint32_t aBehavior) { MakeApzcUnzoomable(); - EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(0); EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0); int touchX = 10, diff --git a/gfx/layers/apz/util/ChromeProcessController.h b/gfx/layers/apz/util/ChromeProcessController.h index ccfed2d1a9..906c4765e4 100644 --- a/gfx/layers/apz/util/ChromeProcessController.h +++ b/gfx/layers/apz/util/ChromeProcessController.h @@ -49,8 +49,6 @@ public: virtual void HandleLongTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers, const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) override; - virtual void SendAsyncScrollDOMEvent(bool aIsRootContent, const mozilla::CSSRect &aContentRect, - const mozilla::CSSSize &aScrollableSize) override {} virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg) override; diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index 669816da06..59253005f4 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -210,6 +210,7 @@ TextureHost::Create(const SurfaceDescriptor& aDesc, case SurfaceDescriptor::TEGLImageDescriptor: case SurfaceDescriptor::TSurfaceTextureDescriptor: + case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture: return CreateTextureHostOGL(aDesc, aDeallocator, aFlags); case SurfaceDescriptor::TNewSurfaceDescriptorGralloc: diff --git a/gfx/layers/ipc/LayersSurfaces.ipdlh b/gfx/layers/ipc/LayersSurfaces.ipdlh index 03f305c867..3a07984ed7 100644 --- a/gfx/layers/ipc/LayersSurfaces.ipdlh +++ b/gfx/layers/ipc/LayersSurfaces.ipdlh @@ -82,6 +82,14 @@ struct EGLImageDescriptor { bool hasAlpha; }; +struct SurfaceDescriptorSharedGLTexture { + uint32_t texture; + uint32_t target; + uintptr_t fence; + IntSize size; + bool hasAlpha; +}; + struct NewSurfaceDescriptorGralloc { MaybeMagicGrallocBufferHandle buffer; bool isOpaque; @@ -116,6 +124,7 @@ union SurfaceDescriptor { EGLImageDescriptor; SurfaceDescriptorMacIOSurface; NewSurfaceDescriptorGralloc; + SurfaceDescriptorSharedGLTexture; null_t; }; diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index e8f7d56409..b0bff91adf 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -104,6 +104,16 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc, break; } #endif + + case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture: { + const auto& desc = aDesc.get_SurfaceDescriptorSharedGLTexture(); + result = new GLTextureHost(aFlags, desc.texture(), + desc.target(), + (GLsync)desc.fence(), + desc.size(), + desc.hasAlpha()); + break; + } default: return nullptr; } return result.forget(); @@ -645,5 +655,76 @@ EGLImageTextureHost::GetFormat() const return mTextureSource->GetFormat(); } +// + +GLTextureHost::GLTextureHost(TextureFlags aFlags, + GLuint aTextureHandle, + GLenum aTarget, + GLsync aSync, + gfx::IntSize aSize, + bool aHasAlpha) + : TextureHost(aFlags) + , mTexture(aTextureHandle) + , mTarget(aTarget) + , mSync(aSync) + , mSize(aSize) + , mHasAlpha(aHasAlpha) + , mCompositor(nullptr) +{} + +GLTextureHost::~GLTextureHost() +{} + +gl::GLContext* +GLTextureHost::gl() const +{ + return mCompositor ? mCompositor->gl() : nullptr; +} + +bool +GLTextureHost::Lock() +{ + if (!mCompositor) { + return false; + } + + if (mSync) { + gl()->MakeCurrent(); + gl()->fWaitSync(mSync, 0, LOCAL_GL_TIMEOUT_IGNORED); + gl()->fDeleteSync(mSync); + mSync = 0; + } + + if (!mTextureSource) { + gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8 + : gfx::SurfaceFormat::R8G8B8X8; + mTextureSource = new GLTextureSource(mCompositor, + mTexture, + mTarget, + mSize, + format, + false /* owned by the client */); + } + + return true; +} +void +GLTextureHost::SetCompositor(Compositor* aCompositor) +{ + MOZ_ASSERT(aCompositor); + CompositorOGL* glCompositor = static_cast(aCompositor); + mCompositor = glCompositor; + if (mTextureSource) { + mTextureSource->SetCompositor(glCompositor); + } +} + +gfx::SurfaceFormat +GLTextureHost::GetFormat() const +{ + MOZ_ASSERT(mTextureSource); + return mTextureSource->GetFormat(); +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/opengl/TextureHostOGL.h b/gfx/layers/opengl/TextureHostOGL.h index b775e93511..efdc19a7ce 100644 --- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -278,6 +278,56 @@ protected: bool mExternallyOwned; }; +class GLTextureHost : public TextureHost +{ +public: + GLTextureHost(TextureFlags aFlags, + GLuint aTextureHandle, + GLenum aTarget, + GLsync aSync, + gfx::IntSize aSize, + bool aHasAlpha); + + virtual ~GLTextureHost(); + + // We don't own anything. + virtual void DeallocateDeviceData() override {} + + virtual void SetCompositor(Compositor* aCompositor) override; + + virtual bool Lock() override; + + virtual void Unlock() override {} + + virtual gfx::SurfaceFormat GetFormat() const override; + + virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override + { + aTexture = mTextureSource; + return !!aTexture; + } + + virtual already_AddRefed GetAsSurface() override + { + return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) + } + + gl::GLContext* gl() const; + + virtual gfx::IntSize GetSize() const override { return mSize; } + + virtual const char* Name() override { return "GLTextureHost"; } + +protected: + const GLuint mTexture; + const GLenum mTarget; + GLsync mSync; + const gfx::IntSize mSize; + const bool mHasAlpha; + RefPtr mCompositor; + RefPtr mTextureSource; +}; + //////////////////////////////////////////////////////////////////////// // SurfaceTexture diff --git a/gfx/src/FilterSupport.cpp b/gfx/src/FilterSupport.cpp index 7ada5c6b9f..3040b0e026 100644 --- a/gfx/src/FilterSupport.cpp +++ b/gfx/src/FilterSupport.cpp @@ -2047,20 +2047,13 @@ AttributeMap::~AttributeMap() { } -static PLDHashOperator -CopyAttribute(const uint32_t& aAttributeName, - Attribute* aAttribute, - void* aAttributes) -{ - typedef nsClassHashtable Map; - Map* map = static_cast(aAttributes); - map->Put(aAttributeName, new Attribute(*aAttribute)); - return PL_DHASH_NEXT; -} - AttributeMap::AttributeMap(const AttributeMap& aOther) { - aOther.mMap.EnumerateRead(CopyAttribute, &mMap); + for (auto iter = aOther.mMap.Iter(); !iter.Done(); iter.Next()) { + const uint32_t& attributeName = iter.Key(); + Attribute* attribute = iter.UserData(); + mMap.Put(attributeName, new Attribute(*attribute)); + } } AttributeMap& @@ -2068,34 +2061,15 @@ AttributeMap::operator=(const AttributeMap& aOther) { if (this != &aOther) { mMap.Clear(); - aOther.mMap.EnumerateRead(CopyAttribute, &mMap); + for (auto iter = aOther.mMap.Iter(); !iter.Done(); iter.Next()) { + const uint32_t& attributeName = iter.Key(); + Attribute* attribute = iter.UserData(); + mMap.Put(attributeName, new Attribute(*attribute)); + } } return *this; } -namespace { - struct MatchingMap { - typedef nsClassHashtable Map; - const Map& map; - bool matches; - }; -} // namespace - -static PLDHashOperator -CheckAttributeEquality(const uint32_t& aAttributeName, - Attribute* aAttribute, - void* aMatchingMap) -{ - MatchingMap& matchingMap = *static_cast(aMatchingMap); - Attribute* matchingAttribute = matchingMap.map.Get(aAttributeName); - if (!matchingAttribute || - *matchingAttribute != *aAttribute) { - matchingMap.matches = false; - return PL_DHASH_STOP; - } - return PL_DHASH_NEXT; -} - bool AttributeMap::operator==(const AttributeMap& aOther) const { @@ -2103,37 +2077,16 @@ AttributeMap::operator==(const AttributeMap& aOther) const return false; } - MatchingMap matchingMap = { mMap, true }; - aOther.mMap.EnumerateRead(CheckAttributeEquality, &matchingMap); - return matchingMap.matches; -} + for (auto iter = aOther.mMap.Iter(); !iter.Done(); iter.Next()) { + const uint32_t& attributeName = iter.Key(); + Attribute* attribute = iter.UserData(); + Attribute* matchingAttribute = mMap.Get(attributeName); + if (!matchingAttribute || *matchingAttribute != *attribute) { + return false; + } + } -namespace { - struct HandlerWithUserData - { - AttributeMap::AttributeHandleCallback handler; - void* userData; - }; -} // namespace - -static PLDHashOperator -PassAttributeToHandleCallback(const uint32_t& aAttributeName, - Attribute* aAttribute, - void* aHandlerWithUserData) -{ - HandlerWithUserData* handlerWithUserData = - static_cast(aHandlerWithUserData); - return handlerWithUserData->handler(AttributeName(aAttributeName), - aAttribute->Type(), - handlerWithUserData->userData) ? - PL_DHASH_NEXT : PL_DHASH_STOP; -} - -void -AttributeMap::EnumerateRead(AttributeMap::AttributeHandleCallback aCallback, void* aUserData) const -{ - HandlerWithUserData handlerWithUserData = { aCallback, aUserData }; - mMap.EnumerateRead(PassAttributeToHandleCallback, &handlerWithUserData); + return true; } uint32_t @@ -2142,6 +2095,18 @@ AttributeMap::Count() const return mMap.Count(); } +nsClassHashtable::Iterator +AttributeMap::ConstIter() const +{ + return mMap.ConstIter(); +} + +/* static */ AttributeType +AttributeMap::GetType(FilterAttribute* aAttribute) +{ + return aAttribute->Type(); +} + #define MAKE_ATTRIBUTE_HANDLERS_BASIC(type, typeLabel, defaultValue) \ type \ AttributeMap::Get##typeLabel(AttributeName aName) const { \ diff --git a/gfx/src/FilterSupport.h b/gfx/src/FilterSupport.h index 8b836b3c93..96a43d7cbb 100644 --- a/gfx/src/FilterSupport.h +++ b/gfx/src/FilterSupport.h @@ -221,10 +221,12 @@ public: AttributeMap GetAttributeMap(AttributeName aName) const; const nsTArray& GetFloats(AttributeName aName) const; - typedef bool (*AttributeHandleCallback)(AttributeName aName, AttributeType aType, void* aUserData); - void EnumerateRead(AttributeHandleCallback aCallback, void* aUserData) const; uint32_t Count() const; + nsClassHashtable::Iterator ConstIter() const; + + static AttributeType GetType(FilterAttribute* aAttribute); + private: mutable nsClassHashtable mMap; }; diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index a8017d3cb1..2880b79ca3 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -139,8 +139,6 @@ private: // The apz prefs are explained in AsyncPanZoomController.cpp DECL_GFX_PREF(Live, "apz.allow_checkerboarding", APZAllowCheckerboarding, bool, true); DECL_GFX_PREF(Live, "apz.allow_zooming", APZAllowZooming, bool, false); - DECL_GFX_PREF(Live, "apz.asyncscroll.throttle", APZAsyncScrollThrottleTime, int32_t, 100); - DECL_GFX_PREF(Live, "apz.asyncscroll.timeout", APZAsyncScrollTimeout, int32_t, 300); DECL_GFX_PREF(Live, "apz.axis_lock.breakout_angle", APZAxisBreakoutAngle, float, float(M_PI / 8.0) /* 22.5 degrees */); DECL_GFX_PREF(Live, "apz.axis_lock.breakout_threshold", APZAxisBreakoutThreshold, float, 1.0f / 32.0f); DECL_GFX_PREF(Live, "apz.axis_lock.direct_pan_angle", APZAllowedDirectPanAngle, float, float(M_PI / 3.0) /* 60 degrees */); @@ -411,6 +409,7 @@ private: DECL_GFX_PREF(Live, "webgl.default-no-alpha", WebGLDefaultNoAlpha, bool, false); DECL_GFX_PREF(Live, "webgl.disable-angle", WebGLDisableANGLE, bool, false); DECL_GFX_PREF(Live, "webgl.disable-extensions", WebGLDisableExtensions, bool, false); + DECL_GFX_PREF(Live, "webgl.dxgl.enabled", WebGLDXGLEnabled, bool, false); DECL_GFX_PREF(Live, "webgl.disable-fail-if-major-performance-caveat", WebGLDisableFailIfMajorPerformanceCaveat, bool, false); diff --git a/hal/HalWakeLock.cpp b/hal/HalWakeLock.cpp index 1848e09424..a4838bcf36 100644 --- a/hal/HalWakeLock.cpp +++ b/hal/HalWakeLock.cpp @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- 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/. */ @@ -54,46 +55,21 @@ WakeLockInfoFromLockCount(const nsAString& aTopic, const LockCount& aLockCount) return info; } -PLDHashOperator -CountWakeLocks(const uint64_t& aKey, LockCount aCount, void* aUserArg) +static void +CountWakeLocks(ProcessLockTable* aTable, LockCount* aTotalCount) { - MOZ_ASSERT(aUserArg); + for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) { + const uint64_t& key = iter.Key(); + LockCount count = iter.UserData(); - LockCount* totalCount = static_cast(aUserArg); - totalCount->numLocks += aCount.numLocks; - totalCount->numHidden += aCount.numHidden; + aTotalCount->numLocks += count.numLocks; + aTotalCount->numHidden += count.numHidden; - // This is linear in the number of processes, but that should be small. - if (!totalCount->processes.Contains(aKey)) { - totalCount->processes.AppendElement(aKey); - } - - return PL_DHASH_NEXT; -} - -static PLDHashOperator -RemoveChildFromList(const nsAString& aKey, nsAutoPtr& aTable, - void* aUserArg) -{ - MOZ_ASSERT(aUserArg); - - PLDHashOperator op = PL_DHASH_NEXT; - uint64_t childID = *static_cast(aUserArg); - if (aTable->Get(childID, nullptr)) { - aTable->Remove(childID); - - LockCount totalCount; - aTable->EnumerateRead(CountWakeLocks, &totalCount); - if (!totalCount.numLocks) { - op = PL_DHASH_REMOVE; - } - - if (sActiveListeners) { - NotifyWakeLockChange(WakeLockInfoFromLockCount(aKey, totalCount)); + // This is linear in the number of processes, but that should be small. + if (!aTotalCount->processes.Contains(key)) { + aTotalCount->processes.AppendElement(key); } } - - return op; } class ClearHashtableOnShutdown final : public nsIObserver { @@ -144,7 +120,25 @@ CleanupOnContentShutdown::Observe(nsISupports* aSubject, const char* aTopic, con nsresult rv = props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID); if (NS_SUCCEEDED(rv)) { - sLockTable->Enumerate(RemoveChildFromList, &childID); + for (auto iter = sLockTable->Iter(); !iter.Done(); iter.Next()) { + nsAutoPtr& table = iter.Data(); + + if (table->Get(childID, nullptr)) { + table->Remove(childID); + + LockCount totalCount; + CountWakeLocks(table, &totalCount); + + if (sActiveListeners) { + NotifyWakeLockChange(WakeLockInfoFromLockCount(iter.Key(), + totalCount)); + } + + if (totalCount.numLocks == 0) { + iter.Remove(); + } + } + } } else { NS_WARNING("ipc:content-shutdown message without childID property"); } @@ -222,7 +216,7 @@ ModifyWakeLock(const nsAString& aTopic, sLockTable->Put(aTopic, table); } else { table->Get(aProcessID, &processCount); - table->EnumerateRead(CountWakeLocks, &totalCount); + CountWakeLocks(table, &totalCount); } MOZ_ASSERT(processCount.numLocks >= processCount.numHidden); @@ -279,7 +273,7 @@ GetWakeLockInfo(const nsAString& aTopic, WakeLockInformation* aWakeLockInfo) return; } LockCount totalCount; - table->EnumerateRead(CountWakeLocks, &totalCount); + CountWakeLocks(table, &totalCount); *aWakeLockInfo = WakeLockInfoFromLockCount(aTopic, totalCount); } diff --git a/hal/moz.build b/hal/moz.build index 2181228577..4f47a80575 100644 --- a/hal/moz.build +++ b/hal/moz.build @@ -177,3 +177,6 @@ CFLAGS += CONFIG['GLIB_CFLAGS'] CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] CXXFLAGS += CONFIG['GLIB_CFLAGS'] CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wshadow'] diff --git a/image/DecodePool.cpp b/image/DecodePool.cpp index f87c26646b..2bef9777fa 100644 --- a/image/DecodePool.cpp +++ b/image/DecodePool.cpp @@ -302,7 +302,7 @@ private: DecodePool::Initialize() { MOZ_ASSERT(NS_IsMainThread()); - sNumCores = PR_GetNumberOfProcessors(); + sNumCores = max(PR_GetNumberOfProcessors(), 1); DecodePool::Singleton(); } @@ -346,6 +346,9 @@ DecodePool::DecodePool() } else { limit = static_cast(prefLimit); } + if (limit > 32) { + limit = 32; + } // Initialize the thread pool. for (uint32_t i = 0 ; i < limit ; ++i) { diff --git a/image/Downscaler.cpp b/image/Downscaler.cpp index db317c2547..ad2e469a94 100644 --- a/image/Downscaler.cpp +++ b/image/Downscaler.cpp @@ -74,8 +74,8 @@ Downscaler::BeginFrame(const nsIntSize& aOriginalSize, mFrameRect = aFrameRect.valueOr(nsIntRect(nsIntPoint(), aOriginalSize)); MOZ_ASSERT(mFrameRect.x >= 0 && mFrameRect.y >= 0 && - mFrameRect.width > 0 && mFrameRect.height > 0, - "Frame rect must have positive components"); + mFrameRect.width >= 0 && mFrameRect.height >= 0, + "Frame rect must have non-negative components"); MOZ_ASSERT(nsIntRect(0, 0, aOriginalSize.width, aOriginalSize.height) .Contains(mFrameRect), "Frame rect must fit inside image"); @@ -164,8 +164,13 @@ Downscaler::ResetForNextProgressivePass() mCurrentInLine = 0; mLinesInBuffer = 0; - // If we have a vertical offset, commit rows to shift us past it. - SkipToRow(mFrameRect.y); + if (mFrameRect.IsEmpty()) { + // Our frame rect is zero size; commit rows until the end of the image. + SkipToRow(mOriginalSize.height - 1); + } else { + // If we have a vertical offset, commit rows to shift us past it. + SkipToRow(mFrameRect.y); + } } static void diff --git a/image/Downscaler.h b/image/Downscaler.h index 907f12118a..5920aaa82f 100644 --- a/image/Downscaler.h +++ b/image/Downscaler.h @@ -83,6 +83,8 @@ public: bool aHasAlpha, bool aFlipVertically = false); + bool IsFrameComplete() const { return mCurrentInLine >= mOriginalSize.height; } + /// Retrieves the buffer into which the Decoder should write each row. uint8_t* RowBuffer() { @@ -161,6 +163,7 @@ public: return NS_ERROR_FAILURE; } + bool IsFrameComplete() const { return false; } uint8_t* RowBuffer() { return nullptr; } void ClearRow(uint32_t = 0) { } void CommitRow() { } diff --git a/image/OrientedImage.cpp b/image/OrientedImage.cpp index 7e0bc15418..91bc0abef7 100644 --- a/image/OrientedImage.cpp +++ b/image/OrientedImage.cpp @@ -343,7 +343,7 @@ OrientedImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect) } // Transform the invalidation rect into the correct orientation. - gfxMatrix matrix(OrientationMatrix(innerSize, /* aInvert = */ true)); + gfxMatrix matrix(OrientationMatrix(innerSize)); gfxRect invalidRect(matrix.TransformBounds(gfxRect(rect.x, rect.y, rect.width, rect.height))); invalidRect.RoundOut(); diff --git a/image/ProgressTracker.h b/image/ProgressTracker.h index 021d8df52f..e15e85323f 100644 --- a/image/ProgressTracker.h +++ b/image/ProgressTracker.h @@ -27,7 +27,12 @@ class AsyncNotifyRunnable; class AsyncNotifyCurrentStateRunnable; class Image; -// Image progress bitflags. +/** + * Image progress bitflags. + * + * See CheckProgressConsistency() for the invariants we enforce about the + * ordering dependencies betweeen these flags. + */ enum { FLAG_SIZE_AVAILABLE = 1u << 0, // STATUS_SIZE_AVAILABLE FLAG_DECODE_COMPLETE = 1u << 1, // STATUS_DECODE_COMPLETE diff --git a/image/RasterImage.cpp b/image/RasterImage.cpp index 5afe7a1a82..c7042c0b84 100644 --- a/image/RasterImage.cpp +++ b/image/RasterImage.cpp @@ -173,7 +173,6 @@ RasterImage::Init(const char* aMimeType, } //****************************************************************************** -// [notxpcom] void requestRefresh ([const] in TimeStamp aTime); NS_IMETHODIMP_(void) RasterImage::RequestRefresh(const TimeStamp& aTime) { @@ -297,31 +296,22 @@ RasterImage::LookupFrameInternal(uint32_t aFrameNum, return mAnim->GetCompositedFrame(aFrameNum); } - Maybe alternateFlags; - if (IsOpaque()) { - // If we're opaque, we can always substitute a frame that was decoded with a - // different decode flag for premultiplied alpha, because that can only - // matter for frames with transparency. - alternateFlags.emplace(ToSurfaceFlags(aFlags) ^ - SurfaceFlags::NO_PREMULTIPLY_ALPHA); - } + SurfaceFlags surfaceFlags = ToSurfaceFlags(aFlags); - // We don't want any substitution for sync decodes (except the premultiplied - // alpha optimization above), so we use SurfaceCache::Lookup in this case. + // We don't want any substitution for sync decodes, so we use + // SurfaceCache::Lookup in this case. if (aFlags & FLAG_SYNC_DECODE) { return SurfaceCache::Lookup(ImageKey(this), RasterSurfaceKey(aSize, - ToSurfaceFlags(aFlags), - aFrameNum), - alternateFlags); + surfaceFlags, + aFrameNum)); } // We'll return the best match we can find to the requested frame. return SurfaceCache::LookupBestMatch(ImageKey(this), RasterSurfaceKey(aSize, - ToSurfaceFlags(aFlags), - aFrameNum), - alternateFlags); + surfaceFlags, + aFrameNum)); } DrawableFrameRef @@ -331,6 +321,12 @@ RasterImage::LookupFrame(uint32_t aFrameNum, { MOZ_ASSERT(NS_IsMainThread()); + // If we're opaque, we don't need to care about premultiplied alpha, because + // that can only matter for frames with transparency. + if (IsOpaque()) { + aFlags &= ~FLAG_DECODE_NO_PREMULTIPLY_ALPHA; + } + IntSize requestedSize = CanDownscaleDuringDecode(aSize, aFlags) ? aSize : mSize; if (requestedSize.IsEmpty()) { @@ -559,8 +555,6 @@ RasterImage::CopyFrame(uint32_t aWhichFrame, uint32_t aFlags) } //****************************************************************************** -/* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame, - * in uint32_t aFlags); */ NS_IMETHODIMP_(already_AddRefed) RasterImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) @@ -823,14 +817,14 @@ RasterImage::OnAddedFrame(uint32_t aNewFrameCount, } } -void +bool RasterImage::SetMetadata(const ImageMetadata& aMetadata, bool aFromMetadataDecode) { MOZ_ASSERT(NS_IsMainThread()); if (mError) { - return; + return true; } if (aMetadata.HasSize()) { @@ -838,7 +832,7 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata, if (size.width < 0 || size.height < 0) { NS_WARNING("Image has negative intrinsic size"); DoError(); - return; + return true; } MOZ_ASSERT(aMetadata.HasOrientation()); @@ -849,7 +843,7 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata, NS_WARNING("Image changed size or orientation on redecode! " "This should not happen!"); DoError(); - return; + return true; } // Set the size and flag that we have it. @@ -871,7 +865,7 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata, // discovered that it actually was during the full decode. This is a // rare failure that only occurs for corrupt images. To recover, we need // to discard all existing surfaces and redecode. - RecoverFromInvalidFrames(mSize, DECODE_FLAGS_DEFAULT); + return false; } } @@ -893,6 +887,8 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata, Set("hotspotX", intwrapx); Set("hotspotY", intwrapy); } + + return true; } NS_IMETHODIMP @@ -986,7 +982,6 @@ RasterImage::ResetAnimation() } //****************************************************************************** -// [notxpcom] void setAnimationStartTime ([const] in TimeStamp aTime); NS_IMETHODIMP_(void) RasterImage::SetAnimationStartTime(const TimeStamp& aTime) { @@ -1294,17 +1289,24 @@ RasterImage::Decode(const IntSize& aSize, uint32_t aFlags) decoderFlags |= DecoderFlags::IS_REDECODE; } + SurfaceFlags surfaceFlags = ToSurfaceFlags(aFlags); + if (IsOpaque()) { + // If there's no transparency, it doesn't matter whether we premultiply + // alpha or not. + surfaceFlags &= ~SurfaceFlags::NO_PREMULTIPLY_ALPHA; + } + // Create a decoder. RefPtr decoder; if (mAnim) { decoder = DecoderFactory::CreateAnimationDecoder(mDecoderType, this, mSourceBuffer, decoderFlags, - ToSurfaceFlags(aFlags), + surfaceFlags, mRequestedResolution); } else { decoder = DecoderFactory::CreateDecoder(mDecoderType, this, mSourceBuffer, targetSize, decoderFlags, - ToSurfaceFlags(aFlags), + surfaceFlags, mRequestedSampleSize, mRequestedResolution); } @@ -1478,15 +1480,6 @@ RasterImage::DrawInternal(DrawableFrameRef&& aFrameRef, } //****************************************************************************** -/* [noscript] void draw(in gfxContext aContext, - * in Filter aFilter, - * [const] in gfxMatrix aUserSpaceToImageSpace, - * [const] in gfxRect aFill, - * [const] in IntRect aSubimage, - * [const] in IntSize aViewportSize, - * [const] in SVGImageContext aSVGContext, - * in uint32_t aWhichFrame, - * in uint32_t aFlags); */ NS_IMETHODIMP_(DrawResult) RasterImage::Draw(gfxContext* aContext, const IntSize& aSize, @@ -1724,7 +1717,18 @@ RasterImage::FinalizeDecoder(Decoder* aDecoder) } // Record all the metadata the decoder gathered about this image. - SetMetadata(aDecoder->GetImageMetadata(), wasMetadata); + bool metadataOK = SetMetadata(aDecoder->GetImageMetadata(), wasMetadata); + if (!metadataOK) { + // This indicates a serious error that requires us to discard all existing + // surfaces and redecode to recover. We'll drop the results from this + // decoder on the floor, since they aren't valid. + aDecoder->TakeProgress(); + aDecoder->TakeInvalidRect(); + RecoverFromInvalidFrames(mSize, + FromSurfaceFlags(aDecoder->GetSurfaceFlags())); + return; + } + MOZ_ASSERT(mError || mHasSize || !aDecoder->HasSize(), "SetMetadata should've gotten a size"); diff --git a/image/RasterImage.h b/image/RasterImage.h index d9ad282625..a92d75f418 100644 --- a/image/RasterImage.h +++ b/image/RasterImage.h @@ -324,8 +324,11 @@ private: * @param aMetadata The metadata to set on this image. * @param aFromMetadataDecode True if this metadata came from a metadata * decode; false if it came from a full decode. + * @return |true| unless a catastrophic failure was discovered. If |false| is + * returned, it indicates that the image is corrupt in a way that requires all + * surfaces to be discarded to recover. */ - void SetMetadata(const ImageMetadata& aMetadata, bool aFromMetadataDecode); + bool SetMetadata(const ImageMetadata& aMetadata, bool aFromMetadataDecode); /** * In catastrophic circumstances like a GPU driver crash, the contents of our diff --git a/image/SVGDocumentWrapper.cpp b/image/SVGDocumentWrapper.cpp index 345c0d8f22..633e837513 100644 --- a/image/SVGDocumentWrapper.cpp +++ b/image/SVGDocumentWrapper.cpp @@ -200,9 +200,6 @@ SVGDocumentWrapper::TickRefreshDriver() /** nsIStreamListener methods **/ -/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, - in nsIInputStream inStr, in unsigned long sourceOffset, - in unsigned long count); */ NS_IMETHODIMP SVGDocumentWrapper::OnDataAvailable(nsIRequest* aRequest, nsISupports* ctxt, nsIInputStream* inStr, @@ -236,8 +233,6 @@ SVGDocumentWrapper::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt) } -/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, - in nsresult status); */ NS_IMETHODIMP SVGDocumentWrapper::OnStopRequest(nsIRequest* aRequest, nsISupports* ctxt, nsresult status) diff --git a/image/SurfaceCache.cpp b/image/SurfaceCache.cpp index 8791cc0dfa..c6fce6ada9 100644 --- a/image/SurfaceCache.cpp +++ b/image/SurfaceCache.cpp @@ -275,8 +275,7 @@ public: } Pair, MatchType> - LookupBestMatch(const SurfaceKey& aSurfaceKey, - const Maybe& aAlternateFlags) + LookupBestMatch(const SurfaceKey& aSurfaceKey) { // Try for an exact match first. RefPtr exactMatch; @@ -286,15 +285,74 @@ public: } // There's no perfect match, so find the best match we can. - MatchContext matchContext(aSurfaceKey, aAlternateFlags); - ForEach(TryToImproveMatch, &matchContext); + RefPtr bestMatch; + for (auto iter = ConstIter(); !iter.Done(); iter.Next()) { + CachedSurface* surface = iter.UserData(); + const SurfaceKey& idealKey = aSurfaceKey; + + // We never match a placeholder. + if (surface->IsPlaceholder()) { + continue; + } + // Matching the animation time and SVG context is required. + if (aSurfaceKey.AnimationTime() != idealKey.AnimationTime() || + aSurfaceKey.SVGContext() != idealKey.SVGContext()) { + continue; + } + // Matching the flags is required. + if (aSurfaceKey.Flags() != idealKey.Flags()) { + continue; + } + // Anything is better than nothing! (Within the constraints we just + // checked, of course.) + if (!bestMatch) { + bestMatch = surface; + continue; + } + + MOZ_ASSERT(bestMatch, "Should have a current best match"); + + // Always prefer completely decoded surfaces. + bool bestMatchIsDecoded = bestMatch->IsDecoded(); + if (bestMatchIsDecoded && !surface->IsDecoded()) { + continue; + } + if (!bestMatchIsDecoded && surface->IsDecoded()) { + bestMatch = surface; + continue; + } + + SurfaceKey bestMatchKey = bestMatch->GetSurfaceKey(); + + // Compare sizes. We use an area-based heuristic here instead of computing a + // truly optimal answer, since it seems very unlikely to make a difference + // for realistic sizes. + int64_t idealArea = idealKey.Size().width * idealKey.Size().height; + int64_t surfaceArea = aSurfaceKey.Size().width * aSurfaceKey.Size().height; + int64_t bestMatchArea = + bestMatchKey.Size().width * bestMatchKey.Size().height; + + // If the best match is smaller than the ideal size, prefer bigger sizes. + if (bestMatchArea < idealArea) { + if (surfaceArea > bestMatchArea) { + bestMatch = surface; + } + continue; + } + // Other, prefer sizes closer to the ideal size, but still not smaller. + if (idealArea <= surfaceArea && surfaceArea < bestMatchArea) { + bestMatch = surface; + continue; + } + // This surface isn't an improvement over the current best match. + } MatchType matchType; - if (matchContext.mBestMatch) { + if (bestMatch) { if (!exactMatch) { // No exact match, but we found a substitute. matchType = MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND; - } else if (exactMatch != matchContext.mBestMatch) { + } else if (exactMatch != bestMatch) { // The exact match is still decoding, but we found a substitute. matchType = MatchType::SUBSTITUTE_BECAUSE_PENDING; } else { @@ -303,8 +361,7 @@ public: } } else { if (exactMatch) { - // We found an "exact match", but since TryToImproveMatch didn't return - // it, it must have been a placeholder. + // We found an "exact match", it must have been a placeholder. MOZ_ASSERT(exactMatch->IsPlaceholder()); matchType = MatchType::PENDING; } else { @@ -313,103 +370,18 @@ public: } } - return MakePair(matchContext.mBestMatch.forget(), matchType); + return MakePair(bestMatch.forget(), matchType); } - void ForEach(SurfaceTable::EnumReadFunction aFunction, void* aData) + SurfaceTable::Iterator ConstIter() const { - mSurfaces.EnumerateRead(aFunction, aData); + return mSurfaces.ConstIter(); } void SetLocked(bool aLocked) { mLocked = aLocked; } bool IsLocked() const { return mLocked; } private: - struct MatchContext - { - MatchContext(const SurfaceKey& aIdealKey, - const Maybe& aAlternateFlags) - : mIdealKey(aIdealKey) - , mAlternateFlags(aAlternateFlags) - { } - - const SurfaceKey& mIdealKey; - const Maybe mAlternateFlags; - RefPtr mBestMatch; - }; - - static PLDHashOperator TryToImproveMatch(const SurfaceKey& aSurfaceKey, - CachedSurface* aSurface, - void* aContext) - { - auto context = static_cast(aContext); - const SurfaceKey& idealKey = context->mIdealKey; - - // We never match a placeholder. - if (aSurface->IsPlaceholder()) { - return PL_DHASH_NEXT; - } - - // Matching the animation time and SVG context is required. - if (aSurfaceKey.AnimationTime() != idealKey.AnimationTime() || - aSurfaceKey.SVGContext() != idealKey.SVGContext()) { - return PL_DHASH_NEXT; - } - - // Matching the flags is required, but we can match the alternate flags as - // well if some were provided. - if (aSurfaceKey.Flags() != idealKey.Flags() && - Some(aSurfaceKey.Flags()) != context->mAlternateFlags) { - return PL_DHASH_NEXT; - } - - // Anything is better than nothing! (Within the constraints we just - // checked, of course.) - if (!context->mBestMatch) { - context->mBestMatch = aSurface; - return PL_DHASH_NEXT; - } - - MOZ_ASSERT(context->mBestMatch, "Should have a current best match"); - - // Always prefer completely decoded surfaces. - bool bestMatchIsDecoded = context->mBestMatch->IsDecoded(); - if (bestMatchIsDecoded && !aSurface->IsDecoded()) { - return PL_DHASH_NEXT; - } - if (!bestMatchIsDecoded && aSurface->IsDecoded()) { - context->mBestMatch = aSurface; - return PL_DHASH_NEXT; - } - - SurfaceKey bestMatchKey = context->mBestMatch->GetSurfaceKey(); - - // Compare sizes. We use an area-based heuristic here instead of computing a - // truly optimal answer, since it seems very unlikely to make a difference - // for realistic sizes. - int64_t idealArea = idealKey.Size().width * idealKey.Size().height; - int64_t surfaceArea = aSurfaceKey.Size().width * aSurfaceKey.Size().height; - int64_t bestMatchArea = - bestMatchKey.Size().width * bestMatchKey.Size().height; - - // If the best match is smaller than the ideal size, prefer bigger sizes. - if (bestMatchArea < idealArea) { - if (surfaceArea > bestMatchArea) { - context->mBestMatch = aSurface; - } - return PL_DHASH_NEXT; - } - - // Other, prefer sizes closer to the ideal size, but still not smaller. - if (idealArea <= surfaceArea && surfaceArea < bestMatchArea) { - context->mBestMatch = aSurface; - return PL_DHASH_NEXT; - } - - // This surface isn't an improvement over the current best match. - return PL_DHASH_NEXT; - } - SurfaceTable mSurfaces; bool mLocked; }; @@ -635,8 +607,7 @@ public: } LookupResult LookupBestMatch(const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey, - const Maybe& aAlternateFlags) + const SurfaceKey& aSurfaceKey) { RefPtr cache = GetImageCache(aImageKey); if (!cache) { @@ -654,8 +625,7 @@ public: DrawableFrameRef ref; MatchType matchType = MatchType::NOT_FOUND; while (true) { - Tie(surface, matchType) = - cache->LookupBestMatch(aSurfaceKey, aAlternateFlags); + Tie(surface, matchType) = cache->LookupBestMatch(aSurfaceKey); if (!surface) { return LookupResult(matchType); // Lookup in the per-image cache missed. @@ -671,12 +641,13 @@ public: Remove(surface); } - MOZ_ASSERT((matchType == MatchType::EXACT) == - (surface->GetSurfaceKey() == aSurfaceKey || - (aAlternateFlags && - surface->GetSurfaceKey() == - aSurfaceKey.WithNewFlags(*aAlternateFlags))), - "Result differs in a way other than size or alternate flags"); + MOZ_ASSERT_IF(matchType == MatchType::EXACT, + surface->GetSurfaceKey() == aSurfaceKey); + MOZ_ASSERT_IF(matchType == MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND || + matchType == MatchType::SUBSTITUTE_BECAUSE_PENDING, + surface->GetSurfaceKey().SVGContext() == aSurfaceKey.SVGContext() && + surface->GetSurfaceKey().AnimationTime() == aSurfaceKey.AnimationTime() && + surface->GetSurfaceKey().Flags() == aSurfaceKey.Flags()); if (matchType == MatchType::EXACT) { MarkUsed(surface, cache); @@ -728,9 +699,7 @@ public: } cache->SetLocked(false); - - // Unlock all the surfaces the per-image cache is holding. - cache->ForEach(DoUnlockSurface, this); + DoUnlockSurfaces(cache); } void UnlockSurfaces(const ImageKey aImageKey) @@ -742,9 +711,7 @@ public: // (Note that we *don't* unlock the per-image cache here; that's the // difference between this and UnlockImage.) - - // Unlock all the surfaces the per-image cache is holding. - cache->ForEach(DoUnlockSurface, this); + DoUnlockSurfaces(cache); } void RemoveImage(const ImageKey aImageKey) @@ -759,7 +726,9 @@ public: // removing an element from the costs array. Since n is expected to be // small, performance should be good, but if usage patterns change we should // change the data structure used for mCosts. - cache->ForEach(DoStopTracking, this); + for (auto iter = cache->ConstIter(); !iter.Done(); iter.Next()) { + StopTracking(iter.UserData()); + } // The per-image cache isn't needed anymore, so remove it as well. // This implicitly unlocks the image if it was locked. @@ -815,31 +784,6 @@ public: StartTracking(aSurface); } - static PLDHashOperator DoStopTracking(const SurfaceKey&, - CachedSurface* aSurface, - void* aCache) - { - static_cast(aCache)->StopTracking(aSurface); - return PL_DHASH_NEXT; - } - - static PLDHashOperator DoUnlockSurface(const SurfaceKey&, - CachedSurface* aSurface, - void* aCache) - { - if (aSurface->IsPlaceholder() || !aSurface->IsLocked()) { - return PL_DHASH_NEXT; - } - - auto cache = static_cast(aCache); - cache->StopTracking(aSurface); - - aSurface->SetLocked(false); - cache->StartTracking(aSurface); - - return PL_DHASH_NEXT; - } - NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData, @@ -888,16 +832,9 @@ public: // Report all surfaces in the per-image cache. CachedSurface::SurfaceMemoryReport report(aCounters, aMallocSizeOf); - cache->ForEach(DoCollectSizeOfSurface, &report); - } - - static PLDHashOperator DoCollectSizeOfSurface(const SurfaceKey&, - CachedSurface* aSurface, - void* aReport) - { - auto report = static_cast(aReport); - report->Add(aSurface); - return PL_DHASH_NEXT; + for (auto iter = cache->ConstIter(); !iter.Done(); iter.Next()) { + report.Add(iter.UserData()); + } } private: @@ -927,6 +864,20 @@ private: } } + void DoUnlockSurfaces(ImageSurfaceCache* aCache) + { + // Unlock all the surfaces the per-image cache is holding. + for (auto iter = aCache->ConstIter(); !iter.Done(); iter.Next()) { + CachedSurface* surface = iter.UserData(); + if (surface->IsPlaceholder() || !surface->IsLocked()) { + continue; + } + StopTracking(surface); + surface->SetLocked(false); + StartTracking(surface); + } + } + struct SurfaceTracker : public nsExpirationTracker { explicit SurfaceTracker(uint32_t aSurfaceCacheExpirationTimeMS) @@ -1049,37 +1000,26 @@ SurfaceCache::Shutdown() /* static */ LookupResult SurfaceCache::Lookup(const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey, - const Maybe& aAlternateFlags - /* = Nothing() */) + const SurfaceKey& aSurfaceKey) { if (!sInstance) { return LookupResult(MatchType::NOT_FOUND); } MutexAutoLock lock(sInstance->GetMutex()); - - LookupResult result = sInstance->Lookup(aImageKey, aSurfaceKey); - if (!result && aAlternateFlags) { - result = sInstance->Lookup(aImageKey, - aSurfaceKey.WithNewFlags(*aAlternateFlags)); - } - - return result; + return sInstance->Lookup(aImageKey, aSurfaceKey); } /* static */ LookupResult SurfaceCache::LookupBestMatch(const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey, - const Maybe& aAlternateFlags - /* = Nothing() */) + const SurfaceKey& aSurfaceKey) { if (!sInstance) { return LookupResult(MatchType::NOT_FOUND); } MutexAutoLock lock(sInstance->GetMutex()); - return sInstance->LookupBestMatch(aImageKey, aSurfaceKey, aAlternateFlags); + return sInstance->LookupBestMatch(aImageKey, aSurfaceKey); } /* static */ InsertOutcome diff --git a/image/SurfaceCache.h b/image/SurfaceCache.h index b8f8f8f346..d6fafa48b0 100644 --- a/image/SurfaceCache.h +++ b/image/SurfaceCache.h @@ -69,11 +69,6 @@ public: float AnimationTime() const { return mAnimationTime; } SurfaceFlags Flags() const { return mFlags; } - SurfaceKey WithNewFlags(SurfaceFlags aFlags) const - { - return SurfaceKey(mSize, mSVGContext, mAnimationTime, aFlags); - } - private: SurfaceKey(const IntSize& aSize, const Maybe& aSVGContext, @@ -181,38 +176,25 @@ struct SurfaceCache * @param aSurfaceKey Key data which uniquely identifies the requested * surface. * - * @param aAlternateFlags If not Nothing(), a different set of flags than the - * ones specified in @aSurfaceKey which are also - * acceptable to the caller. This is more efficient - * than calling Lookup() twice, which requires taking a - * lock each time. - * * @return a LookupResult, which will either contain a * DrawableFrameRef to the requested surface, or an * empty DrawableFrameRef if the surface was not found. */ static LookupResult Lookup(const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey, - const Maybe& aAlternateFlags - = Nothing()); + const SurfaceKey& aSurfaceKey); /** * Looks up the best matching surface in the cache and returns a drawable * reference to the imgFrame containing it. * * Returned surfaces may vary from the requested surface only in terms of - * size, unless @aAlternateFlags is specified. + * size. * * @param aImageKey Key data identifying which image the surface belongs * to. * * @param aSurfaceKey Key data which identifies the ideal surface to return. * - * @param aAlternateFlags If not Nothing(), a different set of flags than the - * ones specified in @aSurfaceKey which are also - * acceptable to the caller. This is much more - * efficient than calling LookupBestMatch() twice. - * * @return a LookupResult, which will either contain a * DrawableFrameRef to a surface similar to the * requested surface, or an empty DrawableFrameRef if @@ -221,9 +203,7 @@ struct SurfaceCache * returned surface exactly matches @aSurfaceKey. */ static LookupResult LookupBestMatch(const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey, - const Maybe& aAlternateFlags - = Nothing()); + const SurfaceKey& aSurfaceKey); /** * Insert a surface into the cache. If a surface with the same ImageKey and diff --git a/image/SurfaceFlags.h b/image/SurfaceFlags.h index ac1c5e6646..1a0000542f 100644 --- a/image/SurfaceFlags.h +++ b/image/SurfaceFlags.h @@ -50,6 +50,23 @@ ToSurfaceFlags(uint32_t aFlags) return flags; } +/** + * Given a set of SurfaceFlags, returns a set of imgIContainer FLAG_* flags with + * the corresponding flags set. + */ +inline uint32_t +FromSurfaceFlags(SurfaceFlags aFlags) +{ + uint32_t flags = imgIContainer::DECODE_FLAGS_DEFAULT; + if (aFlags & SurfaceFlags::NO_PREMULTIPLY_ALPHA) { + flags |= imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA; + } + if (aFlags & SurfaceFlags::NO_COLORSPACE_CONVERSION) { + flags |= imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION; + } + return flags; +} + } // namespace image } // namespace mozilla diff --git a/image/VectorImage.cpp b/image/VectorImage.cpp index 3d8ca81256..7b96514582 100644 --- a/image/VectorImage.cpp +++ b/image/VectorImage.cpp @@ -683,8 +683,6 @@ VectorImage::IsOpaque() } //****************************************************************************** -/* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame, - * in uint32_t aFlags; */ NS_IMETHODIMP_(already_AddRefed) VectorImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) { @@ -793,13 +791,6 @@ struct SVGDrawingParameters }; //****************************************************************************** -/* [noscript] void draw(in gfxContext aContext, - * [const] in nsIntSize aSize, - * [const] in ImageRegion aRegion, - * in uint32_t aWhichFrame, - * in Filter aFilter, - * [const] in MaybeSVGImageContext aSVGContext, - * in uint32_t aFlags); */ NS_IMETHODIMP_(DrawResult) VectorImage::Draw(gfxContext* aContext, const nsIntSize& aSize, @@ -1125,8 +1116,6 @@ VectorImage::OnStartRequest(nsIRequest* aRequest, nsISupports* aCtxt) } //****************************************************************************** -/* void onStopRequest(in nsIRequest request, in nsISupports ctxt, - in nsresult status); */ NS_IMETHODIMP VectorImage::OnStopRequest(nsIRequest* aRequest, nsISupports* aCtxt, nsresult aStatus) @@ -1219,9 +1208,7 @@ VectorImage::OnSVGDocumentError() if (mProgressTracker) { // Notify observers about the error and unblock page load. - Progress progress = FLAG_DECODE_COMPLETE | - FLAG_ONLOAD_UNBLOCKED | - FLAG_HAS_ERROR; + Progress progress = FLAG_ONLOAD_UNBLOCKED | FLAG_HAS_ERROR; // Merge in any saved progress from OnImageDataComplete. if (mLoadProgress) { @@ -1237,9 +1224,6 @@ VectorImage::OnSVGDocumentError() // nsIStreamListener method //****************************************************************************** -/* void onDataAvailable(in nsIRequest request, in nsISupports ctxt, - in nsIInputStream inStr, in unsigned long sourceOffset, - in unsigned long count); */ NS_IMETHODIMP VectorImage::OnDataAvailable(nsIRequest* aRequest, nsISupports* aCtxt, nsIInputStream* aInStr, uint64_t aSourceOffset, diff --git a/image/decoders/nsGIFDecoder2.cpp b/image/decoders/nsGIFDecoder2.cpp index 2f382cfbca..bb3a117901 100644 --- a/image/decoders/nsGIFDecoder2.cpp +++ b/image/decoders/nsGIFDecoder2.cpp @@ -207,7 +207,7 @@ nsGIFDecoder2::BeginGIF() } bool -nsGIFDecoder2::CheckForTransparency(IntRect aFrameRect) +nsGIFDecoder2::CheckForTransparency(const IntRect& aFrameRect) { // Check if the image has a transparent color in its palette. if (mGIFStruct.is_transparent) { @@ -231,6 +231,22 @@ nsGIFDecoder2::CheckForTransparency(IntRect aFrameRect) return false; } +IntRect +nsGIFDecoder2::ClampToImageRect(const IntRect& aRect) +{ + IntRect imageRect(0, 0, mGIFStruct.screen_width, mGIFStruct.screen_height); + IntRect visibleFrameRect = aRect.Intersect(imageRect); + + // If there's no intersection, |visibleFrameRect| will be an empty rect + // positioned at the maximum of |imageRect|'s and |aRect|'s coordinates, which + // is not what we want. Force it to (0, 0) in that case. + if (visibleFrameRect.IsEmpty()) { + visibleFrameRect.MoveTo(0, 0); + } + + return visibleFrameRect; +} + //****************************************************************************** nsresult nsGIFDecoder2::BeginImageFrame(uint16_t aDepth) @@ -275,8 +291,8 @@ nsGIFDecoder2::BeginImageFrame(uint16_t aDepth) } if (mDownscaler) { - rv = mDownscaler->BeginFrame(GetSize(), Some(frameRect), mImageData, - hasTransparency); + rv = mDownscaler->BeginFrame(GetSize(), Some(ClampToImageRect(frameRect)), + mImageData, hasTransparency); } return rv; @@ -487,6 +503,9 @@ nsGIFDecoder2::DoLzw(const uint8_t* q) if (!mGIFStruct.rows_remaining) { return true; } + if (MOZ_UNLIKELY(mDownscaler && mDownscaler->IsFrameComplete())) { + return true; + } // Copy all the decoder state variables into locals so the compiler // won't worry about them being aliased. The locals will be homed @@ -543,6 +562,10 @@ nsGIFDecoder2::DoLzw(const uint8_t* q) return (mGIFStruct.rows_remaining == 0); } + if (MOZ_UNLIKELY(mDownscaler && mDownscaler->IsFrameComplete())) { + goto END; + } + if (oldcode == -1) { if (code >= MAX_BITS) { return false; diff --git a/image/decoders/nsGIFDecoder2.h b/image/decoders/nsGIFDecoder2.h index 952c6015a6..a73102a157 100644 --- a/image/decoders/nsGIFDecoder2.h +++ b/image/decoders/nsGIFDecoder2.h @@ -50,7 +50,8 @@ private: bool DoLzw(const uint8_t* q); bool SetHold(const uint8_t* buf, uint32_t count, const uint8_t* buf2 = nullptr, uint32_t count2 = 0); - bool CheckForTransparency(gfx::IntRect aFrameRect); + bool CheckForTransparency(const gfx::IntRect& aFrameRect); + gfx::IntRect ClampToImageRect(const gfx::IntRect& aFrameRect); inline int ClearCode() const { return 1 << mGIFStruct.datasize; } diff --git a/image/encoders/jpeg/nsJPEGEncoder.cpp b/image/encoders/jpeg/nsJPEGEncoder.cpp index b110a2abec..4eca8de5e6 100644 --- a/image/encoders/jpeg/nsJPEGEncoder.cpp +++ b/image/encoders/jpeg/nsJPEGEncoder.cpp @@ -268,8 +268,6 @@ nsJPEGEncoder::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval); } -/* [noscript] unsigned long readSegments (in nsWriteSegmentFun aWriter, in - voidPtr aClosure, in unsigned long aCount); */ NS_IMETHODIMP nsJPEGEncoder::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount, uint32_t* _retval) diff --git a/image/encoders/png/nsPNGEncoder.cpp b/image/encoders/png/nsPNGEncoder.cpp index 34b4c11eee..4101463172 100644 --- a/image/encoders/png/nsPNGEncoder.cpp +++ b/image/encoders/png/nsPNGEncoder.cpp @@ -544,17 +544,12 @@ nsPNGEncoder::Available(uint64_t* _retval) return NS_OK; } -/* [noscript] unsigned long read (in charPtr aBuf, - in unsigned long aCount); */ NS_IMETHODIMP nsPNGEncoder::Read(char* aBuf, uint32_t aCount, uint32_t* _retval) { return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval); } -/* [noscript] unsigned long readSegments (in nsWriteSegmentFun aWriter, - in voidPtr aClosure, - in unsigned long aCount); */ NS_IMETHODIMP nsPNGEncoder::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount, diff --git a/image/imgLoader.cpp b/image/imgLoader.cpp index 18f3d60715..cdb29a82a1 100644 --- a/image/imgLoader.cpp +++ b/image/imgLoader.cpp @@ -76,8 +76,16 @@ public: nsTArray uncached; for (uint32_t i = 0; i < mKnownLoaders.Length(); i++) { - mKnownLoaders[i]->mChromeCache.EnumerateRead(DoRecordCounter, &chrome); - mKnownLoaders[i]->mCache.EnumerateRead(DoRecordCounter, &content); + for (auto iter = mKnownLoaders[i]->mChromeCache.Iter(); !iter.Done(); iter.Next()) { + imgCacheEntry* entry = iter.UserData(); + RefPtr req = entry->GetRequest(); + RecordCounterForRequest(req, &chrome, !entry->HasNoProxies()); + } + for (auto iter = mKnownLoaders[i]->mCache.Iter(); !iter.Done(); iter.Next()) { + imgCacheEntry* entry = iter.UserData(); + RefPtr req = entry->GetRequest(); + RecordCounterForRequest(req, &content, !entry->HasNoProxies()); + } MutexAutoLock lock(mKnownLoaders[i]->mUncachedImagesMutex); for (auto iter = mKnownLoaders[i]->mUncachedImages.Iter(); !iter.Done(); @@ -110,8 +118,29 @@ public: size_t n = 0; for (uint32_t i = 0; i < imgLoader::sMemReporter->mKnownLoaders.Length(); i++) { - imgLoader::sMemReporter->mKnownLoaders[i]-> - mCache.EnumerateRead(DoRecordCounterUsedDecoded, &n); + for (auto iter = imgLoader::sMemReporter->mKnownLoaders[i]->mCache.Iter(); + !iter.Done(); + iter.Next()) { + imgCacheEntry* entry = iter.UserData(); + if (entry->HasNoProxies()) { + continue; + } + + RefPtr req = entry->GetRequest(); + RefPtr image = req->GetImage(); + if (!image) { + continue; + } + + // Both this and EntryImageSizes measure images/content/raster/used/decoded + // memory. This function's measurement is secondary -- the result doesn't + // go in the "explicit" tree -- so we use moz_malloc_size_of instead of + // ImagesMallocSizeOf to prevent DMD from seeing it reported twice. + ImageMemoryCounter counter(image, moz_malloc_size_of, /* aIsUsed = */ true); + + n += counter.Values().DecodedHeap(); + n += counter.Values().DecodedNonHeap(); + } } return n; } @@ -406,17 +435,6 @@ private: aValue, desc, aData); } - static PLDHashOperator DoRecordCounter(const ImageCacheKey&, - imgCacheEntry* aEntry, - void* aUserArg) - { - RefPtr req = aEntry->GetRequest(); - RecordCounterForRequest(req, - static_cast*>(aUserArg), - !aEntry->HasNoProxies()); - return PL_DHASH_NEXT; - } - static void RecordCounterForRequest(imgRequest* aRequest, nsTArray* aArray, bool aIsUsed) @@ -430,33 +448,6 @@ private: aArray->AppendElement(Move(counter)); } - - static PLDHashOperator DoRecordCounterUsedDecoded(const ImageCacheKey&, - imgCacheEntry* aEntry, - void* aUserArg) - { - if (aEntry->HasNoProxies()) { - return PL_DHASH_NEXT; - } - - RefPtr req = aEntry->GetRequest(); - RefPtr image = req->GetImage(); - if (!image) { - return PL_DHASH_NEXT; - } - - // Both this and EntryImageSizes measure images/content/raster/used/decoded - // memory. This function's measurement is secondary -- the result doesn't - // go in the "explicit" tree -- so we use moz_malloc_size_of instead of - // ImagesMallocSizeOf to prevent DMD from seeing it reported twice. - ImageMemoryCounter counter(image, moz_malloc_size_of, /* aIsUsed = */ true); - - auto n = static_cast(aUserArg); - *n += counter.Values().DecodedHeap(); - *n += counter.Values().DecodedNonHeap(); - - return PL_DHASH_NEXT; - } }; NS_IMPL_ISUPPORTS(imgMemoryReporter, nsIMemoryReporter) @@ -2107,15 +2098,6 @@ imgLoader::LoadImageXPCOM(nsIURI* aURI, return rv; } -// imgIRequest loadImage(in nsIURI aURI, -// in nsIURI aInitialDocumentURL, -// in nsIURI aReferrerURI, -// in nsIPrincipal aLoadingPrincipal, -// in nsILoadGroup aLoadGroup, -// in imgINotificationObserver aObserver, -// in nsISupports aCX, -// in nsLoadFlags aLoadFlags, -// in nsISupports cacheKey); nsresult imgLoader::LoadImage(nsIURI* aURI, nsIURI* aInitialDocumentURI, @@ -2396,11 +2378,6 @@ imgLoader::LoadImage(nsIURI* aURI, return NS_OK; } -/* imgIRequest -loadImageWithChannelXPCOM(in nsIChannel channel, - in imgINotificationObserver aObserver, - in nsISupports cx, - out nsIStreamListener); */ NS_IMETHODIMP imgLoader::LoadImageWithChannelXPCOM(nsIChannel* channel, imgINotificationObserver* aObserver, @@ -2915,8 +2892,6 @@ ProxyListener::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt) return mDestListener->OnStartRequest(aRequest, ctxt); } -/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, - in nsresult status); */ NS_IMETHODIMP ProxyListener::OnStopRequest(nsIRequest* aRequest, nsISupports* ctxt, @@ -2931,10 +2906,6 @@ ProxyListener::OnStopRequest(nsIRequest* aRequest, /** nsIStreamListener methods **/ -/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, - in nsIInputStream inStr, - in unsigned long long sourceOffset, - in unsigned long count); */ NS_IMETHODIMP ProxyListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* ctxt, nsIInputStream* inStr, uint64_t sourceOffset, @@ -3139,8 +3110,6 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt) return mDestListener->OnStartRequest(aRequest, ctxt); } -/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, - in nsresult status); */ NS_IMETHODIMP imgCacheValidator::OnStopRequest(nsIRequest* aRequest, nsISupports* ctxt, @@ -3159,10 +3128,6 @@ imgCacheValidator::OnStopRequest(nsIRequest* aRequest, /** nsIStreamListener methods **/ -/* void - onDataAvailable (in nsIRequest request, in nsISupports ctxt, - in nsIInputStream inStr, in unsigned long long sourceOffset, - in unsigned long count); */ NS_IMETHODIMP imgCacheValidator::OnDataAvailable(nsIRequest* aRequest, nsISupports* ctxt, nsIInputStream* inStr, diff --git a/image/imgRequest.cpp b/image/imgRequest.cpp index 55356982ac..e6e10e4b78 100644 --- a/image/imgRequest.cpp +++ b/image/imgRequest.cpp @@ -804,8 +804,6 @@ imgRequest::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt) return NS_OK; } -/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, - nsresult status); */ NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest* aRequest, nsISupports* ctxt, nsresult status) diff --git a/intl/uconv/nsScriptableUConv.cpp b/intl/uconv/nsScriptableUConv.cpp index 60e18e9da1..64b96df0ba 100644 --- a/intl/uconv/nsScriptableUConv.cpp +++ b/intl/uconv/nsScriptableUConv.cpp @@ -136,9 +136,6 @@ nsScriptableUnicodeConverter::ConvertToUnicode(const nsACString& aSrc, nsAString _retval); } -/* AString convertFromByteArray([const,array,size_is(aCount)] in octet aData, - in unsigned long aCount); - */ NS_IMETHODIMP nsScriptableUnicodeConverter::ConvertFromByteArray(const uint8_t* aData, uint32_t aCount, @@ -180,10 +177,6 @@ nsScriptableUnicodeConverter::ConvertFromByteArray(const uint8_t* aData, } -/* void convertToByteArray(in AString aString, - [optional] out unsigned long aLen, - [array, size_is(aLen),retval] out octet aData); - */ NS_IMETHODIMP nsScriptableUnicodeConverter::ConvertToByteArray(const nsAString& aString, uint32_t* aLen, diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 37ad9842af..9fa45711ac 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -887,7 +887,7 @@ SetSavedStacksRNGState(JSContext* cx, unsigned argc, Value* vp) if (!ToInt32(cx, args[0], &seed)) return false; - cx->compartment()->savedStacks().setRNGState((seed ^ RNG_MULTIPLIER) & RNG_MASK); + cx->compartment()->savedStacks().setRNGState(seed, seed * 33); return true; } diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index b702007a8e..1f78e4ebba 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -5747,6 +5747,13 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, ptrdiff_t top) if (!emitTree(forHead->pn_kid2)) return false; + } else if (!forHead->pn_kid3) { + // If there is no condition clause and no update clause, mark + // the loop-ending "goto" with the location of the "for". + // This ensures that the debugger will stop on each loop + // iteration. + if (!updateSourceCoordNotes(pn->pn_pos.begin)) + return false; } /* Set the first note offset so we can find the loop condition. */ @@ -8474,11 +8481,9 @@ CGBlockScopeList::findEnclosingScope(uint32_t index) // scope contains POS, it should still be open, so its length should // be zero. return list[index].index; - } else { - // Conversely, if the length is not zero, it should not contain - // POS. - MOZ_ASSERT_IF(inPrologue == list[index].endInPrologue, list[index].end <= pos); } + // Conversely, if the length is not zero, it should not contain POS. + MOZ_ASSERT_IF(inPrologue == list[index].endInPrologue, list[index].end <= pos); } return BlockScopeNote::NoBlockScopeIndex; diff --git a/js/src/jit-test/tests/debug/Frame-onStep-15.js b/js/src/jit-test/tests/debug/Frame-onStep-15.js new file mode 100644 index 0000000000..539ff5f054 --- /dev/null +++ b/js/src/jit-test/tests/debug/Frame-onStep-15.js @@ -0,0 +1,43 @@ +// Test how stepping interacts with for(;;) statements. + +let g = newGlobal(); + +// We want a for(;;) loop whose body is evaluated at least once, to +// see whether the loop head is hit a second time. +g.eval(`function f() { + let x = 0; + debugger; // +0 + for(;;) { // +1 + if (x++ == 1) break; // +2 + } // +3 + debugger; // +4 +}`); + +let dbg = Debugger(g); + +function test(s, expected) { + let result = ''; + + dbg.onDebuggerStatement = function(frame) { + // On the second debugger statement, we're done. + dbg.onDebuggerStatement = function(frame) { + frame.onStep = undefined; + }; + + let debugLine = frame.script.getOffsetLocation(frame.offset).lineNumber; + frame.onStep = function() { + // Only examine stops at entry points for the line. + let lineNo = this.script.getOffsetLocation(this.offset).lineNumber; + if (this.script.getLineOffsets(lineNo).indexOf(this.offset) < 0) { + return undefined; + } + + let delta = this.script.getOffsetLocation(this.offset).lineNumber - debugLine; + result += delta; + }; + }; + g.eval(s); + assertEq(result, expected); +} + +test('f()', '2124'); diff --git a/js/src/jit-test/tests/debug/Memory-allocationSamplingProbability-02.js b/js/src/jit-test/tests/debug/Memory-allocationSamplingProbability-02.js index 106f39e620..4afa868385 100644 --- a/js/src/jit-test/tests/debug/Memory-allocationSamplingProbability-02.js +++ b/js/src/jit-test/tests/debug/Memory-allocationSamplingProbability-02.js @@ -32,5 +32,5 @@ dbg.memory.trackingAllocationSites = true; // probability is fine. measure(0.0, 0); measure(1.0, 100); -measure(0.1, 9); -measure(0.5, 51); +measure(0.1, 7); +measure(0.5, 44); diff --git a/js/src/jit-test/tests/debug/Script-getLineOffsets-08.js b/js/src/jit-test/tests/debug/Script-getLineOffsets-08.js index 84914d7334..8a7fb69e1b 100644 --- a/js/src/jit-test/tests/debug/Script-getLineOffsets-08.js +++ b/js/src/jit-test/tests/debug/Script-getLineOffsets-08.js @@ -22,3 +22,4 @@ function test(code) { test('while (false)\n;'); test('for (;false;)\n;'); +test('for (;;) break;\n;'); diff --git a/js/src/proxy/ScriptedDirectProxyHandler.cpp b/js/src/proxy/ScriptedDirectProxyHandler.cpp index 6ad1509cc0..91c20db078 100644 --- a/js/src/proxy/ScriptedDirectProxyHandler.cpp +++ b/js/src/proxy/ScriptedDirectProxyHandler.cpp @@ -10,6 +10,8 @@ #include "jsobjinlines.h" +#include "vm/NativeObject-inl.h" + using namespace js; using JS::IsArrayAnswer; diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 6a3c70db6e..b440c4d478 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -8014,7 +8014,7 @@ DebuggerEnv_getCallee(JSContext* cx, unsigned argc, Value* vp) return true; JSObject& scope = env->as().scope(); - if (!scope.is() || scope.is()) + if (!scope.is()) return true; CallObject& callobj = scope.as(); diff --git a/js/src/vm/SavedFrame.h b/js/src/vm/SavedFrame.h index b1b22d299b..0e7ed47354 100644 --- a/js/src/vm/SavedFrame.h +++ b/js/src/vm/SavedFrame.h @@ -184,7 +184,7 @@ class SavedFrame : public NativeObject { struct SavedFrame::HashPolicy { typedef SavedFrame::Lookup Lookup; - typedef PointerHasher SavedFramePtrHasher; + typedef MovableCellHasher SavedFramePtrHasher; typedef PointerHasher JSPrincipalsPtrHasher; static HashNumber hash(const Lookup& lookup); diff --git a/js/src/vm/SavedStacks.cpp b/js/src/vm/SavedStacks.cpp index 99ca2085e6..5b1bf59240 100644 --- a/js/src/vm/SavedStacks.cpp +++ b/js/src/vm/SavedStacks.cpp @@ -6,6 +6,7 @@ #include "vm/SavedStacks.h" +#include "mozilla/ArrayUtils.h" #include "mozilla/Attributes.h" #include "mozilla/Move.h" @@ -986,6 +987,10 @@ SavedFrame::toStringMethod(JSContext* cx, unsigned argc, Value* vp) bool SavedStacks::init() { + uint64_t seed[2]; + random_generateSeed(seed, mozilla::ArrayLength(seed)); + bernoulli.setRandomState(seed[0], seed[1]); + if (!pcLocationMap.init()) return false; @@ -1030,26 +1035,8 @@ SavedStacks::sweep(JSRuntime* rt) { if (frames.initialized()) { for (SavedFrame::Set::Enum e(frames); !e.empty(); e.popFront()) { - JSObject* obj = e.front().unbarrieredGet(); - JSObject* temp = obj; - - if (IsAboutToBeFinalizedUnbarriered(&obj)) { + if (IsAboutToBeFinalized(&e.mutableFront())) e.removeFront(); - } else { - SavedFrame* frame = &obj->as(); - - SavedFrame* parent = frame->getParent(); - bool parentMoved = parent && IsForwarded(parent); - if (parentMoved) - parent = Forwarded(parent); - - if (obj != temp || parentMoved) { - MOZ_ASSERT(!IsForwarded(frame)); - SavedFrame::Lookup newLocation(*frame); - newLocation.parent = parent; - e.rekeyFront(newLocation, ReadBarriered(frame)); - } - } } } @@ -1421,7 +1408,7 @@ SavedStacks::chooseSamplingProbability(JSCompartment* compartment) mozilla::DebugOnly begin = dbgs->begin(); mozilla::DebugOnly foundAnyDebuggers = false; - allocationSamplingProbability = 0; + double probability = 0; for (Debugger** dbgp = dbgs->begin(); dbgp < dbgs->end(); dbgp++) { // The set of debuggers had better not change while we're iterating, // such that the vector gets reallocated. @@ -1429,11 +1416,13 @@ SavedStacks::chooseSamplingProbability(JSCompartment* compartment) if ((*dbgp)->trackingAllocationSites && (*dbgp)->enabled) { foundAnyDebuggers = true; - allocationSamplingProbability = std::max((*dbgp)->allocationSamplingProbability, - allocationSamplingProbability); + probability = std::max((*dbgp)->allocationSamplingProbability, + probability); } } MOZ_ASSERT(foundAnyDebuggers); + + bernoulli.setProbability(probability); } JSObject* @@ -1442,38 +1431,8 @@ SavedStacksMetadataCallback(JSContext* cx, JSObject* target) RootedObject obj(cx, target); SavedStacks& stacks = cx->compartment()->savedStacks(); - if (stacks.allocationSkipCount > 0) { - stacks.allocationSkipCount--; + if (!stacks.bernoulli.trial()) return nullptr; - } - - if (stacks.allocationSamplingProbability == 0.0) - return nullptr; - - // If the sampling probability is set to 1.0, we are always taking a sample - // and can therefore leave allocationSkipCount at 0. - if (stacks.allocationSamplingProbability != 1.0) { - // Rather than generating a random number on every allocation to decide - // if we want to sample that particular allocation (which would be - // expensive), we calculate the number of allocations to skip before - // taking the next sample. - // - // P = the probability we sample any given event. - // - // ~P = 1-P, the probability we don't sample a given event. - // - // (~P)^n = the probability that we skip at least the next n events. - // - // let X = random between 0 and 1. - // - // floor(log base ~P of X) = n, aka the number of events we should skip - // until we take the next sample. Any value for X less than (~P)^n - // yields a skip count greater than n, so the likelihood of a skip count - // greater than n is (~P)^n, as required. - double notSamplingProb = 1.0 - stacks.allocationSamplingProbability; - stacks.allocationSkipCount = std::floor(std::log(random_nextDouble(&stacks.rngState)) / - std::log(notSamplingProb)); - } AutoEnterOOMUnsafeRegion oomUnsafe; RootedSavedFrame frame(cx); diff --git a/js/src/vm/SavedStacks.h b/js/src/vm/SavedStacks.h index 2ad0a48c2c..2d820b7bd6 100644 --- a/js/src/vm/SavedStacks.h +++ b/js/src/vm/SavedStacks.h @@ -7,6 +7,8 @@ #ifndef vm_SavedStacks_h #define vm_SavedStacks_h +#include "mozilla/FastBernoulliTrial.h" + #include "jscntxt.h" #include "jsmath.h" #include "jswrapper.h" @@ -152,12 +154,11 @@ class SavedStacks { JS::ubi::StackFrame& ubiFrame, MutableHandleObject outSavedFrameStack); + public: SavedStacks() : frames(), - allocationSamplingProbability(1.0), - allocationSkipCount(0), - rngState(0), + bernoulli(1.0, 0x59fdad7f6b4cc573, 0x91adf38db96a9354), creatingSavedFrame(false) { } @@ -170,16 +171,14 @@ class SavedStacks { void trace(JSTracer* trc); uint32_t count(); void clear(); - void setRNGState(uint64_t state) { rngState = state; } + void setRNGState(uint64_t state0, uint64_t state1) { bernoulli.setRandomState(state0, state1); } void chooseSamplingProbability(JSCompartment*); size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf); private: SavedFrame::Set frames; - double allocationSamplingProbability; - uint32_t allocationSkipCount; - uint64_t rngState; + mozilla::FastBernoulliTrial bernoulli; bool creatingSavedFrame; // Similar to mozilla::ReentrancyGuard, but instead of asserting against diff --git a/js/src/vm/ScopeObject-inl.h b/js/src/vm/ScopeObject-inl.h index 84ab6bda72..b0f41fa8ef 100644 --- a/js/src/vm/ScopeObject-inl.h +++ b/js/src/vm/ScopeObject-inl.h @@ -27,7 +27,7 @@ NearestEnclosingExtensibleLexicalScope(JSObject* scope) inline void ScopeObject::setAliasedVar(JSContext* cx, ScopeCoordinate sc, PropertyName* name, const Value& v) { - MOZ_ASSERT(is() || is()); + MOZ_ASSERT(is() || is()); JS_STATIC_ASSERT(CallObject::RESERVED_SLOTS == BlockObject::RESERVED_SLOTS); // name may be null if we don't need to track side effects on the object. @@ -48,7 +48,8 @@ ScopeObject::setAliasedVar(JSContext* cx, ScopeCoordinate sc, PropertyName* name } inline void -CallObject::setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* name, const Value& v) +LexicalScopeBase::setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* name, + const Value& v) { MOZ_ASSERT(name == fi->name()); setSlot(fi.scopeSlot(), v); @@ -57,7 +58,8 @@ CallObject::setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* nam } inline void -CallObject::setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, jsid id, const Value& v) +LexicalScopeBase::setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, jsid id, + const Value& v) { setSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue), v); if (isSingleton()) @@ -65,7 +67,7 @@ CallObject::setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, js } inline void -CallObject::initRemainingSlotsToUninitializedLexicals(uint32_t begin) +LexicalScopeBase::initRemainingSlotsToUninitializedLexicals(uint32_t begin) { uint32_t end = slotSpan(); for (uint32_t slot = begin; slot < end; slot++) @@ -73,7 +75,7 @@ CallObject::initRemainingSlotsToUninitializedLexicals(uint32_t begin) } inline void -CallObject::initAliasedLexicalsToThrowOnTouch(JSScript* script) +LexicalScopeBase::initAliasedLexicalsToThrowOnTouch(JSScript* script) { initRemainingSlotsToUninitializedLexicals(script->bindings.aliasedBodyLevelLexicalBegin()); } diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 93463b5e4d..9be6561643 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -125,7 +125,7 @@ js::ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc) void ScopeObject::setEnclosingScope(HandleObject obj) { - MOZ_ASSERT_IF(obj->is() || obj->is() || obj->is(), + MOZ_ASSERT_IF(obj->is() || obj->is() || obj->is(), obj->isDelegate()); setFixedSlot(SCOPE_CHAIN_SLOT, ObjectValue(*obj)); } @@ -1776,9 +1776,7 @@ class DebugScopeProxy : public BaseProxyHandler static bool isFunctionScope(const JSObject& scope) { - return scope.is() && - !scope.is() && - !scope.as().isForEval(); + return scope.is() && !scope.as().isForEval(); } /* @@ -2203,7 +2201,7 @@ bool DebugScopeObject::isForDeclarative() const { ScopeObject& s = scope(); - return s.is() || s.is() || s.is(); + return s.is() || s.is() || s.is(); } bool @@ -2224,7 +2222,7 @@ DebugScopeObject::isOptimizedOut() const if (s.is()) return !s.as().staticBlock().needsClone(); - if (s.is() && !s.is()) { + if (s.is()) { return !s.as().isForEval() && !s.as().callee().needsCallObject() && !maybeSnapshot(); diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index e76456edc8..edeea5c65c 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -221,7 +221,9 @@ ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc); * | | | * | | DeclEnvObject Holds name of recursive/needsCallObject named lambda * | | - * | CallObject Scope of entire function or strict eval + * | LexicalScopeBase Shared base for function and modules scopes + * | | | + * | | CallObject Scope of entire function or strict eval * | | * | ModuleEnvironmentObject Module top-level scope on run-time scope chain * | @@ -287,7 +289,36 @@ class ScopeObject : public NativeObject } }; -class CallObject : public ScopeObject +class LexicalScopeBase : public ScopeObject +{ + protected: + inline void initRemainingSlotsToUninitializedLexicals(uint32_t begin); + inline void initAliasedLexicalsToThrowOnTouch(JSScript* script); + + public: + /* Get/set the aliased variable referred to by 'fi'. */ + const Value& aliasedVar(AliasedFormalIter fi) { + return getSlot(fi.scopeSlot()); + } + inline void setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* name, + const Value& v); + + /* + * When an aliased var (var accessed by nested closures) is also aliased by + * the arguments object, it must of course exist in one canonical location + * and that location is always the CallObject. For this to work, the + * ArgumentsObject stores special MagicValue in its array for forwarded-to- + * CallObject variables. This MagicValue's payload is the slot of the + * CallObject to access. + */ + const Value& aliasedVarFromArguments(const Value& argsValue) { + return getSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue)); + } + inline void setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, jsid id, + const Value& v); +}; + +class CallObject : public LexicalScopeBase { protected: static const uint32_t CALLEE_SLOT = 1; @@ -295,9 +326,6 @@ class CallObject : public ScopeObject static CallObject* create(JSContext* cx, HandleScript script, HandleObject enclosing, HandleFunction callee); - inline void initRemainingSlotsToUninitializedLexicals(uint32_t begin); - inline void initAliasedLexicalsToThrowOnTouch(JSScript* script); - public: static const Class class_; @@ -347,27 +375,6 @@ class CallObject : public ScopeObject return getFixedSlot(CALLEE_SLOT).toObject().as(); } - /* Get/set the aliased variable referred to by 'bi'. */ - const Value& aliasedVar(AliasedFormalIter fi) { - return getSlot(fi.scopeSlot()); - } - inline void setAliasedVar(JSContext* cx, AliasedFormalIter fi, PropertyName* name, - const Value& v); - - /* - * When an aliased var (var accessed by nested closures) is also aliased by - * the arguments object, it must of course exist in one canonical location - * and that location is always the CallObject. For this to work, the - * ArgumentsObject stores special MagicValue in its array for forwarded-to- - * CallObject variables. This MagicValue's payload is the slot of the - * CallObject to access. - */ - const Value& aliasedVarFromArguments(const Value& argsValue) { - return getSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue)); - } - inline void setAliasedVarFromArguments(JSContext* cx, const Value& argsValue, jsid id, - const Value& v); - /* For jit access. */ static size_t offsetOfCallee() { return getFixedSlotOffset(CALLEE_SLOT); @@ -378,13 +385,15 @@ class CallObject : public ScopeObject } }; -class ModuleEnvironmentObject : public CallObject +class ModuleEnvironmentObject : public LexicalScopeBase { - static const uint32_t MODULE_SLOT = CallObject::CALLEE_SLOT; + static const uint32_t MODULE_SLOT = 1; public: static const Class class_; + static const uint32_t RESERVED_SLOTS = 2; + static ModuleEnvironmentObject* create(ExclusiveContext* cx, HandleModuleObject module); ModuleObject& module(); IndirectBindingMap& importBindings(); @@ -1261,9 +1270,9 @@ JSObject::is() const template<> inline bool -JSObject::is() const +JSObject::is() const { - return getClass() == &js::CallObject::class_ || + return is() || is(); } @@ -1271,7 +1280,7 @@ template<> inline bool JSObject::is() const { - return is() || + return is() || is() || is() || is() || @@ -1342,7 +1351,7 @@ IsStaticGlobalLexicalScope(JSObject* scope) inline const Value& ScopeObject::aliasedVar(ScopeCoordinate sc) { - MOZ_ASSERT(is() || is()); + MOZ_ASSERT(is() || is()); return getSlot(sc.slot()); } diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index db2d9137f1..e4bc3a6c77 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -35,10 +35,7 @@ namespace js { static inline bool IsCacheableNonGlobalScope(JSObject* obj) { - bool cacheable = - (obj->is() && !obj->is()) || - obj->is() || - obj->is(); + bool cacheable = obj->is() || obj->is() || obj->is(); MOZ_ASSERT_IF(cacheable, !obj->getOps()->lookupProperty); return cacheable; diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 747b89749f..aa7858a37d 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -1056,8 +1056,6 @@ mozJSComponentLoader::Import(const nsACString& registryLocation, return rv; } -/* [noscript] JSObjectPtr importInto(in AUTF8String registryLocation, - in JSObjectPtr targetObj); */ NS_IMETHODIMP mozJSComponentLoader::ImportInto(const nsACString& aLocation, JSObject* aTargetObj, diff --git a/js/xpconnect/src/Sandbox.cpp b/js/xpconnect/src/Sandbox.cpp index 5aae0c2fbc..92d7c3be48 100644 --- a/js/xpconnect/src/Sandbox.cpp +++ b/js/xpconnect/src/Sandbox.cpp @@ -1150,13 +1150,6 @@ xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp, nsISupports* prin return NS_OK; } -/* bool call(in nsIXPConnectWrappedNative wrapper, - * in JSContextPtr cx, - * in JSObjectPtr obj, - * in uint32_t argc, - * in JSValPtr argv, - * in JSValPtr vp); - */ NS_IMETHODIMP nsXPCComponents_utils_Sandbox::Call(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject* objArg, const CallArgs& args, bool* _retval) @@ -1165,13 +1158,6 @@ nsXPCComponents_utils_Sandbox::Call(nsIXPConnectWrappedNative* wrapper, JSContex return CallOrConstruct(wrapper, cx, obj, args, _retval); } -/* bool construct(in nsIXPConnectWrappedNative wrapper, - * in JSContextPtr cx, - * in JSObjectPtr obj, - * in uint32_t argc, - * in JSValPtr argv, - * in JSValPtr vp); - */ NS_IMETHODIMP nsXPCComponents_utils_Sandbox::Construct(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject* objArg, const CallArgs& args, bool* _retval) diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index 939953b7bb..2111b53240 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -115,8 +115,6 @@ private: nsCOMArray mInterfaces; }; -/* void getInterfaces (out uint32_t count, [array, size_is (count), retval] - out nsIIDPtr array); */ NS_IMETHODIMP nsXPCComponents_Interfaces::GetInterfaces(uint32_t* aCount, nsIID * **aArray) { @@ -342,8 +340,6 @@ private: }; /***************************************************************************/ -/* void getInterfaces (out uint32_t count, [array, size_is (count), retval] - out nsIIDPtr array); */ NS_IMETHODIMP nsXPCComponents_InterfacesByID::GetInterfaces(uint32_t* aCount, nsIID * **aArray) { @@ -571,8 +567,6 @@ private: }; /***************************************************************************/ -/* void getInterfaces (out uint32_t count, [array, size_is (count), retval] - out nsIIDPtr array); */ NS_IMETHODIMP nsXPCComponents_Classes::GetInterfaces(uint32_t* aCount, nsIID * **aArray) { @@ -780,8 +774,6 @@ private: }; /***************************************************************************/ -/* void getInterfaces (out uint32_t count, [array, size_is (count), retval] - out nsIIDPtr array); */ NS_IMETHODIMP nsXPCComponents_ClassesByID::GetInterfaces(uint32_t* aCount, nsIID * **aArray) { @@ -1012,8 +1004,6 @@ private: }; /***************************************************************************/ -/* void getInterfaces (out uint32_t count, [array, size_is (count), retval] - out nsIIDPtr array); */ NS_IMETHODIMP nsXPCComponents_Results::GetInterfaces(uint32_t* aCount, nsIID * **aArray) { @@ -1204,8 +1194,6 @@ private: }; /***************************************************************************/ -/* void getInterfaces (out uint32_t count, [array, size_is (count), retval] - out nsIIDPtr array); */ NS_IMETHODIMP nsXPCComponents_ID::GetInterfaces(uint32_t* aCount, nsIID * **aArray) { @@ -1403,8 +1391,6 @@ private: }; /***************************************************************************/ -/* void getInterfaces (out uint32_t count, [array, size_is (count), retval] - out nsIIDPtr array); */ NS_IMETHODIMP nsXPCComponents_Exception::GetInterfaces(uint32_t* aCount, nsIID * **aArray) { @@ -1770,8 +1756,6 @@ private: }; /***************************************************************************/ -/* void getInterfaces (out uint32_t count, [array, size_is (count), retval] - out nsIIDPtr array); */ NS_IMETHODIMP nsXPCConstructor::GetInterfaces(uint32_t* aCount, nsIID * **aArray) { @@ -1997,8 +1981,6 @@ private: }; /***************************************************************************/ -/* void getInterfaces (out uint32_t count, [array, size_is (count), retval] - out nsIIDPtr array); */ NS_IMETHODIMP nsXPCComponents_Constructor::GetInterfaces(uint32_t* aCount, nsIID * **aArray) { @@ -2486,9 +2468,6 @@ nsXPCComponents_Utils::SetSandboxMetadata(HandleValue sandboxVal, return NS_OK; } -/* JSObject import (in AUTF8String registryLocation, - * [optional] in JSObject targetObj); - */ NS_IMETHODIMP nsXPCComponents_Utils::Import(const nsACString& registryLocation, HandleValue targetObj, @@ -2503,8 +2482,6 @@ nsXPCComponents_Utils::Import(const nsACString& registryLocation, return moduleloader->Import(registryLocation, targetObj, cx, optionalArgc, retval); } -/* boolean isModuleLoaded (in AUTF8String registryLocation); - */ NS_IMETHODIMP nsXPCComponents_Utils::IsModuleLoaded(const nsACString& registryLocation, bool* retval) { @@ -2515,8 +2492,6 @@ nsXPCComponents_Utils::IsModuleLoaded(const nsACString& registryLocation, bool* return moduleloader->IsModuleLoaded(registryLocation, retval); } -/* unload (in AUTF8String registryLocation); - */ NS_IMETHODIMP nsXPCComponents_Utils::Unload(const nsACString & registryLocation) { @@ -2527,9 +2502,6 @@ nsXPCComponents_Utils::Unload(const nsACString & registryLocation) return moduleloader->Unload(registryLocation); } -/* - * JSObject importGlobalProperties (in jsval aPropertyList); - */ NS_IMETHODIMP nsXPCComponents_Utils::ImportGlobalProperties(HandleValue aPropertyList, JSContext* cx) @@ -2714,8 +2686,6 @@ nsXPCComponents_Utils::GetJSTestingFunctions(JSContext* cx, return NS_OK; } -/* jsval callFunctionWithStack(in jsval function, in nsIStackFrame stack, - in AString asyncCause); */ NS_IMETHODIMP nsXPCComponents_Utils::CallFunctionWithAsyncStack(HandleValue function, nsIStackFrame* stack, diff --git a/js/xpconnect/src/XPCRuntimeService.cpp b/js/xpconnect/src/XPCRuntimeService.cpp index 7e6fbda9f4..ce79dcc86a 100644 --- a/js/xpconnect/src/XPCRuntimeService.cpp +++ b/js/xpconnect/src/XPCRuntimeService.cpp @@ -79,8 +79,6 @@ BackstagePass::Enumerate(nsIXPConnectWrappedNative* wrapper, JSContext* cx, } /***************************************************************************/ -/* void getInterfaces (out uint32_t count, [array, size_is (count), retval] - out nsIIDPtr array); */ NS_IMETHODIMP BackstagePass::GetInterfaces(uint32_t* aCount, nsIID * **aArray) { diff --git a/js/xpconnect/tests/components/native/xpctest_params.cpp b/js/xpconnect/tests/components/native/xpctest_params.cpp index cbaff46d26..4268847bec 100644 --- a/js/xpconnect/tests/components/native/xpctest_params.cpp +++ b/js/xpconnect/tests/components/native/xpctest_params.cpp @@ -188,9 +188,6 @@ NS_IMETHODIMP nsXPCTestParams::TestJsval(JS::Handle a, return NS_OK; } -/* void testShortArray (in unsigned long aLength, [array, size_is (aLength)] in short a, - * inout unsigned long bLength, [array, size_is (bLength)] inout short b, - * out unsigned long rvLength, [array, size_is (rvLength), retval] out short rv); */ NS_IMETHODIMP nsXPCTestParams::TestShortArray(uint32_t aLength, int16_t* a, uint32_t* bLength, int16_t** b, uint32_t* rvLength, int16_t** rv) @@ -198,9 +195,6 @@ NS_IMETHODIMP nsXPCTestParams::TestShortArray(uint32_t aLength, int16_t* a, BUFFER_METHOD_IMPL(int16_t, 0, TAKE_OWNERSHIP_NOOP); } -/* void testDoubleArray (in unsigned long aLength, [array, size_is (aLength)] in double a, - * inout unsigned long bLength, [array, size_is (bLength)] inout double b, - * out unsigned long rvLength, [array, size_is (rvLength), retval] out double rv); */ NS_IMETHODIMP nsXPCTestParams::TestDoubleArray(uint32_t aLength, double* a, uint32_t* bLength, double** b, uint32_t* rvLength, double** rv) @@ -208,9 +202,6 @@ NS_IMETHODIMP nsXPCTestParams::TestDoubleArray(uint32_t aLength, double* a, BUFFER_METHOD_IMPL(double, 0, TAKE_OWNERSHIP_NOOP); } -/* void testStringArray (in unsigned long aLength, [array, size_is (aLength)] in string a, - * inout unsigned long bLength, [array, size_is (bLength)] inout string b, - * out unsigned long rvLength, [array, size_is (rvLength), retval] out string rv); */ NS_IMETHODIMP nsXPCTestParams::TestStringArray(uint32_t aLength, const char * *a, uint32_t* bLength, char * **b, uint32_t* rvLength, char * **rv) @@ -218,9 +209,6 @@ NS_IMETHODIMP nsXPCTestParams::TestStringArray(uint32_t aLength, const char * *a BUFFER_METHOD_IMPL(char*, 0, TAKE_OWNERSHIP_STRING); } -/* void testWstringArray (in unsigned long aLength, [array, size_is (aLength)] in wstring a, - * inout unsigned long bLength, [array, size_is (bLength)] inout wstring b, - * out unsigned long rvLength, [array, size_is (rvLength), retval] out wstring rv); */ NS_IMETHODIMP nsXPCTestParams::TestWstringArray(uint32_t aLength, const char16_t * *a, uint32_t* bLength, char16_t * **b, uint32_t* rvLength, char16_t * **rv) @@ -228,9 +216,6 @@ NS_IMETHODIMP nsXPCTestParams::TestWstringArray(uint32_t aLength, const char16_t BUFFER_METHOD_IMPL(char16_t*, 0, TAKE_OWNERSHIP_WSTRING); } -/* void testInterfaceArray (in unsigned long aLength, [array, size_is (aLength)] in nsIXPCTestInterfaceA a, - * inout unsigned long bLength, [array, size_is (bLength)] inout nsIXPCTestInterfaceA b, - * out unsigned long rvLength, [array, size_is (rvLength), retval] out nsIXPCTestInterfaceA rv); */ NS_IMETHODIMP nsXPCTestParams::TestInterfaceArray(uint32_t aLength, nsIXPCTestInterfaceA** a, uint32_t* bLength, nsIXPCTestInterfaceA * **b, uint32_t* rvLength, nsIXPCTestInterfaceA * **rv) @@ -238,9 +223,6 @@ NS_IMETHODIMP nsXPCTestParams::TestInterfaceArray(uint32_t aLength, nsIXPCTestIn BUFFER_METHOD_IMPL(nsIXPCTestInterfaceA*, 0, TAKE_OWNERSHIP_INTERFACE); } -/* void testSizedString (in unsigned long aLength, [size_is (aLength)] in string a, - * inout unsigned long bLength, [size_is (bLength)] inout string b, - * out unsigned long rvLength, [size_is (rvLength), retval] out string rv); */ NS_IMETHODIMP nsXPCTestParams::TestSizedString(uint32_t aLength, const char * a, uint32_t* bLength, char * *b, uint32_t* rvLength, char * *rv) @@ -248,9 +230,6 @@ NS_IMETHODIMP nsXPCTestParams::TestSizedString(uint32_t aLength, const char * a, BUFFER_METHOD_IMPL(char, 1, TAKE_OWNERSHIP_NOOP); } -/* void testSizedWstring (in unsigned long aLength, [size_is (aLength)] in wstring a, - * inout unsigned long bLength, [size_is (bLength)] inout wstring b, - * out unsigned long rvLength, [size_is (rvLength), retval] out wstring rv); */ NS_IMETHODIMP nsXPCTestParams::TestSizedWstring(uint32_t aLength, const char16_t * a, uint32_t* bLength, char16_t * *b, uint32_t* rvLength, char16_t * *rv) @@ -258,9 +237,6 @@ NS_IMETHODIMP nsXPCTestParams::TestSizedWstring(uint32_t aLength, const char16_t BUFFER_METHOD_IMPL(char16_t, 1, TAKE_OWNERSHIP_NOOP); } -/* void testInterfaceIs (in nsIIDPtr aIID, [iid_is (aIID)] in nsQIResult a, - * inout nsIIDPtr bIID, [iid_is (bIID)] inout nsQIResult b, - * out nsIIDPtr rvIID, [iid_is (rvIID), retval] out nsQIResult rv); */ NS_IMETHODIMP nsXPCTestParams::TestInterfaceIs(const nsIID* aIID, void* a, nsIID** bIID, void** b, nsIID** rvIID, void** rv) @@ -294,12 +270,6 @@ NS_IMETHODIMP nsXPCTestParams::TestInterfaceIs(const nsIID* aIID, void* a, return NS_OK; } -/* void testInterfaceIsArray (in unsigned long aLength, in nsIIDPtr aIID, - * [array, size_is (aLength), iid_is (aIID)] in nsQIResult a, - * inout unsigned long bLength, inout nsIIDPtr bIID, - * [array, size_is (bLength), iid_is (bIID)] inout nsQIResult b, - * out unsigned long rvLength, out nsIIDPtr rvIID, - * [retval, array, size_is (rvLength), iid_is (rvIID)] out nsQIResult rv); */ NS_IMETHODIMP nsXPCTestParams::TestInterfaceIsArray(uint32_t aLength, const nsIID* aIID, void** a, uint32_t* bLength, nsIID** bIID, @@ -327,9 +297,6 @@ NS_IMETHODIMP nsXPCTestParams::TestOutAString(nsAString & o) return NS_OK; } -/* - * ACString testStringArrayOptionalSize([array, size_is(aLength)] in string a, [optional] in unsigned long aLength); - */ NS_IMETHODIMP nsXPCTestParams::TestStringArrayOptionalSize(const char * *a, uint32_t length, nsACString& out) { out.Truncate(); diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index 3330c5ba3e..671e2ad601 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -34,6 +34,10 @@ #include "ClientLayerManager.h" #include "FrameLayerBuilder.h" +#ifdef MOZ_ANDROID_APZ +#include "AndroidBridge.h" +#endif + using namespace mozilla::dom; using namespace mozilla::gfx; using namespace mozilla::layers; @@ -197,29 +201,14 @@ public: void ClearRenderFrame() { mRenderFrame = nullptr; } - virtual void SendAsyncScrollDOMEvent(bool aIsRootContent, - const CSSRect& aContentRect, - const CSSSize& aContentSize) override - { - if (MessageLoop::current() != mUILoop) { - mUILoop->PostTask( - FROM_HERE, - NewRunnableMethod(this, - &RemoteContentController::SendAsyncScrollDOMEvent, - aIsRootContent, aContentRect, aContentSize)); - return; - } - if (mRenderFrame && aIsRootContent) { - TabParent* browser = TabParent::GetFrom(mRenderFrame->Manager()); - BrowserElementParent::DispatchAsyncScrollEvent(browser, aContentRect, - aContentSize); - } - } - virtual void PostDelayedTask(Task* aTask, int aDelayMs) override { +#ifdef MOZ_ANDROID_APZ + AndroidBridge::Bridge()->PostTaskToUiThread(aTask, aDelayMs); +#else (MessageLoop::current() ? MessageLoop::current() : mUILoop)-> PostDelayedTask(FROM_HERE, aTask, aDelayMs); +#endif } virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) override diff --git a/layout/style/nsCSSRules.cpp b/layout/style/nsCSSRules.cpp index dad92b21e7..a2a8fa7556 100644 --- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -1333,7 +1333,6 @@ nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID, } -// attribute DOMString cssText; NS_IMETHODIMP nsCSSFontFaceStyleDecl::GetCssText(nsAString & aCssText) { @@ -1363,7 +1362,6 @@ nsCSSFontFaceStyleDecl::SetCssText(const nsAString & aCssText) return NS_ERROR_NOT_IMPLEMENTED; // bug 443978 } -// DOMString getPropertyValue (in DOMString propertyName); NS_IMETHODIMP nsCSSFontFaceStyleDecl::GetPropertyValue(const nsAString & propertyName, nsAString & aResult) @@ -1380,7 +1378,6 @@ nsCSSFontFaceStyleDecl::GetAuthoredPropertyValue(const nsAString& propertyName, return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult); } -// nsIDOMCSSValue getPropertyCSSValue (in DOMString propertyName); already_AddRefed nsCSSFontFaceStyleDecl::GetPropertyCSSValue(const nsAString & propertyName, ErrorResult& aRv) @@ -1390,7 +1387,6 @@ nsCSSFontFaceStyleDecl::GetPropertyCSSValue(const nsAString & propertyName, return nullptr; } -// DOMString removeProperty (in DOMString propertyName) raises (DOMException); NS_IMETHODIMP nsCSSFontFaceStyleDecl::RemoveProperty(const nsAString & propertyName, nsAString & aResult) @@ -1410,7 +1406,6 @@ nsCSSFontFaceStyleDecl::RemoveProperty(const nsAString & propertyName, return NS_OK; } -// DOMString getPropertyPriority (in DOMString propertyName); NS_IMETHODIMP nsCSSFontFaceStyleDecl::GetPropertyPriority(const nsAString & propertyName, nsAString & aResult) @@ -1420,8 +1415,6 @@ nsCSSFontFaceStyleDecl::GetPropertyPriority(const nsAString & propertyName, return NS_OK; } -// void setProperty (in DOMString propertyName, in DOMString value, -// in DOMString priority) raises (DOMException); NS_IMETHODIMP nsCSSFontFaceStyleDecl::SetProperty(const nsAString & propertyName, const nsAString & value, @@ -1430,7 +1423,6 @@ nsCSSFontFaceStyleDecl::SetProperty(const nsAString & propertyName, return NS_ERROR_NOT_IMPLEMENTED; // bug 443978 } -// readonly attribute unsigned long length; NS_IMETHODIMP nsCSSFontFaceStyleDecl::GetLength(uint32_t *aLength) { @@ -1445,7 +1437,6 @@ nsCSSFontFaceStyleDecl::GetLength(uint32_t *aLength) return NS_OK; } -// DOMString item (in unsigned long index); NS_IMETHODIMP nsCSSFontFaceStyleDecl::Item(uint32_t aIndex, nsAString& aReturn) { @@ -1476,7 +1467,6 @@ nsCSSFontFaceStyleDecl::IndexedGetter(uint32_t index, bool& aFound, nsAString & aFound = false; } -// readonly attribute nsIDOMCSSRule parentRule; NS_IMETHODIMP nsCSSFontFaceStyleDecl::GetParentRule(nsIDOMCSSRule** aParentRule) { diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index 8934fc5e52..28e3d5787d 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -28,7 +28,7 @@ class nsStyleContext; namespace mozilla { class WritingMode; class LogicalMargin; -} +} // namespace mozilla struct nsTableReflowState; struct BCPropertyData; diff --git a/memory/build/mozjemalloc_compat.c b/memory/build/mozjemalloc_compat.c index 046f9e8a45..9db4cd89f9 100644 --- a/memory/build/mozjemalloc_compat.c +++ b/memory/build/mozjemalloc_compat.c @@ -91,8 +91,8 @@ malloc_good_size_impl(size_t size) return je_(nallocx)(size, 0); } -static size_t -compute_bin_unused(unsigned int narenas) +static void +compute_bin_unused_and_bookkeeping(jemalloc_stats_t *stats, unsigned int narenas) { size_t bin_unused = 0; @@ -104,6 +104,9 @@ compute_bin_unused(unsigned int narenas) unsigned int nbins; // number of bins per arena unsigned int i, j; + size_t stats_metadata; + size_t stats_ametadata = 0; // total internal allocations in all arenas + // narenas also counts uninitialized arenas, and initialized arenas // are not guaranteed to be adjacent VARIABLE_ARRAY(bool, initialized, narenas); @@ -128,7 +131,13 @@ compute_bin_unused(unsigned int narenas) } } - return bin_unused; + CTL_GET("stats.metadata", stats_metadata); + + /* get the summation for all arenas, i == narenas */ + CTL_I_GET("stats.arenas.0.metadata.allocated", stats_ametadata, narenas); + + stats->bookkeeping = stats_metadata - stats_ametadata; + stats->bin_unused = bin_unused; } MOZ_JEMALLOC_API void @@ -150,7 +159,6 @@ jemalloc_stats_impl(jemalloc_stats_t *stats) CTL_GET("stats.allocated", allocated); CTL_GET("stats.mapped", mapped); CTL_GET("opt.lg_chunk", lg_chunk); - CTL_GET("stats.bookkeeping", stats->bookkeeping); /* get the summation for all arenas, i == narenas */ CTL_I_GET("stats.arenas.0.pdirty", pdirty, narenas); @@ -160,7 +168,7 @@ jemalloc_stats_impl(jemalloc_stats_t *stats) stats->allocated = allocated; stats->waste = active - allocated; stats->page_cache = pdirty * page; - stats->bin_unused = compute_bin_unused(narenas); + compute_bin_unused_and_bookkeeping(stats, narenas); stats->waste -= stats->bin_unused; } diff --git a/memory/fallible/moz.build b/memory/fallible/moz.build index 22d17becea..5f6b2d0058 100644 --- a/memory/fallible/moz.build +++ b/memory/fallible/moz.build @@ -33,3 +33,6 @@ if CONFIG['_MSC_VER']: # This further prevents the CRT name from getting into the .obj file, # by avoiding pulling in a bunch of string code that uses the CRT. DEFINES['mozilla_Char16_h'] = True + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wshadow'] diff --git a/mfbt/FastBernoulliTrial.h b/mfbt/FastBernoulliTrial.h new file mode 100644 index 0000000000..fbfc34b3ca --- /dev/null +++ b/mfbt/FastBernoulliTrial.h @@ -0,0 +1,376 @@ +/* -*- 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_FastBernoulliTrial_h +#define mozilla_FastBernoulliTrial_h + +#include "mozilla/Assertions.h" +#include "mozilla/XorShift128PlusRNG.h" + +#include +#include + +namespace mozilla { + +/** + * class FastBernoulliTrial: Efficient sampling with uniform probability + * + * When gathering statistics about a program's behavior, we may be observing + * events that occur very frequently (e.g., function calls or memory + * allocations) and we may be gathering information that is somewhat expensive + * to produce (e.g., call stacks). Sampling all the events could have a + * significant impact on the program's performance. + * + * Why not just sample every N'th event? This technique is called "systematic + * sampling"; it's simple and efficient, and it's fine if we imagine a + * patternless stream of events. But what if we're sampling allocations, and the + * program happens to have a loop where each iteration does exactly N + * allocations? You would end up sampling the same allocation every time through + * the loop; the entire rest of the loop becomes invisible to your measurements! + * More generally, if each iteration does M allocations, and M and N have any + * common divisor at all, most allocation sites will never be sampled. If + * they're both even, say, the odd-numbered allocations disappear from your + * results. + * + * Ideally, we'd like each event to have some probability P of being sampled, + * independent of its neighbors and of its position in the sequence. This is + * called "Bernoulli sampling", and it doesn't suffer from any of the problems + * mentioned above. + * + * One disadvantage of Bernoulli sampling is that you can't be sure exactly how + * many samples you'll get: technically, it's possible that you might sample + * none of them, or all of them. But if the number of events N is large, these + * aren't likely outcomes; you can generally expect somewhere around P * N + * events to be sampled. + * + * The other disadvantage of Bernoulli sampling is that you have to generate a + * random number for every event, which can be slow. + * + * [significant pause] + * + * BUT NOT WITH THIS CLASS! FastBernoulliTrial lets you do true Bernoulli + * sampling, while generating a fresh random number only when we do decide to + * sample an event, not on every trial. When it decides not to sample, a call to + * |FastBernoulliTrial::trial| is nothing but decrementing a counter and + * comparing it to zero. So the lower your sampling probability is, the less + * overhead FastBernoulliTrial imposes. + * + * Probabilities of 0 and 1 are handled efficiently. (In neither case need we + * ever generate a random number at all.) + * + * The essential API: + * + * - FastBernoulliTrial(double P) + * Construct an instance that selects events with probability P. + * + * - FastBernoulliTrial::trial() + * Return true with probability P. Call this each time an event occurs, to + * decide whether to sample it or not. + * + * - FastBernoulliTrial::trial(size_t n) + * Equivalent to calling trial() |n| times, and returning true if any of those + * calls do. However, like trial, this runs in fast constant time. + * + * What is this good for? In some applications, some events are "bigger" than + * others. For example, large allocations are more significant than small + * allocations. Perhaps we'd like to imagine that we're drawing allocations + * from a stream of bytes, and performing a separate Bernoulli trial on every + * byte from the stream. We can accomplish this by calling |t.trial(S)| for + * the number of bytes S, and sampling the event if that returns true. + * + * Of course, this style of sampling needs to be paired with analysis and + * presentation that makes the size of the event apparent, lest trials with + * large values for |n| appear to be indistinguishable from those with small + * values for |n|. + */ +class FastBernoulliTrial { + /* + * This comment should just read, "Generate skip counts with a geometric + * distribution", and leave everyone to go look that up and see why it's the + * right thing to do, if they don't know already. + * + * BUT IF YOU'RE CURIOUS, COMMENTS ARE FREE... + * + * Instead of generating a fresh random number for every trial, we can + * randomly generate a count of how many times we should return false before + * the next time we return true. We call this a "skip count". Once we've + * returned true, we generate a fresh skip count, and begin counting down + * again. + * + * Here's an awesome fact: by exercising a little care in the way we generate + * skip counts, we can produce results indistinguishable from those we would + * get "rolling the dice" afresh for every trial. + * + * In short, skip counts in Bernoulli trials of probability P obey a geometric + * distribution. If a random variable X is uniformly distributed from [0..1), + * then std::floor(std::log(X) / std::log(1-P)) has the appropriate geometric + * distribution for the skip counts. + * + * Why that formula? + * + * Suppose we're to return |true| with some probability P, say, 0.3. Spread + * all possible futures along a line segment of length 1. In portion P of + * those cases, we'll return true on the next call to |trial|; the skip count + * is 0. For the remaining portion 1-P of cases, the skip count is 1 or more. + * + * skip: 0 1 or more + * |------------------^-----------------------------------------| + * portion: 0.3 0.7 + * P 1-P + * + * But the "1 or more" section of the line is subdivided the same way: *within + * that section*, in portion P the second call to |trial()| returns true, and in + * portion 1-P it returns false a second time; the skip count is two or more. + * So we return true on the second call in proportion 0.7 * 0.3, and skip at + * least the first two in proportion 0.7 * 0.7. + * + * skip: 0 1 2 or more + * |------------------^------------^----------------------------| + * portion: 0.3 0.7 * 0.3 0.7 * 0.7 + * P (1-P)*P (1-P)^2 + * + * We can continue to subdivide: + * + * skip >= 0: |------------------------------------------------- (1-P)^0 --| + * skip >= 1: | ------------------------------- (1-P)^1 --| + * skip >= 2: | ------------------ (1-P)^2 --| + * skip >= 3: | ^ ---------- (1-P)^3 --| + * skip >= 4: | . --- (1-P)^4 --| + * . + * ^X, see below + * + * In other words, the likelihood of the next n calls to |trial| returning + * false is (1-P)^n. The longer a run we require, the more the likelihood + * drops. Further calls may return false too, but this is the probability + * we'll skip at least n. + * + * This is interesting, because we can pick a point along this line segment + * and see which skip count's range it falls within; the point X above, for + * example, is within the ">= 2" range, but not within the ">= 3" range, so it + * designates a skip count of 2. So if we pick points on the line at random + * and use the skip counts they fall under, that will be indistinguishable + * from generating a fresh random number between 0 and 1 for each trial and + * comparing it to P. + * + * So to find the skip count for a point X, we must ask: To what whole power + * must we raise 1-P such that we include X, but the next power would exclude + * it? This is exactly std::floor(std::log(X) / std::log(1-P)). + * + * Our algorithm is then, simply: When constructed, compute an initial skip + * count. Return false from |trial| that many times, and then compute a new skip + * count. + * + * For a call to |trial(n)|, if the skip count is greater than n, return false + * and subtract n from the skip count. If the skip count is less than n, + * return true and compute a new skip count. Since each trial is independent, + * it doesn't matter by how much n overshoots the skip count; we can actually + * compute a new skip count at *any* time without affecting the distribution. + * This is really beautiful. + */ + public: + /** + * Construct a fast Bernoulli trial generator. Calls to |trial()| return true + * with probability |aProbability|. Use |aState0| and |aState1| to seed the + * random number generator; both may not be zero. + */ + FastBernoulliTrial(double aProbability, uint64_t aState0, uint64_t aState1) + : mGenerator(aState0, aState1) + { + setProbability(aProbability); + } + + /** + * Return true with probability |mProbability|. Call this each time an event + * occurs, to decide whether to sample it or not. The lower |mProbability| is, + * the faster this function runs. + */ + bool trial() { + if (mSkipCount) { + mSkipCount--; + return false; + } + + return chooseSkipCount(); + } + + /** + * Equivalent to calling trial() |n| times, and returning true if any of those + * calls do. However, like trial, this runs in fast constant time. + * + * What is this good for? In some applications, some events are "bigger" than + * others. For example, large allocations are more significant than small + * allocations. Perhaps we'd like to imagine that we're drawing allocations + * from a stream of bytes, and performing a separate Bernoulli trial on every + * byte from the stream. We can accomplish this by calling |t.trial(S)| for + * the number of bytes S, and sampling the event if that returns true. + * + * Of course, this style of sampling needs to be paired with analysis and + * presentation that makes the "size" of the event apparent, lest trials with + * large values for |n| appear to be indistinguishable from those with small + * values for |n|, despite being potentially much more likely to be sampled. + */ + bool trial(size_t aCount) { + if (mSkipCount > aCount) { + mSkipCount -= aCount; + return false; + } + + return chooseSkipCount(); + } + + void setRandomState(uint64_t aState0, uint64_t aState1) { + mGenerator.setState(aState0, aState1); + } + + void setProbability(double aProbability) { + MOZ_ASSERT(0 <= aProbability && aProbability <= 1); + mProbability = aProbability; + if (0 < mProbability && mProbability < 1) { + /* + * Let's look carefully at how this calculation plays out in floating- + * point arithmetic. We'll assume IEEE, but the final C++ code we arrive + * at would still be fine if our numbers were mathematically perfect. So, + * while we've considered IEEE's edge cases, we haven't done anything that + * should be actively bad when using other representations. + * + * (In the below, read comparisons as exact mathematical comparisons: when + * we say something "equals 1", that means it's exactly equal to 1. We + * treat approximation using intervals with open boundaries: saying a + * value is in (0,1) doesn't specify how close to 0 or 1 the value gets. + * When we use closed boundaries like [2**-53, 1], we're careful to ensure + * the boundary values are actually representable.) + * + * - After the comparison above, we know mProbability is in (0,1). + * + * - The gaps below 1 are 2**-53, so that interval is (0, 1-2**-53]. + * + * - Because the floating-point gaps near 1 are wider than those near + * zero, there are many small positive doubles ε such that 1-ε rounds to + * exactly 1. However, 2**-53 can be represented exactly. So + * 1-mProbability is in [2**-53, 1]. + * + * - log(1 - mProbability) is thus in (-37, 0]. + * + * That range includes zero, but when we use mInvLogNotProbability, it + * would be helpful if we could trust that it's negative. So when log(1 + * - mProbability) is 0, we'll just set mProbability to 0, so that + * mInvLogNotProbability is not used in chooseSkipCount. + * + * - How much of the range of mProbability does this cause us to ignore? + * The only value for which log returns 0 is exactly 1; the slope of log + * at 1 is 1, so for small ε such that 1 - ε != 1, log(1 - ε) is -ε, + * never 0. The gaps near one are larger than the gaps near zero, so if + * 1 - ε wasn't 1, then -ε is representable. So if log(1 - mProbability) + * isn't 0, then 1 - mProbability isn't 1, which means that mProbability + * is at least 2**-53, as discussed earlier. This is a sampling + * likelihood of roughly one in ten trillion, which is unlikely to be + * distinguishable from zero in practice. + * + * So by forbidding zero, we've tightened our range to (-37, -2**-53]. + * + * - Finally, 1 / log(1 - mProbability) is in [-2**53, -1/37). This all + * falls readily within the range of an IEEE double. + * + * ALL THAT HAVING BEEN SAID: here are the five lines of actual code: + */ + double logNotProbability = std::log(1 - mProbability); + if (logNotProbability == 0.0) + mProbability = 0.0; + else + mInvLogNotProbability = 1 / logNotProbability; + } + + chooseSkipCount(); + } + + private: + /* The likelihood that any given call to |trial| should return true. */ + double mProbability; + + /* + * The value of 1/std::log(1 - mProbability), cached for repeated use. + * + * If mProbability is exactly 0 or exactly 1, we don't use this value. + * Otherwise, we guarantee this value is in the range [-2**53, -1/37), i.e. + * definitely negative, as required by chooseSkipCount. See setProbability for + * the details. + */ + double mInvLogNotProbability; + + /* Our random number generator. */ + non_crypto::XorShift128PlusRNG mGenerator; + + /* The number of times |trial| should return false before next returning true. */ + size_t mSkipCount; + + /* + * Choose the next skip count. This also returns the value that |trial| should + * return, since we have to check for the extreme values for mProbability + * anyway, and |trial| should never return true at all when mProbability is 0. + */ + bool chooseSkipCount() { + /* + * If the probability is 1.0, every call to |trial| returns true. Make sure + * mSkipCount is 0. + */ + if (mProbability == 1.0) { + mSkipCount = 0; + return true; + } + + /* + * If the probabilility is zero, |trial| never returns true. Don't bother us + * for a while. + */ + if (mProbability == 0.0) { + mSkipCount = SIZE_MAX; + return false; + } + + /* + * What sorts of values can this call to std::floor produce? + * + * Since mGenerator.nextDouble returns a value in [0, 1-2**-53], std::log + * returns a value in the range [-infinity, -2**-53], all negative. Since + * mInvLogNotProbability is negative (see its comments), the product is + * positive and possibly infinite. std::floor returns +infinity unchanged. + * So the result will always be positive. + * + * Converting a double to an integer that is out of range for that integer + * is undefined behavior, so we must clamp our result to SIZE_MAX, to ensure + * we get an acceptable value for mSkipCount. + * + * The clamp is written carefully. Note that if we had said: + * + * if (skipCount > SIZE_MAX) + * skipCount = SIZE_MAX; + * + * that leads to undefined behavior 64-bit machines: SIZE_MAX coerced to + * double is 2^64, not 2^64-1, so this doesn't actually set skipCount to a + * value that can be safely assigned to mSkipCount. + * + * Jakub Oleson cleverly suggested flipping the sense of the comparison: if + * we require that skipCount < SIZE_MAX, then because of the gaps (2048) + * between doubles at that magnitude, the highest double less than 2^64 is + * 2^64 - 2048, which is fine to store in a size_t. + * + * (On 32-bit machines, all size_t values can be represented exactly in + * double, so all is well.) + */ + double skipCount = std::floor(std::log(mGenerator.nextDouble()) + * mInvLogNotProbability); + if (skipCount < SIZE_MAX) + mSkipCount = skipCount; + else + mSkipCount = SIZE_MAX; + + return true; + } +}; + +} /* namespace mozilla */ + +#endif /* mozilla_FastBernoulliTrial_h */ diff --git a/mfbt/double-conversion/fix-aarch64-macro.patch b/mfbt/double-conversion/fix-aarch64-macro.patch deleted file mode 100644 index 2338c7fbee..0000000000 --- a/mfbt/double-conversion/fix-aarch64-macro.patch +++ /dev/null @@ -1,23 +0,0 @@ -Backport from upstream. - -https://code.google.com/p/double-conversion/source/detail?r=4e24bb31bcc76d6d218f3056b4c24a109d367561 - ---- - mfbt/double-conversion/utils.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/mfbt/double-conversion/utils.h -+++ b/mfbt/double-conversion/utils.h -@@ -58,11 +58,11 @@ - defined(__mips__) || \ - defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \ - defined(__sparc__) || defined(__sparc) || defined(__s390__) || \ - defined(__SH4__) || defined(__alpha__) || \ - defined(_MIPS_ARCH_MIPS32R2) || \ -- defined(_AARCH64EL_) -+ defined(__AARCH64EL__) - #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 - #elif defined(_M_IX86) || defined(__i386__) || defined(__i386) - #if defined(_WIN32) - // Windows uses a 64bit wide floating point stack. - #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 diff --git a/mfbt/double-conversion/fix-gcc-warnings.patch b/mfbt/double-conversion/fix-gcc-warnings.patch deleted file mode 100644 index 4e13dd0b08..0000000000 --- a/mfbt/double-conversion/fix-gcc-warnings.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/a/mfbt/double-conversion/strtod.cc b/inbound/mfbt/double-conversion/strtod.cc -index 9758989..97fa4a5 100644 ---- a/a/mfbt/double-conversion/strtod.cc -+++ b/inbound/mfbt/double-conversion/strtod.cc -@@ -501,17 +501,19 @@ float Strtof(Vector buffer, int exponent) { - // if they would round to the same float. If the guess is not correct we have - // to look at four values (since two different doubles could be the correct - // double). - - double double_next = Double(double_guess).NextDouble(); - double double_previous = Double(double_guess).PreviousDouble(); - - float f1 = static_cast(double_previous); -+#if defined(DEBUG) - float f2 = float_guess; -+#endif - float f3 = static_cast(double_next); - float f4; - if (is_correct) { - f4 = f3; - } else { - double double_next2 = Double(double_next).NextDouble(); - f4 = static_cast(double_next2); - } diff --git a/mfbt/double-conversion/strtod.cc b/mfbt/double-conversion/strtod.cc index 97fa4a58a9..b097afe0eb 100644 --- a/mfbt/double-conversion/strtod.cc +++ b/mfbt/double-conversion/strtod.cc @@ -506,9 +506,7 @@ float Strtof(Vector buffer, int exponent) { double double_previous = Double(double_guess).PreviousDouble(); float f1 = static_cast(double_previous); -#if defined(DEBUG) float f2 = float_guess; -#endif float f3 = static_cast(double_next); float f4; if (is_correct) { @@ -517,6 +515,7 @@ float Strtof(Vector buffer, int exponent) { double double_next2 = Double(double_next).NextDouble(); f4 = static_cast(double_next2); } + (void) f2; // Mark variable as used. ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4); // If the guess doesn't lie near a single-precision boundary we can simply diff --git a/mfbt/double-conversion/update.sh b/mfbt/double-conversion/update.sh index 8bdd655e00..22233b92b4 100755 --- a/mfbt/double-conversion/update.sh +++ b/mfbt/double-conversion/update.sh @@ -21,7 +21,3 @@ patch -p3 < use-StandardInteger.patch patch -p3 < use-mozilla-assertions.patch patch -p3 < use-static_assert.patch patch -p3 < ToPrecision-exponential.patch -patch -p3 < fix-gcc-warnings.patch - -# Merged upstream, part of 2.0.1 version -patch -p3 < fix-aarch64-macro.patch diff --git a/mfbt/double-conversion/utils.h b/mfbt/double-conversion/utils.h index 21ff12aafc..15dd4bfb3b 100644 --- a/mfbt/double-conversion/utils.h +++ b/mfbt/double-conversion/utils.h @@ -60,7 +60,7 @@ defined(__sparc__) || defined(__sparc) || defined(__s390__) || \ defined(__SH4__) || defined(__alpha__) || \ defined(_MIPS_ARCH_MIPS32R2) || \ - defined(__AARCH64EL__) + defined(__AARCH64EL__) || defined(__aarch64__) #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 #elif defined(_M_IX86) || defined(__i386__) || defined(__i386) #if defined(_WIN32) @@ -141,8 +141,8 @@ template class Vector { public: Vector() : start_(NULL), length_(0) {} - Vector(T* data, int length) : start_(data), length_(length) { - ASSERT(length == 0 || (length > 0 && data != NULL)); + Vector(T* data, int len) : start_(data), length_(len) { + ASSERT(len == 0 || (len > 0 && data != NULL)); } // Returns a vector using the same backing storage as this one, @@ -184,8 +184,8 @@ class Vector { // buffer bounds on all operations in debug mode. class StringBuilder { public: - StringBuilder(char* buffer, int size) - : buffer_(buffer, size), position_(0) { } + StringBuilder(char* buffer, int buffer_size) + : buffer_(buffer, buffer_size), position_(0) { } ~StringBuilder() { if (!is_finalized()) Finalize(); } diff --git a/mfbt/moz.build b/mfbt/moz.build index 46e5ee248b..b0669e01f5 100644 --- a/mfbt/moz.build +++ b/mfbt/moz.build @@ -39,6 +39,7 @@ EXPORTS.mozilla = [ 'EnumeratedArray.h', 'EnumeratedRange.h', 'EnumSet.h', + 'FastBernoulliTrial.h', 'FloatingPoint.h', 'Function.h', 'GuardObjects.h', diff --git a/mfbt/tests/TestFastBernoulliTrial.cpp b/mfbt/tests/TestFastBernoulliTrial.cpp new file mode 100644 index 0000000000..62d4b51a79 --- /dev/null +++ b/mfbt/tests/TestFastBernoulliTrial.cpp @@ -0,0 +1,209 @@ +/* -*- 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 "mozilla/Assertions.h" +#include "mozilla/FastBernoulliTrial.h" + +#include + +// Note that because we always provide FastBernoulliTrial with a fixed +// pseudorandom seed in these tests, the results here are completely +// deterministic. +// +// A non-optimized version of this test runs in .009s on my laptop. Using larger +// sample sizes lets us meet tighter bounds on the counts. + +static void +TestProportions() +{ + mozilla::FastBernoulliTrial bernoulli(1.0, + 698079309544035222ULL, + 6012389156611637584ULL); + + for (size_t i = 0; i < 100; i++) + MOZ_RELEASE_ASSERT(bernoulli.trial()); + + { + bernoulli.setProbability(0.5); + size_t count = 0; + for (size_t i = 0; i < 1000; i++) + count += bernoulli.trial(); + MOZ_RELEASE_ASSERT(count == 496); + } + + { + bernoulli.setProbability(0.001); + size_t count = 0; + for (size_t i = 0; i < 1000; i++) + count += bernoulli.trial(); + MOZ_RELEASE_ASSERT(count == 2); + } + + { + bernoulli.setProbability(0.85); + size_t count = 0; + for (size_t i = 0; i < 1000; i++) + count += bernoulli.trial(); + MOZ_RELEASE_ASSERT(count == 852); + } + + bernoulli.setProbability(0.0); + for (size_t i = 0; i < 100; i++) + MOZ_RELEASE_ASSERT(!bernoulli.trial()); +} + +static void +TestHarmonics() +{ + mozilla::FastBernoulliTrial bernoulli(0.1, + 698079309544035222ULL, + 6012389156611637584ULL); + + const size_t n = 100000; + bool trials[n]; + for (size_t i = 0; i < n; i++) + trials[i] = bernoulli.trial(); + + // For each harmonic and phase, check that the proportion sampled is + // within acceptable bounds. + for (size_t harmonic = 1; harmonic < 20; harmonic++) { + size_t expected = n / harmonic / 10; + size_t low_expected = expected * 85 / 100; + size_t high_expected = expected * 115 / 100; + + for (size_t phase = 0; phase < harmonic; phase++) { + size_t count = 0; + for (size_t i = phase; i < n; i += harmonic) + count += trials[i]; + + MOZ_RELEASE_ASSERT(low_expected <= count && count <= high_expected); + } + } +} + +static void +TestTrialN() +{ + mozilla::FastBernoulliTrial bernoulli(0.01, + 0x67ff17e25d855942ULL, + 0x74f298193fe1c5b1ULL); + + { + size_t count = 0; + for (size_t i = 0; i < 10000; i++) + count += bernoulli.trial(1); + + // Expected value: 0.01 * 10000 == 100 + MOZ_RELEASE_ASSERT(count == 97); + } + + { + size_t count = 0; + for (size_t i = 0; i < 10000; i++) + count += bernoulli.trial(3); + + // Expected value: (1 - (1 - 0.01) ** 3) == 0.0297, + // 0.0297 * 10000 == 297 + MOZ_RELEASE_ASSERT(count == 304); + } + + { + size_t count = 0; + for (size_t i = 0; i < 10000; i++) + count += bernoulli.trial(10); + + // Expected value: (1 - (1 - 0.01) ** 10) == 0.0956, + // 0.0956 * 10000 == 956 + MOZ_RELEASE_ASSERT(count == 936); + } + + { + size_t count = 0; + for (size_t i = 0; i < 10000; i++) + count += bernoulli.trial(100); + + // Expected value: (1 - (1 - 0.01) ** 100) == 0.6339 + // 0.6339 * 10000 == 6339 + MOZ_RELEASE_ASSERT(count == 6372); + } + + { + size_t count = 0; + for (size_t i = 0; i < 10000; i++) + count += bernoulli.trial(1000); + + // Expected value: (1 - (1 - 0.01) ** 1000) == 0.9999 + // 0.9999 * 10000 == 9999 + MOZ_RELEASE_ASSERT(count == 9998); + } +} + +static void +TestChangeProbability() +{ + mozilla::FastBernoulliTrial bernoulli(1.0, + 0x67ff17e25d855942ULL, + 0x74f298193fe1c5b1ULL); + + // Establish a very high skip count. + bernoulli.setProbability(0.0); + + // This should re-establish a zero skip count. + bernoulli.setProbability(1.0); + + // So this should return true. + MOZ_RELEASE_ASSERT(bernoulli.trial()); +} + +static void +TestCuspProbabilities() +{ + /* + * FastBernoulliTrial takes care to avoid screwing up on edge cases. The + * checks here all look pretty dumb, but they exercise paths in the code that + * could exhibit undefined behavior if coded naïvely. + */ + + /* + * This should not be perceptibly different from 1; for 64-bit doubles, this + * is a one in ten trillion chance of the trial not succeeding. Overflows + * converting doubles to size_t skip counts may change this, though. + */ + mozilla::FastBernoulliTrial bernoulli(nextafter(1, 0), + 0x67ff17e25d855942ULL, + 0x74f298193fe1c5b1ULL); + + for (size_t i = 0; i < 1000; i++) + MOZ_RELEASE_ASSERT(bernoulli.trial()); + + /* + * This should not be perceptibly different from 0; for 64-bit doubles, + * the FastBernoulliTrial will actually treat this as exactly zero. + */ + bernoulli.setProbability(nextafter(0, 1)); + for (size_t i = 0; i < 1000; i++) + MOZ_RELEASE_ASSERT(!bernoulli.trial()); + + /* + * This should be a vanishingly low probability which FastBernoulliTrial does + * *not* treat as exactly zero. + */ + bernoulli.setProbability(1 - nextafter(1, 0)); + for (size_t i = 0; i < 1000; i++) + MOZ_RELEASE_ASSERT(!bernoulli.trial()); +} + +int +main() +{ + TestProportions(); + TestHarmonics(); + TestTrialN(); + TestChangeProbability(); + TestCuspProbabilities(); + + return 0; +} diff --git a/mfbt/tests/moz.build b/mfbt/tests/moz.build index 2621ce2479..8b6133ac77 100644 --- a/mfbt/tests/moz.build +++ b/mfbt/tests/moz.build @@ -16,6 +16,7 @@ CppUnitTests([ 'TestCountZeroes', 'TestEndian', 'TestEnumSet', + 'TestFastBernoulliTrial', 'TestFloatingPoint', 'TestFunction', 'TestInitializerList', diff --git a/modules/libjar/zipwriter/nsDeflateConverter.cpp b/modules/libjar/zipwriter/nsDeflateConverter.cpp index 40ee1b8343..b83d2286fe 100644 --- a/modules/libjar/zipwriter/nsDeflateConverter.cpp +++ b/modules/libjar/zipwriter/nsDeflateConverter.cpp @@ -60,8 +60,6 @@ nsresult nsDeflateConverter::Init() return NS_OK; } -/* nsIInputStream convert (in nsIInputStream aFromStream, in string aFromType - * in string aToType, in nsISupports aCtxt); */ NS_IMETHODIMP nsDeflateConverter::Convert(nsIInputStream *aFromStream, const char *aFromType, const char *aToType, @@ -71,9 +69,6 @@ NS_IMETHODIMP nsDeflateConverter::Convert(nsIInputStream *aFromStream, return NS_ERROR_NOT_IMPLEMENTED; } -/* void asyncConvertData (in string aFromType, in string aToType, - * in nsIStreamListener aListener, - * in nsISupports aCtxt); */ NS_IMETHODIMP nsDeflateConverter::AsyncConvertData(const char *aFromType, const char *aToType, nsIStreamListener *aListener, @@ -100,10 +95,6 @@ NS_IMETHODIMP nsDeflateConverter::AsyncConvertData(const char *aFromType, return rv; } -/* void onDataAvailable (in nsIRequest aRequest, in nsISupports aContext, - * in nsIInputStream aInputStream, - * in unsigned long long aOffset, - * in unsigned long aCount); */ NS_IMETHODIMP nsDeflateConverter::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, nsIInputStream *aInputStream, @@ -148,8 +139,6 @@ NS_IMETHODIMP nsDeflateConverter::OnStartRequest(nsIRequest *aRequest, return mListener->OnStartRequest(aRequest, mContext); } -/* void onStopRequest (in nsIRequest aRequest, in nsISupports aContext, - * in nsresult aStatusCode); */ NS_IMETHODIMP nsDeflateConverter::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatusCode) diff --git a/modules/libjar/zipwriter/nsZipDataStream.cpp b/modules/libjar/zipwriter/nsZipDataStream.cpp index 4b3b7b18c1..b545dc9d02 100644 --- a/modules/libjar/zipwriter/nsZipDataStream.cpp +++ b/modules/libjar/zipwriter/nsZipDataStream.cpp @@ -59,9 +59,6 @@ nsresult nsZipDataStream::Init(nsZipWriter *aWriter, return NS_OK; } -/* void onDataAvailable (in nsIRequest aRequest, in nsISupports aContext, - * in nsIInputStream aInputStream, - * in unsigned long long aOffset, in unsigned long aCount); */ NS_IMETHODIMP nsZipDataStream::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, nsIInputStream *aInputStream, @@ -89,8 +86,6 @@ NS_IMETHODIMP nsZipDataStream::OnStartRequest(nsIRequest *aRequest, return mOutput->OnStartRequest(aRequest, aContext); } -/* void onStopRequest (in nsIRequest aRequest, in nsISupports aContext, - * in nsresult aStatusCode); */ NS_IMETHODIMP nsZipDataStream::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatusCode) diff --git a/modules/libjar/zipwriter/nsZipWriter.cpp b/modules/libjar/zipwriter/nsZipWriter.cpp index d2054dde57..cd2060116c 100644 --- a/modules/libjar/zipwriter/nsZipWriter.cpp +++ b/modules/libjar/zipwriter/nsZipWriter.cpp @@ -302,8 +302,6 @@ NS_IMETHODIMP nsZipWriter::HasEntry(const nsACString & aZipEntry, return NS_OK; } -/* void addEntryDirectory (in AUTF8String aZipEntry, in PRTime aModTime, - * in boolean aQueue); */ NS_IMETHODIMP nsZipWriter::AddEntryDirectory(const nsACString & aZipEntry, PRTime aModTime, bool aQueue) { @@ -326,8 +324,6 @@ NS_IMETHODIMP nsZipWriter::AddEntryDirectory(const nsACString & aZipEntry, return InternalAddEntryDirectory(aZipEntry, aModTime, PERMISSIONS_DIR); } -/* void addEntryFile (in AUTF8String aZipEntry, in int32_t aCompression, - * in nsIFile aFile, in boolean aQueue); */ NS_IMETHODIMP nsZipWriter::AddEntryFile(const nsACString & aZipEntry, int32_t aCompression, nsIFile *aFile, bool aQueue) @@ -389,9 +385,6 @@ NS_IMETHODIMP nsZipWriter::AddEntryFile(const nsACString & aZipEntry, return inputStream->Close(); } -/* void addEntryChannel (in AUTF8String aZipEntry, in PRTime aModTime, - * in int32_t aCompression, in nsIChannel aChannel, - * in boolean aQueue); */ NS_IMETHODIMP nsZipWriter::AddEntryChannel(const nsACString & aZipEntry, PRTime aModTime, int32_t aCompression, @@ -431,9 +424,6 @@ NS_IMETHODIMP nsZipWriter::AddEntryChannel(const nsACString & aZipEntry, return inputStream->Close(); } -/* void addEntryStream (in AUTF8String aZipEntry, in PRTime aModTime, - * in int32_t aCompression, in nsIInputStream aStream, - * in boolean aQueue); */ NS_IMETHODIMP nsZipWriter::AddEntryStream(const nsACString & aZipEntry, PRTime aModTime, int32_t aCompression, @@ -444,9 +434,6 @@ NS_IMETHODIMP nsZipWriter::AddEntryStream(const nsACString & aZipEntry, PERMISSIONS_FILE); } -/* void addEntryStream (in AUTF8String aZipEntry, in PRTime aModTime, - * in int32_t aCompression, in nsIInputStream aStream, - * in boolean aQueue, in unsigned long aPermissions); */ nsresult nsZipWriter::AddEntryStream(const nsACString & aZipEntry, PRTime aModTime, int32_t aCompression, @@ -597,8 +584,6 @@ NS_IMETHODIMP nsZipWriter::RemoveEntry(const nsACString & aZipEntry, return NS_ERROR_FILE_NOT_FOUND; } -/* void processQueue (in nsIRequestObserver aObserver, - * in nsISupports aContext); */ NS_IMETHODIMP nsZipWriter::ProcessQueue(nsIRequestObserver *aObserver, nsISupports *aContext) { @@ -702,8 +687,6 @@ NS_IMETHODIMP nsZipWriter::OnStartRequest(nsIRequest *aRequest, return NS_OK; } -/* void onStopRequest (in nsIRequest aRequest, in nsISupports aContext, - * in nsresult aStatusCode); */ NS_IMETHODIMP nsZipWriter::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatusCode) diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 05e8740967..7c9e7f85ec 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -566,8 +566,6 @@ pref("layout.event-regions.enabled", false); // gfx/layers/apz/src/AsyncPanZoomController.cpp. pref("apz.allow_checkerboarding", true); pref("apz.allow_zooming", false); -pref("apz.asyncscroll.throttle", 100); -pref("apz.asyncscroll.timeout", 300); // Whether to lock touch scrolling to one axis at a time // 0 = FREE (No locking at all) @@ -4471,6 +4469,7 @@ pref("webgl.vendor-string-override", ""); pref("webgl.angle.try-d3d11", true); pref("webgl.angle.force-d3d11", false); pref("webgl.angle.force-warp", false); +pref("webgl.dxgl.enabled", false); #endif pref("gfx.offscreencanvas.enabled", false); diff --git a/netwerk/base/LoadContextInfo.cpp b/netwerk/base/LoadContextInfo.cpp index 5f93899849..796f58bd98 100644 --- a/netwerk/base/LoadContextInfo.cpp +++ b/netwerk/base/LoadContextInfo.cpp @@ -56,7 +56,6 @@ NS_IMETHODIMP LoadContextInfo::GetOriginAttributes(JSContext *aCx, NS_IMPL_ISUPPORTS(LoadContextInfoFactory, nsILoadContextInfoFactory) -/* readonly attribute nsILoadContextInfo default; */ NS_IMETHODIMP LoadContextInfoFactory::GetDefault(nsILoadContextInfo * *aDefault) { nsCOMPtr info = GetLoadContextInfo(false, false, OriginAttributes()); @@ -64,7 +63,6 @@ NS_IMETHODIMP LoadContextInfoFactory::GetDefault(nsILoadContextInfo * *aDefault) return NS_OK; } -/* readonly attribute nsILoadContextInfo private; */ NS_IMETHODIMP LoadContextInfoFactory::GetPrivate(nsILoadContextInfo * *aPrivate) { nsCOMPtr info = GetLoadContextInfo(true, false, OriginAttributes()); @@ -72,7 +70,6 @@ NS_IMETHODIMP LoadContextInfoFactory::GetPrivate(nsILoadContextInfo * *aPrivate) return NS_OK; } -/* readonly attribute nsILoadContextInfo anonymous; */ NS_IMETHODIMP LoadContextInfoFactory::GetAnonymous(nsILoadContextInfo * *aAnonymous) { nsCOMPtr info = GetLoadContextInfo(false, true, OriginAttributes()); @@ -80,7 +77,6 @@ NS_IMETHODIMP LoadContextInfoFactory::GetAnonymous(nsILoadContextInfo * *aAnonym return NS_OK; } -/* nsILoadContextInfo custom (in boolean aPrivate, in boolean aAnonymous, in jsval aOriginAttributes); */ NS_IMETHODIMP LoadContextInfoFactory::Custom(bool aPrivate, bool aAnonymous, JS::HandleValue aOriginAttributes, JSContext *cx, nsILoadContextInfo * *_retval) @@ -94,7 +90,6 @@ NS_IMETHODIMP LoadContextInfoFactory::Custom(bool aPrivate, bool aAnonymous, return NS_OK; } -/* nsILoadContextInfo fromLoadContext (in nsILoadContext aLoadContext, in boolean aAnonymous); */ NS_IMETHODIMP LoadContextInfoFactory::FromLoadContext(nsILoadContext *aLoadContext, bool aAnonymous, nsILoadContextInfo * *_retval) { @@ -103,7 +98,6 @@ NS_IMETHODIMP LoadContextInfoFactory::FromLoadContext(nsILoadContext *aLoadConte return NS_OK; } -/* nsILoadContextInfo fromWindow (in nsIDOMWindow aWindow, in boolean aAnonymous); */ NS_IMETHODIMP LoadContextInfoFactory::FromWindow(nsIDOMWindow *aWindow, bool aAnonymous, nsILoadContextInfo * *_retval) { diff --git a/netwerk/cache/nsCacheService.cpp b/netwerk/cache/nsCacheService.cpp index fda6954d38..0e24b9f4f8 100644 --- a/netwerk/cache/nsCacheService.cpp +++ b/netwerk/cache/nsCacheService.cpp @@ -1568,9 +1568,6 @@ NS_IMETHODIMP nsCacheService::GetCacheIOTarget(nsIEventTarget * *aCacheIOTarget) return rv; } -/* nsICacheServiceInternal - * readonly attribute double lockHeldTime; -*/ NS_IMETHODIMP nsCacheService::GetLockHeldTime(double *aLockHeldTime) { MutexAutoLock lock(mTimeStampLock); diff --git a/security/manager/pki/nsNSSDialogs.cpp b/security/manager/pki/nsNSSDialogs.cpp index cddbc50f2e..068caf9d67 100644 --- a/security/manager/pki/nsNSSDialogs.cpp +++ b/security/manager/pki/nsNSSDialogs.cpp @@ -82,7 +82,6 @@ nsNSSDialogs::SetPassword(nsIInterfaceRequestor *ctx, do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID); if (!block) return NS_ERROR_FAILURE; - // void ChangePassword(in wstring tokenName, out int status); rv = block->SetString(1, tokenName); if (NS_FAILED(rv)) return rv; diff --git a/security/manager/ssl/CertBlocklist.cpp b/security/manager/ssl/CertBlocklist.cpp index 43f0063752..e5068833cf 100644 --- a/security/manager/ssl/CertBlocklist.cpp +++ b/security/manager/ssl/CertBlocklist.cpp @@ -288,7 +288,6 @@ CertBlocklist::EnsureBackingFileInitialized(MutexAutoLock& lock) return NS_OK; } -// void revokeCertBySubjectAndPubKey(in string subject, in string pubKeyHash); NS_IMETHODIMP CertBlocklist::RevokeCertBySubjectAndPubKey(const char* aSubject, const char* aPubKeyHash) @@ -304,7 +303,6 @@ CertBlocklist::RevokeCertBySubjectAndPubKey(const char* aSubject, CertNewFromBlocklist, lock); } -// void revokeCertByIssuerAndSerial(in string issuer, in string serialNumber); NS_IMETHODIMP CertBlocklist::RevokeCertByIssuerAndSerial(const char* aIssuer, const char* aSerialNumber) @@ -507,14 +505,6 @@ CertBlocklist::SaveEntries() return NS_OK; } -// boolean isCertRevoked([const, array, size_is(issuerLength)] in octet issuer, -// in unsigned long issuerLength, -// [const, array, size_is(serialLength)] in octet serial, -// in unsigned long serialLength), -// [const, array, size_is(subject_length)] in octet subject, -// in unsigned long subject_length, -// [const, array, size_is(pubkey_length)] in octet pubkey, -// in unsigned long pubkey_length); NS_IMETHODIMP CertBlocklist::IsCertRevoked(const uint8_t* aIssuer, uint32_t aIssuerLength, diff --git a/security/manager/ssl/nsCertTree.cpp b/security/manager/ssl/nsCertTree.cpp index 9527579fe0..5456cf4542 100644 --- a/security/manager/ssl/nsCertTree.cpp +++ b/security/manager/ssl/nsCertTree.cpp @@ -1282,9 +1282,6 @@ nsCertTree::PerformActionOnRow(const char16_t *action, int32_t row) return NS_OK; } -/* void performActionOnCell (in wstring action, in long row, - * in wstring colID); - */ NS_IMETHODIMP nsCertTree::PerformActionOnCell(const char16_t *action, int32_t row, nsITreeColumn* col) diff --git a/security/manager/ssl/nsNSSCertificateDB.cpp b/security/manager/ssl/nsNSSCertificateDB.cpp index 50d9c6a7f3..e2efb479c6 100644 --- a/security/manager/ssl/nsNSSCertificateDB.cpp +++ b/security/manager/ssl/nsNSSCertificateDB.cpp @@ -437,11 +437,6 @@ nsNSSCertificateDB::handleCACertDownload(nsIArray *x509Certs, return ImportValidCACertsInList(certList.get(), ctx, proofOfLock); } -/* - * [noscript] void importCertificates(in charPtr data, in unsigned long length, - * in unsigned long type, - * in nsIInterfaceRequestor ctx); - */ NS_IMETHODIMP nsNSSCertificateDB::ImportCertificates(uint8_t * data, uint32_t length, uint32_t type, @@ -531,10 +526,6 @@ ImportCertsIntoPermanentStorage( } -/* - * [noscript] void importEmailCertificates(in charPtr data, in unsigned long length, - * in nsIInterfaceRequestor ctx); - */ NS_IMETHODIMP nsNSSCertificateDB::ImportEmailCertificate(uint8_t * data, uint32_t length, nsIInterfaceRequestor *ctx) @@ -932,9 +923,6 @@ loser: return rv; } -/* - * void deleteCertificate(in nsIX509Cert aCert); - */ NS_IMETHODIMP nsNSSCertificateDB::DeleteCertificate(nsIX509Cert *aCert) { @@ -971,11 +959,6 @@ nsNSSCertificateDB::DeleteCertificate(nsIX509Cert *aCert) return (srv) ? NS_ERROR_FAILURE : NS_OK; } -/* - * void setCertTrust(in nsIX509Cert cert, - * in unsigned long type, - * in unsigned long trust); - */ NS_IMETHODIMP nsNSSCertificateDB::SetCertTrust(nsIX509Cert *cert, uint32_t type, diff --git a/security/manager/ssl/nsPK11TokenDB.cpp b/security/manager/ssl/nsPK11TokenDB.cpp index ca769eba82..540055cc87 100644 --- a/security/manager/ssl/nsPK11TokenDB.cpp +++ b/security/manager/ssl/nsPK11TokenDB.cpp @@ -329,9 +329,6 @@ nsPK11Token::GetAskPasswordTimeout(int32_t *rvAskTimeout) return NS_OK; } -/* void setAskPasswordDefaults(in unsigned long askTimes, - * in unsigned long timeout); - */ NS_IMETHODIMP nsPK11Token::SetAskPasswordDefaults(const int32_t askTimes, const int32_t askTimeout) diff --git a/security/manager/ssl/nsRandomGenerator.cpp b/security/manager/ssl/nsRandomGenerator.cpp index a97de7e7cd..3672924515 100644 --- a/security/manager/ssl/nsRandomGenerator.cpp +++ b/security/manager/ssl/nsRandomGenerator.cpp @@ -11,8 +11,6 @@ NS_IMPL_ISUPPORTS(nsRandomGenerator, nsIRandomGenerator) -// void generateRandomBytes(in unsigned long aLength, -// [retval, array, size_is(aLength)] out octet aBuffer) NS_IMETHODIMP nsRandomGenerator::GenerateRandomBytes(uint32_t aLength, uint8_t** aBuffer) diff --git a/xpcom/io/nsMultiplexInputStream.cpp b/xpcom/io/nsMultiplexInputStream.cpp index c4b6bc75cc..c72ff0de9b 100644 --- a/xpcom/io/nsMultiplexInputStream.cpp +++ b/xpcom/io/nsMultiplexInputStream.cpp @@ -295,9 +295,6 @@ nsMultiplexInputStream::Read(char* aBuf, uint32_t aCount, uint32_t* aResult) return *aResult ? NS_OK : rv; } -/* [noscript] unsigned long readSegments (in nsWriteSegmentFun writer, - * in voidPtr closure, - * in unsigned long count); */ NS_IMETHODIMP nsMultiplexInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount, uint32_t* aResult)