OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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_AST_GRAPH_BUILDER_H_ | 5 #ifndef V8_COMPILER_AST_GRAPH_BUILDER_H_ |
6 #define V8_COMPILER_AST_GRAPH_BUILDER_H_ | 6 #define V8_COMPILER_AST_GRAPH_BUILDER_H_ |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/ast.h" | 10 #include "src/ast.h" |
11 #include "src/compiler/graph-builder.h" | |
12 #include "src/compiler/js-graph.h" | 11 #include "src/compiler/js-graph.h" |
13 | 12 |
14 namespace v8 { | 13 namespace v8 { |
15 namespace internal { | 14 namespace internal { |
15 | |
16 class BitVector; | |
17 | |
16 namespace compiler { | 18 namespace compiler { |
17 | 19 |
18 class ControlBuilder; | 20 class ControlBuilder; |
19 class Graph; | 21 class Graph; |
20 class LoopAssignmentAnalysis; | 22 class LoopAssignmentAnalysis; |
21 class LoopBuilder; | 23 class LoopBuilder; |
24 class Node; | |
22 | 25 |
23 // The AstGraphBuilder produces a high-level IR graph, based on an | 26 // The AstGraphBuilder produces a high-level IR graph, based on an |
24 // underlying AST. The produced graph can either be compiled into a | 27 // underlying AST. The produced graph can either be compiled into a |
25 // stand-alone function or be wired into another graph for the purposes | 28 // stand-alone function or be wired into another graph for the purposes |
26 // of function inlining. | 29 // of function inlining. |
27 class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor { | 30 class AstGraphBuilder : public AstVisitor { |
28 public: | 31 public: |
29 AstGraphBuilder(Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph, | 32 AstGraphBuilder(Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph, |
30 LoopAssignmentAnalysis* loop_assignment = NULL); | 33 LoopAssignmentAnalysis* loop_assignment = NULL); |
31 | 34 |
32 // Creates a graph by visiting the entire AST. | 35 // Creates a graph by visiting the entire AST. |
33 bool CreateGraph(); | 36 bool CreateGraph(); |
34 | 37 |
38 // Get the node that represents the outer function context. | |
39 Node* GetFunctionContext(); | |
Michael Starzinger
2015/02/02 18:34:55
nit: This can be made protected I think.
titzer
2015/02/02 18:39:06
Done.
| |
40 | |
41 // Helpers to create new control nodes. | |
42 Node* NewIfTrue() { return NewNode(common()->IfTrue()); } | |
43 Node* NewIfFalse() { return NewNode(common()->IfFalse()); } | |
44 Node* NewMerge() { return NewNode(common()->Merge(1), true); } | |
45 Node* NewLoop() { return NewNode(common()->Loop(1), true); } | |
46 Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) { | |
47 return NewNode(common()->Branch(hint), condition); | |
48 } | |
49 | |
35 protected: | 50 protected: |
51 #define DECLARE_VISIT(type) void Visit##type(type* node) OVERRIDE; | |
52 // Visiting functions for AST nodes make this an AstVisitor. | |
53 AST_NODE_LIST(DECLARE_VISIT) | |
54 #undef DECLARE_VISIT | |
55 | |
56 // Visiting function for declarations list is overridden. | |
57 void VisitDeclarations(ZoneList<Declaration*>* declarations) OVERRIDE; | |
58 | |
59 private: | |
36 class AstContext; | 60 class AstContext; |
37 class AstEffectContext; | 61 class AstEffectContext; |
38 class AstValueContext; | 62 class AstValueContext; |
39 class AstTestContext; | 63 class AstTestContext; |
40 class BreakableScope; | 64 class BreakableScope; |
41 class ContextScope; | 65 class ContextScope; |
42 class Environment; | 66 class Environment; |
67 friend class ControlBuilder; | |
43 | 68 |
44 Environment* environment() { | 69 Zone* local_zone_; |
45 return reinterpret_cast<Environment*>( | 70 CompilationInfo* info_; |
46 StructuredGraphBuilder::environment()); | 71 JSGraph* jsgraph_; |
47 } | 72 Environment* environment_; |
73 AstContext* ast_context_; | |
48 | 74 |
75 // List of global declarations for functions and variables. | |
76 ZoneVector<Handle<Object>> globals_; | |
77 | |
78 // Stack of breakable statements entered by the visitor. | |
79 BreakableScope* breakable_; | |
80 | |
81 // Stack of context objects pushed onto the chain by the visitor. | |
82 ContextScope* execution_context_; | |
83 | |
84 // Nodes representing values in the activation record. | |
85 SetOncePointer<Node> function_closure_; | |
86 SetOncePointer<Node> function_context_; | |
87 | |
88 // Temporary storage for building node input lists. | |
89 int input_buffer_size_; | |
90 Node** input_buffer_; | |
91 | |
92 // Node representing the control dependency for dead code. | |
93 SetOncePointer<Node> dead_control_; | |
94 | |
95 // Node representing the current context within the function body. | |
96 Node* current_context_; | |
97 | |
98 // Merge of all control nodes that exit the function body. | |
99 Node* exit_control_; | |
100 | |
101 // Result of loop assignment analysis performed before graph creation. | |
102 LoopAssignmentAnalysis* loop_assignment_analysis_; | |
103 | |
104 // Growth increment for the temporary buffer used to construct input lists to | |
105 // new nodes. | |
106 static const int kInputBufferSizeIncrement = 64; | |
107 | |
108 Zone* local_zone() const { return local_zone_; } | |
109 Environment* environment() { return environment_; } | |
49 AstContext* ast_context() const { return ast_context_; } | 110 AstContext* ast_context() const { return ast_context_; } |
50 BreakableScope* breakable() const { return breakable_; } | 111 BreakableScope* breakable() const { return breakable_; } |
51 ContextScope* execution_context() const { return execution_context_; } | 112 ContextScope* execution_context() const { return execution_context_; } |
113 CommonOperatorBuilder* common() const { return jsgraph_->common(); } | |
114 CompilationInfo* info() const { return info_; } | |
115 StrictMode strict_mode() const; | |
116 JSGraph* jsgraph() { return jsgraph_; } | |
117 Graph* graph() { return jsgraph_->graph(); } | |
118 Zone* graph_zone() { return graph()->zone(); } | |
119 JSOperatorBuilder* javascript() { return jsgraph_->javascript(); } | |
120 ZoneVector<Handle<Object>>* globals() { return &globals_; } | |
121 inline Scope* current_scope() const; | |
122 Node* current_context() const { return current_context_; } | |
123 Node* dead_control(); | |
124 Node* exit_control() const { return exit_control_; } | |
52 | 125 |
53 void set_ast_context(AstContext* ctx) { ast_context_ = ctx; } | 126 void set_ast_context(AstContext* ctx) { ast_context_ = ctx; } |
54 void set_breakable(BreakableScope* brk) { breakable_ = brk; } | 127 void set_breakable(BreakableScope* brk) { breakable_ = brk; } |
55 void set_execution_context(ContextScope* ctx) { execution_context_ = ctx; } | 128 void set_execution_context(ContextScope* ctx) { execution_context_ = ctx; } |
129 void set_exit_control(Node* exit) { exit_control_ = exit; } | |
130 void set_current_context(Node* ctx) { current_context_ = ctx; } | |
131 void set_environment(Environment* env) { environment_ = env; } | |
56 | 132 |
57 // Support for control flow builders. The concrete type of the environment | 133 // Node creation helpers. |
58 // depends on the graph builder, but environments themselves are not virtual. | 134 Node* NewNode(const Operator* op, bool incomplete = false) { |
59 typedef StructuredGraphBuilder::Environment BaseEnvironment; | 135 return MakeNode(op, 0, static_cast<Node**>(NULL), incomplete); |
60 BaseEnvironment* CopyEnvironment(BaseEnvironment* env) OVERRIDE; | 136 } |
137 | |
138 Node* NewNode(const Operator* op, Node* n1) { | |
139 return MakeNode(op, 1, &n1, false); | |
140 } | |
141 | |
142 Node* NewNode(const Operator* op, Node* n1, Node* n2) { | |
143 Node* buffer[] = {n1, n2}; | |
144 return MakeNode(op, arraysize(buffer), buffer, false); | |
145 } | |
146 | |
147 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) { | |
148 Node* buffer[] = {n1, n2, n3}; | |
149 return MakeNode(op, arraysize(buffer), buffer, false); | |
150 } | |
151 | |
152 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) { | |
153 Node* buffer[] = {n1, n2, n3, n4}; | |
154 return MakeNode(op, arraysize(buffer), buffer, false); | |
155 } | |
156 | |
157 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4, | |
158 Node* n5) { | |
159 Node* buffer[] = {n1, n2, n3, n4, n5}; | |
160 return MakeNode(op, arraysize(buffer), buffer, false); | |
161 } | |
162 | |
163 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4, | |
164 Node* n5, Node* n6) { | |
165 Node* nodes[] = {n1, n2, n3, n4, n5, n6}; | |
166 return MakeNode(op, arraysize(nodes), nodes, false); | |
167 } | |
168 | |
169 Node* NewNode(const Operator* op, int value_input_count, Node** value_inputs, | |
170 bool incomplete = false) { | |
171 return MakeNode(op, value_input_count, value_inputs, incomplete); | |
172 } | |
173 | |
174 // Creates a new Phi node having {count} input values. | |
175 Node* NewPhi(int count, Node* input, Node* control); | |
176 Node* NewEffectPhi(int count, Node* input, Node* control); | |
177 | |
178 // Helpers for merging control, effect or value dependencies. | |
179 Node* MergeControl(Node* control, Node* other); | |
180 Node* MergeEffect(Node* value, Node* other, Node* control); | |
181 Node* MergeValue(Node* value, Node* other, Node* control); | |
182 | |
183 // The main node creation chokepoint. Adds context, frame state, effect, | |
184 // and control dependencies depending on the operator. | |
185 Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs, | |
186 bool incomplete); | |
61 | 187 |
62 // Getters for values in the activation record. | 188 // Getters for values in the activation record. |
63 Node* GetFunctionClosure(); | 189 Node* GetFunctionClosure(); |
Michael Starzinger
2015/02/02 18:34:55
nit: Can we keep this one together with GetFunctio
titzer
2015/02/02 18:39:06
Done.
| |
64 Node* GetFunctionContext(); | 190 |
191 // Helper to indicate a node exits the function body. | |
192 void UpdateControlDependencyToLeaveFunction(Node* exit); | |
65 | 193 |
66 // | 194 // |
67 // The following build methods all generate graph fragments and return one | 195 // The following build methods all generate graph fragments and return one |
68 // resulting node. The operand stack height remains the same, variables and | 196 // resulting node. The operand stack height remains the same, variables and |
69 // other dependencies tracked by the environment might be mutated though. | 197 // other dependencies tracked by the environment might be mutated though. |
70 // | 198 // |
71 | 199 |
72 // Builder to create a receiver check for sloppy mode. | 200 // Builder to create a receiver check for sloppy mode. |
73 Node* BuildPatchReceiverToGlobalProxy(Node* receiver); | 201 Node* BuildPatchReceiverToGlobalProxy(Node* receiver); |
74 | 202 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 // Builders for binary operations. | 241 // Builders for binary operations. |
114 Node* BuildBinaryOp(Node* left, Node* right, Token::Value op); | 242 Node* BuildBinaryOp(Node* left, Node* right, Token::Value op); |
115 | 243 |
116 // Builder for stack-check guards. | 244 // Builder for stack-check guards. |
117 Node* BuildStackCheck(); | 245 Node* BuildStackCheck(); |
118 | 246 |
119 // Check if the given statement is an OSR entry. | 247 // Check if the given statement is an OSR entry. |
120 // If so, record the stack height into the compilation and return {true}. | 248 // If so, record the stack height into the compilation and return {true}. |
121 bool CheckOsrEntry(IterationStatement* stmt); | 249 bool CheckOsrEntry(IterationStatement* stmt); |
122 | 250 |
123 #define DECLARE_VISIT(type) void Visit##type(type* node) OVERRIDE; | 251 // Helper to wrap a Handle<T> into a Unique<T>. |
252 template <class T> | |
253 Unique<T> MakeUnique(Handle<T> object) { | |
254 return Unique<T>::CreateUninitialized(object); | |
255 } | |
124 | 256 |
125 // Visiting functions for AST nodes make this an AstVisitor. | 257 Node** EnsureInputBufferSize(int size); |
126 AST_NODE_LIST(DECLARE_VISIT) | |
127 #undef DECLARE_VISIT | |
128 | |
129 // Visiting function for declarations list is overridden. | |
130 void VisitDeclarations(ZoneList<Declaration*>* declarations) OVERRIDE; | |
131 | |
132 private: | |
133 CompilationInfo* info_; | |
134 AstContext* ast_context_; | |
135 JSGraph* jsgraph_; | |
136 | |
137 // List of global declarations for functions and variables. | |
138 ZoneVector<Handle<Object>> globals_; | |
139 | |
140 // Stack of breakable statements entered by the visitor. | |
141 BreakableScope* breakable_; | |
142 | |
143 // Stack of context objects pushed onto the chain by the visitor. | |
144 ContextScope* execution_context_; | |
145 | |
146 // Nodes representing values in the activation record. | |
147 SetOncePointer<Node> function_closure_; | |
148 SetOncePointer<Node> function_context_; | |
149 | |
150 // The node representing the OSR entry into the loop, if any. | |
151 SetOncePointer<Node> osr_loop_entry_; | |
152 | |
153 // Result of loop assignment analysis performed before graph creation. | |
154 LoopAssignmentAnalysis* loop_assignment_analysis_; | |
155 | |
156 CompilationInfo* info() const { return info_; } | |
157 inline StrictMode strict_mode() const; | |
158 JSGraph* jsgraph() { return jsgraph_; } | |
159 JSOperatorBuilder* javascript() { return jsgraph_->javascript(); } | |
160 ZoneVector<Handle<Object>>* globals() { return &globals_; } | |
161 | |
162 // Current scope during visitation. | |
163 inline Scope* current_scope() const; | |
164 | 258 |
165 // Named and keyed loads require a VectorSlotPair for successful lowering. | 259 // Named and keyed loads require a VectorSlotPair for successful lowering. |
166 VectorSlotPair CreateVectorSlotPair(FeedbackVectorICSlot slot) const; | 260 VectorSlotPair CreateVectorSlotPair(FeedbackVectorICSlot slot) const; |
167 | 261 |
168 // Process arguments to a call by popping {arity} elements off the operand | 262 // Process arguments to a call by popping {arity} elements off the operand |
169 // stack and build a call node using the given call operator. | 263 // stack and build a call node using the given call operator. |
170 Node* ProcessArguments(const Operator* op, int arity); | 264 Node* ProcessArguments(const Operator* op, int arity); |
171 | 265 |
172 // Visit statements. | 266 // Visit statements. |
173 void VisitIfNotNull(Statement* stmt); | 267 void VisitIfNotNull(Statement* stmt); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 | 313 |
220 | 314 |
221 // The abstract execution environment for generated code consists of | 315 // The abstract execution environment for generated code consists of |
222 // parameter variables, local variables and the operand stack. The | 316 // parameter variables, local variables and the operand stack. The |
223 // environment will perform proper SSA-renaming of all tracked nodes | 317 // environment will perform proper SSA-renaming of all tracked nodes |
224 // at split and merge points in the control flow. Internally all the | 318 // at split and merge points in the control flow. Internally all the |
225 // values are stored in one list using the following layout: | 319 // values are stored in one list using the following layout: |
226 // | 320 // |
227 // [parameters (+receiver)] [locals] [operand stack] | 321 // [parameters (+receiver)] [locals] [operand stack] |
228 // | 322 // |
229 class AstGraphBuilder::Environment | 323 class AstGraphBuilder::Environment : public ZoneObject { |
230 : public StructuredGraphBuilder::Environment { | |
231 public: | 324 public: |
232 Environment(AstGraphBuilder* builder, Scope* scope, Node* control_dependency); | 325 Environment(AstGraphBuilder* builder, Scope* scope, Node* control_dependency); |
233 Environment(const Environment& copy); | |
234 | 326 |
235 int parameters_count() const { return parameters_count_; } | 327 int parameters_count() const { return parameters_count_; } |
236 int locals_count() const { return locals_count_; } | 328 int locals_count() const { return locals_count_; } |
237 int stack_height() { | 329 int stack_height() { |
238 return static_cast<int>(values()->size()) - parameters_count_ - | 330 return static_cast<int>(values()->size()) - parameters_count_ - |
239 locals_count_; | 331 locals_count_; |
240 } | 332 } |
241 | 333 |
242 // Operations on parameter or local variables. The parameter indices are | 334 // Operations on parameter or local variables. The parameter indices are |
243 // shifted by 1 (receiver is parameter index -1 but environment index 0). | 335 // shifted by 1 (receiver is parameter index -1 but environment index 0). |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
288 } | 380 } |
289 void Drop(int depth) { | 381 void Drop(int depth) { |
290 DCHECK(depth >= 0 && depth <= stack_height()); | 382 DCHECK(depth >= 0 && depth <= stack_height()); |
291 values()->erase(values()->end() - depth, values()->end()); | 383 values()->erase(values()->end() - depth, values()->end()); |
292 } | 384 } |
293 | 385 |
294 // Preserve a checkpoint of the environment for the IR graph. Any | 386 // Preserve a checkpoint of the environment for the IR graph. Any |
295 // further mutation of the environment will not affect checkpoints. | 387 // further mutation of the environment will not affect checkpoints. |
296 Node* Checkpoint(BailoutId ast_id, OutputFrameStateCombine combine); | 388 Node* Checkpoint(BailoutId ast_id, OutputFrameStateCombine combine); |
297 | 389 |
298 protected: | 390 // Control dependency tracked by this environment. |
299 AstGraphBuilder* builder() const { | 391 Node* GetControlDependency() { return control_dependency_; } |
300 return reinterpret_cast<AstGraphBuilder*>( | 392 void UpdateControlDependency(Node* dependency) { |
301 StructuredGraphBuilder::Environment::builder()); | 393 control_dependency_ = dependency; |
394 } | |
395 | |
396 // Effect dependency tracked by this environment. | |
397 Node* GetEffectDependency() { return effect_dependency_; } | |
398 void UpdateEffectDependency(Node* dependency) { | |
399 effect_dependency_ = dependency; | |
400 } | |
401 | |
402 // Mark this environment as being unreachable. | |
403 void MarkAsUnreachable() { | |
404 UpdateControlDependency(builder()->dead_control()); | |
405 } | |
406 bool IsMarkedAsUnreachable() { | |
407 return GetControlDependency()->opcode() == IrOpcode::kDead; | |
408 } | |
409 | |
410 // Merge another environment into this one. | |
411 void Merge(Environment* other); | |
412 | |
413 // Copies this environment at a control-flow split point. | |
414 Environment* CopyForConditional() { return Copy(); } | |
415 | |
416 // Copies this environment to a potentially unreachable control-flow point. | |
417 Environment* CopyAsUnreachable() { | |
418 Environment* env = Copy(); | |
419 env->MarkAsUnreachable(); | |
420 return env; | |
421 } | |
422 | |
423 // Copies this environment at a loop header control-flow point. | |
424 Environment* CopyForLoop(BitVector* assigned, bool is_osr = false) { | |
425 PrepareForLoop(assigned, is_osr); | |
426 return Copy(); | |
302 } | 427 } |
303 | 428 |
304 private: | 429 private: |
305 void UpdateStateValues(Node** state_values, int offset, int count); | 430 AstGraphBuilder* builder_; |
306 | |
307 int parameters_count_; | 431 int parameters_count_; |
308 int locals_count_; | 432 int locals_count_; |
433 NodeVector values_; | |
434 Node* control_dependency_; | |
435 Node* effect_dependency_; | |
309 Node* parameters_node_; | 436 Node* parameters_node_; |
310 Node* locals_node_; | 437 Node* locals_node_; |
311 Node* stack_node_; | 438 Node* stack_node_; |
439 | |
440 explicit Environment(const Environment* copy); | |
441 Environment* Copy() { return new (zone()) Environment(this); } | |
442 void UpdateStateValues(Node** state_values, int offset, int count); | |
443 Zone* zone() const { return builder_->local_zone(); } | |
444 Graph* graph() const { return builder_->graph(); } | |
445 AstGraphBuilder* builder() const { return builder_; } | |
446 CommonOperatorBuilder* common() { return builder_->common(); } | |
447 NodeVector* values() { return &values_; } | |
448 | |
449 // Prepare environment to be used as loop header. | |
450 void PrepareForLoop(BitVector* assigned, bool is_osr = false); | |
312 }; | 451 }; |
313 | 452 |
314 | 453 |
315 // Each expression in the AST is evaluated in a specific context. This context | 454 // Each expression in the AST is evaluated in a specific context. This context |
316 // decides how the evaluation result is passed up the visitor. | 455 // decides how the evaluation result is passed up the visitor. |
317 class AstGraphBuilder::AstContext BASE_EMBEDDED { | 456 class AstGraphBuilder::AstContext BASE_EMBEDDED { |
318 public: | 457 public: |
319 bool IsEffect() const { return kind_ == Expression::kEffect; } | 458 bool IsEffect() const { return kind_ == Expression::kEffect; } |
320 bool IsValue() const { return kind_ == Expression::kValue; } | 459 bool IsValue() const { return kind_ == Expression::kValue; } |
321 bool IsTest() const { return kind_ == Expression::kTest; } | 460 bool IsTest() const { return kind_ == Expression::kTest; } |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
458 | 597 |
459 Scope* AstGraphBuilder::current_scope() const { | 598 Scope* AstGraphBuilder::current_scope() const { |
460 return execution_context_->scope(); | 599 return execution_context_->scope(); |
461 } | 600 } |
462 | 601 |
463 } // namespace compiler | 602 } // namespace compiler |
464 } // namespace internal | 603 } // namespace internal |
465 } // namespace v8 | 604 } // namespace v8 |
466 | 605 |
467 #endif // V8_COMPILER_AST_GRAPH_BUILDER_H_ | 606 #endif // V8_COMPILER_AST_GRAPH_BUILDER_H_ |
OLD | NEW |