| 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 case LookupIterator::DATA: | 258 case LookupIterator::DATA: |
| 259 return; | 259 return; |
| 260 } | 260 } |
| 261 } | 261 } |
| 262 } | 262 } |
| 263 | 263 |
| 264 | 264 |
| 265 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, | 265 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, |
| 266 Handle<String> name) { | 266 Handle<String> name) { |
| 267 if (!IsNameCompatibleWithPrototypeFailure(name)) return false; | 267 if (!IsNameCompatibleWithPrototypeFailure(name)) return false; |
| 268 Handle<Map> receiver_map = TypeToMap(*receiver_type(), isolate()); | |
| 269 if (UseVector()) { | 268 if (UseVector()) { |
| 270 maybe_handler_ = nexus()->FindHandlerForMap(receiver_map); | 269 maybe_handler_ = nexus()->FindHandlerForMap(receiver_map()); |
| 271 } else { | 270 } else { |
| 272 maybe_handler_ = target()->FindHandlerForMap(*receiver_map); | 271 maybe_handler_ = target()->FindHandlerForMap(*receiver_map()); |
| 273 } | 272 } |
| 274 | 273 |
| 275 // The current map wasn't handled yet. There's no reason to stay monomorphic, | 274 // The current map wasn't handled yet. There's no reason to stay monomorphic, |
| 276 // *unless* we're moving from a deprecated map to its replacement, or | 275 // *unless* we're moving from a deprecated map to its replacement, or |
| 277 // to a more general elements kind. | 276 // to a more general elements kind. |
| 278 // TODO(verwaest): Check if the current map is actually what the old map | 277 // TODO(verwaest): Check if the current map is actually what the old map |
| 279 // would transition to. | 278 // would transition to. |
| 280 if (maybe_handler_.is_null()) { | 279 if (maybe_handler_.is_null()) { |
| 281 if (!receiver_map->IsJSObjectMap()) return false; | 280 if (!receiver_map()->IsJSObjectMap()) return false; |
| 282 Map* first_map = FirstTargetMap(); | 281 Map* first_map = FirstTargetMap(); |
| 283 if (first_map == NULL) return false; | 282 if (first_map == NULL) return false; |
| 284 Handle<Map> old_map(first_map); | 283 Handle<Map> old_map(first_map); |
| 285 if (old_map->is_deprecated()) return true; | 284 if (old_map->is_deprecated()) return true; |
| 286 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(), | 285 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(), |
| 287 receiver_map->elements_kind())) { | 286 receiver_map()->elements_kind())) { |
| 288 return true; | 287 return true; |
| 289 } | 288 } |
| 290 return false; | 289 return false; |
| 291 } | 290 } |
| 292 | 291 |
| 293 CacheHolderFlag flag; | 292 CacheHolderFlag flag; |
| 294 Handle<Map> ic_holder_map( | 293 Handle<Map> ic_holder_map(GetICCacheHolder(receiver_map(), isolate(), &flag)); |
| 295 GetICCacheHolder(*receiver_type(), isolate(), &flag)); | |
| 296 | 294 |
| 297 DCHECK(flag != kCacheOnReceiver || receiver->IsJSObject()); | 295 DCHECK(flag != kCacheOnReceiver || receiver->IsJSObject()); |
| 298 DCHECK(flag != kCacheOnPrototype || !receiver->IsJSReceiver()); | 296 DCHECK(flag != kCacheOnPrototype || !receiver->IsJSReceiver()); |
| 299 DCHECK(flag != kCacheOnPrototypeReceiverIsDictionary); | 297 DCHECK(flag != kCacheOnPrototypeReceiverIsDictionary); |
| 300 | 298 |
| 301 if (state() == MONOMORPHIC) { | 299 if (state() == MONOMORPHIC) { |
| 302 int index = ic_holder_map->IndexInCodeCache(*name, *target()); | 300 int index = ic_holder_map->IndexInCodeCache(*name, *target()); |
| 303 if (index >= 0) { | 301 if (index >= 0) { |
| 304 ic_holder_map->RemoveFromCodeCache(*name, *target(), index); | 302 ic_holder_map->RemoveFromCodeCache(*name, *target(), index); |
| 305 } | 303 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 325 Name* stub_name = | 323 Name* stub_name = |
| 326 UseVector() ? nexus()->FindFirstName() : target()->FindFirstName(); | 324 UseVector() ? nexus()->FindFirstName() : target()->FindFirstName(); |
| 327 if (*name != stub_name) return false; | 325 if (*name != stub_name) return false; |
| 328 } | 326 } |
| 329 | 327 |
| 330 return true; | 328 return true; |
| 331 } | 329 } |
| 332 | 330 |
| 333 | 331 |
| 334 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { | 332 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { |
| 335 update_receiver_type(receiver); | 333 update_receiver_map(receiver); |
| 336 if (!name->IsString()) return; | 334 if (!name->IsString()) return; |
| 337 if (state() != MONOMORPHIC && state() != POLYMORPHIC) return; | 335 if (state() != MONOMORPHIC && state() != POLYMORPHIC) return; |
| 338 if (receiver->IsUndefined() || receiver->IsNull()) return; | 336 if (receiver->IsUndefined() || receiver->IsNull()) return; |
| 339 | 337 |
| 340 // Remove the target from the code cache if it became invalid | 338 // Remove the target from the code cache if it became invalid |
| 341 // because of changes in the prototype chain to avoid hitting it | 339 // because of changes in the prototype chain to avoid hitting it |
| 342 // again. | 340 // again. |
| 343 if (TryRemoveInvalidPrototypeDependentStub(receiver, | 341 if (TryRemoveInvalidPrototypeDependentStub(receiver, |
| 344 Handle<String>::cast(name))) { | 342 Handle<String>::cast(name))) { |
| 345 MarkPrototypeFailure(name); | 343 MarkPrototypeFailure(name); |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 643 } else { | 641 } else { |
| 644 UNREACHABLE(); | 642 UNREACHABLE(); |
| 645 } | 643 } |
| 646 | 644 |
| 647 vector_set_ = true; | 645 vector_set_ = true; |
| 648 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 646 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), |
| 649 new_state); | 647 new_state); |
| 650 } | 648 } |
| 651 | 649 |
| 652 | 650 |
| 653 void IC::ConfigureVectorState(Handle<Name> name, Handle<HeapType> type, | 651 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, |
| 654 Handle<Code> handler) { | 652 Handle<Code> handler) { |
| 655 DCHECK(UseVector()); | 653 DCHECK(UseVector()); |
| 656 if (kind() == Code::LOAD_IC) { | 654 if (kind() == Code::LOAD_IC) { |
| 657 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 655 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
| 658 nexus->ConfigureMonomorphic(type, handler); | 656 nexus->ConfigureMonomorphic(map, handler); |
| 659 } else { | 657 } else { |
| 660 DCHECK(kind() == Code::KEYED_LOAD_IC); | 658 DCHECK(kind() == Code::KEYED_LOAD_IC); |
| 661 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 659 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 662 nexus->ConfigureMonomorphic(name, type, handler); | 660 nexus->ConfigureMonomorphic(name, map, handler); |
| 663 } | 661 } |
| 664 | 662 |
| 665 vector_set_ = true; | 663 vector_set_ = true; |
| 666 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 664 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), |
| 667 MONOMORPHIC); | 665 MONOMORPHIC); |
| 668 } | 666 } |
| 669 | 667 |
| 670 | 668 |
| 671 void IC::ConfigureVectorState(Handle<Name> name, TypeHandleList* types, | 669 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, |
| 672 CodeHandleList* handlers) { | 670 CodeHandleList* handlers) { |
| 673 DCHECK(UseVector()); | 671 DCHECK(UseVector()); |
| 674 if (kind() == Code::LOAD_IC) { | 672 if (kind() == Code::LOAD_IC) { |
| 675 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 673 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
| 676 nexus->ConfigurePolymorphic(types, handlers); | 674 nexus->ConfigurePolymorphic(maps, handlers); |
| 677 } else { | 675 } else { |
| 678 DCHECK(kind() == Code::KEYED_LOAD_IC); | 676 DCHECK(kind() == Code::KEYED_LOAD_IC); |
| 679 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 677 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 680 nexus->ConfigurePolymorphic(name, types, handlers); | 678 nexus->ConfigurePolymorphic(name, maps, handlers); |
| 681 } | 679 } |
| 682 | 680 |
| 683 vector_set_ = true; | 681 vector_set_ = true; |
| 684 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 682 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), |
| 685 POLYMORPHIC); | 683 POLYMORPHIC); |
| 686 } | 684 } |
| 687 | 685 |
| 688 | 686 |
| 689 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { | 687 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { |
| 690 // If the object is undefined or null it's illegal to try to get any | 688 // If the object is undefined or null it's illegal to try to get any |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 } | 774 } |
| 777 } | 775 } |
| 778 receiver_maps->Add(new_receiver_map); | 776 receiver_maps->Add(new_receiver_map); |
| 779 return true; | 777 return true; |
| 780 } | 778 } |
| 781 | 779 |
| 782 | 780 |
| 783 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) { | 781 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) { |
| 784 if (!code->is_handler()) return false; | 782 if (!code->is_handler()) return false; |
| 785 if (target()->is_keyed_stub() && state() != PROTOTYPE_FAILURE) return false; | 783 if (target()->is_keyed_stub() && state() != PROTOTYPE_FAILURE) return false; |
| 786 Handle<HeapType> type = receiver_type(); | 784 Handle<Map> map = receiver_map(); |
| 787 TypeHandleList types; | 785 MapHandleList maps; |
| 788 CodeHandleList handlers; | 786 CodeHandleList handlers; |
| 789 | 787 |
| 790 TargetTypes(&types); | 788 TargetMaps(&maps); |
| 791 int number_of_types = types.length(); | 789 int number_of_maps = maps.length(); |
| 792 int deprecated_types = 0; | 790 int deprecated_maps = 0; |
| 793 int handler_to_overwrite = -1; | 791 int handler_to_overwrite = -1; |
| 794 | 792 |
| 795 for (int i = 0; i < number_of_types; i++) { | 793 for (int i = 0; i < number_of_maps; i++) { |
| 796 Handle<HeapType> current_type = types.at(i); | 794 Handle<Map> current_map = maps.at(i); |
| 797 if (current_type->IsClass() && | 795 if (current_map->is_deprecated()) { |
| 798 current_type->AsClass()->Map()->is_deprecated()) { | |
| 799 // Filter out deprecated maps to ensure their instances get migrated. | 796 // Filter out deprecated maps to ensure their instances get migrated. |
| 800 ++deprecated_types; | 797 ++deprecated_maps; |
| 801 } else if (type->NowIs(current_type)) { | 798 } else if (map.is_identical_to(current_map)) { |
| 802 // If the receiver type is already in the polymorphic IC, this indicates | 799 // If the receiver type is already in the polymorphic IC, this indicates |
| 803 // there was a prototoype chain failure. In that case, just overwrite the | 800 // there was a prototoype chain failure. In that case, just overwrite the |
| 804 // handler. | 801 // handler. |
| 805 handler_to_overwrite = i; | 802 handler_to_overwrite = i; |
| 806 } else if (handler_to_overwrite == -1 && current_type->IsClass() && | 803 } else if (handler_to_overwrite == -1 && |
| 807 type->IsClass() && | 804 IsTransitionOfMonomorphicTarget(*current_map, *map)) { |
| 808 IsTransitionOfMonomorphicTarget(*current_type->AsClass()->Map(), | |
| 809 *type->AsClass()->Map())) { | |
| 810 handler_to_overwrite = i; | 805 handler_to_overwrite = i; |
| 811 } | 806 } |
| 812 } | 807 } |
| 813 | 808 |
| 814 int number_of_valid_types = | 809 int number_of_valid_maps = |
| 815 number_of_types - deprecated_types - (handler_to_overwrite != -1); | 810 number_of_maps - deprecated_maps - (handler_to_overwrite != -1); |
| 816 | 811 |
| 817 if (number_of_valid_types >= 4) return false; | 812 if (number_of_valid_maps >= 4) return false; |
| 818 if (number_of_types == 0 && state() != MONOMORPHIC && | 813 if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) { |
| 819 state() != POLYMORPHIC) { | |
| 820 return false; | 814 return false; |
| 821 } | 815 } |
| 822 if (UseVector()) { | 816 if (UseVector()) { |
| 823 if (!nexus()->FindHandlers(&handlers, types.length())) return false; | 817 if (!nexus()->FindHandlers(&handlers, maps.length())) return false; |
| 824 } else { | 818 } else { |
| 825 if (!target()->FindHandlers(&handlers, types.length())) return false; | 819 if (!target()->FindHandlers(&handlers, maps.length())) return false; |
| 826 } | 820 } |
| 827 | 821 |
| 828 number_of_valid_types++; | 822 number_of_valid_maps++; |
| 829 if (number_of_valid_types > 1 && target()->is_keyed_stub()) return false; | 823 if (number_of_valid_maps > 1 && target()->is_keyed_stub()) return false; |
| 830 Handle<Code> ic; | 824 Handle<Code> ic; |
| 831 if (number_of_valid_types == 1) { | 825 if (number_of_valid_maps == 1) { |
| 832 if (UseVector()) { | 826 if (UseVector()) { |
| 833 ConfigureVectorState(name, receiver_type(), code); | 827 ConfigureVectorState(name, receiver_map(), code); |
| 834 } else { | 828 } else { |
| 835 ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, type, code, | 829 ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, map, code, |
| 836 extra_ic_state()); | 830 extra_ic_state()); |
| 837 } | 831 } |
| 838 } else { | 832 } else { |
| 839 if (handler_to_overwrite >= 0) { | 833 if (handler_to_overwrite >= 0) { |
| 840 handlers.Set(handler_to_overwrite, code); | 834 handlers.Set(handler_to_overwrite, code); |
| 841 if (!type->NowIs(types.at(handler_to_overwrite))) { | 835 if (!map.is_identical_to(maps.at(handler_to_overwrite))) { |
| 842 types.Set(handler_to_overwrite, type); | 836 maps.Set(handler_to_overwrite, map); |
| 843 } | 837 } |
| 844 } else { | 838 } else { |
| 845 types.Add(type); | 839 maps.Add(map); |
| 846 handlers.Add(code); | 840 handlers.Add(code); |
| 847 } | 841 } |
| 848 | 842 |
| 849 if (UseVector()) { | 843 if (UseVector()) { |
| 850 ConfigureVectorState(name, &types, &handlers); | 844 ConfigureVectorState(name, &maps, &handlers); |
| 851 } else { | 845 } else { |
| 852 ic = PropertyICCompiler::ComputePolymorphic(kind(), &types, &handlers, | 846 ic = PropertyICCompiler::ComputePolymorphic(kind(), &maps, &handlers, |
| 853 number_of_valid_types, name, | 847 number_of_valid_maps, name, |
| 854 extra_ic_state()); | 848 extra_ic_state()); |
| 855 } | 849 } |
| 856 } | 850 } |
| 857 | 851 |
| 858 if (!UseVector()) set_target(*ic); | 852 if (!UseVector()) set_target(*ic); |
| 859 return true; | 853 return true; |
| 860 } | 854 } |
| 861 | 855 |
| 862 | 856 |
| 863 Handle<HeapType> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { | |
| 864 return object->IsJSGlobalObject() | |
| 865 ? HeapType::Constant(Handle<JSGlobalObject>::cast(object), isolate) | |
| 866 : HeapType::NowOf(object, isolate); | |
| 867 } | |
| 868 | |
| 869 | |
| 870 Handle<Map> IC::TypeToMap(HeapType* type, Isolate* isolate) { | |
| 871 if (type->Is(HeapType::Number())) | |
| 872 return isolate->factory()->heap_number_map(); | |
| 873 if (type->Is(HeapType::Boolean())) return isolate->factory()->boolean_map(); | |
| 874 if (type->IsConstant()) { | |
| 875 return handle( | |
| 876 Handle<JSGlobalObject>::cast(type->AsConstant()->Value())->map()); | |
| 877 } | |
| 878 DCHECK(type->IsClass()); | |
| 879 return type->AsClass()->Map(); | |
| 880 } | |
| 881 | |
| 882 | |
| 883 template <class T> | |
| 884 typename T::TypeHandle IC::MapToType(Handle<Map> map, | |
| 885 typename T::Region* region) { | |
| 886 if (map->instance_type() == HEAP_NUMBER_TYPE) { | |
| 887 return T::Number(region); | |
| 888 } else if (map->instance_type() == ODDBALL_TYPE) { | |
| 889 // The only oddballs that can be recorded in ICs are booleans. | |
| 890 return T::Boolean(region); | |
| 891 } else { | |
| 892 return T::Class(map, region); | |
| 893 } | |
| 894 } | |
| 895 | |
| 896 | |
| 897 template Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone); | |
| 898 | |
| 899 | |
| 900 template Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, | |
| 901 Isolate* region); | |
| 902 | |
| 903 | |
| 904 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) { | 857 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) { |
| 905 DCHECK(handler->is_handler()); | 858 DCHECK(handler->is_handler()); |
| 906 if (UseVector()) { | 859 if (UseVector()) { |
| 907 ConfigureVectorState(name, receiver_type(), handler); | 860 ConfigureVectorState(name, receiver_map(), handler); |
| 908 } else { | 861 } else { |
| 909 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( | 862 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( |
| 910 kind(), name, receiver_type(), handler, extra_ic_state()); | 863 kind(), name, receiver_map(), handler, extra_ic_state()); |
| 911 set_target(*ic); | 864 set_target(*ic); |
| 912 } | 865 } |
| 913 } | 866 } |
| 914 | 867 |
| 915 | 868 |
| 916 void IC::CopyICToMegamorphicCache(Handle<Name> name) { | 869 void IC::CopyICToMegamorphicCache(Handle<Name> name) { |
| 917 TypeHandleList types; | 870 MapHandleList maps; |
| 918 CodeHandleList handlers; | 871 CodeHandleList handlers; |
| 919 TargetTypes(&types); | 872 TargetMaps(&maps); |
| 920 if (!target()->FindHandlers(&handlers, types.length())) return; | 873 if (!target()->FindHandlers(&handlers, maps.length())) return; |
| 921 for (int i = 0; i < types.length(); i++) { | 874 for (int i = 0; i < maps.length(); i++) { |
| 922 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); | 875 UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i)); |
| 923 } | 876 } |
| 924 } | 877 } |
| 925 | 878 |
| 926 | 879 |
| 927 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { | 880 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { |
| 928 if (source_map == NULL) return true; | 881 if (source_map == NULL) return true; |
| 929 if (target_map == NULL) return false; | 882 if (target_map == NULL) return false; |
| 930 ElementsKind target_elements_kind = target_map->elements_kind(); | 883 ElementsKind target_elements_kind = target_map->elements_kind(); |
| 931 bool more_general_transition = IsMoreGeneralElementsKindTransition( | 884 bool more_general_transition = IsMoreGeneralElementsKindTransition( |
| 932 source_map->elements_kind(), target_elements_kind); | 885 source_map->elements_kind(), target_elements_kind); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 954 // same key. | 907 // same key. |
| 955 CopyICToMegamorphicCache(name); | 908 CopyICToMegamorphicCache(name); |
| 956 } | 909 } |
| 957 if (UseVector()) { | 910 if (UseVector()) { |
| 958 ConfigureVectorState(MEGAMORPHIC); | 911 ConfigureVectorState(MEGAMORPHIC); |
| 959 } else { | 912 } else { |
| 960 set_target(*megamorphic_stub()); | 913 set_target(*megamorphic_stub()); |
| 961 } | 914 } |
| 962 // Fall through. | 915 // Fall through. |
| 963 case MEGAMORPHIC: | 916 case MEGAMORPHIC: |
| 964 UpdateMegamorphicCache(*receiver_type(), *name, *code); | 917 UpdateMegamorphicCache(*receiver_map(), *name, *code); |
| 965 // Indicate that we've handled this case. | 918 // Indicate that we've handled this case. |
| 966 if (UseVector()) { | 919 if (UseVector()) { |
| 967 vector_set_ = true; | 920 vector_set_ = true; |
| 968 } else { | 921 } else { |
| 969 target_set_ = true; | 922 target_set_ = true; |
| 970 } | 923 } |
| 971 break; | 924 break; |
| 972 case DEBUG_STUB: | 925 case DEBUG_STUB: |
| 973 break; | 926 break; |
| 974 case DEFAULT: | 927 case DEFAULT: |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1067 return; | 1020 return; |
| 1068 } | 1021 } |
| 1069 | 1022 |
| 1070 Handle<Code> code; | 1023 Handle<Code> code; |
| 1071 if (lookup->state() == LookupIterator::JSPROXY || | 1024 if (lookup->state() == LookupIterator::JSPROXY || |
| 1072 lookup->state() == LookupIterator::ACCESS_CHECK) { | 1025 lookup->state() == LookupIterator::ACCESS_CHECK) { |
| 1073 code = slow_stub(); | 1026 code = slow_stub(); |
| 1074 } else if (!lookup->IsFound()) { | 1027 } else if (!lookup->IsFound()) { |
| 1075 if (kind() == Code::LOAD_IC) { | 1028 if (kind() == Code::LOAD_IC) { |
| 1076 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), | 1029 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(), |
| 1077 receiver_type()); | 1030 receiver_map()); |
| 1078 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. | 1031 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case. |
| 1079 if (code.is_null()) code = slow_stub(); | 1032 if (code.is_null()) code = slow_stub(); |
| 1080 } else { | 1033 } else { |
| 1081 code = slow_stub(); | 1034 code = slow_stub(); |
| 1082 } | 1035 } |
| 1083 } else { | 1036 } else { |
| 1084 code = ComputeHandler(lookup); | 1037 code = ComputeHandler(lookup); |
| 1085 } | 1038 } |
| 1086 | 1039 |
| 1087 PatchCache(lookup->name(), code); | 1040 PatchCache(lookup->name(), code); |
| 1088 TRACE_IC("LoadIC", lookup->name()); | 1041 TRACE_IC("LoadIC", lookup->name()); |
| 1089 } | 1042 } |
| 1090 | 1043 |
| 1091 | 1044 |
| 1092 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) { | 1045 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { |
| 1093 Map* map = *TypeToMap(type, isolate()); | |
| 1094 isolate()->stub_cache()->Set(name, map, code); | 1046 isolate()->stub_cache()->Set(name, map, code); |
| 1095 } | 1047 } |
| 1096 | 1048 |
| 1097 | 1049 |
| 1098 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) { | 1050 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) { |
| 1099 bool receiver_is_holder = | 1051 bool receiver_is_holder = |
| 1100 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); | 1052 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); |
| 1101 CacheHolderFlag flag; | 1053 CacheHolderFlag flag; |
| 1102 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( | 1054 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( |
| 1103 *receiver_type(), receiver_is_holder, isolate(), &flag); | 1055 receiver_map(), receiver_is_holder, isolate(), &flag); |
| 1104 | 1056 |
| 1105 Handle<Code> code = PropertyHandlerCompiler::Find( | 1057 Handle<Code> code = PropertyHandlerCompiler::Find( |
| 1106 lookup->name(), stub_holder_map, kind(), flag, | 1058 lookup->name(), stub_holder_map, kind(), flag, |
| 1107 lookup->is_dictionary_holder() ? Code::NORMAL : Code::FAST); | 1059 lookup->is_dictionary_holder() ? Code::NORMAL : Code::FAST); |
| 1108 // Use the cached value if it exists, and if it is different from the | 1060 // Use the cached value if it exists, and if it is different from the |
| 1109 // handler that just missed. | 1061 // handler that just missed. |
| 1110 if (!code.is_null()) { | 1062 if (!code.is_null()) { |
| 1111 if (!maybe_handler_.is_null() && | 1063 if (!maybe_handler_.is_null() && |
| 1112 !maybe_handler_.ToHandleChecked().is_identical_to(code)) { | 1064 !maybe_handler_.ToHandleChecked().is_identical_to(code)) { |
| 1113 return code; | 1065 return code; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1166 Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) && | 1118 Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) && |
| 1167 Handle<JSFunction>::cast(receiver)->should_have_prototype() && | 1119 Handle<JSFunction>::cast(receiver)->should_have_prototype() && |
| 1168 !Handle<JSFunction>::cast(receiver) | 1120 !Handle<JSFunction>::cast(receiver) |
| 1169 ->map() | 1121 ->map() |
| 1170 ->has_non_instance_prototype()) { | 1122 ->has_non_instance_prototype()) { |
| 1171 Handle<Code> stub; | 1123 Handle<Code> stub; |
| 1172 FunctionPrototypeStub function_prototype_stub(isolate()); | 1124 FunctionPrototypeStub function_prototype_stub(isolate()); |
| 1173 return function_prototype_stub.GetCode(); | 1125 return function_prototype_stub.GetCode(); |
| 1174 } | 1126 } |
| 1175 | 1127 |
| 1176 Handle<HeapType> type = receiver_type(); | 1128 Handle<Map> map = receiver_map(); |
| 1177 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 1129 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
| 1178 bool receiver_is_holder = receiver.is_identical_to(holder); | 1130 bool receiver_is_holder = receiver.is_identical_to(holder); |
| 1179 switch (lookup->state()) { | 1131 switch (lookup->state()) { |
| 1180 case LookupIterator::INTERCEPTOR: { | 1132 case LookupIterator::INTERCEPTOR: { |
| 1181 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1133 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1182 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | 1134 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1183 cache_holder); | |
| 1184 // Perform a lookup behind the interceptor. Copy the LookupIterator since | 1135 // Perform a lookup behind the interceptor. Copy the LookupIterator since |
| 1185 // the original iterator will be used to fetch the value. | 1136 // the original iterator will be used to fetch the value. |
| 1186 LookupIterator it = *lookup; | 1137 LookupIterator it = *lookup; |
| 1187 it.Next(); | 1138 it.Next(); |
| 1188 LookupForRead(&it); | 1139 LookupForRead(&it); |
| 1189 return compiler.CompileLoadInterceptor(&it); | 1140 return compiler.CompileLoadInterceptor(&it); |
| 1190 } | 1141 } |
| 1191 | 1142 |
| 1192 case LookupIterator::ACCESSOR: { | 1143 case LookupIterator::ACCESSOR: { |
| 1193 // Use simple field loads for some well-known callback properties. | 1144 // Use simple field loads for some well-known callback properties. |
| 1194 if (receiver_is_holder) { | 1145 if (receiver_is_holder) { |
| 1195 DCHECK(receiver->IsJSObject()); | 1146 DCHECK(receiver->IsJSObject()); |
| 1196 Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver); | 1147 Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver); |
| 1197 int object_offset; | 1148 int object_offset; |
| 1198 if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, lookup->name(), | 1149 if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(), |
| 1199 &object_offset)) { | 1150 &object_offset)) { |
| 1200 FieldIndex index = | 1151 FieldIndex index = |
| 1201 FieldIndex::ForInObjectOffset(object_offset, js_receiver->map()); | 1152 FieldIndex::ForInObjectOffset(object_offset, js_receiver->map()); |
| 1202 return SimpleFieldLoad(index); | 1153 return SimpleFieldLoad(index); |
| 1203 } | 1154 } |
| 1204 } | 1155 } |
| 1205 | 1156 |
| 1206 Handle<Object> accessors = lookup->GetAccessors(); | 1157 Handle<Object> accessors = lookup->GetAccessors(); |
| 1207 if (accessors->IsExecutableAccessorInfo()) { | 1158 if (accessors->IsExecutableAccessorInfo()) { |
| 1208 Handle<ExecutableAccessorInfo> info = | 1159 Handle<ExecutableAccessorInfo> info = |
| 1209 Handle<ExecutableAccessorInfo>::cast(accessors); | 1160 Handle<ExecutableAccessorInfo>::cast(accessors); |
| 1210 if (v8::ToCData<Address>(info->getter()) == 0) break; | 1161 if (v8::ToCData<Address>(info->getter()) == 0) break; |
| 1211 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info, | 1162 if (!ExecutableAccessorInfo::IsCompatibleReceiverMap(isolate(), info, |
| 1212 type)) { | 1163 map)) { |
| 1213 break; | 1164 break; |
| 1214 } | 1165 } |
| 1215 if (!holder->HasFastProperties()) break; | 1166 if (!holder->HasFastProperties()) break; |
| 1216 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | 1167 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1217 cache_holder); | |
| 1218 return compiler.CompileLoadCallback(lookup->name(), info); | 1168 return compiler.CompileLoadCallback(lookup->name(), info); |
| 1219 } | 1169 } |
| 1220 if (accessors->IsAccessorPair()) { | 1170 if (accessors->IsAccessorPair()) { |
| 1221 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), | 1171 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), |
| 1222 isolate()); | 1172 isolate()); |
| 1223 if (!getter->IsJSFunction()) break; | 1173 if (!getter->IsJSFunction()) break; |
| 1224 if (!holder->HasFastProperties()) break; | 1174 if (!holder->HasFastProperties()) break; |
| 1225 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | 1175 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
| 1226 if (!receiver->IsJSObject() && !function->IsBuiltin() && | 1176 if (!receiver->IsJSObject() && !function->IsBuiltin() && |
| 1227 is_sloppy(function->shared()->language_mode())) { | 1177 is_sloppy(function->shared()->language_mode())) { |
| 1228 // Calling sloppy non-builtins with a value as the receiver | 1178 // Calling sloppy non-builtins with a value as the receiver |
| 1229 // requires boxing. | 1179 // requires boxing. |
| 1230 break; | 1180 break; |
| 1231 } | 1181 } |
| 1232 CallOptimization call_optimization(function); | 1182 CallOptimization call_optimization(function); |
| 1233 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | 1183 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1234 cache_holder); | |
| 1235 if (call_optimization.is_simple_api_call() && | 1184 if (call_optimization.is_simple_api_call() && |
| 1236 call_optimization.IsCompatibleReceiver(receiver, holder)) { | 1185 call_optimization.IsCompatibleReceiver(receiver, holder)) { |
| 1237 return compiler.CompileLoadCallback(lookup->name(), call_optimization, | 1186 return compiler.CompileLoadCallback(lookup->name(), call_optimization, |
| 1238 lookup->GetAccessorIndex()); | 1187 lookup->GetAccessorIndex()); |
| 1239 } | 1188 } |
| 1240 int expected_arguments = | 1189 int expected_arguments = |
| 1241 function->shared()->internal_formal_parameter_count(); | 1190 function->shared()->internal_formal_parameter_count(); |
| 1242 return compiler.CompileLoadViaGetter( | 1191 return compiler.CompileLoadViaGetter( |
| 1243 lookup->name(), lookup->GetAccessorIndex(), expected_arguments); | 1192 lookup->name(), lookup->GetAccessorIndex(), expected_arguments); |
| 1244 } | 1193 } |
| 1245 break; | 1194 break; |
| 1246 } | 1195 } |
| 1247 | 1196 |
| 1248 case LookupIterator::DATA: { | 1197 case LookupIterator::DATA: { |
| 1249 if (lookup->is_dictionary_holder()) { | 1198 if (lookup->is_dictionary_holder()) { |
| 1250 if (kind() != Code::LOAD_IC) break; | 1199 if (kind() != Code::LOAD_IC) break; |
| 1251 if (holder->IsGlobalObject()) { | 1200 if (holder->IsGlobalObject()) { |
| 1252 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | 1201 NamedLoadHandlerCompiler compiler(isolate(), map, holder, |
| 1253 cache_holder); | 1202 cache_holder); |
| 1254 Handle<PropertyCell> cell = lookup->GetPropertyCell(); | 1203 Handle<PropertyCell> cell = lookup->GetPropertyCell(); |
| 1255 Handle<Code> code = compiler.CompileLoadGlobal( | 1204 Handle<Code> code = compiler.CompileLoadGlobal( |
| 1256 cell, lookup->name(), lookup->IsConfigurable()); | 1205 cell, lookup->name(), lookup->IsConfigurable()); |
| 1257 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1206 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
| 1258 CacheHolderFlag flag; | 1207 CacheHolderFlag flag; |
| 1259 Handle<Map> stub_holder_map = GetHandlerCacheHolder( | 1208 Handle<Map> stub_holder_map = |
| 1260 *type, receiver_is_holder, isolate(), &flag); | 1209 GetHandlerCacheHolder(map, receiver_is_holder, isolate(), &flag); |
| 1261 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); | 1210 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); |
| 1262 return code; | 1211 return code; |
| 1263 } | 1212 } |
| 1264 // There is only one shared stub for loading normalized | 1213 // There is only one shared stub for loading normalized |
| 1265 // properties. It does not traverse the prototype chain, so the | 1214 // properties. It does not traverse the prototype chain, so the |
| 1266 // property must be found in the object for the stub to be | 1215 // property must be found in the object for the stub to be |
| 1267 // applicable. | 1216 // applicable. |
| 1268 if (!receiver_is_holder) break; | 1217 if (!receiver_is_holder) break; |
| 1269 return isolate()->builtins()->LoadIC_Normal(); | 1218 return isolate()->builtins()->LoadIC_Normal(); |
| 1270 } | 1219 } |
| 1271 | 1220 |
| 1272 // -------------- Fields -------------- | 1221 // -------------- Fields -------------- |
| 1273 if (lookup->property_details().type() == DATA) { | 1222 if (lookup->property_details().type() == DATA) { |
| 1274 FieldIndex field = lookup->GetFieldIndex(); | 1223 FieldIndex field = lookup->GetFieldIndex(); |
| 1275 if (receiver_is_holder) { | 1224 if (receiver_is_holder) { |
| 1276 return SimpleFieldLoad(field); | 1225 return SimpleFieldLoad(field); |
| 1277 } | 1226 } |
| 1278 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | 1227 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1279 cache_holder); | |
| 1280 return compiler.CompileLoadField(lookup->name(), field); | 1228 return compiler.CompileLoadField(lookup->name(), field); |
| 1281 } | 1229 } |
| 1282 | 1230 |
| 1283 // -------------- Constant properties -------------- | 1231 // -------------- Constant properties -------------- |
| 1284 DCHECK(lookup->property_details().type() == DATA_CONSTANT); | 1232 DCHECK(lookup->property_details().type() == DATA_CONSTANT); |
| 1285 if (receiver_is_holder) { | 1233 if (receiver_is_holder) { |
| 1286 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); | 1234 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); |
| 1287 return stub.GetCode(); | 1235 return stub.GetCode(); |
| 1288 } | 1236 } |
| 1289 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | 1237 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1290 cache_holder); | |
| 1291 return compiler.CompileLoadConstant(lookup->name(), | 1238 return compiler.CompileLoadConstant(lookup->name(), |
| 1292 lookup->GetConstantIndex()); | 1239 lookup->GetConstantIndex()); |
| 1293 } | 1240 } |
| 1294 | 1241 |
| 1295 case LookupIterator::ACCESS_CHECK: | 1242 case LookupIterator::ACCESS_CHECK: |
| 1296 case LookupIterator::JSPROXY: | 1243 case LookupIterator::JSPROXY: |
| 1297 case LookupIterator::NOT_FOUND: | 1244 case LookupIterator::NOT_FOUND: |
| 1298 case LookupIterator::TRANSITION: | 1245 case LookupIterator::TRANSITION: |
| 1299 UNREACHABLE(); | 1246 UNREACHABLE(); |
| 1300 } | 1247 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1327 Handle<Code> null_handle; | 1274 Handle<Code> null_handle; |
| 1328 Handle<Map> receiver_map(receiver->map(), isolate()); | 1275 Handle<Map> receiver_map(receiver->map(), isolate()); |
| 1329 MapHandleList target_receiver_maps; | 1276 MapHandleList target_receiver_maps; |
| 1330 TargetMaps(&target_receiver_maps); | 1277 TargetMaps(&target_receiver_maps); |
| 1331 | 1278 |
| 1332 | 1279 |
| 1333 if (target_receiver_maps.length() == 0) { | 1280 if (target_receiver_maps.length() == 0) { |
| 1334 if (FLAG_vector_ics) { | 1281 if (FLAG_vector_ics) { |
| 1335 Handle<Code> handler = | 1282 Handle<Code> handler = |
| 1336 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); | 1283 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); |
| 1337 ConfigureVectorState(Handle<Name>::null(), receiver_type(), handler); | 1284 ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); |
| 1338 return null_handle; | 1285 return null_handle; |
| 1339 } | 1286 } |
| 1340 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); | 1287 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); |
| 1341 } | 1288 } |
| 1342 | 1289 |
| 1343 // The first time a receiver is seen that is a transitioned version of the | 1290 // The first time a receiver is seen that is a transitioned version of the |
| 1344 // previous monomorphic receiver type, assume the new ElementsKind is the | 1291 // previous monomorphic receiver type, assume the new ElementsKind is the |
| 1345 // monomorphic type. This benefits global arrays that only transition | 1292 // monomorphic type. This benefits global arrays that only transition |
| 1346 // once, and all call sites accessing them are faster if they remain | 1293 // once, and all call sites accessing them are faster if they remain |
| 1347 // monomorphic. If this optimistic assumption is not true, the IC will | 1294 // monomorphic. If this optimistic assumption is not true, the IC will |
| 1348 // miss again and it will become polymorphic and support both the | 1295 // miss again and it will become polymorphic and support both the |
| 1349 // untransitioned and transitioned maps. | 1296 // untransitioned and transitioned maps. |
| 1350 if (state() == MONOMORPHIC && !receiver->IsString() && | 1297 if (state() == MONOMORPHIC && !receiver->IsString() && |
| 1351 IsMoreGeneralElementsKindTransition( | 1298 IsMoreGeneralElementsKindTransition( |
| 1352 target_receiver_maps.at(0)->elements_kind(), | 1299 target_receiver_maps.at(0)->elements_kind(), |
| 1353 Handle<JSObject>::cast(receiver)->GetElementsKind())) { | 1300 Handle<JSObject>::cast(receiver)->GetElementsKind())) { |
| 1354 if (FLAG_vector_ics) { | 1301 if (FLAG_vector_ics) { |
| 1355 Handle<Code> handler = | 1302 Handle<Code> handler = |
| 1356 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); | 1303 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); |
| 1357 ConfigureVectorState(Handle<Name>::null(), receiver_type(), handler); | 1304 ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); |
| 1358 return null_handle; | 1305 return null_handle; |
| 1359 } | 1306 } |
| 1360 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); | 1307 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); |
| 1361 } | 1308 } |
| 1362 | 1309 |
| 1363 DCHECK(state() != GENERIC); | 1310 DCHECK(state() != GENERIC); |
| 1364 | 1311 |
| 1365 // Determine the list of receiver maps that this call site has seen, | 1312 // Determine the list of receiver maps that this call site has seen, |
| 1366 // adding the map that was just encountered. | 1313 // adding the map that was just encountered. |
| 1367 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { | 1314 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
| 1368 // If the miss wasn't due to an unseen map, a polymorphic stub | 1315 // If the miss wasn't due to an unseen map, a polymorphic stub |
| 1369 // won't help, use the generic stub. | 1316 // won't help, use the generic stub. |
| 1370 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); | 1317 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); |
| 1371 return megamorphic_stub(); | 1318 return megamorphic_stub(); |
| 1372 } | 1319 } |
| 1373 | 1320 |
| 1374 // If the maximum number of receiver maps has been exceeded, use the generic | 1321 // If the maximum number of receiver maps has been exceeded, use the generic |
| 1375 // version of the IC. | 1322 // version of the IC. |
| 1376 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1323 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
| 1377 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 1324 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); |
| 1378 return megamorphic_stub(); | 1325 return megamorphic_stub(); |
| 1379 } | 1326 } |
| 1380 | 1327 |
| 1381 if (FLAG_vector_ics) { | 1328 if (FLAG_vector_ics) { |
| 1382 CodeHandleList handlers(target_receiver_maps.length()); | 1329 CodeHandleList handlers(target_receiver_maps.length()); |
| 1383 ElementHandlerCompiler compiler(isolate()); | 1330 ElementHandlerCompiler compiler(isolate()); |
| 1384 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); | 1331 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); |
| 1385 TypeHandleList types(target_receiver_maps.length()); | 1332 ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, |
| 1386 for (int i = 0; i < target_receiver_maps.length(); i++) { | 1333 &handlers); |
| 1387 types.Add(HeapType::Class(target_receiver_maps.at(i), isolate())); | |
| 1388 } | |
| 1389 ConfigureVectorState(Handle<Name>::null(), &types, &handlers); | |
| 1390 return null_handle; | 1334 return null_handle; |
| 1391 } | 1335 } |
| 1392 | 1336 |
| 1393 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); | 1337 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); |
| 1394 } | 1338 } |
| 1395 | 1339 |
| 1396 | 1340 |
| 1397 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 1341 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, |
| 1398 Handle<Object> key) { | 1342 Handle<Object> key) { |
| 1399 if (MigrateDeprecated(object)) { | 1343 if (MigrateDeprecated(object)) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1485 break; | 1429 break; |
| 1486 case LookupIterator::ACCESSOR: | 1430 case LookupIterator::ACCESSOR: |
| 1487 return !it->IsReadOnly(); | 1431 return !it->IsReadOnly(); |
| 1488 case LookupIterator::DATA: { | 1432 case LookupIterator::DATA: { |
| 1489 if (it->IsReadOnly()) return false; | 1433 if (it->IsReadOnly()) return false; |
| 1490 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 1434 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
| 1491 if (receiver.is_identical_to(holder)) { | 1435 if (receiver.is_identical_to(holder)) { |
| 1492 it->PrepareForDataProperty(value); | 1436 it->PrepareForDataProperty(value); |
| 1493 // The previous receiver map might just have been deprecated, | 1437 // The previous receiver map might just have been deprecated, |
| 1494 // so reload it. | 1438 // so reload it. |
| 1495 update_receiver_type(receiver); | 1439 update_receiver_map(receiver); |
| 1496 return true; | 1440 return true; |
| 1497 } | 1441 } |
| 1498 | 1442 |
| 1499 // Receiver != holder. | 1443 // Receiver != holder. |
| 1500 PrototypeIterator iter(it->isolate(), receiver); | 1444 PrototypeIterator iter(it->isolate(), receiver); |
| 1501 if (receiver->IsJSGlobalProxy()) { | 1445 if (receiver->IsJSGlobalProxy()) { |
| 1502 return it->GetHolder<Object>().is_identical_to( | 1446 return it->GetHolder<Object>().is_identical_to( |
| 1503 PrototypeIterator::GetCurrent(iter)); | 1447 PrototypeIterator::GetCurrent(iter)); |
| 1504 } | 1448 } |
| 1505 | 1449 |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1710 lookup->name(), cell, value); | 1654 lookup->name(), cell, value); |
| 1711 } | 1655 } |
| 1712 Handle<Map> transition = lookup->transition_map(); | 1656 Handle<Map> transition = lookup->transition_map(); |
| 1713 // Currently not handled by CompileStoreTransition. | 1657 // Currently not handled by CompileStoreTransition. |
| 1714 if (!holder->HasFastProperties()) { | 1658 if (!holder->HasFastProperties()) { |
| 1715 TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow"); | 1659 TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow"); |
| 1716 break; | 1660 break; |
| 1717 } | 1661 } |
| 1718 | 1662 |
| 1719 DCHECK(lookup->IsCacheableTransition()); | 1663 DCHECK(lookup->IsCacheableTransition()); |
| 1720 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1664 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
| 1721 return compiler.CompileStoreTransition(transition, lookup->name()); | 1665 return compiler.CompileStoreTransition(transition, lookup->name()); |
| 1722 } | 1666 } |
| 1723 | 1667 |
| 1724 case LookupIterator::INTERCEPTOR: { | 1668 case LookupIterator::INTERCEPTOR: { |
| 1725 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined()); | 1669 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined()); |
| 1726 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1670 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
| 1727 return compiler.CompileStoreInterceptor(lookup->name()); | 1671 return compiler.CompileStoreInterceptor(lookup->name()); |
| 1728 } | 1672 } |
| 1729 | 1673 |
| 1730 case LookupIterator::ACCESSOR: { | 1674 case LookupIterator::ACCESSOR: { |
| 1731 if (!holder->HasFastProperties()) { | 1675 if (!holder->HasFastProperties()) { |
| 1732 TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map"); | 1676 TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map"); |
| 1733 break; | 1677 break; |
| 1734 } | 1678 } |
| 1735 Handle<Object> accessors = lookup->GetAccessors(); | 1679 Handle<Object> accessors = lookup->GetAccessors(); |
| 1736 if (accessors->IsExecutableAccessorInfo()) { | 1680 if (accessors->IsExecutableAccessorInfo()) { |
| 1737 Handle<ExecutableAccessorInfo> info = | 1681 Handle<ExecutableAccessorInfo> info = |
| 1738 Handle<ExecutableAccessorInfo>::cast(accessors); | 1682 Handle<ExecutableAccessorInfo>::cast(accessors); |
| 1739 if (v8::ToCData<Address>(info->setter()) == 0) { | 1683 if (v8::ToCData<Address>(info->setter()) == 0) { |
| 1740 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0"); | 1684 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0"); |
| 1741 break; | 1685 break; |
| 1742 } | 1686 } |
| 1743 if (!ExecutableAccessorInfo::IsCompatibleReceiverType( | 1687 if (!ExecutableAccessorInfo::IsCompatibleReceiverMap(isolate(), info, |
| 1744 isolate(), info, receiver_type())) { | 1688 receiver_map())) { |
| 1745 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type"); | 1689 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type"); |
| 1746 break; | 1690 break; |
| 1747 } | 1691 } |
| 1748 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1692 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
| 1749 return compiler.CompileStoreCallback(receiver, lookup->name(), | 1693 return compiler.CompileStoreCallback(receiver, lookup->name(), |
| 1750 lookup->GetAccessorIndex()); | 1694 lookup->GetAccessorIndex()); |
| 1751 } else if (accessors->IsAccessorPair()) { | 1695 } else if (accessors->IsAccessorPair()) { |
| 1752 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), | 1696 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), |
| 1753 isolate()); | 1697 isolate()); |
| 1754 if (!setter->IsJSFunction()) { | 1698 if (!setter->IsJSFunction()) { |
| 1755 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function"); | 1699 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function"); |
| 1756 break; | 1700 break; |
| 1757 } | 1701 } |
| 1758 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); | 1702 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); |
| 1759 CallOptimization call_optimization(function); | 1703 CallOptimization call_optimization(function); |
| 1760 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1704 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
| 1761 if (call_optimization.is_simple_api_call() && | 1705 if (call_optimization.is_simple_api_call() && |
| 1762 call_optimization.IsCompatibleReceiver(receiver, holder)) { | 1706 call_optimization.IsCompatibleReceiver(receiver, holder)) { |
| 1763 return compiler.CompileStoreCallback(receiver, lookup->name(), | 1707 return compiler.CompileStoreCallback(receiver, lookup->name(), |
| 1764 call_optimization, | 1708 call_optimization, |
| 1765 lookup->GetAccessorIndex()); | 1709 lookup->GetAccessorIndex()); |
| 1766 } | 1710 } |
| 1767 int expected_arguments = | 1711 int expected_arguments = |
| 1768 function->shared()->internal_formal_parameter_count(); | 1712 function->shared()->internal_formal_parameter_count(); |
| 1769 return compiler.CompileStoreViaSetter(receiver, lookup->name(), | 1713 return compiler.CompileStoreViaSetter(receiver, lookup->name(), |
| 1770 lookup->GetAccessorIndex(), | 1714 lookup->GetAccessorIndex(), |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1794 // Only use a generic stub if no types need to be tracked. | 1738 // Only use a generic stub if no types need to be tracked. |
| 1795 Handle<HeapType> field_type = lookup->GetFieldType(); | 1739 Handle<HeapType> field_type = lookup->GetFieldType(); |
| 1796 HeapType::Iterator<Map> it = field_type->Classes(); | 1740 HeapType::Iterator<Map> it = field_type->Classes(); |
| 1797 use_stub = it.Done(); | 1741 use_stub = it.Done(); |
| 1798 } | 1742 } |
| 1799 if (use_stub) { | 1743 if (use_stub) { |
| 1800 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), | 1744 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), |
| 1801 lookup->representation()); | 1745 lookup->representation()); |
| 1802 return stub.GetCode(); | 1746 return stub.GetCode(); |
| 1803 } | 1747 } |
| 1804 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1748 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
| 1805 return compiler.CompileStoreField(lookup); | 1749 return compiler.CompileStoreField(lookup); |
| 1806 } | 1750 } |
| 1807 | 1751 |
| 1808 // -------------- Constant properties -------------- | 1752 // -------------- Constant properties -------------- |
| 1809 DCHECK(lookup->property_details().type() == DATA_CONSTANT); | 1753 DCHECK(lookup->property_details().type() == DATA_CONSTANT); |
| 1810 TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property"); | 1754 TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property"); |
| 1811 break; | 1755 break; |
| 1812 } | 1756 } |
| 1813 | 1757 |
| 1814 case LookupIterator::ACCESS_CHECK: | 1758 case LookupIterator::ACCESS_CHECK: |
| (...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3014 static const Address IC_utilities[] = { | 2958 static const Address IC_utilities[] = { |
| 3015 #define ADDR(name) FUNCTION_ADDR(name), | 2959 #define ADDR(name) FUNCTION_ADDR(name), |
| 3016 IC_UTIL_LIST(ADDR) NULL | 2960 IC_UTIL_LIST(ADDR) NULL |
| 3017 #undef ADDR | 2961 #undef ADDR |
| 3018 }; | 2962 }; |
| 3019 | 2963 |
| 3020 | 2964 |
| 3021 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 2965 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
| 3022 } | 2966 } |
| 3023 } // namespace v8::internal | 2967 } // namespace v8::internal |
| OLD | NEW |