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
36namespace JSC { namespace DFG {
37
38enum VariableEventKind {
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
70union 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
82class VariableEvent {
83public:
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 event.m_which.id = id.bits();
105 event.m_representation.gpr = gpr;
106 event.m_kind = kind;
107 event.m_dataFormat = dataFormat;
108 return event;
109 }
110
111#if USE(JSVALUE32_64)
112 static VariableEvent fillPair(VariableEventKind kind, MinifiedID id, MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR)
113 {
114 ASSERT(kind == BirthToFill || kind == Fill);
115 VariableEvent event;
116 event.m_which.id = id.bits();
117 event.m_representation.pair.tagGPR = tagGPR;
118 event.m_representation.pair.payloadGPR = payloadGPR;
119 event.m_kind = kind;
120 event.m_dataFormat = DataFormatJS;
121 return event;
122 }
123#endif // USE(JSVALUE32_64)
124
125 static VariableEvent fillFPR(VariableEventKind kind, MinifiedID id, MacroAssembler::FPRegisterID fpr)
126 {
127 ASSERT(kind == BirthToFill || kind == Fill);
128 VariableEvent event;
129 event.m_which.id = id.bits();
130 event.m_representation.fpr = fpr;
131 event.m_kind = kind;
132 event.m_dataFormat = DataFormatDouble;
133 return event;
134 }
135
136 static VariableEvent birth(MinifiedID id)
137 {
138 VariableEvent event;
139 event.m_which.id = id.bits();
140 event.m_kind = Birth;
141 return event;
142 }
143
144 static VariableEvent spill(VariableEventKind kind, MinifiedID id, VirtualRegister virtualRegister, DataFormat format)
145 {
146 ASSERT(kind == BirthToSpill || kind == Spill);
147 VariableEvent event;
148 event.m_which.id = id.bits();
149 event.m_representation.virtualReg = virtualRegister.offset();
150 event.m_kind = kind;
151 event.m_dataFormat = format;
152 return event;
153 }
154
155 static VariableEvent death(MinifiedID id)
156 {
157 VariableEvent event;
158 event.m_which.id = id.bits();
159 event.m_kind = Death;
160 return event;
161 }
162
163 static VariableEvent setLocal(
164 VirtualRegister bytecodeReg, VirtualRegister machineReg, DataFormat format)
165 {
166 VariableEvent event;
167 event.m_which.virtualReg = machineReg.offset();
168 event.m_representation.virtualReg = bytecodeReg.offset();
169 event.m_kind = SetLocalEvent;
170 event.m_dataFormat = format;
171 return event;
172 }
173
174 static VariableEvent movHint(MinifiedID id, VirtualRegister bytecodeReg)
175 {
176 VariableEvent event;
177 event.m_which.id = id.bits();
178 event.m_representation.virtualReg = bytecodeReg.offset();
179 event.m_kind = MovHintEvent;
180 return event;
181 }
182
183 VariableEventKind kind() const
184 {
185 return static_cast<VariableEventKind>(m_kind);
186 }
187
188 MinifiedID id() const
189 {
190 ASSERT(
191 m_kind == BirthToFill || m_kind == Fill || m_kind == BirthToSpill || m_kind == Spill
192 || m_kind == Death || m_kind == MovHintEvent || m_kind == Birth);
193 return MinifiedID::fromBits(m_which.id);
194 }
195
196 DataFormat dataFormat() const
197 {
198 ASSERT(
199 m_kind == BirthToFill || m_kind == Fill || m_kind == BirthToSpill || m_kind == Spill
200 || m_kind == SetLocalEvent);
201 return static_cast<DataFormat>(m_dataFormat);
202 }
203
204 MacroAssembler::RegisterID gpr() const
205 {
206 ASSERT(m_kind == BirthToFill || m_kind == Fill);
207 ASSERT(m_dataFormat);
208 ASSERT(m_dataFormat != DataFormatDouble);
209#if USE(JSVALUE32_64)
210 ASSERT(!(m_dataFormat & DataFormatJS));
211#endif
212 return m_representation.gpr;
213 }
214
215#if USE(JSVALUE32_64)
216 MacroAssembler::RegisterID tagGPR() const
217 {
218 ASSERT(m_kind == BirthToFill || m_kind == Fill);
219 ASSERT(m_dataFormat & DataFormatJS);
220 return m_representation.pair.tagGPR;
221 }
222 MacroAssembler::RegisterID payloadGPR() const
223 {
224 ASSERT(m_kind == BirthToFill || m_kind == Fill);
225 ASSERT(m_dataFormat & DataFormatJS);
226 return m_representation.pair.payloadGPR;
227 }
228#endif // USE(JSVALUE32_64)
229
230 MacroAssembler::FPRegisterID fpr() const
231 {
232 ASSERT(m_kind == BirthToFill || m_kind == Fill);
233 ASSERT(m_dataFormat == DataFormatDouble);
234 return m_representation.fpr;
235 }
236
237 VirtualRegister spillRegister() const
238 {
239 ASSERT(m_kind == BirthToSpill || m_kind == Spill);
240 return VirtualRegister(m_representation.virtualReg);
241 }
242
243 VirtualRegister bytecodeRegister() const
244 {
245 ASSERT(m_kind == SetLocalEvent || m_kind == MovHintEvent);
246 return VirtualRegister(m_representation.virtualReg);
247 }
248
249 VirtualRegister machineRegister() const
250 {
251 ASSERT(m_kind == SetLocalEvent);
252 return VirtualRegister(m_which.virtualReg);
253 }
254
255 const VariableRepresentation& variableRepresentation() const { return m_representation; }
256
257 void dump(PrintStream&) const;
258
259private:
260 void dumpFillInfo(const char* name, PrintStream&) const;
261 void dumpSpillInfo(const char* name, PrintStream&) const;
262
263 union {
264 int virtualReg;
265 uintptr_t id;
266 } m_which;
267
268 // For BirthToFill, Fill:
269 // - The GPR or FPR, or a GPR pair.
270 // For BirthToSpill, Spill:
271 // - The virtual register.
272 // For MovHintEvent, SetLocalEvent:
273 // - The bytecode operand.
274 // For Death:
275 // - Unused.
276 VariableRepresentation m_representation;
277
278 int8_t m_kind;
279 int8_t m_dataFormat;
280};
281
282} } // namespace JSC::DFG
283
284#endif // ENABLE(DFG_JIT)
285