• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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