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