Index: src/compiler/bytecode-analysis.cc |
diff --git a/src/compiler/bytecode-analysis.cc b/src/compiler/bytecode-analysis.cc |
index 8d077abc9f519eb0090726be60b9705e73f484e2..40e4563894b2f90b917bcf753b3505ba86bf4553 100644 |
--- a/src/compiler/bytecode-analysis.cc |
+++ b/src/compiler/bytecode-analysis.cc |
@@ -5,7 +5,7 @@ |
#include "src/compiler/bytecode-analysis.h" |
#include "src/interpreter/bytecode-array-iterator.h" |
-#include "src/interpreter/bytecode-array-reverse-iterator.h" |
+#include "src/interpreter/bytecode-array-random-iterator.h" |
#include "src/objects-inl.h" |
namespace v8 { |
@@ -20,6 +20,7 @@ BytecodeAnalysis::BytecodeAnalysis(Handle<BytecodeArray> bytecode_array, |
do_liveness_analysis_(do_liveness_analysis), |
zone_(zone), |
loop_stack_(zone), |
+ loop_end_index_queue_(zone), |
end_to_header_(zone), |
header_to_parent_(zone), |
liveness_map_(bytecode_array->length(), zone) {} |
@@ -151,12 +152,8 @@ void BytecodeAnalysis::Analyze() { |
BitVector* next_bytecode_in_liveness = nullptr; |
- // The last JumpLoop that we haven't done a guaranteed valid liveness pass |
- // over. See the below wall of text for a more thorough explanation. |
- int last_invalid_jumploop_offset = -1; |
- |
- BytecodeArrayReverseIterator iterator(bytecode_array(), zone()); |
- for (; !iterator.done(); iterator.Advance()) { |
+ BytecodeArrayRandomIterator iterator(bytecode_array(), zone()); |
+ for (iterator.GoToEnd(); iterator.IsValid(); --iterator) { |
Bytecode bytecode = iterator.current_bytecode(); |
int current_offset = iterator.current_offset(); |
@@ -166,9 +163,9 @@ void BytecodeAnalysis::Analyze() { |
int loop_end = current_offset + iterator.current_bytecode_size(); |
PushLoop(iterator.GetJumpTargetOffset(), loop_end); |
- // Save the last offset so that we can do another pass later. |
- if (last_invalid_jumploop_offset == -1) { |
- last_invalid_jumploop_offset = current_offset; |
+ // Save the index so that we can do another pass later. |
+ if (do_liveness_analysis_) { |
+ loop_end_index_queue_.push_back(iterator.current_index()); |
} |
} else if (current_offset == loop_stack_.top()) { |
loop_stack_.pop(); |
@@ -214,69 +211,48 @@ void BytecodeAnalysis::Analyze() { |
// This means that in a pass, we can iterate backwards over the bytecode |
// array, process any loops that we encounter, and on subsequent passes we can |
// skip processing those loops (though we still have to process inner loops). |
+ // |
+ // Equivalently, we can queue up loop ends from back to front, and pass over |
+ // the loops in that order, as this preserves both the bottom-to-top and |
+ // outer-to-inner requirements. |
- while (last_invalid_jumploop_offset != -1) { |
- // TODO(leszeks): We shouldn't need to iterate here, we should just have a |
- // random access iterator. |
- iterator.Reset(); |
- while (last_invalid_jumploop_offset < iterator.current_offset()) { |
- iterator.Advance(); |
- } |
- last_invalid_jumploop_offset = -1; |
+ for (int loop_end_index : loop_end_index_queue_) { |
+ iterator.GoToIndex(loop_end_index); |
DCHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); |
- for (; !iterator.done(); iterator.Advance()) { |
- Bytecode bytecode = iterator.current_bytecode(); |
- if (bytecode != Bytecode::kJumpLoop) { |
- // Skip bytecodes until we hit a JumpLoop. This check isn't needed for |
- // the first loop we see (thanks to saving its offset), but it is for |
- // subsequent ones we want to process on this pass. |
- continue; |
- } |
+ int header_offset = iterator.GetJumpTargetOffset(); |
+ int end_offset = iterator.current_offset(); |
- int header_offset = iterator.GetJumpTargetOffset(); |
- int end_offset = iterator.current_offset(); |
- |
- Liveness& header_liveness = liveness_map_.GetLiveness(header_offset); |
- Liveness& end_liveness = liveness_map_.GetLiveness(end_offset); |
- |
- if (end_liveness.out->UnionIsChanged(*header_liveness.in)) { |
- // Only update the loop body if the loop end liveness changed. |
- end_liveness.in->CopyFrom(*end_liveness.out); |
- next_bytecode_in_liveness = end_liveness.in; |
- |
- // Advance into the loop body. |
- iterator.Advance(); |
- for (; iterator.current_offset() > header_offset; iterator.Advance()) { |
- bytecode = iterator.current_bytecode(); |
- if (bytecode == Bytecode::kJumpLoop) { |
- // We can't validate this loop at the moment because we can't |
- // guarantee that its header is valid yet. Save it for later. |
- if (last_invalid_jumploop_offset == -1) { |
- last_invalid_jumploop_offset = iterator.current_offset(); |
- } |
- } |
+ Liveness& header_liveness = liveness_map_.GetLiveness(header_offset); |
+ Liveness& end_liveness = liveness_map_.GetLiveness(end_offset); |
- int current_offset = iterator.current_offset(); |
- Liveness& liveness = liveness_map_.GetLiveness(current_offset); |
+ if (!end_liveness.out->UnionIsChanged(*header_liveness.in)) { |
+ // Only update the loop body if the loop end liveness changed. |
+ continue; |
+ } |
+ end_liveness.in->CopyFrom(*end_liveness.out); |
+ next_bytecode_in_liveness = end_liveness.in; |
- UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness, |
- iterator, liveness_map_); |
- liveness.in->CopyFrom(*liveness.out); |
- UpdateInLiveness(bytecode, *liveness.in, iterator); |
+ // Advance into the loop body. |
+ --iterator; |
+ for (; iterator.current_offset() > header_offset; --iterator) { |
+ Bytecode bytecode = iterator.current_bytecode(); |
- next_bytecode_in_liveness = liveness.in; |
- } |
- // Now we are at the loop header. Since the in-liveness of the header |
- // can't change, we need only to update the out-liveness. |
- bytecode = iterator.current_bytecode(); |
- UpdateOutLiveness(bytecode, *header_liveness.out, |
- next_bytecode_in_liveness, iterator, liveness_map_); |
- } |
+ int current_offset = iterator.current_offset(); |
+ Liveness& liveness = liveness_map_.GetLiveness(current_offset); |
+ |
+ UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness, |
+ iterator, liveness_map_); |
+ liveness.in->CopyFrom(*liveness.out); |
+ UpdateInLiveness(bytecode, *liveness.in, iterator); |
- // Keep the iterator going so that we can find other loops. |
+ next_bytecode_in_liveness = liveness.in; |
} |
+ // Now we are at the loop header. Since the in-liveness of the header |
+ // can't change, we need only to update the out-liveness. |
+ UpdateOutLiveness(iterator.current_bytecode(), *header_liveness.out, |
+ next_bytecode_in_liveness, iterator, liveness_map_); |
} |
DCHECK(LivenessIsValid()); |
@@ -376,7 +352,7 @@ std::ostream& BytecodeAnalysis::PrintLivenessTo(std::ostream& os) const { |
#if DEBUG |
bool BytecodeAnalysis::LivenessIsValid() { |
- BytecodeArrayReverseIterator iterator(bytecode_array(), zone()); |
+ BytecodeArrayRandomIterator iterator(bytecode_array(), zone()); |
BitVector previous_liveness(bytecode_array()->register_count() + 1, zone()); |
@@ -386,7 +362,7 @@ bool BytecodeAnalysis::LivenessIsValid() { |
BitVector* next_bytecode_in_liveness = nullptr; |
// Ensure that there are no liveness changes if we iterate one more time. |
- for (iterator.Reset(); !iterator.done(); iterator.Advance()) { |
+ for (iterator.GoToEnd(); iterator.IsValid(); --iterator) { |
Bytecode bytecode = iterator.current_bytecode(); |
int current_offset = iterator.current_offset(); |