2 * Copyright (C) 2011 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 DFGGenerationInfo_h
27 #define DFGGenerationInfo_h
31 #include "DataFormat.h"
32 #include <dfg/DFGJITCompiler.h>
34 namespace JSC { namespace DFG {
36 // === GenerationInfo ===
38 // This class is used to track the current status of a live values during code generation.
39 // Can provide information as to whether a value is in machine registers, and if so which,
40 // whether a value has been spilled to the RegsiterFile, and if so may be able to provide
41 // details of the format in memory (all values are spilled in a boxed form, but we may be
42 // able to track the type of box), and tracks how many outstanding uses of a value remain,
43 // so that we know when the value is dead and the machine registers associated with it
45 class GenerationInfo {
50 , m_registerFormat(DataFormatNone)
51 , m_spillFormat(DataFormatNone)
56 void initConstant(NodeIndex nodeIndex, uint32_t useCount)
58 m_nodeIndex = nodeIndex;
59 m_useCount = useCount;
60 m_registerFormat = DataFormatNone;
61 m_spillFormat = DataFormatNone;
64 void initInteger(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
66 m_nodeIndex = nodeIndex;
67 m_useCount = useCount;
68 m_registerFormat = DataFormatInteger;
69 m_spillFormat = DataFormatNone;
74 void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS)
76 ASSERT(format & DataFormatJS);
78 m_nodeIndex = nodeIndex;
79 m_useCount = useCount;
80 m_registerFormat = format;
81 m_spillFormat = DataFormatNone;
85 #elif USE(JSVALUE32_64)
86 void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg tagGPR, GPRReg payloadGPR, DataFormat format = DataFormatJS)
88 ASSERT(format & DataFormatJS);
90 m_nodeIndex = nodeIndex;
91 m_useCount = useCount;
92 m_registerFormat = format;
93 m_spillFormat = DataFormatNone;
96 u.v.payloadGPR = payloadGPR;
99 void initCell(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
101 m_nodeIndex = nodeIndex;
102 m_useCount = useCount;
103 m_registerFormat = DataFormatCell;
104 m_spillFormat = DataFormatNone;
108 void initBoolean(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
110 m_nodeIndex = nodeIndex;
111 m_useCount = useCount;
112 m_registerFormat = DataFormatBoolean;
113 m_spillFormat = DataFormatNone;
117 void initDouble(NodeIndex nodeIndex, uint32_t useCount, FPRReg fpr)
119 ASSERT(fpr != InvalidFPRReg);
120 m_nodeIndex = nodeIndex;
121 m_useCount = useCount;
122 m_registerFormat = DataFormatDouble;
123 m_spillFormat = DataFormatNone;
127 void initStorage(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
129 m_nodeIndex = nodeIndex;
130 m_useCount = useCount;
131 m_registerFormat = DataFormatStorage;
132 m_spillFormat = DataFormatNone;
137 // Get the index of the node that produced this value.
138 NodeIndex nodeIndex() { return m_nodeIndex; }
140 // Mark the value as having been used (decrement the useCount).
141 // Returns true if this was the last use of the value, and any
142 // associated machine registers may be freed.
145 return !--m_useCount;
148 // Used to check the operands of operations to see if they are on
149 // their last use; in some cases it may be safe to reuse the same
150 // machine register for the result of the operation.
154 return m_useCount == 1;
157 // Get the format of the value in machine registers (or 'none').
158 DataFormat registerFormat() { return m_registerFormat; }
159 // Get the format of the value as it is spilled in the RegisterFile (or 'none').
160 DataFormat spillFormat() { return m_spillFormat; }
162 bool isJSFormat(DataFormat expectedFormat)
164 return JSC::isJSFormat(registerFormat(), expectedFormat) || JSC::isJSFormat(spillFormat(), expectedFormat);
169 return isJSFormat(DataFormatJSInteger);
174 return isJSFormat(DataFormatJSDouble);
179 return isJSFormat(DataFormatJSCell);
184 return isJSFormat(DataFormatJSBoolean);
189 return registerFormat() == DataFormatNone || registerFormat() == DataFormatJS
190 || spillFormat() == DataFormatNone || spillFormat() == DataFormatJS;
193 // Get the machine resister currently holding the value.
195 GPRReg gpr() { ASSERT(m_registerFormat && m_registerFormat != DataFormatDouble); return u.gpr; }
196 FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble); return u.fpr; }
197 JSValueRegs jsValueRegs() { ASSERT(m_registerFormat & DataFormatJS); return JSValueRegs(u.gpr); }
198 #elif USE(JSVALUE32_64)
199 GPRReg gpr() { ASSERT(!(m_registerFormat & DataFormatJS) && m_registerFormat != DataFormatDouble); return u.gpr; }
200 GPRReg tagGPR() { ASSERT(m_registerFormat & DataFormatJS); return u.v.tagGPR; }
201 GPRReg payloadGPR() { ASSERT(m_registerFormat & DataFormatJS); return u.v.payloadGPR; }
202 FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble || m_registerFormat == DataFormatJSDouble); return u.fpr; }
203 JSValueRegs jsValueRegs() { ASSERT(m_registerFormat & DataFormatJS); return JSValueRegs(u.v.tagGPR, u.v.payloadGPR); }
206 // Check whether a value needs spilling in order to free up any associated machine registers.
209 // This should only be called on values that are currently in a register.
210 ASSERT(m_registerFormat != DataFormatNone);
211 // Constants do not need spilling, nor do values that have already been
212 // spilled to the RegisterFile.
216 // Called when a VirtualRegister is being spilled to the RegisterFile for the first time.
217 void spill(DataFormat spillFormat)
219 // We shouldn't be spill values that don't need spilling.
221 ASSERT(m_spillFormat == DataFormatNone);
222 // We should only be spilling values that are currently in machine registers.
223 ASSERT(m_registerFormat != DataFormatNone);
224 // We only spill values that have been boxed as a JSValue because historically
225 // we assumed that the GC would want to be able to precisely identify heap
226 // pointers. This is not true anymore, but we still assume, in the fill code,
227 // that any spill slot for a JS value is boxed. For storage pointers, there is
228 // nothing we can do to box them, so we allow that to be an exception.
229 ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatStorage || spillFormat == DataFormatInteger || spillFormat == DataFormatDouble);
231 m_registerFormat = DataFormatNone;
232 m_spillFormat = spillFormat;
236 // Called on values that don't need spilling (constants and values that have
237 // already been spilled), to mark them as no longer being in machine registers.
240 // Should only be called on values that don't need spilling, and are currently in registers.
241 ASSERT(m_canFill && m_registerFormat != DataFormatNone);
242 m_registerFormat = DataFormatNone;
247 m_spillFormat = DataFormatNone;
251 // Record that this value is filled into machine registers,
252 // tracking which registers, and what format the value has.
254 void fillJSValue(GPRReg gpr, DataFormat format = DataFormatJS)
256 ASSERT(format & DataFormatJS);
257 m_registerFormat = format;
260 #elif USE(JSVALUE32_64)
261 void fillJSValue(GPRReg tagGPR, GPRReg payloadGPR, DataFormat format = DataFormatJS)
263 ASSERT(format & DataFormatJS);
264 m_registerFormat = format;
265 u.v.tagGPR = tagGPR; // FIXME: for JSValues with known type (boolean, integer, cell etc.) no tagGPR is needed?
266 u.v.payloadGPR = payloadGPR;
268 void fillCell(GPRReg gpr)
270 m_registerFormat = DataFormatCell;
274 void fillInteger(GPRReg gpr)
276 m_registerFormat = DataFormatInteger;
279 void fillBoolean(GPRReg gpr)
281 m_registerFormat = DataFormatBoolean;
284 void fillDouble(FPRReg fpr)
286 ASSERT(fpr != InvalidFPRReg);
287 m_registerFormat = DataFormatDouble;
290 void fillStorage(GPRReg gpr)
292 m_registerFormat = DataFormatStorage;
302 // The index of the node whose result is stored in this virtual register.
303 NodeIndex m_nodeIndex;
305 DataFormat m_registerFormat;
306 DataFormat m_spillFormat;
311 #if USE(JSVALUE32_64)
320 } } // namespace JSC::DFG