Commit 01080fa7 authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

Fix possible stack overflow in range analysis.

Avoid the implicit recursion for range analysis, using a loop with
an explicit stack instead.

BUG=chromium:259452
R=dslomov@chromium.org

Review URL: https://codereview.chromium.org/19145002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15661 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent fb77805a
......@@ -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);
}
......
......@@ -39,13 +39,10 @@ class HRangeAnalysisPhase : public HPhase {
explicit HRangeAnalysisPhase(HGraph* graph)
: HPhase("H_Range analysis", graph), changed_ranges_(16, zone()) { }
void Run() {
Analyze(graph()->entry_block());
}
void Run();
private:
void TraceRange(const char* msg, ...);
void Analyze(HBasicBlock* block);
void InferControlFlowRange(HCompareNumericAndBranch* test,
HBasicBlock* dest);
void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment