]> git.saurik.com Git - apple/javascriptcore.git/blob - bytecode/ValueRecovery.h
JavaScriptCore-1097.3.3.tar.gz
[apple/javascriptcore.git] / bytecode / ValueRecovery.h
1 /*
2 * Copyright (C) 2011 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 #ifndef ValueRecovery_h
27 #define ValueRecovery_h
28
29 #include "DataFormat.h"
30 #include "JSValue.h"
31 #include "MacroAssembler.h"
32 #include "VirtualRegister.h"
33 #include <stdio.h>
34 #include <wtf/Platform.h>
35
36 namespace JSC {
37
38 // Describes how to recover a given bytecode virtual register at a given
39 // code point.
40 enum ValueRecoveryTechnique {
41 // It's already in the register file at the right location.
42 AlreadyInRegisterFile,
43 // It's already in the register file but unboxed.
44 AlreadyInRegisterFileAsUnboxedInt32,
45 AlreadyInRegisterFileAsUnboxedCell,
46 AlreadyInRegisterFileAsUnboxedBoolean,
47 AlreadyInRegisterFileAsUnboxedDouble,
48 // It's in a register.
49 InGPR,
50 UnboxedInt32InGPR,
51 UnboxedBooleanInGPR,
52 #if USE(JSVALUE32_64)
53 InPair,
54 #endif
55 InFPR,
56 UInt32InGPR,
57 // It's in the register file, but at a different location.
58 DisplacedInRegisterFile,
59 // It's in the register file, at a different location, and it's unboxed.
60 Int32DisplacedInRegisterFile,
61 DoubleDisplacedInRegisterFile,
62 CellDisplacedInRegisterFile,
63 BooleanDisplacedInRegisterFile,
64 // It's a constant.
65 Constant,
66 // Don't know how to recover it.
67 DontKnow
68 };
69
70 class ValueRecovery {
71 public:
72 ValueRecovery()
73 : m_technique(DontKnow)
74 {
75 }
76
77 static ValueRecovery alreadyInRegisterFile()
78 {
79 ValueRecovery result;
80 result.m_technique = AlreadyInRegisterFile;
81 return result;
82 }
83
84 static ValueRecovery alreadyInRegisterFileAsUnboxedInt32()
85 {
86 ValueRecovery result;
87 result.m_technique = AlreadyInRegisterFileAsUnboxedInt32;
88 return result;
89 }
90
91 static ValueRecovery alreadyInRegisterFileAsUnboxedCell()
92 {
93 ValueRecovery result;
94 result.m_technique = AlreadyInRegisterFileAsUnboxedCell;
95 return result;
96 }
97
98 static ValueRecovery alreadyInRegisterFileAsUnboxedBoolean()
99 {
100 ValueRecovery result;
101 result.m_technique = AlreadyInRegisterFileAsUnboxedBoolean;
102 return result;
103 }
104
105 static ValueRecovery alreadyInRegisterFileAsUnboxedDouble()
106 {
107 ValueRecovery result;
108 result.m_technique = AlreadyInRegisterFileAsUnboxedDouble;
109 return result;
110 }
111
112 static ValueRecovery inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat)
113 {
114 ASSERT(dataFormat != DataFormatNone);
115 #if USE(JSVALUE32_64)
116 ASSERT(dataFormat == DataFormatInteger || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean);
117 #endif
118 ValueRecovery result;
119 if (dataFormat == DataFormatInteger)
120 result.m_technique = UnboxedInt32InGPR;
121 else if (dataFormat == DataFormatBoolean)
122 result.m_technique = UnboxedBooleanInGPR;
123 else
124 result.m_technique = InGPR;
125 result.m_source.gpr = gpr;
126 return result;
127 }
128
129 static ValueRecovery uint32InGPR(MacroAssembler::RegisterID gpr)
130 {
131 ValueRecovery result;
132 result.m_technique = UInt32InGPR;
133 result.m_source.gpr = gpr;
134 return result;
135 }
136
137 #if USE(JSVALUE32_64)
138 static ValueRecovery inPair(MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR)
139 {
140 ValueRecovery result;
141 result.m_technique = InPair;
142 result.m_source.pair.tagGPR = tagGPR;
143 result.m_source.pair.payloadGPR = payloadGPR;
144 return result;
145 }
146 #endif
147
148 static ValueRecovery inFPR(MacroAssembler::FPRegisterID fpr)
149 {
150 ValueRecovery result;
151 result.m_technique = InFPR;
152 result.m_source.fpr = fpr;
153 return result;
154 }
155
156 static ValueRecovery displacedInRegisterFile(VirtualRegister virtualReg, DataFormat dataFormat)
157 {
158 ValueRecovery result;
159 switch (dataFormat) {
160 case DataFormatInteger:
161 result.m_technique = Int32DisplacedInRegisterFile;
162 break;
163
164 case DataFormatDouble:
165 result.m_technique = DoubleDisplacedInRegisterFile;
166 break;
167
168 case DataFormatCell:
169 result.m_technique = CellDisplacedInRegisterFile;
170 break;
171
172 case DataFormatBoolean:
173 result.m_technique = BooleanDisplacedInRegisterFile;
174 break;
175
176 default:
177 ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage);
178 result.m_technique = DisplacedInRegisterFile;
179 break;
180 }
181 result.m_source.virtualReg = virtualReg;
182 return result;
183 }
184
185 static ValueRecovery constant(JSValue value)
186 {
187 ValueRecovery result;
188 result.m_technique = Constant;
189 result.m_source.constant = JSValue::encode(value);
190 return result;
191 }
192
193 ValueRecoveryTechnique technique() const { return m_technique; }
194
195 bool isConstant() const { return m_technique == Constant; }
196
197 bool isInRegisters() const
198 {
199 switch (m_technique) {
200 case InGPR:
201 case UnboxedInt32InGPR:
202 case UnboxedBooleanInGPR:
203 #if USE(JSVALUE32_64)
204 case InPair:
205 #endif
206 case InFPR:
207 return true;
208 default:
209 return false;
210 }
211 }
212
213 bool isAlreadyInRegisterFile() const
214 {
215 switch (technique()) {
216 case AlreadyInRegisterFile:
217 case AlreadyInRegisterFileAsUnboxedInt32:
218 case AlreadyInRegisterFileAsUnboxedCell:
219 case AlreadyInRegisterFileAsUnboxedBoolean:
220 case AlreadyInRegisterFileAsUnboxedDouble:
221 return true;
222 default:
223 return false;
224 }
225 }
226
227 MacroAssembler::RegisterID gpr() const
228 {
229 ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR);
230 return m_source.gpr;
231 }
232
233 #if USE(JSVALUE32_64)
234 MacroAssembler::RegisterID tagGPR() const
235 {
236 ASSERT(m_technique == InPair);
237 return m_source.pair.tagGPR;
238 }
239
240 MacroAssembler::RegisterID payloadGPR() const
241 {
242 ASSERT(m_technique == InPair);
243 return m_source.pair.payloadGPR;
244 }
245 #endif
246
247 MacroAssembler::FPRegisterID fpr() const
248 {
249 ASSERT(m_technique == InFPR);
250 return m_source.fpr;
251 }
252
253 VirtualRegister virtualRegister() const
254 {
255 ASSERT(m_technique == DisplacedInRegisterFile || m_technique == Int32DisplacedInRegisterFile || m_technique == DoubleDisplacedInRegisterFile || m_technique == CellDisplacedInRegisterFile || m_technique == BooleanDisplacedInRegisterFile);
256 return m_source.virtualReg;
257 }
258
259 JSValue constant() const
260 {
261 ASSERT(m_technique == Constant);
262 return JSValue::decode(m_source.constant);
263 }
264
265 void dump(FILE* out) const
266 {
267 switch (technique()) {
268 case AlreadyInRegisterFile:
269 fprintf(out, "-");
270 break;
271 case AlreadyInRegisterFileAsUnboxedInt32:
272 fprintf(out, "(int32)");
273 break;
274 case AlreadyInRegisterFileAsUnboxedCell:
275 fprintf(out, "(cell)");
276 break;
277 case AlreadyInRegisterFileAsUnboxedBoolean:
278 fprintf(out, "(bool)");
279 break;
280 case AlreadyInRegisterFileAsUnboxedDouble:
281 fprintf(out, "(double)");
282 break;
283 case InGPR:
284 fprintf(out, "%%r%d", gpr());
285 break;
286 case UnboxedInt32InGPR:
287 fprintf(out, "int32(%%r%d)", gpr());
288 break;
289 case UnboxedBooleanInGPR:
290 fprintf(out, "bool(%%r%d)", gpr());
291 break;
292 case UInt32InGPR:
293 fprintf(out, "uint32(%%r%d)", gpr());
294 break;
295 case InFPR:
296 fprintf(out, "%%fr%d", fpr());
297 break;
298 #if USE(JSVALUE32_64)
299 case InPair:
300 fprintf(out, "pair(%%r%d, %%r%d)", tagGPR(), payloadGPR());
301 break;
302 #endif
303 case DisplacedInRegisterFile:
304 fprintf(out, "*%d", virtualRegister());
305 break;
306 case Int32DisplacedInRegisterFile:
307 fprintf(out, "*int32(%d)", virtualRegister());
308 break;
309 case DoubleDisplacedInRegisterFile:
310 fprintf(out, "*double(%d)", virtualRegister());
311 break;
312 case CellDisplacedInRegisterFile:
313 fprintf(out, "*cell(%d)", virtualRegister());
314 break;
315 case BooleanDisplacedInRegisterFile:
316 fprintf(out, "*bool(%d)", virtualRegister());
317 break;
318 case Constant:
319 fprintf(out, "[%s]", constant().description());
320 break;
321 case DontKnow:
322 fprintf(out, "!");
323 break;
324 default:
325 fprintf(out, "?%d", technique());
326 break;
327 }
328 }
329
330 private:
331 ValueRecoveryTechnique m_technique;
332 union {
333 MacroAssembler::RegisterID gpr;
334 MacroAssembler::FPRegisterID fpr;
335 #if USE(JSVALUE32_64)
336 struct {
337 MacroAssembler::RegisterID tagGPR;
338 MacroAssembler::RegisterID payloadGPR;
339 } pair;
340 #endif
341 VirtualRegister virtualReg;
342 EncodedJSValue constant;
343 } m_source;
344 };
345
346 } // namespace JSC
347
348 #endif // ValueRecovery_h