Bug 1407549 - Avoid array operations that can cause alloc/dalloc in MediaSegment. r?padenot draft
authorAndreas Pehrson <pehrsons@mozilla.com>
Wed, 28 Mar 2018 14:41:11 +0200
changeset 776610 931c56f7113f6d4331062f0e2a5b9fc2b30416da
parent 776609 74f617894a3a76bcd8a90cea4b45f989541e4d00
child 776611 5eafbc17fcf3145a433961a775851c7348a6d92a
push id104925
push userbmo:apehrson@mozilla.com
push dateTue, 03 Apr 2018 13:43:03 +0000
reviewerspadenot
bugs1407549
milestone61.0a1
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
 };