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