author | Andrea Marchesini <amarchesini@mozilla.com> |
Fri, 03 Apr 2015 20:37:52 +0100 | |
changeset 237574 | 3aea48a423be9e726ccb22586ff6047439dd699a |
parent 237573 | 8dce32099811ce6baa7bf141ba9b4c90a46ce635 |
child 237575 | 809e54954e6f9308ece0ba769a862d90158bc64f |
push id | 28540 |
push user | philringnalda@gmail.com |
push date | Sat, 04 Apr 2015 17:42:19 +0000 |
treeherder | mozilla-central@035959eef3f9 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | ehsan |
bugs | 1049091 |
milestone | 40.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/base/Console.cpp +++ b/dom/base/Console.cpp @@ -18,16 +18,17 @@ #include "nsJSUtils.h" #include "nsPerformance.h" #include "ScriptSettings.h" #include "WorkerPrivate.h" #include "WorkerRunnable.h" #include "xpcprivate.h" #include "nsContentUtils.h" #include "nsDocShell.h" +#include "nsProxyRelease.h" #include "nsIConsoleAPIStorage.h" #include "nsIDOMWindowUtils.h" #include "nsIInterfaceRequestorUtils.h" #include "nsILoadContext.h" #include "nsIProgrammingLanguage.h" #include "nsIServiceManager.h" #include "nsISupportsPrimitives.h" @@ -147,16 +148,18 @@ static const JSStructuredCloneCallbacks ConsoleStructuredCloneCallbacksRead, ConsoleStructuredCloneCallbacksWrite, ConsoleStructuredCloneCallbacksError }; class ConsoleCallData final { public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ConsoleCallData) + ConsoleCallData() : mMethodName(Console::MethodLog) , mPrivate(false) , mTimeStamp(JS_Now() / PR_USEC_PER_MSEC) , mIDType(eUnknown) , mOuterIDNumber(0) , mInnerIDNumber(0) { } @@ -233,16 +236,20 @@ public: // lazily as possible. Therefore, we have the following behavior: // 1) mTopStackFrame is initialized whenever we have any JS on the stack // 2) mReifiedStack is initialized if we're created in a worker. // 3) mStack is set (possibly to null if there is no JS on the stack) if // we're created on main thread. Maybe<ConsoleStackEntry> mTopStackFrame; Maybe<nsTArray<ConsoleStackEntry>> mReifiedStack; nsCOMPtr<nsIStackFrame> mStack; + +private: + ~ConsoleCallData() + { } }; // This class is used to clear any exception at the end of this method. class ClearException { public: explicit ClearException(JSContext* aCx) : mCx(aCx) @@ -279,26 +286,23 @@ public: mWorkerPrivate->AssertIsOnWorkerThread(); JSContext* cx = mWorkerPrivate->GetJSContext(); if (!PreDispatch(cx)) { return false; } - AutoSyncLoopHolder syncLoop(mWorkerPrivate); - mSyncLoopTarget = syncLoop.EventTarget(); - if (NS_FAILED(NS_DispatchToMainThread(this))) { JS_ReportError(cx, "Failed to dispatch to main thread for the Console API!"); return false; } - return syncLoop.Run(); + return true; } private: NS_IMETHOD Run() { AssertIsOnMainThread(); // Walk up to our containing page @@ -309,24 +313,16 @@ private: nsPIDOMWindow* window = wp->GetWindow(); if (!window) { RunWindowless(); } else { RunWithWindow(window); } - nsRefPtr<MainThreadStopSyncLoopRunnable> response = - new MainThreadStopSyncLoopRunnable(mWorkerPrivate, - mSyncLoopTarget.forget(), - true); - if (!response->Dispatch(nullptr)) { - NS_WARNING("Failed to dispatch response!"); - } - return NS_OK; } void RunWithWindow(nsPIDOMWindow* aWindow) { AutoJSAPI jsapi; MOZ_ASSERT(aWindow); @@ -383,35 +379,55 @@ protected: RunConsole(JSContext* aCx, nsPIDOMWindow* aOuterWindow, nsPIDOMWindow* aInnerWindow) = 0; WorkerPrivate* mWorkerPrivate; // Raw pointer because this method is async and this object is kept alive by // the caller. Console* mConsole; - -private: - nsCOMPtr<nsIEventTarget> mSyncLoopTarget; }; // This runnable appends a CallData object into the Console queue running on // the main-thread. class ConsoleCallDataRunnable final : public ConsoleRunnable { public: ConsoleCallDataRunnable(Console* aConsole, ConsoleCallData* aCallData) : ConsoleRunnable(aConsole) , mCallData(aCallData) { } private: ~ConsoleCallDataRunnable() - { } + { + class ReleaseCallData final : public nsRunnable + { + public: + explicit ReleaseCallData(nsRefPtr<ConsoleCallData>& aCallData) + { + mCallData.swap(aCallData); + } + + NS_IMETHOD Run() override + { + mCallData = nullptr; + return NS_OK; + } + + private: + nsRefPtr<ConsoleCallData> mCallData; + }; + + nsRefPtr<ReleaseCallData> runnable = new ReleaseCallData(mCallData); + if(NS_FAILED(NS_DispatchToMainThread(runnable))) { + NS_WARNING("Failed to dispatch a ReleaseCallData runnable. Leaking."); + } + } bool PreDispatch(JSContext* aCx) override { mWorkerPrivate->AssertIsOnWorkerThread(); ClearException ce(aCx); JSAutoCompartment ac(aCx, mCallData->mGlobal); @@ -509,17 +525,17 @@ private: } MOZ_ASSERT(mCallData->mArguments.Length() == length); mCallData->mGlobal = JS::CurrentGlobalOrNull(aCx); mConsole->ProcessCallData(mCallData); } - ConsoleCallData* mCallData; + nsRefPtr<ConsoleCallData> mCallData; JSAutoStructuredCloneBuffer mArguments; ConsoleStructuredCloneData mData; }; // This runnable calls ProfileMethod() on the console on the main-thread. class ConsoleProfileRunnable final : public ConsoleRunnable { @@ -561,16 +577,17 @@ private: } JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*arguments)); if (!mBuffer.write(aCx, value, &gConsoleCallbacks, &mData)) { return false; } + mArguments.Clear(); return true; } void RunConsole(JSContext* aCx, nsPIDOMWindow* aOuterWindow, nsPIDOMWindow* aInnerWindow) override { ClearException ce(aCx); @@ -954,17 +971,17 @@ public: }; // Queue a call to a console method. See the CALL_DELAY constant. void Console::Method(JSContext* aCx, MethodName aMethodName, const nsAString& aMethodString, const Sequence<JS::Value>& aData) { - nsAutoPtr<ConsoleCallData> callData(new ConsoleCallData()); + nsRefPtr<ConsoleCallData> callData(new ConsoleCallData()); ClearException ce(aCx); callData->Initialize(aCx, aMethodName, aMethodString, aData); if (mWindow) { nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(mWindow); if (!webNav) { @@ -1073,18 +1090,16 @@ Console::Method(JSContext* aCx, MethodNa } if (NS_IsMainThread()) { callData->SetIDs(mOuterID, mInnerID); ProcessCallData(callData); return; } - // Note: we can pass the reference of callData because this runnable calls - // ProcessCallData() synchronously. nsRefPtr<ConsoleCallDataRunnable> runnable = new ConsoleCallDataRunnable(this, callData); runnable->Dispatch(); } // We store information to lazily compute the stack in the reserved slots of // LazyStackGetter. The first slot always stores a JS object: it's either the // JS wrapper of the nsIStackFrame or the actual reified stack representation.