Bug 1449833 - Use StaticPrefs in nsJSEnvironment.cpp. r=sfink draft
authorNicholas Nethercote <nnethercote@mozilla.com>
Tue, 27 Mar 2018 13:26:38 +1100
changeset 776348 c014b72824d800fe256e051aeb5a70e45feee91d
parent 776347 7183b81043999bbcc3d95091d498f3bf930132b2
push id104841
push usernnethercote@mozilla.com
push dateMon, 02 Apr 2018 21:18:37 +0000
reviewerssfink
bugs1449833
milestone61.0a1
Bug 1449833 - Use StaticPrefs in nsJSEnvironment.cpp. r=sfink MozReview-Commit-ID: GELa2l1ZonV
dom/base/nsJSEnvironment.cpp
mobile/android/app/mobile.js
modules/libpref/init/StaticPrefList.h
modules/libpref/init/all.js
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -50,16 +50,17 @@
 #include "js/SliceBudget.h"
 #include "nsIArray.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "WrapperFactory.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/MainThreadIdlePeriod.h"
+#include "mozilla/StaticPrefs.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMExceptionBinding.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ErrorEvent.h"
 #include "mozilla/dom/FetchUtil.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
@@ -105,20 +106,16 @@ const size_t gStackSize = 8192;
 #define NS_SHRINK_GC_BUFFERS_DELAY  4000 // ms
 
 // The amount of time we wait from the first request to GC to actually
 // doing the first GC.
 #define NS_FIRST_GC_DELAY           10000 // ms
 
 #define NS_FULL_GC_DELAY            60000 // ms
 
-// The default amount of time to wait from the user being idle to starting a
-// shrinking GC.
-#define NS_DEAULT_INACTIVE_GC_DELAY 300000 // ms
-
 // Maximum amount of time that should elapse between incremental GC slices
 #define NS_INTERSLICE_GC_DELAY      100 // ms
 
 // The amount of time we wait between a request to CC (after GC ran)
 // and doing the actual CC.
 #define NS_CC_DELAY                 6000 // ms
 
 #define NS_CC_SKIPPABLE_DELAY       250 // ms
@@ -178,18 +175,16 @@ static bool sHasRunGC;
 // we're waiting for a slow page to load. IOW, this count may be 0
 // even when there are pending loads.
 static uint32_t sPendingLoadCount;
 static bool sLoadingInProgress;
 
 static uint32_t sCCollectedWaitingForGC;
 static uint32_t sCCollectedZonesWaitingForGC;
 static uint32_t sLikelyShortLivingObjectsNeedingGC;
-static bool sPostGCEventsToConsole;
-static bool sPostGCEventsToObserver;
 static int32_t sCCRunnerFireCount = 0;
 static uint32_t sMinForgetSkippableTime = UINT32_MAX;
 static uint32_t sMaxForgetSkippableTime = 0;
 static uint32_t sTotalForgetSkippableTime = 0;
 static uint32_t sRemovedPurples = 0;
 static uint32_t sForgetSkippableBeforeCC = 0;
 static uint32_t sPreviousSuspectedCount = 0;
 static uint32_t sCleanupsSinceLastGC = UINT32_MAX;
@@ -200,28 +195,20 @@ static bool sIncrementalCC = false;
 static int32_t sActiveIntersliceGCBudget = 5; // ms;
 
 static PRTime sFirstCollectionTime;
 
 static bool sIsInitialized;
 static bool sDidShutdown;
 static bool sShuttingDown;
 
-// nsJSEnvironmentObserver observes the memory-pressure notifications
-// and forces a garbage collection and cycle collection when it happens, if
-// the appropriate pref is set.
-
-static bool sGCOnMemoryPressure;
-
 // nsJSEnvironmentObserver observes the user-interaction-inactive notifications
 // and triggers a shrinking a garbage collection if the user is still inactive
 // after NS_SHRINKING_GC_DELAY ms later, if the appropriate pref is set.
 
-static bool sCompactOnUserInactive;
-static uint32_t sCompactOnUserInactiveDelay = NS_DEAULT_INACTIVE_GC_DELAY;
 static bool sIsCompactingOnUserInactive = false;
 
 static TimeDuration sGCUnnotifiedTotalTime;
 
 static const char*
 ProcessNameForCollectorLog()
 {
   return XRE_GetProcessType() == GeckoProcessType_Default ?
@@ -324,35 +311,35 @@ public:
 
 NS_IMPL_ISUPPORTS(nsJSEnvironmentObserver, nsIObserver)
 
 NS_IMETHODIMP
 nsJSEnvironmentObserver::Observe(nsISupports* aSubject, const char* aTopic,
                                  const char16_t* aData)
 {
   if (!nsCRT::strcmp(aTopic, "memory-pressure")) {
-    if (sGCOnMemoryPressure) {
-      if(StringBeginsWith(nsDependentString(aData),
-                          NS_LITERAL_STRING("low-memory-ongoing"))) {
+    if (StaticPrefs::javascript_options_gc_on_memory_pressure()) {
+      if (StringBeginsWith(nsDependentString(aData),
+                           NS_LITERAL_STRING("low-memory-ongoing"))) {
         // Don't GC/CC if we are in an ongoing low-memory state since its very
         // slow and it likely won't help us anyway.
         return NS_OK;
       }
       nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE,
                                      nsJSContext::NonIncrementalGC,
                                      nsJSContext::ShrinkingGC);
       nsJSContext::CycleCollectNow();
       if (NeedsGCAfterCC()) {
         nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE,
                                        nsJSContext::NonIncrementalGC,
                                        nsJSContext::ShrinkingGC);
       }
     }
   } else if (!nsCRT::strcmp(aTopic, "user-interaction-inactive")) {
-    if (sCompactOnUserInactive) {
+    if (StaticPrefs::javascript_options_compact_on_user_inactive()) {
       nsJSContext::PokeShrinkingGC();
     }
   } else if (!nsCRT::strcmp(aTopic, "user-interaction-active")) {
     nsJSContext::KillShrinkingGCTimer();
     if (sIsCompactingOnUserInactive) {
       AutoJSAPI jsapi;
       jsapi.Init();
       JS::AbortIncrementalGC(jsapi.cx());
@@ -593,18 +580,16 @@ PrintWinCodebaseOuter(nsGlobalWindowOute
 
 void
 DumpString(const nsAString &str)
 {
   printf("%s\n", NS_ConvertUTF16toUTF8(str).get());
 }
 #endif
 
-#define JS_OPTIONS_DOT_STR "javascript.options."
-
 nsJSContext::nsJSContext(bool aGCOnDestruction,
                          nsIScriptGlobalObject* aGlobalObject)
   : mWindowProxy(nullptr)
   , mGCOnDestruction(aGCOnDestruction)
   , mGlobalObjectRef(aGlobalObject)
 {
   EnsureStatics();
 
@@ -1692,17 +1677,17 @@ nsJSContext::EndCycleCollectionCallback(
                         sMaxForgetSkippableTime / PR_USEC_PER_MSEC);
 
   PRTime delta = GetCollectionTimeDelta();
 
   uint32_t cleanups = sForgetSkippableBeforeCC ? sForgetSkippableBeforeCC : 1;
   uint32_t minForgetSkippableTime = (sMinForgetSkippableTime == UINT32_MAX)
     ? 0 : sMinForgetSkippableTime;
 
-  if (sPostGCEventsToConsole || gCCStats.mFile) {
+  if (StaticPrefs::javascript_options_mem_log() || gCCStats.mFile) {
     nsCString mergeMsg;
     if (aResults.mMergedZones) {
       mergeMsg.AssignLiteral(" merged");
     }
 
     nsCString gcMsg;
     if (aResults.mForcedGC) {
       gcMsg.AssignLiteral(", forced a GC");
@@ -1722,29 +1707,29 @@ nsJSContext::EndCycleCollectionCallback(
                               gcMsg.get(),
                               sForgetSkippableBeforeCC,
                               minForgetSkippableTime / PR_USEC_PER_MSEC,
                               sMaxForgetSkippableTime / PR_USEC_PER_MSEC,
                               (sTotalForgetSkippableTime / cleanups) /
                               PR_USEC_PER_MSEC,
                               sTotalForgetSkippableTime / PR_USEC_PER_MSEC,
                               gCCStats.mMaxSkippableDuration, sRemovedPurples);
-    if (sPostGCEventsToConsole) {
+    if (StaticPrefs::javascript_options_mem_log()) {
       nsCOMPtr<nsIConsoleService> cs =
         do_GetService(NS_CONSOLESERVICE_CONTRACTID);
       if (cs) {
         cs->LogStringMessage(msg.get());
       }
     }
     if (gCCStats.mFile) {
       fprintf(gCCStats.mFile, "%s\n", NS_ConvertUTF16toUTF8(msg).get());
     }
   }
 
-  if (sPostGCEventsToObserver) {
+  if (StaticPrefs::javascript_options_mem_notify()) {
     const char16_t* kJSONFmt =
        u"{ \"timestamp\": %llu, "
          u"\"duration\": %lu, "
          u"\"max_slice_pause\": %lu, "
          u"\"total_slice_pause\": %lu, "
          u"\"max_finish_gc_duration\": %lu, "
          u"\"max_sync_skippable_duration\": %lu, "
          u"\"suspected\": %lu, "
@@ -2170,17 +2155,17 @@ void
 nsJSContext::PokeShrinkingGC()
 {
   if (sShrinkingGCTimer || sShuttingDown) {
     return;
   }
 
   NS_NewTimerWithFuncCallback(&sShrinkingGCTimer,
                               ShrinkingGCTimerFired, nullptr,
-                              sCompactOnUserInactiveDelay,
+                              StaticPrefs::javascript_options_compact_on_user_inactive_delay(),
                               nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
                               "ShrinkingGCTimerFired",
                               SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
 }
 
 // static
 void
 nsJSContext::MaybePokeCC()
@@ -2312,32 +2297,33 @@ DOMGCSliceCallback(JSContext* aCx, JS::G
       // Prevent cycle collections and shrinking during incremental GC.
       sCCLockedOut = true;
       break;
     }
 
     case JS::GC_CYCLE_END: {
       PRTime delta = GetCollectionTimeDelta();
 
-      if (sPostGCEventsToConsole) {
+      if (StaticPrefs::javascript_options_mem_log()) {
         nsString gcstats;
         gcstats.Adopt(aDesc.formatSummaryMessage(aCx));
         nsAutoString prefix;
         nsTextFormatter::ssprintf(prefix, u"GC(T+%.1f)[%s-%i] ",
                                   double(delta) / PR_USEC_PER_SEC,
                                   ProcessNameForCollectorLog(), getpid());
         nsString msg = prefix + gcstats;
         nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
         if (cs) {
           cs->LogStringMessage(msg.get());
         }
       }
 
       if (!sShuttingDown) {
-        if (sPostGCEventsToObserver || Telemetry::CanRecordExtended()) {
+        if (StaticPrefs::javascript_options_mem_notify() ||
+            Telemetry::CanRecordExtended()) {
           nsString json;
           json.Adopt(aDesc.formatJSON(aCx, PR_Now()));
           RefPtr<NotifyGCEndRunnable> notify = new NotifyGCEndRunnable(json);
           SystemGroup::Dispatch(TaskCategory::GarbageCollection, notify.forget());
         }
       }
 
       sCCLockedOut = false;
@@ -2399,17 +2385,17 @@ DOMGCSliceCallback(JSContext* aCx, JS::G
              []{ return sShuttingDown; },
              TaskCategory::GarbageCollection);
       }
 
       if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
         nsCycleCollector_dispatchDeferredDeletion();
       }
 
-      if (sPostGCEventsToConsole) {
+      if (StaticPrefs::javascript_options_mem_log()) {
         nsString gcstats;
         gcstats.Adopt(aDesc.formatSliceMessage(aCx));
         nsAutoString prefix;
         nsTextFormatter::ssprintf(prefix, u"[%s-%i] ",
                                   ProcessNameForCollectorLog(), getpid());
         nsString msg = prefix + gcstats;
         nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
         if (cs) {
@@ -2456,17 +2442,16 @@ mozilla::dom::StartupJSEnvironment()
   sCCLockedOutTime = 0;
   sLastCCEndTime = TimeStamp();
   sHasRunGC = false;
   sPendingLoadCount = 0;
   sLoadingInProgress = false;
   sCCollectedWaitingForGC = 0;
   sCCollectedZonesWaitingForGC = 0;
   sLikelyShortLivingObjectsNeedingGC = 0;
-  sPostGCEventsToConsole = false;
   sNeedsFullCC = false;
   sNeedsFullGC = true;
   sNeedsGCAfterCC = false;
   sIsInitialized = false;
   sDidShutdown = false;
   sShuttingDown = false;
   gCCStats.Init();
 }
@@ -2770,33 +2755,16 @@ nsJSContext::EnsureStatics()
                                        "javascript.options.mem.gc_max_empty_chunk_count",
                                        (void *)JSGC_MAX_EMPTY_CHUNK_COUNT);
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (!obs) {
     MOZ_CRASH();
   }
 
-  Preferences::AddBoolVarCache(&sGCOnMemoryPressure,
-                               "javascript.options.gc_on_memory_pressure",
-                               true);
-
-  Preferences::AddBoolVarCache(&sCompactOnUserInactive,
-                               "javascript.options.compact_on_user_inactive",
-                               true);
-
-  Preferences::AddUintVarCache(&sCompactOnUserInactiveDelay,
-                               "javascript.options.compact_on_user_inactive_delay",
-                               NS_DEAULT_INACTIVE_GC_DELAY);
-
-  Preferences::AddBoolVarCache(&sPostGCEventsToConsole,
-                               JS_OPTIONS_DOT_STR "mem.log");
-  Preferences::AddBoolVarCache(&sPostGCEventsToObserver,
-                               JS_OPTIONS_DOT_STR "mem.notify");
-
   nsIObserver* observer = new nsJSEnvironmentObserver();
   obs->AddObserver(observer, "memory-pressure", false);
   obs->AddObserver(observer, "user-interaction-inactive", false);
   obs->AddObserver(observer, "user-interaction-active", false);
   obs->AddObserver(observer, "quit-application", false);
   obs->AddObserver(observer, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
 
   sIsInitialized = true;
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -363,20 +363,16 @@ pref("geo.enabled", true);
 
 // content sink control -- controls responsiveness during page load
 // see https://bugzilla.mozilla.org/show_bug.cgi?id=481566#c9
 //pref("content.sink.enable_perf_mode",  2); // 0 - switch, 1 - interactive, 2 - perf
 //pref("content.sink.pending_event_mode", 0);
 //pref("content.sink.perf_deflect_count", 1000000);
 //pref("content.sink.perf_parse_time", 50000000);
 
-// Disable the JS engine's gc on memory pressure, since we do one in the mobile
-// browser (bug 669346).
-pref("javascript.options.gc_on_memory_pressure", false);
-
 pref("javascript.options.mem.high_water_mark", 32);
 
 pref("dom.max_chrome_script_run_time", 0); // disable slow script dialog for chrome
 pref("dom.max_script_run_time", 20);
 
 // Absolute path to the devtools unix domain socket file used
 // to communicate with a usb cable via adb forward.
 pref("devtools.debugger.unix-domain-socket", "/data/data/@ANDROID_PACKAGE_NAME@/firefox-debugger-socket");
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -101,16 +101,71 @@ VARCACHE_PREF(
 // firing when the timer has already fired previously in this parse.
 VARCACHE_PREF(
   "html5.flushtimer.subsequentdelay",
    html5_flushtimer_subsequentdelay,
   int32_t, 120
 )
 
 //---------------------------------------------------------------------------
+// JavaScript prefs
+//---------------------------------------------------------------------------
+
+// nsJSEnvironmentObserver observes the memory-pressure notifications and
+// forces a garbage collection and cycle collection when it happens, if the
+// appropriate pref is set.
+#ifdef ANDROID
+  // Disable the JS engine's GC on memory pressure, since we do one in the
+  // mobile browser (bug 669346).
+  // XXX: this value possibly should be changed, or the pref removed entirely.
+  //      See bug 1450787.
+# define PREF_VALUE false
+#else
+# define PREF_VALUE true
+#endif
+VARCACHE_PREF(
+  "javascript.options.gc_on_memory_pressure",
+   javascript_options_gc_on_memory_pressure,
+  bool, PREF_VALUE
+)
+#undef PREF_VALUE
+
+VARCACHE_PREF(
+  "javascript.options.compact_on_user_inactive",
+   javascript_options_compact_on_user_inactive,
+  bool, true
+)
+
+// The default amount of time to wait from the user being idle to starting a
+// shrinking GC.
+#ifdef NIGHTLY_BUILD
+# define PREF_VALUE  15000  // ms
+#else
+# define PREF_VALUE 300000  // ms
+#endif
+VARCACHE_PREF(
+  "javascript.options.compact_on_user_inactive_delay",
+   javascript_options_compact_on_user_inactive_delay,
+   uint32_t, PREF_VALUE
+)
+#undef PREF_VALUE
+
+VARCACHE_PREF(
+  "javascript.options.mem.log",
+   javascript_options_mem_log,
+  bool, false
+)
+
+VARCACHE_PREF(
+  "javascript.options.mem.notify",
+   javascript_options_mem_notify,
+  bool, false
+)
+
+//---------------------------------------------------------------------------
 // Network prefs
 //---------------------------------------------------------------------------
 
 // Sub-resources HTTP-authentication:
 //   0 - don't allow sub-resources to open HTTP authentication credentials
 //       dialogs
 //   1 - allow sub-resources to open HTTP authentication credentials dialogs,
 //       but don't allow it for cross-origin sub-resources
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1517,26 +1517,16 @@ pref("javascript.options.mem.gc_incremen
 
 // JSGC_SLICE_TIME_BUDGET
 // Override the shell's default of unlimited slice time.
 pref("javascript.options.mem.gc_incremental_slice_ms", 5);
 
 // JSGC_COMPACTING_ENABLED
 pref("javascript.options.mem.gc_compacting", true);
 
-pref("javascript.options.mem.log", false);
-pref("javascript.options.mem.notify", false);
-pref("javascript.options.gc_on_memory_pressure", true);
-pref("javascript.options.compact_on_user_inactive", true);
-#ifdef NIGHTLY_BUILD
-pref("javascript.options.compact_on_user_inactive_delay", 15000); // ms
-#else
-pref("javascript.options.compact_on_user_inactive_delay", 300000); // ms
-#endif
-
 // JSGC_HIGH_FREQUENCY_TIME_LIMIT
 pref("javascript.options.mem.gc_high_frequency_time_limit_ms", 1000);
 
 // JSGC_HIGH_FREQUENCY_LOW_LIMIT
 pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 100);
 
 // JSGC_HIGH_FREQUENCY_HIGH_LIMIT
 pref("javascript.options.mem.gc_high_frequency_high_limit_mb", 500);