1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/compiler/types.h"
6
7 #include <iomanip>
8
9 #include "src/handles/handles-inl.h"
10 #include "src/objects/instance-type.h"
11 #include "src/objects/objects-inl.h"
12 #include "src/utils/ostreams.h"
13
14 namespace v8 {
15 namespace internal {
16 namespace compiler {
17
18 // -----------------------------------------------------------------------------
19 // Range-related helper functions.
20
IsEmpty()21 bool RangeType::Limits::IsEmpty() { return this->min > this->max; }
22
Intersect(Limits lhs,Limits rhs)23 RangeType::Limits RangeType::Limits::Intersect(Limits lhs, Limits rhs) {
24 DisallowHeapAllocation no_allocation;
25 Limits result(lhs);
26 if (lhs.min < rhs.min) result.min = rhs.min;
27 if (lhs.max > rhs.max) result.max = rhs.max;
28 return result;
29 }
30
Union(Limits lhs,Limits rhs)31 RangeType::Limits RangeType::Limits::Union(Limits lhs, Limits rhs) {
32 DisallowHeapAllocation no_allocation;
33 if (lhs.IsEmpty()) return rhs;
34 if (rhs.IsEmpty()) return lhs;
35 Limits result(lhs);
36 if (lhs.min > rhs.min) result.min = rhs.min;
37 if (lhs.max < rhs.max) result.max = rhs.max;
38 return result;
39 }
40
Overlap(const RangeType * lhs,const RangeType * rhs)41 bool Type::Overlap(const RangeType* lhs, const RangeType* rhs) {
42 DisallowHeapAllocation no_allocation;
43 return !RangeType::Limits::Intersect(RangeType::Limits(lhs),
44 RangeType::Limits(rhs))
45 .IsEmpty();
46 }
47
Contains(const RangeType * lhs,const RangeType * rhs)48 bool Type::Contains(const RangeType* lhs, const RangeType* rhs) {
49 DisallowHeapAllocation no_allocation;
50 return lhs->Min() <= rhs->Min() && rhs->Max() <= lhs->Max();
51 }
52
53 // -----------------------------------------------------------------------------
54 // Min and Max computation.
55
Min() const56 double Type::Min() const {
57 DCHECK(this->Is(Number()));
58 DCHECK(!this->Is(NaN()));
59 if (this->IsBitset()) return BitsetType::Min(this->AsBitset());
60 if (this->IsUnion()) {
61 double min = +V8_INFINITY;
62 for (int i = 1, n = AsUnion()->Length(); i < n; ++i) {
63 min = std::min(min, AsUnion()->Get(i).Min());
64 }
65 Type bitset = AsUnion()->Get(0);
66 if (!bitset.Is(NaN())) min = std::min(min, bitset.Min());
67 return min;
68 }
69 if (this->IsRange()) return this->AsRange()->Min();
70 DCHECK(this->IsOtherNumberConstant());
71 return this->AsOtherNumberConstant()->Value();
72 }
73
Max() const74 double Type::Max() const {
75 DCHECK(this->Is(Number()));
76 DCHECK(!this->Is(NaN()));
77 if (this->IsBitset()) return BitsetType::Max(this->AsBitset());
78 if (this->IsUnion()) {
79 double max = -V8_INFINITY;
80 for (int i = 1, n = this->AsUnion()->Length(); i < n; ++i) {
81 max = std::max(max, this->AsUnion()->Get(i).Max());
82 }
83 Type bitset = this->AsUnion()->Get(0);
84 if (!bitset.Is(NaN())) max = std::max(max, bitset.Max());
85 return max;
86 }
87 if (this->IsRange()) return this->AsRange()->Max();
88 DCHECK(this->IsOtherNumberConstant());
89 return this->AsOtherNumberConstant()->Value();
90 }
91
92 // -----------------------------------------------------------------------------
93 // Glb and lub computation.
94
95 // The largest bitset subsumed by this type.
BitsetGlb() const96 Type::bitset Type::BitsetGlb() const {
97 DisallowHeapAllocation no_allocation;
98 // Fast case.
99 if (IsBitset()) {
100 return AsBitset();
101 } else if (IsUnion()) {
102 SLOW_DCHECK(AsUnion()->Wellformed());
103 return AsUnion()->Get(0).BitsetGlb() |
104 AsUnion()->Get(1).BitsetGlb(); // Shortcut.
105 } else if (IsRange()) {
106 bitset glb = BitsetType::Glb(AsRange()->Min(), AsRange()->Max());
107 return glb;
108 } else {
109 return BitsetType::kNone;
110 }
111 }
112
113 // The smallest bitset subsuming this type, possibly not a proper one.
BitsetLub() const114 Type::bitset Type::BitsetLub() const {
115 DisallowHeapAllocation no_allocation;
116 if (IsBitset()) return AsBitset();
117 if (IsUnion()) {
118 // Take the representation from the first element, which is always
119 // a bitset.
120 int bitset = AsUnion()->Get(0).BitsetLub();
121 for (int i = 0, n = AsUnion()->Length(); i < n; ++i) {
122 // Other elements only contribute their semantic part.
123 bitset |= AsUnion()->Get(i).BitsetLub();
124 }
125 return bitset;
126 }
127 if (IsHeapConstant()) return AsHeapConstant()->Lub();
128 if (IsOtherNumberConstant()) {
129 return AsOtherNumberConstant()->Lub();
130 }
131 if (IsRange()) return AsRange()->Lub();
132 if (IsTuple()) return BitsetType::kOtherInternal;
133 UNREACHABLE();
134 }
135
136 // TODO(neis): Once the broker mode kDisabled is gone, change the input type to
137 // MapRef and get rid of the HeapObjectType class.
138 template <typename MapRefLike>
Lub(const MapRefLike & map)139 Type::bitset BitsetType::Lub(const MapRefLike& map) {
140 switch (map.instance_type()) {
141 case CONS_STRING_TYPE:
142 case CONS_ONE_BYTE_STRING_TYPE:
143 case THIN_STRING_TYPE:
144 case THIN_ONE_BYTE_STRING_TYPE:
145 case SLICED_STRING_TYPE:
146 case SLICED_ONE_BYTE_STRING_TYPE:
147 case EXTERNAL_STRING_TYPE:
148 case EXTERNAL_ONE_BYTE_STRING_TYPE:
149 case UNCACHED_EXTERNAL_STRING_TYPE:
150 case UNCACHED_EXTERNAL_ONE_BYTE_STRING_TYPE:
151 case STRING_TYPE:
152 case ONE_BYTE_STRING_TYPE:
153 return kString;
154 case EXTERNAL_INTERNALIZED_STRING_TYPE:
155 case EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
156 case UNCACHED_EXTERNAL_INTERNALIZED_STRING_TYPE:
157 case UNCACHED_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
158 case INTERNALIZED_STRING_TYPE:
159 case ONE_BYTE_INTERNALIZED_STRING_TYPE:
160 return kInternalizedString;
161 case SYMBOL_TYPE:
162 return kSymbol;
163 case BIGINT_TYPE:
164 return kBigInt;
165 case ODDBALL_TYPE:
166 switch (map.oddball_type()) {
167 case OddballType::kNone:
168 break;
169 case OddballType::kHole:
170 return kHole;
171 case OddballType::kBoolean:
172 return kBoolean;
173 case OddballType::kNull:
174 return kNull;
175 case OddballType::kUndefined:
176 return kUndefined;
177 case OddballType::kUninitialized:
178 case OddballType::kOther:
179 // TODO(neis): We should add a kOtherOddball type.
180 return kOtherInternal;
181 }
182 UNREACHABLE();
183 case HEAP_NUMBER_TYPE:
184 return kNumber;
185 case JS_OBJECT_TYPE:
186 case JS_ARGUMENTS_OBJECT_TYPE:
187 case JS_ERROR_TYPE:
188 case JS_GLOBAL_OBJECT_TYPE:
189 case JS_GLOBAL_PROXY_TYPE:
190 case JS_API_OBJECT_TYPE:
191 case JS_SPECIAL_API_OBJECT_TYPE:
192 if (map.is_undetectable()) {
193 // Currently we assume that every undetectable receiver is also
194 // callable, which is what we need to support document.all. We
195 // could add another Type bit to support other use cases in the
196 // future if necessary.
197 DCHECK(map.is_callable());
198 return kOtherUndetectable;
199 }
200 if (map.is_callable()) {
201 return kOtherCallable;
202 }
203 return kOtherObject;
204 case JS_ARRAY_TYPE:
205 return kArray;
206 case JS_PRIMITIVE_WRAPPER_TYPE:
207 case JS_MESSAGE_OBJECT_TYPE:
208 case JS_DATE_TYPE:
209 #ifdef V8_INTL_SUPPORT
210 case JS_V8_BREAK_ITERATOR_TYPE:
211 case JS_COLLATOR_TYPE:
212 case JS_DATE_TIME_FORMAT_TYPE:
213 case JS_DISPLAY_NAMES_TYPE:
214 case JS_LIST_FORMAT_TYPE:
215 case JS_LOCALE_TYPE:
216 case JS_NUMBER_FORMAT_TYPE:
217 case JS_PLURAL_RULES_TYPE:
218 case JS_RELATIVE_TIME_FORMAT_TYPE:
219 case JS_SEGMENT_ITERATOR_TYPE:
220 case JS_SEGMENTER_TYPE:
221 case JS_SEGMENTS_TYPE:
222 #endif // V8_INTL_SUPPORT
223 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
224 case JS_GENERATOR_OBJECT_TYPE:
225 case JS_ASYNC_FUNCTION_OBJECT_TYPE:
226 case JS_ASYNC_GENERATOR_OBJECT_TYPE:
227 case JS_MODULE_NAMESPACE_TYPE:
228 case JS_ARRAY_BUFFER_TYPE:
229 case JS_ARRAY_ITERATOR_TYPE:
230 case JS_REG_EXP_TYPE:
231 case JS_REG_EXP_STRING_ITERATOR_TYPE:
232 case JS_TYPED_ARRAY_TYPE:
233 case JS_DATA_VIEW_TYPE:
234 case JS_SET_TYPE:
235 case JS_MAP_TYPE:
236 case JS_SET_KEY_VALUE_ITERATOR_TYPE:
237 case JS_SET_VALUE_ITERATOR_TYPE:
238 case JS_MAP_KEY_ITERATOR_TYPE:
239 case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
240 case JS_MAP_VALUE_ITERATOR_TYPE:
241 case JS_STRING_ITERATOR_TYPE:
242 case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
243 case JS_FINALIZATION_REGISTRY_TYPE:
244 case JS_WEAK_MAP_TYPE:
245 case JS_WEAK_REF_TYPE:
246 case JS_WEAK_SET_TYPE:
247 case JS_PROMISE_TYPE:
248 case WASM_ARRAY_TYPE:
249 case WASM_EXCEPTION_OBJECT_TYPE:
250 case WASM_GLOBAL_OBJECT_TYPE:
251 case WASM_INSTANCE_OBJECT_TYPE:
252 case WASM_MEMORY_OBJECT_TYPE:
253 case WASM_MODULE_OBJECT_TYPE:
254 case WASM_STRUCT_TYPE:
255 case WASM_TABLE_OBJECT_TYPE:
256 case WEAK_CELL_TYPE:
257 DCHECK(!map.is_callable());
258 DCHECK(!map.is_undetectable());
259 return kOtherObject;
260 case JS_BOUND_FUNCTION_TYPE:
261 DCHECK(!map.is_undetectable());
262 return kBoundFunction;
263 case JS_FUNCTION_TYPE:
264 DCHECK(!map.is_undetectable());
265 return kFunction;
266 case JS_PROXY_TYPE:
267 DCHECK(!map.is_undetectable());
268 if (map.is_callable()) return kCallableProxy;
269 return kOtherProxy;
270 case MAP_TYPE:
271 case ALLOCATION_SITE_TYPE:
272 case ACCESSOR_INFO_TYPE:
273 case SHARED_FUNCTION_INFO_TYPE:
274 case FUNCTION_TEMPLATE_INFO_TYPE:
275 case FUNCTION_TEMPLATE_RARE_DATA_TYPE:
276 case ACCESSOR_PAIR_TYPE:
277 case EMBEDDER_DATA_ARRAY_TYPE:
278 case FIXED_ARRAY_TYPE:
279 case PROPERTY_DESCRIPTOR_OBJECT_TYPE:
280 case HASH_TABLE_TYPE:
281 case ORDERED_HASH_MAP_TYPE:
282 case ORDERED_HASH_SET_TYPE:
283 case ORDERED_NAME_DICTIONARY_TYPE:
284 case NAME_DICTIONARY_TYPE:
285 case GLOBAL_DICTIONARY_TYPE:
286 case NUMBER_DICTIONARY_TYPE:
287 case SIMPLE_NUMBER_DICTIONARY_TYPE:
288 case EPHEMERON_HASH_TABLE_TYPE:
289 case WEAK_FIXED_ARRAY_TYPE:
290 case WEAK_ARRAY_LIST_TYPE:
291 case FIXED_DOUBLE_ARRAY_TYPE:
292 case FEEDBACK_METADATA_TYPE:
293 case BYTE_ARRAY_TYPE:
294 case BYTECODE_ARRAY_TYPE:
295 case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
296 case ARRAY_BOILERPLATE_DESCRIPTION_TYPE:
297 case TRANSITION_ARRAY_TYPE:
298 case FEEDBACK_CELL_TYPE:
299 case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
300 case FEEDBACK_VECTOR_TYPE:
301 case PROPERTY_ARRAY_TYPE:
302 case FOREIGN_TYPE:
303 case SCOPE_INFO_TYPE:
304 case SCRIPT_CONTEXT_TABLE_TYPE:
305 case AWAIT_CONTEXT_TYPE:
306 case BLOCK_CONTEXT_TYPE:
307 case CATCH_CONTEXT_TYPE:
308 case DEBUG_EVALUATE_CONTEXT_TYPE:
309 case EVAL_CONTEXT_TYPE:
310 case FUNCTION_CONTEXT_TYPE:
311 case MODULE_CONTEXT_TYPE:
312 case MODULE_REQUEST_TYPE:
313 case NATIVE_CONTEXT_TYPE:
314 case SCRIPT_CONTEXT_TYPE:
315 case WITH_CONTEXT_TYPE:
316 case SCRIPT_TYPE:
317 case CODE_TYPE:
318 case PROPERTY_CELL_TYPE:
319 case SOURCE_TEXT_MODULE_TYPE:
320 case SOURCE_TEXT_MODULE_INFO_ENTRY_TYPE:
321 case SYNTHETIC_MODULE_TYPE:
322 case CELL_TYPE:
323 case PREPARSE_DATA_TYPE:
324 case UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE:
325 case UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE:
326 case COVERAGE_INFO_TYPE:
327 case WASM_TYPE_INFO_TYPE:
328 return kOtherInternal;
329
330 // Remaining instance types are unsupported for now. If any of them do
331 // require bit set types, they should get kOtherInternal.
332 default:
333 UNREACHABLE();
334 }
335 UNREACHABLE();
336 }
337
338 // Explicit instantiation.
339 template Type::bitset BitsetType::Lub<MapRef>(const MapRef& map);
340
Lub(double value)341 Type::bitset BitsetType::Lub(double value) {
342 DisallowHeapAllocation no_allocation;
343 if (IsMinusZero(value)) return kMinusZero;
344 if (std::isnan(value)) return kNaN;
345 if (IsUint32Double(value) || IsInt32Double(value)) return Lub(value, value);
346 return kOtherNumber;
347 }
348
349 // Minimum values of plain numeric bitsets.
350 const BitsetType::Boundary BitsetType::BoundariesArray[] = {
351 {kOtherNumber, kPlainNumber, -V8_INFINITY},
352 {kOtherSigned32, kNegative32, kMinInt},
353 {kNegative31, kNegative31, -0x40000000},
354 {kUnsigned30, kUnsigned30, 0},
355 {kOtherUnsigned31, kUnsigned31, 0x40000000},
356 {kOtherUnsigned32, kUnsigned32, 0x80000000},
357 {kOtherNumber, kPlainNumber, static_cast<double>(kMaxUInt32) + 1}};
358
Boundaries()359 const BitsetType::Boundary* BitsetType::Boundaries() { return BoundariesArray; }
360
BoundariesSize()361 size_t BitsetType::BoundariesSize() {
362 // Windows doesn't like arraysize here.
363 // return arraysize(BoundariesArray);
364 return 7;
365 }
366
ExpandInternals(Type::bitset bits)367 Type::bitset BitsetType::ExpandInternals(Type::bitset bits) {
368 DCHECK_IMPLIES(bits & kOtherString, (bits & kString) == kString);
369 DisallowHeapAllocation no_allocation;
370 if (!(bits & kPlainNumber)) return bits; // Shortcut.
371 const Boundary* boundaries = Boundaries();
372 for (size_t i = 0; i < BoundariesSize(); ++i) {
373 DCHECK(BitsetType::Is(boundaries[i].internal, boundaries[i].external));
374 if (bits & boundaries[i].internal) bits |= boundaries[i].external;
375 }
376 return bits;
377 }
378
Lub(double min,double max)379 Type::bitset BitsetType::Lub(double min, double max) {
380 DisallowHeapAllocation no_allocation;
381 int lub = kNone;
382 const Boundary* mins = Boundaries();
383
384 for (size_t i = 1; i < BoundariesSize(); ++i) {
385 if (min < mins[i].min) {
386 lub |= mins[i - 1].internal;
387 if (max < mins[i].min) return lub;
388 }
389 }
390 return lub | mins[BoundariesSize() - 1].internal;
391 }
392
NumberBits(bitset bits)393 Type::bitset BitsetType::NumberBits(bitset bits) { return bits & kPlainNumber; }
394
Glb(double min,double max)395 Type::bitset BitsetType::Glb(double min, double max) {
396 DisallowHeapAllocation no_allocation;
397 int glb = kNone;
398 const Boundary* mins = Boundaries();
399
400 // If the range does not touch 0, the bound is empty.
401 if (max < -1 || min > 0) return glb;
402
403 for (size_t i = 1; i + 1 < BoundariesSize(); ++i) {
404 if (min <= mins[i].min) {
405 if (max + 1 < mins[i + 1].min) break;
406 glb |= mins[i].external;
407 }
408 }
409 // OtherNumber also contains float numbers, so it can never be
410 // in the greatest lower bound.
411 return glb & ~(kOtherNumber);
412 }
413
Min(bitset bits)414 double BitsetType::Min(bitset bits) {
415 DisallowHeapAllocation no_allocation;
416 DCHECK(Is(bits, kNumber));
417 DCHECK(!Is(bits, kNaN));
418 const Boundary* mins = Boundaries();
419 bool mz = bits & kMinusZero;
420 for (size_t i = 0; i < BoundariesSize(); ++i) {
421 if (Is(mins[i].internal, bits)) {
422 return mz ? std::min(0.0, mins[i].min) : mins[i].min;
423 }
424 }
425 DCHECK(mz);
426 return 0;
427 }
428
Max(bitset bits)429 double BitsetType::Max(bitset bits) {
430 DisallowHeapAllocation no_allocation;
431 DCHECK(Is(bits, kNumber));
432 DCHECK(!Is(bits, kNaN));
433 const Boundary* mins = Boundaries();
434 bool mz = bits & kMinusZero;
435 if (BitsetType::Is(mins[BoundariesSize() - 1].internal, bits)) {
436 return +V8_INFINITY;
437 }
438 for (size_t i = BoundariesSize() - 1; i-- > 0;) {
439 if (Is(mins[i].internal, bits)) {
440 return mz ? std::max(0.0, mins[i + 1].min - 1) : mins[i + 1].min - 1;
441 }
442 }
443 DCHECK(mz);
444 return 0;
445 }
446
447 // static
IsOtherNumberConstant(double value)448 bool OtherNumberConstantType::IsOtherNumberConstant(double value) {
449 // Not an integer, not NaN, and not -0.
450 return !std::isnan(value) && !RangeType::IsInteger(value) &&
451 !IsMinusZero(value);
452 }
453
HeapConstantType(BitsetType::bitset bitset,const HeapObjectRef & heap_ref)454 HeapConstantType::HeapConstantType(BitsetType::bitset bitset,
455 const HeapObjectRef& heap_ref)
456 : TypeBase(kHeapConstant), bitset_(bitset), heap_ref_(heap_ref) {}
457
Value() const458 Handle<HeapObject> HeapConstantType::Value() const {
459 return heap_ref_.object();
460 }
461
462 // -----------------------------------------------------------------------------
463 // Predicates.
464
SimplyEquals(Type that) const465 bool Type::SimplyEquals(Type that) const {
466 DisallowHeapAllocation no_allocation;
467 if (this->IsHeapConstant()) {
468 return that.IsHeapConstant() &&
469 this->AsHeapConstant()->Value().address() ==
470 that.AsHeapConstant()->Value().address();
471 }
472 if (this->IsOtherNumberConstant()) {
473 return that.IsOtherNumberConstant() &&
474 this->AsOtherNumberConstant()->Value() ==
475 that.AsOtherNumberConstant()->Value();
476 }
477 if (this->IsRange()) {
478 if (that.IsHeapConstant() || that.IsOtherNumberConstant()) return false;
479 }
480 if (this->IsTuple()) {
481 if (!that.IsTuple()) return false;
482 const TupleType* this_tuple = this->AsTuple();
483 const TupleType* that_tuple = that.AsTuple();
484 if (this_tuple->Arity() != that_tuple->Arity()) {
485 return false;
486 }
487 for (int i = 0, n = this_tuple->Arity(); i < n; ++i) {
488 if (!this_tuple->Element(i).Equals(that_tuple->Element(i))) return false;
489 }
490 return true;
491 }
492 UNREACHABLE();
493 }
494
495 // Check if [this] <= [that].
SlowIs(Type that) const496 bool Type::SlowIs(Type that) const {
497 DisallowHeapAllocation no_allocation;
498
499 // Fast bitset cases
500 if (that.IsBitset()) {
501 return BitsetType::Is(this->BitsetLub(), that.AsBitset());
502 }
503
504 if (this->IsBitset()) {
505 return BitsetType::Is(this->AsBitset(), that.BitsetGlb());
506 }
507
508 // (T1 \/ ... \/ Tn) <= T if (T1 <= T) /\ ... /\ (Tn <= T)
509 if (this->IsUnion()) {
510 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
511 if (!this->AsUnion()->Get(i).Is(that)) return false;
512 }
513 return true;
514 }
515
516 // T <= (T1 \/ ... \/ Tn) if (T <= T1) \/ ... \/ (T <= Tn)
517 if (that.IsUnion()) {
518 for (int i = 0, n = that.AsUnion()->Length(); i < n; ++i) {
519 if (this->Is(that.AsUnion()->Get(i))) return true;
520 if (i > 1 && this->IsRange()) return false; // Shortcut.
521 }
522 return false;
523 }
524
525 if (that.IsRange()) {
526 return this->IsRange() && Contains(that.AsRange(), this->AsRange());
527 }
528 if (this->IsRange()) return false;
529
530 return this->SimplyEquals(that);
531 }
532
533 // Check if [this] and [that] overlap.
Maybe(Type that) const534 bool Type::Maybe(Type that) const {
535 DisallowHeapAllocation no_allocation;
536
537 if (BitsetType::IsNone(this->BitsetLub() & that.BitsetLub())) return false;
538
539 // (T1 \/ ... \/ Tn) overlaps T if (T1 overlaps T) \/ ... \/ (Tn overlaps T)
540 if (this->IsUnion()) {
541 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
542 if (this->AsUnion()->Get(i).Maybe(that)) return true;
543 }
544 return false;
545 }
546
547 // T overlaps (T1 \/ ... \/ Tn) if (T overlaps T1) \/ ... \/ (T overlaps Tn)
548 if (that.IsUnion()) {
549 for (int i = 0, n = that.AsUnion()->Length(); i < n; ++i) {
550 if (this->Maybe(that.AsUnion()->Get(i))) return true;
551 }
552 return false;
553 }
554
555 if (this->IsBitset() && that.IsBitset()) return true;
556
557 if (this->IsRange()) {
558 if (that.IsRange()) {
559 return Overlap(this->AsRange(), that.AsRange());
560 }
561 if (that.IsBitset()) {
562 bitset number_bits = BitsetType::NumberBits(that.AsBitset());
563 if (number_bits == BitsetType::kNone) {
564 return false;
565 }
566 double min = std::max(BitsetType::Min(number_bits), this->Min());
567 double max = std::min(BitsetType::Max(number_bits), this->Max());
568 return min <= max;
569 }
570 }
571 if (that.IsRange()) {
572 return that.Maybe(*this); // This case is handled above.
573 }
574
575 if (this->IsBitset() || that.IsBitset()) return true;
576
577 return this->SimplyEquals(that);
578 }
579
580 // Return the range in [this], or [nullptr].
GetRange() const581 Type Type::GetRange() const {
582 DisallowHeapAllocation no_allocation;
583 if (this->IsRange()) return *this;
584 if (this->IsUnion() && this->AsUnion()->Get(1).IsRange()) {
585 return this->AsUnion()->Get(1);
586 }
587 return nullptr;
588 }
589
Wellformed() const590 bool UnionType::Wellformed() const {
591 DisallowHeapAllocation no_allocation;
592 // This checks the invariants of the union representation:
593 // 1. There are at least two elements.
594 // 2. The first element is a bitset, no other element is a bitset.
595 // 3. At most one element is a range, and it must be the second one.
596 // 4. No element is itself a union.
597 // 5. No element (except the bitset) is a subtype of any other.
598 // 6. If there is a range, then the bitset type does not contain
599 // plain number bits.
600 DCHECK_LE(2, this->Length()); // (1)
601 DCHECK(this->Get(0).IsBitset()); // (2a)
602
603 for (int i = 0; i < this->Length(); ++i) {
604 if (i != 0) DCHECK(!this->Get(i).IsBitset()); // (2b)
605 if (i != 1) DCHECK(!this->Get(i).IsRange()); // (3)
606 DCHECK(!this->Get(i).IsUnion()); // (4)
607 for (int j = 0; j < this->Length(); ++j) {
608 if (i != j && i != 0) DCHECK(!this->Get(i).Is(this->Get(j))); // (5)
609 }
610 }
611 DCHECK(!this->Get(1).IsRange() ||
612 (BitsetType::NumberBits(this->Get(0).AsBitset()) ==
613 BitsetType::kNone)); // (6)
614 return true;
615 }
616
617 // -----------------------------------------------------------------------------
618 // Union and intersection
619
Intersect(Type type1,Type type2,Zone * zone)620 Type Type::Intersect(Type type1, Type type2, Zone* zone) {
621 // Fast case: bit sets.
622 if (type1.IsBitset() && type2.IsBitset()) {
623 return NewBitset(type1.AsBitset() & type2.AsBitset());
624 }
625
626 // Fast case: top or bottom types.
627 if (type1.IsNone() || type2.IsAny()) return type1; // Shortcut.
628 if (type2.IsNone() || type1.IsAny()) return type2; // Shortcut.
629
630 // Semi-fast case.
631 if (type1.Is(type2)) return type1;
632 if (type2.Is(type1)) return type2;
633
634 // Slow case: create union.
635
636 // Semantic subtyping check - this is needed for consistency with the
637 // semi-fast case above.
638 if (type1.Is(type2)) {
639 type2 = Any();
640 } else if (type2.Is(type1)) {
641 type1 = Any();
642 }
643
644 bitset bits = type1.BitsetGlb() & type2.BitsetGlb();
645 int size1 = type1.IsUnion() ? type1.AsUnion()->Length() : 1;
646 int size2 = type2.IsUnion() ? type2.AsUnion()->Length() : 1;
647 int size;
648 if (base::bits::SignedAddOverflow32(size1, size2, &size)) return Any();
649 if (base::bits::SignedAddOverflow32(size, 2, &size)) return Any();
650 UnionType* result = UnionType::New(size, zone);
651 size = 0;
652
653 // Deal with bitsets.
654 result->Set(size++, NewBitset(bits));
655
656 RangeType::Limits lims = RangeType::Limits::Empty();
657 size = IntersectAux(type1, type2, result, size, &lims, zone);
658
659 // If the range is not empty, then insert it into the union and
660 // remove the number bits from the bitset.
661 if (!lims.IsEmpty()) {
662 size = UpdateRange(Type::Range(lims, zone), result, size, zone);
663
664 // Remove the number bits.
665 bitset number_bits = BitsetType::NumberBits(bits);
666 bits &= ~number_bits;
667 result->Set(0, NewBitset(bits));
668 }
669 return NormalizeUnion(result, size, zone);
670 }
671
UpdateRange(Type range,UnionType * result,int size,Zone * zone)672 int Type::UpdateRange(Type range, UnionType* result, int size, Zone* zone) {
673 if (size == 1) {
674 result->Set(size++, range);
675 } else {
676 // Make space for the range.
677 result->Set(size++, result->Get(1));
678 result->Set(1, range);
679 }
680
681 // Remove any components that just got subsumed.
682 for (int i = 2; i < size;) {
683 if (result->Get(i).Is(range)) {
684 result->Set(i, result->Get(--size));
685 } else {
686 ++i;
687 }
688 }
689 return size;
690 }
691
ToLimits(bitset bits,Zone * zone)692 RangeType::Limits Type::ToLimits(bitset bits, Zone* zone) {
693 bitset number_bits = BitsetType::NumberBits(bits);
694
695 if (number_bits == BitsetType::kNone) {
696 return RangeType::Limits::Empty();
697 }
698
699 return RangeType::Limits(BitsetType::Min(number_bits),
700 BitsetType::Max(number_bits));
701 }
702
IntersectRangeAndBitset(Type range,Type bitset,Zone * zone)703 RangeType::Limits Type::IntersectRangeAndBitset(Type range, Type bitset,
704 Zone* zone) {
705 RangeType::Limits range_lims(range.AsRange());
706 RangeType::Limits bitset_lims = ToLimits(bitset.AsBitset(), zone);
707 return RangeType::Limits::Intersect(range_lims, bitset_lims);
708 }
709
IntersectAux(Type lhs,Type rhs,UnionType * result,int size,RangeType::Limits * lims,Zone * zone)710 int Type::IntersectAux(Type lhs, Type rhs, UnionType* result, int size,
711 RangeType::Limits* lims, Zone* zone) {
712 if (lhs.IsUnion()) {
713 for (int i = 0, n = lhs.AsUnion()->Length(); i < n; ++i) {
714 size = IntersectAux(lhs.AsUnion()->Get(i), rhs, result, size, lims, zone);
715 }
716 return size;
717 }
718 if (rhs.IsUnion()) {
719 for (int i = 0, n = rhs.AsUnion()->Length(); i < n; ++i) {
720 size = IntersectAux(lhs, rhs.AsUnion()->Get(i), result, size, lims, zone);
721 }
722 return size;
723 }
724
725 if (BitsetType::IsNone(lhs.BitsetLub() & rhs.BitsetLub())) return size;
726
727 if (lhs.IsRange()) {
728 if (rhs.IsBitset()) {
729 RangeType::Limits lim = IntersectRangeAndBitset(lhs, rhs, zone);
730
731 if (!lim.IsEmpty()) {
732 *lims = RangeType::Limits::Union(lim, *lims);
733 }
734 return size;
735 }
736 if (rhs.IsRange()) {
737 RangeType::Limits lim = RangeType::Limits::Intersect(
738 RangeType::Limits(lhs.AsRange()), RangeType::Limits(rhs.AsRange()));
739 if (!lim.IsEmpty()) {
740 *lims = RangeType::Limits::Union(lim, *lims);
741 }
742 }
743 return size;
744 }
745 if (rhs.IsRange()) {
746 // This case is handled symmetrically above.
747 return IntersectAux(rhs, lhs, result, size, lims, zone);
748 }
749 if (lhs.IsBitset() || rhs.IsBitset()) {
750 return AddToUnion(lhs.IsBitset() ? rhs : lhs, result, size, zone);
751 }
752 if (lhs.SimplyEquals(rhs)) {
753 return AddToUnion(lhs, result, size, zone);
754 }
755 return size;
756 }
757
758 // Make sure that we produce a well-formed range and bitset:
759 // If the range is non-empty, the number bits in the bitset should be
760 // clear. Moreover, if we have a canonical range (such as Signed32),
761 // we want to produce a bitset rather than a range.
NormalizeRangeAndBitset(Type range,bitset * bits,Zone * zone)762 Type Type::NormalizeRangeAndBitset(Type range, bitset* bits, Zone* zone) {
763 // Fast path: If the bitset does not mention numbers, we can just keep the
764 // range.
765 bitset number_bits = BitsetType::NumberBits(*bits);
766 if (number_bits == 0) {
767 return range;
768 }
769
770 // If the range is semantically contained within the bitset, return None and
771 // leave the bitset untouched.
772 bitset range_lub = range.BitsetLub();
773 if (BitsetType::Is(range_lub, *bits)) {
774 return None();
775 }
776
777 // Slow path: reconcile the bitset range and the range.
778 double bitset_min = BitsetType::Min(number_bits);
779 double bitset_max = BitsetType::Max(number_bits);
780
781 double range_min = range.Min();
782 double range_max = range.Max();
783
784 // Remove the number bits from the bitset, they would just confuse us now.
785 // NOTE: bits contains OtherNumber iff bits contains PlainNumber, in which
786 // case we already returned after the subtype check above.
787 *bits &= ~number_bits;
788
789 if (range_min <= bitset_min && range_max >= bitset_max) {
790 // Bitset is contained within the range, just return the range.
791 return range;
792 }
793
794 if (bitset_min < range_min) {
795 range_min = bitset_min;
796 }
797 if (bitset_max > range_max) {
798 range_max = bitset_max;
799 }
800 return Type::Range(range_min, range_max, zone);
801 }
802
Constant(double value,Zone * zone)803 Type Type::Constant(double value, Zone* zone) {
804 if (RangeType::IsInteger(value)) {
805 return Range(value, value, zone);
806 } else if (IsMinusZero(value)) {
807 return Type::MinusZero();
808 } else if (std::isnan(value)) {
809 return Type::NaN();
810 }
811
812 DCHECK(OtherNumberConstantType::IsOtherNumberConstant(value));
813 return OtherNumberConstant(value, zone);
814 }
815
Constant(JSHeapBroker * broker,Handle<i::Object> value,Zone * zone)816 Type Type::Constant(JSHeapBroker* broker, Handle<i::Object> value, Zone* zone) {
817 ObjectRef ref(broker, value);
818 if (ref.IsSmi()) {
819 return Constant(static_cast<double>(ref.AsSmi()), zone);
820 }
821 if (ref.IsHeapNumber()) {
822 return Constant(ref.AsHeapNumber().value(), zone);
823 }
824 if (ref.IsString() && !ref.IsInternalizedString()) {
825 return Type::String();
826 }
827 return HeapConstant(ref.AsHeapObject(), zone);
828 }
829
Union(Type type1,Type type2,Zone * zone)830 Type Type::Union(Type type1, Type type2, Zone* zone) {
831 // Fast case: bit sets.
832 if (type1.IsBitset() && type2.IsBitset()) {
833 return NewBitset(type1.AsBitset() | type2.AsBitset());
834 }
835
836 // Fast case: top or bottom types.
837 if (type1.IsAny() || type2.IsNone()) return type1;
838 if (type2.IsAny() || type1.IsNone()) return type2;
839
840 // Semi-fast case.
841 if (type1.Is(type2)) return type2;
842 if (type2.Is(type1)) return type1;
843
844 // Slow case: create union.
845 int size1 = type1.IsUnion() ? type1.AsUnion()->Length() : 1;
846 int size2 = type2.IsUnion() ? type2.AsUnion()->Length() : 1;
847 int size;
848 if (base::bits::SignedAddOverflow32(size1, size2, &size)) return Any();
849 if (base::bits::SignedAddOverflow32(size, 2, &size)) return Any();
850 UnionType* result = UnionType::New(size, zone);
851 size = 0;
852
853 // Compute the new bitset.
854 bitset new_bitset = type1.BitsetGlb() | type2.BitsetGlb();
855
856 // Deal with ranges.
857 Type range = None();
858 Type range1 = type1.GetRange();
859 Type range2 = type2.GetRange();
860 if (range1 != nullptr && range2 != nullptr) {
861 RangeType::Limits lims =
862 RangeType::Limits::Union(RangeType::Limits(range1.AsRange()),
863 RangeType::Limits(range2.AsRange()));
864 Type union_range = Type::Range(lims, zone);
865 range = NormalizeRangeAndBitset(union_range, &new_bitset, zone);
866 } else if (range1 != nullptr) {
867 range = NormalizeRangeAndBitset(range1, &new_bitset, zone);
868 } else if (range2 != nullptr) {
869 range = NormalizeRangeAndBitset(range2, &new_bitset, zone);
870 }
871 Type bits = NewBitset(new_bitset);
872 result->Set(size++, bits);
873 if (!range.IsNone()) result->Set(size++, range);
874
875 size = AddToUnion(type1, result, size, zone);
876 size = AddToUnion(type2, result, size, zone);
877 return NormalizeUnion(result, size, zone);
878 }
879
880 // Add [type] to [result] unless [type] is bitset, range, or already subsumed.
881 // Return new size of [result].
AddToUnion(Type type,UnionType * result,int size,Zone * zone)882 int Type::AddToUnion(Type type, UnionType* result, int size, Zone* zone) {
883 if (type.IsBitset() || type.IsRange()) return size;
884 if (type.IsUnion()) {
885 for (int i = 0, n = type.AsUnion()->Length(); i < n; ++i) {
886 size = AddToUnion(type.AsUnion()->Get(i), result, size, zone);
887 }
888 return size;
889 }
890 for (int i = 0; i < size; ++i) {
891 if (type.Is(result->Get(i))) return size;
892 }
893 result->Set(size++, type);
894 return size;
895 }
896
NormalizeUnion(UnionType * unioned,int size,Zone * zone)897 Type Type::NormalizeUnion(UnionType* unioned, int size, Zone* zone) {
898 DCHECK_LE(1, size);
899 DCHECK(unioned->Get(0).IsBitset());
900 // If the union has just one element, return it.
901 if (size == 1) {
902 return unioned->Get(0);
903 }
904 bitset bits = unioned->Get(0).AsBitset();
905 // If the union only consists of a range, we can get rid of the union.
906 if (size == 2 && bits == BitsetType::kNone) {
907 if (unioned->Get(1).IsRange()) {
908 return Type::Range(unioned->Get(1).AsRange()->Min(),
909 unioned->Get(1).AsRange()->Max(), zone);
910 }
911 }
912 unioned->Shrink(size);
913 SLOW_DCHECK(unioned->Wellformed());
914 return Type(unioned);
915 }
916
NumConstants() const917 int Type::NumConstants() const {
918 DisallowHeapAllocation no_allocation;
919 if (this->IsHeapConstant() || this->IsOtherNumberConstant()) {
920 return 1;
921 } else if (this->IsUnion()) {
922 int result = 0;
923 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
924 if (this->AsUnion()->Get(i).IsHeapConstant()) ++result;
925 }
926 return result;
927 } else {
928 return 0;
929 }
930 }
931
932 // -----------------------------------------------------------------------------
933 // Printing.
934
Name(bitset bits)935 const char* BitsetType::Name(bitset bits) {
936 switch (bits) {
937 #define RETURN_NAMED_TYPE(type, value) \
938 case k##type: \
939 return #type;
940 PROPER_BITSET_TYPE_LIST(RETURN_NAMED_TYPE)
941 INTERNAL_BITSET_TYPE_LIST(RETURN_NAMED_TYPE)
942 #undef RETURN_NAMED_TYPE
943
944 default:
945 return nullptr;
946 }
947 }
948
Print(std::ostream & os,bitset bits)949 void BitsetType::Print(std::ostream& os, // NOLINT
950 bitset bits) {
951 DisallowHeapAllocation no_allocation;
952 const char* name = Name(bits);
953 if (name != nullptr) {
954 os << name;
955 return;
956 }
957
958 // clang-format off
959 static const bitset named_bitsets[] = {
960 #define BITSET_CONSTANT(type, value) k##type,
961 INTERNAL_BITSET_TYPE_LIST(BITSET_CONSTANT)
962 PROPER_BITSET_TYPE_LIST(BITSET_CONSTANT)
963 #undef BITSET_CONSTANT
964 };
965 // clang-format on
966
967 bool is_first = true;
968 os << "(";
969 for (int i(arraysize(named_bitsets) - 1); bits != 0 && i >= 0; --i) {
970 bitset subset = named_bitsets[i];
971 if ((bits & subset) == subset) {
972 if (!is_first) os << " | ";
973 is_first = false;
974 os << Name(subset);
975 bits -= subset;
976 }
977 }
978 DCHECK_EQ(0, bits);
979 os << ")";
980 }
981
PrintTo(std::ostream & os) const982 void Type::PrintTo(std::ostream& os) const {
983 DisallowHeapAllocation no_allocation;
984 if (this->IsBitset()) {
985 BitsetType::Print(os, this->AsBitset());
986 } else if (this->IsHeapConstant()) {
987 os << "HeapConstant(" << this->AsHeapConstant()->Ref() << ")";
988 } else if (this->IsOtherNumberConstant()) {
989 os << "OtherNumberConstant(" << this->AsOtherNumberConstant()->Value()
990 << ")";
991 } else if (this->IsRange()) {
992 std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed);
993 std::streamsize saved_precision = os.precision(0);
994 os << "Range(" << this->AsRange()->Min() << ", " << this->AsRange()->Max()
995 << ")";
996 os.flags(saved_flags);
997 os.precision(saved_precision);
998 } else if (this->IsUnion()) {
999 os << "(";
1000 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
1001 Type type_i = this->AsUnion()->Get(i);
1002 if (i > 0) os << " | ";
1003 os << type_i;
1004 }
1005 os << ")";
1006 } else if (this->IsTuple()) {
1007 os << "<";
1008 for (int i = 0, n = this->AsTuple()->Arity(); i < n; ++i) {
1009 Type type_i = this->AsTuple()->Element(i);
1010 if (i > 0) os << ", ";
1011 os << type_i;
1012 }
1013 os << ">";
1014 } else {
1015 UNREACHABLE();
1016 }
1017 }
1018
1019 #ifdef DEBUG
Print() const1020 void Type::Print() const {
1021 StdoutStream os;
1022 PrintTo(os);
1023 os << std::endl;
1024 }
Print(bitset bits)1025 void BitsetType::Print(bitset bits) {
1026 StdoutStream os;
1027 Print(os, bits);
1028 os << std::endl;
1029 }
1030 #endif
1031
SignedSmall()1032 BitsetType::bitset BitsetType::SignedSmall() {
1033 return SmiValuesAre31Bits() ? kSigned31 : kSigned32;
1034 }
1035
UnsignedSmall()1036 BitsetType::bitset BitsetType::UnsignedSmall() {
1037 return SmiValuesAre31Bits() ? kUnsigned30 : kUnsigned31;
1038 }
1039
1040 // static
Tuple(Type first,Type second,Type third,Zone * zone)1041 Type Type::Tuple(Type first, Type second, Type third, Zone* zone) {
1042 TupleType* tuple = TupleType::New(3, zone);
1043 tuple->InitElement(0, first);
1044 tuple->InitElement(1, second);
1045 tuple->InitElement(2, third);
1046 return FromTypeBase(tuple);
1047 }
1048
1049 // static
OtherNumberConstant(double value,Zone * zone)1050 Type Type::OtherNumberConstant(double value, Zone* zone) {
1051 return FromTypeBase(OtherNumberConstantType::New(value, zone));
1052 }
1053
1054 // static
HeapConstant(const HeapObjectRef & value,Zone * zone)1055 Type Type::HeapConstant(const HeapObjectRef& value, Zone* zone) {
1056 DCHECK(!value.IsHeapNumber());
1057 DCHECK_IMPLIES(value.IsString(), value.IsInternalizedString());
1058 BitsetType::bitset bitset = BitsetType::Lub(value.GetHeapObjectType());
1059 if (Type(bitset).IsSingleton()) return Type(bitset);
1060 return HeapConstantType::New(value, bitset, zone);
1061 }
1062
1063 // static
Range(double min,double max,Zone * zone)1064 Type Type::Range(double min, double max, Zone* zone) {
1065 return FromTypeBase(RangeType::New(min, max, zone));
1066 }
1067
1068 // static
Range(RangeType::Limits lims,Zone * zone)1069 Type Type::Range(RangeType::Limits lims, Zone* zone) {
1070 return FromTypeBase(RangeType::New(lims, zone));
1071 }
1072
AsHeapConstant() const1073 const HeapConstantType* Type::AsHeapConstant() const {
1074 DCHECK(IsKind(TypeBase::kHeapConstant));
1075 return static_cast<const HeapConstantType*>(ToTypeBase());
1076 }
1077
AsOtherNumberConstant() const1078 const OtherNumberConstantType* Type::AsOtherNumberConstant() const {
1079 DCHECK(IsKind(TypeBase::kOtherNumberConstant));
1080 return static_cast<const OtherNumberConstantType*>(ToTypeBase());
1081 }
1082
AsRange() const1083 const RangeType* Type::AsRange() const {
1084 DCHECK(IsKind(TypeBase::kRange));
1085 return static_cast<const RangeType*>(ToTypeBase());
1086 }
1087
AsTuple() const1088 const TupleType* Type::AsTuple() const {
1089 DCHECK(IsKind(TypeBase::kTuple));
1090 return static_cast<const TupleType*>(ToTypeBase());
1091 }
1092
AsUnion() const1093 const UnionType* Type::AsUnion() const {
1094 DCHECK(IsKind(TypeBase::kUnion));
1095 return static_cast<const UnionType*>(ToTypeBase());
1096 }
1097
operator <<(std::ostream & os,Type type)1098 std::ostream& operator<<(std::ostream& os, Type type) {
1099 type.PrintTo(os);
1100 return os;
1101 }
1102
1103 } // namespace compiler
1104 } // namespace internal
1105 } // namespace v8
1106