Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(297)

Side by Side Diff: src/compiler/bytecode-analysis.cc

Issue 2536653003: [ignition] Rewrite reverse iterator as random iterator (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/bytecode-analysis.h" 5 #include "src/compiler/bytecode-analysis.h"
6 6
7 #include "src/interpreter/bytecode-array-iterator.h" 7 #include "src/interpreter/bytecode-array-iterator.h"
8 #include "src/interpreter/bytecode-array-reverse-iterator.h" 8 #include "src/interpreter/bytecode-array-random-iterator.h"
9 #include "src/objects-inl.h" 9 #include "src/objects-inl.h"
10 10
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 namespace compiler { 13 namespace compiler {
14 14
15 using namespace interpreter; 15 using namespace interpreter;
16 16
17 BytecodeAnalysis::BytecodeAnalysis(Handle<BytecodeArray> bytecode_array, 17 BytecodeAnalysis::BytecodeAnalysis(Handle<BytecodeArray> bytecode_array,
18 Zone* zone, bool do_liveness_analysis) 18 Zone* zone, bool do_liveness_analysis)
19 : bytecode_array_(bytecode_array), 19 : bytecode_array_(bytecode_array),
20 do_liveness_analysis_(do_liveness_analysis), 20 do_liveness_analysis_(do_liveness_analysis),
21 zone_(zone), 21 zone_(zone),
22 loop_stack_(zone), 22 loop_stack_(zone),
23 loop_end_index_queue_(zone),
23 end_to_header_(zone), 24 end_to_header_(zone),
24 header_to_parent_(zone), 25 header_to_parent_(zone),
25 liveness_map_(bytecode_array->length(), zone) {} 26 liveness_map_(bytecode_array->length(), zone) {}
26 27
27 namespace { 28 namespace {
28 29
29 void UpdateInLiveness(Bytecode bytecode, BitVector& in_liveness, 30 void UpdateInLiveness(Bytecode bytecode, BitVector& in_liveness,
30 const BytecodeArrayAccessor& accessor) { 31 const BytecodeArrayAccessor& accessor) {
31 int num_operands = Bytecodes::NumberOfOperands(bytecode); 32 int num_operands = Bytecodes::NumberOfOperands(bytecode);
32 const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode); 33 const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 out_liveness.Add(handler_context); 142 out_liveness.Add(handler_context);
142 } 143 }
143 } 144 }
144 } 145 }
145 146
146 } // namespace 147 } // namespace
147 148
148 void BytecodeAnalysis::Analyze() { 149 void BytecodeAnalysis::Analyze() {
149 loop_stack_.push(-1); 150 loop_stack_.push(-1);
150 151
151 // The last JumpLoop that we haven't done a guaranteed valid liveness pass 152 BytecodeArrayRandomIterator iterator(bytecode_array(), zone());
152 // over. See the below wall of text for a more thorough explanation. 153 for (iterator.GoToEnd(); iterator.Valid(); --iterator) {
153 int last_invalid_jumploop_offset = -1;
154
155 BytecodeArrayReverseIterator iterator(bytecode_array(), zone());
156 for (; !iterator.done(); iterator.Advance()) {
157 Bytecode bytecode = iterator.current_bytecode(); 154 Bytecode bytecode = iterator.current_bytecode();
158 int current_offset = iterator.current_offset(); 155 int current_offset = iterator.current_offset();
159 156
160 if (bytecode == Bytecode::kJumpLoop) { 157 if (bytecode == Bytecode::kJumpLoop) {
161 PushLoop(iterator.GetJumpTargetOffset(), current_offset); 158 PushLoop(iterator.GetJumpTargetOffset(), current_offset);
162 159
163 // Save the last offset so that we can do another pass later. 160 // Save the index so that we can do another pass later.
164 if (last_invalid_jumploop_offset == -1) { 161 if (do_liveness_analysis_) {
165 last_invalid_jumploop_offset = current_offset; 162 loop_end_index_queue_.push_back(iterator.current_index());
166 } 163 }
167 } else if (current_offset == loop_stack_.top()) { 164 } else if (current_offset == loop_stack_.top()) {
168 loop_stack_.pop(); 165 loop_stack_.pop();
169 } 166 }
170 167
171 if (do_liveness_analysis_) { 168 if (do_liveness_analysis_) {
172 // The liveness vector had bits for the liveness of the registers, and one 169 // The liveness vector had bits for the liveness of the registers, and one
173 // more bit for the liveness of the accumulator. 170 // more bit for the liveness of the accumulator.
174 Liveness& liveness = liveness_map_.InitializeLiveness( 171 Liveness& liveness = liveness_map_.InitializeLiveness(
175 current_offset, bytecode_array()->register_count() + 1, zone()); 172 current_offset, bytecode_array()->register_count() + 1, zone());
(...skipping 22 matching lines...) Expand all
198 // So, if we know that the liveness of bytecodes after a loop header won't 195 // So, if we know that the liveness of bytecodes after a loop header won't
199 // change (e.g. because there are no loops in them, or we have already ensured 196 // change (e.g. because there are no loops in them, or we have already ensured
200 // those loops are valid), we can safely update the loop end and pass over the 197 // those loops are valid), we can safely update the loop end and pass over the
201 // loop body, and then never have to pass over that loop end again, because we 198 // loop body, and then never have to pass over that loop end again, because we
202 // have shown that its target, the loop header, can't change from the entries 199 // have shown that its target, the loop header, can't change from the entries
203 // after the loop, and can't change from any loop body pass. 200 // after the loop, and can't change from any loop body pass.
204 // 201 //
205 // This means that in a pass, we can iterate backwards over the bytecode 202 // This means that in a pass, we can iterate backwards over the bytecode
206 // array, process any loops that we encounter, and on subsequent passes we can 203 // array, process any loops that we encounter, and on subsequent passes we can
207 // skip processing those loops (though we still have to process inner loops). 204 // skip processing those loops (though we still have to process inner loops).
205 //
206 // Equivalently, we can queue up loop ends from back to front, and pass over
207 // the loops in that order, as this preserves both the bottom-to-top and
208 // outer-to-inner requirements.
208 209
209 while (last_invalid_jumploop_offset != -1) { 210 for (int loop_end_index : loop_end_index_queue_) {
210 // TODO(leszeks): We shouldn't need to iterate here, we should just have a 211 iterator.GoToIndex(loop_end_index);
211 // random access iterator.
212 iterator.Reset();
213 while (last_invalid_jumploop_offset < iterator.current_offset()) {
214 iterator.Advance();
215 }
216 last_invalid_jumploop_offset = -1;
217 212
218 DCHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); 213 DCHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
219 214
220 for (; !iterator.done(); iterator.Advance()) { 215 int header_offset = iterator.GetJumpTargetOffset();
216 int end_offset = iterator.current_offset();
217
218 Liveness& header_liveness = liveness_map_.GetLiveness(header_offset);
219 Liveness& end_liveness = liveness_map_.GetLiveness(end_offset);
220
221 if (!end_liveness.out->UnionIsChanged(*header_liveness.in)) {
222 // Only update the loop body if the loop end liveness changed.
223 continue;
224 }
225 end_liveness.in->CopyFrom(*end_liveness.out);
226
227 // Advance into the loop body.
228 --iterator;
229 for (; iterator.current_offset() > header_offset; --iterator) {
221 Bytecode bytecode = iterator.current_bytecode(); 230 Bytecode bytecode = iterator.current_bytecode();
222 if (bytecode != Bytecode::kJumpLoop) {
223 // Skip bytecodes until we hit a JumpLoop. This check isn't needed for
224 // the first loop we see (thanks to saving its offset), but it is for
225 // subsequent ones we want to process on this pass.
226 continue;
227 }
228 231
229 int header_offset = iterator.GetJumpTargetOffset(); 232 int current_offset = iterator.current_offset();
230 int end_offset = iterator.current_offset(); 233 Liveness& liveness = liveness_map_.GetLiveness(current_offset);
231 234
232 Liveness& header_liveness = liveness_map_.GetLiveness(header_offset); 235 UpdateOutLiveness(bytecode, *liveness.out, iterator, liveness_map_);
233 Liveness& end_liveness = liveness_map_.GetLiveness(end_offset); 236 liveness.in->CopyFrom(*liveness.out);
234 237 UpdateInLiveness(bytecode, *liveness.in, iterator);
235 if (end_liveness.out->UnionIsChanged(*header_liveness.in)) {
236 // Only update the loop body if the loop end liveness changed.
237 end_liveness.in->CopyFrom(*end_liveness.out);
238
239 // Advance into the loop body.
240 iterator.Advance();
241 for (; iterator.current_offset() > header_offset; iterator.Advance()) {
242 bytecode = iterator.current_bytecode();
243 if (bytecode == Bytecode::kJumpLoop) {
244 // We can't validate this loop at the moment because we can't
245 // guarantee that its header is valid yet. Save it for later.
246 if (last_invalid_jumploop_offset == -1) {
247 last_invalid_jumploop_offset = iterator.current_offset();
248 }
249 }
250
251 int current_offset = iterator.current_offset();
252 Liveness& liveness = liveness_map_.GetLiveness(current_offset);
253
254 UpdateOutLiveness(bytecode, *liveness.out, iterator, liveness_map_);
255 liveness.in->CopyFrom(*liveness.out);
256 UpdateInLiveness(bytecode, *liveness.in, iterator);
257 }
258 // Now we are at the loop header. Since the in-liveness of the header
259 // can't change, we need only to update the out-liveness.
260 bytecode = iterator.current_bytecode();
261 UpdateOutLiveness(bytecode, *header_liveness.out, iterator,
262 liveness_map_);
263 }
264
265 // Keep the iterator going so that we can find other loops.
266 } 238 }
239 // Now we are at the loop header. Since the in-liveness of the header
240 // can't change, we need only to update the out-liveness.
241 UpdateOutLiveness(iterator.current_bytecode(), *header_liveness.out,
242 iterator, liveness_map_);
267 } 243 }
268 244
269 DCHECK(LivenessIsValid()); 245 DCHECK(LivenessIsValid());
270 } 246 }
271 247
272 void BytecodeAnalysis::PushLoop(int loop_header, int loop_end) { 248 void BytecodeAnalysis::PushLoop(int loop_header, int loop_end) {
273 DCHECK(loop_header < loop_end); 249 DCHECK(loop_header < loop_end);
274 DCHECK(loop_stack_.top() < loop_header); 250 DCHECK(loop_stack_.top() < loop_header);
275 DCHECK(end_to_header_.find(loop_end) == end_to_header_.end()); 251 DCHECK(end_to_header_.find(loop_end) == end_to_header_.end());
276 DCHECK(header_to_parent_.find(loop_header) == header_to_parent_.end()); 252 DCHECK(header_to_parent_.find(loop_header) == header_to_parent_.end());
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 332
357 os << " | " << current_offset << ": "; 333 os << " | " << current_offset << ": ";
358 iterator.PrintTo(os) << std::endl; 334 iterator.PrintTo(os) << std::endl;
359 } 335 }
360 336
361 return os; 337 return os;
362 } 338 }
363 339
364 #if DEBUG 340 #if DEBUG
365 bool BytecodeAnalysis::LivenessIsValid() { 341 bool BytecodeAnalysis::LivenessIsValid() {
366 BytecodeArrayReverseIterator iterator(bytecode_array(), zone()); 342 BytecodeArrayRandomIterator iterator(bytecode_array(), zone());
367 343
368 BitVector previous_liveness(bytecode_array()->register_count() + 1, zone()); 344 BitVector previous_liveness(bytecode_array()->register_count() + 1, zone());
369 345
370 int invalid_offset = -1; 346 int invalid_offset = -1;
371 int which_invalid = -1; 347 int which_invalid = -1;
372 348
373 // Ensure that there are no liveness changes if we iterate one more time. 349 // Ensure that there are no liveness changes if we iterate one more time.
374 for (iterator.Reset(); !iterator.done(); iterator.Advance()) { 350 for (iterator.GoToEnd(); iterator.Valid(); --iterator) {
375 Bytecode bytecode = iterator.current_bytecode(); 351 Bytecode bytecode = iterator.current_bytecode();
376 352
377 int current_offset = iterator.current_offset(); 353 int current_offset = iterator.current_offset();
378 354
379 Liveness& liveness = liveness_map_.GetLiveness(current_offset); 355 Liveness& liveness = liveness_map_.GetLiveness(current_offset);
380 356
381 previous_liveness.CopyFrom(*liveness.out); 357 previous_liveness.CopyFrom(*liveness.out);
382 358
383 UpdateOutLiveness(bytecode, *liveness.out, iterator, liveness_map_); 359 UpdateOutLiveness(bytecode, *liveness.out, iterator, liveness_map_);
384 // UpdateOutLiveness skips kJumpLoop, so we update it manually. 360 // UpdateOutLiveness skips kJumpLoop, so we update it manually.
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 } 453 }
478 } 454 }
479 455
480 return invalid_offset == -1; 456 return invalid_offset == -1;
481 } 457 }
482 #endif 458 #endif
483 459
484 } // namespace compiler 460 } // namespace compiler
485 } // namespace internal 461 } // namespace internal
486 } // namespace v8 462 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698