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

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

Issue 18097004: Support fast noSuchMethod dispatch for any number of arguments. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments Created 7 years, 5 months 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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.h" 7 #include "vm/assembler.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 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 Object* result) { 1151 Object* result) {
1152 // 1. Check if there is a getter with the same name. 1152 // 1. Check if there is a getter with the same name.
1153 const String& getter_name = String::Handle(Field::GetterName(target_name)); 1153 const String& getter_name = String::Handle(Field::GetterName(target_name));
1154 const int kNumArguments = 1; 1154 const int kNumArguments = 1;
1155 const int kNumNamedArguments = 0; 1155 const int kNumNamedArguments = 0;
1156 const Function& getter = Function::Handle( 1156 const Function& getter = Function::Handle(
1157 Resolver::ResolveDynamicForReceiverClass(receiver_class, 1157 Resolver::ResolveDynamicForReceiverClass(receiver_class,
1158 getter_name, 1158 getter_name,
1159 kNumArguments, 1159 kNumArguments,
1160 kNumNamedArguments)); 1160 kNumNamedArguments));
1161 if (getter.IsNull() || 1161 if (getter.IsNull() || getter.IsMethodExtractor()) {
1162 getter.IsMethodExtractor() ||
1163 getter.IsNoSuchMethodDispatcher()) {
1164 return false; 1162 return false;
1165 } 1163 }
1166 1164
1167 // 2. Invoke the getter. 1165 // 2. Invoke the getter.
1168 const Array& args = Array::Handle(Array::New(kNumArguments)); 1166 const Array& args = Array::Handle(Array::New(kNumArguments));
1169 args.SetAt(0, receiver); 1167 args.SetAt(0, receiver);
1170 const Object& value = Object::Handle(DartEntry::InvokeFunction(getter, args)); 1168 const Object& value = Object::Handle(DartEntry::InvokeFunction(getter, args));
1171 1169
1172 // 3. If there was some error, propagate it. 1170 // 3. If there was some error, propagate it.
1173 CheckResultError(value); 1171 CheckResultError(value);
1174 1172
1175 // 4. Invoke the value as a closure. 1173 // 4. Invoke the value as a closure.
1176 Instance& instance = Instance::Handle(); 1174 Instance& instance = Instance::Handle();
1177 instance ^= value.raw(); 1175 instance ^= value.raw();
1178 arguments.SetAt(0, instance); 1176 arguments.SetAt(0, instance);
1179 *result = DartEntry::InvokeClosure(arguments, arguments_descriptor); 1177 *result = DartEntry::InvokeClosure(arguments, arguments_descriptor);
1180 CheckResultError(*result); 1178 CheckResultError(*result);
1181 return true; 1179 return true;
1182 } 1180 }
1183 1181
1184 1182
1185 // Create a method for noSuchMethod invocation and attach it to the receiver
1186 // class.
1187 static RawFunction* CreateNoSuchMethodDispatcher(
1188 const String& target_name,
1189 const Class& receiver_class,
1190 const Array& arguments_descriptor) {
1191 Function& invocation = Function::Handle(
1192 Function::New(String::Handle(Symbols::New(target_name)),
1193 RawFunction::kNoSuchMethodDispatcher,
1194 false, // Not static.
1195 false, // Not const.
1196 false, // Not abstract.
1197 false, // Not external.
1198 receiver_class,
1199 0)); // No token position.
1200
1201 // Initialize signature: receiver is a single fixed parameter.
1202 const intptr_t kNumParameters = 1;
1203 invocation.set_num_fixed_parameters(kNumParameters);
1204 invocation.SetNumOptionalParameters(0, 0);
1205 invocation.set_parameter_types(Array::Handle(Array::New(kNumParameters,
1206 Heap::kOld)));
1207 invocation.set_parameter_names(Array::Handle(Array::New(kNumParameters,
1208 Heap::kOld)));
1209 invocation.SetParameterTypeAt(0, Type::Handle(Type::DynamicType()));
1210 invocation.SetParameterNameAt(0, Symbols::This());
1211 invocation.set_result_type(Type::Handle(Type::DynamicType()));
1212 invocation.set_is_visible(false); // Not visible in stack trace.
1213
1214 receiver_class.AddFunction(invocation);
1215
1216 return invocation.raw();
1217 }
1218
1219
1220 // The IC miss handler has failed to find a (cacheable) instance function to 1183 // The IC miss handler has failed to find a (cacheable) instance function to
1221 // invoke. Handle three possibilities: 1184 // invoke. Handle three possibilities:
1222 // 1185 //
1223 // 1. If the call was a getter o.f, there may be an instance function with 1186 // 1. If the call was a getter o.f, there may be an instance function with
1224 // the same name. If so, create an implicit closure and return it. 1187 // the same name. If so, create an implicit closure and return it.
1225 // 1188 //
1226 // 2. If the call was an instance call o.f(...), there may be a getter with 1189 // 2. If the call was an instance call o.f(...), there may be a getter with
1227 // the same name. If so, invoke it. If the value is a closure, invoke 1190 // the same name. If so, invoke it. If the value is a closure, invoke
1228 // it with the given arguments. If the value is a non-closure, attempt 1191 // it with the given arguments. If the value is a non-closure, attempt
1229 // to invoke "call" on it. 1192 // to invoke "call" on it.
(...skipping 15 matching lines...) Expand all
1245 const String& target_name = String::Handle(ic_data.target_name()); 1208 const String& target_name = String::Handle(ic_data.target_name());
1246 1209
1247 Object& result = Object::Handle(); 1210 Object& result = Object::Handle();
1248 if (!ResolveCallThroughGetter(receiver, 1211 if (!ResolveCallThroughGetter(receiver,
1249 receiver_class, 1212 receiver_class,
1250 target_name, 1213 target_name,
1251 args_descriptor, 1214 args_descriptor,
1252 args, 1215 args,
1253 &result)) { 1216 &result)) {
1254 ArgumentsDescriptor desc(args_descriptor); 1217 ArgumentsDescriptor desc(args_descriptor);
1255 Function& target_function = Function::Handle( 1218 const Function& target_function = Function::Handle(
1256 Resolver::ResolveDynamicAnyArgs(receiver_class, target_name)); 1219 receiver_class.GetNoSuchMethodDispatcher(target_name, args_descriptor));
1257 // Check number of arguments and check that there is not already a method 1220 // Update IC data.
1258 // with the same name present. 1221 ASSERT(!target_function.IsNull());
1259 // TODO(fschneider): Handle multiple arguments. 1222 if (ic_data.num_args_tested() == 1) {
1260 if (target_function.IsNull() &&
1261 (desc.Count() == 1) && (desc.PositionalCount() == 1)) {
1262 // Create Function for noSuchMethodInvocation and add it to the class.
1263 target_function ^= CreateNoSuchMethodDispatcher(target_name,
1264 receiver_class,
1265 args_descriptor);
1266
1267 // Update IC data.
1268 ASSERT(!target_function.IsNull());
1269 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); 1223 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
1270 if (FLAG_trace_ic) { 1224 } else {
1271 OS::PrintErr("NoSuchMethod IC miss: adding <%s> id:%"Pd" -> <%s>\n", 1225 // Operators calls have two or three arguments tested ([], []=, etc.)
1272 Class::Handle(receiver.clazz()).ToCString(), 1226 ASSERT(ic_data.num_args_tested() > 1);
1273 receiver.GetClassId(), 1227 GrowableArray<intptr_t> class_ids(ic_data.num_args_tested());
1274 target_function.ToCString()); 1228 class_ids.Add(receiver.GetClassId());
1229 for (intptr_t i = 1; i < ic_data.num_args_tested(); ++i) {
1230 class_ids.Add(Object::Handle(args.At(i)).GetClassId());
1275 } 1231 }
1276 result = 1232 ic_data.AddCheck(class_ids, target_function);
1277 DartEntry::InvokeFunction(target_function, args, args_descriptor);
1278 } else {
1279 result = DartEntry::InvokeNoSuchMethod(receiver,
1280 target_name,
1281 args,
1282 args_descriptor);
1283 } 1233 }
1234 if (FLAG_trace_ic) {
1235 OS::PrintErr("NoSuchMethod IC miss: adding <%s> id:%"Pd" -> <%s>\n",
1236 Class::Handle(receiver.clazz()).ToCString(),
1237 receiver.GetClassId(),
1238 target_function.ToCString());
1239 }
1240 result = DartEntry::InvokeFunction(target_function, args, args_descriptor);
1284 } 1241 }
1285 CheckResultError(result); 1242 CheckResultError(result);
1286 arguments.SetReturn(result); 1243 arguments.SetReturn(result);
1287 } 1244 }
1288 1245
1289 1246
1290 static bool CanOptimizeFunction(const Function& function, Isolate* isolate) { 1247 static bool CanOptimizeFunction(const Function& function, Isolate* isolate) {
1291 const intptr_t kLowInvocationCount = -100000000; 1248 const intptr_t kLowInvocationCount = -100000000;
1292 if (isolate->debugger()->HasBreakpoint(function)) { 1249 if (isolate->debugger()->HasBreakpoint(function)) {
1293 // We cannot set breakpoints in optimized code, so do not optimize 1250 // We cannot set breakpoints in optimized code, so do not optimize
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
1868 // Arg1: Value that is being stored. 1825 // Arg1: Value that is being stored.
1869 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { 1826 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) {
1870 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count()); 1827 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count());
1871 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); 1828 const Field& field = Field::CheckedHandle(arguments.ArgAt(0));
1872 const Object& value = Object::Handle(arguments.ArgAt(1)); 1829 const Object& value = Object::Handle(arguments.ArgAt(1));
1873 1830
1874 field.UpdateCid(value.GetClassId()); 1831 field.UpdateCid(value.GetClassId());
1875 } 1832 }
1876 1833
1877 } // namespace dart 1834 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698