Bug 1335148 - Part 3: Notify Gecko and turn bfcache back on when Fennec memory pressure decays to 0. r?snorp draft
authorJan Henning <jh+bugzilla@buttercookie.de>
Sun, 06 May 2018 13:40:05 +0200
changeset 793279 224fae405615cb81e4cb2f5176960538c2dbba8d
parent 793278 2147d58661f98c49b905d032975c0422ed8cffc1
child 793280 e75dd5029154e0228a3c1fb7f316d5089c1f3770
push id109332
push usermozilla@buttercookie.de
push dateWed, 09 May 2018 19:48:41 +0000
reviewerssnorp
bugs1335148
milestone62.0a1
Bug 1335148 - Part 3: Notify Gecko and turn bfcache back on when Fennec memory pressure decays to 0. r?snorp MozReview-Commit-ID: 6Oyu7Lx1gFQ
mobile/android/base/java/org/mozilla/gecko/MemoryMonitor.java
mobile/android/chrome/content/MemoryObserver.js
mobile/android/chrome/content/browser.js
widget/android/fennec/MemoryMonitor.h
--- a/mobile/android/base/java/org/mozilla/gecko/MemoryMonitor.java
+++ b/mobile/android/base/java/org/mozilla/gecko/MemoryMonitor.java
@@ -200,27 +200,39 @@ class MemoryMonitor extends BroadcastRec
 
     /**
      * Thread-safe due to mStoragePressure's volatility.
      */
     boolean isUnderStoragePressure() {
         return mStoragePressure;
     }
 
+    @WrapForJNI
+    private static native void dispatchMemoryPressureStop();
+
+    /**
+     * @return False if we have decremented all the way down to {@code MEMORY_PRESSURE_NONE}.
+     */
     private boolean decreaseMemoryPressure() {
         int newLevel;
         synchronized (this) {
-            if (mMemoryPressure <= 0) {
+            if (mMemoryPressure <= MEMORY_PRESSURE_NONE) {
                 return false;
+            } else {
+                newLevel = --mMemoryPressure;
             }
-
-            newLevel = --mMemoryPressure;
         }
         Log.d(LOGTAG, "Decreased memory pressure to " + newLevel);
 
+        if (newLevel == MEMORY_PRESSURE_NONE) {
+            if (GeckoThread.isRunning()) {
+                dispatchMemoryPressureStop();
+            }
+        }
+
         return true;
     }
 
     class PressureDecrementer implements Runnable {
         private static final int DECREMENT_DELAY = 5 * 60 * 1000; // 5 minutes
 
         private boolean mPosted;
 
--- a/mobile/android/chrome/content/MemoryObserver.js
+++ b/mobile/android/chrome/content/MemoryObserver.js
@@ -1,23 +1,31 @@
 /* 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/. */
 "use strict";
 
+const MAX_CONTENT_VIEWERS_PREF = "browser.sessionhistory.max_total_viewers";
+
 var MemoryObserver = {
+  // When we turn off the bfcache by overwriting the old default value, we want
+  // to be able to restore it later on if memory pressure decreases again.
+  _defaultMaxContentViewers: -1,
+
   observe: function mo_observe(aSubject, aTopic, aData) {
     if (aTopic == "memory-pressure") {
       if (aData != "heap-minimize") {
         this.handleLowMemory();
       }
       // The JS engine would normally GC on this notification, but since we
       // disabled that in favor of this method (bug 669346), we should gc here.
       // See bug 784040 for when this code was ported from XUL to native Fennec.
       this.gc();
+    } else if (aTopic == "memory-pressure-stop") {
+      this.handleEnoughMemory();
     } else if (aTopic == "Memory:Dump") {
       this.dumpMemoryStats(aData);
     }
   },
 
   handleLowMemory: function() {
     // do things to reduce memory usage here
     if (!Services.prefs.getBoolPref("browser.tabs.disableBackgroundZombification")) {
@@ -33,17 +41,26 @@ var MemoryObserver = {
     // Change some preferences temporarily for only this session
     let defaults = Services.prefs.getDefaultBranch(null);
 
     // Reduce the amount of decoded image data we keep around
     defaults.setIntPref("image.mem.max_decoded_image_kb", 0);
 
     // Stop using the bfcache
     if (!Services.prefs.getBoolPref("browser.sessionhistory.bfcacheIgnoreMemoryPressure")) {
-      defaults.setIntPref("browser.sessionhistory.max_total_viewers", 0);
+      this._defaultMaxContentViewers = defaults.getIntPref(MAX_CONTENT_VIEWERS_PREF);
+      defaults.setIntPref(MAX_CONTENT_VIEWERS_PREF, 0);
+    }
+  },
+
+  handleEnoughMemory: function() {
+    // Re-enable the bfcache
+    let defaults = Services.prefs.getDefaultBranch(null);
+    if (!Services.prefs.getBoolPref("browser.sessionhistory.bfcacheIgnoreMemoryPressure")) {
+      defaults.setIntPref(MAX_CONTENT_VIEWERS_PREF, this._defaultMaxContentViewers);
     }
   },
 
   gc: function() {
     window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).garbageCollect();
     Cu.forceGC();
   },
 
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -133,17 +133,20 @@ lazilyLoadedBrowserScripts.forEach(funct
   XPCOMUtils.defineLazyGetter(window, name, function() {
     let sandbox = {};
     Services.scriptloader.loadSubScript(script, sandbox);
     return sandbox[name];
   });
 });
 
 var lazilyLoadedObserverScripts = [
-  ["MemoryObserver", ["memory-pressure", "Memory:Dump"], "chrome://browser/content/MemoryObserver.js"],
+  ["MemoryObserver", ["memory-pressure",
+                      "memory-pressure-stop",
+                      "Memory:Dump"],
+   "chrome://browser/content/MemoryObserver.js"],
   ["ConsoleAPI", ["console-api-log-event"], "chrome://browser/content/ConsoleAPI.js"],
   ["ExtensionPermissions", ["webextension-permission-prompt",
                             "webextension-update-permissions",
                             "webextension-optional-permission-prompt"],
    "chrome://browser/content/ExtensionPermissions.js"],
 ];
 
 lazilyLoadedObserverScripts.forEach(function (aScript) {
--- a/widget/android/fennec/MemoryMonitor.h
+++ b/widget/android/fennec/MemoryMonitor.h
@@ -15,13 +15,19 @@ class MemoryMonitor final
     : public java::MemoryMonitor::Natives<MemoryMonitor>
 {
 public:
     static void
     DispatchMemoryPressure()
     {
         NS_DispatchMemoryPressure(MemoryPressureState::MemPressure_New);
     }
+
+    static void
+    DispatchMemoryPressureStop()
+    {
+        NS_DispatchMemoryPressure(MemoryPressureState::MemPressure_Stopping);
+    }
 };
 
 } // namespace mozilla
 
 #endif // MemoryMonitor_h