| 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 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 Value** index) { | 463 Value** index) { |
| 464 *array = call->ArgumentAt(0)->value(); | 464 *array = call->ArgumentAt(0)->value(); |
| 465 *index = call->ArgumentAt(1)->value(); | 465 *index = call->ArgumentAt(1)->value(); |
| 466 // Insert class check and index smi checks and attach a copy of the | 466 // Insert class check and index smi checks and attach a copy of the |
| 467 // original environment because the operation can still deoptimize. | 467 // original environment because the operation can still deoptimize. |
| 468 AddCheckClass(call, (*array)->Copy()); | 468 AddCheckClass(call, (*array)->Copy()); |
| 469 InsertBefore(call, | 469 InsertBefore(call, |
| 470 new CheckSmiInstr((*index)->Copy(), call->deopt_id()), | 470 new CheckSmiInstr((*index)->Copy(), call->deopt_id()), |
| 471 call->env(), | 471 call->env(), |
| 472 Definition::kEffect); | 472 Definition::kEffect); |
| 473 // If both index and array are constants, then the bound check always | 473 // If both index and array are constants, then do a compile-time check. |
| 474 // succeeded. | 474 // TODO(srdjan): Remove once constant propagation handles bounds checks. |
| 475 // TODO(srdjan): Remove once constant propagation lands. | 475 bool skip_check = false; |
| 476 if (!((*array)->BindsToConstant() && (*index)->BindsToConstant())) { | 476 if ((*array)->BindsToConstant() && (*index)->BindsToConstant()) { |
| 477 ConstantInstr* array_def = (*array)->definition()->AsConstant(); |
| 478 const ImmutableArray& constant_array = |
| 479 ImmutableArray::Cast(array_def->value()); |
| 480 ConstantInstr* index_def = (*index)->definition()->AsConstant(); |
| 481 if (index_def->value().IsSmi()) { |
| 482 intptr_t constant_index = Smi::Cast(index_def->value()).Value(); |
| 483 skip_check = (constant_index < constant_array.Length()); |
| 484 } |
| 485 } |
| 486 if (!skip_check) { |
| 477 // Insert array bounds check. | 487 // Insert array bounds check. |
| 478 InsertBefore(call, | 488 InsertBefore(call, |
| 479 new CheckArrayBoundInstr((*array)->Copy(), | 489 new CheckArrayBoundInstr((*array)->Copy(), |
| 480 (*index)->Copy(), | 490 (*index)->Copy(), |
| 481 class_id, | 491 class_id, |
| 482 call), | 492 call), |
| 483 call->env(), | 493 call->env(), |
| 484 Definition::kEffect); | 494 Definition::kEffect); |
| 485 } | 495 } |
| 486 if (class_id == kGrowableObjectArrayCid) { | 496 if (class_id == kGrowableObjectArrayCid) { |
| (...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 const ICData& ic_data = *call->ic_data(); | 1099 const ICData& ic_data = *call->ic_data(); |
| 1090 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { | 1100 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { |
| 1091 // No type feedback collected or multiple targets found. | 1101 // No type feedback collected or multiple targets found. |
| 1092 return false; | 1102 return false; |
| 1093 } | 1103 } |
| 1094 Function& target = Function::Handle(); | 1104 Function& target = Function::Handle(); |
| 1095 GrowableArray<intptr_t> class_ids; | 1105 GrowableArray<intptr_t> class_ids; |
| 1096 ic_data.GetCheckAt(0, &class_ids, &target); | 1106 ic_data.GetCheckAt(0, &class_ids, &target); |
| 1097 MethodRecognizer::Kind recognized_kind = | 1107 MethodRecognizer::Kind recognized_kind = |
| 1098 MethodRecognizer::RecognizeKind(target); | 1108 MethodRecognizer::RecognizeKind(target); |
| 1109 if ((recognized_kind == MethodRecognizer::kStringBaseCharCodeAt) && |
| 1110 (ic_data.NumberOfChecks() == 1) && |
| 1111 ((class_ids[0] == kOneByteStringCid) || |
| 1112 (class_ids[0] == kTwoByteStringCid))) { |
| 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 class_ids[0], |
| 1139 call), |
| 1140 call->env(), |
| 1141 Definition::kEffect); |
| 1142 } |
| 1143 StringCharCodeAtInstr* instr = |
| 1144 new StringCharCodeAtInstr(str, index, class_ids[0]); |
| 1145 call->ReplaceWith(instr, current_iterator()); |
| 1146 RemovePushArguments(call); |
| 1147 return true; |
| 1148 } |
| 1099 | 1149 |
| 1100 if ((recognized_kind == MethodRecognizer::kIntegerToDouble) && | 1150 if ((recognized_kind == MethodRecognizer::kIntegerToDouble) && |
| 1101 (class_ids[0] == kSmiCid)) { | 1151 (class_ids[0] == kSmiCid)) { |
| 1102 SmiToDoubleInstr* s2d_instr = new SmiToDoubleInstr(call); | 1152 SmiToDoubleInstr* s2d_instr = new SmiToDoubleInstr(call); |
| 1103 call->ReplaceWith(s2d_instr, current_iterator()); | 1153 call->ReplaceWith(s2d_instr, current_iterator()); |
| 1104 // Pushed arguments are not removed because SmiToDouble is implemented | 1154 // Pushed arguments are not removed because SmiToDouble is implemented |
| 1105 // as a call. | 1155 // as a call. |
| 1106 return true; | 1156 return true; |
| 1107 } | 1157 } |
| 1108 | 1158 |
| (...skipping 2114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3223 SetValue(instr, non_constant_); | 3273 SetValue(instr, non_constant_); |
| 3224 } | 3274 } |
| 3225 } | 3275 } |
| 3226 | 3276 |
| 3227 | 3277 |
| 3228 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { | 3278 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { |
| 3229 SetValue(instr, non_constant_); | 3279 SetValue(instr, non_constant_); |
| 3230 } | 3280 } |
| 3231 | 3281 |
| 3232 | 3282 |
| 3283 void ConstantPropagator::VisitStringCharCodeAt(StringCharCodeAtInstr* instr) { |
| 3284 SetValue(instr, non_constant_); |
| 3285 } |
| 3286 |
| 3287 |
| 3233 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { | 3288 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { |
| 3234 SetValue(instr, non_constant_); | 3289 SetValue(instr, non_constant_); |
| 3235 } | 3290 } |
| 3236 | 3291 |
| 3237 | 3292 |
| 3238 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { | 3293 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { |
| 3239 SetValue(instr, instr->value()->definition()->constant_value()); | 3294 SetValue(instr, instr->value()->definition()->constant_value()); |
| 3240 } | 3295 } |
| 3241 | 3296 |
| 3242 | 3297 |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3655 | 3710 |
| 3656 if (FLAG_trace_constant_propagation) { | 3711 if (FLAG_trace_constant_propagation) { |
| 3657 OS::Print("\n==== After constant propagation ====\n"); | 3712 OS::Print("\n==== After constant propagation ====\n"); |
| 3658 FlowGraphPrinter printer(*graph_); | 3713 FlowGraphPrinter printer(*graph_); |
| 3659 printer.PrintBlocks(); | 3714 printer.PrintBlocks(); |
| 3660 } | 3715 } |
| 3661 } | 3716 } |
| 3662 | 3717 |
| 3663 | 3718 |
| 3664 } // namespace dart | 3719 } // namespace dart |
| OLD | NEW |