]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGVariableAccessData.h
JavaScriptCore-1097.13.tar.gz
[apple/javascriptcore.git] / dfg / DFGVariableAccessData.h
CommitLineData
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 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef DFGVariableAccessData_h
27#define DFGVariableAccessData_h
28
29#include "DFGDoubleFormatState.h"
30#include "DFGNodeFlags.h"
31#include "Operands.h"
32#include "PredictedType.h"
33#include "VirtualRegister.h"
34#include <wtf/Platform.h>
35#include <wtf/UnionFind.h>
36#include <wtf/Vector.h>
37
38namespace JSC { namespace DFG {
39
40class VariableAccessData : public UnionFind<VariableAccessData> {
41public:
42 enum Ballot { VoteValue, VoteDouble };
43
44 VariableAccessData()
45 : m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min()))
46 , m_prediction(PredictNone)
47 , m_argumentAwarePrediction(PredictNone)
48 , m_flags(0)
49 , m_doubleFormatState(EmptyDoubleFormatState)
50 {
51 clearVotes();
52 }
53
54 VariableAccessData(VirtualRegister local)
55 : m_local(local)
56 , m_prediction(PredictNone)
57 , m_argumentAwarePrediction(PredictNone)
58 , m_flags(0)
59 , m_doubleFormatState(EmptyDoubleFormatState)
60 {
61 clearVotes();
62 }
63
64 VirtualRegister local()
65 {
66 ASSERT(m_local == find()->m_local);
67 return m_local;
68 }
69
70 int operand()
71 {
72 return static_cast<int>(local());
73 }
74
75 bool predict(PredictedType prediction)
76 {
77 VariableAccessData* self = find();
78 bool result = mergePrediction(self->m_prediction, prediction);
79 if (result)
80 mergePrediction(m_argumentAwarePrediction, m_prediction);
81 return result;
82 }
83
84 PredictedType nonUnifiedPrediction()
85 {
86 return m_prediction;
87 }
88
89 PredictedType prediction()
90 {
91 return find()->m_prediction;
92 }
93
94 PredictedType argumentAwarePrediction()
95 {
96 return find()->m_argumentAwarePrediction;
97 }
98
99 bool mergeArgumentAwarePrediction(PredictedType prediction)
100 {
101 return mergePrediction(find()->m_argumentAwarePrediction, prediction);
102 }
103
104 void clearVotes()
105 {
106 ASSERT(find() == this);
107 m_votes[VoteValue] = 0;
108 m_votes[VoteDouble] = 0;
109 }
110
111 void vote(Ballot ballot)
112 {
113 ASSERT(static_cast<unsigned>(ballot) < 2);
114 m_votes[ballot]++;
115 }
116
117 double doubleVoteRatio()
118 {
119 ASSERT(find() == this);
120 return static_cast<double>(m_votes[VoteDouble]) / m_votes[VoteValue];
121 }
122
123 bool shouldUseDoubleFormatAccordingToVote()
124 {
125 // We don't support this facility for arguments, yet.
126 // FIXME: make this work for arguments.
127 if (operandIsArgument(operand()))
128 return false;
129
130 // If the variable is not a number prediction, then this doesn't
131 // make any sense.
132 if (!isNumberPrediction(prediction()))
133 return false;
134
135 // If the variable is predicted to hold only doubles, then it's a
136 // no-brainer: it should be formatted as a double.
137 if (isDoublePrediction(prediction()))
138 return true;
139
140 // If the variable is known to be used as an integer, then be safe -
141 // don't force it to be a double.
142 if (flags() & NodeUsedAsInt)
143 return false;
144
145 // If the variable has been voted to become a double, then make it a
146 // double.
147 if (doubleVoteRatio() >= Options::doubleVoteRatioForDoubleFormat)
148 return true;
149
150 return false;
151 }
152
153 DoubleFormatState doubleFormatState()
154 {
155 return find()->m_doubleFormatState;
156 }
157
158 bool shouldUseDoubleFormat()
159 {
160 ASSERT(isRoot());
161 return m_doubleFormatState == UsingDoubleFormat;
162 }
163
164 bool tallyVotesForShouldUseDoubleFormat()
165 {
166 ASSERT(isRoot());
167
168 if (m_doubleFormatState == CantUseDoubleFormat)
169 return false;
170
171 bool newValueOfShouldUseDoubleFormat = shouldUseDoubleFormatAccordingToVote();
172 if (!newValueOfShouldUseDoubleFormat) {
173 // We monotonically convert to double. Hence, if the fixpoint leads us to conclude that we should
174 // switch back to int, we instead ignore this and stick with double.
175 return false;
176 }
177
178 if (m_doubleFormatState == UsingDoubleFormat)
179 return false;
180
181 return DFG::mergeDoubleFormatState(m_doubleFormatState, UsingDoubleFormat);
182 }
183
184 bool mergeDoubleFormatState(DoubleFormatState doubleFormatState)
185 {
186 return DFG::mergeDoubleFormatState(find()->m_doubleFormatState, doubleFormatState);
187 }
188
189 bool makePredictionForDoubleFormat()
190 {
191 ASSERT(isRoot());
192
193 if (m_doubleFormatState != UsingDoubleFormat)
194 return false;
195
196 return mergePrediction(m_prediction, PredictDouble);
197 }
198
199 NodeFlags flags() const { return m_flags; }
200
201 bool mergeFlags(NodeFlags newFlags)
202 {
203 newFlags |= m_flags;
204 if (newFlags == m_flags)
205 return false;
206 m_flags = newFlags;
207 return true;
208 }
209
210private:
211 // This is slightly space-inefficient, since anything we're unified with
212 // will have the same operand and should have the same prediction. But
213 // putting them here simplifies the code, and we don't expect DFG space
214 // usage for variable access nodes do be significant.
215
216 VirtualRegister m_local;
217 PredictedType m_prediction;
218 PredictedType m_argumentAwarePrediction;
219 NodeFlags m_flags;
220
221 float m_votes[2];
222 DoubleFormatState m_doubleFormatState;
223};
224
225} } // namespace JSC::DFG
226
227#endif // DFGVariableAccessData_h