Index: src/hydrogen-range-analysis.cc |
diff --git a/src/hydrogen-range-analysis.cc b/src/hydrogen-range-analysis.cc |
index ed254db19c433f3588a08dd442096ec3e4fa45d5..76fd5f35f285c9889fe7a4f5fadff3e7ecf8e13c 100644 |
--- a/src/hydrogen-range-analysis.cc |
+++ b/src/hydrogen-range-analysis.cc |
@@ -31,6 +31,20 @@ namespace v8 { |
namespace internal { |
+class Pending { |
+ public: |
+ Pending(HBasicBlock* block, int last_changed_range) |
+ : block_(block), last_changed_range_(last_changed_range) {} |
+ |
+ HBasicBlock* block() const { return block_; } |
+ int last_changed_range() const { return last_changed_range_; } |
+ |
+ private: |
+ HBasicBlock* block_; |
+ int last_changed_range_; |
+}; |
+ |
+ |
void HRangeAnalysisPhase::TraceRange(const char* msg, ...) { |
if (FLAG_trace_range) { |
va_list arguments; |
@@ -41,37 +55,52 @@ void HRangeAnalysisPhase::TraceRange(const char* msg, ...) { |
} |
-void HRangeAnalysisPhase::Analyze(HBasicBlock* block) { |
- TraceRange("Analyzing block B%d\n", block->block_id()); |
- |
- int last_changed_range = changed_ranges_.length() - 1; |
+void HRangeAnalysisPhase::Run() { |
+ HBasicBlock* block(graph()->entry_block()); |
+ ZoneList<Pending> stack(graph()->blocks()->length(), zone()); |
+ while (block != NULL) { |
+ TraceRange("Analyzing block B%d\n", block->block_id()); |
- // Infer range based on control flow. |
- if (block->predecessors()->length() == 1) { |
- HBasicBlock* pred = block->predecessors()->first(); |
- if (pred->end()->IsCompareNumericAndBranch()) { |
- InferControlFlowRange(HCompareNumericAndBranch::cast(pred->end()), |
- block); |
+ // Infer range based on control flow. |
+ if (block->predecessors()->length() == 1) { |
+ HBasicBlock* pred = block->predecessors()->first(); |
+ if (pred->end()->IsCompareNumericAndBranch()) { |
+ InferControlFlowRange(HCompareNumericAndBranch::cast(pred->end()), |
+ block); |
+ } |
} |
- } |
- // Process phi instructions. |
- for (int i = 0; i < block->phis()->length(); ++i) { |
- HPhi* phi = block->phis()->at(i); |
- InferRange(phi); |
- } |
+ // Process phi instructions. |
+ for (int i = 0; i < block->phis()->length(); ++i) { |
+ HPhi* phi = block->phis()->at(i); |
+ InferRange(phi); |
+ } |
- // Go through all instructions of the current block. |
- for (HInstructionIterator it(block); !it.Done(); it.Advance()) { |
- InferRange(it.Current()); |
- } |
+ // Go through all instructions of the current block. |
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) { |
+ InferRange(it.Current()); |
+ } |
- // Continue analysis in all dominated blocks. |
- for (int i = 0; i < block->dominated_blocks()->length(); ++i) { |
- Analyze(block->dominated_blocks()->at(i)); |
+ // Continue analysis in all dominated blocks. |
+ const ZoneList<HBasicBlock*>* dominated_blocks(block->dominated_blocks()); |
+ if (!dominated_blocks->is_empty()) { |
+ // Continue with first dominated block, and push the |
+ // remaining blocks on the stack (in reverse order). |
+ int last_changed_range = changed_ranges_.length(); |
+ for (int i = dominated_blocks->length() - 1; i > 0; --i) { |
+ stack.Add(Pending(dominated_blocks->at(i), last_changed_range), zone()); |
+ } |
+ block = dominated_blocks->at(0); |
+ } else if (!stack.is_empty()) { |
+ // Pop next pending block from stack. |
+ Pending pending = stack.RemoveLast(); |
+ RollBackTo(pending.last_changed_range()); |
+ block = pending.block(); |
+ } else { |
+ // All blocks done. |
+ block = NULL; |
+ } |
} |
- |
- RollBackTo(last_changed_range); |
} |
@@ -140,10 +169,11 @@ void HRangeAnalysisPhase::InferRange(HValue* value) { |
void HRangeAnalysisPhase::RollBackTo(int index) { |
- for (int i = index + 1; i < changed_ranges_.length(); ++i) { |
+ ASSERT(index <= changed_ranges_.length()); |
+ for (int i = index; i < changed_ranges_.length(); ++i) { |
changed_ranges_[i]->RemoveLastAddedRange(); |
} |
- changed_ranges_.Rewind(index + 1); |
+ changed_ranges_.Rewind(index); |
} |