2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef FTLExitValue_h
27 #define FTLExitValue_h
31 #include "FTLExitArgument.h"
32 #include "FTLRecoveryOpcode.h"
33 #include "JSCJSValue.h"
34 #include "VirtualRegister.h"
35 #include <wtf/PrintStream.h>
39 class TrackedReferences
;
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
55 ExitValueInJSStackAsInt32
,
56 ExitValueInJSStackAsInt52
,
57 ExitValueInJSStackAsDouble
,
59 ExitValueMaterializeNewObject
62 class ExitTimeObjectMaterialization
;
67 : m_kind(InvalidExitValue
)
71 bool operator!() const { return m_kind
== InvalidExitValue
; }
73 static ExitValue
dead()
76 result
.m_kind
= ExitValueDead
;
80 static ExitValue
inJSStack(VirtualRegister reg
)
83 result
.m_kind
= ExitValueInJSStack
;
84 result
.u
.virtualRegister
= reg
.offset();
88 static ExitValue
inJSStackAsInt32(VirtualRegister reg
)
91 result
.m_kind
= ExitValueInJSStackAsInt32
;
92 result
.u
.virtualRegister
= reg
.offset();
96 static ExitValue
inJSStackAsInt52(VirtualRegister reg
)
99 result
.m_kind
= ExitValueInJSStackAsInt52
;
100 result
.u
.virtualRegister
= reg
.offset();
104 static ExitValue
inJSStackAsDouble(VirtualRegister reg
)
107 result
.m_kind
= ExitValueInJSStackAsDouble
;
108 result
.u
.virtualRegister
= reg
.offset();
112 static ExitValue
constant(JSValue value
)
115 result
.m_kind
= ExitValueConstant
;
116 result
.u
.constant
= JSValue::encode(value
);
120 static ExitValue
exitArgument(const ExitArgument
& argument
)
123 result
.m_kind
= ExitValueArgument
;
124 result
.u
.argument
= argument
.representation();
128 static ExitValue
recovery(RecoveryOpcode opcode
, unsigned leftArgument
, unsigned rightArgument
, ValueFormat format
)
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
;
139 static ExitValue
materializeNewObject(ExitTimeObjectMaterialization
*);
141 ExitValueKind
kind() const { return m_kind
; }
143 bool isDead() const { return kind() == ExitValueDead
; }
144 bool isInJSStackSomehow() const
147 case ExitValueInJSStack
:
148 case ExitValueInJSStackAsInt32
:
149 case ExitValueInJSStackAsInt52
:
150 case ExitValueInJSStackAsDouble
:
156 bool isConstant() const { return kind() == ExitValueConstant
; }
157 bool isArgument() const { return kind() == ExitValueArgument
; }
158 bool isRecovery() const { return kind() == ExitValueRecovery
; }
159 bool isObjectMaterialization() const { return kind() == ExitValueMaterializeNewObject
; }
161 ExitArgument
exitArgument() const
163 ASSERT(isArgument());
164 return ExitArgument(u
.argument
);
167 unsigned leftRecoveryArgument() const
169 ASSERT(isRecovery());
170 return u
.recovery
.leftArgument
;
173 unsigned rightRecoveryArgument() const
175 ASSERT(isRecovery());
176 return u
.recovery
.rightArgument
;
179 ValueFormat
recoveryFormat() const
181 ASSERT(isRecovery());
182 return static_cast<ValueFormat
>(u
.recovery
.format
);
185 RecoveryOpcode
recoveryOpcode() const
187 ASSERT(isRecovery());
188 return static_cast<RecoveryOpcode
>(u
.recovery
.opcode
);
191 JSValue
constant() const
193 ASSERT(isConstant());
194 return JSValue::decode(u
.constant
);
197 VirtualRegister
virtualRegister() const
199 ASSERT(isInJSStackSomehow());
200 return VirtualRegister(u
.virtualRegister
);
203 ExitTimeObjectMaterialization
* objectMaterialization() const
205 ASSERT(isObjectMaterialization());
206 return u
.newObjectMaterializationData
;
209 ExitValue
withVirtualRegister(VirtualRegister virtualRegister
) const
211 ASSERT(isInJSStackSomehow());
213 result
.m_kind
= m_kind
;
214 result
.u
.virtualRegister
= virtualRegister
.offset();
218 ExitValue
withLocalsOffset(int offset
) const;
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
224 ValueFormat
valueFormat() const;
226 void dump(PrintStream
&) const;
227 void dumpInContext(PrintStream
&, DumpContext
*) const;
229 void validateReferences(const TrackedReferences
&) const;
232 ExitValueKind m_kind
;
234 ExitArgumentRepresentation argument
;
235 EncodedJSValue constant
;
238 uint16_t leftArgument
;
239 uint16_t rightArgument
;
243 ExitTimeObjectMaterialization
* newObjectMaterializationData
;
247 } } // namespace JSC::FTL
249 #endif // ENABLE(FTL_JIT)
251 #endif // FTLExitValue_h