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

Unified Diff: runtime/vm/code_generator.cc

Issue 1195573006: Handle field-invocation and method-extraction in the runtime when --lazy_dispatchers=false. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/lib/mirrors.cc ('k') | runtime/vm/dart_entry.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/code_generator.cc
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index a4359a75817fa6f3845247c33ff2e11460ab7bcf..dd977b239684252db484eb32a0e25e3a92e5da2d 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -724,6 +724,7 @@ static bool ResolveCallThroughGetter(const Instance& receiver,
const String& target_name,
const Array& arguments_descriptor,
Function* result) {
+ ASSERT(FLAG_lazy_dispatchers);
// 1. Check if there is a getter with the same name.
const String& getter_name = String::Handle(Field::GetterName(target_name));
const int kNumArguments = 1;
@@ -764,6 +765,10 @@ static bool ResolveCallThroughGetter(const Instance& receiver,
RawFunction* InlineCacheMissHelper(
const Instance& receiver,
const ICData& ic_data) {
+ if (!FLAG_lazy_dispatchers) {
+ return Function::null(); // We'll handle it in the runtime.
+ }
+
const Array& args_descriptor = Array::Handle(ic_data.arguments_descriptor());
const Class& receiver_class = Class::Handle(receiver.clazz());
@@ -775,9 +780,6 @@ RawFunction* InlineCacheMissHelper(
target_name,
args_descriptor,
&result)) {
- if (!FLAG_lazy_dispatchers) {
- return result.raw(); // Return null.
- }
ArgumentsDescriptor desc(args_descriptor);
const Function& target_function =
Function::Handle(receiver_class.GetInvocationDispatcher(
@@ -1042,6 +1044,78 @@ DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) {
const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2));
const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3));
const String& target_name = String::Handle(ic_data.target_name());
+
+ Class& cls = Class::Handle(receiver.clazz());
+ Function& function = Function::Handle();
+
+ // Dart distinguishes getters and regular methods and allows their calls
+ // to mix with conversions, and its selectors are independent of arity. So do
+ // a zigzagged lookup to see if this call failed because of an arity mismatch,
+ // need for conversion, or there really is no such method.
+
+ const bool is_getter = Field::IsGetterName(target_name);
+ if (is_getter) {
+ // o.foo failed, closurize o.foo() if it exists
+ const String& field_name =
+ String::Handle(Field::NameFromGetter(target_name));
+ while (!cls.IsNull()) {
+ function ^= cls.LookupDynamicFunction(field_name);
+ if (!function.IsNull()) {
+ const Function& closure_function =
+ Function::Handle(function.ImplicitClosureFunction());
+ const Object& result =
+ Object::Handle(closure_function.ImplicitInstanceClosure(receiver));
+ arguments.SetReturn(result);
+ return;
+ }
+ cls = cls.SuperClass();
+ }
+ } else {
+ // o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong
+ // number of arguments, or try (o.foo).call(...)
+
+ if ((target_name.raw() == Symbols::Call().raw()) && receiver.IsClosure()) {
+ // Special case: closures are implemented with a call getter instead of a
+ // call method and with lazy dispatchers the field-invocation-dispatcher
+ // would perform the closure call.
+ const Object& result =
+ Object::Handle(DartEntry::InvokeClosure(orig_arguments,
+ orig_arguments_desc));
+ CheckResultError(result);
+ arguments.SetReturn(result);
+ return;
+ }
+
+ const String& getter_name = String::Handle(Field::GetterName(target_name));
+ while (!cls.IsNull()) {
+ function ^= cls.LookupDynamicFunction(target_name);
+ if (!function.IsNull()) {
+ ArgumentsDescriptor args_desc(orig_arguments_desc);
+ ASSERT(!function.AreValidArguments(args_desc, NULL));
+ break; // mismatch, invoke noSuchMethod
+ }
+ function ^= cls.LookupDynamicFunction(getter_name);
+ if (!function.IsNull()) {
+ const Array& getter_arguments = Array::Handle(Array::New(1));
+ getter_arguments.SetAt(0, receiver);
+ const Object& getter_result =
+ Object::Handle(DartEntry::InvokeFunction(function,
+ getter_arguments));
+ CheckResultError(getter_result);
+ ASSERT(getter_result.IsNull() || getter_result.IsInstance());
+
+ orig_arguments.SetAt(0, getter_result);
+ const Object& call_result =
+ Object::Handle(DartEntry::InvokeClosure(orig_arguments,
+ orig_arguments_desc));
+ CheckResultError(call_result);
+ arguments.SetReturn(call_result);
+ return;
+ }
+ cls = cls.SuperClass();
+ }
+ }
+
// Handle noSuchMethod invocation.
const Object& result = Object::Handle(
DartEntry::InvokeNoSuchMethod(receiver,
« no previous file with comments | « runtime/lib/mirrors.cc ('k') | runtime/vm/dart_entry.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698