]> git.saurik.com Git - apple/javascriptcore.git/blame - bytecode/ArrayProfile.h
JavaScriptCore-1218.tar.gz
[apple/javascriptcore.git] / bytecode / ArrayProfile.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 ArrayProfile_h
27#define ArrayProfile_h
28
29#include "JSArray.h"
30#include "Structure.h"
31#include <wtf/HashMap.h>
32#include <wtf/SegmentedVector.h>
33
34namespace JSC {
35
36class CodeBlock;
37class LLIntOffsetsExtractor;
38
39// This is a bitfield where each bit represents an IndexingType that we have seen.
40// There are 32 indexing types, so an unsigned is enough.
41typedef unsigned ArrayModes;
42
43#define asArrayModes(type) \
44 (static_cast<unsigned>(1) << static_cast<unsigned>(type))
45
46#define ALL_NON_ARRAY_ARRAY_MODES \
47 (asArrayModes(NonArray) \
48 | asArrayModes(NonArrayWithInt32) \
49 | asArrayModes(NonArrayWithDouble) \
50 | asArrayModes(NonArrayWithContiguous) \
51 | asArrayModes(NonArrayWithArrayStorage) \
52 | asArrayModes(NonArrayWithSlowPutArrayStorage))
53
54#define ALL_ARRAY_ARRAY_MODES \
55 (asArrayModes(ArrayClass) \
56 | asArrayModes(ArrayWithUndecided) \
57 | asArrayModes(ArrayWithInt32) \
58 | asArrayModes(ArrayWithDouble) \
59 | asArrayModes(ArrayWithContiguous) \
60 | asArrayModes(ArrayWithArrayStorage) \
61 | asArrayModes(ArrayWithSlowPutArrayStorage))
62
63#define ALL_ARRAY_MODES (ALL_NON_ARRAY_ARRAY_MODES | ALL_ARRAY_ARRAY_MODES)
64
65inline ArrayModes arrayModeFromStructure(Structure* structure)
66{
67 return asArrayModes(structure->indexingType());
68}
69
70void dumpArrayModes(PrintStream&, ArrayModes);
71MAKE_PRINT_ADAPTOR(ArrayModesDump, ArrayModes, dumpArrayModes);
72
73inline bool mergeArrayModes(ArrayModes& left, ArrayModes right)
74{
75 ArrayModes newModes = left | right;
76 if (newModes == left)
77 return false;
78 left = newModes;
79 return true;
80}
81
82// Checks if proven is a subset of expected.
83inline bool arrayModesAlreadyChecked(ArrayModes proven, ArrayModes expected)
84{
85 return (expected | proven) == expected;
86}
87
88inline bool arrayModesInclude(ArrayModes arrayModes, IndexingType shape)
89{
90 return !!(arrayModes & (asArrayModes(NonArray | shape) | asArrayModes(ArrayClass | shape)));
91}
92
93inline bool shouldUseSlowPutArrayStorage(ArrayModes arrayModes)
94{
95 return arrayModesInclude(arrayModes, SlowPutArrayStorageShape);
96}
97
98inline bool shouldUseFastArrayStorage(ArrayModes arrayModes)
99{
100 return arrayModesInclude(arrayModes, ArrayStorageShape);
101}
102
103inline bool shouldUseContiguous(ArrayModes arrayModes)
104{
105 return arrayModesInclude(arrayModes, ContiguousShape);
106}
107
108inline bool shouldUseDouble(ArrayModes arrayModes)
109{
110 return arrayModesInclude(arrayModes, DoubleShape);
111}
112
113inline bool shouldUseInt32(ArrayModes arrayModes)
114{
115 return arrayModesInclude(arrayModes, Int32Shape);
116}
117
118inline bool hasSeenArray(ArrayModes arrayModes)
119{
120 return arrayModes & ALL_ARRAY_ARRAY_MODES;
121}
122
123inline bool hasSeenNonArray(ArrayModes arrayModes)
124{
125 return arrayModes & ALL_NON_ARRAY_ARRAY_MODES;
126}
127
128class ArrayProfile {
129public:
130 ArrayProfile()
131 : m_bytecodeOffset(std::numeric_limits<unsigned>::max())
132 , m_lastSeenStructure(0)
133 , m_expectedStructure(0)
134 , m_mayStoreToHole(false)
135 , m_outOfBounds(false)
136 , m_mayInterceptIndexedAccesses(false)
137 , m_usesOriginalArrayStructures(true)
138 , m_observedArrayModes(0)
139 {
140 }
141
142 ArrayProfile(unsigned bytecodeOffset)
143 : m_bytecodeOffset(bytecodeOffset)
144 , m_lastSeenStructure(0)
145 , m_expectedStructure(0)
146 , m_mayStoreToHole(false)
147 , m_outOfBounds(false)
148 , m_mayInterceptIndexedAccesses(false)
149 , m_usesOriginalArrayStructures(true)
150 , m_observedArrayModes(0)
151 {
152 }
153
154 unsigned bytecodeOffset() const { return m_bytecodeOffset; }
155
156 Structure** addressOfLastSeenStructure() { return &m_lastSeenStructure; }
157 ArrayModes* addressOfArrayModes() { return &m_observedArrayModes; }
158 bool* addressOfMayStoreToHole() { return &m_mayStoreToHole; }
159 bool* addressOfOutOfBounds() { return &m_outOfBounds; }
160
161 void observeStructure(Structure* structure)
162 {
163 m_lastSeenStructure = structure;
164 }
165
166 void computeUpdatedPrediction(CodeBlock*, OperationInProgress = NoOperation);
167
168 Structure* expectedStructure() const
169 {
170 if (structureIsPolymorphic())
171 return 0;
172 return m_expectedStructure;
173 }
174 bool structureIsPolymorphic() const
175 {
176 return m_expectedStructure == polymorphicStructure();
177 }
178 bool hasDefiniteStructure() const
179 {
180 return !structureIsPolymorphic() && m_expectedStructure;
181 }
182 ArrayModes observedArrayModes() const { return m_observedArrayModes; }
183 ArrayModes updatedObservedArrayModes() const; // Computes the observed array modes without updating the profile.
184 bool mayInterceptIndexedAccesses() const { return m_mayInterceptIndexedAccesses; }
185
186 bool mayStoreToHole() const { return m_mayStoreToHole; }
187 bool outOfBounds() const { return m_outOfBounds; }
188
189 bool usesOriginalArrayStructures() const { return m_usesOriginalArrayStructures; }
190
191 CString briefDescription(CodeBlock*);
192
193private:
194 friend class LLIntOffsetsExtractor;
195
196 static Structure* polymorphicStructure() { return static_cast<Structure*>(reinterpret_cast<void*>(1)); }
197
198 unsigned m_bytecodeOffset;
199 Structure* m_lastSeenStructure;
200 Structure* m_expectedStructure;
201 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.
202 bool m_outOfBounds;
203 bool m_mayInterceptIndexedAccesses;
204 bool m_usesOriginalArrayStructures;
205 ArrayModes m_observedArrayModes;
206};
207
208typedef SegmentedVector<ArrayProfile, 4, 0> ArrayProfileVector;
209
210} // namespace JSC
211
212#endif // ArrayProfile_h
213