Bug 859817 - Make nsStringBuffer::Alloc return already_AddRefed; r=bz
authorAryeh Gregor <ayg@aryeh.name>
Mon, 22 Apr 2013 14:13:22 +0300
changeset 130604 866fa5faea3f447f5f0ce02e21706bb420ee0c85
parent 130603 ff9eed6225d7ae571c71d5b2301161e936c0b118
child 130605 10ff3d7fbf6dd286f060c043ca76e72e54184d65
push id24625
push userryanvm@gmail.com
push dateThu, 02 May 2013 17:09:02 +0000
treeherdermozilla-central@42cf263214c3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs859817
milestone23.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 859817 - Make nsStringBuffer::Alloc return already_AddRefed; r=bz
content/base/src/nsAttrValue.cpp
content/base/src/nsAttrValue.h
content/base/src/nsDocumentEncoder.cpp
layout/style/nsCSSValue.cpp
parser/html/nsHtml5Atom.cpp
xpcom/ds/nsAtomTable.cpp
xpcom/string/public/nsStringBuffer.h
xpcom/string/src/nsSubstring.cpp
xpcom/string/src/nsTSubstring.cpp
--- a/content/base/src/nsAttrValue.cpp
+++ b/content/base/src/nsAttrValue.cpp
@@ -368,17 +368,17 @@ nsAttrValue::SetTo(const nsAttrValue& aO
   // work correctly.
   cont->mType = otherCont->mType;
 }
 
 void
 nsAttrValue::SetTo(const nsAString& aValue)
 {
   ResetIfSet();
-  nsStringBuffer* buf = GetStringBuffer(aValue);
+  nsStringBuffer* buf = GetStringBuffer(aValue).get();
   if (buf) {
     SetPtrValueAndType(buf, eStringBase);
   }
 }
 
 void
 nsAttrValue::SetTo(nsIAtom* aValue)
 {
@@ -1521,17 +1521,17 @@ nsAttrValue::ParsePositiveIntValue(const
   SetIntValueAndType(originalVal, eInteger, strict ? nullptr : &aString);
 
   return true;
 }
 
 void
 nsAttrValue::SetColorValue(nscolor aColor, const nsAString& aString)
 {
-  nsStringBuffer* buf = GetStringBuffer(aString);
+  nsStringBuffer* buf = GetStringBuffer(aString).get();
   if (!buf) {
     return;
   }
 
   MiscContainer* cont = EnsureEmptyMiscContainer();
   cont->mValue.mColor = aColor;
   cont->mType = eColor;
 
@@ -1712,17 +1712,17 @@ nsAttrValue::SetMiscAtomOrString(const n
     MiscContainer* cont = GetMiscContainer();
     if (len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) {
       nsCOMPtr<nsIAtom> atom = NS_NewAtom(*aValue);
       if (atom) {
         cont->mStringBits =
           reinterpret_cast<uintptr_t>(atom.forget().get()) | eAtomBase;
       }
     } else {
-      nsStringBuffer* buf = GetStringBuffer(*aValue);
+      nsStringBuffer* buf = GetStringBuffer(*aValue).get();
       if (buf) {
         cont->mStringBits = reinterpret_cast<uintptr_t>(buf) | eStringBase;
       }
     }
   }
 }
 
 void
@@ -1848,38 +1848,37 @@ nsAttrValue::EnsureEmptyAtomArray()
 
   MiscContainer* cont = EnsureEmptyMiscContainer();
   cont->mValue.mAtomArray = array;
   cont->mType = eAtomArray;
 
   return true;
 }
 
-nsStringBuffer*
+already_AddRefed<nsStringBuffer>
 nsAttrValue::GetStringBuffer(const nsAString& aValue) const
 {
   uint32_t len = aValue.Length();
   if (!len) {
     return nullptr;
   }
 
-  nsStringBuffer* buf = nsStringBuffer::FromString(aValue);
+  nsRefPtr<nsStringBuffer> buf = nsStringBuffer::FromString(aValue);
   if (buf && (buf->StorageSize()/sizeof(PRUnichar) - 1) == len) {
-    buf->AddRef();
-    return buf;
+    return buf.forget();
   }
 
   buf = nsStringBuffer::Alloc((len + 1) * sizeof(PRUnichar));
   if (!buf) {
     return nullptr;
   }
   PRUnichar *data = static_cast<PRUnichar*>(buf->Data());
   CopyUnicodeTo(aValue, 0, data, len);
   data[len] = PRUnichar(0);
-  return buf;
+  return buf.forget();
 }
 
 int32_t
 nsAttrValue::StringToInteger(const nsAString& aValue, bool* aStrict,
                              nsresult* aErrorCode,
                              bool aCanBePercent,
                              bool* aIsPercent) const
 {
--- a/content/base/src/nsAttrValue.h
+++ b/content/base/src/nsAttrValue.h
@@ -410,17 +410,18 @@ private:
 
   // Clears the current MiscContainer.  This will return null if there is no
   // existing container.
   MiscContainer* ClearMiscContainer();
   // Like ClearMiscContainer, except allocates a new container if one does not
   // exist already.
   MiscContainer* EnsureEmptyMiscContainer();
   bool EnsureEmptyAtomArray();
-  nsStringBuffer* GetStringBuffer(const nsAString& aValue) const;
+  already_AddRefed<nsStringBuffer>
+    GetStringBuffer(const nsAString& aValue) const;
   // aStrict is set true if stringifying the return value equals with
   // aValue.
   int32_t StringToInteger(const nsAString& aValue,
                           bool* aStrict,
                           nsresult* aErrorCode,
                           bool aCanBePercent = false,
                           bool* aIsPercent = nullptr) const;
   // Given an enum table and a particular entry in that table, return
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -1003,17 +1003,17 @@ nsDocumentEncoder::EncodeToString(nsAStr
   if (!mDocument)
     return NS_ERROR_NOT_INITIALIZED;
 
   aOutputString.Truncate();
 
   nsString output;
   static const size_t bufferSize = 2048;
   if (!mCachedBuffer) {
-    mCachedBuffer = nsStringBuffer::Alloc(bufferSize);
+    mCachedBuffer = nsStringBuffer::Alloc(bufferSize).get();
   }
   NS_ASSERTION(!mCachedBuffer->IsReadonly(),
                "DocumentEncoder shouldn't keep reference to non-readonly buffer!");
   static_cast<PRUnichar*>(mCachedBuffer->Data())[0] = PRUnichar(0);
   mCachedBuffer->ToString(0, output, true);
   // output owns the buffer now!
   mCachedBuffer = nullptr;
   
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -619,36 +619,35 @@ nsCSSValue::EqualsFunction(nsCSSKeyword 
     static_cast<nsCSSKeyword>(func->Item(0).GetIntValue());
   return thisFunctionId == aFunctionId;
 }
 
 // static
 already_AddRefed<nsStringBuffer>
 nsCSSValue::BufferFromString(const nsString& aValue)
 {
-  nsStringBuffer* buffer = nsStringBuffer::FromString(aValue);
+  nsRefPtr<nsStringBuffer> buffer = nsStringBuffer::FromString(aValue);
   if (buffer) {
-    buffer->AddRef();
-    return buffer;
+    return buffer.forget();
   }
 
   nsString::size_type length = aValue.Length();
 
   // NOTE: Alloc prouduces a new, already-addref'd (refcnt = 1) buffer.
   // NOTE: String buffer allocation is currently fallible.
   buffer = nsStringBuffer::Alloc((length + 1) * sizeof(PRUnichar));
   if (MOZ_UNLIKELY(!buffer)) {
     NS_RUNTIMEABORT("out of memory");
   }
 
   PRUnichar* data = static_cast<PRUnichar*>(buffer->Data());
   nsCharTraits<PRUnichar>::copy(data, aValue.get(), length);
   // Null-terminate.
   data[length] = 0;
-  return buffer;
+  return buffer.forget();
 }
 
 namespace {
 
 struct CSSValueSerializeCalcOps {
   CSSValueSerializeCalcOps(nsCSSProperty aProperty, nsAString& aResult)
     : mProperty(aProperty),
       mResult(aResult)
--- a/parser/html/nsHtml5Atom.cpp
+++ b/parser/html/nsHtml5Atom.cpp
@@ -3,32 +3,33 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsHtml5Atom.h"
 #include "nsAutoPtr.h"
 
 nsHtml5Atom::nsHtml5Atom(const nsAString& aString)
 {
   mLength = aString.Length();
-  nsStringBuffer* buf = nsStringBuffer::FromString(aString);
+  nsRefPtr<nsStringBuffer> buf = nsStringBuffer::FromString(aString);
   if (buf) {
-    buf->AddRef();
     mString = static_cast<PRUnichar*>(buf->Data());
-  }
-  else {
+  } else {
     buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(PRUnichar));
     mString = static_cast<PRUnichar*>(buf->Data());
     CopyUnicodeTo(aString, 0, mString, mLength);
     mString[mLength] = PRUnichar(0);
   }
 
   NS_ASSERTION(mString[mLength] == PRUnichar(0), "null terminated");
   NS_ASSERTION(buf && buf->StorageSize() >= (mLength+1) * sizeof(PRUnichar),
                "enough storage");
   NS_ASSERTION(Equals(aString), "correct data");
+
+  // Take ownership of buffer
+  buf.forget();
 }
 
 nsHtml5Atom::~nsHtml5Atom()
 {
   nsStringBuffer::FromData(mString)->Release();
 }
 
 NS_IMETHODIMP_(nsrefcnt)
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -294,36 +294,37 @@ NS_PurgeAtomTable()
     gAtomTable.entryCount = 0;
     gAtomTable.ops = nullptr;
   }
 }
 
 AtomImpl::AtomImpl(const nsAString& aString, PLDHashNumber aKeyHash)
 {
   mLength = aString.Length();
-  nsStringBuffer* buf = nsStringBuffer::FromString(aString);
+  nsRefPtr<nsStringBuffer> buf = nsStringBuffer::FromString(aString);
   if (buf) {
-    buf->AddRef();
     mString = static_cast<PRUnichar*>(buf->Data());
-  }
-  else {
+  } else {
     buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(PRUnichar));
     mString = static_cast<PRUnichar*>(buf->Data());
     CopyUnicodeTo(aString, 0, mString, mLength);
     mString[mLength] = PRUnichar(0);
   }
 
   // The low bit of aKeyHash is generally useless, so shift it out
   MOZ_ASSERT(sizeof(mHash) == sizeof(PLDHashNumber));
   mHash = aKeyHash >> 1;
 
   NS_ASSERTION(mString[mLength] == PRUnichar(0), "null terminated");
   NS_ASSERTION(buf && buf->StorageSize() >= (mLength+1) * sizeof(PRUnichar),
                "enough storage");
   NS_ASSERTION(Equals(aString), "correct data");
+
+  // Take ownership of buffer
+  buf.forget();
 }
 
 AtomImpl::AtomImpl(nsStringBuffer* aStringBuffer, uint32_t aLength,
                    PLDHashNumber aKeyHash)
 {
   mLength = aLength;
   mString = static_cast<PRUnichar*>(aStringBuffer->Data());
   // Technically we could currently avoid doing this addref by instead making
--- a/xpcom/string/public/nsStringBuffer.h
+++ b/xpcom/string/public/nsStringBuffer.h
@@ -2,16 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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 nsStringBuffer_h__
 #define nsStringBuffer_h__
 
+template<class T> struct already_AddRefed;
 
 /**
  * This structure precedes the string buffers "we" allocate.  It may be the
  * case that nsTAString::mData does not point to one of these special
  * buffers.  The mFlags member variable distinguishes the buffer type.
  *
  * When this header is in use, it enables reference counting, and capacity
  * tracking.  NOTE: A string buffer can be modified only if its reference
@@ -36,17 +37,17 @@ class nsStringBuffer
        * buffer by calling the Data method to fetch the raw data pointer.  Care
        * must be taken to properly null terminate the character array.  The
        * storage size can be greater than the length of the actual string
        * (i.e., it is not required that the null terminator appear in the last
        * storage unit of the string buffer's data).
        *
        * @return new string buffer or null if out of memory.
        */
-      static nsStringBuffer* Alloc(size_t storageSize);
+      static already_AddRefed<nsStringBuffer> Alloc(size_t storageSize);
 
       /**
        * Resizes the given string buffer to the specified storage size.  This
        * method must not be called on a readonly string buffer.  Use this API
        * carefully!!
        *
        * This method behaves like the ANSI-C realloc function.  (i.e., If the
        * allocation fails, null will be returned and the given string buffer
--- a/xpcom/string/src/nsSubstring.cpp
+++ b/xpcom/string/src/nsSubstring.cpp
@@ -16,16 +16,17 @@
 #include "nsSubstring.h"
 #include "nsString.h"
 #include "nsStringBuffer.h"
 #include "nsDependentString.h"
 #include "nsMemory.h"
 #include "pratom.h"
 #include "prprf.h"
 #include "nsStaticAtom.h"
+#include "nsCOMPtr.h"
 
 // ---------------------------------------------------------------------------
 
 static PRUnichar gNullChar = 0;
 
 char*      nsCharTraits<char>     ::sEmptyBuffer = (char*) &gNullChar;
 PRUnichar* nsCharTraits<PRUnichar>::sEmptyBuffer =         &gNullChar;
 
@@ -160,17 +161,17 @@ nsStringBuffer::Release()
         STRING_STAT_INCREMENT(Free);
         free(this); // we were allocated with |malloc|
       }
   }
 
   /**
    * Alloc returns a pointer to a new string header with set capacity.
    */
-nsStringBuffer*
+already_AddRefed<nsStringBuffer>
 nsStringBuffer::Alloc(size_t size)
   {
     NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
     NS_ASSERTION(sizeof(nsStringBuffer) + size <= size_t(uint32_t(-1)) &&
                  sizeof(nsStringBuffer) + size > size,
                  "mStorageSize will truncate");
 
     nsStringBuffer *hdr =
@@ -178,17 +179,17 @@ nsStringBuffer::Alloc(size_t size)
     if (hdr)
       {
         STRING_STAT_INCREMENT(Alloc);
 
         hdr->mRefCount = 1;
         hdr->mStorageSize = size;
         NS_LOG_ADDREF(hdr, 1, "nsStringBuffer", sizeof(*hdr));
       }
-    return hdr;
+    return dont_AddRef(hdr);
   }
 
 nsStringBuffer*
 nsStringBuffer::Realloc(nsStringBuffer* hdr, size_t size)
   {
     STRING_STAT_INCREMENT(Realloc);
 
     NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
--- a/xpcom/string/src/nsTSubstring.cpp
+++ b/xpcom/string/src/nsTSubstring.cpp
@@ -122,17 +122,17 @@ nsTSubstring_CharT::MutatePrep( size_typ
         newDataFlags = F_TERMINATED | F_FIXED;
       }
     else
       {
         // if we reach here then, we must allocate a new buffer.  we cannot
         // make use of our F_OWNED or F_FIXED buffers because they are not
         // large enough.
 
-        nsStringBuffer* newHdr = nsStringBuffer::Alloc(storageSize);
+        nsStringBuffer* newHdr = nsStringBuffer::Alloc(storageSize).get();
         if (!newHdr)
           return false; // we are still in a consistent state
 
         newData = (char_type*) newHdr->Data();
         newDataFlags = F_TERMINATED | F_SHARED;
       }
 
     // save old data and flags