| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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_macros.h" | 7 #include "vm/assembler_macros.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 1073 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1084 kNumNamedArguments); | 1084 kNumNamedArguments); |
| 1085 ASSERT(!target_function.IsNull()); | 1085 ASSERT(!target_function.IsNull()); |
| 1086 GrowableArray<intptr_t> class_ids(kNumArguments); | 1086 GrowableArray<intptr_t> class_ids(kNumArguments); |
| 1087 ASSERT(ic_data.num_args_tested() == kNumArguments); | 1087 ASSERT(ic_data.num_args_tested() == kNumArguments); |
| 1088 class_ids.Add(Class::Handle(receiver.clazz()).id()); | 1088 class_ids.Add(Class::Handle(receiver.clazz()).id()); |
| 1089 class_ids.Add(Class::Handle(arg1.clazz()).id()); | 1089 class_ids.Add(Class::Handle(arg1.clazz()).id()); |
| 1090 ic_data.AddCheck(class_ids, target_function); | 1090 ic_data.AddCheck(class_ids, target_function); |
| 1091 } | 1091 } |
| 1092 | 1092 |
| 1093 | 1093 |
| 1094 // Invoke appropriate noSuchMethod function. |
| 1095 // Arg0: receiver. |
| 1096 // Arg1: ic-data. |
| 1097 // Arg2: arguments descriptor array. |
| 1098 // Arg3: arguments array. |
| 1099 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction, 4) { |
| 1100 ASSERT(arguments.ArgCount() == |
| 1101 kInvokeNoSuchMethodFunctionRuntimeEntry.argument_count()); |
| 1102 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); |
| 1103 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); |
| 1104 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2)); |
| 1105 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3)); |
| 1106 |
| 1107 const String& original_function_name = String::Handle(ic_data.target_name()); |
| 1108 const Object& result = Object::Handle( |
| 1109 DartEntry::InvokeNoSuchMethod(receiver, |
| 1110 original_function_name, |
| 1111 orig_arguments, |
| 1112 orig_arguments_desc)); |
| 1113 CheckResultError(result); |
| 1114 arguments.SetReturn(result); |
| 1115 } |
| 1116 |
| 1117 |
| 1118 // A non-closure object was invoked as a closure, so call the "call" method |
| 1119 // on it. |
| 1120 // Arg0: non-closure object. |
| 1121 // Arg1: arguments descriptor. |
| 1122 // Arg2: arguments array, including non-closure object. |
| 1123 DEFINE_RUNTIME_ENTRY(InvokeNonClosure, 3) { |
| 1124 ASSERT(arguments.ArgCount() == |
| 1125 kInvokeNonClosureRuntimeEntry.argument_count()); |
| 1126 const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0)); |
| 1127 const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(1)); |
| 1128 const Array& function_args = Array::CheckedHandle(arguments.ArgAt(2)); |
| 1129 |
| 1130 const Object& result = Object::Handle( |
| 1131 DartEntry::InvokeClosure(instance, |
| 1132 function_args, |
| 1133 args_descriptor)); |
| 1134 CheckResultError(result); |
| 1135 arguments.SetReturn(result); |
| 1136 } |
| 1137 |
| 1138 |
| 1094 // An instance call could not be resolved by an IC miss handler. Check if | 1139 // An instance call could not be resolved by an IC miss handler. Check if |
| 1095 // it was a getter call and if there is an instance function with the same | 1140 // it was a getter call and if there is an instance function with the same |
| 1096 // name. If so, create and return an implicit closure from the function. | 1141 // name. If so, create and return an implicit closure from the function. |
| 1097 // Otherwise return null. | 1142 // Otherwise return null. |
| 1098 static RawInstance* ResolveImplicitClosure(const Instance& receiver, | 1143 static RawInstance* ResolveImplicitClosure(const Instance& receiver, |
| 1099 const Class& receiver_class, | 1144 const Class& receiver_class, |
| 1100 const String& target_name) { | 1145 const String& target_name) { |
| 1101 // 1. Check if was a getter call. | 1146 // 1. Check if was a getter call. |
| 1102 if (!Field::IsGetterName(target_name)) return Instance::null(); | 1147 if (!Field::IsGetterName(target_name)) return Instance::null(); |
| 1103 | 1148 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1117 Instance::Handle(Closure::New(closure_function, context)); | 1162 Instance::Handle(Closure::New(closure_function, context)); |
| 1118 if (receiver_class.HasTypeArguments()) { | 1163 if (receiver_class.HasTypeArguments()) { |
| 1119 const AbstractTypeArguments& type_arguments = | 1164 const AbstractTypeArguments& type_arguments = |
| 1120 AbstractTypeArguments::Handle(receiver.GetTypeArguments()); | 1165 AbstractTypeArguments::Handle(receiver.GetTypeArguments()); |
| 1121 closure.SetTypeArguments(type_arguments); | 1166 closure.SetTypeArguments(type_arguments); |
| 1122 } | 1167 } |
| 1123 return closure.raw(); | 1168 return closure.raw(); |
| 1124 } | 1169 } |
| 1125 | 1170 |
| 1126 | 1171 |
| 1127 static RawObject* InvokeNoSuchMethod(const Instance& receiver, | |
| 1128 const String& target_name, | |
| 1129 const Array& arguments_descriptor, | |
| 1130 const Array& arguments) { | |
| 1131 // Allocate an InvocationMirror object. | |
| 1132 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | |
| 1133 const String& invocation_mirror_name = | |
| 1134 String::Handle(Symbols::InvocationMirror()); | |
| 1135 Class& invocation_mirror_class = | |
| 1136 Class::Handle(core_lib.LookupClassAllowPrivate(invocation_mirror_name)); | |
| 1137 ASSERT(!invocation_mirror_class.IsNull()); | |
| 1138 const String& allocation_function_name = | |
| 1139 String::Handle(Symbols::AllocateInvocationMirror()); | |
| 1140 const Function& allocation_function = Function::Handle( | |
| 1141 Resolver::ResolveStaticByName(invocation_mirror_class, | |
| 1142 allocation_function_name, | |
| 1143 Resolver::kIsQualified)); | |
| 1144 ASSERT(!allocation_function.IsNull()); | |
| 1145 const int kNumAllocationArgs = 3; | |
| 1146 const Array& allocation_args = Array::Handle(Array::New(kNumAllocationArgs)); | |
| 1147 allocation_args.SetAt(0, target_name); | |
| 1148 allocation_args.SetAt(1, arguments_descriptor); | |
| 1149 allocation_args.SetAt(2, arguments); | |
| 1150 const Object& invocation_mirror = | |
| 1151 Object::Handle(DartEntry::InvokeStatic(allocation_function, | |
| 1152 allocation_args)); | |
| 1153 | |
| 1154 // Now use the invocation mirror object and invoke NoSuchMethod. | |
| 1155 const String& function_name = String::Handle(Symbols::NoSuchMethod()); | |
| 1156 const int kNumArguments = 2; | |
| 1157 const int kNumNamedArguments = 0; | |
| 1158 const Function& function = Function::Handle( | |
| 1159 Resolver::ResolveDynamic(receiver, | |
| 1160 function_name, | |
| 1161 kNumArguments, | |
| 1162 kNumNamedArguments)); | |
| 1163 ASSERT(!function.IsNull()); | |
| 1164 const Array& args = Array::Handle(Array::New(kNumArguments)); | |
| 1165 args.SetAt(0, receiver); | |
| 1166 args.SetAt(1, invocation_mirror); | |
| 1167 const Object& result = Object::Handle(DartEntry::InvokeDynamic(function, | |
| 1168 args)); | |
| 1169 CheckResultError(result); | |
| 1170 return result.raw(); | |
| 1171 } | |
| 1172 | |
| 1173 | |
| 1174 static RawObject* InvokeNonClosure(const Instance& receiver, | |
| 1175 const Class& receiver_class, | |
| 1176 const Array& arguments_descriptor, | |
| 1177 const Array& arguments) { | |
| 1178 // Resolve and invoke the "call" method if it exists. | |
| 1179 const String& call_symbol = String::Handle(Symbols::Call()); | |
| 1180 | |
| 1181 Class& current_class = Class::Handle(receiver_class.raw()); | |
| 1182 Function& call_function = Function::Handle(); | |
| 1183 do { | |
| 1184 call_function = current_class.LookupDynamicFunction(call_symbol); | |
| 1185 | |
| 1186 if (!call_function.IsNull()) { | |
| 1187 // The non-closure object is passed as implicit first argument | |
| 1188 // (receiver). It is already included in the arguments array. | |
| 1189 | |
| 1190 // Now call the invoke stub which will invoke the call method. | |
| 1191 const Object& result = | |
| 1192 Object::Handle(DartEntry::InvokeDynamic(call_function, | |
| 1193 arguments, | |
| 1194 arguments_descriptor)); | |
| 1195 CheckResultError(result); | |
| 1196 return result.raw(); | |
| 1197 } | |
| 1198 | |
| 1199 current_class = current_class.SuperClass(); | |
| 1200 } while (!current_class.IsNull()); | |
| 1201 | |
| 1202 // There is no 'call' method, so invoke noSuchMethod. | |
| 1203 return InvokeNoSuchMethod(receiver, | |
| 1204 call_symbol, | |
| 1205 arguments_descriptor, | |
| 1206 arguments); | |
| 1207 } | |
| 1208 | |
| 1209 | |
| 1210 // An instance call of the form o.f(...) could not be resolved. Check if | 1172 // An instance call of the form o.f(...) could not be resolved. Check if |
| 1211 // there is a getter with the same name. If so, invoke it. If the value is | 1173 // there is a getter with the same name. If so, invoke it. If the value is |
| 1212 // a closure, invoke it with the given arguments. If the value is a | 1174 // a closure, invoke it with the given arguments. If the value is a |
| 1213 // non-closure, attempt to invoke "call" on it. | 1175 // non-closure, attempt to invoke "call" on it. |
| 1214 static bool ResolveCallThroughGetter(const Instance& receiver, | 1176 static bool ResolveCallThroughGetter(const Instance& receiver, |
| 1215 const Class& receiver_class, | 1177 const Class& receiver_class, |
| 1216 const String& target_name, | 1178 const String& target_name, |
| 1217 const Array& arguments_descriptor, | 1179 const Array& arguments_descriptor, |
| 1218 const Array& arguments, | 1180 const Array& arguments, |
| 1219 Object* result) { | 1181 Object* result) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1230 | 1192 |
| 1231 // 2. Invoke the getter. | 1193 // 2. Invoke the getter. |
| 1232 const Array& args = Array::Handle(Array::New(kNumArguments)); | 1194 const Array& args = Array::Handle(Array::New(kNumArguments)); |
| 1233 args.SetAt(0, receiver); | 1195 args.SetAt(0, receiver); |
| 1234 const Object& value = Object::Handle(DartEntry::InvokeDynamic(getter, args)); | 1196 const Object& value = Object::Handle(DartEntry::InvokeDynamic(getter, args)); |
| 1235 | 1197 |
| 1236 // 3. If the getter threw an exception, treat it as no such method. | 1198 // 3. If the getter threw an exception, treat it as no such method. |
| 1237 if (value.IsUnhandledException()) return false; | 1199 if (value.IsUnhandledException()) return false; |
| 1238 | 1200 |
| 1239 // 4. If there was some other error, propagate it. | 1201 // 4. If there was some other error, propagate it. |
| 1240 if (value.IsError()) { | 1202 CheckResultError(value); |
| 1241 Exceptions::PropagateError(Error::Cast(value)); | |
| 1242 } | |
| 1243 | 1203 |
| 1244 // 5. If the value is a closure, invoke it and return the result. If it | 1204 // 5. Invoke the value as a closure. |
| 1245 // is a non-closure, invoke "call" on it and return the result. | |
| 1246 Instance& instance = Instance::Handle(); | 1205 Instance& instance = Instance::Handle(); |
| 1247 instance ^= value.raw(); | 1206 instance ^= value.raw(); |
| 1248 const Class& instance_class = Class::Handle(instance.clazz()); | 1207 arguments.SetAt(0, instance); |
| 1249 ASSERT(!instance_class.IsNull()); | 1208 *result = DartEntry::InvokeClosure(instance, |
| 1250 // An object is a closure iff. its class has a non-null signature function. | 1209 arguments, |
| 1251 if (instance_class.signature_function() != Function::null()) { | 1210 arguments_descriptor); |
| 1252 // The closure object is passed as implicit first argument to closure | 1211 CheckResultError(*result); |
| 1253 // functions, since it may be needed to throw a NoSuchMethodError, in case | |
| 1254 // the wrong number of arguments is passed. | |
| 1255 // Replace the original receiver in the arguments array by the closure. | |
| 1256 arguments.SetAt(0, instance); | |
| 1257 *result = DartEntry::InvokeClosure(instance, | |
| 1258 arguments, | |
| 1259 arguments_descriptor); | |
| 1260 CheckResultError(*result); | |
| 1261 } else { | |
| 1262 *result = InvokeNonClosure(instance, | |
| 1263 instance_class, | |
| 1264 arguments_descriptor, | |
| 1265 arguments); | |
| 1266 } | |
| 1267 return true; | 1212 return true; |
| 1268 } | 1213 } |
| 1269 | 1214 |
| 1270 | 1215 |
| 1271 // Invoke appropriate noSuchMethod function. | |
| 1272 // Arg0: receiver. | |
| 1273 // Arg1: ic-data. | |
| 1274 // Arg2: arguments descriptor array. | |
| 1275 // Arg3: arguments array. | |
| 1276 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction, 4) { | |
| 1277 ASSERT(arguments.ArgCount() == | |
| 1278 kInvokeNoSuchMethodFunctionRuntimeEntry.argument_count()); | |
| 1279 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | |
| 1280 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); | |
| 1281 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2)); | |
| 1282 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3)); | |
| 1283 | |
| 1284 const String& original_function_name = String::Handle(ic_data.target_name()); | |
| 1285 const Object& result = | |
| 1286 Object::Handle(InvokeNoSuchMethod(receiver, | |
| 1287 original_function_name, | |
| 1288 orig_arguments_desc, | |
| 1289 orig_arguments)); | |
| 1290 arguments.SetReturn(result); | |
| 1291 } | |
| 1292 | |
| 1293 | |
| 1294 // A non-closure object was invoked as a closure, so call the "call" method | |
| 1295 // on it. | |
| 1296 // Arg0: non-closure object. | |
| 1297 // Arg1: arguments descriptor. | |
| 1298 // Arg2: arguments array, including non-closure object. | |
| 1299 DEFINE_RUNTIME_ENTRY(InvokeNonClosure, 3) { | |
| 1300 ASSERT(arguments.ArgCount() == | |
| 1301 kInvokeNonClosureRuntimeEntry.argument_count()); | |
| 1302 const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0)); | |
| 1303 const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(1)); | |
| 1304 const Array& function_args = Array::CheckedHandle(arguments.ArgAt(2)); | |
| 1305 | |
| 1306 const Class& instance_class = Class::Handle(instance.clazz()); | |
| 1307 const Object& result = Object::Handle(InvokeNonClosure(instance, | |
| 1308 instance_class, | |
| 1309 args_descriptor, | |
| 1310 function_args)); | |
| 1311 arguments.SetReturn(result); | |
| 1312 } | |
| 1313 | |
| 1314 | |
| 1315 // The IC miss handler has failed to find a (cacheable) instance function to | 1216 // The IC miss handler has failed to find a (cacheable) instance function to |
| 1316 // invoke. Handle three possibilities: | 1217 // invoke. Handle three possibilities: |
| 1317 // | 1218 // |
| 1318 // 1. If the call was a getter o.f, there may be an instance function with | 1219 // 1. If the call was a getter o.f, there may be an instance function with |
| 1319 // the same name. If so, create an implicit closure and return it. | 1220 // the same name. If so, create an implicit closure and return it. |
| 1320 // | 1221 // |
| 1321 // 2. If the call was an instance call o.f(...), there may be a getter with | 1222 // 2. If the call was an instance call o.f(...), there may be a getter with |
| 1322 // the same name. If so, invoke it. If the value is a closure, invoke | 1223 // the same name. If so, invoke it. If the value is a closure, invoke |
| 1323 // it with the given arguments. If the value is a non-closure, attempt | 1224 // it with the given arguments. If the value is a non-closure, attempt |
| 1324 // to invoke "call" on it. | 1225 // to invoke "call" on it. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1347 return; | 1248 return; |
| 1348 } | 1249 } |
| 1349 | 1250 |
| 1350 Object& result = Object::Handle(); | 1251 Object& result = Object::Handle(); |
| 1351 if (!ResolveCallThroughGetter(receiver, | 1252 if (!ResolveCallThroughGetter(receiver, |
| 1352 receiver_class, | 1253 receiver_class, |
| 1353 target_name, | 1254 target_name, |
| 1354 args_descriptor, | 1255 args_descriptor, |
| 1355 args, | 1256 args, |
| 1356 &result)) { | 1257 &result)) { |
| 1357 result = InvokeNoSuchMethod(receiver, target_name, args_descriptor, args); | 1258 result = DartEntry::InvokeNoSuchMethod(receiver, |
| 1259 target_name, |
| 1260 args, |
| 1261 args_descriptor); |
| 1358 } | 1262 } |
| 1263 CheckResultError(result); |
| 1359 arguments.SetReturn(result); | 1264 arguments.SetReturn(result); |
| 1360 } | 1265 } |
| 1361 | 1266 |
| 1362 | 1267 |
| 1363 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { | 1268 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { |
| 1364 ASSERT(arguments.ArgCount() == | 1269 ASSERT(arguments.ArgCount() == |
| 1365 kStackOverflowRuntimeEntry.argument_count()); | 1270 kStackOverflowRuntimeEntry.argument_count()); |
| 1366 uword stack_pos = reinterpret_cast<uword>(&arguments); | 1271 uword stack_pos = reinterpret_cast<uword>(&arguments); |
| 1367 | 1272 |
| 1368 // If an interrupt happens at the same time as a stack overflow, we | 1273 // If an interrupt happens at the same time as a stack overflow, we |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1892 return; | 1797 return; |
| 1893 } | 1798 } |
| 1894 HeapTrace* heap_trace = Isolate::Current()->heap()->trace(); | 1799 HeapTrace* heap_trace = Isolate::Current()->heap()->trace(); |
| 1895 heap_trace->TraceStoreIntoObject(RawObject::ToAddr(object), | 1800 heap_trace->TraceStoreIntoObject(RawObject::ToAddr(object), |
| 1896 field_addr, | 1801 field_addr, |
| 1897 RawObject::ToAddr(value)); | 1802 RawObject::ToAddr(value)); |
| 1898 } | 1803 } |
| 1899 END_LEAF_RUNTIME_ENTRY | 1804 END_LEAF_RUNTIME_ENTRY |
| 1900 | 1805 |
| 1901 } // namespace dart | 1806 } // namespace dart |
| OLD | NEW |