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,
47 DataFormatJSInteger
= DataFormatJS
| DataFormatInteger
,
48 DataFormatJSDouble
= DataFormatJS
| DataFormatDouble
,
49 DataFormatJSCell
= DataFormatJS
| DataFormatCell
,
52 // === GenerationInfo ===
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
61 class GenerationInfo
{
66 , m_registerFormat(DataFormatNone
)
67 , m_spillFormat(DataFormatNone
)
72 void initConstant(NodeIndex nodeIndex
, uint32_t useCount
)
74 m_nodeIndex
= nodeIndex
;
75 m_useCount
= useCount
;
76 m_registerFormat
= DataFormatNone
;
77 m_spillFormat
= DataFormatNone
;
80 void initInteger(NodeIndex nodeIndex
, uint32_t useCount
, GPRReg gpr
)
82 m_nodeIndex
= nodeIndex
;
83 m_useCount
= useCount
;
84 m_registerFormat
= DataFormatInteger
;
85 m_spillFormat
= DataFormatNone
;
89 void initJSValue(NodeIndex nodeIndex
, uint32_t useCount
, GPRReg gpr
, DataFormat format
= DataFormatJS
)
91 ASSERT(format
& DataFormatJS
);
93 m_nodeIndex
= nodeIndex
;
94 m_useCount
= useCount
;
95 m_registerFormat
= format
;
96 m_spillFormat
= DataFormatNone
;
100 void initCell(NodeIndex nodeIndex
, uint32_t useCount
, GPRReg gpr
)
102 m_nodeIndex
= nodeIndex
;
103 m_useCount
= useCount
;
104 m_registerFormat
= DataFormatCell
;
105 m_spillFormat
= DataFormatNone
;
109 void initDouble(NodeIndex nodeIndex
, uint32_t useCount
, FPRReg fpr
)
111 m_nodeIndex
= nodeIndex
;
112 m_useCount
= useCount
;
113 m_registerFormat
= DataFormatDouble
;
114 m_spillFormat
= DataFormatNone
;
119 // Get the index of the node that produced this value.
120 NodeIndex
nodeIndex() { return m_nodeIndex
; }
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.
127 return !--m_useCount
;
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.
136 return m_useCount
== 1;
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
; }
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
; }
148 // Check whether a value needs spilling in order to free up any associated machine registers.
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.
158 // Called when a VirtualRegister is being spilled to the RegisterFile for the first time.
159 void spill(DataFormat spillFormat
)
161 // We shouldn't be spill values that don't need spilling.
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
);
170 m_registerFormat
= DataFormatNone
;
171 m_spillFormat
= spillFormat
;
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.
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
;
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
)
188 ASSERT(format
& DataFormatJS
);
189 m_registerFormat
= format
;
192 void fillInteger(GPRReg gpr
)
194 m_registerFormat
= DataFormatInteger
;
197 void fillDouble(FPRReg fpr
)
199 m_registerFormat
= DataFormatDouble
;
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
216 NodeIndex m_nodeIndex
;
218 DataFormat m_registerFormat
;
219 DataFormat m_spillFormat
;
227 } } // namespace JSC::DFG