blob: 0337c813b9e08d4f6ccb5898ef1104934b2579ba [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
3// found in the LICENSE file.
4
5#ifndef V8_COMPILER_AST_GRAPH_BUILDER_H_
6#define V8_COMPILER_AST_GRAPH_BUILDER_H_
7
8#include "src/v8.h"
9
10#include "src/ast.h"
11#include "src/compiler/graph-builder.h"
12#include "src/compiler/js-graph.h"
13
14namespace v8 {
15namespace internal {
16namespace compiler {
17
18class ControlBuilder;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019class Graph;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020class LoopAssignmentAnalysis;
21class LoopBuilder;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022
23// The AstGraphBuilder produces a high-level IR graph, based on an
24// underlying AST. The produced graph can either be compiled into a
25// stand-alone function or be wired into another graph for the purposes
26// of function inlining.
27class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
28 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040029 AstGraphBuilder(Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph,
30 LoopAssignmentAnalysis* loop_assignment = NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031
32 // Creates a graph by visiting the entire AST.
33 bool CreateGraph();
34
35 protected:
36 class AstContext;
37 class AstEffectContext;
38 class AstValueContext;
39 class AstTestContext;
40 class BreakableScope;
41 class ContextScope;
42 class Environment;
43
44 Environment* environment() {
45 return reinterpret_cast<Environment*>(
46 StructuredGraphBuilder::environment());
47 }
48
49 AstContext* ast_context() const { return ast_context_; }
50 BreakableScope* breakable() const { return breakable_; }
51 ContextScope* execution_context() const { return execution_context_; }
52
53 void set_ast_context(AstContext* ctx) { ast_context_ = ctx; }
54 void set_breakable(BreakableScope* brk) { breakable_ = brk; }
55 void set_execution_context(ContextScope* ctx) { execution_context_ = ctx; }
56
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;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040060 BaseEnvironment* CopyEnvironment(BaseEnvironment* env) OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000061
62 // Getters for values in the activation record.
63 Node* GetFunctionClosure();
64 Node* GetFunctionContext();
65
66 //
67 // The following build methods all generate graph fragments and return one
68 // resulting node. The operand stack height remains the same, variables and
69 // other dependencies tracked by the environment might be mutated though.
70 //
71
Emily Bernierd0a1eb72015-03-24 16:35:39 -040072 // Builder to create a receiver check for sloppy mode.
73 Node* BuildPatchReceiverToGlobalProxy(Node* receiver);
74
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075 // Builder to create a local function context.
76 Node* BuildLocalFunctionContext(Node* context, Node* closure);
77
78 // Builder to create an arguments object if it is used.
79 Node* BuildArgumentsObject(Variable* arguments);
80
81 // Builders for variable load and assignment.
82 Node* BuildVariableAssignment(Variable* var, Node* value, Token::Value op,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040083 BailoutId bailout_id,
84 OutputFrameStateCombine state_combine =
85 OutputFrameStateCombine::Ignore());
86 Node* BuildVariableDelete(Variable* var, BailoutId bailout_id,
87 OutputFrameStateCombine state_combine);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088 Node* BuildVariableLoad(Variable* var, BailoutId bailout_id,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040089 const VectorSlotPair& feedback,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000090 ContextualMode mode = CONTEXTUAL);
91
92 // Builders for accessing the function context.
93 Node* BuildLoadBuiltinsObject();
94 Node* BuildLoadGlobalObject();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040095 Node* BuildLoadGlobalProxy();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000096 Node* BuildLoadClosure();
97 Node* BuildLoadObjectField(Node* object, int offset);
98
99 // Builders for automatic type conversion.
100 Node* BuildToBoolean(Node* value);
101
102 // Builders for error reporting at runtime.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400103 Node* BuildThrowReferenceError(Variable* var, BailoutId bailout_id);
104 Node* BuildThrowConstAssignError(BailoutId bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105
106 // Builders for dynamic hole-checks at runtime.
107 Node* BuildHoleCheckSilent(Node* value, Node* for_hole, Node* not_hole);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400108 Node* BuildHoleCheckThrow(Node* value, Variable* var, Node* not_hole,
109 BailoutId bailout_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000110
111 // Builders for binary operations.
112 Node* BuildBinaryOp(Node* left, Node* right, Token::Value op);
113
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400114 // Builder for stack-check guards.
115 Node* BuildStackCheck();
116
117#define DECLARE_VISIT(type) void Visit##type(type* node) OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118 // Visiting functions for AST nodes make this an AstVisitor.
119 AST_NODE_LIST(DECLARE_VISIT)
120#undef DECLARE_VISIT
121
122 // Visiting function for declarations list is overridden.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123 void VisitDeclarations(ZoneList<Declaration*>* declarations) OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000124
125 private:
126 CompilationInfo* info_;
127 AstContext* ast_context_;
128 JSGraph* jsgraph_;
129
130 // List of global declarations for functions and variables.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400131 ZoneVector<Handle<Object>> globals_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000132
133 // Stack of breakable statements entered by the visitor.
134 BreakableScope* breakable_;
135
136 // Stack of context objects pushed onto the chain by the visitor.
137 ContextScope* execution_context_;
138
139 // Nodes representing values in the activation record.
140 SetOncePointer<Node> function_closure_;
141 SetOncePointer<Node> function_context_;
142
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400143 // Result of loop assignment analysis performed before graph creation.
144 LoopAssignmentAnalysis* loop_assignment_analysis_;
145
146 CompilationInfo* info() const { return info_; }
147 inline StrictMode strict_mode() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148 JSGraph* jsgraph() { return jsgraph_; }
149 JSOperatorBuilder* javascript() { return jsgraph_->javascript(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400150 ZoneVector<Handle<Object>>* globals() { return &globals_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151
152 // Current scope during visitation.
153 inline Scope* current_scope() const;
154
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400155 // Named and keyed loads require a VectorSlotPair for successful lowering.
156 VectorSlotPair CreateVectorSlotPair(FeedbackVectorICSlot slot) const;
157
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 // Process arguments to a call by popping {arity} elements off the operand
159 // stack and build a call node using the given call operator.
160 Node* ProcessArguments(const Operator* op, int arity);
161
162 // Visit statements.
163 void VisitIfNotNull(Statement* stmt);
164
165 // Visit expressions.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400166 void Visit(Expression* expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167 void VisitForTest(Expression* expr);
168 void VisitForEffect(Expression* expr);
169 void VisitForValue(Expression* expr);
170 void VisitForValueOrNull(Expression* expr);
171 void VisitForValues(ZoneList<Expression*>* exprs);
172
173 // Common for all IterationStatement bodies.
174 void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop, int);
175
176 // Dispatched from VisitCallRuntime.
177 void VisitCallJSRuntime(CallRuntime* expr);
178
179 // Dispatched from VisitUnaryOperation.
180 void VisitDelete(UnaryOperation* expr);
181 void VisitVoid(UnaryOperation* expr);
182 void VisitTypeof(UnaryOperation* expr);
183 void VisitNot(UnaryOperation* expr);
184
185 // Dispatched from VisitBinaryOperation.
186 void VisitComma(BinaryOperation* expr);
187 void VisitLogicalExpression(BinaryOperation* expr);
188 void VisitArithmeticExpression(BinaryOperation* expr);
189
190 // Dispatched from VisitForInStatement.
191 void VisitForInAssignment(Expression* expr, Node* value);
192
193 // Builds deoptimization for a given node.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400194 void PrepareFrameState(
195 Node* node, BailoutId ast_id,
196 OutputFrameStateCombine combine = OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000197
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400198 BitVector* GetVariablesAssignedInLoop(IterationStatement* stmt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199
200 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
201 DISALLOW_COPY_AND_ASSIGN(AstGraphBuilder);
202};
203
204
205// The abstract execution environment for generated code consists of
206// parameter variables, local variables and the operand stack. The
207// environment will perform proper SSA-renaming of all tracked nodes
208// at split and merge points in the control flow. Internally all the
209// values are stored in one list using the following layout:
210//
211// [parameters (+receiver)] [locals] [operand stack]
212//
213class AstGraphBuilder::Environment
214 : public StructuredGraphBuilder::Environment {
215 public:
216 Environment(AstGraphBuilder* builder, Scope* scope, Node* control_dependency);
217 Environment(const Environment& copy);
218
219 int parameters_count() const { return parameters_count_; }
220 int locals_count() const { return locals_count_; }
221 int stack_height() {
222 return static_cast<int>(values()->size()) - parameters_count_ -
223 locals_count_;
224 }
225
226 // Operations on parameter or local variables. The parameter indices are
227 // shifted by 1 (receiver is parameter index -1 but environment index 0).
228 void Bind(Variable* variable, Node* node) {
229 DCHECK(variable->IsStackAllocated());
230 if (variable->IsParameter()) {
231 values()->at(variable->index() + 1) = node;
232 } else {
233 DCHECK(variable->IsStackLocal());
234 values()->at(variable->index() + parameters_count_) = node;
235 }
236 }
237 Node* Lookup(Variable* variable) {
238 DCHECK(variable->IsStackAllocated());
239 if (variable->IsParameter()) {
240 return values()->at(variable->index() + 1);
241 } else {
242 DCHECK(variable->IsStackLocal());
243 return values()->at(variable->index() + parameters_count_);
244 }
245 }
246
247 // Operations on the operand stack.
248 void Push(Node* node) {
249 values()->push_back(node);
250 }
251 Node* Top() {
252 DCHECK(stack_height() > 0);
253 return values()->back();
254 }
255 Node* Pop() {
256 DCHECK(stack_height() > 0);
257 Node* back = values()->back();
258 values()->pop_back();
259 return back;
260 }
261
262 // Direct mutations of the operand stack.
263 void Poke(int depth, Node* node) {
264 DCHECK(depth >= 0 && depth < stack_height());
265 int index = static_cast<int>(values()->size()) - depth - 1;
266 values()->at(index) = node;
267 }
268 Node* Peek(int depth) {
269 DCHECK(depth >= 0 && depth < stack_height());
270 int index = static_cast<int>(values()->size()) - depth - 1;
271 return values()->at(index);
272 }
273 void Drop(int depth) {
274 DCHECK(depth >= 0 && depth <= stack_height());
275 values()->erase(values()->end() - depth, values()->end());
276 }
277
278 // Preserve a checkpoint of the environment for the IR graph. Any
279 // further mutation of the environment will not affect checkpoints.
280 Node* Checkpoint(BailoutId ast_id, OutputFrameStateCombine combine);
281
282 protected:
283 AstGraphBuilder* builder() const {
284 return reinterpret_cast<AstGraphBuilder*>(
285 StructuredGraphBuilder::Environment::builder());
286 }
287
288 private:
289 void UpdateStateValues(Node** state_values, int offset, int count);
290
291 int parameters_count_;
292 int locals_count_;
293 Node* parameters_node_;
294 Node* locals_node_;
295 Node* stack_node_;
296};
297
298
299// Each expression in the AST is evaluated in a specific context. This context
300// decides how the evaluation result is passed up the visitor.
301class AstGraphBuilder::AstContext BASE_EMBEDDED {
302 public:
303 bool IsEffect() const { return kind_ == Expression::kEffect; }
304 bool IsValue() const { return kind_ == Expression::kValue; }
305 bool IsTest() const { return kind_ == Expression::kTest; }
306
307 // Determines how to combine the frame state with the value
308 // that is about to be plugged into this AstContext.
309 OutputFrameStateCombine GetStateCombine() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400310 return IsEffect() ? OutputFrameStateCombine::Ignore()
311 : OutputFrameStateCombine::Push();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312 }
313
314 // Plug a node into this expression context. Call this function in tail
315 // position in the Visit functions for expressions.
316 virtual void ProduceValue(Node* value) = 0;
317
318 // Unplugs a node from this expression context. Call this to retrieve the
319 // result of another Visit function that already plugged the context.
320 virtual Node* ConsumeValue() = 0;
321
322 // Shortcut for "context->ProduceValue(context->ConsumeValue())".
323 void ReplaceValue() { ProduceValue(ConsumeValue()); }
324
325 protected:
326 AstContext(AstGraphBuilder* owner, Expression::Context kind);
327 virtual ~AstContext();
328
329 AstGraphBuilder* owner() const { return owner_; }
330 Environment* environment() const { return owner_->environment(); }
331
332// We want to be able to assert, in a context-specific way, that the stack
333// height makes sense when the context is filled.
334#ifdef DEBUG
335 int original_height_;
336#endif
337
338 private:
339 Expression::Context kind_;
340 AstGraphBuilder* owner_;
341 AstContext* outer_;
342};
343
344
345// Context to evaluate expression for its side effects only.
346class AstGraphBuilder::AstEffectContext FINAL : public AstContext {
347 public:
348 explicit AstEffectContext(AstGraphBuilder* owner)
349 : AstContext(owner, Expression::kEffect) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400350 ~AstEffectContext() FINAL;
351 void ProduceValue(Node* value) FINAL;
352 Node* ConsumeValue() FINAL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000353};
354
355
356// Context to evaluate expression for its value (and side effects).
357class AstGraphBuilder::AstValueContext FINAL : public AstContext {
358 public:
359 explicit AstValueContext(AstGraphBuilder* owner)
360 : AstContext(owner, Expression::kValue) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400361 ~AstValueContext() FINAL;
362 void ProduceValue(Node* value) FINAL;
363 Node* ConsumeValue() FINAL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364};
365
366
367// Context to evaluate expression for a condition value (and side effects).
368class AstGraphBuilder::AstTestContext FINAL : public AstContext {
369 public:
370 explicit AstTestContext(AstGraphBuilder* owner)
371 : AstContext(owner, Expression::kTest) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400372 ~AstTestContext() FINAL;
373 void ProduceValue(Node* value) FINAL;
374 Node* ConsumeValue() FINAL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000375};
376
377
378// Scoped class tracking breakable statements entered by the visitor. Allows to
379// properly 'break' and 'continue' iteration statements as well as to 'break'
380// from blocks within switch statements.
381class AstGraphBuilder::BreakableScope BASE_EMBEDDED {
382 public:
383 BreakableScope(AstGraphBuilder* owner, BreakableStatement* target,
384 ControlBuilder* control, int drop_extra)
385 : owner_(owner),
386 target_(target),
387 next_(owner->breakable()),
388 control_(control),
389 drop_extra_(drop_extra) {
390 owner_->set_breakable(this); // Push.
391 }
392
393 ~BreakableScope() {
394 owner_->set_breakable(next_); // Pop.
395 }
396
397 // Either 'break' or 'continue' the target statement.
398 void BreakTarget(BreakableStatement* target);
399 void ContinueTarget(BreakableStatement* target);
400
401 private:
402 AstGraphBuilder* owner_;
403 BreakableStatement* target_;
404 BreakableScope* next_;
405 ControlBuilder* control_;
406 int drop_extra_;
407
408 // Find the correct scope for the target statement. Note that this also drops
409 // extra operands from the environment for each scope skipped along the way.
410 BreakableScope* FindBreakable(BreakableStatement* target);
411};
412
413
414// Scoped class tracking context objects created by the visitor. Represents
415// mutations of the context chain within the function body and allows to
416// change the current {scope} and {context} during visitation.
417class AstGraphBuilder::ContextScope BASE_EMBEDDED {
418 public:
419 ContextScope(AstGraphBuilder* owner, Scope* scope, Node* context)
420 : owner_(owner),
421 next_(owner->execution_context()),
422 outer_(owner->current_context()),
423 scope_(scope) {
424 owner_->set_execution_context(this); // Push.
425 owner_->set_current_context(context);
426 }
427
428 ~ContextScope() {
429 owner_->set_execution_context(next_); // Pop.
430 owner_->set_current_context(outer_);
431 }
432
433 // Current scope during visitation.
434 Scope* scope() const { return scope_; }
435
436 private:
437 AstGraphBuilder* owner_;
438 ContextScope* next_;
439 Node* outer_;
440 Scope* scope_;
441};
442
443Scope* AstGraphBuilder::current_scope() const {
444 return execution_context_->scope();
445}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400446
447} // namespace compiler
448} // namespace internal
449} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000450
451#endif // V8_COMPILER_AST_GRAPH_BUILDER_H_