| 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 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 call->function_name(), | 191 call->function_name(), |
| 192 args_desc)); | 192 args_desc)); |
| 193 if (function.IsNull()) { | 193 if (function.IsNull()) { |
| 194 return false; | 194 return false; |
| 195 } | 195 } |
| 196 // Create new ICData, do not modify the one attached to the instruction | 196 // Create new ICData, do not modify the one attached to the instruction |
| 197 // since it is attached to the assembly instruction itself. | 197 // since it is attached to the assembly instruction itself. |
| 198 // TODO(srdjan): Prevent modification of ICData object that is | 198 // TODO(srdjan): Prevent modification of ICData object that is |
| 199 // referenced in assembly code. | 199 // referenced in assembly code. |
| 200 ICData& ic_data = ICData::ZoneHandle(I, ICData::New( | 200 ICData& ic_data = ICData::ZoneHandle(I, ICData::New( |
| 201 flow_graph_->parsed_function().function(), | 201 flow_graph_->parsed_function()->function(), |
| 202 call->function_name(), | 202 call->function_name(), |
| 203 args_desc_array, | 203 args_desc_array, |
| 204 call->deopt_id(), | 204 call->deopt_id(), |
| 205 class_ids.length())); | 205 class_ids.length())); |
| 206 if (class_ids.length() > 1) { | 206 if (class_ids.length() > 1) { |
| 207 ic_data.AddCheck(class_ids, function); | 207 ic_data.AddCheck(class_ids, function); |
| 208 } else { | 208 } else { |
| 209 ASSERT(class_ids.length() == 1); | 209 ASSERT(class_ids.length() == 1); |
| 210 ic_data.AddReceiverCheck(class_ids[0], function); | 210 ic_data.AddReceiverCheck(class_ids[0], function); |
| 211 } | 211 } |
| (...skipping 2131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2343 | 2343 |
| 2344 | 2344 |
| 2345 // Use CHA to determine if the call needs a class check: if the callee's | 2345 // Use CHA to determine if the call needs a class check: if the callee's |
| 2346 // receiver is the same as the caller's receiver and there are no overriden | 2346 // receiver is the same as the caller's receiver and there are no overriden |
| 2347 // callee functions, then no class check is needed. | 2347 // callee functions, then no class check is needed. |
| 2348 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck( | 2348 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck( |
| 2349 InstanceCallInstr* call, RawFunction::Kind kind) const { | 2349 InstanceCallInstr* call, RawFunction::Kind kind) const { |
| 2350 if (!FLAG_use_cha) return true; | 2350 if (!FLAG_use_cha) return true; |
| 2351 Definition* callee_receiver = call->ArgumentAt(0); | 2351 Definition* callee_receiver = call->ArgumentAt(0); |
| 2352 ASSERT(callee_receiver != NULL); | 2352 ASSERT(callee_receiver != NULL); |
| 2353 const Function& function = flow_graph_->parsed_function().function(); | 2353 const Function& function = flow_graph_->parsed_function()->function(); |
| 2354 if (function.IsDynamicFunction() && | 2354 if (function.IsDynamicFunction() && |
| 2355 callee_receiver->IsParameter() && | 2355 callee_receiver->IsParameter() && |
| 2356 (callee_receiver->AsParameter()->index() == 0)) { | 2356 (callee_receiver->AsParameter()->index() == 0)) { |
| 2357 const String& name = (kind == RawFunction::kMethodExtractor) | 2357 const String& name = (kind == RawFunction::kMethodExtractor) |
| 2358 ? String::Handle(I, Field::NameFromGetter(call->function_name())) | 2358 ? String::Handle(I, Field::NameFromGetter(call->function_name())) |
| 2359 : call->function_name(); | 2359 : call->function_name(); |
| 2360 return isolate()->cha()->HasOverride(Class::Handle(I, function.Owner()), | 2360 return isolate()->cha()->HasOverride(Class::Handle(I, function.Owner()), |
| 2361 name); | 2361 name); |
| 2362 } | 2362 } |
| 2363 return true; | 2363 return true; |
| (...skipping 1352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3716 ICData& value_check = ICData::ZoneHandle(I); | 3716 ICData& value_check = ICData::ZoneHandle(I); |
| 3717 switch (view_cid) { | 3717 switch (view_cid) { |
| 3718 case kTypedDataInt8ArrayCid: | 3718 case kTypedDataInt8ArrayCid: |
| 3719 case kTypedDataUint8ArrayCid: | 3719 case kTypedDataUint8ArrayCid: |
| 3720 case kTypedDataUint8ClampedArrayCid: | 3720 case kTypedDataUint8ClampedArrayCid: |
| 3721 case kExternalTypedDataUint8ArrayCid: | 3721 case kExternalTypedDataUint8ArrayCid: |
| 3722 case kExternalTypedDataUint8ClampedArrayCid: | 3722 case kExternalTypedDataUint8ClampedArrayCid: |
| 3723 case kTypedDataInt16ArrayCid: | 3723 case kTypedDataInt16ArrayCid: |
| 3724 case kTypedDataUint16ArrayCid: { | 3724 case kTypedDataUint16ArrayCid: { |
| 3725 // Check that value is always smi. | 3725 // Check that value is always smi. |
| 3726 value_check = ICData::New(flow_graph_->parsed_function().function(), | 3726 value_check = ICData::New(flow_graph_->parsed_function()->function(), |
| 3727 i_call->function_name(), | 3727 i_call->function_name(), |
| 3728 Object::empty_array(), // Dummy args. descr. | 3728 Object::empty_array(), // Dummy args. descr. |
| 3729 Isolate::kNoDeoptId, | 3729 Isolate::kNoDeoptId, |
| 3730 1); | 3730 1); |
| 3731 value_check.AddReceiverCheck(kSmiCid, target); | 3731 value_check.AddReceiverCheck(kSmiCid, target); |
| 3732 break; | 3732 break; |
| 3733 } | 3733 } |
| 3734 case kTypedDataInt32ArrayCid: | 3734 case kTypedDataInt32ArrayCid: |
| 3735 case kTypedDataUint32ArrayCid: | 3735 case kTypedDataUint32ArrayCid: |
| 3736 // On 64-bit platforms assume that stored value is always a smi. | 3736 // On 64-bit platforms assume that stored value is always a smi. |
| 3737 if (kSmiBits >= 32) { | 3737 if (kSmiBits >= 32) { |
| 3738 value_check = ICData::New(flow_graph_->parsed_function().function(), | 3738 value_check = ICData::New(flow_graph_->parsed_function()->function(), |
| 3739 i_call->function_name(), | 3739 i_call->function_name(), |
| 3740 Object::empty_array(), // Dummy args. descr. | 3740 Object::empty_array(), // Dummy args. descr. |
| 3741 Isolate::kNoDeoptId, | 3741 Isolate::kNoDeoptId, |
| 3742 1); | 3742 1); |
| 3743 value_check.AddReceiverCheck(kSmiCid, target); | 3743 value_check.AddReceiverCheck(kSmiCid, target); |
| 3744 } | 3744 } |
| 3745 break; | 3745 break; |
| 3746 case kTypedDataFloat32ArrayCid: | 3746 case kTypedDataFloat32ArrayCid: |
| 3747 case kTypedDataFloat64ArrayCid: { | 3747 case kTypedDataFloat64ArrayCid: { |
| 3748 // Check that value is always double. | 3748 // Check that value is always double. |
| 3749 value_check = ICData::New(flow_graph_->parsed_function().function(), | 3749 value_check = ICData::New(flow_graph_->parsed_function()->function(), |
| 3750 i_call->function_name(), | 3750 i_call->function_name(), |
| 3751 Object::empty_array(), // Dummy args. descr. | 3751 Object::empty_array(), // Dummy args. descr. |
| 3752 Isolate::kNoDeoptId, | 3752 Isolate::kNoDeoptId, |
| 3753 1); | 3753 1); |
| 3754 value_check.AddReceiverCheck(kDoubleCid, target); | 3754 value_check.AddReceiverCheck(kDoubleCid, target); |
| 3755 break; | 3755 break; |
| 3756 } | 3756 } |
| 3757 case kTypedDataInt32x4ArrayCid: { | 3757 case kTypedDataInt32x4ArrayCid: { |
| 3758 // Check that value is always Int32x4. | 3758 // Check that value is always Int32x4. |
| 3759 value_check = ICData::New(flow_graph_->parsed_function().function(), | 3759 value_check = ICData::New(flow_graph_->parsed_function()->function(), |
| 3760 i_call->function_name(), | 3760 i_call->function_name(), |
| 3761 Object::empty_array(), // Dummy args. descr. | 3761 Object::empty_array(), // Dummy args. descr. |
| 3762 Isolate::kNoDeoptId, | 3762 Isolate::kNoDeoptId, |
| 3763 1); | 3763 1); |
| 3764 value_check.AddReceiverCheck(kInt32x4Cid, target); | 3764 value_check.AddReceiverCheck(kInt32x4Cid, target); |
| 3765 break; | 3765 break; |
| 3766 } | 3766 } |
| 3767 case kTypedDataFloat32x4ArrayCid: { | 3767 case kTypedDataFloat32x4ArrayCid: { |
| 3768 // Check that value is always Float32x4. | 3768 // Check that value is always Float32x4. |
| 3769 value_check = ICData::New(flow_graph_->parsed_function().function(), | 3769 value_check = ICData::New(flow_graph_->parsed_function()->function(), |
| 3770 i_call->function_name(), | 3770 i_call->function_name(), |
| 3771 Object::empty_array(), // Dummy args. descr. | 3771 Object::empty_array(), // Dummy args. descr. |
| 3772 Isolate::kNoDeoptId, | 3772 Isolate::kNoDeoptId, |
| 3773 1); | 3773 1); |
| 3774 value_check.AddReceiverCheck(kFloat32x4Cid, target); | 3774 value_check.AddReceiverCheck(kFloat32x4Cid, target); |
| 3775 break; | 3775 break; |
| 3776 } | 3776 } |
| 3777 default: | 3777 default: |
| 3778 // Array cids are already checked in the caller. | 3778 // Array cids are already checked in the caller. |
| 3779 UNREACHABLE(); | 3779 UNREACHABLE(); |
| (...skipping 1291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5071 Instruction* instr) { | 5071 Instruction* instr) { |
| 5072 return IsLoadEliminationCandidate(instr) && | 5072 return IsLoadEliminationCandidate(instr) && |
| 5073 (sets != NULL) && | 5073 (sets != NULL) && |
| 5074 instr->HasPlaceId() && | 5074 instr->HasPlaceId() && |
| 5075 ((*sets)[loop_header_index] != NULL) && | 5075 ((*sets)[loop_header_index] != NULL) && |
| 5076 (*sets)[loop_header_index]->Contains(instr->place_id()); | 5076 (*sets)[loop_header_index]->Contains(instr->place_id()); |
| 5077 } | 5077 } |
| 5078 | 5078 |
| 5079 | 5079 |
| 5080 void LICM::OptimisticallySpecializeSmiPhis() { | 5080 void LICM::OptimisticallySpecializeSmiPhis() { |
| 5081 if (!flow_graph()->parsed_function().function(). | 5081 if (!flow_graph()->parsed_function()->function(). |
| 5082 allows_hoisting_check_class()) { | 5082 allows_hoisting_check_class()) { |
| 5083 // Do not hoist any. | 5083 // Do not hoist any. |
| 5084 return; | 5084 return; |
| 5085 } | 5085 } |
| 5086 | 5086 |
| 5087 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = | 5087 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = |
| 5088 flow_graph()->LoopHeaders(); | 5088 flow_graph()->LoopHeaders(); |
| 5089 | 5089 |
| 5090 for (intptr_t i = 0; i < loop_headers.length(); ++i) { | 5090 for (intptr_t i = 0; i < loop_headers.length(); ++i) { |
| 5091 JoinEntryInstr* header = loop_headers[i]->AsJoinEntry(); | 5091 JoinEntryInstr* header = loop_headers[i]->AsJoinEntry(); |
| 5092 // Skip loop that don't have a pre-header block. | 5092 // Skip loop that don't have a pre-header block. |
| 5093 BlockEntryInstr* pre_header = header->ImmediateDominator(); | 5093 BlockEntryInstr* pre_header = header->ImmediateDominator(); |
| 5094 if (pre_header == NULL) continue; | 5094 if (pre_header == NULL) continue; |
| 5095 | 5095 |
| 5096 for (PhiIterator it(header); !it.Done(); it.Advance()) { | 5096 for (PhiIterator it(header); !it.Done(); it.Advance()) { |
| 5097 TrySpecializeSmiPhi(it.Current(), header, pre_header); | 5097 TrySpecializeSmiPhi(it.Current(), header, pre_header); |
| 5098 } | 5098 } |
| 5099 } | 5099 } |
| 5100 } | 5100 } |
| 5101 | 5101 |
| 5102 | 5102 |
| 5103 void LICM::Optimize() { | 5103 void LICM::Optimize() { |
| 5104 if (!flow_graph()->parsed_function().function(). | 5104 if (!flow_graph()->parsed_function()->function(). |
| 5105 allows_hoisting_check_class()) { | 5105 allows_hoisting_check_class()) { |
| 5106 // Do not hoist any. | 5106 // Do not hoist any. |
| 5107 return; | 5107 return; |
| 5108 } | 5108 } |
| 5109 | 5109 |
| 5110 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = | 5110 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = |
| 5111 flow_graph()->LoopHeaders(); | 5111 flow_graph()->LoopHeaders(); |
| 5112 | 5112 |
| 5113 ZoneGrowableArray<BitVector*>* loop_invariant_loads = | 5113 ZoneGrowableArray<BitVector*>* loop_invariant_loads = |
| 5114 flow_graph()->loop_invariant_loads(); | 5114 flow_graph()->loop_invariant_loads(); |
| (...skipping 4947 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10062 | 10062 |
| 10063 // Insert materializations at environment uses. | 10063 // Insert materializations at environment uses. |
| 10064 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 10064 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 10065 CreateMaterializationAt( | 10065 CreateMaterializationAt( |
| 10066 exits_collector_.exits()[i], alloc, *slots); | 10066 exits_collector_.exits()[i], alloc, *slots); |
| 10067 } | 10067 } |
| 10068 } | 10068 } |
| 10069 | 10069 |
| 10070 | 10070 |
| 10071 } // namespace dart | 10071 } // namespace dart |
| OLD | NEW |