| 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 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 | 482 |
| 470 | 483 |
| 471 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { | 484 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { |
| 472 for (intptr_t i = 0; i < predecessors_.length(); ++i) { | 485 for (intptr_t i = 0; i < predecessors_.length(); ++i) { |
| 473 if (predecessors_[i] == pred) return i; | 486 if (predecessors_[i] == pred) return i; |
| 474 } | 487 } |
| 475 return -1; | 488 return -1; |
| 476 } | 489 } |
| 477 | 490 |
| 478 | 491 |
| 492 void JoinEntryInstr::EliminateUnreachablePhiInputs() { |
| 493 if (phis_ == NULL || phis_->is_empty()) return; |
| 494 |
| 495 // Loop over the predecessors, reorganize phi inputs. |
| 496 // TODO(kmillikin): Replace phis that have a single remaining input with |
| 497 // the input. This requires being a bit careful about use lists. |
| 498 intptr_t input_count = predecessors_.length(); |
| 499 for (intptr_t new_idx = 0; new_idx < input_count; ++new_idx) { |
| 500 BlockEntryInstr* pred = predecessors_[new_idx]; |
| 501 // Linear search for the old predecessor index. We can't directly |
| 502 // compare block entries, because unreachable code elimination has |
| 503 // replaced some targets with joins. |
| 504 intptr_t old_idx = 0; |
| 505 for (; old_idx < stale_predecessors_.length(); ++old_idx) { |
| 506 if (stale_predecessors_[old_idx]->next() == pred->next()) break; |
| 507 } |
| 508 ASSERT(old_idx < stale_predecessors_.length()); |
| 509 // If the index has changed, adjust all phi inputs. |
| 510 if (old_idx != new_idx) { |
| 511 ASSERT(new_idx < old_idx); |
| 512 // Swap each phi's inputs so the input at new_idx is correct. |
| 513 // Preserve the previous value in case it is from a reachable |
| 514 // predecessor. |
| 515 for (intptr_t phi_idx = 0; phi_idx < phis_->length(); ++phi_idx) { |
| 516 PhiInstr* phi = (*phis_)[phi_idx]; |
| 517 if (phi == NULL) continue; |
| 518 Value* temp = phi->InputAt(new_idx); |
| 519 phi->SetInputAt(new_idx, phi->InputAt(old_idx)); |
| 520 phi->SetInputAt(old_idx, temp); |
| 521 } |
| 522 // The old input at new_idx is now found at old_idx. It may be a |
| 523 // reachable predecessor so swap the old predecessors too. |
| 524 BlockEntryInstr* temp = stale_predecessors_[new_idx]; |
| 525 stale_predecessors_[new_idx] = stale_predecessors_[old_idx]; |
| 526 stale_predecessors_[old_idx] = temp; |
| 527 } |
| 528 } |
| 529 // Now truncate each phi if necessary. |
| 530 if (input_count < stale_predecessors_.length()) { |
| 531 for (intptr_t phi_idx = 0; phi_idx < phis_->length(); ++phi_idx) { |
| 532 PhiInstr* phi = (*phis_)[phi_idx]; |
| 533 if (phi == NULL) continue; |
| 534 phi->inputs_.TruncateTo(input_count); |
| 535 } |
| 536 } |
| 537 } |
| 538 |
| 539 |
| 479 // ==== Recording assigned variables. | 540 // ==== Recording assigned variables. |
| 480 void Definition::RecordAssignedVars(BitVector* assigned_vars, | 541 void Definition::RecordAssignedVars(BitVector* assigned_vars, |
| 481 intptr_t fixed_parameter_count) { | 542 intptr_t fixed_parameter_count) { |
| 482 // Nothing to do for the base class. | 543 // Nothing to do for the base class. |
| 483 } | 544 } |
| 484 | 545 |
| 485 | 546 |
| 486 void StoreLocalInstr::RecordAssignedVars(BitVector* assigned_vars, | 547 void StoreLocalInstr::RecordAssignedVars(BitVector* assigned_vars, |
| 487 intptr_t fixed_parameter_count) { | 548 intptr_t fixed_parameter_count) { |
| 488 if (!local().is_captured()) { | 549 if (!local().is_captured()) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 return propagated_cid(); | 639 return propagated_cid(); |
| 579 } | 640 } |
| 580 | 641 |
| 581 | 642 |
| 582 intptr_t ParameterInstr::GetPropagatedCid() { | 643 intptr_t ParameterInstr::GetPropagatedCid() { |
| 583 return propagated_cid(); | 644 return propagated_cid(); |
| 584 } | 645 } |
| 585 | 646 |
| 586 | 647 |
| 587 // ==== Postorder graph traversal. | 648 // ==== Postorder graph traversal. |
| 649 static bool IsMarked(BlockEntryInstr* block, |
| 650 GrowableArray<BlockEntryInstr*>* preorder) { |
| 651 // Detect that a block has been visited as part of the current |
| 652 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block |
| 653 // will be 'marked' by (1) having a preorder number in the range of the |
| 654 // preorder array and (2) being in the preorder array at that index. |
| 655 intptr_t i = block->preorder_number(); |
| 656 return (i >= 0) && (i < preorder->length()) && ((*preorder)[i] == block); |
| 657 } |
| 658 |
| 659 |
| 588 void GraphEntryInstr::DiscoverBlocks( | 660 void GraphEntryInstr::DiscoverBlocks( |
| 589 BlockEntryInstr* current_block, | 661 BlockEntryInstr* current_block, |
| 590 GrowableArray<BlockEntryInstr*>* preorder, | 662 GrowableArray<BlockEntryInstr*>* preorder, |
| 591 GrowableArray<BlockEntryInstr*>* postorder, | 663 GrowableArray<BlockEntryInstr*>* postorder, |
| 592 GrowableArray<intptr_t>* parent, | 664 GrowableArray<intptr_t>* parent, |
| 593 GrowableArray<BitVector*>* assigned_vars, | 665 GrowableArray<BitVector*>* assigned_vars, |
| 594 intptr_t variable_count, | 666 intptr_t variable_count, |
| 595 intptr_t fixed_parameter_count) { | 667 intptr_t fixed_parameter_count) { |
| 596 // We only visit this block once, first of all blocks. | 668 // We only visit this block once, first of all blocks. |
| 597 ASSERT(preorder_number() == -1); | 669 ASSERT(!IsMarked(this, preorder)); |
| 598 ASSERT(current_block == NULL); | 670 ASSERT(current_block == NULL); |
| 599 ASSERT(preorder->is_empty()); | 671 ASSERT(preorder->is_empty()); |
| 600 ASSERT(postorder->is_empty()); | 672 ASSERT(postorder->is_empty()); |
| 601 ASSERT(parent->is_empty()); | 673 ASSERT(parent->is_empty()); |
| 602 | 674 |
| 603 // This node has no parent, indicated by -1. The preorder number is 0. | 675 // This node has no parent, indicated by -1. The preorder number is 0. |
| 604 parent->Add(-1); | 676 parent->Add(-1); |
| 605 set_preorder_number(0); | 677 set_preorder_number(0); |
| 606 preorder->Add(this); | 678 preorder->Add(this); |
| 607 BitVector* vars = | 679 BitVector* vars = |
| (...skipping 27 matching lines...) Expand all Loading... |
| 635 GrowableArray<BlockEntryInstr*>* preorder, | 707 GrowableArray<BlockEntryInstr*>* preorder, |
| 636 GrowableArray<BlockEntryInstr*>* postorder, | 708 GrowableArray<BlockEntryInstr*>* postorder, |
| 637 GrowableArray<intptr_t>* parent, | 709 GrowableArray<intptr_t>* parent, |
| 638 GrowableArray<BitVector*>* assigned_vars, | 710 GrowableArray<BitVector*>* assigned_vars, |
| 639 intptr_t variable_count, | 711 intptr_t variable_count, |
| 640 intptr_t fixed_parameter_count) { | 712 intptr_t fixed_parameter_count) { |
| 641 // We have already visited the graph entry, so we can assume current_block | 713 // We have already visited the graph entry, so we can assume current_block |
| 642 // is non-null and preorder array is non-empty. | 714 // is non-null and preorder array is non-empty. |
| 643 ASSERT(current_block != NULL); | 715 ASSERT(current_block != NULL); |
| 644 ASSERT(!preorder->is_empty()); | 716 ASSERT(!preorder->is_empty()); |
| 717 // Blocks with a single predecessor cannot have been reached before. |
| 718 ASSERT(!IsTargetEntry() || !IsMarked(this, preorder)); |
| 645 | 719 |
| 646 // 1. Record control-flow-graph basic-block predecessors. | 720 // 1. If the block has already been reached, add current_block as a |
| 721 // basic-block predecessor and we are done. |
| 722 if (IsMarked(this, preorder)) { |
| 723 AddPredecessor(current_block); |
| 724 return; |
| 725 } |
| 726 |
| 727 // 2. Otherwise, clear the predecessors which might have been computed on |
| 728 // some earlier call to DiscoverBlocks and record this predecessor. For |
| 729 // joins save the original predecessors, if any, so we can garbage collect |
| 730 // phi inputs from unreachable predecessors without recomputing SSA. |
| 731 ClearPredecessors(); |
| 647 AddPredecessor(current_block); | 732 AddPredecessor(current_block); |
| 648 | 733 |
| 649 // 2. If the block has already been reached by the traversal, we are | |
| 650 // done. Blocks with a single predecessor cannot have been reached | |
| 651 // before. | |
| 652 ASSERT(!IsTargetEntry() || (preorder_number() == -1)); | |
| 653 if (preorder_number() >= 0) return; | |
| 654 | |
| 655 // 3. The current block is the spanning-tree parent. | 734 // 3. The current block is the spanning-tree parent. |
| 656 parent->Add(current_block->preorder_number()); | 735 parent->Add(current_block->preorder_number()); |
| 657 | 736 |
| 658 // 4. Assign preorder number and add the block entry to the list. | 737 // 4. Assign preorder number and add the block entry to the list. |
| 659 // Allocate an empty set of assigned variables for the block. | 738 // Allocate an empty set of assigned variables for the block. |
| 660 set_preorder_number(preorder->length()); | 739 set_preorder_number(preorder->length()); |
| 661 preorder->Add(this); | 740 preorder->Add(this); |
| 662 BitVector* vars = | 741 BitVector* vars = |
| 663 (variable_count == 0) ? NULL : new BitVector(variable_count); | 742 (variable_count == 0) ? NULL : new BitVector(variable_count); |
| 664 assigned_vars->Add(vars); | 743 assigned_vars->Add(vars); |
| (...skipping 1090 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1755 value->set_use_index(use_index++); | 1834 value->set_use_index(use_index++); |
| 1756 value->AddToEnvUseList(); | 1835 value->AddToEnvUseList(); |
| 1757 } | 1836 } |
| 1758 instr->env()->outer_ = copy; | 1837 instr->env()->outer_ = copy; |
| 1759 } | 1838 } |
| 1760 | 1839 |
| 1761 | 1840 |
| 1762 #undef __ | 1841 #undef __ |
| 1763 | 1842 |
| 1764 } // namespace dart | 1843 } // namespace dart |
| OLD | NEW |