]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/Butterfly.h
JavaScriptCore-1218.33.tar.gz
[apple/javascriptcore.git] / runtime / Butterfly.h
CommitLineData
93a37866
A
1/*
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>
33#include <wtf/Platform.h>
34
35namespace JSC {
36
37class VM;
38class CopyVisitor;
39struct ArrayStorage;
40
41template <typename T> struct ContiguousData {
42 ContiguousData()
43 : m_data(0)
44#if !ASSERT_DISABLED
45 , m_length(0)
46#endif
47 {
48 }
49 ContiguousData(T* data, size_t length)
50 : m_data(data)
51#if !ASSERT_DISABLED
52 , m_length(length)
53#endif
54 {
55 UNUSED_PARAM(length);
56 }
57
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]; }
60
61 T* data() const { return m_data; }
62#if !ASSERT_DISABLED
63 size_t length() const { return m_length; }
64#endif
65
66private:
67 T* m_data;
68#if !ASSERT_DISABLED
69 size_t m_length;
70#endif
71};
72
73typedef ContiguousData<double> ContiguousDoubles;
74typedef ContiguousData<WriteBarrier<Unknown> > ContiguousJSValues;
75
76class Butterfly {
77 WTF_MAKE_NONCOPYABLE(Butterfly);
78private:
79 Butterfly() { } // Not instantiable.
80public:
81
82 static size_t totalSize(size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes)
83 {
84 ASSERT(indexingPayloadSizeInBytes ? hasIndexingHeader : true);
85 ASSERT(sizeof(EncodedJSValue) == sizeof(IndexingHeader));
86 return (preCapacity + propertyCapacity) * sizeof(EncodedJSValue) + (hasIndexingHeader ? sizeof(IndexingHeader) : 0) + indexingPayloadSizeInBytes;
87 }
88
89 static Butterfly* fromBase(void* base, size_t preCapacity, size_t propertyCapacity)
90 {
91 return reinterpret_cast<Butterfly*>(static_cast<EncodedJSValue*>(base) + preCapacity + propertyCapacity + 1);
92 }
93
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)
97 {
98 return reinterpret_cast<Butterfly*>(ptr);
99 }
100
101 char* pointer() { return reinterpret_cast<char*>(this); }
102
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(); }
106
107 static Butterfly* createUninitialized(VM&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes);
108
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);
112
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(); }
117
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
123 template<typename T>
124 T* indexingPayload() { return reinterpret_cast_ptr<T*>(this); }
125 ArrayStorage* arrayStorage() { return indexingPayload<ArrayStorage>(); }
126 ContiguousJSValues contiguousInt32() { return ContiguousJSValues(indexingPayload<WriteBarrier<Unknown> >(), vectorLength()); }
127
128 ContiguousDoubles contiguousDouble() { return ContiguousDoubles(indexingPayload<double>(), vectorLength()); }
129 ContiguousJSValues contiguous() { return ContiguousJSValues(indexingPayload<WriteBarrier<Unknown> >(), vectorLength()); }
130
131 static Butterfly* fromContiguous(WriteBarrier<Unknown>* contiguous)
132 {
133 return reinterpret_cast<Butterfly*>(contiguous);
134 }
135 static Butterfly* fromContiguous(double* contiguous)
136 {
137 return reinterpret_cast<Butterfly*>(contiguous);
138 }
139
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*);
149
150 static Butterfly* createOrGrowArrayRight(Butterfly*, VM&, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes);
151
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);
166};
167
168} // namespace JSC
169
170#endif // Butterfly_h
171