| Index: runtime/vm/aot_optimizer.cc
|
| diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
|
| index a30e36b328a0b24abbbb54cc6b4e084b11729764..dedbde4c5175e30d1af1133106c97f4370e73ebd 100644
|
| --- a/runtime/vm/aot_optimizer.cc
|
| +++ b/runtime/vm/aot_optimizer.cc
|
| @@ -113,22 +113,21 @@ 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 = call->GetArgumentsDescriptor(Z);
|
| 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 +177,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,9 +224,7 @@ bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) {
|
| // finalized yet.
|
| return false;
|
| }
|
| - const Array& args_desc_array =
|
| - Array::Handle(Z, ArgumentsDescriptor::New(call->ArgumentCount(),
|
| - call->argument_names()));
|
| + const Array& args_desc_array = call->GetArgumentsDescriptor(Z);
|
| ArgumentsDescriptor args_desc(args_desc_array);
|
| const Function& function = Function::Handle(
|
| Z, Resolver::ResolveDynamicForReceiverClass(
|
| @@ -253,11 +253,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 =
|
| @@ -628,6 +635,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);
|
| @@ -649,10 +657,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;
|
| @@ -667,6 +677,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* left = call->ArgumentAt(0);
|
| Definition* right = call->ArgumentAt(1);
|
| @@ -753,6 +764,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);
|
| @@ -902,6 +914,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);
|
| @@ -990,6 +1003,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;
|
| @@ -1076,6 +1090,7 @@ bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
|
| if (!ShouldInlineSimd()) {
|
| return false;
|
| }
|
| + ASSERT(call->type_args_len() == 0);
|
| ASSERT(call->ArgumentCount() == 2);
|
| Definition* left = call->ArgumentAt(0);
|
| Definition* right = call->ArgumentAt(1);
|
| @@ -1101,6 +1116,7 @@ bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call,
|
| if (!ShouldInlineSimd()) {
|
| return false;
|
| }
|
| + ASSERT(call->type_args_len() == 0);
|
| ASSERT(call->ArgumentCount() == 2);
|
| Definition* left = call->ArgumentAt(0);
|
| Definition* right = call->ArgumentAt(1);
|
| @@ -1125,6 +1141,7 @@ bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call,
|
| if (!ShouldInlineSimd()) {
|
| return false;
|
| }
|
| + ASSERT(call->type_args_len() == 0);
|
| ASSERT(call->ArgumentCount() == 2);
|
| Definition* left = call->ArgumentAt(0);
|
| Definition* right = call->ArgumentAt(1);
|
| @@ -1172,6 +1189,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());
|
| @@ -1452,6 +1470,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();
|
| @@ -1515,8 +1534,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(
|
| @@ -1564,6 +1584,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);
|
| @@ -1607,8 +1628,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 =
|
| @@ -1670,8 +1692,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(
|
| @@ -1731,6 +1754,9 @@ bool AotOptimizer::IsAllowedForInlining(intptr_t call_deopt_id) {
|
|
|
|
|
| static bool HasLikelySmiOperand(InstanceCallInstr* instr) {
|
| + if (instr->type_args_len() > 0) {
|
| + 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();
|
| @@ -1901,10 +1927,7 @@ 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(instr->GetArgumentsDescriptor(Z));
|
| Function& function = Function::Handle(
|
| Z, Resolver::ResolveDynamicForReceiverClass(
|
| receiver_class, instr->function_name(), args_desc));
|
| @@ -1951,12 +1974,8 @@ 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()));
|
| + const Array& args_desc_array = instr->GetArgumentsDescriptor(Z);
|
| 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++) {
|
| @@ -2032,7 +2051,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()) &&
|
| @@ -2073,11 +2093,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(
|
| + call->instance_call()->GetArgumentsDescriptor(Z));
|
| const Function& function = Function::Handle(
|
| Z, Resolver::ResolveDynamicForReceiverClass(
|
| receiver_class, call->instance_call()->function_name(),
|
|
|