2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #ifndef ValueProfile_h
30 #define ValueProfile_h
33 #include "PredictedType.h"
34 #include "Structure.h"
35 #include "WriteBarrier.h"
39 #if ENABLE(VALUE_PROFILER)
41 static const unsigned logNumberOfBuckets = 3; // 8 buckets
42 static const unsigned numberOfBuckets = 1 << logNumberOfBuckets;
43 static const unsigned bucketIndexMask = numberOfBuckets - 1;
44 static const unsigned certainty = numberOfBuckets * numberOfBuckets;
45 static const unsigned majority = certainty / 2;
47 ValueProfile(int bytecodeOffset)
48 : m_bytecodeOffset(bytecodeOffset)
49 , m_prediction(PredictNone)
50 , m_numberOfSamplesInPrediction(0)
52 for (unsigned i = 0; i < numberOfBuckets; ++i)
53 m_buckets[i] = JSValue::encode(JSValue());
56 const ClassInfo* classInfo(unsigned bucket) const
58 if (!!m_buckets[bucket]) {
59 JSValue value = JSValue::decode(m_buckets[bucket]);
62 return value.asCell()->structure()->classInfo();
64 return m_weakBuckets[bucket].getClassInfo();
67 unsigned numberOfSamples() const
70 for (unsigned i = 0; i < numberOfBuckets; ++i) {
71 if (!!m_buckets[i] || !!m_weakBuckets[i])
77 unsigned totalNumberOfSamples() const
79 return numberOfSamples() + m_numberOfSamplesInPrediction;
84 for (unsigned i = 0; i < numberOfBuckets; ++i) {
85 if (!!m_buckets[i] || !!m_weakBuckets[i])
91 static unsigned computeProbability(unsigned counts, unsigned numberOfSamples)
95 return counts * certainty / numberOfSamples;
98 unsigned numberOfInt32s() const
101 for (unsigned i = 0; i < numberOfBuckets; ++i) {
102 if (!!m_buckets[i] && JSValue::decode(m_buckets[i]).isInt32())
108 unsigned numberOfDoubles() const
111 for (unsigned i = 0; i < numberOfBuckets; ++i) {
112 if (!!m_buckets[i] && JSValue::decode(m_buckets[i]).isDouble())
118 unsigned numberOfCells() const
121 for (unsigned i = 0; i < numberOfBuckets; ++i) {
128 unsigned numberOfObjects() const
131 for (unsigned i = 0; i < numberOfBuckets; ++i) {
132 const ClassInfo* ci = classInfo(i);
133 if (!!ci && ci->isSubClassOf(&JSObject::s_info))
139 unsigned numberOfFinalObjects() const
142 for (unsigned i = 0; i < numberOfBuckets; ++i) {
143 if (classInfo(i) == &JSFinalObject::s_info)
149 unsigned numberOfStrings() const
152 for (unsigned i = 0; i < numberOfBuckets; ++i) {
153 if (classInfo(i) == &JSString::s_info)
159 unsigned numberOfArrays() const
162 for (unsigned i = 0; i < numberOfBuckets; ++i) {
163 if (classInfo(i) == &JSArray::s_info)
169 unsigned numberOfBooleans() const
172 for (unsigned i = 0; i < numberOfBuckets; ++i) {
173 if (!!m_buckets[i] && JSValue::decode(m_buckets[i]).isBoolean())
179 // These methods are not particularly optimized, in that they will each
180 // perform two passes over the buckets array. However, they are
181 // probably the best bet unless you are sure that you will be making
182 // these calls with high frequency.
184 unsigned probabilityOfInt32() const
186 return computeProbability(numberOfInt32s(), numberOfSamples());
189 unsigned probabilityOfDouble() const
191 return computeProbability(numberOfDoubles(), numberOfSamples());
194 unsigned probabilityOfCell() const
196 return computeProbability(numberOfCells(), numberOfSamples());
199 unsigned probabilityOfObject() const
201 return computeProbability(numberOfObjects(), numberOfSamples());
204 unsigned probabilityOfFinalObject() const
206 return computeProbability(numberOfFinalObjects(), numberOfSamples());
209 unsigned probabilityOfArray() const
211 return computeProbability(numberOfArrays(), numberOfSamples());
214 unsigned probabilityOfString() const
216 return computeProbability(numberOfStrings(), numberOfSamples());
219 unsigned probabilityOfBoolean() const
221 return computeProbability(numberOfBooleans(), numberOfSamples());
228 "samples = %u, int32 = %u (%u), double = %u (%u), cell = %u (%u), object = %u (%u), final object = %u (%u), array = %u (%u), string = %u (%u), boolean = %u (%u), prediction = %s, samples in prediction = %u",
230 probabilityOfInt32(), numberOfInt32s(),
231 probabilityOfDouble(), numberOfDoubles(),
232 probabilityOfCell(), numberOfCells(),
233 probabilityOfObject(), numberOfObjects(),
234 probabilityOfFinalObject(), numberOfFinalObjects(),
235 probabilityOfArray(), numberOfArrays(),
236 probabilityOfString(), numberOfStrings(),
237 probabilityOfBoolean(), numberOfBooleans(),
238 predictionToString(m_prediction), m_numberOfSamplesInPrediction);
240 for (unsigned i = 0; i < numberOfBuckets; ++i) {
241 if (!!m_buckets[i] || !!m_weakBuckets[i]) {
250 fprintf(out, "%s", JSValue::decode(m_buckets[i]).description());
252 if (!!m_weakBuckets[i])
253 fprintf(out, "DeadCell");
264 unsigned finalObjects;
271 bzero(this, sizeof(Statistics));
275 // Method for incrementing all relevant statistics for a ClassInfo, except for
276 // incrementing the number of samples, which the caller is responsible for
278 static void computeStatistics(const ClassInfo*, Statistics&);
280 // Optimized method for getting all counts at once.
281 void computeStatistics(Statistics&) const;
283 // Updates the prediction and returns the new one.
284 PredictedType computeUpdatedPrediction();
286 int m_bytecodeOffset; // -1 for prologue
288 PredictedType m_prediction;
289 unsigned m_numberOfSamplesInPrediction;
291 EncodedJSValue m_buckets[numberOfBuckets];
300 WeakBucket(Structure* structure)
301 : m_value(reinterpret_cast<uintptr_t>(structure))
305 WeakBucket(const ClassInfo* classInfo)
306 : m_value(reinterpret_cast<uintptr_t>(classInfo) | 1)
310 bool operator!() const
320 bool isClassInfo() const
322 return !!(m_value & 1);
325 bool isStructure() const
327 return !isEmpty() && !isClassInfo();
330 Structure* asStructure() const
332 ASSERT(isStructure());
333 return reinterpret_cast<Structure*>(m_value);
336 const ClassInfo* asClassInfo() const
338 ASSERT(isClassInfo());
339 return reinterpret_cast<ClassInfo*>(m_value & ~static_cast<uintptr_t>(1));
342 const ClassInfo* getClassInfo() const
347 return asClassInfo();
348 return asStructure()->classInfo();
355 WeakBucket m_weakBuckets[numberOfBuckets]; // this is not covered by a write barrier because it is only set from GC
358 inline int getValueProfileBytecodeOffset(ValueProfile* valueProfile)
360 return valueProfile->m_bytecodeOffset;