Bug 749010 (part 1) - Make WorkerMemoryReporter less crashy. r=bent.

--HG--
extra : rebase_source : 9c73e73ef71968236ed15cf5e7afab3d113a350a
This commit is contained in:
Nicholas Nethercote 2012-05-29 19:39:38 -07:00
parent 4fe4e6539d
commit 4c080fd062
2 changed files with 51 additions and 38 deletions

View File

@ -123,6 +123,8 @@ SwapToISupportsArray(SmartPtr<T>& aSrc,
dest->swap(rawSupports);
}
} /* anonymous namespace */
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsWorkerMallocSizeOf, "js-worker")
struct WorkerJSRuntimeStats : public JS::RuntimeStats
@ -163,6 +165,8 @@ private:
nsCString mRtPath;
};
BEGIN_WORKERS_NAMESPACE
class WorkerMemoryReporter MOZ_FINAL : public nsIMemoryMultiReporter
{
WorkerPrivate* mWorkerPrivate;
@ -208,36 +212,31 @@ public:
{
AssertIsOnMainThread();
if (mWorkerPrivate) {
bool disabled;
if (!mWorkerPrivate->BlockAndCollectRuntimeStats(aIsQuick, aData, &disabled)) {
return NS_ERROR_FAILURE;
}
// Don't ever try to talk to the worker again.
if (disabled) {
if (!mWorkerPrivate) {
#ifdef DEBUG
{
nsCAutoString message("Unable to report memory for ");
if (mWorkerPrivate->IsChromeWorker()) {
message.AppendLiteral("Chrome");
}
message += NS_LITERAL_CSTRING("Worker (") + mAddressString +
NS_LITERAL_CSTRING(")! It is either using ctypes or is in "
"the process of being destroyed");
NS_WARNING(message.get());
}
#endif
mWorkerPrivate = nsnull;
nsCAutoString message("Unable to report memory for ");
if (mWorkerPrivate->IsChromeWorker()) {
message.AppendLiteral("Chrome");
}
message += NS_LITERAL_CSTRING("Worker (") + mAddressString +
NS_LITERAL_CSTRING(")! It is either using ctypes or is in "
"the process of being destroyed");
NS_WARNING(message.get());
#endif
return NS_OK;
}
if (!mWorkerPrivate->BlockAndCollectRuntimeStats(aIsQuick, aData)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHOD GetName(nsACString &aName)
{
aName.AssignLiteral("workers");
return NS_OK;
aName.AssignLiteral("workers");
return NS_OK;
}
NS_IMETHOD
@ -265,10 +264,30 @@ public:
return CollectForRuntime(/* isQuick = */true, aAmount);
}
void Disable()
{
#ifdef DEBUG
// Setting mWorkerPrivate to nsnull is safe only because we've locked the
// worker's mutex on the worker's thread, in the caller. So we check that.
//
// Also, we may have already disabled the reporter (and thus set
// mWorkerPrivate to nsnull) due to the use of CTypes (see
// ChromeWorkerScope.cpp). That's why the NULL check is necessary.
if (mWorkerPrivate) {
mWorkerPrivate->mMutex.AssertCurrentThreadOwns();
}
#endif
mWorkerPrivate = nsnull;
}
};
END_WORKERS_NAMESPACE
NS_IMPL_THREADSAFE_ISUPPORTS1(WorkerMemoryReporter, nsIMemoryMultiReporter)
namespace {
struct WorkerStructuredCloneCallbacks
{
static JSObject*
@ -2451,8 +2470,7 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx, JSObject* aObject,
mJSContext(nsnull), mErrorHandlerRecursionCount(0), mNextTimeoutId(1),
mStatus(Pending), mSuspended(false), mTimerRunning(false),
mRunningExpiredTimeouts(false), mCloseHandlerStarted(false),
mCloseHandlerFinished(false), mMemoryReporterRunning(false),
mMemoryReporterDisabled(false)
mCloseHandlerFinished(false), mMemoryReporterRunning(false)
{
MOZ_COUNT_CTOR(mozilla::dom::workers::WorkerPrivate);
}
@ -2899,20 +2917,13 @@ WorkerPrivate::ScheduleDeletion(bool aWasPending)
}
bool
WorkerPrivate::BlockAndCollectRuntimeStats(bool aIsQuick, void* aData, bool* aDisabled)
WorkerPrivate::BlockAndCollectRuntimeStats(bool aIsQuick, void* aData)
{
AssertIsOnMainThread();
NS_ASSERTION(aData, "Null data!");
{
MutexAutoLock lock(mMutex);
if (mMemoryReporterDisabled) {
*aDisabled = true;
return true;
}
*aDisabled = false;
mMemoryReporterRunning = true;
}
@ -2943,12 +2954,14 @@ WorkerPrivate::DisableMemoryReporter()
{
MutexAutoLock lock(mMutex);
mMemoryReporterDisabled = true;
while (mMemoryReporterRunning) {
MutexAutoUnlock unlock(mMutex);
result = ProcessAllControlRunnables() && result;
}
if (mMemoryReporter) {
mMemoryReporter->Disable();
}
}
return result;

View File

@ -31,7 +31,6 @@
class JSAutoStructuredCloneBuffer;
class nsIDocument;
class nsIPrincipal;
class nsIMemoryMultiReporter;
class nsIScriptContext;
class nsIURI;
class nsPIDOMWindow;
@ -40,6 +39,7 @@ class nsIXPCScriptNotify;
BEGIN_WORKERS_NAMESPACE
class WorkerMemoryReporter;
class WorkerPrivate;
class WorkerRunnable : public nsIRunnable
@ -495,6 +495,7 @@ public:
class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
{
friend class WorkerPrivateParent<WorkerPrivate>;
friend class WorkerMemoryReporter;
typedef WorkerPrivateParent<WorkerPrivate> ParentType;
struct TimeoutInfo;
@ -534,7 +535,7 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
nsTArray<nsAutoPtr<TimeoutInfo> > mTimeouts;
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsIMemoryMultiReporter> mMemoryReporter;
nsRefPtr<WorkerMemoryReporter> mMemoryReporter;
mozilla::TimeStamp mKillTime;
PRUint32 mErrorHandlerRecursionCount;
@ -546,7 +547,6 @@ class WorkerPrivate : public WorkerPrivateParent<WorkerPrivate>
bool mCloseHandlerStarted;
bool mCloseHandlerFinished;
bool mMemoryReporterRunning;
bool mMemoryReporterDisabled;
#ifdef DEBUG
nsCOMPtr<nsIThread> mThread;
@ -682,7 +682,7 @@ public:
ScheduleDeletion(bool aWasPending);
bool
BlockAndCollectRuntimeStats(bool isQuick, void* aData, bool* aDisabled);
BlockAndCollectRuntimeStats(bool isQuick, void* aData);
bool
DisableMemoryReporter();