| 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 DCHECK(unioned->Wellformed()); |
| 25 for (int i = 0; i < unioned->Length(); ++i) { | 25 return unioned->Get(0)->BitsetGlb(); // Other BitsetGlb's are kNone anyway. |
| 26 bitset |= unioned->Get(i)->BitsetGlb(); | |
| 27 } | |
| 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 { | 26 } else { |
| 43 UNREACHABLE(); | |
| 44 return kNone; | 27 return kNone; |
| 45 } | 28 } |
| 46 } | 29 } |
| 47 | 30 |
| 48 | 31 |
| 49 // The smallest bitset subsuming this type. | 32 // The smallest bitset subsuming this type. |
| 50 template<class Config> | 33 template<class Config> |
| 51 int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { | 34 int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { |
| 52 DisallowHeapAllocation no_allocation; | 35 DisallowHeapAllocation no_allocation; |
| 53 if (type->IsBitset()) { | 36 if (type->IsBitset()) { |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 // Check this <= that. | 236 // Check this <= that. |
| 254 template<class Config> | 237 template<class Config> |
| 255 bool TypeImpl<Config>::SlowIs(TypeImpl* that) { | 238 bool TypeImpl<Config>::SlowIs(TypeImpl* that) { |
| 256 DisallowHeapAllocation no_allocation; | 239 DisallowHeapAllocation no_allocation; |
| 257 | 240 |
| 258 // Fast path for bitsets. | 241 // Fast path for bitsets. |
| 259 if (this->IsNone()) return true; | 242 if (this->IsNone()) return true; |
| 260 if (that->IsBitset()) { | 243 if (that->IsBitset()) { |
| 261 return BitsetType::Is(BitsetType::Lub(this), that->AsBitset()); | 244 return BitsetType::Is(BitsetType::Lub(this), that->AsBitset()); |
| 262 } | 245 } |
| 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 | 246 |
| 268 if (that->IsClass()) { | 247 if (that->IsClass()) { |
| 269 return this->IsClass() | 248 return this->IsClass() |
| 270 && *this->AsClass()->Map() == *that->AsClass()->Map() | 249 && *this->AsClass()->Map() == *that->AsClass()->Map() |
| 271 && ((Config::is_class(that) && Config::is_class(this)) || | 250 && ((Config::is_class(that) && Config::is_class(this)) || |
| 272 BitsetType::New(this->BitsetLub())->Is( | 251 BitsetType::New(this->BitsetLub())->Is( |
| 273 BitsetType::New(that->BitsetLub()))); | 252 BitsetType::New(that->BitsetLub()))); |
| 274 } | 253 } |
| 275 if (that->IsConstant()) { | 254 if (that->IsConstant()) { |
| 276 return this->IsConstant() | 255 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; | 527 if (new_bound == type_i_bound) return size; |
| 549 } | 528 } |
| 550 if (new_bound != old_bound) type = type->Rebound(new_bound, region); | 529 if (new_bound != old_bound) type = type->Rebound(new_bound, region); |
| 551 result->Set(i, type); | 530 result->Set(i, type); |
| 552 } | 531 } |
| 553 } | 532 } |
| 554 return size; | 533 return size; |
| 555 } | 534 } |
| 556 | 535 |
| 557 | 536 |
| 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. | 537 // Union is O(1) on simple bitsets, but O(n*m) on structured unions. |
| 579 template<class Config> | 538 template<class Config> |
| 580 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union( | 539 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union( |
| 581 TypeHandle type1, TypeHandle type2, Region* region) { | 540 TypeHandle type1, TypeHandle type2, Region* region) { |
| 582 // Fast case: bit sets. | 541 // Fast case: bit sets. |
| 583 if (type1->IsBitset() && type2->IsBitset()) { | 542 if (type1->IsBitset() && type2->IsBitset()) { |
| 584 return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region); | 543 return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region); |
| 585 } | 544 } |
| 586 | 545 |
| 587 // Fast case: top or bottom types. | 546 // Fast case: top or bottom types. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 606 if (bitset != BitsetType::kNone) ++size; | 565 if (bitset != BitsetType::kNone) ++size; |
| 607 DCHECK(size >= 1); | 566 DCHECK(size >= 1); |
| 608 | 567 |
| 609 UnionHandle unioned = UnionType::New(size, region); | 568 UnionHandle unioned = UnionType::New(size, region); |
| 610 size = 0; | 569 size = 0; |
| 611 if (bitset != BitsetType::kNone) { | 570 if (bitset != BitsetType::kNone) { |
| 612 unioned->Set(size++, BitsetType::New(bitset, region)); | 571 unioned->Set(size++, BitsetType::New(bitset, region)); |
| 613 } | 572 } |
| 614 size = ExtendUnion(unioned, size, type1, type2, false, region); | 573 size = ExtendUnion(unioned, size, type1, type2, false, region); |
| 615 size = ExtendUnion(unioned, size, type2, type1, false, region); | 574 size = ExtendUnion(unioned, size, type2, type1, false, region); |
| 616 size = NormalizeUnion(unioned, size, bitset); | |
| 617 | 575 |
| 618 if (size == 1) { | 576 if (size == 1) { |
| 619 return unioned->Get(0); | 577 return unioned->Get(0); |
| 620 } else { | 578 } else { |
| 621 unioned->Shrink(size); | 579 unioned->Shrink(size); |
| 622 DCHECK(unioned->Wellformed()); | 580 DCHECK(unioned->Wellformed()); |
| 623 return unioned; | 581 return unioned; |
| 624 } | 582 } |
| 625 } | 583 } |
| 626 | 584 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 656 if (bitset != BitsetType::kNone) ++size; | 614 if (bitset != BitsetType::kNone) ++size; |
| 657 DCHECK(size >= 1); | 615 DCHECK(size >= 1); |
| 658 | 616 |
| 659 UnionHandle unioned = UnionType::New(size, region); | 617 UnionHandle unioned = UnionType::New(size, region); |
| 660 size = 0; | 618 size = 0; |
| 661 if (bitset != BitsetType::kNone) { | 619 if (bitset != BitsetType::kNone) { |
| 662 unioned->Set(size++, BitsetType::New(bitset, region)); | 620 unioned->Set(size++, BitsetType::New(bitset, region)); |
| 663 } | 621 } |
| 664 size = ExtendUnion(unioned, size, type1, type2, true, region); | 622 size = ExtendUnion(unioned, size, type1, type2, true, region); |
| 665 size = ExtendUnion(unioned, size, type2, type1, true, region); | 623 size = ExtendUnion(unioned, size, type2, type1, true, region); |
| 666 size = NormalizeUnion(unioned, size, bitset); | |
| 667 | 624 |
| 668 if (size == 0) { | 625 if (size == 0) { |
| 669 return None(region); | 626 return None(region); |
| 670 } else if (size == 1) { | 627 } else if (size == 1) { |
| 671 return unioned->Get(0); | 628 return unioned->Get(0); |
| 672 } else { | 629 } else { |
| 673 unioned->Shrink(size); | 630 unioned->Shrink(size); |
| 674 DCHECK(unioned->Wellformed()); | 631 DCHECK(unioned->Wellformed()); |
| 675 return unioned; | 632 return unioned; |
| 676 } | 633 } |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; | 917 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; |
| 961 | 918 |
| 962 template TypeImpl<ZoneTypeConfig>::TypeHandle | 919 template TypeImpl<ZoneTypeConfig>::TypeHandle |
| 963 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( | 920 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( |
| 964 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); | 921 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); |
| 965 template TypeImpl<HeapTypeConfig>::TypeHandle | 922 template TypeImpl<HeapTypeConfig>::TypeHandle |
| 966 TypeImpl<HeapTypeConfig>::Convert<Type>( | 923 TypeImpl<HeapTypeConfig>::Convert<Type>( |
| 967 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); | 924 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); |
| 968 | 925 |
| 969 } } // namespace v8::internal | 926 } } // namespace v8::internal |
| OLD | NEW |