Index: src/compiler/schedule.cc |
diff --git a/src/compiler/schedule.cc b/src/compiler/schedule.cc |
index a3b5ed383b6c6d621f302ad08a5ad5af96ef4933..989505a338ffd0d2e99e705e64e5457d65079ae2 100644 |
--- a/src/compiler/schedule.cc |
+++ b/src/compiler/schedule.cc |
@@ -12,17 +12,115 @@ namespace v8 { |
namespace internal { |
namespace compiler { |
-OStream& operator<<(OStream& os, const BasicBlockData::Control& c) { |
+ |
+BasicBlock::BasicBlock(Zone* zone, Id id) |
+ : rpo_number_(-1), |
+ dominator_(NULL), |
+ loop_header_(NULL), |
+ loop_depth_(0), |
+ loop_end_(-1), |
+ code_start_(-1), |
+ code_end_(-1), |
+ deferred_(false), |
+ control_(kNone), |
+ control_input_(NULL), |
+ nodes_(zone), |
+ successors_(zone), |
+ predecessors_(zone), |
+ id_(id) {} |
+ |
+ |
+bool BasicBlock::LoopContains(BasicBlock* block) const { |
+ // RPO numbers must be initialized. |
+ DCHECK(rpo_number_ >= 0); |
+ DCHECK(block->rpo_number_ >= 0); |
+ if (loop_end_ < 0) return false; // This is not a loop. |
+ return block->rpo_number_ >= rpo_number_ && block->rpo_number_ < loop_end_; |
+} |
+ |
+ |
+BasicBlock* BasicBlock::ContainingLoop() { |
+ if (IsLoopHeader()) return this; |
+ return loop_header(); |
+} |
+ |
+ |
+void BasicBlock::AddSuccessor(BasicBlock* successor) { |
+ successors_.push_back(successor); |
+} |
+ |
+ |
+void BasicBlock::AddPredecessor(BasicBlock* predecessor) { |
+ predecessors_.push_back(predecessor); |
+} |
+ |
+ |
+void BasicBlock::AddNode(Node* node) { nodes_.push_back(node); } |
+ |
+ |
+void BasicBlock::set_control(Control control) { |
+ DCHECK(control_ == BasicBlock::kNone); |
+ control_ = control; |
+} |
+ |
+ |
+void BasicBlock::set_control_input(Node* control_input) { |
+ control_input_ = control_input; |
+} |
+ |
+ |
+void BasicBlock::set_dominator(BasicBlock* dominator) { |
+ dominator_ = dominator; |
+} |
+ |
+ |
+void BasicBlock::set_loop_depth(int32_t loop_depth) { |
+ loop_depth_ = loop_depth; |
+} |
+ |
+ |
+void BasicBlock::set_rpo_number(int32_t rpo_number) { |
+ rpo_number_ = rpo_number; |
+} |
+ |
+ |
+void BasicBlock::set_loop_end(int32_t loop_end) { loop_end_ = loop_end; } |
+ |
+ |
+void BasicBlock::set_code_start(int32_t code_start) { |
+ code_start_ = code_start; |
+} |
+ |
+ |
+void BasicBlock::set_code_end(int32_t code_end) { code_end_ = code_end; } |
+ |
+ |
+void BasicBlock::set_loop_header(BasicBlock* loop_header) { |
+ loop_header_ = loop_header; |
+} |
+ |
+ |
+size_t BasicBlock::PredecessorIndexOf(BasicBlock* predecessor) { |
+ size_t j = 0; |
+ for (BasicBlock::Predecessors::iterator i = predecessors_.begin(); |
+ i != predecessors_.end(); ++i, ++j) { |
+ if (*i == predecessor) break; |
+ } |
+ return j; |
+} |
+ |
+ |
+OStream& operator<<(OStream& os, const BasicBlock::Control& c) { |
switch (c) { |
- case BasicBlockData::kNone: |
+ case BasicBlock::kNone: |
return os << "none"; |
- case BasicBlockData::kGoto: |
+ case BasicBlock::kGoto: |
return os << "goto"; |
- case BasicBlockData::kBranch: |
+ case BasicBlock::kBranch: |
return os << "branch"; |
- case BasicBlockData::kReturn: |
+ case BasicBlock::kReturn: |
return os << "return"; |
- case BasicBlockData::kThrow: |
+ case BasicBlock::kThrow: |
return os << "throw"; |
} |
UNREACHABLE(); |
@@ -30,6 +128,145 @@ OStream& operator<<(OStream& os, const BasicBlockData::Control& c) { |
} |
+OStream& operator<<(OStream& os, const BasicBlock::Id& id) { |
+ return os << id.ToSize(); |
+} |
+ |
+ |
+Schedule::Schedule(Zone* zone, size_t node_count_hint) |
+ : zone_(zone), |
+ all_blocks_(zone), |
+ nodeid_to_block_(zone), |
+ rpo_order_(zone), |
+ start_(NewBasicBlock()), |
+ end_(NewBasicBlock()) { |
+ nodeid_to_block_.reserve(node_count_hint); |
+} |
+ |
+ |
+BasicBlock* Schedule::block(Node* node) const { |
+ if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) { |
+ return nodeid_to_block_[node->id()]; |
+ } |
+ return NULL; |
+} |
+ |
+ |
+bool Schedule::IsScheduled(Node* node) { |
+ int length = static_cast<int>(nodeid_to_block_.size()); |
+ if (node->id() >= length) return false; |
+ return nodeid_to_block_[node->id()] != NULL; |
+} |
+ |
+ |
+BasicBlock* Schedule::GetBlockById(BasicBlock::Id block_id) { |
+ DCHECK(block_id.ToSize() < all_blocks_.size()); |
+ return all_blocks_[block_id.ToSize()]; |
+} |
+ |
+ |
+bool Schedule::SameBasicBlock(Node* a, Node* b) const { |
+ BasicBlock* block = this->block(a); |
+ return block != NULL && block == this->block(b); |
+} |
+ |
+ |
+BasicBlock* Schedule::NewBasicBlock() { |
+ BasicBlock* block = new (zone_) |
+ BasicBlock(zone_, BasicBlock::Id::FromSize(all_blocks_.size())); |
+ all_blocks_.push_back(block); |
+ return block; |
+} |
+ |
+ |
+void Schedule::PlanNode(BasicBlock* block, Node* node) { |
+ if (FLAG_trace_turbo_scheduler) { |
+ OFStream os(stdout); |
+ os << "Planning #" << node->id() << ":" << node->op()->mnemonic() |
+ << " for future add to B" << block->id() << "\n"; |
+ } |
+ DCHECK(this->block(node) == NULL); |
+ SetBlockForNode(block, node); |
+} |
+ |
+ |
+void Schedule::AddNode(BasicBlock* block, Node* node) { |
+ if (FLAG_trace_turbo_scheduler) { |
+ OFStream os(stdout); |
+ os << "Adding #" << node->id() << ":" << node->op()->mnemonic() << " to B" |
+ << block->id() << "\n"; |
+ } |
+ DCHECK(this->block(node) == NULL || this->block(node) == block); |
+ block->AddNode(node); |
+ SetBlockForNode(block, node); |
+} |
+ |
+ |
+void Schedule::AddGoto(BasicBlock* block, BasicBlock* succ) { |
+ DCHECK(block->control() == BasicBlock::kNone); |
+ block->set_control(BasicBlock::kGoto); |
+ AddSuccessor(block, succ); |
+} |
+ |
+ |
+void Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock, |
+ BasicBlock* fblock) { |
+ DCHECK(block->control() == BasicBlock::kNone); |
+ DCHECK(branch->opcode() == IrOpcode::kBranch); |
+ block->set_control(BasicBlock::kBranch); |
+ AddSuccessor(block, tblock); |
+ AddSuccessor(block, fblock); |
+ SetControlInput(block, branch); |
+ if (branch->opcode() == IrOpcode::kBranch) { |
+ // TODO(titzer): require a Branch node here. (sloppy tests). |
+ SetBlockForNode(block, branch); |
+ } |
+} |
+ |
+ |
+void Schedule::AddReturn(BasicBlock* block, Node* input) { |
+ DCHECK(block->control() == BasicBlock::kNone); |
+ block->set_control(BasicBlock::kReturn); |
+ SetControlInput(block, input); |
+ if (block != end()) { |
+ AddSuccessor(block, end()); |
+ } |
+ if (input->opcode() == IrOpcode::kReturn) { |
+ // TODO(titzer): require a Return node here. (sloppy tests). |
+ SetBlockForNode(block, input); |
+ } |
+} |
+ |
+ |
+void Schedule::AddThrow(BasicBlock* block, Node* input) { |
+ DCHECK(block->control() == BasicBlock::kNone); |
+ block->set_control(BasicBlock::kThrow); |
+ SetControlInput(block, input); |
+ if (block != end()) AddSuccessor(block, end()); |
+} |
+ |
+ |
+void Schedule::AddSuccessor(BasicBlock* block, BasicBlock* succ) { |
+ block->AddSuccessor(succ); |
+ succ->AddPredecessor(block); |
+} |
+ |
+ |
+void Schedule::SetControlInput(BasicBlock* block, Node* node) { |
+ block->set_control_input(node); |
+ SetBlockForNode(block, node); |
+} |
+ |
+ |
+void Schedule::SetBlockForNode(BasicBlock* block, Node* node) { |
+ int length = static_cast<int>(nodeid_to_block_.size()); |
+ if (node->id() >= length) { |
+ nodeid_to_block_.resize(node->id() + 1); |
+ } |
+ nodeid_to_block_[node->id()] = block; |
+} |
+ |
+ |
OStream& operator<<(OStream& os, const Schedule& s) { |
// TODO(svenpanne) Const-correct the RPO stuff/iterators. |
BasicBlockVector* rpo = const_cast<Schedule*>(&s)->rpo_order(); |
@@ -37,10 +274,9 @@ OStream& operator<<(OStream& os, const Schedule& s) { |
BasicBlock* block = *i; |
os << "--- BLOCK B" << block->id(); |
if (block->PredecessorCount() != 0) os << " <- "; |
- BasicBlock::Predecessors predecessors = block->predecessors(); |
bool comma = false; |
- for (BasicBlock::Predecessors::iterator j = predecessors.begin(); |
- j != predecessors.end(); ++j) { |
+ for (BasicBlock::Predecessors::iterator j = block->predecessors_begin(); |
+ j != block->predecessors_end(); ++j) { |
if (comma) os << ", "; |
comma = true; |
os << "B" << (*j)->id(); |
@@ -61,19 +297,18 @@ OStream& operator<<(OStream& os, const Schedule& s) { |
} |
os << "\n"; |
} |
- BasicBlock::Control control = block->control_; |
+ BasicBlock::Control control = block->control(); |
if (control != BasicBlock::kNone) { |
os << " "; |
- if (block->control_input_ != NULL) { |
- os << *block->control_input_; |
+ if (block->control_input() != NULL) { |
+ os << *block->control_input(); |
} else { |
os << "Goto"; |
} |
os << " -> "; |
- BasicBlock::Successors successors = block->successors(); |
comma = false; |
- for (BasicBlock::Successors::iterator j = successors.begin(); |
- j != successors.end(); ++j) { |
+ for (BasicBlock::Successors::iterator j = block->successors_begin(); |
+ j != block->successors_end(); ++j) { |
if (comma) os << ", "; |
comma = true; |
os << "B" << (*j)->id(); |