ValueRecovery.h 8.25 KB
Newer Older
1
/*
2
 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#ifndef ValueRecovery_h
#define ValueRecovery_h

#include "DataFormat.h"
30
#if ENABLE(JIT)
31
32
#include "GPRInfo.h"
#include "FPRInfo.h"
33
#endif
34
#include "JSCJSValue.h"
35
36
#include "MacroAssembler.h"
#include "VirtualRegister.h"
37
#include <wtf/Platform.h>
38

39
40
namespace JSC {

41
42
struct DumpContext;

43
44
45
46
47
48
// Describes how to recover a given bytecode virtual register at a given
// code point.
enum ValueRecoveryTechnique {
    // It's in a register.
    InGPR,
    UnboxedInt32InGPR,
49
50
    UnboxedInt52InGPR,
    UnboxedStrictInt52InGPR,
51
    UnboxedBooleanInGPR,
52
    UnboxedCellInGPR,
53
54
55
56
#if USE(JSVALUE32_64)
    InPair,
#endif
    InFPR,
57
    UInt32InGPR,
58
59
60
61
    // It's in the stack, but at a different location.
    DisplacedInJSStack,
    // It's in the stack, at a different location, and it's unboxed.
    Int32DisplacedInJSStack,
62
63
    Int52DisplacedInJSStack,
    StrictInt52DisplacedInJSStack,
64
65
66
    DoubleDisplacedInJSStack,
    CellDisplacedInJSStack,
    BooleanDisplacedInJSStack,
67
68
    // It's an Arguments object.
    ArgumentsThatWereNotCreated,
69
70
71
72
73
74
75
76
77
78
79
80
81
    // It's a constant.
    Constant,
    // Don't know how to recover it.
    DontKnow
};

class ValueRecovery {
public:
    ValueRecovery()
        : m_technique(DontKnow)
    {
    }
    
82
83
84
    bool isSet() const { return m_technique != DontKnow; }
    bool operator!() const { return !isSet(); }
    
85
86
87
88
    static ValueRecovery inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat)
    {
        ASSERT(dataFormat != DataFormatNone);
#if USE(JSVALUE32_64)
89
        ASSERT(dataFormat == DataFormatInt32 || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean);
90
91
#endif
        ValueRecovery result;
92
        if (dataFormat == DataFormatInt32)
93
            result.m_technique = UnboxedInt32InGPR;
94
95
96
97
        else if (dataFormat == DataFormatInt52)
            result.m_technique = UnboxedInt52InGPR;
        else if (dataFormat == DataFormatStrictInt52)
            result.m_technique = UnboxedStrictInt52InGPR;
98
99
        else if (dataFormat == DataFormatBoolean)
            result.m_technique = UnboxedBooleanInGPR;
100
101
        else if (dataFormat == DataFormatCell)
            result.m_technique = UnboxedCellInGPR;
102
103
104
105
106
107
        else
            result.m_technique = InGPR;
        result.m_source.gpr = gpr;
        return result;
    }
    
108
109
110
111
112
113
114
115
    static ValueRecovery uint32InGPR(MacroAssembler::RegisterID gpr)
    {
        ValueRecovery result;
        result.m_technique = UInt32InGPR;
        result.m_source.gpr = gpr;
        return result;
    }
    
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#if USE(JSVALUE32_64)
    static ValueRecovery inPair(MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR)
    {
        ValueRecovery result;
        result.m_technique = InPair;
        result.m_source.pair.tagGPR = tagGPR;
        result.m_source.pair.payloadGPR = payloadGPR;
        return result;
    }
#endif

    static ValueRecovery inFPR(MacroAssembler::FPRegisterID fpr)
    {
        ValueRecovery result;
        result.m_technique = InFPR;
        result.m_source.fpr = fpr;
        return result;
    }
    
135
    static ValueRecovery displacedInJSStack(VirtualRegister virtualReg, DataFormat dataFormat)
136
137
138
    {
        ValueRecovery result;
        switch (dataFormat) {
139
        case DataFormatInt32:
140
            result.m_technique = Int32DisplacedInJSStack;
141
142
            break;
            
143
144
145
146
147
148
149
150
        case DataFormatInt52:
            result.m_technique = Int52DisplacedInJSStack;
            break;
            
        case DataFormatStrictInt52:
            result.m_technique = StrictInt52DisplacedInJSStack;
            break;
            
151
        case DataFormatDouble:
152
            result.m_technique = DoubleDisplacedInJSStack;
153
154
            break;

155
        case DataFormatCell:
156
            result.m_technique = CellDisplacedInJSStack;
157
158
159
            break;
            
        case DataFormatBoolean:
160
            result.m_technique = BooleanDisplacedInJSStack;
161
162
            break;
            
163
164
        default:
            ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage);
165
            result.m_technique = DisplacedInJSStack;
166
167
            break;
        }
168
        result.m_source.virtualReg = virtualReg.offset();
169
170
171
172
173
174
175
176
177
178
179
        return result;
    }
    
    static ValueRecovery constant(JSValue value)
    {
        ValueRecovery result;
        result.m_technique = Constant;
        result.m_source.constant = JSValue::encode(value);
        return result;
    }
    
180
181
182
183
184
185
186
    static ValueRecovery argumentsThatWereNotCreated()
    {
        ValueRecovery result;
        result.m_technique = ArgumentsThatWereNotCreated;
        return result;
    }
    
187
188
    ValueRecoveryTechnique technique() const { return m_technique; }
    
189
190
    bool isConstant() const { return m_technique == Constant; }
    
191
192
193
194
195
196
    bool isInRegisters() const
    {
        switch (m_technique) {
        case InGPR:
        case UnboxedInt32InGPR:
        case UnboxedBooleanInGPR:
197
198
199
        case UnboxedCellInGPR:
        case UnboxedInt52InGPR:
        case UnboxedStrictInt52InGPR:
200
201
202
203
204
205
206
207
208
209
210
211
#if USE(JSVALUE32_64)
        case InPair:
#endif
        case InFPR:
            return true;
        default:
            return false;
        }
    }
    
    MacroAssembler::RegisterID gpr() const
    {
212
        ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR || m_technique == UnboxedInt52InGPR || m_technique == UnboxedStrictInt52InGPR || m_technique == UnboxedCellInGPR);
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
        return m_source.gpr;
    }
    
#if USE(JSVALUE32_64)
    MacroAssembler::RegisterID tagGPR() const
    {
        ASSERT(m_technique == InPair);
        return m_source.pair.tagGPR;
    }
    
    MacroAssembler::RegisterID payloadGPR() const
    {
        ASSERT(m_technique == InPair);
        return m_source.pair.payloadGPR;
    }
#endif
    
    MacroAssembler::FPRegisterID fpr() const
    {
        ASSERT(m_technique == InFPR);
        return m_source.fpr;
    }
    
    VirtualRegister virtualRegister() const
    {
238
        ASSERT(m_technique == DisplacedInJSStack || m_technique == Int32DisplacedInJSStack || m_technique == DoubleDisplacedInJSStack || m_technique == CellDisplacedInJSStack || m_technique == BooleanDisplacedInJSStack || m_technique == Int52DisplacedInJSStack || m_technique == StrictInt52DisplacedInJSStack);
239
        return VirtualRegister(m_source.virtualReg);
240
241
242
243
244
245
246
247
    }
    
    JSValue constant() const
    {
        ASSERT(m_technique == Constant);
        return JSValue::decode(m_source.constant);
    }
    
248
    JSValue recover(ExecState*) const;
249
    
250
#if ENABLE(JIT)
251
252
    void dumpInContext(PrintStream& out, DumpContext* context) const;
    void dump(PrintStream& out) const;
253
#endif
254

255
256
257
258
259
260
261
262
263
264
265
private:
    ValueRecoveryTechnique m_technique;
    union {
        MacroAssembler::RegisterID gpr;
        MacroAssembler::FPRegisterID fpr;
#if USE(JSVALUE32_64)
        struct {
            MacroAssembler::RegisterID tagGPR;
            MacroAssembler::RegisterID payloadGPR;
        } pair;
#endif
266
        int virtualReg;
267
268
269
270
271
272
273
        EncodedJSValue constant;
    } m_source;
};

} // namespace JSC

#endif // ValueRecovery_h