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/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 4184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4195 new(Z) Value(left), | 4195 new(Z) Value(left), |
4196 new(Z) Value(instantiator), | 4196 new(Z) Value(instantiator), |
4197 new(Z) Value(type_args), | 4197 new(Z) Value(type_args), |
4198 type, | 4198 type, |
4199 dst_name, | 4199 dst_name, |
4200 call->deopt_id()); | 4200 call->deopt_id()); |
4201 ReplaceCall(call, assert_as); | 4201 ReplaceCall(call, assert_as); |
4202 } | 4202 } |
4203 | 4203 |
4204 | 4204 |
| 4205 bool FlowGraphOptimizer::IsBlackListedForInlining(intptr_t call_deopt_id) { |
| 4206 for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) { |
| 4207 if ((*inlining_black_list_)[i] == call_deopt_id) return true; |
| 4208 } |
| 4209 return false; |
| 4210 } |
| 4211 |
4205 // Special optimizations when running in --noopt mode. | 4212 // Special optimizations when running in --noopt mode. |
4206 void FlowGraphOptimizer::InstanceCallNoopt(InstanceCallInstr* instr) { | 4213 void FlowGraphOptimizer::InstanceCallNoopt(InstanceCallInstr* instr) { |
4207 // TODO(srdjan): Investigate other attempts, as they are not allowed to | 4214 // TODO(srdjan): Investigate other attempts, as they are not allowed to |
4208 // deoptimize. | 4215 // deoptimize. |
4209 | 4216 |
4210 // Type test is special as it always gets converted into inlined code. | 4217 // Type test is special as it always gets converted into inlined code. |
4211 const Token::Kind op_kind = instr->token_kind(); | 4218 const Token::Kind op_kind = instr->token_kind(); |
4212 if (Token::IsTypeTestOperator(op_kind)) { | 4219 if (Token::IsTypeTestOperator(op_kind)) { |
4213 ReplaceWithInstanceOf(instr); | 4220 ReplaceWithInstanceOf(instr); |
4214 return; | 4221 return; |
4215 } | 4222 } |
4216 if (Token::IsTypeCastOperator(op_kind)) { | 4223 if (Token::IsTypeCastOperator(op_kind)) { |
4217 ReplaceWithTypeCast(instr); | 4224 ReplaceWithTypeCast(instr); |
4218 return; | 4225 return; |
4219 } | 4226 } |
4220 | 4227 |
4221 if ((op_kind == Token::kGET) && | 4228 if ((op_kind == Token::kGET) && |
4222 TryInlineInstanceGetter(instr, false /* no checks allowed */)) { | 4229 TryInlineInstanceGetter(instr, false /* no checks allowed */)) { |
4223 return; | 4230 return; |
4224 } | 4231 } |
4225 const ICData& unary_checks = | 4232 const ICData& unary_checks = |
4226 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); | 4233 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); |
4227 if ((unary_checks.NumberOfChecks() > 0) && | 4234 if ((unary_checks.NumberOfChecks() > 0) && |
4228 (op_kind == Token::kSET) && | 4235 (op_kind == Token::kSET) && |
4229 TryInlineInstanceSetter(instr, unary_checks, false /* no checks */)) { | 4236 TryInlineInstanceSetter(instr, unary_checks, false /* no checks */)) { |
4230 return; | 4237 return; |
4231 } | 4238 } |
4232 | 4239 |
| 4240 if (use_speculative_inlining_ && |
| 4241 !IsBlackListedForInlining(instr->deopt_id()) && |
| 4242 (unary_checks.NumberOfChecks() > 0)) { |
| 4243 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) { |
| 4244 return; |
| 4245 } |
| 4246 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { |
| 4247 return; |
| 4248 } |
| 4249 if ((op_kind == Token::kEQ) && TryReplaceWithEqualityOp(instr, op_kind)) { |
| 4250 return; |
| 4251 } |
| 4252 |
| 4253 if (Token::IsRelationalOperator(op_kind) && |
| 4254 TryReplaceWithRelationalOp(instr, op_kind)) { |
| 4255 return; |
| 4256 } |
| 4257 |
| 4258 if (Token::IsBinaryOperator(op_kind) && |
| 4259 TryReplaceWithBinaryOp(instr, op_kind)) { |
| 4260 return; |
| 4261 } |
| 4262 if (Token::IsUnaryOperator(op_kind) && |
| 4263 TryReplaceWithUnaryOp(instr, op_kind)) { |
| 4264 return; |
| 4265 } |
| 4266 } |
| 4267 |
4233 bool has_one_target = | 4268 bool has_one_target = |
4234 (unary_checks.NumberOfChecks() > 0) && unary_checks.HasOneTarget(); | 4269 (unary_checks.NumberOfChecks() > 0) && unary_checks.HasOneTarget(); |
4235 if (has_one_target) { | 4270 if (has_one_target) { |
4236 // Check if the single target is a polymorphic target, if it is, | 4271 // Check if the single target is a polymorphic target, if it is, |
4237 // we don't have one target. | 4272 // we don't have one target. |
4238 const Function& target = | 4273 const Function& target = |
4239 Function::Handle(Z, unary_checks.GetTargetAt(0)); | 4274 Function::Handle(Z, unary_checks.GetTargetAt(0)); |
4240 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); | 4275 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); |
4241 has_one_target = !polymorphic_target; | 4276 has_one_target = !polymorphic_target; |
4242 } | 4277 } |
(...skipping 926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5169 Instruction* instr) { | 5204 Instruction* instr) { |
5170 return IsLoadEliminationCandidate(instr) && | 5205 return IsLoadEliminationCandidate(instr) && |
5171 (sets != NULL) && | 5206 (sets != NULL) && |
5172 instr->HasPlaceId() && | 5207 instr->HasPlaceId() && |
5173 ((*sets)[loop_header_index] != NULL) && | 5208 ((*sets)[loop_header_index] != NULL) && |
5174 (*sets)[loop_header_index]->Contains(instr->place_id()); | 5209 (*sets)[loop_header_index]->Contains(instr->place_id()); |
5175 } | 5210 } |
5176 | 5211 |
5177 | 5212 |
5178 void LICM::OptimisticallySpecializeSmiPhis() { | 5213 void LICM::OptimisticallySpecializeSmiPhis() { |
5179 if (!flow_graph()->function().allows_hoisting_check_class()) { | 5214 if (!flow_graph()->function().allows_hoisting_check_class() || |
5180 // Do not hoist any. | 5215 Compiler::always_optimize()) { |
| 5216 // Do not hoist any: Either deoptimized on a hoisted check, |
| 5217 // or compiling precompiled code where we can't do optimistic |
| 5218 // hoisting of checks. |
5181 return; | 5219 return; |
5182 } | 5220 } |
5183 | 5221 |
5184 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = | 5222 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = |
5185 flow_graph()->LoopHeaders(); | 5223 flow_graph()->LoopHeaders(); |
5186 | 5224 |
5187 for (intptr_t i = 0; i < loop_headers.length(); ++i) { | 5225 for (intptr_t i = 0; i < loop_headers.length(); ++i) { |
5188 JoinEntryInstr* header = loop_headers[i]->AsJoinEntry(); | 5226 JoinEntryInstr* header = loop_headers[i]->AsJoinEntry(); |
5189 // Skip loop that don't have a pre-header block. | 5227 // Skip loop that don't have a pre-header block. |
5190 BlockEntryInstr* pre_header = header->ImmediateDominator(); | 5228 BlockEntryInstr* pre_header = header->ImmediateDominator(); |
(...skipping 3598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8789 | 8827 |
8790 // Insert materializations at environment uses. | 8828 // Insert materializations at environment uses. |
8791 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8829 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
8792 CreateMaterializationAt( | 8830 CreateMaterializationAt( |
8793 exits_collector_.exits()[i], alloc, *slots); | 8831 exits_collector_.exits()[i], alloc, *slots); |
8794 } | 8832 } |
8795 } | 8833 } |
8796 | 8834 |
8797 | 8835 |
8798 } // namespace dart | 8836 } // namespace dart |
OLD | NEW |