OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_ | 5 #ifndef V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_ |
6 #define V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_ | 6 #define V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_ |
7 | 7 |
8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/interpreter/bytecode-array-iterator.h" | 10 #include "src/interpreter/bytecode-array-iterator.h" |
11 #include "src/interpreter/bytecodes.h" | 11 #include "src/interpreter/bytecodes.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 namespace compiler { | 15 namespace compiler { |
16 | 16 |
| 17 class BytecodeBasicBlock; |
| 18 |
17 // The BytecodeGraphBuilder produces a high-level IR graph based on | 19 // The BytecodeGraphBuilder produces a high-level IR graph based on |
18 // interpreter bytecodes. | 20 // interpreter bytecodes. |
19 class BytecodeGraphBuilder { | 21 class BytecodeGraphBuilder { |
20 public: | 22 public: |
21 BytecodeGraphBuilder(Zone* local_zone, CompilationInfo* info, | 23 BytecodeGraphBuilder(Zone* local_zone, CompilationInfo* info, |
22 JSGraph* jsgraph); | 24 JSGraph* jsgraph); |
23 | 25 |
24 // Creates a graph by visiting bytecodes. | 26 // Creates a graph by visiting bytecodes. |
25 bool CreateGraph(bool stack_check = true); | 27 bool CreateGraph(bool stack_check = true); |
26 | 28 |
27 Graph* graph() const { return jsgraph_->graph(); } | 29 Graph* graph() const { return jsgraph_->graph(); } |
28 | 30 |
29 private: | 31 private: |
30 class Environment; | 32 class Environment; |
| 33 class BlockEnvironmentInfo; |
31 | 34 |
32 void CreateGraphBody(bool stack_check); | 35 void CreateGraphBody(bool stack_check); |
33 void VisitBytecodes(); | 36 void VisitBasicBlocks(); |
| 37 void VisitBytecodesInBasicBlock(BytecodeBasicBlock* block); |
34 | 38 |
35 Node* LoadAccumulator(Node* value); | 39 Node* LoadAccumulator(Node* value); |
36 | 40 |
37 // Get or create the node that represents the outer function closure. | 41 // Get or create the node that represents the outer function closure. |
38 Node* GetFunctionClosure(); | 42 Node* GetFunctionClosure(); |
39 | 43 |
40 // Get or create the node that represents the outer function context. | 44 // Get or create the node that represents the outer function context. |
41 Node* GetFunctionContext(); | 45 Node* GetFunctionContext(); |
42 | 46 |
43 // Get or create the node that represents the incoming new target value. | 47 // Get or create the node that represents the incoming new target value. |
(...skipping 13 matching lines...) Expand all Loading... |
57 // a feedback slot. | 61 // a feedback slot. |
58 VectorSlotPair CreateVectorSlotPair(int slot_id); | 62 VectorSlotPair CreateVectorSlotPair(int slot_id); |
59 | 63 |
60 // Replaces the frame state inputs with empty frame states. | 64 // Replaces the frame state inputs with empty frame states. |
61 void AddEmptyFrameStateInputs(Node* node); | 65 void AddEmptyFrameStateInputs(Node* node); |
62 | 66 |
63 void set_environment(Environment* env) { environment_ = env; } | 67 void set_environment(Environment* env) { environment_ = env; } |
64 const Environment* environment() const { return environment_; } | 68 const Environment* environment() const { return environment_; } |
65 Environment* environment() { return environment_; } | 69 Environment* environment() { return environment_; } |
66 | 70 |
| 71 void set_basic_block(const BytecodeBasicBlock* block) { |
| 72 basic_block_ = block; |
| 73 } |
| 74 const BytecodeBasicBlock* basic_block() const { return basic_block_; } |
| 75 |
67 // Node creation helpers | 76 // Node creation helpers |
68 Node* NewNode(const Operator* op, bool incomplete = false) { | 77 Node* NewNode(const Operator* op, bool incomplete = false) { |
69 return MakeNode(op, 0, static_cast<Node**>(NULL), incomplete); | 78 return MakeNode(op, 0, static_cast<Node**>(NULL), incomplete); |
70 } | 79 } |
71 | 80 |
72 Node* NewNode(const Operator* op, Node* n1) { | 81 Node* NewNode(const Operator* op, Node* n1) { |
73 Node* buffer[] = {n1}; | 82 Node* buffer[] = {n1}; |
74 return MakeNode(op, arraysize(buffer), buffer, false); | 83 return MakeNode(op, arraysize(buffer), buffer, false); |
75 } | 84 } |
76 | 85 |
77 Node* NewNode(const Operator* op, Node* n1, Node* n2) { | 86 Node* NewNode(const Operator* op, Node* n1, Node* n2) { |
78 Node* buffer[] = {n1, n2}; | 87 Node* buffer[] = {n1, n2}; |
79 return MakeNode(op, arraysize(buffer), buffer, false); | 88 return MakeNode(op, arraysize(buffer), buffer, false); |
80 } | 89 } |
81 | 90 |
82 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) { | 91 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) { |
83 Node* buffer[] = {n1, n2, n3}; | 92 Node* buffer[] = {n1, n2, n3}; |
84 return MakeNode(op, arraysize(buffer), buffer, false); | 93 return MakeNode(op, arraysize(buffer), buffer, false); |
85 } | 94 } |
86 | 95 |
87 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) { | 96 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) { |
88 Node* buffer[] = {n1, n2, n3, n4}; | 97 Node* buffer[] = {n1, n2, n3, n4}; |
89 return MakeNode(op, arraysize(buffer), buffer, false); | 98 return MakeNode(op, arraysize(buffer), buffer, false); |
90 } | 99 } |
91 | 100 |
| 101 // Helpers to create new control nodes. |
| 102 Node* NewIfTrue() { return NewNode(common()->IfTrue()); } |
| 103 Node* NewIfFalse() { return NewNode(common()->IfFalse()); } |
| 104 Node* NewMerge() { return NewNode(common()->Merge(1), true); } |
| 105 Node* NewLoop() { return NewNode(common()->Loop(1), true); } |
| 106 Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) { |
| 107 return NewNode(common()->Branch(hint), condition); |
| 108 } |
| 109 |
| 110 // Creates a new Phi node having {count} input values. |
| 111 Node* NewPhi(int count, Node* input, Node* control); |
| 112 Node* NewEffectPhi(int count, Node* input, Node* control); |
| 113 |
| 114 // Helpers for merging control, effect or value dependencies. |
| 115 Node* MergeControl(Node* control, Node* other); |
| 116 Node* MergeEffect(Node* effect, Node* other_effect, Node* control); |
| 117 Node* MergeValue(Node* value, Node* other_value, Node* control); |
| 118 |
| 119 // The main node creation chokepoint. Adds context, frame state, effect, |
| 120 // and control dependencies depending on the operator. |
92 Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs, | 121 Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs, |
93 bool incomplete); | 122 bool incomplete); |
94 | 123 |
95 Node* MergeControl(Node* control, Node* other); | 124 // Helper to indicate a node exits the function body. |
| 125 void UpdateControlDependencyToLeaveFunction(Node* exit); |
96 | 126 |
97 Node** EnsureInputBufferSize(int size); | 127 Node** EnsureInputBufferSize(int size); |
98 | 128 |
99 void UpdateControlDependencyToLeaveFunction(Node* exit); | |
100 | |
101 Node* ProcessCallArguments(const Operator* call_op, Node* callee, | 129 Node* ProcessCallArguments(const Operator* call_op, Node* callee, |
102 interpreter::Register receiver, size_t arity); | 130 interpreter::Register receiver, size_t arity); |
103 Node* ProcessCallNewArguments(const Operator* call_new_op, | 131 Node* ProcessCallNewArguments(const Operator* call_new_op, |
104 interpreter::Register callee, | 132 interpreter::Register callee, |
105 interpreter::Register first_arg, size_t arity); | 133 interpreter::Register first_arg, size_t arity); |
106 Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op, | 134 Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op, |
107 interpreter::Register first_arg, | 135 interpreter::Register first_arg, |
108 size_t arity); | 136 size_t arity); |
109 | 137 |
110 void BuildLoadGlobal(const interpreter::BytecodeArrayIterator& iterator, | 138 void BuildLoadGlobal(const interpreter::BytecodeArrayIterator& iterator, |
111 TypeofMode typeof_mode); | 139 TypeofMode typeof_mode); |
112 void BuildStoreGlobal(const interpreter::BytecodeArrayIterator& iterator); | 140 void BuildStoreGlobal(const interpreter::BytecodeArrayIterator& iterator); |
113 void BuildNamedLoad(const interpreter::BytecodeArrayIterator& iterator); | 141 void BuildNamedLoad(const interpreter::BytecodeArrayIterator& iterator); |
114 void BuildKeyedLoad(const interpreter::BytecodeArrayIterator& iterator); | 142 void BuildKeyedLoad(const interpreter::BytecodeArrayIterator& iterator); |
115 void BuildNamedStore(const interpreter::BytecodeArrayIterator& iterator); | 143 void BuildNamedStore(const interpreter::BytecodeArrayIterator& iterator); |
116 void BuildKeyedStore(const interpreter::BytecodeArrayIterator& iterator); | 144 void BuildKeyedStore(const interpreter::BytecodeArrayIterator& iterator); |
117 void BuildCall(const interpreter::BytecodeArrayIterator& iterator); | 145 void BuildCall(const interpreter::BytecodeArrayIterator& iterator); |
118 void BuildBinaryOp(const Operator* op, | 146 void BuildBinaryOp(const Operator* op, |
119 const interpreter::BytecodeArrayIterator& iterator); | 147 const interpreter::BytecodeArrayIterator& iterator); |
120 void BuildCompareOp(const Operator* op, | 148 void BuildCompareOp(const Operator* op, |
121 const interpreter::BytecodeArrayIterator& iterator); | 149 const interpreter::BytecodeArrayIterator& iterator); |
122 void BuildDelete(const interpreter::BytecodeArrayIterator& iterator); | 150 void BuildDelete(const interpreter::BytecodeArrayIterator& iterator); |
123 void BuildCastOperator(const Operator* js_op, | 151 void BuildCastOperator(const Operator* js_op, |
124 const interpreter::BytecodeArrayIterator& iterator); | 152 const interpreter::BytecodeArrayIterator& iterator); |
125 | 153 |
| 154 // Control flow plumbing. |
| 155 void PrepareForNewBasicBlockVisit(); |
| 156 void CompleteNewBasicBlockVisit(); |
| 157 void BuildReturn(); |
| 158 void BuildJump(); |
| 159 void BuildConditionalJump(Node* condition); |
| 160 void BuildBackEdgeIfRequired(BytecodeBasicBlock* target); |
| 161 |
126 // Growth increment for the temporary buffer used to construct input lists to | 162 // Growth increment for the temporary buffer used to construct input lists to |
127 // new nodes. | 163 // new nodes. |
128 static const int kInputBufferSizeIncrement = 64; | 164 static const int kInputBufferSizeIncrement = 64; |
129 | 165 |
130 // Field accessors | 166 // Field accessors |
131 CommonOperatorBuilder* common() const { return jsgraph_->common(); } | 167 CommonOperatorBuilder* common() const { return jsgraph_->common(); } |
132 Zone* graph_zone() const { return graph()->zone(); } | 168 Zone* graph_zone() const { return graph()->zone(); } |
133 CompilationInfo* info() const { return info_; } | 169 CompilationInfo* info() const { return info_; } |
134 JSGraph* jsgraph() const { return jsgraph_; } | 170 JSGraph* jsgraph() const { return jsgraph_; } |
135 JSOperatorBuilder* javascript() const { return jsgraph_->javascript(); } | 171 JSOperatorBuilder* javascript() const { return jsgraph_->javascript(); } |
(...skipping 11 matching lines...) Expand all Loading... |
147 void Visit##name(const interpreter::BytecodeArrayIterator& iterator); | 183 void Visit##name(const interpreter::BytecodeArrayIterator& iterator); |
148 BYTECODE_LIST(DECLARE_VISIT_BYTECODE) | 184 BYTECODE_LIST(DECLARE_VISIT_BYTECODE) |
149 #undef DECLARE_VISIT_BYTECODE | 185 #undef DECLARE_VISIT_BYTECODE |
150 | 186 |
151 Zone* local_zone_; | 187 Zone* local_zone_; |
152 CompilationInfo* info_; | 188 CompilationInfo* info_; |
153 JSGraph* jsgraph_; | 189 JSGraph* jsgraph_; |
154 Handle<BytecodeArray> bytecode_array_; | 190 Handle<BytecodeArray> bytecode_array_; |
155 Environment* environment_; | 191 Environment* environment_; |
156 | 192 |
| 193 const BytecodeBasicBlock* basic_block_; |
| 194 ZoneVector<BlockEnvironmentInfo*> block_environment_infos_; |
| 195 |
157 // Temporary storage for building node input lists. | 196 // Temporary storage for building node input lists. |
158 int input_buffer_size_; | 197 int input_buffer_size_; |
159 Node** input_buffer_; | 198 Node** input_buffer_; |
160 | 199 |
161 // Nodes representing values in the activation record. | 200 // Nodes representing values in the activation record. |
162 SetOncePointer<Node> function_context_; | 201 SetOncePointer<Node> function_context_; |
163 SetOncePointer<Node> function_closure_; | 202 SetOncePointer<Node> function_closure_; |
164 SetOncePointer<Node> new_target_; | 203 SetOncePointer<Node> new_target_; |
165 | 204 |
166 // Optimization to cache loaded feedback vector. | 205 // Optimization to cache loaded feedback vector. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 | 237 |
199 // Control dependency tracked by this environment. | 238 // Control dependency tracked by this environment. |
200 Node* GetControlDependency() const { return control_dependency_; } | 239 Node* GetControlDependency() const { return control_dependency_; } |
201 void UpdateControlDependency(Node* dependency) { | 240 void UpdateControlDependency(Node* dependency) { |
202 control_dependency_ = dependency; | 241 control_dependency_ = dependency; |
203 } | 242 } |
204 | 243 |
205 Node* Context() const { return context_; } | 244 Node* Context() const { return context_; } |
206 void SetContext(Node* new_context) { context_ = new_context; } | 245 void SetContext(Node* new_context) { context_ = new_context; } |
207 | 246 |
| 247 Environment* CopyForConditional() const; |
| 248 Environment* CopyForLoop(); |
| 249 void Merge(Environment* other); |
| 250 |
208 private: | 251 private: |
| 252 explicit Environment(const Environment* copy); |
| 253 void PrepareForLoop(); |
| 254 |
209 int RegisterToValuesIndex(interpreter::Register the_register) const; | 255 int RegisterToValuesIndex(interpreter::Register the_register) const; |
210 | |
211 Zone* zone() const { return builder_->local_zone(); } | 256 Zone* zone() const { return builder_->local_zone(); } |
212 Graph* graph() const { return builder_->graph(); } | 257 Graph* graph() const { return builder_->graph(); } |
213 CommonOperatorBuilder* common() const { return builder_->common(); } | 258 CommonOperatorBuilder* common() const { return builder_->common(); } |
214 BytecodeGraphBuilder* builder() const { return builder_; } | 259 BytecodeGraphBuilder* builder() const { return builder_; } |
215 const NodeVector* values() const { return &values_; } | 260 const NodeVector* values() const { return &values_; } |
216 NodeVector* values() { return &values_; } | 261 NodeVector* values() { return &values_; } |
217 Node* accumulator() { return accumulator_; } | 262 Node* accumulator() { return accumulator_; } |
218 int register_base() const { return register_base_; } | 263 int register_base() const { return register_base_; } |
219 | 264 |
220 BytecodeGraphBuilder* builder_; | 265 BytecodeGraphBuilder* builder_; |
221 int register_count_; | 266 int register_count_; |
222 int parameter_count_; | 267 int parameter_count_; |
223 Node* accumulator_; | 268 Node* accumulator_; |
224 Node* context_; | 269 Node* context_; |
225 Node* control_dependency_; | 270 Node* control_dependency_; |
226 Node* effect_dependency_; | 271 Node* effect_dependency_; |
227 NodeVector values_; | 272 NodeVector values_; |
228 int register_base_; | 273 int register_base_; |
229 }; | 274 }; |
230 | 275 |
| 276 // A class to help passage between the environments associated with basic |
| 277 // blocks. |
| 278 class BytecodeGraphBuilder::BlockEnvironmentInfo final : public ZoneObject { |
| 279 public: |
| 280 typedef BytecodeGraphBuilder::Environment Environment; |
| 281 |
| 282 BlockEnvironmentInfo() |
| 283 : loop_header_env_(nullptr), |
| 284 if_true_env_(nullptr), |
| 285 if_false_env_(nullptr) {} |
| 286 |
| 287 Environment* loop_header_environment() const { return loop_header_env_; } |
| 288 Environment* if_true_environment() const { return if_true_env_; } |
| 289 Environment* if_false_environment() const { return if_false_env_; } |
| 290 |
| 291 void set_loop_header_environment(Environment* env) { loop_header_env_ = env; } |
| 292 void set_if_true_environment(Environment* env) { if_true_env_ = env; } |
| 293 void set_if_false_environment(Environment* env) { if_false_env_ = env; } |
| 294 |
| 295 private: |
| 296 Environment* loop_header_env_; |
| 297 Environment* if_true_env_; |
| 298 Environment* if_false_env_; |
| 299 }; |
231 | 300 |
232 } // namespace compiler | 301 } // namespace compiler |
233 } // namespace internal | 302 } // namespace internal |
234 } // namespace v8 | 303 } // namespace v8 |
235 | 304 |
236 #endif // V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_ | 305 #endif // V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_ |
OLD | NEW |