]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - bytecode/ArrayProfile.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / bytecode / ArrayProfile.h
... / ...
CommitLineData
1/*
2 * Copyright (C) 2012, 2013 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 ArrayProfile_h
27#define ArrayProfile_h
28
29#include "ConcurrentJITLock.h"
30#include "JSArray.h"
31#include "Structure.h"
32#include <wtf/HashMap.h>
33#include <wtf/SegmentedVector.h>
34
35namespace JSC {
36
37class CodeBlock;
38class LLIntOffsetsExtractor;
39
40// This is a bitfield where each bit represents an type of array access that we have seen.
41// There are 16 indexing types that use the lower bits.
42// There are 9 typed array types taking the bits 16 to 25.
43typedef unsigned ArrayModes;
44
45const ArrayModes Int8ArrayMode = 1 << 16;
46const ArrayModes Int16ArrayMode = 1 << 17;
47const ArrayModes Int32ArrayMode = 1 << 18;
48const ArrayModes Uint8ArrayMode = 1 << 19;
49const ArrayModes Uint8ClampedArrayMode = 1 << 20;
50const ArrayModes Uint16ArrayMode = 1 << 21;
51const ArrayModes Uint32ArrayMode = 1 << 22;
52const ArrayModes Float32ArrayMode = 1 << 23;
53const ArrayModes Float64ArrayMode = 1 << 24;
54
55#define asArrayModes(type) \
56 (static_cast<unsigned>(1) << static_cast<unsigned>(type))
57
58#define ALL_TYPED_ARRAY_MODES \
59 (Int8ArrayMode \
60 | Int16ArrayMode \
61 | Int32ArrayMode \
62 | Uint8ArrayMode \
63 | Uint8ClampedArrayMode \
64 | Uint16ArrayMode \
65 | Uint32ArrayMode \
66 | Float32ArrayMode \
67 | Float64ArrayMode \
68 )
69
70#define ALL_NON_ARRAY_ARRAY_MODES \
71 (asArrayModes(NonArray) \
72 | asArrayModes(NonArrayWithInt32) \
73 | asArrayModes(NonArrayWithDouble) \
74 | asArrayModes(NonArrayWithContiguous) \
75 | asArrayModes(NonArrayWithArrayStorage) \
76 | asArrayModes(NonArrayWithSlowPutArrayStorage) \
77 | ALL_TYPED_ARRAY_MODES)
78
79#define ALL_ARRAY_ARRAY_MODES \
80 (asArrayModes(ArrayClass) \
81 | asArrayModes(ArrayWithUndecided) \
82 | asArrayModes(ArrayWithInt32) \
83 | asArrayModes(ArrayWithDouble) \
84 | asArrayModes(ArrayWithContiguous) \
85 | asArrayModes(ArrayWithArrayStorage) \
86 | asArrayModes(ArrayWithSlowPutArrayStorage))
87
88#define ALL_ARRAY_MODES (ALL_NON_ARRAY_ARRAY_MODES | ALL_ARRAY_ARRAY_MODES)
89
90inline ArrayModes arrayModeFromStructure(Structure* structure)
91{
92 switch (structure->classInfo()->typedArrayStorageType) {
93 case TypeInt8:
94 return Int8ArrayMode;
95 case TypeUint8:
96 return Uint8ArrayMode;
97 case TypeUint8Clamped:
98 return Uint8ClampedArrayMode;
99 case TypeInt16:
100 return Int16ArrayMode;
101 case TypeUint16:
102 return Uint16ArrayMode;
103 case TypeInt32:
104 return Int32ArrayMode;
105 case TypeUint32:
106 return Uint32ArrayMode;
107 case TypeFloat32:
108 return Float32ArrayMode;
109 case TypeFloat64:
110 return Float64ArrayMode;
111 case TypeDataView:
112 case NotTypedArray:
113 break;
114 }
115 return asArrayModes(structure->indexingType());
116}
117
118void dumpArrayModes(PrintStream&, ArrayModes);
119MAKE_PRINT_ADAPTOR(ArrayModesDump, ArrayModes, dumpArrayModes);
120
121inline bool mergeArrayModes(ArrayModes& left, ArrayModes right)
122{
123 ArrayModes newModes = left | right;
124 if (newModes == left)
125 return false;
126 left = newModes;
127 return true;
128}
129
130inline bool arrayModesAreClearOrTop(ArrayModes modes)
131{
132 return !modes || modes == ALL_ARRAY_MODES;
133}
134
135// Checks if proven is a subset of expected.
136inline bool arrayModesAlreadyChecked(ArrayModes proven, ArrayModes expected)
137{
138 return (expected | proven) == expected;
139}
140
141inline bool arrayModesInclude(ArrayModes arrayModes, IndexingType shape)
142{
143 return !!(arrayModes & (asArrayModes(NonArray | shape) | asArrayModes(ArrayClass | shape)));
144}
145
146inline bool shouldUseSlowPutArrayStorage(ArrayModes arrayModes)
147{
148 return arrayModesInclude(arrayModes, SlowPutArrayStorageShape);
149}
150
151inline bool shouldUseFastArrayStorage(ArrayModes arrayModes)
152{
153 return arrayModesInclude(arrayModes, ArrayStorageShape);
154}
155
156inline bool shouldUseContiguous(ArrayModes arrayModes)
157{
158 return arrayModesInclude(arrayModes, ContiguousShape);
159}
160
161inline bool shouldUseDouble(ArrayModes arrayModes)
162{
163 return arrayModesInclude(arrayModes, DoubleShape);
164}
165
166inline bool shouldUseInt32(ArrayModes arrayModes)
167{
168 return arrayModesInclude(arrayModes, Int32Shape);
169}
170
171inline bool hasSeenArray(ArrayModes arrayModes)
172{
173 return arrayModes & ALL_ARRAY_ARRAY_MODES;
174}
175
176inline bool hasSeenNonArray(ArrayModes arrayModes)
177{
178 return arrayModes & ALL_NON_ARRAY_ARRAY_MODES;
179}
180
181class ArrayProfile {
182public:
183 ArrayProfile()
184 : m_bytecodeOffset(std::numeric_limits<unsigned>::max())
185 , m_lastSeenStructureID(0)
186 , m_mayStoreToHole(false)
187 , m_outOfBounds(false)
188 , m_mayInterceptIndexedAccesses(false)
189 , m_usesOriginalArrayStructures(true)
190 , m_didPerformFirstRunPruning(false)
191 , m_observedArrayModes(0)
192 {
193 }
194
195 ArrayProfile(unsigned bytecodeOffset)
196 : m_bytecodeOffset(bytecodeOffset)
197 , m_lastSeenStructureID(0)
198 , m_mayStoreToHole(false)
199 , m_outOfBounds(false)
200 , m_mayInterceptIndexedAccesses(false)
201 , m_usesOriginalArrayStructures(true)
202 , m_didPerformFirstRunPruning(false)
203 , m_observedArrayModes(0)
204 {
205 }
206
207 unsigned bytecodeOffset() const { return m_bytecodeOffset; }
208
209 StructureID* addressOfLastSeenStructureID() { return &m_lastSeenStructureID; }
210 ArrayModes* addressOfArrayModes() { return &m_observedArrayModes; }
211 bool* addressOfMayStoreToHole() { return &m_mayStoreToHole; }
212
213 void setOutOfBounds() { m_outOfBounds = true; }
214 bool* addressOfOutOfBounds() { return &m_outOfBounds; }
215
216 void observeStructure(Structure* structure)
217 {
218 m_lastSeenStructureID = structure->id();
219 }
220
221 void computeUpdatedPrediction(const ConcurrentJITLocker&, CodeBlock*);
222 void computeUpdatedPrediction(const ConcurrentJITLocker&, CodeBlock*, Structure* lastSeenStructure);
223
224 ArrayModes observedArrayModes(const ConcurrentJITLocker&) const { return m_observedArrayModes; }
225 bool mayInterceptIndexedAccesses(const ConcurrentJITLocker&) const { return m_mayInterceptIndexedAccesses; }
226
227 bool mayStoreToHole(const ConcurrentJITLocker&) const { return m_mayStoreToHole; }
228 bool outOfBounds(const ConcurrentJITLocker&) const { return m_outOfBounds; }
229
230 bool usesOriginalArrayStructures(const ConcurrentJITLocker&) const { return m_usesOriginalArrayStructures; }
231
232 CString briefDescription(const ConcurrentJITLocker&, CodeBlock*);
233 CString briefDescriptionWithoutUpdating(const ConcurrentJITLocker&);
234
235private:
236 friend class LLIntOffsetsExtractor;
237
238 static Structure* polymorphicStructure() { return static_cast<Structure*>(reinterpret_cast<void*>(1)); }
239
240 unsigned m_bytecodeOffset;
241 StructureID m_lastSeenStructureID;
242 bool m_mayStoreToHole; // This flag may become overloaded to indicate other special cases that were encountered during array access, as it depends on indexing type. Since we currently have basically just one indexing type (two variants of ArrayStorage), this flag for now just means exactly what its name implies.
243 bool m_outOfBounds;
244 bool m_mayInterceptIndexedAccesses : 1;
245 bool m_usesOriginalArrayStructures : 1;
246 bool m_didPerformFirstRunPruning : 1;
247 ArrayModes m_observedArrayModes;
248};
249
250typedef SegmentedVector<ArrayProfile, 4> ArrayProfileVector;
251
252} // namespace JSC
253
254#endif // ArrayProfile_h
255