]> git.saurik.com Git - apple/javascriptcore.git/blame - ftl/FTLExitValue.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / ftl / FTLExitValue.h
CommitLineData
81345200 1/*
ed1e77d3 2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
81345200
A
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 FTLExitValue_h
27#define FTLExitValue_h
28
29#if ENABLE(FTL_JIT)
30
31#include "FTLExitArgument.h"
32#include "FTLRecoveryOpcode.h"
33#include "JSCJSValue.h"
34#include "VirtualRegister.h"
35#include <wtf/PrintStream.h>
36
ed1e77d3
A
37namespace JSC {
38
39class TrackedReferences;
40
41namespace FTL {
81345200
A
42
43// This is like ValueRecovery, but respects the way that the FTL does OSR
44// exit: the live non-constant non-flushed values are passed as arguments
45// to a noreturn tail call. ExitValue is hence mostly responsible for
46// telling us the mapping between operands in bytecode and the arguments to
47// the call.
48
49enum ExitValueKind {
50 InvalidExitValue,
51 ExitValueDead,
52 ExitValueArgument,
53 ExitValueConstant,
54 ExitValueInJSStack,
55 ExitValueInJSStackAsInt32,
56 ExitValueInJSStackAsInt52,
57 ExitValueInJSStackAsDouble,
ed1e77d3
A
58 ExitValueRecovery,
59 ExitValueMaterializeNewObject
81345200
A
60};
61
ed1e77d3
A
62class ExitTimeObjectMaterialization;
63
81345200
A
64class ExitValue {
65public:
66 ExitValue()
67 : m_kind(InvalidExitValue)
68 {
69 }
70
71 bool operator!() const { return m_kind == InvalidExitValue; }
72
73 static ExitValue dead()
74 {
75 ExitValue result;
76 result.m_kind = ExitValueDead;
77 return result;
78 }
79
80 static ExitValue inJSStack(VirtualRegister reg)
81 {
82 ExitValue result;
83 result.m_kind = ExitValueInJSStack;
84 result.u.virtualRegister = reg.offset();
85 return result;
86 }
87
88 static ExitValue inJSStackAsInt32(VirtualRegister reg)
89 {
90 ExitValue result;
91 result.m_kind = ExitValueInJSStackAsInt32;
92 result.u.virtualRegister = reg.offset();
93 return result;
94 }
95
96 static ExitValue inJSStackAsInt52(VirtualRegister reg)
97 {
98 ExitValue result;
99 result.m_kind = ExitValueInJSStackAsInt52;
100 result.u.virtualRegister = reg.offset();
101 return result;
102 }
103
104 static ExitValue inJSStackAsDouble(VirtualRegister reg)
105 {
106 ExitValue result;
107 result.m_kind = ExitValueInJSStackAsDouble;
108 result.u.virtualRegister = reg.offset();
109 return result;
110 }
111
112 static ExitValue constant(JSValue value)
113 {
114 ExitValue result;
115 result.m_kind = ExitValueConstant;
116 result.u.constant = JSValue::encode(value);
117 return result;
118 }
119
120 static ExitValue exitArgument(const ExitArgument& argument)
121 {
122 ExitValue result;
123 result.m_kind = ExitValueArgument;
124 result.u.argument = argument.representation();
125 return result;
126 }
127
81345200
A
128 static ExitValue recovery(RecoveryOpcode opcode, unsigned leftArgument, unsigned rightArgument, ValueFormat format)
129 {
130 ExitValue result;
131 result.m_kind = ExitValueRecovery;
132 result.u.recovery.opcode = opcode;
133 result.u.recovery.leftArgument = leftArgument;
134 result.u.recovery.rightArgument = rightArgument;
135 result.u.recovery.format = format;
136 return result;
137 }
138
ed1e77d3
A
139 static ExitValue materializeNewObject(ExitTimeObjectMaterialization*);
140
81345200
A
141 ExitValueKind kind() const { return m_kind; }
142
143 bool isDead() const { return kind() == ExitValueDead; }
144 bool isInJSStackSomehow() const
145 {
146 switch (kind()) {
147 case ExitValueInJSStack:
148 case ExitValueInJSStackAsInt32:
149 case ExitValueInJSStackAsInt52:
150 case ExitValueInJSStackAsDouble:
151 return true;
152 default:
153 return false;
154 }
155 }
156 bool isConstant() const { return kind() == ExitValueConstant; }
157 bool isArgument() const { return kind() == ExitValueArgument; }
81345200 158 bool isRecovery() const { return kind() == ExitValueRecovery; }
ed1e77d3 159 bool isObjectMaterialization() const { return kind() == ExitValueMaterializeNewObject; }
81345200
A
160
161 ExitArgument exitArgument() const
162 {
163 ASSERT(isArgument());
164 return ExitArgument(u.argument);
165 }
166
167 unsigned leftRecoveryArgument() const
168 {
169 ASSERT(isRecovery());
170 return u.recovery.leftArgument;
171 }
172
173 unsigned rightRecoveryArgument() const
174 {
175 ASSERT(isRecovery());
176 return u.recovery.rightArgument;
177 }
178
179 ValueFormat recoveryFormat() const
180 {
181 ASSERT(isRecovery());
182 return static_cast<ValueFormat>(u.recovery.format);
183 }
184
185 RecoveryOpcode recoveryOpcode() const
186 {
187 ASSERT(isRecovery());
188 return static_cast<RecoveryOpcode>(u.recovery.opcode);
189 }
190
191 JSValue constant() const
192 {
193 ASSERT(isConstant());
194 return JSValue::decode(u.constant);
195 }
196
197 VirtualRegister virtualRegister() const
198 {
199 ASSERT(isInJSStackSomehow());
200 return VirtualRegister(u.virtualRegister);
201 }
202
ed1e77d3
A
203 ExitTimeObjectMaterialization* objectMaterialization() const
204 {
205 ASSERT(isObjectMaterialization());
206 return u.newObjectMaterializationData;
207 }
208
209 ExitValue withVirtualRegister(VirtualRegister virtualRegister) const
81345200
A
210 {
211 ASSERT(isInJSStackSomehow());
212 ExitValue result;
213 result.m_kind = m_kind;
214 result.u.virtualRegister = virtualRegister.offset();
215 return result;
216 }
ed1e77d3
A
217
218 ExitValue withLocalsOffset(int offset) const;
219
81345200
A
220 // If it's in the JSStack somehow, this will tell you what format it's in, in a manner
221 // that is compatible with exitArgument().format(). If it's a constant or it's dead, it
222 // will claim to be a JSValue. If it's an argument then it will tell you the argument's
223 // format.
ed1e77d3 224 ValueFormat valueFormat() const;
81345200
A
225
226 void dump(PrintStream&) const;
227 void dumpInContext(PrintStream&, DumpContext*) const;
228
ed1e77d3
A
229 void validateReferences(const TrackedReferences&) const;
230
81345200
A
231private:
232 ExitValueKind m_kind;
233 union {
234 ExitArgumentRepresentation argument;
235 EncodedJSValue constant;
236 int virtualRegister;
237 struct {
238 uint16_t leftArgument;
239 uint16_t rightArgument;
240 uint16_t opcode;
241 uint16_t format;
242 } recovery;
ed1e77d3 243 ExitTimeObjectMaterialization* newObjectMaterializationData;
81345200
A
244 } u;
245};
246
247} } // namespace JSC::FTL
248
249#endif // ENABLE(FTL_JIT)
250
251#endif // FTLExitValue_h