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..16b23da8c15fbe06a14086ba5954babef0f9640e 100644 |
| --- a/runtime/vm/aot_optimizer.cc |
| +++ b/runtime/vm/aot_optimizer.cc |
| @@ -281,11 +281,11 @@ void AotOptimizer::SpecializePolymorphicInstanceCall( |
| return; |
| } |
| - const bool with_checks = false; |
| PolymorphicInstanceCallInstr* specialized = |
| new(Z) PolymorphicInstanceCallInstr(call->instance_call(), |
| ic_data, |
| - with_checks); |
| + /* with_checks = */ false, |
| + /* complete = */ false); |
| call->ReplaceWith(specialized, current_iterator()); |
| } |
| @@ -2441,7 +2441,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 +2515,71 @@ 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) { |
|
srdjan
2016/04/11 18:10:42
How about parametrizing 5 (with a flag), or at lea
rmacnak
2016/04/11 19:33:42
Added FLAG_max_exhaustive_polymorphic_checks
|
| + 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 && (ic_data.NumberOfChecks() > 0)) { |
| + PolymorphicInstanceCallInstr* call = |
|
Florian Schneider
2016/04/11 17:42:25
Could you change IL printing for PolymorphicInstan
rmacnak
2016/04/11 19:33:42
Done.
|
| + 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 +2588,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; |
| } |