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

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

Issue 2536653003: [ignition] Rewrite reverse iterator as random iterator (Closed)
Patch Set: Rebase 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
« no previous file with comments | « src/compiler/bytecode-analysis.h ('k') | src/interpreter/bytecode-array-random-iterator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 } 145 }
145 } 146 }
146 147
147 } // namespace 148 } // namespace
148 149
149 void BytecodeAnalysis::Analyze() { 150 void BytecodeAnalysis::Analyze() {
150 loop_stack_.push(-1); 151 loop_stack_.push(-1);
151 152
152 BitVector* next_bytecode_in_liveness = nullptr; 153 BitVector* next_bytecode_in_liveness = nullptr;
153 154
154 // The last JumpLoop that we haven't done a guaranteed valid liveness pass 155 BytecodeArrayRandomIterator iterator(bytecode_array(), zone());
155 // over. See the below wall of text for a more thorough explanation. 156 for (iterator.GoToEnd(); iterator.IsValid(); --iterator) {
156 int last_invalid_jumploop_offset = -1;
157
158 BytecodeArrayReverseIterator iterator(bytecode_array(), zone());
159 for (; !iterator.done(); iterator.Advance()) {
160 Bytecode bytecode = iterator.current_bytecode(); 157 Bytecode bytecode = iterator.current_bytecode();
161 int current_offset = iterator.current_offset(); 158 int current_offset = iterator.current_offset();
162 159
163 if (bytecode == Bytecode::kJumpLoop) { 160 if (bytecode == Bytecode::kJumpLoop) {
164 // Every byte up to and including the last byte within the backwards jump 161 // Every byte up to and including the last byte within the backwards jump
165 // instruction is considered part of the loop, set loop end accordingly. 162 // instruction is considered part of the loop, set loop end accordingly.
166 int loop_end = current_offset + iterator.current_bytecode_size(); 163 int loop_end = current_offset + iterator.current_bytecode_size();
167 PushLoop(iterator.GetJumpTargetOffset(), loop_end); 164 PushLoop(iterator.GetJumpTargetOffset(), loop_end);
168 165
169 // Save the last offset so that we can do another pass later. 166 // Save the index so that we can do another pass later.
170 if (last_invalid_jumploop_offset == -1) { 167 if (do_liveness_analysis_) {
171 last_invalid_jumploop_offset = current_offset; 168 loop_end_index_queue_.push_back(iterator.current_index());
172 } 169 }
173 } else if (current_offset == loop_stack_.top()) { 170 } else if (current_offset == loop_stack_.top()) {
174 loop_stack_.pop(); 171 loop_stack_.pop();
175 } 172 }
176 173
177 if (do_liveness_analysis_) { 174 if (do_liveness_analysis_) {
178 // The liveness vector had bits for the liveness of the registers, and one 175 // The liveness vector had bits for the liveness of the registers, and one
179 // more bit for the liveness of the accumulator. 176 // more bit for the liveness of the accumulator.
180 Liveness& liveness = liveness_map_.InitializeLiveness( 177 Liveness& liveness = liveness_map_.InitializeLiveness(
181 current_offset, bytecode_array()->register_count() + 1, zone()); 178 current_offset, bytecode_array()->register_count() + 1, zone());
(...skipping 25 matching lines...) Expand all
207 // So, if we know that the liveness of bytecodes after a loop header won't 204 // So, if we know that the liveness of bytecodes after a loop header won't
208 // change (e.g. because there are no loops in them, or we have already ensured 205 // change (e.g. because there are no loops in them, or we have already ensured
209 // those loops are valid), we can safely update the loop end and pass over the 206 // those loops are valid), we can safely update the loop end and pass over the
210 // loop body, and then never have to pass over that loop end again, because we 207 // loop body, and then never have to pass over that loop end again, because we
211 // have shown that its target, the loop header, can't change from the entries 208 // have shown that its target, the loop header, can't change from the entries
212 // after the loop, and can't change from any loop body pass. 209 // after the loop, and can't change from any loop body pass.
213 // 210 //
214 // This means that in a pass, we can iterate backwards over the bytecode 211 // This means that in a pass, we can iterate backwards over the bytecode
215 // array, process any loops that we encounter, and on subsequent passes we can 212 // array, process any loops that we encounter, and on subsequent passes we can
216 // skip processing those loops (though we still have to process inner loops). 213 // skip processing those loops (though we still have to process inner loops).
214 //
215 // Equivalently, we can queue up loop ends from back to front, and pass over
216 // the loops in that order, as this preserves both the bottom-to-top and
217 // outer-to-inner requirements.
217 218
218 while (last_invalid_jumploop_offset != -1) { 219 for (int loop_end_index : loop_end_index_queue_) {
219 // TODO(leszeks): We shouldn't need to iterate here, we should just have a 220 iterator.GoToIndex(loop_end_index);
220 // random access iterator.
221 iterator.Reset();
222 while (last_invalid_jumploop_offset < iterator.current_offset()) {
223 iterator.Advance();
224 }
225 last_invalid_jumploop_offset = -1;
226 221
227 DCHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); 222 DCHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
228 223
229 for (; !iterator.done(); iterator.Advance()) { 224 int header_offset = iterator.GetJumpTargetOffset();
225 int end_offset = iterator.current_offset();
226
227 Liveness& header_liveness = liveness_map_.GetLiveness(header_offset);
228 Liveness& end_liveness = liveness_map_.GetLiveness(end_offset);
229
230 if (!end_liveness.out->UnionIsChanged(*header_liveness.in)) {
231 // Only update the loop body if the loop end liveness changed.
232 continue;
233 }
234 end_liveness.in->CopyFrom(*end_liveness.out);
235 next_bytecode_in_liveness = end_liveness.in;
236
237 // Advance into the loop body.
238 --iterator;
239 for (; iterator.current_offset() > header_offset; --iterator) {
230 Bytecode bytecode = iterator.current_bytecode(); 240 Bytecode bytecode = iterator.current_bytecode();
231 if (bytecode != Bytecode::kJumpLoop) {
232 // Skip bytecodes until we hit a JumpLoop. This check isn't needed for
233 // the first loop we see (thanks to saving its offset), but it is for
234 // subsequent ones we want to process on this pass.
235 continue;
236 }
237 241
238 int header_offset = iterator.GetJumpTargetOffset(); 242 int current_offset = iterator.current_offset();
239 int end_offset = iterator.current_offset(); 243 Liveness& liveness = liveness_map_.GetLiveness(current_offset);
240 244
241 Liveness& header_liveness = liveness_map_.GetLiveness(header_offset); 245 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness,
242 Liveness& end_liveness = liveness_map_.GetLiveness(end_offset); 246 iterator, liveness_map_);
247 liveness.in->CopyFrom(*liveness.out);
248 UpdateInLiveness(bytecode, *liveness.in, iterator);
243 249
244 if (end_liveness.out->UnionIsChanged(*header_liveness.in)) { 250 next_bytecode_in_liveness = liveness.in;
245 // Only update the loop body if the loop end liveness changed.
246 end_liveness.in->CopyFrom(*end_liveness.out);
247 next_bytecode_in_liveness = end_liveness.in;
248
249 // Advance into the loop body.
250 iterator.Advance();
251 for (; iterator.current_offset() > header_offset; iterator.Advance()) {
252 bytecode = iterator.current_bytecode();
253 if (bytecode == Bytecode::kJumpLoop) {
254 // We can't validate this loop at the moment because we can't
255 // guarantee that its header is valid yet. Save it for later.
256 if (last_invalid_jumploop_offset == -1) {
257 last_invalid_jumploop_offset = iterator.current_offset();
258 }
259 }
260
261 int current_offset = iterator.current_offset();
262 Liveness& liveness = liveness_map_.GetLiveness(current_offset);
263
264 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness,
265 iterator, liveness_map_);
266 liveness.in->CopyFrom(*liveness.out);
267 UpdateInLiveness(bytecode, *liveness.in, iterator);
268
269 next_bytecode_in_liveness = liveness.in;
270 }
271 // Now we are at the loop header. Since the in-liveness of the header
272 // can't change, we need only to update the out-liveness.
273 bytecode = iterator.current_bytecode();
274 UpdateOutLiveness(bytecode, *header_liveness.out,
275 next_bytecode_in_liveness, iterator, liveness_map_);
276 }
277
278 // Keep the iterator going so that we can find other loops.
279 } 251 }
252 // Now we are at the loop header. Since the in-liveness of the header
253 // can't change, we need only to update the out-liveness.
254 UpdateOutLiveness(iterator.current_bytecode(), *header_liveness.out,
255 next_bytecode_in_liveness, iterator, liveness_map_);
280 } 256 }
281 257
282 DCHECK(LivenessIsValid()); 258 DCHECK(LivenessIsValid());
283 } 259 }
284 260
285 void BytecodeAnalysis::PushLoop(int loop_header, int loop_end) { 261 void BytecodeAnalysis::PushLoop(int loop_header, int loop_end) {
286 DCHECK(loop_header < loop_end); 262 DCHECK(loop_header < loop_end);
287 DCHECK(loop_stack_.top() < loop_header); 263 DCHECK(loop_stack_.top() < loop_header);
288 DCHECK(end_to_header_.find(loop_end) == end_to_header_.end()); 264 DCHECK(end_to_header_.find(loop_end) == end_to_header_.end());
289 DCHECK(header_to_parent_.find(loop_header) == header_to_parent_.end()); 265 DCHECK(header_to_parent_.find(loop_header) == header_to_parent_.end());
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 345
370 os << " | " << current_offset << ": "; 346 os << " | " << current_offset << ": ";
371 iterator.PrintTo(os) << std::endl; 347 iterator.PrintTo(os) << std::endl;
372 } 348 }
373 349
374 return os; 350 return os;
375 } 351 }
376 352
377 #if DEBUG 353 #if DEBUG
378 bool BytecodeAnalysis::LivenessIsValid() { 354 bool BytecodeAnalysis::LivenessIsValid() {
379 BytecodeArrayReverseIterator iterator(bytecode_array(), zone()); 355 BytecodeArrayRandomIterator iterator(bytecode_array(), zone());
380 356
381 BitVector previous_liveness(bytecode_array()->register_count() + 1, zone()); 357 BitVector previous_liveness(bytecode_array()->register_count() + 1, zone());
382 358
383 int invalid_offset = -1; 359 int invalid_offset = -1;
384 int which_invalid = -1; 360 int which_invalid = -1;
385 361
386 BitVector* next_bytecode_in_liveness = nullptr; 362 BitVector* next_bytecode_in_liveness = nullptr;
387 363
388 // Ensure that there are no liveness changes if we iterate one more time. 364 // Ensure that there are no liveness changes if we iterate one more time.
389 for (iterator.Reset(); !iterator.done(); iterator.Advance()) { 365 for (iterator.GoToEnd(); iterator.IsValid(); --iterator) {
390 Bytecode bytecode = iterator.current_bytecode(); 366 Bytecode bytecode = iterator.current_bytecode();
391 367
392 int current_offset = iterator.current_offset(); 368 int current_offset = iterator.current_offset();
393 369
394 Liveness& liveness = liveness_map_.GetLiveness(current_offset); 370 Liveness& liveness = liveness_map_.GetLiveness(current_offset);
395 371
396 previous_liveness.CopyFrom(*liveness.out); 372 previous_liveness.CopyFrom(*liveness.out);
397 373
398 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness, 374 UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness,
399 iterator, liveness_map_); 375 iterator, liveness_map_);
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 } 471 }
496 } 472 }
497 473
498 return invalid_offset == -1; 474 return invalid_offset == -1;
499 } 475 }
500 #endif 476 #endif
501 477
502 } // namespace compiler 478 } // namespace compiler
503 } // namespace internal 479 } // namespace internal
504 } // namespace v8 480 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/bytecode-analysis.h ('k') | src/interpreter/bytecode-array-random-iterator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698