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 |