OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 15 matching lines...) Expand all Loading... |
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 | 28 |
29 #include "hydrogen-environment-liveness.h" | 29 #include "hydrogen-environment-liveness.h" |
30 | 30 |
31 | 31 |
32 namespace v8 { | 32 namespace v8 { |
33 namespace internal { | 33 namespace internal { |
34 | 34 |
35 | 35 |
36 EnvironmentSlotLivenessAnalyzer::EnvironmentSlotLivenessAnalyzer( | 36 HEnvironmentLivenessAnalysisPhase::HEnvironmentLivenessAnalysisPhase( |
37 HGraph* graph) | 37 HGraph* graph) |
38 : graph_(graph), | 38 : HPhase("H_Environment liveness analysis", graph), |
39 zone_(graph->isolate()), | |
40 block_count_(graph->blocks()->length()), | 39 block_count_(graph->blocks()->length()), |
41 maximum_environment_size_(graph->maximum_environment_size()), | 40 maximum_environment_size_(graph->maximum_environment_size()), |
| 41 live_at_block_start_(block_count_, zone()), |
| 42 first_simulate_(block_count_, zone()), |
| 43 first_simulate_invalid_for_index_(block_count_, zone()), |
| 44 markers_(maximum_environment_size_, zone()), |
42 collect_markers_(true), | 45 collect_markers_(true), |
43 last_simulate_(NULL) { | 46 last_simulate_(NULL), |
44 if (maximum_environment_size_ == 0) return; | 47 went_live_since_last_simulate_(maximum_environment_size_, zone()) { |
45 | 48 ASSERT(maximum_environment_size_ > 0); |
46 live_at_block_start_ = | |
47 new(zone()) ZoneList<BitVector*>(block_count_, zone()); | |
48 first_simulate_ = new(zone()) ZoneList<HSimulate*>(block_count_, zone()); | |
49 first_simulate_invalid_for_index_ = | |
50 new(zone()) ZoneList<BitVector*>(block_count_, zone()); | |
51 markers_ = new(zone()) | |
52 ZoneList<HEnvironmentMarker*>(maximum_environment_size_, zone()); | |
53 went_live_since_last_simulate_ = | |
54 new(zone()) BitVector(maximum_environment_size_, zone()); | |
55 | |
56 for (int i = 0; i < block_count_; ++i) { | 49 for (int i = 0; i < block_count_; ++i) { |
57 live_at_block_start_->Add( | 50 live_at_block_start_.Add( |
58 new(zone()) BitVector(maximum_environment_size_, zone()), zone()); | 51 new(zone()) BitVector(maximum_environment_size_, zone()), zone()); |
59 first_simulate_->Add(NULL, zone()); | 52 first_simulate_.Add(NULL, zone()); |
60 first_simulate_invalid_for_index_->Add( | 53 first_simulate_invalid_for_index_.Add( |
61 new(zone()) BitVector(maximum_environment_size_, zone()), zone()); | 54 new(zone()) BitVector(maximum_environment_size_, zone()), zone()); |
62 } | 55 } |
63 } | 56 } |
64 | 57 |
65 | 58 |
66 void EnvironmentSlotLivenessAnalyzer::ZapEnvironmentSlot(int index, | 59 void HEnvironmentLivenessAnalysisPhase::ZapEnvironmentSlot( |
67 HSimulate* simulate) { | 60 int index, HSimulate* simulate) { |
68 int operand_index = simulate->ToOperandIndex(index); | 61 int operand_index = simulate->ToOperandIndex(index); |
69 if (operand_index == -1) { | 62 if (operand_index == -1) { |
70 simulate->AddAssignedValue(index, graph_->GetConstantUndefined()); | 63 simulate->AddAssignedValue(index, graph()->GetConstantUndefined()); |
71 } else { | 64 } else { |
72 simulate->SetOperandAt(operand_index, graph_->GetConstantUndefined()); | 65 simulate->SetOperandAt(operand_index, graph()->GetConstantUndefined()); |
73 } | 66 } |
74 } | 67 } |
75 | 68 |
76 | 69 |
77 void EnvironmentSlotLivenessAnalyzer::ZapEnvironmentSlotsInSuccessors( | 70 void HEnvironmentLivenessAnalysisPhase::ZapEnvironmentSlotsInSuccessors( |
78 HBasicBlock* block, | 71 HBasicBlock* block, BitVector* live) { |
79 BitVector* live) { | |
80 // When a value is live in successor A but dead in B, we must | 72 // When a value is live in successor A but dead in B, we must |
81 // explicitly zap it in B. | 73 // explicitly zap it in B. |
82 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) { | 74 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) { |
83 HBasicBlock* successor = it.Current(); | 75 HBasicBlock* successor = it.Current(); |
84 int successor_id = successor->block_id(); | 76 int successor_id = successor->block_id(); |
85 BitVector* live_in_successor = live_at_block_start_->at(successor_id); | 77 BitVector* live_in_successor = live_at_block_start_[successor_id]; |
86 if (live_in_successor->Equals(*live)) continue; | 78 if (live_in_successor->Equals(*live)) continue; |
87 for (int i = 0; i < live->length(); ++i) { | 79 for (int i = 0; i < live->length(); ++i) { |
88 if (!live->Contains(i)) continue; | 80 if (!live->Contains(i)) continue; |
89 if (live_in_successor->Contains(i)) continue; | 81 if (live_in_successor->Contains(i)) continue; |
90 if (first_simulate_invalid_for_index_->at(successor_id)->Contains(i)) { | 82 if (first_simulate_invalid_for_index_.at(successor_id)->Contains(i)) { |
91 continue; | 83 continue; |
92 } | 84 } |
93 HSimulate* simulate = first_simulate_->at(successor_id); | 85 HSimulate* simulate = first_simulate_.at(successor_id); |
94 if (simulate == NULL) continue; | 86 if (simulate == NULL) continue; |
95 ASSERT(simulate->closure().is_identical_to( | 87 ASSERT(simulate->closure().is_identical_to( |
96 block->last_environment()->closure())); | 88 block->last_environment()->closure())); |
97 ZapEnvironmentSlot(i, simulate); | 89 ZapEnvironmentSlot(i, simulate); |
98 } | 90 } |
99 } | 91 } |
100 } | 92 } |
101 | 93 |
102 | 94 |
103 void EnvironmentSlotLivenessAnalyzer::ZapEnvironmentSlotsForInstruction( | 95 void HEnvironmentLivenessAnalysisPhase::ZapEnvironmentSlotsForInstruction( |
104 HEnvironmentMarker* marker) { | 96 HEnvironmentMarker* marker) { |
105 if (!marker->CheckFlag(HValue::kEndsLiveRange)) return; | 97 if (!marker->CheckFlag(HValue::kEndsLiveRange)) return; |
106 HSimulate* simulate = marker->next_simulate(); | 98 HSimulate* simulate = marker->next_simulate(); |
107 if (simulate != NULL) { | 99 if (simulate != NULL) { |
108 ASSERT(simulate->closure().is_identical_to(marker->closure())); | 100 ASSERT(simulate->closure().is_identical_to(marker->closure())); |
109 ZapEnvironmentSlot(marker->index(), simulate); | 101 ZapEnvironmentSlot(marker->index(), simulate); |
110 } | 102 } |
111 } | 103 } |
112 | 104 |
113 | 105 |
114 void EnvironmentSlotLivenessAnalyzer::UpdateLivenessAtBlockEnd( | 106 void HEnvironmentLivenessAnalysisPhase::UpdateLivenessAtBlockEnd( |
115 HBasicBlock* block, | 107 HBasicBlock* block, |
116 BitVector* live) { | 108 BitVector* live) { |
117 // Liveness at the end of each block: union of liveness in successors. | 109 // Liveness at the end of each block: union of liveness in successors. |
118 live->Clear(); | 110 live->Clear(); |
119 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) { | 111 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) { |
120 live->Union(*live_at_block_start_->at(it.Current()->block_id())); | 112 live->Union(*live_at_block_start_[it.Current()->block_id()]); |
121 } | 113 } |
122 } | 114 } |
123 | 115 |
124 | 116 |
125 void EnvironmentSlotLivenessAnalyzer::UpdateLivenessAtInstruction( | 117 void HEnvironmentLivenessAnalysisPhase::UpdateLivenessAtInstruction( |
126 HInstruction* instr, | 118 HInstruction* instr, |
127 BitVector* live) { | 119 BitVector* live) { |
128 switch (instr->opcode()) { | 120 switch (instr->opcode()) { |
129 case HValue::kEnvironmentMarker: { | 121 case HValue::kEnvironmentMarker: { |
130 HEnvironmentMarker* marker = HEnvironmentMarker::cast(instr); | 122 HEnvironmentMarker* marker = HEnvironmentMarker::cast(instr); |
131 int index = marker->index(); | 123 int index = marker->index(); |
132 if (!live->Contains(index)) { | 124 if (!live->Contains(index)) { |
133 marker->SetFlag(HValue::kEndsLiveRange); | 125 marker->SetFlag(HValue::kEndsLiveRange); |
134 } else { | 126 } else { |
135 marker->ClearFlag(HValue::kEndsLiveRange); | 127 marker->ClearFlag(HValue::kEndsLiveRange); |
136 } | 128 } |
137 if (!went_live_since_last_simulate_->Contains(index)) { | 129 if (!went_live_since_last_simulate_.Contains(index)) { |
138 marker->set_next_simulate(last_simulate_); | 130 marker->set_next_simulate(last_simulate_); |
139 } | 131 } |
140 if (marker->kind() == HEnvironmentMarker::LOOKUP) { | 132 if (marker->kind() == HEnvironmentMarker::LOOKUP) { |
141 live->Add(index); | 133 live->Add(index); |
142 } else { | 134 } else { |
143 ASSERT(marker->kind() == HEnvironmentMarker::BIND); | 135 ASSERT(marker->kind() == HEnvironmentMarker::BIND); |
144 live->Remove(index); | 136 live->Remove(index); |
145 went_live_since_last_simulate_->Add(index); | 137 went_live_since_last_simulate_.Add(index); |
146 } | 138 } |
147 if (collect_markers_) { | 139 if (collect_markers_) { |
148 // Populate |markers_| list during the first pass. | 140 // Populate |markers_| list during the first pass. |
149 markers_->Add(marker, zone()); | 141 markers_.Add(marker, zone()); |
150 } | 142 } |
151 break; | 143 break; |
152 } | 144 } |
153 case HValue::kLeaveInlined: | 145 case HValue::kLeaveInlined: |
154 // No environment values are live at the end of an inlined section. | 146 // No environment values are live at the end of an inlined section. |
155 live->Clear(); | 147 live->Clear(); |
156 last_simulate_ = NULL; | 148 last_simulate_ = NULL; |
157 | 149 |
158 // The following ASSERTs guard the assumption used in case | 150 // The following ASSERTs guard the assumption used in case |
159 // kEnterInlined below: | 151 // kEnterInlined below: |
160 ASSERT(instr->next()->IsSimulate()); | 152 ASSERT(instr->next()->IsSimulate()); |
161 ASSERT(instr->next()->next()->IsGoto()); | 153 ASSERT(instr->next()->next()->IsGoto()); |
162 | 154 |
163 break; | 155 break; |
164 case HValue::kEnterInlined: { | 156 case HValue::kEnterInlined: { |
165 // Those environment values are live that are live at any return | 157 // Those environment values are live that are live at any return |
166 // target block. Here we make use of the fact that the end of an | 158 // target block. Here we make use of the fact that the end of an |
167 // inline sequence always looks like this: HLeaveInlined, HSimulate, | 159 // inline sequence always looks like this: HLeaveInlined, HSimulate, |
168 // HGoto (to return_target block), with no environment lookups in | 160 // HGoto (to return_target block), with no environment lookups in |
169 // between (see ASSERTs above). | 161 // between (see ASSERTs above). |
170 HEnterInlined* enter = HEnterInlined::cast(instr); | 162 HEnterInlined* enter = HEnterInlined::cast(instr); |
171 live->Clear(); | 163 live->Clear(); |
172 for (int i = 0; i < enter->return_targets()->length(); ++i) { | 164 for (int i = 0; i < enter->return_targets()->length(); ++i) { |
173 int return_id = enter->return_targets()->at(i)->block_id(); | 165 int return_id = enter->return_targets()->at(i)->block_id(); |
174 // When an AbnormalExit is involved, it can happen that the return | 166 // When an AbnormalExit is involved, it can happen that the return |
175 // target block doesn't actually exist. | 167 // target block doesn't actually exist. |
176 if (return_id < live_at_block_start_->length()) { | 168 if (return_id < live_at_block_start_.length()) { |
177 live->Union(*live_at_block_start_->at(return_id)); | 169 live->Union(*live_at_block_start_[return_id]); |
178 } | 170 } |
179 } | 171 } |
180 last_simulate_ = NULL; | 172 last_simulate_ = NULL; |
181 break; | 173 break; |
182 } | 174 } |
183 case HValue::kDeoptimize: { | 175 case HValue::kDeoptimize: { |
184 // Keep all environment slots alive. | 176 // Keep all environment slots alive. |
185 HDeoptimize* deopt = HDeoptimize::cast(instr); | 177 HDeoptimize* deopt = HDeoptimize::cast(instr); |
186 for (int i = deopt->first_local_index(); | 178 for (int i = deopt->first_local_index(); |
187 i < deopt->first_expression_index(); ++i) { | 179 i < deopt->first_expression_index(); ++i) { |
188 live->Add(i); | 180 live->Add(i); |
189 } | 181 } |
190 break; | 182 break; |
191 } | 183 } |
192 case HValue::kSimulate: | 184 case HValue::kSimulate: |
193 last_simulate_ = HSimulate::cast(instr); | 185 last_simulate_ = HSimulate::cast(instr); |
194 went_live_since_last_simulate_->Clear(); | 186 went_live_since_last_simulate_.Clear(); |
195 break; | 187 break; |
196 default: | 188 default: |
197 break; | 189 break; |
198 } | 190 } |
199 } | 191 } |
200 | 192 |
201 | 193 |
202 void EnvironmentSlotLivenessAnalyzer::AnalyzeAndTrim() { | 194 void HEnvironmentLivenessAnalysisPhase::Run() { |
203 HPhase phase("H_EnvironmentLivenessAnalysis", graph_); | 195 ASSERT(maximum_environment_size_ > 0); |
204 if (maximum_environment_size_ == 0) return; | |
205 | 196 |
206 // Main iteration. Compute liveness of environment slots, and store it | 197 // Main iteration. Compute liveness of environment slots, and store it |
207 // for each block until it doesn't change any more. For efficiency, visit | 198 // for each block until it doesn't change any more. For efficiency, visit |
208 // blocks in reverse order and walk backwards through each block. We | 199 // blocks in reverse order and walk backwards through each block. We |
209 // need several iterations to propagate liveness through nested loops. | 200 // need several iterations to propagate liveness through nested loops. |
210 BitVector* live = new(zone()) BitVector(maximum_environment_size_, zone()); | 201 BitVector live(maximum_environment_size_, zone()); |
211 BitVector* worklist = new(zone()) BitVector(block_count_, zone()); | 202 BitVector worklist(block_count_, zone()); |
212 for (int i = 0; i < block_count_; ++i) { | 203 for (int i = 0; i < block_count_; ++i) { |
213 worklist->Add(i); | 204 worklist.Add(i); |
214 } | 205 } |
215 while (!worklist->IsEmpty()) { | 206 while (!worklist.IsEmpty()) { |
216 for (int block_id = block_count_ - 1; block_id >= 0; --block_id) { | 207 for (int block_id = block_count_ - 1; block_id >= 0; --block_id) { |
217 if (!worklist->Contains(block_id)) { | 208 if (!worklist.Contains(block_id)) { |
218 continue; | 209 continue; |
219 } | 210 } |
220 worklist->Remove(block_id); | 211 worklist.Remove(block_id); |
221 last_simulate_ = NULL; | 212 last_simulate_ = NULL; |
222 | 213 |
223 HBasicBlock* block = graph_->blocks()->at(block_id); | 214 HBasicBlock* block = graph()->blocks()->at(block_id); |
224 UpdateLivenessAtBlockEnd(block, live); | 215 UpdateLivenessAtBlockEnd(block, &live); |
225 | 216 |
226 for (HInstruction* instr = block->last(); instr != NULL; | 217 for (HInstruction* instr = block->last(); instr != NULL; |
227 instr = instr->previous()) { | 218 instr = instr->previous()) { |
228 UpdateLivenessAtInstruction(instr, live); | 219 UpdateLivenessAtInstruction(instr, &live); |
229 } | 220 } |
230 | 221 |
231 // Reached the start of the block, do necessary bookkeeping: | 222 // Reached the start of the block, do necessary bookkeeping: |
232 // store computed information for this block and add predecessors | 223 // store computed information for this block and add predecessors |
233 // to the work list as necessary. | 224 // to the work list as necessary. |
234 first_simulate_->Set(block_id, last_simulate_); | 225 first_simulate_.Set(block_id, last_simulate_); |
235 first_simulate_invalid_for_index_->at(block_id)->CopyFrom( | 226 first_simulate_invalid_for_index_[block_id]->CopyFrom( |
236 *went_live_since_last_simulate_); | 227 went_live_since_last_simulate_); |
237 if (live_at_block_start_->at(block_id)->UnionIsChanged(*live)) { | 228 if (live_at_block_start_[block_id]->UnionIsChanged(live)) { |
238 for (int i = 0; i < block->predecessors()->length(); ++i) { | 229 for (int i = 0; i < block->predecessors()->length(); ++i) { |
239 worklist->Add(block->predecessors()->at(i)->block_id()); | 230 worklist.Add(block->predecessors()->at(i)->block_id()); |
240 } | 231 } |
241 if (block->IsInlineReturnTarget()) { | 232 if (block->IsInlineReturnTarget()) { |
242 worklist->Add(block->inlined_entry_block()->block_id()); | 233 worklist.Add(block->inlined_entry_block()->block_id()); |
243 } | 234 } |
244 } | 235 } |
245 } | 236 } |
246 // Only collect bind/lookup instructions during the first pass. | 237 // Only collect bind/lookup instructions during the first pass. |
247 collect_markers_ = false; | 238 collect_markers_ = false; |
248 } | 239 } |
249 | 240 |
250 // Analysis finished. Zap dead environment slots. | 241 // Analysis finished. Zap dead environment slots. |
251 for (int i = 0; i < markers_->length(); ++i) { | 242 for (int i = 0; i < markers_.length(); ++i) { |
252 ZapEnvironmentSlotsForInstruction(markers_->at(i)); | 243 ZapEnvironmentSlotsForInstruction(markers_[i]); |
253 } | 244 } |
254 for (int block_id = block_count_ - 1; block_id >= 0; --block_id) { | 245 for (int block_id = block_count_ - 1; block_id >= 0; --block_id) { |
255 HBasicBlock* block = graph_->blocks()->at(block_id); | 246 HBasicBlock* block = graph()->blocks()->at(block_id); |
256 UpdateLivenessAtBlockEnd(block, live); | 247 UpdateLivenessAtBlockEnd(block, &live); |
257 ZapEnvironmentSlotsInSuccessors(block, live); | 248 ZapEnvironmentSlotsInSuccessors(block, &live); |
258 } | 249 } |
259 | 250 |
260 // Finally, remove the HEnvironment{Bind,Lookup} markers. | 251 // Finally, remove the HEnvironment{Bind,Lookup} markers. |
261 for (int i = 0; i < markers_->length(); ++i) { | 252 for (int i = 0; i < markers_.length(); ++i) { |
262 markers_->at(i)->DeleteAndReplaceWith(NULL); | 253 markers_[i]->DeleteAndReplaceWith(NULL); |
263 } | 254 } |
264 } | 255 } |
265 | 256 |
266 } } // namespace v8::internal | 257 } } // namespace v8::internal |
OLD | NEW |