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 |