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