1/*
2 * Copyright (C) 2008 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
28namespace JSC {
29
30 // FIXME: Consider whether this is actually necessary. Is LLInt and Baseline's profiling information enough?
31 // https://bugs.webkit.org/show_bug.cgi?id=201659
32 struct ResultType {
33 private:
34 friend struct OperandTypes;
35
36 using Type = uint8_t;
37 static constexpr Type TypeInt32 = 0x1 << 0;
38 static constexpr Type TypeMaybeNumber = 0x1 << 1;
39 static constexpr Type TypeMaybeString = 0x1 << 2;
40 static constexpr Type TypeMaybeBigInt = 0x1 << 3;
41 static constexpr Type TypeMaybeNull = 0x1 << 4;
42 static constexpr Type TypeMaybeBool = 0x1 << 5;
43 static constexpr Type TypeMaybeOther = 0x1 << 6;
44
45 static constexpr Type TypeBits = TypeMaybeNumber | TypeMaybeString | TypeMaybeBigInt | TypeMaybeNull | TypeMaybeBool | TypeMaybeOther;
46
47 public:
48 static constexpr int numBitsNeeded = 7;
49 static_assert((TypeBits & ((1 << numBitsNeeded) - 1)) == TypeBits, "This is necessary for correctness.");
50
51 constexpr explicit ResultType()
52 : ResultType(unknownType())
53 {
54 }
55 constexpr explicit ResultType(Type type)
56 : m_bits(type)
57 {
58 }
59
60 constexpr bool isInt32() const
61 {
62 return m_bits & TypeInt32;
63 }
64
65 constexpr bool definitelyIsNumber() const
66 {
67 return (m_bits & TypeBits) == TypeMaybeNumber;
68 }
69
70 constexpr bool definitelyIsString() const
71 {
72 return (m_bits & TypeBits) == TypeMaybeString;
73 }
74
75 constexpr bool definitelyIsBoolean() const
76 {
77 return (m_bits & TypeBits) == TypeMaybeBool;
78 }
79
80 constexpr bool definitelyIsBigInt() const
81 {
82 return (m_bits & TypeBits) == TypeMaybeBigInt;
83 }
84
85 constexpr bool definitelyIsNull() const
86 {
87 return (m_bits & TypeBits) == TypeMaybeNull;
88 }
89
90 constexpr bool mightBeUndefinedOrNull() const
91 {
92 return m_bits & (TypeMaybeNull | TypeMaybeOther);
93 }
94
95 constexpr bool mightBeNumber() const
96 {
97 return m_bits & TypeMaybeNumber;
98 }
99
100 constexpr bool isNotNumber() const
101 {
102 return !mightBeNumber();
103 }
104
105 constexpr bool mightBeBigInt() const
106 {
107 return m_bits & TypeMaybeBigInt;
108 }
109
110 constexpr bool isNotBigInt() const
111 {
112 return !mightBeBigInt();
113 }
114
115 static constexpr ResultType nullType()
116 {
117 return ResultType(TypeMaybeNull);
118 }
119
120 static constexpr ResultType booleanType()
121 {
122 return ResultType(TypeMaybeBool);
123 }
124
125 static constexpr ResultType numberType()
126 {
127 return ResultType(TypeMaybeNumber);
128 }
129
130 static constexpr ResultType numberTypeIsInt32()
131 {
132 return ResultType(TypeInt32 | TypeMaybeNumber);
133 }
134
135 static constexpr ResultType stringOrNumberType()
136 {
137 return ResultType(TypeMaybeNumber | TypeMaybeString);
138 }
139
140 static constexpr ResultType addResultType()
141 {
142 return ResultType(TypeMaybeNumber | TypeMaybeString | TypeMaybeBigInt);
143 }
144
145 static constexpr ResultType stringType()
146 {
147 return ResultType(TypeMaybeString);
148 }
149
150 static constexpr ResultType bigIntType()
151 {
152 return ResultType(TypeMaybeBigInt);
153 }
154
155 static constexpr ResultType bigIntOrInt32Type()
156 {
157 return ResultType(TypeMaybeBigInt | TypeInt32 | TypeMaybeNumber);
158 }
159
160 static constexpr ResultType unknownType()
161 {
162 return ResultType(TypeBits);
163 }
164
165 static constexpr ResultType forAdd(ResultType op1, ResultType op2)
166 {
167 if (op1.definitelyIsNumber() && op2.definitelyIsNumber())
168 return numberType();
169 if (op1.definitelyIsString() || op2.definitelyIsString())
170 return stringType();
171 if (op1.definitelyIsBigInt() && op2.definitelyIsBigInt())
172 return bigIntType();
173 return addResultType();
174 }
175
176 // Unlike in C, a logical op produces the value of the
177 // last expression evaluated (and not true or false).
178 static constexpr ResultType forLogicalOp(ResultType op1, ResultType op2)
179 {
180 if (op1.definitelyIsBoolean() && op2.definitelyIsBoolean())
181 return booleanType();
182 if (op1.definitelyIsNumber() && op2.definitelyIsNumber())
183 return numberType();
184 if (op1.definitelyIsString() && op2.definitelyIsString())
185 return stringType();
186 if (op1.definitelyIsBigInt() && op2.definitelyIsBigInt())
187 return bigIntType();
188 return unknownType();
189 }
190
191 static constexpr ResultType forCoalesce(ResultType op1, ResultType op2)
192 {
193 if (op1.definitelyIsNull())
194 return op2;
195 if (!op1.mightBeUndefinedOrNull())
196 return op1;
197 return unknownType();
198 }
199
200 static constexpr ResultType forBitOp()
201 {
202 return bigIntOrInt32Type();
203 }
204
205 constexpr Type bits() const { return m_bits; }
206
207 void dump(PrintStream& out) const
208 {
209 // FIXME: more meaningful information
210 // https://bugs.webkit.org/show_bug.cgi?id=190930
211 out.print(bits());
212 }
213
214 private:
215 Type m_bits;
216 };
217
218 struct OperandTypes
219 {
220 OperandTypes(ResultType first = ResultType::unknownType(), ResultType second = ResultType::unknownType())
221 {
222 m_first = first.m_bits;
223 m_second = second.m_bits;
224 }
225
226 ResultType::Type m_first;
227 ResultType::Type m_second;
228
229 ResultType first() const
230 {
231 return ResultType(m_first);
232 }
233
234 ResultType second() const
235 {
236 return ResultType(m_second);
237 }
238
239 uint16_t bits()
240 {
241 static_assert(sizeof(OperandTypes) == sizeof(uint16_t));
242 return bitwise_cast<uint16_t>(*this);
243 }
244
245 static OperandTypes fromBits(uint16_t bits)
246 {
247 return bitwise_cast<OperandTypes>(bits);
248 }
249
250 void dump(PrintStream& out) const
251 {
252 out.print("OperandTypes(", first(), ", ", second(), ")");
253 }
254 };
255
256} // namespace JSC
257