| 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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/flow_graph_optimizer.h" |
| 12 #include "vm/locations.h" | 13 #include "vm/locations.h" |
| 13 #include "vm/object.h" | 14 #include "vm/object.h" |
| 14 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
| 15 #include "vm/os.h" | 16 #include "vm/os.h" |
| 16 #include "vm/scopes.h" | 17 #include "vm/scopes.h" |
| 17 #include "vm/stub_code.h" | 18 #include "vm/stub_code.h" |
| 18 #include "vm/symbols.h" | 19 #include "vm/symbols.h" |
| 19 | 20 |
| 20 namespace dart { | 21 namespace dart { |
| 21 | 22 |
| 22 DECLARE_FLAG(bool, enable_type_checks); | 23 DECLARE_FLAG(bool, enable_type_checks); |
| 23 | 24 |
| 24 | 25 |
| 26 Definition::Definition() |
| 27 : temp_index_(-1), |
| 28 ssa_temp_index_(-1), |
| 29 propagated_type_(AbstractType::Handle()), |
| 30 propagated_cid_(kIllegalCid), |
| 31 input_use_list_(NULL), |
| 32 env_use_list_(NULL), |
| 33 use_kind_(kValue), // Phis and parameters rely on this default. |
| 34 constant_value_(Object::ZoneHandle(ConstantPropagator::Unknown())) { |
| 35 } |
| 36 |
| 37 |
| 25 intptr_t Definition::Hashcode() const { | 38 intptr_t Definition::Hashcode() const { |
| 26 intptr_t result = tag(); | 39 intptr_t result = tag(); |
| 27 for (intptr_t i = 0; i < InputCount(); ++i) { | 40 for (intptr_t i = 0; i < InputCount(); ++i) { |
| 28 Value* value = InputAt(i); | 41 Value* value = InputAt(i); |
| 29 intptr_t j = value->definition()->ssa_temp_index(); | 42 intptr_t j = value->definition()->ssa_temp_index(); |
| 30 result = result * 31 + j; | 43 result = result * 31 + j; |
| 31 } | 44 } |
| 32 return result; | 45 return result; |
| 33 } | 46 } |
| 34 | 47 |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 | 428 |
| 416 | 429 |
| 417 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { | 430 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { |
| 418 for (intptr_t i = 0; i < predecessors_.length(); ++i) { | 431 for (intptr_t i = 0; i < predecessors_.length(); ++i) { |
| 419 if (predecessors_[i] == pred) return i; | 432 if (predecessors_[i] == pred) return i; |
| 420 } | 433 } |
| 421 return -1; | 434 return -1; |
| 422 } | 435 } |
| 423 | 436 |
| 424 | 437 |
| 438 void JoinEntryInstr::EliminateUnreachablePhiInputs() { |
| 439 if (phis_ == NULL || phis_->is_empty()) return; |
| 440 |
| 441 // Loop over the predecessors, reorganize phi inputs. |
| 442 // TODO(kmillikin): Replace phis that have a single remaining input with |
| 443 // the input. This requires being a bit careful about use lists. |
| 444 intptr_t input_count = predecessors_.length(); |
| 445 for (intptr_t new_idx = 0; new_idx < input_count; ++new_idx) { |
| 446 BlockEntryInstr* pred = predecessors_[new_idx]; |
| 447 // Linear search for the old predecessor index. We can't directly |
| 448 // compare block entries, because unreachable code elimination has |
| 449 // replaced some targets with joins. |
| 450 intptr_t old_idx = 0; |
| 451 for (; old_idx < stale_predecessors_.length(); ++old_idx) { |
| 452 if (stale_predecessors_[old_idx]->next() == pred->next()) break; |
| 453 } |
| 454 ASSERT(old_idx < stale_predecessors_.length()); |
| 455 // If the index has changed, adjust all phi inputs. |
| 456 if (old_idx != new_idx) { |
| 457 ASSERT(new_idx < old_idx); |
| 458 // Swap each phi's inputs so the input at new_idx is correct. |
| 459 // Preserve the previous value in case it is from a reachable |
| 460 // predecessor. |
| 461 for (intptr_t phi_idx = 0; phi_idx < phis_->length(); ++phi_idx) { |
| 462 PhiInstr* phi = (*phis_)[phi_idx]; |
| 463 if (phi == NULL) continue; |
| 464 Value* temp = phi->InputAt(new_idx); |
| 465 phi->SetInputAt(new_idx, phi->InputAt(old_idx)); |
| 466 phi->SetInputAt(old_idx, temp); |
| 467 } |
| 468 // The old input at new_idx is now found at old_idx. It may be a |
| 469 // reachable predecessor so swap the old predecessors too. |
| 470 BlockEntryInstr* temp = stale_predecessors_[new_idx]; |
| 471 stale_predecessors_[new_idx] = stale_predecessors_[old_idx]; |
| 472 stale_predecessors_[old_idx] = temp; |
| 473 } |
| 474 } |
| 475 // Now truncate each phi if necessary. |
| 476 if (input_count < stale_predecessors_.length()) { |
| 477 for (intptr_t phi_idx = 0; phi_idx < phis_->length(); ++phi_idx) { |
| 478 PhiInstr* phi = (*phis_)[phi_idx]; |
| 479 if (phi == NULL) continue; |
| 480 phi->inputs_.TruncateTo(input_count); |
| 481 } |
| 482 } |
| 483 } |
| 484 |
| 485 |
| 425 // ==== Recording assigned variables. | 486 // ==== Recording assigned variables. |
| 426 void Definition::RecordAssignedVars(BitVector* assigned_vars, | 487 void Definition::RecordAssignedVars(BitVector* assigned_vars, |
| 427 intptr_t fixed_parameter_count) { | 488 intptr_t fixed_parameter_count) { |
| 428 // Nothing to do for the base class. | 489 // Nothing to do for the base class. |
| 429 } | 490 } |
| 430 | 491 |
| 431 | 492 |
| 432 void StoreLocalInstr::RecordAssignedVars(BitVector* assigned_vars, | 493 void StoreLocalInstr::RecordAssignedVars(BitVector* assigned_vars, |
| 433 intptr_t fixed_parameter_count) { | 494 intptr_t fixed_parameter_count) { |
| 434 if (!local().is_captured()) { | 495 if (!local().is_captured()) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 return propagated_cid(); | 585 return propagated_cid(); |
| 525 } | 586 } |
| 526 | 587 |
| 527 | 588 |
| 528 intptr_t ParameterInstr::GetPropagatedCid() { | 589 intptr_t ParameterInstr::GetPropagatedCid() { |
| 529 return propagated_cid(); | 590 return propagated_cid(); |
| 530 } | 591 } |
| 531 | 592 |
| 532 | 593 |
| 533 // ==== Postorder graph traversal. | 594 // ==== Postorder graph traversal. |
| 595 static bool IsMarked(BlockEntryInstr* block, |
| 596 GrowableArray<BlockEntryInstr*>* preorder) { |
| 597 // Detect that a block has been visited as part of the current |
| 598 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block |
| 599 // will be 'marked' by (1) having a preorder number in the range of the |
| 600 // preorder array and (2) being in the preorder array at that index. |
| 601 intptr_t i = block->preorder_number(); |
| 602 return (i >= 0) && (i < preorder->length()) && ((*preorder)[i] == block); |
| 603 } |
| 604 |
| 605 |
| 534 void GraphEntryInstr::DiscoverBlocks( | 606 void GraphEntryInstr::DiscoverBlocks( |
| 535 BlockEntryInstr* current_block, | 607 BlockEntryInstr* current_block, |
| 536 GrowableArray<BlockEntryInstr*>* preorder, | 608 GrowableArray<BlockEntryInstr*>* preorder, |
| 537 GrowableArray<BlockEntryInstr*>* postorder, | 609 GrowableArray<BlockEntryInstr*>* postorder, |
| 538 GrowableArray<intptr_t>* parent, | 610 GrowableArray<intptr_t>* parent, |
| 539 GrowableArray<BitVector*>* assigned_vars, | 611 GrowableArray<BitVector*>* assigned_vars, |
| 540 intptr_t variable_count, | 612 intptr_t variable_count, |
| 541 intptr_t fixed_parameter_count) { | 613 intptr_t fixed_parameter_count) { |
| 542 // We only visit this block once, first of all blocks. | 614 // We only visit this block once, first of all blocks. |
| 543 ASSERT(preorder_number() == -1); | 615 ASSERT(!IsMarked(this, preorder)); |
| 544 ASSERT(current_block == NULL); | 616 ASSERT(current_block == NULL); |
| 545 ASSERT(preorder->is_empty()); | 617 ASSERT(preorder->is_empty()); |
| 546 ASSERT(postorder->is_empty()); | 618 ASSERT(postorder->is_empty()); |
| 547 ASSERT(parent->is_empty()); | 619 ASSERT(parent->is_empty()); |
| 548 | 620 |
| 549 // This node has no parent, indicated by -1. The preorder number is 0. | 621 // This node has no parent, indicated by -1. The preorder number is 0. |
| 550 parent->Add(-1); | 622 parent->Add(-1); |
| 551 set_preorder_number(0); | 623 set_preorder_number(0); |
| 552 preorder->Add(this); | 624 preorder->Add(this); |
| 553 BitVector* vars = | 625 BitVector* vars = |
| (...skipping 27 matching lines...) Expand all Loading... |
| 581 GrowableArray<BlockEntryInstr*>* preorder, | 653 GrowableArray<BlockEntryInstr*>* preorder, |
| 582 GrowableArray<BlockEntryInstr*>* postorder, | 654 GrowableArray<BlockEntryInstr*>* postorder, |
| 583 GrowableArray<intptr_t>* parent, | 655 GrowableArray<intptr_t>* parent, |
| 584 GrowableArray<BitVector*>* assigned_vars, | 656 GrowableArray<BitVector*>* assigned_vars, |
| 585 intptr_t variable_count, | 657 intptr_t variable_count, |
| 586 intptr_t fixed_parameter_count) { | 658 intptr_t fixed_parameter_count) { |
| 587 // We have already visited the graph entry, so we can assume current_block | 659 // We have already visited the graph entry, so we can assume current_block |
| 588 // is non-null and preorder array is non-empty. | 660 // is non-null and preorder array is non-empty. |
| 589 ASSERT(current_block != NULL); | 661 ASSERT(current_block != NULL); |
| 590 ASSERT(!preorder->is_empty()); | 662 ASSERT(!preorder->is_empty()); |
| 663 // Blocks with a single predecessor cannot have been reached before. |
| 664 ASSERT(!IsTargetEntry() || !IsMarked(this, preorder)); |
| 591 | 665 |
| 592 // 1. Record control-flow-graph basic-block predecessors. | 666 // 1. If the block has already been reached, add current_block as a |
| 667 // basic-block predecessor and we are done. |
| 668 if (IsMarked(this, preorder)) { |
| 669 AddPredecessor(current_block); |
| 670 return; |
| 671 } |
| 672 |
| 673 // 2. Otherwise, clear the predecessors which might have been computed on |
| 674 // some earlier call to DiscoverBlocks and record this predecessor. For |
| 675 // joins save the original predecessors, if any, so we can garbage collect |
| 676 // phi inputs from unreachable predecessors without recomputing SSA. |
| 677 ClearPredecessors(); |
| 593 AddPredecessor(current_block); | 678 AddPredecessor(current_block); |
| 594 | 679 |
| 595 // 2. If the block has already been reached by the traversal, we are | |
| 596 // done. Blocks with a single predecessor cannot have been reached | |
| 597 // before. | |
| 598 ASSERT(!IsTargetEntry() || (preorder_number() == -1)); | |
| 599 if (preorder_number() >= 0) return; | |
| 600 | |
| 601 // 3. The current block is the spanning-tree parent. | 680 // 3. The current block is the spanning-tree parent. |
| 602 parent->Add(current_block->preorder_number()); | 681 parent->Add(current_block->preorder_number()); |
| 603 | 682 |
| 604 // 4. Assign preorder number and add the block entry to the list. | 683 // 4. Assign preorder number and add the block entry to the list. |
| 605 // Allocate an empty set of assigned variables for the block. | 684 // Allocate an empty set of assigned variables for the block. |
| 606 set_preorder_number(preorder->length()); | 685 set_preorder_number(preorder->length()); |
| 607 preorder->Add(this); | 686 preorder->Add(this); |
| 608 BitVector* vars = | 687 BitVector* vars = |
| 609 (variable_count == 0) ? NULL : new BitVector(variable_count); | 688 (variable_count == 0) ? NULL : new BitVector(variable_count); |
| 610 assigned_vars->Add(vars); | 689 assigned_vars->Add(vars); |
| (...skipping 1081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1692 value->set_use_index(use_index++); | 1771 value->set_use_index(use_index++); |
| 1693 value->AddToEnvUseList(); | 1772 value->AddToEnvUseList(); |
| 1694 } | 1773 } |
| 1695 instr->set_env(copy); | 1774 instr->set_env(copy); |
| 1696 } | 1775 } |
| 1697 | 1776 |
| 1698 | 1777 |
| 1699 #undef __ | 1778 #undef __ |
| 1700 | 1779 |
| 1701 } // namespace dart | 1780 } // namespace dart |
| OLD | NEW |