OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/aot_optimizer.h" | 5 #include "vm/aot_optimizer.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/branch_optimizer.h" | 8 #include "vm/branch_optimizer.h" |
9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
81 call->checked_argument_count(), false)); | 81 call->checked_argument_count(), false)); |
82 call->set_ic_data(&ic_data); | 82 call->set_ic_data(&ic_data); |
83 } | 83 } |
84 } | 84 } |
85 } | 85 } |
86 current_iterator_ = NULL; | 86 current_iterator_ = NULL; |
87 } | 87 } |
88 } | 88 } |
89 | 89 |
90 | 90 |
91 bool AotOptimizer::RecognizeRuntimeTypeGetter(InstanceCallInstr* call) { | |
92 if ((precompiler_ == NULL) || !precompiler_->get_runtime_type_is_unique()) { | |
93 return false; | |
94 } | |
95 | |
96 if (call->function_name().raw() != Symbols::GetRuntimeType().raw()) { | |
97 return false; | |
98 } | |
99 | |
100 // There is only a single function Object.get:runtimeType that can be invoked | |
101 // by this call. Convert dynamic invocation to a static one. | |
102 const Class& cls = | |
103 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.
| |
104 const Array& args_desc_array = Array::Handle(Z, | |
105 ArgumentsDescriptor::New(call->ArgumentCount(), | |
106 call->argument_names())); | |
107 ArgumentsDescriptor args_desc(args_desc_array); | |
108 const Function& function = Function::Handle(Z, | |
109 Resolver::ResolveDynamicForReceiverClass( | |
110 cls, | |
111 call->function_name(), | |
112 args_desc)); | |
113 ASSERT(!function.IsNull()); | |
114 | |
115 ZoneGrowableArray<PushArgumentInstr*>* args = | |
116 new (Z) ZoneGrowableArray<PushArgumentInstr*>( | |
117 call->ArgumentCount()); | |
118 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | |
119 args->Add(call->PushArgumentAt(i)); | |
120 } | |
121 StaticCallInstr* static_call = new (Z) StaticCallInstr( | |
122 call->token_pos(), | |
123 Function::ZoneHandle(Z, function.raw()), | |
124 call->argument_names(), | |
125 args, | |
126 call->deopt_id()); | |
127 static_call->set_result_cid(kTypeCid); | |
128 call->ReplaceWith(static_call, current_iterator()); | |
129 return true; | |
130 } | |
131 | |
132 | |
91 // Optimize instance calls using cid. This is called after optimizer | 133 // Optimize instance calls using cid. This is called after optimizer |
92 // converted instance calls to instructions. Any remaining | 134 // converted instance calls to instructions. Any remaining |
93 // instance calls are either megamorphic calls, cannot be optimized or | 135 // instance calls are either megamorphic calls, cannot be optimized or |
94 // have no runtime type feedback collected. | 136 // have no runtime type feedback collected. |
95 // Attempts to convert an instance call (IC call) using propagated class-ids, | 137 // Attempts to convert an instance call (IC call) using propagated class-ids, |
96 // e.g., receiver class id, guarded-cid, or by guessing cid-s. | 138 // e.g., receiver class id, guarded-cid, or by guessing cid-s. |
97 void AotOptimizer::ApplyClassIds() { | 139 void AotOptimizer::ApplyClassIds() { |
98 ASSERT(current_iterator_ == NULL); | 140 ASSERT(current_iterator_ == NULL); |
99 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); | 141 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
100 !block_it.Done(); | 142 !block_it.Done(); |
101 block_it.Advance()) { | 143 block_it.Advance()) { |
102 ForwardInstructionIterator it(block_it.Current()); | 144 ForwardInstructionIterator it(block_it.Current()); |
103 current_iterator_ = ⁢ | 145 current_iterator_ = ⁢ |
104 for (; !it.Done(); it.Advance()) { | 146 for (; !it.Done(); it.Advance()) { |
105 Instruction* instr = it.Current(); | 147 Instruction* instr = it.Current(); |
106 if (instr->IsInstanceCall()) { | 148 if (instr->IsInstanceCall()) { |
107 InstanceCallInstr* call = instr->AsInstanceCall(); | 149 InstanceCallInstr* call = instr->AsInstanceCall(); |
108 if (call->HasICData()) { | 150 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.
| |
151 continue; | |
152 } else if (call->HasICData()) { | |
109 if (TryCreateICData(call)) { | 153 if (TryCreateICData(call)) { |
110 VisitInstanceCall(call); | 154 VisitInstanceCall(call); |
111 } | 155 } |
112 } | 156 } |
113 } | 157 } |
114 } | 158 } |
115 current_iterator_ = NULL; | 159 current_iterator_ = NULL; |
116 } | 160 } |
117 } | 161 } |
118 | 162 |
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
599 to_remove_right->RemoveFromGraph(); | 643 to_remove_right->RemoveFromGraph(); |
600 } | 644 } |
601 return true; | 645 return true; |
602 } | 646 } |
603 return false; | 647 return false; |
604 } | 648 } |
605 | 649 |
606 | 650 |
607 static bool SmiFitsInDouble() { return kSmiBits < 53; } | 651 static bool SmiFitsInDouble() { return kSmiBits < 53; } |
608 | 652 |
653 static bool IsGetRuntimeType(Definition* defn) { | |
654 StaticCallInstr* call = defn->AsStaticCall(); | |
655 return (call != NULL) && | |
656 (call->function().recognized_kind() == | |
657 MethodRecognizer::kObjectRuntimeType); | |
658 } | |
659 | |
609 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, | 660 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, |
610 Token::Kind op_kind) { | 661 Token::Kind op_kind) { |
611 const ICData& ic_data = *call->ic_data(); | 662 const ICData& ic_data = *call->ic_data(); |
612 ASSERT(ic_data.NumArgsTested() == 2); | 663 ASSERT(ic_data.NumArgsTested() == 2); |
613 | 664 |
614 ASSERT(call->ArgumentCount() == 2); | 665 ASSERT(call->ArgumentCount() == 2); |
615 Definition* left = call->ArgumentAt(0); | 666 Definition* left = call->ArgumentAt(0); |
616 Definition* right = call->ArgumentAt(1); | 667 Definition* right = call->ArgumentAt(1); |
617 | 668 |
669 // Recognize a.runtimeType == b.runtimeType and fold it into | |
670 // Object._haveSameRuntimeType(a, b). | |
671 if (IsGetRuntimeType(left) && left->input_use_list()->IsSingleUse() && | |
672 IsGetRuntimeType(right) && right->input_use_list()->IsSingleUse()) { | |
673 const Class& cls = | |
674 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.
| |
675 const Function& hasSameRuntimeType = Function::ZoneHandle(Z, | |
676 cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType())); | |
677 ASSERT(!hasSameRuntimeType.IsNull()); | |
678 | |
679 ZoneGrowableArray<PushArgumentInstr*>* args = | |
680 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); | |
681 PushArgumentInstr* arg = new (Z) PushArgumentInstr( | |
682 new (Z) Value(left->ArgumentAt(0))); | |
683 InsertBefore(call, arg, NULL, FlowGraph::kEffect); | |
684 args->Add(arg); | |
685 arg = new (Z) PushArgumentInstr( | |
686 new (Z) Value(right->ArgumentAt(0))); | |
687 InsertBefore(call, arg, NULL, FlowGraph::kEffect); | |
688 args->Add(arg); | |
689 StaticCallInstr* static_call = new (Z) StaticCallInstr( | |
690 call->token_pos(), | |
691 hasSameRuntimeType, | |
692 Object::null_array(), // argument_names | |
693 args, | |
694 call->deopt_id()); | |
695 static_call->set_result_cid(kBoolCid); | |
696 ReplaceCall(call, static_call); | |
697 return true; | |
698 } | |
699 | |
618 intptr_t cid = kIllegalCid; | 700 intptr_t cid = kIllegalCid; |
619 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { | 701 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { |
620 if (TryStringLengthOneEquality(call, op_kind)) { | 702 return TryStringLengthOneEquality(call, op_kind); |
621 return true; | |
622 } else { | |
623 return false; | |
624 } | |
625 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 703 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
626 InsertBefore(call, | 704 InsertBefore(call, |
627 new(Z) CheckSmiInstr(new(Z) Value(left), | 705 new(Z) CheckSmiInstr(new(Z) Value(left), |
628 call->deopt_id(), | 706 call->deopt_id(), |
629 call->token_pos()), | 707 call->token_pos()), |
630 call->env(), | 708 call->env(), |
631 FlowGraph::kEffect); | 709 FlowGraph::kEffect); |
632 InsertBefore(call, | 710 InsertBefore(call, |
633 new(Z) CheckSmiInstr(new(Z) Value(right), | 711 new(Z) CheckSmiInstr(new(Z) Value(right), |
634 call->deopt_id(), | 712 call->deopt_id(), |
(...skipping 1543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2178 check->env(), FlowGraph::kEffect); | 2256 check->env(), FlowGraph::kEffect); |
2179 current_iterator()->RemoveCurrentFromGraph(); | 2257 current_iterator()->RemoveCurrentFromGraph(); |
2180 } | 2258 } |
2181 } | 2259 } |
2182 } | 2260 } |
2183 } | 2261 } |
2184 | 2262 |
2185 #endif // DART_PRECOMPILER | 2263 #endif // DART_PRECOMPILER |
2186 | 2264 |
2187 } // namespace dart | 2265 } // namespace dart |
OLD | NEW |