OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/runtime_entry.h" | 5 #include "vm/runtime_entry.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 // there is a getter with the same name. If so, invoke it. If the value is | 851 // there is a getter with the same name. If so, invoke it. If the value is |
852 // a closure, invoke it with the given arguments. If the value is a | 852 // a closure, invoke it with the given arguments. If the value is a |
853 // non-closure, attempt to invoke "call" on it. | 853 // non-closure, attempt to invoke "call" on it. |
854 static bool ResolveCallThroughGetter(const Instance& receiver, | 854 static bool ResolveCallThroughGetter(const Instance& receiver, |
855 const Class& receiver_class, | 855 const Class& receiver_class, |
856 const String& target_name, | 856 const String& target_name, |
857 const Array& arguments_descriptor, | 857 const Array& arguments_descriptor, |
858 Function* result) { | 858 Function* result) { |
859 // 1. Check if there is a getter with the same name. | 859 // 1. Check if there is a getter with the same name. |
860 const String& getter_name = String::Handle(Field::GetterName(target_name)); | 860 const String& getter_name = String::Handle(Field::GetterName(target_name)); |
| 861 const int kTypeArgsLen = 0; |
861 const int kNumArguments = 1; | 862 const int kNumArguments = 1; |
862 ArgumentsDescriptor args_desc( | 863 ArgumentsDescriptor args_desc( |
863 Array::Handle(ArgumentsDescriptor::New(kNumArguments))); | 864 Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments))); |
864 const Function& getter = | 865 const Function& getter = |
865 Function::Handle(Resolver::ResolveDynamicForReceiverClass( | 866 Function::Handle(Resolver::ResolveDynamicForReceiverClass( |
866 receiver_class, getter_name, args_desc)); | 867 receiver_class, getter_name, args_desc)); |
867 if (getter.IsNull() || getter.IsMethodExtractor()) { | 868 if (getter.IsNull() || getter.IsMethodExtractor()) { |
868 return false; | 869 return false; |
869 } | 870 } |
870 const Function& target_function = | 871 const Function& target_function = |
871 Function::Handle(receiver_class.GetInvocationDispatcher( | 872 Function::Handle(receiver_class.GetInvocationDispatcher( |
872 target_name, arguments_descriptor, | 873 target_name, arguments_descriptor, |
873 RawFunction::kInvokeFieldDispatcher, FLAG_lazy_dispatchers)); | 874 RawFunction::kInvokeFieldDispatcher, FLAG_lazy_dispatchers)); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 ObjectStore* store = Isolate::Current()->object_store(); | 924 ObjectStore* store = Isolate::Current()->object_store(); |
924 const Function& target = | 925 const Function& target = |
925 Function::Handle(result ? store->simple_instance_of_true_function() | 926 Function::Handle(result ? store->simple_instance_of_true_function() |
926 : store->simple_instance_of_false_function()); | 927 : store->simple_instance_of_false_function()); |
927 ASSERT(!target.IsNull()); | 928 ASSERT(!target.IsNull()); |
928 return target.raw(); | 929 return target.raw(); |
929 } | 930 } |
930 | 931 |
931 | 932 |
932 static RawFunction* InlineCacheMissHandler( | 933 static RawFunction* InlineCacheMissHandler( |
933 const GrowableArray<const Instance*>& args, | 934 const GrowableArray<const Instance*>& args, // Checked arguments only. |
934 const ICData& ic_data) { | 935 const ICData& ic_data) { |
935 const Instance& receiver = *args[0]; | 936 const Instance& receiver = *args[0]; |
936 ArgumentsDescriptor arguments_descriptor( | 937 ArgumentsDescriptor arguments_descriptor( |
937 Array::Handle(ic_data.arguments_descriptor())); | 938 Array::Handle(ic_data.arguments_descriptor())); |
938 String& function_name = String::Handle(ic_data.target_name()); | 939 String& function_name = String::Handle(ic_data.target_name()); |
939 ASSERT(function_name.IsSymbol()); | 940 ASSERT(function_name.IsSymbol()); |
940 | 941 |
941 Function& target_function = Function::Handle( | 942 Function& target_function = Function::Handle( |
942 Resolver::ResolveDynamic(receiver, function_name, arguments_descriptor)); | 943 Resolver::ResolveDynamic(receiver, function_name, arguments_descriptor)); |
943 | 944 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1137 SingleTargetCache& cache = SingleTargetCache::Handle(zone); | 1138 SingleTargetCache& cache = SingleTargetCache::Handle(zone); |
1138 cache ^= | 1139 cache ^= |
1139 CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), caller_code); | 1140 CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), caller_code); |
1140 Code& old_target_code = Code::Handle(zone, cache.target()); | 1141 Code& old_target_code = Code::Handle(zone, cache.target()); |
1141 Function& old_target = Function::Handle(zone); | 1142 Function& old_target = Function::Handle(zone); |
1142 old_target ^= old_target_code.owner(); | 1143 old_target ^= old_target_code.owner(); |
1143 | 1144 |
1144 // We lost the original ICData when we patched to the monomorphic case. | 1145 // We lost the original ICData when we patched to the monomorphic case. |
1145 const String& name = String::Handle(zone, old_target.name()); | 1146 const String& name = String::Handle(zone, old_target.name()); |
1146 ASSERT(!old_target.HasOptionalParameters()); | 1147 ASSERT(!old_target.HasOptionalParameters()); |
1147 const Array& descriptor = Array::Handle( | 1148 ASSERT(!old_target.IsGeneric()); |
1148 zone, ArgumentsDescriptor::New(old_target.num_fixed_parameters())); | 1149 const int kTypeArgsLen = 0; |
| 1150 const Array& descriptor = |
| 1151 Array::Handle(zone, ArgumentsDescriptor::New( |
| 1152 kTypeArgsLen, old_target.num_fixed_parameters())); |
1149 const ICData& ic_data = | 1153 const ICData& ic_data = |
1150 ICData::Handle(zone, ICData::New(caller_function, name, descriptor, | 1154 ICData::Handle(zone, ICData::New(caller_function, name, descriptor, |
1151 Thread::kNoDeoptId, 1, /* args_tested */ | 1155 Thread::kNoDeoptId, 1, /* args_tested */ |
1152 false /* static_call */)); | 1156 false /* static_call */)); |
1153 | 1157 |
1154 // Maybe add the new target. | 1158 // Maybe add the new target. |
1155 Class& cls = Class::Handle(zone, receiver.clazz()); | 1159 Class& cls = Class::Handle(zone, receiver.clazz()); |
1156 ArgumentsDescriptor args_desc(descriptor); | 1160 ArgumentsDescriptor args_desc(descriptor); |
1157 Function& target_function = Function::Handle( | 1161 Function& target_function = Function::Handle( |
1158 zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc)); | 1162 zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc)); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1234 zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc)); | 1238 zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc)); |
1235 if (target_function.IsNull()) { | 1239 if (target_function.IsNull()) { |
1236 target_function = InlineCacheMissHelper(receiver, descriptor, name); | 1240 target_function = InlineCacheMissHelper(receiver, descriptor, name); |
1237 } | 1241 } |
1238 if (target_function.IsNull()) { | 1242 if (target_function.IsNull()) { |
1239 ASSERT(!FLAG_lazy_dispatchers); | 1243 ASSERT(!FLAG_lazy_dispatchers); |
1240 } else { | 1244 } else { |
1241 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); | 1245 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); |
1242 } | 1246 } |
1243 | 1247 |
1244 if (!target_function.IsNull() && !target_function.HasOptionalParameters()) { | 1248 if (!target_function.IsNull() && !target_function.HasOptionalParameters() && |
| 1249 !target_function.IsGeneric()) { |
1245 // Patch to monomorphic call. | 1250 // Patch to monomorphic call. |
1246 ASSERT(target_function.HasCode()); | 1251 ASSERT(target_function.HasCode()); |
1247 const Code& target_code = Code::Handle(zone, target_function.CurrentCode()); | 1252 const Code& target_code = Code::Handle(zone, target_function.CurrentCode()); |
1248 const Smi& expected_cid = | 1253 const Smi& expected_cid = |
1249 Smi::Handle(zone, Smi::New(receiver.GetClassId())); | 1254 Smi::Handle(zone, Smi::New(receiver.GetClassId())); |
1250 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, | 1255 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, |
1251 expected_cid, target_code); | 1256 expected_cid, target_code); |
1252 | 1257 |
1253 // Return the ICData. The miss stub will jump to continue in the IC call | 1258 // Return the ICData. The miss stub will jump to continue in the IC call |
1254 // stub. | 1259 // stub. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1292 old_expected_cid ^= | 1297 old_expected_cid ^= |
1293 CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), caller_code); | 1298 CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), caller_code); |
1294 const Code& old_target_code = Code::Handle( | 1299 const Code& old_target_code = Code::Handle( |
1295 CodePatcher::GetSwitchableCallTargetAt(caller_frame->pc(), caller_code)); | 1300 CodePatcher::GetSwitchableCallTargetAt(caller_frame->pc(), caller_code)); |
1296 Function& old_target = Function::Handle(zone); | 1301 Function& old_target = Function::Handle(zone); |
1297 old_target ^= old_target_code.owner(); | 1302 old_target ^= old_target_code.owner(); |
1298 | 1303 |
1299 // We lost the original ICData when we patched to the monomorphic case. | 1304 // We lost the original ICData when we patched to the monomorphic case. |
1300 const String& name = String::Handle(zone, old_target.name()); | 1305 const String& name = String::Handle(zone, old_target.name()); |
1301 ASSERT(!old_target.HasOptionalParameters()); | 1306 ASSERT(!old_target.HasOptionalParameters()); |
1302 const Array& descriptor = Array::Handle( | 1307 ASSERT(!old_target.IsGeneric()); |
1303 zone, ArgumentsDescriptor::New(old_target.num_fixed_parameters())); | 1308 const int kTypeArgsLen = 0; |
| 1309 const Array& descriptor = |
| 1310 Array::Handle(zone, ArgumentsDescriptor::New( |
| 1311 kTypeArgsLen, old_target.num_fixed_parameters())); |
1304 const ICData& ic_data = | 1312 const ICData& ic_data = |
1305 ICData::Handle(zone, ICData::New(caller_function, name, descriptor, | 1313 ICData::Handle(zone, ICData::New(caller_function, name, descriptor, |
1306 Thread::kNoDeoptId, 1, /* args_tested */ | 1314 Thread::kNoDeoptId, 1, /* args_tested */ |
1307 false /* static_call */)); | 1315 false /* static_call */)); |
1308 | 1316 |
1309 // Add the first target. | 1317 // Add the first target. |
1310 ic_data.AddReceiverCheck(old_expected_cid.Value(), old_target); | 1318 ic_data.AddReceiverCheck(old_expected_cid.Value(), old_target); |
1311 | 1319 |
1312 // Maybe add the new target. | 1320 // Maybe add the new target. |
1313 Class& cls = Class::Handle(zone, receiver.clazz()); | 1321 Class& cls = Class::Handle(zone, receiver.clazz()); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1402 if (target_function.IsNull()) { | 1410 if (target_function.IsNull()) { |
1403 ASSERT(!FLAG_lazy_dispatchers); | 1411 ASSERT(!FLAG_lazy_dispatchers); |
1404 arguments.SetReturn(target_function); | 1412 arguments.SetReturn(target_function); |
1405 return; | 1413 return; |
1406 } | 1414 } |
1407 | 1415 |
1408 if (ic_data_or_cache.IsICData()) { | 1416 if (ic_data_or_cache.IsICData()) { |
1409 const ICData& ic_data = ICData::Cast(ic_data_or_cache); | 1417 const ICData& ic_data = ICData::Cast(ic_data_or_cache); |
1410 const intptr_t number_of_checks = ic_data.NumberOfChecks(); | 1418 const intptr_t number_of_checks = ic_data.NumberOfChecks(); |
1411 | 1419 |
1412 if (number_of_checks == 0 && !target_function.HasOptionalParameters() && | 1420 if ((number_of_checks == 0) && !target_function.HasOptionalParameters() && |
| 1421 !target_function.IsGeneric() && |
1413 !Isolate::Current()->compilation_allowed()) { | 1422 !Isolate::Current()->compilation_allowed()) { |
1414 // This call site is unlinked: transition to a monomorphic direct call. | 1423 // This call site is unlinked: transition to a monomorphic direct call. |
1415 // Note we cannot do this if the target has optional parameters because | 1424 // Note we cannot do this if the target has optional parameters because |
1416 // the monomorphic direct call does not load the arguments descriptor. | 1425 // the monomorphic direct call does not load the arguments descriptor. |
1417 // We cannot do this if we are still in the middle of precompiling because | 1426 // We cannot do this if we are still in the middle of precompiling because |
1418 // the monomorphic case hides an live instance selector from the | 1427 // the monomorphic case hides an live instance selector from the |
1419 // treeshaker. | 1428 // treeshaker. |
1420 | 1429 |
1421 const Code& target_code = | 1430 const Code& target_code = |
1422 Code::Handle(zone, target_function.EnsureHasCode()); | 1431 Code::Handle(zone, target_function.EnsureHasCode()); |
(...skipping 922 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2345 const intptr_t new_size = 2 * old_size; | 2354 const intptr_t new_size = 2 * old_size; |
2346 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 2355 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
2347 const TypedData& new_data = | 2356 const TypedData& new_data = |
2348 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 2357 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
2349 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 2358 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
2350 typed_data_cell.SetAt(0, new_data); | 2359 typed_data_cell.SetAt(0, new_data); |
2351 arguments.SetReturn(new_data); | 2360 arguments.SetReturn(new_data); |
2352 } | 2361 } |
2353 | 2362 |
2354 } // namespace dart | 2363 } // namespace dart |
OLD | NEW |