Merge inbound to mozilla-central. a=merge
authorGurzau Raul <rgurzau@mozilla.com>
Thu, 27 Jun 2019 00:54:09 +0300
changeset 480191 3752d5cac66b9f72bfe7252e399349cb0eb3f59f
parent 480190 9b181decb95c108407e60a67222a7437cc20c8d8 (current diff)
parent 480137 472f05b9105a0cea468f213e1aa56dd4a900514c (diff)
child 480192 bc8757f8192411df053d64ee15c1d1e2d5d764d7
child 480259 8f65263683c4d6e787edb35104be861399bcd79e
child 480308 91c42888cf7fa67f2b9d08d0e62cb203ad1e6619
push id113534
push userrgurzau@mozilla.com
push dateWed, 26 Jun 2019 22:06:25 +0000
treeherdermozilla-inbound@bc8757f81924 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone69.0a1
first release with
nightly linux32
3752d5cac66b / 69.0a1 / 20190626215508 / files
nightly linux64
3752d5cac66b / 69.0a1 / 20190626215508 / files
nightly mac
3752d5cac66b / 69.0a1 / 20190626215508 / files
nightly win32
3752d5cac66b / 69.0a1 / 20190626215508 / files
nightly win64
3752d5cac66b / 69.0a1 / 20190626215508 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -327,32 +327,37 @@ class nsJSEnvironmentObserver final : pu
 
 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 (StaticPrefs::javascript_options_gc_on_memory_pressure()) {
-      if (StringBeginsWith(nsDependentString(aData),
-                           NS_LITERAL_STRING("low-memory-ongoing"))) {
+      nsDependentString data(aData);
+      if (data.EqualsLiteral("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;
       }
+      if (data.EqualsLiteral("low-memory")) {
+        nsJSContext::SetLowMemoryState(true);
+      }
       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, "memory-pressure-stop")) {
+    nsJSContext::SetLowMemoryState(false);
   } else if (!nsCRT::strcmp(aTopic, "user-interaction-inactive")) {
     if (StaticPrefs::javascript_options_compact_on_user_inactive()) {
       nsJSContext::PokeShrinkingGC();
     }
   } else if (!nsCRT::strcmp(aTopic, "user-interaction-active")) {
     nsJSContext::KillShrinkingGCTimer();
     if (sIsCompactingOnUserInactive) {
       AutoJSAPI jsapi;
@@ -1076,16 +1081,22 @@ void nsJSContext::SetProcessingScriptTag
 void FullGCTimerFired(nsITimer* aTimer, void* aClosure) {
   nsJSContext::KillFullGCTimer();
   MOZ_ASSERT(!aClosure, "Don't pass a closure to FullGCTimerFired");
   nsJSContext::GarbageCollectNow(JS::GCReason::FULL_GC_TIMER,
                                  nsJSContext::IncrementalGC);
 }
 
 // static
+void nsJSContext::SetLowMemoryState(bool aState) {
+  JSContext* cx = danger::GetJSContext();
+  JS::SetLowMemoryState(cx, aState);
+}
+
+// static
 void nsJSContext::GarbageCollectNow(JS::GCReason aReason,
                                     IsIncremental aIncremental,
                                     IsShrinking aShrinking,
                                     int64_t aSliceMillis) {
   AUTO_PROFILER_LABEL_DYNAMIC_CSTR("nsJSContext::GarbageCollectNow", GCCC,
                                    JS::ExplainGCReason(aReason));
 
   MOZ_ASSERT_IF(aSliceMillis, aIncremental == IncrementalGC);
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -61,16 +61,18 @@ class nsJSContext : public nsIScriptCont
 
   enum IsShrinking { ShrinkingGC, NonShrinkingGC };
 
   enum IsIncremental { IncrementalGC, NonIncrementalGC };
 
   // Setup all the statics etc - safe to call multiple times after Startup().
   static void EnsureStatics();
 
+  static void SetLowMemoryState(bool aState);
+
   static void GarbageCollectNow(JS::GCReason reason,
                                 IsIncremental aIncremental = NonIncrementalGC,
                                 IsShrinking aShrinking = NonShrinkingGC,
                                 int64_t aSliceMillis = 0);
 
   static void CycleCollectNow(nsICycleCollectorListener* aListener = nullptr);
 
   // Run a cycle collector slice, using a heuristic to decide how long to run
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -134,17 +134,19 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 
 #define PREF_WORKERS_MAX_HARDWARE_CONCURRENCY "dom.maxHardwareConcurrency"
 
 #define PREF_MAX_SCRIPT_RUN_TIME_CONTENT "dom.max_script_run_time"
 #define PREF_MAX_SCRIPT_RUN_TIME_CHROME "dom.max_chrome_script_run_time"
 
 #define GC_REQUEST_OBSERVER_TOPIC "child-gc-request"
 #define CC_REQUEST_OBSERVER_TOPIC "child-cc-request"
 #define MEMORY_PRESSURE_OBSERVER_TOPIC "memory-pressure"
-#define MEMORY_PRESSURE_ONGOING_DATA "low-memory-ongoing"
+#define LOW_MEMORY_DATA "low-memory"
+#define LOW_MEMORY_ONGOING_DATA "low-memory-ongoing"
+#define MEMORY_PRESSURE_STOP_OBSERVER_TOPIC "memory-pressure-stop"
 
 #define BROADCAST_ALL_WORKERS(_func, ...)                         \
   PR_BEGIN_MACRO                                                  \
   AssertIsOnMainThread();                                         \
                                                                   \
   AutoTArray<WorkerPrivate*, 100> workers;                        \
   {                                                               \
     MutexAutoLock lock(mMutex);                                   \
@@ -2116,16 +2118,20 @@ void RuntimeService::UpdateAllWorkerMemo
 
 #ifdef JS_GC_ZEAL
 void RuntimeService::UpdateAllWorkerGCZeal() {
   BROADCAST_ALL_WORKERS(UpdateGCZeal, sDefaultJSSettings.gcZeal,
                         sDefaultJSSettings.gcZealFrequency);
 }
 #endif
 
+void RuntimeService::SetLowMemoryStateAllWorkers(bool aState) {
+  BROADCAST_ALL_WORKERS(SetLowMemoryState, aState);
+}
+
 void RuntimeService::GarbageCollectAllWorkers(bool aShrinking) {
   BROADCAST_ALL_WORKERS(GarbageCollect, aShrinking);
 }
 
 void RuntimeService::CycleCollectAllWorkers() {
   BROADCAST_ALL_WORKERS(CycleCollect, /* dummy = */ false);
 }
 
@@ -2195,23 +2201,32 @@ RuntimeService::Observe(nsISupports* aSu
     GarbageCollectAllWorkers(/* shrinking = */ false);
     return NS_OK;
   }
   if (!strcmp(aTopic, CC_REQUEST_OBSERVER_TOPIC)) {
     CycleCollectAllWorkers();
     return NS_OK;
   }
   if (!strcmp(aTopic, MEMORY_PRESSURE_OBSERVER_TOPIC)) {
+    nsDependentString data(aData);
     // Don't continue to GC/CC if we are in an ongoing low-memory state since
     // its very slow and it likely won't help us anyway.
-    if (!nsDependentString(aData).EqualsLiteral(MEMORY_PRESSURE_ONGOING_DATA)) {
-      GarbageCollectAllWorkers(/* shrinking = */ true);
-      CycleCollectAllWorkers();
-      MemoryPressureAllWorkers();
+    if (data.EqualsLiteral(LOW_MEMORY_ONGOING_DATA)) {
+      return NS_OK;
+    }
+    if (data.EqualsLiteral(LOW_MEMORY_DATA)) {
+      SetLowMemoryStateAllWorkers(true);
     }
+    GarbageCollectAllWorkers(/* shrinking = */ true);
+    CycleCollectAllWorkers();
+    MemoryPressureAllWorkers();
+    return NS_OK;
+  }
+  if (!strcmp(aTopic, MEMORY_PRESSURE_STOP_OBSERVER_TOPIC)) {
+    SetLowMemoryStateAllWorkers(false);
     return NS_OK;
   }
   if (!strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC)) {
     SendOfflineStatusChangeEventToAllWorkers(NS_IsOffline());
     return NS_OK;
   }
 
   MOZ_ASSERT_UNREACHABLE("Unknown observer topic!");
--- a/dom/workers/RuntimeService.h
+++ b/dom/workers/RuntimeService.h
@@ -153,16 +153,18 @@ class RuntimeService final : public nsIO
     AssertIsOnMainThread();
     sDefaultJSSettings.gcZeal = aGCZeal;
     sDefaultJSSettings.gcZealFrequency = aFrequency;
   }
 
   void UpdateAllWorkerGCZeal();
 #endif
 
+  void SetLowMemoryStateAllWorkers(bool aState);
+
   void GarbageCollectAllWorkers(bool aShrinking);
 
   void CycleCollectAllWorkers();
 
   void SendOfflineStatusChangeEventToAllWorkers(bool aIsOffline);
 
   void MemoryPressureAllWorkers();
 
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -691,16 +691,32 @@ class UpdateGCZealRunnable final : publi
   virtual bool WorkerRun(JSContext* aCx,
                          WorkerPrivate* aWorkerPrivate) override {
     aWorkerPrivate->UpdateGCZealInternal(aCx, mGCZeal, mFrequency);
     return true;
   }
 };
 #endif
 
+class SetLowMemoryStateRunnable final : public WorkerControlRunnable {
+  bool mState;
+
+ public:
+  SetLowMemoryStateRunnable(WorkerPrivate* aWorkerPrivate, bool aState)
+      : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
+        mState(aState) {}
+
+ private:
+  virtual bool WorkerRun(JSContext* aCx,
+                         WorkerPrivate* aWorkerPrivate) override {
+    aWorkerPrivate->SetLowMemoryStateInternal(aCx, mState);
+    return true;
+  }
+};
+
 class GarbageCollectRunnable final : public WorkerControlRunnable {
   bool mShrinking;
   bool mCollectChildren;
 
  public:
   GarbageCollectRunnable(WorkerPrivate* aWorkerPrivate, bool aShrinking,
                          bool aCollectChildren)
       : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
@@ -1814,16 +1830,26 @@ void WorkerPrivate::UpdateGCZeal(uint8_t
   RefPtr<UpdateGCZealRunnable> runnable =
       new UpdateGCZealRunnable(this, aGCZeal, aFrequency);
   if (!runnable->Dispatch()) {
     NS_WARNING("Failed to update worker gczeal!");
   }
 }
 #endif
 
+void WorkerPrivate::SetLowMemoryState(bool aState) {
+  AssertIsOnParentThread();
+
+  RefPtr<SetLowMemoryStateRunnable> runnable =
+      new SetLowMemoryStateRunnable(this, aState);
+  if (!runnable->Dispatch()) {
+    NS_WARNING("Failed to set low memory state!");
+  }
+}
+
 void WorkerPrivate::GarbageCollect(bool aShrinking) {
   AssertIsOnParentThread();
 
   RefPtr<GarbageCollectRunnable> runnable = new GarbageCollectRunnable(
       this, aShrinking, /* collectChildren = */ true);
   if (!runnable->Dispatch()) {
     NS_WARNING("Failed to GC worker!");
   }
@@ -4497,16 +4523,26 @@ void WorkerPrivate::UpdateGCZealInternal
   JS_SetGCZeal(aCx, aGCZeal, aFrequency);
 
   for (uint32_t index = 0; index < data->mChildWorkers.Length(); index++) {
     data->mChildWorkers[index]->UpdateGCZeal(aGCZeal, aFrequency);
   }
 }
 #endif
 
+void WorkerPrivate::SetLowMemoryStateInternal(JSContext* aCx, bool aState) {
+  MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
+
+  JS::SetLowMemoryState(aCx, aState);
+
+  for (uint32_t index = 0; index < data->mChildWorkers.Length(); index++) {
+    data->mChildWorkers[index]->SetLowMemoryState(aState);
+  }
+}
+
 void WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking,
                                            bool aCollectChildren) {
   MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
 
   if (!GlobalScope()) {
     // We haven't compiled anything yet. Just bail out.
     return;
   }
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -273,16 +273,18 @@ class WorkerPrivate : public RelativeTim
 
   bool CollectRuntimeStats(JS::RuntimeStats* aRtStats, bool aAnonymize);
 
 #ifdef JS_GC_ZEAL
   void UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal,
                             uint32_t aFrequency);
 #endif
 
+  void SetLowMemoryStateInternal(JSContext* aCx, bool aState);
+
   void GarbageCollectInternal(JSContext* aCx, bool aShrinking,
                               bool aCollectChildren);
 
   void CycleCollectInternal(bool aCollectChildren);
 
   void OfflineStatusChangeEventInternal(bool aIsOffline);
 
   void MemoryPressureInternal();
@@ -798,16 +800,18 @@ class WorkerPrivate : public RelativeTim
 
   void DisableDebugger();
 
   already_AddRefed<WorkerRunnable> MaybeWrapAsWorkerRunnable(
       already_AddRefed<nsIRunnable> aRunnable);
 
   bool ProxyReleaseMainThreadObjects();
 
+  void SetLowMemoryState(bool aState);
+
   void GarbageCollect(bool aShrinking);
 
   void CycleCollect(bool aDummy);
 
   nsresult SetPrincipalsAndCSPOnMainThread(nsIPrincipal* aPrincipal,
                                            nsIPrincipal* aStoragePrincipal,
                                            nsILoadGroup* aLoadGroup,
                                            nsIContentSecurityPolicy* aCsp);
--- a/js/public/GCAPI.h
+++ b/js/public/GCAPI.h
@@ -917,16 +917,18 @@ class JS_PUBLIC_API AutoCheckCannotGC : 
 } JS_HAZ_GC_INVALIDATED;
 #else
 class JS_PUBLIC_API AutoCheckCannotGC : public AutoRequireNoGC {
  public:
   explicit AutoCheckCannotGC(JSContext* cx = nullptr) {}
 } JS_HAZ_GC_INVALIDATED;
 #endif
 
+extern JS_PUBLIC_API void SetLowMemoryState(JSContext* cx, bool newState);
+
 /*
  * Internal to Firefox.
  */
 extern JS_FRIEND_API void NotifyGCRootsRemoved(JSContext* cx);
 
 } /* namespace JS */
 
 /**
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -1033,16 +1033,17 @@ GCRuntime::GCRuntime(JSRuntime* rt)
       zealFrequency(0),
       nextScheduled(0),
       deterministicOnly(false),
       incrementalLimit(0),
 #endif
       fullCompartmentChecks(false),
       gcCallbackDepth(0),
       alwaysPreserveCode(false),
+      lowMemoryState(false),
 #ifdef DEBUG
       arenasEmptyAtShutdown(true),
 #endif
       lock(mutexid::GCLock),
       allocTask(rt, emptyChunks_.ref()),
       sweepTask(rt),
       freeTask(rt),
       decommitTask(rt),
@@ -8913,16 +8914,20 @@ JS_PUBLIC_API JS::DoCycleCollectionCallb
 }
 
 JS_PUBLIC_API JS::GCNurseryCollectionCallback
 JS::SetGCNurseryCollectionCallback(JSContext* cx,
                                    GCNurseryCollectionCallback callback) {
   return cx->runtime()->gc.setNurseryCollectionCallback(callback);
 }
 
+JS_PUBLIC_API void JS::SetLowMemoryState(JSContext* cx, bool newState) {
+  return cx->runtime()->gc.setLowMemoryState(newState);
+}
+
 JS_PUBLIC_API void JS::DisableIncrementalGC(JSContext* cx) {
   cx->runtime()->gc.disallowIncrementalGC();
 }
 
 JS_PUBLIC_API bool JS::IsIncrementalGCEnabled(JSContext* cx) {
   return cx->runtime()->gc.isIncrementalGCEnabled() &&
          !mozilla::recordreplay::IsRecordingOrReplaying();
 }
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -312,16 +312,19 @@ class GCRuntime {
 #endif
 
   uint64_t nextCellUniqueId() {
     MOZ_ASSERT(nextCellUniqueId_ > 0);
     uint64_t uid = ++nextCellUniqueId_;
     return uid;
   }
 
+  void setLowMemoryState(bool newState) { lowMemoryState = newState; }
+  bool systemHasLowMemory() const { return lowMemoryState; }
+
 #ifdef DEBUG
   bool shutdownCollectedEverything() const { return arenasEmptyAtShutdown; }
 #endif
 
  public:
   // Internal public interface
   State state() const { return incrementalState; }
   bool isHeapCompacting() const { return state() == State::Compact; }
@@ -403,17 +406,16 @@ class GCRuntime {
       JSWeakPointerCompartmentCallback callback, void* data);
   void removeWeakPointerCompartmentCallback(
       JSWeakPointerCompartmentCallback callback);
   JS::GCSliceCallback setSliceCallback(JS::GCSliceCallback callback);
   JS::GCNurseryCollectionCallback setNurseryCollectionCallback(
       JS::GCNurseryCollectionCallback callback);
   JS::DoCycleCollectionCallback setDoCycleCollectionCallback(
       JS::DoCycleCollectionCallback callback);
-  void callDoCycleCollectionCallback(JSContext* cx);
 
   void setFullCompartmentChecks(bool enable);
 
   JS::Zone* getCurrentSweepGroup() { return currentSweepGroup; }
   unsigned getCurrentSweepGroupIndex() {
     return state() == State::Sweep ? sweepGroupIndex : 0;
   }
 
@@ -700,16 +702,17 @@ class GCRuntime {
 
 #ifdef DEBUG
   void checkForCompartmentMismatches();
 #endif
 
   void callFinalizeCallbacks(FreeOp* fop, JSFinalizeStatus status) const;
   void callWeakPointerZonesCallbacks() const;
   void callWeakPointerCompartmentCallbacks(JS::Compartment* comp) const;
+  void callDoCycleCollectionCallback(JSContext* cx);
 
  public:
   JSRuntime* const rt;
 
   /* Embedders can use this zone and group however they wish. */
   UnprotectedData<JS::Zone*> systemZone;
 
   // All zones in the runtime, except the atoms zone.
@@ -1010,16 +1013,18 @@ class GCRuntime {
    * collector.
    */
   CallbackVector<JSTraceDataOp> blackRootTracers;
   Callback<JSTraceDataOp> grayRootTracer;
 
   /* Always preserve JIT code during GCs, for testing. */
   MainThreadData<bool> alwaysPreserveCode;
 
+  MainThreadData<bool> lowMemoryState;
+
 #ifdef DEBUG
   MainThreadData<bool> arenasEmptyAtShutdown;
 #endif
 
   /* Synchronize GC heap access among GC helper threads and the main thread. */
   friend class js::AutoLockGC;
   friend class js::AutoLockGCBgAlloc;
   js::Mutex lock;
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -1298,19 +1298,19 @@ bool js::Nursery::maybeResizeExact(JS::G
   // Disable the nursery if the user changed the configuration setting. The
   // nursery can only be re-enabled by resetting the configuration and
   // restarting firefox.
   if (tunables().gcMaxNurseryBytes() == 0) {
     disable();
     return true;
   }
 
-  // Shrink the nursery to its minimum size of we ran out of memory or
+  // Shrink the nursery to its minimum size if we ran out of memory or
   // received a memory pressure event.
-  if (gc::IsOOMReason(reason)) {
+  if (gc::IsOOMReason(reason) || runtime()->gc.systemHasLowMemory()) {
     minimizeAllocableSpace();
     return true;
   }
 
 #ifdef JS_GC_ZEAL
   // This zeal mode disabled nursery resizing.
   if (runtime()->hasZealMode(ZealMode::GenerationalGC)) {
     return true;
--- a/xpcom/base/AvailableMemoryTracker.cpp
+++ b/xpcom/base/AvailableMemoryTracker.cpp
@@ -89,16 +89,17 @@ class nsAvailableMemoryWatcher final : p
 
   static bool IsVirtualMemoryLow();
   static bool IsCommitSpaceLow();
 
   ~nsAvailableMemoryWatcher(){};
   bool OngoingMemoryPressure() { return mUnderMemoryPressure; }
   void AdjustPollingInterval(const bool aLowMemory);
   void SendMemoryPressureEvent();
+  void MaybeSendMemoryPressureStopEvent();
   void MaybeSaveMemoryReport();
   void Shutdown();
 
   nsCOMPtr<nsITimer> mTimer;
   bool mUnderMemoryPressure;
   bool mSavedReport;
 };
 
@@ -183,16 +184,22 @@ bool nsAvailableMemoryWatcher::IsCommitS
 }
 
 void nsAvailableMemoryWatcher::SendMemoryPressureEvent() {
   MemoryPressureState state =
       OngoingMemoryPressure() ? MemPressure_Ongoing : MemPressure_New;
   NS_DispatchEventualMemoryPressure(state);
 }
 
+void nsAvailableMemoryWatcher::MaybeSendMemoryPressureStopEvent() {
+  if (OngoingMemoryPressure()) {
+    NS_DispatchEventualMemoryPressure(MemPressure_Stopping);
+  }
+}
+
 void nsAvailableMemoryWatcher::MaybeSaveMemoryReport() {
   if (!mSavedReport && OngoingMemoryPressure()) {
     nsCOMPtr<nsICrashReporter> cr =
         do_GetService("@mozilla.org/toolkit/crash-reporter;1");
     if (cr) {
       if (NS_SUCCEEDED(cr->SaveMemoryReport())) {
         mSavedReport = true;
       }
@@ -216,16 +223,21 @@ void nsAvailableMemoryWatcher::AdjustPol
 // will send memory-pressure events if memory is running low and adjust the
 // polling interval accordingly.
 NS_IMETHODIMP
 nsAvailableMemoryWatcher::Notify(nsITimer* aTimer) {
   bool lowMemory = IsVirtualMemoryLow() || IsCommitSpaceLow();
 
   if (lowMemory) {
     SendMemoryPressureEvent();
+  } else {
+    MaybeSendMemoryPressureStopEvent();
+  }
+
+  if (lowMemory) {
     MaybeSaveMemoryReport();
   } else {
     mSavedReport = false;  // Save a new report if memory gets low again
   }
 
   AdjustPollingInterval(lowMemory);
   mUnderMemoryPressure = lowMemory;
 
--- a/xpcom/threads/nsMemoryPressure.h
+++ b/xpcom/threads/nsMemoryPressure.h
@@ -50,17 +50,20 @@ enum MemoryPressureState {
    * The priority ordering between concurrent attempts to queue both stopped
    * and ongoing memory pressure is currently not defined.
    */
   MemPressure_Stopping
 };
 
 /**
  * Return and erase the latest state of the memory pressure event set by any of
- * the corresponding dispatch function.
+ * the corresponding dispatch functions.
+ *
+ * This is called when processing events on the main thread to check whether to
+ * fire a memory pressure notification.
  */
 MemoryPressureState NS_GetPendingMemoryPressure();
 
 /**
  * This function causes the main thread to fire a memory pressure event
  * before processing the next event, but if there are no events pending in
  * the main thread's event queue, the memory pressure event would not be
  * dispatched until one is enqueued. It is infallible and does not allocate