Chromium Code Reviews| Index: runtime/vm/aot_optimizer.cc |
| diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc |
| index 208a2240fc853d3f771e61e847f7b873398de16c..7289960a1a7cbe3652833eb58ede71ffe647e32e 100644 |
| --- a/runtime/vm/aot_optimizer.cc |
| +++ b/runtime/vm/aot_optimizer.cc |
| @@ -88,6 +88,48 @@ void AotOptimizer::PopulateWithICData() { |
| } |
| +bool AotOptimizer::RecognizeRuntimeTypeGetter(InstanceCallInstr* call) { |
| + if ((precompiler_ == NULL) || !precompiler_->get_runtime_type_is_unique()) { |
| + return false; |
| + } |
| + |
| + if (call->function_name().raw() != Symbols::GetRuntimeType().raw()) { |
| + return false; |
| + } |
| + |
| + // 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, thread()->isolate()->object_store()->object_class()); |
|
siva
2016/09/29 02:28:20
there seems to be an I in this file so I->object_s
Vyacheslav Egorov (Google)
2016/09/29 15:01:43
Done.
|
| + 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)); |
| + ASSERT(!function.IsNull()); |
| + |
| + 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->argument_names(), |
| + args, |
| + call->deopt_id()); |
| + static_call->set_result_cid(kTypeCid); |
| + call->ReplaceWith(static_call, current_iterator()); |
| + return true; |
| +} |
| + |
| + |
| // Optimize instance calls using cid. This is called after optimizer |
| // converted instance calls to instructions. Any remaining |
| // instance calls are either megamorphic calls, cannot be optimized or |
| @@ -105,7 +147,9 @@ void AotOptimizer::ApplyClassIds() { |
| Instruction* instr = it.Current(); |
| if (instr->IsInstanceCall()) { |
| InstanceCallInstr* call = instr->AsInstanceCall(); |
| - if (call->HasICData()) { |
| + if (RecognizeRuntimeTypeGetter(call)) { |
|
Florian Schneider
2016/09/28 22:49:24
Any reason why this is here and not in AotOptimize
Vyacheslav Egorov (Google)
2016/09/29 00:31:22
Because we will never get into VisitInstanceCall i
Florian Schneider
2016/09/29 18:03:28
Yes, I meant that the ApplyICData phase always vis
Vyacheslav Egorov (Google)
2016/09/30 09:56:28
Fair enough. Moved it into VisitInstanceCall.
|
| + continue; |
| + } else if (call->HasICData()) { |
| if (TryCreateICData(call)) { |
| VisitInstanceCall(call); |
| } |
| @@ -606,6 +650,13 @@ bool AotOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call, |
| static bool SmiFitsInDouble() { return kSmiBits < 53; } |
| +static bool IsGetRuntimeType(Definition* defn) { |
| + StaticCallInstr* call = defn->AsStaticCall(); |
| + return (call != NULL) && |
| + (call->function().recognized_kind() == |
| + MethodRecognizer::kObjectRuntimeType); |
| +} |
| + |
| bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, |
| Token::Kind op_kind) { |
| const ICData& ic_data = *call->ic_data(); |
| @@ -615,13 +666,40 @@ bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, |
| Definition* left = call->ArgumentAt(0); |
| Definition* right = call->ArgumentAt(1); |
| + // Recognize a.runtimeType == b.runtimeType and fold it into |
| + // Object._haveSameRuntimeType(a, b). |
| + if (IsGetRuntimeType(left) && left->input_use_list()->IsSingleUse() && |
| + IsGetRuntimeType(right) && right->input_use_list()->IsSingleUse()) { |
| + const Class& cls = |
| + Class::Handle(Z, thread()->isolate()->object_store()->object_class()); |
|
siva
2016/09/29 02:28:20
Ditto comment about I
Vyacheslav Egorov (Google)
2016/09/29 15:01:43
Done.
|
| + const Function& hasSameRuntimeType = Function::ZoneHandle(Z, |
| + cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType())); |
| + ASSERT(!hasSameRuntimeType.IsNull()); |
| + |
| + ZoneGrowableArray<PushArgumentInstr*>* args = |
| + new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
| + PushArgumentInstr* arg = new (Z) PushArgumentInstr( |
| + new (Z) Value(left->ArgumentAt(0))); |
| + InsertBefore(call, arg, NULL, FlowGraph::kEffect); |
| + args->Add(arg); |
| + 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(), |
| + hasSameRuntimeType, |
| + Object::null_array(), // argument_names |
| + args, |
| + call->deopt_id()); |
| + static_call->set_result_cid(kBoolCid); |
| + ReplaceCall(call, static_call); |
| + return true; |
| + } |
| + |
| intptr_t cid = kIllegalCid; |
| if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { |
| - if (TryStringLengthOneEquality(call, op_kind)) { |
| - return true; |
| - } else { |
| - return false; |
| - } |
| + return TryStringLengthOneEquality(call, op_kind); |
| } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
| InsertBefore(call, |
| new(Z) CheckSmiInstr(new(Z) Value(left), |