bug 378637 part 5 - move Spdy*::EnsureBuffer to nsHttp r=hurley
authorPatrick McManus <mcmanus@ducksong.com>
Tue, 15 Apr 2014 17:06:59 -0400
changeset 183600 1455ff7a4ecf
parent 183599 ec87f45db49e
child 183601 fcf7f73bd7bb
push id26799
push userphilringnalda@gmail.com
push date2014-05-18 00:55 +0000
treeherdermozilla-central@00ef3a7d7aa7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershurley
bugs378637
milestone32.0a1
bug 378637 part 5 - move Spdy*::EnsureBuffer to nsHttp r=hurley
netwerk/protocol/http/Http2Push.cpp
netwerk/protocol/http/Http2Session.cpp
netwerk/protocol/http/Http2Session.h
netwerk/protocol/http/Http2Stream.cpp
netwerk/protocol/http/SpdyPush3.cpp
netwerk/protocol/http/SpdyPush31.cpp
netwerk/protocol/http/SpdySession3.cpp
netwerk/protocol/http/SpdySession3.h
netwerk/protocol/http/SpdySession31.cpp
netwerk/protocol/http/SpdySession31.h
netwerk/protocol/http/SpdyStream3.cpp
netwerk/protocol/http/SpdyStream31.cpp
netwerk/protocol/http/nsHttp.cpp
netwerk/protocol/http/nsHttp.h
--- a/netwerk/protocol/http/Http2Push.cpp
+++ b/netwerk/protocol/http/Http2Push.cpp
@@ -228,20 +228,18 @@ Http2PushTransactionBuffer::ReadSegments
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 nsresult
 Http2PushTransactionBuffer::WriteSegments(nsAHttpSegmentWriter *writer,
                                           uint32_t count, uint32_t *countWritten)
 {
   if ((mBufferedHTTP1Size - mBufferedHTTP1Used) < 20480) {
-    Http2Session::EnsureBuffer(mBufferedHTTP1,
-                                mBufferedHTTP1Size + kDefaultBufferSize,
-                                mBufferedHTTP1Used,
-                                mBufferedHTTP1Size);
+    EnsureBuffer(mBufferedHTTP1,mBufferedHTTP1Size + kDefaultBufferSize,
+                 mBufferedHTTP1Used, mBufferedHTTP1Size);
   }
 
   count = std::min(count, mBufferedHTTP1Size - mBufferedHTTP1Used);
   nsresult rv = writer->OnWriteSegment(mBufferedHTTP1 + mBufferedHTTP1Used,
                                        count, countWritten);
   if (NS_SUCCEEDED(rv)) {
     mBufferedHTTP1Used += *countWritten;
   }
--- a/netwerk/protocol/http/Http2Session.cpp
+++ b/netwerk/protocol/http/Http2Session.cpp
@@ -570,44 +570,16 @@ Http2Session::ResetDownstreamState()
     LOG3(("  SetRecvdFin id=0x%x\n", mInputFrameDataStream->StreamID()));
     mInputFrameDataStream->SetRecvdFin(true);
     MaybeDecrementConcurrent(mInputFrameDataStream);
   }
   mInputFrameBufferUsed = 0;
   mInputFrameDataStream = nullptr;
 }
 
-template<typename T> void
-Http2Session::EnsureBuffer(nsAutoArrayPtr<T> &buf, uint32_t newSize,
-                           uint32_t preserve, uint32_t &objSize)
-{
-  if (objSize >= newSize)
-    return;
-
-  // Leave a little slop on the new allocation - add 2KB to
-  // what we need and then round the result up to a 4KB (page)
-  // boundary.
-
-  objSize = (newSize + 2048 + 4095) & ~4095;
-
-  static_assert(sizeof(T) == 1, "sizeof(T) must be 1");
-  nsAutoArrayPtr<T> tmp(new T[objSize]);
-  memcpy(tmp, buf, preserve);
-  buf = tmp;
-}
-
-// Instantiate supported templates explicitly.
-template void
-Http2Session::EnsureBuffer(nsAutoArrayPtr<char> &buf, uint32_t newSize,
-                                  uint32_t preserve, uint32_t &objSize);
-
-template void
-Http2Session::EnsureBuffer(nsAutoArrayPtr<uint8_t> &buf, uint32_t newSize,
-                                  uint32_t preserve, uint32_t &objSize);
-
 // call with data length (i.e. 0 for 0 data bytes - ignore 8 byte header)
 // dest must have 8 bytes of allocated space
 template<typename charType> void
 Http2Session::CreateFrameHeader(charType dest, uint16_t frameLength,
                                 uint8_t frameType, uint8_t frameFlags,
                                 uint32_t streamID)
 {
   MOZ_ASSERT(frameLength <= kMaxFrameData, "framelength too large");
--- a/netwerk/protocol/http/Http2Session.h
+++ b/netwerk/protocol/http/Http2Session.h
@@ -161,19 +161,16 @@ public:
   static nsresult RecvPushPromise(Http2Session *);
   static nsresult RecvPing(Http2Session *);
   static nsresult RecvGoAway(Http2Session *);
   static nsresult RecvWindowUpdate(Http2Session *);
   static nsresult RecvContinuation(Http2Session *);
   static nsresult RecvAltSvc(Http2Session *);
   static nsresult RecvBlocked(Http2Session *);
 
-  template<typename T>
-  static void EnsureBuffer(nsAutoArrayPtr<T> &,
-                           uint32_t, uint32_t, uint32_t &);
   char       *EnsureOutputBuffer(uint32_t needed);
 
   template<typename charType>
   void CreateFrameHeader(charType dest, uint16_t frameLength,
                          uint8_t frameType, uint8_t frameFlags,
                          uint32_t streamID);
 
   // For writing the data stream to LOG4
--- a/netwerk/protocol/http/Http2Stream.cpp
+++ b/netwerk/protocol/http/Http2Stream.cpp
@@ -416,20 +416,18 @@ Http2Stream::ParseHttpRequestHeaders(con
   }
 
   // note that we could still have 1 frame for 0 bytes of data. that's ok.
 
   uint32_t messageSize = dataLength;
   messageSize += 13; // frame header + priority overhead in HEADERS frame
   messageSize += (numFrames - 1) * 8; // frame header overhead in CONTINUATION frames
 
-  Http2Session::EnsureBuffer(mTxInlineFrame,
-                             dataLength + messageSize,
-                             mTxInlineFrameUsed,
-                             mTxInlineFrameSize);
+  EnsureBuffer(mTxInlineFrame, dataLength + messageSize,
+               mTxInlineFrameUsed, mTxInlineFrameSize);
 
   mTxInlineFrameUsed += messageSize;
   LOG3(("%p Generating %d bytes of HEADERS for stream 0x%X with priority weight %u frames %u\n",
         this, mTxInlineFrameUsed, mStreamID, mPriorityWeight, numFrames));
 
   uint32_t outputOffset = 0;
   uint32_t compressedDataOffset = 0;
   for (uint32_t idx = 0; idx < numFrames; ++idx) {
@@ -541,20 +539,18 @@ Http2Stream::AdjustInitialWindow()
 
     // If the pushed stream has recvd a FIN, there is no reason to update
     // the window
     if (stream->RecvdFin() || stream->RecvdReset())
       return;
   }
 
   uint8_t *packet = mTxInlineFrame.get() + mTxInlineFrameUsed;
-  Http2Session::EnsureBuffer(mTxInlineFrame,
-                             mTxInlineFrameUsed + 12,
-                             mTxInlineFrameUsed,
-                             mTxInlineFrameSize);
+  EnsureBuffer(mTxInlineFrame, mTxInlineFrameUsed + 12,
+               mTxInlineFrameUsed, mTxInlineFrameSize);
   mTxInlineFrameUsed += 12;
 
   mSession->CreateFrameHeader(packet, 4,
                               Http2Session::FRAME_TYPE_WINDOW_UPDATE,
                               0, stream->mStreamID);
 
   MOZ_ASSERT(mClientReceiveWindow <= ASpdySession::kInitialRwin);
   uint32_t bump = ASpdySession::kInitialRwin - mClientReceiveWindow;
@@ -577,20 +573,18 @@ Http2Stream::AdjustPushedPriority()
   MOZ_ASSERT(mPushSource->mStreamID && !(mPushSource->mStreamID & 1));
 
   // If the pushed stream has recvd a FIN, there is no reason to update
   // the window
   if (mPushSource->RecvdFin() || mPushSource->RecvdReset())
     return;
 
   uint8_t *packet = mTxInlineFrame.get() + mTxInlineFrameUsed;
-  Http2Session::EnsureBuffer(mTxInlineFrame,
-                             mTxInlineFrameUsed + 13,
-                             mTxInlineFrameUsed,
-                             mTxInlineFrameSize);
+  EnsureBuffer(mTxInlineFrame, mTxInlineFrameUsed + 13,
+               mTxInlineFrameUsed, mTxInlineFrameSize);
   mTxInlineFrameUsed += 13;
 
   mSession->CreateFrameHeader(packet, 5,
                               Http2Session::FRAME_TYPE_PRIORITY,
                               Http2Session::kFlag_PRIORITY,
                               mPushSource->mStreamID);
 
   mPushSource->SetPriority(mPriority);
--- a/netwerk/protocol/http/SpdyPush3.cpp
+++ b/netwerk/protocol/http/SpdyPush3.cpp
@@ -252,20 +252,18 @@ SpdyPush3TransactionBuffer::ReadSegments
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 nsresult
 SpdyPush3TransactionBuffer::WriteSegments(nsAHttpSegmentWriter *writer,
                                          uint32_t count, uint32_t *countWritten)
 {
   if ((mBufferedHTTP1Size - mBufferedHTTP1Used) < 20480) {
-    SpdySession3::EnsureBuffer(mBufferedHTTP1,
-                               mBufferedHTTP1Size + kDefaultBufferSize,
-                               mBufferedHTTP1Used,
-                               mBufferedHTTP1Size);
+    EnsureBuffer(mBufferedHTTP1, mBufferedHTTP1Size + kDefaultBufferSize,
+                 mBufferedHTTP1Used, mBufferedHTTP1Size);
   }
 
   count = std::min(count, mBufferedHTTP1Size - mBufferedHTTP1Used);
   nsresult rv = writer->OnWriteSegment(mBufferedHTTP1 + mBufferedHTTP1Used,
                                        count, countWritten);
   if (NS_SUCCEEDED(rv)) {
     mBufferedHTTP1Used += *countWritten;
   }
--- a/netwerk/protocol/http/SpdyPush31.cpp
+++ b/netwerk/protocol/http/SpdyPush31.cpp
@@ -250,20 +250,18 @@ SpdyPush31TransactionBuffer::ReadSegment
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 nsresult
 SpdyPush31TransactionBuffer::WriteSegments(nsAHttpSegmentWriter *writer,
                                            uint32_t count, uint32_t *countWritten)
 {
   if ((mBufferedHTTP1Size - mBufferedHTTP1Used) < 20480) {
-    SpdySession31::EnsureBuffer(mBufferedHTTP1,
-                                mBufferedHTTP1Size + kDefaultBufferSize,
-                                mBufferedHTTP1Used,
-                                mBufferedHTTP1Size);
+    EnsureBuffer(mBufferedHTTP1, mBufferedHTTP1Size + kDefaultBufferSize,
+                 mBufferedHTTP1Used, mBufferedHTTP1Size);
   }
 
   count = std::min(count, mBufferedHTTP1Size - mBufferedHTTP1Used);
   nsresult rv = writer->OnWriteSegment(mBufferedHTTP1 + mBufferedHTTP1Used,
                                        count, countWritten);
   if (NS_SUCCEEDED(rv)) {
     mBufferedHTTP1Used += *countWritten;
   }
--- a/netwerk/protocol/http/SpdySession3.cpp
+++ b/netwerk/protocol/http/SpdySession3.cpp
@@ -530,50 +530,16 @@ SpdySession3::ResetDownstreamState()
       mInputFrameDataStream->SetRecvdFin(true);
       DecrementConcurrent(mInputFrameDataStream);
     }
   }
   mInputFrameBufferUsed = 0;
   mInputFrameDataStream = nullptr;
 }
 
-template<typename T> void
-SpdySession3::EnsureBuffer(nsAutoArrayPtr<T> &buf,
-                          uint32_t newSize,
-                          uint32_t preserve,
-                          uint32_t &objSize)
-{
-  if (objSize >= newSize)
-      return;
-
-  // Leave a little slop on the new allocation - add 2KB to
-  // what we need and then round the result up to a 4KB (page)
-  // boundary.
-
-  objSize = (newSize + 2048 + 4095) & ~4095;
-
-  static_assert(sizeof(T) == 1, "sizeof(T) must be 1");
-  nsAutoArrayPtr<T> tmp(new T[objSize]);
-  memcpy(tmp, buf, preserve);
-  buf = tmp;
-}
-
-// Instantiate supported templates explicitly.
-template void
-SpdySession3::EnsureBuffer(nsAutoArrayPtr<char> &buf,
-                           uint32_t newSize,
-                           uint32_t preserve,
-                           uint32_t &objSize);
-
-template void
-SpdySession3::EnsureBuffer(nsAutoArrayPtr<uint8_t> &buf,
-                           uint32_t newSize,
-                           uint32_t preserve,
-                           uint32_t &objSize);
-
 void
 SpdySession3::DecrementConcurrent(SpdyStream3 *aStream)
 {
   uint32_t id = aStream->StreamID();
 
   if (id && !(id & 0x1))
     return; // pushed streams aren't counted in concurrent limit
 
--- a/netwerk/protocol/http/SpdySession3.h
+++ b/netwerk/protocol/http/SpdySession3.h
@@ -153,20 +153,16 @@ public:
   static nsresult HandleSettings(SpdySession3 *);
   static nsresult HandleNoop(SpdySession3 *);
   static nsresult HandlePing(SpdySession3 *);
   static nsresult HandleGoAway(SpdySession3 *);
   static nsresult HandleHeaders(SpdySession3 *);
   static nsresult HandleWindowUpdate(SpdySession3 *);
   static nsresult HandleCredential(SpdySession3 *);
 
-  template<typename T>
-  static void EnsureBuffer(nsAutoArrayPtr<T> &,
-                           uint32_t, uint32_t, uint32_t &);
-
   // For writing the SPDY data stream to LOG4
   static void LogIO(SpdySession3 *, SpdyStream3 *, const char *,
                     const char *, uint32_t);
 
   // an overload of nsAHttpConnection
   void TransactionHasDataToWrite(nsAHttpTransaction *);
 
   // a similar version for SpdyStream3
--- a/netwerk/protocol/http/SpdySession31.cpp
+++ b/netwerk/protocol/http/SpdySession31.cpp
@@ -535,50 +535,16 @@ SpdySession31::ResetDownstreamState()
       mInputFrameDataStream->SetRecvdFin(true);
       DecrementConcurrent(mInputFrameDataStream);
     }
   }
   mInputFrameBufferUsed = 0;
   mInputFrameDataStream = nullptr;
 }
 
-template<typename T> void
-SpdySession31::EnsureBuffer(nsAutoArrayPtr<T> &buf,
-                            uint32_t newSize,
-                            uint32_t preserve,
-                            uint32_t &objSize)
-{
-  if (objSize >= newSize)
-    return;
-
-  // Leave a little slop on the new allocation - add 2KB to
-  // what we need and then round the result up to a 4KB (page)
-  // boundary.
-
-  objSize = (newSize + 2048 + 4095) & ~4095;
-
-  static_assert(sizeof(T) == 1, "sizeof(T) must be 1");
-  nsAutoArrayPtr<T> tmp(new T[objSize]);
-  memcpy(tmp, buf, preserve);
-  buf = tmp;
-}
-
-// Instantiate supported templates explicitly.
-template void
-SpdySession31::EnsureBuffer(nsAutoArrayPtr<char> &buf,
-                            uint32_t newSize,
-                            uint32_t preserve,
-                            uint32_t &objSize);
-
-template void
-SpdySession31::EnsureBuffer(nsAutoArrayPtr<uint8_t> &buf,
-                            uint32_t newSize,
-                            uint32_t preserve,
-                            uint32_t &objSize);
-
 void
 SpdySession31::DecrementConcurrent(SpdyStream31 *aStream)
 {
   uint32_t id = aStream->StreamID();
 
   if (id && !(id & 0x1))
     return; // pushed streams aren't counted in concurrent limit
 
--- a/netwerk/protocol/http/SpdySession31.h
+++ b/netwerk/protocol/http/SpdySession31.h
@@ -152,20 +152,16 @@ public:
   static nsresult HandleSettings(SpdySession31 *);
   static nsresult HandleNoop(SpdySession31 *);
   static nsresult HandlePing(SpdySession31 *);
   static nsresult HandleGoAway(SpdySession31 *);
   static nsresult HandleHeaders(SpdySession31 *);
   static nsresult HandleWindowUpdate(SpdySession31 *);
   static nsresult HandleCredential(SpdySession31 *);
 
-  template<typename T>
-    static void EnsureBuffer(nsAutoArrayPtr<T> &,
-                             uint32_t, uint32_t, uint32_t &);
-
   // For writing the SPDY data stream to LOG4
   static void LogIO(SpdySession31 *, SpdyStream31 *, const char *,
                     const char *, uint32_t);
 
   // an overload of nsAHttpConnection
   void TransactionHasDataToWrite(nsAHttpTransaction *);
 
   // a similar version for SpdyStream31
--- a/netwerk/protocol/http/SpdyStream3.cpp
+++ b/netwerk/protocol/http/SpdyStream3.cpp
@@ -564,20 +564,18 @@ SpdyStream3::AdjustInitialWindow()
     stream->mLocalUnacked = toack64 - 0x7fffffff;
     toack64 = 0x7fffffff;
   }
   uint32_t toack = static_cast<uint32_t>(toack64);
   if (!toack)
     return;
   toack = PR_htonl(toack);
 
-  SpdySession3::EnsureBuffer(mTxInlineFrame,
-                             mTxInlineFrameUsed + 16,
-                             mTxInlineFrameUsed,
-                             mTxInlineFrameSize);
+  EnsureBuffer(mTxInlineFrame, mTxInlineFrameUsed + 16,
+               mTxInlineFrameUsed, mTxInlineFrameSize);
 
   unsigned char *packet = mTxInlineFrame.get() + mTxInlineFrameUsed;
   mTxInlineFrameUsed += 16;
 
   memset(packet, 0, 8);
   packet[0] = SpdySession3::kFlag_Control;
   packet[1] = SpdySession3::kVersion;
   packet[3] = SpdySession3::CONTROL_TYPE_WINDOW_UPDATE;
@@ -1034,20 +1032,18 @@ SpdyStream3::Uncompress(z_stream *contex
       context->avail_out;
 
     // When there is no more output room, but input still available then
     // increase the output space
     if (zlib_rv == Z_OK &&
         !context->avail_out && context->avail_in) {
       LOG3(("SpdyStream3::Uncompress %p Large Headers - so far %d",
             this, mDecompressBufferSize));
-      SpdySession3::EnsureBuffer(mDecompressBuffer,
-                                 mDecompressBufferSize + 4096,
-                                 mDecompressBufferUsed,
-                                 mDecompressBufferSize);
+      EnsureBuffer(mDecompressBuffer, mDecompressBufferSize + 4096,
+                   mDecompressBufferUsed, mDecompressBufferSize);
     }
   }
   while (context->avail_in);
   return NS_OK;
 }
 
 // mDecompressBuffer contains 0 to N uncompressed Name/Value Header blocks
 nsresult
@@ -1258,20 +1254,18 @@ SpdyStream3::ExecuteCompress(uint32_t fl
 {
   // Expect mZlib->avail_in and mZlib->next_in to be set.
   // Append the compressed version of next_in to mTxInlineFrame
 
   do
   {
     uint32_t avail = mTxInlineFrameSize - mTxInlineFrameUsed;
     if (avail < 1) {
-      SpdySession3::EnsureBuffer(mTxInlineFrame,
-                                mTxInlineFrameSize + 2000,
-                                mTxInlineFrameUsed,
-                                mTxInlineFrameSize);
+      EnsureBuffer(mTxInlineFrame, mTxInlineFrameSize + 2000,
+                   mTxInlineFrameUsed, mTxInlineFrameSize);
       avail = mTxInlineFrameSize - mTxInlineFrameUsed;
     }
 
     mZlib->next_out = mTxInlineFrame + mTxInlineFrameUsed;
     mZlib->avail_out = avail;
     deflate(mZlib, flushMode);
     mTxInlineFrameUsed += avail - mZlib->avail_out;
   } while (mZlib->avail_in > 0 || !mZlib->avail_out);
--- a/netwerk/protocol/http/SpdyStream31.cpp
+++ b/netwerk/protocol/http/SpdyStream31.cpp
@@ -570,20 +570,18 @@ SpdyStream31::AdjustInitialWindow()
     stream->mLocalUnacked = toack64 - 0x7fffffff;
     toack64 = 0x7fffffff;
   }
   uint32_t toack = static_cast<uint32_t>(toack64);
   if (!toack)
     return;
   toack = PR_htonl(toack);
 
-  SpdySession31::EnsureBuffer(mTxInlineFrame,
-                              mTxInlineFrameUsed + 16,
-                              mTxInlineFrameUsed,
-                              mTxInlineFrameSize);
+  EnsureBuffer(mTxInlineFrame, mTxInlineFrameUsed + 16,
+               mTxInlineFrameUsed, mTxInlineFrameSize);
 
   unsigned char *packet = mTxInlineFrame.get() + mTxInlineFrameUsed;
   mTxInlineFrameUsed += 16;
 
   memset(packet, 0, 8);
   packet[0] = SpdySession31::kFlag_Control;
   packet[1] = SpdySession31::kVersion;
   packet[3] = SpdySession31::CONTROL_TYPE_WINDOW_UPDATE;
@@ -1050,20 +1048,18 @@ SpdyStream31::Uncompress(z_stream *conte
       context->avail_out;
 
     // When there is no more output room, but input still available then
     // increase the output space
     if (zlib_rv == Z_OK &&
         !context->avail_out && context->avail_in) {
       LOG3(("SpdyStream31::Uncompress %p Large Headers - so far %d",
             this, mDecompressBufferSize));
-      SpdySession31::EnsureBuffer(mDecompressBuffer,
-                                  mDecompressBufferSize + 4096,
-                                  mDecompressBufferUsed,
-                                  mDecompressBufferSize);
+      EnsureBuffer(mDecompressBuffer, mDecompressBufferSize + 4096,
+                   mDecompressBufferUsed, mDecompressBufferSize);
     }
   }
   while (context->avail_in);
   return NS_OK;
 }
 
 // mDecompressBuffer contains 0 to N uncompressed Name/Value Header blocks
 nsresult
@@ -1274,20 +1270,18 @@ SpdyStream31::ExecuteCompress(uint32_t f
 {
   // Expect mZlib->avail_in and mZlib->next_in to be set.
   // Append the compressed version of next_in to mTxInlineFrame
 
   do
   {
     uint32_t avail = mTxInlineFrameSize - mTxInlineFrameUsed;
     if (avail < 1) {
-      SpdySession31::EnsureBuffer(mTxInlineFrame,
-                                  mTxInlineFrameSize + 2000,
-                                  mTxInlineFrameUsed,
-                                  mTxInlineFrameSize);
+      EnsureBuffer(mTxInlineFrame, mTxInlineFrameSize + 2000,
+                   mTxInlineFrameUsed, mTxInlineFrameSize);
       avail = mTxInlineFrameSize - mTxInlineFrameUsed;
     }
 
     mZlib->next_out = mTxInlineFrame + mTxInlineFrameUsed;
     mZlib->avail_out = avail;
     deflate(mZlib, flushMode);
     mTxInlineFrameUsed += avail - mZlib->avail_out;
   } while (mZlib->avail_in > 0 || !mZlib->avail_out);
--- a/netwerk/protocol/http/nsHttp.cpp
+++ b/netwerk/protocol/http/nsHttp.cpp
@@ -290,10 +290,44 @@ nsHttp::ParseInt64(const char *input, co
 }
 
 bool
 nsHttp::IsPermanentRedirect(uint32_t httpStatus)
 {
   return httpStatus == 301 || httpStatus == 308;
 }
 
+
+template<typename T> void
+localEnsureBuffer(nsAutoArrayPtr<T> &buf, uint32_t newSize,
+             uint32_t preserve, uint32_t &objSize)
+{
+  if (objSize >= newSize)
+    return;
+
+  // Leave a little slop on the new allocation - add 2KB to
+  // what we need and then round the result up to a 4KB (page)
+  // boundary.
+
+  objSize = (newSize + 2048 + 4095) & ~4095;
+
+  static_assert(sizeof(T) == 1, "sizeof(T) must be 1");
+  nsAutoArrayPtr<T> tmp(new T[objSize]);
+  if (preserve) {
+    memcpy(tmp, buf, preserve);
+  }
+  buf = tmp;
+}
+
+void EnsureBuffer(nsAutoArrayPtr<char> &buf, uint32_t newSize,
+                  uint32_t preserve, uint32_t &objSize)
+{
+    localEnsureBuffer<char> (buf, newSize, preserve, objSize);
+}
+
+void EnsureBuffer(nsAutoArrayPtr<uint8_t> &buf, uint32_t newSize,
+                  uint32_t preserve, uint32_t &objSize)
+{
+    localEnsureBuffer<uint8_t> (buf, newSize, preserve, objSize);
+}
+
 } // namespace mozilla::net
 } // namespace mozilla
--- a/netwerk/protocol/http/nsHttp.h
+++ b/netwerk/protocol/http/nsHttp.h
@@ -4,16 +4,17 @@
  * 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 nsHttp_h__
 #define nsHttp_h__
 
 #include <stdint.h>
 #include "prtime.h"
+#include "nsAutoPtr.h"
 #include "nsString.h"
 #include "nsError.h"
 
 // http version codes
 #define NS_HTTP_VERSION_UNKNOWN  0
 #define NS_HTTP_VERSION_0_9      9
 #define NS_HTTP_VERSION_1_0     10
 #define NS_HTTP_VERSION_1_1     11
@@ -185,12 +186,17 @@ PRTimeToSeconds(PRTime t_usec)
 #define NowInSeconds() PRTimeToSeconds(PR_Now())
 
 // Round q-value to 2 decimal places; return 2 most significant digits as uint.
 #define QVAL_TO_UINT(q) ((unsigned int) ((q + 0.005) * 100.0))
 
 #define HTTP_LWS " \t"
 #define HTTP_HEADER_VALUE_SEPS HTTP_LWS ","
 
+void EnsureBuffer(nsAutoArrayPtr<char> &buf, uint32_t newSize,
+                  uint32_t preserve, uint32_t &objSize);
+void EnsureBuffer(nsAutoArrayPtr<uint8_t> &buf, uint32_t newSize,
+                  uint32_t preserve, uint32_t &objSize);
+
 } // namespace mozilla::net
 } // namespace mozilla
 
 #endif // nsHttp_h__