| 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 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1116 return true; | 1116 return true; |
| 1117 } | 1117 } |
| 1118 | 1118 |
| 1119 return false; | 1119 return false; |
| 1120 } | 1120 } |
| 1121 | 1121 |
| 1122 | 1122 |
| 1123 // Tries to optimize instance call by replacing it with a faster instruction | 1123 // Tries to optimize instance call by replacing it with a faster instruction |
| 1124 // (e.g, binary op, field load, ..). | 1124 // (e.g, binary op, field load, ..). |
| 1125 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 1125 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| 1126 if (instr->HasICData() && (instr->ic_data()->NumberOfChecks() > 0)) { | 1126 if (!instr->HasICData() || (instr->ic_data()->NumberOfChecks() == 0)) { |
| 1127 const Token::Kind op_kind = instr->token_kind(); | 1127 // An instance call without ICData will trigger deoptimization. |
| 1128 if ((op_kind == Token::kASSIGN_INDEX) && | 1128 return; |
| 1129 TryReplaceWithStoreIndexed(instr)) { | 1129 } |
| 1130 return; | 1130 |
| 1131 const ICData& unary_checks = |
| 1132 ICData::ZoneHandle(instr->ic_data()->AsUnaryClassChecks()); |
| 1133 if ((unary_checks.NumberOfChecks() > FLAG_max_polymorphic_checks) && |
| 1134 InstanceCallNeedsClassCheck(instr)) { |
| 1135 // Too many checks, leave it megamorphic. |
| 1136 return; |
| 1137 } |
| 1138 |
| 1139 const Token::Kind op_kind = instr->token_kind(); |
| 1140 if ((op_kind == Token::kASSIGN_INDEX) && |
| 1141 TryReplaceWithStoreIndexed(instr)) { |
| 1142 return; |
| 1143 } |
| 1144 if ((op_kind == Token::kINDEX) && TryReplaceWithLoadIndexed(instr)) { |
| 1145 return; |
| 1146 } |
| 1147 if (Token::IsBinaryOperator(op_kind) && |
| 1148 TryReplaceWithBinaryOp(instr, op_kind)) { |
| 1149 return; |
| 1150 } |
| 1151 if (Token::IsPrefixOperator(op_kind) && |
| 1152 TryReplaceWithUnaryOp(instr, op_kind)) { |
| 1153 return; |
| 1154 } |
| 1155 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr)) { |
| 1156 return; |
| 1157 } |
| 1158 if ((op_kind == Token::kSET) && TryInlineInstanceSetter(instr)) { |
| 1159 return; |
| 1160 } |
| 1161 if (TryInlineInstanceMethod(instr)) { |
| 1162 return; |
| 1163 } |
| 1164 if (!InstanceCallNeedsClassCheck(instr)) { |
| 1165 const bool call_with_checks = false; |
| 1166 PolymorphicInstanceCallInstr* call = |
| 1167 new PolymorphicInstanceCallInstr(instr, unary_checks, |
| 1168 call_with_checks); |
| 1169 instr->ReplaceWith(call, current_iterator()); |
| 1170 return; |
| 1171 } |
| 1172 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { |
| 1173 bool call_with_checks; |
| 1174 if (unary_checks.HasOneTarget()) { |
| 1175 // Type propagation has not run yet, we cannot eliminate the check. |
| 1176 AddCheckClass(instr, instr->ArgumentAt(0)->value()->Copy()); |
| 1177 // Call can still deoptimize, do not detach environment from instr. |
| 1178 call_with_checks = false; |
| 1179 } else { |
| 1180 call_with_checks = true; |
| 1131 } | 1181 } |
| 1132 if ((op_kind == Token::kINDEX) && TryReplaceWithLoadIndexed(instr)) { | 1182 PolymorphicInstanceCallInstr* call = |
| 1133 return; | 1183 new PolymorphicInstanceCallInstr(instr, unary_checks, |
| 1134 } | 1184 call_with_checks); |
| 1135 if (Token::IsBinaryOperator(op_kind) && | 1185 instr->ReplaceWith(call, current_iterator()); |
| 1136 TryReplaceWithBinaryOp(instr, op_kind)) { | |
| 1137 return; | |
| 1138 } | |
| 1139 if (Token::IsPrefixOperator(op_kind) && | |
| 1140 TryReplaceWithUnaryOp(instr, op_kind)) { | |
| 1141 return; | |
| 1142 } | |
| 1143 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr)) { | |
| 1144 return; | |
| 1145 } | |
| 1146 if ((op_kind == Token::kSET) && TryInlineInstanceSetter(instr)) { | |
| 1147 return; | |
| 1148 } | |
| 1149 if (TryInlineInstanceMethod(instr)) { | |
| 1150 return; | |
| 1151 } | |
| 1152 const ICData& unary_checks = | |
| 1153 ICData::ZoneHandle(instr->ic_data()->AsUnaryClassChecks()); | |
| 1154 if (!InstanceCallNeedsClassCheck(instr)) { | |
| 1155 const bool call_with_checks = false; | |
| 1156 PolymorphicInstanceCallInstr* call = | |
| 1157 new PolymorphicInstanceCallInstr(instr, unary_checks, | |
| 1158 call_with_checks); | |
| 1159 instr->ReplaceWith(call, current_iterator()); | |
| 1160 return; | |
| 1161 } | |
| 1162 if (instr->ic_data()->NumberOfChecks() <= FLAG_max_polymorphic_checks) { | |
| 1163 bool call_with_checks; | |
| 1164 if (unary_checks.HasOneTarget()) { | |
| 1165 // Type propagation has not run yet, we cannot eliminate the check. | |
| 1166 AddCheckClass(instr, instr->ArgumentAt(0)->value()->Copy()); | |
| 1167 // Call can still deoptimize, do not detach environment from instr. | |
| 1168 call_with_checks = false; | |
| 1169 } else { | |
| 1170 call_with_checks = true; | |
| 1171 } | |
| 1172 PolymorphicInstanceCallInstr* call = | |
| 1173 new PolymorphicInstanceCallInstr(instr, unary_checks, | |
| 1174 call_with_checks); | |
| 1175 instr->ReplaceWith(call, current_iterator()); | |
| 1176 } | |
| 1177 } | 1186 } |
| 1178 // An instance call without ICData will trigger deoptimization. | |
| 1179 } | 1187 } |
| 1180 | 1188 |
| 1181 | 1189 |
| 1182 void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) { | 1190 void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) { |
| 1183 MethodRecognizer::Kind recognized_kind = | 1191 MethodRecognizer::Kind recognized_kind = |
| 1184 MethodRecognizer::RecognizeKind(call->function()); | 1192 MethodRecognizer::RecognizeKind(call->function()); |
| 1185 if (recognized_kind == MethodRecognizer::kMathSqrt) { | 1193 if (recognized_kind == MethodRecognizer::kMathSqrt) { |
| 1186 MathSqrtInstr* sqrt = new MathSqrtInstr(call->ArgumentAt(0)->value(), call); | 1194 MathSqrtInstr* sqrt = new MathSqrtInstr(call->ArgumentAt(0)->value(), call); |
| 1187 call->ReplaceWith(sqrt, current_iterator()); | 1195 call->ReplaceWith(sqrt, current_iterator()); |
| 1188 RemovePushArguments(call); | 1196 RemovePushArguments(call); |
| (...skipping 2458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3647 | 3655 |
| 3648 if (FLAG_trace_constant_propagation) { | 3656 if (FLAG_trace_constant_propagation) { |
| 3649 OS::Print("\n==== After constant propagation ====\n"); | 3657 OS::Print("\n==== After constant propagation ====\n"); |
| 3650 FlowGraphPrinter printer(*graph_); | 3658 FlowGraphPrinter printer(*graph_); |
| 3651 printer.PrintBlocks(); | 3659 printer.PrintBlocks(); |
| 3652 } | 3660 } |
| 3653 } | 3661 } |
| 3654 | 3662 |
| 3655 | 3663 |
| 3656 } // namespace dart | 3664 } // namespace dart |
| OLD | NEW |