OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/ic/ic.h" | 5 #include "src/ic/ic.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/api-arguments.h" | 9 #include "src/api-arguments.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
624 FixedArray::get(*ScriptContextTable::GetContext( | 624 FixedArray::get(*ScriptContextTable::GetContext( |
625 script_contexts, lookup_result.context_index), | 625 script_contexts, lookup_result.context_index), |
626 lookup_result.slot_index, isolate()); | 626 lookup_result.slot_index, isolate()); |
627 if (*result == *isolate()->factory()->the_hole_value()) { | 627 if (*result == *isolate()->factory()->the_hole_value()) { |
628 // Do not install stubs and stay pre-monomorphic for | 628 // Do not install stubs and stay pre-monomorphic for |
629 // uninitialized accesses. | 629 // uninitialized accesses. |
630 return ReferenceError(name); | 630 return ReferenceError(name); |
631 } | 631 } |
632 | 632 |
633 if (use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) { | 633 if (use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) { |
| 634 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadScriptContextFieldStub); |
634 LoadScriptContextFieldStub stub(isolate(), &lookup_result); | 635 LoadScriptContextFieldStub stub(isolate(), &lookup_result); |
635 PatchCache(name, stub.GetCode()); | 636 PatchCache(name, stub.GetCode()); |
636 } | 637 } |
637 return result; | 638 return result; |
638 } | 639 } |
639 } | 640 } |
640 | 641 |
641 // Named lookup in the object. | 642 // Named lookup in the object. |
642 LookupIterator it(object, name); | 643 LookupIterator it(object, name); |
643 LookupForRead(&it); | 644 LookupForRead(&it); |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate, | 829 Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate, |
829 ExtraICState extra_state) { | 830 ExtraICState extra_state) { |
830 LanguageMode mode = StoreICState::GetLanguageMode(extra_state); | 831 LanguageMode mode = StoreICState::GetLanguageMode(extra_state); |
831 return is_strict(mode) | 832 return is_strict(mode) |
832 ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict() | 833 ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict() |
833 : isolate->builtins()->KeyedStoreIC_Megamorphic(); | 834 : isolate->builtins()->KeyedStoreIC_Megamorphic(); |
834 } | 835 } |
835 | 836 |
836 | 837 |
837 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { | 838 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { |
| 839 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub); |
838 LoadFieldStub stub(isolate(), index); | 840 LoadFieldStub stub(isolate(), index); |
839 return stub.GetCode(); | 841 return stub.GetCode(); |
840 } | 842 } |
841 | 843 |
842 | 844 |
843 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { | 845 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) { |
844 DCHECK(lookup->state() == LookupIterator::ACCESSOR); | 846 DCHECK(lookup->state() == LookupIterator::ACCESSOR); |
845 Isolate* isolate = lookup->isolate(); | 847 Isolate* isolate = lookup->isolate(); |
846 Handle<Object> accessors = lookup->GetAccessors(); | 848 Handle<Object> accessors = lookup->GetAccessors(); |
847 if (accessors->IsAccessorInfo()) { | 849 if (accessors->IsAccessorInfo()) { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
939 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( | 941 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( |
940 receiver_map(), receiver_is_holder, isolate(), &flag); | 942 receiver_map(), receiver_is_holder, isolate(), &flag); |
941 | 943 |
942 Handle<Code> code = PropertyHandlerCompiler::Find( | 944 Handle<Code> code = PropertyHandlerCompiler::Find( |
943 lookup->name(), stub_holder_map, kind(), flag); | 945 lookup->name(), stub_holder_map, kind(), flag); |
944 // Use the cached value if it exists, and if it is different from the | 946 // Use the cached value if it exists, and if it is different from the |
945 // handler that just missed. | 947 // handler that just missed. |
946 if (!code.is_null()) { | 948 if (!code.is_null()) { |
947 Handle<Code> handler; | 949 Handle<Code> handler; |
948 if (maybe_handler_.ToHandle(&handler)) { | 950 if (maybe_handler_.ToHandle(&handler)) { |
949 if (!handler.is_identical_to(code)) return code; | 951 if (!handler.is_identical_to(code)) { |
| 952 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); |
| 953 return code; |
| 954 } |
950 } else { | 955 } else { |
951 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. | 956 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. |
952 // In MEGAMORPHIC case, check if the handler in the megamorphic stub | 957 // In MEGAMORPHIC case, check if the handler in the megamorphic stub |
953 // cache (which just missed) is different from the cached handler. | 958 // cache (which just missed) is different from the cached handler. |
954 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) { | 959 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) { |
955 Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map(); | 960 Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map(); |
956 Code* megamorphic_cached_code = | 961 Code* megamorphic_cached_code = |
957 isolate()->stub_cache()->Get(*lookup->name(), map, code->flags()); | 962 isolate()->stub_cache()->Get(*lookup->name(), map, code->flags()); |
958 if (megamorphic_cached_code != *code) return code; | 963 if (megamorphic_cached_code != *code) { |
| 964 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); |
| 965 return code; |
| 966 } |
959 } else { | 967 } else { |
| 968 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); |
960 return code; | 969 return code; |
961 } | 970 } |
962 } | 971 } |
963 } | 972 } |
964 | 973 |
965 code = CompileHandler(lookup, value, flag); | 974 code = CompileHandler(lookup, value, flag); |
966 DCHECK(code->is_handler()); | 975 DCHECK(code->is_handler()); |
967 | 976 |
968 // TODO(mvstanton): we'd only like to cache code on the map when it's custom | 977 // TODO(mvstanton): we'd only like to cache code on the map when it's custom |
969 // code compiled for this map, otherwise it's already cached in the global | 978 // code compiled for this map, otherwise it's already cached in the global |
(...skipping 15 matching lines...) Expand all Loading... |
985 CacheHolderFlag cache_holder) { | 994 CacheHolderFlag cache_holder) { |
986 Handle<Object> receiver = lookup->GetReceiver(); | 995 Handle<Object> receiver = lookup->GetReceiver(); |
987 if (receiver->IsString() && | 996 if (receiver->IsString() && |
988 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { | 997 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { |
989 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); | 998 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); |
990 return SimpleFieldLoad(index); | 999 return SimpleFieldLoad(index); |
991 } | 1000 } |
992 | 1001 |
993 if (receiver->IsStringWrapper() && | 1002 if (receiver->IsStringWrapper() && |
994 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { | 1003 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { |
| 1004 TRACE_HANDLER_STATS(isolate(), LoadIC_StringLengthStub); |
995 StringLengthStub string_length_stub(isolate()); | 1005 StringLengthStub string_length_stub(isolate()); |
996 return string_length_stub.GetCode(); | 1006 return string_length_stub.GetCode(); |
997 } | 1007 } |
998 | 1008 |
999 // Use specialized code for getting prototype of functions. | 1009 // Use specialized code for getting prototype of functions. |
1000 if (receiver->IsJSFunction() && | 1010 if (receiver->IsJSFunction() && |
1001 Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) && | 1011 Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) && |
1002 receiver->IsConstructor() && | 1012 receiver->IsConstructor() && |
1003 !Handle<JSFunction>::cast(receiver) | 1013 !Handle<JSFunction>::cast(receiver) |
1004 ->map() | 1014 ->map() |
1005 ->has_non_instance_prototype()) { | 1015 ->has_non_instance_prototype()) { |
1006 Handle<Code> stub; | 1016 Handle<Code> stub; |
| 1017 TRACE_HANDLER_STATS(isolate(), LoadIC_FunctionPrototypeStub); |
1007 FunctionPrototypeStub function_prototype_stub(isolate()); | 1018 FunctionPrototypeStub function_prototype_stub(isolate()); |
1008 return function_prototype_stub.GetCode(); | 1019 return function_prototype_stub.GetCode(); |
1009 } | 1020 } |
1010 | 1021 |
1011 Handle<Map> map = receiver_map(); | 1022 Handle<Map> map = receiver_map(); |
1012 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 1023 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
1013 bool receiver_is_holder = receiver.is_identical_to(holder); | 1024 bool receiver_is_holder = receiver.is_identical_to(holder); |
1014 switch (lookup->state()) { | 1025 switch (lookup->state()) { |
1015 case LookupIterator::INTERCEPTOR: { | 1026 case LookupIterator::INTERCEPTOR: { |
1016 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1027 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1028 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptor); |
1017 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | 1029 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
1018 // Perform a lookup behind the interceptor. Copy the LookupIterator since | 1030 // Perform a lookup behind the interceptor. Copy the LookupIterator since |
1019 // the original iterator will be used to fetch the value. | 1031 // the original iterator will be used to fetch the value. |
1020 LookupIterator it = *lookup; | 1032 LookupIterator it = *lookup; |
1021 it.Next(); | 1033 it.Next(); |
1022 LookupForRead(&it); | 1034 LookupForRead(&it); |
1023 return compiler.CompileLoadInterceptor(&it); | 1035 return compiler.CompileLoadInterceptor(&it); |
1024 } | 1036 } |
1025 | 1037 |
1026 case LookupIterator::ACCESSOR: { | 1038 case LookupIterator::ACCESSOR: { |
1027 // Use simple field loads for some well-known callback properties. | 1039 // Use simple field loads for some well-known callback properties. |
1028 // The method will only return true for absolute truths based on the | 1040 // The method will only return true for absolute truths based on the |
1029 // receiver maps. | 1041 // receiver maps. |
1030 int object_offset; | 1042 int object_offset; |
1031 if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(), | 1043 if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(), |
1032 &object_offset)) { | 1044 &object_offset)) { |
1033 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); | 1045 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); |
1034 return SimpleFieldLoad(index); | 1046 return SimpleFieldLoad(index); |
1035 } | 1047 } |
1036 if (Accessors::IsJSArrayBufferViewFieldAccessor(map, lookup->name(), | 1048 if (Accessors::IsJSArrayBufferViewFieldAccessor(map, lookup->name(), |
1037 &object_offset)) { | 1049 &object_offset)) { |
| 1050 TRACE_HANDLER_STATS(isolate(), LoadIC_ArrayBufferViewLoadFieldStub); |
1038 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); | 1051 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); |
1039 ArrayBufferViewLoadFieldStub stub(isolate(), index); | 1052 ArrayBufferViewLoadFieldStub stub(isolate(), index); |
1040 return stub.GetCode(); | 1053 return stub.GetCode(); |
1041 } | 1054 } |
1042 | 1055 |
1043 if (IsCompatibleReceiver(lookup, map)) { | 1056 if (IsCompatibleReceiver(lookup, map)) { |
1044 Handle<Object> accessors = lookup->GetAccessors(); | 1057 Handle<Object> accessors = lookup->GetAccessors(); |
1045 if (accessors->IsAccessorPair()) { | 1058 if (accessors->IsAccessorPair()) { |
1046 if (!holder->HasFastProperties()) break; | 1059 if (!holder->HasFastProperties()) break; |
1047 // When debugging we need to go the slow path to flood the accessor. | 1060 // When debugging we need to go the slow path to flood the accessor. |
1048 if (GetSharedFunctionInfo()->HasDebugInfo()) break; | 1061 if (GetSharedFunctionInfo()->HasDebugInfo()) break; |
1049 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), | 1062 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), |
1050 isolate()); | 1063 isolate()); |
1051 CallOptimization call_optimization(getter); | 1064 CallOptimization call_optimization(getter); |
1052 NamedLoadHandlerCompiler compiler(isolate(), map, holder, | 1065 NamedLoadHandlerCompiler compiler(isolate(), map, holder, |
1053 cache_holder); | 1066 cache_holder); |
1054 if (call_optimization.is_simple_api_call()) { | 1067 if (call_optimization.is_simple_api_call()) { |
| 1068 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback); |
1055 int index = lookup->GetAccessorIndex(); | 1069 int index = lookup->GetAccessorIndex(); |
1056 return compiler.CompileLoadCallback(lookup->name(), | 1070 return compiler.CompileLoadCallback(lookup->name(), |
1057 call_optimization, index); | 1071 call_optimization, index); |
1058 } | 1072 } |
| 1073 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadViaGetter); |
1059 int expected_arguments = Handle<JSFunction>::cast(getter) | 1074 int expected_arguments = Handle<JSFunction>::cast(getter) |
1060 ->shared() | 1075 ->shared() |
1061 ->internal_formal_parameter_count(); | 1076 ->internal_formal_parameter_count(); |
1062 return compiler.CompileLoadViaGetter( | 1077 return compiler.CompileLoadViaGetter( |
1063 lookup->name(), lookup->GetAccessorIndex(), expected_arguments); | 1078 lookup->name(), lookup->GetAccessorIndex(), expected_arguments); |
1064 } else if (accessors->IsAccessorInfo()) { | 1079 } else if (accessors->IsAccessorInfo()) { |
1065 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); | 1080 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); |
1066 if (v8::ToCData<Address>(info->getter()) == nullptr) break; | 1081 if (v8::ToCData<Address>(info->getter()) == nullptr) break; |
1067 if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map)) { | 1082 if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map)) { |
1068 // This case should be already handled in LoadIC::UpdateCaches. | 1083 // This case should be already handled in LoadIC::UpdateCaches. |
1069 UNREACHABLE(); | 1084 UNREACHABLE(); |
1070 break; | 1085 break; |
1071 } | 1086 } |
1072 if (!holder->HasFastProperties()) break; | 1087 if (!holder->HasFastProperties()) break; |
1073 if (receiver_is_holder) { | 1088 if (receiver_is_holder) { |
| 1089 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterStub); |
1074 int index = lookup->GetAccessorIndex(); | 1090 int index = lookup->GetAccessorIndex(); |
1075 LoadApiGetterStub stub(isolate(), true, index); | 1091 LoadApiGetterStub stub(isolate(), true, index); |
1076 return stub.GetCode(); | 1092 return stub.GetCode(); |
1077 } | 1093 } |
1078 if (info->is_sloppy() && !receiver->IsJSReceiver()) break; | 1094 if (info->is_sloppy() && !receiver->IsJSReceiver()) break; |
| 1095 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback); |
1079 NamedLoadHandlerCompiler compiler(isolate(), map, holder, | 1096 NamedLoadHandlerCompiler compiler(isolate(), map, holder, |
1080 cache_holder); | 1097 cache_holder); |
1081 return compiler.CompileLoadCallback(lookup->name(), info); | 1098 return compiler.CompileLoadCallback(lookup->name(), info); |
1082 } | 1099 } |
1083 } | 1100 } |
1084 break; | 1101 break; |
1085 } | 1102 } |
1086 | 1103 |
1087 case LookupIterator::DATA: { | 1104 case LookupIterator::DATA: { |
1088 if (lookup->is_dictionary_holder()) { | 1105 if (lookup->is_dictionary_holder()) { |
1089 if (kind() != Code::LOAD_IC) break; | 1106 if (kind() != Code::LOAD_IC) break; |
1090 if (holder->IsJSGlobalObject()) { | 1107 if (holder->IsJSGlobalObject()) { |
| 1108 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal); |
1091 NamedLoadHandlerCompiler compiler(isolate(), map, holder, | 1109 NamedLoadHandlerCompiler compiler(isolate(), map, holder, |
1092 cache_holder); | 1110 cache_holder); |
1093 Handle<PropertyCell> cell = lookup->GetPropertyCell(); | 1111 Handle<PropertyCell> cell = lookup->GetPropertyCell(); |
1094 Handle<Code> code = compiler.CompileLoadGlobal( | 1112 Handle<Code> code = compiler.CompileLoadGlobal( |
1095 cell, lookup->name(), lookup->IsConfigurable()); | 1113 cell, lookup->name(), lookup->IsConfigurable()); |
1096 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1114 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
1097 CacheHolderFlag flag; | 1115 CacheHolderFlag flag; |
1098 Handle<Map> stub_holder_map = | 1116 Handle<Map> stub_holder_map = |
1099 GetHandlerCacheHolder(map, receiver_is_holder, isolate(), &flag); | 1117 GetHandlerCacheHolder(map, receiver_is_holder, isolate(), &flag); |
1100 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); | 1118 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); |
1101 return code; | 1119 return code; |
1102 } | 1120 } |
1103 // There is only one shared stub for loading normalized | 1121 // There is only one shared stub for loading normalized |
1104 // properties. It does not traverse the prototype chain, so the | 1122 // properties. It does not traverse the prototype chain, so the |
1105 // property must be found in the object for the stub to be | 1123 // property must be found in the object for the stub to be |
1106 // applicable. | 1124 // applicable. |
1107 if (!receiver_is_holder) break; | 1125 if (!receiver_is_holder) break; |
| 1126 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal); |
1108 return isolate()->builtins()->LoadIC_Normal(); | 1127 return isolate()->builtins()->LoadIC_Normal(); |
1109 } | 1128 } |
1110 | 1129 |
1111 // -------------- Fields -------------- | 1130 // -------------- Fields -------------- |
1112 if (lookup->property_details().type() == DATA) { | 1131 if (lookup->property_details().type() == DATA) { |
1113 FieldIndex field = lookup->GetFieldIndex(); | 1132 FieldIndex field = lookup->GetFieldIndex(); |
1114 if (receiver_is_holder) { | 1133 if (receiver_is_holder) { |
1115 return SimpleFieldLoad(field); | 1134 return SimpleFieldLoad(field); |
1116 } | 1135 } |
| 1136 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadField); |
1117 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | 1137 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
1118 return compiler.CompileLoadField(lookup->name(), field); | 1138 return compiler.CompileLoadField(lookup->name(), field); |
1119 } | 1139 } |
1120 | 1140 |
1121 // -------------- Constant properties -------------- | 1141 // -------------- Constant properties -------------- |
1122 DCHECK(lookup->property_details().type() == DATA_CONSTANT); | 1142 DCHECK(lookup->property_details().type() == DATA_CONSTANT); |
1123 if (receiver_is_holder) { | 1143 if (receiver_is_holder) { |
| 1144 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub); |
1124 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); | 1145 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); |
1125 return stub.GetCode(); | 1146 return stub.GetCode(); |
1126 } | 1147 } |
| 1148 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstant); |
1127 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | 1149 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
1128 return compiler.CompileLoadConstant(lookup->name(), | 1150 return compiler.CompileLoadConstant(lookup->name(), |
1129 lookup->GetConstantIndex()); | 1151 lookup->GetConstantIndex()); |
1130 } | 1152 } |
1131 | 1153 |
1132 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 1154 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
1133 return slow_stub(); | 1155 break; |
1134 case LookupIterator::ACCESS_CHECK: | 1156 case LookupIterator::ACCESS_CHECK: |
1135 case LookupIterator::JSPROXY: | 1157 case LookupIterator::JSPROXY: |
1136 case LookupIterator::NOT_FOUND: | 1158 case LookupIterator::NOT_FOUND: |
1137 case LookupIterator::TRANSITION: | 1159 case LookupIterator::TRANSITION: |
1138 UNREACHABLE(); | 1160 UNREACHABLE(); |
1139 } | 1161 } |
1140 | 1162 |
| 1163 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
1141 return slow_stub(); | 1164 return slow_stub(); |
1142 } | 1165 } |
1143 | 1166 |
1144 | 1167 |
1145 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { | 1168 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { |
1146 // This helper implements a few common fast cases for converting | 1169 // This helper implements a few common fast cases for converting |
1147 // non-smi keys of keyed loads/stores to a smi or a string. | 1170 // non-smi keys of keyed loads/stores to a smi or a string. |
1148 if (key->IsHeapNumber()) { | 1171 if (key->IsHeapNumber()) { |
1149 double value = Handle<HeapNumber>::cast(key)->value(); | 1172 double value = Handle<HeapNumber>::cast(key)->value(); |
1150 if (std::isnan(value)) { | 1173 if (std::isnan(value)) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1217 } | 1240 } |
1218 | 1241 |
1219 // If the maximum number of receiver maps has been exceeded, use the generic | 1242 // If the maximum number of receiver maps has been exceeded, use the generic |
1220 // version of the IC. | 1243 // version of the IC. |
1221 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1244 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
1222 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 1245 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); |
1223 return; | 1246 return; |
1224 } | 1247 } |
1225 | 1248 |
1226 CodeHandleList handlers(target_receiver_maps.length()); | 1249 CodeHandleList handlers(target_receiver_maps.length()); |
| 1250 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_PolymorphicElement); |
1227 ElementHandlerCompiler compiler(isolate()); | 1251 ElementHandlerCompiler compiler(isolate()); |
1228 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); | 1252 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); |
1229 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers); | 1253 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers); |
1230 } | 1254 } |
1231 | 1255 |
1232 | 1256 |
1233 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 1257 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, |
1234 Handle<Object> key) { | 1258 Handle<Object> key) { |
1235 if (MigrateDeprecated(object)) { | 1259 if (MigrateDeprecated(object)) { |
1236 Handle<Object> result; | 1260 Handle<Object> result; |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1382 FixedArray::get(*script_context, lookup_result.slot_index, isolate()); | 1406 FixedArray::get(*script_context, lookup_result.slot_index, isolate()); |
1383 | 1407 |
1384 if (*previous_value == *isolate()->factory()->the_hole_value()) { | 1408 if (*previous_value == *isolate()->factory()->the_hole_value()) { |
1385 // Do not install stubs and stay pre-monomorphic for | 1409 // Do not install stubs and stay pre-monomorphic for |
1386 // uninitialized accesses. | 1410 // uninitialized accesses. |
1387 return ReferenceError(name); | 1411 return ReferenceError(name); |
1388 } | 1412 } |
1389 | 1413 |
1390 if (FLAG_use_ic && | 1414 if (FLAG_use_ic && |
1391 StoreScriptContextFieldStub::Accepted(&lookup_result)) { | 1415 StoreScriptContextFieldStub::Accepted(&lookup_result)) { |
| 1416 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreScriptContextFieldStub); |
1392 StoreScriptContextFieldStub stub(isolate(), &lookup_result); | 1417 StoreScriptContextFieldStub stub(isolate(), &lookup_result); |
1393 PatchCache(name, stub.GetCode()); | 1418 PatchCache(name, stub.GetCode()); |
1394 } | 1419 } |
1395 | 1420 |
1396 script_context->set(lookup_result.slot_index, *value); | 1421 script_context->set(lookup_result.slot_index, *value); |
1397 return value; | 1422 return value; |
1398 } | 1423 } |
1399 } | 1424 } |
1400 | 1425 |
1401 // TODO(verwaest): Let SetProperty do the migration, since storing a property | 1426 // TODO(verwaest): Let SetProperty do the migration, since storing a property |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1496 // This is currently guaranteed by checks in StoreIC::Store. | 1521 // This is currently guaranteed by checks in StoreIC::Store. |
1497 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); | 1522 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); |
1498 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 1523 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
1499 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); | 1524 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); |
1500 | 1525 |
1501 switch (lookup->state()) { | 1526 switch (lookup->state()) { |
1502 case LookupIterator::TRANSITION: { | 1527 case LookupIterator::TRANSITION: { |
1503 auto store_target = lookup->GetStoreTarget(); | 1528 auto store_target = lookup->GetStoreTarget(); |
1504 if (store_target->IsJSGlobalObject()) { | 1529 if (store_target->IsJSGlobalObject()) { |
1505 // TODO(dcarney): this currently just deopts. Use the transition cell. | 1530 // TODO(dcarney): this currently just deopts. Use the transition cell. |
| 1531 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransition); |
1506 auto cell = isolate()->factory()->NewPropertyCell(); | 1532 auto cell = isolate()->factory()->NewPropertyCell(); |
1507 cell->set_value(*value); | 1533 cell->set_value(*value); |
1508 auto code = PropertyCellStoreHandler( | 1534 auto code = PropertyCellStoreHandler( |
1509 isolate(), store_target, Handle<JSGlobalObject>::cast(store_target), | 1535 isolate(), store_target, Handle<JSGlobalObject>::cast(store_target), |
1510 lookup->name(), cell, PropertyCellType::kConstant); | 1536 lookup->name(), cell, PropertyCellType::kConstant); |
1511 cell->set_value(isolate()->heap()->the_hole_value()); | 1537 cell->set_value(isolate()->heap()->the_hole_value()); |
1512 return code; | 1538 return code; |
1513 } | 1539 } |
1514 Handle<Map> transition = lookup->transition_map(); | 1540 Handle<Map> transition = lookup->transition_map(); |
1515 // Currently not handled by CompileStoreTransition. | 1541 // Currently not handled by CompileStoreTransition. |
1516 if (!holder->HasFastProperties()) { | 1542 if (!holder->HasFastProperties()) { |
1517 TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow"); | 1543 TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow"); |
1518 break; | 1544 break; |
1519 } | 1545 } |
1520 | 1546 |
1521 DCHECK(lookup->IsCacheableTransition()); | 1547 DCHECK(lookup->IsCacheableTransition()); |
| 1548 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransition); |
1522 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); | 1549 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
1523 return compiler.CompileStoreTransition(transition, lookup->name()); | 1550 return compiler.CompileStoreTransition(transition, lookup->name()); |
1524 } | 1551 } |
1525 | 1552 |
1526 case LookupIterator::INTERCEPTOR: { | 1553 case LookupIterator::INTERCEPTOR: { |
1527 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined()); | 1554 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined()); |
| 1555 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub); |
1528 StoreInterceptorStub stub(isolate()); | 1556 StoreInterceptorStub stub(isolate()); |
1529 return stub.GetCode(); | 1557 return stub.GetCode(); |
1530 } | 1558 } |
1531 | 1559 |
1532 case LookupIterator::ACCESSOR: { | 1560 case LookupIterator::ACCESSOR: { |
1533 if (!holder->HasFastProperties()) { | 1561 if (!holder->HasFastProperties()) { |
1534 TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map"); | 1562 TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map"); |
1535 break; | 1563 break; |
1536 } | 1564 } |
1537 Handle<Object> accessors = lookup->GetAccessors(); | 1565 Handle<Object> accessors = lookup->GetAccessors(); |
1538 if (accessors->IsAccessorInfo()) { | 1566 if (accessors->IsAccessorInfo()) { |
1539 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); | 1567 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); |
1540 if (v8::ToCData<Address>(info->setter()) == 0) { | 1568 if (v8::ToCData<Address>(info->setter()) == 0) { |
1541 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0"); | 1569 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0"); |
1542 break; | 1570 break; |
1543 } | 1571 } |
1544 if (AccessorInfo::cast(*accessors)->is_special_data_property() && | 1572 if (AccessorInfo::cast(*accessors)->is_special_data_property() && |
1545 !lookup->HolderIsReceiverOrHiddenPrototype()) { | 1573 !lookup->HolderIsReceiverOrHiddenPrototype()) { |
1546 TRACE_GENERIC_IC(isolate(), "StoreIC", | 1574 TRACE_GENERIC_IC(isolate(), "StoreIC", |
1547 "special data property in prototype chain"); | 1575 "special data property in prototype chain"); |
1548 break; | 1576 break; |
1549 } | 1577 } |
1550 if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info, | 1578 if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info, |
1551 receiver_map())) { | 1579 receiver_map())) { |
1552 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type"); | 1580 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type"); |
1553 break; | 1581 break; |
1554 } | 1582 } |
1555 if (info->is_sloppy() && !receiver->IsJSReceiver()) break; | 1583 if (info->is_sloppy() && !receiver->IsJSReceiver()) break; |
| 1584 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback); |
1556 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); | 1585 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
1557 return compiler.CompileStoreCallback(receiver, lookup->name(), info, | 1586 return compiler.CompileStoreCallback(receiver, lookup->name(), info, |
1558 language_mode()); | 1587 language_mode()); |
1559 } else if (accessors->IsAccessorPair()) { | 1588 } else if (accessors->IsAccessorPair()) { |
1560 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), | 1589 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), |
1561 isolate()); | 1590 isolate()); |
1562 if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) { | 1591 if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) { |
1563 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function"); | 1592 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function"); |
1564 break; | 1593 break; |
1565 } | 1594 } |
1566 CallOptimization call_optimization(setter); | 1595 CallOptimization call_optimization(setter); |
1567 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); | 1596 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
1568 if (call_optimization.is_simple_api_call()) { | 1597 if (call_optimization.is_simple_api_call()) { |
1569 if (call_optimization.IsCompatibleReceiver(receiver, holder)) { | 1598 if (call_optimization.IsCompatibleReceiver(receiver, holder)) { |
| 1599 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback); |
1570 return compiler.CompileStoreCallback(receiver, lookup->name(), | 1600 return compiler.CompileStoreCallback(receiver, lookup->name(), |
1571 call_optimization, | 1601 call_optimization, |
1572 lookup->GetAccessorIndex()); | 1602 lookup->GetAccessorIndex()); |
1573 } | 1603 } |
1574 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver"); | 1604 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver"); |
1575 break; | 1605 break; |
1576 } | 1606 } |
| 1607 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter); |
1577 int expected_arguments = JSFunction::cast(*setter) | 1608 int expected_arguments = JSFunction::cast(*setter) |
1578 ->shared() | 1609 ->shared() |
1579 ->internal_formal_parameter_count(); | 1610 ->internal_formal_parameter_count(); |
1580 return compiler.CompileStoreViaSetter(receiver, lookup->name(), | 1611 return compiler.CompileStoreViaSetter(receiver, lookup->name(), |
1581 lookup->GetAccessorIndex(), | 1612 lookup->GetAccessorIndex(), |
1582 expected_arguments); | 1613 expected_arguments); |
1583 } | 1614 } |
1584 break; | 1615 break; |
1585 } | 1616 } |
1586 | 1617 |
1587 case LookupIterator::DATA: { | 1618 case LookupIterator::DATA: { |
1588 if (lookup->is_dictionary_holder()) { | 1619 if (lookup->is_dictionary_holder()) { |
1589 if (holder->IsJSGlobalObject()) { | 1620 if (holder->IsJSGlobalObject()) { |
| 1621 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobal); |
1590 DCHECK(holder.is_identical_to(receiver) || | 1622 DCHECK(holder.is_identical_to(receiver) || |
1591 receiver->map()->prototype() == *holder); | 1623 receiver->map()->prototype() == *holder); |
1592 auto cell = lookup->GetPropertyCell(); | 1624 auto cell = lookup->GetPropertyCell(); |
1593 auto updated_type = PropertyCell::UpdatedType( | 1625 auto updated_type = PropertyCell::UpdatedType( |
1594 cell, value, lookup->property_details()); | 1626 cell, value, lookup->property_details()); |
1595 auto code = PropertyCellStoreHandler( | 1627 auto code = PropertyCellStoreHandler( |
1596 isolate(), receiver, Handle<JSGlobalObject>::cast(holder), | 1628 isolate(), receiver, Handle<JSGlobalObject>::cast(holder), |
1597 lookup->name(), cell, updated_type); | 1629 lookup->name(), cell, updated_type); |
1598 return code; | 1630 return code; |
1599 } | 1631 } |
| 1632 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormal); |
1600 DCHECK(holder.is_identical_to(receiver)); | 1633 DCHECK(holder.is_identical_to(receiver)); |
1601 return isolate()->builtins()->StoreIC_Normal(); | 1634 return isolate()->builtins()->StoreIC_Normal(); |
1602 } | 1635 } |
1603 | 1636 |
1604 // -------------- Fields -------------- | 1637 // -------------- Fields -------------- |
1605 if (lookup->property_details().type() == DATA) { | 1638 if (lookup->property_details().type() == DATA) { |
1606 bool use_stub = true; | 1639 bool use_stub = true; |
1607 if (lookup->representation().IsHeapObject()) { | 1640 if (lookup->representation().IsHeapObject()) { |
1608 // Only use a generic stub if no types need to be tracked. | 1641 // Only use a generic stub if no types need to be tracked. |
1609 Handle<FieldType> field_type = lookup->GetFieldType(); | 1642 Handle<FieldType> field_type = lookup->GetFieldType(); |
1610 use_stub = !field_type->IsClass(); | 1643 use_stub = !field_type->IsClass(); |
1611 } | 1644 } |
1612 if (use_stub) { | 1645 if (use_stub) { |
| 1646 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldStub); |
1613 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), | 1647 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), |
1614 lookup->representation()); | 1648 lookup->representation()); |
1615 return stub.GetCode(); | 1649 return stub.GetCode(); |
1616 } | 1650 } |
| 1651 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreField); |
1617 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); | 1652 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
1618 return compiler.CompileStoreField(lookup); | 1653 return compiler.CompileStoreField(lookup); |
1619 } | 1654 } |
1620 | 1655 |
1621 // -------------- Constant properties -------------- | 1656 // -------------- Constant properties -------------- |
1622 DCHECK(lookup->property_details().type() == DATA_CONSTANT); | 1657 DCHECK(lookup->property_details().type() == DATA_CONSTANT); |
1623 TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property"); | 1658 TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property"); |
1624 break; | 1659 break; |
1625 } | 1660 } |
1626 | 1661 |
1627 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 1662 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
1628 case LookupIterator::ACCESS_CHECK: | 1663 case LookupIterator::ACCESS_CHECK: |
1629 case LookupIterator::JSPROXY: | 1664 case LookupIterator::JSPROXY: |
1630 case LookupIterator::NOT_FOUND: | 1665 case LookupIterator::NOT_FOUND: |
1631 UNREACHABLE(); | 1666 UNREACHABLE(); |
1632 } | 1667 } |
| 1668 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); |
1633 return slow_stub(); | 1669 return slow_stub(); |
1634 } | 1670 } |
1635 | 1671 |
1636 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map, | 1672 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map, |
1637 KeyedAccessStoreMode store_mode) { | 1673 KeyedAccessStoreMode store_mode) { |
1638 MapHandleList target_receiver_maps; | 1674 MapHandleList target_receiver_maps; |
1639 TargetMaps(&target_receiver_maps); | 1675 TargetMaps(&target_receiver_maps); |
1640 if (target_receiver_maps.length() == 0) { | 1676 if (target_receiver_maps.length() == 0) { |
1641 Handle<Map> monomorphic_map = | 1677 Handle<Map> monomorphic_map = |
1642 ComputeTransitionedMap(receiver_map, store_mode); | 1678 ComputeTransitionedMap(receiver_map, store_mode); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1742 } | 1778 } |
1743 } | 1779 } |
1744 if (external_arrays != 0 && | 1780 if (external_arrays != 0 && |
1745 external_arrays != target_receiver_maps.length()) { | 1781 external_arrays != target_receiver_maps.length()) { |
1746 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | 1782 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
1747 "unsupported combination of external and normal arrays"); | 1783 "unsupported combination of external and normal arrays"); |
1748 return; | 1784 return; |
1749 } | 1785 } |
1750 } | 1786 } |
1751 | 1787 |
| 1788 TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_Polymorphic); |
1752 MapHandleList transitioned_maps(target_receiver_maps.length()); | 1789 MapHandleList transitioned_maps(target_receiver_maps.length()); |
1753 CodeHandleList handlers(target_receiver_maps.length()); | 1790 CodeHandleList handlers(target_receiver_maps.length()); |
1754 PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers( | 1791 PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers( |
1755 &target_receiver_maps, &transitioned_maps, &handlers, store_mode); | 1792 &target_receiver_maps, &transitioned_maps, &handlers, store_mode); |
1756 ConfigureVectorState(&target_receiver_maps, &transitioned_maps, &handlers); | 1793 ConfigureVectorState(&target_receiver_maps, &transitioned_maps, &handlers); |
1757 } | 1794 } |
1758 | 1795 |
1759 | 1796 |
1760 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( | 1797 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( |
1761 Handle<Map> map, KeyedAccessStoreMode store_mode) { | 1798 Handle<Map> map, KeyedAccessStoreMode store_mode) { |
(...skipping 984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2746 KeyedLoadICNexus nexus(vector, vector_slot); | 2783 KeyedLoadICNexus nexus(vector, vector_slot); |
2747 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2784 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
2748 ic.UpdateState(receiver, key); | 2785 ic.UpdateState(receiver, key); |
2749 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2786 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
2750 } | 2787 } |
2751 | 2788 |
2752 return *result; | 2789 return *result; |
2753 } | 2790 } |
2754 } // namespace internal | 2791 } // namespace internal |
2755 } // namespace v8 | 2792 } // namespace v8 |
OLD | NEW |