| 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 | 
|---|