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