Bug 1407549 - Avoid array operations that can cause alloc/dalloc in MediaSegment. r=padenot
authorAndreas Pehrson <pehrsons@mozilla.com>
Wed, 28 Mar 2018 14:41:11 +0200
changeset 411661 a95b0c5c8e9f6add090de2055d508e020805fbe1
parent 411660 a3ce13ac0563e67a69ebcf6562111d805dca262c
child 411662 c9e04ecaaa463586021c69beb388020e52d88d5d
push id33764
push usercsabou@mozilla.com
push dateWed, 04 Apr 2018 17:53:18 +0000
treeherdermozilla-central@90eb45ff0a64 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1407549
milestone61.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 1407549 - Avoid array operations that can cause alloc/dalloc in MediaSegment. r=padenot MozReview-Commit-ID: Fhg9NIltFti
dom/media/MediaSegment.h
--- a/dom/media/MediaSegment.h
+++ b/dom/media/MediaSegment.h
@@ -449,36 +449,50 @@ public:
 protected:
   explicit MediaSegmentBase(Type aType)
     : MediaSegment(aType)
     , mChunks(DEFAULT_SEGMENT_CAPACITY)
   {}
 
   MediaSegmentBase(MediaSegmentBase&& aSegment)
     : MediaSegment(Move(aSegment))
-    , mChunks(Move(aSegment.mChunks))
+    , mChunks(aSegment.mChunks.Capacity())
 #ifdef MOZILLA_INTERNAL_API
     , mTimeStamp(Move(aSegment.mTimeStamp))
 #endif
-  {}
+  {
+    mChunks.SwapElements(aSegment.mChunks);
+    MOZ_ASSERT(mChunks.Capacity() >= DEFAULT_SEGMENT_CAPACITY,
+               "Capacity must be retained in self after swap");
+    MOZ_ASSERT(aSegment.mChunks.Capacity() >= DEFAULT_SEGMENT_CAPACITY,
+               "Capacity must be retained in other after swap");
+  }
 
   /**
    * Appends the contents of aSource to this segment, clearing aSource.
    */
   void AppendFromInternal(MediaSegmentBase<C, Chunk>* aSource)
   {
     MOZ_ASSERT(aSource->mDuration >= 0);
     mDuration += aSource->mDuration;
     aSource->mDuration = 0;
+    size_t offset = 0;
     if (!mChunks.IsEmpty() && !aSource->mChunks.IsEmpty() &&
         mChunks[mChunks.Length() - 1].CanCombineWithFollowing(aSource->mChunks[0])) {
       mChunks[mChunks.Length() - 1].mDuration += aSource->mChunks[0].mDuration;
-      aSource->mChunks.RemoveElementAt(0);
+      offset = 1;
     }
-    mChunks.AppendElements(Move(aSource->mChunks));
+
+    for (; offset < aSource->mChunks.Length(); ++offset) {
+      mChunks.AppendElement(Move(aSource->mChunks[offset]));
+    }
+
+    aSource->mChunks.ClearAndRetainStorage();
+    MOZ_ASSERT(aSource->mChunks.Capacity() >= DEFAULT_SEGMENT_CAPACITY,
+               "Capacity must be retained after appending from aSource");
   }
 
   void AppendSliceInternal(const MediaSegmentBase<C, Chunk>& aSource,
                            StreamTime aStart, StreamTime aEnd)
   {
     MOZ_ASSERT(aStart <= aEnd, "Endpoints inverted");
     NS_ASSERTION(aStart >= 0 && aEnd <= aSource.mDuration, "Slice out of range");
     mDuration += aEnd - aStart;
@@ -521,18 +535,25 @@ protected:
       if (c->GetDuration() > t) {
         c->SliceTo(t, c->GetDuration());
         t = 0;
         break;
       }
       t -= c->GetDuration();
       chunksToRemove = i + 1 - aStartIndex;
     }
-    mChunks.RemoveElementsAt(aStartIndex, chunksToRemove);
+    if (aStartIndex == 0 && chunksToRemove == mChunks.Length()) {
+      mChunks.ClearAndRetainStorage();
+    } else {
+      mChunks.RemoveElementsAt(aStartIndex, chunksToRemove);
+    }
     mDuration -= aDuration - t;
+
+    MOZ_ASSERT(mChunks.Capacity() >= DEFAULT_SEGMENT_CAPACITY,
+               "Capacity must be retained after removing chunks");
   }
 
   void RemoveTrailing(StreamTime aKeep, uint32_t aStartIndex)
   {
     NS_ASSERTION(aKeep >= 0, "Can't keep negative duration");
     StreamTime t = aKeep;
     uint32_t i;
     for (i = aStartIndex; i < mChunks.Length(); ++i) {
@@ -544,16 +565,18 @@ protected:
       t -= c->GetDuration();
       if (t == 0) {
         break;
       }
     }
     if (i+1 < mChunks.Length()) {
       mChunks.RemoveElementsAt(i+1, mChunks.Length() - (i+1));
     }
+    MOZ_ASSERT(mChunks.Capacity() >= DEFAULT_SEGMENT_CAPACITY,
+               "Capacity must be retained after removing chunks");
     // Caller must adjust mDuration
   }
 
   nsTArray<Chunk> mChunks;
 #ifdef MOZILLA_INTERNAL_API
   mozilla::TimeStamp mTimeStamp;
 #endif
 };