]>
Commit | Line | Data |
---|---|---|
6fe7ccc8 A |
1 | /* |
2 | * Copyright (C) 2011, 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 | * | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of | |
14 | * its contributors may be used to endorse or promote products derived | |
15 | * from this software without specific prior written permission. | |
16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
18 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
20 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | |
28 | ||
29 | #ifndef ValueProfile_h | |
30 | #define ValueProfile_h | |
31 | ||
32 | #include <wtf/Platform.h> | |
33 | ||
34 | #if ENABLE(VALUE_PROFILER) | |
35 | ||
93a37866 | 36 | #include "Heap.h" |
6fe7ccc8 | 37 | #include "JSArray.h" |
93a37866 | 38 | #include "SpeculatedType.h" |
6fe7ccc8 A |
39 | #include "Structure.h" |
40 | #include "WriteBarrier.h" | |
93a37866 A |
41 | #include <wtf/PrintStream.h> |
42 | #include <wtf/StringPrintStream.h> | |
6fe7ccc8 A |
43 | |
44 | namespace JSC { | |
45 | ||
46 | template<unsigned numberOfBucketsArgument> | |
47 | struct ValueProfileBase { | |
48 | static const unsigned numberOfBuckets = numberOfBucketsArgument; | |
49 | static const unsigned numberOfSpecFailBuckets = 1; | |
50 | static const unsigned bucketIndexMask = numberOfBuckets - 1; | |
51 | static const unsigned totalNumberOfBuckets = numberOfBuckets + numberOfSpecFailBuckets; | |
52 | ||
53 | ValueProfileBase() | |
54 | : m_bytecodeOffset(-1) | |
93a37866 | 55 | , m_prediction(SpecNone) |
6fe7ccc8 | 56 | , m_numberOfSamplesInPrediction(0) |
93a37866 | 57 | , m_singletonValueIsTop(false) |
6fe7ccc8 A |
58 | { |
59 | for (unsigned i = 0; i < totalNumberOfBuckets; ++i) | |
60 | m_buckets[i] = JSValue::encode(JSValue()); | |
61 | } | |
62 | ||
63 | ValueProfileBase(int bytecodeOffset) | |
64 | : m_bytecodeOffset(bytecodeOffset) | |
93a37866 | 65 | , m_prediction(SpecNone) |
6fe7ccc8 | 66 | , m_numberOfSamplesInPrediction(0) |
93a37866 | 67 | , m_singletonValueIsTop(false) |
6fe7ccc8 A |
68 | { |
69 | for (unsigned i = 0; i < totalNumberOfBuckets; ++i) | |
70 | m_buckets[i] = JSValue::encode(JSValue()); | |
71 | } | |
72 | ||
73 | EncodedJSValue* specFailBucket(unsigned i) | |
74 | { | |
75 | ASSERT(numberOfBuckets + i < totalNumberOfBuckets); | |
76 | return m_buckets + numberOfBuckets + i; | |
77 | } | |
78 | ||
79 | const ClassInfo* classInfo(unsigned bucket) const | |
80 | { | |
81 | JSValue value = JSValue::decode(m_buckets[bucket]); | |
82 | if (!!value) { | |
83 | if (!value.isCell()) | |
84 | return 0; | |
85 | return value.asCell()->structure()->classInfo(); | |
86 | } | |
87 | return 0; | |
88 | } | |
89 | ||
90 | unsigned numberOfSamples() const | |
91 | { | |
92 | unsigned result = 0; | |
93 | for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { | |
94 | if (!!JSValue::decode(m_buckets[i])) | |
95 | result++; | |
96 | } | |
97 | return result; | |
98 | } | |
99 | ||
100 | unsigned totalNumberOfSamples() const | |
101 | { | |
102 | return numberOfSamples() + m_numberOfSamplesInPrediction; | |
103 | } | |
104 | ||
105 | bool isLive() const | |
106 | { | |
107 | for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { | |
108 | if (!!JSValue::decode(m_buckets[i])) | |
109 | return true; | |
110 | } | |
111 | return false; | |
112 | } | |
113 | ||
93a37866 | 114 | CString briefDescription() |
6fe7ccc8 | 115 | { |
93a37866 A |
116 | computeUpdatedPrediction(); |
117 | ||
118 | StringPrintStream out; | |
119 | ||
120 | if (m_singletonValueIsTop) | |
121 | out.print("predicting ", SpeculationDump(m_prediction)); | |
122 | else if (m_singletonValue) | |
123 | out.print("predicting ", m_singletonValue); | |
124 | ||
125 | return out.toCString(); | |
126 | } | |
127 | ||
128 | void dump(PrintStream& out) | |
129 | { | |
130 | out.print("samples = ", totalNumberOfSamples(), " prediction = ", SpeculationDump(m_prediction)); | |
131 | out.printf(", value = "); | |
132 | if (m_singletonValueIsTop) | |
133 | out.printf("TOP"); | |
134 | else | |
135 | out.print(m_singletonValue); | |
6fe7ccc8 A |
136 | bool first = true; |
137 | for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { | |
138 | JSValue value = JSValue::decode(m_buckets[i]); | |
139 | if (!!value) { | |
140 | if (first) { | |
93a37866 | 141 | out.printf(": "); |
6fe7ccc8 A |
142 | first = false; |
143 | } else | |
93a37866 A |
144 | out.printf(", "); |
145 | out.print(value); | |
6fe7ccc8 A |
146 | } |
147 | } | |
148 | } | |
149 | ||
150 | // Updates the prediction and returns the new one. | |
93a37866 | 151 | SpeculatedType computeUpdatedPrediction(OperationInProgress operation = NoOperation) |
6fe7ccc8 A |
152 | { |
153 | for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { | |
154 | JSValue value = JSValue::decode(m_buckets[i]); | |
155 | if (!value) | |
156 | continue; | |
157 | ||
158 | m_numberOfSamplesInPrediction++; | |
93a37866 A |
159 | mergeSpeculation(m_prediction, speculationFromValue(value)); |
160 | ||
161 | if (!m_singletonValueIsTop && !!value) { | |
162 | if (!m_singletonValue) | |
163 | m_singletonValue = value; | |
164 | else if (m_singletonValue != value) | |
165 | m_singletonValueIsTop = true; | |
166 | } | |
6fe7ccc8 A |
167 | |
168 | m_buckets[i] = JSValue::encode(JSValue()); | |
169 | } | |
170 | ||
93a37866 A |
171 | if (operation == Collection |
172 | && !m_singletonValueIsTop | |
173 | && !!m_singletonValue | |
174 | && m_singletonValue.isCell() | |
175 | && !Heap::isMarked(m_singletonValue.asCell())) | |
176 | m_singletonValueIsTop = true; | |
177 | ||
6fe7ccc8 A |
178 | return m_prediction; |
179 | } | |
180 | ||
181 | int m_bytecodeOffset; // -1 for prologue | |
182 | ||
93a37866 | 183 | SpeculatedType m_prediction; |
6fe7ccc8 A |
184 | unsigned m_numberOfSamplesInPrediction; |
185 | ||
93a37866 A |
186 | bool m_singletonValueIsTop; |
187 | JSValue m_singletonValue; | |
188 | ||
6fe7ccc8 A |
189 | EncodedJSValue m_buckets[totalNumberOfBuckets]; |
190 | }; | |
191 | ||
192 | struct MinimalValueProfile : public ValueProfileBase<0> { | |
193 | MinimalValueProfile(): ValueProfileBase<0>() { } | |
194 | MinimalValueProfile(int bytecodeOffset): ValueProfileBase<0>(bytecodeOffset) { } | |
195 | }; | |
196 | ||
197 | template<unsigned logNumberOfBucketsArgument> | |
198 | struct ValueProfileWithLogNumberOfBuckets : public ValueProfileBase<1 << logNumberOfBucketsArgument> { | |
199 | static const unsigned logNumberOfBuckets = logNumberOfBucketsArgument; | |
200 | ||
201 | ValueProfileWithLogNumberOfBuckets() | |
202 | : ValueProfileBase<1 << logNumberOfBucketsArgument>() | |
203 | { | |
204 | } | |
205 | ValueProfileWithLogNumberOfBuckets(int bytecodeOffset) | |
206 | : ValueProfileBase<1 << logNumberOfBucketsArgument>(bytecodeOffset) | |
207 | { | |
208 | } | |
209 | }; | |
210 | ||
211 | struct ValueProfile : public ValueProfileWithLogNumberOfBuckets<0> { | |
212 | ValueProfile(): ValueProfileWithLogNumberOfBuckets<0>() { } | |
213 | ValueProfile(int bytecodeOffset): ValueProfileWithLogNumberOfBuckets<0>(bytecodeOffset) { } | |
214 | }; | |
215 | ||
216 | template<typename T> | |
217 | inline int getValueProfileBytecodeOffset(T* valueProfile) | |
218 | { | |
219 | return valueProfile->m_bytecodeOffset; | |
220 | } | |
221 | ||
222 | // This is a mini value profile to catch pathologies. It is a counter that gets | |
223 | // incremented when we take the slow path on any instruction. | |
224 | struct RareCaseProfile { | |
225 | RareCaseProfile(int bytecodeOffset) | |
226 | : m_bytecodeOffset(bytecodeOffset) | |
227 | , m_counter(0) | |
228 | { | |
229 | } | |
230 | ||
231 | int m_bytecodeOffset; | |
232 | uint32_t m_counter; | |
233 | }; | |
234 | ||
235 | inline int getRareCaseProfileBytecodeOffset(RareCaseProfile* rareCaseProfile) | |
236 | { | |
237 | return rareCaseProfile->m_bytecodeOffset; | |
238 | } | |
239 | ||
240 | } // namespace JSC | |
241 | ||
242 | #endif // ENABLE(VALUE_PROFILER) | |
243 | ||
244 | #endif // ValueProfile_h | |
245 |