3 * Copyright (C) 2011 Apple Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #ifndef DFGGenerationInfo_h
28 #define DFGGenerationInfo_h
32 #include "DataFormat.h"
33 #include <dfg/DFGJITCompiler.h>
35 namespace JSC
{ namespace DFG
{
37 // === GenerationInfo ===
39 // This class is used to track the current status of a live values during code generation.
40 // Can provide information as to whether a value is in machine registers, and if so which,
41 // whether a value has been spilled to the RegsiterFile, and if so may be able to provide
42 // details of the format in memory (all values are spilled in a boxed form, but we may be
43 // able to track the type of box), and tracks how many outstanding uses of a value remain,
44 // so that we know when the value is dead and the machine registers associated with it
46 class GenerationInfo
{
51 , m_registerFormat(DataFormatNone
)
52 , m_spillFormat(DataFormatNone
)
57 void initConstant(NodeIndex nodeIndex
, uint32_t useCount
)
59 m_nodeIndex
= nodeIndex
;
60 m_useCount
= useCount
;
61 m_registerFormat
= DataFormatNone
;
62 m_spillFormat
= DataFormatNone
;
66 void initInteger(NodeIndex nodeIndex
, uint32_t useCount
, GPRReg gpr
)
68 m_nodeIndex
= nodeIndex
;
69 m_useCount
= useCount
;
70 m_registerFormat
= DataFormatInteger
;
71 m_spillFormat
= DataFormatNone
;
77 void initJSValue(NodeIndex nodeIndex
, uint32_t useCount
, GPRReg gpr
, DataFormat format
= DataFormatJS
)
79 ASSERT(format
& DataFormatJS
);
81 m_nodeIndex
= nodeIndex
;
82 m_useCount
= useCount
;
83 m_registerFormat
= format
;
84 m_spillFormat
= DataFormatNone
;
89 #elif USE(JSVALUE32_64)
90 void initJSValue(NodeIndex nodeIndex
, uint32_t useCount
, GPRReg tagGPR
, GPRReg payloadGPR
, DataFormat format
= DataFormatJS
)
92 ASSERT(format
& DataFormatJS
);
94 m_nodeIndex
= nodeIndex
;
95 m_useCount
= useCount
;
96 m_registerFormat
= format
;
97 m_spillFormat
= DataFormatNone
;
100 u
.v
.payloadGPR
= payloadGPR
;
104 void initCell(NodeIndex nodeIndex
, uint32_t useCount
, GPRReg gpr
)
106 m_nodeIndex
= nodeIndex
;
107 m_useCount
= useCount
;
108 m_registerFormat
= DataFormatCell
;
109 m_spillFormat
= DataFormatNone
;
114 void initBoolean(NodeIndex nodeIndex
, uint32_t useCount
, GPRReg gpr
)
116 m_nodeIndex
= nodeIndex
;
117 m_useCount
= useCount
;
118 m_registerFormat
= DataFormatBoolean
;
119 m_spillFormat
= DataFormatNone
;
124 void initDouble(NodeIndex nodeIndex
, uint32_t useCount
, FPRReg fpr
)
126 ASSERT(fpr
!= InvalidFPRReg
);
127 m_nodeIndex
= nodeIndex
;
128 m_useCount
= useCount
;
129 m_registerFormat
= DataFormatDouble
;
130 m_spillFormat
= DataFormatNone
;
135 void initStorage(NodeIndex nodeIndex
, uint32_t useCount
, GPRReg gpr
)
137 m_nodeIndex
= nodeIndex
;
138 m_useCount
= useCount
;
139 m_registerFormat
= DataFormatStorage
;
140 m_spillFormat
= DataFormatNone
;
146 // Get the index of the node that produced this value.
147 NodeIndex
nodeIndex() { return m_nodeIndex
; }
149 // Mark the value as having been used (decrement the useCount).
150 // Returns true if this was the last use of the value, and any
151 // associated machine registers may be freed.
155 return !--m_useCount
;
158 // Used to check the operands of operations to see if they are on
159 // their last use; in some cases it may be safe to reuse the same
160 // machine register for the result of the operation.
164 return m_useCount
== 1;
167 // Get the format of the value in machine registers (or 'none').
168 DataFormat
registerFormat() { return m_registerFormat
; }
169 // Get the format of the value as it is spilled in the RegisterFile (or 'none').
170 DataFormat
spillFormat() { return m_spillFormat
; }
172 bool isJSFormat(DataFormat expectedFormat
)
174 return JSC::isJSFormat(registerFormat(), expectedFormat
) || JSC::isJSFormat(spillFormat(), expectedFormat
);
179 return isJSFormat(DataFormatJSInteger
);
184 return isJSFormat(DataFormatJSDouble
);
189 return isJSFormat(DataFormatJSCell
);
194 return isJSFormat(DataFormatJSBoolean
);
199 return spillFormat() == DataFormatNone
200 ? registerFormat() == DataFormatJS
|| registerFormat() == DataFormatNone
201 : spillFormat() == DataFormatJS
;
204 // Get the machine resister currently holding the value.
206 GPRReg
gpr() { ASSERT(m_registerFormat
&& m_registerFormat
!= DataFormatDouble
); return u
.gpr
; }
207 FPRReg
fpr() { ASSERT(m_registerFormat
== DataFormatDouble
); return u
.fpr
; }
208 JSValueRegs
jsValueRegs() { ASSERT(m_registerFormat
& DataFormatJS
); return JSValueRegs(u
.gpr
); }
209 #elif USE(JSVALUE32_64)
210 GPRReg
gpr() { ASSERT(!(m_registerFormat
& DataFormatJS
) && m_registerFormat
!= DataFormatDouble
); return u
.gpr
; }
211 GPRReg
tagGPR() { ASSERT(m_registerFormat
& DataFormatJS
); return u
.v
.tagGPR
; }
212 GPRReg
payloadGPR() { ASSERT(m_registerFormat
& DataFormatJS
); return u
.v
.payloadGPR
; }
213 FPRReg
fpr() { ASSERT(m_registerFormat
== DataFormatDouble
|| m_registerFormat
== DataFormatJSDouble
); return u
.fpr
; }
214 JSValueRegs
jsValueRegs() { ASSERT(m_registerFormat
& DataFormatJS
); return JSValueRegs(u
.v
.tagGPR
, u
.v
.payloadGPR
); }
217 // Check whether a value needs spilling in order to free up any associated machine registers.
220 // This should only be called on values that are currently in a register.
221 ASSERT(m_registerFormat
!= DataFormatNone
);
222 // Constants do not need spilling, nor do values that have already been
223 // spilled to the RegisterFile.
227 // Called when a VirtualRegister is being spilled to the RegisterFile for the first time.
228 void spill(DataFormat spillFormat
)
230 // We shouldn't be spill values that don't need spilling.
232 ASSERT(m_spillFormat
== DataFormatNone
);
233 // We should only be spilling values that are currently in machine registers.
234 ASSERT(m_registerFormat
!= DataFormatNone
);
236 m_registerFormat
= DataFormatNone
;
237 m_spillFormat
= spillFormat
;
241 // Called on values that don't need spilling (constants and values that have
242 // already been spilled), to mark them as no longer being in machine registers.
245 // Should only be called on values that don't need spilling, and are currently in registers.
246 ASSERT(m_canFill
&& m_registerFormat
!= DataFormatNone
);
247 m_registerFormat
= DataFormatNone
;
252 m_spillFormat
= DataFormatNone
;
256 // Record that this value is filled into machine registers,
257 // tracking which registers, and what format the value has.
259 void fillJSValue(GPRReg gpr
, DataFormat format
= DataFormatJS
)
261 ASSERT(format
& DataFormatJS
);
262 m_registerFormat
= format
;
265 #elif USE(JSVALUE32_64)
266 void fillJSValue(GPRReg tagGPR
, GPRReg payloadGPR
, DataFormat format
= DataFormatJS
)
268 ASSERT(format
& DataFormatJS
);
269 m_registerFormat
= format
;
270 u
.v
.tagGPR
= tagGPR
; // FIXME: for JSValues with known type (boolean, integer, cell etc.) no tagGPR is needed?
271 u
.v
.payloadGPR
= payloadGPR
;
273 void fillCell(GPRReg gpr
)
275 m_registerFormat
= DataFormatCell
;
279 void fillInteger(GPRReg gpr
)
281 m_registerFormat
= DataFormatInteger
;
284 void fillBoolean(GPRReg gpr
)
286 m_registerFormat
= DataFormatBoolean
;
289 void fillDouble(FPRReg fpr
)
291 ASSERT(fpr
!= InvalidFPRReg
);
292 m_registerFormat
= DataFormatDouble
;
295 void fillStorage(GPRReg gpr
)
297 m_registerFormat
= DataFormatStorage
;
307 // The index of the node whose result is stored in this virtual register.
308 NodeIndex m_nodeIndex
;
310 DataFormat m_registerFormat
;
311 DataFormat m_spillFormat
;
316 #if USE(JSVALUE32_64)
325 } } // namespace JSC::DFG