| Index: runtime/vm/flow_graph_optimizer.cc
|
| diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
|
| index 7096933a90cae095d5c24cab3825c965771c7431..ad05b66b5a364c90701f1b4b6590684e539b07a1 100644
|
| --- a/runtime/vm/flow_graph_optimizer.cc
|
| +++ b/runtime/vm/flow_graph_optimizer.cc
|
| @@ -603,10 +603,8 @@ bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) {
|
| case kUint8ArrayCid:
|
| case kFloat32ArrayCid:
|
| case kFloat64ArrayCid: {
|
| - ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle());
|
| - InsertBefore(call, null_constant, NULL, Definition::kValue);
|
| - instantiator = new Value(null_constant);
|
| - type_args = new Value(null_constant);
|
| + instantiator = new Value(flow_graph_->constant_null());
|
| + type_args = new Value(flow_graph_->constant_null());
|
| ASSERT((class_id != kUint8ArrayCid) || value_type.IsIntType());
|
| ASSERT((class_id != kFloat32ArrayCid && class_id != kFloat64ArrayCid) ||
|
| value_type.IsDoubleType());
|
| @@ -964,6 +962,23 @@ bool FlowGraphOptimizer::InstanceCallNeedsClassCheck(
|
| }
|
|
|
|
|
| +bool FlowGraphOptimizer::MethodExtractorNeedsClassCheck(
|
| + InstanceCallInstr* call) const {
|
| + if (!FLAG_use_cha) return true;
|
| + Definition* callee_receiver = call->ArgumentAt(0)->value()->definition();
|
| + ASSERT(callee_receiver != NULL);
|
| + const Function& function = flow_graph_->parsed_function().function();
|
| + if (function.IsDynamicFunction() &&
|
| + callee_receiver->IsParameter() &&
|
| + (callee_receiver->AsParameter()->index() == 0)) {
|
| + const String& field_name =
|
| + String::Handle(Field::NameFromGetter(call->function_name()));
|
| + return CHA::HasOverride(Class::Handle(function.Owner()), field_name);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +
|
| void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) {
|
| ASSERT(call->HasICData());
|
| const ICData& ic_data = *call->ic_data();
|
| @@ -1111,6 +1126,8 @@ bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) {
|
| }
|
| InlineImplicitInstanceGetter(call);
|
| return true;
|
| + } else if (target.kind() == RawFunction::kMethodExtractor) {
|
| + return false;
|
| }
|
|
|
| // Not an implicit getter.
|
| @@ -1363,6 +1380,7 @@ void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
|
|
|
| const ICData& unary_checks =
|
| ICData::ZoneHandle(instr->ic_data()->AsUnaryClassChecks());
|
| +
|
| if ((unary_checks.NumberOfChecks() > FLAG_max_polymorphic_checks) &&
|
| InstanceCallNeedsClassCheck(instr)) {
|
| // Too many checks, it will be megamorphic which needs unary checks.
|
| @@ -1395,17 +1413,27 @@ void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
|
| if (TryInlineInstanceMethod(instr)) {
|
| return;
|
| }
|
| - if (!InstanceCallNeedsClassCheck(instr)) {
|
| - const bool call_with_checks = false;
|
| - PolymorphicInstanceCallInstr* call =
|
| - new PolymorphicInstanceCallInstr(instr, unary_checks,
|
| - call_with_checks);
|
| - instr->ReplaceWith(call, current_iterator());
|
| - return;
|
| +
|
| + const bool has_one_target = unary_checks.HasOneTarget();
|
| +
|
| + if (has_one_target) {
|
| + const bool is_method_extraction =
|
| + Function::Handle(unary_checks.GetTargetAt(0)).IsMethodExtractor();
|
| +
|
| + if ((is_method_extraction && !MethodExtractorNeedsClassCheck(instr)) ||
|
| + (!is_method_extraction && !InstanceCallNeedsClassCheck(instr))) {
|
| + const bool call_with_checks = false;
|
| + PolymorphicInstanceCallInstr* call =
|
| + new PolymorphicInstanceCallInstr(instr, unary_checks,
|
| + call_with_checks);
|
| + instr->ReplaceWith(call, current_iterator());
|
| + return;
|
| + }
|
| }
|
| +
|
| if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
|
| bool call_with_checks;
|
| - if (unary_checks.HasOneTarget()) {
|
| + if (has_one_target) {
|
| // Type propagation has not run yet, we cannot eliminate the check.
|
| AddCheckClass(instr, instr->ArgumentAt(0)->value()->Copy());
|
| // Call can still deoptimize, do not detach environment from instr.
|
|
|