Chromium Code Reviews| Index: runtime/vm/aot_optimizer.cc |
| diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc |
| index 63464660faa69969d09f1def2e32b1a030d12f89..2a8d7d393d0489d9ed1904ebbdeed6f90ad74bcc 100644 |
| --- a/runtime/vm/aot_optimizer.cc |
| +++ b/runtime/vm/aot_optimizer.cc |
| @@ -113,22 +113,22 @@ 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())); |
| + const Array& args_desc_array = |
|
Vyacheslav Egorov (Google)
2017/05/13 22:20:13
This pattern is repeated - maybe call instruction
regis
2017/05/18 21:02:12
Done.
|
| + Array::Handle(Z, call->GetArgumentsDescriptor()); |
| ArgumentsDescriptor args_desc(args_desc_array); |
| const Function& function = |
| Function::Handle(Z, Resolver::ResolveDynamicForReceiverClass( |
| cls, call->function_name(), args_desc)); |
| 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 +178,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(); |
| @@ -223,8 +226,7 @@ bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) { |
| return false; |
| } |
| const Array& args_desc_array = |
| - Array::Handle(Z, ArgumentsDescriptor::New(call->ArgumentCount(), |
| - call->argument_names())); |
| + Array::Handle(Z, call->GetArgumentsDescriptor()); |
| ArgumentsDescriptor args_desc(args_desc_array); |
| const Function& function = Function::Handle( |
| Z, Resolver::ResolveDynamicForReceiverClass( |
| @@ -253,11 +255,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 +622,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 +644,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 +664,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 +747,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 +897,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 +986,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 +1073,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 +1094,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 +1114,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 +1157,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 +1438,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 +1502,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 +1552,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 +1596,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 +1660,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 +1722,9 @@ bool AotOptimizer::IsAllowedForInlining(intptr_t call_deopt_id) { |
| static bool HasLikelySmiOperand(InstanceCallInstr* instr) { |
| + if (instr->type_args_len() > 0) { |
|
Vyacheslav Egorov (Google)
2017/05/13 22:20:13
Should not be possible. These are operators, no wa
regis
2017/05/18 21:02:12
What I thought. Replaced by assert.
|
| + return false; // TODO(regis): Is it even possible? Replace with assert. |
| + } |
| // 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(); |
| @@ -1869,10 +1897,8 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| 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); |
| + ArgumentsDescriptor args_desc( |
| + Array::Handle(Z, instr->GetArgumentsDescriptor())); |
| Function& function = Function::Handle( |
| Z, Resolver::ResolveDynamicForReceiverClass( |
| receiver_class, instr->function_name(), args_desc)); |
| @@ -1919,12 +1945,9 @@ 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())); |
| + Array::Handle(Z, instr->GetArgumentsDescriptor()); |
| ArgumentsDescriptor args_desc(args_desc_array); |
| - |
| Function& target = Function::Handle(Z); |
| Class& cls = Class::Handle(Z); |
| for (intptr_t i = 0; i < class_ids.length(); i++) { |
| @@ -2000,7 +2023,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,11 +2065,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); |
| + ArgumentsDescriptor args_desc( |
| + Array::Handle(Z, call->instance_call()->GetArgumentsDescriptor())); |
| const Function& function = Function::Handle( |
| Z, Resolver::ResolveDynamicForReceiverClass( |
| receiver_class, call->instance_call()->function_name(), |