Index: src/compiler/schedule.h |
diff --git a/src/compiler/schedule.h b/src/compiler/schedule.h |
index 0094d57525684e16f263d1ebab9fc18fe3ac7727..6954b75c51bb0af9ec91f04240e09fcf399f40eb 100644 |
--- a/src/compiler/schedule.h |
+++ b/src/compiler/schedule.h |
@@ -9,10 +9,6 @@ |
#include "src/v8.h" |
-#include "src/compiler/generic-algorithm.h" |
-#include "src/compiler/generic-graph.h" |
-#include "src/compiler/generic-node.h" |
-#include "src/compiler/generic-node-inl.h" |
#include "src/compiler/node.h" |
#include "src/compiler/opcodes.h" |
#include "src/zone.h" |
@@ -27,7 +23,10 @@ class Graph; |
class ConstructScheduleData; |
class CodeGenerator; // Because of a namespace bug in clang. |
-class BasicBlockData { |
+// A basic block contains an ordered list of nodes and ends with a control |
+// node. Note that if a basic block has phis, then all phis must appear as the |
+// first nodes in the block. |
+class BasicBlock FINAL : public ZoneObject { |
public: |
// Possible control nodes that can end a block. |
enum Control { |
@@ -38,42 +37,23 @@ class BasicBlockData { |
kThrow // Throw an exception. |
}; |
- int32_t rpo_number_; // special RPO number of the block. |
- BasicBlock* dominator_; // Immediate dominator of the block. |
- BasicBlock* loop_header_; // Pointer to dominating loop header basic block, |
- // NULL if none. For loop headers, this points to |
- // enclosing loop header. |
- int32_t loop_depth_; // loop nesting, 0 is top-level |
- int32_t loop_end_; // end of the loop, if this block is a loop header. |
- int32_t code_start_; // start index of arch-specific code. |
- int32_t code_end_; // end index of arch-specific code. |
- bool deferred_; // {true} if this block is considered the slow |
- // path. |
- Control control_; // Control at the end of the block. |
- Node* control_input_; // Input value for control. |
- NodeVector nodes_; // nodes of this block in forward order. |
+ class Id { |
+ public: |
+ int ToInt() const { return static_cast<int>(index_); } |
+ size_t ToSize() const { return index_; } |
+ static Id FromSize(size_t index) { return Id(index); } |
+ static Id FromInt(int index) { return Id(static_cast<size_t>(index)); } |
- explicit BasicBlockData(Zone* zone) |
- : 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) {} |
+ private: |
+ explicit Id(size_t index) : index_(index) {} |
+ size_t index_; |
+ }; |
- inline bool IsLoopHeader() const { return loop_end_ >= 0; } |
- inline bool LoopContains(BasicBlockData* 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(Zone* zone, Id id); |
+ |
+ Id id() const { return id_; } |
+ |
+ // Instruction indexes (used by the register allocator). |
int first_instruction_index() { |
DCHECK(code_start_ >= 0); |
DCHECK(code_end_ > 0); |
@@ -86,46 +66,26 @@ class BasicBlockData { |
DCHECK(code_end_ >= code_start_); |
return code_end_ - 1; |
} |
-}; |
-OStream& operator<<(OStream& os, const BasicBlockData::Control& c); |
+ // Predecessors and successors. |
+ typedef ZoneVector<BasicBlock*> Predecessors; |
+ Predecessors::iterator predecessors_begin() { return predecessors_.begin(); } |
+ Predecessors::iterator predecessors_end() { return predecessors_.end(); } |
+ size_t PredecessorCount() const { return predecessors_.size(); } |
+ BasicBlock* PredecessorAt(size_t index) { return predecessors_[index]; } |
+ size_t PredecessorIndexOf(BasicBlock* predecessor); |
+ void AddPredecessor(BasicBlock* predecessor); |
-// A basic block contains an ordered list of nodes and ends with a control |
-// node. Note that if a basic block has phis, then all phis must appear as the |
-// first nodes in the block. |
-class BasicBlock FINAL : public GenericNode<BasicBlockData, BasicBlock> { |
- public: |
- BasicBlock(GenericGraphBase* graph, int input_count) |
- : GenericNode<BasicBlockData, BasicBlock>(graph, input_count) {} |
- |
- typedef Uses Successors; |
- typedef Inputs Predecessors; |
- |
- Successors successors() { return static_cast<Successors>(uses()); } |
- Predecessors predecessors() { return static_cast<Predecessors>(inputs()); } |
+ typedef ZoneVector<BasicBlock*> Successors; |
+ Successors::iterator successors_begin() { return successors_.begin(); } |
+ Successors::iterator successors_end() { return successors_.end(); } |
+ size_t SuccessorCount() const { return successors_.size(); } |
+ BasicBlock* SuccessorAt(size_t index) { return successors_[index]; } |
+ void AddSuccessor(BasicBlock* successor); |
- int PredecessorCount() { return InputCount(); } |
- BasicBlock* PredecessorAt(int index) { return InputAt(index); } |
- |
- int SuccessorCount() { return UseCount(); } |
- BasicBlock* SuccessorAt(int index) { return UseAt(index); } |
- |
- int PredecessorIndexOf(BasicBlock* predecessor) { |
- BasicBlock::Predecessors predecessors = this->predecessors(); |
- for (BasicBlock::Predecessors::iterator i = predecessors.begin(); |
- i != predecessors.end(); ++i) { |
- if (*i == predecessor) return i.index(); |
- } |
- return -1; |
- } |
- |
- inline BasicBlock* loop_header() { |
- return static_cast<BasicBlock*>(loop_header_); |
- } |
- inline BasicBlock* ContainingLoop() { |
- if (IsLoopHeader()) return this; |
- return static_cast<BasicBlock*>(loop_header_); |
- } |
+ // Nodes in the basic block. |
+ Node* NodeAt(size_t index) { return nodes_[index]; } |
+ size_t NodeCount() const { return nodes_.size(); } |
typedef NodeVector::iterator iterator; |
iterator begin() { return nodes_.begin(); } |
@@ -139,12 +99,73 @@ class BasicBlock FINAL : public GenericNode<BasicBlockData, BasicBlock> { |
reverse_iterator rbegin() { return nodes_.rbegin(); } |
reverse_iterator rend() { return nodes_.rend(); } |
+ void AddNode(Node* node); |
+ template <class InputIterator> |
+ void InsertNodes(iterator insertion_point, InputIterator insertion_start, |
+ InputIterator insertion_end) { |
+ nodes_.insert(insertion_point, insertion_start, insertion_end); |
+ } |
+ |
+ // Accessors. |
+ Control control() const { return control_; } |
+ void set_control(Control control); |
+ |
+ Node* control_input() const { return control_input_; } |
+ void set_control_input(Node* control_input); |
+ |
+ BasicBlock* dominator() const { return dominator_; } |
+ void set_dominator(BasicBlock* dominator); |
+ |
+ BasicBlock* loop_header() const { return loop_header_; } |
+ void set_loop_header(BasicBlock* loop_header); |
+ |
+ int32_t loop_depth() const { return loop_depth_; } |
+ void set_loop_depth(int32_t loop_depth); |
+ |
+ int32_t loop_end() const { return loop_end_; } |
+ void set_loop_end(int32_t loop_end); |
+ |
+ int32_t rpo_number() const { return rpo_number_; } |
+ void set_rpo_number(int32_t rpo_number); |
+ |
+ int32_t code_start() const { return code_start_; } |
+ void set_code_start(int32_t start); |
+ |
+ int32_t code_end() const { return code_end_; } |
+ void set_code_end(int32_t end); |
+ |
+ bool deferred() const { return deferred_; } |
+ |
+ // Loop membership helpers. |
+ inline bool IsLoopHeader() const { return loop_end_ >= 0; } |
+ bool LoopContains(BasicBlock* block) const; |
+ BasicBlock* ContainingLoop(); |
+ |
private: |
+ int32_t rpo_number_; // special RPO number of the block. |
+ BasicBlock* dominator_; // Immediate dominator of the block. |
+ BasicBlock* loop_header_; // Pointer to dominating loop header basic block, |
+ // NULL if none. For loop headers, this points to |
+ // enclosing loop header. |
+ int32_t loop_depth_; // loop nesting, 0 is top-level |
+ int32_t loop_end_; // end of the loop, if this block is a loop header. |
+ int32_t code_start_; // start index of arch-specific code. |
+ int32_t code_end_; // end index of arch-specific code. |
+ bool deferred_; // {true} if this block is considered the slow |
+ // path. |
+ Control control_; // Control at the end of the block. |
+ Node* control_input_; // Input value for control. |
+ NodeVector nodes_; // nodes of this block in forward order. |
+ |
+ Successors successors_; |
+ Predecessors predecessors_; |
+ Id id_; |
+ |
DISALLOW_COPY_AND_ASSIGN(BasicBlock); |
}; |
-typedef GenericGraphVisit::NullNodeVisitor<BasicBlockData, BasicBlock> |
- NullBasicBlockVisitor; |
+OStream& operator<<(OStream& os, const BasicBlock::Control& c); |
+OStream& operator<<(OStream& os, const BasicBlock::Id& id); |
typedef ZoneVector<BasicBlock*> BasicBlockVector; |
typedef BasicBlockVector::iterator BasicBlockVectorIter; |
@@ -154,151 +175,69 @@ typedef BasicBlockVector::reverse_iterator BasicBlockVectorRIter; |
// and ordering them within basic blocks. Prior to computing a schedule, |
// a graph has no notion of control flow ordering other than that induced |
// by the graph's dependencies. A schedule is required to generate code. |
-class Schedule : public GenericGraph<BasicBlock> { |
+class Schedule FINAL : public ZoneObject { |
public: |
- explicit Schedule(Zone* zone, size_t node_count_hint = 0) |
- : GenericGraph<BasicBlock>(zone), |
- zone_(zone), |
- all_blocks_(zone), |
- nodeid_to_block_(zone), |
- rpo_order_(zone) { |
- SetStart(NewBasicBlock()); // entry. |
- SetEnd(NewBasicBlock()); // exit. |
- nodeid_to_block_.reserve(node_count_hint); |
- } |
+ explicit Schedule(Zone* zone, size_t node_count_hint = 0); |
// Return the block which contains {node}, if any. |
- BasicBlock* block(Node* node) const { |
- if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) { |
- return nodeid_to_block_[node->id()]; |
- } |
- return NULL; |
- } |
+ BasicBlock* block(Node* node) const; |
- bool 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; |
- } |
+ bool IsScheduled(Node* node); |
+ BasicBlock* GetBlockById(BasicBlock::Id block_id); |
- BasicBlock* GetBlockById(int block_id) { return all_blocks_[block_id]; } |
- |
- int BasicBlockCount() const { return NodeCount(); } |
- int RpoBlockCount() const { return static_cast<int>(rpo_order_.size()); } |
- |
- typedef ContainerPointerWrapper<BasicBlockVector> BasicBlocks; |
- |
- // Return a list of all the blocks in the schedule, in arbitrary order. |
- BasicBlocks all_blocks() { return BasicBlocks(&all_blocks_); } |
+ size_t BasicBlockCount() const { return all_blocks_.size(); } |
+ size_t RpoBlockCount() const { return rpo_order_.size(); } |
// Check if nodes {a} and {b} are in the same block. |
- inline bool SameBasicBlock(Node* a, Node* b) const { |
- BasicBlock* block = this->block(a); |
- return block != NULL && block == this->block(b); |
- } |
+ bool SameBasicBlock(Node* a, Node* b) const; |
// BasicBlock building: create a new block. |
- inline BasicBlock* NewBasicBlock() { |
- BasicBlock* block = |
- BasicBlock::New(this, 0, static_cast<BasicBlock**>(NULL)); |
- all_blocks_.push_back(block); |
- return block; |
- } |
+ BasicBlock* NewBasicBlock(); |
// BasicBlock building: records that a node will later be added to a block but |
// doesn't actually add the node to the block. |
- inline void PlanNode(BasicBlock* block, Node* node) { |
- if (FLAG_trace_turbo_scheduler) { |
- PrintF("Planning #%d:%s for future add to B%d\n", node->id(), |
- node->op()->mnemonic(), block->id()); |
- } |
- DCHECK(this->block(node) == NULL); |
- SetBlockForNode(block, node); |
- } |
+ void PlanNode(BasicBlock* block, Node* node); |
// BasicBlock building: add a node to the end of the block. |
- inline void AddNode(BasicBlock* block, Node* node) { |
- if (FLAG_trace_turbo_scheduler) { |
- PrintF("Adding #%d:%s to B%d\n", node->id(), node->op()->mnemonic(), |
- block->id()); |
- } |
- DCHECK(this->block(node) == NULL || this->block(node) == block); |
- block->nodes_.push_back(node); |
- SetBlockForNode(block, node); |
- } |
+ void AddNode(BasicBlock* block, Node* node); |
// BasicBlock building: add a goto to the end of {block}. |
- void AddGoto(BasicBlock* block, BasicBlock* succ) { |
- DCHECK(block->control_ == BasicBlock::kNone); |
- block->control_ = BasicBlock::kGoto; |
- AddSuccessor(block, succ); |
- } |
+ void AddGoto(BasicBlock* block, BasicBlock* succ); |
// BasicBlock building: add a branch at the end of {block}. |
void AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock, |
- BasicBlock* fblock) { |
- DCHECK(block->control_ == BasicBlock::kNone); |
- DCHECK(branch->opcode() == IrOpcode::kBranch); |
- block->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); |
- } |
- } |
+ BasicBlock* fblock); |
// BasicBlock building: add a return at the end of {block}. |
- void AddReturn(BasicBlock* block, Node* input) { |
- DCHECK(block->control_ == BasicBlock::kNone); |
- block->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 AddReturn(BasicBlock* block, Node* input); |
// BasicBlock building: add a throw at the end of {block}. |
- void AddThrow(BasicBlock* block, Node* input) { |
- DCHECK(block->control_ == BasicBlock::kNone); |
- block->control_ = BasicBlock::kThrow; |
- SetControlInput(block, input); |
- if (block != end()) AddSuccessor(block, end()); |
- } |
+ void AddThrow(BasicBlock* block, Node* input); |
- friend class Scheduler; |
- friend class CodeGenerator; |
- |
- void AddSuccessor(BasicBlock* block, BasicBlock* succ) { |
- succ->AppendInput(zone_, block); |
- } |
+ void AddSuccessor(BasicBlock* block, BasicBlock* succ); |
BasicBlockVector* rpo_order() { return &rpo_order_; } |
+ BasicBlock* start() { return start_; } |
+ BasicBlock* end() { return end_; } |
+ |
+ Zone* zone() { return zone_; } |
+ |
private: |
+ friend class Scheduler; |
+ friend class CodeGenerator; |
friend class ScheduleVisualizer; |
friend class BasicBlockInstrumentor; |
- void SetControlInput(BasicBlock* block, Node* node) { |
- block->control_input_ = node; |
- SetBlockForNode(block, node); |
- } |
- |
- void 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; |
- } |
+ void SetControlInput(BasicBlock* block, Node* node); |
+ void SetBlockForNode(BasicBlock* block, Node* node); |
Zone* zone_; |
BasicBlockVector all_blocks_; // All basic blocks in the schedule. |
BasicBlockVector nodeid_to_block_; // Map from node to containing block. |
BasicBlockVector rpo_order_; // Reverse-post-order block list. |
+ BasicBlock* start_; |
+ BasicBlock* end_; |
}; |
OStream& operator<<(OStream& os, const Schedule& s); |