Chromium Code Reviews| 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 1072 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1083 kNumNamedArguments); | 1083 kNumNamedArguments); |
| 1084 ASSERT(!target_function.IsNull()); | 1084 ASSERT(!target_function.IsNull()); |
| 1085 GrowableArray<intptr_t> class_ids(kNumArguments); | 1085 GrowableArray<intptr_t> class_ids(kNumArguments); |
| 1086 ASSERT(ic_data.num_args_tested() == kNumArguments); | 1086 ASSERT(ic_data.num_args_tested() == kNumArguments); |
| 1087 class_ids.Add(Class::Handle(receiver.clazz()).id()); | 1087 class_ids.Add(Class::Handle(receiver.clazz()).id()); |
| 1088 class_ids.Add(Class::Handle(arg1.clazz()).id()); | 1088 class_ids.Add(Class::Handle(arg1.clazz()).id()); |
| 1089 ic_data.AddCheck(class_ids, target_function); | 1089 ic_data.AddCheck(class_ids, target_function); |
| 1090 } | 1090 } |
| 1091 | 1091 |
| 1092 | 1092 |
| 1093 static RawFunction* LookupDynamicFunction(Isolate* isolate, | 1093 // An instance call could not be resolved by an IC miss handler. Check if |
| 1094 const Class& in_cls, | 1094 // it was a getter call and if there is an instance function with the same |
| 1095 const String& name) { | 1095 // name. If so, create and return an implicit closure from the function. |
| 1096 Class& cls = Class::Handle(); | 1096 // Otherwise return null. |
| 1097 // For lookups treat null as an instance of class Object. | 1097 static RawInstance* ResolveImplicitClosure(const Instance& receiver, |
| 1098 if (in_cls.IsNullClass()) { | 1098 const Class& receiver_class, |
| 1099 cls = isolate->object_store()->object_class(); | 1099 const String& target_name) { |
| 1100 } else { | 1100 // 1. Check if was a getter call. |
| 1101 cls = in_cls.raw(); | 1101 if (!Field::IsGetterName(target_name)) return Instance::null(); |
| 1102 } | 1102 |
| 1103 | 1103 // 2. Check if there is an instance function with the same name. |
| 1104 Function& function = Function::Handle(); | 1104 String& function_name = String::Handle(Field::NameFromGetter(target_name)); |
| 1105 while (!cls.IsNull()) { | 1105 function_name = Symbols::New(function_name); |
| 1106 // Check if function exists. | |
| 1107 function = cls.LookupDynamicFunction(name); | |
| 1108 if (!function.IsNull()) { | |
| 1109 break; | |
| 1110 } | |
| 1111 cls = cls.SuperClass(); | |
| 1112 } | |
| 1113 return function.raw(); | |
| 1114 } | |
| 1115 | |
| 1116 | |
| 1117 // Resolve an implicit closure by checking if an instance function | |
| 1118 // of the same name exists and creating a closure object of the function. | |
| 1119 // Arg0: receiver object. | |
| 1120 // Arg1: ic-data. | |
| 1121 // Returns: Closure object or NULL (instance function not found). | |
| 1122 // This is called by the megamorphic stub when it is unable to resolve an | |
| 1123 // instance method. This is done just before the call to noSuchMethod. | |
| 1124 DEFINE_RUNTIME_ENTRY(ResolveImplicitClosureFunction, 2) { | |
| 1125 ASSERT(arguments.ArgCount() == | |
| 1126 kResolveImplicitClosureFunctionRuntimeEntry.argument_count()); | |
| 1127 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | |
| 1128 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); | |
| 1129 const String& original_function_name = String::Handle(ic_data.target_name()); | |
| 1130 Instance& closure = Instance::Handle(); | |
| 1131 if (!Field::IsGetterName(original_function_name)) { | |
| 1132 // This is not a getter so can't be the case where we are trying to | |
| 1133 // create an implicit closure of an instance function. | |
| 1134 arguments.SetReturn(closure); | |
| 1135 return; | |
| 1136 } | |
| 1137 const Class& receiver_class = Class::Handle(receiver.clazz()); | |
| 1138 ASSERT(!receiver_class.IsNull()); | |
| 1139 String& func_name = String::Handle(); | |
| 1140 func_name = Field::NameFromGetter(original_function_name); | |
| 1141 func_name = Symbols::New(func_name); | |
| 1142 const Function& function = Function::Handle( | 1106 const Function& function = Function::Handle( |
| 1143 LookupDynamicFunction(isolate, receiver_class, func_name)); | 1107 Resolver::ResolveDynamicAnyArgs(receiver_class, function_name)); |
| 1144 if (function.IsNull()) { | 1108 if (function.IsNull()) return Instance::null(); |
| 1145 // There is no function of the same name so can't be the case where | 1109 |
| 1146 // we are trying to create an implicit closure of an instance function. | 1110 // Create a closure object for the implicit closure function. |
| 1147 arguments.SetReturn(closure); | 1111 const Function& closure_function = |
| 1148 return; | |
| 1149 } | |
| 1150 Function& implicit_closure_function = | |
| 1151 Function::Handle(function.ImplicitClosureFunction()); | 1112 Function::Handle(function.ImplicitClosureFunction()); |
| 1152 // Create a closure object for the implicit closure function. | |
| 1153 const Context& context = Context::Handle(Context::New(1)); | 1113 const Context& context = Context::Handle(Context::New(1)); |
| 1154 context.SetAt(0, receiver); | 1114 context.SetAt(0, receiver); |
| 1155 closure = Closure::New(implicit_closure_function, context); | 1115 const Instance& closure = |
| 1116 Instance::Handle(Closure::New(closure_function, context)); | |
| 1156 if (receiver_class.HasTypeArguments()) { | 1117 if (receiver_class.HasTypeArguments()) { |
| 1157 const AbstractTypeArguments& type_arguments = | 1118 const AbstractTypeArguments& type_arguments = |
| 1158 AbstractTypeArguments::Handle(receiver.GetTypeArguments()); | 1119 AbstractTypeArguments::Handle(receiver.GetTypeArguments()); |
| 1159 closure.SetTypeArguments(type_arguments); | 1120 closure.SetTypeArguments(type_arguments); |
| 1160 } | 1121 } |
| 1161 arguments.SetReturn(closure); | 1122 return closure.raw(); |
| 1162 } | 1123 } |
| 1163 | 1124 |
| 1164 | 1125 |
| 1165 // Resolve an implicit closure by invoking getter and checking if the return | 1126 static RawInstructions* EnsureCompiled(const Function& function) { |
| 1166 // value from getter is a closure. | |
| 1167 // Arg0: receiver object. | |
| 1168 // Arg1: ic-data. | |
| 1169 // Returns: Closure object or NULL (closure not found). | |
| 1170 // This is called by the megamorphic stub when it is unable to resolve an | |
| 1171 // instance method. This is done just before the call to noSuchMethod. | |
| 1172 DEFINE_RUNTIME_ENTRY(ResolveImplicitClosureThroughGetter, 2) { | |
| 1173 ASSERT(arguments.ArgCount() == | |
| 1174 kResolveImplicitClosureThroughGetterRuntimeEntry.argument_count()); | |
| 1175 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | |
| 1176 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); | |
| 1177 const String& original_function_name = String::Handle(ic_data.target_name()); | |
| 1178 const int kNumArguments = 1; | |
| 1179 const int kNumNamedArguments = 0; | |
| 1180 const String& getter_function_name = | |
| 1181 String::Handle(Field::GetterName(original_function_name)); | |
| 1182 Function& function = Function::ZoneHandle( | |
| 1183 Resolver::ResolveDynamic(receiver, | |
| 1184 getter_function_name, | |
| 1185 kNumArguments, | |
| 1186 kNumNamedArguments)); | |
| 1187 const Object& null_object = Object::Handle(); | |
| 1188 if (function.IsNull()) { | |
| 1189 arguments.SetReturn(null_object); | |
| 1190 return; // No getter function found so can't be an implicit closure. | |
| 1191 } | |
| 1192 GrowableArray<const Object*> invoke_arguments(0); | |
| 1193 const Array& kNoArgumentNames = Array::Handle(); | |
| 1194 const Object& result = | |
| 1195 Object::Handle(DartEntry::InvokeDynamic(receiver, | |
| 1196 function, | |
| 1197 invoke_arguments, | |
| 1198 kNoArgumentNames)); | |
| 1199 if (result.IsError()) { | |
| 1200 if (result.IsUnhandledException()) { | |
| 1201 // If the getter throws an exception, treat as no such method. | |
| 1202 arguments.SetReturn(null_object); | |
| 1203 return; | |
| 1204 } else { | |
| 1205 Exceptions::PropagateError(Error::Cast(result)); | |
| 1206 } | |
| 1207 } | |
| 1208 if (!result.IsSmi()) { | |
| 1209 const Class& cls = Class::Handle(result.clazz()); | |
| 1210 ASSERT(!cls.IsNull()); | |
| 1211 function = cls.signature_function(); | |
| 1212 if (!function.IsNull()) { | |
| 1213 arguments.SetReturn(result); | |
| 1214 return; // Return closure object. | |
| 1215 } | |
| 1216 } | |
| 1217 // The result instance is not a closure, try to invoke method "call" before | |
| 1218 // throwing a NoSuchMethodError. | |
| 1219 | |
| 1220 // TODO(regis): Factorize the following code. | |
| 1221 | |
| 1222 // TODO(regis): Args should be passed. | |
| 1223 const Array& function_args = Array::Handle(); | |
| 1224 const String& function_name = String::Handle(Symbols::Call()); | |
| 1225 GrowableArray<const Object*> dart_arguments(5); | |
| 1226 | |
| 1227 // TODO(regis): Resolve and invoke "call" method, if existing. | |
| 1228 | |
| 1229 dart_arguments.Add(&result); | |
| 1230 dart_arguments.Add(&function_name); | |
| 1231 dart_arguments.Add(&function_args); | |
| 1232 dart_arguments.Add(&null_object); | |
| 1233 | |
| 1234 // Report if a function "call" with different arguments has been found. | |
| 1235 { | |
| 1236 Class& instance_class = Class::Handle(result.clazz()); | |
| 1237 Function& function = | |
| 1238 Function::Handle(instance_class.LookupDynamicFunction(function_name)); | |
| 1239 while (function.IsNull()) { | |
| 1240 instance_class = instance_class.SuperClass(); | |
| 1241 if (instance_class.IsNull()) break; | |
| 1242 function = instance_class.LookupDynamicFunction(function_name); | |
| 1243 } | |
| 1244 if (!function.IsNull()) { | |
| 1245 const int total_num_parameters = function.NumParameters(); | |
| 1246 const Array& array = Array::Handle(Array::New(total_num_parameters - 1)); | |
| 1247 // Skip receiver. | |
| 1248 for (int i = 1; i < total_num_parameters; i++) { | |
| 1249 array.SetAt(i - 1, String::Handle(function.ParameterNameAt(i))); | |
| 1250 } | |
| 1251 dart_arguments.Add(&array); | |
| 1252 } | |
| 1253 } | |
| 1254 Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments); | |
| 1255 UNREACHABLE(); | |
| 1256 } | |
| 1257 | |
| 1258 | |
| 1259 // Invoke Implicit Closure function. | |
| 1260 // Arg0: closure object. | |
| 1261 // Arg1: arguments descriptor (originally passed as dart instance invocation). | |
| 1262 // Arg2: arguments array (originally passed to dart instance invocation). | |
| 1263 DEFINE_RUNTIME_ENTRY(InvokeImplicitClosureFunction, 3) { | |
| 1264 ASSERT(arguments.ArgCount() == | |
| 1265 kInvokeImplicitClosureFunctionRuntimeEntry.argument_count()); | |
| 1266 const Instance& closure = Instance::CheckedHandle(arguments.ArgAt(0)); | |
| 1267 const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(1)); | |
| 1268 const Array& func_arguments = Array::CheckedHandle(arguments.ArgAt(2)); | |
| 1269 const Function& function = Function::Handle(Closure::function(closure)); | |
| 1270 ASSERT(!function.IsNull()); | |
| 1271 if (!function.HasCode()) { | 1127 if (!function.HasCode()) { |
| 1272 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 1128 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
| 1273 if (!error.IsNull()) { | 1129 if (!error.IsNull()) { |
| 1274 Exceptions::PropagateError(error); | 1130 Exceptions::PropagateError(error); |
| 1131 UNREACHABLE(); | |
| 1275 } | 1132 } |
| 1276 } | 1133 } |
| 1277 const Context& context = Context::Handle(Closure::context(closure)); | |
| 1278 const Code& code = Code::Handle(function.CurrentCode()); | 1134 const Code& code = Code::Handle(function.CurrentCode()); |
| 1279 ASSERT(!code.IsNull()); | 1135 ASSERT(!code.IsNull()); |
| 1280 const Instructions& instrs = Instructions::Handle(code.instructions()); | 1136 const Instructions& instrs = Instructions::Handle(code.instructions()); |
| 1281 ASSERT(!instrs.IsNull()); | 1137 ASSERT(!instrs.IsNull()); |
| 1138 return instrs.raw(); | |
| 1139 } | |
| 1140 | |
| 1141 | |
| 1142 static RawObject* InvokeClosure(const Instance& closure, | |
| 1143 const Array& arguments_descriptor, | |
| 1144 const Array& arguments) { | |
| 1145 const Function& function = Function::Handle(Closure::function(closure)); | |
| 1146 ASSERT(!function.IsNull()); | |
| 1147 const Instructions& instrs = Instructions::Handle(EnsureCompiled(function)); | |
| 1148 const Context& context = Context::Handle(Closure::context(closure)); | |
| 1282 | 1149 |
| 1283 // The closure object is passed as implicit first argument to closure | 1150 // The closure object is passed as implicit first argument to closure |
| 1284 // functions, since it may be needed to throw a NoSuchMethodError, in case | 1151 // functions, since it may be needed to throw a NoSuchMethodError, in case |
| 1285 // the wrong number of arguments is passed. | 1152 // the wrong number of arguments is passed. |
| 1286 // Replace the original receiver in the arguments array by the closure. | 1153 // Replace the original receiver in the arguments array by the closure. |
| 1287 GrowableArray<const Object*> invoke_arguments(func_arguments.Length()); | 1154 GrowableArray<const Object*> invoke_arguments(arguments.Length()); |
| 1288 invoke_arguments.Add(&closure); | 1155 invoke_arguments.Add(&closure); |
| 1289 for (intptr_t i = 1; i < func_arguments.Length(); i++) { | 1156 for (intptr_t i = 1; i < arguments.Length(); i++) { |
| 1290 const Object& value = Object::Handle(func_arguments.At(i)); | 1157 const Object& value = Object::Handle(arguments.At(i)); |
| 1291 invoke_arguments.Add(&value); | 1158 invoke_arguments.Add(&value); |
| 1292 } | 1159 } |
| 1293 | |
| 1294 // Now call the invoke stub which will invoke the closure. | 1160 // Now call the invoke stub which will invoke the closure. |
| 1295 DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>( | 1161 DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>( |
| 1296 StubCode::InvokeDartCodeEntryPoint()); | 1162 StubCode::InvokeDartCodeEntryPoint()); |
| 1297 ASSERT(context.isolate() == Isolate::Current()); | 1163 ASSERT(context.isolate() == Isolate::Current()); |
| 1298 const Object& result = Object::Handle( | 1164 const Object& result = Object::Handle(entrypoint(instrs.EntryPoint(), |
| 1299 entrypoint(instrs.EntryPoint(), | 1165 arguments_descriptor, |
| 1300 args_descriptor, | 1166 invoke_arguments.data(), |
| 1301 invoke_arguments.data(), | 1167 context)); |
| 1302 context)); | |
| 1303 CheckResultError(result); | 1168 CheckResultError(result); |
| 1304 arguments.SetReturn(result); | 1169 return result.raw(); |
| 1305 } | 1170 } |
| 1306 | 1171 |
| 1307 | 1172 |
| 1308 // Invoke appropriate noSuchMethod function. | 1173 static RawObject* InvokeNonClosure(const Instance& receiver, |
| 1309 // Arg0: receiver. | 1174 const Class& receiver_class, |
| 1310 // Arg1: ic-data. | 1175 const Array& arguments_descriptor, |
| 1311 // Arg2: original arguments descriptor array. | 1176 const Array& arguments) { |
| 1312 // Arg3: original arguments array. | 1177 // Resolve and invoke the "call" method if it exists. |
| 1313 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction, 4) { | 1178 const String& call_symbol = String::Handle(Symbols::Call()); |
| 1314 ASSERT(arguments.ArgCount() == | 1179 |
| 1315 kInvokeNoSuchMethodFunctionRuntimeEntry.argument_count()); | 1180 Class& current_class = Class::Handle(receiver_class.raw()); |
| 1316 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | 1181 Function& call_function = Function::Handle(); |
| 1317 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); | 1182 do { |
| 1318 const String& original_function_name = String::Handle(ic_data.target_name()); | 1183 call_function = current_class.LookupDynamicFunction(call_symbol); |
| 1319 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2)); | 1184 |
| 1320 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3)); | 1185 if (!call_function.IsNull()) { |
| 1186 const Instructions& instrs = | |
| 1187 Instructions::Handle(EnsureCompiled(call_function)); | |
| 1188 // The non-closure object is passed as implicit first argument | |
| 1189 // (receiver). It is already included in the arguments array. | |
| 1190 GrowableArray<const Object*> invoke_arguments(arguments.Length()); | |
| 1191 for (intptr_t i = 0; i < arguments.Length(); i++) { | |
| 1192 const Object& value = Object::Handle(arguments.At(i)); | |
| 1193 invoke_arguments.Add(&value); | |
| 1194 } | |
| 1195 | |
| 1196 // Now call the invoke stub which will invoke the call method. | |
| 1197 DartEntry::invokestub entrypoint = | |
| 1198 reinterpret_cast<DartEntry::invokestub>( | |
| 1199 StubCode::InvokeDartCodeEntryPoint()); | |
| 1200 const Context& context = Context::ZoneHandle( | |
| 1201 Isolate::Current()->object_store()->empty_context()); | |
| 1202 const Object& result = | |
| 1203 Object::Handle(entrypoint(instrs.EntryPoint(), | |
| 1204 arguments_descriptor, | |
| 1205 invoke_arguments.data(), | |
| 1206 context)); | |
| 1207 CheckResultError(result); | |
| 1208 return result.raw(); | |
| 1209 } | |
| 1210 | |
| 1211 current_class = current_class.SuperClass(); | |
| 1212 } while (!current_class.IsNull()); | |
| 1213 | |
| 1214 const Object& null_object = Object::Handle(); | |
| 1215 GrowableArray<const Object*> dart_arguments(5); | |
| 1216 dart_arguments.Add(&receiver); | |
| 1217 dart_arguments.Add(&call_symbol); | |
| 1218 dart_arguments.Add(&arguments); | |
| 1219 dart_arguments.Add(&null_object); | |
| 1220 // If a function "call" with different arguments exists, it will have been | |
| 1221 // invoked above, so no need to handle this case here. | |
| 1222 Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments); | |
| 1223 UNREACHABLE(); | |
| 1224 return Object::null(); | |
| 1225 } | |
| 1226 | |
| 1227 | |
| 1228 // An instance call of the form o.f(...) could not be resolved. Check if | |
| 1229 // there is a getter with the same name. If so, invoke it. If the value is | |
| 1230 // a closure, invoke it with the given arguments. If the value is a | |
| 1231 // non-closure, attempt to invoke "call" on it. | |
| 1232 static bool ResolveCallThroughGetter(const Instance& receiver, | |
| 1233 const Class& receiver_class, | |
| 1234 const String& target_name, | |
| 1235 const Array& arguments_descriptor, | |
| 1236 const Array& arguments, | |
| 1237 Object* result) { | |
| 1238 // 1. Check if there is a getter with the same name. | |
| 1239 const String& getter_name = String::Handle(Field::GetterName(target_name)); | |
| 1240 const int kNumArguments = 1; | |
| 1241 const int kNumNamedArguments = 0; | |
| 1242 const Function& getter = Function::ZoneHandle( | |
| 1243 Resolver::ResolveDynamicForReceiverClass(receiver_class, | |
| 1244 getter_name, | |
| 1245 kNumArguments, | |
| 1246 kNumNamedArguments)); | |
| 1247 if (getter.IsNull()) return false; | |
| 1248 | |
| 1249 // 2. Invoke the getter. | |
| 1250 GrowableArray<const Object*> invoke_arguments(0); | |
| 1251 const Array& kNoArgumentNames = Array::Handle(); | |
| 1252 const Object& value = | |
| 1253 Object::Handle(DartEntry::InvokeDynamic(receiver, | |
| 1254 getter, | |
| 1255 invoke_arguments, | |
| 1256 kNoArgumentNames)); | |
| 1257 | |
| 1258 // 3. If the getter threw an exception, treat it as no such method. | |
| 1259 if (value.IsUnhandledException()) return false; | |
| 1260 | |
| 1261 // 4. If there was some other error, propagate it. | |
| 1262 if (value.IsError()) { | |
| 1263 Exceptions::PropagateError(Error::Cast(value)); | |
| 1264 UNREACHABLE(); | |
| 1265 } | |
| 1266 | |
| 1267 // 5. If the value is a closure, invoke it and return the result. If it | |
| 1268 // is a non-closure, invoke "call" on it and return the result. | |
| 1269 Instance& instance = Instance::Handle(); | |
| 1270 instance ^= value.raw(); | |
|
Kevin Millikin (Google)
2012/12/12 14:18:38
I'm not sure what compels value to be an Instance.
regis
2012/12/12 17:37:38
I am not sure it answers your question, but all va
| |
| 1271 const Class& instance_class = Class::Handle(instance.clazz()); | |
| 1272 ASSERT(!instance_class.IsNull()); | |
| 1273 // An object is a closure iff. its class has a non-null signature function. | |
| 1274 if (instance_class.signature_function() != Function::null()) { | |
| 1275 *result = InvokeClosure(instance, arguments_descriptor, arguments); | |
| 1276 } else { | |
| 1277 *result = InvokeNonClosure(instance, | |
| 1278 instance_class, | |
| 1279 arguments_descriptor, | |
| 1280 arguments); | |
| 1281 } | |
| 1282 return true; | |
| 1283 } | |
| 1284 | |
| 1285 | |
| 1286 static RawObject* InvokeNoSuchMethod(const Instance& receiver, | |
| 1287 const String& target_name, | |
| 1288 const Array& arguments_descriptor, | |
| 1289 const Array& arguments) { | |
| 1321 // Allocate an InvocationMirror object. | 1290 // Allocate an InvocationMirror object. |
| 1322 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 1291 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 1323 const String& invocation_mirror_name = String::Handle( | 1292 const String& invocation_mirror_name = |
| 1324 Symbols::InvocationMirror()); | 1293 String::Handle(Symbols::InvocationMirror()); |
| 1325 Class& invocation_mirror_class = Class::Handle( | 1294 Class& invocation_mirror_class = |
| 1326 core_lib.LookupClassAllowPrivate(invocation_mirror_name)); | 1295 Class::Handle(core_lib.LookupClassAllowPrivate(invocation_mirror_name)); |
| 1327 ASSERT(!invocation_mirror_class.IsNull()); | 1296 ASSERT(!invocation_mirror_class.IsNull()); |
| 1328 const String& allocation_function_name = String::Handle( | 1297 const String& allocation_function_name = |
| 1329 Symbols::AllocateInvocationMirror()); | 1298 String::Handle(Symbols::AllocateInvocationMirror()); |
| 1330 const Function& allocation_function = Function::ZoneHandle( | 1299 const Function& allocation_function = Function::ZoneHandle( |
| 1331 Resolver::ResolveStaticByName(invocation_mirror_class, | 1300 Resolver::ResolveStaticByName(invocation_mirror_class, |
| 1332 allocation_function_name, | 1301 allocation_function_name, |
| 1333 Resolver::kIsQualified)); | 1302 Resolver::kIsQualified)); |
| 1334 ASSERT(!allocation_function.IsNull()); | 1303 ASSERT(!allocation_function.IsNull()); |
| 1335 GrowableArray<const Object*> allocation_arguments(3); | 1304 GrowableArray<const Object*> allocation_arguments(3); |
| 1336 allocation_arguments.Add(&original_function_name); | 1305 allocation_arguments.Add(&target_name); |
| 1337 allocation_arguments.Add(&orig_arguments_desc); | 1306 allocation_arguments.Add(&arguments_descriptor); |
| 1338 allocation_arguments.Add(&orig_arguments); | 1307 allocation_arguments.Add(&arguments); |
| 1339 const Array& kNoArgumentNames = Array::Handle(); | 1308 const Array& kNoArgumentNames = Array::Handle(); |
| 1340 const Object& invocation_mirror = Object::Handle( | 1309 const Object& invocation_mirror = |
| 1341 DartEntry::InvokeStatic(allocation_function, | 1310 Object::Handle(DartEntry::InvokeStatic(allocation_function, |
| 1342 allocation_arguments, | 1311 allocation_arguments, |
| 1343 kNoArgumentNames)); | 1312 kNoArgumentNames)); |
| 1344 | 1313 |
| 1314 const String& function_name = String::Handle(Symbols::NoSuchMethod()); | |
| 1345 const int kNumArguments = 2; | 1315 const int kNumArguments = 2; |
| 1346 const int kNumNamedArguments = 0; | 1316 const int kNumNamedArguments = 0; |
| 1347 const String& function_name = String::Handle(Symbols::NoSuchMethod()); | 1317 const Function& function = |
| 1348 const Function& function = Function::ZoneHandle( | 1318 Function::ZoneHandle(Resolver::ResolveDynamic(receiver, |
| 1349 Resolver::ResolveDynamic(receiver, | 1319 function_name, |
| 1350 function_name, | 1320 kNumArguments, |
| 1351 kNumArguments, | 1321 kNumNamedArguments)); |
| 1352 kNumNamedArguments)); | |
| 1353 ASSERT(!function.IsNull()); | 1322 ASSERT(!function.IsNull()); |
| 1354 GrowableArray<const Object*> invoke_arguments(1); | 1323 GrowableArray<const Object*> invoke_arguments(1); |
| 1355 invoke_arguments.Add(&invocation_mirror); | 1324 invoke_arguments.Add(&invocation_mirror); |
| 1356 const Object& result = Object::Handle( | 1325 const Object& result = |
| 1357 DartEntry::InvokeDynamic(receiver, | 1326 Object::Handle(DartEntry::InvokeDynamic(receiver, |
| 1358 function, | 1327 function, |
| 1359 invoke_arguments, | 1328 invoke_arguments, |
| 1360 kNoArgumentNames)); | 1329 kNoArgumentNames)); |
| 1361 CheckResultError(result); | 1330 CheckResultError(result); |
| 1331 return result.raw(); | |
| 1332 } | |
| 1333 | |
| 1334 | |
| 1335 // Invoke appropriate noSuchMethod function. | |
| 1336 // Arg0: receiver. | |
| 1337 // Arg1: ic-data. | |
| 1338 // Arg2: arguments descriptor array. | |
| 1339 // Arg3: arguments array. | |
| 1340 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction, 4) { | |
| 1341 ASSERT(arguments.ArgCount() == | |
| 1342 kInvokeNoSuchMethodFunctionRuntimeEntry.argument_count()); | |
| 1343 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | |
| 1344 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); | |
| 1345 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2)); | |
| 1346 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3)); | |
| 1347 | |
| 1348 const String& original_function_name = String::Handle(ic_data.target_name()); | |
| 1349 const Object& result = | |
| 1350 Object::Handle(InvokeNoSuchMethod(receiver, | |
| 1351 original_function_name, | |
| 1352 orig_arguments_desc, | |
| 1353 orig_arguments)); | |
| 1362 arguments.SetReturn(result); | 1354 arguments.SetReturn(result); |
| 1363 } | 1355 } |
| 1364 | 1356 |
| 1365 | 1357 |
| 1366 // A non-closure object was invoked as a closure, so call the "call" method | 1358 // A non-closure object was invoked as a closure, so call the "call" method |
| 1367 // on it. | 1359 // on it. |
| 1368 // Arg0: non-closure object. | 1360 // Arg0: non-closure object. |
| 1369 // Arg1: arguments descriptor. | 1361 // Arg1: arguments descriptor. |
| 1370 // Arg2: arguments array, including non-closure object. | 1362 // Arg2: arguments array, including non-closure object. |
| 1371 DEFINE_RUNTIME_ENTRY(InvokeNonClosure, 3) { | 1363 DEFINE_RUNTIME_ENTRY(InvokeNonClosure, 3) { |
| 1372 ASSERT(arguments.ArgCount() == | 1364 ASSERT(arguments.ArgCount() == |
| 1373 kInvokeNonClosureRuntimeEntry.argument_count()); | 1365 kInvokeNonClosureRuntimeEntry.argument_count()); |
| 1374 const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0)); | 1366 const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0)); |
| 1375 const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(1)); | 1367 const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(1)); |
| 1376 const Array& function_args = Array::CheckedHandle(arguments.ArgAt(2)); | 1368 const Array& function_args = Array::CheckedHandle(arguments.ArgAt(2)); |
| 1377 | 1369 |
| 1378 // Resolve and invoke "call" method, if existing. | 1370 const Class& instance_class = Class::Handle(instance.clazz()); |
| 1379 const String& function_name = String::Handle(Symbols::Call()); | 1371 const Object& result = Object::Handle(InvokeNonClosure(instance, |
| 1380 Class& instance_class = Class::Handle(instance.clazz()); | 1372 instance_class, |
| 1381 Function& function = | 1373 args_descriptor, |
| 1382 Function::Handle(instance_class.LookupDynamicFunction(function_name)); | 1374 function_args)); |
| 1383 while (function.IsNull()) { | 1375 arguments.SetReturn(result); |
| 1384 instance_class = instance_class.SuperClass(); | |
| 1385 if (instance_class.IsNull()) break; | |
| 1386 function = instance_class.LookupDynamicFunction(function_name); | |
| 1387 } | |
| 1388 if (!function.IsNull()) { | |
| 1389 if (!function.HasCode()) { | |
| 1390 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | |
| 1391 if (!error.IsNull()) { | |
| 1392 Exceptions::PropagateError(error); | |
| 1393 } | |
| 1394 } | |
| 1395 const Code& code = Code::Handle(function.CurrentCode()); | |
| 1396 ASSERT(!code.IsNull()); | |
| 1397 const Instructions& instrs = Instructions::Handle(code.instructions()); | |
| 1398 ASSERT(!instrs.IsNull()); | |
| 1399 | |
| 1400 // The non-closure object is passed as implicit first argument (receiver). | |
| 1401 // It is already included in the arguments array. | |
| 1402 GrowableArray<const Object*> invoke_arguments(function_args.Length()); | |
| 1403 for (intptr_t i = 0; i < function_args.Length(); i++) { | |
| 1404 const Object& value = Object::Handle(function_args.At(i)); | |
| 1405 invoke_arguments.Add(&value); | |
| 1406 } | |
| 1407 | |
| 1408 // Now call the invoke stub which will invoke the call method. | |
| 1409 DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>( | |
| 1410 StubCode::InvokeDartCodeEntryPoint()); | |
| 1411 const Context& context = Context::ZoneHandle( | |
| 1412 Isolate::Current()->object_store()->empty_context()); | |
| 1413 const Object& result = Object::Handle( | |
| 1414 entrypoint(instrs.EntryPoint(), | |
| 1415 args_descriptor, | |
| 1416 invoke_arguments.data(), | |
| 1417 context)); | |
| 1418 CheckResultError(result); | |
| 1419 arguments.SetReturn(result); | |
| 1420 return; | |
| 1421 } | |
| 1422 const Object& null_object = Object::Handle(); | |
| 1423 GrowableArray<const Object*> dart_arguments(5); | |
| 1424 dart_arguments.Add(&instance); | |
| 1425 dart_arguments.Add(&function_name); | |
| 1426 dart_arguments.Add(&function_args); | |
| 1427 dart_arguments.Add(&null_object); | |
| 1428 // If a function "call" with different arguments exists, it will have been | |
| 1429 // invoked above, so no need to handle this case here. | |
| 1430 Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments); | |
| 1431 UNREACHABLE(); | |
| 1432 } | 1376 } |
| 1433 | 1377 |
| 1434 | 1378 |
| 1379 // The IC miss handler has failed to find a (cacheable) instance function to | |
| 1380 // invoke. Handle three possibilities: | |
| 1381 // | |
| 1382 // 1. If the call was a getter o.f, there may be an instance function with | |
| 1383 // the same name. If so, create an implicit closure and return it. | |
| 1384 // | |
| 1385 // 2. If the call was an instance call o.f(...), there may be a getter with | |
| 1386 // the same name. If so, invoke it. If the value is a closure, invoke | |
| 1387 // it with the given arguments. If the value is a non-closure, attempt | |
| 1388 // to invoke "call" on it. | |
| 1389 // | |
| 1390 // 3. There is no such method. | |
| 1391 DEFINE_RUNTIME_ENTRY(InstanceFunctionLookup, 4) { | |
| 1392 ASSERT(arguments.ArgCount() == | |
| 1393 kInstanceFunctionLookupRuntimeEntry.argument_count()); | |
| 1394 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); | |
| 1395 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); | |
| 1396 const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(2)); | |
| 1397 const Array& args = Array::CheckedHandle(arguments.ArgAt(3)); | |
| 1398 | |
| 1399 Class& receiver_class = Class::Handle(receiver.clazz()); | |
| 1400 // For lookups treat null as an instance of class Object. | |
| 1401 if (receiver_class.IsNullClass()) { | |
| 1402 receiver_class = isolate->object_store()->object_class(); | |
| 1403 } | |
| 1404 const String& target_name = String::Handle(ic_data.target_name()); | |
| 1405 | |
| 1406 Instance& closure = Instance::Handle(ResolveImplicitClosure(receiver, | |
| 1407 receiver_class, | |
| 1408 target_name)); | |
| 1409 if (!closure.IsNull()) { | |
| 1410 arguments.SetReturn(closure); | |
| 1411 return; | |
| 1412 } | |
| 1413 | |
| 1414 Object& result = Object::Handle(); | |
| 1415 if (!ResolveCallThroughGetter(receiver, | |
| 1416 receiver_class, | |
| 1417 target_name, | |
| 1418 args_descriptor, | |
| 1419 args, | |
| 1420 &result)) { | |
| 1421 result = InvokeNoSuchMethod(receiver, target_name, args_descriptor, args); | |
| 1422 } | |
| 1423 arguments.SetReturn(result); | |
| 1424 } | |
| 1425 | |
| 1426 | |
| 1435 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { | 1427 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { |
| 1436 ASSERT(arguments.ArgCount() == | 1428 ASSERT(arguments.ArgCount() == |
| 1437 kStackOverflowRuntimeEntry.argument_count()); | 1429 kStackOverflowRuntimeEntry.argument_count()); |
| 1438 uword stack_pos = reinterpret_cast<uword>(&arguments); | 1430 uword stack_pos = reinterpret_cast<uword>(&arguments); |
| 1439 | 1431 |
| 1440 // If an interrupt happens at the same time as a stack overflow, we | 1432 // If an interrupt happens at the same time as a stack overflow, we |
| 1441 // process the stack overflow first. | 1433 // process the stack overflow first. |
| 1442 if (stack_pos < isolate->saved_stack_limit()) { | 1434 if (stack_pos < isolate->saved_stack_limit()) { |
| 1443 // Use the preallocated stack overflow exception to avoid calling | 1435 // Use the preallocated stack overflow exception to avoid calling |
| 1444 // into dart code. | 1436 // into dart code. |
| (...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1948 Isolate* isolate = Isolate::Current(); | 1940 Isolate* isolate = Isolate::Current(); |
| 1949 StackZone zone(isolate); | 1941 StackZone zone(isolate); |
| 1950 HANDLESCOPE(isolate); | 1942 HANDLESCOPE(isolate); |
| 1951 const Bigint& big_left = Bigint::Handle(left); | 1943 const Bigint& big_left = Bigint::Handle(left); |
| 1952 const Bigint& big_right = Bigint::Handle(right); | 1944 const Bigint& big_right = Bigint::Handle(right); |
| 1953 return BigintOperations::Compare(big_left, big_right); | 1945 return BigintOperations::Compare(big_left, big_right); |
| 1954 } | 1946 } |
| 1955 END_LEAF_RUNTIME_ENTRY | 1947 END_LEAF_RUNTIME_ENTRY |
| 1956 | 1948 |
| 1957 } // namespace dart | 1949 } // namespace dart |
| OLD | NEW |