op_to_this shouldn't use value profiling
[WebKit-https.git] / Source / JavaScriptCore / bytecode / ValueProfile.h
1 /*
2  * Copyright (C) 2011, 2012, 2013 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 "ConcurrentJITLock.h"
37 #include "Heap.h"
38 #include "JSArray.h"
39 #include "SpeculatedType.h"
40 #include "Structure.h"
41 #include "WriteBarrier.h"
42 #include <wtf/PrintStream.h>
43 #include <wtf/StringPrintStream.h>
44
45 namespace JSC {
46
47 template<unsigned numberOfBucketsArgument>
48 struct ValueProfileBase {
49     static const unsigned numberOfBuckets = numberOfBucketsArgument;
50     static const unsigned numberOfSpecFailBuckets = 1;
51     static const unsigned bucketIndexMask = numberOfBuckets - 1;
52     static const unsigned totalNumberOfBuckets = numberOfBuckets + numberOfSpecFailBuckets;
53     
54     ValueProfileBase()
55         : m_bytecodeOffset(-1)
56         , m_prediction(SpecNone)
57         , m_numberOfSamplesInPrediction(0)
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)
65         , m_prediction(SpecNone)
66         , m_numberOfSamplesInPrediction(0)
67     {
68         for (unsigned i = 0; i < totalNumberOfBuckets; ++i)
69             m_buckets[i] = JSValue::encode(JSValue());
70     }
71     
72     EncodedJSValue* specFailBucket(unsigned i)
73     {
74         ASSERT(numberOfBuckets + i < totalNumberOfBuckets);
75         return m_buckets + numberOfBuckets + i;
76     }
77     
78     const ClassInfo* classInfo(unsigned bucket) const
79     {
80         JSValue value = JSValue::decode(m_buckets[bucket]);
81         if (!!value) {
82             if (!value.isCell())
83                 return 0;
84             return value.asCell()->structure()->classInfo();
85         }
86         return 0;
87     }
88     
89     unsigned numberOfSamples() const
90     {
91         unsigned result = 0;
92         for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
93             if (!!JSValue::decode(m_buckets[i]))
94                 result++;
95         }
96         return result;
97     }
98     
99     unsigned totalNumberOfSamples() const
100     {
101         return numberOfSamples() + m_numberOfSamplesInPrediction;
102     }
103     
104     bool isLive() const
105     {
106         for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
107             if (!!JSValue::decode(m_buckets[i]))
108                 return true;
109         }
110         return false;
111     }
112     
113     CString briefDescription(const ConcurrentJITLocker& locker)
114     {
115         computeUpdatedPrediction(locker);
116         
117         StringPrintStream out;
118         out.print("predicting ", SpeculationDump(m_prediction));
119         return out.toCString();
120     }
121     
122     void dump(PrintStream& out)
123     {
124         out.print("samples = ", totalNumberOfSamples(), " prediction = ", SpeculationDump(m_prediction));
125         bool first = true;
126         for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
127             JSValue value = JSValue::decode(m_buckets[i]);
128             if (!!value) {
129                 if (first) {
130                     out.printf(": ");
131                     first = false;
132                 } else
133                     out.printf(", ");
134                 out.print(value);
135             }
136         }
137     }
138     
139     // Updates the prediction and returns the new one. Never call this from any thread
140     // that isn't executing the code.
141     SpeculatedType computeUpdatedPrediction(const ConcurrentJITLocker&)
142     {
143         for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
144             JSValue value = JSValue::decode(m_buckets[i]);
145             if (!value)
146                 continue;
147             
148             m_numberOfSamplesInPrediction++;
149             mergeSpeculation(m_prediction, speculationFromValue(value));
150             
151             m_buckets[i] = JSValue::encode(JSValue());
152         }
153         
154         return m_prediction;
155     }
156     
157     int m_bytecodeOffset; // -1 for prologue
158     
159     SpeculatedType m_prediction;
160     unsigned m_numberOfSamplesInPrediction;
161     
162     EncodedJSValue m_buckets[totalNumberOfBuckets];
163 };
164
165 struct MinimalValueProfile : public ValueProfileBase<0> {
166     MinimalValueProfile(): ValueProfileBase<0>() { }
167     MinimalValueProfile(int bytecodeOffset): ValueProfileBase<0>(bytecodeOffset) { }
168 };
169
170 template<unsigned logNumberOfBucketsArgument>
171 struct ValueProfileWithLogNumberOfBuckets : public ValueProfileBase<1 << logNumberOfBucketsArgument> {
172     static const unsigned logNumberOfBuckets = logNumberOfBucketsArgument;
173     
174     ValueProfileWithLogNumberOfBuckets()
175         : ValueProfileBase<1 << logNumberOfBucketsArgument>()
176     {
177     }
178     ValueProfileWithLogNumberOfBuckets(int bytecodeOffset)
179         : ValueProfileBase<1 << logNumberOfBucketsArgument>(bytecodeOffset)
180     {
181     }
182 };
183
184 struct ValueProfile : public ValueProfileWithLogNumberOfBuckets<0> {
185     ValueProfile(): ValueProfileWithLogNumberOfBuckets<0>() { }
186     ValueProfile(int bytecodeOffset): ValueProfileWithLogNumberOfBuckets<0>(bytecodeOffset) { }
187 };
188
189 template<typename T>
190 inline int getValueProfileBytecodeOffset(T* valueProfile)
191 {
192     return valueProfile->m_bytecodeOffset;
193 }
194
195 // This is a mini value profile to catch pathologies. It is a counter that gets
196 // incremented when we take the slow path on any instruction.
197 struct RareCaseProfile {
198     RareCaseProfile(int bytecodeOffset)
199         : m_bytecodeOffset(bytecodeOffset)
200         , m_counter(0)
201     {
202     }
203     
204     int m_bytecodeOffset;
205     uint32_t m_counter;
206 };
207
208 inline int getRareCaseProfileBytecodeOffset(RareCaseProfile* rareCaseProfile)
209 {
210     return rareCaseProfile->m_bytecodeOffset;
211 }
212
213 } // namespace JSC
214
215 #endif // ENABLE(VALUE_PROFILER)
216
217 #endif // ValueProfile_h
218