Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(484)

Side by Side Diff: src/ic/ic.cc

Issue 2412043003: [ic] Support non-code handlers in megamorphic stub cache. (Closed)
Patch Set: Addressing comments Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ic/ic.h ('k') | src/ic/ic-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic/ic.h ('k') | src/ic/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698