2 * Copyright (C) 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include "IndexingHeader.h"
30 #include "PropertyOffset.h"
31 #include "PropertyStorage.h"
32 #include <wtf/Noncopyable.h>
33 #include <wtf/Platform.h>
41 template <typename T
> struct ContiguousData
{
49 ContiguousData(T
* data
, size_t length
)
58 const T
& operator[](size_t index
) const { ASSERT(index
< m_length
); return m_data
[index
]; }
59 T
& operator[](size_t index
) { ASSERT(index
< m_length
); return m_data
[index
]; }
61 T
* data() const { return m_data
; }
63 size_t length() const { return m_length
; }
73 typedef ContiguousData
<double> ContiguousDoubles
;
74 typedef ContiguousData
<WriteBarrier
<Unknown
> > ContiguousJSValues
;
77 WTF_MAKE_NONCOPYABLE(Butterfly
);
79 Butterfly() { } // Not instantiable.
82 static size_t totalSize(size_t preCapacity
, size_t propertyCapacity
, bool hasIndexingHeader
, size_t indexingPayloadSizeInBytes
)
84 ASSERT(indexingPayloadSizeInBytes
? hasIndexingHeader
: true);
85 ASSERT(sizeof(EncodedJSValue
) == sizeof(IndexingHeader
));
86 return (preCapacity
+ propertyCapacity
) * sizeof(EncodedJSValue
) + (hasIndexingHeader
? sizeof(IndexingHeader
) : 0) + indexingPayloadSizeInBytes
;
89 static Butterfly
* fromBase(void* base
, size_t preCapacity
, size_t propertyCapacity
)
91 return reinterpret_cast<Butterfly
*>(static_cast<EncodedJSValue
*>(base
) + preCapacity
+ propertyCapacity
+ 1);
94 // This method is here not just because it's handy, but to remind you that
95 // the whole point of butterflies is to do evil pointer arithmetic.
96 static Butterfly
* fromPointer(char* ptr
)
98 return reinterpret_cast<Butterfly
*>(ptr
);
101 char* pointer() { return reinterpret_cast<char*>(this); }
103 static ptrdiff_t offsetOfIndexingHeader() { return IndexingHeader::offsetOfIndexingHeader(); }
104 static ptrdiff_t offsetOfPublicLength() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfPublicLength(); }
105 static ptrdiff_t offsetOfVectorLength() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfVectorLength(); }
107 static Butterfly
* createUninitialized(VM
&, size_t preCapacity
, size_t propertyCapacity
, bool hasIndexingHeader
, size_t indexingPayloadSizeInBytes
);
109 static Butterfly
* create(VM
&, size_t preCapacity
, size_t propertyCapacity
, bool hasIndexingHeader
, const IndexingHeader
&, size_t indexingPayloadSizeInBytes
);
110 static Butterfly
* create(VM
&, Structure
*);
111 static Butterfly
* createUninitializedDuringCollection(CopyVisitor
&, size_t preCapacity
, size_t propertyCapacity
, bool hasIndexingHeader
, size_t indexingPayloadSizeInBytes
);
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(); }
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
); }
124 T
* indexingPayload() { return reinterpret_cast_ptr
<T
*>(this); }
125 ArrayStorage
* arrayStorage() { return indexingPayload
<ArrayStorage
>(); }
126 ContiguousJSValues
contiguousInt32() { return ContiguousJSValues(indexingPayload
<WriteBarrier
<Unknown
> >(), vectorLength()); }
128 ContiguousDoubles
contiguousDouble() { return ContiguousDoubles(indexingPayload
<double>(), vectorLength()); }
129 ContiguousJSValues
contiguous() { return ContiguousJSValues(indexingPayload
<WriteBarrier
<Unknown
> >(), vectorLength()); }
131 static Butterfly
* fromContiguous(WriteBarrier
<Unknown
>* contiguous
)
133 return reinterpret_cast<Butterfly
*>(contiguous
);
135 static Butterfly
* fromContiguous(double* contiguous
)
137 return reinterpret_cast<Butterfly
*>(contiguous
);
140 static ptrdiff_t offsetOfPropertyStorage() { return -static_cast<ptrdiff_t>(sizeof(IndexingHeader
)); }
141 static int indexOfPropertyStorage()
143 ASSERT(sizeof(IndexingHeader
) == sizeof(EncodedJSValue
));
147 void* base(size_t preCapacity
, size_t propertyCapacity
) { return propertyStorage() - propertyCapacity
- preCapacity
; }
148 void* base(Structure
*);
150 static Butterfly
* createOrGrowArrayRight(Butterfly
*, VM
&, Structure
* oldStructure
, size_t propertyCapacity
, bool hadIndexingHeader
, size_t oldIndexingPayloadSizeInBytes
, size_t newIndexingPayloadSizeInBytes
);
152 // The butterfly reallocation methods perform the reallocation itself but do not change any
153 // of the meta-data to reflect that the reallocation occurred. Note that this set of
154 // methods is not exhaustive and is not intended to encapsulate all possible allocation
155 // modes of butterflies - there are code paths that allocate butterflies by calling
156 // directly into Heap::tryAllocateStorage.
157 Butterfly
* growPropertyStorage(VM
&, size_t preCapacity
, size_t oldPropertyCapacity
, bool hasIndexingHeader
, size_t indexingPayloadSizeInBytes
, size_t newPropertyCapacity
);
158 Butterfly
* growPropertyStorage(VM
&, Structure
* oldStructure
, size_t oldPropertyCapacity
, size_t newPropertyCapacity
);
159 Butterfly
* growPropertyStorage(VM
&, Structure
* oldStructure
, size_t newPropertyCapacity
);
160 Butterfly
* growArrayRight(VM
&, Structure
* oldStructure
, size_t propertyCapacity
, bool hadIndexingHeader
, size_t oldIndexingPayloadSizeInBytes
, size_t newIndexingPayloadSizeInBytes
); // Assumes that preCapacity is zero, and asserts as much.
161 Butterfly
* growArrayRight(VM
&, Structure
*, size_t newIndexingPayloadSizeInBytes
);
162 Butterfly
* resizeArray(VM
&, size_t propertyCapacity
, bool oldHasIndexingHeader
, size_t oldIndexingPayloadSizeInBytes
, size_t newPreCapacity
, bool newHasIndexingHeader
, size_t newIndexingPayloadSizeInBytes
);
163 Butterfly
* resizeArray(VM
&, Structure
*, size_t newPreCapacity
, size_t newIndexingPayloadSizeInBytes
); // Assumes that you're not changing whether or not the object has an indexing header.
164 Butterfly
* unshift(Structure
*, size_t numberOfSlots
);
165 Butterfly
* shift(Structure
*, size_t numberOfSlots
);
170 #endif // Butterfly_h