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 4070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4081 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 4081 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
4082 if (FLAG_warn_on_javascript_compatibility && | 4082 if (FLAG_warn_on_javascript_compatibility && |
4083 !unary_checks.IssuedJSWarning() && | 4083 !unary_checks.IssuedJSWarning() && |
4084 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { | 4084 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { |
4085 // No warning was reported yet for this type check, either because it has | 4085 // No warning was reported yet for this type check, either because it has |
4086 // not been executed yet, or because no problematic combinations of instance | 4086 // not been executed yet, or because no problematic combinations of instance |
4087 // type and test type have been encountered so far. A warning may still be | 4087 // type and test type have been encountered so far. A warning may still be |
4088 // reported, so do not replace the instance call. | 4088 // reported, so do not replace the instance call. |
4089 return; | 4089 return; |
4090 } | 4090 } |
4091 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { | 4091 if ((unary_checks.NumberOfChecks() > 0) && |
| 4092 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { |
4092 ZoneGrowableArray<intptr_t>* results = | 4093 ZoneGrowableArray<intptr_t>* results = |
4093 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 4094 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); |
4094 Bool& as_bool = | 4095 Bool& as_bool = |
4095 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); | 4096 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); |
4096 if (as_bool.IsNull()) { | 4097 if (as_bool.IsNull()) { |
4097 if (results->length() == unary_checks.NumberOfChecks() * 2) { | 4098 if (results->length() == unary_checks.NumberOfChecks() * 2) { |
4098 const bool can_deopt = TryExpandTestCidsResult(results, type); | 4099 const bool can_deopt = TryExpandTestCidsResult(results, type); |
4099 TestCidsInstr* test_cids = new(Z) TestCidsInstr( | 4100 TestCidsInstr* test_cids = new(Z) TestCidsInstr( |
4100 call->token_pos(), | 4101 call->token_pos(), |
4101 negate ? Token::kISNOT : Token::kIS, | 4102 negate ? Token::kISNOT : Token::kIS, |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4172 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 4173 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
4173 if (FLAG_warn_on_javascript_compatibility && | 4174 if (FLAG_warn_on_javascript_compatibility && |
4174 !unary_checks.IssuedJSWarning() && | 4175 !unary_checks.IssuedJSWarning() && |
4175 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { | 4176 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { |
4176 // No warning was reported yet for this type check, either because it has | 4177 // No warning was reported yet for this type check, either because it has |
4177 // not been executed yet, or because no problematic combinations of instance | 4178 // not been executed yet, or because no problematic combinations of instance |
4178 // type and test type have been encountered so far. A warning may still be | 4179 // type and test type have been encountered so far. A warning may still be |
4179 // reported, so do not replace the instance call. | 4180 // reported, so do not replace the instance call. |
4180 return; | 4181 return; |
4181 } | 4182 } |
4182 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { | 4183 if ((unary_checks.NumberOfChecks() > 0) && |
| 4184 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { |
4183 ZoneGrowableArray<intptr_t>* results = | 4185 ZoneGrowableArray<intptr_t>* results = |
4184 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); | 4186 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); |
4185 const Bool& as_bool = Bool::ZoneHandle(Z, | 4187 const Bool& as_bool = Bool::ZoneHandle(Z, |
4186 InstanceOfAsBool(unary_checks, type, results)); | 4188 InstanceOfAsBool(unary_checks, type, results)); |
4187 if (as_bool.raw() == Bool::True().raw()) { | 4189 if (as_bool.raw() == Bool::True().raw()) { |
4188 AddReceiverCheck(call); | 4190 AddReceiverCheck(call); |
4189 // Remove the original push arguments. | 4191 // Remove the original push arguments. |
4190 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 4192 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
4191 PushArgumentInstr* push = call->PushArgumentAt(i); | 4193 PushArgumentInstr* push = call->PushArgumentAt(i); |
4192 push->ReplaceUsesWith(push->value()->definition()); | 4194 push->ReplaceUsesWith(push->value()->definition()); |
(...skipping 13 matching lines...) Expand all Loading... |
4206 new(Z) Value(left), | 4208 new(Z) Value(left), |
4207 new(Z) Value(instantiator), | 4209 new(Z) Value(instantiator), |
4208 new(Z) Value(type_args), | 4210 new(Z) Value(type_args), |
4209 type, | 4211 type, |
4210 dst_name, | 4212 dst_name, |
4211 call->deopt_id()); | 4213 call->deopt_id()); |
4212 ReplaceCall(call, assert_as); | 4214 ReplaceCall(call, assert_as); |
4213 } | 4215 } |
4214 | 4216 |
4215 | 4217 |
| 4218 // Special optimizations when running in --noopt mode. |
| 4219 void FlowGraphOptimizer::InstanceCallNoopt(InstanceCallInstr* instr) { |
| 4220 // TODO(srdjan): Investigate other attempts, as they are not allowed to |
| 4221 // deoptimize. |
| 4222 const Token::Kind op_kind = instr->token_kind(); |
| 4223 if (instr->HasICData() && (instr->ic_data()->NumberOfUsedChecks() > 0)) { |
| 4224 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr, false)) { |
| 4225 return; |
| 4226 } |
| 4227 } |
| 4228 |
| 4229 // Type test is special as it always gets converted into inlined code. |
| 4230 if (Token::IsTypeTestOperator(op_kind)) { |
| 4231 ReplaceWithInstanceOf(instr); |
| 4232 return; |
| 4233 } |
| 4234 if (Token::IsTypeCastOperator(op_kind)) { |
| 4235 ReplaceWithTypeCast(instr); |
| 4236 return; |
| 4237 } |
| 4238 } |
| 4239 |
| 4240 |
4216 // Tries to optimize instance call by replacing it with a faster instruction | 4241 // Tries to optimize instance call by replacing it with a faster instruction |
4217 // (e.g, binary op, field load, ..). | 4242 // (e.g, binary op, field load, ..). |
4218 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 4243 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| 4244 if (Compiler::always_optimize()) { |
| 4245 InstanceCallNoopt(instr); |
| 4246 return; |
| 4247 } |
| 4248 |
4219 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) { | 4249 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) { |
4220 return; | 4250 return; |
4221 } | 4251 } |
4222 | |
4223 const Token::Kind op_kind = instr->token_kind(); | 4252 const Token::Kind op_kind = instr->token_kind(); |
4224 if (Compiler::always_optimize()) { | |
4225 // TODO(srdjan): Investigate other attempts, as they are not allowed to | |
4226 // deoptimize. | |
4227 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr, false)) { | |
4228 return; | |
4229 } | |
4230 return; | |
4231 } | |
4232 | 4253 |
4233 // Type test is special as it always gets converted into inlined code. | 4254 // Type test is special as it always gets converted into inlined code. |
4234 if (Token::IsTypeTestOperator(op_kind)) { | 4255 if (Token::IsTypeTestOperator(op_kind)) { |
4235 ReplaceWithInstanceOf(instr); | 4256 ReplaceWithInstanceOf(instr); |
4236 return; | 4257 return; |
4237 } | 4258 } |
4238 | 4259 |
4239 if (Token::IsTypeCastOperator(op_kind)) { | 4260 if (Token::IsTypeCastOperator(op_kind)) { |
4240 ReplaceWithTypeCast(instr); | 4261 ReplaceWithTypeCast(instr); |
4241 return; | 4262 return; |
(...skipping 4425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8667 | 8688 |
8668 // Insert materializations at environment uses. | 8689 // Insert materializations at environment uses. |
8669 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8690 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
8670 CreateMaterializationAt( | 8691 CreateMaterializationAt( |
8671 exits_collector_.exits()[i], alloc, *slots); | 8692 exits_collector_.exits()[i], alloc, *slots); |
8672 } | 8693 } |
8673 } | 8694 } |
8674 | 8695 |
8675 | 8696 |
8676 } // namespace dart | 8697 } // namespace dart |
OLD | NEW |