Chromium Code Reviews| 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 intptr_t constant_index = Smi::Cast(index_def->value()).Value(); | |
| 482 skip_check = (constant_index < constant_array.Length()); | |
| 483 } | |
|
srdjan
2012/11/01 20:32:18
I get a crash with following code. Can you please
Florian Schneider
2012/11/01 22:58:56
Good point. I added the test and fixed the non-smi
| |
| 484 if (!skip_check) { | |
| 477 // Insert array bounds check. | 485 // Insert array bounds check. |
| 478 InsertBefore(call, | 486 InsertBefore(call, |
| 479 new CheckArrayBoundInstr((*array)->Copy(), | 487 new CheckArrayBoundInstr((*array)->Copy(), |
| 480 (*index)->Copy(), | 488 (*index)->Copy(), |
| 481 class_id, | 489 class_id, |
| 482 call), | 490 call), |
| 483 call->env(), | 491 call->env(), |
| 484 Definition::kEffect); | 492 Definition::kEffect); |
| 485 } | 493 } |
| 486 if (class_id == kGrowableObjectArrayCid) { | 494 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(); | 1097 const ICData& ic_data = *call->ic_data(); |
| 1090 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { | 1098 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { |
| 1091 // No type feedback collected or multiple targets found. | 1099 // No type feedback collected or multiple targets found. |
| 1092 return false; | 1100 return false; |
| 1093 } | 1101 } |
| 1094 Function& target = Function::Handle(); | 1102 Function& target = Function::Handle(); |
| 1095 GrowableArray<intptr_t> class_ids; | 1103 GrowableArray<intptr_t> class_ids; |
| 1096 ic_data.GetCheckAt(0, &class_ids, &target); | 1104 ic_data.GetCheckAt(0, &class_ids, &target); |
| 1097 MethodRecognizer::Kind recognized_kind = | 1105 MethodRecognizer::Kind recognized_kind = |
| 1098 MethodRecognizer::RecognizeKind(target); | 1106 MethodRecognizer::RecognizeKind(target); |
| 1107 if ((recognized_kind == MethodRecognizer::kStringBaseCharCodeAt) && | |
| 1108 (ic_data.NumberOfChecks() == 1) && | |
| 1109 ((class_ids[0] == kOneByteStringCid) || | |
| 1110 (class_ids[0] == kTwoByteStringCid))) { | |
| 1111 Value* str= call->ArgumentAt(0)->value(); | |
| 1112 Value* index = call->ArgumentAt(1)->value(); | |
| 1113 AddCheckClass(call, str->Copy()); | |
| 1114 InsertBefore(call, | |
| 1115 new CheckSmiInstr(index->Copy(), call->deopt_id()), | |
| 1116 call->env(), | |
| 1117 Definition::kEffect); | |
| 1118 // If both index and string are constants, then do a compile-time check. | |
| 1119 // TODO(srdjan): Remove once constant propagation handles bounds checks. | |
| 1120 bool skip_check = false; | |
| 1121 if (str->BindsToConstant() && index->BindsToConstant()) { | |
| 1122 ConstantInstr* string_def = str->definition()->AsConstant(); | |
| 1123 const String& constant_string = | |
| 1124 String::Cast(string_def->value()); | |
| 1125 ConstantInstr* index_def = index->definition()->AsConstant(); | |
| 1126 intptr_t constant_index = Smi::Cast(index_def->value()).Value(); | |
| 1127 skip_check = (constant_index < constant_string.Length()); | |
| 1128 } | |
| 1129 if (!skip_check) { | |
| 1130 // Insert bounds check. | |
| 1131 InsertBefore(call, | |
| 1132 new CheckArrayBoundInstr(str->Copy(), | |
| 1133 index->Copy(), | |
| 1134 class_ids[0], | |
| 1135 call), | |
| 1136 call->env(), | |
| 1137 Definition::kEffect); | |
| 1138 } | |
| 1139 StringCharCodeAtInstr* instr = | |
| 1140 new StringCharCodeAtInstr(str, index, class_ids[0]); | |
| 1141 call->ReplaceWith(instr, current_iterator()); | |
| 1142 RemovePushArguments(call); | |
| 1143 return true; | |
| 1144 } | |
| 1099 | 1145 |
| 1100 if ((recognized_kind == MethodRecognizer::kIntegerToDouble) && | 1146 if ((recognized_kind == MethodRecognizer::kIntegerToDouble) && |
| 1101 (class_ids[0] == kSmiCid)) { | 1147 (class_ids[0] == kSmiCid)) { |
| 1102 SmiToDoubleInstr* s2d_instr = new SmiToDoubleInstr(call); | 1148 SmiToDoubleInstr* s2d_instr = new SmiToDoubleInstr(call); |
| 1103 call->ReplaceWith(s2d_instr, current_iterator()); | 1149 call->ReplaceWith(s2d_instr, current_iterator()); |
| 1104 // Pushed arguments are not removed because SmiToDouble is implemented | 1150 // Pushed arguments are not removed because SmiToDouble is implemented |
| 1105 // as a call. | 1151 // as a call. |
| 1106 return true; | 1152 return true; |
| 1107 } | 1153 } |
| 1108 | 1154 |
| (...skipping 2114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3223 SetValue(instr, non_constant_); | 3269 SetValue(instr, non_constant_); |
| 3224 } | 3270 } |
| 3225 } | 3271 } |
| 3226 | 3272 |
| 3227 | 3273 |
| 3228 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { | 3274 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { |
| 3229 SetValue(instr, non_constant_); | 3275 SetValue(instr, non_constant_); |
| 3230 } | 3276 } |
| 3231 | 3277 |
| 3232 | 3278 |
| 3279 void ConstantPropagator::VisitStringCharCodeAt(StringCharCodeAtInstr* instr) { | |
| 3280 SetValue(instr, non_constant_); | |
| 3281 } | |
| 3282 | |
| 3283 | |
| 3233 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { | 3284 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { |
| 3234 SetValue(instr, non_constant_); | 3285 SetValue(instr, non_constant_); |
| 3235 } | 3286 } |
| 3236 | 3287 |
| 3237 | 3288 |
| 3238 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { | 3289 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { |
| 3239 SetValue(instr, instr->value()->definition()->constant_value()); | 3290 SetValue(instr, instr->value()->definition()->constant_value()); |
| 3240 } | 3291 } |
| 3241 | 3292 |
| 3242 | 3293 |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3655 | 3706 |
| 3656 if (FLAG_trace_constant_propagation) { | 3707 if (FLAG_trace_constant_propagation) { |
| 3657 OS::Print("\n==== After constant propagation ====\n"); | 3708 OS::Print("\n==== After constant propagation ====\n"); |
| 3658 FlowGraphPrinter printer(*graph_); | 3709 FlowGraphPrinter printer(*graph_); |
| 3659 printer.PrintBlocks(); | 3710 printer.PrintBlocks(); |
| 3660 } | 3711 } |
| 3661 } | 3712 } |
| 3662 | 3713 |
| 3663 | 3714 |
| 3664 } // namespace dart | 3715 } // namespace dart |
| OLD | NEW |