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 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1151 Object* result) { | 1151 Object* result) { |
1152 // 1. Check if there is a getter with the same name. | 1152 // 1. Check if there is a getter with the same name. |
1153 const String& getter_name = String::Handle(Field::GetterName(target_name)); | 1153 const String& getter_name = String::Handle(Field::GetterName(target_name)); |
1154 const int kNumArguments = 1; | 1154 const int kNumArguments = 1; |
1155 const int kNumNamedArguments = 0; | 1155 const int kNumNamedArguments = 0; |
1156 const Function& getter = Function::Handle( | 1156 const Function& getter = Function::Handle( |
1157 Resolver::ResolveDynamicForReceiverClass(receiver_class, | 1157 Resolver::ResolveDynamicForReceiverClass(receiver_class, |
1158 getter_name, | 1158 getter_name, |
1159 kNumArguments, | 1159 kNumArguments, |
1160 kNumNamedArguments)); | 1160 kNumNamedArguments)); |
1161 if (getter.IsNull() || | 1161 if (getter.IsNull() || getter.IsMethodExtractor()) { |
1162 getter.IsMethodExtractor() || | |
1163 getter.IsNoSuchMethodDispatcher()) { | |
1164 return false; | 1162 return false; |
1165 } | 1163 } |
1166 | 1164 |
1167 // 2. Invoke the getter. | 1165 // 2. Invoke the getter. |
1168 const Array& args = Array::Handle(Array::New(kNumArguments)); | 1166 const Array& args = Array::Handle(Array::New(kNumArguments)); |
1169 args.SetAt(0, receiver); | 1167 args.SetAt(0, receiver); |
1170 const Object& value = Object::Handle(DartEntry::InvokeFunction(getter, args)); | 1168 const Object& value = Object::Handle(DartEntry::InvokeFunction(getter, args)); |
1171 | 1169 |
1172 // 3. If there was some error, propagate it. | 1170 // 3. If there was some error, propagate it. |
1173 CheckResultError(value); | 1171 CheckResultError(value); |
1174 | 1172 |
1175 // 4. Invoke the value as a closure. | 1173 // 4. Invoke the value as a closure. |
1176 Instance& instance = Instance::Handle(); | 1174 Instance& instance = Instance::Handle(); |
1177 instance ^= value.raw(); | 1175 instance ^= value.raw(); |
1178 arguments.SetAt(0, instance); | 1176 arguments.SetAt(0, instance); |
1179 *result = DartEntry::InvokeClosure(arguments, arguments_descriptor); | 1177 *result = DartEntry::InvokeClosure(arguments, arguments_descriptor); |
1180 CheckResultError(*result); | 1178 CheckResultError(*result); |
1181 return true; | 1179 return true; |
1182 } | 1180 } |
1183 | 1181 |
1184 | 1182 |
1185 // Create a method for noSuchMethod invocation and attach it to the receiver | |
1186 // class. | |
1187 static RawFunction* CreateNoSuchMethodDispatcher( | |
1188 const String& target_name, | |
1189 const Class& receiver_class, | |
1190 const Array& arguments_descriptor) { | |
1191 Function& invocation = Function::Handle( | |
1192 Function::New(String::Handle(Symbols::New(target_name)), | |
1193 RawFunction::kNoSuchMethodDispatcher, | |
1194 false, // Not static. | |
1195 false, // Not const. | |
1196 false, // Not abstract. | |
1197 false, // Not external. | |
1198 receiver_class, | |
1199 0)); // No token position. | |
1200 | |
1201 // Initialize signature: receiver is a single fixed parameter. | |
1202 const intptr_t kNumParameters = 1; | |
1203 invocation.set_num_fixed_parameters(kNumParameters); | |
1204 invocation.SetNumOptionalParameters(0, 0); | |
1205 invocation.set_parameter_types(Array::Handle(Array::New(kNumParameters, | |
1206 Heap::kOld))); | |
1207 invocation.set_parameter_names(Array::Handle(Array::New(kNumParameters, | |
1208 Heap::kOld))); | |
1209 invocation.SetParameterTypeAt(0, Type::Handle(Type::DynamicType())); | |
1210 invocation.SetParameterNameAt(0, Symbols::This()); | |
1211 invocation.set_result_type(Type::Handle(Type::DynamicType())); | |
1212 invocation.set_is_visible(false); // Not visible in stack trace. | |
1213 | |
1214 receiver_class.AddFunction(invocation); | |
1215 | |
1216 return invocation.raw(); | |
1217 } | |
1218 | |
1219 | |
1220 // The IC miss handler has failed to find a (cacheable) instance function to | 1183 // The IC miss handler has failed to find a (cacheable) instance function to |
1221 // invoke. Handle three possibilities: | 1184 // invoke. Handle three possibilities: |
1222 // | 1185 // |
1223 // 1. If the call was a getter o.f, there may be an instance function with | 1186 // 1. If the call was a getter o.f, there may be an instance function with |
1224 // the same name. If so, create an implicit closure and return it. | 1187 // the same name. If so, create an implicit closure and return it. |
1225 // | 1188 // |
1226 // 2. If the call was an instance call o.f(...), there may be a getter with | 1189 // 2. If the call was an instance call o.f(...), there may be a getter with |
1227 // the same name. If so, invoke it. If the value is a closure, invoke | 1190 // the same name. If so, invoke it. If the value is a closure, invoke |
1228 // it with the given arguments. If the value is a non-closure, attempt | 1191 // it with the given arguments. If the value is a non-closure, attempt |
1229 // to invoke "call" on it. | 1192 // to invoke "call" on it. |
(...skipping 15 matching lines...) Expand all Loading... |
1245 const String& target_name = String::Handle(ic_data.target_name()); | 1208 const String& target_name = String::Handle(ic_data.target_name()); |
1246 | 1209 |
1247 Object& result = Object::Handle(); | 1210 Object& result = Object::Handle(); |
1248 if (!ResolveCallThroughGetter(receiver, | 1211 if (!ResolveCallThroughGetter(receiver, |
1249 receiver_class, | 1212 receiver_class, |
1250 target_name, | 1213 target_name, |
1251 args_descriptor, | 1214 args_descriptor, |
1252 args, | 1215 args, |
1253 &result)) { | 1216 &result)) { |
1254 ArgumentsDescriptor desc(args_descriptor); | 1217 ArgumentsDescriptor desc(args_descriptor); |
1255 Function& target_function = Function::Handle( | 1218 const Function& target_function = Function::Handle( |
1256 Resolver::ResolveDynamicAnyArgs(receiver_class, target_name)); | 1219 receiver_class.GetNoSuchMethodDispatcher(target_name, args_descriptor)); |
1257 // Check number of arguments and check that there is not already a method | 1220 // Update IC data. |
1258 // with the same name present. | 1221 ASSERT(!target_function.IsNull()); |
1259 // TODO(fschneider): Handle multiple arguments. | 1222 if (ic_data.num_args_tested() == 1) { |
1260 if (target_function.IsNull() && | |
1261 (desc.Count() == 1) && (desc.PositionalCount() == 1)) { | |
1262 // Create Function for noSuchMethodInvocation and add it to the class. | |
1263 target_function ^= CreateNoSuchMethodDispatcher(target_name, | |
1264 receiver_class, | |
1265 args_descriptor); | |
1266 | |
1267 // Update IC data. | |
1268 ASSERT(!target_function.IsNull()); | |
1269 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); | 1223 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); |
1270 if (FLAG_trace_ic) { | 1224 } else { |
1271 OS::PrintErr("NoSuchMethod IC miss: adding <%s> id:%"Pd" -> <%s>\n", | 1225 // Operators calls have two or three arguments tested ([], []=, etc.) |
1272 Class::Handle(receiver.clazz()).ToCString(), | 1226 ASSERT(ic_data.num_args_tested() > 1); |
1273 receiver.GetClassId(), | 1227 GrowableArray<intptr_t> class_ids(ic_data.num_args_tested()); |
1274 target_function.ToCString()); | 1228 class_ids.Add(receiver.GetClassId()); |
| 1229 for (intptr_t i = 1; i < ic_data.num_args_tested(); ++i) { |
| 1230 class_ids.Add(Object::Handle(args.At(i)).GetClassId()); |
1275 } | 1231 } |
1276 result = | 1232 ic_data.AddCheck(class_ids, target_function); |
1277 DartEntry::InvokeFunction(target_function, args, args_descriptor); | |
1278 } else { | |
1279 result = DartEntry::InvokeNoSuchMethod(receiver, | |
1280 target_name, | |
1281 args, | |
1282 args_descriptor); | |
1283 } | 1233 } |
| 1234 if (FLAG_trace_ic) { |
| 1235 OS::PrintErr("NoSuchMethod IC miss: adding <%s> id:%"Pd" -> <%s>\n", |
| 1236 Class::Handle(receiver.clazz()).ToCString(), |
| 1237 receiver.GetClassId(), |
| 1238 target_function.ToCString()); |
| 1239 } |
| 1240 result = DartEntry::InvokeFunction(target_function, args, args_descriptor); |
1284 } | 1241 } |
1285 CheckResultError(result); | 1242 CheckResultError(result); |
1286 arguments.SetReturn(result); | 1243 arguments.SetReturn(result); |
1287 } | 1244 } |
1288 | 1245 |
1289 | 1246 |
1290 static bool CanOptimizeFunction(const Function& function, Isolate* isolate) { | 1247 static bool CanOptimizeFunction(const Function& function, Isolate* isolate) { |
1291 const intptr_t kLowInvocationCount = -100000000; | 1248 const intptr_t kLowInvocationCount = -100000000; |
1292 if (isolate->debugger()->HasBreakpoint(function)) { | 1249 if (isolate->debugger()->HasBreakpoint(function)) { |
1293 // We cannot set breakpoints in optimized code, so do not optimize | 1250 // We cannot set breakpoints in optimized code, so do not optimize |
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1868 // Arg1: Value that is being stored. | 1825 // Arg1: Value that is being stored. |
1869 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { | 1826 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { |
1870 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count()); | 1827 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count()); |
1871 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); | 1828 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); |
1872 const Object& value = Object::Handle(arguments.ArgAt(1)); | 1829 const Object& value = Object::Handle(arguments.ArgAt(1)); |
1873 | 1830 |
1874 field.UpdateCid(value.GetClassId()); | 1831 field.UpdateCid(value.GetClassId()); |
1875 } | 1832 } |
1876 | 1833 |
1877 } // namespace dart | 1834 } // namespace dart |
OLD | NEW |