OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/ic/ic.h" | 5 #include "src/ic/ic.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api-arguments-inl.h" | 8 #include "src/api-arguments-inl.h" |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 for (int current = 0; current < receiver_maps->length(); ++current) { | 684 for (int current = 0; current < receiver_maps->length(); ++current) { |
685 if (!receiver_maps->at(current).is_null() && | 685 if (!receiver_maps->at(current).is_null() && |
686 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | 686 receiver_maps->at(current).is_identical_to(new_receiver_map)) { |
687 return false; | 687 return false; |
688 } | 688 } |
689 } | 689 } |
690 receiver_maps->Add(new_receiver_map); | 690 receiver_maps->Add(new_receiver_map); |
691 return true; | 691 return true; |
692 } | 692 } |
693 | 693 |
694 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code) { | 694 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> handler) { |
695 DCHECK(code->IsSmi() || code->IsCode()); | 695 DCHECK(IsHandler(*handler)); |
696 if (!code->IsSmi() && !Code::cast(*code)->is_handler()) { | |
697 return false; | |
698 } | |
699 if (is_keyed() && state() != RECOMPUTE_HANDLER) return false; | 696 if (is_keyed() && state() != RECOMPUTE_HANDLER) return false; |
700 Handle<Map> map = receiver_map(); | 697 Handle<Map> map = receiver_map(); |
701 MapHandleList maps; | 698 MapHandleList maps; |
702 List<Handle<Object>> handlers; | 699 List<Handle<Object>> handlers; |
703 | 700 |
704 TargetMaps(&maps); | 701 TargetMaps(&maps); |
705 int number_of_maps = maps.length(); | 702 int number_of_maps = maps.length(); |
706 int deprecated_maps = 0; | 703 int deprecated_maps = 0; |
707 int handler_to_overwrite = -1; | 704 int handler_to_overwrite = -1; |
708 | 705 |
(...skipping 19 matching lines...) Expand all Loading... |
728 if (number_of_valid_maps >= 4) return false; | 725 if (number_of_valid_maps >= 4) return false; |
729 if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) { | 726 if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) { |
730 return false; | 727 return false; |
731 } | 728 } |
732 DCHECK(UseVector()); | 729 DCHECK(UseVector()); |
733 if (!nexus()->FindHandlers(&handlers, maps.length())) return false; | 730 if (!nexus()->FindHandlers(&handlers, maps.length())) return false; |
734 | 731 |
735 number_of_valid_maps++; | 732 number_of_valid_maps++; |
736 if (number_of_valid_maps > 1 && is_keyed()) return false; | 733 if (number_of_valid_maps > 1 && is_keyed()) return false; |
737 if (number_of_valid_maps == 1) { | 734 if (number_of_valid_maps == 1) { |
738 ConfigureVectorState(name, receiver_map(), code); | 735 ConfigureVectorState(name, receiver_map(), handler); |
739 } else { | 736 } else { |
740 if (handler_to_overwrite >= 0) { | 737 if (handler_to_overwrite >= 0) { |
741 handlers.Set(handler_to_overwrite, code); | 738 handlers.Set(handler_to_overwrite, handler); |
742 if (!map.is_identical_to(maps.at(handler_to_overwrite))) { | 739 if (!map.is_identical_to(maps.at(handler_to_overwrite))) { |
743 maps.Set(handler_to_overwrite, map); | 740 maps.Set(handler_to_overwrite, map); |
744 } | 741 } |
745 } else { | 742 } else { |
746 maps.Add(map); | 743 maps.Add(map); |
747 handlers.Add(code); | 744 handlers.Add(handler); |
748 } | 745 } |
749 | 746 |
750 ConfigureVectorState(name, &maps, &handlers); | 747 ConfigureVectorState(name, &maps, &handlers); |
751 } | 748 } |
752 | 749 |
753 return true; | 750 return true; |
754 } | 751 } |
755 | 752 |
756 void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) { | 753 void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) { |
757 DCHECK(handler->IsSmi() || | 754 DCHECK(IsHandler(*handler)); |
758 (handler->IsCode() && Handle<Code>::cast(handler)->is_handler())); | |
759 ConfigureVectorState(name, receiver_map(), handler); | 755 ConfigureVectorState(name, receiver_map(), handler); |
760 } | 756 } |
761 | 757 |
762 | 758 |
763 void IC::CopyICToMegamorphicCache(Handle<Name> name) { | 759 void IC::CopyICToMegamorphicCache(Handle<Name> name) { |
764 MapHandleList maps; | 760 MapHandleList maps; |
765 List<Handle<Object>> handlers; | 761 List<Handle<Object>> handlers; |
766 TargetMaps(&maps); | 762 TargetMaps(&maps); |
767 if (!nexus()->FindHandlers(&handlers, maps.length())) return; | 763 if (!nexus()->FindHandlers(&handlers, maps.length())) return; |
768 for (int i = 0; i < maps.length(); i++) { | 764 for (int i = 0; i < maps.length(); i++) { |
(...skipping 10 matching lines...) Expand all Loading... |
779 source_map->elements_kind(), target_elements_kind); | 775 source_map->elements_kind(), target_elements_kind); |
780 Map* transitioned_map = nullptr; | 776 Map* transitioned_map = nullptr; |
781 if (more_general_transition) { | 777 if (more_general_transition) { |
782 MapHandleList map_list; | 778 MapHandleList map_list; |
783 map_list.Add(handle(target_map)); | 779 map_list.Add(handle(target_map)); |
784 transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list); | 780 transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list); |
785 } | 781 } |
786 return transitioned_map == target_map; | 782 return transitioned_map == target_map; |
787 } | 783 } |
788 | 784 |
789 void IC::PatchCache(Handle<Name> name, Handle<Object> code) { | 785 void IC::PatchCache(Handle<Name> name, Handle<Object> handler) { |
790 DCHECK(code->IsCode() || (code->IsSmi() && (kind() == Code::LOAD_IC || | 786 DCHECK(IsHandler(*handler)); |
791 kind() == Code::KEYED_LOAD_IC))); | 787 // Currently only LoadIC and KeyedLoadIC support non-code handlers. |
| 788 DCHECK_IMPLIES(!handler->IsCode(), |
| 789 kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC); |
792 switch (state()) { | 790 switch (state()) { |
793 case UNINITIALIZED: | 791 case UNINITIALIZED: |
794 case PREMONOMORPHIC: | 792 case PREMONOMORPHIC: |
795 UpdateMonomorphicIC(code, name); | 793 UpdateMonomorphicIC(handler, name); |
796 break; | 794 break; |
797 case RECOMPUTE_HANDLER: | 795 case RECOMPUTE_HANDLER: |
798 case MONOMORPHIC: | 796 case MONOMORPHIC: |
799 if (kind() == Code::LOAD_GLOBAL_IC) { | 797 if (kind() == Code::LOAD_GLOBAL_IC) { |
800 UpdateMonomorphicIC(code, name); | 798 UpdateMonomorphicIC(handler, name); |
801 break; | 799 break; |
802 } | 800 } |
803 // Fall through. | 801 // Fall through. |
804 case POLYMORPHIC: | 802 case POLYMORPHIC: |
805 if (!is_keyed() || state() == RECOMPUTE_HANDLER) { | 803 if (!is_keyed() || state() == RECOMPUTE_HANDLER) { |
806 if (UpdatePolymorphicIC(name, code)) break; | 804 if (UpdatePolymorphicIC(name, handler)) break; |
807 // For keyed stubs, we can't know whether old handlers were for the | 805 // For keyed stubs, we can't know whether old handlers were for the |
808 // same key. | 806 // same key. |
809 CopyICToMegamorphicCache(name); | 807 CopyICToMegamorphicCache(name); |
810 } | 808 } |
811 DCHECK(UseVector()); | 809 DCHECK(UseVector()); |
812 ConfigureVectorState(MEGAMORPHIC, name); | 810 ConfigureVectorState(MEGAMORPHIC, name); |
813 // Fall through. | 811 // Fall through. |
814 case MEGAMORPHIC: | 812 case MEGAMORPHIC: |
815 UpdateMegamorphicCache(*receiver_map(), *name, *code); | 813 UpdateMegamorphicCache(*receiver_map(), *name, *handler); |
816 // Indicate that we've handled this case. | 814 // Indicate that we've handled this case. |
817 DCHECK(UseVector()); | 815 DCHECK(UseVector()); |
818 vector_set_ = true; | 816 vector_set_ = true; |
819 break; | 817 break; |
820 case GENERIC: | 818 case GENERIC: |
821 UNREACHABLE(); | 819 UNREACHABLE(); |
822 break; | 820 break; |
823 } | 821 } |
824 } | 822 } |
825 | 823 |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
957 case Code::KEYED_STORE_IC: | 955 case Code::KEYED_STORE_IC: |
958 return isolate()->store_stub_cache(); | 956 return isolate()->store_stub_cache(); |
959 | 957 |
960 default: | 958 default: |
961 break; | 959 break; |
962 } | 960 } |
963 UNREACHABLE(); | 961 UNREACHABLE(); |
964 return nullptr; | 962 return nullptr; |
965 } | 963 } |
966 | 964 |
967 void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* code) { | 965 void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* handler) { |
968 if (code->IsSmi()) { | 966 stub_cache()->Set(name, map, handler); |
969 // TODO(jkummerow): Support Smis in the code cache. | |
970 Handle<Map> map_handle(map, isolate()); | |
971 Handle<Name> name_handle(name, isolate()); | |
972 FieldIndex index = | |
973 FieldIndex::ForLoadByFieldOffset(map, Smi::cast(code)->value()); | |
974 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub); | |
975 LoadFieldStub stub(isolate(), index); | |
976 Code* handler = *stub.GetCode(); | |
977 stub_cache()->Set(*name_handle, *map_handle, handler); | |
978 return; | |
979 } | |
980 DCHECK(code->IsCode()); | |
981 stub_cache()->Set(name, map, Code::cast(code)); | |
982 } | 967 } |
983 | 968 |
984 Handle<Object> IC::ComputeHandler(LookupIterator* lookup, | 969 Handle<Object> IC::ComputeHandler(LookupIterator* lookup, |
985 Handle<Object> value) { | 970 Handle<Object> value) { |
986 // Try to find a globally shared handler stub. | 971 // Try to find a globally shared handler stub. |
987 Handle<Object> handler_or_index = GetMapIndependentHandler(lookup); | 972 Handle<Object> handler = GetMapIndependentHandler(lookup); |
988 if (!handler_or_index.is_null()) { | 973 if (!handler.is_null()) { |
989 DCHECK(handler_or_index->IsCode() || handler_or_index->IsSmi()); | 974 DCHECK(IC::IsHandler(*handler)); |
990 return handler_or_index; | 975 return handler; |
991 } | 976 } |
992 | 977 |
993 // Otherwise check the map's handler cache for a map-specific handler, and | 978 // Otherwise check the map's handler cache for a map-specific handler, and |
994 // compile one if the cache comes up empty. | 979 // compile one if the cache comes up empty. |
995 bool receiver_is_holder = | 980 bool receiver_is_holder = |
996 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); | 981 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); |
997 CacheHolderFlag flag; | 982 CacheHolderFlag flag; |
998 Handle<Map> stub_holder_map; | 983 Handle<Map> stub_holder_map; |
999 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC || | 984 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC || |
1000 kind() == Code::KEYED_LOAD_IC) { | 985 kind() == Code::KEYED_LOAD_IC) { |
(...skipping 16 matching lines...) Expand all Loading... |
1017 if (!handler.is_identical_to(code)) { | 1002 if (!handler.is_identical_to(code)) { |
1018 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); | 1003 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); |
1019 return code; | 1004 return code; |
1020 } | 1005 } |
1021 } else { | 1006 } else { |
1022 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. | 1007 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. |
1023 // In MEGAMORPHIC case, check if the handler in the megamorphic stub | 1008 // In MEGAMORPHIC case, check if the handler in the megamorphic stub |
1024 // cache (which just missed) is different from the cached handler. | 1009 // cache (which just missed) is different from the cached handler. |
1025 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) { | 1010 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) { |
1026 Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map(); | 1011 Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map(); |
1027 Code* megamorphic_cached_code = stub_cache()->Get(*lookup->name(), map); | 1012 Object* megamorphic_cached_handler = |
1028 if (megamorphic_cached_code != *code) { | 1013 stub_cache()->Get(*lookup->name(), map); |
| 1014 if (megamorphic_cached_handler != *code) { |
1029 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); | 1015 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); |
1030 return code; | 1016 return code; |
1031 } | 1017 } |
1032 } else { | 1018 } else { |
1033 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); | 1019 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); |
1034 return code; | 1020 return code; |
1035 } | 1021 } |
1036 } | 1022 } |
1037 } | 1023 } |
1038 | 1024 |
(...skipping 1874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2913 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); | 2899 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); |
2914 it.Next(); | 2900 it.Next(); |
2915 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 2901 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
2916 Object::GetProperty(&it)); | 2902 Object::GetProperty(&it)); |
2917 } | 2903 } |
2918 | 2904 |
2919 return *result; | 2905 return *result; |
2920 } | 2906 } |
2921 } // namespace internal | 2907 } // namespace internal |
2922 } // namespace v8 | 2908 } // namespace v8 |
OLD | NEW |