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 ValueRecovery_h
27 #define ValueRecovery_h
29 #include "DataFormat.h"
30 #include "JSCJSValue.h"
31 #include "MacroAssembler.h"
32 #include "VirtualRegister.h"
34 #include <wtf/Platform.h>
38 // Describes how to recover a given bytecode virtual register at a given
40 enum ValueRecoveryTechnique
{
41 // It's already in the stack at the right location.
43 // It's already in the stack but unboxed.
44 AlreadyInJSStackAsUnboxedInt32
,
45 AlreadyInJSStackAsUnboxedCell
,
46 AlreadyInJSStackAsUnboxedBoolean
,
47 AlreadyInJSStackAsUnboxedDouble
,
48 // It's in a register.
57 // It's in the stack, but at a different location.
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
,
68 // Don't know how to recover it.
75 : m_technique(DontKnow
)
79 bool isSet() const { return m_technique
!= DontKnow
; }
80 bool operator!() const { return !isSet(); }
82 static ValueRecovery
alreadyInJSStack()
85 result
.m_technique
= AlreadyInJSStack
;
89 static ValueRecovery
alreadyInJSStackAsUnboxedInt32()
92 result
.m_technique
= AlreadyInJSStackAsUnboxedInt32
;
96 static ValueRecovery
alreadyInJSStackAsUnboxedCell()
99 result
.m_technique
= AlreadyInJSStackAsUnboxedCell
;
103 static ValueRecovery
alreadyInJSStackAsUnboxedBoolean()
105 ValueRecovery result
;
106 result
.m_technique
= AlreadyInJSStackAsUnboxedBoolean
;
110 static ValueRecovery
alreadyInJSStackAsUnboxedDouble()
112 ValueRecovery result
;
113 result
.m_technique
= AlreadyInJSStackAsUnboxedDouble
;
117 static ValueRecovery
inGPR(MacroAssembler::RegisterID gpr
, DataFormat dataFormat
)
119 ASSERT(dataFormat
!= DataFormatNone
);
120 #if USE(JSVALUE32_64)
121 ASSERT(dataFormat
== DataFormatInteger
|| dataFormat
== DataFormatCell
|| dataFormat
== DataFormatBoolean
);
123 ValueRecovery result
;
124 if (dataFormat
== DataFormatInteger
)
125 result
.m_technique
= UnboxedInt32InGPR
;
126 else if (dataFormat
== DataFormatBoolean
)
127 result
.m_technique
= UnboxedBooleanInGPR
;
129 result
.m_technique
= InGPR
;
130 result
.m_source
.gpr
= gpr
;
134 static ValueRecovery
uint32InGPR(MacroAssembler::RegisterID gpr
)
136 ValueRecovery result
;
137 result
.m_technique
= UInt32InGPR
;
138 result
.m_source
.gpr
= gpr
;
142 #if USE(JSVALUE32_64)
143 static ValueRecovery
inPair(MacroAssembler::RegisterID tagGPR
, MacroAssembler::RegisterID payloadGPR
)
145 ValueRecovery result
;
146 result
.m_technique
= InPair
;
147 result
.m_source
.pair
.tagGPR
= tagGPR
;
148 result
.m_source
.pair
.payloadGPR
= payloadGPR
;
153 static ValueRecovery
inFPR(MacroAssembler::FPRegisterID fpr
)
155 ValueRecovery result
;
156 result
.m_technique
= InFPR
;
157 result
.m_source
.fpr
= fpr
;
161 static ValueRecovery
displacedInJSStack(VirtualRegister virtualReg
, DataFormat dataFormat
)
163 ValueRecovery result
;
164 switch (dataFormat
) {
165 case DataFormatInteger
:
166 result
.m_technique
= Int32DisplacedInJSStack
;
169 case DataFormatDouble
:
170 result
.m_technique
= DoubleDisplacedInJSStack
;
174 result
.m_technique
= CellDisplacedInJSStack
;
177 case DataFormatBoolean
:
178 result
.m_technique
= BooleanDisplacedInJSStack
;
182 ASSERT(dataFormat
!= DataFormatNone
&& dataFormat
!= DataFormatStorage
);
183 result
.m_technique
= DisplacedInJSStack
;
186 result
.m_source
.virtualReg
= virtualReg
;
190 static ValueRecovery
constant(JSValue value
)
192 ValueRecovery result
;
193 result
.m_technique
= Constant
;
194 result
.m_source
.constant
= JSValue::encode(value
);
198 static ValueRecovery
argumentsThatWereNotCreated()
200 ValueRecovery result
;
201 result
.m_technique
= ArgumentsThatWereNotCreated
;
205 ValueRecoveryTechnique
technique() const { return m_technique
; }
207 bool isConstant() const { return m_technique
== Constant
; }
209 bool isInRegisters() const
211 switch (m_technique
) {
213 case UnboxedInt32InGPR
:
214 case UnboxedBooleanInGPR
:
215 #if USE(JSVALUE32_64)
225 bool isAlreadyInJSStack() const
227 switch (technique()) {
228 case AlreadyInJSStack
:
229 case AlreadyInJSStackAsUnboxedInt32
:
230 case AlreadyInJSStackAsUnboxedCell
:
231 case AlreadyInJSStackAsUnboxedBoolean
:
232 case AlreadyInJSStackAsUnboxedDouble
:
239 MacroAssembler::RegisterID
gpr() const
241 ASSERT(m_technique
== InGPR
|| m_technique
== UnboxedInt32InGPR
|| m_technique
== UnboxedBooleanInGPR
|| m_technique
== UInt32InGPR
);
245 #if USE(JSVALUE32_64)
246 MacroAssembler::RegisterID
tagGPR() const
248 ASSERT(m_technique
== InPair
);
249 return m_source
.pair
.tagGPR
;
252 MacroAssembler::RegisterID
payloadGPR() const
254 ASSERT(m_technique
== InPair
);
255 return m_source
.pair
.payloadGPR
;
259 MacroAssembler::FPRegisterID
fpr() const
261 ASSERT(m_technique
== InFPR
);
265 VirtualRegister
virtualRegister() const
267 ASSERT(m_technique
== DisplacedInJSStack
|| m_technique
== Int32DisplacedInJSStack
|| m_technique
== DoubleDisplacedInJSStack
|| m_technique
== CellDisplacedInJSStack
|| m_technique
== BooleanDisplacedInJSStack
);
268 return m_source
.virtualReg
;
271 JSValue
constant() const
273 ASSERT(m_technique
== Constant
);
274 return JSValue::decode(m_source
.constant
);
277 void dump(PrintStream
& out
) const
279 switch (technique()) {
280 case AlreadyInJSStack
:
283 case AlreadyInJSStackAsUnboxedInt32
:
284 out
.printf("(int32)");
286 case AlreadyInJSStackAsUnboxedCell
:
287 out
.printf("(cell)");
289 case AlreadyInJSStackAsUnboxedBoolean
:
290 out
.printf("(bool)");
292 case AlreadyInJSStackAsUnboxedDouble
:
293 out
.printf("(double)");
296 out
.printf("%%r%d", gpr());
298 case UnboxedInt32InGPR
:
299 out
.printf("int32(%%r%d)", gpr());
301 case UnboxedBooleanInGPR
:
302 out
.printf("bool(%%r%d)", gpr());
305 out
.printf("uint32(%%r%d)", gpr());
308 out
.printf("%%fr%d", fpr());
310 #if USE(JSVALUE32_64)
312 out
.printf("pair(%%r%d, %%r%d)", tagGPR(), payloadGPR());
315 case DisplacedInJSStack
:
316 out
.printf("*%d", virtualRegister());
318 case Int32DisplacedInJSStack
:
319 out
.printf("*int32(%d)", virtualRegister());
321 case DoubleDisplacedInJSStack
:
322 out
.printf("*double(%d)", virtualRegister());
324 case CellDisplacedInJSStack
:
325 out
.printf("*cell(%d)", virtualRegister());
327 case BooleanDisplacedInJSStack
:
328 out
.printf("*bool(%d)", virtualRegister());
330 case ArgumentsThatWereNotCreated
:
331 out
.printf("arguments");
334 out
.print("[", constant(), "]");
340 out
.printf("?%d", technique());
346 ValueRecoveryTechnique m_technique
;
348 MacroAssembler::RegisterID gpr
;
349 MacroAssembler::FPRegisterID fpr
;
350 #if USE(JSVALUE32_64)
352 MacroAssembler::RegisterID tagGPR
;
353 MacroAssembler::RegisterID payloadGPR
;
356 VirtualRegister virtualReg
;
357 EncodedJSValue constant
;
363 #endif // ValueRecovery_h