]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 2011, 2013 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 | #if ENABLE(JIT) | |
31 | #include "GPRInfo.h" | |
32 | #include "FPRInfo.h" | |
33 | #endif | |
34 | #include "JSCJSValue.h" | |
35 | #include "MacroAssembler.h" | |
36 | #include "VirtualRegister.h" | |
37 | ||
38 | namespace JSC { | |
39 | ||
40 | struct DumpContext; | |
41 | ||
42 | // Describes how to recover a given bytecode virtual register at a given | |
43 | // code point. | |
44 | enum ValueRecoveryTechnique { | |
45 | // It's in a register. | |
46 | InGPR, | |
47 | UnboxedInt32InGPR, | |
48 | UnboxedInt52InGPR, | |
49 | UnboxedStrictInt52InGPR, | |
50 | UnboxedBooleanInGPR, | |
51 | UnboxedCellInGPR, | |
52 | #if USE(JSVALUE32_64) | |
53 | InPair, | |
54 | #endif | |
55 | InFPR, | |
56 | // It's in the stack, but at a different location. | |
57 | DisplacedInJSStack, | |
58 | // It's in the stack, at a different location, and it's unboxed. | |
59 | Int32DisplacedInJSStack, | |
60 | Int52DisplacedInJSStack, | |
61 | StrictInt52DisplacedInJSStack, | |
62 | DoubleDisplacedInJSStack, | |
63 | CellDisplacedInJSStack, | |
64 | BooleanDisplacedInJSStack, | |
65 | // It's an Arguments object. | |
66 | ArgumentsThatWereNotCreated, | |
67 | // It's a constant. | |
68 | Constant, | |
69 | // Don't know how to recover it. | |
70 | DontKnow | |
71 | }; | |
72 | ||
73 | class ValueRecovery { | |
74 | public: | |
75 | ValueRecovery() | |
76 | : m_technique(DontKnow) | |
77 | { | |
78 | } | |
79 | ||
80 | bool isSet() const { return m_technique != DontKnow; } | |
81 | bool operator!() const { return !isSet(); } | |
82 | ||
83 | static ValueRecovery inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat) | |
84 | { | |
85 | ASSERT(dataFormat != DataFormatNone); | |
86 | #if USE(JSVALUE32_64) | |
87 | ASSERT(dataFormat == DataFormatInt32 || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean); | |
88 | #endif | |
89 | ValueRecovery result; | |
90 | if (dataFormat == DataFormatInt32) | |
91 | result.m_technique = UnboxedInt32InGPR; | |
92 | else if (dataFormat == DataFormatInt52) | |
93 | result.m_technique = UnboxedInt52InGPR; | |
94 | else if (dataFormat == DataFormatStrictInt52) | |
95 | result.m_technique = UnboxedStrictInt52InGPR; | |
96 | else if (dataFormat == DataFormatBoolean) | |
97 | result.m_technique = UnboxedBooleanInGPR; | |
98 | else if (dataFormat == DataFormatCell) | |
99 | result.m_technique = UnboxedCellInGPR; | |
100 | else | |
101 | result.m_technique = InGPR; | |
102 | result.m_source.gpr = gpr; | |
103 | return result; | |
104 | } | |
105 | ||
106 | #if USE(JSVALUE32_64) | |
107 | static ValueRecovery inPair(MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR) | |
108 | { | |
109 | ValueRecovery result; | |
110 | result.m_technique = InPair; | |
111 | result.m_source.pair.tagGPR = tagGPR; | |
112 | result.m_source.pair.payloadGPR = payloadGPR; | |
113 | return result; | |
114 | } | |
115 | #endif | |
116 | ||
117 | static ValueRecovery inFPR(MacroAssembler::FPRegisterID fpr) | |
118 | { | |
119 | ValueRecovery result; | |
120 | result.m_technique = InFPR; | |
121 | result.m_source.fpr = fpr; | |
122 | return result; | |
123 | } | |
124 | ||
125 | static ValueRecovery displacedInJSStack(VirtualRegister virtualReg, DataFormat dataFormat) | |
126 | { | |
127 | ValueRecovery result; | |
128 | switch (dataFormat) { | |
129 | case DataFormatInt32: | |
130 | result.m_technique = Int32DisplacedInJSStack; | |
131 | break; | |
132 | ||
133 | case DataFormatInt52: | |
134 | result.m_technique = Int52DisplacedInJSStack; | |
135 | break; | |
136 | ||
137 | case DataFormatStrictInt52: | |
138 | result.m_technique = StrictInt52DisplacedInJSStack; | |
139 | break; | |
140 | ||
141 | case DataFormatDouble: | |
142 | result.m_technique = DoubleDisplacedInJSStack; | |
143 | break; | |
144 | ||
145 | case DataFormatCell: | |
146 | result.m_technique = CellDisplacedInJSStack; | |
147 | break; | |
148 | ||
149 | case DataFormatBoolean: | |
150 | result.m_technique = BooleanDisplacedInJSStack; | |
151 | break; | |
152 | ||
153 | default: | |
154 | ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage); | |
155 | result.m_technique = DisplacedInJSStack; | |
156 | break; | |
157 | } | |
158 | result.m_source.virtualReg = virtualReg.offset(); | |
159 | return result; | |
160 | } | |
161 | ||
162 | static ValueRecovery constant(JSValue value) | |
163 | { | |
164 | ValueRecovery result; | |
165 | result.m_technique = Constant; | |
166 | result.m_source.constant = JSValue::encode(value); | |
167 | return result; | |
168 | } | |
169 | ||
170 | static ValueRecovery argumentsThatWereNotCreated() | |
171 | { | |
172 | ValueRecovery result; | |
173 | result.m_technique = ArgumentsThatWereNotCreated; | |
174 | return result; | |
175 | } | |
176 | ||
177 | ValueRecoveryTechnique technique() const { return m_technique; } | |
178 | ||
179 | bool isConstant() const { return m_technique == Constant; } | |
180 | ||
181 | bool isInRegisters() const | |
182 | { | |
183 | switch (m_technique) { | |
184 | case InGPR: | |
185 | case UnboxedInt32InGPR: | |
186 | case UnboxedBooleanInGPR: | |
187 | case UnboxedCellInGPR: | |
188 | case UnboxedInt52InGPR: | |
189 | case UnboxedStrictInt52InGPR: | |
190 | #if USE(JSVALUE32_64) | |
191 | case InPair: | |
192 | #endif | |
193 | case InFPR: | |
194 | return true; | |
195 | default: | |
196 | return false; | |
197 | } | |
198 | } | |
199 | ||
200 | MacroAssembler::RegisterID gpr() const | |
201 | { | |
202 | ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UnboxedInt52InGPR || m_technique == UnboxedStrictInt52InGPR || m_technique == UnboxedCellInGPR); | |
203 | return m_source.gpr; | |
204 | } | |
205 | ||
206 | #if USE(JSVALUE32_64) | |
207 | MacroAssembler::RegisterID tagGPR() const | |
208 | { | |
209 | ASSERT(m_technique == InPair); | |
210 | return m_source.pair.tagGPR; | |
211 | } | |
212 | ||
213 | MacroAssembler::RegisterID payloadGPR() const | |
214 | { | |
215 | ASSERT(m_technique == InPair); | |
216 | return m_source.pair.payloadGPR; | |
217 | } | |
218 | #endif | |
219 | ||
220 | MacroAssembler::FPRegisterID fpr() const | |
221 | { | |
222 | ASSERT(m_technique == InFPR); | |
223 | return m_source.fpr; | |
224 | } | |
225 | ||
226 | VirtualRegister virtualRegister() const | |
227 | { | |
228 | ASSERT(m_technique == DisplacedInJSStack || m_technique == Int32DisplacedInJSStack || m_technique == DoubleDisplacedInJSStack || m_technique == CellDisplacedInJSStack || m_technique == BooleanDisplacedInJSStack || m_technique == Int52DisplacedInJSStack || m_technique == StrictInt52DisplacedInJSStack); | |
229 | return VirtualRegister(m_source.virtualReg); | |
230 | } | |
231 | ||
232 | ValueRecovery withLocalsOffset(int offset) const | |
233 | { | |
234 | switch (m_technique) { | |
235 | case DisplacedInJSStack: | |
236 | case Int32DisplacedInJSStack: | |
237 | case DoubleDisplacedInJSStack: | |
238 | case CellDisplacedInJSStack: | |
239 | case BooleanDisplacedInJSStack: | |
240 | case Int52DisplacedInJSStack: | |
241 | case StrictInt52DisplacedInJSStack: { | |
242 | ValueRecovery result; | |
243 | result.m_technique = m_technique; | |
244 | result.m_source.virtualReg = m_source.virtualReg + offset; | |
245 | return result; | |
246 | } | |
247 | ||
248 | default: | |
249 | return *this; | |
250 | } | |
251 | } | |
252 | ||
253 | JSValue constant() const | |
254 | { | |
255 | ASSERT(m_technique == Constant); | |
256 | return JSValue::decode(m_source.constant); | |
257 | } | |
258 | ||
259 | JSValue recover(ExecState*) const; | |
260 | ||
261 | #if ENABLE(JIT) | |
262 | void dumpInContext(PrintStream& out, DumpContext* context) const; | |
263 | void dump(PrintStream& out) const; | |
264 | #endif | |
265 | ||
266 | private: | |
267 | ValueRecoveryTechnique m_technique; | |
268 | union { | |
269 | MacroAssembler::RegisterID gpr; | |
270 | MacroAssembler::FPRegisterID fpr; | |
271 | #if USE(JSVALUE32_64) | |
272 | struct { | |
273 | MacroAssembler::RegisterID tagGPR; | |
274 | MacroAssembler::RegisterID payloadGPR; | |
275 | } pair; | |
276 | #endif | |
277 | int virtualReg; | |
278 | EncodedJSValue constant; | |
279 | } m_source; | |
280 | }; | |
281 | ||
282 | } // namespace JSC | |
283 | ||
284 | #endif // ValueRecovery_h |