Index: src/compiler/bytecode-graph-builder.h |
diff --git a/src/compiler/bytecode-graph-builder.h b/src/compiler/bytecode-graph-builder.h |
index ed90d79cb077ee30c14e20425830c4d2c3e33ee9..812731cdeb91066ddb13755b82cbfd3f6d47e0c0 100644 |
--- a/src/compiler/bytecode-graph-builder.h |
+++ b/src/compiler/bytecode-graph-builder.h |
@@ -14,6 +14,8 @@ namespace v8 { |
namespace internal { |
namespace compiler { |
+class BytecodeBasicBlock; |
+ |
// The BytecodeGraphBuilder produces a high-level IR graph based on |
// interpreter bytecodes. |
class BytecodeGraphBuilder { |
@@ -28,9 +30,11 @@ class BytecodeGraphBuilder { |
private: |
class Environment; |
+ class BlockEnvironmentInfo; |
void CreateGraphBody(bool stack_check); |
- void VisitBytecodes(); |
+ void VisitBasicBlocks(); |
+ void VisitBytecodesInBasicBlock(BytecodeBasicBlock* block); |
Node* LoadAccumulator(Node* value); |
@@ -64,6 +68,11 @@ class BytecodeGraphBuilder { |
const Environment* environment() const { return environment_; } |
Environment* environment() { return environment_; } |
+ void set_basic_block(const BytecodeBasicBlock* block) { |
+ basic_block_ = block; |
+ } |
+ const BytecodeBasicBlock* basic_block() const { return basic_block_; } |
+ |
// Node creation helpers |
Node* NewNode(const Operator* op, bool incomplete = false) { |
return MakeNode(op, 0, static_cast<Node**>(NULL), incomplete); |
@@ -89,15 +98,34 @@ class BytecodeGraphBuilder { |
return MakeNode(op, arraysize(buffer), buffer, false); |
} |
- Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs, |
- bool incomplete); |
+ // Helpers to create new control nodes. |
+ Node* NewIfTrue() { return NewNode(common()->IfTrue()); } |
+ Node* NewIfFalse() { return NewNode(common()->IfFalse()); } |
+ Node* NewMerge() { return NewNode(common()->Merge(1), true); } |
+ Node* NewLoop() { return NewNode(common()->Loop(1), true); } |
+ Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) { |
+ return NewNode(common()->Branch(hint), condition); |
+ } |
+ // Creates a new Phi node having {count} input values. |
+ Node* NewPhi(int count, Node* input, Node* control); |
+ Node* NewEffectPhi(int count, Node* input, Node* control); |
+ |
+ // Helpers for merging control, effect or value dependencies. |
Node* MergeControl(Node* control, Node* other); |
+ Node* MergeEffect(Node* effect, Node* other_effect, Node* control); |
+ Node* MergeValue(Node* value, Node* other_value, Node* control); |
- Node** EnsureInputBufferSize(int size); |
+ // The main node creation chokepoint. Adds context, frame state, effect, |
+ // and control dependencies depending on the operator. |
+ Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs, |
+ bool incomplete); |
+ // Helper to indicate a node exits the function body. |
void UpdateControlDependencyToLeaveFunction(Node* exit); |
+ Node** EnsureInputBufferSize(int size); |
+ |
Node* ProcessCallArguments(const Operator* call_op, Node* callee, |
interpreter::Register receiver, size_t arity); |
Node* ProcessCallNewArguments(const Operator* call_new_op, |
@@ -123,6 +151,14 @@ class BytecodeGraphBuilder { |
void BuildCastOperator(const Operator* js_op, |
const interpreter::BytecodeArrayIterator& iterator); |
+ // Control flow plumbing. |
+ void PrepareForNewBasicBlockVisit(); |
+ void CompleteNewBasicBlockVisit(); |
+ void BuildReturn(); |
+ void BuildJump(); |
+ void BuildConditionalJump(Node* condition); |
+ void BuildBackEdgeIfRequired(BytecodeBasicBlock* target); |
+ |
// Growth increment for the temporary buffer used to construct input lists to |
// new nodes. |
static const int kInputBufferSizeIncrement = 64; |
@@ -154,6 +190,9 @@ class BytecodeGraphBuilder { |
Handle<BytecodeArray> bytecode_array_; |
Environment* environment_; |
+ const BytecodeBasicBlock* basic_block_; |
+ ZoneVector<BlockEnvironmentInfo*> block_environment_infos_; |
+ |
// Temporary storage for building node input lists. |
int input_buffer_size_; |
Node** input_buffer_; |
@@ -205,9 +244,15 @@ class BytecodeGraphBuilder::Environment : public ZoneObject { |
Node* Context() const { return context_; } |
void SetContext(Node* new_context) { context_ = new_context; } |
+ Environment* CopyForConditional() const; |
+ Environment* CopyForLoop(); |
+ void Merge(Environment* other); |
+ |
private: |
- int RegisterToValuesIndex(interpreter::Register the_register) const; |
+ explicit Environment(const Environment* copy); |
+ void PrepareForLoop(); |
+ int RegisterToValuesIndex(interpreter::Register the_register) const; |
Zone* zone() const { return builder_->local_zone(); } |
Graph* graph() const { return builder_->graph(); } |
CommonOperatorBuilder* common() const { return builder_->common(); } |
@@ -228,6 +273,30 @@ class BytecodeGraphBuilder::Environment : public ZoneObject { |
int register_base_; |
}; |
+// A class to help passage between the environments associated with basic |
+// blocks. |
+class BytecodeGraphBuilder::BlockEnvironmentInfo final : public ZoneObject { |
+ public: |
+ typedef BytecodeGraphBuilder::Environment Environment; |
+ |
+ BlockEnvironmentInfo() |
+ : loop_header_env_(nullptr), |
+ if_true_env_(nullptr), |
+ if_false_env_(nullptr) {} |
+ |
+ Environment* loop_header_environment() const { return loop_header_env_; } |
+ Environment* if_true_environment() const { return if_true_env_; } |
+ Environment* if_false_environment() const { return if_false_env_; } |
+ |
+ void set_loop_header_environment(Environment* env) { loop_header_env_ = env; } |
+ void set_if_true_environment(Environment* env) { if_true_env_ = env; } |
+ void set_if_false_environment(Environment* env) { if_false_env_ = env; } |
+ |
+ private: |
+ Environment* loop_header_env_; |
+ Environment* if_true_env_; |
+ Environment* if_false_env_; |
+}; |
} // namespace compiler |
} // namespace internal |