2  * Copyright (C) 2011, 2012, 2013 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 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 
  32 #include "ConcurrentJITLock.h" 
  35 #include "SpeculatedType.h" 
  36 #include "Structure.h" 
  37 #include "WriteBarrier.h" 
  38 #include <wtf/PrintStream.h> 
  39 #include <wtf/StringPrintStream.h> 
  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
; 
  51         : m_bytecodeOffset(-1) 
  52         , m_prediction(SpecNone
) 
  53         , m_numberOfSamplesInPrediction(0) 
  55         for (unsigned i 
= 0; i 
< totalNumberOfBuckets
; ++i
) 
  56             m_buckets
[i
] = JSValue::encode(JSValue()); 
  59     ValueProfileBase(int bytecodeOffset
) 
  60         : m_bytecodeOffset(bytecodeOffset
) 
  61         , m_prediction(SpecNone
) 
  62         , m_numberOfSamplesInPrediction(0) 
  64         for (unsigned i 
= 0; i 
< totalNumberOfBuckets
; ++i
) 
  65             m_buckets
[i
] = JSValue::encode(JSValue()); 
  68     EncodedJSValue
* specFailBucket(unsigned i
) 
  70         ASSERT(numberOfBuckets 
+ i 
< totalNumberOfBuckets
); 
  71         return m_buckets 
+ numberOfBuckets 
+ i
; 
  74     const ClassInfo
* classInfo(unsigned bucket
) const 
  76         JSValue value 
= JSValue::decode(m_buckets
[bucket
]); 
  80             return value
.asCell()->structure()->classInfo(); 
  85     unsigned numberOfSamples() const 
  88         for (unsigned i 
= 0; i 
< totalNumberOfBuckets
; ++i
) { 
  89             if (!!JSValue::decode(m_buckets
[i
])) 
  95     unsigned totalNumberOfSamples() const 
  97         return numberOfSamples() + m_numberOfSamplesInPrediction
; 
 102         for (unsigned i 
= 0; i 
< totalNumberOfBuckets
; ++i
) { 
 103             if (!!JSValue::decode(m_buckets
[i
])) 
 109     CString 
briefDescription(const ConcurrentJITLocker
& locker
) 
 111         computeUpdatedPrediction(locker
); 
 113         StringPrintStream out
; 
 114         out
.print("predicting ", SpeculationDump(m_prediction
)); 
 115         return out
.toCString(); 
 118     void dump(PrintStream
& out
) 
 120         out
.print("samples = ", totalNumberOfSamples(), " prediction = ", SpeculationDump(m_prediction
)); 
 122         for (unsigned i 
= 0; i 
< totalNumberOfBuckets
; ++i
) { 
 123             JSValue value 
= JSValue::decode(m_buckets
[i
]); 
 135     // Updates the prediction and returns the new one. Never call this from any thread 
 136     // that isn't executing the code. 
 137     SpeculatedType 
computeUpdatedPrediction(const ConcurrentJITLocker
&) 
 139         for (unsigned i 
= 0; i 
< totalNumberOfBuckets
; ++i
) { 
 140             JSValue value 
= JSValue::decode(m_buckets
[i
]); 
 144             m_numberOfSamplesInPrediction
++; 
 145             mergeSpeculation(m_prediction
, speculationFromValue(value
)); 
 147             m_buckets
[i
] = JSValue::encode(JSValue()); 
 153     int m_bytecodeOffset
; // -1 for prologue 
 155     SpeculatedType m_prediction
; 
 156     unsigned m_numberOfSamplesInPrediction
; 
 158     EncodedJSValue m_buckets
[totalNumberOfBuckets
]; 
 161 struct MinimalValueProfile 
: public ValueProfileBase
<0> { 
 162     MinimalValueProfile(): ValueProfileBase
<0>() { } 
 163     MinimalValueProfile(int bytecodeOffset
): ValueProfileBase
<0>(bytecodeOffset
) { } 
 166 template<unsigned logNumberOfBucketsArgument
> 
 167 struct ValueProfileWithLogNumberOfBuckets 
: public ValueProfileBase
<1 << logNumberOfBucketsArgument
> { 
 168     static const unsigned logNumberOfBuckets 
= logNumberOfBucketsArgument
; 
 170     ValueProfileWithLogNumberOfBuckets() 
 171         : ValueProfileBase
<1 << logNumberOfBucketsArgument
>() 
 174     ValueProfileWithLogNumberOfBuckets(int bytecodeOffset
) 
 175         : ValueProfileBase
<1 << logNumberOfBucketsArgument
>(bytecodeOffset
) 
 180 struct ValueProfile 
: public ValueProfileWithLogNumberOfBuckets
<0> { 
 181     ValueProfile(): ValueProfileWithLogNumberOfBuckets
<0>() { } 
 182     ValueProfile(int bytecodeOffset
): ValueProfileWithLogNumberOfBuckets
<0>(bytecodeOffset
) { } 
 186 inline int getValueProfileBytecodeOffset(T
* valueProfile
) 
 188     return valueProfile
->m_bytecodeOffset
; 
 191 // This is a mini value profile to catch pathologies. It is a counter that gets 
 192 // incremented when we take the slow path on any instruction. 
 193 struct RareCaseProfile 
{ 
 194     RareCaseProfile(int bytecodeOffset
) 
 195         : m_bytecodeOffset(bytecodeOffset
) 
 200     int m_bytecodeOffset
; 
 204 inline int getRareCaseProfileBytecodeOffset(RareCaseProfile
* rareCaseProfile
) 
 206     return rareCaseProfile
->m_bytecodeOffset
; 
 211 #endif // ValueProfile_h