 Chromium Code Reviews
 Chromium Code Reviews Issue 2133233002:
  [LoadIC] Handle simple field loads in the dispatcher  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 2133233002:
  [LoadIC] Handle simple field loads in the dispatcher  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| 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 if (!(code->IsSmi() || | 
| 
Igor Sheludko
2016/07/15 10:44:18
It is hard to understand this "if". How about:
DC
 
Jakob Kummerow
2016/07/15 14:16:42
Done.
 | |
| 691 if (!code->is_handler()) return false; | 689 (code->IsCode() && Handle<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 12 matching lines...) Expand all Loading... | |
| 1038 } | 1057 } | 
| 1039 | 1058 | 
| 1040 code = CompileHandler(lookup, value, flag); | 1059 code = CompileHandler(lookup, value, flag); | 
| 1041 DCHECK(code->is_handler()); | 1060 DCHECK(code->is_handler()); | 
| 1042 DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag); | 1061 DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag); | 
| 1043 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); | 1062 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); | 
| 1044 | 1063 | 
| 1045 return code; | 1064 return code; | 
| 1046 } | 1065 } | 
| 1047 | 1066 | 
| 1048 Handle<Code> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) { | 1067 Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) { | 
| 1049 Handle<Object> receiver = lookup->GetReceiver(); | 1068 Handle<Object> receiver = lookup->GetReceiver(); | 
| 1050 if (receiver->IsString() && | 1069 if (receiver->IsString() && | 
| 1051 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { | 1070 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { | 
| 1052 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); | 1071 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); | 
| 1053 return SimpleFieldLoad(index); | 1072 return SimpleFieldLoad(index); | 
| 1054 } | 1073 } | 
| 1055 | 1074 | 
| 1056 if (receiver->IsStringWrapper() && | 1075 if (receiver->IsStringWrapper() && | 
| 1057 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { | 1076 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { | 
| 1058 TRACE_HANDLER_STATS(isolate(), LoadIC_StringLengthStub); | 1077 TRACE_HANDLER_STATS(isolate(), LoadIC_StringLengthStub); | 
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1382 return; | 1401 return; | 
| 1383 } | 1402 } | 
| 1384 | 1403 | 
| 1385 // If the maximum number of receiver maps has been exceeded, use the generic | 1404 // If the maximum number of receiver maps has been exceeded, use the generic | 
| 1386 // version of the IC. | 1405 // version of the IC. | 
| 1387 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1406 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 
| 1388 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 1407 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 
| 1389 return; | 1408 return; | 
| 1390 } | 1409 } | 
| 1391 | 1410 | 
| 1392 CodeHandleList handlers(target_receiver_maps.length()); | 1411 List<Handle<Object>> handlers(target_receiver_maps.length()); | 
| 1393 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_PolymorphicElement); | 1412 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_PolymorphicElement); | 
| 1394 ElementHandlerCompiler compiler(isolate()); | 1413 ElementHandlerCompiler compiler(isolate()); | 
| 1395 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); | 1414 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); | 
| 1396 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers); | 1415 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers); | 
| 1397 } | 1416 } | 
| 1398 | 1417 | 
| 1399 | 1418 | 
| 1400 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 1419 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 
| 1401 Handle<Object> key) { | 1420 Handle<Object> key) { | 
| 1402 if (MigrateDeprecated(object)) { | 1421 if (MigrateDeprecated(object)) { | 
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1599 // the pre monomorphic stub to delay setting the monomorphic state. | 1618 // the pre monomorphic stub to delay setting the monomorphic state. | 
| 1600 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); | 1619 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); | 
| 1601 TRACE_IC("StoreIC", lookup->name()); | 1620 TRACE_IC("StoreIC", lookup->name()); | 
| 1602 return; | 1621 return; | 
| 1603 } | 1622 } | 
| 1604 | 1623 | 
| 1605 bool use_ic = LookupForWrite(lookup, value, store_mode); | 1624 bool use_ic = LookupForWrite(lookup, value, store_mode); | 
| 1606 if (!use_ic) { | 1625 if (!use_ic) { | 
| 1607 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); | 1626 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); | 
| 1608 } | 1627 } | 
| 1609 Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub(); | 1628 Handle<Code> code = | 
| 1629 use_ic ? Handle<Code>::cast(ComputeHandler(lookup, value)) : slow_stub(); | |
| 1610 | 1630 | 
| 1611 PatchCache(lookup->name(), code); | 1631 PatchCache(lookup->name(), code); | 
| 1612 TRACE_IC("StoreIC", lookup->name()); | 1632 TRACE_IC("StoreIC", lookup->name()); | 
| 1613 } | 1633 } | 
| 1614 | 1634 | 
| 1615 | 1635 | 
| 1616 static Handle<Code> PropertyCellStoreHandler( | 1636 static Handle<Code> PropertyCellStoreHandler( | 
| 1617 Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder, | 1637 Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder, | 
| 1618 Handle<Name> name, Handle<PropertyCell> cell, PropertyCellType type) { | 1638 Handle<Name> name, Handle<PropertyCell> cell, PropertyCellType type) { | 
| 1619 auto constant_type = Nothing<PropertyCellConstantType>(); | 1639 auto constant_type = Nothing<PropertyCellConstantType>(); | 
| 1620 if (type == PropertyCellType::kConstantType) { | 1640 if (type == PropertyCellType::kConstantType) { | 
| 1621 constant_type = Just(cell->GetConstantType()); | 1641 constant_type = Just(cell->GetConstantType()); | 
| 1622 } | 1642 } | 
| 1623 StoreGlobalStub stub(isolate, type, constant_type, | 1643 StoreGlobalStub stub(isolate, type, constant_type, | 
| 1624 receiver->IsJSGlobalProxy()); | 1644 receiver->IsJSGlobalProxy()); | 
| 1625 auto code = stub.GetCodeCopyFromTemplate(holder, cell); | 1645 auto code = stub.GetCodeCopyFromTemplate(holder, cell); | 
| 1626 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1646 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 
| 1627 HeapObject::UpdateMapCodeCache(receiver, name, code); | 1647 HeapObject::UpdateMapCodeCache(receiver, name, code); | 
| 1628 return code; | 1648 return code; | 
| 1629 } | 1649 } | 
| 1630 | 1650 | 
| 1631 Handle<Code> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { | 1651 Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { | 
| 1632 DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); | 1652 DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); | 
| 1633 | 1653 | 
| 1634 // This is currently guaranteed by checks in StoreIC::Store. | 1654 // This is currently guaranteed by checks in StoreIC::Store. | 
| 1635 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); | 1655 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); | 
| 1636 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 1656 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 
| 1637 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); | 1657 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); | 
| 1638 | 1658 | 
| 1639 switch (lookup->state()) { | 1659 switch (lookup->state()) { | 
| 1640 case LookupIterator::TRANSITION: { | 1660 case LookupIterator::TRANSITION: { | 
| 1641 auto store_target = lookup->GetStoreTarget(); | 1661 auto store_target = lookup->GetStoreTarget(); | 
| (...skipping 1351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2993 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, | 3013 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, | 
| 2994 vector->GetKind(vector_slot)); | 3014 vector->GetKind(vector_slot)); | 
| 2995 KeyedLoadICNexus nexus(vector, vector_slot); | 3015 KeyedLoadICNexus nexus(vector, vector_slot); | 
| 2996 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 3016 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 
| 2997 ic.UpdateState(receiver, key); | 3017 ic.UpdateState(receiver, key); | 
| 2998 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); | 3018 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); | 
| 2999 } | 3019 } | 
| 3000 } | 3020 } | 
| 3001 } // namespace internal | 3021 } // namespace internal | 
| 3002 } // namespace v8 | 3022 } // namespace v8 | 
| OLD | NEW |