| 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 OS::Print("Removing v%d.\n", instr->ssa_temp_index()); | 47 OS::Print("Removing v%d.\n", instr->ssa_temp_index()); |
| 48 } | 48 } |
| 49 it.RemoveCurrentFromGraph(); | 49 it.RemoveCurrentFromGraph(); |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 } | 52 } |
| 53 } | 53 } |
| 54 } | 54 } |
| 55 | 55 |
| 56 | 56 |
| 57 static Computation* CreateConversion(Representation from, |
| 58 Representation to, |
| 59 Definition* def, |
| 60 Instruction* deopt_target) { |
| 61 if ((from == kUnboxedDouble) && (to == kTagged)) { |
| 62 return new BoxDoubleComp(new Value(def), NULL); |
| 63 } else if ((from == kTagged) && (to == kUnboxedDouble)) { |
| 64 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 65 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 66 ASSERT((deopt_target != NULL) || (def->GetPropagatedCid() == kDoubleCid)); |
| 67 return new UnboxDoubleComp(new Value(def), deopt_id); |
| 68 } else { |
| 69 UNREACHABLE(); |
| 70 return NULL; |
| 71 } |
| 72 } |
| 73 |
| 74 |
| 75 void FlowGraphOptimizer::InsertConversionsFor(Definition* def) { |
| 76 const Representation from_rep = def->representation(); |
| 77 |
| 78 for (Value* use = def->input_use_list(); |
| 79 use != NULL; |
| 80 use = use->next_use()) { |
| 81 const Representation to_rep = |
| 82 use->instruction()->RequiredInputRepresentation(use->use_index()); |
| 83 if (from_rep == to_rep) { |
| 84 continue; |
| 85 } |
| 86 |
| 87 Instruction* deopt_target = NULL; |
| 88 Instruction* instr = use->instruction(); |
| 89 if (instr->IsPhi()) { |
| 90 if (!instr->AsPhi()->is_alive()) continue; |
| 91 |
| 92 // For phis conversions have to be inserted in the predecessor. |
| 93 const BlockEntryInstr* pred = |
| 94 instr->AsPhi()->block()->PredecessorAt(use->use_index()); |
| 95 instr = pred->last_instruction(); |
| 96 } else { |
| 97 deopt_target = instr; |
| 98 } |
| 99 |
| 100 BindInstr* converted = InsertBefore( |
| 101 instr, |
| 102 CreateConversion(from_rep, to_rep, def, deopt_target), |
| 103 use->instruction()->env(), |
| 104 BindInstr::kUsed); |
| 105 |
| 106 use->set_definition(converted); |
| 107 } |
| 108 } |
| 109 |
| 110 void FlowGraphOptimizer::SelectRepresentations() { |
| 111 // Convervatively unbox all phis that were proven to be of type Double. |
| 112 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 113 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); |
| 114 if (join_entry == NULL) continue; |
| 115 |
| 116 if (join_entry->phis() != NULL) { |
| 117 for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { |
| 118 PhiInstr* phi = (*join_entry->phis())[i]; |
| 119 if ((phi != NULL) && (phi->GetPropagatedCid() == kDoubleCid)) { |
| 120 phi->set_representation(kUnboxedDouble); |
| 121 } |
| 122 } |
| 123 } |
| 124 } |
| 125 |
| 126 // Process all instructions and insert conversions where needed. |
| 127 GraphEntryInstr* graph_entry = block_order_[0]->AsGraphEntry(); |
| 128 |
| 129 // Visit incoming parameters. |
| 130 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { |
| 131 Value* val = graph_entry->start_env()->values()[i]; |
| 132 InsertConversionsFor(val->definition()); |
| 133 } |
| 134 |
| 135 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 136 BlockEntryInstr* entry = block_order_[i]; |
| 137 |
| 138 JoinEntryInstr* join_entry = entry->AsJoinEntry(); |
| 139 if ((join_entry != NULL) && (join_entry->phis() != NULL)) { |
| 140 for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { |
| 141 PhiInstr* phi = (*join_entry->phis())[i]; |
| 142 if ((phi != NULL) && (phi->is_alive())) { |
| 143 InsertConversionsFor(phi); |
| 144 } |
| 145 } |
| 146 } |
| 147 |
| 148 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 149 Definition* def = it.Current()->AsDefinition(); |
| 150 if (def != NULL) { |
| 151 InsertConversionsFor(def); |
| 152 } |
| 153 } |
| 154 } |
| 155 } |
| 156 |
| 157 |
| 57 static bool ICDataHasReceiverClassId(const ICData& ic_data, intptr_t class_id) { | 158 static bool ICDataHasReceiverClassId(const ICData& ic_data, intptr_t class_id) { |
| 58 ASSERT(ic_data.num_args_tested() > 0); | 159 ASSERT(ic_data.num_args_tested() > 0); |
| 59 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 160 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 60 const intptr_t test_class_id = ic_data.GetReceiverClassIdAt(i); | 161 const intptr_t test_class_id = ic_data.GetReceiverClassIdAt(i); |
| 61 if (test_class_id == class_id) { | 162 if (test_class_id == class_id) { |
| 62 return true; | 163 return true; |
| 63 } | 164 } |
| 64 } | 165 } |
| 65 return false; | 166 return false; |
| 66 } | 167 } |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 | 435 |
| 335 ASSERT(comp->ArgumentCount() == 2); | 436 ASSERT(comp->ArgumentCount() == 2); |
| 336 if (operands_type == kDoubleCid) { | 437 if (operands_type == kDoubleCid) { |
| 337 if (FLAG_use_unboxed_doubles) { | 438 if (FLAG_use_unboxed_doubles) { |
| 338 Value* left = comp->ArgumentAt(0)->value(); | 439 Value* left = comp->ArgumentAt(0)->value(); |
| 339 Value* right = comp->ArgumentAt(1)->value(); | 440 Value* right = comp->ArgumentAt(1)->value(); |
| 340 | 441 |
| 341 // Check that either left or right are not a smi. Result or a | 442 // Check that either left or right are not a smi. Result or a |
| 342 // binary operation with two smis is a smi not a double. | 443 // binary operation with two smis is a smi not a double. |
| 343 InsertBefore(instr, | 444 InsertBefore(instr, |
| 344 new CheckEitherNonSmiComp(left, right, comp), | 445 new CheckEitherNonSmiComp(left->Copy(), |
| 446 right->Copy(), |
| 447 comp), |
| 345 instr->env(), | 448 instr->env(), |
| 346 BindInstr::kUnused); | 449 BindInstr::kUnused); |
| 347 | 450 |
| 348 // Unbox operands. | |
| 349 BindInstr* unbox_left = InsertBefore( | |
| 350 instr, | |
| 351 new UnboxDoubleComp(left->Copy(), comp), | |
| 352 instr->env(), | |
| 353 BindInstr::kUsed); | |
| 354 BindInstr* unbox_right = InsertBefore( | |
| 355 instr, | |
| 356 new UnboxDoubleComp(right->Copy(), comp), | |
| 357 instr->env(), | |
| 358 BindInstr::kUsed); | |
| 359 | |
| 360 UnboxedDoubleBinaryOpComp* double_bin_op = | 451 UnboxedDoubleBinaryOpComp* double_bin_op = |
| 361 new UnboxedDoubleBinaryOpComp(op_kind, | 452 new UnboxedDoubleBinaryOpComp(op_kind, |
| 362 new Value(unbox_left), | 453 left->Copy(), |
| 363 new Value(unbox_right)); | 454 right->Copy(), |
| 455 comp); |
| 364 double_bin_op->set_ic_data(comp->ic_data()); | 456 double_bin_op->set_ic_data(comp->ic_data()); |
| 365 instr->set_computation(double_bin_op); | 457 instr->set_computation(double_bin_op); |
| 366 | 458 |
| 367 if (instr->is_used()) { | |
| 368 // Box result. | |
| 369 Value* value = new Value(instr); | |
| 370 BindInstr* bind = InsertAfter(instr, | |
| 371 new BoxDoubleComp(value, comp), | |
| 372 NULL, | |
| 373 BindInstr::kUsed); | |
| 374 instr->ReplaceUsesWith(bind); | |
| 375 } | |
| 376 | |
| 377 RemovePushArguments(comp); | 459 RemovePushArguments(comp); |
| 378 } else { | 460 } else { |
| 379 BinaryDoubleOpComp* double_bin_op = new BinaryDoubleOpComp(op_kind, comp); | 461 BinaryDoubleOpComp* double_bin_op = new BinaryDoubleOpComp(op_kind, comp); |
| 380 double_bin_op->set_ic_data(comp->ic_data()); | 462 double_bin_op->set_ic_data(comp->ic_data()); |
| 381 instr->set_computation(double_bin_op); | 463 instr->set_computation(double_bin_op); |
| 382 } | 464 } |
| 383 } else if (operands_type == kMintCid) { | 465 } else if (operands_type == kMintCid) { |
| 384 Value* left = comp->ArgumentAt(0)->value(); | 466 Value* left = comp->ArgumentAt(0)->value(); |
| 385 Value* right = comp->ArgumentAt(1)->value(); | 467 Value* right = comp->ArgumentAt(1)->value(); |
| 386 BinaryMintOpComp* bin_op = new BinaryMintOpComp(op_kind, | 468 BinaryMintOpComp* bin_op = new BinaryMintOpComp(op_kind, |
| (...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1066 DirectChainedHashMap<BindInstr*> child_map(*map); // Copy map. | 1148 DirectChainedHashMap<BindInstr*> child_map(*map); // Copy map. |
| 1067 OptimizeRecursive(child, &child_map); | 1149 OptimizeRecursive(child, &child_map); |
| 1068 } else { | 1150 } else { |
| 1069 OptimizeRecursive(child, map); // Reuse map for the last child. | 1151 OptimizeRecursive(child, map); // Reuse map for the last child. |
| 1070 } | 1152 } |
| 1071 } | 1153 } |
| 1072 } | 1154 } |
| 1073 | 1155 |
| 1074 | 1156 |
| 1075 } // namespace dart | 1157 } // namespace dart |
| OLD | NEW |