1/*
2 * Copyright (C) 2011, 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(DFG_JIT)
29
30#include "DFGFlushFormat.h"
31#include "DFGMinifiedID.h"
32#include "DataFormat.h"
33#include "ValueRecovery.h"
34
35namespace JSC { namespace DFG {
36
37enum ValueSourceKind {
38 SourceNotSet,
39 ValueInJSStack,
40 Int32InJSStack,
41 Int52InJSStack,
42 CellInJSStack,
43 BooleanInJSStack,
44 DoubleInJSStack,
45 SourceIsDead,
46 HaveNode
47};
48
49static inline ValueSourceKind dataFormatToValueSourceKind(DataFormat dataFormat)
50{
51 switch (dataFormat) {
52 case DataFormatInt32:
53 return Int32InJSStack;
54 case DataFormatInt52:
55 return Int52InJSStack;
56 case DataFormatDouble:
57 return DoubleInJSStack;
58 case DataFormatBoolean:
59 return BooleanInJSStack;
60 case DataFormatCell:
61 return CellInJSStack;
62 case DataFormatDead:
63 return SourceIsDead;
64 default:
65 RELEASE_ASSERT(dataFormat & DataFormatJS);
66 return ValueInJSStack;
67 }
68}
69
70static inline DataFormat valueSourceKindToDataFormat(ValueSourceKind kind)
71{
72 switch (kind) {
73 case ValueInJSStack:
74 return DataFormatJS;
75 case Int32InJSStack:
76 return DataFormatInt32;
77 case Int52InJSStack:
78 return DataFormatInt52;
79 case CellInJSStack:
80 return DataFormatCell;
81 case BooleanInJSStack:
82 return DataFormatBoolean;
83 case DoubleInJSStack:
84 return DataFormatDouble;
85 case SourceIsDead:
86 return DataFormatDead;
87 default:
88 return DataFormatNone;
89 }
90}
91
92static inline bool isInJSStack(ValueSourceKind kind)
93{
94 DataFormat format = valueSourceKindToDataFormat(kind);
95 return format != DataFormatNone && format < DataFormatOSRMarker;
96}
97
98// Can this value be recovered without having to look at register allocation state or
99// DFG node liveness?
100static inline bool isTriviallyRecoverable(ValueSourceKind kind)
101{
102 return valueSourceKindToDataFormat(kind) != DataFormatNone;
103}
104
105class ValueSource {
106public:
107 ValueSource()
108 : m_kind(SourceNotSet)
109 {
110 }
111
112 explicit ValueSource(ValueSourceKind valueSourceKind)
113 : m_kind(valueSourceKind)
114 {
115 ASSERT(kind() == SourceIsDead);
116 }
117
118 explicit ValueSource(MinifiedID id)
119 : m_kind(HaveNode)
120 , m_value(id.bits())
121 {
122 ASSERT(!!id);
123 ASSERT(kind() == HaveNode);
124 }
125
126 ValueSource(ValueSourceKind valueSourceKind, VirtualRegister where)
127 : m_kind(valueSourceKind)
128 , m_value(where.offset())
129 {
130 ASSERT(kind() != SourceNotSet);
131 ASSERT(kind() != HaveNode);
132 }
133
134 static ValueSource forFlushFormat(VirtualRegister where, FlushFormat format)
135 {
136 switch (format) {
137 case DeadFlush:
138 case ConflictingFlush:
139 return ValueSource(SourceIsDead);
140 case FlushedJSValue:
141 return ValueSource(ValueInJSStack, where);
142 case FlushedDouble:
143 return ValueSource(DoubleInJSStack, where);
144 case FlushedInt32:
145 return ValueSource(Int32InJSStack, where);
146 case FlushedInt52:
147 return ValueSource(Int52InJSStack, where);
148 case FlushedCell:
149 return ValueSource(CellInJSStack, where);
150 case FlushedBoolean:
151 return ValueSource(BooleanInJSStack, where);
152 }
153 RELEASE_ASSERT_NOT_REACHED();
154 return ValueSource();
155 }
156
157 static ValueSource forDataFormat(VirtualRegister where, DataFormat dataFormat)
158 {
159 return ValueSource(dataFormatToValueSourceKind(dataFormat), where);
160 }
161
162 bool isSet() const
163 {
164 return kind() != SourceNotSet;
165 }
166
167 bool operator!() const { return !isSet(); }
168
169 ValueSourceKind kind() const
170 {
171 return m_kind;
172 }
173
174 bool isInJSStack() const { return JSC::DFG::isInJSStack(kind()); }
175 bool isTriviallyRecoverable() const { return JSC::DFG::isTriviallyRecoverable(kind()); }
176
177 DataFormat dataFormat() const
178 {
179 return valueSourceKindToDataFormat(kind());
180 }
181
182 ValueRecovery valueRecovery() const
183 {
184 ASSERT(isTriviallyRecoverable());
185 switch (kind()) {
186 case SourceIsDead:
187 return ValueRecovery::constant(jsUndefined());
188
189 default:
190 return ValueRecovery::displacedInJSStack(virtualRegister(), dataFormat());
191 }
192 }
193
194 MinifiedID id() const
195 {
196 ASSERT(kind() == HaveNode);
197 return MinifiedID::fromBits(m_value);
198 }
199
200 VirtualRegister virtualRegister() const
201 {
202 ASSERT(isInJSStack());
203 return VirtualRegister(m_value);
204 }
205
206 void dump(PrintStream&) const;
207 void dumpInContext(PrintStream&, DumpContext*) const;
208
209private:
210 ValueSourceKind m_kind;
211 unsigned m_value;
212};
213
214} } // namespace JSC::DFG
215
216#endif // ENABLE(DFG_JIT)
217