Bug 1341549 - Label runnables in dom/media/webaudio/ r=billm
authorPaul Adenot <paul@paul.cx>
Tue, 04 Apr 2017 13:47:47 +0200
changeset 351799 a436c8af1ba23ccb47f2f681fd2d32a441827e1b
parent 351798 cdd87ce7a01594f6ae51fbe494555eb0c1ea3ef4
child 351800 e11dac8513ec74cc1bca27a7ebbd2933d2deaeef
push id31621
push userarchaeopteryx@coole-files.de
push dateFri, 07 Apr 2017 20:14:04 +0000
treeherdermozilla-central@35c7be9c2db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1341549
milestone55.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
Bug 1341549 - Label runnables in dom/media/webaudio/ r=billm MozReview-Commit-ID: 1SG1KoVjivS
dom/media/webaudio/AnalyserNode.cpp
dom/media/webaudio/AudioBufferSourceNode.cpp
dom/media/webaudio/AudioContext.cpp
dom/media/webaudio/AudioContext.h
dom/media/webaudio/AudioDestinationNode.cpp
dom/media/webaudio/ConstantSourceNode.cpp
dom/media/webaudio/DynamicsCompressorNode.cpp
dom/media/webaudio/MediaBufferDecoder.cpp
dom/media/webaudio/OscillatorNode.cpp
dom/media/webaudio/ScriptProcessorNode.cpp
--- a/dom/media/webaudio/AnalyserNode.cpp
+++ b/dom/media/webaudio/AnalyserNode.cpp
@@ -80,17 +80,17 @@ public:
 
     } else {
       // This many null chunks will be required to empty AnalyserNode::mChunks.
       mChunksToProcess = CHUNK_COUNT;
     }
 
     RefPtr<TransferBuffer> transfer =
       new TransferBuffer(aStream, aInput.AsAudioChunk());
-    NS_DispatchToMainThread(transfer);
+    mAbstractMainThread->Dispatch(transfer.forget());
   }
 
   virtual bool IsActive() const override
   {
     return mChunksToProcess != 0;
   }
 
   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override
--- a/dom/media/webaudio/AudioBufferSourceNode.cpp
+++ b/dom/media/webaudio/AudioBufferSourceNode.cpp
@@ -822,17 +822,17 @@ AudioBufferSourceNode::NotifyMainThreadS
       // Release stream resources.
       mNode->DestroyMediaStream();
       return NS_OK;
     }
   private:
     RefPtr<AudioBufferSourceNode> mNode;
   };
 
-  NS_DispatchToMainThread(new EndedEventDispatcher(this));
+  Context()->Dispatch(do_AddRef(new EndedEventDispatcher(this)));
 
   // Drop the playing reference
   // Warning: The below line might delete this.
   MarkInactive();
 }
 
 void
 AudioBufferSourceNode::SendDopplerShiftToStream(double aDopplerShift)
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AudioContext.h"
 
 #include "blink/PeriodicWave.h"
 
 #include "mozilla/ErrorResult.h"
 #include "mozilla/OwningNonNull.h"
+#include "mozilla/RefPtr.h"
 
 #include "mozilla/dom/AnalyserNode.h"
 #include "mozilla/dom/AnalyserNodeBinding.h"
 #include "mozilla/dom/AudioBufferSourceNodeBinding.h"
 #include "mozilla/dom/AudioContextBinding.h"
 #include "mozilla/dom/BaseAudioContextBinding.h"
 #include "mozilla/dom/BiquadFilterNodeBinding.h"
 #include "mozilla/dom/ChannelMergerNodeBinding.h"
@@ -757,16 +758,34 @@ public:
                                 NS_LITERAL_STRING("statechange"),
                                 false, false);
   }
 
 private:
   RefPtr<AudioContext> mAudioContext;
 };
 
+
+void
+AudioContext::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  nsCOMPtr<nsIGlobalObject> parentObject =
+    do_QueryInterface(GetParentObject());
+  // It can happen that this runnable took a long time to reach the main thread,
+  // and the global is not valid anymore.
+  if (parentObject) {
+    parentObject->AbstractMainThreadFor(TaskCategory::Other)
+                ->Dispatch(std::move(aRunnable));
+  } else {
+    RefPtr<nsIRunnable> runnable(aRunnable);
+    runnable = nullptr;
+  }
+}
+
 void
 AudioContext::OnStateChanged(void* aPromise, AudioContextState aNewState)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // This can happen if close() was called right after creating the
   // AudioContext, before the context has switched to "running".
   if (mAudioContextState == AudioContextState::Closed &&
@@ -821,19 +840,18 @@ AudioContext::OnStateChanged(void* aProm
     if (mPromiseGripArray.Contains(promise)) {
       promise->MaybeResolveWithUndefined();
       DebugOnly<bool> rv = mPromiseGripArray.RemoveElement(promise);
       MOZ_ASSERT(rv, "Promise wasn't in the grip array?");
     }
   }
 
   if (mAudioContextState != aNewState) {
-    RefPtr<OnStateChangeTask> onStateChangeTask =
-      new OnStateChangeTask(this);
-    NS_DispatchToMainThread(onStateChangeTask);
+    RefPtr<OnStateChangeTask> task = new OnStateChangeTask(this);
+    Dispatch(task.forget());
   }
 
   mAudioContextState = aNewState;
 }
 
 nsTArray<MediaStream*>
 AudioContext::GetAllStreams() const
 {
--- a/dom/media/webaudio/AudioContext.h
+++ b/dom/media/webaudio/AudioContext.h
@@ -323,16 +323,18 @@ public:
 
   BasicWaveFormCache* GetBasicWaveFormCache();
 
   IMPL_EVENT_HANDLER(mozinterruptbegin)
   IMPL_EVENT_HANDLER(mozinterruptend)
 
   bool CheckClosed(ErrorResult& aRv);
 
+  void Dispatch(already_AddRefed<nsIRunnable>&& aRunnable);
+
 private:
   void DisconnectFromWindow();
   void RemoveFromDecodeQueue(WebAudioDecodeJob* aDecodeJob);
   void ShutdownDecoder();
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   NS_DECL_NSIMEMORYREPORTER
 
--- a/dom/media/webaudio/AudioDestinationNode.cpp
+++ b/dom/media/webaudio/AudioDestinationNode.cpp
@@ -162,19 +162,18 @@ public:
                           mSampleRate, mBuffer.forget(), rv);
     if (rv.Failed()) {
       rv.SuppressException();
       return;
     }
 
     aNode->ResolvePromise(renderedBuffer);
 
-    RefPtr<OnCompleteTask> onCompleteTask =
-      new OnCompleteTask(context, renderedBuffer);
-    NS_DispatchToMainThread(onCompleteTask);
+    mAbstractMainThread->Dispatch(do_AddRef(new OnCompleteTask(context,
+                                                               renderedBuffer)));
 
     context->OnStateChanged(nullptr, AudioContextState::Closed);
   }
 
   size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
   {
     size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
     if (mBuffer) {
--- a/dom/media/webaudio/ConstantSourceNode.cpp
+++ b/dom/media/webaudio/ConstantSourceNode.cpp
@@ -270,17 +270,17 @@ ConstantSourceNode::NotifyMainThreadStre
       // Release stream resources.
       mNode->DestroyMediaStream();
       return NS_OK;
     }
   private:
     RefPtr<ConstantSourceNode> mNode;
   };
 
-  NS_DispatchToMainThread(new EndedEventDispatcher(this));
+  Context()->Dispatch(do_AddRef(new EndedEventDispatcher(this)));
 
   // Drop the playing reference
   // Warning: The below line might delete this.
   MarkInactive();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/webaudio/DynamicsCompressorNode.cpp
+++ b/dom/media/webaudio/DynamicsCompressorNode.cpp
@@ -164,17 +164,17 @@ private:
         return NS_OK;
       }
 
     private:
       RefPtr<AudioNodeStream> mStream;
       float mReduction;
     };
 
-    NS_DispatchToMainThread(new Command(aStream, aReduction));
+    mAbstractMainThread->Dispatch(do_AddRef(new Command(aStream, aReduction)));
   }
 
 private:
   AudioNodeStream* mDestination;
   AudioParamTimeline mThreshold;
   AudioParamTimeline mKnee;
   AudioParamTimeline mRatio;
   AudioParamTimeline mAttack;
--- a/dom/media/webaudio/MediaBufferDecoder.cpp
+++ b/dom/media/webaudio/MediaBufferDecoder.cpp
@@ -99,21 +99,22 @@ public:
 
 private:
   void ReportFailureOnMainThread(WebAudioDecodeJob::ErrorCode aErrorCode) {
     if (NS_IsMainThread()) {
       Cleanup();
       mDecodeJob.OnFailure(aErrorCode);
     } else {
       // Take extra care to cleanup on the main thread
-      NS_DispatchToMainThread(NewRunnableMethod(this, &MediaDecodeTask::Cleanup));
+      mMainThread->Dispatch(NewRunnableMethod(this, &MediaDecodeTask::Cleanup));
+
 
       nsCOMPtr<nsIRunnable> event =
         new ReportResultTask(mDecodeJob, &WebAudioDecodeJob::OnFailure, aErrorCode);
-      NS_DispatchToMainThread(event);
+      mMainThread->Dispatch(event.forget());
     }
   }
 
   void Decode();
   void OnMetadataRead(MetadataHolder* aMetadata);
   void OnMetadataNotRead(const MediaResult& aError);
   void RequestSample();
   void SampleDecoded(AudioData* aData);
@@ -137,16 +138,17 @@ private:
   uint8_t* mBuffer;
   uint32_t mLength;
   WebAudioDecodeJob& mDecodeJob;
   PhaseEnum mPhase;
   RefPtr<BufferDecoder> mBufferDecoder;
   RefPtr<MediaDecoderReader> mDecoderReader;
   MediaInfo mMediaInfo;
   MediaQueue<AudioData> mAudioQueue;
+  RefPtr<AbstractThread> mMainThread;
   bool mFirstFrameDecoded;
 };
 
 NS_IMETHODIMP
 MediaDecodeTask::Run()
 {
   MOZ_ASSERT(mBufferDecoder);
   MOZ_ASSERT(mDecoderReader);
@@ -196,19 +198,19 @@ MediaDecodeTask::CreateReader()
     principal = sop->GetPrincipal();
   }
 
   RefPtr<BufferMediaResource> resource =
     new BufferMediaResource(static_cast<uint8_t*> (mBuffer),
                             mLength, principal, mContainerType);
 
   MOZ_ASSERT(!mBufferDecoder);
-  RefPtr<AbstractThread> mainThread =
+  mMainThread =
     mDecodeJob.mContext->GetOwnerGlobal()->AbstractMainThreadFor(TaskCategory::Other);
-  mBufferDecoder = new BufferDecoder(resource, mainThread,
+  mBufferDecoder = new BufferDecoder(resource, mMainThread,
                                      new BufferDecoderGMPCrashHelper(parent));
 
   // If you change this list to add support for new decoders, please consider
   // updating HTMLMediaElement::CreateDecoder as well.
 
   mDecoderReader = DecoderTraits::CreateReader(mContainerType, mBufferDecoder);
 
   if (!mDecoderReader) {
@@ -436,17 +438,17 @@ MediaDecodeTask::FinishDecode()
         mDecodeJob.mWriteIndex += outSamples;
         MOZ_ASSERT(mDecodeJob.mWriteIndex <= resampledFrames);
         MOZ_ASSERT(inSamples == inputLatency);
       }
     }
   }
 
   mPhase = PhaseEnum::AllocateBuffer;
-  NS_DispatchToMainThread(this);
+  mMainThread->Dispatch(do_AddRef(this));
 }
 
 void
 MediaDecodeTask::AllocateBuffer()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mDecodeJob.AllocateBuffer()) {
@@ -494,28 +496,28 @@ AsyncDecodeWebAudio(const char* aContent
   if (!*aContentType ||
       strcmp(aContentType, APPLICATION_OCTET_STREAM) == 0 ||
       !containerType) {
     nsCOMPtr<nsIRunnable> event =
       new ReportResultTask(aDecodeJob,
                            &WebAudioDecodeJob::OnFailure,
                            WebAudioDecodeJob::UnknownContent);
     JS_free(nullptr, aBuffer);
-    NS_DispatchToMainThread(event);
+    aDecodeJob.mContext->Dispatch(event.forget());
     return;
   }
 
   RefPtr<MediaDecodeTask> task =
     new MediaDecodeTask(*containerType, aBuffer, aLength, aDecodeJob);
   if (!task->CreateReader()) {
     nsCOMPtr<nsIRunnable> event =
       new ReportResultTask(aDecodeJob,
                            &WebAudioDecodeJob::OnFailure,
                            WebAudioDecodeJob::UnknownError);
-    NS_DispatchToMainThread(event);
+    aDecodeJob.mContext->Dispatch(event.forget());
   } else {
     // If we did this without a temporary:
     //   task->Reader()->OwnerThread()->Dispatch(task.forget())
     // we might evaluate the task.forget() before calling Reader(). Enforce
     // a non-crashy order-of-operations.
     TaskQueue* taskQueue = task->Reader()->OwnerThread();
     taskQueue->Dispatch(task.forget());
   }
--- a/dom/media/webaudio/OscillatorNode.cpp
+++ b/dom/media/webaudio/OscillatorNode.cpp
@@ -593,17 +593,17 @@ OscillatorNode::NotifyMainThreadStreamFi
       // Release stream resources.
       mNode->DestroyMediaStream();
       return NS_OK;
     }
   private:
     RefPtr<OscillatorNode> mNode;
   };
 
-  NS_DispatchToMainThread(new EndedEventDispatcher(this));
+  Context()->Dispatch(do_AddRef(new EndedEventDispatcher(this)));
 
   // Drop the playing reference
   // Warning: The below line might delete this.
   MarkInactive();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/webaudio/ScriptProcessorNode.cpp
+++ b/dom/media/webaudio/ScriptProcessorNode.cpp
@@ -463,18 +463,19 @@ private:
         return nullptr;
       }
     private:
       RefPtr<AudioNodeStream> mStream;
       RefPtr<ThreadSharedFloatArrayBufferList> mInputBuffer;
       double mPlaybackTime;
     };
 
-    NS_DispatchToMainThread(new Command(aStream, mInputBuffer.forget(),
-                                        playbackTime));
+    RefPtr<Command> command = new Command(aStream, mInputBuffer.forget(),
+                                          playbackTime);
+    mAbstractMainThread->Dispatch(command.forget());
   }
 
   friend class ScriptProcessorNode;
 
   AudioNodeStream* mDestination;
   nsAutoPtr<SharedBuffers> mSharedBuffers;
   RefPtr<ThreadSharedFloatArrayBufferList> mInputBuffer;
   const uint32_t mBufferSize;