mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 1560931 - Set JS engine low memory state based on memory pressure notifications r=smaug
Update the memory pressure observers for main thread and workers to call the new JS API to set/clear the low memory state. Differential Revision: https://phabricator.services.mozilla.com/D35682
This commit is contained in:
parent
ca04a00e08
commit
22952620f8
@ -332,12 +332,15 @@ 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);
|
||||
@ -348,6 +351,8 @@ nsJSEnvironmentObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
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();
|
||||
@ -1080,6 +1085,12 @@ void FullGCTimerFired(nsITimer* aTimer, void* aClosure) {
|
||||
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,
|
||||
|
@ -66,6 +66,8 @@ class nsJSContext : public nsIScriptContext {
|
||||
// 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,
|
||||
|
@ -139,7 +139,9 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
|
||||
#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 \
|
||||
@ -2121,6 +2123,10 @@ void RuntimeService::UpdateAllWorkerGCZeal() {
|
||||
}
|
||||
#endif
|
||||
|
||||
void RuntimeService::SetLowMemoryStateAllWorkers(bool aState) {
|
||||
BROADCAST_ALL_WORKERS(SetLowMemoryState, aState);
|
||||
}
|
||||
|
||||
void RuntimeService::GarbageCollectAllWorkers(bool aShrinking) {
|
||||
BROADCAST_ALL_WORKERS(GarbageCollect, aShrinking);
|
||||
}
|
||||
@ -2200,13 +2206,22 @@ RuntimeService::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
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)) {
|
||||
|
@ -158,6 +158,8 @@ class RuntimeService final : public nsIObserver {
|
||||
void UpdateAllWorkerGCZeal();
|
||||
#endif
|
||||
|
||||
void SetLowMemoryStateAllWorkers(bool aState);
|
||||
|
||||
void GarbageCollectAllWorkers(bool aShrinking);
|
||||
|
||||
void CycleCollectAllWorkers();
|
||||
|
@ -696,6 +696,22 @@ class UpdateGCZealRunnable final : public WorkerControlRunnable {
|
||||
};
|
||||
#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;
|
||||
@ -1819,6 +1835,16 @@ void WorkerPrivate::UpdateGCZeal(uint8_t aGCZeal, uint32_t aFrequency) {
|
||||
}
|
||||
#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();
|
||||
|
||||
@ -4502,6 +4528,16 @@ void WorkerPrivate::UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal,
|
||||
}
|
||||
#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);
|
||||
|
@ -278,6 +278,8 @@ class WorkerPrivate : public RelativeTimeline {
|
||||
uint32_t aFrequency);
|
||||
#endif
|
||||
|
||||
void SetLowMemoryStateInternal(JSContext* aCx, bool aState);
|
||||
|
||||
void GarbageCollectInternal(JSContext* aCx, bool aShrinking,
|
||||
bool aCollectChildren);
|
||||
|
||||
@ -803,6 +805,8 @@ class WorkerPrivate : public RelativeTimeline {
|
||||
|
||||
bool ProxyReleaseMainThreadObjects();
|
||||
|
||||
void SetLowMemoryState(bool aState);
|
||||
|
||||
void GarbageCollect(bool aShrinking);
|
||||
|
||||
void CycleCollect(bool aDummy);
|
||||
|
@ -922,6 +922,8 @@ class JS_PUBLIC_API AutoCheckCannotGC : public AutoRequireNoGC {
|
||||
} JS_HAZ_GC_INVALIDATED;
|
||||
#endif
|
||||
|
||||
extern JS_PUBLIC_API void SetLowMemoryState(JSContext* cx, bool newState);
|
||||
|
||||
/*
|
||||
* Internal to Firefox.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user