Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/ic/ic.cc

Issue 1969733002: [runtime] Refine runtime call stats for IC misses. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@classify-misses
Patch Set: Rebasing Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ic/handler-compiler.cc ('k') | src/ic/ic-compiler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic/handler-compiler.cc ('k') | src/ic/ic-compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698