DFG should infer when local variables are doubles
[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     AlreadyInRegisterFileAsUnboxedDouble,
51     // It's in a register.
52     InGPR,
53     UnboxedInt32InGPR,
54     UnboxedBooleanInGPR,
55 #if USE(JSVALUE32_64)
56     InPair,
57 #endif
58     InFPR,
59     UInt32InGPR,
60     // It's in the register file, but at a different location.
61     DisplacedInRegisterFile,
62     // It's in the register file, at a different location, and it's unboxed.
63     Int32DisplacedInRegisterFile,
64     DoubleDisplacedInRegisterFile,
65     // It's a constant.
66     Constant,
67     // Don't know how to recover it.
68     DontKnow
69 };
70
71 class ValueRecovery {
72 public:
73     ValueRecovery()
74         : m_technique(DontKnow)
75     {
76     }
77     
78     static ValueRecovery alreadyInRegisterFile()
79     {
80         ValueRecovery result;
81         result.m_technique = AlreadyInRegisterFile;
82         return result;
83     }
84     
85     static ValueRecovery alreadyInRegisterFileAsUnboxedInt32()
86     {
87         ValueRecovery result;
88         result.m_technique = AlreadyInRegisterFileAsUnboxedInt32;
89         return result;
90     }
91     
92     static ValueRecovery alreadyInRegisterFileAsUnboxedCell()
93     {
94         ValueRecovery result;
95         result.m_technique = AlreadyInRegisterFileAsUnboxedCell;
96         return result;
97     }
98     
99     static ValueRecovery alreadyInRegisterFileAsUnboxedBoolean()
100     {
101         ValueRecovery result;
102         result.m_technique = AlreadyInRegisterFileAsUnboxedBoolean;
103         return result;
104     }
105     
106     static ValueRecovery alreadyInRegisterFileAsUnboxedDouble()
107     {
108         ValueRecovery result;
109         result.m_technique = AlreadyInRegisterFileAsUnboxedDouble;
110         return result;
111     }
112     
113     static ValueRecovery inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat)
114     {
115         ASSERT(dataFormat != DataFormatNone);
116 #if USE(JSVALUE32_64)
117         ASSERT(dataFormat == DataFormatInteger || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean);
118 #endif
119         ValueRecovery result;
120         if (dataFormat == DataFormatInteger)
121             result.m_technique = UnboxedInt32InGPR;
122         else if (dataFormat == DataFormatBoolean)
123             result.m_technique = UnboxedBooleanInGPR;
124         else
125             result.m_technique = InGPR;
126         result.m_source.gpr = gpr;
127         return result;
128     }
129     
130     static ValueRecovery uint32InGPR(MacroAssembler::RegisterID gpr)
131     {
132         ValueRecovery result;
133         result.m_technique = UInt32InGPR;
134         result.m_source.gpr = gpr;
135         return result;
136     }
137     
138 #if USE(JSVALUE32_64)
139     static ValueRecovery inPair(MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR)
140     {
141         ValueRecovery result;
142         result.m_technique = InPair;
143         result.m_source.pair.tagGPR = tagGPR;
144         result.m_source.pair.payloadGPR = payloadGPR;
145         return result;
146     }
147 #endif
148
149     static ValueRecovery inFPR(MacroAssembler::FPRegisterID fpr)
150     {
151         ValueRecovery result;
152         result.m_technique = InFPR;
153         result.m_source.fpr = fpr;
154         return result;
155     }
156     
157     static ValueRecovery displacedInRegisterFile(VirtualRegister virtualReg, DataFormat dataFormat)
158     {
159         ValueRecovery result;
160         switch (dataFormat) {
161         case DataFormatInteger:
162             result.m_technique = Int32DisplacedInRegisterFile;
163             break;
164             
165         case DataFormatDouble:
166             result.m_technique = DoubleDisplacedInRegisterFile;
167             break;
168
169         default:
170             ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage);
171             result.m_technique = DisplacedInRegisterFile;
172             break;
173         }
174         result.m_source.virtualReg = virtualReg;
175         return result;
176     }
177     
178     static ValueRecovery constant(JSValue value)
179     {
180         ValueRecovery result;
181         result.m_technique = Constant;
182         result.m_source.constant = JSValue::encode(value);
183         return result;
184     }
185     
186     ValueRecoveryTechnique technique() const { return m_technique; }
187     
188     bool isInRegisters() const
189     {
190         switch (m_technique) {
191         case InGPR:
192         case UnboxedInt32InGPR:
193         case UnboxedBooleanInGPR:
194 #if USE(JSVALUE32_64)
195         case InPair:
196 #endif
197         case InFPR:
198             return true;
199         default:
200             return false;
201         }
202     }
203     
204     MacroAssembler::RegisterID gpr() const
205     {
206         ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR);
207         return m_source.gpr;
208     }
209     
210 #if USE(JSVALUE32_64)
211     MacroAssembler::RegisterID tagGPR() const
212     {
213         ASSERT(m_technique == InPair);
214         return m_source.pair.tagGPR;
215     }
216     
217     MacroAssembler::RegisterID payloadGPR() const
218     {
219         ASSERT(m_technique == InPair);
220         return m_source.pair.payloadGPR;
221     }
222 #endif
223     
224     MacroAssembler::FPRegisterID fpr() const
225     {
226         ASSERT(m_technique == InFPR);
227         return m_source.fpr;
228     }
229     
230     VirtualRegister virtualRegister() const
231     {
232         ASSERT(m_technique == DisplacedInRegisterFile || m_technique == Int32DisplacedInRegisterFile || m_technique == DoubleDisplacedInRegisterFile);
233         return m_source.virtualReg;
234     }
235     
236     JSValue constant() const
237     {
238         ASSERT(m_technique == Constant);
239         return JSValue::decode(m_source.constant);
240     }
241     
242 #ifndef NDEBUG
243     void dump(FILE* out) const
244     {
245         switch (technique()) {
246         case AlreadyInRegisterFile:
247             fprintf(out, "-");
248             break;
249         case AlreadyInRegisterFileAsUnboxedInt32:
250             fprintf(out, "(int32)");
251             break;
252         case AlreadyInRegisterFileAsUnboxedCell:
253             fprintf(out, "(cell)");
254             break;
255         case AlreadyInRegisterFileAsUnboxedBoolean:
256             fprintf(out, "(bool)");
257             break;
258         case AlreadyInRegisterFileAsUnboxedDouble:
259             fprintf(out, "(double)");
260             break;
261         case InGPR:
262             fprintf(out, "%%r%d", gpr());
263             break;
264         case UnboxedInt32InGPR:
265             fprintf(out, "int32(%%r%d)", gpr());
266             break;
267         case UnboxedBooleanInGPR:
268             fprintf(out, "bool(%%r%d)", gpr());
269             break;
270         case UInt32InGPR:
271             fprintf(out, "uint32(%%r%d)", gpr());
272             break;
273         case InFPR:
274             fprintf(out, "%%fr%d", fpr());
275             break;
276 #if USE(JSVALUE32_64)
277         case InPair:
278             fprintf(out, "pair(%%r%d, %%r%d)", tagGPR(), payloadGPR());
279             break;
280 #endif
281         case DisplacedInRegisterFile:
282             fprintf(out, "*%d", virtualRegister());
283             break;
284         case Int32DisplacedInRegisterFile:
285             fprintf(out, "*int32(%d)", virtualRegister());
286             break;
287         case DoubleDisplacedInRegisterFile:
288             fprintf(out, "*double(%d)", virtualRegister());
289             break;
290         case Constant:
291             fprintf(out, "[%s]", constant().description());
292             break;
293         case DontKnow:
294             fprintf(out, "!");
295             break;
296         default:
297             fprintf(out, "?%d", technique());
298             break;
299         }
300     }
301 #endif
302     
303 private:
304     ValueRecoveryTechnique m_technique;
305     union {
306         MacroAssembler::RegisterID gpr;
307         MacroAssembler::FPRegisterID fpr;
308 #if USE(JSVALUE32_64)
309         struct {
310             MacroAssembler::RegisterID tagGPR;
311             MacroAssembler::RegisterID payloadGPR;
312         } pair;
313 #endif
314         VirtualRegister virtualReg;
315         EncodedJSValue constant;
316     } m_source;
317 };
318
319 } // namespace JSC
320
321 #endif // ValueRecovery_h