Bug Bug 713381 - backout 38271572005b,d5ebbc25b4b8,6435f51dd10d. r=backout
authorChris Pearce <chris@pearce.org.nz>
Thu, 19 Jan 2012 11:56:54 +1300
changeset 86054 d24c4d2ffde94ac0d2e6a2d2bf6041cdf65189c2
parent 86040 6435f51dd10d6ace3a410d560ed8d92b27ed4ede
child 86055 04d508fb9e4c3b30d301edf15585a4458aef7286
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs713381
milestone12.0a1
Bug Bug 713381 - backout 38271572005b,d5ebbc25b4b8,6435f51dd10d. r=backout
content/html/content/src/nsHTMLMediaElement.cpp
content/media/nsBuiltinDecoder.cpp
content/media/nsBuiltinDecoderStateMachine.cpp
content/media/nsBuiltinDecoderStateMachine.h
content/media/test/Makefile.in
content/media/test/crashtests/crashtests.list
content/media/test/manifest.js
content/media/test/test_too_many_elements.html
xpcom/glue/nsDeque.cpp
xpcom/glue/nsDeque.h
xpcom/tests/Makefile.in
xpcom/tests/TestDeque.cpp
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -1994,37 +1994,34 @@ nsresult nsHTMLMediaElement::InitializeD
     return NS_ERROR_FAILURE;
   nsRefPtr<nsMediaDecoder> decoder = aOriginal->Clone();
   if (!decoder)
     return NS_ERROR_FAILURE;
 
   LOG(PR_LOG_DEBUG, ("%p Cloned decoder %p from %p", this, decoder.get(), aOriginal));
 
   if (!decoder->Init(this)) {
-    LOG(PR_LOG_DEBUG, ("%p Failed to init cloned decoder %p", this, decoder.get()));
     return NS_ERROR_FAILURE;
   }
 
   double duration = aOriginal->GetDuration();
   if (duration >= 0) {
     decoder->SetDuration(duration);
     decoder->SetSeekable(aOriginal->IsSeekable());
   }
 
   nsMediaStream* stream = originalStream->CloneData(decoder);
   if (!stream) {
-    LOG(PR_LOG_DEBUG, ("%p Failed to cloned stream for decoder %p", this, decoder.get()));
     return NS_ERROR_FAILURE;
   }
 
   mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
 
   nsresult rv = decoder->Load(stream, nsnull, aOriginal);
   if (NS_FAILED(rv)) {
-    LOG(PR_LOG_DEBUG, ("%p Failed to load decoder/stream for decoder %p", this, decoder.get()));
     return rv;
   }
 
   return FinishDecoderSetup(decoder);
 }
 
 nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
                                                          nsIStreamListener **aListener)
--- a/content/media/nsBuiltinDecoder.cpp
+++ b/content/media/nsBuiltinDecoder.cpp
@@ -188,17 +188,16 @@ nsresult nsBuiltinDecoder::Load(nsMediaS
   {
     // Hold the lock while we do this to set proper lock ordering
     // expectations for dynamic deadlock detectors: decoder lock(s)
     // should be grabbed before the cache lock
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
 
     nsresult rv = aStream->Open(aStreamListener);
     if (NS_FAILED(rv)) {
-      LOG(PR_LOG_DEBUG, ("%p Failed to open stream!", this));
       delete aStream;
       return rv;
     }
 
     mStream = aStream;
   }
 
   mDecoderStateMachine = CreateStateMachine();
@@ -241,31 +240,29 @@ nsresult nsBuiltinDecoder::RequestFrameB
   return res;
 }
 
 nsresult nsBuiltinDecoder::ScheduleStateMachineThread()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   NS_ASSERTION(mDecoderStateMachine,
                "Must have state machine to start state machine thread");
-  NS_ENSURE_STATE(mDecoderStateMachine);
 
   if (mShuttingDown)
     return NS_OK;
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   nsBuiltinDecoderStateMachine* m =
     static_cast<nsBuiltinDecoderStateMachine*>(mDecoderStateMachine.get());
   return m->ScheduleStateMachine();
 }
 
 nsresult nsBuiltinDecoder::Play()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-  NS_ASSERTION(mDecoderStateMachine != nsnull, "Should have state machine.");
   nsresult res = ScheduleStateMachineThread();
   NS_ENSURE_SUCCESS(res,res);
   if (mPlayState == PLAY_STATE_SEEKING) {
     mNextState = PLAY_STATE_PLAYING;
     return NS_OK;
   }
   if (mPlayState == PLAY_STATE_ENDED)
     return Seek(0);
@@ -830,29 +827,39 @@ void nsBuiltinDecoder::ChangeState(PlayS
   }
 
   if (mPlayState == PLAY_STATE_SHUTDOWN) {
     mReentrantMonitor.NotifyAll();
     return;
   }
 
   mPlayState = aState;
-  if (mDecoderStateMachine) {
-    switch (aState) {
-    case PLAY_STATE_PLAYING:
-      mDecoderStateMachine->Play();
-      break;
-    case PLAY_STATE_SEEKING:
-      mDecoderStateMachine->Seek(mRequestedSeekTime);
-      mRequestedSeekTime = -1.0;
-      break;
-    default:
-      /* No action needed */
-      break;
-    }
+  switch (aState) {
+  case PLAY_STATE_PAUSED:
+    /* No action needed */
+    break;
+  case PLAY_STATE_PLAYING:
+    mDecoderStateMachine->Play();
+    break;
+  case PLAY_STATE_SEEKING:
+    mDecoderStateMachine->Seek(mRequestedSeekTime);
+    mRequestedSeekTime = -1.0;
+    break;
+  case PLAY_STATE_LOADING:
+    /* No action needed */
+    break;
+  case PLAY_STATE_START:
+    /* No action needed */
+    break;
+  case PLAY_STATE_ENDED:
+    /* No action needed */
+    break;
+  case PLAY_STATE_SHUTDOWN:
+    /* No action needed */
+    break;
   }
   mReentrantMonitor.NotifyAll();
 }
 
 void nsBuiltinDecoder::PlaybackPositionChanged()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   if (mShuttingDown)
@@ -961,19 +968,17 @@ void nsBuiltinDecoder::Suspend()
 void nsBuiltinDecoder::Resume(bool aForceBuffering)
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   if (mStream) {
     mStream->Resume();
   }
   if (aForceBuffering) {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-    if (mDecoderStateMachine) {
-      mDecoderStateMachine->StartBuffering();
-    }
+    mDecoderStateMachine->StartBuffering();
   }
 }
 
 void nsBuiltinDecoder::StopProgressUpdates()
 {
   NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
                "Should be on state machine or decode thread.");
   GetReentrantMonitor().AssertCurrentThreadIn();
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -40,17 +40,16 @@
 #include "nsAudioStream.h"
 #include "nsTArray.h"
 #include "nsBuiltinDecoder.h"
 #include "nsBuiltinDecoderReader.h"
 #include "nsBuiltinDecoderStateMachine.h"
 #include "mozilla/mozalloc.h"
 #include "VideoUtils.h"
 #include "nsTimeRanges.h"
-#include "nsDeque.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/StdInt.h"
 
 using namespace mozilla;
 using namespace mozilla::layers;
 
 #ifdef PR_LOGGING
@@ -225,47 +224,35 @@ public:
   // Return the global state machine thread. Call from any thread.
   nsIThread* GetGlobalStateMachineThread()
   {
     ReentrantMonitorAutoEnter mon(mMonitor);
     NS_ASSERTION(mStateMachineThread, "Should have non-null state machine thread!");
     return mStateMachineThread;
   }
 
-  // Requests that a decode thread be created for aStateMachine. The thread
-  // may be created immediately, or after some delay, once a thread becomes
-  // available. The request can be cancelled using CancelCreateDecodeThread().
-  // It's the callers responsibility to not call this more than once for any
-  // given state machine.
-  nsresult RequestCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine);
-
-  // Cancels a request made by RequestCreateDecodeThread to create a decode
-  // thread for aStateMachine.
-  nsresult CancelCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine);
-
   // Maximum number of active decode threads allowed. When more
   // than this number are active the thread creation will fail.
   static const PRUint32 MAX_DECODE_THREADS = 25;
 
   // Returns the number of active decode threads.
   // Call on any thread. Holds the internal monitor so don't
   // call with any other monitor held to avoid deadlock.
   PRUint32 GetDecodeThreadCount();
 
+  // Keep track of the fact that a decode thread was created.
+  // Call on any thread. Holds the internal monitor so don't
+  // call with any other monitor held to avoid deadlock.
+  void NoteDecodeThreadCreated();
+
   // Keep track of the fact that a decode thread was destroyed.
   // Call on any thread. Holds the internal monitor so don't
   // call with any other monitor held to avoid deadlock.
   void NoteDecodeThreadDestroyed();
 
-#ifdef DEBUG
-  // Returns true if aStateMachine has a pending request for a
-  // decode thread.
-  bool IsQueued(nsBuiltinDecoderStateMachine* aStateMachine);
-#endif
-
 private:
   // Holds global instance of StateMachineTracker.
   // Writable on main thread only.
   static StateMachineTracker* mInstance;
 
   // Reentrant monitor that must be obtained to access
   // the decode thread count member and methods.
   ReentrantMonitor mMonitor;
@@ -279,20 +266,16 @@ private:
   // currently instantiated. Access only with the
   // mMonitor lock held. Can be used from any thread.
   PRUint32 mDecodeThreadCount;
 
   // Global state machine thread. Write on the main thread
   // only, read from the decoder threads. Synchronized via
   // the mMonitor.
   nsIThread* mStateMachineThread;
-
-  // Queue of state machines waiting for decode threads. Entries at the front
-  // get their threads first.
-  nsDeque mPending;
 };
 
 StateMachineTracker* StateMachineTracker::mInstance = nsnull;
 
 StateMachineTracker& StateMachineTracker::Instance()
 {
   if (!mInstance) {
     NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
@@ -308,119 +291,57 @@ void StateMachineTracker::EnsureGlobalSt
   if (mStateMachineCount == 0) {
     NS_ASSERTION(!mStateMachineThread, "Should have null state machine thread!");
     nsresult res = NS_NewThread(&mStateMachineThread,
                                 nsnull);
     NS_ABORT_IF_FALSE(NS_SUCCEEDED(res), "Can't create media state machine thread");
   }
   mStateMachineCount++;
 }
-
-#ifdef DEBUG
-bool StateMachineTracker::IsQueued(nsBuiltinDecoderStateMachine* aStateMachine)
-{
-  ReentrantMonitorAutoEnter mon(mMonitor);
-  PRInt32 size = mPending.GetSize();
-  for (int i = 0; i < size; ++i) {
-    nsBuiltinDecoderStateMachine* m =
-      static_cast<nsBuiltinDecoderStateMachine*>(mPending.ObjectAt(i));
-    if (m == aStateMachine) {
-      return true;
-    }
-  }
-  return false;
-}
-#endif
-
+ 
 void StateMachineTracker::CleanupGlobalStateMachine() 
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   NS_ABORT_IF_FALSE(mStateMachineCount > 0,
     "State machine ref count must be > 0");
   mStateMachineCount--;
   if (mStateMachineCount == 0) {
     LOG(PR_LOG_DEBUG, ("Destroying media state machine thread"));
-    NS_ASSERTION(mPending.GetSize() == 0, "Shouldn't all requests be handled by now?");
     {
       ReentrantMonitorAutoEnter mon(mMonitor);
       nsCOMPtr<nsIRunnable> event = new ShutdownThreadEvent(mStateMachineThread);
       NS_RELEASE(mStateMachineThread);
       mStateMachineThread = nsnull;
       NS_DispatchToMainThread(event);
 
       NS_ASSERTION(mDecodeThreadCount == 0, "Decode thread count must be zero.");
       mInstance = nsnull;
     }
     delete this;
   }
 }
 
+void StateMachineTracker::NoteDecodeThreadCreated()
+{
+  ReentrantMonitorAutoEnter mon(mMonitor);
+  ++mDecodeThreadCount;
+}
+
 void StateMachineTracker::NoteDecodeThreadDestroyed()
 {
   ReentrantMonitorAutoEnter mon(mMonitor);
   --mDecodeThreadCount;
-  while (mDecodeThreadCount < MAX_DECODE_THREADS && mPending.GetSize() > 0) {
-    nsBuiltinDecoderStateMachine* m =
-      static_cast<nsBuiltinDecoderStateMachine*>(mPending.PopFront());
-    nsresult rv;
-    {
-      ReentrantMonitorAutoExit exitMon(mMonitor);
-      rv = m->StartDecodeThread();
-    }
-    if (NS_SUCCEEDED(rv)) {
-      ++mDecodeThreadCount;
-    }
-  }
 }
 
 PRUint32 StateMachineTracker::GetDecodeThreadCount()
 {
   ReentrantMonitorAutoEnter mon(mMonitor);
   return mDecodeThreadCount;
 }
 
-nsresult StateMachineTracker::CancelCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine) {
-  ReentrantMonitorAutoEnter mon(mMonitor);
-  PRInt32 size = mPending.GetSize();
-  for (PRInt32 i = 0; i < size; ++i) {
-    void* m = static_cast<nsBuiltinDecoderStateMachine*>(mPending.ObjectAt(i));
-    if (m == aStateMachine) {
-      mPending.RemoveObjectAt(i);
-      break;
-    }
-  }
-  NS_ASSERTION(!IsQueued(aStateMachine), "State machine should no longer have queued request.");
-  return NS_OK;
-}
-
-nsresult StateMachineTracker::RequestCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine)
-{
-  NS_ENSURE_STATE(aStateMachine);
-  ReentrantMonitorAutoEnter mon(mMonitor);
-  if (mPending.GetSize() > 0 || mDecodeThreadCount + 1 >= MAX_DECODE_THREADS) {
-    // If there's already state machines in the queue, or we've exceeded the
-    // limit, append the state machine to the queue of state machines waiting
-    // for a decode thread. This ensures state machines already waiting get
-    // their threads first.
-    mPending.Push(aStateMachine);
-    return NS_OK;
-  }
-  nsresult rv;
-  {
-    ReentrantMonitorAutoExit exitMon(mMonitor);
-    rv = aStateMachine->StartDecodeThread();
-  }
-  if (NS_SUCCEEDED(rv)) {
-    ++mDecodeThreadCount;
-  }
-  NS_ASSERTION(mDecodeThreadCount <= MAX_DECODE_THREADS,
-                "Should keep to thread limit!");
-  return NS_OK;
-}
-
 nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDecoder,
                                                            nsBuiltinDecoderReader* aReader,
                                                            bool aRealTime) :
   mDecoder(aDecoder),
   mState(DECODER_STATE_DECODING_METADATA),
   mCbCrSize(0),
   mPlayDuration(0),
   mStartTime(-1),
@@ -441,17 +362,16 @@ nsBuiltinDecoderStateMachine::nsBuiltinD
   mDecodeThreadIdle(false),
   mStopAudioThread(true),
   mQuickBuffering(false),
   mIsRunning(false),
   mRunAgain(false),
   mDispatchedRunEvent(false),
   mDecodeThreadWaiting(false),
   mRealTime(aRealTime),
-  mRequestedNewDecodeThread(false),
   mEventManager(aDecoder)
 {
   MOZ_COUNT_CTOR(nsBuiltinDecoderStateMachine);
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
 
   StateMachineTracker::Instance().EnsureGlobalStateMachine();
 
   // only enable realtime mode when "media.realtime_decoder.enabled" is true.
@@ -461,20 +381,16 @@ nsBuiltinDecoderStateMachine::nsBuiltinD
   mBufferingWait = mRealTime ? 0 : BUFFERING_WAIT;
   mLowDataThresholdUsecs = mRealTime ? 0 : LOW_DATA_THRESHOLD_USECS;
 }
 
 nsBuiltinDecoderStateMachine::~nsBuiltinDecoderStateMachine()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   MOZ_COUNT_DTOR(nsBuiltinDecoderStateMachine);
-  NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
-    "Should not have a pending request for a new decode thread");
-  NS_ASSERTION(!mRequestedNewDecodeThread,
-    "Should not have (or flagged) a pending request for a new decode thread");
   if (mTimer)
     mTimer->Cancel();
   mTimer = nsnull;
  
   StateMachineTracker::Instance().CleanupGlobalStateMachine();
 }
 
 bool nsBuiltinDecoderStateMachine::HasFutureAudio() const {
@@ -1266,40 +1182,28 @@ void nsBuiltinDecoderStateMachine::Seek(
   mState = DECODER_STATE_SEEKING;
   ScheduleStateMachine();
 }
 
 void nsBuiltinDecoderStateMachine::StopDecodeThread()
 {
   NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
-  if (mRequestedNewDecodeThread) {
-    // We've requested that the decode be created, but it hasn't been yet.
-    // Cancel that request.
-    NS_ASSERTION(!mDecodeThread,
-      "Shouldn't have a decode thread until after request processed");
-    StateMachineTracker::Instance().CancelCreateDecodeThread(this);
-    mRequestedNewDecodeThread = false;
-  }
   mStopDecodeThread = true;
   mDecoder->GetReentrantMonitor().NotifyAll();
   if (mDecodeThread) {
     LOG(PR_LOG_DEBUG, ("%p Shutdown decode thread", mDecoder.get()));
     {
       ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
       mDecodeThread->Shutdown();
       StateMachineTracker::Instance().NoteDecodeThreadDestroyed();
     }
     mDecodeThread = nsnull;
     mDecodeThreadIdle = false;
   }
-  NS_ASSERTION(!mRequestedNewDecodeThread,
-    "Any pending requests for decode threads must be canceled and unflagged");
-  NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
-    "Any pending requests for decode threads must be canceled");
 }
 
 void nsBuiltinDecoderStateMachine::StopAudioThread()
 {
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
   mStopAudioThread = true;
   mDecoder->GetReentrantMonitor().NotifyAll();
   if (mAudioThread) {
@@ -1308,94 +1212,77 @@ void nsBuiltinDecoderStateMachine::StopA
       ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
       mAudioThread->Shutdown();
     }
     mAudioThread = nsnull;
   }
 }
 
 nsresult
-nsBuiltinDecoderStateMachine::ScheduleDecodeThread()
+nsBuiltinDecoderStateMachine::StartDecodeThread()
 {
   NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
- 
-  mStopDecodeThread = false;
-  if (mState >= DECODER_STATE_COMPLETED) {
-    return NS_OK;
-  }
-  if (mDecodeThread) {
-    NS_ASSERTION(!mRequestedNewDecodeThread,
-      "Shouldn't have requested new decode thread when we have a decode thread");
-    // We already have a decode thread...
-    if (mDecodeThreadIdle) {
-      // ... and it's not been shutdown yet, wake it up.
-      nsCOMPtr<nsIRunnable> event =
-        NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeThreadRun);
-      mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
-      mDecodeThreadIdle = false;
-    }
-    return NS_OK;
-  } else if (!mRequestedNewDecodeThread) {
-  // We don't already have a decode thread, request a new one.
-    mRequestedNewDecodeThread = true;
+  PRUint32 count = 0;
+  bool created = false;
+  {
     ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
-    StateMachineTracker::Instance().RequestCreateDecodeThread(this);
-  }
-  return NS_OK;
-}
-
-nsresult
-nsBuiltinDecoderStateMachine::StartDecodeThread()
-{
-  NS_ASSERTION(StateMachineTracker::Instance().GetDecodeThreadCount() <
-               StateMachineTracker::MAX_DECODE_THREADS,
-               "Should not have reached decode thread limit");
-
-  ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-  NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
-    "Should not already have a pending request for a new decode thread.");
-  NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
-  NS_ASSERTION(!mDecodeThread, "Should not have decode thread yet");
-  NS_ASSERTION(mRequestedNewDecodeThread, "Should have requested this...");
-
-  mRequestedNewDecodeThread = false;
-
-  nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread),
-                              nsnull,
-                              MEDIA_THREAD_STACK_SIZE);
-  if (NS_FAILED(rv)) {
-    // Give up, report error to media element.
-    nsCOMPtr<nsIRunnable> event =
-      NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::DecodeError);
-    NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
-    return rv;
+    count = StateMachineTracker::Instance().GetDecodeThreadCount();
   }
 
+  mStopDecodeThread = false;
+  if ((mDecodeThread && !mDecodeThreadIdle) || mState >= DECODER_STATE_COMPLETED)
+    return NS_OK;
+
+  if (!mDecodeThread && count > StateMachineTracker::MAX_DECODE_THREADS) {
+    // Have to run one iteration of the state machine loop to ensure the
+    // shutdown state is processed.
+    ScheduleStateMachine();
+    mState = DECODER_STATE_SHUTDOWN;
+    return NS_ERROR_FAILURE;
+  }
+
+  if (!mDecodeThread) {
+    nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread),
+                               nsnull,
+                               MEDIA_THREAD_STACK_SIZE);
+    if (NS_FAILED(rv)) {
+      // Have to run one iteration of the state machine loop to ensure the
+      // shutdown state is processed.
+      ScheduleStateMachine();
+      mState = DECODER_STATE_SHUTDOWN;
+      return rv;
+    }
+    created = true;
+  }
   nsCOMPtr<nsIRunnable> event =
     NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeThreadRun);
   mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
   mDecodeThreadIdle = false;
 
+  if (created) {
+    ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
+    StateMachineTracker::Instance().NoteDecodeThreadCreated();
+  }
+
   return NS_OK;
 }
 
 nsresult
 nsBuiltinDecoderStateMachine::StartAudioThread()
 {
   NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
                "Should be on state machine or decode thread.");
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
   mStopAudioThread = false;
   if (HasAudio() && !mAudioThread) {
     nsresult rv = NS_NewThread(getter_AddRefs(mAudioThread),
                                nsnull,
                                MEDIA_THREAD_STACK_SIZE);
     if (NS_FAILED(rv)) {
-      LOG(PR_LOG_DEBUG, ("%p Changed state to SHUTDOWN because failed to create audio thread", mDecoder.get()));
       mState = DECODER_STATE_SHUTDOWN;
       return rv;
     }
     nsCOMPtr<nsIRunnable> event =
       NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::AudioLoop);
     mAudioThread->Dispatch(event, NS_DISPATCH_NORMAL);
   }
   return NS_OK;
@@ -1743,17 +1630,17 @@ nsresult nsBuiltinDecoderStateMachine::R
       // dispatch an event to the main thread to release the decoder and
       // state machine.
       NS_DispatchToCurrentThread(new nsDispatchDisposeEvent(mDecoder, this));
       return NS_OK;
     }
 
     case DECODER_STATE_DECODING_METADATA: {
       // Ensure we have a decode thread to decode metadata.
-      return ScheduleDecodeThread();
+      return StartDecodeThread();
     }
   
     case DECODER_STATE_DECODING: {
       if (mDecoder->GetState() != nsBuiltinDecoder::PLAY_STATE_PLAYING &&
           IsPlaying())
       {
         // We're playing, but the element/decoder is in paused state. Stop
         // playing! Note we do this before StopDecodeThread() below because
@@ -1767,17 +1654,17 @@ nsresult nsBuiltinDecoderStateMachine::R
         // The decode buffers are full, and playback is paused. Shutdown the
         // decode thread.
         StopDecodeThread();
         return NS_OK;
       }
 
       // We're playing and/or our decode buffers aren't full. Ensure we have
       // an active decode thread.
-      if (NS_FAILED(ScheduleDecodeThread())) {
+      if (NS_FAILED(StartDecodeThread())) {
         NS_WARNING("Failed to start media decode thread!");
         return NS_ERROR_FAILURE;
       }
 
       AdvanceFrame();
       NS_ASSERTION(mDecoder->GetState() != nsBuiltinDecoder::PLAY_STATE_PLAYING ||
                    IsStateMachineScheduled(), "Must have timer scheduled");
       return NS_OK;
@@ -1832,17 +1719,17 @@ nsresult nsBuiltinDecoderStateMachine::R
         StartPlayback();
       }
       NS_ASSERTION(IsStateMachineScheduled(), "Must have timer scheduled");
       return NS_OK;
     }
 
     case DECODER_STATE_SEEKING: {
       // Ensure we have a decode thread to perform the seek.
-     return ScheduleDecodeThread();
+     return StartDecodeThread();
     }
 
     case DECODER_STATE_COMPLETED: {
       StopDecodeThread();
 
       if (mState != DECODER_STATE_COMPLETED) {
         // While we're waiting for the decode thread to shutdown, we can
         // change state, for example to seeking or shutdown state.
--- a/content/media/nsBuiltinDecoderStateMachine.h
+++ b/content/media/nsBuiltinDecoderStateMachine.h
@@ -248,22 +248,16 @@ public:
   // machine again.
   nsresult ScheduleStateMachine();
 
   // Schedules the shared state machine thread to run the state machine
   // in aUsecs microseconds from now, if it's not already scheduled to run
   // earlier, in which case the request is discarded.
   nsresult ScheduleStateMachine(PRInt64 aUsecs);
 
-  // Creates and starts a new decode thread. Don't call this directly,
-  // request a new decode thread by calling
-  // StateMachineTracker::RequestCreateDecodeThread().
-  // The decoder monitor must not be held. Called on the state machine thread.
-  nsresult StartDecodeThread();
-
   // Timer function to implement ScheduleStateMachine(aUsecs).
   void TimeoutExpired();
 
   // Set the media fragment end time. aEndTime is in microseconds.
   void SetFragmentEndTime(PRInt64 aEndTime);
 
   // Drop reference to decoder.  Only called during shutdown dance.
   void ReleaseDecoder() { mDecoder = nsnull; }
@@ -353,30 +347,27 @@ protected:
                        PRUint32 aChannels,
                        PRUint64 aFrameOffset);
 
   // Pops an audio chunk from the front of the audio queue, and pushes its
   // audio data to the audio hardware. MozAudioAvailable data is also queued
   // here. Called on the audio thread.
   PRUint32 PlayFromAudioQueue(PRUint64 aFrameOffset, PRUint32 aChannels);
 
-  // Stops the decode thread, and if we have a pending request for a new
-  // decode thread it is canceled. The decoder monitor must be held with exactly
+  // Stops the decode thread. The decoder monitor must be held with exactly
   // one lock count. Called on the state machine thread.
   void StopDecodeThread();
 
   // Stops the audio thread. The decoder monitor must be held with exactly
   // one lock count. Called on the state machine thread.
   void StopAudioThread();
 
-  // Ensures the decode thread is running if it already exists, or requests
-  // a new decode thread be started if there currently is no decode thread.
-  // The decoder monitor must be held with exactly one lock count. Called on
-  // the state machine thread.
-  nsresult ScheduleDecodeThread();
+  // Starts the decode thread. The decoder monitor must be held with exactly
+  // one lock count. Called on the state machine thread.
+  nsresult StartDecodeThread();
 
   // Starts the audio thread. The decoder monitor must be held with exactly
   // one lock count. Called on the state machine thread.
   nsresult StartAudioThread();
 
   // The main loop for the audio thread. Sent to the thread as
   // an nsRunnableMethod. This continually does blocking writes to
   // to audio stream to play audio data.
@@ -629,20 +620,16 @@ protected:
 
   // True if the decode thread has gone filled its buffers and is now
   // waiting to be awakened before it continues decoding. Synchronized
   // by the decoder monitor.
   bool mDecodeThreadWaiting;
 
   // True is we are decoding a realtime stream, like a camera stream
   bool mRealTime;
-
-  // True if we've requested a new decode thread, but it has not yet been
-  // created. Synchronized by the decoder monitor.
-  bool mRequestedNewDecodeThread;
   
   PRUint32 mBufferingWait;
   PRInt64  mLowDataThresholdUsecs;
 
 private:
   // Manager for queuing and dispatching MozAudioAvailable events.  The
   // event manager is accessed from the state machine and audio threads,
   // and takes care of synchronizing access to its internal queue.
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -145,17 +145,16 @@ include $(topsrcdir)/config/rules.mk
 		test_seek.html \
 		test_seek2.html \
 		test_seekLies.html \
 		test_seek_out_of_range.html \
 		test_source.html \
 		test_source_write.html \
 		test_standalone.html \
 		test_timeupdate_small_files.html \
-		test_too_many_elements.html \
 		test_volume.html \
 		test_video_to_canvas.html \
 		use_large_cache.js \
 		test_audiowrite.html \
 		$(NULL)
 
 # Don't run in suite
 ifndef MOZ_SUITE
--- a/content/media/test/crashtests/crashtests.list
+++ b/content/media/test/crashtests/crashtests.list
@@ -3,9 +3,9 @@ load 466607-1.html
 load 466945-1.html
 load 468763-1.html
 load 474744-1.html
 HTTP load 481136-1.html # needs to be HTTP to recognize the ogg as an audio file?
 load 493915-1.html
 skip-if(Android) load 495794-1.html
 load 492286-1.xhtml
 load 576612-1.html
-skip-if(Android) load 691096-1.html # Android sound API can't handle playing large number of sounds at once.
+load 691096-1.html
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -1,18 +1,18 @@
 // In each list of tests below, test file types that are not supported should
 // be ignored. To make sure tests respect that, we include a file of type
 // "bogus/duh" in each list.
 
 // These are small test files, good for just seeing if something loads. We
 // really only need one test file per backend here.
 var gSmallTests = [
-  { name:"small-shot.ogg", type:"audio/ogg", duration:0.276 },
   { name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
   { name:"320x240.ogv", type:"video/ogg", width:320, height:240, duration:0.233 },
+  { name:"small-shot.ogg", type:"audio/ogg", duration:0.276 },
   { name:"seek.webm", type:"video/webm", duration:3.966 },
   { name:"bogus.duh", type:"bogus/duh" }
 ];
 
 // Used by test_progress to ensure we get the correct progress information
 // during resource download.
 var gProgressTests = [
   { name:"r11025_u8_c1.wav", type:"audio/x-wav", duration:1.0, size:11069 },
@@ -294,24 +294,16 @@ function checkMetadata(msg, e, test) {
 function getPlayableVideo(candidates) {
   var v = document.createElement("video");
   var resources = candidates.filter(function(x){return /^video/.test(x.type) && v.canPlayType(x.type);});
   if (resources.length > 0)
     return resources[0];
   return null;
 }
 
-function getPlayableAudio(candidates) {
-  var v = document.createElement("audio");
-  var resources = candidates.filter(function(x){return /^audio/.test(x.type) && v.canPlayType(x.type);});
-  if (resources.length > 0)
-    return resources[0];
-  return null;
-}
-
 // Number of tests to run in parallel. Warning: Each media element requires
 // at least 3 threads (4 on Linux), and on Linux each thread uses 10MB of
 // virtual address space. Beware!
 var PARALLEL_TESTS = 2;
 
 // When true, we'll loop forever on whatever test we run. Use this to debug
 // intermittent test failures.
 const DEBUG_TEST_LOOP_FOREVER = false;
deleted file mode 100644
--- a/content/media/test/test_too_many_elements.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=713381
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 713381</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-  <script type="text/javascript" src="manifest.js"></script>  
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=713381">Mozilla Bug 713381</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-  
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 713381 **/
-
-const num = 500;
-var ended = 0;
-
-var finish = function(testNum) {
-  return function() {
-    ok(true, "Received ended event for instance " + testNum );
-    ended++;
-    if (ended == num) {
-      ok(true, "Should receive ended events for all " + num + " elements.");
-      SimpleTest.finish();
-    }
-  }
-};
-
-var resource = getPlayableAudio(gSmallTests);
-
-if (resource == null) {
-  todo(false, "No types supported");
-} else {
-  SimpleTest.waitForExplicitFinish();
-  // Load the resource, and play it to ensure it's entirely downloaded.
-  // Once it's played through, create a large number of audio elements which
-  // are the same resource. These will share data with the other resource, and
-  // so be really cheap to create.
-  var res = new Audio(resource.name);
-  res.addEventListener("ended",
-    function() {  
-      for (var i=0; i<num; ++i) {
-        var a = new Audio(resource.name);
-        a.addEventListener("ended", finish(i), false);
-        a.volume = 0.1;
-        a.play();
-      }
-    }, false);
-  res.play();
-}
-
-
-</script>
-</pre>
-</body>
-</html>
--- a/xpcom/glue/nsDeque.cpp
+++ b/xpcom/glue/nsDeque.cpp
@@ -345,32 +345,16 @@ void* nsDeque::PeekFront() {
 void* nsDeque::ObjectAt(PRInt32 aIndex) const {
   void* result=0;
   if ((aIndex>=0) && (aIndex<mSize)) {
     result=mData[modulus(mOrigin + aIndex, mCapacity)];
   }
   return result;
 }
 
-void* nsDeque::RemoveObjectAt(PRInt32 aIndex) {
-  if ((aIndex<0) || (aIndex>=mSize)) {
-    return 0;
-  }
-  void* result=mData[modulus(mOrigin + aIndex, mCapacity)];
-
-  // "Shuffle down" all elements in the array by 1, overwritting the element
-  // being removed.
-  for (PRInt32 i=aIndex; i<mSize; i++) {
-    mData[modulus(mOrigin + i, mCapacity)] = mData[modulus(mOrigin + i + 1, mCapacity)];
-  }
-  mSize--;
-
-  return result;
-}
-
 /**
  * Create and return an iterator pointing to
  * the beginning of the queue. Note that this
  * takes the circular buffer semantics into account.
  *
  * @return  new deque iterator, init'ed to 1st item
  */
 nsDequeIterator nsDeque::Begin() const{
--- a/xpcom/glue/nsDeque.h
+++ b/xpcom/glue/nsDeque.h
@@ -148,24 +148,16 @@ class NS_COM_GLUE nsDeque {
    * Retrieve the i'th member from the deque without removing it.
    *
    * @param   index of desired item
    * @return  i'th element in list
    */
   void* ObjectAt(int aIndex) const;
 
   /**
-   * Removes and returns the i'th member from the deque.
-   *
-   * @param   index of desired item
-   * @return  the element which was removed
-   */
-  void* RemoveObjectAt(int aIndex);
-
-  /**
    * Remove all items from container without destroying them.
    *
    * @return  *this
    */
   nsDeque& Empty();
 
   /**
    * Remove and delete all items from container.
--- a/xpcom/tests/Makefile.in
+++ b/xpcom/tests/Makefile.in
@@ -84,17 +84,16 @@ SIMPLE_PROGRAMS	:= $(CPPSRCS:.cpp=$(BIN_
 
 CPP_UNIT_TESTS = \
                  ShowAlignments.cpp \
                  ShowSSEConfig.cpp \
                  TestAutoPtr.cpp \
                  TestCOMArray.cpp \
                  TestCOMPtr.cpp \
                  TestCOMPtrEq.cpp \
-                 TestDeque.cpp \
                  TestFile.cpp \
                  TestHashtables.cpp \
                  TestID.cpp \
                  TestObserverArray.cpp \
                  TestObserverService.cpp \
                  TestPipe.cpp \
                  TestRefPtr.cpp \
                  TestTextFormatter.cpp \
@@ -105,16 +104,17 @@ CPP_UNIT_TESTS = \
 ifdef MOZ_MEMORY
 CPP_UNIT_TESTS += TestJemalloc.cpp
 endif
 
 # XXX Make this tests work in libxul builds.
 #CPP_UNIT_TESTS += \
 #                  TestArray.cpp \
 #                  TestCRT.cpp \
+#                  TestDeque.cpp \
 #                  TestEncoding.cpp \
 #                  TestExpirationTracker.cpp \
 #                  TestPipes.cpp \
 #                  TestPriorityQueue.cpp \
 #                  TestStorageStream.cpp \
 #                  TestStrings.cpp \
 #                  TestSynchronization.cpp \
 #                  TestTArray.cpp \
--- a/xpcom/tests/TestDeque.cpp
+++ b/xpcom/tests/TestDeque.cpp
@@ -30,244 +30,126 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "TestHarness.h"
 #include "nsDeque.h"
 #include "nsCRT.h"
 #include <stdio.h>
 
 /**************************************************************
   Now define the token deallocator class...
  **************************************************************/
 class _TestDeque {
 public:
-  int Test();
-private:
-  int OriginalTest();
-  int OriginalFlaw();
-  int AssignFlaw();
-  int TestRemove();
+  _TestDeque() {
+    SelfTest();
+  }
+  int SelfTest();
+  nsresult OriginalTest();
+  nsresult OriginalFlaw();
+  nsresult AssignFlaw();
 };
 static _TestDeque sTestDeque;
 
 class _Dealloc: public nsDequeFunctor {
   virtual void* operator()(void* aObject) {
     return 0;
   }
 };
 
-#define TEST(aCondition, aMsg) \
-  if (!(aCondition)) { fail("TestDeque: "#aMsg); return 1; }
-
-
 /**
  * conduct automated self test for this class
  *
  * @param
  * @return
  */
-int _TestDeque::Test() {
+int _TestDeque::SelfTest() {
   /* the old deque should have failed a bunch of these tests */
   int results=0;
   results+=OriginalTest();
   results+=OriginalFlaw();
   results+=AssignFlaw();
-  results+=TestRemove();
   return results;
 }
 
-int _TestDeque::OriginalTest() {
-  const int size = 200;
-  int ints[size];
+nsresult _TestDeque::OriginalTest() {
+  int ints[200];
+  int count=sizeof(ints)/sizeof(int);
   int i=0;
-  int temp;
+  int* temp;
   nsDeque theDeque(new _Dealloc); //construct a simple one...
  
-  // ints = [0...199]
-  for (i=0;i<size;i++) { //initialize'em
-    ints[i]=i;
+  for (i=0;i<count;i++) { //initialize'em
+    ints[i]=10*(1+i);
   }
-  // queue = [0...69]
   for (i=0;i<70;i++) {
     theDeque.Push(&ints[i]);
-    temp=*(int*)theDeque.Peek();
-    TEST(temp == i, "Verify end after push #1");
-    TEST(theDeque.GetSize() == i + 1, "Verify size after push #1");
   }
-  TEST(theDeque.GetSize() == 70, "Verify overall size after pushes #1");
-  // queue = [0...14]
-  for (i=1;i<=55;i++) {
-    temp=*(int*)theDeque.Pop();
-    TEST(temp == 70-i, "Verify end after pop # 1");
-    TEST(theDeque.GetSize() == 70 - i, "Verify size after pop # 1");
+  for (i=0;i<56;i++) {
+    temp=(int*)theDeque.Pop();
   }
-  TEST(theDeque.GetSize() == 15, "Verify overall size after pops");
-
-  // queue = [0...14,0...54]
   for (i=0;i<55;i++) {
     theDeque.Push(&ints[i]);
-    temp=*(int*)theDeque.Peek();
-    TEST(temp == i, "Verify end after push #2");
-    TEST(theDeque.GetSize() == i + 15 + 1, "Verify size after push # 2");
   }
-  TEST(theDeque.GetSize() == 70, "Verify size after end of all pushes #2");
-
-  // queue = [0...14,0...19]
-  for (i=1;i<=35;i++) {
-    temp=*(int*)theDeque.Pop();
-    TEST(temp == 55-i, "Verify end after pop # 2");
-    TEST(theDeque.GetSize() == 70 - i, "Verify size after pop #2");
+  for (i=0;i<35;i++) {
+    temp=(int*)theDeque.Pop();
   }
-  TEST(theDeque.GetSize() == 35, "Verify overall size after end of all pops #2");
-
-  // queue = [0...14,0...19,0...34]
   for (i=0;i<35;i++) {
     theDeque.Push(&ints[i]);
-    temp = *(int*)theDeque.Peek();
-    TEST(temp == i, "Verify end after push # 3");
-    TEST(theDeque.GetSize() == 35 + 1 + i, "Verify size after push #3");
-  }
-
-  // queue = [0...14,0...19]
-  for (i=0;i<35;i++) {
-    temp=*(int*)theDeque.Pop();
-    TEST(temp == 34 - i, "Verify end after pop # 3");
   }
-
-  // queue = [0...14]
-  for (i=0;i<20;i++) {
-    temp=*(int*)theDeque.Pop();
-    TEST(temp == 19 - i, "Verify end after pop # 4");
+  for (i=0;i<38;i++) {
+    temp=(int*)theDeque.Pop();
   }
-
-  // queue = []
-  for (i=0;i<15;i++) {
-    temp=*(int*)theDeque.Pop();
-    TEST(temp == 14 - i, "Verify end after pop # 5");
-  }
-
-  TEST(theDeque.GetSize() == 0, "Deque should finish empty.");
-
-  return 0;
+  return NS_OK;
 }
 
-int _TestDeque::OriginalFlaw() {
+nsresult _TestDeque::OriginalFlaw() {
   int ints[200];
   int i=0;
-  int temp;
-  nsDeque d(new _Dealloc);
+  int* temp;
+  nsDeque secondDeque(new _Dealloc);
   /**
    * Test 1. Origin near end, semi full, call Peek().
    * you start, mCapacity is 8
    */
   printf("fill array\n");
-  for (i=0; i<30; i++)
-    ints[i]=i;
-
-  for (i=0; i<6; i++) {
-    d.Push(&ints[i]);
-    temp = *(int*)d.Peek();
-    TEST(temp == i, "OriginalFlaw push #1");
-  }
-  TEST(d.GetSize() == 6, "OriginalFlaw size check #1");
-
-  for (i=0; i<4; i++) {
-    temp=*(int*)d.PopFront();
-    TEST(temp == i, "PopFront test");
-  }
-  // d = [4,5]
-  TEST(d.GetSize() == 2, "OriginalFlaw size check #2");
-
-  for (i=0; i<4; i++) {
-    d.Push(&ints[6 + i]);
+  for (i=32; i; --i)
+    ints[i]=i*3+10;
+  printf("push 6 times\n");
+  for (i=0; i<6; i++)
+    secondDeque.Push(&ints[i]);
+  printf("popfront 4 times:\n");
+  for (i=4; i; --i) {
+    temp=(int*)secondDeque.PopFront();
+    printf("%d\t",*temp);
   }
-  // d = [4...9]
-
-  for (i=4; i<=9; i++) {
-    temp=*(int*)d.PopFront();
-    TEST(temp == i, "OriginalFlaw empty check");
-  }
-
-  return 0;
-}
+  printf("push 4 times\n");
+  for (int j=4; j; --j)
+    secondDeque.Push(&ints[++i]);
+  printf("origin should now be about 4\n");
+  printf("and size should be 6\n");
+  printf("origin+size>capacity\n");
 
-int _TestDeque::AssignFlaw() {
-  nsDeque src(new _Dealloc),dest(new _Dealloc);
-  return 0;
-}
+   /*<akk> Oh, I see ... it's a circular buffer */
+  printf("but the old code wasn't behaving accordingly.\n");
 
-static bool VerifyContents(const nsDeque& aDeque, const int* aContents, int aLength) {
-  for (int i=0; i<aLength; ++i) {
-    if (*(int*)aDeque.ObjectAt(i) != aContents[i]) {
-      return false;
-    }
-  }
-  return true;
+   /*right*/
+  printf("we shouldn't crash or anything interesting, ");
+
+  temp=(int*)secondDeque.Peek();
+  printf("peek: %d\n",*temp);
+  return NS_OK;
 }
 
-int _TestDeque::TestRemove() {
-  nsDeque d;
-  const int count = 10;
-  int ints[count];
-  for (int i=0; i<count; i++) {
-    ints[i] = i;
-  }
-
-  for (int i=0; i<6; i++) {
-    d.Push(&ints[i]);
-  }
-  // d = [0...5]
-  d.PopFront();
-  d.PopFront();
-
-  // d = [2,5]
-  for (int i=2; i<=5; i++) {
-    int t = *(int*)d.ObjectAt(i-2);
-    TEST(t == i, "Verify ObjectAt()");
-  }
-
-  d.RemoveObjectAt(1);
-  // d == [2,4,5]
-  static const int t1[] = {2,4,5};
-  TEST(VerifyContents(d, t1, 3), "verify contents t1");
-
-  d.PushFront(&ints[1]);
-  d.PushFront(&ints[0]);
-  d.PushFront(&ints[7]);
-  d.PushFront(&ints[6]);
-  //  d == [6,7,0,1,2,4,5] // (0==mOrigin)
-  static const int t2[] = {6,7,0,1,2,4,5};
-  TEST(VerifyContents(d, t2, 7), "verify contents t2");
-
-  d.RemoveObjectAt(1);
-  //  d == [6,0,1,2,4,5] // (1==mOrigin)
-  static const int t3[] = {6,0,1,2,4,5};
-  TEST(VerifyContents(d, t3, 6), "verify contents t3");
-
-  d.RemoveObjectAt(5);
-  //  d == [6,0,1,2,4] // (1==mOrigin)
-  static const int t4[] = {6,0,1,2,4};
-  TEST(VerifyContents(d, t4, 5), "verify contents t4");
-
-  d.RemoveObjectAt(0);
-  //  d == [0,1,2,4] // (2==mOrigin)
-  static const int t5[] = {0,1,2,4};
-  TEST(VerifyContents(d, t5, 4), "verify contents t5");
-
-
-  return 0;
+nsresult _TestDeque::AssignFlaw() {
+  nsDeque src(new _Dealloc),dest(new _Dealloc);
+  return NS_OK;
 }
 
 int main (void) {
-  ScopedXPCOM xpcom("TestTimers");
-  NS_ENSURE_FALSE(xpcom.failed(), 1);
-
   _TestDeque test;
-  int result = test.Test();
-  TEST(result == 0, "All tests pass");
   return 0;
 }