Index: runtime/vm/parser.cc |
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
index d11536b775f48a4432b98e5783fd348e6293a117..f949c0001f02d6e34b83de575ab03936f39fe791 100644 |
--- a/runtime/vm/parser.cc |
+++ b/runtime/vm/parser.cc |
@@ -1548,32 +1548,14 @@ SequenceNode* Parser::ParseImplicitClosure(const Function& func) { |
&Object::dynamic_type()); |
const Function& parent = Function::Handle(func.parent_function()); |
- const String& target_name = String::Handle(parent.name()); |
- const Class& owner = Class::Handle(parent.Owner()); |
- Function& target = Function::ZoneHandle(owner.LookupFunction(target_name)); |
- if (target.raw() != parent.raw()) { |
- ASSERT(Isolate::Current()->HasAttemptedReload()); |
- if (target.IsNull() || |
- (target.is_static() != parent.is_static()) || |
- (target.kind() != parent.kind())) { |
- // TODO(26977): call noSuchMethod/throw NSME instead. |
- target = parent.raw(); |
- } |
- } |
- |
- if (target.IsImplicitSetterFunction()) { |
+ if (parent.IsImplicitSetterFunction()) { |
const TokenPosition ident_pos = func.token_pos(); |
ASSERT(IsIdentifier()); |
- const String& field_name = *CurrentLiteral(); |
- const Class& field_class = Class::ZoneHandle(Z, target.Owner()); |
- const Field& field = |
- Field::ZoneHandle(Z, field_class.LookupInstanceField(field_name)); |
- const AbstractType& field_type = AbstractType::ZoneHandle(Z, field.type()); |
params.AddFinalParameter(ident_pos, |
&Symbols::Value(), |
Cutch
2016/08/04 00:38:05
why drop the field type here?
rmacnak
2016/08/04 16:19:31
The lookup can fail if the target no longer exists
|
- &field_type); |
+ &Object::dynamic_type()); |
ASSERT(func.num_fixed_parameters() == 2); // closure, value. |
- } else if (!target.IsGetterFunction() && !target.IsImplicitGetterFunction()) { |
+ } else if (!parent.IsGetterFunction() && !parent.IsImplicitGetterFunction()) { |
const bool allow_explicit_default_values = true; |
SkipFunctionPreamble(); |
ParseFormalParameterList(allow_explicit_default_values, false, ¶ms); |
@@ -1604,7 +1586,71 @@ SequenceNode* Parser::ParseImplicitClosure(const Function& func) { |
} |
func_args->set_names(arg_names); |
} |
- StaticCallNode* call = new StaticCallNode(token_pos, target, func_args); |
+ |
+ const String& func_name = String::ZoneHandle(parent.name()); |
+ const Class& owner = Class::Handle(parent.Owner()); |
+ Function& target = Function::ZoneHandle(owner.LookupFunction(func_name)); |
+ if (target.raw() != parent.raw()) { |
+ ASSERT(Isolate::Current()->HasAttemptedReload()); |
+ if (target.IsNull() || |
+ (target.is_static() != parent.is_static()) || |
+ (target.kind() != parent.kind())) { |
+ target = Function::null(); |
+ } |
+ } |
+ |
+ AstNode* call = NULL; |
+ if (!target.IsNull()) { |
+ call = new StaticCallNode(token_pos, target, func_args); |
+ } else if (!parent.is_static()) { |
+ ASSERT(Isolate::Current()->HasAttemptedReload()); |
+ // If a subsequent reload reintroduces the target in the middle of the |
+ // Invocation object being constructed, we won't be able to successfully |
+ // deopt because the generated AST will change. |
+ current_function().SetIsOptimizable(false); |
+ |
+ ArgumentListNode* arguments = BuildNoSuchMethodArguments( |
+ token_pos, func_name, *func_args, NULL, false); |
+ const intptr_t kNumArguments = 2; // Receiver, InvocationMirror. |
+ ArgumentsDescriptor args_desc( |
+ Array::Handle(Z, ArgumentsDescriptor::New(kNumArguments))); |
+ Function& no_such_method = Function::ZoneHandle(Z, |
+ Resolver::ResolveDynamicForReceiverClass(owner, |
+ Symbols::NoSuchMethod(), |
+ args_desc)); |
+ if (no_such_method.IsNull()) { |
+ // If noSuchMethod(i) is not found, call Object:noSuchMethod. |
+ no_such_method ^= Resolver::ResolveDynamicForReceiverClass( |
+ Class::Handle(Z, I->object_store()->object_class()), |
+ Symbols::NoSuchMethod(), |
+ args_desc); |
+ } |
+ call = new StaticCallNode(token_pos, no_such_method, arguments); |
+ } else { |
+ ASSERT(Isolate::Current()->HasAttemptedReload()); |
+ // If a subsequent reload reintroduces the target in the middle of the |
+ // arguments array being constructed, we won't be able to successfully |
+ // deopt because the generated AST will change. |
+ current_function().SetIsOptimizable(false); |
+ |
+ InvocationMirror::Type im_type; |
+ if (parent.IsImplicitGetterFunction()) { |
+ im_type = InvocationMirror::kGetter; |
+ } else if (parent.IsImplicitSetterFunction()) { |
+ im_type = InvocationMirror::kSetter; |
+ } else { |
+ im_type = InvocationMirror::kMethod; |
+ } |
+ call = ThrowNoSuchMethodError(TokenPos(), |
+ owner, |
+ func_name, |
+ func_args, |
+ InvocationMirror::kStatic, |
+ im_type, |
+ NULL); // No existing function. |
+ } |
+ |
+ ASSERT(call != NULL); |
ReturnNode* return_node = new ReturnNode(token_pos, call); |
current_block_->statements->Add(return_node); |
return CloseBlock(); |