author | Wes Kocher <wkocher@mozilla.com> |
Fri, 02 Oct 2015 10:35:09 -0700 | |
changeset 299206 | c917988efd78a3f082be29d388b87fdb194f592d |
parent 299205 | fd1540ba641fae147d54c2ee690513f0646b7930 |
child 299207 | 48dfe8c77b2f6f3cf8a81ea22d47c3f095d38b35 |
push id | 5392 |
push user | raliiev@mozilla.com |
push date | Mon, 14 Dec 2015 20:08:23 +0000 |
treeherder | mozilla-beta@16ce8562a975 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1186745 |
milestone | 44.0a1 |
backs out | 237a6acf0709d7392e7dc25c13e699f715b0dcf5 7b530871783ac74a6dcb8a3dbf46798a991bbc87 73f73b531fc892ba8dae447528bba09ed2ee43ff e36909748ddf51e8d3a0d40f2fb5328b1db83f53 3a31df8787f0d80600ae8446b53eea44ab1f4375 df9cb8f5f0a5eb1fa6bfe93d501f84fb0d79b077 |
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/tools/profiler/tasktracer/GeckoTaskTracer.h +++ b/tools/profiler/tasktracer/GeckoTaskTracer.h @@ -70,18 +70,17 @@ nsTArray<nsCString>* GetLoggedData(TimeS const PRTime GetStartTime(); /** * Internal functions. */ Task* CreateTracedTask(Task* aTask); -already_AddRefed<nsIRunnable> -CreateTracedRunnable(already_AddRefed<nsIRunnable>&& aRunnable); +already_AddRefed<nsIRunnable> CreateTracedRunnable(nsIRunnable* aRunnable); // Free the TraceInfo allocated on a thread's TLS. Currently we are wrapping // tasks running on nsThreads and base::thread, so FreeTraceInfo is called at // where nsThread and base::thread release themselves. void FreeTraceInfo(); const char* GetJSLabelPrefix();
--- a/tools/profiler/tasktracer/TracedTaskCommon.cpp +++ b/tools/profiler/tasktracer/TracedTaskCommon.cpp @@ -85,19 +85,19 @@ TracedTaskCommon::ClearTLSTraceInfo() info->mCurTraceSourceId = 0; info->mCurTraceSourceType = SourceEventType::Unknown; info->mCurTaskId = 0; } /** * Implementation of class TracedRunnable. */ -TracedRunnable::TracedRunnable(already_AddRefed<nsIRunnable>&& aOriginalObj) +TracedRunnable::TracedRunnable(nsIRunnable* aOriginalObj) : TracedTaskCommon() - , mOriginalObj(Move(aOriginalObj)) + , mOriginalObj(aOriginalObj) { Init(); LogVirtualTablePtr(mTaskId, mSourceEventId, *(int**)(aOriginalObj)); } TracedRunnable::~TracedRunnable() { } @@ -143,19 +143,19 @@ TracedTask::Run() ClearTLSTraceInfo(); } /** * CreateTracedRunnable() returns a TracedRunnable wrapping the original * nsIRunnable object, aRunnable. */ already_AddRefed<nsIRunnable> -CreateTracedRunnable(already_AddRefed<nsIRunnable>&& aRunnable) +CreateTracedRunnable(nsIRunnable* aRunnable) { - nsCOMPtr<nsIRunnable> runnable = new TracedRunnable(Move(aRunnable)); + nsCOMPtr<nsIRunnable> runnable = new TracedRunnable(aRunnable); return runnable.forget(); } /** * CreateTracedTask() returns a TracedTask wrapping the original Task object, * aTask. */ Task*
--- a/tools/profiler/tasktracer/TracedTaskCommon.h +++ b/tools/profiler/tasktracer/TracedTaskCommon.h @@ -41,17 +41,17 @@ protected: }; class TracedRunnable : public TracedTaskCommon , public nsRunnable { public: NS_DECL_NSIRUNNABLE - TracedRunnable(already_AddRefed<nsIRunnable>&& aOriginalObj); + TracedRunnable(nsIRunnable* aOriginalObj); private: virtual ~TracedRunnable(); nsCOMPtr<nsIRunnable> mOriginalObj; }; class TracedTask : public TracedTaskCommon
--- a/xpcom/glue/moz.build +++ b/xpcom/glue/moz.build @@ -101,17 +101,16 @@ FORCE_STATIC_LIB = True if CONFIG['_MSC_VER']: DEFINES['_USE_ANSI_CPP'] = True # Don't include directives about which CRT to use CFLAGS += ['-Zl'] CXXFLAGS += ['-Zl'] LOCAL_INCLUDES += [ '../build', - '../threads', ] if CONFIG['ENABLE_TESTS']: DIRS += ['tests/gtest'] # Include fallible for third party code using the xpcom glue USE_LIBS += [ 'fallible',
--- a/xpcom/glue/nsThreadUtils.cpp +++ b/xpcom/glue/nsThreadUtils.cpp @@ -2,17 +2,16 @@ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsThreadUtils.h" #include "mozilla/Attributes.h" #include "mozilla/Likely.h" -#include "LeakRefPtr.h" #ifdef MOZILLA_INTERNAL_API # include "nsThreadManager.h" #else # include "nsXPCOMCIDInternal.h" # include "nsIThreadManager.h" # include "nsServiceManagerUtils.h" #endif @@ -23,18 +22,16 @@ using mozilla::IsVistaOrLater; #elif defined(XP_MACOSX) #include <sys/resource.h> #endif #include <pratom.h> #include <prthread.h> -using namespace mozilla; - #ifndef XPCOM_GLUE_AVOID_NSPR NS_IMPL_ISUPPORTS(nsRunnable, nsIRunnable) NS_IMETHODIMP nsRunnable::Run() { // Do nothing @@ -137,69 +134,52 @@ NS_IsMainThread() do_GetService(NS_THREADMANAGER_CONTRACTID); if (mgr) { mgr->GetIsMainThread(&result); } return bool(result); } #endif +// It is common to call NS_DispatchToCurrentThread with a newly +// allocated runnable with a refcount of zero. To keep us from leaking +// the runnable if the dispatch method fails, we take a death grip. NS_METHOD -NS_DispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent) +NS_DispatchToCurrentThread(nsIRunnable* aEvent) { - nsresult rv; - nsCOMPtr<nsIRunnable> event(aEvent); + nsCOMPtr<nsIRunnable> deathGrip = aEvent; #ifdef MOZILLA_INTERNAL_API nsIThread* thread = NS_GetCurrentThread(); if (!thread) { return NS_ERROR_UNEXPECTED; } #else nsCOMPtr<nsIThread> thread; - rv = NS_GetCurrentThread(getter_AddRefs(thread)); + nsresult rv = NS_GetCurrentThread(getter_AddRefs(thread)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } #endif - // To keep us from leaking the runnable if dispatch method fails, - // we grab the reference on failures and release it. - nsIRunnable* temp = event.get(); - rv = thread->Dispatch(event.forget(), NS_DISPATCH_NORMAL); - if (NS_WARN_IF(NS_FAILED(rv))) { - // Dispatch() leaked the reference to the event, but due to caller's - // assumptions, we shouldn't leak here. And given we are on the same - // thread as the dispatch target, it's mostly safe to do it here. - NS_RELEASE(temp); - } - return rv; -} - -// It is common to call NS_DispatchToCurrentThread with a newly -// allocated runnable with a refcount of zero. To keep us from leaking -// the runnable if the dispatch method fails, we take a death grip. -NS_METHOD -NS_DispatchToCurrentThread(nsIRunnable* aEvent) -{ - nsCOMPtr<nsIRunnable> event(aEvent); - return NS_DispatchToCurrentThread(event.forget()); + return thread->Dispatch(aEvent, NS_DISPATCH_NORMAL); } NS_METHOD NS_DispatchToMainThread(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aDispatchFlags) { - LeakRefPtr<nsIRunnable> event(Move(aEvent)); + nsCOMPtr<nsIRunnable> event(aEvent); nsCOMPtr<nsIThread> thread; nsresult rv = NS_GetMainThread(getter_AddRefs(thread)); if (NS_WARN_IF(NS_FAILED(rv))) { NS_ASSERTION(false, "Failed NS_DispatchToMainThread() in shutdown; leaking"); // NOTE: if you stop leaking here, adjust Promise::MaybeReportRejected(), // which assumes a leak here, or split into leaks and no-leaks versions - return rv; + nsIRunnable* temp = event.forget().take(); // leak without using "unused <<" due to Windows (boo) + return temp ? rv : rv; // to make compiler not bletch on us } - return thread->Dispatch(event.take(), aDispatchFlags); + return thread->Dispatch(event.forget(), aDispatchFlags); } // In the case of failure with a newly allocated runnable with a // refcount of zero, we intentionally leak the runnable, because it is // likely that the runnable is being dispatched to the main thread // because it owns main thread only objects, so it is not safe to // release them here. NS_METHOD
--- a/xpcom/glue/nsThreadUtils.h +++ b/xpcom/glue/nsThreadUtils.h @@ -101,18 +101,16 @@ extern NS_METHOD NS_GetCurrentThread(nsI * * @param aEvent * The event to dispatch. * * @returns NS_ERROR_INVALID_ARG * If event is null. */ extern NS_METHOD NS_DispatchToCurrentThread(nsIRunnable* aEvent); -extern NS_METHOD -NS_DispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent); /** * Dispatch the given event to the main thread. * * @param aEvent * The event to dispatch. * @param aDispatchFlags * The flags to pass to the main thread's dispatch method.
--- a/xpcom/glue/standalone/moz.build +++ b/xpcom/glue/standalone/moz.build @@ -33,17 +33,16 @@ if CONFIG['_MSC_VER']: # Don't include directives about which CRT to use CFLAGS += ['-Zl'] CXXFLAGS += ['-Zl'] DEFINES['XPCOM_GLUE'] = True LOCAL_INCLUDES += [ '../../build', - '../../threads', ] # Don't use STL wrappers here (i.e. wrapped <new>); they require mozalloc DISABLE_STL_WRAPPING = True if CONFIG['GNU_CXX']: CXXFLAGS += ['-Wshadow']
--- a/xpcom/glue/standalone/staticruntime/moz.build +++ b/xpcom/glue/standalone/staticruntime/moz.build @@ -25,17 +25,16 @@ if CONFIG['_MSC_VER']: # Don't include directives about which CRT to use CFLAGS += ['-Zl'] CXXFLAGS += ['-Zl'] DEFINES['XPCOM_GLUE'] = True LOCAL_INCLUDES += [ '../../../build', - '../../../threads', ] # Statically link to the CRT on Windows USE_STATIC_LIBS = True # Don't use STL wrappers here (i.e. wrapped <new>); they require mozalloc DISABLE_STL_WRAPPING = True
--- a/xpcom/glue/staticruntime/moz.build +++ b/xpcom/glue/staticruntime/moz.build @@ -23,17 +23,16 @@ FORCE_STATIC_LIB = True if CONFIG['_MSC_VER']: DEFINES['_USE_ANSI_CPP'] = True # Don't include directives about which CRT to use CFLAGS += ['-Zl'] CXXFLAGS += ['-Zl'] LOCAL_INCLUDES += [ '../../build', - '../../threads', ] # Statically link to the CRT on Windows USE_STATIC_LIBS = True # Don't use STL wrappers here (i.e. wrapped <new>); they require mozalloc DISABLE_STL_WRAPPING = True
deleted file mode 100644 --- a/xpcom/threads/LeakRefPtr.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* Smart pointer which leaks its owning refcounted object by default. */ - -#ifndef LeakRefPtr_h -#define LeakRefPtr_h - -#include "mozilla/AlreadyAddRefed.h" - -namespace mozilla { - -/** - * Instance of this class behaves like a raw pointer which leaks the - * resource it's owning if not explicitly released. - */ -template<class T> -class LeakRefPtr -{ -public: - explicit LeakRefPtr(already_AddRefed<T>&& aPtr) - : mRawPtr(aPtr.take()) { } - - explicit operator bool() const { return !!mRawPtr; } - - LeakRefPtr<T>& operator=(already_AddRefed<T>&& aPtr) - { - mRawPtr = aPtr.take(); - return *this; - } - - already_AddRefed<T> take() - { - T* rawPtr = mRawPtr; - mRawPtr = nullptr; - return already_AddRefed<T>(rawPtr); - } - -private: - T* MOZ_OWNING_REF mRawPtr; -}; - -} // namespace mozilla - -#endif // LeakRefPtr_h
--- a/xpcom/threads/nsIEventTarget.idl +++ b/xpcom/threads/nsIEventTarget.idl @@ -55,20 +55,17 @@ interface nsIEventTarget : nsISupports */ boolean isOnCurrentThread(); /** * Dispatch an event to this event target. This function may be called from * any thread, and it may be called re-entrantly. * * @param event - * The alreadyAddRefed<> event to dispatch. - * NOTE that the event will be leaked if it fails to dispatch. Also note - * that if "flags" includes DISPATCH_SYNC, it may return error from Run() - * after a successful dispatch. In that case, the event is not leaked. + * The alreadyAddRefed<> event to dispatch * @param flags * The flags modifying event dispatch. The flags are described in detail * below. * * @throws NS_ERROR_INVALID_ARG * Indicates that event is null. * @throws NS_ERROR_UNEXPECTED * Indicates that the thread is shutting down and has finished processing
--- a/xpcom/threads/nsThread.cpp +++ b/xpcom/threads/nsThread.cpp @@ -31,18 +31,16 @@ #include "mozilla/IOInterposer.h" #include "mozilla/ipc/MessageChannel.h" #include "mozilla/ipc/BackgroundChild.h" #endif // defined(MOZILLA_XPCOMRT_API) #include "mozilla/Services.h" #include "nsXPCOMPrivate.h" #include "mozilla/ChaosMode.h" #include "mozilla/TimeStamp.h" -#include "nsThreadSyncDispatch.h" -#include "LeakRefPtr.h" #ifdef MOZ_CRASHREPORTER #include "nsServiceManagerUtils.h" #include "nsICrashReporter.h" #endif #ifdef MOZ_NUWA_PROCESS #include "private/pprthred.h" @@ -538,35 +536,34 @@ nsThread::PutEvent(nsIRunnable* aEvent, { nsCOMPtr<nsIRunnable> event(aEvent); return PutEvent(event.forget(), aTarget); } nsresult nsThread::PutEvent(already_AddRefed<nsIRunnable>&& aEvent, nsNestedEventTarget* aTarget) { - // We want to leak the reference when we fail to dispatch it, so that - // we won't release the event in a wrong thread. - LeakRefPtr<nsIRunnable> event(Move(aEvent)); nsCOMPtr<nsIThreadObserver> obs; #ifdef MOZ_NUWA_PROCESS // On debug build or when tests are enabled, assert that we are not about to // create a deadlock in the Nuwa process. NuwaAssertNotFrozen(PR_GetThreadID(mThread), PR_GetThreadName(mThread)); #endif { MutexAutoLock lock(mLock); nsChainedEventQueue* queue = aTarget ? aTarget->mQueue : &mEventsRoot; if (!queue || (queue == &mEventsRoot && mEventsAreDoomed)) { NS_WARNING("An event was posted to a thread that will never run it (rejected)"); - return NS_ERROR_UNEXPECTED; + nsCOMPtr<nsIRunnable> temp(aEvent); + nsIRunnable* temp2 = temp.forget().take(); // can't use unused << aEvent here due to Windows (boo) + return temp2 ? NS_ERROR_UNEXPECTED : NS_ERROR_UNEXPECTED; // to make compiler not bletch on us } - queue->PutEvent(event.take(), lock); + queue->PutEvent(Move(aEvent), lock); // Make sure to grab the observer before dropping the lock, otherwise the // event that we just placed into the queue could run and eventually delete // this nsThread before the calling thread is scheduled again. We would then // crash while trying to access a dead nsThread. obs = mObserver; } @@ -576,68 +573,59 @@ nsThread::PutEvent(already_AddRefed<nsIR return NS_OK; } nsresult nsThread::DispatchInternal(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aFlags, nsNestedEventTarget* aTarget) { - // We want to leak the reference when we fail to dispatch it, so that - // we won't release the event in a wrong thread. - LeakRefPtr<nsIRunnable> event(Move(aEvent)); + nsCOMPtr<nsIRunnable> event(aEvent); if (NS_WARN_IF(!event)) { return NS_ERROR_INVALID_ARG; } if (gXPCOMThreadsShutDown && MAIN_THREAD != mIsMainThread && !aTarget) { NS_ASSERTION(false, "Failed Dispatch after xpcom-shutdown-threads"); return NS_ERROR_ILLEGAL_DURING_SHUTDOWN; } #ifdef MOZ_TASK_TRACER - nsCOMPtr<nsIRunnable> tracedRunnable = CreateTracedRunnable(event.take()); + nsCOMPtr<nsIRunnable> tracedRunnable = CreateTracedRunnable(event); // adds a ref (static_cast<TracedRunnable*>(tracedRunnable.get()))->DispatchTask(); - // XXX tracedRunnable will always leaked when we fail to disptch. event = tracedRunnable.forget(); #endif if (aFlags & DISPATCH_SYNC) { nsThread* thread = nsThreadManager::get()->GetCurrentThread(); if (NS_WARN_IF(!thread)) { return NS_ERROR_NOT_AVAILABLE; } // XXX we should be able to do something better here... we should // be able to monitor the slot occupied by this event and use // that to tell us when the event has been processed. nsRefPtr<nsThreadSyncDispatch> wrapper = - new nsThreadSyncDispatch(thread, event.take()); + new nsThreadSyncDispatch(thread, event.forget()); nsresult rv = PutEvent(wrapper, aTarget); // hold a ref // Don't wait for the event to finish if we didn't dispatch it... if (NS_FAILED(rv)) { - // PutEvent leaked the wrapper runnable object on failure, so we - // explicitly release this object once for that. Note that this - // object will be released again soon because it exits the scope. - wrapper.get()->Release(); return rv; } // Allows waiting; ensure no locks are held that would deadlock us! while (wrapper->IsPending()) { NS_ProcessNextEvent(thread, true); } - // NOTE that, unlike the behavior above, the event is not leaked by - // this place, while it is possible that the result is an error. return wrapper->Result(); } NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL, "unexpected dispatch flags"); - return PutEvent(event.take(), aTarget); + return PutEvent(event.forget(), aTarget); } //----------------------------------------------------------------------------- // nsIEventTarget NS_IMETHODIMP nsThread::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags) { @@ -1177,16 +1165,30 @@ nsThread::SetScriptObserver(mozilla::Cyc } MOZ_ASSERT(!mScriptObserver); mScriptObserver = aScriptObserver; } //----------------------------------------------------------------------------- +NS_IMETHODIMP +nsThreadSyncDispatch::Run() +{ + if (mSyncTask) { + mResult = mSyncTask->Run(); + mSyncTask = nullptr; + // unblock the origin thread + mOrigin->Dispatch(this, NS_DISPATCH_NORMAL); + } + return NS_OK; +} + +//----------------------------------------------------------------------------- + NS_IMPL_ISUPPORTS(nsThread::nsNestedEventTarget, nsIEventTarget) NS_IMETHODIMP nsThread::nsNestedEventTarget::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags) { nsCOMPtr<nsIRunnable> event(aEvent); return Dispatch(event.forget(), aFlags); }
--- a/xpcom/threads/nsThread.h +++ b/xpcom/threads/nsThread.h @@ -202,16 +202,46 @@ protected: nsTArray<nsAutoPtr<struct nsThreadShutdownContext>> mRequestedShutdownContexts; bool mShutdownRequired; // Set to true when events posted to this thread will never run. bool mEventsAreDoomed; MainThreadFlag mIsMainThread; }; +//----------------------------------------------------------------------------- + +class nsThreadSyncDispatch : public nsRunnable +{ +public: + nsThreadSyncDispatch(nsIThread* aOrigin, already_AddRefed<nsIRunnable>&& aTask) + : mOrigin(aOrigin) + , mSyncTask(aTask) + , mResult(NS_ERROR_NOT_INITIALIZED) + { + } + + bool IsPending() + { + return mSyncTask != nullptr; + } + + nsresult Result() + { + return mResult; + } + +private: + NS_DECL_NSIRUNNABLE + + nsCOMPtr<nsIThread> mOrigin; + nsCOMPtr<nsIRunnable> mSyncTask; + nsresult mResult; +}; + #if defined(XP_UNIX) && !defined(ANDROID) && !defined(DEBUG) && HAVE_UALARM \ && defined(_GNU_SOURCE) # define MOZ_CANARY extern int sCanaryOutputFD; #endif #endif // nsThread_h__
--- a/xpcom/threads/nsThreadPool.cpp +++ b/xpcom/threads/nsThreadPool.cpp @@ -7,17 +7,16 @@ #include "nsIClassInfoImpl.h" #include "nsThreadPool.h" #include "nsThreadManager.h" #include "nsThread.h" #include "nsMemory.h" #include "nsAutoPtr.h" #include "prinrval.h" #include "mozilla/Logging.h" -#include "nsThreadSyncDispatch.h" using namespace mozilla; static PRLogModuleInfo* GetThreadPoolLog() { static PRLogModuleInfo* sLog; if (!sLog) {
deleted file mode 100644 --- a/xpcom/threads/nsThreadSyncDispatch.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef nsThreadSyncDispatch_h_ -#define nsThreadSyncDispatch_h_ - -#include "nsThreadUtils.h" -#include "LeakRefPtr.h" - -class nsThreadSyncDispatch : public nsRunnable -{ -public: - nsThreadSyncDispatch(nsIThread* aOrigin, already_AddRefed<nsIRunnable>&& aTask) - : mOrigin(aOrigin) - , mSyncTask(mozilla::Move(aTask)) - , mResult(NS_ERROR_NOT_INITIALIZED) - { - } - - bool IsPending() - { - return !!mSyncTask; - } - - nsresult Result() - { - return mResult; - } - -private: - NS_IMETHOD Run() override - { - if (nsCOMPtr<nsIRunnable> task = mSyncTask.take()) { - mResult = task->Run(); - // We must release the task here to ensure that when the original - // thread is unblocked, this task has been released. - task = nullptr; - // unblock the origin thread - mOrigin->Dispatch(this, NS_DISPATCH_NORMAL); - } - return NS_OK; - } - - nsCOMPtr<nsIThread> mOrigin; - // The task is leaked by default when Run() is not called, because - // otherwise we may release it in an incorrect thread. - mozilla::LeakRefPtr<nsIRunnable> mSyncTask; - nsresult mResult; -}; - -#endif // nsThreadSyncDispatch_h_