| Index: runtime/vm/aot_optimizer.cc | 
| diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc | 
| index 63464660faa69969d09f1def2e32b1a030d12f89..526cbe97e9b9998cc50c3b89e14ec717c3f922d9 100644 | 
| --- a/runtime/vm/aot_optimizer.cc | 
| +++ b/runtime/vm/aot_optimizer.cc | 
| @@ -113,22 +113,18 @@ bool AotOptimizer::RecognizeRuntimeTypeGetter(InstanceCallInstr* call) { | 
| // There is only a single function Object.get:runtimeType that can be invoked | 
| // by this call. Convert dynamic invocation to a static one. | 
| const Class& cls = Class::Handle(Z, I->object_store()->object_class()); | 
| -  const Array& args_desc_array = Array::Handle( | 
| -      Z, | 
| -      ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names())); | 
| -  ArgumentsDescriptor args_desc(args_desc_array); | 
| const Function& function = | 
| -      Function::Handle(Z, Resolver::ResolveDynamicForReceiverClass( | 
| -                              cls, call->function_name(), args_desc)); | 
| +      Function::Handle(Z, call->ResolveForReceiverClass(cls)); | 
| ASSERT(!function.IsNull()); | 
| - | 
| +  const intptr_t kTypeArgsLen = 0; | 
| +  ASSERT(call->type_args_len() == kTypeArgsLen); | 
| ZoneGrowableArray<PushArgumentInstr*>* args = | 
| new (Z) ZoneGrowableArray<PushArgumentInstr*>(call->ArgumentCount()); | 
| for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 
| args->Add(call->PushArgumentAt(i)); | 
| } | 
| StaticCallInstr* static_call = new (Z) StaticCallInstr( | 
| -      call->token_pos(), Function::ZoneHandle(Z, function.raw()), | 
| +      call->token_pos(), Function::ZoneHandle(Z, function.raw()), kTypeArgsLen, | 
| call->argument_names(), args, call->deopt_id()); | 
| static_call->set_result_cid(kTypeCid); | 
| call->ReplaceWith(static_call, current_iterator()); | 
| @@ -178,9 +174,12 @@ bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) { | 
| return false; | 
| } | 
| GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); | 
| -  ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); | 
| +  const intptr_t receiver_idx = call->FirstParamIndex(); | 
| +  ASSERT(call->ic_data()->NumArgsTested() <= | 
| +         call->ArgumentCountWithoutTypeArgs()); | 
| for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { | 
| -    class_ids.Add(call->PushArgumentAt(i)->value()->Type()->ToCid()); | 
| +    class_ids.Add( | 
| +        call->PushArgumentAt(receiver_idx + i)->value()->Type()->ToCid()); | 
| } | 
|  | 
| const Token::Kind op_kind = call->token_kind(); | 
| @@ -222,13 +221,8 @@ bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) { | 
| // finalized yet. | 
| return false; | 
| } | 
| -    const Array& args_desc_array = | 
| -        Array::Handle(Z, ArgumentsDescriptor::New(call->ArgumentCount(), | 
| -                                                  call->argument_names())); | 
| -    ArgumentsDescriptor args_desc(args_desc_array); | 
| -    const Function& function = Function::Handle( | 
| -        Z, Resolver::ResolveDynamicForReceiverClass( | 
| -               receiver_class, call->function_name(), args_desc)); | 
| +    const Function& function = | 
| +        Function::Handle(Z, call->ResolveForReceiverClass(receiver_class)); | 
| if (function.IsNull()) { | 
| return false; | 
| } | 
| @@ -253,11 +247,18 @@ bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) { | 
| // Check if the target is unique. | 
| Function& target_function = Function::Handle(Z); | 
| GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function); | 
| -    // Calls with named arguments must be resolved/checked at runtime. | 
| +    // Calls passing named arguments and calls to a function taking named | 
| +    // arguments must be resolved/checked at runtime. | 
| +    // Calls passing a type argument vector and calls to a generic function must | 
| +    // be resolved/checked at runtime. | 
| if (!target_function.IsNull() && | 
| !target_function.HasOptionalNamedParameters() && | 
| -        target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, | 
| -                                               /* error_message = */ NULL)) { | 
| +        !target_function.IsGeneric() && | 
| +        target_function.AreValidArgumentCounts( | 
| +            call->type_args_len(), call->ArgumentCountWithoutTypeArgs(), | 
| +            call->argument_names().IsNull() ? 0 | 
| +                                            : call->argument_names().Length(), | 
| +            /* error_message = */ NULL)) { | 
| const Class& cls = Class::Handle(Z, target_function.Owner()); | 
| if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) { | 
| const ICData& ic_data = | 
| @@ -613,6 +614,7 @@ bool AotOptimizer::TryReplaceWithHaveSameRuntimeType(InstanceCallInstr* call) { | 
| const ICData& ic_data = *call->ic_data(); | 
| ASSERT(ic_data.NumArgsTested() == 2); | 
|  | 
| +  ASSERT(call->type_args_len() == 0); | 
| ASSERT(call->ArgumentCount() == 2); | 
| Definition* left = call->ArgumentAt(0); | 
| Definition* right = call->ArgumentAt(1); | 
| @@ -634,10 +636,12 @@ bool AotOptimizer::TryReplaceWithHaveSameRuntimeType(InstanceCallInstr* call) { | 
| arg = new (Z) PushArgumentInstr(new (Z) Value(right->ArgumentAt(0))); | 
| InsertBefore(call, arg, NULL, FlowGraph::kEffect); | 
| args->Add(arg); | 
| -    StaticCallInstr* static_call = | 
| -        new (Z) StaticCallInstr(call->token_pos(), have_same_runtime_type, | 
| -                                Object::null_array(),  // argument_names | 
| -                                args, call->deopt_id()); | 
| +    const intptr_t kTypeArgsLen = 0; | 
| +    ASSERT(call->type_args_len() == kTypeArgsLen); | 
| +    StaticCallInstr* static_call = new (Z) | 
| +        StaticCallInstr(call->token_pos(), have_same_runtime_type, kTypeArgsLen, | 
| +                        Object::null_array(),  // argument_names | 
| +                        args, call->deopt_id()); | 
| static_call->set_result_cid(kBoolCid); | 
| ReplaceCall(call, static_call); | 
| return true; | 
| @@ -652,6 +656,7 @@ bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, | 
| const ICData& ic_data = *call->ic_data(); | 
| ASSERT(ic_data.NumArgsTested() == 2); | 
|  | 
| +  ASSERT(call->type_args_len() == 0); | 
| ASSERT(call->ArgumentCount() == 2); | 
| Definition* const left = call->ArgumentAt(0); | 
| Definition* const right = call->ArgumentAt(1); | 
| @@ -734,6 +739,7 @@ bool AotOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call, | 
| const ICData& ic_data = *call->ic_data(); | 
| ASSERT(ic_data.NumArgsTested() == 2); | 
|  | 
| +  ASSERT(call->type_args_len() == 0); | 
| ASSERT(call->ArgumentCount() == 2); | 
| Definition* left = call->ArgumentAt(0); | 
| Definition* right = call->ArgumentAt(1); | 
| @@ -883,6 +889,7 @@ bool AotOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, | 
| UNREACHABLE(); | 
| } | 
|  | 
| +  ASSERT(call->type_args_len() == 0); | 
| ASSERT(call->ArgumentCount() == 2); | 
| Definition* left = call->ArgumentAt(0); | 
| Definition* right = call->ArgumentAt(1); | 
| @@ -971,6 +978,7 @@ bool AotOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, | 
|  | 
| bool AotOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, | 
| Token::Kind op_kind) { | 
| +  ASSERT(call->type_args_len() == 0); | 
| ASSERT(call->ArgumentCount() == 1); | 
| Definition* input = call->ArgumentAt(0); | 
| Definition* unary_op = NULL; | 
| @@ -1057,6 +1065,7 @@ bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, | 
| if (!ShouldInlineSimd()) { | 
| return false; | 
| } | 
| +  ASSERT(call->type_args_len() == 0); | 
| ASSERT(call->ArgumentCount() == 2); | 
| Definition* const left = call->ArgumentAt(0); | 
| Definition* const right = call->ArgumentAt(1); | 
| @@ -1077,6 +1086,7 @@ bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, | 
| if (!ShouldInlineSimd()) { | 
| return false; | 
| } | 
| +  ASSERT(call->type_args_len() == 0); | 
| ASSERT(call->ArgumentCount() == 2); | 
| Definition* const left = call->ArgumentAt(0); | 
| Definition* const right = call->ArgumentAt(1); | 
| @@ -1096,6 +1106,7 @@ bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, | 
| if (!ShouldInlineSimd()) { | 
| return false; | 
| } | 
| +  ASSERT(call->type_args_len() == 0); | 
| ASSERT(call->ArgumentCount() == 2); | 
| Definition* const left = call->ArgumentAt(0); | 
| Definition* const right = call->ArgumentAt(1); | 
| @@ -1138,6 +1149,7 @@ bool AotOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { | 
| void AotOptimizer::ReplaceWithMathCFunction( | 
| InstanceCallInstr* call, | 
| MethodRecognizer::Kind recognized_kind) { | 
| +  ASSERT(call->type_args_len() == 0); | 
| AddReceiverCheck(call); | 
| ZoneGrowableArray<Value*>* args = | 
| new (Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); | 
| @@ -1418,6 +1430,7 @@ void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { | 
| Definition* instantiator_type_args = NULL; | 
| Definition* function_type_args = NULL; | 
| AbstractType& type = AbstractType::ZoneHandle(Z); | 
| +  ASSERT(call->type_args_len() == 0); | 
| if (call->ArgumentCount() == 2) { | 
| instantiator_type_args = flow_graph()->constant_null(); | 
| function_type_args = flow_graph()->constant_null(); | 
| @@ -1481,8 +1494,9 @@ void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { | 
| ASSERT(!target.IsNull()); | 
| ASSERT(target.IsRecognized() && target.always_inline()); | 
|  | 
| +      const intptr_t kTypeArgsLen = 0; | 
| StaticCallInstr* new_call = | 
| -          new (Z) StaticCallInstr(call->token_pos(), target, | 
| +          new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen, | 
| Object::null_array(),  // argument_names | 
| args, call->deopt_id()); | 
| Environment* copy = call->env()->DeepCopy( | 
| @@ -1530,6 +1544,7 @@ void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { | 
| // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). | 
| void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 
| ASSERT(Token::IsTypeCastOperator(call->token_kind())); | 
| +  ASSERT(call->type_args_len() == 0); | 
| Definition* left = call->ArgumentAt(0); | 
| Definition* instantiator_type_args = call->ArgumentAt(1); | 
| Definition* function_type_args = call->ArgumentAt(2); | 
| @@ -1573,8 +1588,9 @@ void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 
| ASSERT(target.IsRecognized()); | 
| ASSERT(target.always_inline()); | 
|  | 
| +    const intptr_t kTypeArgsLen = 0; | 
| StaticCallInstr* new_call = | 
| -        new (Z) StaticCallInstr(call->token_pos(), target, | 
| +        new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen, | 
| Object::null_array(),  // argument_names | 
| args, call->deopt_id()); | 
| Environment* copy = | 
| @@ -1636,8 +1652,9 @@ void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 
| ASSERT(target.IsRecognized()); | 
| ASSERT(target.always_inline()); | 
|  | 
| +      const intptr_t kTypeArgsLen = 0; | 
| StaticCallInstr* new_call = | 
| -          new (Z) StaticCallInstr(call->token_pos(), target, | 
| +          new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen, | 
| Object::null_array(),  // argument_names | 
| args, call->deopt_id()); | 
| Environment* copy = call->env()->DeepCopy( | 
| @@ -1697,6 +1714,7 @@ bool AotOptimizer::IsAllowedForInlining(intptr_t call_deopt_id) { | 
|  | 
|  | 
| static bool HasLikelySmiOperand(InstanceCallInstr* instr) { | 
| +  ASSERT(instr->type_args_len() == 0); | 
| // Phis with at least one known smi are // guessed to be likely smi as well. | 
| for (intptr_t i = 0; i < instr->ArgumentCount(); ++i) { | 
| PhiInstr* phi = instr->ArgumentAt(i)->AsPhi(); | 
| @@ -1868,14 +1886,8 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 
| if (receiver_cid != kDynamicCid) { | 
| const Class& receiver_class = | 
| Class::Handle(Z, isolate()->class_table()->At(receiver_cid)); | 
| - | 
| -    const Array& args_desc_array = | 
| -        Array::Handle(Z, ArgumentsDescriptor::New(instr->ArgumentCount(), | 
| -                                                  instr->argument_names())); | 
| -    ArgumentsDescriptor args_desc(args_desc_array); | 
| -    Function& function = Function::Handle( | 
| -        Z, Resolver::ResolveDynamicForReceiverClass( | 
| -               receiver_class, instr->function_name(), args_desc)); | 
| +    const Function& function = | 
| +        Function::Handle(Z, instr->ResolveForReceiverClass(receiver_class)); | 
| if (!function.IsNull()) { | 
| CallTargets* targets = new (Z) CallTargets(Z); | 
| Function& target = Function::ZoneHandle(Z, function.raw()); | 
| @@ -1919,20 +1931,14 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 
| // targets with appropriate checks. | 
| Function& single_target = Function::Handle(Z); | 
| ICData& ic_data = ICData::Handle(Z); | 
| - | 
| const Array& args_desc_array = | 
| -          Array::Handle(Z, ArgumentsDescriptor::New(instr->ArgumentCount(), | 
| -                                                    instr->argument_names())); | 
| -      ArgumentsDescriptor args_desc(args_desc_array); | 
| - | 
| +          Array::Handle(Z, instr->GetArgumentsDescriptor()); | 
| Function& target = Function::Handle(Z); | 
| Class& cls = Class::Handle(Z); | 
| for (intptr_t i = 0; i < class_ids.length(); i++) { | 
| const intptr_t cid = class_ids[i]; | 
| cls = isolate()->class_table()->At(cid); | 
| -        target = Resolver::ResolveDynamicForReceiverClass( | 
| -            cls, instr->function_name(), args_desc); | 
| - | 
| +        target = instr->ResolveForReceiverClass(cls); | 
| if (target.IsNull()) { | 
| // Can't resolve the target. It might be a noSuchMethod, | 
| // call through getter or closurization. | 
| @@ -2000,7 +2006,8 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 
| } | 
| StaticCallInstr* call = new (Z) StaticCallInstr( | 
| instr->token_pos(), Function::ZoneHandle(Z, single_target.raw()), | 
| -            instr->argument_names(), args, instr->deopt_id()); | 
| +            instr->type_args_len(), instr->argument_names(), args, | 
| +            instr->deopt_id()); | 
| instr->ReplaceWith(call, current_iterator()); | 
| return; | 
| } else if ((ic_data.raw() != ICData::null()) && | 
| @@ -2041,15 +2048,8 @@ void AotOptimizer::VisitPolymorphicInstanceCall( | 
| if (receiver_cid != kDynamicCid) { | 
| const Class& receiver_class = | 
| Class::Handle(Z, isolate()->class_table()->At(receiver_cid)); | 
| - | 
| -      const Array& args_desc_array = Array::Handle( | 
| -          Z, ArgumentsDescriptor::New(call->ArgumentCount(), | 
| -                                      call->instance_call()->argument_names())); | 
| -      ArgumentsDescriptor args_desc(args_desc_array); | 
| const Function& function = Function::Handle( | 
| -          Z, Resolver::ResolveDynamicForReceiverClass( | 
| -                 receiver_class, call->instance_call()->function_name(), | 
| -                 args_desc)); | 
| +          Z, call->instance_call()->ResolveForReceiverClass(receiver_class)); | 
| if (!function.IsNull()) { | 
| call->set_with_checks(false); | 
| } | 
|  |