]> git.saurik.com Git - apple/javascriptcore.git/blob - bytecode/ValueRecovery.h
JavaScriptCore-1218.34.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 "JSCJSValue.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 stack at the right location.
42 AlreadyInJSStack,
43 // It's already in the stack but unboxed.
44 AlreadyInJSStackAsUnboxedInt32,
45 AlreadyInJSStackAsUnboxedCell,
46 AlreadyInJSStackAsUnboxedBoolean,
47 AlreadyInJSStackAsUnboxedDouble,
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 stack, but at a different location.
58 DisplacedInJSStack,
59 // It's in the stack, at a different location, and it's unboxed.
60 Int32DisplacedInJSStack,
61 DoubleDisplacedInJSStack,
62 CellDisplacedInJSStack,
63 BooleanDisplacedInJSStack,
64 // It's an Arguments object.
65 ArgumentsThatWereNotCreated,
66 // It's a constant.
67 Constant,
68 // Don't know how to recover it.
69 DontKnow
70 };
71
72 class ValueRecovery {
73 public:
74 ValueRecovery()
75 : m_technique(DontKnow)
76 {
77 }
78
79 bool isSet() const { return m_technique != DontKnow; }
80 bool operator!() const { return !isSet(); }
81
82 static ValueRecovery alreadyInJSStack()
83 {
84 ValueRecovery result;
85 result.m_technique = AlreadyInJSStack;
86 return result;
87 }
88
89 static ValueRecovery alreadyInJSStackAsUnboxedInt32()
90 {
91 ValueRecovery result;
92 result.m_technique = AlreadyInJSStackAsUnboxedInt32;
93 return result;
94 }
95
96 static ValueRecovery alreadyInJSStackAsUnboxedCell()
97 {
98 ValueRecovery result;
99 result.m_technique = AlreadyInJSStackAsUnboxedCell;
100 return result;
101 }
102
103 static ValueRecovery alreadyInJSStackAsUnboxedBoolean()
104 {
105 ValueRecovery result;
106 result.m_technique = AlreadyInJSStackAsUnboxedBoolean;
107 return result;
108 }
109
110 static ValueRecovery alreadyInJSStackAsUnboxedDouble()
111 {
112 ValueRecovery result;
113 result.m_technique = AlreadyInJSStackAsUnboxedDouble;
114 return result;
115 }
116
117 static ValueRecovery inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat)
118 {
119 ASSERT(dataFormat != DataFormatNone);
120 #if USE(JSVALUE32_64)
121 ASSERT(dataFormat == DataFormatInteger || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean);
122 #endif
123 ValueRecovery result;
124 if (dataFormat == DataFormatInteger)
125 result.m_technique = UnboxedInt32InGPR;
126 else if (dataFormat == DataFormatBoolean)
127 result.m_technique = UnboxedBooleanInGPR;
128 else
129 result.m_technique = InGPR;
130 result.m_source.gpr = gpr;
131 return result;
132 }
133
134 static ValueRecovery uint32InGPR(MacroAssembler::RegisterID gpr)
135 {
136 ValueRecovery result;
137 result.m_technique = UInt32InGPR;
138 result.m_source.gpr = gpr;
139 return result;
140 }
141
142 #if USE(JSVALUE32_64)
143 static ValueRecovery inPair(MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR)
144 {
145 ValueRecovery result;
146 result.m_technique = InPair;
147 result.m_source.pair.tagGPR = tagGPR;
148 result.m_source.pair.payloadGPR = payloadGPR;
149 return result;
150 }
151 #endif
152
153 static ValueRecovery inFPR(MacroAssembler::FPRegisterID fpr)
154 {
155 ValueRecovery result;
156 result.m_technique = InFPR;
157 result.m_source.fpr = fpr;
158 return result;
159 }
160
161 static ValueRecovery displacedInJSStack(VirtualRegister virtualReg, DataFormat dataFormat)
162 {
163 ValueRecovery result;
164 switch (dataFormat) {
165 case DataFormatInteger:
166 result.m_technique = Int32DisplacedInJSStack;
167 break;
168
169 case DataFormatDouble:
170 result.m_technique = DoubleDisplacedInJSStack;
171 break;
172
173 case DataFormatCell:
174 result.m_technique = CellDisplacedInJSStack;
175 break;
176
177 case DataFormatBoolean:
178 result.m_technique = BooleanDisplacedInJSStack;
179 break;
180
181 default:
182 ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage);
183 result.m_technique = DisplacedInJSStack;
184 break;
185 }
186 result.m_source.virtualReg = virtualReg;
187 return result;
188 }
189
190 static ValueRecovery constant(JSValue value)
191 {
192 ValueRecovery result;
193 result.m_technique = Constant;
194 result.m_source.constant = JSValue::encode(value);
195 return result;
196 }
197
198 static ValueRecovery argumentsThatWereNotCreated()
199 {
200 ValueRecovery result;
201 result.m_technique = ArgumentsThatWereNotCreated;
202 return result;
203 }
204
205 ValueRecoveryTechnique technique() const { return m_technique; }
206
207 bool isConstant() const { return m_technique == Constant; }
208
209 bool isInRegisters() const
210 {
211 switch (m_technique) {
212 case InGPR:
213 case UnboxedInt32InGPR:
214 case UnboxedBooleanInGPR:
215 #if USE(JSVALUE32_64)
216 case InPair:
217 #endif
218 case InFPR:
219 return true;
220 default:
221 return false;
222 }
223 }
224
225 bool isAlreadyInJSStack() const
226 {
227 switch (technique()) {
228 case AlreadyInJSStack:
229 case AlreadyInJSStackAsUnboxedInt32:
230 case AlreadyInJSStackAsUnboxedCell:
231 case AlreadyInJSStackAsUnboxedBoolean:
232 case AlreadyInJSStackAsUnboxedDouble:
233 return true;
234 default:
235 return false;
236 }
237 }
238
239 MacroAssembler::RegisterID gpr() const
240 {
241 ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR);
242 return m_source.gpr;
243 }
244
245 #if USE(JSVALUE32_64)
246 MacroAssembler::RegisterID tagGPR() const
247 {
248 ASSERT(m_technique == InPair);
249 return m_source.pair.tagGPR;
250 }
251
252 MacroAssembler::RegisterID payloadGPR() const
253 {
254 ASSERT(m_technique == InPair);
255 return m_source.pair.payloadGPR;
256 }
257 #endif
258
259 MacroAssembler::FPRegisterID fpr() const
260 {
261 ASSERT(m_technique == InFPR);
262 return m_source.fpr;
263 }
264
265 VirtualRegister virtualRegister() const
266 {
267 ASSERT(m_technique == DisplacedInJSStack || m_technique == Int32DisplacedInJSStack || m_technique == DoubleDisplacedInJSStack || m_technique == CellDisplacedInJSStack || m_technique == BooleanDisplacedInJSStack);
268 return m_source.virtualReg;
269 }
270
271 JSValue constant() const
272 {
273 ASSERT(m_technique == Constant);
274 return JSValue::decode(m_source.constant);
275 }
276
277 void dump(PrintStream& out) const
278 {
279 switch (technique()) {
280 case AlreadyInJSStack:
281 out.printf("-");
282 break;
283 case AlreadyInJSStackAsUnboxedInt32:
284 out.printf("(int32)");
285 break;
286 case AlreadyInJSStackAsUnboxedCell:
287 out.printf("(cell)");
288 break;
289 case AlreadyInJSStackAsUnboxedBoolean:
290 out.printf("(bool)");
291 break;
292 case AlreadyInJSStackAsUnboxedDouble:
293 out.printf("(double)");
294 break;
295 case InGPR:
296 out.printf("%%r%d", gpr());
297 break;
298 case UnboxedInt32InGPR:
299 out.printf("int32(%%r%d)", gpr());
300 break;
301 case UnboxedBooleanInGPR:
302 out.printf("bool(%%r%d)", gpr());
303 break;
304 case UInt32InGPR:
305 out.printf("uint32(%%r%d)", gpr());
306 break;
307 case InFPR:
308 out.printf("%%fr%d", fpr());
309 break;
310 #if USE(JSVALUE32_64)
311 case InPair:
312 out.printf("pair(%%r%d, %%r%d)", tagGPR(), payloadGPR());
313 break;
314 #endif
315 case DisplacedInJSStack:
316 out.printf("*%d", virtualRegister());
317 break;
318 case Int32DisplacedInJSStack:
319 out.printf("*int32(%d)", virtualRegister());
320 break;
321 case DoubleDisplacedInJSStack:
322 out.printf("*double(%d)", virtualRegister());
323 break;
324 case CellDisplacedInJSStack:
325 out.printf("*cell(%d)", virtualRegister());
326 break;
327 case BooleanDisplacedInJSStack:
328 out.printf("*bool(%d)", virtualRegister());
329 break;
330 case ArgumentsThatWereNotCreated:
331 out.printf("arguments");
332 break;
333 case Constant:
334 out.print("[", constant(), "]");
335 break;
336 case DontKnow:
337 out.printf("!");
338 break;
339 default:
340 out.printf("?%d", technique());
341 break;
342 }
343 }
344
345 private:
346 ValueRecoveryTechnique m_technique;
347 union {
348 MacroAssembler::RegisterID gpr;
349 MacroAssembler::FPRegisterID fpr;
350 #if USE(JSVALUE32_64)
351 struct {
352 MacroAssembler::RegisterID tagGPR;
353 MacroAssembler::RegisterID payloadGPR;
354 } pair;
355 #endif
356 VirtualRegister virtualReg;
357 EncodedJSValue constant;
358 } m_source;
359 };
360
361 } // namespace JSC
362
363 #endif // ValueRecovery_h