Chromium Code Reviews| 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 "src/types.h" | 5 #include "src/types.h" |
| 6 | 6 |
| 7 #include "src/ostreams.h" | 7 #include "src/ostreams.h" |
| 8 #include "src/types-inl.h" | 8 #include "src/types-inl.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| 11 namespace internal { | 11 namespace internal { |
| 12 | 12 |
| 13 // ----------------------------------------------------------------------------- | 13 // ----------------------------------------------------------------------------- |
| 14 // Glb and lub computation. | 14 // Glb and lub computation. |
| 15 | 15 |
| 16 // The largest bitset subsumed by this type. | 16 // The largest bitset subsumed by this type. |
| 17 template<class Config> | 17 template<class Config> |
| 18 int TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) { | 18 int TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) { |
| 19 DisallowHeapAllocation no_allocation; | 19 DisallowHeapAllocation no_allocation; |
| 20 if (type->IsBitset()) { | 20 if (type->IsBitset()) { |
| 21 return type->AsBitset(); | 21 return type->AsBitset(); |
| 22 } else if (type->IsUnion()) { | 22 } else if (type->IsUnion()) { |
| 23 UnionHandle unioned = handle(type->AsUnion()); | 23 UnionHandle unioned = handle(type->AsUnion()); |
| 24 int bitset = kNone; | 24 int bitset = kNone; |
| 25 for (int i = 0; i < unioned->Length(); ++i) { | 25 for (int i = 0; i < unioned->Length(); ++i) { |
|
rossberg
2014/08/05 15:07:53
You don't need this loop anymore: only the first e
neis
2014/08/05 17:01:10
Good point.
| |
| 26 bitset |= unioned->Get(i)->BitsetGlb(); | 26 bitset |= unioned->Get(i)->BitsetGlb(); |
| 27 } | 27 } |
| 28 return bitset; | 28 return bitset; |
| 29 } else if (type->IsClass()) { | |
| 30 // Little hack to avoid the need for a region for handlification here... | |
| 31 return REPRESENTATION(Config::is_class(type) | |
| 32 ? Lub(*Config::as_class(type)) | |
| 33 : type->AsClass()->Bound(NULL)->AsBitset()); | |
| 34 } else if (type->IsConstant()) { | |
| 35 return REPRESENTATION(type->AsConstant()->Bound()->AsBitset()); | |
| 36 } else if (type->IsContext()) { | |
| 37 return REPRESENTATION(type->AsContext()->Bound()->AsBitset()); | |
| 38 } else if (type->IsArray()) { | |
| 39 return REPRESENTATION(type->AsArray()->Bound()->AsBitset()); | |
| 40 } else if (type->IsFunction()) { | |
| 41 return REPRESENTATION(type->AsFunction()->Bound()->AsBitset()); | |
| 42 } else { | 29 } else { |
| 43 UNREACHABLE(); | |
| 44 return kNone; | 30 return kNone; |
| 45 } | 31 } |
| 46 } | 32 } |
| 47 | 33 |
| 48 | 34 |
| 49 // The smallest bitset subsuming this type. | 35 // The smallest bitset subsuming this type. |
| 50 template<class Config> | 36 template<class Config> |
| 51 int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { | 37 int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { |
| 52 DisallowHeapAllocation no_allocation; | 38 DisallowHeapAllocation no_allocation; |
| 53 if (type->IsBitset()) { | 39 if (type->IsBitset()) { |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 // Check this <= that. | 239 // Check this <= that. |
| 254 template<class Config> | 240 template<class Config> |
| 255 bool TypeImpl<Config>::SlowIs(TypeImpl* that) { | 241 bool TypeImpl<Config>::SlowIs(TypeImpl* that) { |
| 256 DisallowHeapAllocation no_allocation; | 242 DisallowHeapAllocation no_allocation; |
| 257 | 243 |
| 258 // Fast path for bitsets. | 244 // Fast path for bitsets. |
| 259 if (this->IsNone()) return true; | 245 if (this->IsNone()) return true; |
| 260 if (that->IsBitset()) { | 246 if (that->IsBitset()) { |
| 261 return BitsetType::Is(BitsetType::Lub(this), that->AsBitset()); | 247 return BitsetType::Is(BitsetType::Lub(this), that->AsBitset()); |
| 262 } | 248 } |
| 263 if (this->IsBitset() && SEMANTIC(this->AsBitset()) == BitsetType::kNone) { | |
| 264 // Bitsets only have non-bitset supertypes along the representation axis. | |
| 265 return BitsetType::Is(this->AsBitset(), that->BitsetGlb()); | |
| 266 } | |
| 267 | 249 |
| 268 if (that->IsClass()) { | 250 if (that->IsClass()) { |
| 269 return this->IsClass() | 251 return this->IsClass() |
| 270 && *this->AsClass()->Map() == *that->AsClass()->Map() | 252 && *this->AsClass()->Map() == *that->AsClass()->Map() |
| 271 && ((Config::is_class(that) && Config::is_class(this)) || | 253 && ((Config::is_class(that) && Config::is_class(this)) || |
| 272 BitsetType::New(this->BitsetLub())->Is( | 254 BitsetType::New(this->BitsetLub())->Is( |
| 273 BitsetType::New(that->BitsetLub()))); | 255 BitsetType::New(that->BitsetLub()))); |
| 274 } | 256 } |
| 275 if (that->IsConstant()) { | 257 if (that->IsConstant()) { |
| 276 return this->IsConstant() | 258 return this->IsConstant() |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 548 if (new_bound == type_i_bound) return size; | 530 if (new_bound == type_i_bound) return size; |
| 549 } | 531 } |
| 550 if (new_bound != old_bound) type = type->Rebound(new_bound, region); | 532 if (new_bound != old_bound) type = type->Rebound(new_bound, region); |
| 551 result->Set(i, type); | 533 result->Set(i, type); |
| 552 } | 534 } |
| 553 } | 535 } |
| 554 return size; | 536 return size; |
| 555 } | 537 } |
| 556 | 538 |
| 557 | 539 |
| 558 // If bitset is subsumed by another entry in the result, remove it. | |
| 559 // (Only bitsets with empty semantic axis can be subtypes of non-bitsets.) | |
| 560 template<class Config> | |
| 561 int TypeImpl<Config>::NormalizeUnion(UnionHandle result, int size, int bitset) { | |
| 562 if (bitset != BitsetType::kNone && SEMANTIC(bitset) == BitsetType::kNone) { | |
| 563 for (int i = 1; i < size; ++i) { | |
| 564 int glb = result->Get(i)->BitsetGlb(); | |
| 565 if (BitsetType::Is(bitset, glb)) { | |
| 566 for (int j = 1; j < size; ++j) { | |
| 567 result->Set(j - 1, result->Get(j)); | |
| 568 } | |
| 569 --size; | |
| 570 break; | |
| 571 } | |
| 572 } | |
| 573 } | |
| 574 return size; | |
| 575 } | |
| 576 | |
| 577 | |
| 578 // Union is O(1) on simple bitsets, but O(n*m) on structured unions. | 540 // Union is O(1) on simple bitsets, but O(n*m) on structured unions. |
| 579 template<class Config> | 541 template<class Config> |
| 580 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union( | 542 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union( |
| 581 TypeHandle type1, TypeHandle type2, Region* region) { | 543 TypeHandle type1, TypeHandle type2, Region* region) { |
| 582 // Fast case: bit sets. | 544 // Fast case: bit sets. |
| 583 if (type1->IsBitset() && type2->IsBitset()) { | 545 if (type1->IsBitset() && type2->IsBitset()) { |
| 584 return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region); | 546 return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region); |
| 585 } | 547 } |
| 586 | 548 |
| 587 // Fast case: top or bottom types. | 549 // Fast case: top or bottom types. |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 606 if (bitset != BitsetType::kNone) ++size; | 568 if (bitset != BitsetType::kNone) ++size; |
| 607 DCHECK(size >= 1); | 569 DCHECK(size >= 1); |
| 608 | 570 |
| 609 UnionHandle unioned = UnionType::New(size, region); | 571 UnionHandle unioned = UnionType::New(size, region); |
| 610 size = 0; | 572 size = 0; |
| 611 if (bitset != BitsetType::kNone) { | 573 if (bitset != BitsetType::kNone) { |
| 612 unioned->Set(size++, BitsetType::New(bitset, region)); | 574 unioned->Set(size++, BitsetType::New(bitset, region)); |
| 613 } | 575 } |
| 614 size = ExtendUnion(unioned, size, type1, type2, false, region); | 576 size = ExtendUnion(unioned, size, type1, type2, false, region); |
| 615 size = ExtendUnion(unioned, size, type2, type1, false, region); | 577 size = ExtendUnion(unioned, size, type2, type1, false, region); |
| 616 size = NormalizeUnion(unioned, size, bitset); | |
| 617 | 578 |
| 618 if (size == 1) { | 579 if (size == 1) { |
| 619 return unioned->Get(0); | 580 return unioned->Get(0); |
| 620 } else { | 581 } else { |
| 621 unioned->Shrink(size); | 582 unioned->Shrink(size); |
| 622 DCHECK(unioned->Wellformed()); | 583 DCHECK(unioned->Wellformed()); |
| 623 return unioned; | 584 return unioned; |
| 624 } | 585 } |
| 625 } | 586 } |
| 626 | 587 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 656 if (bitset != BitsetType::kNone) ++size; | 617 if (bitset != BitsetType::kNone) ++size; |
| 657 DCHECK(size >= 1); | 618 DCHECK(size >= 1); |
| 658 | 619 |
| 659 UnionHandle unioned = UnionType::New(size, region); | 620 UnionHandle unioned = UnionType::New(size, region); |
| 660 size = 0; | 621 size = 0; |
| 661 if (bitset != BitsetType::kNone) { | 622 if (bitset != BitsetType::kNone) { |
| 662 unioned->Set(size++, BitsetType::New(bitset, region)); | 623 unioned->Set(size++, BitsetType::New(bitset, region)); |
| 663 } | 624 } |
| 664 size = ExtendUnion(unioned, size, type1, type2, true, region); | 625 size = ExtendUnion(unioned, size, type1, type2, true, region); |
| 665 size = ExtendUnion(unioned, size, type2, type1, true, region); | 626 size = ExtendUnion(unioned, size, type2, type1, true, region); |
| 666 size = NormalizeUnion(unioned, size, bitset); | |
| 667 | 627 |
| 668 if (size == 0) { | 628 if (size == 0) { |
| 669 return None(region); | 629 return None(region); |
| 670 } else if (size == 1) { | 630 } else if (size == 1) { |
| 671 return unioned->Get(0); | 631 return unioned->Get(0); |
| 672 } else { | 632 } else { |
| 673 unioned->Shrink(size); | 633 unioned->Shrink(size); |
| 674 DCHECK(unioned->Wellformed()); | 634 DCHECK(unioned->Wellformed()); |
| 675 return unioned; | 635 return unioned; |
| 676 } | 636 } |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 960 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; | 920 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; |
| 961 | 921 |
| 962 template TypeImpl<ZoneTypeConfig>::TypeHandle | 922 template TypeImpl<ZoneTypeConfig>::TypeHandle |
| 963 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( | 923 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( |
| 964 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); | 924 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); |
| 965 template TypeImpl<HeapTypeConfig>::TypeHandle | 925 template TypeImpl<HeapTypeConfig>::TypeHandle |
| 966 TypeImpl<HeapTypeConfig>::Convert<Type>( | 926 TypeImpl<HeapTypeConfig>::Convert<Type>( |
| 967 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); | 927 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); |
| 968 | 928 |
| 969 } } // namespace v8::internal | 929 } } // namespace v8::internal |
| OLD | NEW |