Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(344)

Side by Side Diff: runtime/vm/code_generator.cc

Issue 11316353: Refactor the InstanceFunctionLookupStub. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/code_generator.h ('k') | runtime/vm/stub_code_ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/code_generator.h ('k') | runtime/vm/stub_code_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698