OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/code_generator.h" | 5 #include "vm/code_generator.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/bigint_operations.h" | 9 #include "vm/bigint_operations.h" |
10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
(...skipping 863 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
874 const Array& args_descriptor_array) { | 874 const Array& args_descriptor_array) { |
875 const Instance& receiver = *args[0]; | 875 const Instance& receiver = *args[0]; |
876 const Code& target_code = | 876 const Code& target_code = |
877 Code::Handle(ResolveCompileInstanceCallTarget(receiver, | 877 Code::Handle(ResolveCompileInstanceCallTarget(receiver, |
878 ic_data, | 878 ic_data, |
879 args_descriptor_array)); | 879 args_descriptor_array)); |
880 if (target_code.IsNull()) { | 880 if (target_code.IsNull()) { |
881 // Let the megamorphic stub handle special cases: NoSuchMethod, | 881 // Let the megamorphic stub handle special cases: NoSuchMethod, |
882 // closure calls. | 882 // closure calls. |
883 if (FLAG_trace_ic) { | 883 if (FLAG_trace_ic) { |
884 OS::PrintErr("InlineCacheMissHandler NULL code for receiver: %s\n", | 884 OS::PrintErr("InlineCacheMissHandler NULL code for %s receiver: %s\n", |
885 receiver.ToCString()); | 885 String::Handle(ic_data.target_name()).ToCString(), |
| 886 receiver.ToCString()); |
886 } | 887 } |
887 return Function::null(); | 888 return Function::null(); |
888 } | 889 } |
889 const Function& target_function = | 890 const Function& target_function = |
890 Function::Handle(target_code.function()); | 891 Function::Handle(target_code.function()); |
891 ASSERT(!target_function.IsNull()); | 892 ASSERT(!target_function.IsNull()); |
892 if (args.length() == 1) { | 893 if (args.length() == 1) { |
893 ic_data.AddReceiverCheck(args[0]->GetClassId(), target_function); | 894 ic_data.AddReceiverCheck(args[0]->GetClassId(), target_function); |
894 } else { | 895 } else { |
895 GrowableArray<intptr_t> class_ids(args.length()); | 896 GrowableArray<intptr_t> class_ids(args.length()); |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1150 Object* result) { | 1151 Object* result) { |
1151 // 1. Check if there is a getter with the same name. | 1152 // 1. Check if there is a getter with the same name. |
1152 const String& getter_name = String::Handle(Field::GetterName(target_name)); | 1153 const String& getter_name = String::Handle(Field::GetterName(target_name)); |
1153 const int kNumArguments = 1; | 1154 const int kNumArguments = 1; |
1154 const int kNumNamedArguments = 0; | 1155 const int kNumNamedArguments = 0; |
1155 const Function& getter = Function::Handle( | 1156 const Function& getter = Function::Handle( |
1156 Resolver::ResolveDynamicForReceiverClass(receiver_class, | 1157 Resolver::ResolveDynamicForReceiverClass(receiver_class, |
1157 getter_name, | 1158 getter_name, |
1158 kNumArguments, | 1159 kNumArguments, |
1159 kNumNamedArguments)); | 1160 kNumNamedArguments)); |
1160 if (getter.IsNull() || getter.IsMethodExtractor()) { | 1161 if (getter.IsNull() || |
| 1162 getter.IsMethodExtractor() || |
| 1163 getter.IsNoSuchMethodDispatcher()) { |
1161 return false; | 1164 return false; |
1162 } | 1165 } |
1163 | 1166 |
1164 // 2. Invoke the getter. | 1167 // 2. Invoke the getter. |
1165 const Array& args = Array::Handle(Array::New(kNumArguments)); | 1168 const Array& args = Array::Handle(Array::New(kNumArguments)); |
1166 args.SetAt(0, receiver); | 1169 args.SetAt(0, receiver); |
1167 const Object& value = Object::Handle(DartEntry::InvokeFunction(getter, args)); | 1170 const Object& value = Object::Handle(DartEntry::InvokeFunction(getter, args)); |
1168 | 1171 |
1169 // 3. If the getter threw an exception, treat it as no such method. | 1172 // 3. If the getter threw an exception, treat it as no such method. |
1170 if (value.IsUnhandledException()) return false; | 1173 if (value.IsUnhandledException()) return false; |
1171 | 1174 |
1172 // 4. If there was some other error, propagate it. | 1175 // 4. If there was some other error, propagate it. |
1173 CheckResultError(value); | 1176 CheckResultError(value); |
1174 | 1177 |
1175 // 5. Invoke the value as a closure. | 1178 // 5. Invoke the value as a closure. |
1176 Instance& instance = Instance::Handle(); | 1179 Instance& instance = Instance::Handle(); |
1177 instance ^= value.raw(); | 1180 instance ^= value.raw(); |
1178 arguments.SetAt(0, instance); | 1181 arguments.SetAt(0, instance); |
1179 *result = DartEntry::InvokeClosure(arguments, arguments_descriptor); | 1182 *result = DartEntry::InvokeClosure(arguments, arguments_descriptor); |
1180 CheckResultError(*result); | 1183 CheckResultError(*result); |
1181 return true; | 1184 return true; |
1182 } | 1185 } |
1183 | 1186 |
1184 | 1187 |
| 1188 // Create a method for noSuchMethod invocation and attach it to the receiver |
| 1189 // class. |
| 1190 static RawFunction* CreateNoSuchMethodDispatcher( |
| 1191 const String& target_name, |
| 1192 const Class& receiver_class, |
| 1193 const Array& arguments_descriptor) { |
| 1194 Function& invocation = Function::Handle( |
| 1195 Function::New(String::Handle(Symbols::New(target_name)), |
| 1196 RawFunction::kNoSuchMethodDispatcher, |
| 1197 false, // Not static. |
| 1198 false, // Not const. |
| 1199 false, // Not abstract. |
| 1200 false, // Not external. |
| 1201 receiver_class, |
| 1202 0)); // No token position. |
| 1203 |
| 1204 // Initialize signature: receiver is a single fixed parameter. |
| 1205 const intptr_t kNumParameters = 1; |
| 1206 invocation.set_num_fixed_parameters(kNumParameters); |
| 1207 invocation.SetNumOptionalParameters(0, 0); |
| 1208 invocation.set_parameter_types(Array::Handle(Array::New(kNumParameters, |
| 1209 Heap::kOld))); |
| 1210 invocation.set_parameter_names(Array::Handle(Array::New(kNumParameters, |
| 1211 Heap::kOld))); |
| 1212 invocation.SetParameterTypeAt(0, Type::Handle(Type::DynamicType())); |
| 1213 invocation.SetParameterNameAt(0, Symbols::This()); |
| 1214 invocation.set_result_type(Type::Handle(Type::DynamicType())); |
| 1215 invocation.set_is_visible(false); // Not visible in stack trace. |
| 1216 |
| 1217 receiver_class.AddFunction(invocation); |
| 1218 |
| 1219 return invocation.raw(); |
| 1220 } |
| 1221 |
| 1222 |
1185 // The IC miss handler has failed to find a (cacheable) instance function to | 1223 // The IC miss handler has failed to find a (cacheable) instance function to |
1186 // invoke. Handle three possibilities: | 1224 // invoke. Handle three possibilities: |
1187 // | 1225 // |
1188 // 1. If the call was a getter o.f, there may be an instance function with | 1226 // 1. If the call was a getter o.f, there may be an instance function with |
1189 // the same name. If so, create an implicit closure and return it. | 1227 // the same name. If so, create an implicit closure and return it. |
1190 // | 1228 // |
1191 // 2. If the call was an instance call o.f(...), there may be a getter with | 1229 // 2. If the call was an instance call o.f(...), there may be a getter with |
1192 // the same name. If so, invoke it. If the value is a closure, invoke | 1230 // the same name. If so, invoke it. If the value is a closure, invoke |
1193 // it with the given arguments. If the value is a non-closure, attempt | 1231 // it with the given arguments. If the value is a non-closure, attempt |
1194 // to invoke "call" on it. | 1232 // to invoke "call" on it. |
(...skipping 14 matching lines...) Expand all Loading... |
1209 } | 1247 } |
1210 const String& target_name = String::Handle(ic_data.target_name()); | 1248 const String& target_name = String::Handle(ic_data.target_name()); |
1211 | 1249 |
1212 Object& result = Object::Handle(); | 1250 Object& result = Object::Handle(); |
1213 if (!ResolveCallThroughGetter(receiver, | 1251 if (!ResolveCallThroughGetter(receiver, |
1214 receiver_class, | 1252 receiver_class, |
1215 target_name, | 1253 target_name, |
1216 args_descriptor, | 1254 args_descriptor, |
1217 args, | 1255 args, |
1218 &result)) { | 1256 &result)) { |
1219 result = DartEntry::InvokeNoSuchMethod(receiver, | 1257 ArgumentsDescriptor desc(args_descriptor); |
1220 target_name, | 1258 // TODO(fschneider): Handle multiple arguments. |
1221 args, | 1259 if ((desc.Count() == 1) && (desc.PositionalCount() == 1)) { |
1222 args_descriptor); | 1260 // Create Function for noSuchMethodInvocation and add it to the class. |
| 1261 Function& target_function = Function::Handle(); |
| 1262 target_function ^= CreateNoSuchMethodDispatcher(target_name, |
| 1263 receiver_class, |
| 1264 args_descriptor); |
| 1265 |
| 1266 // Update IC data. |
| 1267 ASSERT(!target_function.IsNull()); |
| 1268 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); |
| 1269 if (FLAG_trace_ic) { |
| 1270 OS::PrintErr("NoSuchMethod IC miss: adding <%s> id:%"Pd" -> <%s>\n", |
| 1271 Class::Handle(receiver.clazz()).ToCString(), |
| 1272 receiver.GetClassId(), |
| 1273 target_function.ToCString()); |
| 1274 } |
| 1275 result = |
| 1276 DartEntry::InvokeFunction(target_function, args, args_descriptor); |
| 1277 } else { |
| 1278 result = DartEntry::InvokeNoSuchMethod(receiver, |
| 1279 target_name, |
| 1280 args, |
| 1281 args_descriptor); |
| 1282 } |
1223 } | 1283 } |
1224 CheckResultError(result); | 1284 CheckResultError(result); |
1225 arguments.SetReturn(result); | 1285 arguments.SetReturn(result); |
1226 } | 1286 } |
1227 | 1287 |
1228 | 1288 |
1229 static bool CanOptimizeFunction(const Function& function, Isolate* isolate) { | 1289 static bool CanOptimizeFunction(const Function& function, Isolate* isolate) { |
1230 const intptr_t kLowInvocationCount = -100000000; | 1290 const intptr_t kLowInvocationCount = -100000000; |
1231 if (isolate->debugger()->HasBreakpoint(function)) { | 1291 if (isolate->debugger()->HasBreakpoint(function)) { |
1232 // We cannot set breakpoints in optimized code, so do not optimize | 1292 // We cannot set breakpoints in optimized code, so do not optimize |
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1806 // Arg1: Value that is being stored. | 1866 // Arg1: Value that is being stored. |
1807 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { | 1867 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { |
1808 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count()); | 1868 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count()); |
1809 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); | 1869 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); |
1810 const Object& value = Object::Handle(arguments.ArgAt(1)); | 1870 const Object& value = Object::Handle(arguments.ArgAt(1)); |
1811 | 1871 |
1812 field.UpdateCid(value.GetClassId()); | 1872 field.UpdateCid(value.GetClassId()); |
1813 } | 1873 } |
1814 | 1874 |
1815 } // namespace dart | 1875 } // namespace dart |
OLD | NEW |