| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 4549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4560 new Value(flow_graph_->constant_null()), | 4560 new Value(flow_graph_->constant_null()), |
| 4561 kNoStoreBarrier, | 4561 kNoStoreBarrier, |
| 4562 instr->token_pos()); | 4562 instr->token_pos()); |
| 4563 store->set_is_initialization(true); // Won't be eliminated by DSE. | 4563 store->set_is_initialization(true); // Won't be eliminated by DSE. |
| 4564 flow_graph_->InsertAfter(cursor, store, NULL, FlowGraph::kEffect); | 4564 flow_graph_->InsertAfter(cursor, store, NULL, FlowGraph::kEffect); |
| 4565 cursor = store; | 4565 cursor = store; |
| 4566 } | 4566 } |
| 4567 } | 4567 } |
| 4568 | 4568 |
| 4569 | 4569 |
| 4570 void FlowGraphOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { | |
| 4571 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized. | |
| 4572 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) | |
| 4573 if (!instr->can_pack_into_smi()) | |
| 4574 instr->set_representation(kUnboxedMint); | |
| 4575 #endif | |
| 4576 } | |
| 4577 | |
| 4578 | |
| 4579 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, | 4570 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, |
| 4580 const ICData& unary_ic_data) { | 4571 const ICData& unary_ic_data) { |
| 4581 ASSERT((unary_ic_data.NumberOfChecks() > 0) && | 4572 ASSERT((unary_ic_data.NumberOfChecks() > 0) && |
| 4582 (unary_ic_data.NumArgsTested() == 1)); | 4573 (unary_ic_data.NumArgsTested() == 1)); |
| 4583 if (FLAG_enable_type_checks) { | 4574 if (FLAG_enable_type_checks) { |
| 4584 // Checked mode setters are inlined like normal methods by conventional | 4575 // Checked mode setters are inlined like normal methods by conventional |
| 4585 // inlining. | 4576 // inlining. |
| 4586 return false; | 4577 return false; |
| 4587 } | 4578 } |
| 4588 | 4579 |
| (...skipping 3003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7592 } | 7583 } |
| 7593 | 7584 |
| 7594 | 7585 |
| 7595 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { | 7586 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { |
| 7596 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 7587 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 7597 it.Current()->Accept(this); | 7588 it.Current()->Accept(this); |
| 7598 } | 7589 } |
| 7599 } | 7590 } |
| 7600 | 7591 |
| 7601 | 7592 |
| 7602 void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) { | |
| 7603 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | |
| 7604 it.Current()->Accept(this); | |
| 7605 } | |
| 7606 } | |
| 7607 | |
| 7608 | |
| 7609 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { | 7593 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { |
| 7610 const GrowableArray<Definition*>& defs = *block->initial_definitions(); | 7594 const GrowableArray<Definition*>& defs = *block->initial_definitions(); |
| 7611 for (intptr_t i = 0; i < defs.length(); ++i) { | 7595 for (intptr_t i = 0; i < defs.length(); ++i) { |
| 7612 defs[i]->Accept(this); | 7596 defs[i]->Accept(this); |
| 7613 } | 7597 } |
| 7614 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 7598 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 7615 it.Current()->Accept(this); | 7599 it.Current()->Accept(this); |
| 7616 } | 7600 } |
| 7617 } | 7601 } |
| 7618 | 7602 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 7646 SetReachable(instr->successor()); | 7630 SetReachable(instr->successor()); |
| 7647 | 7631 |
| 7648 // Phi value depends on the reachability of a predecessor. We have | 7632 // Phi value depends on the reachability of a predecessor. We have |
| 7649 // to revisit phis every time a predecessor becomes reachable. | 7633 // to revisit phis every time a predecessor becomes reachable. |
| 7650 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { | 7634 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { |
| 7651 it.Current()->Accept(this); | 7635 it.Current()->Accept(this); |
| 7652 } | 7636 } |
| 7653 } | 7637 } |
| 7654 | 7638 |
| 7655 | 7639 |
| 7656 void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) { | |
| 7657 for (intptr_t i = 0; i < instr->SuccessorCount(); i++) { | |
| 7658 SetReachable(instr->SuccessorAt(i)); | |
| 7659 } | |
| 7660 } | |
| 7661 | |
| 7662 | |
| 7663 void ConstantPropagator::VisitBranch(BranchInstr* instr) { | 7640 void ConstantPropagator::VisitBranch(BranchInstr* instr) { |
| 7664 instr->comparison()->Accept(this); | 7641 instr->comparison()->Accept(this); |
| 7665 | 7642 |
| 7666 // The successors may be reachable, but only if this instruction is. (We | 7643 // The successors may be reachable, but only if this instruction is. (We |
| 7667 // might be analyzing it because the constant value of one of its inputs | 7644 // might be analyzing it because the constant value of one of its inputs |
| 7668 // has changed.) | 7645 // has changed.) |
| 7669 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { | 7646 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { |
| 7670 if (instr->constant_target() != NULL) { | 7647 if (instr->constant_target() != NULL) { |
| 7671 ASSERT((instr->constant_target() == instr->true_successor()) || | 7648 ASSERT((instr->constant_target() == instr->true_successor()) || |
| 7672 (instr->constant_target() == instr->false_successor())); | 7649 (instr->constant_target() == instr->false_successor())); |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8115 SetValue(instr, result); | 8092 SetValue(instr, result); |
| 8116 return; | 8093 return; |
| 8117 } | 8094 } |
| 8118 } | 8095 } |
| 8119 } | 8096 } |
| 8120 SetValue(instr, non_constant_); | 8097 SetValue(instr, non_constant_); |
| 8121 } | 8098 } |
| 8122 } | 8099 } |
| 8123 | 8100 |
| 8124 | 8101 |
| 8125 void ConstantPropagator::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { | |
| 8126 // TODO(zerny): Implement constant propagation. | |
| 8127 SetValue(instr, non_constant_); | |
| 8128 } | |
| 8129 | |
| 8130 | |
| 8131 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { | 8102 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { |
| 8132 SetValue(instr, instr->value()->definition()->constant_value()); | 8103 SetValue(instr, instr->value()->definition()->constant_value()); |
| 8133 } | 8104 } |
| 8134 | 8105 |
| 8135 | 8106 |
| 8136 void ConstantPropagator::VisitStoreInstanceField( | 8107 void ConstantPropagator::VisitStoreInstanceField( |
| 8137 StoreInstanceFieldInstr* instr) { | 8108 StoreInstanceFieldInstr* instr) { |
| 8138 SetValue(instr, instr->value()->definition()->constant_value()); | 8109 SetValue(instr, instr->value()->definition()->constant_value()); |
| 8139 } | 8110 } |
| 8140 | 8111 |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8763 const Object& right = instr->right()->definition()->constant_value(); | 8734 const Object& right = instr->right()->definition()->constant_value(); |
| 8764 if (IsNonConstant(left) || IsNonConstant(right)) { | 8735 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 8765 SetValue(instr, non_constant_); | 8736 SetValue(instr, non_constant_); |
| 8766 } else if (IsConstant(left) && IsConstant(right)) { | 8737 } else if (IsConstant(left) && IsConstant(right)) { |
| 8767 // TODO(srdjan): Handle min and max. | 8738 // TODO(srdjan): Handle min and max. |
| 8768 SetValue(instr, non_constant_); | 8739 SetValue(instr, non_constant_); |
| 8769 } | 8740 } |
| 8770 } | 8741 } |
| 8771 | 8742 |
| 8772 | 8743 |
| 8773 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( | |
| 8774 CaseInsensitiveCompareUC16Instr *instr) { | |
| 8775 SetValue(instr, non_constant_); | |
| 8776 } | |
| 8777 | |
| 8778 | |
| 8779 void ConstantPropagator::VisitUnbox(UnboxInstr* instr) { | 8744 void ConstantPropagator::VisitUnbox(UnboxInstr* instr) { |
| 8780 const Object& value = instr->value()->definition()->constant_value(); | 8745 const Object& value = instr->value()->definition()->constant_value(); |
| 8781 if (IsNonConstant(value)) { | 8746 if (IsNonConstant(value)) { |
| 8782 SetValue(instr, non_constant_); | 8747 SetValue(instr, non_constant_); |
| 8783 } else if (IsConstant(value)) { | 8748 } else if (IsConstant(value)) { |
| 8784 // TODO(kmillikin): Handle conversion. | 8749 // TODO(kmillikin): Handle conversion. |
| 8785 SetValue(instr, non_constant_); | 8750 SetValue(instr, non_constant_); |
| 8786 } | 8751 } |
| 8787 } | 8752 } |
| 8788 | 8753 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8851 } else { | 8816 } else { |
| 8852 BlockEntryInstr* block = block_worklist_.RemoveLast(); | 8817 BlockEntryInstr* block = block_worklist_.RemoveLast(); |
| 8853 block->Accept(this); | 8818 block->Accept(this); |
| 8854 } | 8819 } |
| 8855 } | 8820 } |
| 8856 } | 8821 } |
| 8857 | 8822 |
| 8858 | 8823 |
| 8859 static bool IsEmptyBlock(BlockEntryInstr* block) { | 8824 static bool IsEmptyBlock(BlockEntryInstr* block) { |
| 8860 return block->next()->IsGoto() && | 8825 return block->next()->IsGoto() && |
| 8861 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && | 8826 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); |
| 8862 !block->IsIndirectEntry(); | |
| 8863 } | 8827 } |
| 8864 | 8828 |
| 8865 | 8829 |
| 8866 // Traverses a chain of empty blocks and returns the first reachable non-empty | 8830 // Traverses a chain of empty blocks and returns the first reachable non-empty |
| 8867 // block that is not dominated by the start block. The empty blocks are added | 8831 // block that is not dominated by the start block. The empty blocks are added |
| 8868 // to the supplied bit vector. | 8832 // to the supplied bit vector. |
| 8869 static BlockEntryInstr* FindFirstNonEmptySuccessor( | 8833 static BlockEntryInstr* FindFirstNonEmptySuccessor( |
| 8870 TargetEntryInstr* block, | 8834 TargetEntryInstr* block, |
| 8871 BitVector* empty_blocks) { | 8835 BitVector* empty_blocks) { |
| 8872 BlockEntryInstr* current = block; | 8836 BlockEntryInstr* current = block; |
| (...skipping 1186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10059 | 10023 |
| 10060 // Insert materializations at environment uses. | 10024 // Insert materializations at environment uses. |
| 10061 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 10025 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 10062 CreateMaterializationAt( | 10026 CreateMaterializationAt( |
| 10063 exits_collector_.exits()[i], alloc, *slots); | 10027 exits_collector_.exits()[i], alloc, *slots); |
| 10064 } | 10028 } |
| 10065 } | 10029 } |
| 10066 | 10030 |
| 10067 | 10031 |
| 10068 } // namespace dart | 10032 } // namespace dart |
| OLD | NEW |