diff --git a/application/palemoon/app/profile/palemoon.js b/application/palemoon/app/profile/palemoon.js index e9324df95d..a239946668 100644 --- a/application/palemoon/app/profile/palemoon.js +++ b/application/palemoon/app/profile/palemoon.js @@ -507,6 +507,12 @@ pref("javascript.options.showInConsole", true); pref("general.warnOnAboutConfig", false); #endif +// Enable unlinking of ghost windows so they can be garbage collected. +pref("browser.ghostbuster.enabled", true); +// Disable GC on memory pressure, avoid incessant recycling when websites +// misbehave. Should also avoid spurious GCs during ghostbusting. +pref("javascript.options.gc_on_memory_pressure", false); + // This is the pref to control the location bar, change this to true to // force this - this makes the origin of popup windows more obvious to avoid // spoofing. We would rather not do it by default because it affects UE for web @@ -576,8 +582,8 @@ pref("network.http.pipelining.ssl", true); pref("network.predictor.enabled", false); pref("network.prefetch-next", false); -// Disable DNS prefetching -pref("network.dns.disablePrefetch", true); +// Enable DNS prefetching +pref("network.dns.disablePrefetch", false); // Tune DNS lookups pref("network.dnsCacheEntries", 800); @@ -631,7 +637,7 @@ pref("browser.xul.error_pages.expert_bad_cert", false); // Work Offline is best manually managed by the user. pref("network.manage-offline-status", false); -// We want to make sure mail URLs are handled externally... +// We want to make sure known external protocol URLs are handled externally. pref("network.protocol-handler.external.mailto", true); // for mail pref("network.protocol-handler.external.news", true); // for news pref("network.protocol-handler.external.snews", true); // for secure news @@ -640,11 +646,11 @@ pref("network.protocol-handler.external.nntp", true); // also news pref("network.protocol-handler.external.ms-windows-store", true); #endif -// ...without warning dialogs +// Configure external handler warning dialogs. pref("network.protocol-handler.warn-external.mailto", false); -pref("network.protocol-handler.warn-external.news", false); -pref("network.protocol-handler.warn-external.snews", false); -pref("network.protocol-handler.warn-external.nntp", false); +pref("network.protocol-handler.warn-external.news", true); +pref("network.protocol-handler.warn-external.snews", true); +pref("network.protocol-handler.warn-external.nntp", true); #ifdef XP_WIN pref("network.protocol-handler.warn-external.ms-windows-store", false); #endif diff --git a/application/palemoon/base/content/tabbrowser.xml b/application/palemoon/base/content/tabbrowser.xml index e630206dc8..bd67ab0903 100644 --- a/application/palemoon/base/content/tabbrowser.xml +++ b/application/palemoon/base/content/tabbrowser.xml @@ -2132,15 +2132,28 @@ } // We're going to remove the tab and the browser now. + + // Interrupt all tab activity to aid in cleaning up detached window objects. + // Using the "STOP_ALL" flag should halt all animations, fetches, network + // activity, etc. to come to a clean state for removal and unlinking (if enabled). + var browser = this.getBrowserForTab(aTab); + browser.webNavigation.stop(nsIWebNavigation.STOP_ALL); + // Clean up mTabFilters and mTabListeners now rather than in // _beginRemoveTab, so that their size is always in sync with the // number of tabs and browsers (the xbl destructor depends on this). this.mTabFilters.splice(aTab._tPos, 1); this.mTabListeners.splice(aTab._tPos, 1); - var browser = this.getBrowserForTab(aTab); this._outerWindowIDBrowserMap.delete(browser.outerWindowID); + if (Services.prefs.getBoolPref("browser.ghostbuster.enabled", true)) { + Cu.unlinkGhostWindows(); +#ifdef DEBUG + dump("Unlinking ghost windows has run on tab close.\n"); +#endif + } + // Because of the way XBL works (fields just set JS // properties on the element) and the code we have in place // to preserve the JS objects for any elements that have diff --git a/application/palemoon/components/nsBrowserGlue.js b/application/palemoon/components/nsBrowserGlue.js index 958475a29e..b66881dbf6 100644 --- a/application/palemoon/components/nsBrowserGlue.js +++ b/application/palemoon/components/nsBrowserGlue.js @@ -62,6 +62,10 @@ const BOOKMARKS_BACKUP_INTERVAL = 86400 * 1000; // Maximum number of backups to create. Old ones will be purged. const BOOKMARKS_BACKUP_MAX_BACKUPS = 10; +// Use users' idle time to unlink ghost windows and clean up memory. +// Trigger this by default every 5 minutes. +const GHOSTBUSTER_INTERVAL = 5 * 60; + // Factory object const BrowserGlueServiceFactory = { _instance: null, @@ -82,6 +86,10 @@ function BrowserGlue() { "@mozilla.org/widget/idleservice;1", "nsIIdleService"); + XPCOMUtils.defineLazyServiceGetter(this, "_ghostBusterService", + "@mozilla.org/widget/idleservice;1", + "nsIIdleService"); + XPCOMUtils.defineLazyGetter(this, "_distributionCustomizer", function() { Cu.import("resource:///modules/distribution.js"); return new DistributionCustomizer(); @@ -109,6 +117,7 @@ BrowserGlue.prototype = { _isPlacesShutdownObserver: false, _isPlacesDatabaseLocked: false, _migrationImportsDefaultBookmarks: false, + _isGhostBusterObserver: false, _setPrefToSaveSession: function(aForce) { if (!this._saveSession && !aForce) { @@ -241,6 +250,15 @@ BrowserGlue.prototype = { if (this._idleService.idleTime > BOOKMARKS_BACKUP_IDLE_TIME * 1000) { this._backupBookmarks(); } + if (this._ghostBusterService.idleTime > GHOSTBUSTER_INTERVAL * 1000) { + if (Services.prefs.getBoolPref("browser.ghostbuster.enabled", true)) { + Cu.unlinkGhostWindows(); + Cu.forceGC(); +#ifdef DEBUG + dump("Unlinking ghost windows + GC has run on idle.\n"); +#endif + } + } break; case "distribution-customization-complete": Services.obs.removeObserver(this, "distribution-customization-complete"); @@ -623,6 +641,13 @@ BrowserGlue.prototype = { DateTimePickerHelper.init(); this._trackSlowStartup(); + + // Initialize ghost window idle observer. + if (!this._isGhostBusterObserver) { + this._ghostBusterService.addIdleObserver(this, GHOSTBUSTER_INTERVAL); + // Prevent re-entry. + this._isGhostBusterObserver = true; + } }, /** @@ -639,6 +664,14 @@ BrowserGlue.prototype = { FormValidationHandler.uninit(); AutoCompletePopup.uninit(); this._dispose(); + + // Shut down ghost window idle observer. + if (this._isGhostBusterObserver) { + this._ghostBusterService.removeIdleObserver(this, GHOSTBUSTER_INTERVAL); + this._isGhostBusterObserver = false; + } + // Do one final unlink to combat shutdown issues. + Cu.unlinkGhostWindows(); }, // All initial windows have opened. diff --git a/application/palemoon/components/preferences/advanced.xul b/application/palemoon/components/preferences/advanced.xul index ec6f5689fd..341f49b815 100644 --- a/application/palemoon/components/preferences/advanced.xul +++ b/application/palemoon/components/preferences/advanced.xul @@ -52,6 +52,9 @@ + + + + @@ -221,7 +225,6 @@ - @@ -233,8 +236,20 @@ oncommand="gAdvancedPane.showConnections();"/> + + + + + + + + + + - diff --git a/application/palemoon/locales/en-US/chrome/browser/preferences/advanced.dtd b/application/palemoon/locales/en-US/chrome/browser/preferences/advanced.dtd index c0a2daa8ec..32f6babf3e 100644 --- a/application/palemoon/locales/en-US/chrome/browser/preferences/advanced.dtd +++ b/application/palemoon/locales/en-US/chrome/browser/preferences/advanced.dtd @@ -61,6 +61,12 @@ + + + + + + diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index be3193ed29..b992c8052a 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2307,13 +2307,11 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow) NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_UNLINK_END -#ifdef DEBUG void nsGlobalWindow::RiskyUnlink() { NS_CYCLE_COLLECTION_INNERNAME.Unlink(this); } -#endif NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindow) if (tmp->mCachedXBLPrototypeHandlers) { diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index c59baee648..564dcee500 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -597,11 +597,9 @@ public: NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsGlobalWindow, nsIDOMEventTarget) -#ifdef DEBUG // Call Unlink on this window. This may cause bad things to happen, so use // with caution. void RiskyUnlink(); -#endif virtual JSObject* GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey) override; diff --git a/dom/base/nsWindowMemoryReporter.cpp b/dom/base/nsWindowMemoryReporter.cpp index bf6eb6342e..82ccb5b350 100644 --- a/dom/base/nsWindowMemoryReporter.cpp +++ b/dom/base/nsWindowMemoryReporter.cpp @@ -829,7 +829,6 @@ nsWindowMemoryReporter::KillCheckTimer() } } -#ifdef DEBUG /* static */ void nsWindowMemoryReporter::UnlinkGhostWindows() { @@ -866,4 +865,3 @@ nsWindowMemoryReporter::UnlinkGhostWindows() } } } -#endif diff --git a/dom/base/nsWindowMemoryReporter.h b/dom/base/nsWindowMemoryReporter.h index 6cf72519da..1fd82431aa 100644 --- a/dom/base/nsWindowMemoryReporter.h +++ b/dom/base/nsWindowMemoryReporter.h @@ -150,13 +150,11 @@ public: static void Init(); -#ifdef DEBUG /** * Unlink all known ghost windows, to enable investigating what caused them * to become ghost windows in the first place. */ static void UnlinkGhostWindows(); -#endif static nsWindowMemoryReporter* Get(); void ObserveDOMWindowDetached(nsGlobalWindow* aWindow); diff --git a/js/src/ctypes/libffi/src/aarch64/sysv.S b/js/src/ctypes/libffi/src/aarch64/sysv.S index 169eab804e..5f447ce571 100644 --- a/js/src/ctypes/libffi/src/aarch64/sysv.S +++ b/js/src/ctypes/libffi/src/aarch64/sysv.S @@ -100,8 +100,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define ffi_call_SYSV_FS (8 * 4) - .cfi_startproc CNAME(ffi_call_SYSV): + .cfi_startproc stp x29, x30, [sp, #-16]! cfi_adjust_cfa_offset (16) cfi_rel_offset (x29, 0) @@ -247,8 +247,8 @@ CNAME(ffi_call_SYSV): #ifdef __APPLE__ .align 2 #endif - .cfi_startproc CNAME(ffi_closure_SYSV): + .cfi_startproc stp x29, x30, [sp, #-16]! cfi_adjust_cfa_offset (16) cfi_rel_offset (x29, 0) diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index cd0e1b29e4..0130b20abc 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -362,10 +362,7 @@ TokenStream::SourceCoords::add(uint32_t lineNum, uint32_t lineStartOffset) lineStartOffsets_[lineIndex] = lineStartOffset; } else { - // We have seen this newline before (and ungot it). Do nothing (other - // than checking it hasn't mysteriously changed). - // This path can be executed after hitting OOM, so check lineIndex. - MOZ_ASSERT_IF(lineIndex < sentinelIndex, lineStartOffsets_[lineIndex] == lineStartOffset); + // We have seen this newline before (and ungot it). Do nothing. } return true; } @@ -615,7 +612,6 @@ TokenStream::ungetChar(int32_t c) if (!userbuf.atStart()) userbuf.matchRawCharBackwards('\r'); - MOZ_ASSERT(prevLinebase != size_t(-1)); // we should never get more than one EOL char linebase = prevLinebase; prevLinebase = size_t(-1); lineno--; diff --git a/js/src/jit/AtomicOperations.h b/js/src/jit/AtomicOperations.h index 7051f7a6db..3d19877694 100644 --- a/js/src/jit/AtomicOperations.h +++ b/js/src/jit/AtomicOperations.h @@ -325,7 +325,7 @@ AtomicOperations::isLockfree(int32_t size) # include "jit/arm64/AtomicOperations-arm64.h" #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) # include "jit/mips-shared/AtomicOperations-mips-shared.h" -#elif defined(__ppc__) || defined(__PPC__) +#elif defined(__ppc__) || defined(__PPC__) || defined(__powerpc__) # include "jit/none/AtomicOperations-ppc.h" #elif defined(__sparc__) # include "jit/none/AtomicOperations-sparc.h" diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index 70103dfd17..0de7ee3adb 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -2664,12 +2664,8 @@ nsXPCComponents_Utils::SchedulePreciseShrinkingGC(ScheduledGCCallback* aCallback NS_IMETHODIMP nsXPCComponents_Utils::UnlinkGhostWindows() { -#ifdef DEBUG nsWindowMemoryReporter::UnlinkGhostWindows(); return NS_OK; -#else - return NS_ERROR_NOT_IMPLEMENTED; -#endif } NS_IMETHODIMP diff --git a/js/xpconnect/src/XPCJSContext.cpp b/js/xpconnect/src/XPCJSContext.cpp index d45f9f49eb..168dd5bf13 100644 --- a/js/xpconnect/src/XPCJSContext.cpp +++ b/js/xpconnect/src/XPCJSContext.cpp @@ -2489,7 +2489,7 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats& rtStats, // gcTotal is the sum of everything we've reported for the GC heap. It // should equal rtStats.gcHeapChunkTotal. - MOZ_ASSERT(gcTotal == rtStats.gcHeapChunkTotal); + NS_WARN_IF(gcTotal != rtStats.gcHeapChunkTotal); } void @@ -2929,7 +2929,7 @@ JSReporter::CollectReports(WindowPaths* windowPaths, KIND_OTHER, rtStats.zTotals.regExpSharedsGCHeap, "Used regexpshared cells."); - MOZ_ASSERT(gcThingTotal == rtStats.gcHeapGCThings); + NS_WARN_IF(gcThingTotal == rtStats.gcHeapGCThings); // Report xpconnect. diff --git a/media/libcubeb/src/moz.build b/media/libcubeb/src/moz.build index 7de75d52c6..b4515a3a9a 100644 --- a/media/libcubeb/src/moz.build +++ b/media/libcubeb/src/moz.build @@ -44,7 +44,7 @@ if CONFIG['MOZ_SNDIO']: ] DEFINES['USE_SNDIO'] = True -if CONFIG['OS_ARCH'] == 'SunOS': +if CONFIG['OS_ARCH'] in ('SunOS', 'NetBSD'): SOURCES += [ 'cubeb_sun.c', ] diff --git a/old-configure.in b/old-configure.in index 6aa17e9836..5e58cd5dfe 100644 --- a/old-configure.in +++ b/old-configure.in @@ -2655,7 +2655,7 @@ if test -n "$MOZ_MAILNEWS"; then MOZ_MORK=1 MOZ_LDAP_XPCOM=1 - if test "$OS_ARCH" == "WINNT"; then + if test "$OS_ARCH" = "WINNT"; then MOZ_MAPI_SUPPORT=1 else MOZ_MOVEMAIL=1 diff --git a/toolkit/components/aboutmemory/content/aboutMemory.js b/toolkit/components/aboutmemory/content/aboutMemory.js index 100228c4bb..243ffbd840 100644 --- a/toolkit/components/aboutmemory/content/aboutMemory.js +++ b/toolkit/components/aboutmemory/content/aboutMemory.js @@ -304,6 +304,9 @@ function onLoad() "collection followed by a cycle collection, and causes the " + "process to reduce memory usage in other ways, e.g. by " + "flushing various caches."; + const UGDesc = "Unlink any known ghost windows, to enable investigating " + + "what caused them. This is only for debugging leaks, and " + + "can cause bad things to happen if called."; const GCAndCCLogDesc = "Save garbage collection log and concise cycle " + "collection log.\n" + @@ -357,6 +360,7 @@ function onLoad() appendButton(row3, GCDesc, doGC, "GC"); appendButton(row3, CCDesc, doCC, "CC"); appendButton(row3, MMDesc, doMMU, "Minimize memory usage"); + appendButton(row3, UGDesc, doUGW, "Unlink ghost windows"); let row4 = appendElement(ops, "div", "opsRow"); @@ -429,6 +433,12 @@ function doMMU() () => updateMainAndFooter("Memory minimization completed", HIDE_FOOTER)); } +function doUGW() +{ + Cu.unlinkGhostWindows(); + updateMainAndFooter("Unlink ghost windows completed", HIDE_FOOTER); +} + function doMeasure() { updateAboutMemoryFromReporters(); diff --git a/xpcom/reflect/xptcall/md/unix/moz.build b/xpcom/reflect/xptcall/md/unix/moz.build index 7ab7e73654..4b44143ad8 100644 --- a/xpcom/reflect/xptcall/md/unix/moz.build +++ b/xpcom/reflect/xptcall/md/unix/moz.build @@ -136,7 +136,7 @@ if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD', 'NetBSD', 'OpenBSD'): ] if CONFIG['OS_TEST'] == 'powerpc': - if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'): + if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD', 'NetBSD'): SOURCES += [ 'xptcinvoke_asm_ppc_linux.S', 'xptcinvoke_ppc_linux.cpp', @@ -145,7 +145,7 @@ if CONFIG['OS_TEST'] == 'powerpc': ] if CONFIG['OS_TEST'] in ('powerpc64', 'powerpc64le'): - if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'): + if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD', 'NetBSD'): SOURCES += [ 'xptcinvoke_asm_ppc64_linux.S', 'xptcinvoke_ppc64_linux.cpp', @@ -198,7 +198,7 @@ if CONFIG['OS_ARCH'] == 'OpenBSD' and CONFIG['OS_TEST'] == 'sparc': # files for 64-bit SPARC with no ill effects, so basically the entire mess that # was there before is no longer needed. -if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD', 'SunOS', 'Linux') and CONFIG['OS_TEST'] == 'sparc64': +if CONFIG['OS_ARCH'] in ('NetBSD', 'OpenBSD', 'FreeBSD', 'SunOS', 'Linux') and CONFIG['OS_TEST'] == 'sparc64': SOURCES += [ 'xptcinvoke_asm_sparc64_openbsd.s', 'xptcinvoke_sparc64_openbsd.cpp',