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