xpcom/string/src/nsSubstring.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifdef DEBUG
     8 #define ENABLE_STRING_STATS
     9 #endif
    11 #include "mozilla/Atomics.h"
    12 #include "mozilla/MemoryReporting.h"
    14 #ifdef ENABLE_STRING_STATS
    15 #include <stdio.h>
    16 #endif
    18 #include <stdlib.h>
    19 #include "nsSubstring.h"
    20 #include "nsString.h"
    21 #include "nsStringBuffer.h"
    22 #include "nsDependentString.h"
    23 #include "nsMemory.h"
    24 #include "prprf.h"
    25 #include "nsStaticAtom.h"
    26 #include "nsCOMPtr.h"
    28 #include "mozilla/IntegerPrintfMacros.h"
    29 #ifdef XP_WIN
    30 #include <windows.h>
    31 #include <process.h>
    32 #define getpid() _getpid()
    33 #define pthread_self() GetCurrentThreadId()
    34 #else
    35 #include <pthread.h>
    36 #include <unistd.h>
    37 #endif
    39 using mozilla::Atomic;
    41 // ---------------------------------------------------------------------------
    43 static const char16_t gNullChar = 0;
    45 char* const nsCharTraits<char>::sEmptyBuffer =
    46   (char*) const_cast<char16_t*>(&gNullChar);
    47 char16_t* const nsCharTraits<char16_t>::sEmptyBuffer =
    48   const_cast<char16_t*>(&gNullChar);
    50 // ---------------------------------------------------------------------------
    52 #ifdef ENABLE_STRING_STATS
    53 class nsStringStats
    54   {
    55     public:
    56       nsStringStats()
    57         : mAllocCount(0), mReallocCount(0), mFreeCount(0), mShareCount(0) {}
    59       ~nsStringStats()
    60         {
    61           // this is a hack to suppress duplicate string stats printing
    62           // in seamonkey as a result of the string code being linked
    63           // into seamonkey and libxpcom! :-(
    64           if (!mAllocCount && !mAdoptCount)
    65             return;
    67           printf("nsStringStats\n");
    68           printf(" => mAllocCount:     % 10d\n", int(mAllocCount));
    69           printf(" => mReallocCount:   % 10d\n", int(mReallocCount));
    70           printf(" => mFreeCount:      % 10d", int(mFreeCount));
    71           if (mAllocCount > mFreeCount)
    72             printf("  --  LEAKED %d !!!\n", mAllocCount - mFreeCount);
    73           else
    74             printf("\n");
    75           printf(" => mShareCount:     % 10d\n", int(mShareCount));
    76           printf(" => mAdoptCount:     % 10d\n", int(mAdoptCount));
    77           printf(" => mAdoptFreeCount: % 10d", int(mAdoptFreeCount));
    78           if (mAdoptCount > mAdoptFreeCount)
    79             printf("  --  LEAKED %d !!!\n", mAdoptCount - mAdoptFreeCount);
    80           else
    81             printf("\n");
    82           printf(" => Process ID: %" PRIuPTR ", Thread ID: %" PRIuPTR "\n",
    83                  uintptr_t(getpid()), uintptr_t(pthread_self()));
    84         }
    86       Atomic<int32_t> mAllocCount;
    87       Atomic<int32_t> mReallocCount;
    88       Atomic<int32_t> mFreeCount;
    89       Atomic<int32_t> mShareCount;
    90       Atomic<int32_t> mAdoptCount;
    91       Atomic<int32_t> mAdoptFreeCount;
    92   };
    93 static nsStringStats gStringStats;
    94 #define STRING_STAT_INCREMENT(_s) (gStringStats.m ## _s ## Count)++
    95 #else
    96 #define STRING_STAT_INCREMENT(_s)
    97 #endif
    99 // ---------------------------------------------------------------------------
   101 inline void
   102 ReleaseData( void* data, uint32_t flags )
   103   {
   104     if (flags & nsSubstring::F_SHARED)
   105       {
   106         nsStringBuffer::FromData(data)->Release();
   107       }
   108     else if (flags & nsSubstring::F_OWNED)
   109       {
   110         nsMemory::Free(data);
   111         STRING_STAT_INCREMENT(AdoptFree);
   112 #ifdef NS_BUILD_REFCNT_LOGGING
   113         // Treat this as destruction of a "StringAdopt" object for leak
   114         // tracking purposes.
   115         NS_LogDtor(data, "StringAdopt", 1);
   116 #endif // NS_BUILD_REFCNT_LOGGING
   117       }
   118     // otherwise, nothing to do.
   119   }
   121 // ---------------------------------------------------------------------------
   123 // XXX or we could make nsStringBuffer be a friend of nsTAString
   125 class nsAStringAccessor : public nsAString
   126   {
   127     private:
   128       nsAStringAccessor(); // NOT IMPLEMENTED
   130     public:
   131       char_type  *data() const   { return mData; }
   132       size_type   length() const { return mLength; }
   133       uint32_t    flags() const  { return mFlags; }
   135       void set(char_type *data, size_type len, uint32_t flags)
   136         {
   137           ReleaseData(mData, mFlags);
   138           mData = data;
   139           mLength = len;
   140           mFlags = flags;
   141         }
   142   };
   144 class nsACStringAccessor : public nsACString
   145   {
   146     private:
   147       nsACStringAccessor(); // NOT IMPLEMENTED
   149     public:
   150       char_type  *data() const   { return mData; }
   151       size_type   length() const { return mLength; }
   152       uint32_t    flags() const  { return mFlags; }
   154       void set(char_type *data, size_type len, uint32_t flags)
   155         {
   156           ReleaseData(mData, mFlags);
   157           mData = data;
   158           mLength = len;
   159           mFlags = flags;
   160         }
   161   };
   163 // ---------------------------------------------------------------------------
   165 void
   166 nsStringBuffer::AddRef()
   167   {
   168     ++mRefCount;
   169     STRING_STAT_INCREMENT(Share);
   170     NS_LOG_ADDREF(this, mRefCount, "nsStringBuffer", sizeof(*this));
   171   }
   173 void
   174 nsStringBuffer::Release()
   175   {
   176     int32_t count = --mRefCount;
   177     NS_LOG_RELEASE(this, count, "nsStringBuffer");
   178     if (count == 0)
   179       {
   180         STRING_STAT_INCREMENT(Free);
   181         free(this); // we were allocated with |malloc|
   182       }
   183   }
   185   /**
   186    * Alloc returns a pointer to a new string header with set capacity.
   187    */
   188 already_AddRefed<nsStringBuffer>
   189 nsStringBuffer::Alloc(size_t size)
   190   {
   191     NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
   192     NS_ASSERTION(sizeof(nsStringBuffer) + size <= size_t(uint32_t(-1)) &&
   193                  sizeof(nsStringBuffer) + size > size,
   194                  "mStorageSize will truncate");
   196     nsStringBuffer *hdr =
   197         (nsStringBuffer *) malloc(sizeof(nsStringBuffer) + size);
   198     if (hdr)
   199       {
   200         STRING_STAT_INCREMENT(Alloc);
   202         hdr->mRefCount = 1;
   203         hdr->mStorageSize = size;
   204         NS_LOG_ADDREF(hdr, 1, "nsStringBuffer", sizeof(*hdr));
   205       }
   206     return dont_AddRef(hdr);
   207   }
   209 nsStringBuffer*
   210 nsStringBuffer::Realloc(nsStringBuffer* hdr, size_t size)
   211   {
   212     STRING_STAT_INCREMENT(Realloc);
   214     NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
   215     NS_ASSERTION(sizeof(nsStringBuffer) + size <= size_t(uint32_t(-1)) &&
   216                  sizeof(nsStringBuffer) + size > size,
   217                  "mStorageSize will truncate");
   219     // no point in trying to save ourselves if we hit this assertion
   220     NS_ASSERTION(!hdr->IsReadonly(), "|Realloc| attempted on readonly string");
   222     // Treat this as a release and addref for refcounting purposes, since we
   223     // just asserted that the refcount is 1.  If we don't do that, refcount
   224     // logging will claim we've leaked all sorts of stuff.
   225     NS_LOG_RELEASE(hdr, 0, "nsStringBuffer");
   227     hdr = (nsStringBuffer*) realloc(hdr, sizeof(nsStringBuffer) + size);
   228     if (hdr) {
   229       NS_LOG_ADDREF(hdr, 1, "nsStringBuffer", sizeof(*hdr));
   230       hdr->mStorageSize = size;
   231     }
   233     return hdr;
   234   }
   236 nsStringBuffer*
   237 nsStringBuffer::FromString(const nsAString& str)
   238   {
   239     const nsAStringAccessor* accessor =
   240         static_cast<const nsAStringAccessor*>(&str);
   242     if (!(accessor->flags() & nsSubstring::F_SHARED))
   243       return nullptr;
   245     return FromData(accessor->data());
   246   }
   248 nsStringBuffer*
   249 nsStringBuffer::FromString(const nsACString& str)
   250   {
   251     const nsACStringAccessor* accessor =
   252         static_cast<const nsACStringAccessor*>(&str);
   254     if (!(accessor->flags() & nsCSubstring::F_SHARED))
   255       return nullptr;
   257     return FromData(accessor->data());
   258   }
   260 void
   261 nsStringBuffer::ToString(uint32_t len, nsAString &str,
   262                          bool aMoveOwnership)
   263   {
   264     char16_t* data = static_cast<char16_t*>(Data());
   266     nsAStringAccessor* accessor = static_cast<nsAStringAccessor*>(&str);
   267     NS_ASSERTION(data[len] == char16_t(0), "data should be null terminated");
   269     // preserve class flags
   270     uint32_t flags = accessor->flags();
   271     flags = (flags & 0xFFFF0000) | nsSubstring::F_SHARED | nsSubstring::F_TERMINATED;
   273     if (!aMoveOwnership) {
   274       AddRef();
   275     }
   276     accessor->set(data, len, flags);
   277   }
   279 void
   280 nsStringBuffer::ToString(uint32_t len, nsACString &str,
   281                          bool aMoveOwnership)
   282   {
   283     char* data = static_cast<char*>(Data());
   285     nsACStringAccessor* accessor = static_cast<nsACStringAccessor*>(&str);
   286     NS_ASSERTION(data[len] == char(0), "data should be null terminated");
   288     // preserve class flags
   289     uint32_t flags = accessor->flags();
   290     flags = (flags & 0xFFFF0000) | nsCSubstring::F_SHARED | nsCSubstring::F_TERMINATED;
   292     if (!aMoveOwnership) {
   293       AddRef();
   294     }
   295     accessor->set(data, len, flags);
   296   }
   298 size_t
   299 nsStringBuffer::SizeOfIncludingThisMustBeUnshared(mozilla::MallocSizeOf aMallocSizeOf) const
   300   {
   301     NS_ASSERTION(!IsReadonly(),
   302                  "shared StringBuffer in SizeOfIncludingThisMustBeUnshared");
   303     return aMallocSizeOf(this);
   304   }
   306 size_t
   307 nsStringBuffer::SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf) const
   308   {
   309     if (!IsReadonly())
   310       {
   311         return SizeOfIncludingThisMustBeUnshared(aMallocSizeOf);
   312       }
   313     return 0;
   314   }
   316 size_t
   317 nsStringBuffer::SizeOfIncludingThisEvenIfShared(mozilla::MallocSizeOf aMallocSizeOf) const
   318   {
   319     return aMallocSizeOf(this);
   320   }
   322 // ---------------------------------------------------------------------------
   325   // define nsSubstring
   326 #include "string-template-def-unichar.h"
   327 #include "nsTSubstring.cpp"
   328 #include "string-template-undef.h"
   330   // define nsCSubstring
   331 #include "string-template-def-char.h"
   332 #include "nsTSubstring.cpp"
   333 #include "string-template-undef.h"
   335 // Check that internal and external strings have the same size.
   336 // See https://bugzilla.mozilla.org/show_bug.cgi?id=430581
   338 #include "prlog.h"
   339 #include "nsXPCOMStrings.h"
   341 static_assert(sizeof(nsStringContainer_base) == sizeof(nsSubstring),
   342               "internal and external strings must have the same size");

mercurial