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 918 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
929 TRACE_IC("LoadIC", lookup->name()); | 929 TRACE_IC("LoadIC", lookup->name()); |
930 } | 930 } |
931 | 931 |
932 | 932 |
933 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { | 933 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { |
934 isolate()->stub_cache()->Set(name, map, code); | 934 isolate()->stub_cache()->Set(name, map, code); |
935 } | 935 } |
936 | 936 |
937 | 937 |
938 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) { | 938 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) { |
| 939 // Try to find a globally shared handler stub. |
| 940 Handle<Code> code = GetMapIndependentHandler(lookup); |
| 941 if (!code.is_null()) return code; |
| 942 |
| 943 // Otherwise check the map's handler cache for a map-specific handler, and |
| 944 // compile one if the cache comes up empty. |
939 bool receiver_is_holder = | 945 bool receiver_is_holder = |
940 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); | 946 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); |
941 CacheHolderFlag flag; | 947 CacheHolderFlag flag; |
942 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( | 948 Handle<Map> stub_holder_map; |
943 receiver_map(), receiver_is_holder, isolate(), &flag); | 949 if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) { |
| 950 stub_holder_map = IC::GetHandlerCacheHolder( |
| 951 receiver_map(), receiver_is_holder, isolate(), &flag); |
| 952 } else { |
| 953 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC); |
| 954 // Store handlers cannot be cached on prototypes. |
| 955 flag = kCacheOnReceiver; |
| 956 stub_holder_map = receiver_map(); |
| 957 } |
944 | 958 |
945 Handle<Code> code = PropertyHandlerCompiler::Find( | 959 code = PropertyHandlerCompiler::Find(lookup->name(), stub_holder_map, kind(), |
946 lookup->name(), stub_holder_map, kind(), flag); | 960 flag); |
947 // Use the cached value if it exists, and if it is different from the | 961 // Use the cached value if it exists, and if it is different from the |
948 // handler that just missed. | 962 // handler that just missed. |
949 if (!code.is_null()) { | 963 if (!code.is_null()) { |
950 Handle<Code> handler; | 964 Handle<Code> handler; |
951 if (maybe_handler_.ToHandle(&handler)) { | 965 if (maybe_handler_.ToHandle(&handler)) { |
952 if (!handler.is_identical_to(code)) { | 966 if (!handler.is_identical_to(code)) { |
953 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); | 967 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); |
954 return code; | 968 return code; |
955 } | 969 } |
956 } else { | 970 } else { |
(...skipping 10 matching lines...) Expand all Loading... |
967 } | 981 } |
968 } else { | 982 } else { |
969 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); | 983 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); |
970 return code; | 984 return code; |
971 } | 985 } |
972 } | 986 } |
973 } | 987 } |
974 | 988 |
975 code = CompileHandler(lookup, value, flag); | 989 code = CompileHandler(lookup, value, flag); |
976 DCHECK(code->is_handler()); | 990 DCHECK(code->is_handler()); |
977 | 991 DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag); |
978 // TODO(mvstanton): we'd only like to cache code on the map when it's custom | 992 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); |
979 // code compiled for this map, otherwise it's already cached in the global | |
980 // code cache. We are also guarding against installing code with flags that | |
981 // don't match the desired CacheHolderFlag computed above, which would lead to | |
982 // invalid lookups later. | |
983 bool is_normal = receiver_is_holder && | |
984 !lookup->GetHolder<JSReceiver>()->HasFastProperties(); | |
985 if (!is_normal && Code::ExtractCacheHolderFromFlags(code->flags()) == flag) { | |
986 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); | |
987 } | |
988 | 993 |
989 return code; | 994 return code; |
990 } | 995 } |
991 | 996 |
992 | 997 Handle<Code> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) { |
993 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, | |
994 Handle<Object> unused, | |
995 CacheHolderFlag cache_holder) { | |
996 Handle<Object> receiver = lookup->GetReceiver(); | 998 Handle<Object> receiver = lookup->GetReceiver(); |
997 if (receiver->IsString() && | 999 if (receiver->IsString() && |
998 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { | 1000 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { |
999 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); | 1001 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); |
1000 return SimpleFieldLoad(index); | 1002 return SimpleFieldLoad(index); |
1001 } | 1003 } |
1002 | 1004 |
1003 if (receiver->IsStringWrapper() && | 1005 if (receiver->IsStringWrapper() && |
1004 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { | 1006 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { |
1005 TRACE_HANDLER_STATS(isolate(), LoadIC_StringLengthStub); | 1007 TRACE_HANDLER_STATS(isolate(), LoadIC_StringLengthStub); |
(...skipping 11 matching lines...) Expand all Loading... |
1017 Handle<Code> stub; | 1019 Handle<Code> stub; |
1018 TRACE_HANDLER_STATS(isolate(), LoadIC_FunctionPrototypeStub); | 1020 TRACE_HANDLER_STATS(isolate(), LoadIC_FunctionPrototypeStub); |
1019 FunctionPrototypeStub function_prototype_stub(isolate()); | 1021 FunctionPrototypeStub function_prototype_stub(isolate()); |
1020 return function_prototype_stub.GetCode(); | 1022 return function_prototype_stub.GetCode(); |
1021 } | 1023 } |
1022 | 1024 |
1023 Handle<Map> map = receiver_map(); | 1025 Handle<Map> map = receiver_map(); |
1024 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 1026 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
1025 bool receiver_is_holder = receiver.is_identical_to(holder); | 1027 bool receiver_is_holder = receiver.is_identical_to(holder); |
1026 switch (lookup->state()) { | 1028 switch (lookup->state()) { |
1027 case LookupIterator::INTERCEPTOR: { | 1029 case LookupIterator::INTERCEPTOR: |
1028 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1030 break; // Custom-compiled handler. |
1029 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptor); | |
1030 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | |
1031 // Perform a lookup behind the interceptor. Copy the LookupIterator since | |
1032 // the original iterator will be used to fetch the value. | |
1033 LookupIterator it = *lookup; | |
1034 it.Next(); | |
1035 LookupForRead(&it); | |
1036 return compiler.CompileLoadInterceptor(&it); | |
1037 } | |
1038 | 1031 |
1039 case LookupIterator::ACCESSOR: { | 1032 case LookupIterator::ACCESSOR: { |
1040 // Use simple field loads for some well-known callback properties. | 1033 // Use simple field loads for some well-known callback properties. |
1041 // The method will only return true for absolute truths based on the | 1034 // The method will only return true for absolute truths based on the |
1042 // receiver maps. | 1035 // receiver maps. |
1043 int object_offset; | 1036 int object_offset; |
1044 if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(), | 1037 if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(), |
1045 &object_offset)) { | 1038 &object_offset)) { |
1046 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); | 1039 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); |
1047 return SimpleFieldLoad(index); | 1040 return SimpleFieldLoad(index); |
1048 } | 1041 } |
1049 if (Accessors::IsJSArrayBufferViewFieldAccessor(map, lookup->name(), | 1042 if (Accessors::IsJSArrayBufferViewFieldAccessor(map, lookup->name(), |
1050 &object_offset)) { | 1043 &object_offset)) { |
1051 TRACE_HANDLER_STATS(isolate(), LoadIC_ArrayBufferViewLoadFieldStub); | 1044 TRACE_HANDLER_STATS(isolate(), LoadIC_ArrayBufferViewLoadFieldStub); |
1052 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); | 1045 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); |
1053 ArrayBufferViewLoadFieldStub stub(isolate(), index); | 1046 ArrayBufferViewLoadFieldStub stub(isolate(), index); |
1054 return stub.GetCode(); | 1047 return stub.GetCode(); |
1055 } | 1048 } |
1056 | 1049 |
1057 if (IsCompatibleReceiver(lookup, map)) { | 1050 if (IsCompatibleReceiver(lookup, map)) { |
1058 Handle<Object> accessors = lookup->GetAccessors(); | 1051 Handle<Object> accessors = lookup->GetAccessors(); |
1059 if (accessors->IsAccessorPair()) { | 1052 if (accessors->IsAccessorPair()) { |
1060 if (!holder->HasFastProperties()) break; | 1053 if (!holder->HasFastProperties()) { |
| 1054 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
| 1055 return slow_stub(); |
| 1056 } |
1061 // When debugging we need to go the slow path to flood the accessor. | 1057 // When debugging we need to go the slow path to flood the accessor. |
1062 if (GetSharedFunctionInfo()->HasDebugInfo()) break; | 1058 if (GetSharedFunctionInfo()->HasDebugInfo()) { |
1063 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), | 1059 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
1064 isolate()); | 1060 return slow_stub(); |
1065 CallOptimization call_optimization(getter); | |
1066 NamedLoadHandlerCompiler compiler(isolate(), map, holder, | |
1067 cache_holder); | |
1068 if (call_optimization.is_simple_api_call()) { | |
1069 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback); | |
1070 int index = lookup->GetAccessorIndex(); | |
1071 return compiler.CompileLoadCallback(lookup->name(), | |
1072 call_optimization, index); | |
1073 } | 1061 } |
1074 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadViaGetter); | 1062 break; // Custom-compiled handler. |
1075 int expected_arguments = Handle<JSFunction>::cast(getter) | |
1076 ->shared() | |
1077 ->internal_formal_parameter_count(); | |
1078 return compiler.CompileLoadViaGetter( | |
1079 lookup->name(), lookup->GetAccessorIndex(), expected_arguments); | |
1080 } else if (accessors->IsAccessorInfo()) { | 1063 } else if (accessors->IsAccessorInfo()) { |
1081 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); | 1064 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); |
1082 if (v8::ToCData<Address>(info->getter()) == nullptr) break; | 1065 if (v8::ToCData<Address>(info->getter()) == nullptr) { |
1083 if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map)) { | 1066 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
1084 // This case should be already handled in LoadIC::UpdateCaches. | 1067 return slow_stub(); |
1085 UNREACHABLE(); | |
1086 break; | |
1087 } | 1068 } |
1088 if (!holder->HasFastProperties()) break; | 1069 // Ruled out by IsCompatibleReceiver() above. |
| 1070 DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map)); |
| 1071 if (!holder->HasFastProperties()) return slow_stub(); |
1089 if (receiver_is_holder) { | 1072 if (receiver_is_holder) { |
1090 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterStub); | 1073 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterStub); |
1091 int index = lookup->GetAccessorIndex(); | 1074 int index = lookup->GetAccessorIndex(); |
1092 LoadApiGetterStub stub(isolate(), true, index); | 1075 LoadApiGetterStub stub(isolate(), true, index); |
1093 return stub.GetCode(); | 1076 return stub.GetCode(); |
1094 } | 1077 } |
1095 if (info->is_sloppy() && !receiver->IsJSReceiver()) break; | 1078 if (info->is_sloppy() && !receiver->IsJSReceiver()) { |
1096 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback); | 1079 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
1097 NamedLoadHandlerCompiler compiler(isolate(), map, holder, | 1080 return slow_stub(); |
1098 cache_holder); | 1081 } |
1099 return compiler.CompileLoadCallback(lookup->name(), info); | 1082 break; // Custom-compiled handler. |
1100 } | 1083 } |
1101 } | 1084 } |
1102 break; | 1085 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
| 1086 return slow_stub(); |
1103 } | 1087 } |
1104 | 1088 |
1105 case LookupIterator::DATA: { | 1089 case LookupIterator::DATA: { |
1106 if (lookup->is_dictionary_holder()) { | 1090 if (lookup->is_dictionary_holder()) { |
1107 if (kind() != Code::LOAD_IC) break; | 1091 if (kind() != Code::LOAD_IC) { |
| 1092 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
| 1093 return slow_stub(); |
| 1094 } |
1108 if (holder->IsJSGlobalObject()) { | 1095 if (holder->IsJSGlobalObject()) { |
1109 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal); | 1096 break; // Custom-compiled handler. |
1110 NamedLoadHandlerCompiler compiler(isolate(), map, holder, | |
1111 cache_holder); | |
1112 Handle<PropertyCell> cell = lookup->GetPropertyCell(); | |
1113 Handle<Code> code = compiler.CompileLoadGlobal( | |
1114 cell, lookup->name(), lookup->IsConfigurable()); | |
1115 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | |
1116 CacheHolderFlag flag; | |
1117 Handle<Map> stub_holder_map = | |
1118 GetHandlerCacheHolder(map, receiver_is_holder, isolate(), &flag); | |
1119 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); | |
1120 return code; | |
1121 } | 1097 } |
1122 // There is only one shared stub for loading normalized | 1098 // There is only one shared stub for loading normalized |
1123 // properties. It does not traverse the prototype chain, so the | 1099 // properties. It does not traverse the prototype chain, so the |
1124 // property must be found in the object for the stub to be | 1100 // property must be found in the object for the stub to be |
1125 // applicable. | 1101 // applicable. |
1126 if (!receiver_is_holder) break; | 1102 if (!receiver_is_holder) { |
| 1103 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
| 1104 return slow_stub(); |
| 1105 } |
1127 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal); | 1106 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal); |
1128 return isolate()->builtins()->LoadIC_Normal(); | 1107 return isolate()->builtins()->LoadIC_Normal(); |
1129 } | 1108 } |
1130 | 1109 |
1131 // -------------- Fields -------------- | 1110 // -------------- Fields -------------- |
1132 if (lookup->property_details().type() == DATA) { | 1111 if (lookup->property_details().type() == DATA) { |
1133 FieldIndex field = lookup->GetFieldIndex(); | 1112 FieldIndex field = lookup->GetFieldIndex(); |
1134 if (receiver_is_holder) { | 1113 if (receiver_is_holder) { |
1135 return SimpleFieldLoad(field); | 1114 return SimpleFieldLoad(field); |
1136 } | 1115 } |
1137 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadField); | 1116 break; // Custom-compiled handler. |
1138 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | |
1139 return compiler.CompileLoadField(lookup->name(), field); | |
1140 } | 1117 } |
1141 | 1118 |
1142 // -------------- Constant properties -------------- | 1119 // -------------- Constant properties -------------- |
1143 DCHECK(lookup->property_details().type() == DATA_CONSTANT); | 1120 DCHECK(lookup->property_details().type() == DATA_CONSTANT); |
1144 if (receiver_is_holder) { | 1121 if (receiver_is_holder) { |
1145 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub); | 1122 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub); |
1146 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); | 1123 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); |
1147 return stub.GetCode(); | 1124 return stub.GetCode(); |
1148 } | 1125 } |
| 1126 break; // Custom-compiled handler. |
| 1127 } |
| 1128 |
| 1129 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
| 1130 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); |
| 1131 return slow_stub(); |
| 1132 case LookupIterator::ACCESS_CHECK: |
| 1133 case LookupIterator::JSPROXY: |
| 1134 case LookupIterator::NOT_FOUND: |
| 1135 case LookupIterator::TRANSITION: |
| 1136 UNREACHABLE(); |
| 1137 } |
| 1138 |
| 1139 return Handle<Code>::null(); |
| 1140 } |
| 1141 |
| 1142 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, |
| 1143 Handle<Object> unused, |
| 1144 CacheHolderFlag cache_holder) { |
| 1145 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
| 1146 #ifdef DEBUG |
| 1147 // Only used by DCHECKs below. |
| 1148 Handle<Object> receiver = lookup->GetReceiver(); |
| 1149 bool receiver_is_holder = receiver.is_identical_to(holder); |
| 1150 #endif |
| 1151 // Non-map-specific handler stubs have already been selected. |
| 1152 DCHECK(!receiver->IsString() || |
| 1153 !Name::Equals(isolate()->factory()->length_string(), lookup->name())); |
| 1154 DCHECK(!receiver->IsStringWrapper() || |
| 1155 !Name::Equals(isolate()->factory()->length_string(), lookup->name())); |
| 1156 |
| 1157 DCHECK(!( |
| 1158 receiver->IsJSFunction() && |
| 1159 Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) && |
| 1160 receiver->IsConstructor() && |
| 1161 !Handle<JSFunction>::cast(receiver) |
| 1162 ->map() |
| 1163 ->has_non_instance_prototype())); |
| 1164 |
| 1165 Handle<Map> map = receiver_map(); |
| 1166 switch (lookup->state()) { |
| 1167 case LookupIterator::INTERCEPTOR: { |
| 1168 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1169 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptor); |
| 1170 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1171 // Perform a lookup behind the interceptor. Copy the LookupIterator since |
| 1172 // the original iterator will be used to fetch the value. |
| 1173 LookupIterator it = *lookup; |
| 1174 it.Next(); |
| 1175 LookupForRead(&it); |
| 1176 return compiler.CompileLoadInterceptor(&it); |
| 1177 } |
| 1178 |
| 1179 case LookupIterator::ACCESSOR: { |
| 1180 #ifdef DEBUG |
| 1181 int object_offset; |
| 1182 DCHECK(!Accessors::IsJSObjectFieldAccessor(map, lookup->name(), |
| 1183 &object_offset)); |
| 1184 DCHECK(!Accessors::IsJSArrayBufferViewFieldAccessor(map, lookup->name(), |
| 1185 &object_offset)); |
| 1186 #endif |
| 1187 |
| 1188 DCHECK(IsCompatibleReceiver(lookup, map)); |
| 1189 Handle<Object> accessors = lookup->GetAccessors(); |
| 1190 if (accessors->IsAccessorPair()) { |
| 1191 DCHECK(holder->HasFastProperties()); |
| 1192 DCHECK(!GetSharedFunctionInfo()->HasDebugInfo()); |
| 1193 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), |
| 1194 isolate()); |
| 1195 CallOptimization call_optimization(getter); |
| 1196 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1197 if (call_optimization.is_simple_api_call()) { |
| 1198 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback); |
| 1199 int index = lookup->GetAccessorIndex(); |
| 1200 return compiler.CompileLoadCallback(lookup->name(), call_optimization, |
| 1201 index); |
| 1202 } |
| 1203 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadViaGetter); |
| 1204 int expected_arguments = Handle<JSFunction>::cast(getter) |
| 1205 ->shared() |
| 1206 ->internal_formal_parameter_count(); |
| 1207 return compiler.CompileLoadViaGetter( |
| 1208 lookup->name(), lookup->GetAccessorIndex(), expected_arguments); |
| 1209 } else { |
| 1210 DCHECK(accessors->IsAccessorInfo()); |
| 1211 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); |
| 1212 DCHECK(v8::ToCData<Address>(info->getter()) != nullptr); |
| 1213 DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map)); |
| 1214 DCHECK(holder->HasFastProperties()); |
| 1215 DCHECK(!receiver_is_holder); |
| 1216 DCHECK(!info->is_sloppy() || receiver->IsJSReceiver()); |
| 1217 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback); |
| 1218 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1219 return compiler.CompileLoadCallback(lookup->name(), info); |
| 1220 } |
| 1221 UNREACHABLE(); |
| 1222 } |
| 1223 |
| 1224 case LookupIterator::DATA: { |
| 1225 if (lookup->is_dictionary_holder()) { |
| 1226 DCHECK(kind() == Code::LOAD_IC); |
| 1227 DCHECK(holder->IsJSGlobalObject()); |
| 1228 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal); |
| 1229 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1230 Handle<PropertyCell> cell = lookup->GetPropertyCell(); |
| 1231 Handle<Code> code = compiler.CompileLoadGlobal( |
| 1232 cell, lookup->name(), lookup->IsConfigurable()); |
| 1233 return code; |
| 1234 } |
| 1235 |
| 1236 // -------------- Fields -------------- |
| 1237 if (lookup->property_details().type() == DATA) { |
| 1238 FieldIndex field = lookup->GetFieldIndex(); |
| 1239 DCHECK(!receiver_is_holder); |
| 1240 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadField); |
| 1241 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
| 1242 return compiler.CompileLoadField(lookup->name(), field); |
| 1243 } |
| 1244 |
| 1245 // -------------- Constant properties -------------- |
| 1246 DCHECK(lookup->property_details().type() == DATA_CONSTANT); |
| 1247 DCHECK(!receiver_is_holder); |
1149 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstant); | 1248 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstant); |
1150 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | 1249 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); |
1151 return compiler.CompileLoadConstant(lookup->name(), | 1250 return compiler.CompileLoadConstant(lookup->name(), |
1152 lookup->GetConstantIndex()); | 1251 lookup->GetConstantIndex()); |
1153 } | 1252 } |
1154 | 1253 |
1155 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 1254 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
1156 break; | |
1157 case LookupIterator::ACCESS_CHECK: | 1255 case LookupIterator::ACCESS_CHECK: |
1158 case LookupIterator::JSPROXY: | 1256 case LookupIterator::JSPROXY: |
1159 case LookupIterator::NOT_FOUND: | 1257 case LookupIterator::NOT_FOUND: |
1160 case LookupIterator::TRANSITION: | 1258 case LookupIterator::TRANSITION: |
1161 UNREACHABLE(); | 1259 UNREACHABLE(); |
1162 } | 1260 } |
1163 | 1261 UNREACHABLE(); |
1164 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub); | |
1165 return slow_stub(); | 1262 return slow_stub(); |
1166 } | 1263 } |
1167 | 1264 |
1168 | 1265 |
1169 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { | 1266 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { |
1170 // This helper implements a few common fast cases for converting | 1267 // This helper implements a few common fast cases for converting |
1171 // non-smi keys of keyed loads/stores to a smi or a string. | 1268 // non-smi keys of keyed loads/stores to a smi or a string. |
1172 if (key->IsHeapNumber()) { | 1269 if (key->IsHeapNumber()) { |
1173 double value = Handle<HeapNumber>::cast(key)->value(); | 1270 double value = Handle<HeapNumber>::cast(key)->value(); |
1174 if (std::isnan(value)) { | 1271 if (std::isnan(value)) { |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1506 constant_type = Just(cell->GetConstantType()); | 1603 constant_type = Just(cell->GetConstantType()); |
1507 } | 1604 } |
1508 StoreGlobalStub stub(isolate, type, constant_type, | 1605 StoreGlobalStub stub(isolate, type, constant_type, |
1509 receiver->IsJSGlobalProxy()); | 1606 receiver->IsJSGlobalProxy()); |
1510 auto code = stub.GetCodeCopyFromTemplate(holder, cell); | 1607 auto code = stub.GetCodeCopyFromTemplate(holder, cell); |
1511 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1608 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
1512 HeapObject::UpdateMapCodeCache(receiver, name, code); | 1609 HeapObject::UpdateMapCodeCache(receiver, name, code); |
1513 return code; | 1610 return code; |
1514 } | 1611 } |
1515 | 1612 |
1516 | 1613 Handle<Code> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { |
1517 Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, | |
1518 Handle<Object> value, | |
1519 CacheHolderFlag cache_holder) { | |
1520 DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); | 1614 DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); |
1521 | 1615 |
1522 // This is currently guaranteed by checks in StoreIC::Store. | 1616 // This is currently guaranteed by checks in StoreIC::Store. |
1523 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); | 1617 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); |
1524 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 1618 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
1525 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); | 1619 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); |
1526 | 1620 |
1527 switch (lookup->state()) { | 1621 switch (lookup->state()) { |
1528 case LookupIterator::TRANSITION: { | 1622 case LookupIterator::TRANSITION: { |
1529 auto store_target = lookup->GetStoreTarget(); | 1623 auto store_target = lookup->GetStoreTarget(); |
1530 if (store_target->IsJSGlobalObject()) { | 1624 if (store_target->IsJSGlobalObject()) { |
1531 // TODO(dcarney): this currently just deopts. Use the transition cell. | 1625 break; // Custom-compiled handler. |
1532 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransition); | |
1533 auto cell = isolate()->factory()->NewPropertyCell(); | |
1534 cell->set_value(*value); | |
1535 auto code = PropertyCellStoreHandler( | |
1536 isolate(), store_target, Handle<JSGlobalObject>::cast(store_target), | |
1537 lookup->name(), cell, PropertyCellType::kConstant); | |
1538 cell->set_value(isolate()->heap()->the_hole_value()); | |
1539 return code; | |
1540 } | 1626 } |
1541 Handle<Map> transition = lookup->transition_map(); | |
1542 // Currently not handled by CompileStoreTransition. | 1627 // Currently not handled by CompileStoreTransition. |
1543 if (!holder->HasFastProperties()) { | 1628 if (!holder->HasFastProperties()) { |
1544 TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow"); | 1629 TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow"); |
1545 break; | 1630 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); |
| 1631 return slow_stub(); |
1546 } | 1632 } |
1547 | 1633 |
1548 DCHECK(lookup->IsCacheableTransition()); | 1634 DCHECK(lookup->IsCacheableTransition()); |
1549 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransition); | 1635 break; // Custom-compiled handler. |
1550 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); | |
1551 return compiler.CompileStoreTransition(transition, lookup->name()); | |
1552 } | 1636 } |
1553 | 1637 |
1554 case LookupIterator::INTERCEPTOR: { | 1638 case LookupIterator::INTERCEPTOR: { |
1555 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined()); | 1639 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined()); |
1556 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub); | 1640 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub); |
1557 StoreInterceptorStub stub(isolate()); | 1641 StoreInterceptorStub stub(isolate()); |
1558 return stub.GetCode(); | 1642 return stub.GetCode(); |
1559 } | 1643 } |
1560 | 1644 |
1561 case LookupIterator::ACCESSOR: { | 1645 case LookupIterator::ACCESSOR: { |
1562 if (!holder->HasFastProperties()) { | 1646 if (!holder->HasFastProperties()) { |
1563 TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map"); | 1647 TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map"); |
1564 break; | 1648 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); |
| 1649 return slow_stub(); |
1565 } | 1650 } |
1566 Handle<Object> accessors = lookup->GetAccessors(); | 1651 Handle<Object> accessors = lookup->GetAccessors(); |
1567 if (accessors->IsAccessorInfo()) { | 1652 if (accessors->IsAccessorInfo()) { |
1568 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); | 1653 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); |
1569 if (v8::ToCData<Address>(info->setter()) == 0) { | 1654 if (v8::ToCData<Address>(info->setter()) == nullptr) { |
1570 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0"); | 1655 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == nullptr"); |
1571 break; | 1656 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); |
| 1657 return slow_stub(); |
1572 } | 1658 } |
1573 if (AccessorInfo::cast(*accessors)->is_special_data_property() && | 1659 if (AccessorInfo::cast(*accessors)->is_special_data_property() && |
1574 !lookup->HolderIsReceiverOrHiddenPrototype()) { | 1660 !lookup->HolderIsReceiverOrHiddenPrototype()) { |
1575 TRACE_GENERIC_IC(isolate(), "StoreIC", | 1661 TRACE_GENERIC_IC(isolate(), "StoreIC", |
1576 "special data property in prototype chain"); | 1662 "special data property in prototype chain"); |
1577 break; | 1663 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); |
| 1664 return slow_stub(); |
1578 } | 1665 } |
1579 if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info, | 1666 if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info, |
1580 receiver_map())) { | 1667 receiver_map())) { |
1581 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type"); | 1668 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type"); |
1582 break; | 1669 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); |
| 1670 return slow_stub(); |
1583 } | 1671 } |
1584 if (info->is_sloppy() && !receiver->IsJSReceiver()) break; | 1672 if (info->is_sloppy() && !receiver->IsJSReceiver()) { |
1585 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback); | 1673 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); |
1586 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); | 1674 return slow_stub(); |
1587 return compiler.CompileStoreCallback(receiver, lookup->name(), info, | 1675 } |
1588 language_mode()); | 1676 break; // Custom-compiled handler. |
1589 } else if (accessors->IsAccessorPair()) { | 1677 } else if (accessors->IsAccessorPair()) { |
1590 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), | 1678 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), |
1591 isolate()); | 1679 isolate()); |
1592 if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) { | 1680 if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) { |
1593 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function"); | 1681 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function"); |
1594 break; | 1682 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); |
| 1683 return slow_stub(); |
1595 } | 1684 } |
1596 CallOptimization call_optimization(setter); | 1685 CallOptimization call_optimization(setter); |
1597 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); | |
1598 if (call_optimization.is_simple_api_call()) { | 1686 if (call_optimization.is_simple_api_call()) { |
1599 if (call_optimization.IsCompatibleReceiver(receiver, holder)) { | 1687 if (call_optimization.IsCompatibleReceiver(receiver, holder)) { |
1600 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback); | 1688 break; // Custom-compiled handler. |
1601 return compiler.CompileStoreCallback(receiver, lookup->name(), | |
1602 call_optimization, | |
1603 lookup->GetAccessorIndex()); | |
1604 } | 1689 } |
1605 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver"); | 1690 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver"); |
1606 break; | 1691 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); |
| 1692 return slow_stub(); |
1607 } | 1693 } |
1608 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter); | 1694 break; // Custom-compiled handler. |
1609 int expected_arguments = JSFunction::cast(*setter) | |
1610 ->shared() | |
1611 ->internal_formal_parameter_count(); | |
1612 return compiler.CompileStoreViaSetter(receiver, lookup->name(), | |
1613 lookup->GetAccessorIndex(), | |
1614 expected_arguments); | |
1615 } | 1695 } |
1616 break; | 1696 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); |
| 1697 return slow_stub(); |
1617 } | 1698 } |
1618 | 1699 |
1619 case LookupIterator::DATA: { | 1700 case LookupIterator::DATA: { |
1620 if (lookup->is_dictionary_holder()) { | 1701 if (lookup->is_dictionary_holder()) { |
1621 if (holder->IsJSGlobalObject()) { | 1702 if (holder->IsJSGlobalObject()) { |
1622 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobal); | 1703 break; // Custom-compiled handler. |
1623 DCHECK(holder.is_identical_to(receiver) || | |
1624 receiver->map()->prototype() == *holder); | |
1625 auto cell = lookup->GetPropertyCell(); | |
1626 auto updated_type = PropertyCell::UpdatedType( | |
1627 cell, value, lookup->property_details()); | |
1628 auto code = PropertyCellStoreHandler( | |
1629 isolate(), receiver, Handle<JSGlobalObject>::cast(holder), | |
1630 lookup->name(), cell, updated_type); | |
1631 return code; | |
1632 } | 1704 } |
1633 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormal); | 1705 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormal); |
1634 DCHECK(holder.is_identical_to(receiver)); | 1706 DCHECK(holder.is_identical_to(receiver)); |
1635 return isolate()->builtins()->StoreIC_Normal(); | 1707 return isolate()->builtins()->StoreIC_Normal(); |
1636 } | 1708 } |
1637 | 1709 |
1638 // -------------- Fields -------------- | 1710 // -------------- Fields -------------- |
1639 if (lookup->property_details().type() == DATA) { | 1711 if (lookup->property_details().type() == DATA) { |
1640 bool use_stub = true; | 1712 bool use_stub = true; |
1641 if (lookup->representation().IsHeapObject()) { | 1713 if (lookup->representation().IsHeapObject()) { |
1642 // Only use a generic stub if no types need to be tracked. | 1714 // Only use a generic stub if no types need to be tracked. |
1643 Handle<FieldType> field_type = lookup->GetFieldType(); | 1715 Handle<FieldType> field_type = lookup->GetFieldType(); |
1644 use_stub = !field_type->IsClass(); | 1716 use_stub = !field_type->IsClass(); |
1645 } | 1717 } |
1646 if (use_stub) { | 1718 if (use_stub) { |
1647 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldStub); | 1719 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldStub); |
1648 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), | 1720 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), |
1649 lookup->representation()); | 1721 lookup->representation()); |
1650 return stub.GetCode(); | 1722 return stub.GetCode(); |
1651 } | 1723 } |
| 1724 break; // Custom-compiled handler. |
| 1725 } |
| 1726 |
| 1727 // -------------- Constant properties -------------- |
| 1728 DCHECK(lookup->property_details().type() == DATA_CONSTANT); |
| 1729 TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property"); |
| 1730 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); |
| 1731 return slow_stub(); |
| 1732 } |
| 1733 |
| 1734 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
| 1735 case LookupIterator::ACCESS_CHECK: |
| 1736 case LookupIterator::JSPROXY: |
| 1737 case LookupIterator::NOT_FOUND: |
| 1738 UNREACHABLE(); |
| 1739 } |
| 1740 return Handle<Code>::null(); |
| 1741 } |
| 1742 |
| 1743 Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, |
| 1744 Handle<Object> value, |
| 1745 CacheHolderFlag cache_holder) { |
| 1746 DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); |
| 1747 |
| 1748 // This is currently guaranteed by checks in StoreIC::Store. |
| 1749 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); |
| 1750 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
| 1751 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); |
| 1752 |
| 1753 switch (lookup->state()) { |
| 1754 case LookupIterator::TRANSITION: { |
| 1755 auto store_target = lookup->GetStoreTarget(); |
| 1756 if (store_target->IsJSGlobalObject()) { |
| 1757 // TODO(dcarney): this currently just deopts. Use the transition cell. |
| 1758 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransition); |
| 1759 auto cell = isolate()->factory()->NewPropertyCell(); |
| 1760 cell->set_value(*value); |
| 1761 auto code = PropertyCellStoreHandler( |
| 1762 isolate(), store_target, Handle<JSGlobalObject>::cast(store_target), |
| 1763 lookup->name(), cell, PropertyCellType::kConstant); |
| 1764 cell->set_value(isolate()->heap()->the_hole_value()); |
| 1765 return code; |
| 1766 } |
| 1767 Handle<Map> transition = lookup->transition_map(); |
| 1768 // Currently not handled by CompileStoreTransition. |
| 1769 DCHECK(holder->HasFastProperties()); |
| 1770 |
| 1771 DCHECK(lookup->IsCacheableTransition()); |
| 1772 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransition); |
| 1773 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
| 1774 return compiler.CompileStoreTransition(transition, lookup->name()); |
| 1775 } |
| 1776 |
| 1777 case LookupIterator::INTERCEPTOR: |
| 1778 UNREACHABLE(); |
| 1779 |
| 1780 case LookupIterator::ACCESSOR: { |
| 1781 DCHECK(holder->HasFastProperties()); |
| 1782 Handle<Object> accessors = lookup->GetAccessors(); |
| 1783 if (accessors->IsAccessorInfo()) { |
| 1784 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); |
| 1785 DCHECK(v8::ToCData<Address>(info->setter()) != 0); |
| 1786 DCHECK(!AccessorInfo::cast(*accessors)->is_special_data_property() || |
| 1787 lookup->HolderIsReceiverOrHiddenPrototype()); |
| 1788 DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info, |
| 1789 receiver_map())); |
| 1790 DCHECK(!info->is_sloppy() || receiver->IsJSReceiver()); |
| 1791 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback); |
| 1792 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
| 1793 return compiler.CompileStoreCallback(receiver, lookup->name(), info, |
| 1794 language_mode()); |
| 1795 } else { |
| 1796 DCHECK(accessors->IsAccessorPair()); |
| 1797 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), |
| 1798 isolate()); |
| 1799 DCHECK(setter->IsJSFunction() || setter->IsFunctionTemplateInfo()); |
| 1800 CallOptimization call_optimization(setter); |
| 1801 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
| 1802 if (call_optimization.is_simple_api_call()) { |
| 1803 DCHECK(call_optimization.IsCompatibleReceiver(receiver, holder)); |
| 1804 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback); |
| 1805 return compiler.CompileStoreCallback(receiver, lookup->name(), |
| 1806 call_optimization, |
| 1807 lookup->GetAccessorIndex()); |
| 1808 } |
| 1809 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter); |
| 1810 int expected_arguments = JSFunction::cast(*setter) |
| 1811 ->shared() |
| 1812 ->internal_formal_parameter_count(); |
| 1813 return compiler.CompileStoreViaSetter(receiver, lookup->name(), |
| 1814 lookup->GetAccessorIndex(), |
| 1815 expected_arguments); |
| 1816 } |
| 1817 } |
| 1818 |
| 1819 case LookupIterator::DATA: { |
| 1820 if (lookup->is_dictionary_holder()) { |
| 1821 DCHECK(holder->IsJSGlobalObject()); |
| 1822 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobal); |
| 1823 DCHECK(holder.is_identical_to(receiver) || |
| 1824 receiver->map()->prototype() == *holder); |
| 1825 auto cell = lookup->GetPropertyCell(); |
| 1826 auto updated_type = |
| 1827 PropertyCell::UpdatedType(cell, value, lookup->property_details()); |
| 1828 auto code = PropertyCellStoreHandler( |
| 1829 isolate(), receiver, Handle<JSGlobalObject>::cast(holder), |
| 1830 lookup->name(), cell, updated_type); |
| 1831 return code; |
| 1832 } |
| 1833 |
| 1834 // -------------- Fields -------------- |
| 1835 if (lookup->property_details().type() == DATA) { |
| 1836 #ifdef DEBUG |
| 1837 bool use_stub = true; |
| 1838 if (lookup->representation().IsHeapObject()) { |
| 1839 // Only use a generic stub if no types need to be tracked. |
| 1840 Handle<FieldType> field_type = lookup->GetFieldType(); |
| 1841 use_stub = !field_type->IsClass(); |
| 1842 } |
| 1843 DCHECK(!use_stub); |
| 1844 #endif |
1652 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreField); | 1845 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreField); |
1653 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); | 1846 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
1654 return compiler.CompileStoreField(lookup); | 1847 return compiler.CompileStoreField(lookup); |
1655 } | 1848 } |
1656 | 1849 |
1657 // -------------- Constant properties -------------- | 1850 // -------------- Constant properties -------------- |
1658 DCHECK(lookup->property_details().type() == DATA_CONSTANT); | 1851 DCHECK(lookup->property_details().type() == DATA_CONSTANT); |
1659 TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property"); | 1852 UNREACHABLE(); |
1660 break; | |
1661 } | 1853 } |
1662 | 1854 |
1663 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 1855 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
1664 case LookupIterator::ACCESS_CHECK: | 1856 case LookupIterator::ACCESS_CHECK: |
1665 case LookupIterator::JSPROXY: | 1857 case LookupIterator::JSPROXY: |
1666 case LookupIterator::NOT_FOUND: | 1858 case LookupIterator::NOT_FOUND: |
1667 UNREACHABLE(); | 1859 UNREACHABLE(); |
1668 } | 1860 } |
1669 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); | 1861 UNREACHABLE(); |
1670 return slow_stub(); | 1862 return slow_stub(); |
1671 } | 1863 } |
1672 | 1864 |
1673 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map, | 1865 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map, |
1674 KeyedAccessStoreMode store_mode) { | 1866 KeyedAccessStoreMode store_mode) { |
1675 MapHandleList target_receiver_maps; | 1867 MapHandleList target_receiver_maps; |
1676 TargetMaps(&target_receiver_maps); | 1868 TargetMaps(&target_receiver_maps); |
1677 if (target_receiver_maps.length() == 0) { | 1869 if (target_receiver_maps.length() == 0) { |
1678 Handle<Map> monomorphic_map = | 1870 Handle<Map> monomorphic_map = |
1679 ComputeTransitionedMap(receiver_map, store_mode); | 1871 ComputeTransitionedMap(receiver_map, store_mode); |
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2794 KeyedLoadICNexus nexus(vector, vector_slot); | 2986 KeyedLoadICNexus nexus(vector, vector_slot); |
2795 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2987 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
2796 ic.UpdateState(receiver, key); | 2988 ic.UpdateState(receiver, key); |
2797 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2989 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
2798 } | 2990 } |
2799 | 2991 |
2800 return *result; | 2992 return *result; |
2801 } | 2993 } |
2802 } // namespace internal | 2994 } // namespace internal |
2803 } // namespace v8 | 2995 } // namespace v8 |
OLD | NEW |