| 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 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 return false; | 1100 return false; |
| 1101 } | 1101 } |
| 1102 InlineStringIsEmptyGetter(call); | 1102 InlineStringIsEmptyGetter(call); |
| 1103 return true; | 1103 return true; |
| 1104 } | 1104 } |
| 1105 | 1105 |
| 1106 return false; | 1106 return false; |
| 1107 } | 1107 } |
| 1108 | 1108 |
| 1109 | 1109 |
| 1110 StringCharCodeAtInstr* FlowGraphOptimizer::BuildStringCharCodeAt( |
| 1111 InstanceCallInstr* call, |
| 1112 intptr_t cid) { |
| 1113 Value* str = call->ArgumentAt(0)->value(); |
| 1114 Value* index = call->ArgumentAt(1)->value(); |
| 1115 AddCheckClass(call, str->Copy()); |
| 1116 InsertBefore(call, |
| 1117 new CheckSmiInstr(index->Copy(), call->deopt_id()), |
| 1118 call->env(), |
| 1119 Definition::kEffect); |
| 1120 // If both index and string are constants, then do a compile-time check. |
| 1121 // TODO(srdjan): Remove once constant propagation handles bounds checks. |
| 1122 bool skip_check = false; |
| 1123 if (str->BindsToConstant() && index->BindsToConstant()) { |
| 1124 ConstantInstr* string_def = str->definition()->AsConstant(); |
| 1125 const String& constant_string = |
| 1126 String::Cast(string_def->value()); |
| 1127 ConstantInstr* index_def = index->definition()->AsConstant(); |
| 1128 if (index_def->value().IsSmi()) { |
| 1129 intptr_t constant_index = Smi::Cast(index_def->value()).Value(); |
| 1130 skip_check = (constant_index < constant_string.Length()); |
| 1131 } |
| 1132 } |
| 1133 if (!skip_check) { |
| 1134 // Insert bounds check. |
| 1135 InsertBefore(call, |
| 1136 new CheckArrayBoundInstr(str->Copy(), |
| 1137 index->Copy(), |
| 1138 cid, |
| 1139 call), |
| 1140 call->env(), |
| 1141 Definition::kEffect); |
| 1142 } |
| 1143 return new StringCharCodeAtInstr(str, index, cid); |
| 1144 } |
| 1145 |
| 1146 |
| 1110 // Inline only simple, frequently called core library methods. | 1147 // Inline only simple, frequently called core library methods. |
| 1111 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { | 1148 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { |
| 1112 ASSERT(call->HasICData()); | 1149 ASSERT(call->HasICData()); |
| 1113 const ICData& ic_data = *call->ic_data(); | 1150 const ICData& ic_data = *call->ic_data(); |
| 1114 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { | 1151 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { |
| 1115 // No type feedback collected or multiple targets found. | 1152 // No type feedback collected or multiple targets found. |
| 1116 return false; | 1153 return false; |
| 1117 } | 1154 } |
| 1118 Function& target = Function::Handle(); | 1155 Function& target = Function::Handle(); |
| 1119 GrowableArray<intptr_t> class_ids; | 1156 GrowableArray<intptr_t> class_ids; |
| 1120 ic_data.GetCheckAt(0, &class_ids, &target); | 1157 ic_data.GetCheckAt(0, &class_ids, &target); |
| 1121 MethodRecognizer::Kind recognized_kind = | 1158 MethodRecognizer::Kind recognized_kind = |
| 1122 MethodRecognizer::RecognizeKind(target); | 1159 MethodRecognizer::RecognizeKind(target); |
| 1123 if ((recognized_kind == MethodRecognizer::kStringBaseCharCodeAt) && | 1160 if ((recognized_kind == MethodRecognizer::kStringBaseCharCodeAt) && |
| 1124 (ic_data.NumberOfChecks() == 1) && | 1161 (ic_data.NumberOfChecks() == 1) && |
| 1125 ((class_ids[0] == kOneByteStringCid) || | 1162 ((class_ids[0] == kOneByteStringCid) || |
| 1126 (class_ids[0] == kTwoByteStringCid))) { | 1163 (class_ids[0] == kTwoByteStringCid))) { |
| 1127 Value* str= call->ArgumentAt(0)->value(); | 1164 StringCharCodeAtInstr* instr = BuildStringCharCodeAt(call, class_ids[0]); |
| 1128 Value* index = call->ArgumentAt(1)->value(); | |
| 1129 AddCheckClass(call, str->Copy()); | |
| 1130 InsertBefore(call, | |
| 1131 new CheckSmiInstr(index->Copy(), call->deopt_id()), | |
| 1132 call->env(), | |
| 1133 Definition::kEffect); | |
| 1134 // If both index and string are constants, then do a compile-time check. | |
| 1135 // TODO(srdjan): Remove once constant propagation handles bounds checks. | |
| 1136 bool skip_check = false; | |
| 1137 if (str->BindsToConstant() && index->BindsToConstant()) { | |
| 1138 ConstantInstr* string_def = str->definition()->AsConstant(); | |
| 1139 const String& constant_string = | |
| 1140 String::Cast(string_def->value()); | |
| 1141 ConstantInstr* index_def = index->definition()->AsConstant(); | |
| 1142 if (index_def->value().IsSmi()) { | |
| 1143 intptr_t constant_index = Smi::Cast(index_def->value()).Value(); | |
| 1144 skip_check = (constant_index < constant_string.Length()); | |
| 1145 } | |
| 1146 } | |
| 1147 if (!skip_check) { | |
| 1148 // Insert bounds check. | |
| 1149 InsertBefore(call, | |
| 1150 new CheckArrayBoundInstr(str->Copy(), | |
| 1151 index->Copy(), | |
| 1152 class_ids[0], | |
| 1153 call), | |
| 1154 call->env(), | |
| 1155 Definition::kEffect); | |
| 1156 } | |
| 1157 StringCharCodeAtInstr* instr = | |
| 1158 new StringCharCodeAtInstr(str, index, class_ids[0]); | |
| 1159 call->ReplaceWith(instr, current_iterator()); | 1165 call->ReplaceWith(instr, current_iterator()); |
| 1160 RemovePushArguments(call); | 1166 RemovePushArguments(call); |
| 1161 return true; | 1167 return true; |
| 1162 } | 1168 } |
| 1169 if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) && |
| 1170 (ic_data.NumberOfChecks() == 1) && |
| 1171 (class_ids[0] == kOneByteStringCid)) { |
| 1172 // TODO(fschneider): Handle TwoByteString. |
| 1173 StringCharCodeAtInstr* load_char_code = |
| 1174 BuildStringCharCodeAt(call, class_ids[0]); |
| 1175 InsertBefore(call, load_char_code, NULL, Definition::kValue); |
| 1176 StringFromCharCodeInstr* char_at = |
| 1177 new StringFromCharCodeInstr(new Value(load_char_code)); |
| 1178 call->ReplaceWith(char_at, current_iterator()); |
| 1179 RemovePushArguments(call); |
| 1180 return true; |
| 1181 } |
| 1163 | 1182 |
| 1164 if ((recognized_kind == MethodRecognizer::kIntegerToDouble) && | 1183 if ((recognized_kind == MethodRecognizer::kIntegerToDouble) && |
| 1165 (class_ids[0] == kSmiCid)) { | 1184 (class_ids[0] == kSmiCid)) { |
| 1166 SmiToDoubleInstr* s2d_instr = new SmiToDoubleInstr(call); | 1185 SmiToDoubleInstr* s2d_instr = new SmiToDoubleInstr(call); |
| 1167 call->ReplaceWith(s2d_instr, current_iterator()); | 1186 call->ReplaceWith(s2d_instr, current_iterator()); |
| 1168 // Pushed arguments are not removed because SmiToDouble is implemented | 1187 // Pushed arguments are not removed because SmiToDouble is implemented |
| 1169 // as a call. | 1188 // as a call. |
| 1170 return true; | 1189 return true; |
| 1171 } | 1190 } |
| 1172 | 1191 |
| (...skipping 2122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3295 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { | 3314 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { |
| 3296 SetValue(instr, non_constant_); | 3315 SetValue(instr, non_constant_); |
| 3297 } | 3316 } |
| 3298 | 3317 |
| 3299 | 3318 |
| 3300 void ConstantPropagator::VisitStringCharCodeAt(StringCharCodeAtInstr* instr) { | 3319 void ConstantPropagator::VisitStringCharCodeAt(StringCharCodeAtInstr* instr) { |
| 3301 SetValue(instr, non_constant_); | 3320 SetValue(instr, non_constant_); |
| 3302 } | 3321 } |
| 3303 | 3322 |
| 3304 | 3323 |
| 3324 void ConstantPropagator::VisitStringFromCharCode( |
| 3325 StringFromCharCodeInstr* instr) { |
| 3326 SetValue(instr, non_constant_); |
| 3327 } |
| 3328 |
| 3329 |
| 3305 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { | 3330 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { |
| 3306 SetValue(instr, non_constant_); | 3331 SetValue(instr, non_constant_); |
| 3307 } | 3332 } |
| 3308 | 3333 |
| 3309 | 3334 |
| 3310 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { | 3335 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { |
| 3311 SetValue(instr, instr->value()->definition()->constant_value()); | 3336 SetValue(instr, instr->value()->definition()->constant_value()); |
| 3312 } | 3337 } |
| 3313 | 3338 |
| 3314 | 3339 |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3732 | 3757 |
| 3733 if (FLAG_trace_constant_propagation) { | 3758 if (FLAG_trace_constant_propagation) { |
| 3734 OS::Print("\n==== After constant propagation ====\n"); | 3759 OS::Print("\n==== After constant propagation ====\n"); |
| 3735 FlowGraphPrinter printer(*graph_); | 3760 FlowGraphPrinter printer(*graph_); |
| 3736 printer.PrintBlocks(); | 3761 printer.PrintBlocks(); |
| 3737 } | 3762 } |
| 3738 } | 3763 } |
| 3739 | 3764 |
| 3740 | 3765 |
| 3741 } // namespace dart | 3766 } // namespace dart |
| OLD | NEW |