| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 /* |  | 
| 2  * Copyright (C) 2011 Apple Inc. All rights reserved. |  | 
| 3  * |  | 
| 4  * Redistribution and use in source and binary forms, with or without |  | 
| 5  * modification, are permitted provided that the following conditions |  | 
| 6  * are met: |  | 
| 7  * 1. Redistributions of source code must retain the above copyright |  | 
| 8  *    notice, this list of conditions and the following disclaimer. |  | 
| 9  * 2. Redistributions in binary form must reproduce the above copyright |  | 
| 10  *    notice, this list of conditions and the following disclaimer in the |  | 
| 11  *    documentation and/or other materials provided with the distribution. |  | 
| 12  * |  | 
| 13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |  | 
| 14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |  | 
| 15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |  | 
| 16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR |  | 
| 17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |  | 
| 18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |  | 
| 19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |  | 
| 20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |  | 
| 21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | 
| 22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |  | 
| 23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | 
| 24  */ |  | 
| 25 |  | 
| 26 #ifndef RefCountedArray_h |  | 
| 27 #define RefCountedArray_h |  | 
| 28 |  | 
| 29 #include <wtf/FastMalloc.h> |  | 
| 30 #include <wtf/StdLibExtras.h> |  | 
| 31 #include <wtf/Vector.h> |  | 
| 32 |  | 
| 33 // This implements a reference counted array for POD** values, which is optimize
     d for: |  | 
| 34 // - An empty array only uses one word. |  | 
| 35 // - A copy of the array only uses one word (i.e. assignment means aliasing). |  | 
| 36 // - The vector can't grow beyond 2^32-1 elements. |  | 
| 37 // - In all other regards this has similar space usage to a Vector. |  | 
| 38 // |  | 
| 39 // ** This could be modified to support non-POD values quite easily. It just |  | 
| 40 //    hasn't been, so far, because there has been no need. Moreover, even now, |  | 
| 41 //    it's used for things that aren't quite POD according to the official |  | 
| 42 //    defintion, such as JSC::Instruction. |  | 
| 43 |  | 
| 44 namespace WTF { |  | 
| 45 |  | 
| 46 template<typename T> |  | 
| 47 class RefCountedArray { |  | 
| 48 public: |  | 
| 49     RefCountedArray() |  | 
| 50         : m_data(0) |  | 
| 51     { |  | 
| 52     } |  | 
| 53 |  | 
| 54     RefCountedArray(const RefCountedArray& other) |  | 
| 55         : m_data(other.m_data) |  | 
| 56     { |  | 
| 57         if (m_data) |  | 
| 58             Header::fromPayload(m_data)->refCount++; |  | 
| 59     } |  | 
| 60 |  | 
| 61     explicit RefCountedArray(size_t size) |  | 
| 62     { |  | 
| 63         if (!size) { |  | 
| 64             m_data = 0; |  | 
| 65             return; |  | 
| 66         } |  | 
| 67 |  | 
| 68         m_data = (static_cast<Header*>(fastMalloc(Header::size() + sizeof(T) * s
     ize)))->payload(); |  | 
| 69         Header::fromPayload(m_data)->refCount = 1; |  | 
| 70         Header::fromPayload(m_data)->length = size; |  | 
| 71         ASSERT(Header::fromPayload(m_data)->length == size); |  | 
| 72         VectorTypeOperations<T>::initialize(begin(), end()); |  | 
| 73     } |  | 
| 74 |  | 
| 75     explicit RefCountedArray(const Vector<T>& other) |  | 
| 76     { |  | 
| 77         if (other.isEmpty()) { |  | 
| 78             m_data = 0; |  | 
| 79             return; |  | 
| 80         } |  | 
| 81 |  | 
| 82         m_data = (static_cast<Header*>(fastMalloc(Header::size() + sizeof(T) * o
     ther.size())))->payload(); |  | 
| 83         Header::fromPayload(m_data)->refCount = 1; |  | 
| 84         Header::fromPayload(m_data)->length = other.size(); |  | 
| 85         ASSERT(Header::fromPayload(m_data)->length == other.size()); |  | 
| 86         memcpy(m_data, other.begin(), sizeof(T) * other.size()); |  | 
| 87     } |  | 
| 88 |  | 
| 89     RefCountedArray& operator=(const RefCountedArray& other) |  | 
| 90     { |  | 
| 91         T* oldData = m_data; |  | 
| 92         m_data = other.m_data; |  | 
| 93         if (m_data) |  | 
| 94             Header::fromPayload(m_data)->refCount++; |  | 
| 95 |  | 
| 96         if (!oldData) |  | 
| 97             return *this; |  | 
| 98         if (--Header::fromPayload(oldData)->refCount) |  | 
| 99             return *this; |  | 
| 100         fastFree(Header::fromPayload(oldData)); |  | 
| 101         return *this; |  | 
| 102     } |  | 
| 103 |  | 
| 104     ~RefCountedArray() |  | 
| 105     { |  | 
| 106         if (!m_data) |  | 
| 107             return; |  | 
| 108         if (--Header::fromPayload(m_data)->refCount) |  | 
| 109             return; |  | 
| 110         fastFree(Header::fromPayload(m_data)); |  | 
| 111     } |  | 
| 112 |  | 
| 113     size_t size() const |  | 
| 114     { |  | 
| 115         if (!m_data) |  | 
| 116             return 0; |  | 
| 117         return Header::fromPayload(m_data)->length; |  | 
| 118     } |  | 
| 119 |  | 
| 120     T* data() { return m_data; } |  | 
| 121     T* begin() { return m_data; } |  | 
| 122     T* end() |  | 
| 123     { |  | 
| 124         if (!m_data) |  | 
| 125             return 0; |  | 
| 126         return m_data + Header::fromPayload(m_data)->length; |  | 
| 127     } |  | 
| 128 |  | 
| 129     const T* data() const { return m_data; } |  | 
| 130     const T* begin() const { return m_data; } |  | 
| 131     const T* end() const { return const_cast<RefCountedArray*>(this)->end(); } |  | 
| 132 |  | 
| 133     T& at(size_t i) |  | 
| 134     { |  | 
| 135         ASSERT_WITH_SECURITY_IMPLICATION(i < size()); |  | 
| 136         return begin()[i]; |  | 
| 137     } |  | 
| 138 |  | 
| 139     const T& at(size_t i) const |  | 
| 140     { |  | 
| 141         ASSERT_WITH_SECURITY_IMPLICATION(i < size()); |  | 
| 142         return begin()[i]; |  | 
| 143     } |  | 
| 144 |  | 
| 145     T& operator[](size_t i) { return at(i); } |  | 
| 146     const T& operator[](size_t i) const { return at(i); } |  | 
| 147 |  | 
| 148 private: |  | 
| 149     struct Header { |  | 
| 150         unsigned refCount; |  | 
| 151         unsigned length; |  | 
| 152 |  | 
| 153         static size_t size() |  | 
| 154         { |  | 
| 155             return (sizeof(Header) + 7) & ~7; |  | 
| 156         } |  | 
| 157 |  | 
| 158         T* payload() |  | 
| 159         { |  | 
| 160             char* result = reinterpret_cast<char*>(this) + size(); |  | 
| 161             ASSERT(!(bitwise_cast<uintptr_t>(result) & 7)); |  | 
| 162             return reinterpret_cast_ptr<T*>(result); |  | 
| 163         } |  | 
| 164 |  | 
| 165         static Header* fromPayload(T* payload) |  | 
| 166         { |  | 
| 167             return reinterpret_cast_ptr<Header*>(reinterpret_cast<char*>(payload
     ) - size()); |  | 
| 168         } |  | 
| 169     }; |  | 
| 170 |  | 
| 171     T* m_data; |  | 
| 172 }; |  | 
| 173 |  | 
| 174 } // namespace WTF |  | 
| 175 |  | 
| 176 using WTF::RefCountedArray; |  | 
| 177 |  | 
| 178 #endif // RefCountedArray_h |  | 
| 179 |  | 
| OLD | NEW | 
|---|