]>
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 | ||
36 | #include "JSArray.h" | |
37 | #include "PredictedType.h" | |
38 | #include "Structure.h" | |
39 | #include "WriteBarrier.h" | |
40 | ||
41 | namespace JSC { | |
42 | ||
43 | template<unsigned numberOfBucketsArgument> | |
44 | struct ValueProfileBase { | |
45 | static const unsigned numberOfBuckets = numberOfBucketsArgument; | |
46 | static const unsigned numberOfSpecFailBuckets = 1; | |
47 | static const unsigned bucketIndexMask = numberOfBuckets - 1; | |
48 | static const unsigned totalNumberOfBuckets = numberOfBuckets + numberOfSpecFailBuckets; | |
49 | ||
50 | ValueProfileBase() | |
51 | : m_bytecodeOffset(-1) | |
52 | , m_prediction(PredictNone) | |
53 | , m_numberOfSamplesInPrediction(0) | |
54 | { | |
55 | for (unsigned i = 0; i < totalNumberOfBuckets; ++i) | |
56 | m_buckets[i] = JSValue::encode(JSValue()); | |
57 | } | |
58 | ||
59 | ValueProfileBase(int bytecodeOffset) | |
60 | : m_bytecodeOffset(bytecodeOffset) | |
61 | , m_prediction(PredictNone) | |
62 | , m_numberOfSamplesInPrediction(0) | |
63 | { | |
64 | for (unsigned i = 0; i < totalNumberOfBuckets; ++i) | |
65 | m_buckets[i] = JSValue::encode(JSValue()); | |
66 | } | |
67 | ||
68 | EncodedJSValue* specFailBucket(unsigned i) | |
69 | { | |
70 | ASSERT(numberOfBuckets + i < totalNumberOfBuckets); | |
71 | return m_buckets + numberOfBuckets + i; | |
72 | } | |
73 | ||
74 | const ClassInfo* classInfo(unsigned bucket) const | |
75 | { | |
76 | JSValue value = JSValue::decode(m_buckets[bucket]); | |
77 | if (!!value) { | |
78 | if (!value.isCell()) | |
79 | return 0; | |
80 | return value.asCell()->structure()->classInfo(); | |
81 | } | |
82 | return 0; | |
83 | } | |
84 | ||
85 | unsigned numberOfSamples() const | |
86 | { | |
87 | unsigned result = 0; | |
88 | for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { | |
89 | if (!!JSValue::decode(m_buckets[i])) | |
90 | result++; | |
91 | } | |
92 | return result; | |
93 | } | |
94 | ||
95 | unsigned totalNumberOfSamples() const | |
96 | { | |
97 | return numberOfSamples() + m_numberOfSamplesInPrediction; | |
98 | } | |
99 | ||
100 | bool isLive() const | |
101 | { | |
102 | for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { | |
103 | if (!!JSValue::decode(m_buckets[i])) | |
104 | return true; | |
105 | } | |
106 | return false; | |
107 | } | |
108 | ||
109 | void dump(FILE* out) | |
110 | { | |
111 | fprintf(out, | |
112 | "samples = %u, prediction = %s", | |
113 | totalNumberOfSamples(), | |
114 | predictionToString(m_prediction)); | |
115 | bool first = true; | |
116 | for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { | |
117 | JSValue value = JSValue::decode(m_buckets[i]); | |
118 | if (!!value) { | |
119 | if (first) { | |
120 | fprintf(out, ": "); | |
121 | first = false; | |
122 | } else | |
123 | fprintf(out, ", "); | |
124 | fprintf(out, "%s", value.description()); | |
125 | } | |
126 | } | |
127 | } | |
128 | ||
129 | // Updates the prediction and returns the new one. | |
130 | PredictedType computeUpdatedPrediction() | |
131 | { | |
132 | for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { | |
133 | JSValue value = JSValue::decode(m_buckets[i]); | |
134 | if (!value) | |
135 | continue; | |
136 | ||
137 | m_numberOfSamplesInPrediction++; | |
138 | mergePrediction(m_prediction, predictionFromValue(value)); | |
139 | ||
140 | m_buckets[i] = JSValue::encode(JSValue()); | |
141 | } | |
142 | ||
143 | return m_prediction; | |
144 | } | |
145 | ||
146 | int m_bytecodeOffset; // -1 for prologue | |
147 | ||
148 | PredictedType m_prediction; | |
149 | unsigned m_numberOfSamplesInPrediction; | |
150 | ||
151 | EncodedJSValue m_buckets[totalNumberOfBuckets]; | |
152 | }; | |
153 | ||
154 | struct MinimalValueProfile : public ValueProfileBase<0> { | |
155 | MinimalValueProfile(): ValueProfileBase<0>() { } | |
156 | MinimalValueProfile(int bytecodeOffset): ValueProfileBase<0>(bytecodeOffset) { } | |
157 | }; | |
158 | ||
159 | template<unsigned logNumberOfBucketsArgument> | |
160 | struct ValueProfileWithLogNumberOfBuckets : public ValueProfileBase<1 << logNumberOfBucketsArgument> { | |
161 | static const unsigned logNumberOfBuckets = logNumberOfBucketsArgument; | |
162 | ||
163 | ValueProfileWithLogNumberOfBuckets() | |
164 | : ValueProfileBase<1 << logNumberOfBucketsArgument>() | |
165 | { | |
166 | } | |
167 | ValueProfileWithLogNumberOfBuckets(int bytecodeOffset) | |
168 | : ValueProfileBase<1 << logNumberOfBucketsArgument>(bytecodeOffset) | |
169 | { | |
170 | } | |
171 | }; | |
172 | ||
173 | struct ValueProfile : public ValueProfileWithLogNumberOfBuckets<0> { | |
174 | ValueProfile(): ValueProfileWithLogNumberOfBuckets<0>() { } | |
175 | ValueProfile(int bytecodeOffset): ValueProfileWithLogNumberOfBuckets<0>(bytecodeOffset) { } | |
176 | }; | |
177 | ||
178 | template<typename T> | |
179 | inline int getValueProfileBytecodeOffset(T* valueProfile) | |
180 | { | |
181 | return valueProfile->m_bytecodeOffset; | |
182 | } | |
183 | ||
184 | // This is a mini value profile to catch pathologies. It is a counter that gets | |
185 | // incremented when we take the slow path on any instruction. | |
186 | struct RareCaseProfile { | |
187 | RareCaseProfile(int bytecodeOffset) | |
188 | : m_bytecodeOffset(bytecodeOffset) | |
189 | , m_counter(0) | |
190 | { | |
191 | } | |
192 | ||
193 | int m_bytecodeOffset; | |
194 | uint32_t m_counter; | |
195 | }; | |
196 | ||
197 | inline int getRareCaseProfileBytecodeOffset(RareCaseProfile* rareCaseProfile) | |
198 | { | |
199 | return rareCaseProfile->m_bytecodeOffset; | |
200 | } | |
201 | ||
202 | } // namespace JSC | |
203 | ||
204 | #endif // ENABLE(VALUE_PROFILER) | |
205 | ||
206 | #endif // ValueProfile_h | |
207 |