Index: runtime/vm/parser.cc |
=================================================================== |
--- runtime/vm/parser.cc (revision 24991) |
+++ runtime/vm/parser.cc (working copy) |
@@ -776,6 +776,10 @@ |
node_sequence = |
parser.ParseNoSuchMethodDispatcher(func, default_parameter_values); |
break; |
+ case RawFunction::kInvokeFieldDispatcher: |
+ node_sequence = |
+ parser.ParseInvokeFieldDispatcher(func, default_parameter_values); |
+ break; |
default: |
UNREACHABLE(); |
} |
@@ -1108,22 +1112,13 @@ |
} |
-SequenceNode* Parser::ParseNoSuchMethodDispatcher(const Function& func, |
- Array& default_values) { |
- TRACE_PARSER("ParseNoSuchMethodDispatcher"); |
- |
- ASSERT(func.IsNoSuchMethodDispatcher()); |
+void Parser::BuildDispatcherScope(const Function& func, |
+ const ArgumentsDescriptor& desc, |
+ Array& default_values) { |
+ ParamList params; |
+ // Receiver first. |
intptr_t token_pos = func.token_pos(); |
- ASSERT(func.token_pos() == 0); |
- ASSERT(current_class().raw() == func.Owner()); |
- |
- ArgumentsDescriptor desc(Array::Handle(func.saved_args_desc())); |
- ASSERT(desc.Count() > 0); |
- |
- // Create parameter list. Receiver first. |
- ParamList params; |
params.AddReceiver(ReceiverType(), token_pos); |
- |
// Remaining positional parameters. |
intptr_t i = 1; |
for (; i < desc.PositionalCount(); ++i) { |
@@ -1135,6 +1130,8 @@ |
params.parameters->Add(p); |
params.num_fixed_parameters++; |
} |
+ ASSERT(desc.PositionalCount() == params.num_fixed_parameters); |
+ |
// Named parameters. |
for (; i < desc.Count(); ++i) { |
ParamDesc p; |
@@ -1146,23 +1143,40 @@ |
params.num_optional_parameters++; |
params.has_optional_named_parameters = true; |
} |
+ ASSERT(desc.NamedCount() == params.num_optional_parameters); |
SetupDefaultsForOptionalParams(¶ms, default_values); |
// Build local scope for function and populate with the formal parameters. |
OpenFunctionBlock(func); |
- LocalScope* scope = current_block_->scope; |
- AddFormalParamsToScope(¶ms, scope); |
+ AddFormalParamsToScope(¶ms, current_block_->scope); |
+} |
+SequenceNode* Parser::ParseNoSuchMethodDispatcher(const Function& func, |
+ Array& default_values) { |
+ TRACE_PARSER("ParseNoSuchMethodDispatcher"); |
+ |
+ ASSERT(func.IsNoSuchMethodDispatcher()); |
+ intptr_t token_pos = func.token_pos(); |
+ ASSERT(func.token_pos() == 0); |
+ ASSERT(current_class().raw() == func.Owner()); |
+ |
+ ArgumentsDescriptor desc(Array::Handle(func.saved_args_desc())); |
+ ASSERT(desc.Count() > 0); |
+ |
+ // Set up scope for this function. |
+ BuildDispatcherScope(func, desc, default_values); |
+ |
// Receiver is local 0. |
+ LocalScope* scope = current_block_->scope; |
ArgumentListNode* func_args = new ArgumentListNode(token_pos); |
for (intptr_t i = 0; i < desc.Count(); ++i) { |
func_args->Add(new LoadLocalNode(token_pos, scope->VariableAt(i))); |
} |
- if (params.num_optional_parameters > 0) { |
+ if (desc.NamedCount() > 0) { |
const Array& arg_names = |
- Array::ZoneHandle(Array::New(params.num_optional_parameters)); |
+ Array::ZoneHandle(Array::New(desc.NamedCount())); |
for (intptr_t i = 0; i < arg_names.Length(); ++i) { |
arg_names.SetAt(i, String::Handle(desc.NameAt(i))); |
} |
@@ -1186,6 +1200,62 @@ |
} |
+SequenceNode* Parser::ParseInvokeFieldDispatcher(const Function& func, |
+ Array& default_values) { |
+ TRACE_PARSER("ParseInvokeFieldDispatcher"); |
+ |
+ ASSERT(func.IsInvokeFieldDispatcher()); |
+ intptr_t token_pos = func.token_pos(); |
+ ASSERT(func.token_pos() == 0); |
+ ASSERT(current_class().raw() == func.Owner()); |
+ |
+ const Array& args_desc = Array::Handle(func.saved_args_desc()); |
+ ArgumentsDescriptor desc(args_desc); |
+ ASSERT(desc.Count() > 0); |
+ |
+ // Set up scope for this function. |
+ BuildDispatcherScope(func, desc, default_values); |
+ |
+ // Receiver is local 0. |
+ LocalScope* scope = current_block_->scope; |
+ ArgumentListNode* no_args = new ArgumentListNode(token_pos); |
+ LoadLocalNode* receiver = new LoadLocalNode(token_pos, scope->VariableAt(0)); |
+ |
+ const String& name = String::Handle(func.name()); |
+ const String& getter_name = |
+ String::ZoneHandle(Symbols::New(String::Handle(Field::GetterName(name)))); |
+ InstanceCallNode* getter_call = new InstanceCallNode(token_pos, |
+ receiver, |
+ getter_name, |
+ no_args); |
+ |
+ // Pass arguments 1..n to the closure call. |
+ ArgumentListNode* closure_args = new ArgumentListNode(token_pos); |
+ const Array& names = Array::Handle(Array::New(desc.NamedCount(), Heap::kOld)); |
+ // Positional parameters. |
+ intptr_t i = 1; |
+ for (; i < desc.PositionalCount(); ++i) { |
+ closure_args->Add(new LoadLocalNode(token_pos, scope->VariableAt(i))); |
+ } |
+ // Named parameters. |
+ for (; i < desc.Count(); i++) { |
+ closure_args->Add(new LoadLocalNode(token_pos, scope->VariableAt(i))); |
+ intptr_t index = i - desc.PositionalCount(); |
+ names.SetAt(index, String::Handle(desc.NameAt(index))); |
+ } |
+ closure_args->set_names(names); |
+ |
+ EnsureSavedCurrentContext(); |
+ ClosureCallNode* closure_call = new ClosureCallNode(token_pos, |
+ getter_call, |
+ closure_args); |
+ |
+ ReturnNode* return_node = new ReturnNode(token_pos, closure_call); |
+ current_block_->statements->Add(return_node); |
+ return CloseBlock(); |
+} |
+ |
+ |
void Parser::SkipBlock() { |
ASSERT(CurrentToken() == Token::kLBRACE); |
GrowableArray<Token::Kind> token_stack(8); |