1/*
2 * Copyright (C) 2013-2016 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 "DFGNodeFlags.h"
31#include "SpeculatedType.h"
32#include <wtf/PrintStream.h>
33
34namespace JSC { namespace DFG {
35
36enum UseKind {
37 // The DFG has 3 representations of values used:
38
39 // 1. The JSValue representation for a JSValue that must be stored in a GP
40 // register (or a GP register pair), and follows rules for boxing and unboxing
41 // that allow the JSValue to be stored as either fully boxed JSValues, or
42 // unboxed Int32, Booleans, Cells, etc. in 32-bit as appropriate.
43 UntypedUse, // UntypedUse must come first (value 0).
44 Int32Use,
45 KnownInt32Use,
46 AnyIntUse,
47 NumberUse,
48 RealNumberUse,
49 BooleanUse,
50 KnownBooleanUse,
51 CellUse,
52 KnownCellUse,
53 CellOrOtherUse,
54 ObjectUse,
55 ArrayUse,
56 FunctionUse,
57 FinalObjectUse,
58 RegExpObjectUse,
59 ProxyObjectUse,
60 DerivedArrayUse,
61 ObjectOrOtherUse,
62 StringIdentUse,
63 StringUse,
64 StringOrOtherUse,
65 KnownStringUse,
66 KnownPrimitiveUse, // This bizarre type arises for op_strcat, which has a bytecode guarantee that it will only see primitives (i.e. not objects).
67 SymbolUse,
68 BigIntUse,
69 MapObjectUse,
70 SetObjectUse,
71 WeakMapObjectUse,
72 WeakSetObjectUse,
73 DataViewObjectUse,
74 StringObjectUse,
75 StringOrStringObjectUse,
76 NotStringVarUse,
77 NotSymbolUse,
78 NotCellUse,
79 KnownOtherUse,
80 OtherUse,
81 MiscUse,
82
83 // 2. The Double representation for an unboxed double value that must be stored
84 // in an FP register.
85 DoubleRepUse,
86 DoubleRepRealUse,
87 DoubleRepAnyIntUse,
88
89 // 3. The Int52 representation for an unboxed integer value that must be stored
90 // in a GP register.
91 Int52RepUse,
92
93 LastUseKind // Must always be the last entry in the enum, as it is used to denote the number of enum elements.
94};
95
96inline SpeculatedType typeFilterFor(UseKind useKind)
97{
98 switch (useKind) {
99 case UntypedUse:
100 return SpecBytecodeTop;
101 case Int32Use:
102 case KnownInt32Use:
103 return SpecInt32Only;
104 case Int52RepUse:
105 return SpecInt52Any;
106 case AnyIntUse:
107 return SpecInt32Only | SpecAnyIntAsDouble;
108 case NumberUse:
109 return SpecBytecodeNumber;
110 case RealNumberUse:
111 return SpecBytecodeRealNumber;
112 case DoubleRepUse:
113 return SpecFullDouble;
114 case DoubleRepRealUse:
115 return SpecDoubleReal;
116 case DoubleRepAnyIntUse:
117 return SpecAnyIntAsDouble;
118 case BooleanUse:
119 case KnownBooleanUse:
120 return SpecBoolean;
121 case CellUse:
122 case KnownCellUse:
123 return SpecCellCheck;
124 case CellOrOtherUse:
125 return SpecCellCheck | SpecOther;
126 case ObjectUse:
127 return SpecObject;
128 case ArrayUse:
129 return SpecArray;
130 case FunctionUse:
131 return SpecFunction;
132 case FinalObjectUse:
133 return SpecFinalObject;
134 case RegExpObjectUse:
135 return SpecRegExpObject;
136 case ProxyObjectUse:
137 return SpecProxyObject;
138 case DerivedArrayUse:
139 return SpecDerivedArray;
140 case ObjectOrOtherUse:
141 return SpecObject | SpecOther;
142 case StringIdentUse:
143 return SpecStringIdent;
144 case StringUse:
145 case KnownStringUse:
146 return SpecString;
147 case StringOrOtherUse:
148 return SpecString | SpecOther;
149 case KnownPrimitiveUse:
150 return SpecHeapTop & ~SpecObject;
151 case SymbolUse:
152 return SpecSymbol;
153 case BigIntUse:
154 return SpecBigInt;
155 case MapObjectUse:
156 return SpecMapObject;
157 case SetObjectUse:
158 return SpecSetObject;
159 case WeakMapObjectUse:
160 return SpecWeakMapObject;
161 case WeakSetObjectUse:
162 return SpecWeakSetObject;
163 case DataViewObjectUse:
164 return SpecDataViewObject;
165 case StringObjectUse:
166 return SpecStringObject;
167 case StringOrStringObjectUse:
168 return SpecString | SpecStringObject;
169 case NotStringVarUse:
170 return ~SpecStringVar;
171 case NotSymbolUse:
172 return ~SpecSymbol;
173 case NotCellUse:
174 return ~SpecCellCheck;
175 case KnownOtherUse:
176 case OtherUse:
177 return SpecOther;
178 case MiscUse:
179 return SpecMisc;
180 default:
181 RELEASE_ASSERT_NOT_REACHED();
182 return SpecFullTop;
183 }
184}
185
186inline bool shouldNotHaveTypeCheck(UseKind kind)
187{
188 switch (kind) {
189 case UntypedUse:
190 case KnownInt32Use:
191 case KnownCellUse:
192 case KnownStringUse:
193 case KnownPrimitiveUse:
194 case KnownBooleanUse:
195 case KnownOtherUse:
196 case Int52RepUse:
197 case DoubleRepUse:
198 return true;
199 default:
200 return false;
201 }
202}
203
204inline bool mayHaveTypeCheck(UseKind kind)
205{
206 return !shouldNotHaveTypeCheck(kind);
207}
208
209inline bool isNumerical(UseKind kind)
210{
211 switch (kind) {
212 case Int32Use:
213 case KnownInt32Use:
214 case NumberUse:
215 case RealNumberUse:
216 case Int52RepUse:
217 case DoubleRepUse:
218 case DoubleRepRealUse:
219 case AnyIntUse:
220 case DoubleRepAnyIntUse:
221 return true;
222 default:
223 return false;
224 }
225}
226
227inline bool isDouble(UseKind kind)
228{
229 switch (kind) {
230 case DoubleRepUse:
231 case DoubleRepRealUse:
232 case DoubleRepAnyIntUse:
233 return true;
234 default:
235 return false;
236 }
237}
238
239// Returns true if the use kind only admits cells, and is therefore appropriate for
240// SpeculateCellOperand in the DFG or lowCell() in the FTL.
241inline bool isCell(UseKind kind)
242{
243 switch (kind) {
244 case CellUse:
245 case KnownCellUse:
246 case ObjectUse:
247 case ArrayUse:
248 case FunctionUse:
249 case FinalObjectUse:
250 case RegExpObjectUse:
251 case ProxyObjectUse:
252 case DerivedArrayUse:
253 case StringIdentUse:
254 case StringUse:
255 case KnownStringUse:
256 case SymbolUse:
257 case BigIntUse:
258 case StringObjectUse:
259 case StringOrStringObjectUse:
260 case MapObjectUse:
261 case SetObjectUse:
262 case WeakMapObjectUse:
263 case WeakSetObjectUse:
264 case DataViewObjectUse:
265 return true;
266 default:
267 return false;
268 }
269}
270
271// Returns true if we've already guaranteed the type
272inline bool alreadyChecked(UseKind kind, SpeculatedType type)
273{
274 return !(type & ~typeFilterFor(kind));
275}
276
277inline UseKind useKindForResult(NodeFlags result)
278{
279 ASSERT(!(result & ~NodeResultMask));
280 switch (result) {
281 case NodeResultInt52:
282 return Int52RepUse;
283 case NodeResultDouble:
284 return DoubleRepUse;
285 default:
286 return UntypedUse;
287 }
288}
289
290inline bool checkMayCrashIfInputIsEmpty(UseKind kind)
291{
292#if USE(JSVALUE64)
293 switch (kind) {
294 case UntypedUse:
295 case Int32Use:
296 case KnownInt32Use:
297 case AnyIntUse:
298 case NumberUse:
299 case BooleanUse:
300 case KnownBooleanUse:
301 case CellUse:
302 case KnownCellUse:
303 case CellOrOtherUse:
304 case KnownOtherUse:
305 case OtherUse:
306 case MiscUse:
307 case NotCellUse:
308 return false;
309 default:
310 return true;
311 }
312#else
313 UNUSED_PARAM(kind);
314 return true;
315#endif
316}
317
318} } // namespace JSC::DFG
319
320namespace WTF {
321
322void printInternal(PrintStream&, JSC::DFG::UseKind);
323
324} // namespace WTF
325
326#endif // ENABLE(DFG_JIT)
327