]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGGenerationInfo.h
968ea20eba6df95862efe48563b0715b42473d70
[apple/javascriptcore.git] / dfg / DFGGenerationInfo.h
1 /*
2 * Copyright (C) 2011 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 DFGGenerationInfo_h
27 #define DFGGenerationInfo_h
28
29 #if ENABLE(DFG_JIT)
30
31 #include <dfg/DFGJITCompiler.h>
32
33 namespace JSC { namespace DFG {
34
35 // === DataFormat ===
36 //
37 // This enum tracks the current representation in which a value is being held.
38 // Values may be unboxed primitives (int32, double, or cell), or boxed as a JSValue.
39 // For boxed values, we may know the type of boxing that has taken place.
40 // (May also need bool, array, object, string types!)
41 enum DataFormat {
42 DataFormatNone = 0,
43 DataFormatInteger = 1,
44 DataFormatDouble = 2,
45 DataFormatCell = 3,
46 DataFormatJS = 8,
47 DataFormatJSInteger = DataFormatJS | DataFormatInteger,
48 DataFormatJSDouble = DataFormatJS | DataFormatDouble,
49 DataFormatJSCell = DataFormatJS | DataFormatCell,
50 };
51
52 // === GenerationInfo ===
53 //
54 // This class is used to track the current status of a live values during code generation.
55 // Can provide information as to whether a value is in machine registers, and if so which,
56 // whether a value has been spilled to the RegsiterFile, and if so may be able to provide
57 // details of the format in memory (all values are spilled in a boxed form, but we may be
58 // able to track the type of box), and tracks how many outstanding uses of a value remain,
59 // so that we know when the value is dead and the machine registers associated with it
60 // may be released.
61 class GenerationInfo {
62 public:
63 GenerationInfo()
64 : m_nodeIndex(NoNode)
65 , m_useCount(0)
66 , m_registerFormat(DataFormatNone)
67 , m_spillFormat(DataFormatNone)
68 , m_canFill(false)
69 {
70 }
71
72 void initConstant(NodeIndex nodeIndex, uint32_t useCount)
73 {
74 m_nodeIndex = nodeIndex;
75 m_useCount = useCount;
76 m_registerFormat = DataFormatNone;
77 m_spillFormat = DataFormatNone;
78 m_canFill = true;
79 }
80 void initInteger(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
81 {
82 m_nodeIndex = nodeIndex;
83 m_useCount = useCount;
84 m_registerFormat = DataFormatInteger;
85 m_spillFormat = DataFormatNone;
86 m_canFill = false;
87 u.gpr = gpr;
88 }
89 void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS)
90 {
91 ASSERT(format & DataFormatJS);
92
93 m_nodeIndex = nodeIndex;
94 m_useCount = useCount;
95 m_registerFormat = format;
96 m_spillFormat = DataFormatNone;
97 m_canFill = false;
98 u.gpr = gpr;
99 }
100 void initCell(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
101 {
102 m_nodeIndex = nodeIndex;
103 m_useCount = useCount;
104 m_registerFormat = DataFormatCell;
105 m_spillFormat = DataFormatNone;
106 m_canFill = false;
107 u.gpr = gpr;
108 }
109 void initDouble(NodeIndex nodeIndex, uint32_t useCount, FPRReg fpr)
110 {
111 m_nodeIndex = nodeIndex;
112 m_useCount = useCount;
113 m_registerFormat = DataFormatDouble;
114 m_spillFormat = DataFormatNone;
115 m_canFill = false;
116 u.fpr = fpr;
117 }
118
119 // Get the index of the node that produced this value.
120 NodeIndex nodeIndex() { return m_nodeIndex; }
121
122 // Mark the value as having been used (decrement the useCount).
123 // Returns true if this was the last use of the value, and any
124 // associated machine registers may be freed.
125 bool use()
126 {
127 return !--m_useCount;
128 }
129
130 // Used to check the operands of operations to see if they are on
131 // their last use; in some cases it may be safe to reuse the same
132 // machine register for the result of the operation.
133 bool canReuse()
134 {
135 ASSERT(m_useCount);
136 return m_useCount == 1;
137 }
138
139 // Get the format of the value in machine registers (or 'none').
140 DataFormat registerFormat() { return m_registerFormat; }
141 // Get the format of the value as it is spilled in the RegisterFile (or 'none').
142 DataFormat spillFormat() { return m_spillFormat; }
143
144 // Get the machine resister currently holding the value.
145 GPRReg gpr() { ASSERT(m_registerFormat && m_registerFormat != DataFormatDouble); return u.gpr; }
146 FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble); return u.fpr; }
147
148 // Check whether a value needs spilling in order to free up any associated machine registers.
149 bool needsSpill()
150 {
151 // This should only be called on values that are currently in a register.
152 ASSERT(m_registerFormat != DataFormatNone);
153 // Constants do not need spilling, nor do values that have already been
154 // spilled to the RegisterFile.
155 return !m_canFill;
156 }
157
158 // Called when a VirtualRegister is being spilled to the RegisterFile for the first time.
159 void spill(DataFormat spillFormat)
160 {
161 // We shouldn't be spill values that don't need spilling.
162 ASSERT(!m_canFill);
163 ASSERT(m_spillFormat == DataFormatNone);
164 // We should only be spilling values that are currently in machine registers.
165 ASSERT(m_registerFormat != DataFormatNone);
166 // We only spill values that have been boxed as a JSValue; otherwise the GC
167 // would need a way to distinguish cell pointers from numeric primitives.
168 ASSERT(spillFormat & DataFormatJS);
169
170 m_registerFormat = DataFormatNone;
171 m_spillFormat = spillFormat;
172 m_canFill = true;
173 }
174
175 // Called on values that don't need spilling (constants and values that have
176 // already been spilled), to mark them as no longer being in machine registers.
177 void setSpilled()
178 {
179 // Should only be called on values that don't need spilling, and are currently in registers.
180 ASSERT(m_canFill && m_registerFormat != DataFormatNone);
181 m_registerFormat = DataFormatNone;
182 }
183
184 // Record that this value is filled into machine registers,
185 // tracking which registers, and what format the value has.
186 void fillJSValue(GPRReg gpr, DataFormat format = DataFormatJS)
187 {
188 ASSERT(format & DataFormatJS);
189 m_registerFormat = format;
190 u.gpr = gpr;
191 }
192 void fillInteger(GPRReg gpr)
193 {
194 m_registerFormat = DataFormatInteger;
195 u.gpr = gpr;
196 }
197 void fillDouble(FPRReg fpr)
198 {
199 m_registerFormat = DataFormatDouble;
200 u.fpr = fpr;
201 }
202
203 #ifndef NDEBUG
204 bool alive()
205 {
206 return m_useCount;
207 }
208 #endif
209
210 private:
211 // The index of the node whose result is stored in this virtual register.
212 // FIXME: Can we remove this? - this is currently only used when collecting
213 // snapshots of the RegisterBank for SpeculationCheck/EntryLocation. Could
214 // investigate storing NodeIndex as the name in RegsiterBank, instead of
215 // VirtualRegister.
216 NodeIndex m_nodeIndex;
217 uint32_t m_useCount;
218 DataFormat m_registerFormat;
219 DataFormat m_spillFormat;
220 bool m_canFill;
221 union {
222 GPRReg gpr;
223 FPRReg fpr;
224 } u;
225 };
226
227 } } // namespace JSC::DFG
228
229 #endif
230 #endif