2 * Copyright (C) 2011, 2012 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
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.
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.
26 #ifndef DFGVariableAccessData_h
27 #define DFGVariableAccessData_h
29 #include "DFGDoubleFormatState.h"
30 #include "DFGNodeFlags.h"
32 #include "PredictedType.h"
33 #include "VirtualRegister.h"
34 #include <wtf/Platform.h>
35 #include <wtf/UnionFind.h>
36 #include <wtf/Vector.h>
38 namespace JSC
{ namespace DFG
{
40 class VariableAccessData
: public UnionFind
<VariableAccessData
> {
42 enum Ballot
{ VoteValue
, VoteDouble
};
45 : m_local(static_cast<VirtualRegister
>(std::numeric_limits
<int>::min()))
46 , m_prediction(PredictNone
)
47 , m_argumentAwarePrediction(PredictNone
)
49 , m_doubleFormatState(EmptyDoubleFormatState
)
54 VariableAccessData(VirtualRegister local
)
56 , m_prediction(PredictNone
)
57 , m_argumentAwarePrediction(PredictNone
)
59 , m_doubleFormatState(EmptyDoubleFormatState
)
64 VirtualRegister
local()
66 ASSERT(m_local
== find()->m_local
);
72 return static_cast<int>(local());
75 bool predict(PredictedType prediction
)
77 VariableAccessData
* self
= find();
78 bool result
= mergePrediction(self
->m_prediction
, prediction
);
80 mergePrediction(m_argumentAwarePrediction
, m_prediction
);
84 PredictedType
nonUnifiedPrediction()
89 PredictedType
prediction()
91 return find()->m_prediction
;
94 PredictedType
argumentAwarePrediction()
96 return find()->m_argumentAwarePrediction
;
99 bool mergeArgumentAwarePrediction(PredictedType prediction
)
101 return mergePrediction(find()->m_argumentAwarePrediction
, prediction
);
106 ASSERT(find() == this);
107 m_votes
[VoteValue
] = 0;
108 m_votes
[VoteDouble
] = 0;
111 void vote(Ballot ballot
)
113 ASSERT(static_cast<unsigned>(ballot
) < 2);
117 double doubleVoteRatio()
119 ASSERT(find() == this);
120 return static_cast<double>(m_votes
[VoteDouble
]) / m_votes
[VoteValue
];
123 bool shouldUseDoubleFormatAccordingToVote()
125 // We don't support this facility for arguments, yet.
126 // FIXME: make this work for arguments.
127 if (operandIsArgument(operand()))
130 // If the variable is not a number prediction, then this doesn't
132 if (!isNumberPrediction(prediction()))
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()))
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
)
145 // If the variable has been voted to become a double, then make it a
147 if (doubleVoteRatio() >= Options::doubleVoteRatioForDoubleFormat
)
153 DoubleFormatState
doubleFormatState()
155 return find()->m_doubleFormatState
;
158 bool shouldUseDoubleFormat()
161 return m_doubleFormatState
== UsingDoubleFormat
;
164 bool tallyVotesForShouldUseDoubleFormat()
168 if (m_doubleFormatState
== CantUseDoubleFormat
)
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.
178 if (m_doubleFormatState
== UsingDoubleFormat
)
181 return DFG::mergeDoubleFormatState(m_doubleFormatState
, UsingDoubleFormat
);
184 bool mergeDoubleFormatState(DoubleFormatState doubleFormatState
)
186 return DFG::mergeDoubleFormatState(find()->m_doubleFormatState
, doubleFormatState
);
189 bool makePredictionForDoubleFormat()
193 if (m_doubleFormatState
!= UsingDoubleFormat
)
196 return mergePrediction(m_prediction
, PredictDouble
);
199 NodeFlags
flags() const { return m_flags
; }
201 bool mergeFlags(NodeFlags newFlags
)
204 if (newFlags
== m_flags
)
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.
216 VirtualRegister m_local
;
217 PredictedType m_prediction
;
218 PredictedType m_argumentAwarePrediction
;
222 DoubleFormatState m_doubleFormatState
;
225 } } // namespace JSC::DFG
227 #endif // DFGVariableAccessData_h