Chromium Code Reviews| Index: runtime/vm/code_generator.cc |
| diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc |
| index 6c1dc9b0027c0859f59f404edca8abae8c8eab78..76733b920e3199a25cc3f374be7456ad8d9e5a4b 100644 |
| --- a/runtime/vm/code_generator.cc |
| +++ b/runtime/vm/code_generator.cc |
| @@ -1054,23 +1054,70 @@ DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) { |
| // a zigzagged lookup to see if this call failed because of an arity mismatch, |
| // need for conversion, or there really is no such method. |
| +#define NO_SUCH_METHOD() \ |
| + const Object& result = Object::Handle( \ |
| + DartEntry::InvokeNoSuchMethod(receiver, \ |
| + target_name, \ |
| + orig_arguments, \ |
| + orig_arguments_desc)); \ |
| + CheckResultError(result); \ |
| + arguments.SetReturn(result); \ |
| + return; \ |
|
hausner
2015/08/04 18:21:53
I'd leave the return statement in the function bod
rmacnak
2015/08/04 23:11:24
Done.
|
| + |
| +#define CLOSURIZE(some_function) \ |
| + const Function& closure_function = \ |
| + Function::Handle(some_function.ImplicitClosureFunction()); \ |
| + const Object& result = \ |
| + Object::Handle(closure_function.ImplicitInstanceClosure(receiver)); \ |
| + arguments.SetReturn(result); \ |
| + return; \ |
|
hausner
2015/08/04 18:21:53
Same here. I would leave the return statement in t
rmacnak
2015/08/04 23:11:25
Done.
|
| + |
| 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)); |
| + // o.foo (o.get:foo) failed, closurize o.foo() if it exists. Or, |
| + // o#foo (o.get:#foo) failed, closurizee o.foo or o.foo(), whichever is |
| + // encountered first on the inheritance chain. Or, |
| + // o#foo= (o.get:#set:foo) failed, closurize o.foo= if it exists. |
| + String& field_name = |
| + String::Handle(Field::NameFromGetter(target_name)); |
| + |
| + const bool is_extractor = field_name.CharAt(0) == '#'; |
| + if (is_extractor) { |
| + field_name = String::SubString(field_name, 1); |
| + ASSERT(!Field::IsGetterName(field_name)); |
| + field_name = Symbols::New(field_name); |
| + |
| + if (!Field::IsSetterName(field_name)) { |
| + const String& getter_name = |
| + String::Handle(Field::GetterName(field_name)); |
| + |
| + // Zigzagged lookup: closure either a regular method or a getter. |
| + while (!cls.IsNull()) { |
| + function ^= cls.LookupDynamicFunction(field_name); |
| + if (!function.IsNull()) { |
| + CLOSURIZE(function); |
| + } |
| + function ^= cls.LookupDynamicFunction(getter_name); |
| + if (!function.IsNull()) { |
| + CLOSURIZE(function); |
| + } |
| + cls = cls.SuperClass(); |
| + } |
| + NO_SUCH_METHOD(); |
| + } else { |
| + // Fall through for non-ziggaged lookup for o#foo=. |
| + } |
| + } |
| + |
| 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; |
| + CLOSURIZE(function); |
| } |
| cls = cls.SuperClass(); |
| } |
| + |
| + // Fall through for noSuchMethod |
| } else { |
| // o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong |
| // number of arguments, or try (o.foo).call(...) |
| @@ -1117,14 +1164,10 @@ DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) { |
| } |
| } |
| - // Handle noSuchMethod invocation. |
| - const Object& result = Object::Handle( |
| - DartEntry::InvokeNoSuchMethod(receiver, |
| - target_name, |
| - orig_arguments, |
| - orig_arguments_desc)); |
| - CheckResultError(result); |
| - arguments.SetReturn(result); |
| + NO_SUCH_METHOD(); |
| + |
| +#undef NO_SUCH_METHOD |
| +#undef CLOSURIZE |
| } |