| 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_builder.h" | 5 #include "vm/flow_graph_builder.h" |
| 6 | 6 |
| 7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
| 9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
| 10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 double scale_factor = static_cast<double>(call_->CallCount()) | 286 double scale_factor = static_cast<double>(call_->CallCount()) |
| 287 / static_cast<double>(caller_graph_->graph_entry()->entry_count()); | 287 / static_cast<double>(caller_graph_->graph_entry()->entry_count()); |
| 288 for (BlockIterator block_it = callee_graph->postorder_iterator(); | 288 for (BlockIterator block_it = callee_graph->postorder_iterator(); |
| 289 !block_it.Done(); | 289 !block_it.Done(); |
| 290 block_it.Advance()) { | 290 block_it.Advance()) { |
| 291 BlockEntryInstr* block = block_it.Current(); | 291 BlockEntryInstr* block = block_it.Current(); |
| 292 if (block->IsTargetEntry()) { | 292 if (block->IsTargetEntry()) { |
| 293 block->AsTargetEntry()->adjust_edge_weight(scale_factor); | 293 block->AsTargetEntry()->adjust_edge_weight(scale_factor); |
| 294 } | 294 } |
| 295 Instruction* instr = block; | 295 Instruction* instr = block; |
| 296 if (block->env() != NULL) { |
| 297 call_->env()->DeepCopyToOuter(callee_graph->isolate(), block); |
| 298 } |
| 296 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 299 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 297 instr = it.Current(); | 300 instr = it.Current(); |
| 298 // TODO(zerny): Avoid creating unnecessary environments. Note that some | 301 // TODO(zerny): Avoid creating unnecessary environments. Note that some |
| 299 // optimizations need deoptimization info for non-deoptable instructions, | 302 // optimizations need deoptimization info for non-deoptable instructions, |
| 300 // eg, LICM on GOTOs. | 303 // eg, LICM on GOTOs. |
| 301 if (instr->env() != NULL) { | 304 if (instr->env() != NULL) { |
| 302 call_->env()->DeepCopyToOuter(callee_graph->isolate(), instr); | 305 call_->env()->DeepCopyToOuter(callee_graph->isolate(), instr); |
| 303 } | 306 } |
| 304 } | 307 } |
| 305 if (instr->IsGoto()) { | 308 if (instr->IsGoto()) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 *exit_block = ExitBlockAt(0); | 354 *exit_block = ExitBlockAt(0); |
| 352 *last_instruction = LastInstructionAt(0); | 355 *last_instruction = LastInstructionAt(0); |
| 353 return call_->HasUses() ? ValueAt(0)->definition() : NULL; | 356 return call_->HasUses() ? ValueAt(0)->definition() : NULL; |
| 354 } else { | 357 } else { |
| 355 ASSERT(num_exits > 1); | 358 ASSERT(num_exits > 1); |
| 356 // Create a join of the returns. | 359 // Create a join of the returns. |
| 357 intptr_t join_id = caller_graph_->max_block_id() + 1; | 360 intptr_t join_id = caller_graph_->max_block_id() + 1; |
| 358 caller_graph_->set_max_block_id(join_id); | 361 caller_graph_->set_max_block_id(join_id); |
| 359 JoinEntryInstr* join = | 362 JoinEntryInstr* join = |
| 360 new(I) JoinEntryInstr(join_id, try_index); | 363 new(I) JoinEntryInstr(join_id, try_index); |
| 361 join->InheritDeoptTargetAfter(isolate(), call_); | |
| 362 | 364 |
| 363 // The dominator set of the join is the intersection of the dominator | 365 // The dominator set of the join is the intersection of the dominator |
| 364 // sets of all the predecessors. If we keep the dominator sets ordered | 366 // sets of all the predecessors. If we keep the dominator sets ordered |
| 365 // by height in the dominator tree, we can also get the immediate | 367 // by height in the dominator tree, we can also get the immediate |
| 366 // dominator of the join node from the intersection. | 368 // dominator of the join node from the intersection. |
| 367 // | 369 // |
| 368 // block_dominators is the dominator set for each block, ordered from | 370 // block_dominators is the dominator set for each block, ordered from |
| 369 // the immediate dominator to the root of the dominator tree. This is | 371 // the immediate dominator to the root of the dominator tree. This is |
| 370 // the order we collect them in (adding at the end). | 372 // the order we collect them in (adding at the end). |
| 371 // | 373 // |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 if (call_->HasUses()) { | 425 if (call_->HasUses()) { |
| 424 // Add a phi of the return values. | 426 // Add a phi of the return values. |
| 425 PhiInstr* phi = new(I) PhiInstr(join, num_exits); | 427 PhiInstr* phi = new(I) PhiInstr(join, num_exits); |
| 426 phi->set_ssa_temp_index(caller_graph_->alloc_ssa_temp_index()); | 428 phi->set_ssa_temp_index(caller_graph_->alloc_ssa_temp_index()); |
| 427 phi->mark_alive(); | 429 phi->mark_alive(); |
| 428 for (intptr_t i = 0; i < num_exits; ++i) { | 430 for (intptr_t i = 0; i < num_exits; ++i) { |
| 429 ReturnAt(i)->RemoveEnvironment(); | 431 ReturnAt(i)->RemoveEnvironment(); |
| 430 phi->SetInputAt(i, ValueAt(i)); | 432 phi->SetInputAt(i, ValueAt(i)); |
| 431 } | 433 } |
| 432 join->InsertPhi(phi); | 434 join->InsertPhi(phi); |
| 435 join->InheritDeoptTargetAfter(caller_graph_, call_, phi); |
| 433 return phi; | 436 return phi; |
| 434 } else { | 437 } else { |
| 435 // In the case that the result is unused, remove the return value uses | 438 // In the case that the result is unused, remove the return value uses |
| 436 // from their definition's use list. | 439 // from their definition's use list. |
| 437 for (intptr_t i = 0; i < num_exits; ++i) { | 440 for (intptr_t i = 0; i < num_exits; ++i) { |
| 438 ReturnAt(i)->UnuseAllInputs(); | 441 ReturnAt(i)->UnuseAllInputs(); |
| 439 } | 442 } |
| 443 join->InheritDeoptTargetAfter(caller_graph_, call_, NULL); |
| 440 return NULL; | 444 return NULL; |
| 441 } | 445 } |
| 442 } | 446 } |
| 443 } | 447 } |
| 444 | 448 |
| 445 | 449 |
| 446 void InlineExitCollector::ReplaceCall(TargetEntryInstr* callee_entry) { | 450 void InlineExitCollector::ReplaceCall(TargetEntryInstr* callee_entry) { |
| 447 ASSERT(call_->previous() != NULL); | 451 ASSERT(call_->previous() != NULL); |
| 448 ASSERT(call_->next() != NULL); | 452 ASSERT(call_->next() != NULL); |
| 449 BlockEntryInstr* call_block = call_->GetBlock(); | 453 BlockEntryInstr* call_block = call_->GetBlock(); |
| 450 | 454 |
| 451 // Insert the callee graph into the caller graph. | 455 // Insert the callee graph into the caller graph. |
| 452 BlockEntryInstr* callee_exit = NULL; | 456 BlockEntryInstr* callee_exit = NULL; |
| 453 Instruction* callee_last_instruction = NULL; | 457 Instruction* callee_last_instruction = NULL; |
| 454 | 458 |
| 455 if (exits_.length() == 0) { | 459 if (exits_.length() == 0) { |
| 456 // Handle the case when there are no normal return exits from the callee | 460 // Handle the case when there are no normal return exits from the callee |
| 457 // (i.e. the callee unconditionally throws) by inserting an artificial | 461 // (i.e. the callee unconditionally throws) by inserting an artificial |
| 458 // branch (true === true). | 462 // branch (true === true). |
| 459 // The true successor is the inlined body, the false successor | 463 // The true successor is the inlined body, the false successor |
| 460 // goes to the rest of the caller graph. It is removed as unreachable code | 464 // goes to the rest of the caller graph. It is removed as unreachable code |
| 461 // by the constant propagation. | 465 // by the constant propagation. |
| 462 TargetEntryInstr* false_block = | 466 TargetEntryInstr* false_block = |
| 463 new(I) TargetEntryInstr(caller_graph_->allocate_block_id(), | 467 new(I) TargetEntryInstr(caller_graph_->allocate_block_id(), |
| 464 call_block->try_index()); | 468 call_block->try_index()); |
| 465 false_block->InheritDeoptTargetAfter(isolate(), call_); | 469 false_block->InheritDeoptTargetAfter(caller_graph_, call_, NULL); |
| 466 false_block->LinkTo(call_->next()); | 470 false_block->LinkTo(call_->next()); |
| 467 call_block->ReplaceAsPredecessorWith(false_block); | 471 call_block->ReplaceAsPredecessorWith(false_block); |
| 468 | 472 |
| 469 ConstantInstr* true_const = caller_graph_->GetConstant(Bool::True()); | 473 ConstantInstr* true_const = caller_graph_->GetConstant(Bool::True()); |
| 470 BranchInstr* branch = | 474 BranchInstr* branch = |
| 471 new(I) BranchInstr( | 475 new(I) BranchInstr( |
| 472 new(I) StrictCompareInstr(call_block->start_pos(), | 476 new(I) StrictCompareInstr(call_block->start_pos(), |
| 473 Token::kEQ_STRICT, | 477 Token::kEQ_STRICT, |
| 474 new(I) Value(true_const), | 478 new(I) Value(true_const), |
| 475 new(I) Value(true_const), | 479 new(I) Value(true_const), |
| (...skipping 3827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4303 Report::MessageF(Report::kBailout, | 4307 Report::MessageF(Report::kBailout, |
| 4304 Script::Handle(function.script()), | 4308 Script::Handle(function.script()), |
| 4305 function.token_pos(), | 4309 function.token_pos(), |
| 4306 "FlowGraphBuilder Bailout: %s %s", | 4310 "FlowGraphBuilder Bailout: %s %s", |
| 4307 String::Handle(function.name()).ToCString(), | 4311 String::Handle(function.name()).ToCString(), |
| 4308 reason); | 4312 reason); |
| 4309 UNREACHABLE(); | 4313 UNREACHABLE(); |
| 4310 } | 4314 } |
| 4311 | 4315 |
| 4312 } // namespace dart | 4316 } // namespace dart |
| OLD | NEW |