FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
WebKit/Source/JavaScriptCore/runtime/Butterfly.h at main · WebKit/WebKit · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
WebKit
/
WebKit
Public
Notifications
You must be signed in to change notification settings
Fork
2.1k
Star
10.1k
Code
Pull requests
2.6k
Actions
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
WebKit
/
Source
/
JavaScriptCore
/
runtime
/
Butterfly.h
Copy path
More file actions
More file actions
Latest commit
History
History
History
255 lines (208 loc) · 11.8 KB
Breadcrumbs
WebKit
/
Source
/
JavaScriptCore
/
runtime
/
Butterfly.h
Copy path
File metadata and controls
255 lines (208 loc) · 11.8 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/*
* Copyright (C) 2012-2018 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.
*/
#
pragma
once
#
include
<
JavaScriptCore/IndexingHeader.h
>
#
include
<
JavaScriptCore/IndexingType.h
>
#
include
<
JavaScriptCore/PropertyStorage.h
>
#
include
<
wtf/Noncopyable.h
>
WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN
namespace
JSC
{
class
VM
;
class
CopyVisitor
;
class
GCDeferralContext
;
struct
ArrayStorage
;
template
<
typename
T>
struct
ContiguousData
{
ContiguousData
() =
default
;
ContiguousData
(T* data,
size_t
length)
: m_data(data)
#
if
ASSERT_ENABLED
, m_length(length)
#
endif
{
UNUSED_PARAM
(length);
}
struct
Data
{
Data
(T& location, IndexingType indexingMode)
: m_data(location)
#
if
ASSERT_ENABLED
, m_isWritable(!isCopyOnWrite(indexingMode))
#
endif
{
UNUSED_PARAM
(indexingMode);
}
explicit
operator
bool
()
const
{
return
!!m_data.
get
(); }
const
T&
operator
=(
const
T& value)
{
ASSERT
(m_isWritable);
m_data = value;
return
value;
}
operator
const
T&()
const
{
return
m_data; }
//
WriteBarrier forwarded methods.
void
set
(
VM
& vm,
const
JSCell* owner,
const
JSValue& value)
{
ASSERT
(m_isWritable);
m_data.
set
(vm, owner, value);
}
void
setWithoutWriteBarrier
(
const
JSValue& value)
{
ASSERT
(m_isWritable);
m_data.
setWithoutWriteBarrier
(value);
}
void
setStartingValue
(JSValue value)
{
m_data.
setStartingValue
(value);
}
void
clear
()
{
ASSERT
(m_isWritable);
m_data.
clear
();
}
JSValue
get
()
const
{
return
m_data.
get
();
}
T& m_data;
#
if
ASSERT_ENABLED
bool
m_isWritable;
#
endif
};
const
Data
at
(
const
JSCell* owner,
size_t
index)
const
;
Data
at
(
const
JSCell* owner,
size_t
index);
T&
atUnsafe
(
size_t
index) {
ASSERT
(index < m_length);
return
m_data[index]; }
T*
data
()
const
{
return
m_data; }
#
if
ASSERT_ENABLED
size_t
length
()
const
{
return
m_length; }
#
endif
private:
T* m_data {
nullptr
};
#
if
ASSERT_ENABLED
size_t
m_length {
0
};
#
endif
};
using
ContiguousDoubles = ContiguousData<
double
>;
using
ContiguousJSValues = ContiguousData<WriteBarrier<Unknown>>;
using
ConstContiguousDoubles = ContiguousData<
const
double
>;
using
ConstContiguousJSValues = ContiguousData<
const
WriteBarrier<Unknown>>;
class
Butterfly
{
WTF_MAKE_NONCOPYABLE
(Butterfly);
private:
Butterfly
() { }
//
Not instantiable.
public:
static
size_t
totalSize
(
size_t
preCapacity,
size_t
propertyCapacity,
bool
hasIndexingHeader,
size_t
indexingPayloadSizeInBytes)
{
ASSERT
(!indexingPayloadSizeInBytes || hasIndexingHeader);
ASSERT
(
sizeof
(EncodedJSValue) ==
sizeof
(IndexingHeader));
return
(preCapacity + propertyCapacity) *
sizeof
(EncodedJSValue) + (hasIndexingHeader ?
sizeof
(IndexingHeader) :
0
) + indexingPayloadSizeInBytes;
}
static
Butterfly*
fromBase
(
void
* base,
size_t
preCapacity,
size_t
propertyCapacity)
{
return
reinterpret_cast
<Butterfly*>(
static_cast
<EncodedJSValue*>(base) + preCapacity + propertyCapacity +
1
);
}
ALWAYS_INLINE
static
unsigned
availableContiguousVectorLength
(
size_t
propertyCapacity,
unsigned
vectorLength);
static
unsigned
availableContiguousVectorLength
(Structure*,
unsigned
vectorLength);
ALWAYS_INLINE
static
unsigned
optimalContiguousVectorLength
(
size_t
propertyCapacity,
unsigned
vectorLength);
static
unsigned
optimalContiguousVectorLength
(Structure*,
unsigned
vectorLength);
//
This method is here not just because it's handy, but to remind you that
//
the whole point of butterflies is to do evil pointer arithmetic.
static
Butterfly*
fromPointer
(
char
* ptr)
{
return
reinterpret_cast
<Butterfly*>(ptr);
}
char
*
pointer
() {
return
reinterpret_cast
<
char
*>(
this
); }
static
constexpr
ptrdiff_t
offsetOfIndexingHeader
() {
return
IndexingHeader::offsetOfIndexingHeader
(); }
static
constexpr
ptrdiff_t
offsetOfArrayBuffer
() {
return
offsetOfIndexingHeader
() +
IndexingHeader::offsetOfArrayBuffer
(); }
static
constexpr
ptrdiff_t
offsetOfPublicLength
() {
return
offsetOfIndexingHeader
() +
IndexingHeader::offsetOfPublicLength
(); }
static
constexpr
ptrdiff_t
offsetOfVectorLength
() {
return
offsetOfIndexingHeader
() +
IndexingHeader::offsetOfVectorLength
(); }
static
Butterfly*
tryCreateUninitialized
(
VM
&, JSObject* intendedOwner,
size_t
preCapacity,
size_t
propertyCapacity,
bool
hasIndexingHeader,
size_t
indexingPayloadSizeInBytes, GCDeferralContext* =
nullptr
);
static
Butterfly*
createUninitialized
(
VM
&, JSObject* intendedOwner,
size_t
preCapacity,
size_t
propertyCapacity,
bool
hasIndexingHeader,
size_t
indexingPayloadSizeInBytes);
//
FIXME: These return uninitialized indexed storage. Either their names should be updated to reflect this
//
and/or they should take some kind of initialization scope.
static
Butterfly*
tryCreate
(
VM
& vm, JSObject*,
size_t
preCapacity,
size_t
propertyCapacity,
bool
hasIndexingHeader,
const
IndexingHeader& indexingHeader,
size_t
indexingPayloadSizeInBytes);
static
Butterfly*
create
(
VM
&, JSObject* intendedOwner,
size_t
preCapacity,
size_t
propertyCapacity,
bool
hasIndexingHeader,
const
IndexingHeader&,
size_t
indexingPayloadSizeInBytes);
static
Butterfly*
create
(
VM
&, JSObject* intendedOwner, Structure*);
IndexingHeader*
indexingHeader
() {
return
IndexingHeader::from
(
this
); }
const
IndexingHeader*
indexingHeader
()
const
{
return
IndexingHeader::from
(
this
); }
PropertyStorage
propertyStorage
() {
return
indexingHeader
()->
propertyStorage
(); }
ConstPropertyStorage
propertyStorage
()
const
{
return
indexingHeader
()->
propertyStorage
(); }
uint32_t
publicLength
()
const
{
return
indexingHeader
()->
publicLength
(); }
uint32_t
vectorLength
()
const
{
return
indexingHeader
()->
vectorLength
(); }
void
setPublicLength
(
uint32_t
value) {
indexingHeader
()->
setPublicLength
(value); }
void
setVectorLength
(
uint32_t
value) {
indexingHeader
()->
setVectorLength
(value); }
template
<
typename
T>
T*
indexingPayload
() {
return
reinterpret_cast_ptr<T*>(
this
); }
ArrayStorage*
arrayStorage
() {
return
indexingPayload<ArrayStorage>(); }
ContiguousJSValues
contiguousInt32
() {
return
ContiguousJSValues
(indexingPayload<WriteBarrier<Unknown>>(),
vectorLength
()); }
ContiguousDoubles
contiguousDouble
() {
return
ContiguousDoubles
(indexingPayload<
double
>(),
vectorLength
()); }
ContiguousJSValues
contiguous
() {
return
ContiguousJSValues
(indexingPayload<WriteBarrier<Unknown>>(),
vectorLength
()); }
template
<
typename
T>
const
T*
indexingPayload
()
const
{
return
reinterpret_cast_ptr<
const
T*>(
this
); }
const
ArrayStorage*
arrayStorage
()
const
{
return
indexingPayload<ArrayStorage>(); }
ConstContiguousJSValues
contiguousInt32
()
const
{
return
ConstContiguousJSValues
(indexingPayload<WriteBarrier<Unknown>>(),
vectorLength
()); }
ConstContiguousDoubles
contiguousDouble
()
const
{
return
ConstContiguousDoubles
(indexingPayload<
double
>(),
vectorLength
()); }
ConstContiguousJSValues
contiguous
()
const
{
return
ConstContiguousJSValues
(indexingPayload<WriteBarrier<Unknown>>(),
vectorLength
()); }
static
Butterfly*
fromContiguous
(WriteBarrier<Unknown>* contiguous)
{
return
reinterpret_cast
<Butterfly*>(contiguous);
}
static
Butterfly*
fromContiguous
(
double
* contiguous)
{
return
reinterpret_cast
<Butterfly*>(contiguous);
}
static
constexpr
ptrdiff_t
offsetOfPropertyStorage
() {
return
-
static_cast
<
ptrdiff_t
>(
sizeof
(IndexingHeader)); }
constexpr
static
int
indexOfPropertyStorage
()
{
ASSERT
(
sizeof
(IndexingHeader) ==
sizeof
(EncodedJSValue));
return
-
1
;
}
void
*
base
(
size_t
preCapacity,
size_t
propertyCapacity) {
return
propertyStorage
() - propertyCapacity - preCapacity; }
void
*
base
(Structure*);
//
FIXME: This returns uninitialized indexed storage. Either their names should be updated to reflect this
//
and/or they should take some kind of initialization scope.
static
Butterfly*
createOrGrowArrayRight
(
Butterfly*,
VM
&, JSObject* intendedOwner, Structure* oldStructure,
size_t
propertyCapacity,
bool
hadIndexingHeader,
size_t
oldIndexingPayloadSizeInBytes,
size_t
newIndexingPayloadSizeInBytes);
//
The butterfly reallocation methods perform the reallocation itself but do not change any
//
of the meta-data to reflect that the reallocation occurred. Note that this set of
//
methods is not exhaustive and is not intended to encapsulate all possible allocation
//
modes of butterflies - there are code paths that allocate butterflies by calling
//
directly into Heap::tryAllocateStorage.
//
FIXME: These return uninitialized indexed storage. Either their names should be updated to reflect this
//
and/or they should take some kind of initialization scope.
static
Butterfly*
createOrGrowPropertyStorage
(Butterfly*,
VM
&, JSObject* intendedOwner, Structure*,
size_t
oldPropertyCapacity,
size_t
newPropertyCapacity);
Butterfly*
growArrayRight
(
VM
&, JSObject* intendedOwner, Structure* oldStructure,
size_t
propertyCapacity,
bool
hadIndexingHeader,
size_t
oldIndexingPayloadSizeInBytes,
size_t
newIndexingPayloadSizeInBytes);
//
Assumes that preCapacity is zero, and asserts as much.
Butterfly*
growArrayRight
(
VM
&, JSObject* intendedOwner, Structure*,
size_t
newIndexingPayloadSizeInBytes);
Butterfly*
reallocArrayRightIfPossible
(
VM
&, GCDeferralContext&, JSObject* intendedOwner, Structure* oldStructure,
size_t
propertyCapacity,
bool
hadIndexingHeader,
size_t
oldIndexingPayloadSizeInBytes,
size_t
newIndexingPayloadSizeInBytes);
//
Assumes that preCapacity is zero, and asserts as much.
Butterfly*
resizeArray
(
VM
&, JSObject* intendedOwner,
size_t
propertyCapacity,
bool
oldHasIndexingHeader,
size_t
oldIndexingPayloadSizeInBytes,
size_t
newPreCapacity,
bool
newHasIndexingHeader,
size_t
newIndexingPayloadSizeInBytes);
Butterfly*
resizeArray
(
VM
&, JSObject* intendedOwner, Structure*,
size_t
newPreCapacity,
size_t
newIndexingPayloadSizeInBytes);
//
Assumes that you're not changing whether or not the object has an indexing header.
Butterfly*
unshift
(Structure*,
size_t
numberOfSlots);
Butterfly*
shift
(Structure*,
size_t
numberOfSlots);
//
FIXME: This should either not be static or take a span.
ALWAYS_INLINE
static
void
clearRange
(IndexingType, Butterfly*,
unsigned
start,
unsigned
end);
};
}
//
namespace JSC
WTF_ALLOW_UNSAFE_BUFFER_USAGE_END
Back
|
FazBrowse Home
|
New Git URL