| 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 1166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1177 const String& original_function_name = String::Handle(ic_data.target_name()); | 1177 const String& original_function_name = String::Handle(ic_data.target_name()); |
| 1178 const int kNumArguments = 1; | 1178 const int kNumArguments = 1; |
| 1179 const int kNumNamedArguments = 0; | 1179 const int kNumNamedArguments = 0; |
| 1180 const String& getter_function_name = | 1180 const String& getter_function_name = |
| 1181 String::Handle(Field::GetterName(original_function_name)); | 1181 String::Handle(Field::GetterName(original_function_name)); |
| 1182 Function& function = Function::ZoneHandle( | 1182 Function& function = Function::ZoneHandle( |
| 1183 Resolver::ResolveDynamic(receiver, | 1183 Resolver::ResolveDynamic(receiver, |
| 1184 getter_function_name, | 1184 getter_function_name, |
| 1185 kNumArguments, | 1185 kNumArguments, |
| 1186 kNumNamedArguments)); | 1186 kNumNamedArguments)); |
| 1187 Code& code = Code::Handle(); | 1187 const Object& null_object = Object::Handle(); |
| 1188 if (function.IsNull()) { | 1188 if (function.IsNull()) { |
| 1189 arguments.SetReturn(code); | 1189 arguments.SetReturn(null_object); |
| 1190 return; // No getter function found so can't be an implicit closure. | 1190 return; // No getter function found so can't be an implicit closure. |
| 1191 } | 1191 } |
| 1192 GrowableArray<const Object*> invoke_arguments(0); | 1192 GrowableArray<const Object*> invoke_arguments(0); |
| 1193 const Array& kNoArgumentNames = Array::Handle(); | 1193 const Array& kNoArgumentNames = Array::Handle(); |
| 1194 const Object& result = | 1194 const Object& result = |
| 1195 Object::Handle(DartEntry::InvokeDynamic(receiver, | 1195 Object::Handle(DartEntry::InvokeDynamic(receiver, |
| 1196 function, | 1196 function, |
| 1197 invoke_arguments, | 1197 invoke_arguments, |
| 1198 kNoArgumentNames)); | 1198 kNoArgumentNames)); |
| 1199 if (result.IsError()) { | 1199 if (result.IsError()) { |
| 1200 if (result.IsUnhandledException()) { | 1200 if (result.IsUnhandledException()) { |
| 1201 // If the getter throws an exception, treat as no such method. | 1201 // If the getter throws an exception, treat as no such method. |
| 1202 arguments.SetReturn(code); | 1202 arguments.SetReturn(null_object); |
| 1203 return; | 1203 return; |
| 1204 } else { | 1204 } else { |
| 1205 Exceptions::PropagateError(Error::Cast(result)); | 1205 Exceptions::PropagateError(Error::Cast(result)); |
| 1206 } | 1206 } |
| 1207 } | 1207 } |
| 1208 if (!result.IsSmi()) { | 1208 if (!result.IsSmi()) { |
| 1209 const Class& cls = Class::Handle(result.clazz()); | 1209 const Class& cls = Class::Handle(result.clazz()); |
| 1210 ASSERT(!cls.IsNull()); | 1210 ASSERT(!cls.IsNull()); |
| 1211 function = cls.signature_function(); | 1211 function = cls.signature_function(); |
| 1212 if (!function.IsNull()) { | 1212 if (!function.IsNull()) { |
| 1213 arguments.SetReturn(result); | 1213 arguments.SetReturn(result); |
| 1214 return; // Return closure object. | 1214 return; // Return closure object. |
| 1215 } | 1215 } |
| 1216 } | 1216 } |
| 1217 // The result instance is not a closure, try to invoke method "call" before | 1217 // The result instance is not a closure, try to invoke method "call" before |
| 1218 // throwing a NoSuchMethodError. | 1218 // throwing a NoSuchMethodError. |
| 1219 | 1219 |
| 1220 // TODO(regis): Factorize the following code. | 1220 // TODO(regis): Factorize the following code. |
| 1221 | 1221 |
| 1222 // TODO(regis): Args should be passed. | 1222 // TODO(regis): Args should be passed. |
| 1223 const Array& function_args = Array::Handle(); | 1223 const Array& function_args = Array::Handle(); |
| 1224 const String& function_name = String::Handle(Symbols::Call()); | 1224 const String& function_name = String::Handle(Symbols::Call()); |
| 1225 GrowableArray<const Object*> dart_arguments(5); | 1225 GrowableArray<const Object*> dart_arguments(5); |
| 1226 | 1226 |
| 1227 // TODO(regis): Resolve and invoke "call" method, if existing. | 1227 // TODO(regis): Resolve and invoke "call" method, if existing. |
| 1228 | 1228 |
| 1229 const Object& null_object = Object::Handle(); | |
| 1230 dart_arguments.Add(&result); | 1229 dart_arguments.Add(&result); |
| 1231 dart_arguments.Add(&function_name); | 1230 dart_arguments.Add(&function_name); |
| 1232 dart_arguments.Add(&function_args); | 1231 dart_arguments.Add(&function_args); |
| 1233 dart_arguments.Add(&null_object); | 1232 dart_arguments.Add(&null_object); |
| 1234 | 1233 |
| 1235 // Report if a function "call" with different arguments has been found. | 1234 // Report if a function "call" with different arguments has been found. |
| 1236 { | 1235 { |
| 1237 Class& instance_class = Class::Handle(result.clazz()); | 1236 Class& instance_class = Class::Handle(result.clazz()); |
| 1238 Function& function = | 1237 Function& function = |
| 1239 Function::Handle(instance_class.LookupDynamicFunction(function_name)); | 1238 Function::Handle(instance_class.LookupDynamicFunction(function_name)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1274 if (!error.IsNull()) { | 1273 if (!error.IsNull()) { |
| 1275 Exceptions::PropagateError(error); | 1274 Exceptions::PropagateError(error); |
| 1276 } | 1275 } |
| 1277 } | 1276 } |
| 1278 const Context& context = Context::Handle(Closure::context(closure)); | 1277 const Context& context = Context::Handle(Closure::context(closure)); |
| 1279 const Code& code = Code::Handle(function.CurrentCode()); | 1278 const Code& code = Code::Handle(function.CurrentCode()); |
| 1280 ASSERT(!code.IsNull()); | 1279 ASSERT(!code.IsNull()); |
| 1281 const Instructions& instrs = Instructions::Handle(code.instructions()); | 1280 const Instructions& instrs = Instructions::Handle(code.instructions()); |
| 1282 ASSERT(!instrs.IsNull()); | 1281 ASSERT(!instrs.IsNull()); |
| 1283 | 1282 |
| 1284 // Receiver parameter has already been skipped by caller. | |
| 1285 // The closure object is passed as implicit first argument to closure | 1283 // The closure object is passed as implicit first argument to closure |
| 1286 // functions, since it may be needed to throw a NoSuchMethodError, in case | 1284 // functions, since it may be needed to throw a NoSuchMethodError, in case |
| 1287 // the wrong number of arguments is passed. | 1285 // the wrong number of arguments is passed. |
| 1288 GrowableArray<const Object*> invoke_arguments(func_arguments.Length() + 1); | 1286 // Replace the original receiver in the arguments array by the closure. |
| 1287 GrowableArray<const Object*> invoke_arguments(func_arguments.Length()); |
| 1289 invoke_arguments.Add(&closure); | 1288 invoke_arguments.Add(&closure); |
| 1290 for (intptr_t i = 0; i < func_arguments.Length(); i++) { | 1289 for (intptr_t i = 1; i < func_arguments.Length(); i++) { |
| 1291 const Object& value = Object::Handle(func_arguments.At(i)); | 1290 const Object& value = Object::Handle(func_arguments.At(i)); |
| 1292 invoke_arguments.Add(&value); | 1291 invoke_arguments.Add(&value); |
| 1293 } | 1292 } |
| 1294 | 1293 |
| 1295 // Now Call the invoke stub which will invoke the closure. | 1294 // Now Call the invoke stub which will invoke the closure. |
| 1296 DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>( | 1295 DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>( |
| 1297 StubCode::InvokeDartCodeEntryPoint()); | 1296 StubCode::InvokeDartCodeEntryPoint()); |
| 1298 ASSERT(context.isolate() == Isolate::Current()); | 1297 ASSERT(context.isolate() == Isolate::Current()); |
| 1299 const Object& result = Object::Handle( | 1298 const Object& result = Object::Handle( |
| 1300 entrypoint(instrs.EntryPoint(), | 1299 entrypoint(instrs.EntryPoint(), |
| 1301 arg_descriptor, | 1300 arg_descriptor, |
| 1302 invoke_arguments.data(), | 1301 invoke_arguments.data(), |
| 1303 context)); | 1302 context)); |
| 1304 CheckResultError(result); | 1303 CheckResultError(result); |
| 1305 arguments.SetReturn(result); | 1304 arguments.SetReturn(result); |
| 1306 } | 1305 } |
| 1307 | 1306 |
| 1308 | 1307 |
| 1309 // Invoke appropriate noSuchMethod function. | 1308 // Invoke appropriate noSuchMethod function. |
| 1310 // Arg0: receiver. | 1309 // Arg0: receiver. |
| 1311 // Arg1: ic-data. | 1310 // Arg1: ic-data. |
| 1312 // Arg2: original arguments descriptor array. | 1311 // Arg2: original arguments descriptor array. |
| 1313 // Arg3: original arguments array. | 1312 // Arg3: original arguments array. |
| 1314 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction, 4) { | 1313 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction, 4) { |
| 1315 ASSERT(arguments.ArgCount() == | 1314 ASSERT(arguments.ArgCount() == |
| 1316 kInvokeNoSuchMethodFunctionRuntimeEntry.argument_count()); | 1315 kInvokeNoSuchMethodFunctionRuntimeEntry.argument_count()); |
| 1317 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | 1316 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); |
| 1318 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); | 1317 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); |
| 1319 const String& original_function_name = String::Handle(ic_data.target_name()); | 1318 const String& original_function_name = String::Handle(ic_data.target_name()); |
| 1320 ASSERT(!Array::CheckedHandle(arguments.ArgAt(2)).IsNull()); | 1319 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2)); |
| 1321 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3)); | 1320 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3)); |
| 1322 // Allocate an InvocationMirror object. | 1321 // Allocate an InvocationMirror object. |
| 1323 // TODO(regis): Fill in the InvocationMirror object correctly at | |
| 1324 // this point we do not deal with named arguments and treat them | |
| 1325 // all as positional. | |
| 1326 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 1322 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 1327 const String& invocation_mirror_name = String::Handle( | 1323 const String& invocation_mirror_name = String::Handle( |
| 1328 Symbols::InvocationMirror()); | 1324 Symbols::InvocationMirror()); |
| 1329 Class& invocation_mirror_class = Class::Handle( | 1325 Class& invocation_mirror_class = Class::Handle( |
| 1330 core_lib.LookupClassAllowPrivate(invocation_mirror_name)); | 1326 core_lib.LookupClassAllowPrivate(invocation_mirror_name)); |
| 1331 ASSERT(!invocation_mirror_class.IsNull()); | 1327 ASSERT(!invocation_mirror_class.IsNull()); |
| 1332 const String& allocation_function_name = String::Handle( | 1328 const String& allocation_function_name = String::Handle( |
| 1333 Symbols::AllocateInvocationMirror()); | 1329 Symbols::AllocateInvocationMirror()); |
| 1334 const Function& allocation_function = Function::ZoneHandle( | 1330 const Function& allocation_function = Function::ZoneHandle( |
| 1335 Resolver::ResolveStaticByName(invocation_mirror_class, | 1331 Resolver::ResolveStaticByName(invocation_mirror_class, |
| 1336 allocation_function_name, | 1332 allocation_function_name, |
| 1337 Resolver::kIsQualified)); | 1333 Resolver::kIsQualified)); |
| 1338 ASSERT(!allocation_function.IsNull()); | 1334 ASSERT(!allocation_function.IsNull()); |
| 1339 GrowableArray<const Object*> allocation_arguments(2); | 1335 GrowableArray<const Object*> allocation_arguments(3); |
| 1340 allocation_arguments.Add(&original_function_name); | 1336 allocation_arguments.Add(&original_function_name); |
| 1337 allocation_arguments.Add(&orig_arguments_desc); |
| 1341 allocation_arguments.Add(&orig_arguments); | 1338 allocation_arguments.Add(&orig_arguments); |
| 1342 const Array& kNoArgumentNames = Array::Handle(); | 1339 const Array& kNoArgumentNames = Array::Handle(); |
| 1343 const Object& invocation_mirror = Object::Handle( | 1340 const Object& invocation_mirror = Object::Handle( |
| 1344 DartEntry::InvokeStatic(allocation_function, | 1341 DartEntry::InvokeStatic(allocation_function, |
| 1345 allocation_arguments, | 1342 allocation_arguments, |
| 1346 kNoArgumentNames)); | 1343 kNoArgumentNames)); |
| 1347 | 1344 |
| 1348 const int kNumArguments = 2; | 1345 const int kNumArguments = 2; |
| 1349 const int kNumNamedArguments = 0; | 1346 const int kNumNamedArguments = 0; |
| 1350 const String& function_name = String::Handle(Symbols::NoSuchMethod()); | 1347 const String& function_name = String::Handle(Symbols::NoSuchMethod()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1362 invoke_arguments, | 1359 invoke_arguments, |
| 1363 kNoArgumentNames)); | 1360 kNoArgumentNames)); |
| 1364 CheckResultError(result); | 1361 CheckResultError(result); |
| 1365 arguments.SetReturn(result); | 1362 arguments.SetReturn(result); |
| 1366 } | 1363 } |
| 1367 | 1364 |
| 1368 | 1365 |
| 1369 // A non-closure object was invoked as a closure, so call the "call" method | 1366 // A non-closure object was invoked as a closure, so call the "call" method |
| 1370 // on it. | 1367 // on it. |
| 1371 // Arg0: non-closure object. | 1368 // Arg0: non-closure object. |
| 1372 // Arg1: arguments array. | 1369 // Arg1: arguments array, including non-closure object. |
| 1373 // TODO(regis): Rename this entry? | 1370 // TODO(regis): Rename this entry? |
| 1374 DEFINE_RUNTIME_ENTRY(ReportObjectNotClosure, 2) { | 1371 DEFINE_RUNTIME_ENTRY(ReportObjectNotClosure, 2) { |
| 1375 ASSERT(arguments.ArgCount() == | 1372 ASSERT(arguments.ArgCount() == |
| 1376 kReportObjectNotClosureRuntimeEntry.argument_count()); | 1373 kReportObjectNotClosureRuntimeEntry.argument_count()); |
| 1377 const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0)); | 1374 const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0)); |
| 1378 const Array& function_args = Array::CheckedHandle(arguments.ArgAt(1)); | 1375 const Array& function_args = Array::CheckedHandle(arguments.ArgAt(1)); |
| 1379 const String& function_name = String::Handle(Symbols::Call()); | 1376 const String& function_name = String::Handle(Symbols::Call()); |
| 1380 GrowableArray<const Object*> dart_arguments(5); | 1377 GrowableArray<const Object*> dart_arguments(5); |
| 1381 | 1378 |
| 1382 // TODO(regis): Resolve and invoke "call" method, if existing. | 1379 // TODO(regis): Resolve and invoke "call" method, if existing. |
| (...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1926 Isolate* isolate = Isolate::Current(); | 1923 Isolate* isolate = Isolate::Current(); |
| 1927 StackZone zone(isolate); | 1924 StackZone zone(isolate); |
| 1928 HANDLESCOPE(isolate); | 1925 HANDLESCOPE(isolate); |
| 1929 const Bigint& big_left = Bigint::Handle(left); | 1926 const Bigint& big_left = Bigint::Handle(left); |
| 1930 const Bigint& big_right = Bigint::Handle(right); | 1927 const Bigint& big_right = Bigint::Handle(right); |
| 1931 return BigintOperations::Compare(big_left, big_right); | 1928 return BigintOperations::Compare(big_left, big_right); |
| 1932 } | 1929 } |
| 1933 END_LEAF_RUNTIME_ENTRY | 1930 END_LEAF_RUNTIME_ENTRY |
| 1934 | 1931 |
| 1935 } // namespace dart | 1932 } // namespace dart |
| OLD | NEW |