| 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/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 call->function_name(), | 189 call->function_name(), |
| 190 args_desc)); | 190 args_desc)); |
| 191 if (function.IsNull()) { | 191 if (function.IsNull()) { |
| 192 return false; | 192 return false; |
| 193 } | 193 } |
| 194 // Create new ICData, do not modify the one attached to the instruction | 194 // Create new ICData, do not modify the one attached to the instruction |
| 195 // since it is attached to the assembly instruction itself. | 195 // since it is attached to the assembly instruction itself. |
| 196 // TODO(srdjan): Prevent modification of ICData object that is | 196 // TODO(srdjan): Prevent modification of ICData object that is |
| 197 // referenced in assembly code. | 197 // referenced in assembly code. |
| 198 ICData& ic_data = ICData::ZoneHandle(Z, ICData::New( | 198 ICData& ic_data = ICData::ZoneHandle(Z, ICData::New( |
| 199 flow_graph_->parsed_function()->function(), | 199 flow_graph_->function(), |
| 200 call->function_name(), | 200 call->function_name(), |
| 201 args_desc_array, | 201 args_desc_array, |
| 202 call->deopt_id(), | 202 call->deopt_id(), |
| 203 class_ids.length())); | 203 class_ids.length())); |
| 204 if (class_ids.length() > 1) { | 204 if (class_ids.length() > 1) { |
| 205 ic_data.AddCheck(class_ids, function); | 205 ic_data.AddCheck(class_ids, function); |
| 206 } else { | 206 } else { |
| 207 ASSERT(class_ids.length() == 1); | 207 ASSERT(class_ids.length() == 1); |
| 208 ic_data.AddReceiverCheck(class_ids[0], function); | 208 ic_data.AddReceiverCheck(class_ids[0], function); |
| 209 } | 209 } |
| (...skipping 2046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2256 | 2256 |
| 2257 | 2257 |
| 2258 // Use CHA to determine if the call needs a class check: if the callee's | 2258 // Use CHA to determine if the call needs a class check: if the callee's |
| 2259 // receiver is the same as the caller's receiver and there are no overriden | 2259 // receiver is the same as the caller's receiver and there are no overriden |
| 2260 // callee functions, then no class check is needed. | 2260 // callee functions, then no class check is needed. |
| 2261 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck( | 2261 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck( |
| 2262 InstanceCallInstr* call, RawFunction::Kind kind) const { | 2262 InstanceCallInstr* call, RawFunction::Kind kind) const { |
| 2263 if (!FLAG_use_cha) return true; | 2263 if (!FLAG_use_cha) return true; |
| 2264 Definition* callee_receiver = call->ArgumentAt(0); | 2264 Definition* callee_receiver = call->ArgumentAt(0); |
| 2265 ASSERT(callee_receiver != NULL); | 2265 ASSERT(callee_receiver != NULL); |
| 2266 const Function& function = flow_graph_->parsed_function()->function(); | 2266 const Function& function = flow_graph_->function(); |
| 2267 if (function.IsDynamicFunction() && | 2267 if (function.IsDynamicFunction() && |
| 2268 callee_receiver->IsParameter() && | 2268 callee_receiver->IsParameter() && |
| 2269 (callee_receiver->AsParameter()->index() == 0)) { | 2269 (callee_receiver->AsParameter()->index() == 0)) { |
| 2270 const String& name = (kind == RawFunction::kMethodExtractor) | 2270 const String& name = (kind == RawFunction::kMethodExtractor) |
| 2271 ? String::Handle(Z, Field::NameFromGetter(call->function_name())) | 2271 ? String::Handle(Z, Field::NameFromGetter(call->function_name())) |
| 2272 : call->function_name(); | 2272 : call->function_name(); |
| 2273 return isolate()->cha()->HasOverride(Class::Handle(Z, function.Owner()), | 2273 return isolate()->cha()->HasOverride(Class::Handle(Z, function.Owner()), |
| 2274 name); | 2274 name); |
| 2275 } | 2275 } |
| 2276 return true; | 2276 return true; |
| (...skipping 1351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3628 ICData& value_check = ICData::ZoneHandle(Z); | 3628 ICData& value_check = ICData::ZoneHandle(Z); |
| 3629 switch (view_cid) { | 3629 switch (view_cid) { |
| 3630 case kTypedDataInt8ArrayCid: | 3630 case kTypedDataInt8ArrayCid: |
| 3631 case kTypedDataUint8ArrayCid: | 3631 case kTypedDataUint8ArrayCid: |
| 3632 case kTypedDataUint8ClampedArrayCid: | 3632 case kTypedDataUint8ClampedArrayCid: |
| 3633 case kExternalTypedDataUint8ArrayCid: | 3633 case kExternalTypedDataUint8ArrayCid: |
| 3634 case kExternalTypedDataUint8ClampedArrayCid: | 3634 case kExternalTypedDataUint8ClampedArrayCid: |
| 3635 case kTypedDataInt16ArrayCid: | 3635 case kTypedDataInt16ArrayCid: |
| 3636 case kTypedDataUint16ArrayCid: { | 3636 case kTypedDataUint16ArrayCid: { |
| 3637 // Check that value is always smi. | 3637 // Check that value is always smi. |
| 3638 value_check = ICData::New(flow_graph_->parsed_function()->function(), | 3638 value_check = ICData::New(flow_graph_->function(), |
| 3639 i_call->function_name(), | 3639 i_call->function_name(), |
| 3640 Object::empty_array(), // Dummy args. descr. | 3640 Object::empty_array(), // Dummy args. descr. |
| 3641 Isolate::kNoDeoptId, | 3641 Isolate::kNoDeoptId, |
| 3642 1); | 3642 1); |
| 3643 value_check.AddReceiverCheck(kSmiCid, target); | 3643 value_check.AddReceiverCheck(kSmiCid, target); |
| 3644 break; | 3644 break; |
| 3645 } | 3645 } |
| 3646 case kTypedDataInt32ArrayCid: | 3646 case kTypedDataInt32ArrayCid: |
| 3647 case kTypedDataUint32ArrayCid: | 3647 case kTypedDataUint32ArrayCid: |
| 3648 // On 64-bit platforms assume that stored value is always a smi. | 3648 // On 64-bit platforms assume that stored value is always a smi. |
| 3649 if (kSmiBits >= 32) { | 3649 if (kSmiBits >= 32) { |
| 3650 value_check = ICData::New(flow_graph_->parsed_function()->function(), | 3650 value_check = ICData::New(flow_graph_->function(), |
| 3651 i_call->function_name(), | 3651 i_call->function_name(), |
| 3652 Object::empty_array(), // Dummy args. descr. | 3652 Object::empty_array(), // Dummy args. descr. |
| 3653 Isolate::kNoDeoptId, | 3653 Isolate::kNoDeoptId, |
| 3654 1); | 3654 1); |
| 3655 value_check.AddReceiverCheck(kSmiCid, target); | 3655 value_check.AddReceiverCheck(kSmiCid, target); |
| 3656 } | 3656 } |
| 3657 break; | 3657 break; |
| 3658 case kTypedDataFloat32ArrayCid: | 3658 case kTypedDataFloat32ArrayCid: |
| 3659 case kTypedDataFloat64ArrayCid: { | 3659 case kTypedDataFloat64ArrayCid: { |
| 3660 // Check that value is always double. | 3660 // Check that value is always double. |
| 3661 value_check = ICData::New(flow_graph_->parsed_function()->function(), | 3661 value_check = ICData::New(flow_graph_->function(), |
| 3662 i_call->function_name(), | 3662 i_call->function_name(), |
| 3663 Object::empty_array(), // Dummy args. descr. | 3663 Object::empty_array(), // Dummy args. descr. |
| 3664 Isolate::kNoDeoptId, | 3664 Isolate::kNoDeoptId, |
| 3665 1); | 3665 1); |
| 3666 value_check.AddReceiverCheck(kDoubleCid, target); | 3666 value_check.AddReceiverCheck(kDoubleCid, target); |
| 3667 break; | 3667 break; |
| 3668 } | 3668 } |
| 3669 case kTypedDataInt32x4ArrayCid: { | 3669 case kTypedDataInt32x4ArrayCid: { |
| 3670 // Check that value is always Int32x4. | 3670 // Check that value is always Int32x4. |
| 3671 value_check = ICData::New(flow_graph_->parsed_function()->function(), | 3671 value_check = ICData::New(flow_graph_->function(), |
| 3672 i_call->function_name(), | 3672 i_call->function_name(), |
| 3673 Object::empty_array(), // Dummy args. descr. | 3673 Object::empty_array(), // Dummy args. descr. |
| 3674 Isolate::kNoDeoptId, | 3674 Isolate::kNoDeoptId, |
| 3675 1); | 3675 1); |
| 3676 value_check.AddReceiverCheck(kInt32x4Cid, target); | 3676 value_check.AddReceiverCheck(kInt32x4Cid, target); |
| 3677 break; | 3677 break; |
| 3678 } | 3678 } |
| 3679 case kTypedDataFloat32x4ArrayCid: { | 3679 case kTypedDataFloat32x4ArrayCid: { |
| 3680 // Check that value is always Float32x4. | 3680 // Check that value is always Float32x4. |
| 3681 value_check = ICData::New(flow_graph_->parsed_function()->function(), | 3681 value_check = ICData::New(flow_graph_->function(), |
| 3682 i_call->function_name(), | 3682 i_call->function_name(), |
| 3683 Object::empty_array(), // Dummy args. descr. | 3683 Object::empty_array(), // Dummy args. descr. |
| 3684 Isolate::kNoDeoptId, | 3684 Isolate::kNoDeoptId, |
| 3685 1); | 3685 1); |
| 3686 value_check.AddReceiverCheck(kFloat32x4Cid, target); | 3686 value_check.AddReceiverCheck(kFloat32x4Cid, target); |
| 3687 break; | 3687 break; |
| 3688 } | 3688 } |
| 3689 default: | 3689 default: |
| 3690 // Array cids are already checked in the caller. | 3690 // Array cids are already checked in the caller. |
| 3691 UNREACHABLE(); | 3691 UNREACHABLE(); |
| (...skipping 1295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4987 Instruction* instr) { | 4987 Instruction* instr) { |
| 4988 return IsLoadEliminationCandidate(instr) && | 4988 return IsLoadEliminationCandidate(instr) && |
| 4989 (sets != NULL) && | 4989 (sets != NULL) && |
| 4990 instr->HasPlaceId() && | 4990 instr->HasPlaceId() && |
| 4991 ((*sets)[loop_header_index] != NULL) && | 4991 ((*sets)[loop_header_index] != NULL) && |
| 4992 (*sets)[loop_header_index]->Contains(instr->place_id()); | 4992 (*sets)[loop_header_index]->Contains(instr->place_id()); |
| 4993 } | 4993 } |
| 4994 | 4994 |
| 4995 | 4995 |
| 4996 void LICM::OptimisticallySpecializeSmiPhis() { | 4996 void LICM::OptimisticallySpecializeSmiPhis() { |
| 4997 if (!flow_graph()->parsed_function()->function(). | 4997 if (!flow_graph()->function().allows_hoisting_check_class()) { |
| 4998 allows_hoisting_check_class()) { | |
| 4999 // Do not hoist any. | 4998 // Do not hoist any. |
| 5000 return; | 4999 return; |
| 5001 } | 5000 } |
| 5002 | 5001 |
| 5003 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = | 5002 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = |
| 5004 flow_graph()->LoopHeaders(); | 5003 flow_graph()->LoopHeaders(); |
| 5005 | 5004 |
| 5006 for (intptr_t i = 0; i < loop_headers.length(); ++i) { | 5005 for (intptr_t i = 0; i < loop_headers.length(); ++i) { |
| 5007 JoinEntryInstr* header = loop_headers[i]->AsJoinEntry(); | 5006 JoinEntryInstr* header = loop_headers[i]->AsJoinEntry(); |
| 5008 // Skip loop that don't have a pre-header block. | 5007 // Skip loop that don't have a pre-header block. |
| 5009 BlockEntryInstr* pre_header = header->ImmediateDominator(); | 5008 BlockEntryInstr* pre_header = header->ImmediateDominator(); |
| 5010 if (pre_header == NULL) continue; | 5009 if (pre_header == NULL) continue; |
| 5011 | 5010 |
| 5012 for (PhiIterator it(header); !it.Done(); it.Advance()) { | 5011 for (PhiIterator it(header); !it.Done(); it.Advance()) { |
| 5013 TrySpecializeSmiPhi(it.Current(), header, pre_header); | 5012 TrySpecializeSmiPhi(it.Current(), header, pre_header); |
| 5014 } | 5013 } |
| 5015 } | 5014 } |
| 5016 } | 5015 } |
| 5017 | 5016 |
| 5018 | 5017 |
| 5019 void LICM::Optimize() { | 5018 void LICM::Optimize() { |
| 5020 if (!flow_graph()->parsed_function()->function(). | 5019 if (!flow_graph()->function().allows_hoisting_check_class()) { |
| 5021 allows_hoisting_check_class()) { | |
| 5022 // Do not hoist any. | 5020 // Do not hoist any. |
| 5023 return; | 5021 return; |
| 5024 } | 5022 } |
| 5025 | 5023 |
| 5026 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = | 5024 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = |
| 5027 flow_graph()->LoopHeaders(); | 5025 flow_graph()->LoopHeaders(); |
| 5028 | 5026 |
| 5029 ZoneGrowableArray<BitVector*>* loop_invariant_loads = | 5027 ZoneGrowableArray<BitVector*>* loop_invariant_loads = |
| 5030 flow_graph()->loop_invariant_loads(); | 5028 flow_graph()->loop_invariant_loads(); |
| 5031 | 5029 |
| (...skipping 3578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8610 | 8608 |
| 8611 // Insert materializations at environment uses. | 8609 // Insert materializations at environment uses. |
| 8612 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8610 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 8613 CreateMaterializationAt( | 8611 CreateMaterializationAt( |
| 8614 exits_collector_.exits()[i], alloc, *slots); | 8612 exits_collector_.exits()[i], alloc, *slots); |
| 8615 } | 8613 } |
| 8616 } | 8614 } |
| 8617 | 8615 |
| 8618 | 8616 |
| 8619 } // namespace dart | 8617 } // namespace dart |
| OLD | NEW |