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); |
} |