blob: 3b6302d3ddcf86bd719df0d910e28314ddc3e684 [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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/ast/ast.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/compiler/js-graph.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/compiler/liveness-analyzer.h"
11#include "src/compiler/state-values-utils.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012
13namespace v8 {
14namespace internal {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015
16// Forward declarations.
17class BitVector;
18
19
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020namespace compiler {
21
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022// Forward declarations.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023class ControlBuilder;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024class Graph;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040025class LoopAssignmentAnalysis;
26class LoopBuilder;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027class Node;
28class TypeHintAnalysis;
29
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030
31// The AstGraphBuilder produces a high-level IR graph, based on an
32// underlying AST. The produced graph can either be compiled into a
33// stand-alone function or be wired into another graph for the purposes
34// of function inlining.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035class AstGraphBuilder : public AstVisitor {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040037 AstGraphBuilder(Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000038 LoopAssignmentAnalysis* loop_assignment = nullptr,
39 TypeHintAnalysis* type_hint_analysis = nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040
41 // Creates a graph by visiting the entire AST.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000042 bool CreateGraph(bool stack_check = true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 // Helpers to create new control nodes.
45 Node* NewIfTrue() { return NewNode(common()->IfTrue()); }
46 Node* NewIfFalse() { return NewNode(common()->IfFalse()); }
47 Node* NewMerge() { return NewNode(common()->Merge(1), true); }
48 Node* NewLoop() { return NewNode(common()->Loop(1), true); }
49 Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) {
50 return NewNode(common()->Branch(hint), condition);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 }
52
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053 protected:
54#define DECLARE_VISIT(type) void Visit##type(type* node) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055 // Visiting functions for AST nodes make this an AstVisitor.
56 AST_NODE_LIST(DECLARE_VISIT)
57#undef DECLARE_VISIT
58
59 // Visiting function for declarations list is overridden.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060 void VisitDeclarations(ZoneList<Declaration*>* declarations) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000061
62 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063 class AstContext;
64 class AstEffectContext;
65 class AstValueContext;
66 class AstTestContext;
67 class ContextScope;
68 class ControlScope;
69 class ControlScopeForBreakable;
70 class ControlScopeForIteration;
71 class ControlScopeForCatch;
72 class ControlScopeForFinally;
73 class Environment;
74 class FrameStateBeforeAndAfter;
75 friend class ControlBuilder;
76
77 Isolate* isolate_;
78 Zone* local_zone_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 CompilationInfo* info_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000080 JSGraph* jsgraph_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 Environment* environment_;
82 AstContext* ast_context_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083
84 // List of global declarations for functions and variables.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040085 ZoneVector<Handle<Object>> globals_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000086
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087 // Stack of control scopes currently entered by the visitor.
88 ControlScope* execution_control_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000089
90 // Stack of context objects pushed onto the chain by the visitor.
91 ContextScope* execution_context_;
92
93 // Nodes representing values in the activation record.
94 SetOncePointer<Node> function_closure_;
95 SetOncePointer<Node> function_context_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000096 SetOncePointer<Node> new_target_;
97
98 // Tracks how many try-blocks are currently entered.
99 int try_catch_nesting_level_;
100 int try_nesting_level_;
101
102 // Temporary storage for building node input lists.
103 int input_buffer_size_;
104 Node** input_buffer_;
105
106 // Optimization to cache loaded feedback vector.
107 SetOncePointer<Node> feedback_vector_;
108
109 // Control nodes that exit the function body.
110 ZoneVector<Node*> exit_controls_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400112 // Result of loop assignment analysis performed before graph creation.
113 LoopAssignmentAnalysis* loop_assignment_analysis_;
114
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 // Result of type hint analysis performed before graph creation.
116 TypeHintAnalysis* type_hint_analysis_;
117
118 // Cache for StateValues nodes for frame states.
119 StateValuesCache state_values_cache_;
120
121 // Analyzer of local variable liveness.
122 LivenessAnalyzer liveness_analyzer_;
123
124 // Function info for frame state construction.
125 const FrameStateFunctionInfo* const frame_state_function_info_;
126
127 // Growth increment for the temporary buffer used to construct input lists to
128 // new nodes.
129 static const int kInputBufferSizeIncrement = 64;
130
131 Zone* local_zone() const { return local_zone_; }
132 Environment* environment() const { return environment_; }
133 AstContext* ast_context() const { return ast_context_; }
134 ControlScope* execution_control() const { return execution_control_; }
135 ContextScope* execution_context() const { return execution_context_; }
136 CommonOperatorBuilder* common() const { return jsgraph_->common(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400137 CompilationInfo* info() const { return info_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138 Isolate* isolate() const { return isolate_; }
139 LanguageMode language_mode() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140 JSGraph* jsgraph() { return jsgraph_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141 Graph* graph() { return jsgraph_->graph(); }
142 Zone* graph_zone() { return graph()->zone(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143 JSOperatorBuilder* javascript() { return jsgraph_->javascript(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400144 ZoneVector<Handle<Object>>* globals() { return &globals_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 Scope* current_scope() const;
146 Node* current_context() const;
147 LivenessAnalyzer* liveness_analyzer() { return &liveness_analyzer_; }
148 const FrameStateFunctionInfo* frame_state_function_info() const {
149 return frame_state_function_info_;
150 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 void set_environment(Environment* env) { environment_ = env; }
153 void set_ast_context(AstContext* ctx) { ast_context_ = ctx; }
154 void set_execution_control(ControlScope* ctrl) { execution_control_ = ctrl; }
155 void set_execution_context(ContextScope* ctx) { execution_context_ = ctx; }
156
157 // Create the main graph body by visiting the AST.
158 void CreateGraphBody(bool stack_check);
159
160 // Get or create the node that represents the incoming function closure.
161 Node* GetFunctionClosureForContext();
162 Node* GetFunctionClosure();
163
164 // Get or create the node that represents the incoming function context.
165 Node* GetFunctionContext();
166
167 // Get or create the node that represents the incoming new target value.
168 Node* GetNewTarget();
169
170 // Node creation helpers.
171 Node* NewNode(const Operator* op, bool incomplete = false) {
172 return MakeNode(op, 0, static_cast<Node**>(nullptr), incomplete);
173 }
174
175 Node* NewNode(const Operator* op, Node* n1) {
176 return MakeNode(op, 1, &n1, false);
177 }
178
179 Node* NewNode(const Operator* op, Node* n1, Node* n2) {
180 Node* buffer[] = {n1, n2};
181 return MakeNode(op, arraysize(buffer), buffer, false);
182 }
183
184 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
185 Node* buffer[] = {n1, n2, n3};
186 return MakeNode(op, arraysize(buffer), buffer, false);
187 }
188
189 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) {
190 Node* buffer[] = {n1, n2, n3, n4};
191 return MakeNode(op, arraysize(buffer), buffer, false);
192 }
193
194 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
195 Node* n5) {
196 Node* buffer[] = {n1, n2, n3, n4, n5};
197 return MakeNode(op, arraysize(buffer), buffer, false);
198 }
199
200 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
201 Node* n5, Node* n6) {
202 Node* nodes[] = {n1, n2, n3, n4, n5, n6};
203 return MakeNode(op, arraysize(nodes), nodes, false);
204 }
205
206 Node* NewNode(const Operator* op, int value_input_count, Node** value_inputs,
207 bool incomplete = false) {
208 return MakeNode(op, value_input_count, value_inputs, incomplete);
209 }
210
211 // Creates a new Phi node having {count} input values.
212 Node* NewPhi(int count, Node* input, Node* control);
213 Node* NewEffectPhi(int count, Node* input, Node* control);
214
215 // Helpers for merging control, effect or value dependencies.
216 Node* MergeControl(Node* control, Node* other);
217 Node* MergeEffect(Node* value, Node* other, Node* control);
218 Node* MergeValue(Node* value, Node* other, Node* control);
219
220 // The main node creation chokepoint. Adds context, frame state, effect,
221 // and control dependencies depending on the operator.
222 Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs,
223 bool incomplete);
224
225 // Helper to indicate a node exits the function body.
226 void UpdateControlDependencyToLeaveFunction(Node* exit);
227
228 // Builds deoptimization for a given node.
229 void PrepareFrameState(Node* node, BailoutId ast_id,
230 OutputFrameStateCombine framestate_combine =
231 OutputFrameStateCombine::Ignore());
232
233 BitVector* GetVariablesAssignedInLoop(IterationStatement* stmt);
234
235 // Check if the given statement is an OSR entry.
236 // If so, record the stack height into the compilation and return {true}.
237 bool CheckOsrEntry(IterationStatement* stmt);
238
239 // Computes local variable liveness and replaces dead variables in
240 // frame states with the undefined values.
241 void ClearNonLiveSlotsInFrameStates();
242
243 Node** EnsureInputBufferSize(int size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000244
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400245 // Named and keyed loads require a VectorSlotPair for successful lowering.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000246 VectorSlotPair CreateVectorSlotPair(FeedbackVectorSlot slot) const;
247
248 // Determine which contexts need to be checked for extension objects that
249 // might shadow the optimistic declaration of dynamic lookup variables.
250 uint32_t ComputeBitsetForDynamicGlobal(Variable* variable);
251 uint32_t ComputeBitsetForDynamicContext(Variable* variable);
252
253 // ===========================================================================
254 // The following build methods all generate graph fragments and return one
255 // resulting node. The operand stack height remains the same, variables and
256 // other dependencies tracked by the environment might be mutated though.
257
258 // Builders to create local function, script and block contexts.
259 Node* BuildLocalActivationContext(Node* context);
260 Node* BuildLocalFunctionContext(Scope* scope);
261 Node* BuildLocalScriptContext(Scope* scope);
262 Node* BuildLocalBlockContext(Scope* scope);
263
264 // Builder to create an arguments object if it is used.
265 Node* BuildArgumentsObject(Variable* arguments);
266
267 // Builder to create an array of rest parameters if used
268 Node* BuildRestArgumentsArray(Variable* rest, int index);
269
270 // Builder that assigns to the {.this_function} internal variable if needed.
271 Node* BuildThisFunctionVariable(Variable* this_function_var);
272
273 // Builder that assigns to the {new.target} internal variable if needed.
274 Node* BuildNewTargetVariable(Variable* new_target_var);
275
276 // Builders for variable load and assignment.
277 Node* BuildVariableAssignment(Variable* variable, Node* value,
278 Token::Value op, const VectorSlotPair& slot,
279 BailoutId bailout_id,
280 FrameStateBeforeAndAfter& states,
281 OutputFrameStateCombine framestate_combine =
282 OutputFrameStateCombine::Ignore());
283 Node* BuildVariableDelete(Variable* variable, BailoutId bailout_id,
284 OutputFrameStateCombine framestate_combine);
285 Node* BuildVariableLoad(Variable* variable, BailoutId bailout_id,
286 FrameStateBeforeAndAfter& states,
287 const VectorSlotPair& feedback,
288 OutputFrameStateCombine framestate_combine,
289 TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
290
291 // Builders for property loads and stores.
292 Node* BuildKeyedLoad(Node* receiver, Node* key,
293 const VectorSlotPair& feedback);
294 Node* BuildNamedLoad(Node* receiver, Handle<Name> name,
295 const VectorSlotPair& feedback);
296 Node* BuildKeyedStore(Node* receiver, Node* key, Node* value,
297 const VectorSlotPair& feedback);
298 Node* BuildNamedStore(Node* receiver, Handle<Name> name, Node* value,
299 const VectorSlotPair& feedback);
300
301 // Builders for super property loads and stores.
302 Node* BuildKeyedSuperStore(Node* receiver, Node* home_object, Node* key,
303 Node* value);
304 Node* BuildNamedSuperStore(Node* receiver, Node* home_object,
305 Handle<Name> name, Node* value);
306 Node* BuildNamedSuperLoad(Node* receiver, Node* home_object,
307 Handle<Name> name, const VectorSlotPair& feedback);
308 Node* BuildKeyedSuperLoad(Node* receiver, Node* home_object, Node* key,
309 const VectorSlotPair& feedback);
310
311 // Builders for global variable loads and stores.
312 Node* BuildGlobalLoad(Handle<Name> name, const VectorSlotPair& feedback,
313 TypeofMode typeof_mode);
314 Node* BuildGlobalStore(Handle<Name> name, Node* value,
315 const VectorSlotPair& feedback);
316
317 // Builders for accessing the function context.
318 Node* BuildLoadGlobalObject();
319 Node* BuildLoadNativeContextField(int index);
320 Node* BuildLoadFeedbackVector();
321
322 // Builder for accessing a (potentially immutable) object field.
323 Node* BuildLoadObjectField(Node* object, int offset);
324 Node* BuildLoadImmutableObjectField(Node* object, int offset);
325
326 // Builders for automatic type conversion.
327 Node* BuildToBoolean(Node* input, TypeFeedbackId feedback_id);
328 Node* BuildToName(Node* input, BailoutId bailout_id);
329 Node* BuildToObject(Node* input, BailoutId bailout_id);
330
331 // Builder for adding the [[HomeObject]] to a value if the value came from a
332 // function literal and needs a home object. Do nothing otherwise.
333 Node* BuildSetHomeObject(Node* value, Node* home_object,
334 ObjectLiteralProperty* property,
335 int slot_number = 0);
336
337 // Builders for error reporting at runtime.
338 Node* BuildThrowError(Node* exception, BailoutId bailout_id);
339 Node* BuildThrowReferenceError(Variable* var, BailoutId bailout_id);
340 Node* BuildThrowConstAssignError(BailoutId bailout_id);
341 Node* BuildThrowStaticPrototypeError(BailoutId bailout_id);
342 Node* BuildThrowUnsupportedSuperError(BailoutId bailout_id);
343
344 // Builders for dynamic hole-checks at runtime.
345 Node* BuildHoleCheckSilent(Node* value, Node* for_hole, Node* not_hole);
346 Node* BuildHoleCheckThenThrow(Node* value, Variable* var, Node* not_hole,
347 BailoutId bailout_id);
348 Node* BuildHoleCheckElseThrow(Node* value, Variable* var, Node* for_hole,
349 BailoutId bailout_id);
350
351 // Builders for conditional errors.
352 Node* BuildThrowIfStaticPrototype(Node* name, BailoutId bailout_id);
353
354 // Builders for non-local control flow.
355 Node* BuildReturn(Node* return_value);
356 Node* BuildThrow(Node* exception_value);
357
358 // Builders for binary operations.
359 Node* BuildBinaryOp(Node* left, Node* right, Token::Value op,
360 TypeFeedbackId feedback_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400361
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 // Process arguments to a call by popping {arity} elements off the operand
363 // stack and build a call node using the given call operator.
364 Node* ProcessArguments(const Operator* op, int arity);
365
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 // ===========================================================================
367 // The following build methods have the same contract as the above ones, but
368 // they can also return {nullptr} to indicate that no fragment was built. Note
369 // that these are optimizations, disabling any of them should still produce
370 // correct graphs.
371
372 // Optimization for variable load from global object.
373 Node* TryLoadGlobalConstant(Handle<Name> name);
374
375 // Optimization for variable load of dynamic lookup slot that is most likely
376 // to resolve to a global slot or context slot (inferred from scope chain).
377 Node* TryLoadDynamicVariable(Variable* variable, Handle<String> name,
378 BailoutId bailout_id,
379 FrameStateBeforeAndAfter& states,
380 const VectorSlotPair& feedback,
381 OutputFrameStateCombine combine,
382 TypeofMode typeof_mode);
383
384 // Optimizations for automatic type conversion.
385 Node* TryFastToBoolean(Node* input);
386 Node* TryFastToName(Node* input);
387
388 // ===========================================================================
389 // The following visitation methods all recursively visit a subtree of the
390 // underlying AST and extent the graph. The operand stack is mutated in a way
391 // consistent with other compilers:
392 // - Expressions pop operands and push result, depending on {AstContext}.
393 // - Statements keep the operand stack balanced.
394
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395 // Visit statements.
396 void VisitIfNotNull(Statement* stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000397 void VisitInScope(Statement* stmt, Scope* scope, Node* context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398
399 // Visit expressions.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400400 void Visit(Expression* expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000401 void VisitForTest(Expression* expr);
402 void VisitForEffect(Expression* expr);
403 void VisitForValue(Expression* expr);
404 void VisitForValueOrNull(Expression* expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000405 void VisitForValueOrTheHole(Expression* expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000406 void VisitForValues(ZoneList<Expression*>* exprs);
407
408 // Common for all IterationStatement bodies.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000409 void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop);
410
411 // Dispatched from VisitCall.
412 void VisitCallSuper(Call* expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413
414 // Dispatched from VisitCallRuntime.
415 void VisitCallJSRuntime(CallRuntime* expr);
416
417 // Dispatched from VisitUnaryOperation.
418 void VisitDelete(UnaryOperation* expr);
419 void VisitVoid(UnaryOperation* expr);
420 void VisitTypeof(UnaryOperation* expr);
421 void VisitNot(UnaryOperation* expr);
422
423 // Dispatched from VisitBinaryOperation.
424 void VisitComma(BinaryOperation* expr);
425 void VisitLogicalExpression(BinaryOperation* expr);
426 void VisitArithmeticExpression(BinaryOperation* expr);
427
428 // Dispatched from VisitForInStatement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000429 void VisitForInAssignment(Expression* expr, Node* value,
430 const VectorSlotPair& feedback,
431 BailoutId bailout_id_before,
432 BailoutId bailout_id_after);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 // Dispatched from VisitObjectLiteral.
435 void VisitObjectLiteralAccessor(Node* home_object,
436 ObjectLiteralProperty* property);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000437
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000438 // Dispatched from VisitClassLiteral.
439 void VisitClassLiteralContents(ClassLiteral* expr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440
441 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
442 DISALLOW_COPY_AND_ASSIGN(AstGraphBuilder);
443};
444
445
446// The abstract execution environment for generated code consists of
447// parameter variables, local variables and the operand stack. The
448// environment will perform proper SSA-renaming of all tracked nodes
449// at split and merge points in the control flow. Internally all the
450// values are stored in one list using the following layout:
451//
452// [parameters (+receiver)] [locals] [operand stack]
453//
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000454class AstGraphBuilder::Environment : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000455 public:
456 Environment(AstGraphBuilder* builder, Scope* scope, Node* control_dependency);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457
458 int parameters_count() const { return parameters_count_; }
459 int locals_count() const { return locals_count_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 int context_chain_length() { return static_cast<int>(contexts_.size()); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000461 int stack_height() {
462 return static_cast<int>(values()->size()) - parameters_count_ -
463 locals_count_;
464 }
465
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 // Operations on parameter or local variables.
467 void Bind(Variable* variable, Node* node);
468 Node* Lookup(Variable* variable);
469 void MarkAllLocalsLive();
470
471 // Raw operations on parameter variables.
472 void RawParameterBind(int index, Node* node);
473 Node* RawParameterLookup(int index);
474
475 // Operations on the context chain.
476 Node* Context() const { return contexts_.back(); }
477 void PushContext(Node* context) { contexts()->push_back(context); }
478 void PopContext() { contexts()->pop_back(); }
479 void TrimContextChain(int trim_to_length) {
480 contexts()->resize(trim_to_length);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000481 }
482
483 // Operations on the operand stack.
484 void Push(Node* node) {
485 values()->push_back(node);
486 }
487 Node* Top() {
488 DCHECK(stack_height() > 0);
489 return values()->back();
490 }
491 Node* Pop() {
492 DCHECK(stack_height() > 0);
493 Node* back = values()->back();
494 values()->pop_back();
495 return back;
496 }
497
498 // Direct mutations of the operand stack.
499 void Poke(int depth, Node* node) {
500 DCHECK(depth >= 0 && depth < stack_height());
501 int index = static_cast<int>(values()->size()) - depth - 1;
502 values()->at(index) = node;
503 }
504 Node* Peek(int depth) {
505 DCHECK(depth >= 0 && depth < stack_height());
506 int index = static_cast<int>(values()->size()) - depth - 1;
507 return values()->at(index);
508 }
509 void Drop(int depth) {
510 DCHECK(depth >= 0 && depth <= stack_height());
511 values()->erase(values()->end() - depth, values()->end());
512 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000513 void TrimStack(int trim_to_height) {
514 int depth = stack_height() - trim_to_height;
515 DCHECK(depth >= 0 && depth <= stack_height());
516 values()->erase(values()->end() - depth, values()->end());
517 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518
519 // Preserve a checkpoint of the environment for the IR graph. Any
520 // further mutation of the environment will not affect checkpoints.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000521 Node* Checkpoint(BailoutId ast_id, OutputFrameStateCombine combine =
522 OutputFrameStateCombine::Ignore());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000524 // Control dependency tracked by this environment.
525 Node* GetControlDependency() { return control_dependency_; }
526 void UpdateControlDependency(Node* dependency) {
527 control_dependency_ = dependency;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000528 }
529
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000530 // Effect dependency tracked by this environment.
531 Node* GetEffectDependency() { return effect_dependency_; }
532 void UpdateEffectDependency(Node* dependency) {
533 effect_dependency_ = dependency;
534 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536 // Mark this environment as being unreachable.
537 void MarkAsUnreachable() {
538 UpdateControlDependency(builder()->jsgraph()->Dead());
539 liveness_block_ = nullptr;
540 }
541 bool IsMarkedAsUnreachable() {
542 return GetControlDependency()->opcode() == IrOpcode::kDead;
543 }
544
545 // Merge another environment into this one.
546 void Merge(Environment* other);
547
548 // Copies this environment at a control-flow split point.
549 Environment* CopyForConditional();
550
551 // Copies this environment to a potentially unreachable control-flow point.
552 Environment* CopyAsUnreachable();
553
554 // Copies this environment at a loop header control-flow point.
555 Environment* CopyForLoop(BitVector* assigned, bool is_osr = false);
556
557 private:
558 AstGraphBuilder* builder_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000559 int parameters_count_;
560 int locals_count_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000561 LivenessAnalyzerBlock* liveness_block_;
562 NodeVector values_;
563 NodeVector contexts_;
564 Node* control_dependency_;
565 Node* effect_dependency_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000566 Node* parameters_node_;
567 Node* locals_node_;
568 Node* stack_node_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569
570 explicit Environment(Environment* copy,
571 LivenessAnalyzerBlock* liveness_block);
572 Environment* CopyAndShareLiveness();
573 void UpdateStateValues(Node** state_values, int offset, int count);
574 void UpdateStateValuesWithCache(Node** state_values, int offset, int count);
575 Zone* zone() const { return builder_->local_zone(); }
576 Graph* graph() const { return builder_->graph(); }
577 AstGraphBuilder* builder() const { return builder_; }
578 CommonOperatorBuilder* common() { return builder_->common(); }
579 NodeVector* values() { return &values_; }
580 NodeVector* contexts() { return &contexts_; }
581 LivenessAnalyzerBlock* liveness_block() { return liveness_block_; }
582 bool IsLivenessAnalysisEnabled();
583 bool IsLivenessBlockConsistent();
584
585 // Prepare environment to be used as loop header.
586 void PrepareForLoop(BitVector* assigned, bool is_osr = false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000587};
588
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400589} // namespace compiler
590} // namespace internal
591} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592
593#endif // V8_COMPILER_AST_GRAPH_BUILDER_H_