| 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 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1117 Instance::Handle(Closure::New(closure_function, context)); | 1117 Instance::Handle(Closure::New(closure_function, context)); |
| 1118 if (receiver_class.HasTypeArguments()) { | 1118 if (receiver_class.HasTypeArguments()) { |
| 1119 const AbstractTypeArguments& type_arguments = | 1119 const AbstractTypeArguments& type_arguments = |
| 1120 AbstractTypeArguments::Handle(receiver.GetTypeArguments()); | 1120 AbstractTypeArguments::Handle(receiver.GetTypeArguments()); |
| 1121 closure.SetTypeArguments(type_arguments); | 1121 closure.SetTypeArguments(type_arguments); |
| 1122 } | 1122 } |
| 1123 return closure.raw(); | 1123 return closure.raw(); |
| 1124 } | 1124 } |
| 1125 | 1125 |
| 1126 | 1126 |
| 1127 static RawInstructions* EnsureCompiled(const Function& function) { | |
| 1128 if (!function.HasCode()) { | |
| 1129 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | |
| 1130 if (!error.IsNull()) { | |
| 1131 Exceptions::PropagateError(error); | |
| 1132 } | |
| 1133 } | |
| 1134 const Code& code = Code::Handle(function.CurrentCode()); | |
| 1135 ASSERT(!code.IsNull()); | |
| 1136 const Instructions& instrs = Instructions::Handle(code.instructions()); | |
| 1137 ASSERT(!instrs.IsNull()); | |
| 1138 return instrs.raw(); | |
| 1139 } | |
| 1140 | |
| 1141 | |
| 1142 static RawObject* InvokeNoSuchMethod(const Instance& receiver, | 1127 static RawObject* InvokeNoSuchMethod(const Instance& receiver, |
| 1143 const String& target_name, | 1128 const String& target_name, |
| 1144 const Array& arguments_descriptor, | 1129 const Array& arguments_descriptor, |
| 1145 const Array& arguments) { | 1130 const Array& arguments) { |
| 1146 // Allocate an InvocationMirror object. | 1131 // Allocate an InvocationMirror object. |
| 1147 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 1132 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 1148 const String& invocation_mirror_name = | 1133 const String& invocation_mirror_name = |
| 1149 String::Handle(Symbols::InvocationMirror()); | 1134 String::Handle(Symbols::InvocationMirror()); |
| 1150 Class& invocation_mirror_class = | 1135 Class& invocation_mirror_class = |
| 1151 Class::Handle(core_lib.LookupClassAllowPrivate(invocation_mirror_name)); | 1136 Class::Handle(core_lib.LookupClassAllowPrivate(invocation_mirror_name)); |
| 1152 ASSERT(!invocation_mirror_class.IsNull()); | 1137 ASSERT(!invocation_mirror_class.IsNull()); |
| 1153 const String& allocation_function_name = | 1138 const String& allocation_function_name = |
| 1154 String::Handle(Symbols::AllocateInvocationMirror()); | 1139 String::Handle(Symbols::AllocateInvocationMirror()); |
| 1155 const Function& allocation_function = Function::Handle( | 1140 const Function& allocation_function = Function::Handle( |
| 1156 Resolver::ResolveStaticByName(invocation_mirror_class, | 1141 Resolver::ResolveStaticByName(invocation_mirror_class, |
| 1157 allocation_function_name, | 1142 allocation_function_name, |
| 1158 Resolver::kIsQualified)); | 1143 Resolver::kIsQualified)); |
| 1159 ASSERT(!allocation_function.IsNull()); | 1144 ASSERT(!allocation_function.IsNull()); |
| 1160 GrowableArray<const Object*> allocation_arguments(3); | 1145 const int kNumAllocationArgs = 3; |
| 1161 allocation_arguments.Add(&target_name); | 1146 const Array& allocation_args = Array::Handle(Array::New(kNumAllocationArgs)); |
| 1162 allocation_arguments.Add(&arguments_descriptor); | 1147 allocation_args.SetAt(0, target_name); |
| 1163 allocation_arguments.Add(&arguments); | 1148 allocation_args.SetAt(1, arguments_descriptor); |
| 1164 const Array& kNoArgumentNames = Array::Handle(); | 1149 allocation_args.SetAt(2, arguments); |
| 1165 const Object& invocation_mirror = | 1150 const Object& invocation_mirror = |
| 1166 Object::Handle(DartEntry::InvokeStatic(allocation_function, | 1151 Object::Handle(DartEntry::InvokeStatic(allocation_function, |
| 1167 allocation_arguments, | 1152 allocation_args)); |
| 1168 kNoArgumentNames)); | |
| 1169 | 1153 |
| 1154 // Now use the invocation mirror object and invoke NoSuchMethod. |
| 1170 const String& function_name = String::Handle(Symbols::NoSuchMethod()); | 1155 const String& function_name = String::Handle(Symbols::NoSuchMethod()); |
| 1171 const int kNumArguments = 2; | 1156 const int kNumArguments = 2; |
| 1172 const int kNumNamedArguments = 0; | 1157 const int kNumNamedArguments = 0; |
| 1173 const Function& function = Function::Handle( | 1158 const Function& function = Function::Handle( |
| 1174 Resolver::ResolveDynamic(receiver, | 1159 Resolver::ResolveDynamic(receiver, |
| 1175 function_name, | 1160 function_name, |
| 1176 kNumArguments, | 1161 kNumArguments, |
| 1177 kNumNamedArguments)); | 1162 kNumNamedArguments)); |
| 1178 ASSERT(!function.IsNull()); | 1163 ASSERT(!function.IsNull()); |
| 1179 GrowableArray<const Object*> invoke_arguments(1); | 1164 const Array& args = Array::Handle(Array::New(kNumArguments)); |
| 1180 invoke_arguments.Add(&invocation_mirror); | 1165 args.SetAt(0, receiver); |
| 1181 const Object& result = | 1166 args.SetAt(1, invocation_mirror); |
| 1182 Object::Handle(DartEntry::InvokeDynamic(receiver, | 1167 const Object& result = Object::Handle(DartEntry::InvokeDynamic(function, |
| 1183 function, | 1168 args)); |
| 1184 invoke_arguments, | |
| 1185 kNoArgumentNames)); | |
| 1186 CheckResultError(result); | |
| 1187 return result.raw(); | |
| 1188 } | |
| 1189 | |
| 1190 | |
| 1191 static RawObject* InvokeClosure(const Instance& closure, | |
| 1192 const Array& arguments_descriptor, | |
| 1193 const Array& arguments) { | |
| 1194 const Function& function = Function::Handle(Closure::function(closure)); | |
| 1195 ASSERT(!function.IsNull()); | |
| 1196 const Instructions& instrs = Instructions::Handle(EnsureCompiled(function)); | |
| 1197 const Context& context = Context::Handle(Closure::context(closure)); | |
| 1198 | |
| 1199 // The closure object is passed as implicit first argument to closure | |
| 1200 // functions, since it may be needed to throw a NoSuchMethodError, in case | |
| 1201 // the wrong number of arguments is passed. | |
| 1202 // Replace the original receiver in the arguments array by the closure. | |
| 1203 GrowableArray<const Object*> invoke_arguments(arguments.Length()); | |
| 1204 invoke_arguments.Add(&closure); | |
| 1205 for (intptr_t i = 1; i < arguments.Length(); i++) { | |
| 1206 const Object& value = Object::Handle(arguments.At(i)); | |
| 1207 invoke_arguments.Add(&value); | |
| 1208 } | |
| 1209 // Now call the invoke stub which will invoke the closure. | |
| 1210 DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>( | |
| 1211 StubCode::InvokeDartCodeEntryPoint()); | |
| 1212 ASSERT(context.isolate() == Isolate::Current()); | |
| 1213 const Object& result = Object::Handle(entrypoint(instrs.EntryPoint(), | |
| 1214 arguments_descriptor, | |
| 1215 invoke_arguments.data(), | |
| 1216 context)); | |
| 1217 CheckResultError(result); | 1169 CheckResultError(result); |
| 1218 return result.raw(); | 1170 return result.raw(); |
| 1219 } | 1171 } |
| 1220 | 1172 |
| 1221 | 1173 |
| 1222 static RawObject* InvokeNonClosure(const Instance& receiver, | 1174 static RawObject* InvokeNonClosure(const Instance& receiver, |
| 1223 const Class& receiver_class, | 1175 const Class& receiver_class, |
| 1224 const Array& arguments_descriptor, | 1176 const Array& arguments_descriptor, |
| 1225 const Array& arguments) { | 1177 const Array& arguments) { |
| 1226 // Resolve and invoke the "call" method if it exists. | 1178 // Resolve and invoke the "call" method if it exists. |
| 1227 const String& call_symbol = String::Handle(Symbols::Call()); | 1179 const String& call_symbol = String::Handle(Symbols::Call()); |
| 1228 | 1180 |
| 1229 Class& current_class = Class::Handle(receiver_class.raw()); | 1181 Class& current_class = Class::Handle(receiver_class.raw()); |
| 1230 Function& call_function = Function::Handle(); | 1182 Function& call_function = Function::Handle(); |
| 1231 do { | 1183 do { |
| 1232 call_function = current_class.LookupDynamicFunction(call_symbol); | 1184 call_function = current_class.LookupDynamicFunction(call_symbol); |
| 1233 | 1185 |
| 1234 if (!call_function.IsNull()) { | 1186 if (!call_function.IsNull()) { |
| 1235 const Instructions& instrs = | |
| 1236 Instructions::Handle(EnsureCompiled(call_function)); | |
| 1237 // The non-closure object is passed as implicit first argument | 1187 // The non-closure object is passed as implicit first argument |
| 1238 // (receiver). It is already included in the arguments array. | 1188 // (receiver). It is already included in the arguments array. |
| 1239 GrowableArray<const Object*> invoke_arguments(arguments.Length()); | |
| 1240 for (intptr_t i = 0; i < arguments.Length(); i++) { | |
| 1241 const Object& value = Object::Handle(arguments.At(i)); | |
| 1242 invoke_arguments.Add(&value); | |
| 1243 } | |
| 1244 | 1189 |
| 1245 // Now call the invoke stub which will invoke the call method. | 1190 // Now call the invoke stub which will invoke the call method. |
| 1246 DartEntry::invokestub entrypoint = | |
| 1247 reinterpret_cast<DartEntry::invokestub>( | |
| 1248 StubCode::InvokeDartCodeEntryPoint()); | |
| 1249 const Context& context = Context::ZoneHandle( | |
| 1250 Isolate::Current()->object_store()->empty_context()); | |
| 1251 const Object& result = | 1191 const Object& result = |
| 1252 Object::Handle(entrypoint(instrs.EntryPoint(), | 1192 Object::Handle(DartEntry::InvokeDynamic(call_function, |
| 1253 arguments_descriptor, | 1193 arguments, |
| 1254 invoke_arguments.data(), | 1194 arguments_descriptor)); |
| 1255 context)); | |
| 1256 CheckResultError(result); | 1195 CheckResultError(result); |
| 1257 return result.raw(); | 1196 return result.raw(); |
| 1258 } | 1197 } |
| 1259 | 1198 |
| 1260 current_class = current_class.SuperClass(); | 1199 current_class = current_class.SuperClass(); |
| 1261 } while (!current_class.IsNull()); | 1200 } while (!current_class.IsNull()); |
| 1262 | 1201 |
| 1263 // There is no 'call' method, so invoke noSuchMethod. | 1202 // There is no 'call' method, so invoke noSuchMethod. |
| 1264 return InvokeNoSuchMethod(receiver, | 1203 return InvokeNoSuchMethod(receiver, |
| 1265 call_symbol, | 1204 call_symbol, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1283 const int kNumArguments = 1; | 1222 const int kNumArguments = 1; |
| 1284 const int kNumNamedArguments = 0; | 1223 const int kNumNamedArguments = 0; |
| 1285 const Function& getter = Function::Handle( | 1224 const Function& getter = Function::Handle( |
| 1286 Resolver::ResolveDynamicForReceiverClass(receiver_class, | 1225 Resolver::ResolveDynamicForReceiverClass(receiver_class, |
| 1287 getter_name, | 1226 getter_name, |
| 1288 kNumArguments, | 1227 kNumArguments, |
| 1289 kNumNamedArguments)); | 1228 kNumNamedArguments)); |
| 1290 if (getter.IsNull()) return false; | 1229 if (getter.IsNull()) return false; |
| 1291 | 1230 |
| 1292 // 2. Invoke the getter. | 1231 // 2. Invoke the getter. |
| 1293 GrowableArray<const Object*> invoke_arguments(0); | 1232 const Array& args = Array::Handle(Array::New(kNumArguments)); |
| 1294 const Array& kNoArgumentNames = Array::Handle(); | 1233 args.SetAt(0, receiver); |
| 1295 const Object& value = | 1234 const Object& value = Object::Handle(DartEntry::InvokeDynamic(getter, args)); |
| 1296 Object::Handle(DartEntry::InvokeDynamic(receiver, | |
| 1297 getter, | |
| 1298 invoke_arguments, | |
| 1299 kNoArgumentNames)); | |
| 1300 | 1235 |
| 1301 // 3. If the getter threw an exception, treat it as no such method. | 1236 // 3. If the getter threw an exception, treat it as no such method. |
| 1302 if (value.IsUnhandledException()) return false; | 1237 if (value.IsUnhandledException()) return false; |
| 1303 | 1238 |
| 1304 // 4. If there was some other error, propagate it. | 1239 // 4. If there was some other error, propagate it. |
| 1305 if (value.IsError()) { | 1240 if (value.IsError()) { |
| 1306 Exceptions::PropagateError(Error::Cast(value)); | 1241 Exceptions::PropagateError(Error::Cast(value)); |
| 1307 } | 1242 } |
| 1308 | 1243 |
| 1309 // 5. If the value is a closure, invoke it and return the result. If it | 1244 // 5. If the value is a closure, invoke it and return the result. If it |
| 1310 // is a non-closure, invoke "call" on it and return the result. | 1245 // is a non-closure, invoke "call" on it and return the result. |
| 1311 Instance& instance = Instance::Handle(); | 1246 Instance& instance = Instance::Handle(); |
| 1312 instance ^= value.raw(); | 1247 instance ^= value.raw(); |
| 1313 const Class& instance_class = Class::Handle(instance.clazz()); | 1248 const Class& instance_class = Class::Handle(instance.clazz()); |
| 1314 ASSERT(!instance_class.IsNull()); | 1249 ASSERT(!instance_class.IsNull()); |
| 1315 // An object is a closure iff. its class has a non-null signature function. | 1250 // An object is a closure iff. its class has a non-null signature function. |
| 1316 if (instance_class.signature_function() != Function::null()) { | 1251 if (instance_class.signature_function() != Function::null()) { |
| 1317 *result = InvokeClosure(instance, arguments_descriptor, arguments); | 1252 // The closure object is passed as implicit first argument to closure |
| 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); |
| 1318 } else { | 1261 } else { |
| 1319 *result = InvokeNonClosure(instance, | 1262 *result = InvokeNonClosure(instance, |
| 1320 instance_class, | 1263 instance_class, |
| 1321 arguments_descriptor, | 1264 arguments_descriptor, |
| 1322 arguments); | 1265 arguments); |
| 1323 } | 1266 } |
| 1324 return true; | 1267 return true; |
| 1325 } | 1268 } |
| 1326 | 1269 |
| 1327 | 1270 |
| (...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1949 return; | 1892 return; |
| 1950 } | 1893 } |
| 1951 HeapTrace* heap_trace = Isolate::Current()->heap()->trace(); | 1894 HeapTrace* heap_trace = Isolate::Current()->heap()->trace(); |
| 1952 heap_trace->TraceStoreIntoObject(RawObject::ToAddr(object), | 1895 heap_trace->TraceStoreIntoObject(RawObject::ToAddr(object), |
| 1953 field_addr, | 1896 field_addr, |
| 1954 RawObject::ToAddr(value)); | 1897 RawObject::ToAddr(value)); |
| 1955 } | 1898 } |
| 1956 END_LEAF_RUNTIME_ENTRY | 1899 END_LEAF_RUNTIME_ENTRY |
| 1957 | 1900 |
| 1958 } // namespace dart | 1901 } // namespace dart |
| OLD | NEW |