| 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/type-feedback-vector.h" | 5 #include "src/type-feedback-vector.h" |
| 6 | 6 |
| 7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
| 8 #include "src/ic/ic.h" | 8 #include "src/ic/ic.h" |
| 9 #include "src/ic/ic-state.h" | 9 #include "src/ic/ic-state.h" |
| 10 #include "src/objects.h" | 10 #include "src/objects.h" |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 SKIP_WRITE_BARRIER); | 577 SKIP_WRITE_BARRIER); |
| 578 } else { | 578 } else { |
| 579 SetFeedback(*name); | 579 SetFeedback(*name); |
| 580 array = EnsureExtraArrayOfSize(receiver_count * 2); | 580 array = EnsureExtraArrayOfSize(receiver_count * 2); |
| 581 } | 581 } |
| 582 | 582 |
| 583 InstallHandlers(array, maps, handlers); | 583 InstallHandlers(array, maps, handlers); |
| 584 } | 584 } |
| 585 | 585 |
| 586 | 586 |
| 587 void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps, |
| 588 MapHandleList* transitioned_maps, |
| 589 CodeHandleList* handlers) { |
| 590 int receiver_count = maps->length(); |
| 591 DCHECK(receiver_count > 1); |
| 592 Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 3); |
| 593 SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()), |
| 594 SKIP_WRITE_BARRIER); |
| 595 |
| 596 Handle<Oddball> undefined_value = GetIsolate()->factory()->undefined_value(); |
| 597 for (int i = 0; i < receiver_count; ++i) { |
| 598 Handle<Map> map = maps->at(i); |
| 599 Handle<WeakCell> cell = Map::WeakCellForMap(map); |
| 600 array->set(i * 3, *cell); |
| 601 if (!transitioned_maps->at(i).is_null()) { |
| 602 Handle<Map> transitioned_map = transitioned_maps->at(i); |
| 603 cell = Map::WeakCellForMap(transitioned_map); |
| 604 array->set((i * 3) + 1, *cell); |
| 605 } else { |
| 606 array->set((i * 3) + 1, *undefined_value); |
| 607 } |
| 608 array->set((i * 3) + 2, *handlers->at(i)); |
| 609 } |
| 610 } |
| 611 |
| 612 |
| 587 int FeedbackNexus::ExtractMaps(MapHandleList* maps) const { | 613 int FeedbackNexus::ExtractMaps(MapHandleList* maps) const { |
| 588 Isolate* isolate = GetIsolate(); | 614 Isolate* isolate = GetIsolate(); |
| 589 Object* feedback = GetFeedback(); | 615 Object* feedback = GetFeedback(); |
| 590 if (feedback->IsFixedArray() || feedback->IsString()) { | 616 if (feedback->IsFixedArray() || feedback->IsString()) { |
| 591 int found = 0; | 617 int found = 0; |
| 592 if (feedback->IsString()) { | 618 if (feedback->IsString()) { |
| 593 feedback = GetFeedbackExtra(); | 619 feedback = GetFeedbackExtra(); |
| 594 } | 620 } |
| 595 FixedArray* array = FixedArray::cast(feedback); | 621 FixedArray* array = FixedArray::cast(feedback); |
| 596 // The array should be of the form [<optional name>], then | 622 // The array should be of the form |
| 597 // [map, handler, map, handler, ... ] | 623 // [map, handler, map, handler, ...] |
| 624 // or |
| 625 // [map, map, handler, map, map, handler, ...] |
| 598 DCHECK(array->length() >= 2); | 626 DCHECK(array->length() >= 2); |
| 599 for (int i = 0; i < array->length(); i += 2) { | 627 int increment = array->get(1)->IsCode() ? 2 : 3; |
| 628 for (int i = 0; i < array->length(); i += increment) { |
| 600 DCHECK(array->get(i)->IsWeakCell()); | 629 DCHECK(array->get(i)->IsWeakCell()); |
| 601 WeakCell* cell = WeakCell::cast(array->get(i)); | 630 WeakCell* cell = WeakCell::cast(array->get(i)); |
| 602 if (!cell->cleared()) { | 631 if (!cell->cleared()) { |
| 603 Map* map = Map::cast(cell->value()); | 632 Map* map = Map::cast(cell->value()); |
| 604 maps->Add(handle(map, isolate)); | 633 maps->Add(handle(map, isolate)); |
| 605 found++; | 634 found++; |
| 606 } | 635 } |
| 607 } | 636 } |
| 608 return found; | 637 return found; |
| 609 } else if (feedback->IsWeakCell()) { | 638 } else if (feedback->IsWeakCell()) { |
| 610 WeakCell* cell = WeakCell::cast(feedback); | 639 WeakCell* cell = WeakCell::cast(feedback); |
| 611 if (!cell->cleared()) { | 640 if (!cell->cleared()) { |
| 612 Map* map = Map::cast(cell->value()); | 641 Map* map = Map::cast(cell->value()); |
| 613 maps->Add(handle(map, isolate)); | 642 maps->Add(handle(map, isolate)); |
| 614 return 1; | 643 return 1; |
| 615 } | 644 } |
| 616 } | 645 } |
| 617 | 646 |
| 618 return 0; | 647 return 0; |
| 619 } | 648 } |
| 620 | 649 |
| 621 | 650 |
| 622 MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const { | 651 MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const { |
| 623 Object* feedback = GetFeedback(); | 652 Object* feedback = GetFeedback(); |
| 624 if (feedback->IsFixedArray() || feedback->IsString()) { | 653 if (feedback->IsFixedArray() || feedback->IsString()) { |
| 625 if (feedback->IsString()) { | 654 if (feedback->IsString()) { |
| 626 feedback = GetFeedbackExtra(); | 655 feedback = GetFeedbackExtra(); |
| 627 } | 656 } |
| 628 FixedArray* array = FixedArray::cast(feedback); | 657 FixedArray* array = FixedArray::cast(feedback); |
| 629 for (int i = 0; i < array->length(); i += 2) { | 658 DCHECK(array->length() >= 2); |
| 659 int increment = array->get(1)->IsCode() ? 2 : 3; |
| 660 for (int i = 0; i < array->length(); i += increment) { |
| 630 DCHECK(array->get(i)->IsWeakCell()); | 661 DCHECK(array->get(i)->IsWeakCell()); |
| 631 WeakCell* cell = WeakCell::cast(array->get(i)); | 662 WeakCell* cell = WeakCell::cast(array->get(i)); |
| 632 if (!cell->cleared()) { | 663 if (!cell->cleared()) { |
| 633 Map* array_map = Map::cast(cell->value()); | 664 Map* array_map = Map::cast(cell->value()); |
| 634 if (array_map == *map) { | 665 if (array_map == *map) { |
| 635 Code* code = Code::cast(array->get(i + 1)); | 666 Code* code = Code::cast(array->get(i + increment - 1)); |
| 636 DCHECK(code->kind() == Code::HANDLER); | 667 DCHECK(code->kind() == Code::HANDLER); |
| 637 return handle(code); | 668 return handle(code); |
| 638 } | 669 } |
| 639 } | 670 } |
| 640 } | 671 } |
| 641 } else if (feedback->IsWeakCell()) { | 672 } else if (feedback->IsWeakCell()) { |
| 642 WeakCell* cell = WeakCell::cast(feedback); | 673 WeakCell* cell = WeakCell::cast(feedback); |
| 643 if (!cell->cleared()) { | 674 if (!cell->cleared()) { |
| 644 Map* cell_map = Map::cast(cell->value()); | 675 Map* cell_map = Map::cast(cell->value()); |
| 645 if (cell_map == *map) { | 676 if (cell_map == *map) { |
| 646 Code* code = Code::cast(GetFeedbackExtra()); | 677 Code* code = Code::cast(GetFeedbackExtra()); |
| 647 DCHECK(code->kind() == Code::HANDLER); | 678 DCHECK(code->kind() == Code::HANDLER); |
| 648 return handle(code); | 679 return handle(code); |
| 649 } | 680 } |
| 650 } | 681 } |
| 651 } | 682 } |
| 652 | 683 |
| 653 return MaybeHandle<Code>(); | 684 return MaybeHandle<Code>(); |
| 654 } | 685 } |
| 655 | 686 |
| 656 | 687 |
| 657 bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const { | 688 bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const { |
| 658 Object* feedback = GetFeedback(); | 689 Object* feedback = GetFeedback(); |
| 659 int count = 0; | 690 int count = 0; |
| 660 if (feedback->IsFixedArray() || feedback->IsString()) { | 691 if (feedback->IsFixedArray() || feedback->IsString()) { |
| 661 if (feedback->IsString()) { | 692 if (feedback->IsString()) { |
| 662 feedback = GetFeedbackExtra(); | 693 feedback = GetFeedbackExtra(); |
| 663 } | 694 } |
| 664 FixedArray* array = FixedArray::cast(feedback); | 695 FixedArray* array = FixedArray::cast(feedback); |
| 665 // The array should be of the form [map, handler, map, handler, ... ]. | 696 // The array should be of the form |
| 697 // [map, handler, map, handler, ...] |
| 698 // or |
| 699 // [map, map, handler, map, map, handler, ...] |
| 666 // Be sure to skip handlers whose maps have been cleared. | 700 // Be sure to skip handlers whose maps have been cleared. |
| 667 DCHECK(array->length() >= 2); | 701 DCHECK(array->length() >= 2); |
| 668 for (int i = 0; i < array->length(); i += 2) { | 702 int increment = array->get(1)->IsCode() ? 2 : 3; |
| 703 for (int i = 0; i < array->length(); i += increment) { |
| 669 DCHECK(array->get(i)->IsWeakCell()); | 704 DCHECK(array->get(i)->IsWeakCell()); |
| 670 WeakCell* cell = WeakCell::cast(array->get(i)); | 705 WeakCell* cell = WeakCell::cast(array->get(i)); |
| 671 if (!cell->cleared()) { | 706 if (!cell->cleared()) { |
| 672 Code* code = Code::cast(array->get(i + 1)); | 707 Code* code = Code::cast(array->get(i + increment - 1)); |
| 673 DCHECK(code->kind() == Code::HANDLER); | 708 DCHECK(code->kind() == Code::HANDLER); |
| 674 code_list->Add(handle(code)); | 709 code_list->Add(handle(code)); |
| 675 count++; | 710 count++; |
| 676 } | 711 } |
| 677 } | 712 } |
| 678 } else if (feedback->IsWeakCell()) { | 713 } else if (feedback->IsWeakCell()) { |
| 679 WeakCell* cell = WeakCell::cast(feedback); | 714 WeakCell* cell = WeakCell::cast(feedback); |
| 680 if (!cell->cleared()) { | 715 if (!cell->cleared()) { |
| 681 Code* code = Code::cast(GetFeedbackExtra()); | 716 Code* code = Code::cast(GetFeedbackExtra()); |
| 682 DCHECK(code->kind() == Code::HANDLER); | 717 DCHECK(code->kind() == Code::HANDLER); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 | 750 |
| 716 | 751 |
| 717 void StoreICNexus::Clear(Code* host) { | 752 void StoreICNexus::Clear(Code* host) { |
| 718 StoreIC::Clear(GetIsolate(), host, this); | 753 StoreIC::Clear(GetIsolate(), host, this); |
| 719 } | 754 } |
| 720 | 755 |
| 721 | 756 |
| 722 void KeyedStoreICNexus::Clear(Code* host) { | 757 void KeyedStoreICNexus::Clear(Code* host) { |
| 723 KeyedStoreIC::Clear(GetIsolate(), host, this); | 758 KeyedStoreIC::Clear(GetIsolate(), host, this); |
| 724 } | 759 } |
| 760 |
| 761 |
| 762 KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const { |
| 763 KeyedAccessStoreMode mode = STANDARD_STORE; |
| 764 MapHandleList maps; |
| 765 CodeHandleList handlers; |
| 766 |
| 767 if (GetKeyType() == PROPERTY) return mode; |
| 768 |
| 769 ExtractMaps(&maps); |
| 770 FindHandlers(&handlers, maps.length()); |
| 771 for (int i = 0; i < handlers.length(); i++) { |
| 772 // The first handler that isn't the slow handler will have the bits we need. |
| 773 Handle<Code> handler = handlers.at(i); |
| 774 CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key()); |
| 775 uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key()); |
| 776 CHECK(major_key == CodeStub::KeyedStoreSloppyArguments || |
| 777 major_key == CodeStub::StoreFastElement || |
| 778 major_key == CodeStub::StoreElement || |
| 779 major_key == CodeStub::ElementsTransitionAndStore || |
| 780 major_key == CodeStub::NoCache); |
| 781 if (major_key != CodeStub::NoCache) { |
| 782 mode = CommonStoreModeBits::decode(minor_key); |
| 783 break; |
| 784 } |
| 785 } |
| 786 |
| 787 return mode; |
| 788 } |
| 789 |
| 790 |
| 791 IcCheckType KeyedStoreICNexus::GetKeyType() const { |
| 792 // The structure of the vector slots tells us the type. |
| 793 return GetFeedback()->IsName() ? PROPERTY : ELEMENT; |
| 794 } |
| 725 } // namespace internal | 795 } // namespace internal |
| 726 } // namespace v8 | 796 } // namespace v8 |
| OLD | NEW |