| 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/cha.h" | 7 #include "vm/cha.h" |
| 8 #include "vm/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
| 9 #include "vm/hash_map.h" | 9 #include "vm/hash_map.h" |
| 10 #include "vm/il_printer.h" | 10 #include "vm/il_printer.h" |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 | 195 |
| 196 void FlowGraphOptimizer::AddCheckClass(BindInstr* instr, | 196 void FlowGraphOptimizer::AddCheckClass(BindInstr* instr, |
| 197 InstanceCallComp* comp, | 197 InstanceCallComp* comp, |
| 198 Value* value) { | 198 Value* value) { |
| 199 // Type propagation has not run yet, we cannot eliminate the check. | 199 // Type propagation has not run yet, we cannot eliminate the check. |
| 200 CheckClassComp* check = new CheckClassComp(value, comp); | 200 CheckClassComp* check = new CheckClassComp(value, comp); |
| 201 const ICData& unary_checks = | 201 const ICData& unary_checks = |
| 202 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); | 202 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); |
| 203 check->set_ic_data(&unary_checks); | 203 check->set_ic_data(&unary_checks); |
| 204 InsertBefore(instr, check, instr->env(), BindInstr::kUnused); | 204 InsertBefore(instr, check, instr->env(), BindInstr::kUnused); |
| 205 // Detach environment from the original instruction because it can't | |
| 206 // deoptimize. | |
| 207 instr->set_env(NULL); | |
| 208 } | 205 } |
| 209 | 206 |
| 210 | 207 |
| 211 bool FlowGraphOptimizer::TryReplaceWithArrayOp(BindInstr* instr, | 208 bool FlowGraphOptimizer::TryReplaceWithArrayOp(BindInstr* instr, |
| 212 InstanceCallComp* comp, | 209 InstanceCallComp* comp, |
| 213 Token::Kind op_kind) { | 210 Token::Kind op_kind) { |
| 214 // TODO(fschneider): Optimize []= operator in checked mode as well. | 211 // TODO(fschneider): Optimize []= operator in checked mode as well. |
| 215 if (op_kind == Token::kASSIGN_INDEX && FLAG_enable_type_checks) return false; | 212 if (op_kind == Token::kASSIGN_INDEX && FLAG_enable_type_checks) return false; |
| 216 | 213 |
| 217 const intptr_t class_id = ReceiverClassId(comp); | 214 const intptr_t class_id = ReceiverClassId(comp); |
| 218 switch (class_id) { | 215 switch (class_id) { |
| 219 case kImmutableArrayCid: | 216 case kImmutableArrayCid: |
| 220 // Stores are only specialized for Array and GrowableObjectArray, | 217 // Stores are only specialized for Array and GrowableObjectArray, |
| 221 // not for ImmutableArray. | 218 // not for ImmutableArray. |
| 222 if (op_kind == Token::kASSIGN_INDEX) return false; | 219 if (op_kind == Token::kASSIGN_INDEX) return false; |
| 223 // Fall through. | 220 // Fall through. |
| 224 case kArrayCid: | 221 case kArrayCid: |
| 225 case kGrowableObjectArrayCid: { | 222 case kGrowableObjectArrayCid: { |
| 223 Value* array = comp->ArgumentAt(0)->value(); |
| 224 Value* index = comp->ArgumentAt(1)->value(); |
| 225 // Insert class check and index smi checks and attach a copy of the |
| 226 // original environment because the operation can still deoptimize. |
| 227 AddCheckClass(instr, comp, array->CopyValue()); |
| 228 InsertBefore(instr, |
| 229 new CheckSmiComp(index->CopyValue(), comp), |
| 230 instr->env(), |
| 231 BindInstr::kUnused); |
| 226 Computation* array_op = NULL; | 232 Computation* array_op = NULL; |
| 227 if (op_kind == Token::kINDEX) { | 233 if (op_kind == Token::kINDEX) { |
| 228 array_op = new LoadIndexedComp(comp->ArgumentAt(0)->value(), | 234 array_op = new LoadIndexedComp(array, index, class_id, comp); |
| 229 comp->ArgumentAt(1)->value(), | |
| 230 class_id, | |
| 231 comp); | |
| 232 } else { | 235 } else { |
| 233 array_op = new StoreIndexedComp(comp->ArgumentAt(0)->value(), | 236 Value* value = comp->ArgumentAt(2)->value(); |
| 234 comp->ArgumentAt(1)->value(), | 237 array_op = new StoreIndexedComp(array, index, value, class_id, comp); |
| 235 comp->ArgumentAt(2)->value(), | |
| 236 class_id, | |
| 237 comp); | |
| 238 } | 238 } |
| 239 array_op->set_ic_data(comp->ic_data()); | 239 array_op->set_ic_data(comp->ic_data()); |
| 240 instr->set_computation(array_op); | 240 instr->set_computation(array_op); |
| 241 RemovePushArguments(comp); | 241 RemovePushArguments(comp); |
| 242 return true; | 242 return true; |
| 243 } | 243 } |
| 244 default: | 244 default: |
| 245 return false; | 245 return false; |
| 246 } | 246 } |
| 247 } | 247 } |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 // TODO(srdjan): Implement for mutiple targets. | 465 // TODO(srdjan): Implement for mutiple targets. |
| 466 return false; | 466 return false; |
| 467 } | 467 } |
| 468 // Inline implicit instance getter. | 468 // Inline implicit instance getter. |
| 469 const String& field_name = | 469 const String& field_name = |
| 470 String::Handle(Field::NameFromGetter(comp->function_name())); | 470 String::Handle(Field::NameFromGetter(comp->function_name())); |
| 471 const Field& field = Field::Handle(GetField(class_ids[0], field_name)); | 471 const Field& field = Field::Handle(GetField(class_ids[0], field_name)); |
| 472 ASSERT(!field.IsNull()); | 472 ASSERT(!field.IsNull()); |
| 473 | 473 |
| 474 AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->CopyValue()); | 474 AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->CopyValue()); |
| 475 // Detach environment from the original instruction because it can't |
| 476 // deoptimize. |
| 477 instr->set_env(NULL); |
| 475 LoadInstanceFieldComp* load = | 478 LoadInstanceFieldComp* load = |
| 476 new LoadInstanceFieldComp(field, | 479 new LoadInstanceFieldComp(field, |
| 477 comp->ArgumentAt(0)->value(), | 480 comp->ArgumentAt(0)->value(), |
| 478 NULL); // Can not deoptimize. | 481 NULL); // Can not deoptimize. |
| 479 instr->set_computation(load); | 482 instr->set_computation(load); |
| 480 RemovePushArguments(comp); | 483 RemovePushArguments(comp); |
| 481 return true; | 484 return true; |
| 482 } | 485 } |
| 483 | 486 |
| 484 // Not an implicit getter. | 487 // Not an implicit getter. |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 // TODO(srdjan): Inline special setters. | 665 // TODO(srdjan): Inline special setters. |
| 663 return false; | 666 return false; |
| 664 } | 667 } |
| 665 // Inline implicit instance setter. | 668 // Inline implicit instance setter. |
| 666 const String& field_name = | 669 const String& field_name = |
| 667 String::Handle(Field::NameFromSetter(comp->function_name())); | 670 String::Handle(Field::NameFromSetter(comp->function_name())); |
| 668 const Field& field = Field::Handle(GetField(class_id, field_name)); | 671 const Field& field = Field::Handle(GetField(class_id, field_name)); |
| 669 ASSERT(!field.IsNull()); | 672 ASSERT(!field.IsNull()); |
| 670 | 673 |
| 671 AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->CopyValue()); | 674 AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->CopyValue()); |
| 675 // Detach environment from the original instruction because it can't |
| 676 // deoptimize. |
| 677 instr->set_env(NULL); |
| 672 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( | 678 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( |
| 673 field, | 679 field, |
| 674 comp->ArgumentAt(0)->value(), | 680 comp->ArgumentAt(0)->value(), |
| 675 comp->ArgumentAt(1)->value(), | 681 comp->ArgumentAt(1)->value(), |
| 676 NULL); // Can not deoptimize. | 682 NULL); // Can not deoptimize. |
| 677 instr->set_computation(store); | 683 instr->set_computation(store); |
| 678 RemovePushArguments(comp); | 684 RemovePushArguments(comp); |
| 679 return true; | 685 return true; |
| 680 } | 686 } |
| 681 | 687 |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 DirectChainedHashMap<BindInstr*> child_map(*map); // Copy map. | 1055 DirectChainedHashMap<BindInstr*> child_map(*map); // Copy map. |
| 1050 OptimizeRecursive(child, &child_map); | 1056 OptimizeRecursive(child, &child_map); |
| 1051 } else { | 1057 } else { |
| 1052 OptimizeRecursive(child, map); // Reuse map for the last child. | 1058 OptimizeRecursive(child, map); // Reuse map for the last child. |
| 1053 } | 1059 } |
| 1054 } | 1060 } |
| 1055 } | 1061 } |
| 1056 | 1062 |
| 1057 | 1063 |
| 1058 } // namespace dart | 1064 } // namespace dart |
| OLD | NEW |