| 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" | |
| 13 #include "vm/locations.h" | 12 #include "vm/locations.h" |
| 14 #include "vm/object.h" | 13 #include "vm/object.h" |
| 15 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 16 #include "vm/os.h" | 15 #include "vm/os.h" |
| 17 #include "vm/scopes.h" | 16 #include "vm/scopes.h" |
| 18 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
| 19 #include "vm/symbols.h" | 18 #include "vm/symbols.h" |
| 20 | 19 |
| 21 namespace dart { | 20 namespace dart { |
| 22 | 21 |
| 23 DECLARE_FLAG(bool, enable_type_checks); | 22 DECLARE_FLAG(bool, enable_type_checks); |
| 24 | 23 |
| 25 | 24 |
| 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 | |
| 38 intptr_t Definition::Hashcode() const { | 25 intptr_t Definition::Hashcode() const { |
| 39 intptr_t result = tag(); | 26 intptr_t result = tag(); |
| 40 for (intptr_t i = 0; i < InputCount(); ++i) { | 27 for (intptr_t i = 0; i < InputCount(); ++i) { |
| 41 Value* value = InputAt(i); | 28 Value* value = InputAt(i); |
| 42 intptr_t j = value->definition()->ssa_temp_index(); | 29 intptr_t j = value->definition()->ssa_temp_index(); |
| 43 result = result * 31 + j; | 30 result = result * 31 + j; |
| 44 } | 31 } |
| 45 return result; | 32 return result; |
| 46 } | 33 } |
| 47 | 34 |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 | 462 |
| 476 | 463 |
| 477 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { | 464 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { |
| 478 for (intptr_t i = 0; i < predecessors_.length(); ++i) { | 465 for (intptr_t i = 0; i < predecessors_.length(); ++i) { |
| 479 if (predecessors_[i] == pred) return i; | 466 if (predecessors_[i] == pred) return i; |
| 480 } | 467 } |
| 481 return -1; | 468 return -1; |
| 482 } | 469 } |
| 483 | 470 |
| 484 | 471 |
| 485 void JoinEntryInstr::EliminateUnreachablePhiInputs() { | |
| 486 if (phis_ == NULL || phis_->is_empty()) return; | |
| 487 | |
| 488 // Loop over the predecessors, reorganize phi inputs. | |
| 489 // TODO(kmillikin): Replace phis that have a single remaining input with | |
| 490 // the input. This requires being a bit careful about use lists. | |
| 491 intptr_t input_count = predecessors_.length(); | |
| 492 for (intptr_t new_idx = 0; new_idx < input_count; ++new_idx) { | |
| 493 BlockEntryInstr* pred = predecessors_[new_idx]; | |
| 494 // Linear search for the old predecessor index. We can't directly | |
| 495 // compare block entries, because unreachable code elimination has | |
| 496 // replaced some targets with joins. | |
| 497 intptr_t old_idx = 0; | |
| 498 for (; old_idx < stale_predecessors_.length(); ++old_idx) { | |
| 499 if (stale_predecessors_[old_idx]->next() == pred->next()) break; | |
| 500 } | |
| 501 ASSERT(old_idx < stale_predecessors_.length()); | |
| 502 // If the index has changed, adjust all phi inputs. | |
| 503 if (old_idx != new_idx) { | |
| 504 ASSERT(new_idx < old_idx); | |
| 505 // Swap each phi's inputs so the input at new_idx is correct. | |
| 506 // Preserve the previous value in case it is from a reachable | |
| 507 // predecessor. | |
| 508 for (intptr_t phi_idx = 0; phi_idx < phis_->length(); ++phi_idx) { | |
| 509 PhiInstr* phi = (*phis_)[phi_idx]; | |
| 510 if (phi == NULL) continue; | |
| 511 Value* temp = phi->InputAt(new_idx); | |
| 512 phi->SetInputAt(new_idx, phi->InputAt(old_idx)); | |
| 513 phi->SetInputAt(old_idx, temp); | |
| 514 } | |
| 515 // The old input at new_idx is now found at old_idx. It may be a | |
| 516 // reachable predecessor so swap the old predecessors too. | |
| 517 BlockEntryInstr* temp = stale_predecessors_[new_idx]; | |
| 518 stale_predecessors_[new_idx] = stale_predecessors_[old_idx]; | |
| 519 stale_predecessors_[old_idx] = temp; | |
| 520 } | |
| 521 } | |
| 522 // Now truncate each phi if necessary. | |
| 523 if (input_count < stale_predecessors_.length()) { | |
| 524 for (intptr_t phi_idx = 0; phi_idx < phis_->length(); ++phi_idx) { | |
| 525 PhiInstr* phi = (*phis_)[phi_idx]; | |
| 526 if (phi == NULL) continue; | |
| 527 phi->inputs_.TruncateTo(input_count); | |
| 528 } | |
| 529 } | |
| 530 } | |
| 531 | |
| 532 | |
| 533 // ==== Recording assigned variables. | 472 // ==== Recording assigned variables. |
| 534 void Definition::RecordAssignedVars(BitVector* assigned_vars, | 473 void Definition::RecordAssignedVars(BitVector* assigned_vars, |
| 535 intptr_t fixed_parameter_count) { | 474 intptr_t fixed_parameter_count) { |
| 536 // Nothing to do for the base class. | 475 // Nothing to do for the base class. |
| 537 } | 476 } |
| 538 | 477 |
| 539 | 478 |
| 540 void StoreLocalInstr::RecordAssignedVars(BitVector* assigned_vars, | 479 void StoreLocalInstr::RecordAssignedVars(BitVector* assigned_vars, |
| 541 intptr_t fixed_parameter_count) { | 480 intptr_t fixed_parameter_count) { |
| 542 if (!local().is_captured()) { | 481 if (!local().is_captured()) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 return propagated_cid(); | 571 return propagated_cid(); |
| 633 } | 572 } |
| 634 | 573 |
| 635 | 574 |
| 636 intptr_t ParameterInstr::GetPropagatedCid() { | 575 intptr_t ParameterInstr::GetPropagatedCid() { |
| 637 return propagated_cid(); | 576 return propagated_cid(); |
| 638 } | 577 } |
| 639 | 578 |
| 640 | 579 |
| 641 // ==== Postorder graph traversal. | 580 // ==== Postorder graph traversal. |
| 642 static bool IsMarked(BlockEntryInstr* block, | |
| 643 GrowableArray<BlockEntryInstr*>* preorder) { | |
| 644 // Detect that a block has been visited as part of the current | |
| 645 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block | |
| 646 // will be 'marked' by (1) having a preorder number in the range of the | |
| 647 // preorder array and (2) being in the preorder array at that index. | |
| 648 intptr_t i = block->preorder_number(); | |
| 649 return (i >= 0) && (i < preorder->length()) && ((*preorder)[i] == block); | |
| 650 } | |
| 651 | |
| 652 | |
| 653 void GraphEntryInstr::DiscoverBlocks( | 581 void GraphEntryInstr::DiscoverBlocks( |
| 654 BlockEntryInstr* current_block, | 582 BlockEntryInstr* current_block, |
| 655 GrowableArray<BlockEntryInstr*>* preorder, | 583 GrowableArray<BlockEntryInstr*>* preorder, |
| 656 GrowableArray<BlockEntryInstr*>* postorder, | 584 GrowableArray<BlockEntryInstr*>* postorder, |
| 657 GrowableArray<intptr_t>* parent, | 585 GrowableArray<intptr_t>* parent, |
| 658 GrowableArray<BitVector*>* assigned_vars, | 586 GrowableArray<BitVector*>* assigned_vars, |
| 659 intptr_t variable_count, | 587 intptr_t variable_count, |
| 660 intptr_t fixed_parameter_count) { | 588 intptr_t fixed_parameter_count) { |
| 661 // We only visit this block once, first of all blocks. | 589 // We only visit this block once, first of all blocks. |
| 662 ASSERT(!IsMarked(this, preorder)); | 590 ASSERT(preorder_number() == -1); |
| 663 ASSERT(current_block == NULL); | 591 ASSERT(current_block == NULL); |
| 664 ASSERT(preorder->is_empty()); | 592 ASSERT(preorder->is_empty()); |
| 665 ASSERT(postorder->is_empty()); | 593 ASSERT(postorder->is_empty()); |
| 666 ASSERT(parent->is_empty()); | 594 ASSERT(parent->is_empty()); |
| 667 | 595 |
| 668 // This node has no parent, indicated by -1. The preorder number is 0. | 596 // This node has no parent, indicated by -1. The preorder number is 0. |
| 669 parent->Add(-1); | 597 parent->Add(-1); |
| 670 set_preorder_number(0); | 598 set_preorder_number(0); |
| 671 preorder->Add(this); | 599 preorder->Add(this); |
| 672 BitVector* vars = | 600 BitVector* vars = |
| (...skipping 27 matching lines...) Expand all Loading... |
| 700 GrowableArray<BlockEntryInstr*>* preorder, | 628 GrowableArray<BlockEntryInstr*>* preorder, |
| 701 GrowableArray<BlockEntryInstr*>* postorder, | 629 GrowableArray<BlockEntryInstr*>* postorder, |
| 702 GrowableArray<intptr_t>* parent, | 630 GrowableArray<intptr_t>* parent, |
| 703 GrowableArray<BitVector*>* assigned_vars, | 631 GrowableArray<BitVector*>* assigned_vars, |
| 704 intptr_t variable_count, | 632 intptr_t variable_count, |
| 705 intptr_t fixed_parameter_count) { | 633 intptr_t fixed_parameter_count) { |
| 706 // We have already visited the graph entry, so we can assume current_block | 634 // We have already visited the graph entry, so we can assume current_block |
| 707 // is non-null and preorder array is non-empty. | 635 // is non-null and preorder array is non-empty. |
| 708 ASSERT(current_block != NULL); | 636 ASSERT(current_block != NULL); |
| 709 ASSERT(!preorder->is_empty()); | 637 ASSERT(!preorder->is_empty()); |
| 710 // Blocks with a single predecessor cannot have been reached before. | |
| 711 ASSERT(!IsTargetEntry() || !IsMarked(this, preorder)); | |
| 712 | 638 |
| 713 // 1. If the block has already been reached, add current_block as a | 639 // 1. Record control-flow-graph basic-block predecessors. |
| 714 // basic-block predecessor and we are done. | 640 AddPredecessor(current_block); |
| 715 if (IsMarked(this, preorder)) { | |
| 716 AddPredecessor(current_block); | |
| 717 return; | |
| 718 } | |
| 719 | 641 |
| 720 // 2. Otherwise, clear the predecessors which might have been computed on | 642 // 2. If the block has already been reached by the traversal, we are |
| 721 // some earlier call to DiscoverBlocks and record this predecessor. For | 643 // done. Blocks with a single predecessor cannot have been reached |
| 722 // joins save the original predecessors, if any, so we can garbage collect | 644 // before. |
| 723 // phi inputs from unreachable predecessors without recomputing SSA. | 645 ASSERT(!IsTargetEntry() || (preorder_number() == -1)); |
| 724 ClearPredecessors(); | 646 if (preorder_number() >= 0) return; |
| 725 AddPredecessor(current_block); | |
| 726 | 647 |
| 727 // 3. The current block is the spanning-tree parent. | 648 // 3. The current block is the spanning-tree parent. |
| 728 parent->Add(current_block->preorder_number()); | 649 parent->Add(current_block->preorder_number()); |
| 729 | 650 |
| 730 // 4. Assign preorder number and add the block entry to the list. | 651 // 4. Assign preorder number and add the block entry to the list. |
| 731 // Allocate an empty set of assigned variables for the block. | 652 // Allocate an empty set of assigned variables for the block. |
| 732 set_preorder_number(preorder->length()); | 653 set_preorder_number(preorder->length()); |
| 733 preorder->Add(this); | 654 preorder->Add(this); |
| 734 BitVector* vars = | 655 BitVector* vars = |
| 735 (variable_count == 0) ? NULL : new BitVector(variable_count); | 656 (variable_count == 0) ? NULL : new BitVector(variable_count); |
| (...skipping 1091 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1827 value->set_use_index(use_index++); | 1748 value->set_use_index(use_index++); |
| 1828 value->AddToEnvUseList(); | 1749 value->AddToEnvUseList(); |
| 1829 } | 1750 } |
| 1830 instr->env()->outer_ = copy; | 1751 instr->env()->outer_ = copy; |
| 1831 } | 1752 } |
| 1832 | 1753 |
| 1833 | 1754 |
| 1834 #undef __ | 1755 #undef __ |
| 1835 | 1756 |
| 1836 } // namespace dart | 1757 } // namespace dart |
| OLD | NEW |