Bug 927740 (part 3) - Make workers respond to "child-cc-request" notifications. r=khuey.

--HG--
extra : rebase_source : 34a15c4bf15bb0fd1601675e7e7cc4b5117ed433
This commit is contained in:
Nicholas Nethercote 2013-12-02 20:07:02 -08:00
parent 71bcf4e744
commit f877b263ed
4 changed files with 98 additions and 5 deletions

View File

@ -101,6 +101,7 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
#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 BROADCAST_ALL_WORKERS(_func, ...) \
@ -1579,6 +1580,10 @@ RuntimeService::Init()
NS_WARNING("Failed to register for GC request notifications!");
}
if (NS_FAILED(obs->AddObserver(this, CC_REQUEST_OBSERVER_TOPIC, false))) {
NS_WARNING("Failed to register for CC request notifications!");
}
if (NS_FAILED(obs->AddObserver(this, MEMORY_PRESSURE_OBSERVER_TOPIC,
false))) {
NS_WARNING("Failed to register for memory pressure notifications!");
@ -1827,6 +1832,10 @@ RuntimeService::Cleanup()
NS_WARNING("Failed to unregister for GC request notifications!");
}
if (NS_FAILED(obs->RemoveObserver(this, CC_REQUEST_OBSERVER_TOPIC))) {
NS_WARNING("Failed to unregister for CC request notifications!");
}
if (NS_FAILED(obs->RemoveObserver(this,
MEMORY_PRESSURE_OBSERVER_TOPIC))) {
NS_WARNING("Failed to unregister for memory pressure notifications!");
@ -2203,6 +2212,12 @@ RuntimeService::GarbageCollectAllWorkers(bool aShrinking)
BROADCAST_ALL_WORKERS(GarbageCollect, aShrinking);
}
void
RuntimeService::CycleCollectAllWorkers()
{
BROADCAST_ALL_WORKERS(CycleCollect, /* dummy = */ false);
}
// nsISupports
NS_IMPL_ISUPPORTS1(RuntimeService, nsIObserver)
@ -2222,11 +2237,15 @@ RuntimeService::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
if (!strcmp(aTopic, GC_REQUEST_OBSERVER_TOPIC)) {
GarbageCollectAllWorkers(false);
GarbageCollectAllWorkers(/* shrinking = */ false);
return NS_OK;
}
if (!strcmp(aTopic, CC_REQUEST_OBSERVER_TOPIC)) {
CycleCollectAllWorkers();
return NS_OK;
}
if (!strcmp(aTopic, MEMORY_PRESSURE_OBSERVER_TOPIC)) {
GarbageCollectAllWorkers(true);
GarbageCollectAllWorkers(/* shrinking = */ true);
return NS_OK;
}

View File

@ -252,6 +252,9 @@ public:
void
GarbageCollectAllWorkers(bool aShrinking);
void
CycleCollectAllWorkers();
private:
RuntimeService();
~RuntimeService();

View File

@ -1573,7 +1573,7 @@ public:
void
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
bool aDispatchResult)
bool aDispatchResult)
{
// Silence bad assertions, this can be dispatched from either the main
// thread or the timer thread..
@ -1587,6 +1587,41 @@ public:
}
};
class CycleCollectRunnable : public WorkerControlRunnable
{
protected:
bool mCollectChildren;
public:
CycleCollectRunnable(WorkerPrivate* aWorkerPrivate, bool aCollectChildren)
: WorkerControlRunnable(aWorkerPrivate, WorkerThread, UnchangedBusyCount),
mCollectChildren(aCollectChildren)
{ }
bool
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
// Silence bad assertions, this can be dispatched from either the main
// thread or the timer thread..
return true;
}
void
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
bool aDispatchResult)
{
// Silence bad assertions, this can be dispatched from either the main
// thread or the timer thread..
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
aWorkerPrivate->CycleCollectInternal(aCx, mCollectChildren);
return true;
}
};
class WorkerJSRuntimeStats : public JS::RuntimeStats
{
const nsACString& mRtPath;
@ -2892,9 +2927,25 @@ WorkerPrivateParent<Derived>::GarbageCollect(JSContext* aCx, bool aShrinking)
AssertIsOnParentThread();
nsRefPtr<GarbageCollectRunnable> runnable =
new GarbageCollectRunnable(ParentAsWorkerPrivate(), aShrinking, true);
new GarbageCollectRunnable(ParentAsWorkerPrivate(), aShrinking,
/* collectChildren = */ true);
if (!runnable->Dispatch(aCx)) {
NS_WARNING("Failed to update worker heap size!");
NS_WARNING("Failed to GC worker!");
JS_ClearPendingException(aCx);
}
}
template <class Derived>
void
WorkerPrivateParent<Derived>::CycleCollect(JSContext* aCx, bool aDummy)
{
AssertIsOnParentThread();
nsRefPtr<CycleCollectRunnable> runnable =
new CycleCollectRunnable(ParentAsWorkerPrivate(),
/* collectChildren = */ true);
if (!runnable->Dispatch(aCx)) {
NS_WARNING("Failed to CC worker!");
JS_ClearPendingException(aCx);
}
}
@ -5218,6 +5269,20 @@ WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking,
}
}
void
WorkerPrivate::CycleCollectInternal(JSContext* aCx, bool aCollectChildren)
{
AssertIsOnWorkerThread();
nsCycleCollector_collect(nullptr);
if (aCollectChildren) {
for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
mChildWorkers[index]->CycleCollect(aCx, /* dummy = */ false);
}
}
}
template <class Derived>
void

View File

@ -494,6 +494,9 @@ public:
void
GarbageCollect(JSContext* aCx, bool aShrinking);
void
CycleCollect(JSContext* aCx, bool aDummy);
bool
RegisterSharedWorker(JSContext* aCx, SharedWorker* aSharedWorker);
@ -1006,6 +1009,9 @@ public:
GarbageCollectInternal(JSContext* aCx, bool aShrinking,
bool aCollectChildren);
void
CycleCollectInternal(JSContext* aCx, bool aCollectChildren);
JSContext*
GetJSContext() const
{