Bug 828887 - "unused-arenas" is not freed unless worker is idle for 5 seconds. r=bent

This commit is contained in:
Gregor Wagner 2013-01-10 23:50:40 +01:00
parent dffc5ee5ab
commit 1af6f59c67
6 changed files with 101 additions and 34 deletions

View File

@ -530,6 +530,9 @@ pref("javascript.options.mem.gc_low_frequency_heap_growth", 105);
pref("javascript.options.mem.high_water_mark", 6);
pref("javascript.options.mem.gc_allocation_threshold_mb", 3);
// Allocation Threshold for workers
pref("dom.workers.mem.gc_allocation_threshold_mb", 3);
// Show/Hide scrollbars when active/inactive
pref("ui.showHideScrollbars", 1);

View File

@ -53,6 +53,9 @@ using mozilla::Preferences;
// The size of the worker runtime heaps in bytes. May be changed via pref.
#define WORKER_DEFAULT_RUNTIME_HEAPSIZE 32 * 1024 * 1024
// The size of the worker JS allocation threshold in MB. May be changed via pref.
#define WORKER_DEFAULT_ALLOCATION_THRESHOLD 30
// The C stack size. We use the same stack size on all platforms for
// consistency.
#define WORKER_STACK_SIZE 256 * sizeof(size_t) * 1024
@ -151,6 +154,7 @@ enum {
PREF_jit_hardening,
PREF_mem_max,
PREF_ion,
PREF_mem_gc_allocation_threshold_mb,
#ifdef JS_GC_ZEAL
PREF_gczeal,
@ -170,7 +174,8 @@ const char* gPrefsToWatch[] = {
JS_OPTIONS_DOT_STR "allow_xml",
JS_OPTIONS_DOT_STR "jit_hardening",
JS_OPTIONS_DOT_STR "mem.max",
JS_OPTIONS_DOT_STR "ion.content"
JS_OPTIONS_DOT_STR "ion.content",
"dom.workers.mem.gc_allocation_threshold_mb"
#ifdef JS_GC_ZEAL
, PREF_WORKERS_GCZEAL
@ -195,10 +200,16 @@ PrefCallback(const char* aPrefName, void* aClosure)
uint32_t maxBytes = (pref <= 0 || pref >= 0x1000) ?
uint32_t(-1) :
uint32_t(pref) * 1024 * 1024;
RuntimeService::SetDefaultJSRuntimeHeapSize(maxBytes);
rts->UpdateAllWorkerJSRuntimeHeapSize();
}
else if (StringBeginsWith(nsDependentCString(aPrefName), jsOptionStr)) {
RuntimeService::SetDefaultJSWorkerMemoryParameter(JSGC_MAX_BYTES, maxBytes);
rts->UpdateAllWorkerMemoryParameter(JSGC_MAX_BYTES);
} else if (!strcmp(aPrefName, gPrefsToWatch[PREF_mem_gc_allocation_threshold_mb])) {
int32_t pref = Preferences::GetInt(aPrefName, 30);
uint32_t threshold = (pref <= 0 || pref >= 0x1000) ?
uint32_t(30) :
uint32_t(pref);
RuntimeService::SetDefaultJSWorkerMemoryParameter(JSGC_ALLOCATION_THRESHOLD, threshold);
rts->UpdateAllWorkerMemoryParameter(JSGC_ALLOCATION_THRESHOLD);
} else if (StringBeginsWith(nsDependentCString(aPrefName), jsOptionStr)) {
uint32_t newOptions = kRequiredJSContextOptions;
if (Preferences::GetBool(gPrefsToWatch[PREF_strict])) {
newOptions |= JSOPTION_STRICT;
@ -419,6 +430,8 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate)
// This is the real place where we set the max memory for the runtime.
JS_SetGCParameter(runtime, JSGC_MAX_BYTES,
aWorkerPrivate->GetJSRuntimeHeapSize());
JS_SetGCParameter(runtime, JSGC_ALLOCATION_THRESHOLD,
aWorkerPrivate->GetJSWorkerAllocationThreshold());
JS_SetNativeStackQuota(runtime, WORKER_CONTEXT_NATIVE_STACK_LIMIT);
@ -686,6 +699,9 @@ uint32_t RuntimeService::sDefaultJSContextOptions = kRequiredJSContextOptions;
uint32_t RuntimeService::sDefaultJSRuntimeHeapSize =
WORKER_DEFAULT_RUNTIME_HEAPSIZE;
uint32_t RuntimeService::sDefaultJSAllocationThreshold =
WORKER_DEFAULT_ALLOCATION_THRESHOLD;
int32_t RuntimeService::sCloseHandlerTimeoutSeconds = MAX_SCRIPT_RUN_TIME_SEC;
#ifdef JS_GC_ZEAL
@ -1364,9 +1380,11 @@ RuntimeService::UpdateAllWorkerJSContextOptions()
}
void
RuntimeService::UpdateAllWorkerJSRuntimeHeapSize()
RuntimeService::UpdateAllWorkerMemoryParameter(JSGCParamKey key)
{
BROADCAST_ALL_WORKERS(UpdateJSRuntimeHeapSize, GetDefaultJSRuntimeHeapSize());
BROADCAST_ALL_WORKERS(UpdateJSWorkerMemoryParameter,
key,
GetDefaultJSWorkerMemoryParameter(key));
}
#ifdef JS_GC_ZEAL

View File

@ -73,6 +73,7 @@ class RuntimeService MOZ_FINAL : public nsIObserver
static uint32_t sDefaultJSContextOptions;
static uint32_t sDefaultJSRuntimeHeapSize;
static uint32_t sDefaultJSAllocationThreshold;
static int32_t sCloseHandlerTimeoutSeconds;
#ifdef JS_GC_ZEAL
@ -160,21 +161,37 @@ public:
UpdateAllWorkerJSContextOptions();
static uint32_t
GetDefaultJSRuntimeHeapSize()
GetDefaultJSWorkerMemoryParameter(JSGCParamKey aKey)
{
AssertIsOnMainThread();
return sDefaultJSRuntimeHeapSize;
switch (aKey) {
case JSGC_ALLOCATION_THRESHOLD:
return sDefaultJSAllocationThreshold;
case JSGC_MAX_BYTES:
return sDefaultJSRuntimeHeapSize;
default:
MOZ_NOT_REACHED("Unknown Worker Memory Parameter.");
}
}
static void
SetDefaultJSRuntimeHeapSize(uint32_t aMaxBytes)
SetDefaultJSWorkerMemoryParameter(JSGCParamKey aKey, uint32_t aValue)
{
AssertIsOnMainThread();
sDefaultJSRuntimeHeapSize = aMaxBytes;
switch(aKey) {
case JSGC_ALLOCATION_THRESHOLD:
sDefaultJSAllocationThreshold = aValue;
break;
case JSGC_MAX_BYTES:
sDefaultJSRuntimeHeapSize = aValue;
break;
default:
MOZ_NOT_REACHED("Unknown Worker Memory Parameter.");
}
}
void
UpdateAllWorkerJSRuntimeHeapSize();
UpdateAllWorkerMemoryParameter(JSGCParamKey aKey);
static uint32_t
GetCloseHandlerTimeoutSeconds()

View File

@ -1320,21 +1320,23 @@ public:
}
};
class UpdateJSRuntimeHeapSizeRunnable : public WorkerControlRunnable
class UpdateJSWorkerMemoryParameterRunnable : public WorkerControlRunnable
{
uint32_t mJSRuntimeHeapSize;
uint32_t mValue;
JSGCParamKey mKey;
public:
UpdateJSRuntimeHeapSizeRunnable(WorkerPrivate* aWorkerPrivate,
uint32_t aJSRuntimeHeapSize)
UpdateJSWorkerMemoryParameterRunnable(WorkerPrivate* aWorkerPrivate,
JSGCParamKey aKey,
uint32_t aValue)
: WorkerControlRunnable(aWorkerPrivate, WorkerThread, UnchangedBusyCount),
mJSRuntimeHeapSize(aJSRuntimeHeapSize)
mValue(aValue), mKey(aKey)
{ }
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
aWorkerPrivate->UpdateJSRuntimeHeapSizeInternal(aCx, mJSRuntimeHeapSize);
aWorkerPrivate->UpdateJSWorkerMemoryParameter(aCx, mKey, mValue);
return true;
}
};
@ -1796,7 +1798,8 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
mMemoryReportCondVar(mMutex, "WorkerPrivateParent Memory Report CondVar"),
mJSObject(aObject), mParent(aParent), mParentJSContext(aParentJSContext),
mScriptURL(aScriptURL), mDomain(aDomain), mBusyCount(0),
mParentStatus(Pending), mJSContextOptions(0), mJSRuntimeHeapSize(0),
mParentStatus(Pending), mJSContextOptions(0),
mJSRuntimeHeapSize(0), mJSWorkerAllocationThreshold(3),
mGCZeal(0), mJSObjectRooted(false), mParentSuspended(false),
mIsChromeWorker(aIsChromeWorker), mPrincipalIsSystem(false),
mMainThreadObjectsForgotten(false), mEvalAllowed(aEvalAllowed)
@ -1826,6 +1829,8 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
"Runtime heap size mismatch!");
mJSRuntimeHeapSize = aParent->GetJSRuntimeHeapSize();
mJSWorkerAllocationThreshold = aParent->GetJSWorkerAllocationThreshold();
#ifdef JS_GC_ZEAL
mGCZeal = aParent->GetGCZeal();
#endif
@ -1834,7 +1839,10 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
AssertIsOnMainThread();
mJSContextOptions = RuntimeService::GetDefaultJSContextOptions();
mJSRuntimeHeapSize = RuntimeService::GetDefaultJSRuntimeHeapSize();
mJSRuntimeHeapSize =
RuntimeService::GetDefaultJSWorkerMemoryParameter(JSGC_MAX_BYTES);
mJSWorkerAllocationThreshold =
RuntimeService::GetDefaultJSWorkerMemoryParameter(JSGC_ALLOCATION_THRESHOLD);
#ifdef JS_GC_ZEAL
mGCZeal = RuntimeService::GetDefaultGCZeal();
#endif
@ -2200,17 +2208,28 @@ WorkerPrivateParent<Derived>::UpdateJSContextOptions(JSContext* aCx,
template <class Derived>
void
WorkerPrivateParent<Derived>::UpdateJSRuntimeHeapSize(JSContext* aCx,
uint32_t aMaxBytes)
WorkerPrivateParent<Derived>::UpdateJSWorkerMemoryParameter(JSContext* aCx,
JSGCParamKey aKey,
uint32_t aValue)
{
AssertIsOnParentThread();
switch(aKey) {
case JSGC_ALLOCATION_THRESHOLD:
mJSWorkerAllocationThreshold = aValue;
break;
case JSGC_MAX_BYTES:
mJSRuntimeHeapSize = aValue;
break;
default:
break;
}
mJSRuntimeHeapSize = aMaxBytes;
nsRefPtr<UpdateJSRuntimeHeapSizeRunnable> runnable =
new UpdateJSRuntimeHeapSizeRunnable(ParentAsWorkerPrivate(), aMaxBytes);
nsRefPtr<UpdateJSWorkerMemoryParameterRunnable> runnable =
new UpdateJSWorkerMemoryParameterRunnable(ParentAsWorkerPrivate(),
aKey,
aValue);
if (!runnable->Dispatch(aCx)) {
NS_WARNING("Failed to update worker heap size!");
NS_WARNING("Failed to update memory parameter!");
JS_ClearPendingException(aCx);
}
}
@ -4011,15 +4030,15 @@ WorkerPrivate::UpdateJSContextOptionsInternal(JSContext* aCx, uint32_t aOptions)
}
void
WorkerPrivate::UpdateJSRuntimeHeapSizeInternal(JSContext* aCx,
uint32_t aMaxBytes)
WorkerPrivate::UpdateJSWorkerMemoryParameterInternal(JSContext* aCx,
JSGCParamKey aKey,
uint32_t aValue)
{
AssertIsOnWorkerThread();
JS_SetGCParameter(JS_GetRuntime(aCx), JSGC_MAX_BYTES, aMaxBytes);
JS_SetGCParameter(JS_GetRuntime(aCx), aKey, aValue);
for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
mChildWorkers[index]->UpdateJSRuntimeHeapSize(aCx, aMaxBytes);
mChildWorkers[index]->UpdateJSWorkerMemoryParameter(aCx, aKey, aValue);
}
}

View File

@ -193,6 +193,7 @@ private:
Status mParentStatus;
uint32_t mJSContextOptions;
uint32_t mJSRuntimeHeapSize;
uint32_t mJSWorkerAllocationThreshold;
uint8_t mGCZeal;
bool mJSObjectRooted;
bool mParentSuspended;
@ -304,7 +305,7 @@ public:
UpdateJSContextOptions(JSContext* aCx, uint32_t aOptions);
void
UpdateJSRuntimeHeapSize(JSContext* aCx, uint32_t aJSRuntimeHeapSize);
UpdateJSWorkerMemoryParameter(JSContext* aCx, JSGCParamKey key, uint32_t value);
#ifdef JS_GC_ZEAL
void
@ -485,6 +486,12 @@ public:
return mJSRuntimeHeapSize;
}
uint32_t
GetJSWorkerAllocationThreshold() const
{
return mJSWorkerAllocationThreshold;
}
#ifdef JS_GC_ZEAL
uint8_t
GetGCZeal() const
@ -706,7 +713,7 @@ public:
UpdateJSContextOptionsInternal(JSContext* aCx, uint32_t aOptions);
void
UpdateJSRuntimeHeapSizeInternal(JSContext* aCx, uint32_t aJSRuntimeHeapSize);
UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key, uint32_t aValue);
void
ScheduleDeletion(bool aWasPending);

View File

@ -694,6 +694,9 @@ pref("dom.experimental_bindings", true);
// Don't use new input types
pref("dom.experimental_forms", false);
// Allocation Threshold for Workers
pref("dom.workers.mem.gc_allocation_threshold_mb", 30);
// Parsing perf prefs. For now just mimic what the old code did.
#ifndef XP_WIN
pref("content.sink.pending_event_mode", 0);