| Index: runtime/vm/resolver.cc
|
| diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
|
| index 23d46b447937f5c1cdd56fdd141cb4035461c4ca..5a55b483ddd19009ac6beca31002698fb2b83cf4 100644
|
| --- a/runtime/vm/resolver.cc
|
| +++ b/runtime/vm/resolver.cc
|
| @@ -8,6 +8,7 @@
|
| #include "vm/isolate.h"
|
| #include "vm/object.h"
|
| #include "vm/object_store.h"
|
| +#include "vm/symbols.h"
|
|
|
| namespace dart {
|
|
|
| @@ -71,6 +72,47 @@ RawFunction* Resolver::ResolveDynamicForReceiverClass(
|
| }
|
|
|
|
|
| +// Method extractors are used to create implicit closures from methods.
|
| +// When an expression obj.M is evaluated for the first time and receiver obj
|
| +// does not have a getter called M but has a method called M then an extractor
|
| +// is created and injected as a getter (under the name get:M) into the class
|
| +// ownining method M.
|
| +static RawFunction* CreateMethodExtractor(const String& getter_name,
|
| + const Function& method) {
|
| + const Function& closure_function =
|
| + Function::Handle(method.ImplicitClosureFunction());
|
| +
|
| + const Class& owner = Class::Handle(closure_function.Owner());
|
| + Function& extractor = Function::Handle(
|
| + Function::New(String::Handle(Symbols::New(getter_name)),
|
| + RawFunction::kMethodExtractor,
|
| + false, // Not static.
|
| + false, // Not const.
|
| + false, // Not abstract.
|
| + false, // Not external.
|
| + owner,
|
| + 0)); // No token position.
|
| +
|
| + // Initialize signature: receiver is a single fixed parameter.
|
| + const intptr_t kNumParameters = 1;
|
| + extractor.set_num_fixed_parameters(kNumParameters);
|
| + extractor.SetNumOptionalParameters(0, 0);
|
| + extractor.set_parameter_types(Array::Handle(Array::New(kNumParameters,
|
| + Heap::kOld)));
|
| + extractor.set_parameter_names(Array::Handle(Array::New(kNumParameters,
|
| + Heap::kOld)));
|
| + extractor.SetParameterTypeAt(0, Type::Handle(Type::DynamicType()));
|
| + extractor.SetParameterNameAt(0, Symbols::This());
|
| + extractor.set_result_type(Type::Handle(Type::DynamicType()));
|
| +
|
| + extractor.set_extracted_method_closure(closure_function);
|
| +
|
| + owner.AddFunction(extractor);
|
| +
|
| + return extractor.raw();
|
| +}
|
| +
|
| +
|
| RawFunction* Resolver::ResolveDynamicAnyArgs(
|
| const Class& receiver_class,
|
| const String& function_name) {
|
| @@ -80,14 +122,30 @@ RawFunction* Resolver::ResolveDynamicAnyArgs(
|
| function_name.ToCString(),
|
| String::Handle(cls.Name()).ToCString());
|
| }
|
| +
|
| + const bool is_getter = Field::IsGetterName(function_name);
|
| + String& field_name = String::Handle();
|
| + if (is_getter) {
|
| + field_name ^= Field::NameFromGetter(function_name);
|
| + }
|
| +
|
| // Now look for an instance function whose name matches function_name
|
| // in the class.
|
| - Function& function =
|
| - Function::Handle(cls.LookupDynamicFunction(function_name));
|
| - while (function.IsNull()) {
|
| + Function& function = Function::Handle();
|
| + while (function.IsNull() && !cls.IsNull()) {
|
| + function ^= cls.LookupDynamicFunction(function_name);
|
| +
|
| + // Getter invocation might actually be a method extraction.
|
| + if (is_getter && function.IsNull()) {
|
| + function ^= cls.LookupDynamicFunction(field_name);
|
| + if (!function.IsNull()) {
|
| + // We were looking for the getter but found a method with the same name.
|
| + // Create a method extractor and return it.
|
| + function ^= CreateMethodExtractor(function_name, function);
|
| + }
|
| + }
|
| +
|
| cls = cls.SuperClass();
|
| - if (cls.IsNull()) break;
|
| - function = cls.LookupDynamicFunction(function_name);
|
| }
|
| return function.raw();
|
| }
|
|
|