OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 12 matching lines...) Expand all Loading... |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "lithium.h" | 28 #include "lithium.h" |
29 | 29 |
30 namespace v8 { | 30 namespace v8 { |
31 namespace internal { | 31 namespace internal { |
32 | 32 |
33 | |
34 class LGapNode: public ZoneObject { | |
35 public: | |
36 explicit LGapNode(LOperand* operand) | |
37 : operand_(operand), resolved_(false), visited_id_(-1) { } | |
38 | |
39 LOperand* operand() const { return operand_; } | |
40 bool IsResolved() const { return !IsAssigned() || resolved_; } | |
41 void MarkResolved() { | |
42 ASSERT(!IsResolved()); | |
43 resolved_ = true; | |
44 } | |
45 int visited_id() const { return visited_id_; } | |
46 void set_visited_id(int id) { | |
47 ASSERT(id > visited_id_); | |
48 visited_id_ = id; | |
49 } | |
50 | |
51 bool IsAssigned() const { return assigned_from_.is_set(); } | |
52 LGapNode* assigned_from() const { return assigned_from_.get(); } | |
53 void set_assigned_from(LGapNode* n) { assigned_from_.set(n); } | |
54 | |
55 private: | |
56 LOperand* operand_; | |
57 SetOncePointer<LGapNode> assigned_from_; | |
58 bool resolved_; | |
59 int visited_id_; | |
60 }; | |
61 | |
62 | |
63 LGapResolver::LGapResolver() | |
64 : nodes_(32), | |
65 identified_cycles_(4), | |
66 result_(16), | |
67 next_visited_id_(0) { | |
68 } | |
69 | |
70 | |
71 const ZoneList<LMoveOperands>* LGapResolver::Resolve( | |
72 const ZoneList<LMoveOperands>* moves, | |
73 LOperand* marker_operand) { | |
74 nodes_.Rewind(0); | |
75 identified_cycles_.Rewind(0); | |
76 result_.Rewind(0); | |
77 next_visited_id_ = 0; | |
78 | |
79 for (int i = 0; i < moves->length(); ++i) { | |
80 LMoveOperands move = moves->at(i); | |
81 if (!move.IsRedundant()) RegisterMove(move); | |
82 } | |
83 | |
84 for (int i = 0; i < identified_cycles_.length(); ++i) { | |
85 ResolveCycle(identified_cycles_[i], marker_operand); | |
86 } | |
87 | |
88 int unresolved_nodes; | |
89 do { | |
90 unresolved_nodes = 0; | |
91 for (int j = 0; j < nodes_.length(); j++) { | |
92 LGapNode* node = nodes_[j]; | |
93 if (!node->IsResolved() && node->assigned_from()->IsResolved()) { | |
94 AddResultMove(node->assigned_from(), node); | |
95 node->MarkResolved(); | |
96 } | |
97 if (!node->IsResolved()) ++unresolved_nodes; | |
98 } | |
99 } while (unresolved_nodes > 0); | |
100 return &result_; | |
101 } | |
102 | |
103 | |
104 void LGapResolver::AddResultMove(LGapNode* from, LGapNode* to) { | |
105 AddResultMove(from->operand(), to->operand()); | |
106 } | |
107 | |
108 | |
109 void LGapResolver::AddResultMove(LOperand* from, LOperand* to) { | |
110 result_.Add(LMoveOperands(from, to)); | |
111 } | |
112 | |
113 | |
114 void LGapResolver::ResolveCycle(LGapNode* start, LOperand* marker_operand) { | |
115 ZoneList<LOperand*> cycle_operands(8); | |
116 cycle_operands.Add(marker_operand); | |
117 LGapNode* cur = start; | |
118 do { | |
119 cur->MarkResolved(); | |
120 cycle_operands.Add(cur->operand()); | |
121 cur = cur->assigned_from(); | |
122 } while (cur != start); | |
123 cycle_operands.Add(marker_operand); | |
124 | |
125 for (int i = cycle_operands.length() - 1; i > 0; --i) { | |
126 LOperand* from = cycle_operands[i]; | |
127 LOperand* to = cycle_operands[i - 1]; | |
128 AddResultMove(from, to); | |
129 } | |
130 } | |
131 | |
132 | |
133 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b, int visited_id) { | |
134 ASSERT(a != b); | |
135 LGapNode* cur = a; | |
136 while (cur != b && cur->visited_id() != visited_id && cur->IsAssigned()) { | |
137 cur->set_visited_id(visited_id); | |
138 cur = cur->assigned_from(); | |
139 } | |
140 | |
141 return cur == b; | |
142 } | |
143 | |
144 | |
145 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b) { | |
146 ASSERT(a != b); | |
147 return CanReach(a, b, next_visited_id_++); | |
148 } | |
149 | |
150 | |
151 void LGapResolver::RegisterMove(LMoveOperands move) { | |
152 if (move.from()->IsConstantOperand()) { | |
153 // Constant moves should be last in the machine code. Therefore add them | |
154 // first to the result set. | |
155 AddResultMove(move.from(), move.to()); | |
156 } else { | |
157 LGapNode* from = LookupNode(move.from()); | |
158 LGapNode* to = LookupNode(move.to()); | |
159 if (to->IsAssigned() && to->assigned_from() == from) { | |
160 move.Eliminate(); | |
161 return; | |
162 } | |
163 ASSERT(!to->IsAssigned()); | |
164 if (CanReach(from, to)) { | |
165 // This introduces a cycle. Save. | |
166 identified_cycles_.Add(from); | |
167 } | |
168 to->set_assigned_from(from); | |
169 } | |
170 } | |
171 | |
172 | |
173 LGapNode* LGapResolver::LookupNode(LOperand* operand) { | |
174 for (int i = 0; i < nodes_.length(); ++i) { | |
175 if (nodes_[i]->operand()->Equals(operand)) return nodes_[i]; | |
176 } | |
177 | |
178 // No node found => create a new one. | |
179 LGapNode* result = new LGapNode(operand); | |
180 nodes_.Add(result); | |
181 return result; | |
182 } | |
183 | |
184 | |
185 bool LParallelMove::IsRedundant() const { | 33 bool LParallelMove::IsRedundant() const { |
186 for (int i = 0; i < move_operands_.length(); ++i) { | 34 for (int i = 0; i < move_operands_.length(); ++i) { |
187 if (!move_operands_[i].IsRedundant()) return false; | 35 if (!move_operands_[i].IsRedundant()) return false; |
188 } | 36 } |
189 return true; | 37 return true; |
190 } | 38 } |
191 | 39 |
192 | 40 |
193 void LParallelMove::PrintDataTo(StringStream* stream) const { | 41 void LParallelMove::PrintDataTo(StringStream* stream) const { |
194 for (int i = move_operands_.length() - 1; i >= 0; --i) { | 42 for (int i = move_operands_.length() - 1; i >= 0; --i) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 stream->Add("{"); | 84 stream->Add("{"); |
237 for (int i = 0; i < pointer_operands_.length(); ++i) { | 85 for (int i = 0; i < pointer_operands_.length(); ++i) { |
238 if (i != 0) stream->Add(";"); | 86 if (i != 0) stream->Add(";"); |
239 pointer_operands_[i]->PrintTo(stream); | 87 pointer_operands_[i]->PrintTo(stream); |
240 } | 88 } |
241 stream->Add("} @%d", position()); | 89 stream->Add("} @%d", position()); |
242 } | 90 } |
243 | 91 |
244 | 92 |
245 } } // namespace v8::internal | 93 } } // namespace v8::internal |
OLD | NEW |