зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1309929 - Use an async memory report for workers r=erahm r=bkelly
This commit is contained in:
Родитель
2e93de882f
Коммит
11dbca2419
|
@ -1510,76 +1510,6 @@ StartsWithExplicit(nsACString& s)
|
|||
}
|
||||
#endif
|
||||
|
||||
class MOZ_STACK_CLASS WorkerJSContextStats final : public JS::RuntimeStats
|
||||
{
|
||||
const nsACString& mRtPath;
|
||||
|
||||
public:
|
||||
explicit WorkerJSContextStats(const nsACString& aRtPath)
|
||||
: JS::RuntimeStats(JsWorkerMallocSizeOf), mRtPath(aRtPath)
|
||||
{ }
|
||||
|
||||
~WorkerJSContextStats()
|
||||
{
|
||||
for (size_t i = 0; i != zoneStatsVector.length(); i++) {
|
||||
delete static_cast<xpc::ZoneStatsExtras*>(zoneStatsVector[i].extra);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i != compartmentStatsVector.length(); i++) {
|
||||
delete static_cast<xpc::CompartmentStatsExtras*>(compartmentStatsVector[i].extra);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void
|
||||
initExtraZoneStats(JS::Zone* aZone,
|
||||
JS::ZoneStats* aZoneStats)
|
||||
override
|
||||
{
|
||||
MOZ_ASSERT(!aZoneStats->extra);
|
||||
|
||||
// ReportJSRuntimeExplicitTreeStats expects that
|
||||
// aZoneStats->extra is a xpc::ZoneStatsExtras pointer.
|
||||
xpc::ZoneStatsExtras* extras = new xpc::ZoneStatsExtras;
|
||||
extras->pathPrefix = mRtPath;
|
||||
extras->pathPrefix += nsPrintfCString("zone(0x%p)/", (void *)aZone);
|
||||
|
||||
MOZ_ASSERT(StartsWithExplicit(extras->pathPrefix));
|
||||
|
||||
aZoneStats->extra = extras;
|
||||
}
|
||||
|
||||
virtual void
|
||||
initExtraCompartmentStats(JSCompartment* aCompartment,
|
||||
JS::CompartmentStats* aCompartmentStats)
|
||||
override
|
||||
{
|
||||
MOZ_ASSERT(!aCompartmentStats->extra);
|
||||
|
||||
// ReportJSRuntimeExplicitTreeStats expects that
|
||||
// aCompartmentStats->extra is a xpc::CompartmentStatsExtras pointer.
|
||||
xpc::CompartmentStatsExtras* extras = new xpc::CompartmentStatsExtras;
|
||||
|
||||
// This is the |jsPathPrefix|. Each worker has exactly two compartments:
|
||||
// one for atoms, and one for everything else.
|
||||
extras->jsPathPrefix.Assign(mRtPath);
|
||||
extras->jsPathPrefix += nsPrintfCString("zone(0x%p)/",
|
||||
(void *)js::GetCompartmentZone(aCompartment));
|
||||
extras->jsPathPrefix += js::IsAtomsCompartment(aCompartment)
|
||||
? NS_LITERAL_CSTRING("compartment(web-worker-atoms)/")
|
||||
: NS_LITERAL_CSTRING("compartment(web-worker)/");
|
||||
|
||||
// This should never be used when reporting with workers (hence the "?!").
|
||||
extras->domPathPrefix.AssignLiteral("explicit/workers/?!/");
|
||||
|
||||
MOZ_ASSERT(StartsWithExplicit(extras->jsPathPrefix));
|
||||
MOZ_ASSERT(StartsWithExplicit(extras->domPathPrefix));
|
||||
|
||||
extras->location = nullptr;
|
||||
|
||||
aCompartmentStats->extra = extras;
|
||||
}
|
||||
};
|
||||
|
||||
class MessagePortRunnable final : public WorkerRunnable
|
||||
{
|
||||
MessagePortIdentifier mPortIdentifier;
|
||||
|
@ -2003,6 +1933,81 @@ struct WorkerPrivate::TimeoutInfo
|
|||
bool mCanceled;
|
||||
};
|
||||
|
||||
class WorkerJSContextStats final : public JS::RuntimeStats
|
||||
{
|
||||
const nsCString mRtPath;
|
||||
|
||||
public:
|
||||
explicit WorkerJSContextStats(const nsACString& aRtPath)
|
||||
: JS::RuntimeStats(JsWorkerMallocSizeOf), mRtPath(aRtPath)
|
||||
{ }
|
||||
|
||||
~WorkerJSContextStats()
|
||||
{
|
||||
for (size_t i = 0; i != zoneStatsVector.length(); i++) {
|
||||
delete static_cast<xpc::ZoneStatsExtras*>(zoneStatsVector[i].extra);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i != compartmentStatsVector.length(); i++) {
|
||||
delete static_cast<xpc::CompartmentStatsExtras*>(compartmentStatsVector[i].extra);
|
||||
}
|
||||
}
|
||||
|
||||
const nsCString& Path() const
|
||||
{
|
||||
return mRtPath;
|
||||
}
|
||||
|
||||
virtual void
|
||||
initExtraZoneStats(JS::Zone* aZone,
|
||||
JS::ZoneStats* aZoneStats)
|
||||
override
|
||||
{
|
||||
MOZ_ASSERT(!aZoneStats->extra);
|
||||
|
||||
// ReportJSRuntimeExplicitTreeStats expects that
|
||||
// aZoneStats->extra is a xpc::ZoneStatsExtras pointer.
|
||||
xpc::ZoneStatsExtras* extras = new xpc::ZoneStatsExtras;
|
||||
extras->pathPrefix = mRtPath;
|
||||
extras->pathPrefix += nsPrintfCString("zone(0x%p)/", (void *)aZone);
|
||||
|
||||
MOZ_ASSERT(StartsWithExplicit(extras->pathPrefix));
|
||||
|
||||
aZoneStats->extra = extras;
|
||||
}
|
||||
|
||||
virtual void
|
||||
initExtraCompartmentStats(JSCompartment* aCompartment,
|
||||
JS::CompartmentStats* aCompartmentStats)
|
||||
override
|
||||
{
|
||||
MOZ_ASSERT(!aCompartmentStats->extra);
|
||||
|
||||
// ReportJSRuntimeExplicitTreeStats expects that
|
||||
// aCompartmentStats->extra is a xpc::CompartmentStatsExtras pointer.
|
||||
xpc::CompartmentStatsExtras* extras = new xpc::CompartmentStatsExtras;
|
||||
|
||||
// This is the |jsPathPrefix|. Each worker has exactly two compartments:
|
||||
// one for atoms, and one for everything else.
|
||||
extras->jsPathPrefix.Assign(mRtPath);
|
||||
extras->jsPathPrefix += nsPrintfCString("zone(0x%p)/",
|
||||
(void *)js::GetCompartmentZone(aCompartment));
|
||||
extras->jsPathPrefix += js::IsAtomsCompartment(aCompartment)
|
||||
? NS_LITERAL_CSTRING("compartment(web-worker-atoms)/")
|
||||
: NS_LITERAL_CSTRING("compartment(web-worker)/");
|
||||
|
||||
// This should never be used when reporting with workers (hence the "?!").
|
||||
extras->domPathPrefix.AssignLiteral("explicit/workers/?!/");
|
||||
|
||||
MOZ_ASSERT(StartsWithExplicit(extras->jsPathPrefix));
|
||||
MOZ_ASSERT(StartsWithExplicit(extras->domPathPrefix));
|
||||
|
||||
extras->location = nullptr;
|
||||
|
||||
aCompartmentStats->extra = extras;
|
||||
}
|
||||
};
|
||||
|
||||
class WorkerPrivate::MemoryReporter final : public nsIMemoryReporter
|
||||
{
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
@ -2019,33 +2024,129 @@ public:
|
|||
mAlreadyMappedToAddon(false)
|
||||
{
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aData, bool aAnonymize) override
|
||||
nsISupports* aData, bool aAnonymize) override;
|
||||
|
||||
private:
|
||||
class FinishCollectRunnable;
|
||||
|
||||
class CollectReportsRunnable final : public MainThreadWorkerControlRunnable
|
||||
{
|
||||
RefPtr<FinishCollectRunnable> mFinishCollectRunnable;
|
||||
const bool mAnonymize;
|
||||
|
||||
public:
|
||||
CollectReportsRunnable(
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aHandlerData,
|
||||
bool aAnonymize,
|
||||
const nsACString& aPath);
|
||||
|
||||
private:
|
||||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override;
|
||||
|
||||
~CollectReportsRunnable()
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
mFinishCollectRunnable->Run();
|
||||
return;
|
||||
}
|
||||
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
workerPrivate->DispatchToMainThread(mFinishCollectRunnable.forget()));
|
||||
}
|
||||
};
|
||||
|
||||
class FinishCollectRunnable final : public Runnable
|
||||
{
|
||||
nsCOMPtr<nsIHandleReportCallback> mHandleReport;
|
||||
nsCOMPtr<nsISupports> mHandlerData;
|
||||
const bool mAnonymize;
|
||||
bool mSuccess;
|
||||
|
||||
public:
|
||||
WorkerJSContextStats mCxStats;
|
||||
|
||||
explicit FinishCollectRunnable(
|
||||
nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aHandlerData,
|
||||
bool aAnonymize,
|
||||
const nsACString& aPath);
|
||||
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
void SetSuccess(bool success)
|
||||
{
|
||||
mSuccess = success;
|
||||
}
|
||||
|
||||
private:
|
||||
~FinishCollectRunnable()
|
||||
{
|
||||
// mHandleReport and mHandlerData are released on the main thread.
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
FinishCollectRunnable(const FinishCollectRunnable&) = delete;
|
||||
FinishCollectRunnable& operator=(const FinishCollectRunnable&) = delete;
|
||||
FinishCollectRunnable& operator=(const FinishCollectRunnable&&) = delete;
|
||||
};
|
||||
|
||||
~MemoryReporter()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Disable()
|
||||
{
|
||||
// Called from WorkerPrivate::DisableMemoryReporter.
|
||||
mMutex.AssertCurrentThreadOwns();
|
||||
|
||||
NS_ASSERTION(mWorkerPrivate, "Disabled more than once!");
|
||||
mWorkerPrivate = nullptr;
|
||||
}
|
||||
|
||||
// Only call this from the main thread and under mMutex lock.
|
||||
void
|
||||
TryToMapAddon(nsACString &path);
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(WorkerPrivate::MemoryReporter, nsIMemoryReporter)
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerPrivate::MemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aData,
|
||||
bool aAnonymize)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// Assumes that WorkerJSContextStats will hold a reference to |path|, and
|
||||
// not a copy, as TryToMapAddon() may later modify it.
|
||||
nsCString path;
|
||||
WorkerJSContextStats cxStats(path);
|
||||
RefPtr<CollectReportsRunnable> runnable;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (!mWorkerPrivate) {
|
||||
// Returning NS_OK here will effectively report 0 memory.
|
||||
// This will effectively report 0 memory.
|
||||
nsCOMPtr<nsIMemoryReporterManager> manager =
|
||||
do_GetService("@mozilla.org/memory-reporter-manager;1");
|
||||
if (manager) {
|
||||
manager->EndReport();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString path;
|
||||
path.AppendLiteral("explicit/workers/workers(");
|
||||
if (aAnonymize && !mWorkerPrivate->Domain().IsEmpty()) {
|
||||
path.AppendLiteral("<anonymized-domain>)/worker(<anonymized-url>");
|
||||
} else {
|
||||
nsCString escapedDomain(mWorkerPrivate->Domain());
|
||||
nsAutoCString escapedDomain(mWorkerPrivate->Domain());
|
||||
if (escapedDomain.IsEmpty()) {
|
||||
escapedDomain += "chrome";
|
||||
} else {
|
||||
|
@ -2061,35 +2162,20 @@ public:
|
|||
|
||||
TryToMapAddon(path);
|
||||
|
||||
if (!mWorkerPrivate->BlockAndCollectRuntimeStats(&cxStats, aAnonymize)) {
|
||||
// Returning NS_OK here will effectively report 0 memory.
|
||||
runnable =
|
||||
new CollectReportsRunnable(mWorkerPrivate, aHandleReport, aData, aAnonymize, path);
|
||||
}
|
||||
|
||||
if (!runnable->Dispatch()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xpc::ReportJSRuntimeExplicitTreeStats(cxStats, path, aHandleReport, aData,
|
||||
aAnonymize);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~MemoryReporter()
|
||||
{ }
|
||||
|
||||
void
|
||||
Disable()
|
||||
{
|
||||
// Called from WorkerPrivate::DisableMemoryReporter.
|
||||
mMutex.AssertCurrentThreadOwns();
|
||||
|
||||
NS_ASSERTION(mWorkerPrivate, "Disabled more than once!");
|
||||
mWorkerPrivate = nullptr;
|
||||
}
|
||||
|
||||
// Only call this from the main thread and under mMutex lock.
|
||||
void
|
||||
TryToMapAddon(nsACString &path)
|
||||
{
|
||||
void
|
||||
WorkerPrivate::MemoryReporter::TryToMapAddon(nsACString &path)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
mMutex.AssertCurrentThreadOwns();
|
||||
|
||||
|
@ -2125,10 +2211,65 @@ private:
|
|||
addonId.Insert(NS_LITERAL_CSTRING("add-ons/"), 0);
|
||||
addonId += "/";
|
||||
path.Insert(addonId, explicitLength);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(WorkerPrivate::MemoryReporter, nsIMemoryReporter)
|
||||
WorkerPrivate::MemoryReporter::CollectReportsRunnable::CollectReportsRunnable(
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aHandlerData,
|
||||
bool aAnonymize,
|
||||
const nsACString& aPath)
|
||||
: MainThreadWorkerControlRunnable(aWorkerPrivate),
|
||||
mFinishCollectRunnable(
|
||||
new FinishCollectRunnable(aHandleReport, aHandlerData, aAnonymize, aPath)),
|
||||
mAnonymize(aAnonymize)
|
||||
{ }
|
||||
|
||||
bool
|
||||
WorkerPrivate::MemoryReporter::CollectReportsRunnable::WorkerRun(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
mFinishCollectRunnable->SetSuccess(
|
||||
aWorkerPrivate->CollectRuntimeStats(&mFinishCollectRunnable->mCxStats, mAnonymize));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
WorkerPrivate::MemoryReporter::FinishCollectRunnable::FinishCollectRunnable(
|
||||
nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aHandlerData,
|
||||
bool aAnonymize,
|
||||
const nsACString& aPath)
|
||||
: mHandleReport(aHandleReport),
|
||||
mHandlerData(aHandlerData),
|
||||
mAnonymize(aAnonymize),
|
||||
mSuccess(false),
|
||||
mCxStats(aPath)
|
||||
{ }
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerPrivate::MemoryReporter::FinishCollectRunnable::Run()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsCOMPtr<nsIMemoryReporterManager> manager =
|
||||
do_GetService("@mozilla.org/memory-reporter-manager;1");
|
||||
|
||||
if (!manager)
|
||||
return NS_OK;
|
||||
|
||||
if (mSuccess) {
|
||||
xpc::ReportJSRuntimeExplicitTreeStats(mCxStats, mCxStats.Path(),
|
||||
mHandleReport, mHandlerData,
|
||||
mAnonymize);
|
||||
}
|
||||
|
||||
manager->EndReport();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
WorkerPrivate::SyncLoopInfo::SyncLoopInfo(EventTarget* aEventTarget)
|
||||
: mEventTarget(aEventTarget), mCompleted(false), mResult(false)
|
||||
|
@ -2177,7 +2318,6 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
|
|||
WorkerLoadInfo& aLoadInfo)
|
||||
: mMutex("WorkerPrivateParent Mutex"),
|
||||
mCondVar(mMutex, "WorkerPrivateParent CondVar"),
|
||||
mMemoryReportCondVar(mMutex, "WorkerPrivateParent Memory Report CondVar"),
|
||||
mParent(aParent), mScriptURL(aScriptURL),
|
||||
mWorkerName(aWorkerName), mLoadingWorkerScript(false),
|
||||
mBusyCount(0), mParentWindowPausedDepth(0), mParentStatus(Pending),
|
||||
|
@ -3960,8 +4100,6 @@ WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent,
|
|||
, mTimerRunning(false)
|
||||
, mRunningExpiredTimeouts(false)
|
||||
, mPendingEventQueueClearing(false)
|
||||
, mMemoryReporterRunning(false)
|
||||
, mBlockedForMemoryReporter(false)
|
||||
, mCancelAllPendingRunnables(false)
|
||||
, mPeriodicGCTimerRunning(false)
|
||||
, mIdleGCTimerRunning(false)
|
||||
|
@ -4894,52 +5032,14 @@ WorkerPrivate::ScheduleDeletion(WorkerRanOrNot aRanOrNot)
|
|||
}
|
||||
|
||||
bool
|
||||
WorkerPrivate::BlockAndCollectRuntimeStats(JS::RuntimeStats* aRtStats,
|
||||
WorkerPrivate::CollectRuntimeStats(JS::RuntimeStats* aRtStats,
|
||||
bool aAnonymize)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
mMutex.AssertCurrentThreadOwns();
|
||||
AssertIsOnWorkerThread();
|
||||
NS_ASSERTION(aRtStats, "Null RuntimeStats!");
|
||||
|
||||
NS_ASSERTION(!mMemoryReporterRunning, "How can we get reentered here?!");
|
||||
|
||||
// This signals the worker that it should block itself as soon as possible.
|
||||
mMemoryReporterRunning = true;
|
||||
|
||||
NS_ASSERTION(mJSContext, "This must never be null!");
|
||||
|
||||
// If the worker is not already blocked (e.g. waiting for a worker event or
|
||||
// currently in a ctypes call) then we need to trigger the interrupt
|
||||
// callback to trap the worker.
|
||||
if (!mBlockedForMemoryReporter) {
|
||||
JS_RequestInterruptCallback(mJSContext);
|
||||
|
||||
// Wait until the worker actually blocks.
|
||||
while (!mBlockedForMemoryReporter) {
|
||||
mMemoryReportCondVar.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
// If mMemoryReporter is still set then we can do the actual report. Otherwise
|
||||
// we're trying to shut down and we don't want to do anything but clean up.
|
||||
if (mMemoryReporter) {
|
||||
// Don't hold the lock while doing the actual report.
|
||||
MutexAutoUnlock unlock(mMutex);
|
||||
succeeded = JS::CollectRuntimeStats(mJSContext, aRtStats, nullptr, aAnonymize);
|
||||
}
|
||||
|
||||
NS_ASSERTION(mMemoryReporterRunning, "This isn't possible!");
|
||||
NS_ASSERTION(mBlockedForMemoryReporter, "Somehow we got unblocked!");
|
||||
|
||||
// Tell the worker that it can now continue its execution.
|
||||
mMemoryReporterRunning = false;
|
||||
|
||||
// The worker may be waiting so we must notify.
|
||||
mMemoryReportCondVar.Notify();
|
||||
|
||||
return succeeded;
|
||||
return JS::CollectRuntimeStats(mJSContext, aRtStats, nullptr, aAnonymize);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -4952,7 +5052,7 @@ WorkerPrivate::EnableMemoryReporter()
|
|||
// successfully registered the reporter.
|
||||
mMemoryReporter = new MemoryReporter(this);
|
||||
|
||||
if (NS_FAILED(RegisterWeakMemoryReporter(mMemoryReporter))) {
|
||||
if (NS_FAILED(RegisterWeakAsyncMemoryReporter(mMemoryReporter))) {
|
||||
NS_WARNING("Failed to register memory reporter!");
|
||||
// No need to lock here since a failed registration means our memory
|
||||
// reporter can't start running. Just clean up.
|
||||
|
@ -4967,6 +5067,8 @@ WorkerPrivate::DisableMemoryReporter()
|
|||
|
||||
RefPtr<MemoryReporter> memoryReporter;
|
||||
{
|
||||
// Mutex protectes MemoryReporter::mWorkerPrivate which is cleared by
|
||||
// MemoryReporter::Disable() below.
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
// There is nothing to do here if the memory reporter was never successfully
|
||||
|
@ -4982,26 +5084,6 @@ WorkerPrivate::DisableMemoryReporter()
|
|||
// Next disable the memory reporter so that the main thread stops trying to
|
||||
// signal us.
|
||||
memoryReporter->Disable();
|
||||
|
||||
// If the memory reporter is waiting to start then we need to wait for it to
|
||||
// finish.
|
||||
if (mMemoryReporterRunning) {
|
||||
NS_ASSERTION(!mBlockedForMemoryReporter,
|
||||
"Can't be blocked in more than one place at the same time!");
|
||||
mBlockedForMemoryReporter = true;
|
||||
|
||||
// Tell the main thread that we're blocked.
|
||||
mMemoryReportCondVar.Notify();
|
||||
|
||||
// Wait for it the main thread to finish. Since we swapped out
|
||||
// mMemoryReporter above the main thread should respond quickly.
|
||||
while (mMemoryReporterRunning) {
|
||||
mMemoryReportCondVar.Wait();
|
||||
}
|
||||
|
||||
NS_ASSERTION(mBlockedForMemoryReporter, "Somehow we got unblocked!");
|
||||
mBlockedForMemoryReporter = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally unregister the memory reporter.
|
||||
|
@ -5016,29 +5098,8 @@ WorkerPrivate::WaitForWorkerEvents(PRIntervalTime aInterval)
|
|||
AssertIsOnWorkerThread();
|
||||
mMutex.AssertCurrentThreadOwns();
|
||||
|
||||
NS_ASSERTION(!mBlockedForMemoryReporter,
|
||||
"Can't be blocked in more than one place at the same time!");
|
||||
|
||||
// Let the main thread know that the worker is blocked and that memory
|
||||
// reporting may proceed.
|
||||
mBlockedForMemoryReporter = true;
|
||||
|
||||
// The main thread may be waiting so we must notify.
|
||||
mMemoryReportCondVar.Notify();
|
||||
|
||||
// Now wait for an actual worker event.
|
||||
// Wait for a worker event.
|
||||
mCondVar.Wait(aInterval);
|
||||
|
||||
// We've gotten some kind of signal but we can't continue until the memory
|
||||
// reporter has finished. Wait again.
|
||||
while (mMemoryReporterRunning) {
|
||||
mMemoryReportCondVar.Wait();
|
||||
}
|
||||
|
||||
NS_ASSERTION(mBlockedForMemoryReporter, "Somehow we got unblocked!");
|
||||
|
||||
// No need to notify here as the main thread isn't watching for this state.
|
||||
mBlockedForMemoryReporter = false;
|
||||
}
|
||||
|
||||
WorkerPrivate::ProcessAllControlRunnablesResult
|
||||
|
@ -5050,29 +5111,6 @@ WorkerPrivate::ProcessAllControlRunnablesLocked()
|
|||
auto result = ProcessAllControlRunnablesResult::Nothing;
|
||||
|
||||
for (;;) {
|
||||
// Block here if the memory reporter is trying to run.
|
||||
if (mMemoryReporterRunning) {
|
||||
MOZ_ASSERT(!mBlockedForMemoryReporter);
|
||||
|
||||
// Let the main thread know that we've received the block request and
|
||||
// that memory reporting may proceed.
|
||||
mBlockedForMemoryReporter = true;
|
||||
|
||||
// The main thread is almost certainly waiting so we must notify here.
|
||||
mMemoryReportCondVar.Notify();
|
||||
|
||||
// Wait for the memory report to finish.
|
||||
while (mMemoryReporterRunning) {
|
||||
mMemoryReportCondVar.Wait();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mBlockedForMemoryReporter);
|
||||
|
||||
// No need to notify here as the main thread isn't watching for this
|
||||
// state.
|
||||
mBlockedForMemoryReporter = false;
|
||||
}
|
||||
|
||||
WorkerControlRunnable* event;
|
||||
if (!mControlQueue.Pop(event)) {
|
||||
break;
|
||||
|
@ -6421,21 +6459,6 @@ WorkerPrivate::BeginCTypesCall()
|
|||
|
||||
// Don't try to GC while we're blocked in a ctypes call.
|
||||
SetGCTimerMode(NoTimer);
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
NS_ASSERTION(!mBlockedForMemoryReporter,
|
||||
"Can't be blocked in more than one place at the same time!");
|
||||
|
||||
// Let the main thread know that the worker is effectively blocked while in
|
||||
// this ctypes call. It isn't technically true (obviously the call could do
|
||||
// non-blocking things), but we're assuming that ctypes can't call back into
|
||||
// JSAPI here and therefore any work the ctypes call does will not alter the
|
||||
// data structures of this JS runtime.
|
||||
mBlockedForMemoryReporter = true;
|
||||
|
||||
// The main thread may be waiting on us so it must be notified.
|
||||
mMemoryReportCondVar.Notify();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -6443,21 +6466,6 @@ WorkerPrivate::EndCTypesCall()
|
|||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
NS_ASSERTION(mBlockedForMemoryReporter, "Somehow we got unblocked!");
|
||||
|
||||
// Don't continue until the memory reporter has finished.
|
||||
while (mMemoryReporterRunning) {
|
||||
mMemoryReportCondVar.Wait();
|
||||
}
|
||||
|
||||
// No need to notify the main thread here as it shouldn't be waiting to see
|
||||
// this state.
|
||||
mBlockedForMemoryReporter = false;
|
||||
}
|
||||
|
||||
// Make sure the periodic timer is running before we start running JS again.
|
||||
SetGCTimerMode(PeriodicTimer);
|
||||
}
|
||||
|
|
|
@ -168,7 +168,6 @@ protected:
|
|||
|
||||
SharedMutex mMutex;
|
||||
mozilla::CondVar mCondVar;
|
||||
mozilla::CondVar mMemoryReportCondVar;
|
||||
|
||||
// Protected by mMutex.
|
||||
RefPtr<EventTarget> mEventTarget;
|
||||
|
@ -984,8 +983,6 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
|
|||
bool mTimerRunning;
|
||||
bool mRunningExpiredTimeouts;
|
||||
bool mPendingEventQueueClearing;
|
||||
bool mMemoryReporterRunning;
|
||||
bool mBlockedForMemoryReporter;
|
||||
bool mCancelAllPendingRunnables;
|
||||
bool mPeriodicGCTimerRunning;
|
||||
bool mIdleGCTimerRunning;
|
||||
|
@ -1208,7 +1205,7 @@ public:
|
|||
ScheduleDeletion(WorkerRanOrNot aRanOrNot);
|
||||
|
||||
bool
|
||||
BlockAndCollectRuntimeStats(JS::RuntimeStats* aRtStats, bool aAnonymize);
|
||||
CollectRuntimeStats(JS::RuntimeStats* aRtStats, bool aAnonymize);
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
void
|
||||
|
|
Загрузка…
Ссылка в новой задаче