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