DFG OSR exit for UInt32ToNumber should roll forward, not roll backward
[WebKit-https.git] / Source / JavaScriptCore / 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 <wtf/Platform.h>
34
35 #ifndef NDEBUG
36 #include <stdio.h>
37 #endif
38
39 namespace JSC {
40
41 // Describes how to recover a given bytecode virtual register at a given
42 // code point.
43 enum ValueRecoveryTechnique {
44     // It's already in the register file at the right location.
45     AlreadyInRegisterFile,
46     // It's already in the register file but unboxed.
47     AlreadyInRegisterFileAsUnboxedInt32,
48     AlreadyInRegisterFileAsUnboxedCell,
49     AlreadyInRegisterFileAsUnboxedBoolean,
50     // It's in a register.
51     InGPR,
52     UnboxedInt32InGPR,
53     UnboxedBooleanInGPR,
54 #if USE(JSVALUE32_64)
55     InPair,
56 #endif
57     InFPR,
58     UInt32InGPR,
59     // It's in the register file, but at a different location.
60     DisplacedInRegisterFile,
61     // It's in the register file, at a different location, and it's unboxed.
62     Int32DisplacedInRegisterFile,
63     DoubleDisplacedInRegisterFile,
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 inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat)
106     {
107         ASSERT(dataFormat != DataFormatNone);
108 #if USE(JSVALUE32_64)
109         ASSERT(dataFormat == DataFormatInteger || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean);
110 #endif
111         ValueRecovery result;
112         if (dataFormat == DataFormatInteger)
113             result.m_technique = UnboxedInt32InGPR;
114         else if (dataFormat == DataFormatBoolean)
115             result.m_technique = UnboxedBooleanInGPR;
116         else
117             result.m_technique = InGPR;
118         result.m_source.gpr = gpr;
119         return result;
120     }
121     
122     static ValueRecovery uint32InGPR(MacroAssembler::RegisterID gpr)
123     {
124         ValueRecovery result;
125         result.m_technique = UInt32InGPR;
126         result.m_source.gpr = gpr;
127         return result;
128     }
129     
130 #if USE(JSVALUE32_64)
131     static ValueRecovery inPair(MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR)
132     {
133         ValueRecovery result;
134         result.m_technique = InPair;
135         result.m_source.pair.tagGPR = tagGPR;
136         result.m_source.pair.payloadGPR = payloadGPR;
137         return result;
138     }
139 #endif
140
141     static ValueRecovery inFPR(MacroAssembler::FPRegisterID fpr)
142     {
143         ValueRecovery result;
144         result.m_technique = InFPR;
145         result.m_source.fpr = fpr;
146         return result;
147     }
148     
149     static ValueRecovery displacedInRegisterFile(VirtualRegister virtualReg, DataFormat dataFormat)
150     {
151         ValueRecovery result;
152         switch (dataFormat) {
153         case DataFormatInteger:
154             result.m_technique = Int32DisplacedInRegisterFile;
155             break;
156             
157         case DataFormatDouble:
158             result.m_technique = DoubleDisplacedInRegisterFile;
159             break;
160
161         default:
162             ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage);
163             result.m_technique = DisplacedInRegisterFile;
164             break;
165         }
166         result.m_source.virtualReg = virtualReg;
167         return result;
168     }
169     
170     static ValueRecovery constant(JSValue value)
171     {
172         ValueRecovery result;
173         result.m_technique = Constant;
174         result.m_source.constant = JSValue::encode(value);
175         return result;
176     }
177     
178     ValueRecoveryTechnique technique() const { return m_technique; }
179     
180     bool isInRegisters() const
181     {
182         switch (m_technique) {
183         case InGPR:
184         case UnboxedInt32InGPR:
185         case UnboxedBooleanInGPR:
186 #if USE(JSVALUE32_64)
187         case InPair:
188 #endif
189         case InFPR:
190             return true;
191         default:
192             return false;
193         }
194     }
195     
196     MacroAssembler::RegisterID gpr() const
197     {
198         ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR);
199         return m_source.gpr;
200     }
201     
202 #if USE(JSVALUE32_64)
203     MacroAssembler::RegisterID tagGPR() const
204     {
205         ASSERT(m_technique == InPair);
206         return m_source.pair.tagGPR;
207     }
208     
209     MacroAssembler::RegisterID payloadGPR() const
210     {
211         ASSERT(m_technique == InPair);
212         return m_source.pair.payloadGPR;
213     }
214 #endif
215     
216     MacroAssembler::FPRegisterID fpr() const
217     {
218         ASSERT(m_technique == InFPR);
219         return m_source.fpr;
220     }
221     
222     VirtualRegister virtualRegister() const
223     {
224         ASSERT(m_technique == DisplacedInRegisterFile || m_technique == Int32DisplacedInRegisterFile || m_technique == DoubleDisplacedInRegisterFile);
225         return m_source.virtualReg;
226     }
227     
228     JSValue constant() const
229     {
230         ASSERT(m_technique == Constant);
231         return JSValue::decode(m_source.constant);
232     }
233     
234 #ifndef NDEBUG
235     void dump(FILE* out) const
236     {
237         switch (technique()) {
238         case AlreadyInRegisterFile:
239             fprintf(out, "-");
240             break;
241         case AlreadyInRegisterFileAsUnboxedInt32:
242             fprintf(out, "(int32)");
243             break;
244         case AlreadyInRegisterFileAsUnboxedCell:
245             fprintf(out, "(cell)");
246             break;
247         case AlreadyInRegisterFileAsUnboxedBoolean:
248             fprintf(out, "(bool)");
249             break;
250         case InGPR:
251             fprintf(out, "%%r%d", gpr());
252             break;
253         case UnboxedInt32InGPR:
254             fprintf(out, "int32(%%r%d)", gpr());
255             break;
256         case UnboxedBooleanInGPR:
257             fprintf(out, "bool(%%r%d)", gpr());
258             break;
259         case UInt32InGPR:
260             fprintf(out, "uint32(%%r%d)", gpr());
261             break;
262         case InFPR:
263             fprintf(out, "%%fr%d", fpr());
264             break;
265 #if USE(JSVALUE32_64)
266         case InPair:
267             fprintf(out, "pair(%%r%d, %%r%d)", tagGPR(), payloadGPR());
268             break;
269 #endif
270         case DisplacedInRegisterFile:
271             fprintf(out, "*%d", virtualRegister());
272             break;
273         case Int32DisplacedInRegisterFile:
274             fprintf(out, "*int32(%d)", virtualRegister());
275             break;
276         case DoubleDisplacedInRegisterFile:
277             fprintf(out, "*double(%d)", virtualRegister());
278             break;
279         case Constant:
280             fprintf(out, "[%s]", constant().description());
281             break;
282         case DontKnow:
283             fprintf(out, "!");
284             break;
285         default:
286             fprintf(out, "?%d", technique());
287             break;
288         }
289     }
290 #endif
291     
292 private:
293     ValueRecoveryTechnique m_technique;
294     union {
295         MacroAssembler::RegisterID gpr;
296         MacroAssembler::FPRegisterID fpr;
297 #if USE(JSVALUE32_64)
298         struct {
299             MacroAssembler::RegisterID tagGPR;
300             MacroAssembler::RegisterID payloadGPR;
301         } pair;
302 #endif
303         VirtualRegister virtualReg;
304         EncodedJSValue constant;
305     } m_source;
306 };
307
308 } // namespace JSC
309
310 #endif // ValueRecovery_h