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