OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2013 the V8 project authors. All rights reserved. | |
2 // Redistribution and use in source and binary forms, with or without | |
3 // modification, are permitted provided that the following conditions are | |
4 // met: | |
5 // | |
6 // * Redistributions of source code must retain the above copyright | |
7 // notice, this list of conditions and the following disclaimer. | |
8 // * Redistributions in binary form must reproduce the above | |
9 // copyright notice, this list of conditions and the following | |
10 // disclaimer in the documentation and/or other materials provided | |
11 // with the distribution. | |
12 // * Neither the name of Google Inc. nor the names of its | |
13 // contributors may be used to endorse or promote products derived | |
14 // from this software without specific prior written permission. | |
15 // | |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
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. | |
27 | |
28 | |
29 #include "hydrogen-environment-liveness.h" | |
30 | |
31 | |
32 namespace v8 { | |
33 namespace internal { | |
34 | |
35 | |
36 void EnvironmentSlotLivenessAnalysis::ZapEnvironmentSlot(int index, | |
37 HSimulate* simulate) { | |
38 int operand_index = simulate->ToOperandIndex(index); | |
39 if (operand_index == -1) { | |
40 simulate->AddAssignedValue(index, graph_->GetConstantUndefined()); | |
41 } else { | |
42 simulate->SetOperandAt(operand_index, graph_->GetConstantUndefined()); | |
43 } | |
44 } | |
45 | |
46 | |
47 void EnvironmentSlotLivenessAnalysis::ZapEnvironmentSlotsInSuccessors( | |
48 HBasicBlock* block) { | |
49 // When a value is live in successor A but dead in B, we must | |
50 // explicitly zap it in B. | |
51 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) { | |
52 HBasicBlock* successor = it.Current(); | |
53 int successor_id = successor->block_id(); | |
54 BitVector* live_in_successor = live_at_block_start_->at(successor_id); | |
55 if (live_in_successor->Equals(*live_)) continue; | |
56 for (int i = 0; i < live_->length(); ++i) { | |
57 if (!live_->Contains(i)) continue; | |
58 if (live_in_successor->Contains(i)) continue; | |
59 if (first_simulate_invalid_for_index_->at(successor_id)->Contains(i)) { | |
60 continue; | |
61 } | |
62 HSimulate* simulate = first_simulate_->at(successor_id); | |
63 if (simulate == NULL) continue; | |
64 ASSERT(simulate->closure().is_identical_to( | |
65 block->last_environment()->closure())); | |
66 ZapEnvironmentSlot(i, simulate); | |
67 } | |
68 } | |
69 } | |
70 | |
71 | |
72 void EnvironmentSlotLivenessAnalysis::ZapEnvironmentSlotsForInstruction( | |
73 HEnvironmentMarker* marker) { | |
74 if (!marker->CheckFlag(HValue::kEndsLiveRange)) return; | |
75 HSimulate* simulate = marker->next_simulate(); | |
76 if (simulate != NULL) { | |
77 ASSERT(simulate->closure().is_identical_to(marker->closure())); | |
78 ZapEnvironmentSlot(marker->index(), simulate); | |
79 } | |
80 } | |
81 | |
82 | |
83 void EnvironmentSlotLivenessAnalysis::UpdateLivenessAtBlockEnd( | |
84 HBasicBlock* block) { | |
titzer
2013/05/29 16:58:05
E.g. here, it would be more clear to pass in the t
Jakob Kummerow
2013/06/03 17:50:38
Done.
| |
85 // Liveness at the end of each block: union of liveness in successors. | |
86 live_->Clear(); | |
87 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) { | |
88 live_->Union(*live_at_block_start_->at(it.Current()->block_id())); | |
89 } | |
90 } | |
91 | |
92 | |
93 void EnvironmentSlotLivenessAnalysis::UpdateLivenessAtInstruction( | |
94 HInstruction* instr) { | |
95 switch (instr->opcode()) { | |
96 case HValue::kEnvironmentMarker: { | |
97 HEnvironmentMarker* marker = HEnvironmentMarker::cast(instr); | |
98 int index = marker->index(); | |
99 if (!live_->Contains(index)) { | |
100 marker->SetFlag(HValue::kEndsLiveRange); | |
101 } else { | |
102 marker->ClearFlag(HValue::kEndsLiveRange); | |
103 } | |
104 if (!went_live_since_last_simulate_->Contains(index)) { | |
105 marker->set_next_simulate(last_simulate_); | |
106 } | |
107 if (marker->kind() == HEnvironmentMarker::LOOKUP) { | |
108 live_->Add(index); | |
109 } else { | |
110 ASSERT(marker->kind() == HEnvironmentMarker::BIND); | |
111 live_->Remove(index); | |
112 went_live_since_last_simulate_->Add(index); | |
113 } | |
114 if (collect_markers_) { | |
titzer
2013/05/29 16:58:05
This is a little tricky; maybe a comment that we o
Jakob Kummerow
2013/06/03 17:50:38
Done.
| |
115 markers_->Add(marker, &zone_); | |
116 } | |
117 break; | |
118 } | |
119 case HValue::kLeaveInlined: | |
120 // No environment values are live at the end of an inlined section. | |
121 live_->Clear(); | |
122 last_simulate_ = NULL; | |
123 | |
124 // The following ASSERTs guard the assumption used in case | |
125 // kEnterInlined below: | |
126 ASSERT(instr->next()->IsSimulate()); | |
127 ASSERT(instr->next()->next()->IsGoto()); | |
128 | |
129 break; | |
130 case HValue::kEnterInlined: { | |
131 // Those environment values are live that are live at any return | |
132 // target block. Here we make use of the fact that the end of an | |
133 // inline sequence always looks like this: HLeaveInlined, HSimulate, | |
134 // HGoto (to return_target block), with no environment lookups in | |
135 // between (see ASSERTs above). | |
136 HEnterInlined* enter = HEnterInlined::cast(instr); | |
137 live_->Clear(); | |
138 for (int i = 0; i < enter->return_targets()->length(); ++i) { | |
139 int return_id = enter->return_targets()->at(i)->block_id(); | |
140 // When an AbnormalExit is involved, it can happen that the return | |
141 // target block doesn't actually exist. | |
142 if (return_id < live_at_block_start_->length()) { | |
143 live_->Union(*live_at_block_start_->at(return_id)); | |
144 } | |
145 } | |
146 last_simulate_ = NULL; | |
147 break; | |
148 } | |
149 case HValue::kDeoptimize: { | |
titzer
2013/05/29 16:58:05
What about kSoftDeoptimize?
Jakob Kummerow
2013/06/03 17:50:38
Usage is different.
HSoftDeoptimize instructions d
| |
150 // Keep all environment slots alive. | |
151 HDeoptimize* deopt = HDeoptimize::cast(instr); | |
152 for (int i = deopt->first_local_index(); | |
153 i < deopt->first_expression_index(); ++i) { | |
154 live_->Add(i); | |
155 } | |
156 break; | |
157 } | |
158 case HValue::kSimulate: | |
159 last_simulate_ = HSimulate::cast(instr); | |
160 went_live_since_last_simulate_->Clear(); | |
161 break; | |
162 default: | |
163 break; | |
164 } | |
165 } | |
166 | |
167 | |
168 // Values in the environment are kept alive by every subsequent LInstruction | |
titzer
2013/05/29 16:58:05
Some reordering of the sentences might make this p
Jakob Kummerow
2013/06/03 17:50:38
Done, and moved to the class, where this comment r
| |
169 // that is assigned an LEnvironment. This creates register pressure and | |
170 // unnecessary spill slot moves. Therefore it is beneficial to trim the | |
171 // live ranges of environment slots by zapping them with a constant after | |
172 // the last lookup that refers to them. This is similar but not identical | |
173 // to live range analysis for HValues, so we perform an explicit liveness | |
174 // analysis on environment slots (identified by their index). | |
175 // This only affects slots whitelisted by | |
176 // HOptimizedGraphBuilder::IsEligibleForEnvironmentLivenessAnalysis(). | |
177 void EnvironmentSlotLivenessAnalysis::AnalyzeAndPrune() { | |
178 HPhase phase("H_EnvironmentLivenessAnalysis", graph_); | |
179 if (maximum_environment_size_ == 0) return; | |
180 | |
181 // Main iteration. Compute liveness of environment slots, and store it | |
182 // for each block until it doesn't change any more. For efficiency, visit | |
183 // blocks in reverse order and walk backwards through each block. We | |
184 // need several iterations to propagate liveness through nested loops. | |
185 BitVector* worklist = new(zone()) BitVector(block_count_, zone()); | |
186 for (int i = 0; i < block_count_; ++i) { | |
187 worklist->Add(i); | |
188 } | |
189 while (!worklist->IsEmpty()) { | |
190 for (int block_id = block_count_ - 1; block_id >= 0; --block_id) { | |
191 if (!worklist->Contains(block_id)) { | |
192 continue; | |
193 } | |
194 worklist->Remove(block_id); | |
195 last_simulate_ = NULL; | |
196 | |
197 HBasicBlock* block = graph_->blocks()->at(block_id); | |
198 UpdateLivenessAtBlockEnd(block); | |
199 | |
200 for (HInstruction* instr = block->last(); instr != NULL; | |
201 instr = instr->previous()) { | |
202 UpdateLivenessAtInstruction(instr); | |
203 } | |
204 | |
205 // Reached the start of the block, do necessary bookkeeping. | |
titzer
2013/05/29 16:58:05
Explain bookkeeping steps. E.g. "propagate livenes
Jakob Kummerow
2013/06/03 17:50:38
Done.
| |
206 first_simulate_->Set(block_id, last_simulate_); | |
207 first_simulate_invalid_for_index_->at(block_id)->CopyFrom( | |
208 *went_live_since_last_simulate_); | |
209 if (live_at_block_start_->at(block_id)->UnionIsChanged(*live_)) { | |
210 for (int i = 0; i < block->predecessors()->length(); ++i) { | |
211 worklist->Add(block->predecessors()->at(i)->block_id()); | |
212 } | |
213 if (block->IsInlineReturnTarget()) { | |
214 worklist->Add(block->inlined_entry_block()->block_id()); | |
215 } | |
216 } | |
217 } | |
218 // Only collect bind/lookup instructions during the first pass. | |
219 collect_markers_ = false; | |
220 } | |
221 | |
222 // Analysis finished. Zap dead environment slots. | |
223 for (int i = 0; i < markers_->length(); ++i) { | |
224 ZapEnvironmentSlotsForInstruction(markers_->at(i)); | |
225 } | |
226 for (int block_id = block_count_ - 1; block_id >= 0; --block_id) { | |
227 HBasicBlock* block = graph_->blocks()->at(block_id); | |
228 UpdateLivenessAtBlockEnd(block); | |
229 ZapEnvironmentSlotsInSuccessors(block); | |
230 } | |
231 | |
232 // Finally, remove the HEnvironment{Bind,Lookup} markers. | |
233 for (int i = 0; i < markers_->length(); ++i) { | |
234 markers_->at(i)->DeleteAndReplaceWith(NULL); | |
235 } | |
236 } | |
237 | |
238 } } // namespace v8::internal | |
OLD | NEW |