| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 869 // callee functions, then no class check is needed. | 869 // callee functions, then no class check is needed. |
| 870 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck( | 870 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck( |
| 871 InstanceCallInstr* call) const { | 871 InstanceCallInstr* call) const { |
| 872 if (!FLAG_use_cha) return true; | 872 if (!FLAG_use_cha) return true; |
| 873 Definition* callee_receiver = call->ArgumentAt(0)->value()->definition(); | 873 Definition* callee_receiver = call->ArgumentAt(0)->value()->definition(); |
| 874 ASSERT(callee_receiver != NULL); | 874 ASSERT(callee_receiver != NULL); |
| 875 const Function& function = flow_graph_->parsed_function().function(); | 875 const Function& function = flow_graph_->parsed_function().function(); |
| 876 if (function.IsDynamicFunction() && | 876 if (function.IsDynamicFunction() && |
| 877 callee_receiver->IsParameter() && | 877 callee_receiver->IsParameter() && |
| 878 (callee_receiver->AsParameter()->index() == 0)) { | 878 (callee_receiver->AsParameter()->index() == 0)) { |
| 879 const intptr_t static_receiver_cid = Class::Handle(function.Owner()).id(); | 879 return CHA::HasOverride(Class::Handle(function.Owner()), |
| 880 ZoneGrowableArray<intptr_t>* subclass_cids = | 880 call->function_name()); |
| 881 CHA::GetSubclassIdsOf(static_receiver_cid); | |
| 882 if (subclass_cids->is_empty()) { | |
| 883 // No subclasses, no check needed. | |
| 884 return false; | |
| 885 } | |
| 886 ZoneGrowableArray<Function*>* overriding_functions = | |
| 887 CHA::GetNamedInstanceFunctionsOf(*subclass_cids, call->function_name()); | |
| 888 if (overriding_functions->is_empty()) { | |
| 889 // No overriding functions. | |
| 890 return false; | |
| 891 } | |
| 892 } | 881 } |
| 893 return true; | 882 return true; |
| 894 } | 883 } |
| 895 | 884 |
| 896 | 885 |
| 897 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { | 886 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { |
| 898 ASSERT(call->HasICData()); | 887 ASSERT(call->HasICData()); |
| 899 const ICData& ic_data = *call->ic_data(); | 888 const ICData& ic_data = *call->ic_data(); |
| 900 Function& target = Function::Handle(); | 889 Function& target = Function::Handle(); |
| 901 GrowableArray<intptr_t> class_ids; | 890 GrowableArray<intptr_t> class_ids; |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 TryReplaceWithBinaryOp(instr, op_kind)) { | 1137 TryReplaceWithBinaryOp(instr, op_kind)) { |
| 1149 return; | 1138 return; |
| 1150 } | 1139 } |
| 1151 if (Token::IsPrefixOperator(op_kind) && | 1140 if (Token::IsPrefixOperator(op_kind) && |
| 1152 TryReplaceWithUnaryOp(instr, op_kind)) { | 1141 TryReplaceWithUnaryOp(instr, op_kind)) { |
| 1153 return; | 1142 return; |
| 1154 } | 1143 } |
| 1155 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr)) { | 1144 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr)) { |
| 1156 return; | 1145 return; |
| 1157 } | 1146 } |
| 1158 if ((op_kind == Token::kSET) && TryInlineInstanceSetter(instr)) { | 1147 if ((op_kind == Token::kSET) && |
| 1148 TryInlineInstanceSetter(instr, unary_checks)) { |
| 1159 return; | 1149 return; |
| 1160 } | 1150 } |
| 1161 if (TryInlineInstanceMethod(instr)) { | 1151 if (TryInlineInstanceMethod(instr)) { |
| 1162 return; | 1152 return; |
| 1163 } | 1153 } |
| 1164 if (!InstanceCallNeedsClassCheck(instr)) { | 1154 if (!InstanceCallNeedsClassCheck(instr)) { |
| 1165 const bool call_with_checks = false; | 1155 const bool call_with_checks = false; |
| 1166 PolymorphicInstanceCallInstr* call = | 1156 PolymorphicInstanceCallInstr* call = |
| 1167 new PolymorphicInstanceCallInstr(instr, unary_checks, | 1157 new PolymorphicInstanceCallInstr(instr, unary_checks, |
| 1168 call_with_checks); | 1158 call_with_checks); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1191 MethodRecognizer::Kind recognized_kind = | 1181 MethodRecognizer::Kind recognized_kind = |
| 1192 MethodRecognizer::RecognizeKind(call->function()); | 1182 MethodRecognizer::RecognizeKind(call->function()); |
| 1193 if (recognized_kind == MethodRecognizer::kMathSqrt) { | 1183 if (recognized_kind == MethodRecognizer::kMathSqrt) { |
| 1194 MathSqrtInstr* sqrt = new MathSqrtInstr(call->ArgumentAt(0)->value(), call); | 1184 MathSqrtInstr* sqrt = new MathSqrtInstr(call->ArgumentAt(0)->value(), call); |
| 1195 call->ReplaceWith(sqrt, current_iterator()); | 1185 call->ReplaceWith(sqrt, current_iterator()); |
| 1196 RemovePushArguments(call); | 1186 RemovePushArguments(call); |
| 1197 } | 1187 } |
| 1198 } | 1188 } |
| 1199 | 1189 |
| 1200 | 1190 |
| 1201 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr) { | 1191 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, |
| 1192 const ICData& unary_ic_data) { |
| 1193 ASSERT((unary_ic_data.NumberOfChecks() > 0) && |
| 1194 (unary_ic_data.num_args_tested() == 1)); |
| 1202 if (FLAG_enable_type_checks) { | 1195 if (FLAG_enable_type_checks) { |
| 1203 // TODO(srdjan): Add assignable check node if --enable_type_checks. | 1196 // TODO(srdjan): Add assignable check node if --enable_type_checks. |
| 1204 return false; | 1197 return false; |
| 1205 } | 1198 } |
| 1206 | 1199 |
| 1207 ASSERT(instr->HasICData()); | 1200 ASSERT(instr->HasICData()); |
| 1208 const ICData& unary_ic_data = | |
| 1209 ICData::Handle(instr->ic_data()->AsUnaryClassChecks()); | |
| 1210 if (unary_ic_data.NumberOfChecks() == 0) { | 1201 if (unary_ic_data.NumberOfChecks() == 0) { |
| 1211 // No type feedback collected. | 1202 // No type feedback collected. |
| 1212 return false; | 1203 return false; |
| 1213 } | 1204 } |
| 1214 if (!unary_ic_data.HasOneTarget()) { | 1205 if (!unary_ic_data.HasOneTarget()) { |
| 1215 // TODO(srdjan): Implement when not all targets are the same. | 1206 // TODO(srdjan): Implement when not all targets are the same. |
| 1216 return false; | 1207 return false; |
| 1217 } | 1208 } |
| 1218 Function& target = Function::Handle(); | 1209 Function& target = Function::Handle(); |
| 1219 intptr_t class_id; | 1210 intptr_t class_id; |
| (...skipping 2435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3655 | 3646 |
| 3656 if (FLAG_trace_constant_propagation) { | 3647 if (FLAG_trace_constant_propagation) { |
| 3657 OS::Print("\n==== After constant propagation ====\n"); | 3648 OS::Print("\n==== After constant propagation ====\n"); |
| 3658 FlowGraphPrinter printer(*graph_); | 3649 FlowGraphPrinter printer(*graph_); |
| 3659 printer.PrintBlocks(); | 3650 printer.PrintBlocks(); |
| 3660 } | 3651 } |
| 3661 } | 3652 } |
| 3662 | 3653 |
| 3663 | 3654 |
| 3664 } // namespace dart | 3655 } // namespace dart |
| OLD | NEW |