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
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/ast/ast.h"
9 #include "src/compiler/compiler-source-position-table.h"
10 #include "src/compiler/js-graph.h"
11 #include "src/compiler/liveness-analyzer.h"
12 #include "src/compiler/state-values-utils.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 // Forward declarations.
18 class BitVector;
19 class CompilationInfo;
20 
21 namespace compiler {
22 
23 // Forward declarations.
24 class ControlBuilder;
25 class Graph;
26 class LoopAssignmentAnalysis;
27 class LoopBuilder;
28 class Node;
29 class TypeHintAnalysis;
30 
31 
32 // The AstGraphBuilder produces a high-level IR graph, based on an
33 // underlying AST. The produced graph can either be compiled into a
34 // stand-alone function or be wired into another graph for the purposes
35 // of function inlining.
36 // This AstVistor is not final, and provides the AstVisitor methods as virtual
37 // methods so they can be specialized by subclasses.
38 class AstGraphBuilder : public AstVisitor<AstGraphBuilder> {
39  public:
40   AstGraphBuilder(Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph,
41                   float invocation_frequency,
42                   LoopAssignmentAnalysis* loop_assignment = nullptr,
43                   TypeHintAnalysis* type_hint_analysis = nullptr);
~AstGraphBuilder()44   virtual ~AstGraphBuilder() {}
45 
46   // Creates a graph by visiting the entire AST.
47   bool CreateGraph(bool stack_check = true);
48 
49   // Helpers to create new control nodes.
NewIfTrue()50   Node* NewIfTrue() { return NewNode(common()->IfTrue()); }
NewIfFalse()51   Node* NewIfFalse() { return NewNode(common()->IfFalse()); }
NewMerge()52   Node* NewMerge() { return NewNode(common()->Merge(1), true); }
NewLoop()53   Node* NewLoop() { return NewNode(common()->Loop(1), true); }
54   Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) {
55     return NewNode(common()->Branch(hint), condition);
56   }
57 
58  protected:
59 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
60   // Visiting functions for AST nodes make this an AstVisitor.
61   AST_NODE_LIST(DECLARE_VISIT)
62 #undef DECLARE_VISIT
63 
64   // Visiting function for declarations list is overridden.
65   void VisitDeclarations(Declaration::List* declarations);
66 
67  private:
68   class AstContext;
69   class AstEffectContext;
70   class AstValueContext;
71   class AstTestContext;
72   class ContextScope;
73   class ControlScope;
74   class ControlScopeForBreakable;
75   class ControlScopeForIteration;
76   class ControlScopeForCatch;
77   class ControlScopeForFinally;
78   class Environment;
79   friend class ControlBuilder;
80 
81   Isolate* isolate_;
82   Zone* local_zone_;
83   CompilationInfo* info_;
84   JSGraph* jsgraph_;
85   float const invocation_frequency_;
86   Environment* environment_;
87   AstContext* ast_context_;
88 
89   // List of global declarations for functions and variables.
90   ZoneVector<Handle<Object>> globals_;
91 
92   // Stack of control scopes currently entered by the visitor.
93   ControlScope* execution_control_;
94 
95   // Stack of context objects pushed onto the chain by the visitor.
96   ContextScope* execution_context_;
97 
98   // Nodes representing values in the activation record.
99   SetOncePointer<Node> function_closure_;
100   SetOncePointer<Node> function_context_;
101   SetOncePointer<Node> new_target_;
102 
103   // Tracks how many try-blocks are currently entered.
104   int try_nesting_level_;
105 
106   // Temporary storage for building node input lists.
107   int input_buffer_size_;
108   Node** input_buffer_;
109 
110   // Optimization to cache loaded feedback vector.
111   SetOncePointer<Node> feedback_vector_;
112 
113   // Optimization to cache empty frame state.
114   SetOncePointer<Node> empty_frame_state_;
115 
116   // Control nodes that exit the function body.
117   ZoneVector<Node*> exit_controls_;
118 
119   // Result of loop assignment analysis performed before graph creation.
120   LoopAssignmentAnalysis* loop_assignment_analysis_;
121 
122   // Result of type hint analysis performed before graph creation.
123   TypeHintAnalysis* type_hint_analysis_;
124 
125   // Cache for StateValues nodes for frame states.
126   StateValuesCache state_values_cache_;
127 
128   // Analyzer of local variable liveness.
129   LivenessAnalyzer liveness_analyzer_;
130 
131   // Function info for frame state construction.
132   const FrameStateFunctionInfo* const frame_state_function_info_;
133 
134   // Growth increment for the temporary buffer used to construct input lists to
135   // new nodes.
136   static const int kInputBufferSizeIncrement = 64;
137 
local_zone()138   Zone* local_zone() const { return local_zone_; }
environment()139   Environment* environment() const { return environment_; }
ast_context()140   AstContext* ast_context() const { return ast_context_; }
execution_control()141   ControlScope* execution_control() const { return execution_control_; }
execution_context()142   ContextScope* execution_context() const { return execution_context_; }
common()143   CommonOperatorBuilder* common() const { return jsgraph_->common(); }
info()144   CompilationInfo* info() const { return info_; }
isolate()145   Isolate* isolate() const { return isolate_; }
146   LanguageMode language_mode() const;
jsgraph()147   JSGraph* jsgraph() { return jsgraph_; }
graph()148   Graph* graph() { return jsgraph_->graph(); }
graph_zone()149   Zone* graph_zone() { return graph()->zone(); }
javascript()150   JSOperatorBuilder* javascript() { return jsgraph_->javascript(); }
globals()151   ZoneVector<Handle<Object>>* globals() { return &globals_; }
152   Scope* current_scope() const;
153   Node* current_context() const;
liveness_analyzer()154   LivenessAnalyzer* liveness_analyzer() { return &liveness_analyzer_; }
frame_state_function_info()155   const FrameStateFunctionInfo* frame_state_function_info() const {
156     return frame_state_function_info_;
157   }
158 
set_environment(Environment * env)159   void set_environment(Environment* env) { environment_ = env; }
set_ast_context(AstContext * ctx)160   void set_ast_context(AstContext* ctx) { ast_context_ = ctx; }
set_execution_control(ControlScope * ctrl)161   void set_execution_control(ControlScope* ctrl) { execution_control_ = ctrl; }
set_execution_context(ContextScope * ctx)162   void set_execution_context(ContextScope* ctx) { execution_context_ = ctx; }
163 
164   // Create the main graph body by visiting the AST.
165   void CreateGraphBody(bool stack_check);
166 
167   // Get or create the node that represents the incoming function closure.
168   Node* GetFunctionClosureForContext();
169   Node* GetFunctionClosure();
170 
171   // Get or create the node that represents the incoming function context.
172   Node* GetFunctionContext();
173 
174   // Get or create the node that represents the incoming new target value.
175   Node* GetNewTarget();
176 
177   // Get or create the node that represents the empty frame state.
178   Node* GetEmptyFrameState();
179 
180   // Node creation helpers.
181   Node* NewNode(const Operator* op, bool incomplete = false) {
182     return MakeNode(op, 0, static_cast<Node**>(nullptr), incomplete);
183   }
184 
NewNode(const Operator * op,Node * n1)185   Node* NewNode(const Operator* op, Node* n1) {
186     return MakeNode(op, 1, &n1, false);
187   }
188 
NewNode(const Operator * op,Node * n1,Node * n2)189   Node* NewNode(const Operator* op, Node* n1, Node* n2) {
190     Node* buffer[] = {n1, n2};
191     return MakeNode(op, arraysize(buffer), buffer, false);
192   }
193 
NewNode(const Operator * op,Node * n1,Node * n2,Node * n3)194   Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
195     Node* buffer[] = {n1, n2, n3};
196     return MakeNode(op, arraysize(buffer), buffer, false);
197   }
198 
NewNode(const Operator * op,Node * n1,Node * n2,Node * n3,Node * n4)199   Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) {
200     Node* buffer[] = {n1, n2, n3, n4};
201     return MakeNode(op, arraysize(buffer), buffer, false);
202   }
203 
NewNode(const Operator * op,Node * n1,Node * n2,Node * n3,Node * n4,Node * n5)204   Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
205                 Node* n5) {
206     Node* buffer[] = {n1, n2, n3, n4, n5};
207     return MakeNode(op, arraysize(buffer), buffer, false);
208   }
209 
NewNode(const Operator * op,Node * n1,Node * n2,Node * n3,Node * n4,Node * n5,Node * n6)210   Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
211                 Node* n5, Node* n6) {
212     Node* nodes[] = {n1, n2, n3, n4, n5, n6};
213     return MakeNode(op, arraysize(nodes), nodes, false);
214   }
215 
216   Node* NewNode(const Operator* op, int value_input_count, Node** value_inputs,
217                 bool incomplete = false) {
218     return MakeNode(op, value_input_count, value_inputs, incomplete);
219   }
220 
221   // Creates a new Phi node having {count} input values.
222   Node* NewPhi(int count, Node* input, Node* control);
223   Node* NewEffectPhi(int count, Node* input, Node* control);
224 
225   // Helpers for merging control, effect or value dependencies.
226   Node* MergeControl(Node* control, Node* other);
227   Node* MergeEffect(Node* value, Node* other, Node* control);
228   Node* MergeValue(Node* value, Node* other, Node* control);
229 
230   // The main node creation chokepoint. Adds context, frame state, effect,
231   // and control dependencies depending on the operator.
232   Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs,
233                  bool incomplete);
234 
235   // Helper to indicate a node exits the function body.
236   void UpdateControlDependencyToLeaveFunction(Node* exit);
237 
238   // Prepare information for lazy deoptimization. This information is attached
239   // to the given node and the output value produced by the node is combined.
240   // Conceptually this frame state is "after" a given operation.
241   void PrepareFrameState(Node* node, BailoutId ast_id,
242                          OutputFrameStateCombine framestate_combine =
243                              OutputFrameStateCombine::Ignore());
244 
245   // Prepare information for eager deoptimization. This information is carried
246   // by dedicated {Checkpoint} nodes that are wired into the effect chain.
247   // Conceptually this frame state is "before" a given operation.
248   void PrepareEagerCheckpoint(BailoutId ast_id);
249 
250   BitVector* GetVariablesAssignedInLoop(IterationStatement* stmt);
251 
252   // Check if the given statement is an OSR entry.
253   // If so, record the stack height into the compilation and return {true}.
254   bool CheckOsrEntry(IterationStatement* stmt);
255 
256   // Computes local variable liveness and replaces dead variables in
257   // frame states with the undefined values.
258   void ClearNonLiveSlotsInFrameStates();
259 
260   Node** EnsureInputBufferSize(int size);
261 
262   // Named and keyed loads require a VectorSlotPair for successful lowering.
263   VectorSlotPair CreateVectorSlotPair(FeedbackVectorSlot slot) const;
264 
265   // Determine which contexts need to be checked for extension objects that
266   // might shadow the optimistic declaration of dynamic lookup variables.
267   uint32_t ComputeBitsetForDynamicGlobal(Variable* variable);
268   uint32_t ComputeBitsetForDynamicContext(Variable* variable);
269 
270   // Computes the frequency for JSCallFunction and JSCallConstruct nodes.
271   float ComputeCallFrequency(FeedbackVectorSlot slot) const;
272 
273   // ===========================================================================
274   // The following build methods all generate graph fragments and return one
275   // resulting node. The operand stack height remains the same, variables and
276   // other dependencies tracked by the environment might be mutated though.
277 
278   // Builders to create local function, script and block contexts.
279   Node* BuildLocalActivationContext(Node* context);
280   Node* BuildLocalFunctionContext(Scope* scope);
281   Node* BuildLocalScriptContext(Scope* scope);
282   Node* BuildLocalBlockContext(Scope* scope);
283 
284   // Builder to create an arguments object if it is used.
285   Node* BuildArgumentsObject(Variable* arguments);
286 
287   // Builder to create an array of rest parameters if used.
288   Node* BuildRestArgumentsArray(Variable* rest);
289 
290   // Builder that assigns to the {.this_function} internal variable if needed.
291   Node* BuildThisFunctionVariable(Variable* this_function_var);
292 
293   // Builder that assigns to the {new.target} internal variable if needed.
294   Node* BuildNewTargetVariable(Variable* new_target_var);
295 
296   // Builders for variable load and assignment.
297   Node* BuildVariableAssignment(Variable* variable, Node* value,
298                                 Token::Value op, const VectorSlotPair& slot,
299                                 BailoutId bailout_id,
300                                 OutputFrameStateCombine framestate_combine =
301                                     OutputFrameStateCombine::Ignore());
302   Node* BuildVariableDelete(Variable* variable, BailoutId bailout_id,
303                             OutputFrameStateCombine framestate_combine);
304   Node* BuildVariableLoad(Variable* variable, BailoutId bailout_id,
305                           const VectorSlotPair& feedback,
306                           OutputFrameStateCombine framestate_combine,
307                           TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
308 
309   // Builders for property loads and stores.
310   Node* BuildKeyedLoad(Node* receiver, Node* key,
311                        const VectorSlotPair& feedback);
312   Node* BuildNamedLoad(Node* receiver, Handle<Name> name,
313                        const VectorSlotPair& feedback);
314   Node* BuildKeyedStore(Node* receiver, Node* key, Node* value,
315                         const VectorSlotPair& feedback);
316   Node* BuildNamedStore(Node* receiver, Handle<Name> name, Node* value,
317                         const VectorSlotPair& feedback);
318 
319   // Builders for super property loads and stores.
320   Node* BuildKeyedSuperStore(Node* receiver, Node* home_object, Node* key,
321                              Node* value);
322   Node* BuildNamedSuperStore(Node* receiver, Node* home_object,
323                              Handle<Name> name, Node* value);
324   Node* BuildNamedSuperLoad(Node* receiver, Node* home_object,
325                             Handle<Name> name, const VectorSlotPair& feedback);
326   Node* BuildKeyedSuperLoad(Node* receiver, Node* home_object, Node* key,
327                             const VectorSlotPair& feedback);
328 
329   // Builders for global variable loads and stores.
330   Node* BuildGlobalLoad(Handle<Name> name, const VectorSlotPair& feedback,
331                         TypeofMode typeof_mode);
332   Node* BuildGlobalStore(Handle<Name> name, Node* value,
333                          const VectorSlotPair& feedback);
334 
335   // Builders for dynamic variable loads and stores.
336   Node* BuildDynamicLoad(Handle<Name> name, TypeofMode typeof_mode);
337   Node* BuildDynamicStore(Handle<Name> name, Node* value);
338 
339   // Builders for accessing the function context.
340   Node* BuildLoadGlobalObject();
341   Node* BuildLoadNativeContextField(int index);
342 
343   // Builders for automatic type conversion.
344   Node* BuildToBoolean(Node* input, TypeFeedbackId feedback_id);
345   Node* BuildToName(Node* input, BailoutId bailout_id);
346   Node* BuildToObject(Node* input, BailoutId bailout_id);
347 
348   // Builder for adding the [[HomeObject]] to a value if the value came from a
349   // function literal and needs a home object. Do nothing otherwise.
350   Node* BuildSetHomeObject(Node* value, Node* home_object,
351                            LiteralProperty* property, int slot_number = 0);
352 
353   // Builders for error reporting at runtime.
354   Node* BuildThrowError(Node* exception, BailoutId bailout_id);
355   Node* BuildThrowReferenceError(Variable* var, BailoutId bailout_id);
356   Node* BuildThrowConstAssignError(BailoutId bailout_id);
357   Node* BuildThrowStaticPrototypeError(BailoutId bailout_id);
358   Node* BuildThrowUnsupportedSuperError(BailoutId bailout_id);
359 
360   // Builders for dynamic hole-checks at runtime.
361   Node* BuildHoleCheckThenThrow(Node* value, Variable* var, Node* not_hole,
362                                 BailoutId bailout_id);
363   Node* BuildHoleCheckElseThrow(Node* value, Variable* var, Node* for_hole,
364                                 BailoutId bailout_id);
365 
366   // Builders for conditional errors.
367   Node* BuildThrowIfStaticPrototype(Node* name, BailoutId bailout_id);
368 
369   // Builders for non-local control flow.
370   Node* BuildReturn(Node* return_value);
371   Node* BuildThrow(Node* exception_value);
372 
373   // Builders for binary operations.
374   Node* BuildBinaryOp(Node* left, Node* right, Token::Value op,
375                       TypeFeedbackId feedback_id);
376 
377   // Process arguments to a call by popping {arity} elements off the operand
378   // stack and build a call node using the given call operator.
379   Node* ProcessArguments(const Operator* op, int arity);
380 
381   // ===========================================================================
382   // The following build methods have the same contract as the above ones, but
383   // they can also return {nullptr} to indicate that no fragment was built. Note
384   // that these are optimizations, disabling any of them should still produce
385   // correct graphs.
386 
387   // Optimization for variable load from global object.
388   Node* TryLoadGlobalConstant(Handle<Name> name);
389 
390   // Optimization for variable load of dynamic lookup slot that is most likely
391   // to resolve to a global slot or context slot (inferred from scope chain).
392   Node* TryLoadDynamicVariable(Variable* variable, Handle<String> name,
393                                BailoutId bailout_id,
394                                const VectorSlotPair& feedback,
395                                OutputFrameStateCombine combine,
396                                TypeofMode typeof_mode);
397 
398   // Optimizations for automatic type conversion.
399   Node* TryFastToBoolean(Node* input);
400   Node* TryFastToName(Node* input);
401 
402   // ===========================================================================
403   // The following visitation methods all recursively visit a subtree of the
404   // underlying AST and extent the graph. The operand stack is mutated in a way
405   // consistent with other compilers:
406   //  - Expressions pop operands and push result, depending on {AstContext}.
407   //  - Statements keep the operand stack balanced.
408 
409   // Visit statements.
410   void VisitIfNotNull(Statement* stmt);
411   void VisitInScope(Statement* stmt, Scope* scope, Node* context);
412 
413   // Visit expressions.
414   void Visit(Expression* expr);
415   void VisitForTest(Expression* expr);
416   void VisitForEffect(Expression* expr);
417   void VisitForValue(Expression* expr);
418   void VisitForValueOrNull(Expression* expr);
419   void VisitForValueOrTheHole(Expression* expr);
420   void VisitForValues(ZoneList<Expression*>* exprs);
421 
422   // Common for all IterationStatement bodies.
423   void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop,
424                           BailoutId stack_check_id);
425 
426   // Dispatched from VisitCall.
427   void VisitCallSuper(Call* expr);
428 
429   // Dispatched from VisitCallRuntime.
430   void VisitCallJSRuntime(CallRuntime* expr);
431 
432   // Dispatched from VisitUnaryOperation.
433   void VisitDelete(UnaryOperation* expr);
434   void VisitVoid(UnaryOperation* expr);
435   void VisitTypeof(UnaryOperation* expr);
436   void VisitNot(UnaryOperation* expr);
437 
438   // Dispatched from VisitTypeof, VisitLiteralCompareTypeof.
439   void VisitTypeofExpression(Expression* expr);
440 
441   // Dispatched from VisitBinaryOperation.
442   void VisitComma(BinaryOperation* expr);
443   void VisitLogicalExpression(BinaryOperation* expr);
444   void VisitArithmeticExpression(BinaryOperation* expr);
445 
446   // Dispatched from VisitCompareOperation.
447   void VisitLiteralCompareNil(CompareOperation* expr, Expression* sub_expr,
448                               Node* nil_value);
449   void VisitLiteralCompareTypeof(CompareOperation* expr, Expression* sub_expr,
450                                  Handle<String> check);
451 
452   // Dispatched from VisitForInStatement.
453   void VisitForInAssignment(Expression* expr, Node* value,
454                             const VectorSlotPair& feedback,
455                             BailoutId bailout_id);
456 
457   // Dispatched from VisitObjectLiteral.
458   void VisitObjectLiteralAccessor(Node* home_object,
459                                   ObjectLiteralProperty* property);
460 
461   DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
462   DISALLOW_COPY_AND_ASSIGN(AstGraphBuilder);
463 };
464 
465 
466 // The abstract execution environment for generated code consists of
467 // parameter variables, local variables and the operand stack. The
468 // environment will perform proper SSA-renaming of all tracked nodes
469 // at split and merge points in the control flow. Internally all the
470 // values are stored in one list using the following layout:
471 //
472 //  [parameters (+receiver)] [locals] [operand stack]
473 //
474 class AstGraphBuilder::Environment : public ZoneObject {
475  public:
476   Environment(AstGraphBuilder* builder, DeclarationScope* scope,
477               Node* control_dependency);
478 
parameters_count()479   int parameters_count() const { return parameters_count_; }
locals_count()480   int locals_count() const { return locals_count_; }
context_chain_length()481   int context_chain_length() { return static_cast<int>(contexts_.size()); }
stack_height()482   int stack_height() {
483     return static_cast<int>(values()->size()) - parameters_count_ -
484            locals_count_;
485   }
486 
487   // Operations on parameter or local variables.
488   void Bind(Variable* variable, Node* node);
489   Node* Lookup(Variable* variable);
490   void MarkAllLocalsLive();
491 
492   // Raw operations on parameter variables.
493   void RawParameterBind(int index, Node* node);
494   Node* RawParameterLookup(int index);
495 
496   // Operations on the context chain.
Context()497   Node* Context() const { return contexts_.back(); }
PushContext(Node * context)498   void PushContext(Node* context) { contexts()->push_back(context); }
PopContext()499   void PopContext() { contexts()->pop_back(); }
TrimContextChain(int trim_to_length)500   void TrimContextChain(int trim_to_length) {
501     contexts()->resize(trim_to_length);
502   }
503 
504   // Operations on the operand stack.
Push(Node * node)505   void Push(Node* node) {
506     values()->push_back(node);
507   }
Top()508   Node* Top() {
509     DCHECK(stack_height() > 0);
510     return values()->back();
511   }
Pop()512   Node* Pop() {
513     DCHECK(stack_height() > 0);
514     Node* back = values()->back();
515     values()->pop_back();
516     return back;
517   }
518 
519   // Direct mutations of the operand stack.
Poke(int depth,Node * node)520   void Poke(int depth, Node* node) {
521     DCHECK(depth >= 0 && depth < stack_height());
522     int index = static_cast<int>(values()->size()) - depth - 1;
523     values()->at(index) = node;
524   }
Peek(int depth)525   Node* Peek(int depth) {
526     DCHECK(depth >= 0 && depth < stack_height());
527     int index = static_cast<int>(values()->size()) - depth - 1;
528     return values()->at(index);
529   }
Drop(int depth)530   void Drop(int depth) {
531     DCHECK(depth >= 0 && depth <= stack_height());
532     values()->erase(values()->end() - depth, values()->end());
533   }
TrimStack(int trim_to_height)534   void TrimStack(int trim_to_height) {
535     int depth = stack_height() - trim_to_height;
536     DCHECK(depth >= 0 && depth <= stack_height());
537     values()->erase(values()->end() - depth, values()->end());
538   }
539 
540   // Preserve a checkpoint of the environment for the IR graph. Any
541   // further mutation of the environment will not affect checkpoints.
542   Node* Checkpoint(BailoutId ast_id, OutputFrameStateCombine combine =
543                                          OutputFrameStateCombine::Ignore(),
544                    bool node_has_exception = false);
545 
546   // Inserts a loop exit control node and renames the environment.
547   // This is useful for loop peeling to insert phis at loop exits.
548   void PrepareForLoopExit(Node* loop, BitVector* assigned_variables);
549 
550   // Control dependency tracked by this environment.
GetControlDependency()551   Node* GetControlDependency() { return control_dependency_; }
UpdateControlDependency(Node * dependency)552   void UpdateControlDependency(Node* dependency) {
553     control_dependency_ = dependency;
554   }
555 
556   // Effect dependency tracked by this environment.
GetEffectDependency()557   Node* GetEffectDependency() { return effect_dependency_; }
UpdateEffectDependency(Node * dependency)558   void UpdateEffectDependency(Node* dependency) {
559     effect_dependency_ = dependency;
560   }
561 
562   // Mark this environment as being unreachable.
MarkAsUnreachable()563   void MarkAsUnreachable() {
564     UpdateControlDependency(builder()->jsgraph()->Dead());
565     liveness_block_ = nullptr;
566   }
IsMarkedAsUnreachable()567   bool IsMarkedAsUnreachable() {
568     return GetControlDependency()->opcode() == IrOpcode::kDead;
569   }
570 
571   // Merge another environment into this one.
572   void Merge(Environment* other);
573 
574   // Copies this environment at a control-flow split point.
575   Environment* CopyForConditional();
576 
577   // Copies this environment to a potentially unreachable control-flow point.
578   Environment* CopyAsUnreachable();
579 
580   // Copies this environment at a loop header control-flow point.
581   Environment* CopyForLoop(BitVector* assigned, bool is_osr = false);
582 
583   // Copies this environment for Osr entry. This only produces environment
584   // of the right shape, the caller is responsible for filling in the right
585   // values and dependencies.
586   Environment* CopyForOsrEntry();
587 
588  private:
589   AstGraphBuilder* builder_;
590   int parameters_count_;
591   int locals_count_;
592   LivenessAnalyzerBlock* liveness_block_;
593   NodeVector values_;
594   NodeVector contexts_;
595   Node* control_dependency_;
596   Node* effect_dependency_;
597   Node* parameters_node_;
598   Node* locals_node_;
599   Node* stack_node_;
600 
601   explicit Environment(Environment* copy,
602                        LivenessAnalyzerBlock* liveness_block);
603   Environment* CopyAndShareLiveness();
604   void UpdateStateValues(Node** state_values, int offset, int count);
zone()605   Zone* zone() const { return builder_->local_zone(); }
graph()606   Graph* graph() const { return builder_->graph(); }
builder()607   AstGraphBuilder* builder() const { return builder_; }
common()608   CommonOperatorBuilder* common() { return builder_->common(); }
values()609   NodeVector* values() { return &values_; }
contexts()610   NodeVector* contexts() { return &contexts_; }
liveness_block()611   LivenessAnalyzerBlock* liveness_block() { return liveness_block_; }
612   bool IsLivenessAnalysisEnabled();
613   bool IsLivenessBlockConsistent();
614 
615   // Prepare environment to be used as loop header.
616   void PrepareForLoop(BitVector* assigned);
617   void PrepareForOsrEntry();
618 };
619 
620 class AstGraphBuilderWithPositions final : public AstGraphBuilder {
621  public:
622   AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info,
623                                JSGraph* jsgraph, float invocation_frequency,
624                                LoopAssignmentAnalysis* loop_assignment,
625                                TypeHintAnalysis* type_hint_analysis,
626                                SourcePositionTable* source_positions,
627                                int inlining_id = SourcePosition::kNotInlined);
628 
629   bool CreateGraph(bool stack_check = true) {
630     SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
631     return AstGraphBuilder::CreateGraph(stack_check);
632   }
633 
634 #define DEF_VISIT(type)                                                  \
635   void Visit##type(type* node) override {                                \
636     SourcePositionTable::Scope pos(                                      \
637         source_positions_,                                               \
638         SourcePosition(node->position(), start_position_.InliningId())); \
639     AstGraphBuilder::Visit##type(node);                                  \
640   }
641   AST_NODE_LIST(DEF_VISIT)
642 #undef DEF_VISIT
643 
644  private:
645   SourcePositionTable* const source_positions_;
646   SourcePosition const start_position_;
647 };
648 
649 }  // namespace compiler
650 }  // namespace internal
651 }  // namespace v8
652 
653 #endif  // V8_COMPILER_AST_GRAPH_BUILDER_H_
654