deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / src / types.cc
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 <iomanip>
6
7 #include "src/types.h"
8
9 #include "src/ostreams.h"
10 #include "src/types-inl.h"
11
12 namespace v8 {
13 namespace internal {
14
15
16 // NOTE: If code is marked as being a "shortcut", this means that removing
17 // the code won't affect the semantics of the surrounding function definition.
18
19
20 // -----------------------------------------------------------------------------
21 // Range-related helper functions.
22
23 // The result may be invalid (max < min).
24 template<class Config>
25 typename TypeImpl<Config>::Limits TypeImpl<Config>::Intersect(
26     Limits lhs, Limits rhs) {
27   DisallowHeapAllocation no_allocation;
28   Limits result(lhs);
29   if (lhs.min < rhs.min) result.min = rhs.min;
30   if (lhs.max > rhs.max) result.max = rhs.max;
31   return result;
32 }
33
34
35 template <class Config>
36 bool TypeImpl<Config>::IsEmpty(Limits lim) {
37   return lim.min > lim.max;
38 }
39
40
41 template <class Config>
42 typename TypeImpl<Config>::Limits TypeImpl<Config>::Union(Limits lhs,
43                                                           Limits rhs) {
44   DisallowHeapAllocation no_allocation;
45   if (IsEmpty(lhs)) return rhs;
46   if (IsEmpty(rhs)) return lhs;
47   Limits result(lhs);
48   if (lhs.min > rhs.min) result.min = rhs.min;
49   if (lhs.max < rhs.max) result.max = rhs.max;
50   return result;
51 }
52
53
54 template<class Config>
55 bool TypeImpl<Config>::Overlap(
56     typename TypeImpl<Config>::RangeType* lhs,
57     typename TypeImpl<Config>::RangeType* rhs) {
58   DisallowHeapAllocation no_allocation;
59   typename TypeImpl<Config>::Limits lim = Intersect(Limits(lhs), Limits(rhs));
60   return lim.min <= lim.max;
61 }
62
63
64 template<class Config>
65 bool TypeImpl<Config>::Contains(
66     typename TypeImpl<Config>::RangeType* lhs,
67     typename TypeImpl<Config>::RangeType* rhs) {
68   DisallowHeapAllocation no_allocation;
69   return lhs->Min() <= rhs->Min() && rhs->Max() <= lhs->Max();
70 }
71
72
73 template <class Config>
74 bool TypeImpl<Config>::Contains(typename TypeImpl<Config>::RangeType* lhs,
75                                 typename TypeImpl<Config>::ConstantType* rhs) {
76   DisallowHeapAllocation no_allocation;
77   return IsInteger(*rhs->Value()) &&
78          lhs->Min() <= rhs->Value()->Number() &&
79          rhs->Value()->Number() <= lhs->Max();
80 }
81
82
83 template<class Config>
84 bool TypeImpl<Config>::Contains(
85     typename TypeImpl<Config>::RangeType* range, i::Object* val) {
86   DisallowHeapAllocation no_allocation;
87   return IsInteger(val) &&
88          range->Min() <= val->Number() && val->Number() <= range->Max();
89 }
90
91
92 // -----------------------------------------------------------------------------
93 // Min and Max computation.
94
95 template<class Config>
96 double TypeImpl<Config>::Min() {
97   DCHECK(this->SemanticIs(Number()));
98   if (this->IsBitset()) return BitsetType::Min(this->AsBitset());
99   if (this->IsUnion()) {
100     double min = +V8_INFINITY;
101     for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
102       min = std::min(min, this->AsUnion()->Get(i)->Min());
103     }
104     return min;
105   }
106   if (this->IsRange()) return this->AsRange()->Min();
107   if (this->IsConstant()) return this->AsConstant()->Value()->Number();
108   UNREACHABLE();
109   return 0;
110 }
111
112
113 template<class Config>
114 double TypeImpl<Config>::Max() {
115   DCHECK(this->SemanticIs(Number()));
116   if (this->IsBitset()) return BitsetType::Max(this->AsBitset());
117   if (this->IsUnion()) {
118     double max = -V8_INFINITY;
119     for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
120       max = std::max(max, this->AsUnion()->Get(i)->Max());
121     }
122     return max;
123   }
124   if (this->IsRange()) return this->AsRange()->Max();
125   if (this->IsConstant()) return this->AsConstant()->Value()->Number();
126   UNREACHABLE();
127   return 0;
128 }
129
130
131 // -----------------------------------------------------------------------------
132 // Glb and lub computation.
133
134
135 // The largest bitset subsumed by this type.
136 template<class Config>
137 typename TypeImpl<Config>::bitset
138 TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) {
139   DisallowHeapAllocation no_allocation;
140   // Fast case.
141   if (type->IsBitset()) {
142     return type->AsBitset();
143   } else if (type->IsUnion()) {
144     SLOW_DCHECK(type->AsUnion()->Wellformed());
145     return type->AsUnion()->Get(0)->BitsetGlb() |
146            SEMANTIC(type->AsUnion()->Get(1)->BitsetGlb());  // Shortcut.
147   } else if (type->IsRange()) {
148     bitset glb = SEMANTIC(
149         BitsetType::Glb(type->AsRange()->Min(), type->AsRange()->Max()));
150     return glb | REPRESENTATION(type->BitsetLub());
151   } else {
152     return type->Representation();
153   }
154 }
155
156
157 // The smallest bitset subsuming this type.
158 template<class Config>
159 typename TypeImpl<Config>::bitset
160 TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) {
161   DisallowHeapAllocation no_allocation;
162   if (type->IsBitset()) return type->AsBitset();
163   if (type->IsUnion()) {
164     // Take the representation from the first element, which is always
165     // a bitset.
166     int bitset = type->AsUnion()->Get(0)->BitsetLub();
167     for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) {
168       // Other elements only contribute their semantic part.
169       bitset |= SEMANTIC(type->AsUnion()->Get(i)->BitsetLub());
170     }
171     return bitset;
172   }
173   if (type->IsClass()) {
174     // Little hack to avoid the need for a region for handlification here...
175     return Config::is_class(type) ? Lub(*Config::as_class(type)) :
176         type->AsClass()->Bound(NULL)->AsBitset();
177   }
178   if (type->IsConstant()) return type->AsConstant()->Bound()->AsBitset();
179   if (type->IsRange()) return type->AsRange()->Bound();
180   if (type->IsContext()) return kInternal & kTaggedPointer;
181   if (type->IsArray()) return kArray;
182   if (type->IsFunction()) return kOtherObject;  // TODO(rossberg): kFunction
183   UNREACHABLE();
184   return kNone;
185 }
186
187
188 template<class Config>
189 typename TypeImpl<Config>::bitset
190 TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
191   DisallowHeapAllocation no_allocation;
192   switch (map->instance_type()) {
193     case STRING_TYPE:
194     case ONE_BYTE_STRING_TYPE:
195     case CONS_STRING_TYPE:
196     case CONS_ONE_BYTE_STRING_TYPE:
197     case SLICED_STRING_TYPE:
198     case SLICED_ONE_BYTE_STRING_TYPE:
199     case EXTERNAL_STRING_TYPE:
200     case EXTERNAL_ONE_BYTE_STRING_TYPE:
201     case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
202     case SHORT_EXTERNAL_STRING_TYPE:
203     case SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE:
204     case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
205       return kOtherString;
206     case INTERNALIZED_STRING_TYPE:
207     case ONE_BYTE_INTERNALIZED_STRING_TYPE:
208     case EXTERNAL_INTERNALIZED_STRING_TYPE:
209     case EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
210     case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
211     case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE:
212     case SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
213     case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
214       return kInternalizedString;
215     case SYMBOL_TYPE:
216       return kSymbol;
217     case ODDBALL_TYPE: {
218       Heap* heap = map->GetHeap();
219       if (map == heap->undefined_map()) return kUndefined;
220       if (map == heap->null_map()) return kNull;
221       if (map == heap->boolean_map()) return kBoolean;
222       DCHECK(map == heap->the_hole_map() ||
223              map == heap->uninitialized_map() ||
224              map == heap->no_interceptor_result_sentinel_map() ||
225              map == heap->termination_exception_map() ||
226              map == heap->arguments_marker_map());
227       return kInternal & kTaggedPointer;
228     }
229     case HEAP_NUMBER_TYPE:
230       return kNumber & kTaggedPointer;
231     case JS_VALUE_TYPE:
232     case JS_DATE_TYPE:
233     case JS_OBJECT_TYPE:
234     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
235     case JS_GENERATOR_OBJECT_TYPE:
236     case JS_MODULE_TYPE:
237     case JS_GLOBAL_OBJECT_TYPE:
238     case JS_BUILTINS_OBJECT_TYPE:
239     case JS_GLOBAL_PROXY_TYPE:
240     case JS_ARRAY_BUFFER_TYPE:
241     case JS_TYPED_ARRAY_TYPE:
242     case JS_DATA_VIEW_TYPE:
243     case JS_SET_TYPE:
244     case JS_MAP_TYPE:
245     case JS_SET_ITERATOR_TYPE:
246     case JS_MAP_ITERATOR_TYPE:
247     case JS_WEAK_MAP_TYPE:
248     case JS_WEAK_SET_TYPE:
249       if (map->is_undetectable()) return kUndetectable;
250       return kOtherObject;
251     case JS_ARRAY_TYPE:
252       return kArray;
253     case JS_FUNCTION_TYPE:
254       return kOtherObject;  // TODO(rossberg): there should be a Function type.
255     case JS_REGEXP_TYPE:
256       return kOtherObject;  // TODO(rossberg): there should be a RegExp type.
257     case JS_PROXY_TYPE:
258     case JS_FUNCTION_PROXY_TYPE:
259       return kProxy;
260     case MAP_TYPE:
261       // When compiling stub templates, the meta map is used as a place holder
262       // for the actual map with which the template is later instantiated.
263       // We treat it as a kind of type variable whose upper bound is Any.
264       // TODO(rossberg): for caching of CompareNilIC stubs to work correctly,
265       // we must exclude Undetectable here. This makes no sense, really,
266       // because it means that the template isn't actually parametric.
267       // Also, it doesn't apply elsewhere. 8-(
268       // We ought to find a cleaner solution for compiling stubs parameterised
269       // over type or class variables, esp ones with bounds...
270       return kDetectable & kTaggedPointer;
271     case DECLARED_ACCESSOR_INFO_TYPE:
272     case EXECUTABLE_ACCESSOR_INFO_TYPE:
273     case SHARED_FUNCTION_INFO_TYPE:
274     case ACCESSOR_PAIR_TYPE:
275     case FIXED_ARRAY_TYPE:
276     case BYTE_ARRAY_TYPE:
277     case FOREIGN_TYPE:
278     case SCRIPT_TYPE:
279     case CODE_TYPE:
280       return kInternal & kTaggedPointer;
281     default:
282       UNREACHABLE();
283       return kNone;
284   }
285 }
286
287
288 template<class Config>
289 typename TypeImpl<Config>::bitset
290 TypeImpl<Config>::BitsetType::Lub(i::Object* value) {
291   DisallowHeapAllocation no_allocation;
292   if (value->IsNumber()) {
293     return Lub(value->Number()) &
294         (value->IsSmi() ? kTaggedSigned : kTaggedPointer);
295   }
296   return Lub(i::HeapObject::cast(value)->map());
297 }
298
299
300 template<class Config>
301 typename TypeImpl<Config>::bitset
302 TypeImpl<Config>::BitsetType::Lub(double value) {
303   DisallowHeapAllocation no_allocation;
304   if (i::IsMinusZero(value)) return kMinusZero;
305   if (std::isnan(value)) return kNaN;
306   if (IsUint32Double(value) || IsInt32Double(value)) return Lub(value, value);
307   return kPlainNumber;
308 }
309
310
311 // Minimum values of regular numeric bitsets.
312 template <class Config>
313 const typename TypeImpl<Config>::BitsetType::Boundary
314     TypeImpl<Config>::BitsetType::BoundariesArray[] = {
315   {kPlainNumber, -V8_INFINITY},
316   {kNegative32, kMinInt},
317   {kNegative31, -0x40000000},
318   {kUnsigned30, 0},
319   {kUnsigned31, 0x40000000},
320   {kUnsigned32, 0x80000000},
321   {kPlainNumber, static_cast<double>(kMaxUInt32) + 1}
322 };
323
324
325 template <class Config>
326 const typename TypeImpl<Config>::BitsetType::Boundary*
327 TypeImpl<Config>::BitsetType::Boundaries() {
328   return BoundariesArray;
329 }
330
331
332 template <class Config>
333 size_t TypeImpl<Config>::BitsetType::BoundariesSize() {
334   // Windows doesn't like arraysize here.
335   // return arraysize(BoundariesArray);
336   return 7;
337 }
338
339
340 template<class Config>
341 typename TypeImpl<Config>::bitset
342 TypeImpl<Config>::BitsetType::Lub(double min, double max) {
343   DisallowHeapAllocation no_allocation;
344   int lub = kNone;
345   const Boundary* mins = Boundaries();
346
347   // Make sure the min-max range touches 0, so we are guaranteed no holes
348   // in unions of valid bitsets.
349   if (max < -1) max = -1;
350   if (min > 0) min = 0;
351
352   for (size_t i = 1; i < BoundariesSize(); ++i) {
353     if (min < mins[i].min) {
354       lub |= mins[i-1].bits;
355       if (max < mins[i].min) return lub;
356     }
357   }
358   return lub |= mins[BoundariesSize() - 1].bits;
359 }
360
361
362 template <class Config>
363 typename TypeImpl<Config>::bitset TypeImpl<Config>::BitsetType::NumberBits(
364     bitset bits) {
365   return SEMANTIC(bits & kPlainNumber);
366 }
367
368
369 template <class Config>
370 void TypeImpl<Config>::BitsetType::CheckNumberBits(bitset bits) {
371   // Check that the bitset does not contain any holes in number ranges.
372   bitset number_bits = NumberBits(bits);
373   if (number_bits != 0) {
374     bitset lub = SEMANTIC(Lub(Min(number_bits), Max(number_bits)));
375     CHECK(lub == number_bits);
376   }
377 }
378
379 template <class Config>
380 typename TypeImpl<Config>::bitset TypeImpl<Config>::BitsetType::Glb(
381     double min, double max) {
382   DisallowHeapAllocation no_allocation;
383   int glb = kNone;
384   const Boundary* mins = Boundaries();
385
386   // If the range does not touch 0, the bound is empty.
387   if (max < -1 || min > 0) return glb;
388
389   for (size_t i = 1; i + 1 < BoundariesSize(); ++i) {
390     if (min <= mins[i].min) {
391       if (max + 1 < mins[i + 1].min) break;
392       glb |= mins[i].bits;
393     }
394   }
395   // OtherNumber also contains float numbers, so it can never be
396   // in the greatest lower bound. (There is also the small trouble
397   // of kOtherNumber having a range hole, which we can conveniently
398   // ignore here.)
399   return glb & ~(SEMANTIC(kOtherNumber));
400 }
401
402
403 template <class Config>
404 double TypeImpl<Config>::BitsetType::Min(bitset bits) {
405   DisallowHeapAllocation no_allocation;
406   DCHECK(Is(SEMANTIC(bits), kNumber));
407   const Boundary* mins = Boundaries();
408   bool mz = SEMANTIC(bits & kMinusZero);
409   for (size_t i = 0; i < BoundariesSize(); ++i) {
410     if (Is(SEMANTIC(mins[i].bits), bits)) {
411       return mz ? std::min(0.0, mins[i].min) : mins[i].min;
412     }
413   }
414   if (mz) return 0;
415   return std::numeric_limits<double>::quiet_NaN();
416 }
417
418
419 template<class Config>
420 double TypeImpl<Config>::BitsetType::Max(bitset bits) {
421   DisallowHeapAllocation no_allocation;
422   DCHECK(Is(SEMANTIC(bits), kNumber));
423   const Boundary* mins = Boundaries();
424   bool mz = SEMANTIC(bits & kMinusZero);
425   if (BitsetType::Is(SEMANTIC(mins[BoundariesSize() - 1].bits), bits)) {
426     return +V8_INFINITY;
427   }
428   for (size_t i = BoundariesSize() - 1; i-- > 0;) {
429     if (Is(SEMANTIC(mins[i].bits), bits)) {
430       return mz ?
431           std::max(0.0, mins[i+1].min - 1) : mins[i+1].min - 1;
432     }
433   }
434   if (mz) return 0;
435   return std::numeric_limits<double>::quiet_NaN();
436 }
437
438
439 // -----------------------------------------------------------------------------
440 // Predicates.
441
442
443 template<class Config>
444 bool TypeImpl<Config>::SimplyEquals(TypeImpl* that) {
445   DisallowHeapAllocation no_allocation;
446   if (this->IsClass()) {
447     return that->IsClass()
448         && *this->AsClass()->Map() == *that->AsClass()->Map();
449   }
450   if (this->IsConstant()) {
451     return that->IsConstant()
452         && *this->AsConstant()->Value() == *that->AsConstant()->Value();
453   }
454   if (this->IsContext()) {
455     return that->IsContext()
456         && this->AsContext()->Outer()->Equals(that->AsContext()->Outer());
457   }
458   if (this->IsArray()) {
459     return that->IsArray()
460         && this->AsArray()->Element()->Equals(that->AsArray()->Element());
461   }
462   if (this->IsFunction()) {
463     if (!that->IsFunction()) return false;
464     FunctionType* this_fun = this->AsFunction();
465     FunctionType* that_fun = that->AsFunction();
466     if (this_fun->Arity() != that_fun->Arity() ||
467         !this_fun->Result()->Equals(that_fun->Result()) ||
468         !this_fun->Receiver()->Equals(that_fun->Receiver())) {
469       return false;
470     }
471     for (int i = 0, n = this_fun->Arity(); i < n; ++i) {
472       if (!this_fun->Parameter(i)->Equals(that_fun->Parameter(i))) return false;
473     }
474     return true;
475   }
476   UNREACHABLE();
477   return false;
478 }
479
480
481 template <class Config>
482 typename TypeImpl<Config>::bitset TypeImpl<Config>::Representation() {
483   return REPRESENTATION(this->BitsetLub());
484 }
485
486
487 // Check if [this] <= [that].
488 template<class Config>
489 bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
490   DisallowHeapAllocation no_allocation;
491
492   // Fast bitset cases
493   if (that->IsBitset()) {
494     return BitsetType::Is(this->BitsetLub(), that->AsBitset());
495   }
496
497   if (this->IsBitset()) {
498     return BitsetType::Is(this->AsBitset(), that->BitsetGlb());
499   }
500
501   // Check the representations.
502   if (!BitsetType::Is(Representation(), that->Representation())) {
503     return false;
504   }
505
506   // Check the semantic part.
507   return SemanticIs(that);
508 }
509
510
511 // Check if SEMANTIC([this]) <= SEMANTIC([that]). The result of the method
512 // should be independent of the representation axis of the types.
513 template <class Config>
514 bool TypeImpl<Config>::SemanticIs(TypeImpl* that) {
515   DisallowHeapAllocation no_allocation;
516
517   if (this == that) return true;
518
519   if (that->IsBitset()) {
520     return BitsetType::Is(SEMANTIC(this->BitsetLub()), that->AsBitset());
521   }
522   if (this->IsBitset()) {
523     return BitsetType::Is(SEMANTIC(this->AsBitset()), that->BitsetGlb());
524   }
525
526   // (T1 \/ ... \/ Tn) <= T  if  (T1 <= T) /\ ... /\ (Tn <= T)
527   if (this->IsUnion()) {
528     for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
529       if (!this->AsUnion()->Get(i)->SemanticIs(that)) return false;
530     }
531     return true;
532   }
533
534   // T <= (T1 \/ ... \/ Tn)  if  (T <= T1) \/ ... \/ (T <= Tn)
535   if (that->IsUnion()) {
536     for (int i = 0, n = that->AsUnion()->Length(); i < n; ++i) {
537       if (this->SemanticIs(that->AsUnion()->Get(i)->unhandle())) return true;
538       if (i > 1 && this->IsRange()) return false;  // Shortcut.
539     }
540     return false;
541   }
542
543   if (that->IsRange()) {
544     return (this->IsRange() && Contains(that->AsRange(), this->AsRange())) ||
545            (this->IsConstant() &&
546             Contains(that->AsRange(), this->AsConstant()));
547   }
548   if (this->IsRange()) return false;
549
550   return this->SimplyEquals(that);
551 }
552
553
554 template<class Config>
555 bool TypeImpl<Config>::NowIs(TypeImpl* that) {
556   DisallowHeapAllocation no_allocation;
557
558   // TODO(rossberg): this is incorrect for
559   //   Union(Constant(V), T)->NowIs(Class(M))
560   // but fuzzing does not cover that!
561   if (this->IsConstant()) {
562     i::Object* object = *this->AsConstant()->Value();
563     if (object->IsHeapObject()) {
564       i::Map* map = i::HeapObject::cast(object)->map();
565       for (Iterator<i::Map> it = that->Classes(); !it.Done(); it.Advance()) {
566         if (*it.Current() == map) return true;
567       }
568     }
569   }
570   return this->Is(that);
571 }
572
573
574 // Check if [this] contains only (currently) stable classes.
575 template<class Config>
576 bool TypeImpl<Config>::NowStable() {
577   DisallowHeapAllocation no_allocation;
578   return !this->IsClass() || this->AsClass()->Map()->is_stable();
579 }
580
581
582 // Check if [this] and [that] overlap.
583 template<class Config>
584 bool TypeImpl<Config>::Maybe(TypeImpl* that) {
585   DisallowHeapAllocation no_allocation;
586
587   // Take care of the representation part (and also approximate
588   // the semantic part).
589   if (!BitsetType::IsInhabited(this->BitsetLub() & that->BitsetLub()))
590     return false;
591
592   return SemanticMaybe(that);
593 }
594
595 template <class Config>
596 bool TypeImpl<Config>::SemanticMaybe(TypeImpl* that) {
597   DisallowHeapAllocation no_allocation;
598
599   // (T1 \/ ... \/ Tn) overlaps T  if  (T1 overlaps T) \/ ... \/ (Tn overlaps T)
600   if (this->IsUnion()) {
601     for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
602       if (this->AsUnion()->Get(i)->SemanticMaybe(that)) return true;
603     }
604     return false;
605   }
606
607   // T overlaps (T1 \/ ... \/ Tn)  if  (T overlaps T1) \/ ... \/ (T overlaps Tn)
608   if (that->IsUnion()) {
609     for (int i = 0, n = that->AsUnion()->Length(); i < n; ++i) {
610       if (this->SemanticMaybe(that->AsUnion()->Get(i)->unhandle())) return true;
611     }
612     return false;
613   }
614
615   if (!BitsetType::SemanticIsInhabited(this->BitsetLub() & that->BitsetLub()))
616     return false;
617
618   if (this->IsBitset() && that->IsBitset()) return true;
619
620   if (this->IsClass() != that->IsClass()) return true;
621
622   if (this->IsRange()) {
623     if (that->IsConstant()) {
624       return Contains(this->AsRange(), that->AsConstant());
625     }
626     if (that->IsRange()) {
627       return Overlap(this->AsRange(), that->AsRange());
628     }
629     if (that->IsBitset()) {
630       bitset number_bits = BitsetType::NumberBits(that->AsBitset());
631       if (number_bits == BitsetType::kNone) {
632         return false;
633       }
634       double min = std::max(BitsetType::Min(number_bits), this->Min());
635       double max = std::min(BitsetType::Max(number_bits), this->Max());
636       return min <= max;
637     }
638   }
639   if (that->IsRange()) {
640     return that->SemanticMaybe(this);  // This case is handled above.
641   }
642
643   if (this->IsBitset() || that->IsBitset()) return true;
644
645   return this->SimplyEquals(that);
646 }
647
648
649 // Return the range in [this], or [NULL].
650 template<class Config>
651 typename TypeImpl<Config>::RangeType* TypeImpl<Config>::GetRange() {
652   DisallowHeapAllocation no_allocation;
653   if (this->IsRange()) return this->AsRange();
654   if (this->IsUnion() && this->AsUnion()->Get(1)->IsRange()) {
655     return this->AsUnion()->Get(1)->AsRange();
656   }
657   return NULL;
658 }
659
660
661 template<class Config>
662 bool TypeImpl<Config>::Contains(i::Object* value) {
663   DisallowHeapAllocation no_allocation;
664   for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) {
665     if (*it.Current() == value) return true;
666   }
667   if (IsInteger(value)) {
668     RangeType* range = this->GetRange();
669     if (range != NULL && Contains(range, value)) return true;
670   }
671   return BitsetType::New(BitsetType::Lub(value))->Is(this);
672 }
673
674
675 template<class Config>
676 bool TypeImpl<Config>::UnionType::Wellformed() {
677   DisallowHeapAllocation no_allocation;
678   // This checks the invariants of the union representation:
679   // 1. There are at least two elements.
680   // 2. The first element is a bitset, no other element is a bitset.
681   // 3. At most one element is a range, and it must be the second one.
682   // 4. No element is itself a union.
683   // 5. No element (except the bitset) is a subtype of any other.
684   // 6. If there is a range, then the bitset type does not contain
685   //    plain number bits.
686   DCHECK(this->Length() >= 2);  // (1)
687   DCHECK(this->Get(0)->IsBitset());  // (2a)
688
689   for (int i = 0; i < this->Length(); ++i) {
690     if (i != 0) DCHECK(!this->Get(i)->IsBitset());  // (2b)
691     if (i != 1) DCHECK(!this->Get(i)->IsRange());   // (3)
692     DCHECK(!this->Get(i)->IsUnion());               // (4)
693     for (int j = 0; j < this->Length(); ++j) {
694       if (i != j && i != 0)
695         DCHECK(!this->Get(i)->SemanticIs(this->Get(j)->unhandle()));  // (5)
696     }
697   }
698   DCHECK(!this->Get(1)->IsRange() ||
699          (BitsetType::NumberBits(this->Get(0)->AsBitset()) ==
700           BitsetType::kNone));  // (6)
701   return true;
702 }
703
704
705 // -----------------------------------------------------------------------------
706 // Union and intersection
707
708
709 static bool AddIsSafe(int x, int y) {
710   return x >= 0 ?
711       y <= std::numeric_limits<int>::max() - x :
712       y >= std::numeric_limits<int>::min() - x;
713 }
714
715
716 template<class Config>
717 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect(
718     TypeHandle type1, TypeHandle type2, Region* region) {
719
720   // Fast case: bit sets.
721   if (type1->IsBitset() && type2->IsBitset()) {
722     return BitsetType::New(type1->AsBitset() & type2->AsBitset(), region);
723   }
724
725   // Fast case: top or bottom types.
726   if (type1->IsNone() || type2->IsAny()) return type1;  // Shortcut.
727   if (type2->IsNone() || type1->IsAny()) return type2;  // Shortcut.
728
729   // Semi-fast case.
730   if (type1->Is(type2)) return type1;
731   if (type2->Is(type1)) return type2;
732
733   // Slow case: create union.
734
735   // Figure out the representation of the result first.
736   // The rest of the method should not change this representation and
737   // it should not make any decisions based on representations (i.e.,
738   // it should only use the semantic part of types).
739   const bitset representation =
740       type1->Representation() & type2->Representation();
741
742   // Semantic subtyping check - this is needed for consistency with the
743   // semi-fast case above - we should behave the same way regardless of
744   // representations. Intersection with a universal bitset should only update
745   // the representations.
746   if (type1->SemanticIs(type2->unhandle())) {
747     type2 = Any(region);
748   } else if (type2->SemanticIs(type1->unhandle())) {
749     type1 = Any(region);
750   }
751
752   bitset bits =
753       SEMANTIC(type1->BitsetGlb() & type2->BitsetGlb()) | representation;
754   int size1 = type1->IsUnion() ? type1->AsUnion()->Length() : 1;
755   int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1;
756   if (!AddIsSafe(size1, size2)) return Any(region);
757   int size = size1 + size2;
758   if (!AddIsSafe(size, 2)) return Any(region);
759   size += 2;
760   UnionHandle result = UnionType::New(size, region);
761   size = 0;
762
763   // Deal with bitsets.
764   result->Set(size++, BitsetType::New(bits, region));
765
766   Limits lims = Limits::Empty(region);
767   size = IntersectAux(type1, type2, result, size, &lims, region);
768
769   // If the range is not empty, then insert it into the union and
770   // remove the number bits from the bitset.
771   if (!IsEmpty(lims)) {
772     size = UpdateRange(RangeType::New(lims, representation, region), result,
773                        size, region);
774
775     // Remove the number bits.
776     bitset number_bits = BitsetType::NumberBits(bits);
777     bits &= ~number_bits;
778     result->Set(0, BitsetType::New(bits, region));
779   }
780   return NormalizeUnion(result, size, region);
781 }
782
783
784 template<class Config>
785 int TypeImpl<Config>::UpdateRange(
786     RangeHandle range, UnionHandle result, int size, Region* region) {
787   if (size == 1) {
788     result->Set(size++, range);
789   } else {
790     // Make space for the range.
791     result->Set(size++, result->Get(1));
792     result->Set(1, range);
793   }
794
795   // Remove any components that just got subsumed.
796   for (int i = 2; i < size; ) {
797     if (result->Get(i)->SemanticIs(range->unhandle())) {
798       result->Set(i, result->Get(--size));
799     } else {
800       ++i;
801     }
802   }
803   return size;
804 }
805
806
807 template <class Config>
808 typename TypeImpl<Config>::Limits TypeImpl<Config>::ToLimits(bitset bits,
809                                                              Region* region) {
810   bitset number_bits = BitsetType::NumberBits(bits);
811
812   if (number_bits == BitsetType::kNone) {
813     return Limits::Empty(region);
814   }
815
816   return Limits(BitsetType::Min(number_bits), BitsetType::Max(number_bits));
817 }
818
819
820 template <class Config>
821 typename TypeImpl<Config>::Limits TypeImpl<Config>::IntersectRangeAndBitset(
822     TypeHandle range, TypeHandle bitset, Region* region) {
823   Limits range_lims(range->AsRange());
824   Limits bitset_lims = ToLimits(bitset->AsBitset(), region);
825   return Intersect(range_lims, bitset_lims);
826 }
827
828
829 template <class Config>
830 int TypeImpl<Config>::IntersectAux(TypeHandle lhs, TypeHandle rhs,
831                                    UnionHandle result, int size, Limits* lims,
832                                    Region* region) {
833   if (lhs->IsUnion()) {
834     for (int i = 0, n = lhs->AsUnion()->Length(); i < n; ++i) {
835       size =
836           IntersectAux(lhs->AsUnion()->Get(i), rhs, result, size, lims, region);
837     }
838     return size;
839   }
840   if (rhs->IsUnion()) {
841     for (int i = 0, n = rhs->AsUnion()->Length(); i < n; ++i) {
842       size =
843           IntersectAux(lhs, rhs->AsUnion()->Get(i), result, size, lims, region);
844     }
845     return size;
846   }
847
848   if (!BitsetType::SemanticIsInhabited(lhs->BitsetLub() & rhs->BitsetLub())) {
849     return size;
850   }
851
852   if (lhs->IsRange()) {
853     if (rhs->IsBitset()) {
854       Limits lim = IntersectRangeAndBitset(lhs, rhs, region);
855
856       if (!IsEmpty(lim)) {
857         *lims = Union(lim, *lims);
858       }
859       return size;
860     }
861     if (rhs->IsClass()) {
862       *lims = Union(Limits(lhs->AsRange()), *lims);
863     }
864     if (rhs->IsConstant() && Contains(lhs->AsRange(), rhs->AsConstant())) {
865       return AddToUnion(rhs, result, size, region);
866     }
867     if (rhs->IsRange()) {
868       Limits lim = Intersect(Limits(lhs->AsRange()), Limits(rhs->AsRange()));
869       if (!IsEmpty(lim)) {
870         *lims = Union(lim, *lims);
871       }
872     }
873     return size;
874   }
875   if (rhs->IsRange()) {
876     // This case is handled symmetrically above.
877     return IntersectAux(rhs, lhs, result, size, lims, region);
878   }
879   if (lhs->IsBitset() || rhs->IsBitset()) {
880     return AddToUnion(lhs->IsBitset() ? rhs : lhs, result, size, region);
881   }
882   if (lhs->IsClass() != rhs->IsClass()) {
883     return AddToUnion(lhs->IsClass() ? rhs : lhs, result, size, region);
884   }
885   if (lhs->SimplyEquals(rhs->unhandle())) {
886     return AddToUnion(lhs, result, size, region);
887   }
888   return size;
889 }
890
891
892 // Make sure that we produce a well-formed range and bitset:
893 // If the range is non-empty, the number bits in the bitset should be
894 // clear. Moreover, if we have a canonical range (such as Signed32(),
895 // we want to produce a bitset rather than a range.
896 template <class Config>
897 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeRangeAndBitset(
898     RangeHandle range, bitset* bits, Region* region) {
899   // Fast path: If the bitset does not mention numbers, we can just keep the
900   // range.
901   bitset number_bits = BitsetType::NumberBits(*bits);
902   if (number_bits == 0) {
903     return range;
904   }
905
906   // If the range is contained within the bitset, return an empty range
907   // (but make sure we take the representation).
908   bitset range_lub = SEMANTIC(range->BitsetLub());
909   if (BitsetType::Is(BitsetType::NumberBits(range_lub), *bits)) {
910     return None(region);
911   }
912
913   // Slow path: reconcile the bitset range and the range.
914   double bitset_min = BitsetType::Min(number_bits);
915   double bitset_max = BitsetType::Max(number_bits);
916
917   double range_min = range->Min();
918   double range_max = range->Max();
919
920   // Remove the number bits from the bitset, they would just confuse us now.
921   *bits &= ~number_bits;
922
923   if (range_min <= bitset_min && range_max >= bitset_max) {
924     // Bitset is contained within the range, just return the range.
925     return range;
926   }
927
928   if (bitset_min < range_min) {
929     range_min = bitset_min;
930   }
931   if (bitset_max > range_max) {
932     range_max = bitset_max;
933   }
934   return RangeType::New(range_min, range_max,
935                         BitsetType::New(BitsetType::kNone, region), region);
936 }
937
938
939 template<class Config>
940 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
941     TypeHandle type1, TypeHandle type2, Region* region) {
942   // Fast case: bit sets.
943   if (type1->IsBitset() && type2->IsBitset()) {
944     return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region);
945   }
946
947   // Fast case: top or bottom types.
948   if (type1->IsAny() || type2->IsNone()) return type1;
949   if (type2->IsAny() || type1->IsNone()) return type2;
950
951   // Semi-fast case.
952   if (type1->Is(type2)) return type2;
953   if (type2->Is(type1)) return type1;
954
955   // Figure out the representation of the result.
956   // The rest of the method should not change this representation and
957   // it should make any decisions based on representations (i.e.,
958   // it should only use the semantic part of types).
959   const bitset representation =
960       type1->Representation() | type2->Representation();
961
962   // Slow case: create union.
963   int size1 = type1->IsUnion() ? type1->AsUnion()->Length() : 1;
964   int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1;
965   if (!AddIsSafe(size1, size2)) return Any(region);
966   int size = size1 + size2;
967   if (!AddIsSafe(size, 2)) return Any(region);
968   size += 2;
969   UnionHandle result = UnionType::New(size, region);
970   size = 0;
971
972   // Compute the new bitset.
973   bitset new_bitset = SEMANTIC(type1->BitsetGlb() | type2->BitsetGlb());
974
975   // Deal with ranges.
976   TypeHandle range = None(region);
977   RangeType* range1 = type1->GetRange();
978   RangeType* range2 = type2->GetRange();
979   if (range1 != NULL && range2 != NULL) {
980     Limits lims = Union(Limits(range1), Limits(range2));
981     RangeHandle union_range = RangeType::New(lims, representation, region);
982     range = NormalizeRangeAndBitset(union_range, &new_bitset, region);
983   } else if (range1 != NULL) {
984     range = NormalizeRangeAndBitset(handle(range1), &new_bitset, region);
985   } else if (range2 != NULL) {
986     range = NormalizeRangeAndBitset(handle(range2), &new_bitset, region);
987   }
988   new_bitset = SEMANTIC(new_bitset) | representation;
989   TypeHandle bits = BitsetType::New(new_bitset, region);
990   result->Set(size++, bits);
991   if (!range->IsNone()) result->Set(size++, range);
992
993   size = AddToUnion(type1, result, size, region);
994   size = AddToUnion(type2, result, size, region);
995   return NormalizeUnion(result, size, region);
996 }
997
998
999 // Add [type] to [result] unless [type] is bitset, range, or already subsumed.
1000 // Return new size of [result].
1001 template<class Config>
1002 int TypeImpl<Config>::AddToUnion(
1003     TypeHandle type, UnionHandle result, int size, Region* region) {
1004   if (type->IsBitset() || type->IsRange()) return size;
1005   if (type->IsUnion()) {
1006     for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) {
1007       size = AddToUnion(type->AsUnion()->Get(i), result, size, region);
1008     }
1009     return size;
1010   }
1011   for (int i = 0; i < size; ++i) {
1012     if (type->SemanticIs(result->Get(i)->unhandle())) return size;
1013   }
1014   result->Set(size++, type);
1015   return size;
1016 }
1017
1018
1019 template <class Config>
1020 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeUnion(
1021     UnionHandle unioned, int size, Region* region) {
1022   DCHECK(size >= 1);
1023   DCHECK(unioned->Get(0)->IsBitset());
1024   // If the union has just one element, return it.
1025   if (size == 1) {
1026     return unioned->Get(0);
1027   }
1028   bitset bits = unioned->Get(0)->AsBitset();
1029   // If the union only consists of a range, we can get rid of the union.
1030   if (size == 2 && SEMANTIC(bits) == BitsetType::kNone) {
1031     bitset representation = REPRESENTATION(bits);
1032     if (representation == unioned->Get(1)->Representation()) {
1033       return unioned->Get(1);
1034     }
1035     if (unioned->Get(1)->IsRange()) {
1036       return RangeType::New(unioned->Get(1)->AsRange()->Min(),
1037                             unioned->Get(1)->AsRange()->Max(), unioned->Get(0),
1038                             region);
1039     }
1040   }
1041   unioned->Shrink(size);
1042   SLOW_DCHECK(unioned->Wellformed());
1043   return unioned;
1044 }
1045
1046
1047 // -----------------------------------------------------------------------------
1048 // Component extraction
1049
1050 // static
1051 template <class Config>
1052 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Representation(
1053     TypeHandle t, Region* region) {
1054   return BitsetType::New(t->Representation(), region);
1055 }
1056
1057
1058 // static
1059 template <class Config>
1060 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Semantic(
1061     TypeHandle t, Region* region) {
1062   return Intersect(t, BitsetType::New(BitsetType::kSemantic, region), region);
1063 }
1064
1065
1066 // -----------------------------------------------------------------------------
1067 // Iteration.
1068
1069 template<class Config>
1070 int TypeImpl<Config>::NumClasses() {
1071   DisallowHeapAllocation no_allocation;
1072   if (this->IsClass()) {
1073     return 1;
1074   } else if (this->IsUnion()) {
1075     int result = 0;
1076     for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
1077       if (this->AsUnion()->Get(i)->IsClass()) ++result;
1078     }
1079     return result;
1080   } else {
1081     return 0;
1082   }
1083 }
1084
1085
1086 template<class Config>
1087 int TypeImpl<Config>::NumConstants() {
1088   DisallowHeapAllocation no_allocation;
1089   if (this->IsConstant()) {
1090     return 1;
1091   } else if (this->IsUnion()) {
1092     int result = 0;
1093     for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
1094       if (this->AsUnion()->Get(i)->IsConstant()) ++result;
1095     }
1096     return result;
1097   } else {
1098     return 0;
1099   }
1100 }
1101
1102
1103 template<class Config> template<class T>
1104 typename TypeImpl<Config>::TypeHandle
1105 TypeImpl<Config>::Iterator<T>::get_type() {
1106   DCHECK(!Done());
1107   return type_->IsUnion() ? type_->AsUnion()->Get(index_) : type_;
1108 }
1109
1110
1111 // C++ cannot specialise nested templates, so we have to go through this
1112 // contortion with an auxiliary template to simulate it.
1113 template<class Config, class T>
1114 struct TypeImplIteratorAux {
1115   static bool matches(typename TypeImpl<Config>::TypeHandle type);
1116   static i::Handle<T> current(typename TypeImpl<Config>::TypeHandle type);
1117 };
1118
1119 template<class Config>
1120 struct TypeImplIteratorAux<Config, i::Map> {
1121   static bool matches(typename TypeImpl<Config>::TypeHandle type) {
1122     return type->IsClass();
1123   }
1124   static i::Handle<i::Map> current(typename TypeImpl<Config>::TypeHandle type) {
1125     return type->AsClass()->Map();
1126   }
1127 };
1128
1129 template<class Config>
1130 struct TypeImplIteratorAux<Config, i::Object> {
1131   static bool matches(typename TypeImpl<Config>::TypeHandle type) {
1132     return type->IsConstant();
1133   }
1134   static i::Handle<i::Object> current(
1135       typename TypeImpl<Config>::TypeHandle type) {
1136     return type->AsConstant()->Value();
1137   }
1138 };
1139
1140 template<class Config> template<class T>
1141 bool TypeImpl<Config>::Iterator<T>::matches(TypeHandle type) {
1142   return TypeImplIteratorAux<Config, T>::matches(type);
1143 }
1144
1145 template<class Config> template<class T>
1146 i::Handle<T> TypeImpl<Config>::Iterator<T>::Current() {
1147   return TypeImplIteratorAux<Config, T>::current(get_type());
1148 }
1149
1150
1151 template<class Config> template<class T>
1152 void TypeImpl<Config>::Iterator<T>::Advance() {
1153   DisallowHeapAllocation no_allocation;
1154   ++index_;
1155   if (type_->IsUnion()) {
1156     for (int n = type_->AsUnion()->Length(); index_ < n; ++index_) {
1157       if (matches(type_->AsUnion()->Get(index_))) return;
1158     }
1159   } else if (index_ == 0 && matches(type_)) {
1160     return;
1161   }
1162   index_ = -1;
1163 }
1164
1165
1166 // -----------------------------------------------------------------------------
1167 // Conversion between low-level representations.
1168
1169 template<class Config>
1170 template<class OtherType>
1171 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert(
1172     typename OtherType::TypeHandle type, Region* region) {
1173   if (type->IsBitset()) {
1174     return BitsetType::New(type->AsBitset(), region);
1175   } else if (type->IsClass()) {
1176     return ClassType::New(type->AsClass()->Map(), region);
1177   } else if (type->IsConstant()) {
1178     return ConstantType::New(type->AsConstant()->Value(), region);
1179   } else if (type->IsRange()) {
1180     return RangeType::New(
1181         type->AsRange()->Min(), type->AsRange()->Max(),
1182         BitsetType::New(REPRESENTATION(type->BitsetLub()), region), region);
1183   } else if (type->IsContext()) {
1184     TypeHandle outer = Convert<OtherType>(type->AsContext()->Outer(), region);
1185     return ContextType::New(outer, region);
1186   } else if (type->IsUnion()) {
1187     int length = type->AsUnion()->Length();
1188     UnionHandle unioned = UnionType::New(length, region);
1189     for (int i = 0; i < length; ++i) {
1190       TypeHandle t = Convert<OtherType>(type->AsUnion()->Get(i), region);
1191       unioned->Set(i, t);
1192     }
1193     return unioned;
1194   } else if (type->IsArray()) {
1195     TypeHandle element = Convert<OtherType>(type->AsArray()->Element(), region);
1196     return ArrayType::New(element, region);
1197   } else if (type->IsFunction()) {
1198     TypeHandle res = Convert<OtherType>(type->AsFunction()->Result(), region);
1199     TypeHandle rcv = Convert<OtherType>(type->AsFunction()->Receiver(), region);
1200     FunctionHandle function = FunctionType::New(
1201         res, rcv, type->AsFunction()->Arity(), region);
1202     for (int i = 0; i < function->Arity(); ++i) {
1203       TypeHandle param = Convert<OtherType>(
1204           type->AsFunction()->Parameter(i), region);
1205       function->InitParameter(i, param);
1206     }
1207     return function;
1208   } else {
1209     UNREACHABLE();
1210     return None(region);
1211   }
1212 }
1213
1214
1215 // -----------------------------------------------------------------------------
1216 // Printing.
1217
1218 template<class Config>
1219 const char* TypeImpl<Config>::BitsetType::Name(bitset bits) {
1220   switch (bits) {
1221     case REPRESENTATION(kAny): return "Any";
1222     #define RETURN_NAMED_REPRESENTATION_TYPE(type, value) \
1223     case REPRESENTATION(k##type): return #type;
1224     REPRESENTATION_BITSET_TYPE_LIST(RETURN_NAMED_REPRESENTATION_TYPE)
1225     #undef RETURN_NAMED_REPRESENTATION_TYPE
1226
1227     #define RETURN_NAMED_SEMANTIC_TYPE(type, value) \
1228     case SEMANTIC(k##type): return #type;
1229     SEMANTIC_BITSET_TYPE_LIST(RETURN_NAMED_SEMANTIC_TYPE)
1230     #undef RETURN_NAMED_SEMANTIC_TYPE
1231
1232     default:
1233       return NULL;
1234   }
1235 }
1236
1237
1238 template <class Config>
1239 void TypeImpl<Config>::BitsetType::Print(std::ostream& os,  // NOLINT
1240                                          bitset bits) {
1241   DisallowHeapAllocation no_allocation;
1242   const char* name = Name(bits);
1243   if (name != NULL) {
1244     os << name;
1245     return;
1246   }
1247
1248   // clang-format off
1249   static const bitset named_bitsets[] = {
1250 #define BITSET_CONSTANT(type, value) REPRESENTATION(k##type),
1251     REPRESENTATION_BITSET_TYPE_LIST(BITSET_CONSTANT)
1252 #undef BITSET_CONSTANT
1253
1254 #define BITSET_CONSTANT(type, value) SEMANTIC(k##type),
1255     INTERNAL_BITSET_TYPE_LIST(BITSET_CONSTANT)
1256     SEMANTIC_BITSET_TYPE_LIST(BITSET_CONSTANT)
1257 #undef BITSET_CONSTANT
1258   };
1259   // clang-format on
1260
1261   bool is_first = true;
1262   os << "(";
1263   for (int i(arraysize(named_bitsets) - 1); bits != 0 && i >= 0; --i) {
1264     bitset subset = named_bitsets[i];
1265     if ((bits & subset) == subset) {
1266       if (!is_first) os << " | ";
1267       is_first = false;
1268       os << Name(subset);
1269       bits -= subset;
1270     }
1271   }
1272   DCHECK(bits == 0);
1273   os << ")";
1274 }
1275
1276
1277 template <class Config>
1278 void TypeImpl<Config>::PrintTo(std::ostream& os, PrintDimension dim) {
1279   DisallowHeapAllocation no_allocation;
1280   if (dim != REPRESENTATION_DIM) {
1281     if (this->IsBitset()) {
1282       BitsetType::Print(os, SEMANTIC(this->AsBitset()));
1283     } else if (this->IsClass()) {
1284       os << "Class(" << static_cast<void*>(*this->AsClass()->Map()) << " < ";
1285       BitsetType::New(BitsetType::Lub(this))->PrintTo(os, dim);
1286       os << ")";
1287     } else if (this->IsConstant()) {
1288       os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")";
1289     } else if (this->IsRange()) {
1290       std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed);
1291       std::streamsize saved_precision = os.precision(0);
1292       os << "Range(" << this->AsRange()->Min() << ", " << this->AsRange()->Max()
1293          << ")";
1294       os.flags(saved_flags);
1295       os.precision(saved_precision);
1296     } else if (this->IsContext()) {
1297       os << "Context(";
1298       this->AsContext()->Outer()->PrintTo(os, dim);
1299       os << ")";
1300     } else if (this->IsUnion()) {
1301       os << "(";
1302       for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) {
1303         TypeHandle type_i = this->AsUnion()->Get(i);
1304         if (i > 0) os << " | ";
1305         type_i->PrintTo(os, dim);
1306       }
1307       os << ")";
1308     } else if (this->IsArray()) {
1309       os << "Array(";
1310       AsArray()->Element()->PrintTo(os, dim);
1311       os << ")";
1312     } else if (this->IsFunction()) {
1313       if (!this->AsFunction()->Receiver()->IsAny()) {
1314         this->AsFunction()->Receiver()->PrintTo(os, dim);
1315         os << ".";
1316       }
1317       os << "(";
1318       for (int i = 0; i < this->AsFunction()->Arity(); ++i) {
1319         if (i > 0) os << ", ";
1320         this->AsFunction()->Parameter(i)->PrintTo(os, dim);
1321       }
1322       os << ")->";
1323       this->AsFunction()->Result()->PrintTo(os, dim);
1324     } else {
1325       UNREACHABLE();
1326     }
1327   }
1328   if (dim == BOTH_DIMS) os << "/";
1329   if (dim != SEMANTIC_DIM) {
1330     BitsetType::Print(os, REPRESENTATION(this->BitsetLub()));
1331   }
1332 }
1333
1334
1335 #ifdef DEBUG
1336 template <class Config>
1337 void TypeImpl<Config>::Print() {
1338   OFStream os(stdout);
1339   PrintTo(os);
1340   os << std::endl;
1341 }
1342 template <class Config>
1343 void TypeImpl<Config>::BitsetType::Print(bitset bits) {
1344   OFStream os(stdout);
1345   Print(os, bits);
1346   os << std::endl;
1347 }
1348 #endif
1349
1350
1351 // -----------------------------------------------------------------------------
1352 // Instantiations.
1353
1354 template class TypeImpl<ZoneTypeConfig>;
1355 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Map>;
1356 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Object>;
1357
1358 template class TypeImpl<HeapTypeConfig>;
1359 template class TypeImpl<HeapTypeConfig>::Iterator<i::Map>;
1360 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>;
1361
1362 template TypeImpl<ZoneTypeConfig>::TypeHandle
1363   TypeImpl<ZoneTypeConfig>::Convert<HeapType>(
1364     TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*);
1365 template TypeImpl<HeapTypeConfig>::TypeHandle
1366   TypeImpl<HeapTypeConfig>::Convert<Type>(
1367     TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*);
1368
1369 } }  // namespace v8::internal