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

Unified Diff: src/hydrogen.cc

Issue 10543138: Reimplemented HGraph::Postorder and HGraph::PostorderLoopBlocks iteratively to avoid stack overflow… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 6 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index d880b02836df33384a97f3dd4cdaf53b0c2a92ae..7779a820d3645611d9858b9396712426b3a13974 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -748,6 +748,301 @@ void HGraph::Canonicalize() {
}
}
+// Block ordering was implemented with two mutually recursive methods,
+// HGraph::Postorder and HGraph::PostorderLoopBlocks.
+// The recursion could lead to stack overflow so the algorithm has been
+// implemented iteratively.
+// At a _very_ high level the algorithm looks like this:
Jakob Kummerow 2012/06/14 17:24:14 Remove the "_very_". Just "high level". It's clean
+//
+// Postorder(block, loop_header) : {
+// if (block has already been visited or is of another loop) return;
+// mark block as visited;
+// if (block is a loop header) {
+// LoopMembersCycle(block, loop_header);
+// SuccessorsOfLoopHeaderCycle(block, loop_header);
Jakob Kummerow 2012/06/14 17:24:14 This only needs "block" as input, right? That's th
+// } else {
+// PostorderCycle(block)
+// }
+// put block in result list;
+// }
+//
+// LoopMembersCycle(block) {
Jakob Kummerow 2012/06/14 17:24:14 This needs a second argument "outer_loop_header".
+// foreach (block b in block loop members) {
+// SuccessorsOfLoopMemberCycle(b);
Jakob Kummerow 2012/06/14 17:24:14 This call must pass on the outer_loop_header.
+// if (b is loop header) LoopMembersCycle(b);
+// }
+// }
+//
+// SuccessorsOfLoopMemberCycle(block, loop_header) {
Jakob Kummerow 2012/06/14 17:24:14 I'd rename the second argument to outer_loop_heade
+// foreach (block b in block successors) Postorder(b, loop_header)
+// }
+//
+// SuccessorsOfLoopHeaderCycle(block) {
+// foreach (block b in block successors) Postorder(b, b)
Jakob Kummerow 2012/06/14 17:24:14 Shouldn't this pass (b, block) instead?
+// }
+//
+// PostorderCycle(block, loop_header) {
Jakob Kummerow 2012/06/14 17:24:14 I don't feel strongly about this, but wouldn't s/P
+// foreach (block b in block successors) Postorder(b, loop_header)
+// }
+//
+// The ordering is started calling Postorder(entry, NULL).
+//
+// Each instance of PostorderProcessor represents the "stack frame" of the
+// recursion, and particularly keeps the state of one of the cycles.
+// To recycle memory we keep all the frames in a double linked list but
+// this means that we cannot use constructors to initialize the frames.
+//
+class PostorderProcessor : ZoneObject {
Jakob Kummerow 2012/06/14 17:24:14 "...: public ZoneObject" please
+ public:
+ // Back list link (towards the stack bottom)
Jakob Kummerow 2012/06/14 17:24:14 nit: "Backward", and a missing full stop at the en
+ PostorderProcessor* father() {return father_; }
Jakob Kummerow 2012/06/14 17:24:14 nit: s/father/parent/? ;-)
+ // Forward list link (towards the stack top)
Jakob Kummerow 2012/06/14 17:24:14 nit: missing full stop at the end.
+ PostorderProcessor* child() {return child_; }
+ HBasicBlock* block() { return block_; }
+ HLoopInformation* loop() { return loop_; }
+ HBasicBlock* loop_header() { return loop_header_; }
+
+ static PostorderProcessor* CreateEntryProcessor(Zone* zone,
+ HBasicBlock* block,
+ BitVector* visited) {
+ PostorderProcessor* result = new(zone) PostorderProcessor(NULL);
+ return result->SetupSuccessors(zone, block, NULL, visited);
+ }
+
+ PostorderProcessor* PerformStep(Zone* zone,
+ BitVector* visited,
+ ZoneList<HBasicBlock*>* order) {
+ PostorderProcessor* next =
+ PerformNonBacktrackingStep(zone, visited, order);
+ if (next != NULL) {
+ return next;
+ } else {
+ return Backtrack(zone, visited, order);
+ }
+ }
+
+ private:
+ // Each enum value states the cycle whose state is kept by this instance.
+ enum LoopKind {
+ NONE,
+ SUCCESSORS,
+ SUCCESSORS_OF_LOOP_HEADER,
+ LOOP_MEMBERS,
+ SUCCESSORS_OF_LOOP_MEMBER
+ };
+
+ // Each "Setup..." method is like a constructor for a cycle state.
+ PostorderProcessor* SetupSuccessors(Zone* zone,
+ HBasicBlock* block,
+ HBasicBlock* loop_header,
+ BitVector* visited) {
+ if ((block == NULL || visited->Contains(block->block_id())) ||
Jakob Kummerow 2012/06/14 17:24:14 nit: you can remove one pair of ().
+ (block->parent_loop_header() != loop_header)) {
Jakob Kummerow 2012/06/14 17:24:14 can remove the outer (...) here too
+ kind_ = NONE;
+ block_ = NULL;
+ loop_ = NULL;
+ loop_header_ = NULL;
+ return this;
+ } else {
+ block_ = block;
+ loop_ = NULL;
+ visited->Add(block->block_id());
+
+ if (block->IsLoopHeader()) {
+ kind_ = SUCCESSORS_OF_LOOP_HEADER;
+ loop_header_ = block;
+ InitializeSuccessors();
+ PostorderProcessor* result = Push(zone);
+ return result->SetupLoopMembers(zone, block, block->loop_information(),
+ loop_header);
+ } else {
+ ASSERT(block->IsFinished());
+ kind_ = SUCCESSORS;
+ loop_header_ = loop_header;
+ InitializeSuccessors();
+ return this;
+ }
+ }
+ }
+
+ PostorderProcessor* SetupLoopMembers(Zone* zone,
+ HBasicBlock* block,
+ HLoopInformation* loop,
+ HBasicBlock* loop_header) {
+ kind_ = LOOP_MEMBERS;
+ block_ = block;
+ loop_ = loop;
+ loop_header_ = loop_header;
+ InitializeLoopMembers();
+ return this;
+ }
+
+ PostorderProcessor* SetupSuccessorsOfLoopMember(
+ HBasicBlock* block,
+ HLoopInformation* loop,
+ HBasicBlock* loop_header) {
+ kind_ = SUCCESSORS_OF_LOOP_MEMBER;
+ block_ = block;
+ loop_ = loop;
+ loop_header_ = loop_header;
+ InitializeSuccessors();
+ return this;
+ }
+
+ // This method "allocates" a new stack frame.
+ PostorderProcessor* Push(Zone* zone) {
+ if (child_ == NULL) {
+ child_ = new(zone) PostorderProcessor(this);
+ }
+ return child_;
+ }
+
+ void ClosePostorder(ZoneList<HBasicBlock*>* order) {
+ ASSERT(block_->end()->FirstSuccessor() == NULL ||
+ order->Contains(block_->end()->FirstSuccessor()) ||
+ block_->end()->FirstSuccessor()->IsLoopHeader());
+ ASSERT(block_->end()->SecondSuccessor() == NULL ||
+ order->Contains(block_->end()->SecondSuccessor()) ||
+ block_->end()->SecondSuccessor()->IsLoopHeader());
+ order->Add(block_);
+ }
+
+ // This method is the basic block to walk up the stack.
+ PostorderProcessor* Pop(Zone* zone,
+ BitVector* visited,
+ ZoneList<HBasicBlock*>* order) {
+ switch (kind_) {
+ case SUCCESSORS:
+ case SUCCESSORS_OF_LOOP_HEADER:
+ ClosePostorder(order);
+ return father_;
+ case LOOP_MEMBERS:
+ return father_;
+ case SUCCESSORS_OF_LOOP_MEMBER:
+ if (block()->IsLoopHeader() && block() != loop_->loop_header()) {
+ // In this case we need to perform a LOOP_MEMBERS cycle so we
+ // initialize it and return this instead of father.
+ return SetupLoopMembers(zone, block(),
+ block()->loop_information(), loop_header_);
+ } else {
+ return father_;
+ }
+ case NONE:
+ return father_;
+ default:
+ ASSERT(false);
Jakob Kummerow 2012/06/14 17:24:14 nit: we have UNREACHABLE() for this. Even better:
+ return NULL;
+ }
+ }
+
+ // Walks up the stack.
+ PostorderProcessor* Backtrack(Zone* zone,
+ BitVector* visited,
+ ZoneList<HBasicBlock*>* order) {
+ PostorderProcessor* father = Pop(zone, visited, order);
Jakob Kummerow 2012/06/14 17:24:14 Again, s/father/parent/.
+ while (father != NULL) {
+ PostorderProcessor* next =
+ father->PerformNonBacktrackingStep(zone, visited, order);
+ if (next != NULL) {
+ return next;
+ } else {
+ father = father->Pop(zone, visited, order);
+ }
+ }
+ return NULL;
+ }
+
+ PostorderProcessor* PerformNonBacktrackingStep(
+ Zone* zone,
+ BitVector* visited,
+ ZoneList<HBasicBlock*>* order) {
+ HBasicBlock* next_block;
+ switch (kind_) {
+ case SUCCESSORS:
+ next_block = AdvanceSuccessors();
+ if (next_block != NULL) {
+ PostorderProcessor* result = Push(zone);
+ return result->SetupSuccessors(zone, next_block,
+ loop_header_, visited);
+ }
+ break;
+ case SUCCESSORS_OF_LOOP_HEADER:
+ next_block = AdvanceSuccessors();
+ if (next_block != NULL) {
+ PostorderProcessor* result = Push(zone);
+ return result->SetupSuccessors(zone, next_block,
+ block(), visited);
+ }
+ break;
+ case LOOP_MEMBERS:
+ next_block = AdvanceLoopMembers();
+ if (next_block != NULL) {
+ PostorderProcessor* result = Push(zone);
+ return result->SetupSuccessorsOfLoopMember(next_block,
+ loop_, loop_header_);
+ }
+ break;
+ case SUCCESSORS_OF_LOOP_MEMBER:
+ next_block = AdvanceSuccessors();
+ if (next_block != NULL) {
+ PostorderProcessor* result = Push(zone);
+ return result->SetupSuccessors(zone, next_block,
+ loop_header_, visited);
+ }
+ break;
+ default:
Jakob Kummerow 2012/06/14 17:24:14 Again, please remove the default case.
Massi 2012/06/18 11:21:30 If I remove it I cannot compile, likewise if I rem
+ return NULL;
+ }
+ return NULL;
+ }
+
+ // The following two methods implement a "foreach b in successors" cycle.
+ void InitializeSuccessors() {
+ loop_index = 0;
+ loop_length = 0;
+ successor_iterator = HSuccessorIterator(block_->end());
+ }
+
+ HBasicBlock* AdvanceSuccessors() {
+ if (!successor_iterator.Done()) {
+ HBasicBlock* result = successor_iterator.Current();
+ successor_iterator.Advance();
+ return result;
+ } else {
Jakob Kummerow 2012/06/14 17:24:14 nit: You could remove the "else" and just "return
+ return NULL;
+ }
+ }
+
+ // The following two methods implement a "foreach b in loop members" cycle.
+ void InitializeLoopMembers() {
+ loop_index = 0;
+ loop_length = loop_->blocks()->length();
+ }
+
+ HBasicBlock* AdvanceLoopMembers() {
+ if (loop_index < loop_length) {
+ HBasicBlock* result = loop_->blocks()->at(loop_index);
+ loop_index++;
+ return result;
+ } else {
+ return NULL;
+ }
+ }
+
+ explicit PostorderProcessor(PostorderProcessor* father)
Jakob Kummerow 2012/06/14 17:24:14 Please put the constructor first (within the "priv
+ : father_(father), child_(NULL), successor_iterator(NULL) { }
+
+ LoopKind kind_;
+ PostorderProcessor* father_;
+ PostorderProcessor* child_;
+ HLoopInformation* loop_;
+ HBasicBlock* block_;
+ HBasicBlock* loop_header_;
+ int loop_index;
Jakob Kummerow 2012/06/14 17:24:14 nit: trailing _ please (again below, twice).
+ int loop_length;
+ HSuccessorIterator successor_iterator;
+};
+
void HGraph::OrderBlocks() {
HPhase phase("H_Block ordering");
@@ -755,8 +1050,11 @@ void HGraph::OrderBlocks() {
ZoneList<HBasicBlock*> reverse_result(8);
HBasicBlock* start = blocks_[0];
- Postorder(start, &visited, &reverse_result, NULL);
-
+ PostorderProcessor* postorder =
+ PostorderProcessor::CreateEntryProcessor(zone(), start, &visited);
+ while (postorder != NULL) {
+ postorder = postorder->PerformStep(zone(), &visited, &reverse_result);
+ }
blocks_.Rewind(0);
int index = 0;
for (int i = reverse_result.length() - 1; i >= 0; --i) {
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698