1 | /* |
2 | * Copyright (C) 2012, 2014 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 | #pragma once |
27 | |
28 | #include "SpeculatedType.h" |
29 | #include <wtf/LockAlgorithm.h> |
30 | #include <wtf/StdLibExtras.h> |
31 | |
32 | namespace JSC { |
33 | |
34 | /* |
35 | Structure of the IndexingType |
36 | ============================= |
37 | Conceptually, the IndexingTypeAndMisc looks like this: |
38 | |
39 | struct IndexingTypeAndMisc { |
40 | struct IndexingModeIncludingHistory { |
41 | struct IndexingMode { |
42 | struct IndexingType { |
43 | uint8_t isArray:1; // bit 0 |
44 | uint8_t shape:3; // bit 1 - 3 |
45 | }; |
46 | uint8_t copyOnWrite:1; // bit 4 |
47 | }; |
48 | uint8_t mayHaveIndexedAccessors:1; // bit 5 |
49 | }; |
50 | uint8_t cellLockBits:2; // bit 6 - 7 |
51 | }; |
52 | |
53 | The shape values (e.g. Int32Shape, ContiguousShape, etc) are an enumeration of |
54 | various shapes (though not necessarily sequential in terms of their values). |
55 | Hence, shape values are not bitwise exclusive with respect to each other. |
56 | |
57 | It's also common to refer to shape + copyOnWrite as IndexingShapeWithWritability. |
58 | */ |
59 | |
60 | typedef uint8_t IndexingType; |
61 | |
62 | // Flags for testing the presence of capabilities. |
63 | static const IndexingType IsArray = 0x01; |
64 | |
65 | // The shape of the indexed property storage. |
66 | static const IndexingType NoIndexingShape = 0x00; |
67 | static const IndexingType UndecidedShape = 0x02; // Only useful for arrays. |
68 | static const IndexingType Int32Shape = 0x04; |
69 | static const IndexingType DoubleShape = 0x06; |
70 | static const IndexingType ContiguousShape = 0x08; |
71 | static const IndexingType ArrayStorageShape = 0x0A; |
72 | static const IndexingType SlowPutArrayStorageShape = 0x0C; |
73 | |
74 | static const IndexingType IndexingShapeMask = 0x0E; |
75 | static const IndexingType IndexingShapeShift = 1; |
76 | static const IndexingType NumberOfIndexingShapes = 7; |
77 | static const IndexingType IndexingTypeMask = IndexingShapeMask | IsArray; |
78 | |
79 | // Whether or not the butterfly is copy on write. If it is copy on write then the butterfly is actually a JSImmutableButterfly. This should only ever be set if there are no named properties. |
80 | static const IndexingType CopyOnWrite = 0x10; |
81 | static const IndexingType IndexingShapeAndWritabilityMask = CopyOnWrite | IndexingShapeMask; |
82 | static const IndexingType IndexingModeMask = CopyOnWrite | IndexingTypeMask; |
83 | static const IndexingType NumberOfCopyOnWriteIndexingModes = 3; // We only have copy on write for int32, double, and contiguous shapes. |
84 | static const IndexingType NumberOfArrayIndexingModes = NumberOfIndexingShapes + NumberOfCopyOnWriteIndexingModes; |
85 | |
86 | // Additional flags for tracking the history of the type. These are usually |
87 | // masked off unless you ask for them directly. |
88 | static const IndexingType MayHaveIndexedAccessors = 0x20; |
89 | |
90 | // The IndexingType field of JSCells is stolen for locks and remembering if the object has been a |
91 | // prototype. |
92 | static const IndexingType IndexingTypeLockIsHeld = 0x40; |
93 | static const IndexingType IndexingTypeLockHasParked = 0x80; |
94 | |
95 | // List of acceptable array types. |
96 | static const IndexingType NonArray = 0x0; |
97 | static const IndexingType NonArrayWithInt32 = Int32Shape; |
98 | static const IndexingType NonArrayWithDouble = DoubleShape; |
99 | static const IndexingType NonArrayWithContiguous = ContiguousShape; |
100 | static const IndexingType NonArrayWithArrayStorage = ArrayStorageShape; |
101 | static const IndexingType NonArrayWithSlowPutArrayStorage = SlowPutArrayStorageShape; |
102 | static const IndexingType ArrayClass = IsArray; // I'd want to call this "Array" but this would lead to disastrous namespace pollution. |
103 | static const IndexingType ArrayWithUndecided = IsArray | UndecidedShape; |
104 | static const IndexingType ArrayWithInt32 = IsArray | Int32Shape; |
105 | static const IndexingType ArrayWithDouble = IsArray | DoubleShape; |
106 | static const IndexingType ArrayWithContiguous = IsArray | ContiguousShape; |
107 | static const IndexingType ArrayWithArrayStorage = IsArray | ArrayStorageShape; |
108 | static const IndexingType ArrayWithSlowPutArrayStorage = IsArray | SlowPutArrayStorageShape; |
109 | static const IndexingType CopyOnWriteArrayWithInt32 = IsArray | Int32Shape | CopyOnWrite; |
110 | static const IndexingType CopyOnWriteArrayWithDouble = IsArray | DoubleShape | CopyOnWrite; |
111 | static const IndexingType CopyOnWriteArrayWithContiguous = IsArray | ContiguousShape | CopyOnWrite; |
112 | |
113 | #define ALL_BLANK_INDEXING_TYPES \ |
114 | NonArray: \ |
115 | case ArrayClass |
116 | |
117 | #define ALL_UNDECIDED_INDEXING_TYPES \ |
118 | ArrayWithUndecided |
119 | |
120 | #define ALL_WRITABLE_INT32_INDEXING_TYPES \ |
121 | NonArrayWithInt32: \ |
122 | case ArrayWithInt32 |
123 | |
124 | #define ALL_INT32_INDEXING_TYPES \ |
125 | ALL_WRITABLE_INT32_INDEXING_TYPES: \ |
126 | case CopyOnWriteArrayWithInt32 |
127 | |
128 | #define ALL_WRITABLE_DOUBLE_INDEXING_TYPES \ |
129 | NonArrayWithDouble: \ |
130 | case ArrayWithDouble \ |
131 | |
132 | #define ALL_DOUBLE_INDEXING_TYPES \ |
133 | ALL_WRITABLE_DOUBLE_INDEXING_TYPES: \ |
134 | case CopyOnWriteArrayWithDouble |
135 | |
136 | #define ALL_WRITABLE_CONTIGUOUS_INDEXING_TYPES \ |
137 | NonArrayWithContiguous: \ |
138 | case ArrayWithContiguous \ |
139 | |
140 | #define ALL_CONTIGUOUS_INDEXING_TYPES \ |
141 | ALL_WRITABLE_CONTIGUOUS_INDEXING_TYPES: \ |
142 | case CopyOnWriteArrayWithContiguous |
143 | |
144 | #define ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES \ |
145 | ArrayWithArrayStorage: \ |
146 | case ArrayWithSlowPutArrayStorage |
147 | |
148 | #define ALL_ARRAY_STORAGE_INDEXING_TYPES \ |
149 | NonArrayWithArrayStorage: \ |
150 | case NonArrayWithSlowPutArrayStorage: \ |
151 | case ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES |
152 | |
153 | inline bool hasIndexedProperties(IndexingType indexingType) |
154 | { |
155 | return (indexingType & IndexingShapeMask) != NoIndexingShape; |
156 | } |
157 | |
158 | inline bool hasUndecided(IndexingType indexingType) |
159 | { |
160 | return (indexingType & IndexingShapeMask) == UndecidedShape; |
161 | } |
162 | |
163 | inline bool hasInt32(IndexingType indexingType) |
164 | { |
165 | return (indexingType & IndexingShapeMask) == Int32Shape; |
166 | } |
167 | |
168 | inline bool hasDouble(IndexingType indexingType) |
169 | { |
170 | return (indexingType & IndexingShapeMask) == DoubleShape; |
171 | } |
172 | |
173 | inline bool hasContiguous(IndexingType indexingType) |
174 | { |
175 | return (indexingType & IndexingShapeMask) == ContiguousShape; |
176 | } |
177 | |
178 | inline bool hasArrayStorage(IndexingType indexingType) |
179 | { |
180 | return (indexingType & IndexingShapeMask) == ArrayStorageShape; |
181 | } |
182 | |
183 | inline bool hasAnyArrayStorage(IndexingType indexingType) |
184 | { |
185 | return static_cast<uint8_t>(indexingType & IndexingShapeMask) >= ArrayStorageShape; |
186 | } |
187 | |
188 | inline bool hasSlowPutArrayStorage(IndexingType indexingType) |
189 | { |
190 | return (indexingType & IndexingShapeMask) == SlowPutArrayStorageShape; |
191 | } |
192 | |
193 | inline bool shouldUseSlowPut(IndexingType indexingType) |
194 | { |
195 | return hasSlowPutArrayStorage(indexingType); |
196 | } |
197 | |
198 | constexpr bool isCopyOnWrite(IndexingType indexingMode) |
199 | { |
200 | return indexingMode & CopyOnWrite; |
201 | } |
202 | |
203 | inline unsigned arrayIndexFromIndexingType(IndexingType indexingType) |
204 | { |
205 | if (isCopyOnWrite(indexingType)) |
206 | return ((indexingType & IndexingShapeMask) - UndecidedShape + SlowPutArrayStorageShape) >> IndexingShapeShift; |
207 | return (indexingType & IndexingShapeMask) >> IndexingShapeShift; |
208 | } |
209 | |
210 | inline IndexingType indexingTypeForValue(JSValue value) |
211 | { |
212 | if (value.isInt32()) |
213 | return Int32Shape; |
214 | |
215 | if (value.isNumber() && value.asNumber() == value.asNumber()) |
216 | return DoubleShape; |
217 | |
218 | return ContiguousShape; |
219 | } |
220 | |
221 | // Return an indexing type that can handle all of the elements of both indexing types. |
222 | IndexingType leastUpperBoundOfIndexingTypes(IndexingType, IndexingType); |
223 | |
224 | IndexingType leastUpperBoundOfIndexingTypeAndType(IndexingType, SpeculatedType); |
225 | IndexingType leastUpperBoundOfIndexingTypeAndValue(IndexingType, JSValue); |
226 | |
227 | void dumpIndexingType(PrintStream&, IndexingType); |
228 | MAKE_PRINT_ADAPTOR(IndexingTypeDump, IndexingType, dumpIndexingType); |
229 | |
230 | static const IndexingType AllWritableArrayTypes = IndexingShapeMask | IsArray; |
231 | static const IndexingType AllArrayTypes = AllWritableArrayTypes | CopyOnWrite; |
232 | static const IndexingType AllWritableArrayTypesAndHistory = AllWritableArrayTypes | MayHaveIndexedAccessors; |
233 | static const IndexingType AllArrayTypesAndHistory = AllArrayTypes | MayHaveIndexedAccessors; |
234 | |
235 | typedef LockAlgorithm<IndexingType, IndexingTypeLockIsHeld, IndexingTypeLockHasParked> IndexingTypeLockAlgorithm; |
236 | |
237 | } // namespace JSC |
238 | |