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 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT); | 534 nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT); |
535 } | 535 } |
536 } else { | 536 } else { |
537 UNREACHABLE(); | 537 UNREACHABLE(); |
538 } | 538 } |
539 | 539 |
540 vector_set_ = true; | 540 vector_set_ = true; |
541 OnTypeFeedbackChanged(isolate(), get_host()); | 541 OnTypeFeedbackChanged(isolate(), get_host()); |
542 } | 542 } |
543 | 543 |
544 | |
545 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, | 544 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, |
546 Handle<Code> handler) { | 545 Handle<Object> handler) { |
547 DCHECK(UseVector()); | 546 DCHECK(UseVector()); |
548 if (kind() == Code::LOAD_IC) { | 547 if (kind() == Code::LOAD_IC) { |
549 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 548 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
550 nexus->ConfigureMonomorphic(map, handler); | 549 nexus->ConfigureMonomorphic(map, handler); |
551 } else if (kind() == Code::LOAD_GLOBAL_IC) { | 550 } else if (kind() == Code::LOAD_GLOBAL_IC) { |
552 LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>(); | 551 LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>(); |
553 nexus->ConfigureHandlerMode(handler); | 552 nexus->ConfigureHandlerMode(Handle<Code>::cast(handler)); |
554 } else if (kind() == Code::KEYED_LOAD_IC) { | 553 } else if (kind() == Code::KEYED_LOAD_IC) { |
555 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 554 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
556 nexus->ConfigureMonomorphic(name, map, handler); | 555 nexus->ConfigureMonomorphic(name, map, Handle<Code>::cast(handler)); |
557 } else if (kind() == Code::STORE_IC) { | 556 } else if (kind() == Code::STORE_IC) { |
558 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); | 557 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); |
559 nexus->ConfigureMonomorphic(map, handler); | 558 nexus->ConfigureMonomorphic(map, Handle<Code>::cast(handler)); |
560 } else { | 559 } else { |
561 DCHECK(kind() == Code::KEYED_STORE_IC); | 560 DCHECK(kind() == Code::KEYED_STORE_IC); |
562 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); | 561 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
563 nexus->ConfigureMonomorphic(name, map, handler); | 562 nexus->ConfigureMonomorphic(name, map, Handle<Code>::cast(handler)); |
564 } | 563 } |
565 | 564 |
566 vector_set_ = true; | 565 vector_set_ = true; |
567 OnTypeFeedbackChanged(isolate(), get_host()); | 566 OnTypeFeedbackChanged(isolate(), get_host()); |
568 } | 567 } |
569 | 568 |
570 | |
571 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, | 569 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, |
572 CodeHandleList* handlers) { | 570 List<Handle<Object>>* handlers) { |
573 DCHECK(UseVector()); | 571 DCHECK(UseVector()); |
574 if (kind() == Code::LOAD_IC) { | 572 if (kind() == Code::LOAD_IC) { |
575 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 573 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
576 nexus->ConfigurePolymorphic(maps, handlers); | 574 nexus->ConfigurePolymorphic(maps, handlers); |
577 } else if (kind() == Code::KEYED_LOAD_IC) { | 575 } else if (kind() == Code::KEYED_LOAD_IC) { |
578 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 576 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
579 nexus->ConfigurePolymorphic(name, maps, handlers); | 577 nexus->ConfigurePolymorphic(name, maps, handlers); |
580 } else if (kind() == Code::STORE_IC) { | 578 } else if (kind() == Code::STORE_IC) { |
581 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); | 579 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); |
582 nexus->ConfigurePolymorphic(maps, handlers); | 580 nexus->ConfigurePolymorphic(maps, handlers); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 for (int current = 0; current < receiver_maps->length(); ++current) { | 677 for (int current = 0; current < receiver_maps->length(); ++current) { |
680 if (!receiver_maps->at(current).is_null() && | 678 if (!receiver_maps->at(current).is_null() && |
681 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | 679 receiver_maps->at(current).is_identical_to(new_receiver_map)) { |
682 return false; | 680 return false; |
683 } | 681 } |
684 } | 682 } |
685 receiver_maps->Add(new_receiver_map); | 683 receiver_maps->Add(new_receiver_map); |
686 return true; | 684 return true; |
687 } | 685 } |
688 | 686 |
689 | 687 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code) { |
690 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) { | 688 DCHECK(code->IsSmi() || code->IsCode()); |
691 if (!code->is_handler()) return false; | 689 if (!code->IsSmi() && !Code::cast(*code)->is_handler()) { |
| 690 return false; |
| 691 } |
692 if (is_keyed() && state() != RECOMPUTE_HANDLER) return false; | 692 if (is_keyed() && state() != RECOMPUTE_HANDLER) return false; |
693 Handle<Map> map = receiver_map(); | 693 Handle<Map> map = receiver_map(); |
694 MapHandleList maps; | 694 MapHandleList maps; |
695 CodeHandleList handlers; | 695 List<Handle<Object>> handlers; |
696 | 696 |
697 TargetMaps(&maps); | 697 TargetMaps(&maps); |
698 int number_of_maps = maps.length(); | 698 int number_of_maps = maps.length(); |
699 int deprecated_maps = 0; | 699 int deprecated_maps = 0; |
700 int handler_to_overwrite = -1; | 700 int handler_to_overwrite = -1; |
701 | 701 |
702 for (int i = 0; i < number_of_maps; i++) { | 702 for (int i = 0; i < number_of_maps; i++) { |
703 Handle<Map> current_map = maps.at(i); | 703 Handle<Map> current_map = maps.at(i); |
704 if (current_map->is_deprecated()) { | 704 if (current_map->is_deprecated()) { |
705 // Filter out deprecated maps to ensure their instances get migrated. | 705 // Filter out deprecated maps to ensure their instances get migrated. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 maps.Add(map); | 740 maps.Add(map); |
741 handlers.Add(code); | 741 handlers.Add(code); |
742 } | 742 } |
743 | 743 |
744 ConfigureVectorState(name, &maps, &handlers); | 744 ConfigureVectorState(name, &maps, &handlers); |
745 } | 745 } |
746 | 746 |
747 return true; | 747 return true; |
748 } | 748 } |
749 | 749 |
750 | 750 void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) { |
751 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) { | 751 DCHECK(handler->IsSmi() || |
752 DCHECK(handler->is_handler()); | 752 (handler->IsCode() && Handle<Code>::cast(handler)->is_handler())); |
753 ConfigureVectorState(name, receiver_map(), handler); | 753 ConfigureVectorState(name, receiver_map(), handler); |
754 } | 754 } |
755 | 755 |
756 | 756 |
757 void IC::CopyICToMegamorphicCache(Handle<Name> name) { | 757 void IC::CopyICToMegamorphicCache(Handle<Name> name) { |
758 MapHandleList maps; | 758 MapHandleList maps; |
759 CodeHandleList handlers; | 759 List<Handle<Object>> handlers; |
760 TargetMaps(&maps); | 760 TargetMaps(&maps); |
761 if (!nexus()->FindHandlers(&handlers, maps.length())) return; | 761 if (!nexus()->FindHandlers(&handlers, maps.length())) return; |
762 for (int i = 0; i < maps.length(); i++) { | 762 for (int i = 0; i < maps.length(); i++) { |
763 UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i)); | 763 UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i)); |
764 } | 764 } |
765 } | 765 } |
766 | 766 |
767 | 767 |
768 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { | 768 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { |
769 if (source_map == NULL) return true; | 769 if (source_map == NULL) return true; |
770 if (target_map == NULL) return false; | 770 if (target_map == NULL) return false; |
771 ElementsKind target_elements_kind = target_map->elements_kind(); | 771 ElementsKind target_elements_kind = target_map->elements_kind(); |
772 bool more_general_transition = IsMoreGeneralElementsKindTransition( | 772 bool more_general_transition = IsMoreGeneralElementsKindTransition( |
773 source_map->elements_kind(), target_elements_kind); | 773 source_map->elements_kind(), target_elements_kind); |
774 Map* transitioned_map = nullptr; | 774 Map* transitioned_map = nullptr; |
775 if (more_general_transition) { | 775 if (more_general_transition) { |
776 MapHandleList map_list; | 776 MapHandleList map_list; |
777 map_list.Add(handle(target_map)); | 777 map_list.Add(handle(target_map)); |
778 transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list); | 778 transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list); |
779 } | 779 } |
780 return transitioned_map == target_map; | 780 return transitioned_map == target_map; |
781 } | 781 } |
782 | 782 |
783 | 783 void IC::PatchCache(Handle<Name> name, Handle<Object> code) { |
784 void IC::PatchCache(Handle<Name> name, Handle<Code> code) { | 784 DCHECK(code->IsCode() || (kind() == Code::LOAD_IC && code->IsSmi())); |
785 switch (state()) { | 785 switch (state()) { |
786 case UNINITIALIZED: | 786 case UNINITIALIZED: |
787 case PREMONOMORPHIC: | 787 case PREMONOMORPHIC: |
788 UpdateMonomorphicIC(code, name); | 788 UpdateMonomorphicIC(code, name); |
789 break; | 789 break; |
790 case RECOMPUTE_HANDLER: | 790 case RECOMPUTE_HANDLER: |
791 case MONOMORPHIC: | 791 case MONOMORPHIC: |
792 if (kind() == Code::LOAD_GLOBAL_IC) { | 792 if (kind() == Code::LOAD_GLOBAL_IC) { |
793 UpdateMonomorphicIC(code, name); | 793 UpdateMonomorphicIC(code, name); |
794 break; | 794 break; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 | 842 |
843 | 843 |
844 Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate, | 844 Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate, |
845 ExtraICState extra_state) { | 845 ExtraICState extra_state) { |
846 LanguageMode mode = StoreICState::GetLanguageMode(extra_state); | 846 LanguageMode mode = StoreICState::GetLanguageMode(extra_state); |
847 return is_strict(mode) | 847 return is_strict(mode) |
848 ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict() | 848 ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict() |
849 : isolate->builtins()->KeyedStoreIC_Megamorphic(); | 849 : isolate->builtins()->KeyedStoreIC_Megamorphic(); |
850 } | 850 } |
851 | 851 |
852 | 852 Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) { |
853 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { | 853 if (kind() == Code::LOAD_IC && FLAG_tf_load_ic_stub) { |
| 854 return handle(Smi::FromInt(index.GetLoadByFieldOffset()), isolate()); |
| 855 } |
| 856 DCHECK(kind() == Code::KEYED_LOAD_IC || !FLAG_tf_load_ic_stub); |
854 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub); | 857 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub); |
855 LoadFieldStub stub(isolate(), index); | 858 LoadFieldStub stub(isolate(), index); |
856 return stub.GetCode(); | 859 return stub.GetCode(); |
857 } | 860 } |
858 | 861 |
859 | 862 |
860 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { | 863 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { |
861 DCHECK(lookup->state() == LookupIterator::ACCESSOR); | 864 DCHECK(lookup->state() == LookupIterator::ACCESSOR); |
862 Isolate* isolate = lookup->isolate(); | 865 Isolate* isolate = lookup->isolate(); |
863 Handle<Object> accessors = lookup->GetAccessors(); | 866 Handle<Object> accessors = lookup->GetAccessors(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
898 | 901 |
899 void LoadIC::UpdateCaches(LookupIterator* lookup) { | 902 void LoadIC::UpdateCaches(LookupIterator* lookup) { |
900 if (state() == UNINITIALIZED && kind() != Code::LOAD_GLOBAL_IC) { | 903 if (state() == UNINITIALIZED && kind() != Code::LOAD_GLOBAL_IC) { |
901 // This is the first time we execute this inline cache. Set the target to | 904 // This is the first time we execute this inline cache. Set the target to |
902 // the pre monomorphic stub to delay setting the monomorphic state. | 905 // the pre monomorphic stub to delay setting the monomorphic state. |
903 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); | 906 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); |
904 TRACE_IC("LoadIC", lookup->name()); | 907 TRACE_IC("LoadIC", lookup->name()); |
905 return; | 908 return; |
906 } | 909 } |
907 | 910 |
908 Handle<Code> code; | 911 Handle<Object> code; |
909 if (lookup->state() == LookupIterator::JSPROXY || | 912 if (lookup->state() == LookupIterator::JSPROXY || |
910 lookup->state() == LookupIterator::ACCESS_CHECK) { | 913 lookup->state() == LookupIterator::ACCESS_CHECK) { |
911 code = slow_stub(); | 914 code = slow_stub(); |
912 } else if (!lookup->IsFound()) { | 915 } else if (!lookup->IsFound()) { |
913 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) { | 916 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) { |
914 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), | 917 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), |
915 receiver_map()); | 918 receiver_map()); |
916 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. | 919 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. |
917 if (code.is_null()) code = slow_stub(); | 920 if (code.is_null()) code = slow_stub(); |
918 } else { | 921 } else { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
973 case Code::KEYED_STORE_IC: | 976 case Code::KEYED_STORE_IC: |
974 return isolate()->store_stub_cache(); | 977 return isolate()->store_stub_cache(); |
975 | 978 |
976 default: | 979 default: |
977 break; | 980 break; |
978 } | 981 } |
979 UNREACHABLE(); | 982 UNREACHABLE(); |
980 return nullptr; | 983 return nullptr; |
981 } | 984 } |
982 | 985 |
983 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { | 986 void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* code) { |
984 stub_cache()->Set(name, map, code); | 987 if (code->IsSmi()) { |
| 988 // TODO(jkummerow): Support Smis in the code cache. |
| 989 Handle<Map> map_handle(map, isolate()); |
| 990 Handle<Name> name_handle(name, isolate()); |
| 991 FieldIndex index = |
| 992 FieldIndex::ForLoadByFieldOffset(map, Smi::cast(code)->value()); |
| 993 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub); |
| 994 LoadFieldStub stub(isolate(), index); |
| 995 Code* handler = *stub.GetCode(); |
| 996 stub_cache()->Set(*name_handle, *map_handle, handler); |
| 997 return; |
| 998 } |
| 999 DCHECK(code->IsCode()); |
| 1000 stub_cache()->Set(name, map, Code::cast(code)); |
985 } | 1001 } |
986 | 1002 |
987 | 1003 Handle<Object> IC::ComputeHandler(LookupIterator* lookup, |
988 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) { | 1004 Handle<Object> value) { |
989 // Try to find a globally shared handler stub. | 1005 // Try to find a globally shared handler stub. |
990 Handle<Code> code = GetMapIndependentHandler(lookup); | 1006 Handle<Object> handler_or_index = GetMapIndependentHandler(lookup); |
991 if (!code.is_null()) return code; | 1007 if (!handler_or_index.is_null()) { |
| 1008 DCHECK(handler_or_index->IsCode() || handler_or_index->IsSmi()); |
| 1009 return handler_or_index; |
| 1010 } |
992 | 1011 |
993 // Otherwise check the map's handler cache for a map-specific handler, and | 1012 // Otherwise check the map's handler cache for a map-specific handler, and |
994 // compile one if the cache comes up empty. | 1013 // compile one if the cache comes up empty. |
995 bool receiver_is_holder = | 1014 bool receiver_is_holder = |
996 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); | 1015 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); |
997 CacheHolderFlag flag; | 1016 CacheHolderFlag flag; |
998 Handle<Map> stub_holder_map; | 1017 Handle<Map> stub_holder_map; |
999 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC || | 1018 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC || |
1000 kind() == Code::KEYED_LOAD_IC) { | 1019 kind() == Code::KEYED_LOAD_IC) { |
1001 stub_holder_map = IC::GetHandlerCacheHolder( | 1020 stub_holder_map = IC::GetHandlerCacheHolder( |
1002 receiver_map(), receiver_is_holder, isolate(), &flag); | 1021 receiver_map(), receiver_is_holder, isolate(), &flag); |
1003 } else { | 1022 } else { |
1004 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC); | 1023 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC); |
1005 // Store handlers cannot be cached on prototypes. | 1024 // Store handlers cannot be cached on prototypes. |
1006 flag = kCacheOnReceiver; | 1025 flag = kCacheOnReceiver; |
1007 stub_holder_map = receiver_map(); | 1026 stub_holder_map = receiver_map(); |
1008 } | 1027 } |
1009 | 1028 |
1010 code = PropertyHandlerCompiler::Find(lookup->name(), stub_holder_map, kind(), | 1029 Handle<Code> code = PropertyHandlerCompiler::Find( |
1011 flag); | 1030 lookup->name(), stub_holder_map, kind(), flag); |
1012 // Use the cached value if it exists, and if it is different from the | 1031 // Use the cached value if it exists, and if it is different from the |
1013 // handler that just missed. | 1032 // handler that just missed. |
1014 if (!code.is_null()) { | 1033 if (!code.is_null()) { |
1015 Handle<Code> handler; | 1034 Handle<Object> handler; |
1016 if (maybe_handler_.ToHandle(&handler)) { | 1035 if (maybe_handler_.ToHandle(&handler)) { |
1017 if (!handler.is_identical_to(code)) { | 1036 if (!handler.is_identical_to(code)) { |
1018 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); | 1037 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); |
1019 return code; | 1038 return code; |
1020 } | 1039 } |
1021 } else { | 1040 } else { |
1022 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. | 1041 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. |
1023 // In MEGAMORPHIC case, check if the handler in the megamorphic stub | 1042 // In MEGAMORPHIC case, check if the handler in the megamorphic stub |
1024 // cache (which just missed) is different from the cached handler. | 1043 // cache (which just missed) is different from the cached handler. |
1025 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) { | 1044 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) { |
(...skipping 11 matching lines...) Expand all Loading... |
1037 } | 1056 } |
1038 | 1057 |
1039 code = CompileHandler(lookup, value, flag); | 1058 code = CompileHandler(lookup, value, flag); |
1040 DCHECK(code->is_handler()); | 1059 DCHECK(code->is_handler()); |
1041 DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag); | 1060 DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag); |
1042 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); | 1061 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); |
1043 | 1062 |
1044 return code; | 1063 return code; |
1045 } | 1064 } |
1046 | 1065 |
1047 Handle<Code> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) { | 1066 Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) { |
1048 Handle<Object> receiver = lookup->GetReceiver(); | 1067 Handle<Object> receiver = lookup->GetReceiver(); |
1049 if (receiver->IsString() && | 1068 if (receiver->IsString() && |
1050 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { | 1069 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { |
1051 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); | 1070 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); |
1052 return SimpleFieldLoad(index); | 1071 return SimpleFieldLoad(index); |
1053 } | 1072 } |
1054 | 1073 |
1055 if (receiver->IsStringWrapper() && | 1074 if (receiver->IsStringWrapper() && |
1056 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { | 1075 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { |
1057 TRACE_HANDLER_STATS(isolate(), LoadIC_StringLengthStub); | 1076 TRACE_HANDLER_STATS(isolate(), LoadIC_StringLengthStub); |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1381 return; | 1400 return; |
1382 } | 1401 } |
1383 | 1402 |
1384 // If the maximum number of receiver maps has been exceeded, use the generic | 1403 // If the maximum number of receiver maps has been exceeded, use the generic |
1385 // version of the IC. | 1404 // version of the IC. |
1386 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1405 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
1387 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 1406 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); |
1388 return; | 1407 return; |
1389 } | 1408 } |
1390 | 1409 |
1391 CodeHandleList handlers(target_receiver_maps.length()); | 1410 List<Handle<Object>> handlers(target_receiver_maps.length()); |
1392 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_PolymorphicElement); | 1411 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_PolymorphicElement); |
1393 ElementHandlerCompiler compiler(isolate()); | 1412 ElementHandlerCompiler compiler(isolate()); |
1394 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); | 1413 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); |
1395 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers); | 1414 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers); |
1396 } | 1415 } |
1397 | 1416 |
1398 | 1417 |
1399 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 1418 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, |
1400 Handle<Object> key) { | 1419 Handle<Object> key) { |
1401 if (MigrateDeprecated(object)) { | 1420 if (MigrateDeprecated(object)) { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1598 // the pre monomorphic stub to delay setting the monomorphic state. | 1617 // the pre monomorphic stub to delay setting the monomorphic state. |
1599 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); | 1618 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); |
1600 TRACE_IC("StoreIC", lookup->name()); | 1619 TRACE_IC("StoreIC", lookup->name()); |
1601 return; | 1620 return; |
1602 } | 1621 } |
1603 | 1622 |
1604 bool use_ic = LookupForWrite(lookup, value, store_mode); | 1623 bool use_ic = LookupForWrite(lookup, value, store_mode); |
1605 if (!use_ic) { | 1624 if (!use_ic) { |
1606 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); | 1625 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); |
1607 } | 1626 } |
1608 Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub(); | 1627 Handle<Code> code = |
| 1628 use_ic ? Handle<Code>::cast(ComputeHandler(lookup, value)) : slow_stub(); |
1609 | 1629 |
1610 PatchCache(lookup->name(), code); | 1630 PatchCache(lookup->name(), code); |
1611 TRACE_IC("StoreIC", lookup->name()); | 1631 TRACE_IC("StoreIC", lookup->name()); |
1612 } | 1632 } |
1613 | 1633 |
1614 | 1634 |
1615 static Handle<Code> PropertyCellStoreHandler( | 1635 static Handle<Code> PropertyCellStoreHandler( |
1616 Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder, | 1636 Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder, |
1617 Handle<Name> name, Handle<PropertyCell> cell, PropertyCellType type) { | 1637 Handle<Name> name, Handle<PropertyCell> cell, PropertyCellType type) { |
1618 auto constant_type = Nothing<PropertyCellConstantType>(); | 1638 auto constant_type = Nothing<PropertyCellConstantType>(); |
1619 if (type == PropertyCellType::kConstantType) { | 1639 if (type == PropertyCellType::kConstantType) { |
1620 constant_type = Just(cell->GetConstantType()); | 1640 constant_type = Just(cell->GetConstantType()); |
1621 } | 1641 } |
1622 StoreGlobalStub stub(isolate, type, constant_type, | 1642 StoreGlobalStub stub(isolate, type, constant_type, |
1623 receiver->IsJSGlobalProxy()); | 1643 receiver->IsJSGlobalProxy()); |
1624 auto code = stub.GetCodeCopyFromTemplate(holder, cell); | 1644 auto code = stub.GetCodeCopyFromTemplate(holder, cell); |
1625 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1645 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
1626 HeapObject::UpdateMapCodeCache(receiver, name, code); | 1646 HeapObject::UpdateMapCodeCache(receiver, name, code); |
1627 return code; | 1647 return code; |
1628 } | 1648 } |
1629 | 1649 |
1630 Handle<Code> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { | 1650 Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { |
1631 DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); | 1651 DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); |
1632 | 1652 |
1633 // This is currently guaranteed by checks in StoreIC::Store. | 1653 // This is currently guaranteed by checks in StoreIC::Store. |
1634 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); | 1654 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); |
1635 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 1655 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
1636 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); | 1656 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); |
1637 | 1657 |
1638 switch (lookup->state()) { | 1658 switch (lookup->state()) { |
1639 case LookupIterator::TRANSITION: { | 1659 case LookupIterator::TRANSITION: { |
1640 auto store_target = lookup->GetStoreTarget(); | 1660 auto store_target = lookup->GetStoreTarget(); |
(...skipping 1351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2992 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, | 3012 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, |
2993 vector->GetKind(vector_slot)); | 3013 vector->GetKind(vector_slot)); |
2994 KeyedLoadICNexus nexus(vector, vector_slot); | 3014 KeyedLoadICNexus nexus(vector, vector_slot); |
2995 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 3015 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
2996 ic.UpdateState(receiver, key); | 3016 ic.UpdateState(receiver, key); |
2997 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); | 3017 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); |
2998 } | 3018 } |
2999 } | 3019 } |
3000 } // namespace internal | 3020 } // namespace internal |
3001 } // namespace v8 | 3021 } // namespace v8 |
OLD | NEW |