xpcom/glue/nsVoidArray.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; c-file-offsets: ((substatement-open . 0))  -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #ifndef nsVoidArray_h___
     6 #define nsVoidArray_h___
     8 //#define DEBUG_VOIDARRAY 1
    10 #include "nsDebug.h"
    12 #include "mozilla/MemoryReporting.h"
    13 #include <stdint.h>
    15 // Comparator callback function for sorting array values.
    16 typedef int (* nsVoidArrayComparatorFunc)
    17             (const void* aElement1, const void* aElement2, void* aData);
    19 // Enumerator callback function. Return false to stop
    20 typedef bool (* nsVoidArrayEnumFunc)(void* aElement, void *aData);
    21 typedef bool (* nsVoidArrayEnumFuncConst)(const void* aElement, void *aData);
    23 // SizeOfExcludingThis callback function.
    24 typedef size_t (* nsVoidArraySizeOfElementIncludingThisFunc)(const void* aElement,
    25                                                              mozilla::MallocSizeOf aMallocSizeOf,
    26                                                              void *aData);
    28 /// A basic zero-based array of void*'s that manages its own memory
    29 class NS_COM_GLUE nsVoidArray {
    30 public:
    31   nsVoidArray();
    32   nsVoidArray(int32_t aCount);  // initial count of aCount elements set to nullptr
    33   ~nsVoidArray();
    35   nsVoidArray& operator=(const nsVoidArray& other);
    37   inline int32_t Count() const {
    38     return mImpl ? mImpl->mCount : 0;
    39   }
    40   // If the array grows, the newly created entries will all be null
    41   bool SetCount(int32_t aNewCount);
    42   // returns the max number that can be held without allocating
    43   inline int32_t GetArraySize() const {
    44     return mImpl ? mImpl->mSize : 0;
    45   }
    47   void* FastElementAt(int32_t aIndex) const
    48   {
    49     NS_ASSERTION(0 <= aIndex && aIndex < Count(), "nsVoidArray::FastElementAt: index out of range");
    50     return mImpl->mArray[aIndex];
    51   }
    53   // This both asserts and bounds-checks, because (1) we don't want
    54   // people to write bad code, but (2) we don't want to change it to
    55   // crashing for backwards compatibility.  See bug 96108.
    56   void* ElementAt(int32_t aIndex) const
    57   {
    58     NS_ASSERTION(0 <= aIndex && aIndex < Count(), "nsVoidArray::ElementAt: index out of range");
    59     return SafeElementAt(aIndex);
    60   }
    62   // bounds-checked version
    63   void* SafeElementAt(int32_t aIndex) const
    64   {
    65     if (uint32_t(aIndex) >= uint32_t(Count())) // handles aIndex < 0 too
    66     {
    67       return nullptr;
    68     }
    69     // The bounds check ensures mImpl is non-null.
    70     return mImpl->mArray[aIndex];
    71   }
    73   void* operator[](int32_t aIndex) const { return ElementAt(aIndex); }
    75   int32_t IndexOf(void* aPossibleElement) const;
    77   bool InsertElementAt(void* aElement, int32_t aIndex);
    78   bool InsertElementsAt(const nsVoidArray &other, int32_t aIndex);
    80   bool ReplaceElementAt(void* aElement, int32_t aIndex);
    82   // useful for doing LRU arrays, sorting, etc
    83   bool MoveElement(int32_t aFrom, int32_t aTo);
    85   bool AppendElement(void* aElement) {
    86     return InsertElementAt(aElement, Count());
    87   }
    89   bool AppendElements(nsVoidArray& aElements) {
    90     return InsertElementsAt(aElements, Count());
    91   }
    93   bool RemoveElement(void* aElement);
    94   void RemoveElementsAt(int32_t aIndex, int32_t aCount);
    95   void RemoveElementAt(int32_t aIndex) { return RemoveElementsAt(aIndex,1); }
    97   void   Clear();
    99   bool SizeTo(int32_t aMin);
   100   // Subtly different - Compact() tries to be smart about whether we
   101   // should reallocate the array; SizeTo() always reallocates.
   102   void Compact();
   104   void Sort(nsVoidArrayComparatorFunc aFunc, void* aData);
   106   bool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData);
   107   bool EnumerateForwards(nsVoidArrayEnumFuncConst aFunc, void* aData) const;
   108   bool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData);
   110   // Measures the size of the array's element storage, and if
   111   // |aSizeOfElementIncludingThis| is non-nullptr, measures the size of things
   112   // pointed to by elements.
   113   size_t SizeOfExcludingThis(
   114            nsVoidArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis,
   115            mozilla::MallocSizeOf aMallocSizeOf, void* aData = nullptr) const;
   117 protected:
   118   bool GrowArrayBy(int32_t aGrowBy);
   120   struct Impl {
   121     /**
   122      * The actual array size.
   123      */
   124     int32_t mSize;
   126     /**
   127      * The number of elements in the array
   128      */
   129     int32_t mCount;
   131     /**
   132      * Array data, padded out to the actual size of the array.
   133      */
   134     void*   mArray[1];
   135   };
   137   Impl* mImpl;
   138 #if DEBUG_VOIDARRAY
   139   int32_t mMaxCount;
   140   int32_t mMaxSize;
   141   bool    mIsAuto;
   142 #endif
   144   // bit twiddlers
   145   void SetArray(Impl *newImpl, int32_t aSize, int32_t aCount);
   147 private:
   148   /// Copy constructors are not allowed
   149   nsVoidArray(const nsVoidArray& other);
   150 };
   152 //===================================================================
   153 //  nsSmallVoidArray is not a general-purpose replacement for
   154 //  ns(Auto)VoidArray because there is (some) extra CPU overhead for arrays
   155 //  larger than 1 element, though not a lot.  It is appropriate for
   156 //  space-sensitive uses where sizes of 0 or 1 are moderately common or
   157 //  more, and where we're NOT storing arbitrary integers or arbitrary
   158 //  pointers.
   160 // NOTE: nsSmallVoidArray can ONLY be used for holding items that always
   161 // have the low bit as a 0 - i.e. element & 1 == 0.  This happens to be
   162 // true for allocated and object pointers for all the architectures we run
   163 // on, but conceivably there might be some architectures/compilers for
   164 // which it is NOT true.  We know this works for all existing architectures
   165 // because if it didn't then nsCheapVoidArray would have failed.  Also note
   166 // that we will ASSERT if this assumption is violated in DEBUG builds.
   168 // XXX we're really re-implementing the whole nsVoidArray interface here -
   169 // some form of abstract class would be useful
   171 // I disagree on the abstraction here.  If the point of this class is to be
   172 // as small as possible, and no one will ever derive from it, as I found
   173 // today, there should not be any virtualness to it to avoid the vtable
   174 // ptr overhead.
   176 class NS_COM_GLUE nsSmallVoidArray : private nsVoidArray
   177 {
   178 public:
   179   ~nsSmallVoidArray();
   181   nsSmallVoidArray& operator=(nsSmallVoidArray& other);
   182   void* operator[](int32_t aIndex) const { return ElementAt(aIndex); }
   184   int32_t GetArraySize() const;
   186   int32_t Count() const;
   187   void* FastElementAt(int32_t aIndex) const;
   188   // This both asserts and bounds-checks, because (1) we don't want
   189   // people to write bad code, but (2) we don't want to change it to
   190   // crashing for backwards compatibility.  See bug 96108.
   191   void* ElementAt(int32_t aIndex) const
   192   {
   193     NS_ASSERTION(0 <= aIndex && aIndex < Count(), "nsSmallVoidArray::ElementAt: index out of range");
   194     return SafeElementAt(aIndex);
   195   }
   196   void* SafeElementAt(int32_t aIndex) const {
   197     // let compiler inline; it may be able to remove these checks
   198     if (uint32_t(aIndex) >= uint32_t(Count())) // handles aIndex < 0 too
   199     {
   200       return nullptr;
   201     }
   202     return FastElementAt(aIndex);
   203   }
   204   int32_t IndexOf(void* aPossibleElement) const;
   205   bool InsertElementAt(void* aElement, int32_t aIndex);
   206   bool InsertElementsAt(const nsVoidArray &other, int32_t aIndex);
   207   bool ReplaceElementAt(void* aElement, int32_t aIndex);
   208   bool MoveElement(int32_t aFrom, int32_t aTo);
   209   bool AppendElement(void* aElement);
   210   bool AppendElements(nsVoidArray& aElements) {
   211     return InsertElementsAt(aElements, Count());
   212   }
   213   bool RemoveElement(void* aElement);
   214   void RemoveElementsAt(int32_t aIndex, int32_t aCount);
   215   void RemoveElementAt(int32_t aIndex);
   217   void Clear();
   218   bool SizeTo(int32_t aMin);
   219   void Compact();
   220   void Sort(nsVoidArrayComparatorFunc aFunc, void* aData);
   222   bool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData);
   223   bool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData);
   225 private:
   227   bool HasSingle() const
   228   {
   229     return !!(reinterpret_cast<intptr_t>(mImpl) & 0x1);
   230   }
   231   void* GetSingle() const
   232   {
   233     NS_ASSERTION(HasSingle(), "wrong type");
   234     return reinterpret_cast<void*>
   235                            (reinterpret_cast<intptr_t>(mImpl) & ~0x1);
   236   }
   237   void SetSingle(void *aChild)
   238   {
   239     NS_ASSERTION(HasSingle() || !mImpl, "overwriting array");
   240     mImpl = reinterpret_cast<Impl*>
   241                             (reinterpret_cast<intptr_t>(aChild) | 0x1);
   242   }
   243   bool IsEmpty() const
   244   {
   245     // Note that this isn't the same as Count()==0
   246     return !mImpl;
   247   }
   248   const nsVoidArray* AsArray() const
   249   {
   250     NS_ASSERTION(!HasSingle(), "This is a single");
   251     return this;
   252   }
   253   nsVoidArray* AsArray()
   254   {
   255     NS_ASSERTION(!HasSingle(), "This is a single");
   256     return this;
   257   }
   258   bool EnsureArray();
   259 };
   261 #endif /* nsVoidArray_h___ */

mercurial