| 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 |