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 <dfg/DFGJITCompiler.h>
33 namespace JSC { namespace DFG {
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!)
43 DataFormatInteger = 1,
45 DataFormatBoolean = 3,
48 DataFormatJSInteger = DataFormatJS | DataFormatInteger,
49 DataFormatJSDouble = DataFormatJS | DataFormatDouble,
50 DataFormatJSCell = DataFormatJS | DataFormatCell,
51 DataFormatJSBoolean = DataFormatJS | DataFormatBoolean
55 inline const char* dataFormatToString(DataFormat dataFormat)
60 case DataFormatInteger:
62 case DataFormatDouble:
66 case DataFormatBoolean:
70 case DataFormatJSInteger:
72 case DataFormatJSDouble:
74 case DataFormatJSCell:
76 case DataFormatJSBoolean:
84 inline bool needDataFormatConversion(DataFormat from, DataFormat to)
86 ASSERT(from != DataFormatNone);
87 ASSERT(to != DataFormatNone);
89 case DataFormatInteger:
90 case DataFormatDouble:
94 case DataFormatJSInteger:
95 case DataFormatJSDouble:
96 case DataFormatJSCell:
97 case DataFormatJSBoolean:
99 case DataFormatInteger:
100 case DataFormatDouble:
104 case DataFormatJSInteger:
105 case DataFormatJSDouble:
106 case DataFormatJSCell:
107 case DataFormatJSBoolean:
110 // This captures DataFormatBoolean, which is currently unused.
111 ASSERT_NOT_REACHED();
114 // This captures DataFormatBoolean, which is currently unused.
115 ASSERT_NOT_REACHED();
120 inline bool isJSFormat(DataFormat format, DataFormat expectedFormat)
122 ASSERT(expectedFormat & DataFormatJS);
123 return (format | DataFormatJS) == expectedFormat;
126 inline bool isJSInteger(DataFormat format)
128 return isJSFormat(format, DataFormatJSInteger);
131 inline bool isJSDouble(DataFormat format)
133 return isJSFormat(format, DataFormatJSDouble);
136 inline bool isJSCell(DataFormat format)
138 return isJSFormat(format, DataFormatJSCell);
141 inline bool isJSBoolean(DataFormat format)
143 return isJSFormat(format, DataFormatJSBoolean);
146 // === GenerationInfo ===
148 // This class is used to track the current status of a live values during code generation.
149 // Can provide information as to whether a value is in machine registers, and if so which,
150 // whether a value has been spilled to the RegsiterFile, and if so may be able to provide
151 // details of the format in memory (all values are spilled in a boxed form, but we may be
152 // able to track the type of box), and tracks how many outstanding uses of a value remain,
153 // so that we know when the value is dead and the machine registers associated with it
155 class GenerationInfo {
158 : m_nodeIndex(NoNode)
160 , m_registerFormat(DataFormatNone)
161 , m_spillFormat(DataFormatNone)
166 void initConstant(NodeIndex nodeIndex, uint32_t useCount)
168 m_nodeIndex = nodeIndex;
169 m_useCount = useCount;
170 m_registerFormat = DataFormatNone;
171 m_spillFormat = DataFormatNone;
174 void initInteger(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
176 m_nodeIndex = nodeIndex;
177 m_useCount = useCount;
178 m_registerFormat = DataFormatInteger;
179 m_spillFormat = DataFormatNone;
183 void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS)
185 ASSERT(format & DataFormatJS);
187 m_nodeIndex = nodeIndex;
188 m_useCount = useCount;
189 m_registerFormat = format;
190 m_spillFormat = DataFormatNone;
194 void initCell(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
196 m_nodeIndex = nodeIndex;
197 m_useCount = useCount;
198 m_registerFormat = DataFormatCell;
199 m_spillFormat = DataFormatNone;
203 void initDouble(NodeIndex nodeIndex, uint32_t useCount, FPRReg fpr)
205 m_nodeIndex = nodeIndex;
206 m_useCount = useCount;
207 m_registerFormat = DataFormatDouble;
208 m_spillFormat = DataFormatNone;
213 // Get the index of the node that produced this value.
214 NodeIndex nodeIndex() { return m_nodeIndex; }
216 // Mark the value as having been used (decrement the useCount).
217 // Returns true if this was the last use of the value, and any
218 // associated machine registers may be freed.
221 return !--m_useCount;
224 // Used to check the operands of operations to see if they are on
225 // their last use; in some cases it may be safe to reuse the same
226 // machine register for the result of the operation.
230 return m_useCount == 1;
233 // Get the format of the value in machine registers (or 'none').
234 DataFormat registerFormat() { return m_registerFormat; }
235 // Get the format of the value as it is spilled in the RegisterFile (or 'none').
236 DataFormat spillFormat() { return m_spillFormat; }
238 bool isJSFormat(DataFormat expectedFormat)
240 return DFG::isJSFormat(registerFormat(), expectedFormat) || DFG::isJSFormat(spillFormat(), expectedFormat);
245 return isJSFormat(DataFormatJSInteger);
250 return isJSFormat(DataFormatJSDouble);
255 return isJSFormat(DataFormatJSCell);
260 return isJSFormat(DataFormatJSBoolean);
263 // Get the machine resister currently holding the value.
264 GPRReg gpr() { ASSERT(m_registerFormat && m_registerFormat != DataFormatDouble); return u.gpr; }
265 FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble); return u.fpr; }
267 // Check whether a value needs spilling in order to free up any associated machine registers.
270 // This should only be called on values that are currently in a register.
271 ASSERT(m_registerFormat != DataFormatNone);
272 // Constants do not need spilling, nor do values that have already been
273 // spilled to the RegisterFile.
277 // Called when a VirtualRegister is being spilled to the RegisterFile for the first time.
278 void spill(DataFormat spillFormat)
280 // We shouldn't be spill values that don't need spilling.
282 ASSERT(m_spillFormat == DataFormatNone);
283 // We should only be spilling values that are currently in machine registers.
284 ASSERT(m_registerFormat != DataFormatNone);
285 // We only spill values that have been boxed as a JSValue; otherwise the GC
286 // would need a way to distinguish cell pointers from numeric primitives.
287 ASSERT(spillFormat & DataFormatJS);
289 m_registerFormat = DataFormatNone;
290 m_spillFormat = spillFormat;
294 // Called on values that don't need spilling (constants and values that have
295 // already been spilled), to mark them as no longer being in machine registers.
298 // Should only be called on values that don't need spilling, and are currently in registers.
299 ASSERT(m_canFill && m_registerFormat != DataFormatNone);
300 m_registerFormat = DataFormatNone;
305 m_spillFormat = DataFormatNone;
309 // Record that this value is filled into machine registers,
310 // tracking which registers, and what format the value has.
311 void fillJSValue(GPRReg gpr, DataFormat format = DataFormatJS)
313 ASSERT(format & DataFormatJS);
314 m_registerFormat = format;
317 void fillInteger(GPRReg gpr)
319 m_registerFormat = DataFormatInteger;
322 void fillDouble(FPRReg fpr)
324 m_registerFormat = DataFormatDouble;
334 // The index of the node whose result is stored in this virtual register.
335 // FIXME: Can we remove this? - this is currently only used when collecting
336 // snapshots of the RegisterBank for SpeculationCheck/EntryLocation. Could
337 // investigate storing NodeIndex as the name in RegsiterBank, instead of
339 NodeIndex m_nodeIndex;
341 DataFormat m_registerFormat;
342 DataFormat m_spillFormat;
350 } } // namespace JSC::DFG