Chromium Code Reviews| Index: runtime/vm/aot_optimizer.cc |
| diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc |
| index c39f74c88523fa12516a60d60113924011f46102..c89b31d4c555583dc65209d07fb1fcca7e2062c7 100644 |
| --- a/runtime/vm/aot_optimizer.cc |
| +++ b/runtime/vm/aot_optimizer.cc |
| @@ -282,10 +282,12 @@ void AotOptimizer::SpecializePolymorphicInstanceCall( |
| } |
| const bool with_checks = false; |
| + const bool complete = false; |
| PolymorphicInstanceCallInstr* specialized = |
| new(Z) PolymorphicInstanceCallInstr(call->instance_call(), |
| ic_data, |
| - with_checks); |
| + with_checks, |
|
Florian Schneider
2016/04/08 22:39:38
for style consistency:
/* with_checks = */ false
rmacnak
2016/04/11 17:20:23
Done.
|
| + complete); |
| call->ReplaceWith(specialized, current_iterator()); |
| } |
| @@ -2441,7 +2443,8 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| instr, function_kind)) { |
| PolymorphicInstanceCallInstr* call = |
| new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
| - /* with_checks = */ false); |
| + /* with_checks = */ false, |
| + /* complete = */ true); |
| instr->ReplaceWith(call, current_iterator()); |
| return; |
| } |
| @@ -2514,13 +2517,73 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| ic_data.AddReceiverCheck(receiver_class.id(), function); |
| PolymorphicInstanceCallInstr* call = |
| new(Z) PolymorphicInstanceCallInstr(instr, ic_data, |
| - /* with_checks = */ false); |
| + /* with_checks = */ false, |
| + /* complete = */ true); |
| instr->ReplaceWith(call, current_iterator()); |
| return; |
| } |
| } |
| } |
| + Definition* callee_receiver = instr->ArgumentAt(0); |
| + const Function& function = flow_graph_->function(); |
| + if (function.IsDynamicFunction() && |
| + flow_graph_->IsReceiver(callee_receiver)) { |
| + // Call receiver is method receiver. |
| + Class& receiver_class = Class::Handle(Z, function.Owner()); |
| + GrowableArray<intptr_t> class_ids(6); |
| + if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) { |
| + if (class_ids.length() <= 5) { |
| + ASSERT(class_ids.length() > 0); |
| + if (FLAG_trace_cha) { |
| + THR_Print(" **(CHA) Only %" Pd " concrete subclasses of %s for %s\n", |
| + class_ids.length(), |
| + receiver_class.ToCString(), |
| + instr->function_name().ToCString()); |
| + } |
| + |
| + const Array& args_desc_array = Array::Handle(Z, |
| + ArgumentsDescriptor::New(instr->ArgumentCount(), |
| + instr->argument_names())); |
| + ArgumentsDescriptor args_desc(args_desc_array); |
| + |
| + const ICData& ic_data = ICData::Handle( |
| + ICData::New(function, |
| + instr->function_name(), |
| + args_desc_array, |
| + Thread::kNoDeoptId, |
| + /* args_tested = */ 1)); |
| + |
| + Function& target = Function::Handle(Z); |
| + Class& cls = Class::Handle(Z); |
| + bool includes_dispatcher_case = false; |
| + for (intptr_t i = 0; i < class_ids.length(); i++) { |
| + intptr_t cid = class_ids[i]; |
| + cls = isolate()->class_table()->At(cid); |
| + target = Resolver::ResolveDynamicForReceiverClass( |
| + cls, |
| + instr->function_name(), |
| + args_desc); |
| + if (target.IsNull()) { |
| + // noSuchMethod, call through getter or closurization |
| + includes_dispatcher_case = true; |
| + } else { |
| + ic_data.AddReceiverCheck(cid, target); |
| + } |
| + } |
| + if (!includes_dispatcher_case) { |
| + ASSERT(ic_data.NumberOfChecks() > 0); |
| + PolymorphicInstanceCallInstr* call = |
| + new(Z) PolymorphicInstanceCallInstr(instr, ic_data, |
| + /* with_checks = */ true, |
| + /* complete = */ true); |
| + instr->ReplaceWith(call, current_iterator()); |
| + return; |
| + } |
| + } |
| + } |
| + } |
| + |
| // More than one targets. Generate generic polymorphic call without |
| // deoptimization. |
| if (instr->ic_data()->NumberOfUsedChecks() > 0) { |
| @@ -2529,7 +2592,8 @@ void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| // deoptimization is allowed. |
| PolymorphicInstanceCallInstr* call = |
| new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
| - /* with_checks = */ true); |
| + /* with_checks = */ true, |
| + /* complete = */ false); |
| instr->ReplaceWith(call, current_iterator()); |
| return; |
| } |