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 |
35 protected: | 38 // Node creation helpers. |
39 Node* NewNode(const Operator* op, bool incomplete = false) { | |
40 return MakeNode(op, 0, static_cast<Node**>(NULL), incomplete); | |
41 } | |
42 | |
43 Node* NewNode(const Operator* op, Node* n1) { | |
44 return MakeNode(op, 1, &n1, false); | |
45 } | |
46 | |
47 Node* NewNode(const Operator* op, Node* n1, Node* n2) { | |
48 Node* buffer[] = {n1, n2}; | |
49 return MakeNode(op, arraysize(buffer), buffer, false); | |
50 } | |
51 | |
52 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) { | |
53 Node* buffer[] = {n1, n2, n3}; | |
54 return MakeNode(op, arraysize(buffer), buffer, false); | |
55 } | |
56 | |
57 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) { | |
58 Node* buffer[] = {n1, n2, n3, n4}; | |
59 return MakeNode(op, arraysize(buffer), buffer, false); | |
60 } | |
61 | |
62 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4, | |
63 Node* n5) { | |
64 Node* buffer[] = {n1, n2, n3, n4, n5}; | |
65 return MakeNode(op, arraysize(buffer), buffer, false); | |
66 } | |
67 | |
68 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4, | |
69 Node* n5, Node* n6) { | |
70 Node* nodes[] = {n1, n2, n3, n4, n5, n6}; | |
71 return MakeNode(op, arraysize(nodes), nodes, false); | |
72 } | |
73 | |
74 Node* NewNode(const Operator* op, int value_input_count, Node** value_inputs, | |
75 bool incomplete = false) { | |
76 return MakeNode(op, value_input_count, value_inputs, incomplete); | |
77 } | |
78 | |
79 // Creates a new Phi node having {count} input values. | |
80 Node* NewPhi(int count, Node* input, Node* control); | |
81 Node* NewEffectPhi(int count, Node* input, Node* control); | |
82 | |
83 // Helpers for merging control, effect or value dependencies. | |
84 Node* MergeControl(Node* control, Node* other); | |
85 Node* MergeEffect(Node* value, Node* other, Node* control); | |
86 Node* MergeValue(Node* value, Node* other, Node* control); | |
87 | |
88 // Helpers to create new control nodes. | |
89 Node* NewIfTrue() { return NewNode(common()->IfTrue()); } | |
90 Node* NewIfFalse() { return NewNode(common()->IfFalse()); } | |
91 Node* NewMerge() { return NewNode(common()->Merge(1), true); } | |
92 Node* NewLoop() { return NewNode(common()->Loop(1), true); } | |
93 Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) { | |
94 return NewNode(common()->Branch(hint), condition); | |
95 } | |
96 | |
97 // The main node creation chokepoint. Adds context, frame state, effect, | |
98 // and control dependencies depending on the operator. | |
99 Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs, | |
Michael Starzinger
2015/02/02 18:08:24
Can we try to make these methods protected again.
titzer
2015/02/02 18:26:48
Done.
| |
100 bool incomplete); | |
101 | |
36 class AstContext; | 102 class AstContext; |
37 class AstEffectContext; | 103 class AstEffectContext; |
38 class AstValueContext; | 104 class AstValueContext; |
39 class AstTestContext; | 105 class AstTestContext; |
40 class BreakableScope; | 106 class BreakableScope; |
41 class ContextScope; | 107 class ContextScope; |
42 class Environment; | 108 class Environment; |
109 friend class ControlBuilder; | |
43 | 110 |
44 Environment* environment() { | 111 Environment* environment() { return environment_; } |
45 return reinterpret_cast<Environment*>( | |
46 StructuredGraphBuilder::environment()); | |
47 } | |
48 | |
49 AstContext* ast_context() const { return ast_context_; } | 112 AstContext* ast_context() const { return ast_context_; } |
50 BreakableScope* breakable() const { return breakable_; } | 113 BreakableScope* breakable() const { return breakable_; } |
51 ContextScope* execution_context() const { return execution_context_; } | 114 ContextScope* execution_context() const { return execution_context_; } |
115 CommonOperatorBuilder* common() const { return jsgraph_->common(); } | |
52 | 116 |
53 void set_ast_context(AstContext* ctx) { ast_context_ = ctx; } | 117 void set_ast_context(AstContext* ctx) { ast_context_ = ctx; } |
54 void set_breakable(BreakableScope* brk) { breakable_ = brk; } | 118 void set_breakable(BreakableScope* brk) { breakable_ = brk; } |
55 void set_execution_context(ContextScope* ctx) { execution_context_ = ctx; } | 119 void set_execution_context(ContextScope* ctx) { execution_context_ = ctx; } |
56 | 120 |
57 // Support for control flow builders. The concrete type of the environment | |
58 // depends on the graph builder, but environments themselves are not virtual. | |
59 typedef StructuredGraphBuilder::Environment BaseEnvironment; | |
60 BaseEnvironment* CopyEnvironment(BaseEnvironment* env) OVERRIDE; | |
61 | |
62 // Getters for values in the activation record. | 121 // Getters for values in the activation record. |
63 Node* GetFunctionClosure(); | 122 Node* GetFunctionClosure(); |
64 Node* GetFunctionContext(); | 123 Node* GetFunctionContext(); |
65 | 124 |
125 // Helper to indicate a node exits the function body. | |
126 void UpdateControlDependencyToLeaveFunction(Node* exit); | |
127 | |
66 // | 128 // |
67 // The following build methods all generate graph fragments and return one | 129 // The following build methods all generate graph fragments and return one |
68 // resulting node. The operand stack height remains the same, variables and | 130 // resulting node. The operand stack height remains the same, variables and |
69 // other dependencies tracked by the environment might be mutated though. | 131 // other dependencies tracked by the environment might be mutated though. |
70 // | 132 // |
71 | 133 |
72 // Builder to create a receiver check for sloppy mode. | 134 // Builder to create a receiver check for sloppy mode. |
73 Node* BuildPatchReceiverToGlobalProxy(Node* receiver); | 135 Node* BuildPatchReceiverToGlobalProxy(Node* receiver); |
74 | 136 |
75 // Builders to create local function and block contexts. | 137 // Builders to create local function and block contexts. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
123 #define DECLARE_VISIT(type) void Visit##type(type* node) OVERRIDE; | 185 #define DECLARE_VISIT(type) void Visit##type(type* node) OVERRIDE; |
124 | 186 |
125 // Visiting functions for AST nodes make this an AstVisitor. | 187 // Visiting functions for AST nodes make this an AstVisitor. |
126 AST_NODE_LIST(DECLARE_VISIT) | 188 AST_NODE_LIST(DECLARE_VISIT) |
127 #undef DECLARE_VISIT | 189 #undef DECLARE_VISIT |
128 | 190 |
129 // Visiting function for declarations list is overridden. | 191 // Visiting function for declarations list is overridden. |
130 void VisitDeclarations(ZoneList<Declaration*>* declarations) OVERRIDE; | 192 void VisitDeclarations(ZoneList<Declaration*>* declarations) OVERRIDE; |
131 | 193 |
132 private: | 194 private: |
195 Zone* local_zone_; | |
133 CompilationInfo* info_; | 196 CompilationInfo* info_; |
197 JSGraph* jsgraph_; | |
198 LoopAssignmentAnalysis* loop_assignment_analysis_; | |
Michael Starzinger
2015/02/02 18:08:24
nit: Can we move the loop_assignment_analysis down
titzer
2015/02/02 18:26:48
Done.
| |
199 Environment* environment_; | |
134 AstContext* ast_context_; | 200 AstContext* ast_context_; |
135 JSGraph* jsgraph_; | 201 |
202 Zone* local_zone() const { return local_zone_; } | |
Michael Starzinger
2015/02/02 18:08:24
nit: Can we move the getter down to the others (ne
titzer
2015/02/02 18:26:48
Done.
| |
136 | 203 |
137 // List of global declarations for functions and variables. | 204 // List of global declarations for functions and variables. |
138 ZoneVector<Handle<Object>> globals_; | 205 ZoneVector<Handle<Object>> globals_; |
139 | 206 |
140 // Stack of breakable statements entered by the visitor. | 207 // Stack of breakable statements entered by the visitor. |
141 BreakableScope* breakable_; | 208 BreakableScope* breakable_; |
142 | 209 |
143 // Stack of context objects pushed onto the chain by the visitor. | 210 // Stack of context objects pushed onto the chain by the visitor. |
144 ContextScope* execution_context_; | 211 ContextScope* execution_context_; |
145 | 212 |
146 // Nodes representing values in the activation record. | 213 // Nodes representing values in the activation record. |
147 SetOncePointer<Node> function_closure_; | 214 SetOncePointer<Node> function_closure_; |
148 SetOncePointer<Node> function_context_; | 215 SetOncePointer<Node> function_context_; |
149 | 216 |
150 // The node representing the OSR entry into the loop, if any. | 217 // Temporary storage for building node input lists. |
151 SetOncePointer<Node> osr_loop_entry_; | 218 int input_buffer_size_; |
219 Node** input_buffer_; | |
152 | 220 |
153 // Result of loop assignment analysis performed before graph creation. | 221 // Node representing the control dependency for dead code. |
154 LoopAssignmentAnalysis* loop_assignment_analysis_; | 222 SetOncePointer<Node> dead_control_; |
223 | |
224 // Node representing the current context within the function body. | |
225 Node* current_context_; | |
226 | |
227 // Merge of all control nodes that exit the function body. | |
228 Node* exit_control_; | |
229 | |
230 // Growth increment for the temporary buffer used to construct input lists to | |
231 // new nodes. | |
232 static const int kInputBufferSizeIncrement = 64; | |
233 | |
234 // Helper to wrap a Handle<T> into a Unique<T>. | |
235 template <class T> | |
236 Unique<T> MakeUnique(Handle<T> object) { | |
237 return Unique<T>::CreateUninitialized(object); | |
238 } | |
239 | |
240 Node** EnsureInputBufferSize(int size); | |
155 | 241 |
156 CompilationInfo* info() const { return info_; } | 242 CompilationInfo* info() const { return info_; } |
157 inline StrictMode strict_mode() const; | 243 StrictMode strict_mode() const; |
158 JSGraph* jsgraph() { return jsgraph_; } | 244 JSGraph* jsgraph() { return jsgraph_; } |
245 Graph* graph() { return jsgraph_->graph(); } | |
246 Zone* graph_zone() { return graph()->zone(); } | |
159 JSOperatorBuilder* javascript() { return jsgraph_->javascript(); } | 247 JSOperatorBuilder* javascript() { return jsgraph_->javascript(); } |
160 ZoneVector<Handle<Object>>* globals() { return &globals_; } | 248 ZoneVector<Handle<Object>>* globals() { return &globals_; } |
161 | 249 |
162 // Current scope during visitation. | 250 // Current scope during visitation. |
163 inline Scope* current_scope() const; | 251 inline Scope* current_scope() const; |
252 Node* current_context() const { return current_context_; } | |
Michael Starzinger
2015/02/02 18:08:24
nit: Can we move this block of accessors (all six
titzer
2015/02/02 18:26:48
Done.
| |
253 Node* dead_control(); | |
254 Node* exit_control() const { return exit_control_; } | |
255 void set_exit_control(Node* exit_control) { exit_control_ = exit_control; } | |
256 void set_current_context(Node* context) { current_context_ = context; } | |
257 void set_environment(Environment* env) { environment_ = env; } | |
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; |
302 } | 394 } |
303 | 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(); | |
427 } | |
428 | |
429 Node* GetContext() { return builder_->current_context(); } | |
Michael Starzinger
2015/02/02 18:08:24
nit: This seems to only have one use, can we inlin
titzer
2015/02/02 18:26:48
Done.
| |
430 | |
304 private: | 431 private: |
305 void UpdateStateValues(Node** state_values, int offset, int count); | 432 AstGraphBuilder* builder_; |
306 | |
307 int parameters_count_; | 433 int parameters_count_; |
308 int locals_count_; | 434 int locals_count_; |
435 NodeVector values_; | |
436 Node* control_dependency_; | |
437 Node* effect_dependency_; | |
309 Node* parameters_node_; | 438 Node* parameters_node_; |
310 Node* locals_node_; | 439 Node* locals_node_; |
311 Node* stack_node_; | 440 Node* stack_node_; |
441 | |
442 explicit Environment(const Environment* copy); | |
443 Environment* Copy() { return new (zone()) Environment(this); } | |
444 void UpdateStateValues(Node** state_values, int offset, int count); | |
445 Zone* zone() const { return builder_->local_zone(); } | |
446 Graph* graph() const { return builder_->graph(); } | |
447 AstGraphBuilder* builder() const { return builder_; } | |
448 CommonOperatorBuilder* common() { return builder_->common(); } | |
449 NodeVector* values() { return &values_; } | |
450 | |
451 // Prepare environment to be used as loop header. | |
452 void PrepareForLoop(BitVector* assigned, bool is_osr = false); | |
312 }; | 453 }; |
313 | 454 |
314 | 455 |
315 // Each expression in the AST is evaluated in a specific context. This context | 456 // Each expression in the AST is evaluated in a specific context. This context |
316 // decides how the evaluation result is passed up the visitor. | 457 // decides how the evaluation result is passed up the visitor. |
317 class AstGraphBuilder::AstContext BASE_EMBEDDED { | 458 class AstGraphBuilder::AstContext BASE_EMBEDDED { |
318 public: | 459 public: |
319 bool IsEffect() const { return kind_ == Expression::kEffect; } | 460 bool IsEffect() const { return kind_ == Expression::kEffect; } |
320 bool IsValue() const { return kind_ == Expression::kValue; } | 461 bool IsValue() const { return kind_ == Expression::kValue; } |
321 bool IsTest() const { return kind_ == Expression::kTest; } | 462 bool IsTest() const { return kind_ == Expression::kTest; } |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
458 | 599 |
459 Scope* AstGraphBuilder::current_scope() const { | 600 Scope* AstGraphBuilder::current_scope() const { |
460 return execution_context_->scope(); | 601 return execution_context_->scope(); |
461 } | 602 } |
462 | 603 |
463 } // namespace compiler | 604 } // namespace compiler |
464 } // namespace internal | 605 } // namespace internal |
465 } // namespace v8 | 606 } // namespace v8 |
466 | 607 |
467 #endif // V8_COMPILER_AST_GRAPH_BUILDER_H_ | 608 #endif // V8_COMPILER_AST_GRAPH_BUILDER_H_ |
OLD | NEW |