summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/wtf/RefCountedArray.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/wtf/RefCountedArray.h')
-rw-r--r--Source/JavaScriptCore/wtf/RefCountedArray.h165
1 files changed, 165 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/wtf/RefCountedArray.h b/Source/JavaScriptCore/wtf/RefCountedArray.h
new file mode 100644
index 000000000..2610a69b8
--- /dev/null
+++ b/Source/JavaScriptCore/wtf/RefCountedArray.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RefCountedArray_h
+#define RefCountedArray_h
+
+#include <wtf/FastMalloc.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+// This implements a reference counted array for POD** values, which is optimized for:
+// - An empty array only uses one word.
+// - A copy of the array only uses one word (i.e. assignment means aliasing).
+// - The vector can't grow beyond 2^32-1 elements.
+// - In all other regards this has similar space usage to a Vector.
+//
+// ** This could be modified to support non-POD values quite easily. It just
+// hasn't been, so far, because there has been no need. Moreover, even now,
+// it's used for things that aren't quite POD according to the official
+// defintion, such as JSC::Instruction.
+
+namespace WTF {
+
+template<typename T>
+class RefCountedArray {
+public:
+ RefCountedArray()
+ : m_data(0)
+ {
+ }
+
+ RefCountedArray(const RefCountedArray& other)
+ : m_data(other.m_data)
+ {
+ if (m_data)
+ Header::fromPayload(m_data)->refCount++;
+ }
+
+ explicit RefCountedArray(const Vector<T>& other)
+ {
+ if (other.isEmpty()) {
+ m_data = 0;
+ return;
+ }
+
+ m_data = (static_cast<Header*>(fastMalloc(Header::size() + sizeof(T) * other.size())))->payload();
+ Header::fromPayload(m_data)->refCount = 1;
+ Header::fromPayload(m_data)->length = other.size();
+ ASSERT(Header::fromPayload(m_data)->length == other.size());
+ memcpy(m_data, other.begin(), sizeof(T) * other.size());
+ }
+
+ RefCountedArray& operator=(const RefCountedArray& other)
+ {
+ T* oldData = m_data;
+ m_data = other.m_data;
+ if (m_data)
+ Header::fromPayload(m_data)->refCount++;
+
+ if (!oldData)
+ return *this;
+ if (--Header::fromPayload(oldData)->refCount)
+ return *this;
+ fastFree(Header::fromPayload(oldData));
+ return *this;
+ }
+
+ ~RefCountedArray()
+ {
+ if (!m_data)
+ return;
+ if (--Header::fromPayload(m_data)->refCount)
+ return;
+ fastFree(Header::fromPayload(m_data));
+ }
+
+ size_t size() const
+ {
+ if (!m_data)
+ return 0;
+ return Header::fromPayload(m_data)->length;
+ }
+
+ T* data() { return m_data; }
+ T* begin() { return m_data; }
+ T* end()
+ {
+ if (!m_data)
+ return 0;
+ return m_data + Header::fromPayload(m_data)->length;
+ }
+
+ const T* data() const { return m_data; }
+ const T* begin() const { return m_data; }
+ const T* end() const { return const_cast<RefCountedArray*>(this)->end(); }
+
+ T& at(size_t i)
+ {
+ ASSERT(i < size());
+ return begin()[i];
+ }
+
+ const T& at(size_t i) const
+ {
+ ASSERT(i < size());
+ return begin()[i];
+ }
+
+ T& operator[](size_t i) { return at(i); }
+ const T& operator[](size_t i) const { return at(i); }
+
+private:
+ struct Header {
+ unsigned refCount;
+ unsigned length;
+
+ static size_t size()
+ {
+ return (sizeof(Header) + 7) & ~7;
+ }
+
+ T* payload()
+ {
+ char* result = reinterpret_cast<char*>(this) + size();
+ ASSERT(!(bitwise_cast<uintptr_t>(result) & 7));
+ return reinterpret_cast<T*>(result);
+ }
+
+ static Header* fromPayload(T* payload)
+ {
+ return reinterpret_cast_ptr<Header*>(reinterpret_cast<char*>(payload) - size());
+ }
+ };
+
+ T* m_data;
+};
+
+} // namespace WTF
+
+using WTF::RefCountedArray;
+
+#endif // RefCountedArray_h
+