 Chromium Code Reviews
 Chromium Code Reviews Issue 904863002:
  [turbofan] Separate representation type operations from the semantic types.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 904863002:
  [turbofan] Separate representation type operations from the semantic types.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| OLD | NEW | 
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include <iomanip> | 5 #include <iomanip> | 
| 6 | 6 | 
| 7 #include "src/types.h" | 7 #include "src/types.h" | 
| 8 | 8 | 
| 9 #include "src/ostreams.h" | 9 #include "src/ostreams.h" | 
| 10 #include "src/types-inl.h" | 10 #include "src/types-inl.h" | 
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 // Range-related helper functions. | 21 // Range-related helper functions. | 
| 22 | 22 | 
| 23 // The result may be invalid (max < min). | 23 // The result may be invalid (max < min). | 
| 24 template<class Config> | 24 template<class Config> | 
| 25 typename TypeImpl<Config>::Limits TypeImpl<Config>::Intersect( | 25 typename TypeImpl<Config>::Limits TypeImpl<Config>::Intersect( | 
| 26 Limits lhs, Limits rhs) { | 26 Limits lhs, Limits rhs) { | 
| 27 DisallowHeapAllocation no_allocation; | 27 DisallowHeapAllocation no_allocation; | 
| 28 Limits result(lhs); | 28 Limits result(lhs); | 
| 29 if (lhs.min < rhs.min) result.min = rhs.min; | 29 if (lhs.min < rhs.min) result.min = rhs.min; | 
| 30 if (lhs.max > rhs.max) result.max = rhs.max; | 30 if (lhs.max > rhs.max) result.max = rhs.max; | 
| 31 result.representation = lhs.representation & rhs.representation; | |
| 32 return result; | 31 return result; | 
| 33 } | 32 } | 
| 34 | 33 | 
| 35 | 34 | 
| 36 template <class Config> | 35 template <class Config> | 
| 37 bool TypeImpl<Config>::IsEmpty(Limits lim) { | 36 bool TypeImpl<Config>::IsEmpty(Limits lim) { | 
| 38 return lim.min > lim.max; | 37 return lim.min > lim.max; | 
| 39 } | 38 } | 
| 40 | 39 | 
| 41 | 40 | 
| 42 template <class Config> | 41 template <class Config> | 
| 43 typename TypeImpl<Config>::Limits TypeImpl<Config>::Union(Limits lhs, | 42 typename TypeImpl<Config>::Limits TypeImpl<Config>::Union(Limits lhs, | 
| 44 Limits rhs) { | 43 Limits rhs) { | 
| 45 DisallowHeapAllocation no_allocation; | 44 DisallowHeapAllocation no_allocation; | 
| 45 if (IsEmpty(lhs)) return rhs; | |
| 46 if (IsEmpty(rhs)) return lhs; | |
| 46 Limits result(lhs); | 47 Limits result(lhs); | 
| 47 if (lhs.min > rhs.min) result.min = rhs.min; | 48 if (lhs.min > rhs.min) result.min = rhs.min; | 
| 48 if (lhs.max < rhs.max) result.max = rhs.max; | 49 if (lhs.max < rhs.max) result.max = rhs.max; | 
| 49 result.representation = lhs.representation | rhs.representation; | |
| 50 return result; | 50 return result; | 
| 51 } | 51 } | 
| 52 | 52 | 
| 53 | 53 | 
| 54 template<class Config> | 54 template<class Config> | 
| 55 bool TypeImpl<Config>::Overlap( | 55 bool TypeImpl<Config>::Overlap( | 
| 56 typename TypeImpl<Config>::RangeType* lhs, | 56 typename TypeImpl<Config>::RangeType* lhs, | 
| 57 typename TypeImpl<Config>::RangeType* rhs) { | 57 typename TypeImpl<Config>::RangeType* rhs) { | 
| 58 DisallowHeapAllocation no_allocation; | 58 DisallowHeapAllocation no_allocation; | 
| 59 typename TypeImpl<Config>::Limits lim = Intersect(Limits(lhs), Limits(rhs)); | 59 typename TypeImpl<Config>::Limits lim = Intersect(Limits(lhs), Limits(rhs)); | 
| 60 return lim.min <= lim.max; | 60 return lim.min <= lim.max; | 
| 61 } | 61 } | 
| 62 | 62 | 
| 63 | 63 | 
| 64 template<class Config> | 64 template<class Config> | 
| 65 bool TypeImpl<Config>::Contains( | 65 bool TypeImpl<Config>::Contains( | 
| 66 typename TypeImpl<Config>::RangeType* lhs, | 66 typename TypeImpl<Config>::RangeType* lhs, | 
| 67 typename TypeImpl<Config>::RangeType* rhs) { | 67 typename TypeImpl<Config>::RangeType* rhs) { | 
| 68 DisallowHeapAllocation no_allocation; | 68 DisallowHeapAllocation no_allocation; | 
| 69 return BitsetType::Is(rhs->Bound(), lhs->Bound()) && | 69 return lhs->Min() <= rhs->Min() && rhs->Max() <= lhs->Max(); | 
| 70 lhs->Min() <= rhs->Min() && rhs->Max() <= lhs->Max(); | |
| 71 } | 70 } | 
| 72 | 71 | 
| 73 | 72 | 
| 74 template <class Config> | 73 template <class Config> | 
| 75 bool TypeImpl<Config>::Contains(typename TypeImpl<Config>::RangeType* lhs, | 74 bool TypeImpl<Config>::Contains(typename TypeImpl<Config>::RangeType* lhs, | 
| 76 typename TypeImpl<Config>::ConstantType* rhs) { | 75 typename TypeImpl<Config>::ConstantType* rhs) { | 
| 77 DisallowHeapAllocation no_allocation; | 76 DisallowHeapAllocation no_allocation; | 
| 78 return IsInteger(*rhs->Value()) && | 77 return IsInteger(*rhs->Value()) && | 
| 79 BitsetType::Is(rhs->Bound()->AsBitset(), lhs->Bound()) && | |
| 80 lhs->Min() <= rhs->Value()->Number() && | 78 lhs->Min() <= rhs->Value()->Number() && | 
| 81 rhs->Value()->Number() <= lhs->Max(); | 79 rhs->Value()->Number() <= lhs->Max(); | 
| 82 } | 80 } | 
| 83 | 81 | 
| 84 | 82 | 
| 85 template<class Config> | 83 template<class Config> | 
| 86 bool TypeImpl<Config>::Contains( | 84 bool TypeImpl<Config>::Contains( | 
| 87 typename TypeImpl<Config>::RangeType* range, i::Object* val) { | 85 typename TypeImpl<Config>::RangeType* range, i::Object* val) { | 
| 88 DisallowHeapAllocation no_allocation; | 86 DisallowHeapAllocation no_allocation; | 
| 89 return IsInteger(val) && | 87 return IsInteger(val) && | 
| 90 BitsetType::Is(BitsetType::Lub(val), range->Bound()) && | |
| 91 range->Min() <= val->Number() && val->Number() <= range->Max(); | 88 range->Min() <= val->Number() && val->Number() <= range->Max(); | 
| 92 } | 89 } | 
| 93 | 90 | 
| 94 | 91 | 
| 95 // ----------------------------------------------------------------------------- | 92 // ----------------------------------------------------------------------------- | 
| 96 // Min and Max computation. | 93 // Min and Max computation. | 
| 97 | 94 | 
| 98 template<class Config> | 95 template<class Config> | 
| 99 double TypeImpl<Config>::Min() { | 96 double TypeImpl<Config>::Min() { | 
| 100 DCHECK(this->Is(Number())); | 97 DCHECK(this->SemanticIs(Number())); | 
| 
rossberg
2015/02/11 12:34:10
Why this?
 
Jarin
2015/02/11 16:10:46
I think we should not fail to give a minimum if we
 | |
| 101 if (this->IsBitset()) return BitsetType::Min(this->AsBitset()); | 98 if (this->IsBitset()) return BitsetType::Min(this->AsBitset()); | 
| 102 if (this->IsUnion()) { | 99 if (this->IsUnion()) { | 
| 103 double min = +V8_INFINITY; | 100 double min = +V8_INFINITY; | 
| 104 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 101 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 
| 105 min = std::min(min, this->AsUnion()->Get(i)->Min()); | 102 min = std::min(min, this->AsUnion()->Get(i)->Min()); | 
| 106 } | 103 } | 
| 107 return min; | 104 return min; | 
| 108 } | 105 } | 
| 109 if (this->IsRange()) return this->AsRange()->Min(); | 106 if (this->IsRange()) return this->AsRange()->Min(); | 
| 110 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); | 107 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); | 
| 111 UNREACHABLE(); | 108 UNREACHABLE(); | 
| 112 return 0; | 109 return 0; | 
| 113 } | 110 } | 
| 114 | 111 | 
| 115 | 112 | 
| 116 template<class Config> | 113 template<class Config> | 
| 117 double TypeImpl<Config>::Max() { | 114 double TypeImpl<Config>::Max() { | 
| 118 DCHECK(this->Is(Number())); | 115 DCHECK(this->SemanticIs(Number())); | 
| 119 if (this->IsBitset()) return BitsetType::Max(this->AsBitset()); | 116 if (this->IsBitset()) return BitsetType::Max(this->AsBitset()); | 
| 120 if (this->IsUnion()) { | 117 if (this->IsUnion()) { | 
| 121 double max = -V8_INFINITY; | 118 double max = -V8_INFINITY; | 
| 122 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 119 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 
| 123 max = std::max(max, this->AsUnion()->Get(i)->Max()); | 120 max = std::max(max, this->AsUnion()->Get(i)->Max()); | 
| 124 } | 121 } | 
| 125 return max; | 122 return max; | 
| 126 } | 123 } | 
| 127 if (this->IsRange()) return this->AsRange()->Max(); | 124 if (this->IsRange()) return this->AsRange()->Max(); | 
| 128 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); | 125 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); | 
| 129 UNREACHABLE(); | 126 UNREACHABLE(); | 
| 130 return 0; | 127 return 0; | 
| 131 } | 128 } | 
| 132 | 129 | 
| 133 | 130 | 
| 134 // ----------------------------------------------------------------------------- | 131 // ----------------------------------------------------------------------------- | 
| 135 // Glb and lub computation. | 132 // Glb and lub computation. | 
| 136 | 133 | 
| 137 | 134 | 
| 138 // The largest bitset subsumed by this type. | 135 // The largest bitset subsumed by this type. | 
| 139 template<class Config> | 136 template<class Config> | 
| 140 typename TypeImpl<Config>::bitset | 137 typename TypeImpl<Config>::bitset | 
| 141 TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) { | 138 TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) { | 
| 142 DisallowHeapAllocation no_allocation; | 139 DisallowHeapAllocation no_allocation; | 
| 140 // Fast case. | |
| 143 if (type->IsBitset()) { | 141 if (type->IsBitset()) { | 
| 144 return type->AsBitset(); | 142 return type->AsBitset(); | 
| 145 } else if (type->IsUnion()) { | 143 } else if (type->IsUnion()) { | 
| 146 SLOW_DCHECK(type->AsUnion()->Wellformed()); | 144 SLOW_DCHECK(type->AsUnion()->Wellformed()); | 
| 147 return type->AsUnion()->Get(0)->BitsetGlb() | | 145 return type->AsUnion()->Get(0)->BitsetGlb() | | 
| 148 type->AsUnion()->Get(1)->BitsetGlb(); // Shortcut. | 146 SEMANTIC(type->AsUnion()->Get(1)->BitsetGlb()); // Shortcut. | 
| 149 } else if (type->IsRange()) { | 147 } else if (type->IsRange()) { | 
| 150 bitset glb = SEMANTIC( | 148 bitset glb = SEMANTIC( | 
| 151 BitsetType::Glb(type->AsRange()->Min(), type->AsRange()->Max())); | 149 BitsetType::Glb(type->AsRange()->Min(), type->AsRange()->Max())); | 
| 152 if (glb == 0) { | 150 return glb | REPRESENTATION(type->BitsetLub()); | 
| 153 return kNone; | |
| 154 } else { | |
| 155 return glb | REPRESENTATION(type->BitsetLub()); | |
| 156 } | |
| 157 } else { | 151 } else { | 
| 158 // (The remaining BitsetGlb's are None anyway). | 152 return type->GetRepresentation(); | 
| 159 return kNone; | |
| 160 } | 153 } | 
| 161 } | 154 } | 
| 162 | 155 | 
| 163 | 156 | 
| 164 // The smallest bitset subsuming this type. | 157 // The smallest bitset subsuming this type. | 
| 165 template<class Config> | 158 template<class Config> | 
| 166 typename TypeImpl<Config>::bitset | 159 typename TypeImpl<Config>::bitset | 
| 167 TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { | 160 TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { | 
| 168 DisallowHeapAllocation no_allocation; | 161 DisallowHeapAllocation no_allocation; | 
| 169 if (type->IsBitset()) return type->AsBitset(); | 162 if (type->IsBitset()) return type->AsBitset(); | 
| 170 if (type->IsUnion()) { | 163 if (type->IsUnion()) { | 
| 171 int bitset = kNone; | 164 // Take the representation from the first element. | 
| 165 int bitset = type->AsUnion()->Get(0)->BitsetLub(); | |
| 172 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { | 166 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { | 
| 173 bitset |= type->AsUnion()->Get(i)->BitsetLub(); | 167 // Other elements only contribute the semantic part. | 
| 168 bitset |= SEMANTIC(type->AsUnion()->Get(i)->BitsetLub()); | |
| 174 } | 169 } | 
| 175 return bitset; | 170 return bitset; | 
| 176 } | 171 } | 
| 177 if (type->IsClass()) { | 172 if (type->IsClass()) { | 
| 178 // Little hack to avoid the need for a region for handlification here... | 173 // Little hack to avoid the need for a region for handlification here... | 
| 179 return Config::is_class(type) ? Lub(*Config::as_class(type)) : | 174 return Config::is_class(type) ? Lub(*Config::as_class(type)) : | 
| 180 type->AsClass()->Bound(NULL)->AsBitset(); | 175 type->AsClass()->Bound(NULL)->AsBitset(); | 
| 181 } | 176 } | 
| 182 if (type->IsConstant()) return type->AsConstant()->Bound()->AsBitset(); | 177 if (type->IsConstant()) return type->AsConstant()->Bound()->AsBitset(); | 
| 183 if (type->IsRange()) return type->AsRange()->Bound(); | 178 if (type->IsRange()) return type->AsRange()->Bound(); | 
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 400 // in the greatest lower bound. (There is also the small trouble | 395 // in the greatest lower bound. (There is also the small trouble | 
| 401 // of kOtherNumber having a range hole, which we can conveniently | 396 // of kOtherNumber having a range hole, which we can conveniently | 
| 402 // ignore here.) | 397 // ignore here.) | 
| 403 return glb & ~(SEMANTIC(kOtherNumber)); | 398 return glb & ~(SEMANTIC(kOtherNumber)); | 
| 404 } | 399 } | 
| 405 | 400 | 
| 406 | 401 | 
| 407 template <class Config> | 402 template <class Config> | 
| 408 double TypeImpl<Config>::BitsetType::Min(bitset bits) { | 403 double TypeImpl<Config>::BitsetType::Min(bitset bits) { | 
| 409 DisallowHeapAllocation no_allocation; | 404 DisallowHeapAllocation no_allocation; | 
| 410 DCHECK(Is(bits, kNumber)); | 405 DCHECK(Is(SEMANTIC(bits), kNumber)); | 
| 411 const Boundary* mins = Boundaries(); | 406 const Boundary* mins = Boundaries(); | 
| 412 bool mz = SEMANTIC(bits & kMinusZero); | 407 bool mz = SEMANTIC(bits & kMinusZero); | 
| 413 for (size_t i = 0; i < BoundariesSize(); ++i) { | 408 for (size_t i = 0; i < BoundariesSize(); ++i) { | 
| 414 if (Is(SEMANTIC(mins[i].bits), bits)) { | 409 if (Is(SEMANTIC(mins[i].bits), bits)) { | 
| 415 return mz ? std::min(0.0, mins[i].min) : mins[i].min; | 410 return mz ? std::min(0.0, mins[i].min) : mins[i].min; | 
| 416 } | 411 } | 
| 417 } | 412 } | 
| 418 if (mz) return 0; | 413 if (mz) return 0; | 
| 419 return std::numeric_limits<double>::quiet_NaN(); | 414 return std::numeric_limits<double>::quiet_NaN(); | 
| 420 } | 415 } | 
| 421 | 416 | 
| 422 | 417 | 
| 423 template<class Config> | 418 template<class Config> | 
| 424 double TypeImpl<Config>::BitsetType::Max(bitset bits) { | 419 double TypeImpl<Config>::BitsetType::Max(bitset bits) { | 
| 425 DisallowHeapAllocation no_allocation; | 420 DisallowHeapAllocation no_allocation; | 
| 426 DCHECK(Is(bits, kNumber)); | 421 DCHECK(Is(SEMANTIC(bits), kNumber)); | 
| 427 const Boundary* mins = Boundaries(); | 422 const Boundary* mins = Boundaries(); | 
| 428 bool mz = SEMANTIC(bits & kMinusZero); | 423 bool mz = SEMANTIC(bits & kMinusZero); | 
| 429 if (BitsetType::Is(SEMANTIC(mins[BoundariesSize() - 1].bits), bits)) { | 424 if (BitsetType::Is(SEMANTIC(mins[BoundariesSize() - 1].bits), bits)) { | 
| 430 return +V8_INFINITY; | 425 return +V8_INFINITY; | 
| 431 } | 426 } | 
| 432 for (size_t i = BoundariesSize() - 1; i-- > 0;) { | 427 for (size_t i = BoundariesSize() - 1; i-- > 0;) { | 
| 433 if (Is(SEMANTIC(mins[i].bits), bits)) { | 428 if (Is(SEMANTIC(mins[i].bits), bits)) { | 
| 434 return mz ? | 429 return mz ? | 
| 435 std::max(0.0, mins[i+1].min - 1) : mins[i+1].min - 1; | 430 std::max(0.0, mins[i+1].min - 1) : mins[i+1].min - 1; | 
| 436 } | 431 } | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 475 for (int i = 0, n = this_fun->Arity(); i < n; ++i) { | 470 for (int i = 0, n = this_fun->Arity(); i < n; ++i) { | 
| 476 if (!this_fun->Parameter(i)->Equals(that_fun->Parameter(i))) return false; | 471 if (!this_fun->Parameter(i)->Equals(that_fun->Parameter(i))) return false; | 
| 477 } | 472 } | 
| 478 return true; | 473 return true; | 
| 479 } | 474 } | 
| 480 UNREACHABLE(); | 475 UNREACHABLE(); | 
| 481 return false; | 476 return false; | 
| 482 } | 477 } | 
| 483 | 478 | 
| 484 | 479 | 
| 480 template <class Config> | |
| 481 typename TypeImpl<Config>::bitset TypeImpl<Config>::GetRepresentation() { | |
| 482 return REPRESENTATION(this->BitsetLub()); | |
| 483 } | |
| 484 | |
| 485 | |
| 485 // Check if [this] <= [that]. | 486 // Check if [this] <= [that]. | 
| 486 template<class Config> | 487 template<class Config> | 
| 487 bool TypeImpl<Config>::SlowIs(TypeImpl* that) { | 488 bool TypeImpl<Config>::SlowIs(TypeImpl* that) { | 
| 488 DisallowHeapAllocation no_allocation; | 489 DisallowHeapAllocation no_allocation; | 
| 489 | 490 | 
| 491 // Fast bitset cases | |
| 490 if (that->IsBitset()) { | 492 if (that->IsBitset()) { | 
| 491 return BitsetType::Is(this->BitsetLub(), that->AsBitset()); | 493 return BitsetType::Is(this->BitsetLub(), that->AsBitset()); | 
| 492 } | 494 } | 
| 495 | |
| 493 if (this->IsBitset()) { | 496 if (this->IsBitset()) { | 
| 494 return BitsetType::Is(this->AsBitset(), that->BitsetGlb()); | 497 return BitsetType::Is(this->AsBitset(), that->BitsetGlb()); | 
| 495 } | 498 } | 
| 496 | 499 | 
| 500 // Check the representations. | |
| 501 if (!BitsetType::Is(GetRepresentation(), that->GetRepresentation())) { | |
| 502 return false; | |
| 503 } | |
| 504 | |
| 505 // Check the semantic part. | |
| 506 return SemanticIs(that); | |
| 507 } | |
| 508 | |
| 509 | |
| 510 // Check if SEMANTIC([this]) <= SEMANTIC([that]). The result of the method | |
| 511 // should be independent of the representation axis of the types. | |
| 512 template <class Config> | |
| 513 bool TypeImpl<Config>::SemanticIs(TypeImpl* that) { | |
| 514 DisallowHeapAllocation no_allocation; | |
| 515 | |
| 516 if (this == that) return true; | |
| 517 | |
| 518 if (that->IsBitset()) { | |
| 519 return BitsetType::Is(SEMANTIC(this->BitsetLub()), that->AsBitset()); | |
| 520 } | |
| 521 if (this->IsBitset()) { | |
| 522 return BitsetType::Is(SEMANTIC(this->AsBitset()), that->BitsetGlb()); | |
| 523 } | |
| 524 | |
| 497 // (T1 \/ ... \/ Tn) <= T if (T1 <= T) /\ ... /\ (Tn <= T) | 525 // (T1 \/ ... \/ Tn) <= T if (T1 <= T) /\ ... /\ (Tn <= T) | 
| 498 if (this->IsUnion()) { | 526 if (this->IsUnion()) { | 
| 499 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 527 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 
| 500 if (!this->AsUnion()->Get(i)->Is(that)) return false; | 528 if (!this->AsUnion()->Get(i)->SemanticIs(that)) return false; | 
| 501 } | 529 } | 
| 502 return true; | 530 return true; | 
| 503 } | 531 } | 
| 504 | 532 | 
| 505 // T <= (T1 \/ ... \/ Tn) if (T <= T1) \/ ... \/ (T <= Tn) | 533 // T <= (T1 \/ ... \/ Tn) if (T <= T1) \/ ... \/ (T <= Tn) | 
| 506 if (that->IsUnion()) { | 534 if (that->IsUnion()) { | 
| 507 for (int i = 0, n = that->AsUnion()->Length(); i < n; ++i) { | 535 for (int i = 0, n = that->AsUnion()->Length(); i < n; ++i) { | 
| 508 if (this->Is(that->AsUnion()->Get(i))) return true; | 536 if (this->SemanticIs(that->AsUnion()->Get(i)->unhandle())) return true; | 
| 509 if (i > 1 && this->IsRange()) return false; // Shortcut. | 537 if (i > 1 && this->IsRange()) return false; // Shortcut. | 
| 510 } | 538 } | 
| 511 return false; | 539 return false; | 
| 512 } | 540 } | 
| 513 | 541 | 
| 514 if (that->IsRange()) { | 542 if (that->IsRange()) { | 
| 515 return (this->IsRange() && Contains(that->AsRange(), this->AsRange())) || | 543 return (this->IsRange() && Contains(that->AsRange(), this->AsRange())) || | 
| 516 (this->IsConstant() && | 544 (this->IsConstant() && | 
| 517 Contains(that->AsRange(), this->AsConstant())); | 545 Contains(that->AsRange(), this->AsConstant())); | 
| 518 } | 546 } | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 551 } | 579 } | 
| 552 return true; | 580 return true; | 
| 553 } | 581 } | 
| 554 | 582 | 
| 555 | 583 | 
| 556 // Check if [this] and [that] overlap. | 584 // Check if [this] and [that] overlap. | 
| 557 template<class Config> | 585 template<class Config> | 
| 558 bool TypeImpl<Config>::Maybe(TypeImpl* that) { | 586 bool TypeImpl<Config>::Maybe(TypeImpl* that) { | 
| 559 DisallowHeapAllocation no_allocation; | 587 DisallowHeapAllocation no_allocation; | 
| 560 | 588 | 
| 589 // Take care of the representation part (and also approximate | |
| 590 // the semantic part). | |
| 591 if (!BitsetType::IsInhabited(this->BitsetLub() & that->BitsetLub())) | |
| 592 return false; | |
| 593 | |
| 594 return SemanticMaybe(that); | |
| 595 } | |
| 596 | |
| 597 template <class Config> | |
| 598 bool TypeImpl<Config>::SemanticMaybe(TypeImpl* that) { | |
| 599 DisallowHeapAllocation no_allocation; | |
| 600 | |
| 561 // (T1 \/ ... \/ Tn) overlaps T if (T1 overlaps T) \/ ... \/ (Tn overlaps T) | 601 // (T1 \/ ... \/ Tn) overlaps T if (T1 overlaps T) \/ ... \/ (Tn overlaps T) | 
| 562 if (this->IsUnion()) { | 602 if (this->IsUnion()) { | 
| 563 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 603 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 
| 564 if (this->AsUnion()->Get(i)->Maybe(that)) return true; | 604 if (this->AsUnion()->Get(i)->SemanticMaybe(that)) return true; | 
| 565 } | 605 } | 
| 566 return false; | 606 return false; | 
| 567 } | 607 } | 
| 568 | 608 | 
| 569 // T overlaps (T1 \/ ... \/ Tn) if (T overlaps T1) \/ ... \/ (T overlaps Tn) | 609 // T overlaps (T1 \/ ... \/ Tn) if (T overlaps T1) \/ ... \/ (T overlaps Tn) | 
| 570 if (that->IsUnion()) { | 610 if (that->IsUnion()) { | 
| 571 for (int i = 0, n = that->AsUnion()->Length(); i < n; ++i) { | 611 for (int i = 0, n = that->AsUnion()->Length(); i < n; ++i) { | 
| 572 if (this->Maybe(that->AsUnion()->Get(i))) return true; | 612 if (this->SemanticMaybe(that->AsUnion()->Get(i)->unhandle())) return true; | 
| 573 } | 613 } | 
| 574 return false; | 614 return false; | 
| 575 } | 615 } | 
| 576 | 616 | 
| 577 if (!BitsetType::IsInhabited(this->BitsetLub() & that->BitsetLub())) | 617 if (!BitsetType::SemanticIsInhabited(this->BitsetLub() & that->BitsetLub())) | 
| 578 return false; | 618 return false; | 
| 579 | 619 | 
| 580 if (this->IsBitset() && that->IsBitset()) return true; | 620 if (this->IsBitset() && that->IsBitset()) return true; | 
| 581 | 621 | 
| 582 if (this->IsClass() != that->IsClass()) return true; | 622 if (this->IsClass() != that->IsClass()) return true; | 
| 583 | 623 | 
| 584 if (this->IsRange()) { | 624 if (this->IsRange()) { | 
| 585 if (that->IsConstant()) { | 625 if (that->IsConstant()) { | 
| 586 return Contains(this->AsRange(), that->AsConstant()); | 626 return Contains(this->AsRange(), that->AsConstant()); | 
| 587 } | 627 } | 
| 588 if (that->IsRange()) { | 628 if (that->IsRange()) { | 
| 589 return Overlap(this->AsRange(), that->AsRange()); | 629 return Overlap(this->AsRange(), that->AsRange()); | 
| 590 } | 630 } | 
| 591 if (that->IsBitset()) { | 631 if (that->IsBitset()) { | 
| 592 bitset number_bits = BitsetType::NumberBits(that->AsBitset()); | 632 bitset number_bits = BitsetType::NumberBits(that->AsBitset()); | 
| 593 if (number_bits == BitsetType::kNone) { | 633 if (number_bits == BitsetType::kNone) { | 
| 594 return false; | 634 return false; | 
| 595 } | 635 } | 
| 596 double min = std::max(BitsetType::Min(number_bits), this->Min()); | 636 double min = std::max(BitsetType::Min(number_bits), this->Min()); | 
| 597 double max = std::min(BitsetType::Max(number_bits), this->Max()); | 637 double max = std::min(BitsetType::Max(number_bits), this->Max()); | 
| 598 return min <= max; | 638 return min <= max; | 
| 599 } | 639 } | 
| 600 } | 640 } | 
| 601 if (that->IsRange()) { | 641 if (that->IsRange()) { | 
| 602 return that->Maybe(this); // This case is handled above. | 642 return that->SemanticMaybe(this); // This case is handled above. | 
| 603 } | 643 } | 
| 604 | 644 | 
| 605 if (this->IsBitset() || that->IsBitset()) return true; | 645 if (this->IsBitset() || that->IsBitset()) return true; | 
| 606 | 646 | 
| 607 return this->SimplyEquals(that); | 647 return this->SimplyEquals(that); | 
| 608 } | 648 } | 
| 609 | 649 | 
| 610 | 650 | 
| 611 // Return the range in [this], or [NULL]. | 651 // Return the range in [this], or [NULL]. | 
| 612 template<class Config> | 652 template<class Config> | 
| (...skipping 19 matching lines...) Expand all Loading... | |
| 632 } | 672 } | 
| 633 return BitsetType::New(BitsetType::Lub(value))->Is(this); | 673 return BitsetType::New(BitsetType::Lub(value))->Is(this); | 
| 634 } | 674 } | 
| 635 | 675 | 
| 636 | 676 | 
| 637 template<class Config> | 677 template<class Config> | 
| 638 bool TypeImpl<Config>::UnionType::Wellformed() { | 678 bool TypeImpl<Config>::UnionType::Wellformed() { | 
| 639 DisallowHeapAllocation no_allocation; | 679 DisallowHeapAllocation no_allocation; | 
| 640 // This checks the invariants of the union representation: | 680 // This checks the invariants of the union representation: | 
| 641 // 1. There are at least two elements. | 681 // 1. There are at least two elements. | 
| 642 // 2. At most one element is a bitset, and it must be the first one. | 682 // 2. The first element is a bitset, no other element is a bitset. | 
| 643 // 3. At most one element is a range, and it must be the second one | 683 // 3. At most one element is a range, and it must be the second one | 
| 644 // (even when the first element is not a bitset). | 684 // (even when the first element is not a bitset). | 
| 645 // 4. No element is itself a union. | 685 // 4. No element is itself a union. | 
| 646 // 5. No element is a subtype of any other. | 686 // 5. No element (except the bitset) is a subtype of any other. | 
| 647 // 6. If there is a range, then the bitset type does not contain | 687 // 6. If there is a range, then the bitset type does not contain | 
| 648 // plain number bits. | 688 // plain number bits. | 
| 649 DCHECK(this->Length() >= 2); // (1) | 689 DCHECK(this->Length() >= 2); // (1) | 
| 650 | 690 DCHECK(this->Get(0)->IsBitset()); // (2a) | 
| 651 bitset number_bits = this->Get(0)->IsBitset() | |
| 652 ? BitsetType::NumberBits(this->Get(0)->AsBitset()) : 0; | |
| 653 USE(number_bits); | |
| 654 | 691 | 
| 655 for (int i = 0; i < this->Length(); ++i) { | 692 for (int i = 0; i < this->Length(); ++i) { | 
| 656 if (i != 0) DCHECK(!this->Get(i)->IsBitset()); // (2) | 693 if (i != 0) DCHECK(!this->Get(i)->IsBitset()); // (2b) | 
| 657 if (i != 1) DCHECK(!this->Get(i)->IsRange()); // (3) | 694 if (i != 1) DCHECK(!this->Get(i)->IsRange()); // (3) | 
| 658 DCHECK(!this->Get(i)->IsUnion()); // (4) | 695 DCHECK(!this->Get(i)->IsUnion()); // (4) | 
| 659 for (int j = 0; j < this->Length(); ++j) { | 696 for (int j = 0; j < this->Length(); ++j) { | 
| 660 if (i != j) DCHECK(!this->Get(i)->Is(this->Get(j))); // (5) | 697 if (i != j && i != 0) | 
| 698 DCHECK(!this->Get(i)->SemanticIs(this->Get(j)->unhandle())); // (5) | |
| 661 } | 699 } | 
| 662 } | 700 } | 
| 663 DCHECK(!this->Get(1)->IsRange() || (number_bits == 0)); // (6) | 701 DCHECK(!this->Get(1)->IsRange() || | 
| 702 (BitsetType::NumberBits(this->Get(0)->AsBitset()) == | |
| 703 BitsetType::kNone)); // (6) | |
| 664 return true; | 704 return true; | 
| 665 } | 705 } | 
| 666 | 706 | 
| 667 | 707 | 
| 668 // ----------------------------------------------------------------------------- | 708 // ----------------------------------------------------------------------------- | 
| 669 // Union and intersection | 709 // Union and intersection | 
| 670 | 710 | 
| 671 | 711 | 
| 672 static bool AddIsSafe(int x, int y) { | 712 static bool AddIsSafe(int x, int y) { | 
| 673 return x >= 0 ? | 713 return x >= 0 ? | 
| 674 y <= std::numeric_limits<int>::max() - x : | 714 y <= std::numeric_limits<int>::max() - x : | 
| 675 y >= std::numeric_limits<int>::min() - x; | 715 y >= std::numeric_limits<int>::min() - x; | 
| 676 } | 716 } | 
| 677 | 717 | 
| 678 | 718 | 
| 679 template<class Config> | 719 template<class Config> | 
| 680 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect( | 720 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect( | 
| 681 TypeHandle type1, TypeHandle type2, Region* region) { | 721 TypeHandle type1, TypeHandle type2, Region* region) { | 
| 682 bitset bits = type1->BitsetGlb() & type2->BitsetGlb(); | |
| 683 if (!BitsetType::IsInhabited(bits)) bits = BitsetType::kNone; | |
| 684 | 722 | 
| 685 // Fast case: bit sets. | 723 // Fast case: bit sets. | 
| 686 if (type1->IsBitset() && type2->IsBitset()) { | 724 if (type1->IsBitset() && type2->IsBitset()) { | 
| 687 return BitsetType::New(bits, region); | 725 return BitsetType::New(type1->AsBitset() & type2->AsBitset(), region); | 
| 688 } | 726 } | 
| 689 | 727 | 
| 690 // Fast case: top or bottom types. | 728 // Fast case: top or bottom types. | 
| 691 if (type1->IsNone() || type2->IsAny()) return type1; // Shortcut. | 729 if (type1->IsNone() || type2->IsAny()) return type1; // Shortcut. | 
| 692 if (type2->IsNone() || type1->IsAny()) return type2; // Shortcut. | 730 if (type2->IsNone() || type1->IsAny()) return type2; // Shortcut. | 
| 693 | 731 | 
| 694 // Semi-fast case. | 732 // Semi-fast case. | 
| 695 if (type1->Is(type2)) return type1; | 733 if (type1->Is(type2)) return type1; | 
| 696 if (type2->Is(type1)) return type2; | 734 if (type2->Is(type1)) return type2; | 
| 697 | 735 | 
| 698 // Slow case: create union. | 736 // Slow case: create union. | 
| 737 | |
| 738 // Figure out the representation of the result first. | |
| 739 // The rest of the method should not change this representation and | |
| 740 // it should make any decisions based on representations (i.e., | |
| 741 // it should only use the semantic part of types). | |
| 742 const bitset representation = | |
| 743 type1->GetRepresentation() & type2->GetRepresentation(); | |
| 744 | |
| 745 bitset bits = | |
| 746 SEMANTIC(type1->BitsetGlb() & type2->BitsetGlb()) | representation; | |
| 699 int size1 = type1->IsUnion() ? type1->AsUnion()->Length() : 1; | 747 int size1 = type1->IsUnion() ? type1->AsUnion()->Length() : 1; | 
| 700 int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1; | 748 int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1; | 
| 701 if (!AddIsSafe(size1, size2)) return Any(region); | 749 if (!AddIsSafe(size1, size2)) return Any(region); | 
| 702 int size = size1 + size2; | 750 int size = size1 + size2; | 
| 703 if (!AddIsSafe(size, 2)) return Any(region); | 751 if (!AddIsSafe(size, 2)) return Any(region); | 
| 704 size += 2; | 752 size += 2; | 
| 705 UnionHandle result = UnionType::New(size, region); | 753 UnionHandle result = UnionType::New(size, region); | 
| 706 size = 0; | 754 size = 0; | 
| 707 | 755 | 
| 708 // Deal with bitsets. | 756 // Deal with bitsets. | 
| 709 result->Set(size++, BitsetType::New(bits, region)); | 757 result->Set(size++, BitsetType::New(bits, region)); | 
| 710 // Insert a placeholder for the range. | |
| 711 result->Set(size++, None(region)); | |
| 712 | 758 | 
| 713 Limits lims = Limits::Empty(region); | 759 Limits lims = Limits::Empty(region); | 
| 714 size = IntersectAux(type1, type2, result, size, &lims, region); | 760 size = IntersectAux(type1, type2, result, size, &lims, region); | 
| 715 | 761 | 
| 716 // If the range is not empty, then insert it into the union and | 762 // If the range is not empty, then insert it into the union and | 
| 717 // remove the number bits from the bitset. | 763 // remove the number bits from the bitset. | 
| 718 if (!IsEmpty(lims)) { | 764 if (!IsEmpty(lims)) { | 
| 719 size = UpdateRange(RangeType::New(lims, region), result, size, region); | 765 size = UpdateRange(RangeType::New(lims, representation, region), result, | 
| 766 size, region); | |
| 720 | 767 | 
| 721 // Remove the number bits. | 768 // Remove the number bits. | 
| 722 bitset number_bits = BitsetType::NumberBits(bits); | 769 bitset number_bits = BitsetType::NumberBits(bits); | 
| 723 bits &= ~number_bits; | 770 bits &= ~number_bits; | 
| 724 if (SEMANTIC(bits) == BitsetType::kNone) { | |
| 725 bits = BitsetType::kNone; | |
| 726 } | |
| 727 result->Set(0, BitsetType::New(bits, region)); | 771 result->Set(0, BitsetType::New(bits, region)); | 
| 728 } | 772 } | 
| 729 return NormalizeUnion(result, size); | 773 return NormalizeUnion(result, size); | 
| 730 } | 774 } | 
| 731 | 775 | 
| 732 | 776 | 
| 733 template<class Config> | 777 template<class Config> | 
| 734 int TypeImpl<Config>::UpdateRange( | 778 int TypeImpl<Config>::UpdateRange( | 
| 735 RangeHandle range, UnionHandle result, int size, Region* region) { | 779 RangeHandle range, UnionHandle result, int size, Region* region) { | 
| 736 TypeHandle old_range = result->Get(1); | 780 if (size == 1) { | 
| 737 DCHECK(old_range->IsRange() || old_range->IsNone()); | 781 result->Set(size++, range); | 
| 738 if (range->Is(old_range)) return size; | 782 } else { | 
| 739 if (!old_range->Is(range->unhandle())) { | 783 // Make space for the range. | 
| 740 range = RangeType::New( | 784 result->Set(size++, result->Get(1)); | 
| 741 Union(Limits(range->AsRange()), Limits(old_range->AsRange())), region); | 785 result->Set(1, range); | 
| 742 } | 786 } | 
| 743 result->Set(1, range); | |
| 744 | 787 | 
| 745 // Remove any components that just got subsumed. | 788 // Remove any components that just got subsumed. | 
| 746 for (int i = 2; i < size; ) { | 789 for (int i = 2; i < size; ) { | 
| 747 if (result->Get(i)->Is(range->unhandle())) { | 790 if (result->Get(i)->SemanticIs(range->unhandle())) { | 
| 748 result->Set(i, result->Get(--size)); | 791 result->Set(i, result->Get(--size)); | 
| 749 } else { | 792 } else { | 
| 750 ++i; | 793 ++i; | 
| 751 } | 794 } | 
| 752 } | 795 } | 
| 753 return size; | 796 return size; | 
| 754 } | 797 } | 
| 755 | 798 | 
| 756 | 799 | 
| 757 template <class Config> | 800 template <class Config> | 
| 758 typename TypeImpl<Config>::Limits TypeImpl<Config>::ToLimits(bitset bits, | 801 typename TypeImpl<Config>::Limits TypeImpl<Config>::ToLimits(bitset bits, | 
| 759 Region* region) { | 802 Region* region) { | 
| 760 bitset representation = REPRESENTATION(bits); | |
| 761 bitset number_bits = BitsetType::NumberBits(bits); | 803 bitset number_bits = BitsetType::NumberBits(bits); | 
| 762 | 804 | 
| 763 if (representation == BitsetType::kNone && number_bits == BitsetType::kNone) { | 805 if (number_bits == BitsetType::kNone) { | 
| 764 return Limits::Empty(region); | 806 return Limits::Empty(region); | 
| 765 } | 807 } | 
| 766 | 808 | 
| 767 return Limits(BitsetType::Min(number_bits), BitsetType::Max(number_bits), | 809 return Limits(BitsetType::Min(number_bits), BitsetType::Max(number_bits)); | 
| 768 representation); | |
| 769 } | 810 } | 
| 770 | 811 | 
| 771 | 812 | 
| 772 template <class Config> | 813 template <class Config> | 
| 773 typename TypeImpl<Config>::Limits TypeImpl<Config>::IntersectRangeAndBitset( | 814 typename TypeImpl<Config>::Limits TypeImpl<Config>::IntersectRangeAndBitset( | 
| 774 TypeHandle range, TypeHandle bitset, Region* region) { | 815 TypeHandle range, TypeHandle bitset, Region* region) { | 
| 775 Limits range_lims(range->AsRange()); | 816 Limits range_lims(range->AsRange()); | 
| 776 Limits bitset_lims = ToLimits(bitset->AsBitset(), region); | 817 Limits bitset_lims = ToLimits(bitset->AsBitset(), region); | 
| 777 return Intersect(range_lims, bitset_lims); | 818 return Intersect(range_lims, bitset_lims); | 
| 778 } | 819 } | 
| (...skipping 11 matching lines...) Expand all Loading... | |
| 790 return size; | 831 return size; | 
| 791 } | 832 } | 
| 792 if (rhs->IsUnion()) { | 833 if (rhs->IsUnion()) { | 
| 793 for (int i = 0, n = rhs->AsUnion()->Length(); i < n; ++i) { | 834 for (int i = 0, n = rhs->AsUnion()->Length(); i < n; ++i) { | 
| 794 size = | 835 size = | 
| 795 IntersectAux(lhs, rhs->AsUnion()->Get(i), result, size, lims, region); | 836 IntersectAux(lhs, rhs->AsUnion()->Get(i), result, size, lims, region); | 
| 796 } | 837 } | 
| 797 return size; | 838 return size; | 
| 798 } | 839 } | 
| 799 | 840 | 
| 800 if (!BitsetType::IsInhabited(lhs->BitsetLub() & rhs->BitsetLub())) { | 841 if (!BitsetType::SemanticIsInhabited(lhs->BitsetLub() & rhs->BitsetLub())) { | 
| 801 return size; | 842 return size; | 
| 802 } | 843 } | 
| 803 | 844 | 
| 804 if (lhs->IsRange()) { | 845 if (lhs->IsRange()) { | 
| 805 if (rhs->IsBitset()) { | 846 if (rhs->IsBitset()) { | 
| 806 Limits lim = IntersectRangeAndBitset(lhs, rhs, region); | 847 Limits lim = IntersectRangeAndBitset(lhs, rhs, region); | 
| 807 | 848 | 
| 808 if (!IsEmpty(lim)) { | 849 if (!IsEmpty(lim)) { | 
| 809 *lims = Union(lim, *lims); | 850 *lims = Union(lim, *lims); | 
| 810 } | 851 } | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 850 RangeHandle range, bitset* bits, Region* region) { | 891 RangeHandle range, bitset* bits, Region* region) { | 
| 851 // Fast path: If the bitset does not mention numbers, we can just keep the | 892 // Fast path: If the bitset does not mention numbers, we can just keep the | 
| 852 // range. | 893 // range. | 
| 853 bitset number_bits = BitsetType::NumberBits(*bits); | 894 bitset number_bits = BitsetType::NumberBits(*bits); | 
| 854 if (number_bits == 0) { | 895 if (number_bits == 0) { | 
| 855 return range; | 896 return range; | 
| 856 } | 897 } | 
| 857 | 898 | 
| 858 // If the range is contained within the bitset, return an empty range | 899 // If the range is contained within the bitset, return an empty range | 
| 859 // (but make sure we take the representation). | 900 // (but make sure we take the representation). | 
| 860 bitset range_lub = range->BitsetLub(); | 901 bitset range_lub = SEMANTIC(range->BitsetLub()); | 
| 861 if (BitsetType::Is(BitsetType::NumberBits(range_lub), *bits)) { | 902 if (BitsetType::Is(BitsetType::NumberBits(range_lub), *bits)) { | 
| 862 *bits |= range_lub; | |
| 863 return None(region); | 903 return None(region); | 
| 864 } | 904 } | 
| 865 | 905 | 
| 866 // Slow path: reconcile the bitset range and the range. | 906 // Slow path: reconcile the bitset range and the range. | 
| 867 double bitset_min = BitsetType::Min(number_bits); | 907 double bitset_min = BitsetType::Min(number_bits); | 
| 868 double bitset_max = BitsetType::Max(number_bits); | 908 double bitset_max = BitsetType::Max(number_bits); | 
| 869 | 909 | 
| 870 double range_min = range->Min(); | 910 double range_min = range->Min(); | 
| 871 double range_max = range->Max(); | 911 double range_max = range->Max(); | 
| 872 | 912 | 
| 873 bitset range_representation = REPRESENTATION(range->BitsetLub()); | |
| 874 bitset bits_representation = REPRESENTATION(*bits); | |
| 875 bitset representation = | |
| 876 (bits_representation | range_representation) & BitsetType::kNumber; | |
| 877 | |
| 878 // Remove the number bits from the bitset, they would just confuse us now. | 913 // Remove the number bits from the bitset, they would just confuse us now. | 
| 879 *bits &= ~number_bits; | 914 *bits &= ~number_bits; | 
| 880 if (bits_representation == *bits) { | |
| 881 *bits = BitsetType::kNone; | |
| 882 } | |
| 883 | 915 | 
| 884 if (representation == range_representation && range_min <= bitset_min && | 916 if (range_min <= bitset_min && range_max >= bitset_max) { | 
| 885 range_max >= bitset_max) { | |
| 886 // Bitset is contained within the range, just return the range. | 917 // Bitset is contained within the range, just return the range. | 
| 887 return range; | 918 return range; | 
| 888 } | 919 } | 
| 889 | 920 | 
| 890 if (bitset_min < range_min) { | 921 if (bitset_min < range_min) { | 
| 891 range_min = bitset_min; | 922 range_min = bitset_min; | 
| 892 } | 923 } | 
| 893 if (bitset_max > range_max) { | 924 if (bitset_max > range_max) { | 
| 894 range_max = bitset_max; | 925 range_max = bitset_max; | 
| 895 } | 926 } | 
| 896 return RangeType::New(range_min, range_max, | 927 return RangeType::New(range_min, range_max, | 
| 897 BitsetType::New(representation, region), region); | 928 BitsetType::New(BitsetType::kNone, region), region); | 
| 898 } | 929 } | 
| 899 | 930 | 
| 900 | 931 | 
| 901 template<class Config> | 932 template<class Config> | 
| 902 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union( | 933 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union( | 
| 903 TypeHandle type1, TypeHandle type2, Region* region) { | 934 TypeHandle type1, TypeHandle type2, Region* region) { | 
| 904 | |
| 905 // Fast case: bit sets. | 935 // Fast case: bit sets. | 
| 906 if (type1->IsBitset() && type2->IsBitset()) { | 936 if (type1->IsBitset() && type2->IsBitset()) { | 
| 907 return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region); | 937 return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region); | 
| 908 } | 938 } | 
| 909 | 939 | 
| 910 // Fast case: top or bottom types. | 940 // Fast case: top or bottom types. | 
| 911 if (type1->IsAny() || type2->IsNone()) return type1; | 941 if (type1->IsAny() || type2->IsNone()) return type1; | 
| 912 if (type2->IsAny() || type1->IsNone()) return type2; | 942 if (type2->IsAny() || type1->IsNone()) return type2; | 
| 913 | 943 | 
| 914 // Semi-fast case. | 944 // Semi-fast case. | 
| 915 if (type1->Is(type2)) return type2; | 945 if (type1->Is(type2)) return type2; | 
| 916 if (type2->Is(type1)) return type1; | 946 if (type2->Is(type1)) return type1; | 
| 917 | 947 | 
| 948 // Figure out the representation of the result. | |
| 949 // The rest of the method should not change this representation and | |
| 950 // it should make any decisions based on representations (i.e., | |
| 951 // it should only use the semantic part of types). | |
| 952 const bitset representation = | |
| 953 type1->GetRepresentation() | type2->GetRepresentation(); | |
| 954 | |
| 918 // Slow case: create union. | 955 // Slow case: create union. | 
| 919 int size1 = type1->IsUnion() ? type1->AsUnion()->Length() : 1; | 956 int size1 = type1->IsUnion() ? type1->AsUnion()->Length() : 1; | 
| 920 int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1; | 957 int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1; | 
| 921 if (!AddIsSafe(size1, size2)) return Any(region); | 958 if (!AddIsSafe(size1, size2)) return Any(region); | 
| 922 int size = size1 + size2; | 959 int size = size1 + size2; | 
| 923 if (!AddIsSafe(size, 2)) return Any(region); | 960 if (!AddIsSafe(size, 2)) return Any(region); | 
| 924 size += 2; | 961 size += 2; | 
| 925 UnionHandle result = UnionType::New(size, region); | 962 UnionHandle result = UnionType::New(size, region); | 
| 926 size = 0; | 963 size = 0; | 
| 927 | 964 | 
| 928 // Compute the new bitset. | 965 // Compute the new bitset. | 
| 929 bitset new_bitset = type1->BitsetGlb() | type2->BitsetGlb(); | 966 bitset new_bitset = SEMANTIC(type1->BitsetGlb() | type2->BitsetGlb()); | 
| 930 | 967 | 
| 931 // Deal with ranges. | 968 // Deal with ranges. | 
| 932 TypeHandle range = None(region); | 969 TypeHandle range = None(region); | 
| 933 RangeType* range1 = type1->GetRange(); | 970 RangeType* range1 = type1->GetRange(); | 
| 934 RangeType* range2 = type2->GetRange(); | 971 RangeType* range2 = type2->GetRange(); | 
| 935 if (range1 != NULL && range2 != NULL) { | 972 if (range1 != NULL && range2 != NULL) { | 
| 936 Limits lims = Union(Limits(range1), Limits(range2)); | 973 Limits lims = Union(Limits(range1), Limits(range2)); | 
| 937 RangeHandle union_range = RangeType::New(lims, region); | 974 RangeHandle union_range = RangeType::New(lims, representation, region); | 
| 938 range = NormalizeRangeAndBitset(union_range, &new_bitset, region); | 975 range = NormalizeRangeAndBitset(union_range, &new_bitset, region); | 
| 939 } else if (range1 != NULL) { | 976 } else if (range1 != NULL) { | 
| 940 range = NormalizeRangeAndBitset(handle(range1), &new_bitset, region); | 977 range = NormalizeRangeAndBitset(handle(range1), &new_bitset, region); | 
| 941 } else if (range2 != NULL) { | 978 } else if (range2 != NULL) { | 
| 942 range = NormalizeRangeAndBitset(handle(range2), &new_bitset, region); | 979 range = NormalizeRangeAndBitset(handle(range2), &new_bitset, region); | 
| 943 } | 980 } | 
| 981 new_bitset = SEMANTIC(new_bitset) | representation; | |
| 944 TypeHandle bits = BitsetType::New(new_bitset, region); | 982 TypeHandle bits = BitsetType::New(new_bitset, region); | 
| 945 result->Set(size++, bits); | 983 result->Set(size++, bits); | 
| 946 result->Set(size++, range); | 984 if (!range->IsNone()) { | 
| 985 result->Set(size++, range); | |
| 986 } | |
| 947 | 987 | 
| 948 size = AddToUnion(type1, result, size, region); | 988 size = AddToUnion(type1, result, size, region); | 
| 949 size = AddToUnion(type2, result, size, region); | 989 size = AddToUnion(type2, result, size, region); | 
| 950 return NormalizeUnion(result, size); | 990 return NormalizeUnion(result, size); | 
| 951 } | 991 } | 
| 952 | 992 | 
| 953 | 993 | 
| 954 // Add [type] to [result] unless [type] is bitset, range, or already subsumed. | 994 // Add [type] to [result] unless [type] is bitset, range, or already subsumed. | 
| 955 // Return new size of [result]. | 995 // Return new size of [result]. | 
| 956 template<class Config> | 996 template<class Config> | 
| 957 int TypeImpl<Config>::AddToUnion( | 997 int TypeImpl<Config>::AddToUnion( | 
| 958 TypeHandle type, UnionHandle result, int size, Region* region) { | 998 TypeHandle type, UnionHandle result, int size, Region* region) { | 
| 959 if (type->IsBitset() || type->IsRange()) return size; | 999 if (type->IsBitset() || type->IsRange()) return size; | 
| 960 if (type->IsUnion()) { | 1000 if (type->IsUnion()) { | 
| 961 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { | 1001 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { | 
| 962 size = AddToUnion(type->AsUnion()->Get(i), result, size, region); | 1002 size = AddToUnion(type->AsUnion()->Get(i), result, size, region); | 
| 963 } | 1003 } | 
| 964 return size; | 1004 return size; | 
| 965 } | 1005 } | 
| 966 for (int i = 0; i < size; ++i) { | 1006 for (int i = 0; i < size; ++i) { | 
| 967 if (type->Is(result->Get(i))) return size; | 1007 if (type->SemanticIs(result->Get(i)->unhandle())) return size; | 
| 968 } | 1008 } | 
| 969 result->Set(size++, type); | 1009 result->Set(size++, type); | 
| 970 return size; | 1010 return size; | 
| 971 } | 1011 } | 
| 972 | 1012 | 
| 973 | 1013 | 
| 974 template<class Config> | 1014 template<class Config> | 
| 975 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeUnion( | 1015 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeUnion( | 
| 976 UnionHandle unioned, int size) { | 1016 UnionHandle unioned, int size) { | 
| 977 DCHECK(size >= 2); | 1017 DCHECK(size >= 1); | 
| 978 // If range is subsumed by bitset, use its place for a different type. | 1018 DCHECK(unioned->Get(0)->IsBitset()); | 
| 979 if (unioned->Get(1)->Is(unioned->Get(0))) { | 1019 // If the union has just one element, return it. | 
| 980 unioned->Set(1, unioned->Get(--size)); | 1020 if (size == 1) { | 
| 1021 return unioned->Get(0); | |
| 981 } | 1022 } | 
| 982 // If bitset is None, use its place for a different type. | 1023 bitset bits = unioned->Get(0)->AsBitset(); | 
| 983 if (size >= 2 && unioned->Get(0)->IsNone()) { | 1024 // If the union only consists of a range, we can get rid of the union. | 
| 984 unioned->Set(0, unioned->Get(--size)); | 1025 if (size == 2 && SEMANTIC(bits) == BitsetType::kNone) { | 
| 1026 bitset representation = REPRESENTATION(bits); | |
| 1027 if (representation == unioned->Get(1)->GetRepresentation()) { | |
| 1028 return unioned->Get(1); | |
| 1029 } | |
| 1030 // TODO(jarin) If the element at 1 is range of constant, slap | |
| 1031 // the representation on it and return that. | |
| 985 } | 1032 } | 
| 986 if (size == 1) return unioned->Get(0); | |
| 987 unioned->Shrink(size); | 1033 unioned->Shrink(size); | 
| 988 SLOW_DCHECK(unioned->Wellformed()); | 1034 SLOW_DCHECK(unioned->Wellformed()); | 
| 989 return unioned; | 1035 return unioned; | 
| 990 } | 1036 } | 
| 991 | 1037 | 
| 992 | 1038 | 
| 993 // ----------------------------------------------------------------------------- | 1039 // ----------------------------------------------------------------------------- | 
| 994 // Iteration. | 1040 // Iteration. | 
| 995 | 1041 | 
| 996 template<class Config> | 1042 template<class Config> | 
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1287 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; | 1333 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; | 
| 1288 | 1334 | 
| 1289 template TypeImpl<ZoneTypeConfig>::TypeHandle | 1335 template TypeImpl<ZoneTypeConfig>::TypeHandle | 
| 1290 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( | 1336 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( | 
| 1291 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); | 1337 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); | 
| 1292 template TypeImpl<HeapTypeConfig>::TypeHandle | 1338 template TypeImpl<HeapTypeConfig>::TypeHandle | 
| 1293 TypeImpl<HeapTypeConfig>::Convert<Type>( | 1339 TypeImpl<HeapTypeConfig>::Convert<Type>( | 
| 1294 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); | 1340 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); | 
| 1295 | 1341 | 
| 1296 } } // namespace v8::internal | 1342 } } // namespace v8::internal | 
| OLD | NEW |