1/*
2 * Copyright (C) 2011-2015 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#pragma once
27
28#if ENABLE(DFG_JIT)
29
30#include "DFGCommon.h"
31#include "DFGDoubleFormatState.h"
32#include "DFGFlushFormat.h"
33#include "DFGFlushedAt.h"
34#include "DFGNodeFlags.h"
35#include "Operands.h"
36#include "SpeculatedType.h"
37#include "VirtualRegister.h"
38#include <wtf/UnionFind.h>
39
40namespace JSC { namespace DFG {
41
42struct Node;
43
44enum DoubleBallot { VoteValue, VoteDouble };
45
46class VariableAccessData : public UnionFind<VariableAccessData> {
47public:
48 VariableAccessData();
49 VariableAccessData(VirtualRegister local);
50
51 VirtualRegister local()
52 {
53 ASSERT(m_local == find()->m_local);
54 return m_local;
55 }
56
57 VirtualRegister& machineLocal()
58 {
59 ASSERT(find() == this);
60 return m_machineLocal;
61 }
62
63 bool mergeIsProfitableToUnbox(bool isProfitableToUnbox)
64 {
65 return checkAndSet(m_isProfitableToUnbox, m_isProfitableToUnbox || isProfitableToUnbox);
66 }
67
68 bool isProfitableToUnbox()
69 {
70 return m_isProfitableToUnbox;
71 }
72
73 bool mergeShouldNeverUnbox(bool shouldNeverUnbox);
74
75 // Returns true if it would be unsound to store the value in an unboxed fashion.
76 // If this returns false, it simply means that it is sound to unbox; it doesn't
77 // mean that we have actually done so.
78 bool shouldNeverUnbox()
79 {
80 return m_shouldNeverUnbox;
81 }
82
83 // Returns true if we should be unboxing the value provided that the predictions
84 // and double format vote say so. This may return false even if shouldNeverUnbox()
85 // returns false, since this incorporates heuristics of profitability.
86 bool shouldUnboxIfPossible()
87 {
88 return !shouldNeverUnbox() && isProfitableToUnbox();
89 }
90
91 bool mergeStructureCheckHoistingFailed(bool failed)
92 {
93 return checkAndSet(m_structureCheckHoistingFailed, m_structureCheckHoistingFailed || failed);
94 }
95
96 bool mergeCheckArrayHoistingFailed(bool failed)
97 {
98 return checkAndSet(m_checkArrayHoistingFailed, m_checkArrayHoistingFailed || failed);
99 }
100
101 bool structureCheckHoistingFailed()
102 {
103 return m_structureCheckHoistingFailed;
104 }
105
106 bool checkArrayHoistingFailed()
107 {
108 return m_checkArrayHoistingFailed;
109 }
110
111 bool mergeIsLoadedFrom(bool isLoadedFrom)
112 {
113 return checkAndSet(m_isLoadedFrom, m_isLoadedFrom || isLoadedFrom);
114 }
115
116 void setIsLoadedFrom(bool isLoadedFrom)
117 {
118 m_isLoadedFrom = isLoadedFrom;
119 }
120
121 bool isLoadedFrom()
122 {
123 return m_isLoadedFrom;
124 }
125
126 bool predict(SpeculatedType prediction);
127
128 SpeculatedType nonUnifiedPrediction()
129 {
130 return m_prediction;
131 }
132
133 SpeculatedType prediction()
134 {
135 return find()->m_prediction;
136 }
137
138 SpeculatedType argumentAwarePrediction()
139 {
140 return find()->m_argumentAwarePrediction;
141 }
142
143 bool mergeArgumentAwarePrediction(SpeculatedType prediction);
144
145 void clearVotes()
146 {
147 ASSERT(find() == this);
148 m_votes[0] = 0;
149 m_votes[1] = 0;
150 }
151
152 void vote(unsigned ballot, float weight = 1)
153 {
154 ASSERT(ballot < 2);
155 m_votes[ballot] += weight;
156 }
157
158 double voteRatio()
159 {
160 ASSERT(find() == this);
161 return static_cast<double>(m_votes[1]) / m_votes[0];
162 }
163
164 bool shouldUseDoubleFormatAccordingToVote();
165
166 DoubleFormatState doubleFormatState()
167 {
168 return find()->m_doubleFormatState;
169 }
170
171 bool shouldUseDoubleFormat()
172 {
173 ASSERT(isRoot());
174 bool doubleState = m_doubleFormatState == UsingDoubleFormat;
175 ASSERT(!(doubleState && shouldNeverUnbox()));
176 return doubleState && isProfitableToUnbox();
177 }
178
179 bool tallyVotesForShouldUseDoubleFormat();
180
181 bool mergeDoubleFormatState(DoubleFormatState);
182
183 bool makePredictionForDoubleFormat();
184
185 NodeFlags flags() const { return m_flags; }
186
187 bool mergeFlags(NodeFlags newFlags)
188 {
189 return checkAndSet(m_flags, m_flags | newFlags);
190 }
191
192 FlushFormat flushFormat();
193
194 bool couldRepresentInt52();
195
196 FlushedAt flushedAt()
197 {
198 return FlushedAt(flushFormat(), machineLocal());
199 }
200
201private:
202 bool couldRepresentInt52Impl();
203
204 // This is slightly space-inefficient, since anything we're unified with
205 // will have the same operand and should have the same prediction. But
206 // putting them here simplifies the code, and we don't expect DFG space
207 // usage for variable access nodes do be significant.
208
209 VirtualRegister m_local;
210 VirtualRegister m_machineLocal;
211 SpeculatedType m_prediction;
212 SpeculatedType m_argumentAwarePrediction;
213 NodeFlags m_flags;
214
215 bool m_shouldNeverUnbox;
216 bool m_structureCheckHoistingFailed;
217 bool m_checkArrayHoistingFailed;
218 bool m_isProfitableToUnbox;
219 bool m_isLoadedFrom;
220
221 float m_votes[2]; // Used primarily for double voting but may be reused for other purposes.
222 DoubleFormatState m_doubleFormatState;
223};
224
225} } // namespace JSC::DFG
226
227#endif // ENABLE(DFG_JIT)
228