| 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/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 978 Handle<Object> accessors = lookup->GetAccessors(); | 978 Handle<Object> accessors = lookup->GetAccessors(); |
| 979 if (accessors->IsAccessorInfo()) { | 979 if (accessors->IsAccessorInfo()) { |
| 980 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); | 980 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); |
| 981 if (info->getter() != NULL && | 981 if (info->getter() != NULL && |
| 982 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) { | 982 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) { |
| 983 return false; | 983 return false; |
| 984 } | 984 } |
| 985 } else if (accessors->IsAccessorPair()) { | 985 } else if (accessors->IsAccessorPair()) { |
| 986 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), | 986 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), |
| 987 isolate); | 987 isolate); |
| 988 if (!getter->IsJSFunction() && !getter->IsFunctionTemplateInfo()) |
| 989 return false; |
| 988 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 990 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
| 989 Handle<Object> receiver = lookup->GetReceiver(); | 991 Handle<Object> receiver = lookup->GetReceiver(); |
| 990 if (getter->IsJSFunction() && holder->HasFastProperties()) { | 992 if (holder->HasFastProperties()) { |
| 991 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | 993 if (getter->IsJSFunction()) { |
| 992 if (receiver->IsJSObject() || function->shared()->IsBuiltin() || | 994 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
| 993 !is_sloppy(function->shared()->language_mode())) { | 995 if (!receiver->IsJSObject() && !function->shared()->IsBuiltin() && |
| 994 CallOptimization call_optimization(function); | 996 is_sloppy(function->shared()->language_mode())) { |
| 995 if (call_optimization.is_simple_api_call() && | 997 // Calling sloppy non-builtins with a value as the receiver |
| 996 !call_optimization.IsCompatibleReceiverMap(receiver_map, holder)) { | 998 // requires boxing. |
| 997 return false; | 999 return false; |
| 998 } | 1000 } |
| 999 } | 1001 } |
| 1002 CallOptimization call_optimization(getter); |
| 1003 if (call_optimization.is_simple_api_call() && |
| 1004 !call_optimization.IsCompatibleReceiverMap(receiver_map, holder)) { |
| 1005 return false; |
| 1006 } |
| 1000 } | 1007 } |
| 1001 } | 1008 } |
| 1002 return true; | 1009 return true; |
| 1003 } | 1010 } |
| 1004 | 1011 |
| 1005 | 1012 |
| 1006 void LoadIC::UpdateCaches(LookupIterator* lookup) { | 1013 void LoadIC::UpdateCaches(LookupIterator* lookup) { |
| 1007 if (state() == UNINITIALIZED) { | 1014 if (state() == UNINITIALIZED) { |
| 1008 // This is the first time we execute this inline cache. Set the target to | 1015 // This is the first time we execute this inline cache. Set the target to |
| 1009 // the pre monomorphic stub to delay setting the monomorphic state. | 1016 // the pre monomorphic stub to delay setting the monomorphic state. |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1159 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); | 1166 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); |
| 1160 return SimpleFieldLoad(index); | 1167 return SimpleFieldLoad(index); |
| 1161 } | 1168 } |
| 1162 if (Accessors::IsJSArrayBufferViewFieldAccessor(map, lookup->name(), | 1169 if (Accessors::IsJSArrayBufferViewFieldAccessor(map, lookup->name(), |
| 1163 &object_offset)) { | 1170 &object_offset)) { |
| 1164 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); | 1171 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); |
| 1165 ArrayBufferViewLoadFieldStub stub(isolate(), index); | 1172 ArrayBufferViewLoadFieldStub stub(isolate(), index); |
| 1166 return stub.GetCode(); | 1173 return stub.GetCode(); |
| 1167 } | 1174 } |
| 1168 | 1175 |
| 1169 Handle<Object> accessors = lookup->GetAccessors(); | 1176 if (IsCompatibleReceiver(lookup, map)) { |
| 1170 if (accessors->IsAccessorInfo()) { | 1177 Handle<Object> accessors = lookup->GetAccessors(); |
| 1171 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); | 1178 if (accessors->IsAccessorPair()) { |
| 1172 if (v8::ToCData<Address>(info->getter()) == 0) break; | 1179 if (!holder->HasFastProperties()) break; |
| 1173 if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map)) { | 1180 // When debugging we need to go the slow path to flood the accessor. |
| 1174 // This case should be already handled in LoadIC::UpdateCaches. | 1181 if (GetSharedFunctionInfo()->HasDebugInfo()) break; |
| 1175 UNREACHABLE(); | 1182 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), |
| 1176 break; | 1183 isolate()); |
| 1177 } | 1184 CallOptimization call_optimization(getter); |
| 1178 if (!holder->HasFastProperties()) break; | 1185 NamedLoadHandlerCompiler compiler(isolate(), map, holder, |
| 1179 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | 1186 cache_holder); |
| 1180 return compiler.CompileLoadCallback(lookup->name(), info); | 1187 if (call_optimization.is_simple_api_call()) { |
| 1181 } | |
| 1182 if (accessors->IsAccessorPair()) { | |
| 1183 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), | |
| 1184 isolate()); | |
| 1185 if (!getter->IsJSFunction()) break; | |
| 1186 if (!holder->HasFastProperties()) break; | |
| 1187 // When debugging we need to go the slow path to flood the accessor. | |
| 1188 if (GetSharedFunctionInfo()->HasDebugInfo()) break; | |
| 1189 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | |
| 1190 if (!receiver->IsJSObject() && !function->shared()->IsBuiltin() && | |
| 1191 is_sloppy(function->shared()->language_mode())) { | |
| 1192 // Calling sloppy non-builtins with a value as the receiver | |
| 1193 // requires boxing. | |
| 1194 break; | |
| 1195 } | |
| 1196 CallOptimization call_optimization(function); | |
| 1197 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); | |
| 1198 if (call_optimization.is_simple_api_call()) { | |
| 1199 if (call_optimization.IsCompatibleReceiver(receiver, holder)) { | |
| 1200 return compiler.CompileLoadCallback( | 1188 return compiler.CompileLoadCallback( |
| 1201 lookup->name(), call_optimization, lookup->GetAccessorIndex()); | 1189 lookup->name(), call_optimization, lookup->GetAccessorIndex()); |
| 1202 } else { | 1190 } |
| 1191 int expected_arguments = Handle<JSFunction>::cast(getter) |
| 1192 ->shared() |
| 1193 ->internal_formal_parameter_count(); |
| 1194 return compiler.CompileLoadViaGetter( |
| 1195 lookup->name(), lookup->GetAccessorIndex(), expected_arguments); |
| 1196 } else if (accessors->IsAccessorInfo()) { |
| 1197 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors); |
| 1198 if (v8::ToCData<Address>(info->getter()) == 0) break; |
| 1199 if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map)) { |
| 1203 // This case should be already handled in LoadIC::UpdateCaches. | 1200 // This case should be already handled in LoadIC::UpdateCaches. |
| 1204 UNREACHABLE(); | 1201 UNREACHABLE(); |
| 1202 break; |
| 1205 } | 1203 } |
| 1204 if (!holder->HasFastProperties()) break; |
| 1205 NamedLoadHandlerCompiler compiler(isolate(), map, holder, |
| 1206 cache_holder); |
| 1207 return compiler.CompileLoadCallback(lookup->name(), info); |
| 1206 } | 1208 } |
| 1207 int expected_arguments = | |
| 1208 function->shared()->internal_formal_parameter_count(); | |
| 1209 return compiler.CompileLoadViaGetter( | |
| 1210 lookup->name(), lookup->GetAccessorIndex(), expected_arguments); | |
| 1211 } | 1209 } |
| 1212 break; | 1210 break; |
| 1213 } | 1211 } |
| 1214 | 1212 |
| 1215 case LookupIterator::DATA: { | 1213 case LookupIterator::DATA: { |
| 1216 if (lookup->is_dictionary_holder()) { | 1214 if (lookup->is_dictionary_holder()) { |
| 1217 if (kind() != Code::LOAD_IC) break; | 1215 if (kind() != Code::LOAD_IC) break; |
| 1218 if (holder->IsJSGlobalObject()) { | 1216 if (holder->IsJSGlobalObject()) { |
| 1219 NamedLoadHandlerCompiler compiler(isolate(), map, holder, | 1217 NamedLoadHandlerCompiler compiler(isolate(), map, holder, |
| 1220 cache_holder); | 1218 cache_holder); |
| (...skipping 1748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2969 KeyedLoadICNexus nexus(vector, vector_slot); | 2967 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2970 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2968 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2971 ic.UpdateState(receiver, key); | 2969 ic.UpdateState(receiver, key); |
| 2972 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2970 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2973 } | 2971 } |
| 2974 | 2972 |
| 2975 return *result; | 2973 return *result; |
| 2976 } | 2974 } |
| 2977 } // namespace internal | 2975 } // namespace internal |
| 2978 } // namespace v8 | 2976 } // namespace v8 |
| OLD | NEW |