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) { |