1 | /* |
2 | * Copyright (C) 2012 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 | #pragma once |
27 | |
28 | #if ENABLE(DFG_JIT) |
29 | |
30 | #include "DFGMinifiedID.h" |
31 | #include "DataFormat.h" |
32 | #include "MacroAssembler.h" |
33 | #include "VirtualRegister.h" |
34 | #include <stdio.h> |
35 | |
36 | namespace JSC { namespace DFG { |
37 | |
38 | enum VariableEventKind : uint8_t { |
39 | // Marks the beginning of a checkpoint. If you interpret the variable |
40 | // events starting at a Reset point then you'll get everything you need. |
41 | Reset, |
42 | |
43 | // Node births. Points in the code where a node becomes relevant for OSR. |
44 | // It may be the point where it is actually born (i.e. assigned) or it may |
45 | // be a later point, if it's only later in the sequence of instructions |
46 | // that we start to care about this node. |
47 | BirthToFill, |
48 | BirthToSpill, |
49 | Birth, |
50 | |
51 | // Events related to how a node is represented. |
52 | Fill, |
53 | Spill, |
54 | |
55 | // Death of a node - after this we no longer care about this node. |
56 | Death, |
57 | |
58 | // A MovHintEvent means that a node is being associated with a bytecode operand, |
59 | // but that it has not been stored into that operand. |
60 | MovHintEvent, |
61 | |
62 | // A SetLocalEvent means that a node's value has been stored into the stack. |
63 | SetLocalEvent, |
64 | |
65 | // Used to indicate an uninitialized VariableEvent. Don't use for other |
66 | // purposes. |
67 | InvalidEventKind |
68 | }; |
69 | |
70 | union VariableRepresentation { |
71 | MacroAssembler::RegisterID gpr; |
72 | MacroAssembler::FPRegisterID fpr; |
73 | #if USE(JSVALUE32_64) |
74 | struct { |
75 | MacroAssembler::RegisterID tagGPR; |
76 | MacroAssembler::RegisterID payloadGPR; |
77 | } pair; |
78 | #endif |
79 | int32_t virtualReg; |
80 | }; |
81 | |
82 | class VariableEvent { |
83 | public: |
84 | VariableEvent() |
85 | : m_kind(InvalidEventKind) |
86 | { |
87 | } |
88 | |
89 | static VariableEvent reset() |
90 | { |
91 | VariableEvent event; |
92 | event.m_kind = Reset; |
93 | return event; |
94 | } |
95 | |
96 | static VariableEvent fillGPR(VariableEventKind kind, MinifiedID id, MacroAssembler::RegisterID gpr, DataFormat dataFormat) |
97 | { |
98 | ASSERT(kind == BirthToFill || kind == Fill); |
99 | ASSERT(dataFormat != DataFormatDouble); |
100 | #if USE(JSVALUE32_64) |
101 | ASSERT(!(dataFormat & DataFormatJS)); |
102 | #endif |
103 | VariableEvent event; |
104 | WhichType which; |
105 | which.id = id.bits(); |
106 | VariableRepresentation representation; |
107 | representation.gpr = gpr; |
108 | event.m_kind = kind; |
109 | event.m_dataFormat = dataFormat; |
110 | event.m_which = WTFMove(which); |
111 | event.m_representation = WTFMove(representation); |
112 | return event; |
113 | } |
114 | |
115 | #if USE(JSVALUE32_64) |
116 | static VariableEvent fillPair(VariableEventKind kind, MinifiedID id, MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR) |
117 | { |
118 | ASSERT(kind == BirthToFill || kind == Fill); |
119 | VariableEvent event; |
120 | WhichType which; |
121 | which.id = id.bits(); |
122 | VariableRepresentation representation; |
123 | representation.pair.tagGPR = tagGPR; |
124 | representation.pair.payloadGPR = payloadGPR; |
125 | event.m_kind = kind; |
126 | event.m_dataFormat = DataFormatJS; |
127 | event.m_which = WTFMove(which); |
128 | event.m_representation = WTFMove(representation); |
129 | return event; |
130 | } |
131 | #endif // USE(JSVALUE32_64) |
132 | |
133 | static VariableEvent fillFPR(VariableEventKind kind, MinifiedID id, MacroAssembler::FPRegisterID fpr) |
134 | { |
135 | ASSERT(kind == BirthToFill || kind == Fill); |
136 | VariableEvent event; |
137 | WhichType which; |
138 | which.id = id.bits(); |
139 | VariableRepresentation representation; |
140 | representation.fpr = fpr; |
141 | event.m_kind = kind; |
142 | event.m_dataFormat = DataFormatDouble; |
143 | event.m_which = WTFMove(which); |
144 | event.m_representation = WTFMove(representation); |
145 | return event; |
146 | } |
147 | |
148 | static VariableEvent birth(MinifiedID id) |
149 | { |
150 | VariableEvent event; |
151 | WhichType which; |
152 | which.id = id.bits(); |
153 | event.m_kind = Birth; |
154 | event.m_which = WTFMove(which); |
155 | return event; |
156 | } |
157 | |
158 | static VariableEvent spill(VariableEventKind kind, MinifiedID id, VirtualRegister virtualRegister, DataFormat format) |
159 | { |
160 | ASSERT(kind == BirthToSpill || kind == Spill); |
161 | VariableEvent event; |
162 | WhichType which; |
163 | which.id = id.bits(); |
164 | VariableRepresentation representation; |
165 | representation.virtualReg = virtualRegister.offset(); |
166 | event.m_kind = kind; |
167 | event.m_dataFormat = format; |
168 | event.m_which = WTFMove(which); |
169 | event.m_representation = WTFMove(representation); |
170 | return event; |
171 | } |
172 | |
173 | static VariableEvent death(MinifiedID id) |
174 | { |
175 | VariableEvent event; |
176 | WhichType which; |
177 | which.id = id.bits(); |
178 | event.m_kind = Death; |
179 | event.m_which = WTFMove(which); |
180 | return event; |
181 | } |
182 | |
183 | static VariableEvent setLocal( |
184 | VirtualRegister bytecodeReg, VirtualRegister machineReg, DataFormat format) |
185 | { |
186 | VariableEvent event; |
187 | WhichType which; |
188 | which.virtualReg = machineReg.offset(); |
189 | VariableRepresentation representation; |
190 | representation.virtualReg = bytecodeReg.offset(); |
191 | event.m_kind = SetLocalEvent; |
192 | event.m_dataFormat = format; |
193 | event.m_which = WTFMove(which); |
194 | event.m_representation = WTFMove(representation); |
195 | return event; |
196 | } |
197 | |
198 | static VariableEvent movHint(MinifiedID id, VirtualRegister bytecodeReg) |
199 | { |
200 | VariableEvent event; |
201 | WhichType which; |
202 | which.id = id.bits(); |
203 | VariableRepresentation representation; |
204 | representation.virtualReg = bytecodeReg.offset(); |
205 | event.m_kind = MovHintEvent; |
206 | event.m_which = WTFMove(which); |
207 | event.m_representation = WTFMove(representation); |
208 | return event; |
209 | } |
210 | |
211 | VariableEventKind kind() const |
212 | { |
213 | return static_cast<VariableEventKind>(m_kind); |
214 | } |
215 | |
216 | MinifiedID id() const |
217 | { |
218 | ASSERT( |
219 | m_kind == BirthToFill || m_kind == Fill || m_kind == BirthToSpill || m_kind == Spill |
220 | || m_kind == Death || m_kind == MovHintEvent || m_kind == Birth); |
221 | return MinifiedID::fromBits(m_which.get().id); |
222 | } |
223 | |
224 | DataFormat dataFormat() const |
225 | { |
226 | ASSERT( |
227 | m_kind == BirthToFill || m_kind == Fill || m_kind == BirthToSpill || m_kind == Spill |
228 | || m_kind == SetLocalEvent); |
229 | return m_dataFormat; |
230 | } |
231 | |
232 | MacroAssembler::RegisterID gpr() const |
233 | { |
234 | ASSERT(m_kind == BirthToFill || m_kind == Fill); |
235 | ASSERT(m_dataFormat); |
236 | ASSERT(m_dataFormat != DataFormatDouble); |
237 | #if USE(JSVALUE32_64) |
238 | ASSERT(!(m_dataFormat & DataFormatJS)); |
239 | #endif |
240 | return m_representation.get().gpr; |
241 | } |
242 | |
243 | #if USE(JSVALUE32_64) |
244 | MacroAssembler::RegisterID tagGPR() const |
245 | { |
246 | ASSERT(m_kind == BirthToFill || m_kind == Fill); |
247 | ASSERT(m_dataFormat & DataFormatJS); |
248 | return m_representation.get().pair.tagGPR; |
249 | } |
250 | MacroAssembler::RegisterID payloadGPR() const |
251 | { |
252 | ASSERT(m_kind == BirthToFill || m_kind == Fill); |
253 | ASSERT(m_dataFormat & DataFormatJS); |
254 | return m_representation.get().pair.payloadGPR; |
255 | } |
256 | #endif // USE(JSVALUE32_64) |
257 | |
258 | MacroAssembler::FPRegisterID fpr() const |
259 | { |
260 | ASSERT(m_kind == BirthToFill || m_kind == Fill); |
261 | ASSERT(m_dataFormat == DataFormatDouble); |
262 | return m_representation.get().fpr; |
263 | } |
264 | |
265 | VirtualRegister spillRegister() const |
266 | { |
267 | ASSERT(m_kind == BirthToSpill || m_kind == Spill); |
268 | return VirtualRegister(m_representation.get().virtualReg); |
269 | } |
270 | |
271 | VirtualRegister bytecodeRegister() const |
272 | { |
273 | ASSERT(m_kind == SetLocalEvent || m_kind == MovHintEvent); |
274 | return VirtualRegister(m_representation.get().virtualReg); |
275 | } |
276 | |
277 | VirtualRegister machineRegister() const |
278 | { |
279 | ASSERT(m_kind == SetLocalEvent); |
280 | return VirtualRegister(m_which.get().virtualReg); |
281 | } |
282 | |
283 | VariableRepresentation variableRepresentation() const { return m_representation.get(); } |
284 | |
285 | void dump(PrintStream&) const; |
286 | |
287 | private: |
288 | void dumpFillInfo(const char* name, PrintStream&) const; |
289 | void dumpSpillInfo(const char* name, PrintStream&) const; |
290 | |
291 | union WhichType { |
292 | int virtualReg; |
293 | unsigned id; |
294 | }; |
295 | Packed<WhichType> m_which; |
296 | |
297 | // For BirthToFill, Fill: |
298 | // - The GPR or FPR, or a GPR pair. |
299 | // For BirthToSpill, Spill: |
300 | // - The virtual register. |
301 | // For MovHintEvent, SetLocalEvent: |
302 | // - The bytecode operand. |
303 | // For Death: |
304 | // - Unused. |
305 | Packed<VariableRepresentation> m_representation; |
306 | |
307 | VariableEventKind m_kind; |
308 | DataFormat m_dataFormat { DataFormatNone }; |
309 | }; |
310 | |
311 | } } // namespace JSC::DFG |
312 | |
313 | #endif // ENABLE(DFG_JIT) |
314 | |