blob: 20dccd9b6928d59699dc69fc681648c263eb92d6 [file] [log] [blame]
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +00001/*
2 * Copyright (C) 2012 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 Butterfly_h
27#define Butterfly_h
28
29#include "IndexingHeader.h"
30#include "PropertyOffset.h"
31#include "PropertyStorage.h"
32#include <wtf/Noncopyable.h>
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +000033
34namespace JSC {
35
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000036class VM;
mhahnenberg@apple.com02e39c72012-10-12 19:38:35 +000037class CopyVisitor;
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +000038struct ArrayStorage;
39
oliver@apple.coma0099622013-01-29 21:11:11 +000040template <typename T> struct ContiguousData {
41 ContiguousData()
42 : m_data(0)
43#if !ASSERT_DISABLED
44 , m_length(0)
45#endif
46 {
47 }
48 ContiguousData(T* data, size_t length)
49 : m_data(data)
50#if !ASSERT_DISABLED
51 , m_length(length)
52#endif
53 {
54 UNUSED_PARAM(length);
55 }
56
57 const T& operator[](size_t index) const { ASSERT(index < m_length); return m_data[index]; }
58 T& operator[](size_t index) { ASSERT(index < m_length); return m_data[index]; }
59
60 T* data() const { return m_data; }
61#if !ASSERT_DISABLED
62 size_t length() const { return m_length; }
63#endif
64
65private:
66 T* m_data;
67#if !ASSERT_DISABLED
68 size_t m_length;
69#endif
70};
71
72typedef ContiguousData<double> ContiguousDoubles;
andersca@apple.comc3523f82013-10-18 23:41:24 +000073typedef ContiguousData<WriteBarrier<Unknown>> ContiguousJSValues;
oliver@apple.coma0099622013-01-29 21:11:11 +000074
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +000075class Butterfly {
76 WTF_MAKE_NONCOPYABLE(Butterfly);
77private:
78 Butterfly() { } // Not instantiable.
79public:
80
81 static size_t totalSize(size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes)
82 {
83 ASSERT(indexingPayloadSizeInBytes ? hasIndexingHeader : true);
84 ASSERT(sizeof(EncodedJSValue) == sizeof(IndexingHeader));
85 return (preCapacity + propertyCapacity) * sizeof(EncodedJSValue) + (hasIndexingHeader ? sizeof(IndexingHeader) : 0) + indexingPayloadSizeInBytes;
86 }
87
88 static Butterfly* fromBase(void* base, size_t preCapacity, size_t propertyCapacity)
89 {
90 return reinterpret_cast<Butterfly*>(static_cast<EncodedJSValue*>(base) + preCapacity + propertyCapacity + 1);
91 }
92
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +000093 // This method is here not just because it's handy, but to remind you that
94 // the whole point of butterflies is to do evil pointer arithmetic.
95 static Butterfly* fromPointer(char* ptr)
96 {
97 return reinterpret_cast<Butterfly*>(ptr);
98 }
99
100 char* pointer() { return reinterpret_cast<char*>(this); }
101
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000102 static ptrdiff_t offsetOfIndexingHeader() { return IndexingHeader::offsetOfIndexingHeader(); }
fpizlo@apple.com537a4772013-08-19 23:16:01 +0000103 static ptrdiff_t offsetOfArrayBuffer() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfArrayBuffer(); }
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000104 static ptrdiff_t offsetOfPublicLength() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfPublicLength(); }
105 static ptrdiff_t offsetOfVectorLength() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfVectorLength(); }
106
oliver@apple.coma03796a2013-07-25 04:01:20 +0000107 static Butterfly* createUninitialized(VM&, JSCell* intendedOwner, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes);
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000108
oliver@apple.coma03796a2013-07-25 04:01:20 +0000109 static Butterfly* create(VM&, JSCell* intendedOwner, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader&, size_t indexingPayloadSizeInBytes);
110 static Butterfly* create(VM&, JSCell* intendedOwner, Structure*);
mhahnenberg@apple.com02e39c72012-10-12 19:38:35 +0000111 static Butterfly* createUninitializedDuringCollection(CopyVisitor&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes);
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000112
113 IndexingHeader* indexingHeader() { return IndexingHeader::from(this); }
114 const IndexingHeader* indexingHeader() const { return IndexingHeader::from(this); }
115 PropertyStorage propertyStorage() { return indexingHeader()->propertyStorage(); }
116 ConstPropertyStorage propertyStorage() const { return indexingHeader()->propertyStorage(); }
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +0000117
118 uint32_t publicLength() { return indexingHeader()->publicLength(); }
119 uint32_t vectorLength() { return indexingHeader()->vectorLength(); }
120 void setPublicLength(uint32_t value) { indexingHeader()->setPublicLength(value); }
121 void setVectorLength(uint32_t value) { indexingHeader()->setVectorLength(value); }
122
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000123 template<typename T>
commit-queue@webkit.org94ea8122013-02-25 13:13:43 +0000124 T* indexingPayload() { return reinterpret_cast_ptr<T*>(this); }
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000125 ArrayStorage* arrayStorage() { return indexingPayload<ArrayStorage>(); }
andersca@apple.comc3523f82013-10-18 23:41:24 +0000126 ContiguousJSValues contiguousInt32() { return ContiguousJSValues(indexingPayload<WriteBarrier<Unknown>>(), vectorLength()); }
oliver@apple.coma0099622013-01-29 21:11:11 +0000127
128 ContiguousDoubles contiguousDouble() { return ContiguousDoubles(indexingPayload<double>(), vectorLength()); }
andersca@apple.comc3523f82013-10-18 23:41:24 +0000129 ContiguousJSValues contiguous() { return ContiguousJSValues(indexingPayload<WriteBarrier<Unknown>>(), vectorLength()); }
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +0000130
131 static Butterfly* fromContiguous(WriteBarrier<Unknown>* contiguous)
132 {
133 return reinterpret_cast<Butterfly*>(contiguous);
134 }
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000135 static Butterfly* fromContiguous(double* contiguous)
136 {
137 return reinterpret_cast<Butterfly*>(contiguous);
138 }
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000139
140 static ptrdiff_t offsetOfPropertyStorage() { return -static_cast<ptrdiff_t>(sizeof(IndexingHeader)); }
141 static int indexOfPropertyStorage()
142 {
143 ASSERT(sizeof(IndexingHeader) == sizeof(EncodedJSValue));
144 return -1;
145 }
146
147 void* base(size_t preCapacity, size_t propertyCapacity) { return propertyStorage() - propertyCapacity - preCapacity; }
148 void* base(Structure*);
mhahnenberg@apple.com30408ac2012-12-18 01:03:54 +0000149
oliver@apple.coma03796a2013-07-25 04:01:20 +0000150 static Butterfly* createOrGrowArrayRight(
151 Butterfly*, VM&, JSCell* intendedOwner, Structure* oldStructure,
152 size_t propertyCapacity, bool hadIndexingHeader,
153 size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes);
mhahnenberg@apple.com30408ac2012-12-18 01:03:54 +0000154
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000155 // The butterfly reallocation methods perform the reallocation itself but do not change any
156 // of the meta-data to reflect that the reallocation occurred. Note that this set of
157 // methods is not exhaustive and is not intended to encapsulate all possible allocation
158 // modes of butterflies - there are code paths that allocate butterflies by calling
159 // directly into Heap::tryAllocateStorage.
ggaren@apple.comecd38ec2014-03-25 03:27:46 +0000160 static Butterfly* createOrGrowPropertyStorage(Butterfly*, VM&, JSCell* intendedOwner, Structure*, size_t oldPropertyCapacity, size_t newPropertyCapacity);
oliver@apple.coma03796a2013-07-25 04:01:20 +0000161 Butterfly* growArrayRight(VM&, JSCell* intendedOwner, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes); // Assumes that preCapacity is zero, and asserts as much.
162 Butterfly* growArrayRight(VM&, JSCell* intendedOwner, Structure*, size_t newIndexingPayloadSizeInBytes);
163 Butterfly* resizeArray(VM&, JSCell* intendedOwner, size_t propertyCapacity, bool oldHasIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newPreCapacity, bool newHasIndexingHeader, size_t newIndexingPayloadSizeInBytes);
164 Butterfly* resizeArray(VM&, JSCell* intendedOwner, Structure*, size_t newPreCapacity, size_t newIndexingPayloadSizeInBytes); // Assumes that you're not changing whether or not the object has an indexing header.
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000165 Butterfly* unshift(Structure*, size_t numberOfSlots);
166 Butterfly* shift(Structure*, size_t numberOfSlots);
167};
168
169} // namespace JSC
170
171#endif // Butterfly_h
172