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