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 #include "src/compiler/ast-graph-builder.h"
6 
7 #include "src/ast/compile-time-value.h"
8 #include "src/ast/scopes.h"
9 #include "src/compilation-info.h"
10 #include "src/compiler.h"
11 #include "src/compiler/ast-loop-assignment-analyzer.h"
12 #include "src/compiler/control-builders.h"
13 #include "src/compiler/linkage.h"
14 #include "src/compiler/liveness-analyzer.h"
15 #include "src/compiler/machine-operator.h"
16 #include "src/compiler/node-matchers.h"
17 #include "src/compiler/node-properties.h"
18 #include "src/compiler/operator-properties.h"
19 #include "src/compiler/state-values-utils.h"
20 #include "src/compiler/type-hint-analyzer.h"
21 
22 namespace v8 {
23 namespace internal {
24 namespace compiler {
25 
26 
27 // Each expression in the AST is evaluated in a specific context. This context
28 // decides how the evaluation result is passed up the visitor.
29 class AstGraphBuilder::AstContext BASE_EMBEDDED {
30  public:
IsEffect() const31   bool IsEffect() const { return kind_ == Expression::kEffect; }
IsValue() const32   bool IsValue() const { return kind_ == Expression::kValue; }
IsTest() const33   bool IsTest() const { return kind_ == Expression::kTest; }
34 
35   // Determines how to combine the frame state with the value
36   // that is about to be plugged into this AstContext.
GetStateCombine()37   OutputFrameStateCombine GetStateCombine() {
38     return IsEffect() ? OutputFrameStateCombine::Ignore()
39                       : OutputFrameStateCombine::Push();
40   }
41 
42   // Plug a node into this expression context.  Call this function in tail
43   // position in the Visit functions for expressions.
44   virtual void ProduceValue(Expression* expr, Node* value) = 0;
45 
46   // Unplugs a node from this expression context.  Call this to retrieve the
47   // result of another Visit function that already plugged the context.
48   virtual Node* ConsumeValue() = 0;
49 
50   // Shortcut for "context->ProduceValue(context->ConsumeValue())".
ReplaceValue(Expression * expr)51   void ReplaceValue(Expression* expr) { ProduceValue(expr, ConsumeValue()); }
52 
53  protected:
54   AstContext(AstGraphBuilder* owner, Expression::Context kind);
55   virtual ~AstContext();
56 
owner() const57   AstGraphBuilder* owner() const { return owner_; }
environment() const58   Environment* environment() const { return owner_->environment(); }
59 
60 // We want to be able to assert, in a context-specific way, that the stack
61 // height makes sense when the context is filled.
62 #ifdef DEBUG
63   int original_height_;
64 #endif
65 
66  private:
67   Expression::Context kind_;
68   AstGraphBuilder* owner_;
69   AstContext* outer_;
70 };
71 
72 
73 // Context to evaluate expression for its side effects only.
74 class AstGraphBuilder::AstEffectContext final : public AstContext {
75  public:
AstEffectContext(AstGraphBuilder * owner)76   explicit AstEffectContext(AstGraphBuilder* owner)
77       : AstContext(owner, Expression::kEffect) {}
78   ~AstEffectContext() final;
79   void ProduceValue(Expression* expr, Node* value) final;
80   Node* ConsumeValue() final;
81 };
82 
83 
84 // Context to evaluate expression for its value (and side effects).
85 class AstGraphBuilder::AstValueContext final : public AstContext {
86  public:
AstValueContext(AstGraphBuilder * owner)87   explicit AstValueContext(AstGraphBuilder* owner)
88       : AstContext(owner, Expression::kValue) {}
89   ~AstValueContext() final;
90   void ProduceValue(Expression* expr, Node* value) final;
91   Node* ConsumeValue() final;
92 };
93 
94 
95 // Context to evaluate expression for a condition value (and side effects).
96 class AstGraphBuilder::AstTestContext final : public AstContext {
97  public:
AstTestContext(AstGraphBuilder * owner,TypeFeedbackId feedback_id)98   AstTestContext(AstGraphBuilder* owner, TypeFeedbackId feedback_id)
99       : AstContext(owner, Expression::kTest), feedback_id_(feedback_id) {}
100   ~AstTestContext() final;
101   void ProduceValue(Expression* expr, Node* value) final;
102   Node* ConsumeValue() final;
103 
104  private:
105   TypeFeedbackId const feedback_id_;
106 };
107 
108 
109 // Scoped class tracking context objects created by the visitor. Represents
110 // mutations of the context chain within the function body and allows to
111 // change the current {scope} and {context} during visitation.
112 class AstGraphBuilder::ContextScope BASE_EMBEDDED {
113  public:
ContextScope(AstGraphBuilder * builder,Scope * scope,Node * context)114   ContextScope(AstGraphBuilder* builder, Scope* scope, Node* context)
115       : builder_(builder),
116         outer_(builder->execution_context()),
117         scope_(scope),
118         depth_(builder_->environment()->context_chain_length()) {
119     builder_->environment()->PushContext(context);  // Push.
120     builder_->set_execution_context(this);
121   }
122 
~ContextScope()123   ~ContextScope() {
124     builder_->set_execution_context(outer_);  // Pop.
125     builder_->environment()->PopContext();
126     CHECK_EQ(depth_, builder_->environment()->context_chain_length());
127   }
128 
129   // Current scope during visitation.
scope() const130   Scope* scope() const { return scope_; }
131 
132  private:
133   AstGraphBuilder* builder_;
134   ContextScope* outer_;
135   Scope* scope_;
136   int depth_;
137 };
138 
139 
140 // Scoped class tracking control statements entered by the visitor. There are
141 // different types of statements participating in this stack to properly track
142 // local as well as non-local control flow:
143 //  - IterationStatement : Allows proper 'break' and 'continue' behavior.
144 //  - BreakableStatement : Allows 'break' from block and switch statements.
145 //  - TryCatchStatement  : Intercepts 'throw' and implicit exceptional edges.
146 //  - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'.
147 class AstGraphBuilder::ControlScope BASE_EMBEDDED {
148  public:
ControlScope(AstGraphBuilder * builder)149   explicit ControlScope(AstGraphBuilder* builder)
150       : builder_(builder),
151         outer_(builder->execution_control()),
152         context_length_(builder->environment()->context_chain_length()),
153         stack_height_(builder->environment()->stack_height()) {
154     builder_->set_execution_control(this);  // Push.
155   }
156 
~ControlScope()157   virtual ~ControlScope() {
158     builder_->set_execution_control(outer_);  // Pop.
159   }
160 
161   // Either 'break' or 'continue' to the target statement.
162   void BreakTo(BreakableStatement* target);
163   void ContinueTo(BreakableStatement* target);
164 
165   // Either 'return' or 'throw' the given value.
166   void ReturnValue(Node* return_value);
167   void ThrowValue(Node* exception_value);
168 
169   class DeferredCommands;
170 
171  protected:
172   enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW };
173 
174   // Performs one of the above commands on this stack of control scopes. This
175   // walks through the stack giving each scope a chance to execute or defer the
176   // given command by overriding the {Execute} method appropriately. Note that
177   // this also drops extra operands from the environment for each skipped scope.
178   void PerformCommand(Command cmd, Statement* target, Node* value);
179 
180   // Interface to execute a given command in this scope. Returning {true} here
181   // indicates successful execution whereas {false} requests to skip scope.
Execute(Command cmd,Statement * target,Node ** value)182   virtual bool Execute(Command cmd, Statement* target, Node** value) {
183     // For function-level control.
184     switch (cmd) {
185       case CMD_THROW:
186         builder()->BuildThrow(*value);
187         return true;
188       case CMD_RETURN:
189         builder()->BuildReturn(*value);
190         return true;
191       case CMD_BREAK:
192       case CMD_CONTINUE:
193         break;
194     }
195     return false;
196   }
197 
environment()198   Environment* environment() { return builder_->environment(); }
builder() const199   AstGraphBuilder* builder() const { return builder_; }
context_length() const200   int context_length() const { return context_length_; }
stack_height() const201   int stack_height() const { return stack_height_; }
202 
203  private:
204   AstGraphBuilder* builder_;
205   ControlScope* outer_;
206   int context_length_;
207   int stack_height_;
208 };
209 
210 // Helper class for a try-finally control scope. It can record intercepted
211 // control-flow commands that cause entry into a finally-block, and re-apply
212 // them after again leaving that block. Special tokens are used to identify
213 // paths going through the finally-block to dispatch after leaving the block.
214 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject {
215  public:
DeferredCommands(AstGraphBuilder * owner)216   explicit DeferredCommands(AstGraphBuilder* owner)
217       : owner_(owner),
218         deferred_(owner->local_zone()),
219         return_token_(nullptr),
220         throw_token_(nullptr) {}
221 
222   // One recorded control-flow command.
223   struct Entry {
224     Command command;       // The command type being applied on this path.
225     Statement* statement;  // The target statement for the command or {nullptr}.
226     Node* token;           // A token identifying this particular path.
227   };
228 
229   // Records a control-flow command while entering the finally-block. This also
230   // generates a new dispatch token that identifies one particular path.
RecordCommand(Command cmd,Statement * stmt,Node * value)231   Node* RecordCommand(Command cmd, Statement* stmt, Node* value) {
232     Node* token = nullptr;
233     switch (cmd) {
234       case CMD_BREAK:
235       case CMD_CONTINUE:
236         token = NewPathToken(dispenser_.GetBreakContinueToken());
237         break;
238       case CMD_THROW:
239         if (throw_token_) return throw_token_;
240         token = NewPathToken(TokenDispenserForFinally::kThrowToken);
241         throw_token_ = token;
242         break;
243       case CMD_RETURN:
244         if (return_token_) return return_token_;
245         token = NewPathToken(TokenDispenserForFinally::kReturnToken);
246         return_token_ = token;
247         break;
248     }
249     DCHECK_NOT_NULL(token);
250     deferred_.push_back({cmd, stmt, token});
251     return token;
252   }
253 
254   // Returns the dispatch token to be used to identify the implicit fall-through
255   // path at the end of a try-block into the corresponding finally-block.
GetFallThroughToken()256   Node* GetFallThroughToken() { return NewPathTokenForImplicitFallThrough(); }
257 
258   // Applies all recorded control-flow commands after the finally-block again.
259   // This generates a dynamic dispatch on the token from the entry point.
ApplyDeferredCommands(Node * token,Node * value)260   void ApplyDeferredCommands(Node* token, Node* value) {
261     SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size()));
262     dispatch.BeginSwitch();
263     for (size_t i = 0; i < deferred_.size(); ++i) {
264       Node* condition = NewPathDispatchCondition(token, deferred_[i].token);
265       dispatch.BeginLabel(static_cast<int>(i), condition);
266       dispatch.EndLabel();
267     }
268     for (size_t i = 0; i < deferred_.size(); ++i) {
269       dispatch.BeginCase(static_cast<int>(i));
270       owner_->execution_control()->PerformCommand(
271           deferred_[i].command, deferred_[i].statement, value);
272       dispatch.EndCase();
273     }
274     dispatch.EndSwitch();
275   }
276 
277  protected:
NewPathToken(int token_id)278   Node* NewPathToken(int token_id) {
279     return owner_->jsgraph()->Constant(token_id);
280   }
NewPathTokenForImplicitFallThrough()281   Node* NewPathTokenForImplicitFallThrough() {
282     return NewPathToken(TokenDispenserForFinally::kFallThroughToken);
283   }
NewPathDispatchCondition(Node * t1,Node * t2)284   Node* NewPathDispatchCondition(Node* t1, Node* t2) {
285     return owner_->NewNode(
286         owner_->javascript()->StrictEqual(CompareOperationHint::kAny), t1, t2);
287   }
288 
289  private:
290   TokenDispenserForFinally dispenser_;
291   AstGraphBuilder* owner_;
292   ZoneVector<Entry> deferred_;
293   Node* return_token_;
294   Node* throw_token_;
295 };
296 
297 
298 // Control scope implementation for a BreakableStatement.
299 class AstGraphBuilder::ControlScopeForBreakable : public ControlScope {
300  public:
ControlScopeForBreakable(AstGraphBuilder * owner,BreakableStatement * target,ControlBuilder * control)301   ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target,
302                            ControlBuilder* control)
303       : ControlScope(owner), target_(target), control_(control) {}
304 
305  protected:
Execute(Command cmd,Statement * target,Node ** value)306   bool Execute(Command cmd, Statement* target, Node** value) override {
307     if (target != target_) return false;  // We are not the command target.
308     switch (cmd) {
309       case CMD_BREAK:
310         control_->Break();
311         return true;
312       case CMD_CONTINUE:
313       case CMD_THROW:
314       case CMD_RETURN:
315         break;
316     }
317     return false;
318   }
319 
320  private:
321   BreakableStatement* target_;
322   ControlBuilder* control_;
323 };
324 
325 
326 // Control scope implementation for an IterationStatement.
327 class AstGraphBuilder::ControlScopeForIteration : public ControlScope {
328  public:
ControlScopeForIteration(AstGraphBuilder * owner,IterationStatement * target,LoopBuilder * control)329   ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target,
330                            LoopBuilder* control)
331       : ControlScope(owner), target_(target), control_(control) {}
332 
333  protected:
Execute(Command cmd,Statement * target,Node ** value)334   bool Execute(Command cmd, Statement* target, Node** value) override {
335     if (target != target_) {
336       control_->ExitLoop(value);
337       return false;
338     }
339     switch (cmd) {
340       case CMD_BREAK:
341         control_->Break();
342         return true;
343       case CMD_CONTINUE:
344         control_->Continue();
345         return true;
346       case CMD_THROW:
347       case CMD_RETURN:
348         break;
349     }
350     return false;
351   }
352 
353  private:
354   BreakableStatement* target_;
355   LoopBuilder* control_;
356 };
357 
358 
359 // Control scope implementation for a TryCatchStatement.
360 class AstGraphBuilder::ControlScopeForCatch : public ControlScope {
361  public:
ControlScopeForCatch(AstGraphBuilder * owner,TryCatchStatement * stmt,TryCatchBuilder * control)362   ControlScopeForCatch(AstGraphBuilder* owner, TryCatchStatement* stmt,
363                        TryCatchBuilder* control)
364       : ControlScope(owner), control_(control) {
365     builder()->try_nesting_level_++;  // Increment nesting.
366   }
~ControlScopeForCatch()367   ~ControlScopeForCatch() {
368     builder()->try_nesting_level_--;  // Decrement nesting.
369   }
370 
371  protected:
Execute(Command cmd,Statement * target,Node ** value)372   bool Execute(Command cmd, Statement* target, Node** value) override {
373     switch (cmd) {
374       case CMD_THROW:
375         control_->Throw(*value);
376         return true;
377       case CMD_BREAK:
378       case CMD_CONTINUE:
379       case CMD_RETURN:
380         break;
381     }
382     return false;
383   }
384 
385  private:
386   TryCatchBuilder* control_;
387 };
388 
389 
390 // Control scope implementation for a TryFinallyStatement.
391 class AstGraphBuilder::ControlScopeForFinally : public ControlScope {
392  public:
ControlScopeForFinally(AstGraphBuilder * owner,TryFinallyStatement * stmt,DeferredCommands * commands,TryFinallyBuilder * control)393   ControlScopeForFinally(AstGraphBuilder* owner, TryFinallyStatement* stmt,
394                          DeferredCommands* commands, TryFinallyBuilder* control)
395       : ControlScope(owner), commands_(commands), control_(control) {
396     builder()->try_nesting_level_++;  // Increment nesting.
397   }
~ControlScopeForFinally()398   ~ControlScopeForFinally() {
399     builder()->try_nesting_level_--;  // Decrement nesting.
400   }
401 
402  protected:
Execute(Command cmd,Statement * target,Node ** value)403   bool Execute(Command cmd, Statement* target, Node** value) override {
404     Node* token = commands_->RecordCommand(cmd, target, *value);
405     control_->LeaveTry(token, *value);
406     return true;
407   }
408 
409  private:
410   DeferredCommands* commands_;
411   TryFinallyBuilder* control_;
412 };
413 
AstGraphBuilder(Zone * local_zone,CompilationInfo * info,JSGraph * jsgraph,float invocation_frequency,LoopAssignmentAnalysis * loop,TypeHintAnalysis * type_hint_analysis)414 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
415                                  JSGraph* jsgraph, float invocation_frequency,
416                                  LoopAssignmentAnalysis* loop,
417                                  TypeHintAnalysis* type_hint_analysis)
418     : isolate_(info->isolate()),
419       local_zone_(local_zone),
420       info_(info),
421       jsgraph_(jsgraph),
422       invocation_frequency_(invocation_frequency),
423       environment_(nullptr),
424       ast_context_(nullptr),
425       globals_(0, local_zone),
426       execution_control_(nullptr),
427       execution_context_(nullptr),
428       try_nesting_level_(0),
429       input_buffer_size_(0),
430       input_buffer_(nullptr),
431       exit_controls_(local_zone),
432       loop_assignment_analysis_(loop),
433       type_hint_analysis_(type_hint_analysis),
434       state_values_cache_(jsgraph),
435       liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()),
436                          false, local_zone),
437       frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
438           FrameStateType::kJavaScriptFunction, info->num_parameters() + 1,
439           info->scope()->num_stack_slots(), info->shared_info())) {
440   InitializeAstVisitor(info->isolate());
441 }
442 
443 
GetFunctionClosureForContext()444 Node* AstGraphBuilder::GetFunctionClosureForContext() {
445   DeclarationScope* closure_scope = current_scope()->GetClosureScope();
446   if (closure_scope->is_script_scope() ||
447       closure_scope->is_module_scope()) {
448     // Contexts nested in the native context have a canonical empty function as
449     // their closure, not the anonymous closure containing the global code.
450     return BuildLoadNativeContextField(Context::CLOSURE_INDEX);
451   } else if (closure_scope->is_eval_scope()) {
452     // Contexts nested inside eval code have the same closure as the context
453     // calling eval, not the anonymous closure containing the eval code.
454     const Operator* op =
455         javascript()->LoadContext(0, Context::CLOSURE_INDEX, false);
456     return NewNode(op, current_context());
457   } else {
458     DCHECK(closure_scope->is_function_scope());
459     return GetFunctionClosure();
460   }
461 }
462 
463 
GetFunctionClosure()464 Node* AstGraphBuilder::GetFunctionClosure() {
465   if (!function_closure_.is_set()) {
466     int index = Linkage::kJSCallClosureParamIndex;
467     const Operator* op = common()->Parameter(index, "%closure");
468     Node* node = NewNode(op, graph()->start());
469     function_closure_.set(node);
470   }
471   return function_closure_.get();
472 }
473 
474 
GetFunctionContext()475 Node* AstGraphBuilder::GetFunctionContext() {
476   if (!function_context_.is_set()) {
477     int params = info()->num_parameters_including_this();
478     int index = Linkage::GetJSCallContextParamIndex(params);
479     const Operator* op = common()->Parameter(index, "%context");
480     Node* node = NewNode(op, graph()->start());
481     function_context_.set(node);
482   }
483   return function_context_.get();
484 }
485 
486 
GetNewTarget()487 Node* AstGraphBuilder::GetNewTarget() {
488   if (!new_target_.is_set()) {
489     int params = info()->num_parameters_including_this();
490     int index = Linkage::GetJSCallNewTargetParamIndex(params);
491     const Operator* op = common()->Parameter(index, "%new.target");
492     Node* node = NewNode(op, graph()->start());
493     new_target_.set(node);
494   }
495   return new_target_.get();
496 }
497 
GetEmptyFrameState()498 Node* AstGraphBuilder::GetEmptyFrameState() {
499   if (!empty_frame_state_.is_set()) {
500     const Operator* op = common()->FrameState(
501         BailoutId::None(), OutputFrameStateCombine::Ignore(), nullptr);
502     Node* node = graph()->NewNode(
503         op, jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
504         jsgraph()->EmptyStateValues(), jsgraph()->NoContextConstant(),
505         jsgraph()->UndefinedConstant(), graph()->start());
506     empty_frame_state_.set(node);
507   }
508   return empty_frame_state_.get();
509 }
510 
CreateGraph(bool stack_check)511 bool AstGraphBuilder::CreateGraph(bool stack_check) {
512   DeclarationScope* scope = info()->scope();
513   DCHECK_NOT_NULL(graph());
514 
515   // Set up the basic structure of the graph. Outputs for {Start} are the formal
516   // parameters (including the receiver) plus new target, number of arguments,
517   // context and closure.
518   int actual_parameter_count = info()->num_parameters_including_this() + 4;
519   graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
520 
521   // Initialize the top-level environment.
522   Environment env(this, scope, graph()->start());
523   set_environment(&env);
524 
525   if (info()->is_osr()) {
526     // Use OSR normal entry as the start of the top-level environment.
527     // It will be replaced with {Dead} after typing and optimizations.
528     NewNode(common()->OsrNormalEntry());
529   }
530 
531   // Initialize the incoming context.
532   ContextScope incoming(this, scope, GetFunctionContext());
533 
534   // Initialize control scope.
535   ControlScope control(this);
536 
537   // TODO(mstarzinger): For now we cannot assume that the {this} parameter is
538   // not {the_hole}, because for derived classes {this} has a TDZ and the
539   // JSConstructStubForDerived magically passes {the_hole} as a receiver.
540   if (scope->has_this_declaration() && scope->receiver()->mode() == CONST) {
541     env.RawParameterBind(0, jsgraph()->TheHoleConstant());
542   }
543 
544   if (scope->NeedsContext()) {
545     // Push a new inner context scope for the current activation.
546     Node* inner_context = BuildLocalActivationContext(GetFunctionContext());
547     ContextScope top_context(this, scope, inner_context);
548     CreateGraphBody(stack_check);
549   } else {
550     // Simply use the outer function context in building the graph.
551     CreateGraphBody(stack_check);
552   }
553 
554   // Finish the basic structure of the graph.
555   DCHECK_NE(0u, exit_controls_.size());
556   int const input_count = static_cast<int>(exit_controls_.size());
557   Node** const inputs = &exit_controls_.front();
558   Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
559   graph()->SetEnd(end);
560 
561   // Compute local variable liveness information and use it to relax
562   // frame states.
563   ClearNonLiveSlotsInFrameStates();
564 
565   // Failures indicated by stack overflow.
566   return !HasStackOverflow();
567 }
568 
569 
CreateGraphBody(bool stack_check)570 void AstGraphBuilder::CreateGraphBody(bool stack_check) {
571   DeclarationScope* scope = info()->scope();
572 
573   // Build the arguments object if it is used.
574   BuildArgumentsObject(scope->arguments());
575 
576   // Build rest arguments array if it is used.
577   Variable* rest_parameter = scope->rest_parameter();
578   BuildRestArgumentsArray(rest_parameter);
579 
580   // Build assignment to {.this_function} variable if it is used.
581   BuildThisFunctionVariable(scope->this_function_var());
582 
583   // Build assignment to {new.target} variable if it is used.
584   BuildNewTargetVariable(scope->new_target_var());
585 
586   // Emit tracing call if requested to do so.
587   if (FLAG_trace) {
588     NewNode(javascript()->CallRuntime(Runtime::kTraceEnter));
589   }
590 
591   // Visit declarations within the function scope.
592   VisitDeclarations(scope->declarations());
593 
594   // Build a stack-check before the body.
595   if (stack_check) {
596     Node* node = NewNode(javascript()->StackCheck());
597     PrepareFrameState(node, BailoutId::FunctionEntry());
598   }
599 
600   // Visit statements in the function body.
601   VisitStatements(info()->literal()->body());
602 
603   // Return 'undefined' in case we can fall off the end.
604   BuildReturn(jsgraph()->UndefinedConstant());
605 }
606 
607 
ClearNonLiveSlotsInFrameStates()608 void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
609   if (!FLAG_analyze_environment_liveness ||
610       !info()->is_deoptimization_enabled()) {
611     return;
612   }
613 
614   NonLiveFrameStateSlotReplacer replacer(
615       &state_values_cache_, jsgraph()->OptimizedOutConstant(),
616       liveness_analyzer()->local_count(), false, local_zone());
617   Variable* arguments = info()->scope()->arguments();
618   if (arguments != nullptr && arguments->IsStackAllocated()) {
619     replacer.MarkPermanentlyLive(arguments->index());
620   }
621   liveness_analyzer()->Run(&replacer);
622   if (FLAG_trace_environment_liveness) {
623     OFStream os(stdout);
624     liveness_analyzer()->Print(os);
625   }
626 }
627 
628 
629 // Gets the bailout id just before reading a variable proxy, but only for
630 // unallocated variables.
BeforeId(VariableProxy * proxy)631 static BailoutId BeforeId(VariableProxy* proxy) {
632   return proxy->var()->IsUnallocated() ? proxy->BeforeId() : BailoutId::None();
633 }
634 
GetDebugParameterName(Zone * zone,DeclarationScope * scope,int index)635 static const char* GetDebugParameterName(Zone* zone, DeclarationScope* scope,
636                                          int index) {
637 #if DEBUG
638   const AstRawString* name = scope->parameter(index)->raw_name();
639   if (name && name->length() > 0) {
640     char* data = zone->NewArray<char>(name->length() + 1);
641     data[name->length()] = 0;
642     memcpy(data, name->raw_data(), name->length());
643     return data;
644   }
645 #endif
646   return nullptr;
647 }
648 
Environment(AstGraphBuilder * builder,DeclarationScope * scope,Node * control_dependency)649 AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
650                                           DeclarationScope* scope,
651                                           Node* control_dependency)
652     : builder_(builder),
653       parameters_count_(scope->num_parameters() + 1),
654       locals_count_(scope->num_stack_slots()),
655       liveness_block_(IsLivenessAnalysisEnabled()
656                           ? builder_->liveness_analyzer()->NewBlock()
657                           : nullptr),
658       values_(builder_->local_zone()),
659       contexts_(builder_->local_zone()),
660       control_dependency_(control_dependency),
661       effect_dependency_(control_dependency),
662       parameters_node_(nullptr),
663       locals_node_(nullptr),
664       stack_node_(nullptr) {
665   DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
666 
667   // Bind the receiver variable.
668   int param_num = 0;
669   if (builder->info()->is_this_defined()) {
670     const Operator* op = common()->Parameter(param_num++, "%this");
671     Node* receiver = builder->graph()->NewNode(op, builder->graph()->start());
672     values()->push_back(receiver);
673   } else {
674     values()->push_back(builder->jsgraph()->UndefinedConstant());
675   }
676 
677   // Bind all parameter variables. The parameter indices are shifted by 1
678   // (receiver is variable index -1 but {Parameter} node index 0 and located at
679   // index 0 in the environment).
680   for (int i = 0; i < scope->num_parameters(); ++i) {
681     const char* debug_name = GetDebugParameterName(graph()->zone(), scope, i);
682     const Operator* op = common()->Parameter(param_num++, debug_name);
683     Node* parameter = builder->graph()->NewNode(op, builder->graph()->start());
684     values()->push_back(parameter);
685   }
686 
687   // Bind all local variables to undefined.
688   Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
689   values()->insert(values()->end(), locals_count(), undefined_constant);
690 }
691 
692 
Environment(AstGraphBuilder::Environment * copy,LivenessAnalyzerBlock * liveness_block)693 AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy,
694                                           LivenessAnalyzerBlock* liveness_block)
695     : builder_(copy->builder_),
696       parameters_count_(copy->parameters_count_),
697       locals_count_(copy->locals_count_),
698       liveness_block_(liveness_block),
699       values_(copy->zone()),
700       contexts_(copy->zone()),
701       control_dependency_(copy->control_dependency_),
702       effect_dependency_(copy->effect_dependency_),
703       parameters_node_(copy->parameters_node_),
704       locals_node_(copy->locals_node_),
705       stack_node_(copy->stack_node_) {
706   const size_t kStackEstimate = 7;  // optimum from experimentation!
707   values_.reserve(copy->values_.size() + kStackEstimate);
708   values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end());
709   contexts_.reserve(copy->contexts_.size());
710   contexts_.insert(contexts_.begin(), copy->contexts_.begin(),
711                    copy->contexts_.end());
712 }
713 
714 
Bind(Variable * variable,Node * node)715 void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) {
716   DCHECK(variable->IsStackAllocated());
717   if (variable->IsParameter()) {
718     // The parameter indices are shifted by 1 (receiver is variable
719     // index -1 but located at index 0 in the environment).
720     values()->at(variable->index() + 1) = node;
721   } else {
722     DCHECK(variable->IsStackLocal());
723     values()->at(variable->index() + parameters_count_) = node;
724     DCHECK(IsLivenessBlockConsistent());
725     if (liveness_block() != nullptr) {
726       liveness_block()->Bind(variable->index());
727     }
728   }
729 }
730 
731 
Lookup(Variable * variable)732 Node* AstGraphBuilder::Environment::Lookup(Variable* variable) {
733   DCHECK(variable->IsStackAllocated());
734   if (variable->IsParameter()) {
735     // The parameter indices are shifted by 1 (receiver is variable
736     // index -1 but located at index 0 in the environment).
737     return values()->at(variable->index() + 1);
738   } else {
739     DCHECK(variable->IsStackLocal());
740     DCHECK(IsLivenessBlockConsistent());
741     if (liveness_block() != nullptr) {
742       liveness_block()->Lookup(variable->index());
743     }
744     return values()->at(variable->index() + parameters_count_);
745   }
746 }
747 
748 
MarkAllLocalsLive()749 void AstGraphBuilder::Environment::MarkAllLocalsLive() {
750   DCHECK(IsLivenessBlockConsistent());
751   if (liveness_block() != nullptr) {
752     for (int i = 0; i < locals_count_; i++) {
753       liveness_block()->Lookup(i);
754     }
755   }
756 }
757 
758 
RawParameterBind(int index,Node * node)759 void AstGraphBuilder::Environment::RawParameterBind(int index, Node* node) {
760   DCHECK_LT(index, parameters_count());
761   values()->at(index) = node;
762 }
763 
764 
RawParameterLookup(int index)765 Node* AstGraphBuilder::Environment::RawParameterLookup(int index) {
766   DCHECK_LT(index, parameters_count());
767   return values()->at(index);
768 }
769 
770 
771 AstGraphBuilder::Environment*
CopyForConditional()772 AstGraphBuilder::Environment::CopyForConditional() {
773   LivenessAnalyzerBlock* copy_liveness_block = nullptr;
774   if (liveness_block() != nullptr) {
775     copy_liveness_block =
776         builder_->liveness_analyzer()->NewBlock(liveness_block());
777     liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
778   }
779   return new (zone()) Environment(this, copy_liveness_block);
780 }
781 
782 
783 AstGraphBuilder::Environment*
CopyAsUnreachable()784 AstGraphBuilder::Environment::CopyAsUnreachable() {
785   Environment* env = new (zone()) Environment(this, nullptr);
786   env->MarkAsUnreachable();
787   return env;
788 }
789 
CopyForOsrEntry()790 AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForOsrEntry() {
791   LivenessAnalyzerBlock* copy_block =
792       liveness_block() == nullptr ? nullptr
793                                   : builder_->liveness_analyzer()->NewBlock();
794   return new (zone()) Environment(this, copy_block);
795 }
796 
797 AstGraphBuilder::Environment*
CopyAndShareLiveness()798 AstGraphBuilder::Environment::CopyAndShareLiveness() {
799   if (liveness_block() != nullptr) {
800     // Finish the current liveness block before copying.
801     liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
802   }
803   Environment* env = new (zone()) Environment(this, liveness_block());
804   return env;
805 }
806 
807 
CopyForLoop(BitVector * assigned,bool is_osr)808 AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
809     BitVector* assigned, bool is_osr) {
810   PrepareForLoop(assigned);
811   Environment* loop = CopyAndShareLiveness();
812   if (is_osr) {
813     // Create and merge the OSR entry if necessary.
814     Environment* osr_env = CopyForOsrEntry();
815     osr_env->PrepareForOsrEntry();
816     loop->Merge(osr_env);
817   }
818   return loop;
819 }
820 
821 
UpdateStateValues(Node ** state_values,int offset,int count)822 void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
823                                                      int offset, int count) {
824   bool should_update = false;
825   Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
826   if (*state_values == nullptr || (*state_values)->InputCount() != count) {
827     should_update = true;
828   } else {
829     DCHECK(static_cast<size_t>(offset + count) <= values()->size());
830     for (int i = 0; i < count; i++) {
831       if ((*state_values)->InputAt(i) != env_values[i]) {
832         should_update = true;
833         break;
834       }
835     }
836   }
837   if (should_update) {
838     const Operator* op = common()->StateValues(count);
839     (*state_values) = graph()->NewNode(op, count, env_values);
840   }
841 }
842 
843 
Checkpoint(BailoutId ast_id,OutputFrameStateCombine combine,bool owner_has_exception)844 Node* AstGraphBuilder::Environment::Checkpoint(BailoutId ast_id,
845                                                OutputFrameStateCombine combine,
846                                                bool owner_has_exception) {
847   if (!builder()->info()->is_deoptimization_enabled()) {
848     return builder()->GetEmptyFrameState();
849   }
850 
851   UpdateStateValues(&parameters_node_, 0, parameters_count());
852   UpdateStateValues(&locals_node_, parameters_count(), locals_count());
853   UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
854                     stack_height());
855 
856   const Operator* op = common()->FrameState(
857       ast_id, combine, builder()->frame_state_function_info());
858 
859   Node* result = graph()->NewNode(op, parameters_node_, locals_node_,
860                                   stack_node_, builder()->current_context(),
861                                   builder()->GetFunctionClosure(),
862                                   builder()->graph()->start());
863 
864   DCHECK(IsLivenessBlockConsistent());
865   if (liveness_block() != nullptr) {
866     // If the owning node has an exception, register the checkpoint to the
867     // predecessor so that the checkpoint is used for both the normal and the
868     // exceptional paths. Yes, this is a terrible hack and we might want
869     // to use an explicit frame state for the exceptional path.
870     if (owner_has_exception) {
871       liveness_block()->GetPredecessor()->Checkpoint(result);
872     } else {
873       liveness_block()->Checkpoint(result);
874     }
875   }
876   return result;
877 }
878 
PrepareForLoopExit(Node * loop,BitVector * assigned_variables)879 void AstGraphBuilder::Environment::PrepareForLoopExit(
880     Node* loop, BitVector* assigned_variables) {
881   if (IsMarkedAsUnreachable()) return;
882 
883   DCHECK_EQ(loop->opcode(), IrOpcode::kLoop);
884 
885   Node* control = GetControlDependency();
886 
887   // Create the loop exit node.
888   Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop);
889   UpdateControlDependency(loop_exit);
890 
891   // Rename the environmnent values.
892   for (size_t i = 0; i < values()->size(); i++) {
893     if (assigned_variables == nullptr ||
894         static_cast<int>(i) >= assigned_variables->length() ||
895         assigned_variables->Contains(static_cast<int>(i))) {
896       Node* rename = graph()->NewNode(common()->LoopExitValue(), (*values())[i],
897                                       loop_exit);
898       (*values())[i] = rename;
899     }
900   }
901 
902   // Rename the effect.
903   Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(),
904                                          GetEffectDependency(), loop_exit);
905   UpdateEffectDependency(effect_rename);
906 }
907 
IsLivenessAnalysisEnabled()908 bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() {
909   return FLAG_analyze_environment_liveness &&
910          builder()->info()->is_deoptimization_enabled();
911 }
912 
913 
IsLivenessBlockConsistent()914 bool AstGraphBuilder::Environment::IsLivenessBlockConsistent() {
915   return (!IsLivenessAnalysisEnabled() || IsMarkedAsUnreachable()) ==
916          (liveness_block() == nullptr);
917 }
918 
919 
AstContext(AstGraphBuilder * own,Expression::Context kind)920 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
921                                         Expression::Context kind)
922     : kind_(kind), owner_(own), outer_(own->ast_context()) {
923   owner()->set_ast_context(this);  // Push.
924 #ifdef DEBUG
925   original_height_ = environment()->stack_height();
926 #endif
927 }
928 
929 
~AstContext()930 AstGraphBuilder::AstContext::~AstContext() {
931   owner()->set_ast_context(outer_);  // Pop.
932 }
933 
934 
~AstEffectContext()935 AstGraphBuilder::AstEffectContext::~AstEffectContext() {
936   DCHECK(environment()->stack_height() == original_height_);
937 }
938 
939 
~AstValueContext()940 AstGraphBuilder::AstValueContext::~AstValueContext() {
941   DCHECK(environment()->stack_height() == original_height_ + 1);
942 }
943 
944 
~AstTestContext()945 AstGraphBuilder::AstTestContext::~AstTestContext() {
946   DCHECK(environment()->stack_height() == original_height_ + 1);
947 }
948 
ProduceValue(Expression * expr,Node * value)949 void AstGraphBuilder::AstEffectContext::ProduceValue(Expression* expr,
950                                                      Node* value) {
951   // The value is ignored.
952   owner()->PrepareEagerCheckpoint(expr->id());
953 }
954 
ProduceValue(Expression * expr,Node * value)955 void AstGraphBuilder::AstValueContext::ProduceValue(Expression* expr,
956                                                     Node* value) {
957   environment()->Push(value);
958   owner()->PrepareEagerCheckpoint(expr->id());
959 }
960 
ProduceValue(Expression * expr,Node * value)961 void AstGraphBuilder::AstTestContext::ProduceValue(Expression* expr,
962                                                    Node* value) {
963   environment()->Push(owner()->BuildToBoolean(value, feedback_id_));
964   owner()->PrepareEagerCheckpoint(expr->id());
965 }
966 
967 
ConsumeValue()968 Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return nullptr; }
969 
970 
ConsumeValue()971 Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
972   return environment()->Pop();
973 }
974 
975 
ConsumeValue()976 Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
977   return environment()->Pop();
978 }
979 
980 
current_scope() const981 Scope* AstGraphBuilder::current_scope() const {
982   return execution_context_->scope();
983 }
984 
985 
current_context() const986 Node* AstGraphBuilder::current_context() const {
987   return environment()->Context();
988 }
989 
990 
PerformCommand(Command command,Statement * target,Node * value)991 void AstGraphBuilder::ControlScope::PerformCommand(Command command,
992                                                    Statement* target,
993                                                    Node* value) {
994   Environment* env = environment()->CopyAsUnreachable();
995   ControlScope* current = this;
996   while (current != nullptr) {
997     environment()->TrimStack(current->stack_height());
998     environment()->TrimContextChain(current->context_length());
999     if (current->Execute(command, target, &value)) break;
1000     current = current->outer_;
1001   }
1002   builder()->set_environment(env);
1003   DCHECK_NOT_NULL(current);  // Always handled (unless stack is malformed).
1004 }
1005 
1006 
BreakTo(BreakableStatement * stmt)1007 void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) {
1008   PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant());
1009 }
1010 
1011 
ContinueTo(BreakableStatement * stmt)1012 void AstGraphBuilder::ControlScope::ContinueTo(BreakableStatement* stmt) {
1013   PerformCommand(CMD_CONTINUE, stmt, builder()->jsgraph()->TheHoleConstant());
1014 }
1015 
1016 
ReturnValue(Node * return_value)1017 void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) {
1018   PerformCommand(CMD_RETURN, nullptr, return_value);
1019 }
1020 
1021 
ThrowValue(Node * exception_value)1022 void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) {
1023   PerformCommand(CMD_THROW, nullptr, exception_value);
1024 }
1025 
1026 
VisitForValueOrNull(Expression * expr)1027 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
1028   if (expr == nullptr) {
1029     return environment()->Push(jsgraph()->NullConstant());
1030   }
1031   VisitForValue(expr);
1032 }
1033 
1034 
VisitForValueOrTheHole(Expression * expr)1035 void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) {
1036   if (expr == nullptr) {
1037     return environment()->Push(jsgraph()->TheHoleConstant());
1038   }
1039   VisitForValue(expr);
1040 }
1041 
1042 
VisitForValues(ZoneList<Expression * > * exprs)1043 void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
1044   for (int i = 0; i < exprs->length(); ++i) {
1045     VisitForValue(exprs->at(i));
1046   }
1047 }
1048 
1049 
VisitForValue(Expression * expr)1050 void AstGraphBuilder::VisitForValue(Expression* expr) {
1051   AstValueContext for_value(this);
1052   if (!CheckStackOverflow()) {
1053     VisitNoStackOverflowCheck(expr);
1054   } else {
1055     ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
1056   }
1057 }
1058 
1059 
VisitForEffect(Expression * expr)1060 void AstGraphBuilder::VisitForEffect(Expression* expr) {
1061   AstEffectContext for_effect(this);
1062   if (!CheckStackOverflow()) {
1063     VisitNoStackOverflowCheck(expr);
1064   } else {
1065     ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
1066   }
1067 }
1068 
1069 
VisitForTest(Expression * expr)1070 void AstGraphBuilder::VisitForTest(Expression* expr) {
1071   AstTestContext for_condition(this, expr->test_id());
1072   if (!CheckStackOverflow()) {
1073     VisitNoStackOverflowCheck(expr);
1074   } else {
1075     ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
1076   }
1077 }
1078 
1079 
Visit(Expression * expr)1080 void AstGraphBuilder::Visit(Expression* expr) {
1081   // Reuses enclosing AstContext.
1082   if (!CheckStackOverflow()) {
1083     VisitNoStackOverflowCheck(expr);
1084   } else {
1085     ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
1086   }
1087 }
1088 
1089 
VisitVariableDeclaration(VariableDeclaration * decl)1090 void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
1091   Variable* variable = decl->proxy()->var();
1092   switch (variable->location()) {
1093     case VariableLocation::UNALLOCATED: {
1094       DCHECK(!variable->binding_needs_init());
1095       FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
1096       DCHECK(!slot.IsInvalid());
1097       globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
1098       globals()->push_back(isolate()->factory()->undefined_value());
1099       break;
1100     }
1101     case VariableLocation::PARAMETER:
1102     case VariableLocation::LOCAL:
1103       if (variable->binding_needs_init()) {
1104         Node* value = jsgraph()->TheHoleConstant();
1105         environment()->Bind(variable, value);
1106       }
1107       break;
1108     case VariableLocation::CONTEXT:
1109       if (variable->binding_needs_init()) {
1110         Node* value = jsgraph()->TheHoleConstant();
1111         const Operator* op = javascript()->StoreContext(0, variable->index());
1112         NewNode(op, current_context(), value);
1113       }
1114       break;
1115     case VariableLocation::LOOKUP: {
1116       DCHECK(!variable->binding_needs_init());
1117       Node* name = jsgraph()->Constant(variable->name());
1118       const Operator* op = javascript()->CallRuntime(Runtime::kDeclareEvalVar);
1119       Node* store = NewNode(op, name);
1120       PrepareFrameState(store, decl->proxy()->id());
1121       break;
1122     }
1123     case VariableLocation::MODULE:
1124       UNREACHABLE();
1125   }
1126 }
1127 
1128 
VisitFunctionDeclaration(FunctionDeclaration * decl)1129 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
1130   Variable* variable = decl->proxy()->var();
1131   switch (variable->location()) {
1132     case VariableLocation::UNALLOCATED: {
1133       Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
1134           decl->fun(), info()->script(), info());
1135       // Check for stack-overflow exception.
1136       if (function.is_null()) return SetStackOverflow();
1137       FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
1138       DCHECK(!slot.IsInvalid());
1139       globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
1140       globals()->push_back(function);
1141       break;
1142     }
1143     case VariableLocation::PARAMETER:
1144     case VariableLocation::LOCAL: {
1145       VisitForValue(decl->fun());
1146       Node* value = environment()->Pop();
1147       environment()->Bind(variable, value);
1148       break;
1149     }
1150     case VariableLocation::CONTEXT: {
1151       VisitForValue(decl->fun());
1152       Node* value = environment()->Pop();
1153       const Operator* op = javascript()->StoreContext(0, variable->index());
1154       NewNode(op, current_context(), value);
1155       break;
1156     }
1157     case VariableLocation::LOOKUP: {
1158       VisitForValue(decl->fun());
1159       Node* value = environment()->Pop();
1160       Node* name = jsgraph()->Constant(variable->name());
1161       const Operator* op =
1162           javascript()->CallRuntime(Runtime::kDeclareEvalFunction);
1163       Node* store = NewNode(op, name, value);
1164       PrepareFrameState(store, decl->proxy()->id());
1165       break;
1166     }
1167     case VariableLocation::MODULE:
1168       UNREACHABLE();
1169   }
1170 }
1171 
1172 
VisitBlock(Block * stmt)1173 void AstGraphBuilder::VisitBlock(Block* stmt) {
1174   BlockBuilder block(this);
1175   ControlScopeForBreakable scope(this, stmt, &block);
1176   if (stmt->labels() != nullptr) block.BeginBlock();
1177   if (stmt->scope() == nullptr) {
1178     // Visit statements in the same scope, no declarations.
1179     VisitStatements(stmt->statements());
1180   } else {
1181     // Visit declarations and statements in a block scope.
1182     if (stmt->scope()->NeedsContext()) {
1183       Node* context = BuildLocalBlockContext(stmt->scope());
1184       ContextScope scope(this, stmt->scope(), context);
1185       VisitDeclarations(stmt->scope()->declarations());
1186       VisitStatements(stmt->statements());
1187     } else {
1188       VisitDeclarations(stmt->scope()->declarations());
1189       VisitStatements(stmt->statements());
1190     }
1191   }
1192   if (stmt->labels() != nullptr) block.EndBlock();
1193 }
1194 
1195 
VisitExpressionStatement(ExpressionStatement * stmt)1196 void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
1197   VisitForEffect(stmt->expression());
1198 }
1199 
1200 
VisitEmptyStatement(EmptyStatement * stmt)1201 void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
1202   // Do nothing.
1203 }
1204 
1205 
VisitSloppyBlockFunctionStatement(SloppyBlockFunctionStatement * stmt)1206 void AstGraphBuilder::VisitSloppyBlockFunctionStatement(
1207     SloppyBlockFunctionStatement* stmt) {
1208   Visit(stmt->statement());
1209 }
1210 
1211 
VisitIfStatement(IfStatement * stmt)1212 void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
1213   IfBuilder compare_if(this);
1214   VisitForTest(stmt->condition());
1215   Node* condition = environment()->Pop();
1216   compare_if.If(condition);
1217   compare_if.Then();
1218   Visit(stmt->then_statement());
1219   compare_if.Else();
1220   Visit(stmt->else_statement());
1221   compare_if.End();
1222 }
1223 
1224 
VisitContinueStatement(ContinueStatement * stmt)1225 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
1226   execution_control()->ContinueTo(stmt->target());
1227 }
1228 
1229 
VisitBreakStatement(BreakStatement * stmt)1230 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
1231   execution_control()->BreakTo(stmt->target());
1232 }
1233 
1234 
VisitReturnStatement(ReturnStatement * stmt)1235 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
1236   VisitForValue(stmt->expression());
1237   Node* result = environment()->Pop();
1238   execution_control()->ReturnValue(result);
1239 }
1240 
1241 
VisitWithStatement(WithStatement * stmt)1242 void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
1243   VisitForValue(stmt->expression());
1244   Node* value = environment()->Pop();
1245   Node* object = BuildToObject(value, stmt->ToObjectId());
1246   Handle<ScopeInfo> scope_info = stmt->scope()->scope_info();
1247   const Operator* op = javascript()->CreateWithContext(scope_info);
1248   Node* context = NewNode(op, object, GetFunctionClosureForContext());
1249   PrepareFrameState(context, stmt->EntryId());
1250   VisitInScope(stmt->statement(), stmt->scope(), context);
1251 }
1252 
1253 
VisitSwitchStatement(SwitchStatement * stmt)1254 void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
1255   ZoneList<CaseClause*>* clauses = stmt->cases();
1256   SwitchBuilder compare_switch(this, clauses->length());
1257   ControlScopeForBreakable scope(this, stmt, &compare_switch);
1258   compare_switch.BeginSwitch();
1259   int default_index = -1;
1260 
1261   // Keep the switch value on the stack until a case matches.
1262   VisitForValue(stmt->tag());
1263 
1264   // Iterate over all cases and create nodes for label comparison.
1265   for (int i = 0; i < clauses->length(); i++) {
1266     CaseClause* clause = clauses->at(i);
1267 
1268     // The default is not a test, remember index.
1269     if (clause->is_default()) {
1270       default_index = i;
1271       continue;
1272     }
1273 
1274     // Create nodes to perform label comparison as if via '==='. The switch
1275     // value is still on the operand stack while the label is evaluated.
1276     VisitForValue(clause->label());
1277     Node* label = environment()->Pop();
1278     Node* tag = environment()->Top();
1279 
1280     CompareOperationHint hint;
1281     if (!type_hint_analysis_ ||
1282         !type_hint_analysis_->GetCompareOperationHint(clause->CompareId(),
1283                                                       &hint)) {
1284       hint = CompareOperationHint::kAny;
1285     }
1286 
1287     const Operator* op = javascript()->StrictEqual(hint);
1288     Node* condition = NewNode(op, tag, label);
1289     compare_switch.BeginLabel(i, condition);
1290 
1291     // Discard the switch value at label match.
1292     environment()->Pop();
1293     compare_switch.EndLabel();
1294   }
1295 
1296   // Discard the switch value and mark the default case.
1297   environment()->Pop();
1298   if (default_index >= 0) {
1299     compare_switch.DefaultAt(default_index);
1300   }
1301 
1302   // Iterate over all cases and create nodes for case bodies.
1303   for (int i = 0; i < clauses->length(); i++) {
1304     CaseClause* clause = clauses->at(i);
1305     compare_switch.BeginCase(i);
1306     VisitStatements(clause->statements());
1307     compare_switch.EndCase();
1308   }
1309 
1310   compare_switch.EndSwitch();
1311 }
1312 
1313 
VisitDoWhileStatement(DoWhileStatement * stmt)1314 void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1315   LoopBuilder while_loop(this);
1316   while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1317   VisitIterationBody(stmt, &while_loop, stmt->StackCheckId());
1318   while_loop.EndBody();
1319   VisitForTest(stmt->cond());
1320   Node* condition = environment()->Pop();
1321   while_loop.BreakUnless(condition);
1322   while_loop.EndLoop();
1323 }
1324 
1325 
VisitWhileStatement(WhileStatement * stmt)1326 void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
1327   LoopBuilder while_loop(this);
1328   while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1329   VisitForTest(stmt->cond());
1330   Node* condition = environment()->Pop();
1331   while_loop.BreakUnless(condition);
1332   VisitIterationBody(stmt, &while_loop, stmt->StackCheckId());
1333   while_loop.EndBody();
1334   while_loop.EndLoop();
1335 }
1336 
1337 
VisitForStatement(ForStatement * stmt)1338 void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
1339   LoopBuilder for_loop(this);
1340   VisitIfNotNull(stmt->init());
1341   for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1342   if (stmt->cond() != nullptr) {
1343     VisitForTest(stmt->cond());
1344     Node* condition = environment()->Pop();
1345     for_loop.BreakUnless(condition);
1346   } else {
1347     for_loop.BreakUnless(jsgraph()->TrueConstant());
1348   }
1349   VisitIterationBody(stmt, &for_loop, stmt->StackCheckId());
1350   for_loop.EndBody();
1351   VisitIfNotNull(stmt->next());
1352   for_loop.EndLoop();
1353 }
1354 
1355 
VisitForInStatement(ForInStatement * stmt)1356 void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
1357   VisitForValue(stmt->subject());
1358   Node* object = environment()->Pop();
1359   BlockBuilder for_block(this);
1360   for_block.BeginBlock();
1361   // Check for null or undefined before entering loop.
1362   Node* is_null_cond =
1363       NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), object,
1364               jsgraph()->NullConstant());
1365   for_block.BreakWhen(is_null_cond, BranchHint::kFalse);
1366   Node* is_undefined_cond =
1367       NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), object,
1368               jsgraph()->UndefinedConstant());
1369   for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse);
1370   {
1371     // Convert object to jsobject.
1372     object = BuildToObject(object, stmt->ToObjectId());
1373     environment()->Push(object);
1374 
1375     // Prepare for-in cache.
1376     Node* prepare = NewNode(javascript()->ForInPrepare(), object);
1377     PrepareFrameState(prepare, stmt->PrepareId(),
1378                       OutputFrameStateCombine::Push(3));
1379     Node* cache_type = NewNode(common()->Projection(0), prepare);
1380     Node* cache_array = NewNode(common()->Projection(1), prepare);
1381     Node* cache_length = NewNode(common()->Projection(2), prepare);
1382 
1383     // Construct the rest of the environment.
1384     environment()->Push(cache_type);
1385     environment()->Push(cache_array);
1386     environment()->Push(cache_length);
1387     environment()->Push(jsgraph()->ZeroConstant());
1388 
1389     // Build the actual loop body.
1390     LoopBuilder for_loop(this);
1391     for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1392     {
1393       // These stack values are renamed in the case of OSR, so reload them
1394       // from the environment.
1395       Node* index = environment()->Peek(0);
1396       Node* cache_length = environment()->Peek(1);
1397       Node* cache_array = environment()->Peek(2);
1398       Node* cache_type = environment()->Peek(3);
1399       Node* object = environment()->Peek(4);
1400 
1401       // Check loop termination condition (we know that the {index} is always
1402       // in Smi range, so we can just set the hint on the comparison below).
1403       PrepareEagerCheckpoint(stmt->EntryId());
1404       Node* exit_cond =
1405           NewNode(javascript()->LessThan(CompareOperationHint::kSignedSmall),
1406                   index, cache_length);
1407       PrepareFrameState(exit_cond, BailoutId::None());
1408       for_loop.BreakUnless(exit_cond);
1409 
1410       // Compute the next enumerated value.
1411       Node* value = NewNode(javascript()->ForInNext(), object, cache_array,
1412                             cache_type, index);
1413       PrepareFrameState(value, stmt->FilterId(),
1414                         OutputFrameStateCombine::Push());
1415       IfBuilder test_value(this);
1416       Node* test_value_cond =
1417           NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), value,
1418                   jsgraph()->UndefinedConstant());
1419       test_value.If(test_value_cond, BranchHint::kFalse);
1420       test_value.Then();
1421       test_value.Else();
1422       {
1423         environment()->Push(value);
1424         PrepareEagerCheckpoint(stmt->FilterId());
1425         value = environment()->Pop();
1426         // Bind value and do loop body.
1427         VectorSlotPair feedback =
1428             CreateVectorSlotPair(stmt->EachFeedbackSlot());
1429         VisitForInAssignment(stmt->each(), value, feedback,
1430                              stmt->AssignmentId());
1431         VisitIterationBody(stmt, &for_loop, stmt->StackCheckId());
1432       }
1433       test_value.End();
1434       for_loop.EndBody();
1435 
1436       // Increment counter and continue (we know that the {index} is always
1437       // in Smi range, so we can just set the hint on the increment below).
1438       index = environment()->Peek(0);
1439       PrepareEagerCheckpoint(stmt->IncrementId());
1440       index = NewNode(javascript()->Add(BinaryOperationHint::kSignedSmall),
1441                       index, jsgraph()->OneConstant());
1442       PrepareFrameState(index, BailoutId::None());
1443       environment()->Poke(0, index);
1444     }
1445     for_loop.EndLoop();
1446     environment()->Drop(5);
1447   }
1448   for_block.EndBlock();
1449 }
1450 
1451 
VisitForOfStatement(ForOfStatement * stmt)1452 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
1453   LoopBuilder for_loop(this);
1454   VisitForEffect(stmt->assign_iterator());
1455   for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1456   VisitForEffect(stmt->next_result());
1457   VisitForTest(stmt->result_done());
1458   Node* condition = environment()->Pop();
1459   for_loop.BreakWhen(condition);
1460   VisitForEffect(stmt->assign_each());
1461   VisitIterationBody(stmt, &for_loop, stmt->StackCheckId());
1462   for_loop.EndBody();
1463   for_loop.EndLoop();
1464 }
1465 
1466 
VisitTryCatchStatement(TryCatchStatement * stmt)1467 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
1468   TryCatchBuilder try_control(this);
1469 
1470   // Evaluate the try-block inside a control scope. This simulates a handler
1471   // that is intercepting 'throw' control commands.
1472   try_control.BeginTry();
1473   {
1474     ControlScopeForCatch scope(this, stmt, &try_control);
1475     STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1476     environment()->Push(current_context());
1477     Visit(stmt->try_block());
1478     environment()->Pop();
1479   }
1480   try_control.EndTry();
1481 
1482   // If requested, clear message object as we enter the catch block.
1483   if (stmt->clear_pending_message()) {
1484     Node* the_hole = jsgraph()->TheHoleConstant();
1485     NewNode(javascript()->StoreMessage(), the_hole);
1486   }
1487 
1488   // Create a catch scope that binds the exception.
1489   Node* exception = try_control.GetExceptionNode();
1490   Handle<String> name = stmt->variable()->name();
1491   Handle<ScopeInfo> scope_info = stmt->scope()->scope_info();
1492   const Operator* op = javascript()->CreateCatchContext(name, scope_info);
1493   Node* context = NewNode(op, exception, GetFunctionClosureForContext());
1494 
1495   // Evaluate the catch-block.
1496   VisitInScope(stmt->catch_block(), stmt->scope(), context);
1497   try_control.EndCatch();
1498 }
1499 
1500 
VisitTryFinallyStatement(TryFinallyStatement * stmt)1501 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1502   TryFinallyBuilder try_control(this);
1503 
1504   // We keep a record of all paths that enter the finally-block to be able to
1505   // dispatch to the correct continuation point after the statements in the
1506   // finally-block have been evaluated.
1507   //
1508   // The try-finally construct can enter the finally-block in three ways:
1509   // 1. By exiting the try-block normally, falling through at the end.
1510   // 2. By exiting the try-block with a function-local control flow transfer
1511   //    (i.e. through break/continue/return statements).
1512   // 3. By exiting the try-block with a thrown exception.
1513   Node* fallthrough_result = jsgraph()->TheHoleConstant();
1514   ControlScope::DeferredCommands* commands =
1515       new (local_zone()) ControlScope::DeferredCommands(this);
1516 
1517   // Evaluate the try-block inside a control scope. This simulates a handler
1518   // that is intercepting all control commands.
1519   try_control.BeginTry();
1520   {
1521     ControlScopeForFinally scope(this, stmt, commands, &try_control);
1522     STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1523     environment()->Push(current_context());
1524     Visit(stmt->try_block());
1525     environment()->Pop();
1526   }
1527   try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result);
1528 
1529   // The result value semantics depend on how the block was entered:
1530   //  - ReturnStatement: It represents the return value being returned.
1531   //  - ThrowStatement: It represents the exception being thrown.
1532   //  - BreakStatement/ContinueStatement: Filled with the hole.
1533   //  - Falling through into finally-block: Filled with the hole.
1534   Node* result = try_control.GetResultValueNode();
1535   Node* token = try_control.GetDispatchTokenNode();
1536 
1537   // The result value, dispatch token and message is expected on the operand
1538   // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock).
1539   Node* message = NewNode(javascript()->LoadMessage());
1540   environment()->Push(token);
1541   environment()->Push(result);
1542   environment()->Push(message);
1543 
1544   // Clear message object as we enter the finally block.
1545   Node* the_hole = jsgraph()->TheHoleConstant();
1546   NewNode(javascript()->StoreMessage(), the_hole);
1547 
1548   // Evaluate the finally-block.
1549   Visit(stmt->finally_block());
1550   try_control.EndFinally();
1551 
1552   // The result value, dispatch token and message is restored from the operand
1553   // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock).
1554   message = environment()->Pop();
1555   result = environment()->Pop();
1556   token = environment()->Pop();
1557   NewNode(javascript()->StoreMessage(), message);
1558 
1559   // Dynamic dispatch after the finally-block.
1560   commands->ApplyDeferredCommands(token, result);
1561 }
1562 
1563 
VisitDebuggerStatement(DebuggerStatement * stmt)1564 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
1565   Node* node =
1566       NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
1567   PrepareFrameState(node, stmt->DebugBreakId());
1568   environment()->MarkAllLocalsLive();
1569 }
1570 
1571 
VisitFunctionLiteral(FunctionLiteral * expr)1572 void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
1573   // Find or build a shared function info.
1574   Handle<SharedFunctionInfo> shared_info =
1575       Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
1576   CHECK(!shared_info.is_null());  // TODO(mstarzinger): Set stack overflow?
1577 
1578   // Create node to instantiate a new closure.
1579   PretenureFlag pretenure = expr->pretenure() ? TENURED : NOT_TENURED;
1580   const Operator* op = javascript()->CreateClosure(shared_info, pretenure);
1581   Node* value = NewNode(op);
1582   ast_context()->ProduceValue(expr, value);
1583 }
1584 
1585 
VisitClassLiteral(ClassLiteral * expr)1586 void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
1587   VisitForValueOrTheHole(expr->extends());
1588   VisitForValue(expr->constructor());
1589 
1590   // Create node to instantiate a new class.
1591   Node* constructor = environment()->Pop();
1592   Node* extends = environment()->Pop();
1593   Node* start = jsgraph()->Constant(expr->start_position());
1594   Node* end = jsgraph()->Constant(expr->end_position());
1595   const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass);
1596   Node* literal = NewNode(opc, extends, constructor, start, end);
1597   PrepareFrameState(literal, expr->CreateLiteralId(),
1598                     OutputFrameStateCombine::Push());
1599   environment()->Push(literal);
1600 
1601   // Load the "prototype" from the constructor.
1602   PrepareEagerCheckpoint(expr->CreateLiteralId());
1603   Handle<Name> name = isolate()->factory()->prototype_string();
1604   VectorSlotPair pair = CreateVectorSlotPair(expr->PrototypeSlot());
1605   Node* prototype = BuildNamedLoad(literal, name, pair);
1606   PrepareFrameState(prototype, expr->PrototypeId(),
1607                     OutputFrameStateCombine::Push());
1608   environment()->Push(prototype);
1609 
1610   // Create nodes to store method values into the literal.
1611   for (int i = 0; i < expr->properties()->length(); i++) {
1612     ClassLiteral::Property* property = expr->properties()->at(i);
1613     environment()->Push(environment()->Peek(property->is_static() ? 1 : 0));
1614 
1615     VisitForValue(property->key());
1616     Node* name = BuildToName(environment()->Pop(), expr->GetIdForProperty(i));
1617     environment()->Push(name);
1618 
1619     // The static prototype property is read only. We handle the non computed
1620     // property name case in the parser. Since this is the only case where we
1621     // need to check for an own read only property we special case this so we do
1622     // not need to do this for every property.
1623     if (property->is_static() && property->is_computed_name()) {
1624       Node* check = BuildThrowIfStaticPrototype(environment()->Pop(),
1625                                                 expr->GetIdForProperty(i));
1626       environment()->Push(check);
1627     }
1628 
1629     VisitForValue(property->value());
1630     Node* value = environment()->Pop();
1631     Node* key = environment()->Pop();
1632     Node* receiver = environment()->Pop();
1633 
1634     BuildSetHomeObject(value, receiver, property);
1635 
1636     switch (property->kind()) {
1637       case ClassLiteral::Property::METHOD: {
1638         Node* attr = jsgraph()->Constant(DONT_ENUM);
1639         Node* set_function_name =
1640             jsgraph()->Constant(property->NeedsSetFunctionName());
1641         const Operator* op =
1642             javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
1643         Node* call = NewNode(op, receiver, key, value, attr, set_function_name);
1644         PrepareFrameState(call, BailoutId::None());
1645         break;
1646       }
1647       case ClassLiteral::Property::GETTER: {
1648         Node* attr = jsgraph()->Constant(DONT_ENUM);
1649         const Operator* op = javascript()->CallRuntime(
1650             Runtime::kDefineGetterPropertyUnchecked, 4);
1651         NewNode(op, receiver, key, value, attr);
1652         break;
1653       }
1654       case ClassLiteral::Property::SETTER: {
1655         Node* attr = jsgraph()->Constant(DONT_ENUM);
1656         const Operator* op = javascript()->CallRuntime(
1657             Runtime::kDefineSetterPropertyUnchecked, 4);
1658         NewNode(op, receiver, key, value, attr);
1659         break;
1660       }
1661       case ClassLiteral::Property::FIELD: {
1662         UNREACHABLE();
1663         break;
1664       }
1665     }
1666   }
1667 
1668   // Set the constructor to have fast properties.
1669   prototype = environment()->Pop();
1670   literal = environment()->Pop();
1671   const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties);
1672   literal = NewNode(op, literal);
1673 
1674   // Assign to class variable.
1675   if (expr->class_variable_proxy() != nullptr) {
1676     Variable* var = expr->class_variable_proxy()->var();
1677     VectorSlotPair feedback = CreateVectorSlotPair(
1678         expr->NeedsProxySlot() ? expr->ProxySlot()
1679                                : FeedbackVectorSlot::Invalid());
1680     BuildVariableAssignment(var, literal, Token::INIT, feedback,
1681                             BailoutId::None());
1682   }
1683   ast_context()->ProduceValue(expr, literal);
1684 }
1685 
1686 
VisitNativeFunctionLiteral(NativeFunctionLiteral * expr)1687 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
1688   UNREACHABLE();
1689 }
1690 
1691 
VisitDoExpression(DoExpression * expr)1692 void AstGraphBuilder::VisitDoExpression(DoExpression* expr) {
1693   VisitBlock(expr->block());
1694   VisitVariableProxy(expr->result());
1695   ast_context()->ReplaceValue(expr);
1696 }
1697 
1698 
VisitConditional(Conditional * expr)1699 void AstGraphBuilder::VisitConditional(Conditional* expr) {
1700   IfBuilder compare_if(this);
1701   VisitForTest(expr->condition());
1702   Node* condition = environment()->Pop();
1703   compare_if.If(condition);
1704   compare_if.Then();
1705   Visit(expr->then_expression());
1706   compare_if.Else();
1707   Visit(expr->else_expression());
1708   compare_if.End();
1709   // Skip plugging AST evaluation contexts of the test kind. This is to stay in
1710   // sync with full codegen which doesn't prepare the proper bailout point (see
1711   // the implementation of FullCodeGenerator::VisitForControl).
1712   if (ast_context()->IsTest()) return;
1713   ast_context()->ReplaceValue(expr);
1714 }
1715 
1716 
VisitVariableProxy(VariableProxy * expr)1717 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
1718   VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
1719   PrepareEagerCheckpoint(BeforeId(expr));
1720   Node* value = BuildVariableLoad(expr->var(), expr->id(), pair,
1721                                   ast_context()->GetStateCombine());
1722   ast_context()->ProduceValue(expr, value);
1723 }
1724 
1725 
VisitLiteral(Literal * expr)1726 void AstGraphBuilder::VisitLiteral(Literal* expr) {
1727   Node* value = jsgraph()->Constant(expr->value());
1728   ast_context()->ProduceValue(expr, value);
1729 }
1730 
1731 
VisitRegExpLiteral(RegExpLiteral * expr)1732 void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1733   Node* closure = GetFunctionClosure();
1734 
1735   // Create node to materialize a regular expression literal.
1736   const Operator* op = javascript()->CreateLiteralRegExp(
1737       expr->pattern(), expr->flags(), expr->literal_index());
1738   Node* literal = NewNode(op, closure);
1739   PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
1740   ast_context()->ProduceValue(expr, literal);
1741 }
1742 
1743 
VisitObjectLiteral(ObjectLiteral * expr)1744 void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1745   Node* closure = GetFunctionClosure();
1746 
1747   // Create node to deep-copy the literal boilerplate.
1748   const Operator* op = javascript()->CreateLiteralObject(
1749       expr->constant_properties(), expr->ComputeFlags(true),
1750       expr->literal_index(), expr->properties_count());
1751   Node* literal = NewNode(op, closure);
1752   PrepareFrameState(literal, expr->CreateLiteralId(),
1753                     OutputFrameStateCombine::Push());
1754 
1755   // The object is expected on the operand stack during computation of the
1756   // property values and is the value of the entire expression.
1757   environment()->Push(literal);
1758 
1759   // Create nodes to store computed values into the literal.
1760   int property_index = 0;
1761   AccessorTable accessor_table(local_zone());
1762   for (; property_index < expr->properties()->length(); property_index++) {
1763     ObjectLiteral::Property* property = expr->properties()->at(property_index);
1764     if (property->is_computed_name()) break;
1765     if (property->IsCompileTimeValue()) continue;
1766 
1767     Literal* key = property->key()->AsLiteral();
1768     switch (property->kind()) {
1769       case ObjectLiteral::Property::CONSTANT:
1770         UNREACHABLE();
1771       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1772         DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1773       // Fall through.
1774       case ObjectLiteral::Property::COMPUTED: {
1775         // It is safe to use [[Put]] here because the boilerplate already
1776         // contains computed properties with an uninitialized value.
1777         if (key->IsStringLiteral()) {
1778           DCHECK(key->IsPropertyName());
1779           if (property->emit_store()) {
1780             VisitForValue(property->value());
1781             Node* value = environment()->Pop();
1782             Node* literal = environment()->Top();
1783             Handle<Name> name = key->AsPropertyName();
1784             VectorSlotPair feedback =
1785                 CreateVectorSlotPair(property->GetSlot(0));
1786             Node* store = BuildNamedStore(literal, name, value, feedback);
1787             PrepareFrameState(store, key->id(),
1788                               OutputFrameStateCombine::Ignore());
1789             BuildSetHomeObject(value, literal, property, 1);
1790           } else {
1791             VisitForEffect(property->value());
1792           }
1793           break;
1794         }
1795         environment()->Push(environment()->Top());  // Duplicate receiver.
1796         VisitForValue(property->key());
1797         VisitForValue(property->value());
1798         Node* value = environment()->Pop();
1799         Node* key = environment()->Pop();
1800         Node* receiver = environment()->Pop();
1801         if (property->emit_store()) {
1802           Node* language = jsgraph()->Constant(SLOPPY);
1803           const Operator* op = javascript()->CallRuntime(Runtime::kSetProperty);
1804           Node* set_property = NewNode(op, receiver, key, value, language);
1805           // SetProperty should not lazy deopt on an object literal.
1806           PrepareFrameState(set_property, BailoutId::None());
1807           BuildSetHomeObject(value, receiver, property);
1808         }
1809         break;
1810       }
1811       case ObjectLiteral::Property::PROTOTYPE: {
1812         environment()->Push(environment()->Top());  // Duplicate receiver.
1813         VisitForValue(property->value());
1814         Node* value = environment()->Pop();
1815         Node* receiver = environment()->Pop();
1816         DCHECK(property->emit_store());
1817         const Operator* op =
1818             javascript()->CallRuntime(Runtime::kInternalSetPrototype);
1819         Node* set_prototype = NewNode(op, receiver, value);
1820         // SetPrototype should not lazy deopt on an object literal.
1821         PrepareFrameState(set_prototype,
1822                           expr->GetIdForPropertySet(property_index));
1823         break;
1824       }
1825       case ObjectLiteral::Property::GETTER:
1826         if (property->emit_store()) {
1827           AccessorTable::Iterator it = accessor_table.lookup(key);
1828           it->second->bailout_id = expr->GetIdForPropertySet(property_index);
1829           it->second->getter = property;
1830         }
1831         break;
1832       case ObjectLiteral::Property::SETTER:
1833         if (property->emit_store()) {
1834           AccessorTable::Iterator it = accessor_table.lookup(key);
1835           it->second->bailout_id = expr->GetIdForPropertySet(property_index);
1836           it->second->setter = property;
1837         }
1838         break;
1839     }
1840   }
1841 
1842   // Create nodes to define accessors, using only a single call to the runtime
1843   // for each pair of corresponding getters and setters.
1844   literal = environment()->Top();  // Reload from operand stack.
1845   for (AccessorTable::Iterator it = accessor_table.begin();
1846        it != accessor_table.end(); ++it) {
1847     VisitForValue(it->first);
1848     VisitObjectLiteralAccessor(literal, it->second->getter);
1849     VisitObjectLiteralAccessor(literal, it->second->setter);
1850     Node* setter = environment()->Pop();
1851     Node* getter = environment()->Pop();
1852     Node* name = environment()->Pop();
1853     Node* attr = jsgraph()->Constant(NONE);
1854     const Operator* op =
1855         javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked);
1856     Node* call = NewNode(op, literal, name, getter, setter, attr);
1857     PrepareFrameState(call, it->second->bailout_id);
1858   }
1859 
1860   // Object literals have two parts. The "static" part on the left contains no
1861   // computed property names, and so we can compute its map ahead of time; see
1862   // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1863   // with the first computed property name and continues with all properties to
1864   // its right. All the code from above initializes the static component of the
1865   // object literal, and arranges for the map of the result to reflect the
1866   // static order in which the keys appear. For the dynamic properties, we
1867   // compile them into a series of "SetOwnProperty" runtime calls. This will
1868   // preserve insertion order.
1869   for (; property_index < expr->properties()->length(); property_index++) {
1870     ObjectLiteral::Property* property = expr->properties()->at(property_index);
1871 
1872     if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1873       environment()->Push(environment()->Top());  // Duplicate receiver.
1874       VisitForValue(property->value());
1875       Node* value = environment()->Pop();
1876       Node* receiver = environment()->Pop();
1877       const Operator* op =
1878           javascript()->CallRuntime(Runtime::kInternalSetPrototype);
1879       Node* call = NewNode(op, receiver, value);
1880       PrepareFrameState(call, expr->GetIdForPropertySet(property_index));
1881       continue;
1882     }
1883 
1884     environment()->Push(environment()->Top());  // Duplicate receiver.
1885     VisitForValue(property->key());
1886     Node* name = BuildToName(environment()->Pop(),
1887                              expr->GetIdForPropertyName(property_index));
1888     environment()->Push(name);
1889     VisitForValue(property->value());
1890     Node* value = environment()->Pop();
1891     Node* key = environment()->Pop();
1892     Node* receiver = environment()->Pop();
1893     BuildSetHomeObject(value, receiver, property);
1894     switch (property->kind()) {
1895       case ObjectLiteral::Property::CONSTANT:
1896       case ObjectLiteral::Property::COMPUTED:
1897       case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
1898         if (!property->emit_store()) continue;
1899         Node* attr = jsgraph()->Constant(NONE);
1900         Node* set_function_name =
1901             jsgraph()->Constant(property->NeedsSetFunctionName());
1902         const Operator* op =
1903             javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
1904         Node* call = NewNode(op, receiver, key, value, attr, set_function_name);
1905         PrepareFrameState(call, expr->GetIdForPropertySet(property_index));
1906         break;
1907       }
1908       case ObjectLiteral::Property::PROTOTYPE:
1909         UNREACHABLE();  // Handled specially above.
1910         break;
1911       case ObjectLiteral::Property::GETTER: {
1912         Node* attr = jsgraph()->Constant(NONE);
1913         const Operator* op = javascript()->CallRuntime(
1914             Runtime::kDefineGetterPropertyUnchecked, 4);
1915         Node* call = NewNode(op, receiver, key, value, attr);
1916         PrepareFrameState(call, BailoutId::None());
1917         break;
1918       }
1919       case ObjectLiteral::Property::SETTER: {
1920         Node* attr = jsgraph()->Constant(NONE);
1921         const Operator* op = javascript()->CallRuntime(
1922             Runtime::kDefineSetterPropertyUnchecked, 4);
1923         Node* call = NewNode(op, receiver, key, value, attr);
1924         PrepareFrameState(call, BailoutId::None());
1925         break;
1926       }
1927     }
1928   }
1929 
1930   ast_context()->ProduceValue(expr, environment()->Pop());
1931 }
1932 
1933 
VisitObjectLiteralAccessor(Node * home_object,ObjectLiteralProperty * property)1934 void AstGraphBuilder::VisitObjectLiteralAccessor(
1935     Node* home_object, ObjectLiteralProperty* property) {
1936   if (property == nullptr) {
1937     VisitForValueOrNull(nullptr);
1938   } else {
1939     VisitForValue(property->value());
1940     BuildSetHomeObject(environment()->Top(), home_object, property);
1941   }
1942 }
1943 
1944 
VisitArrayLiteral(ArrayLiteral * expr)1945 void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1946   Node* closure = GetFunctionClosure();
1947 
1948   // Create node to deep-copy the literal boilerplate.
1949   const Operator* op = javascript()->CreateLiteralArray(
1950       expr->constant_elements(), expr->ComputeFlags(true),
1951       expr->literal_index(), expr->values()->length());
1952   Node* literal = NewNode(op, closure);
1953   PrepareFrameState(literal, expr->CreateLiteralId(),
1954                     OutputFrameStateCombine::Push());
1955 
1956   // The array is expected on the operand stack during computation of the
1957   // element values.
1958   environment()->Push(literal);
1959 
1960   // Create nodes to evaluate all the non-constant subexpressions and to store
1961   // them into the newly cloned array.
1962   for (int array_index = 0; array_index < expr->values()->length();
1963        array_index++) {
1964     Expression* subexpr = expr->values()->at(array_index);
1965     DCHECK(!subexpr->IsSpread());
1966     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1967 
1968     VisitForValue(subexpr);
1969     VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
1970     Node* value = environment()->Pop();
1971     Node* index = jsgraph()->Constant(array_index);
1972     Node* literal = environment()->Top();
1973     Node* store = BuildKeyedStore(literal, index, value, pair);
1974     PrepareFrameState(store, expr->GetIdForElement(array_index),
1975                       OutputFrameStateCombine::Ignore());
1976   }
1977 
1978   ast_context()->ProduceValue(expr, environment()->Pop());
1979 }
1980 
VisitForInAssignment(Expression * expr,Node * value,const VectorSlotPair & feedback,BailoutId bailout_id)1981 void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
1982                                            const VectorSlotPair& feedback,
1983                                            BailoutId bailout_id) {
1984   DCHECK(expr->IsValidReferenceExpressionOrThis());
1985 
1986   // Left-hand side can only be a property, a global or a variable slot.
1987   Property* property = expr->AsProperty();
1988   LhsKind assign_type = Property::GetAssignType(property);
1989 
1990   // Evaluate LHS expression and store the value.
1991   switch (assign_type) {
1992     case VARIABLE: {
1993       Variable* var = expr->AsVariableProxy()->var();
1994       BuildVariableAssignment(var, value, Token::ASSIGN, feedback, bailout_id);
1995       break;
1996     }
1997     case NAMED_PROPERTY: {
1998       environment()->Push(value);
1999       VisitForValue(property->obj());
2000       Node* object = environment()->Pop();
2001       value = environment()->Pop();
2002       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2003       Node* store = BuildNamedStore(object, name, value, feedback);
2004       PrepareFrameState(store, bailout_id, OutputFrameStateCombine::Ignore());
2005       break;
2006     }
2007     case KEYED_PROPERTY: {
2008       environment()->Push(value);
2009       VisitForValue(property->obj());
2010       VisitForValue(property->key());
2011       Node* key = environment()->Pop();
2012       Node* object = environment()->Pop();
2013       value = environment()->Pop();
2014       Node* store = BuildKeyedStore(object, key, value, feedback);
2015       PrepareFrameState(store, bailout_id, OutputFrameStateCombine::Ignore());
2016       break;
2017     }
2018     case NAMED_SUPER_PROPERTY: {
2019       environment()->Push(value);
2020       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2021       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2022       Node* home_object = environment()->Pop();
2023       Node* receiver = environment()->Pop();
2024       value = environment()->Pop();
2025       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2026       Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2027       PrepareFrameState(store, bailout_id, OutputFrameStateCombine::Ignore());
2028       break;
2029     }
2030     case KEYED_SUPER_PROPERTY: {
2031       environment()->Push(value);
2032       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2033       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2034       VisitForValue(property->key());
2035       Node* key = environment()->Pop();
2036       Node* home_object = environment()->Pop();
2037       Node* receiver = environment()->Pop();
2038       value = environment()->Pop();
2039       Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2040       PrepareFrameState(store, bailout_id, OutputFrameStateCombine::Ignore());
2041       break;
2042     }
2043   }
2044 }
2045 
2046 
VisitAssignment(Assignment * expr)2047 void AstGraphBuilder::VisitAssignment(Assignment* expr) {
2048   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
2049 
2050   // Left-hand side can only be a property, a global or a variable slot.
2051   Property* property = expr->target()->AsProperty();
2052   LhsKind assign_type = Property::GetAssignType(property);
2053   bool needs_frame_state_before = true;
2054 
2055   // Evaluate LHS expression.
2056   switch (assign_type) {
2057     case VARIABLE: {
2058       Variable* variable = expr->target()->AsVariableProxy()->var();
2059       if (variable->location() == VariableLocation::PARAMETER ||
2060           variable->location() == VariableLocation::LOCAL ||
2061           variable->location() == VariableLocation::CONTEXT) {
2062         needs_frame_state_before = false;
2063       }
2064       break;
2065     }
2066     case NAMED_PROPERTY:
2067       VisitForValue(property->obj());
2068       break;
2069     case KEYED_PROPERTY:
2070       VisitForValue(property->obj());
2071       VisitForValue(property->key());
2072       break;
2073     case NAMED_SUPER_PROPERTY:
2074       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2075       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2076       break;
2077     case KEYED_SUPER_PROPERTY:
2078       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2079       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2080       VisitForValue(property->key());
2081       break;
2082   }
2083 
2084   // Evaluate the value and potentially handle compound assignments by loading
2085   // the left-hand side value and performing a binary operation.
2086   if (expr->is_compound()) {
2087     Node* old_value = nullptr;
2088     switch (assign_type) {
2089       case VARIABLE: {
2090         VariableProxy* proxy = expr->target()->AsVariableProxy();
2091         VectorSlotPair pair =
2092             CreateVectorSlotPair(proxy->VariableFeedbackSlot());
2093         PrepareEagerCheckpoint(BeforeId(proxy));
2094         old_value = BuildVariableLoad(proxy->var(), expr->target()->id(), pair,
2095                                       OutputFrameStateCombine::Push());
2096         break;
2097       }
2098       case NAMED_PROPERTY: {
2099         Node* object = environment()->Top();
2100         Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2101         VectorSlotPair pair =
2102             CreateVectorSlotPair(property->PropertyFeedbackSlot());
2103         old_value = BuildNamedLoad(object, name, pair);
2104         PrepareFrameState(old_value, property->LoadId(),
2105                           OutputFrameStateCombine::Push());
2106         break;
2107       }
2108       case KEYED_PROPERTY: {
2109         Node* key = environment()->Top();
2110         Node* object = environment()->Peek(1);
2111         VectorSlotPair pair =
2112             CreateVectorSlotPair(property->PropertyFeedbackSlot());
2113         old_value = BuildKeyedLoad(object, key, pair);
2114         PrepareFrameState(old_value, property->LoadId(),
2115                           OutputFrameStateCombine::Push());
2116         break;
2117       }
2118       case NAMED_SUPER_PROPERTY: {
2119         Node* home_object = environment()->Top();
2120         Node* receiver = environment()->Peek(1);
2121         Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2122         VectorSlotPair pair =
2123             CreateVectorSlotPair(property->PropertyFeedbackSlot());
2124         old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2125         PrepareFrameState(old_value, property->LoadId(),
2126                           OutputFrameStateCombine::Push());
2127         break;
2128       }
2129       case KEYED_SUPER_PROPERTY: {
2130         Node* key = environment()->Top();
2131         Node* home_object = environment()->Peek(1);
2132         Node* receiver = environment()->Peek(2);
2133         VectorSlotPair pair =
2134             CreateVectorSlotPair(property->PropertyFeedbackSlot());
2135         old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2136         PrepareFrameState(old_value, property->LoadId(),
2137                           OutputFrameStateCombine::Push());
2138         break;
2139       }
2140     }
2141     environment()->Push(old_value);
2142     VisitForValue(expr->value());
2143     Node* right = environment()->Pop();
2144     Node* left = environment()->Pop();
2145     Node* value =
2146         BuildBinaryOp(left, right, expr->binary_op(),
2147                       expr->binary_operation()->BinaryOperationFeedbackId());
2148     PrepareFrameState(value, expr->binary_operation()->id(),
2149                       OutputFrameStateCombine::Push());
2150     environment()->Push(value);
2151     if (needs_frame_state_before) {
2152       PrepareEagerCheckpoint(expr->binary_operation()->id());
2153     }
2154   } else {
2155     VisitForValue(expr->value());
2156   }
2157 
2158   // Store the value.
2159   Node* value = environment()->Pop();
2160   VectorSlotPair feedback = CreateVectorSlotPair(expr->AssignmentSlot());
2161   switch (assign_type) {
2162     case VARIABLE: {
2163       Variable* variable = expr->target()->AsVariableProxy()->var();
2164       BuildVariableAssignment(variable, value, expr->op(), feedback, expr->id(),
2165                               ast_context()->GetStateCombine());
2166       break;
2167     }
2168     case NAMED_PROPERTY: {
2169       Node* object = environment()->Pop();
2170       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2171       Node* store = BuildNamedStore(object, name, value, feedback);
2172       PrepareFrameState(store, expr->AssignmentId(),
2173                         OutputFrameStateCombine::Push());
2174       break;
2175     }
2176     case KEYED_PROPERTY: {
2177       Node* key = environment()->Pop();
2178       Node* object = environment()->Pop();
2179       Node* store = BuildKeyedStore(object, key, value, feedback);
2180       PrepareFrameState(store, expr->AssignmentId(),
2181                         OutputFrameStateCombine::Push());
2182       break;
2183     }
2184     case NAMED_SUPER_PROPERTY: {
2185       Node* home_object = environment()->Pop();
2186       Node* receiver = environment()->Pop();
2187       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2188       Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2189       PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
2190       break;
2191     }
2192     case KEYED_SUPER_PROPERTY: {
2193       Node* key = environment()->Pop();
2194       Node* home_object = environment()->Pop();
2195       Node* receiver = environment()->Pop();
2196       Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2197       PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
2198       break;
2199     }
2200   }
2201 
2202   ast_context()->ProduceValue(expr, value);
2203 }
2204 
2205 
VisitYield(Yield * expr)2206 void AstGraphBuilder::VisitYield(Yield* expr) {
2207   // Generator functions are supported only by going through Ignition first.
2208   SetStackOverflow();
2209   ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
2210 }
2211 
2212 
VisitThrow(Throw * expr)2213 void AstGraphBuilder::VisitThrow(Throw* expr) {
2214   VisitForValue(expr->exception());
2215   Node* exception = environment()->Pop();
2216   Node* value = BuildThrowError(exception, expr->id());
2217   ast_context()->ProduceValue(expr, value);
2218 }
2219 
2220 
VisitProperty(Property * expr)2221 void AstGraphBuilder::VisitProperty(Property* expr) {
2222   Node* value = nullptr;
2223   LhsKind property_kind = Property::GetAssignType(expr);
2224   VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
2225   switch (property_kind) {
2226     case VARIABLE:
2227       UNREACHABLE();
2228       break;
2229     case NAMED_PROPERTY: {
2230       VisitForValue(expr->obj());
2231       Node* object = environment()->Pop();
2232       Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2233       value = BuildNamedLoad(object, name, pair);
2234       PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
2235       break;
2236     }
2237     case KEYED_PROPERTY: {
2238       VisitForValue(expr->obj());
2239       VisitForValue(expr->key());
2240       Node* key = environment()->Pop();
2241       Node* object = environment()->Pop();
2242       value = BuildKeyedLoad(object, key, pair);
2243       PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
2244       break;
2245     }
2246     case NAMED_SUPER_PROPERTY: {
2247       VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2248       VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2249       Node* home_object = environment()->Pop();
2250       Node* receiver = environment()->Pop();
2251       Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2252       value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2253       PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
2254       break;
2255     }
2256     case KEYED_SUPER_PROPERTY: {
2257       VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2258       VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2259       VisitForValue(expr->key());
2260       Node* key = environment()->Pop();
2261       Node* home_object = environment()->Pop();
2262       Node* receiver = environment()->Pop();
2263       value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2264       PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
2265       break;
2266     }
2267   }
2268   ast_context()->ProduceValue(expr, value);
2269 }
2270 
2271 
VisitCall(Call * expr)2272 void AstGraphBuilder::VisitCall(Call* expr) {
2273   Expression* callee = expr->expression();
2274   Call::CallType call_type = expr->GetCallType();
2275 
2276   // Prepare the callee and the receiver to the function call. This depends on
2277   // the semantics of the underlying call type.
2278   ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
2279   Node* receiver_value = nullptr;
2280   Node* callee_value = nullptr;
2281   if (expr->is_possibly_eval()) {
2282     if (callee->AsVariableProxy()->var()->IsLookupSlot()) {
2283       Variable* variable = callee->AsVariableProxy()->var();
2284       Node* name = jsgraph()->Constant(variable->name());
2285       const Operator* op =
2286           javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
2287       Node* pair = NewNode(op, name);
2288       callee_value = NewNode(common()->Projection(0), pair);
2289       receiver_value = NewNode(common()->Projection(1), pair);
2290       PrepareFrameState(pair, expr->LookupId(),
2291                         OutputFrameStateCombine::Push(2));
2292     } else {
2293       VisitForValue(callee);
2294       callee_value = environment()->Pop();
2295       receiver_hint = ConvertReceiverMode::kNullOrUndefined;
2296       receiver_value = jsgraph()->UndefinedConstant();
2297     }
2298   } else {
2299     switch (call_type) {
2300       case Call::GLOBAL_CALL: {
2301         VariableProxy* proxy = callee->AsVariableProxy();
2302         VectorSlotPair pair =
2303             CreateVectorSlotPair(proxy->VariableFeedbackSlot());
2304         PrepareEagerCheckpoint(BeforeId(proxy));
2305         callee_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
2306                                          pair, OutputFrameStateCombine::Push());
2307         receiver_hint = ConvertReceiverMode::kNullOrUndefined;
2308         receiver_value = jsgraph()->UndefinedConstant();
2309         break;
2310       }
2311       case Call::WITH_CALL: {
2312         Variable* variable = callee->AsVariableProxy()->var();
2313         Node* name = jsgraph()->Constant(variable->name());
2314         const Operator* op =
2315             javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
2316         Node* pair = NewNode(op, name);
2317         callee_value = NewNode(common()->Projection(0), pair);
2318         receiver_value = NewNode(common()->Projection(1), pair);
2319         PrepareFrameState(pair, expr->LookupId(),
2320                           OutputFrameStateCombine::Push(2));
2321         break;
2322       }
2323       case Call::NAMED_PROPERTY_CALL: {
2324         Property* property = callee->AsProperty();
2325         VectorSlotPair feedback =
2326             CreateVectorSlotPair(property->PropertyFeedbackSlot());
2327         VisitForValue(property->obj());
2328         Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2329         Node* object = environment()->Top();
2330         callee_value = BuildNamedLoad(object, name, feedback);
2331         PrepareFrameState(callee_value, property->LoadId(),
2332                           OutputFrameStateCombine::Push());
2333         // Note that a property call requires the receiver to be wrapped into
2334         // an object for sloppy callees. However the receiver is guaranteed
2335         // not to be null or undefined at this point.
2336         receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
2337         receiver_value = environment()->Pop();
2338         break;
2339       }
2340       case Call::KEYED_PROPERTY_CALL: {
2341         Property* property = callee->AsProperty();
2342         VectorSlotPair feedback =
2343             CreateVectorSlotPair(property->PropertyFeedbackSlot());
2344         VisitForValue(property->obj());
2345         VisitForValue(property->key());
2346         Node* key = environment()->Pop();
2347         Node* object = environment()->Top();
2348         callee_value = BuildKeyedLoad(object, key, feedback);
2349         PrepareFrameState(callee_value, property->LoadId(),
2350                           OutputFrameStateCombine::Push());
2351         // Note that a property call requires the receiver to be wrapped into
2352         // an object for sloppy callees. However the receiver is guaranteed
2353         // not to be null or undefined at this point.
2354         receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
2355         receiver_value = environment()->Pop();
2356         break;
2357       }
2358       case Call::NAMED_SUPER_PROPERTY_CALL: {
2359         Property* property = callee->AsProperty();
2360         SuperPropertyReference* super_ref =
2361             property->obj()->AsSuperPropertyReference();
2362         VisitForValue(super_ref->home_object());
2363         VisitForValue(super_ref->this_var());
2364         Node* home = environment()->Peek(1);
2365         Node* object = environment()->Top();
2366         Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2367         callee_value =
2368             BuildNamedSuperLoad(object, home, name, VectorSlotPair());
2369         PrepareFrameState(callee_value, property->LoadId(),
2370                           OutputFrameStateCombine::Push());
2371         // Note that a property call requires the receiver to be wrapped into
2372         // an object for sloppy callees. Since the receiver is not the target of
2373         // the load, it could very well be null or undefined at this point.
2374         receiver_value = environment()->Pop();
2375         environment()->Drop(1);
2376         break;
2377       }
2378       case Call::KEYED_SUPER_PROPERTY_CALL: {
2379         Property* property = callee->AsProperty();
2380         SuperPropertyReference* super_ref =
2381             property->obj()->AsSuperPropertyReference();
2382         VisitForValue(super_ref->home_object());
2383         VisitForValue(super_ref->this_var());
2384         environment()->Push(environment()->Top());    // Duplicate this_var.
2385         environment()->Push(environment()->Peek(2));  // Duplicate home_obj.
2386         VisitForValue(property->key());
2387         Node* key = environment()->Pop();
2388         Node* home = environment()->Pop();
2389         Node* object = environment()->Pop();
2390         callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair());
2391         PrepareFrameState(callee_value, property->LoadId(),
2392                           OutputFrameStateCombine::Push());
2393         // Note that a property call requires the receiver to be wrapped into
2394         // an object for sloppy callees. Since the receiver is not the target of
2395         // the load, it could very well be null or undefined at this point.
2396         receiver_value = environment()->Pop();
2397         environment()->Drop(1);
2398         break;
2399       }
2400       case Call::SUPER_CALL:
2401         return VisitCallSuper(expr);
2402       case Call::OTHER_CALL:
2403         VisitForValue(callee);
2404         callee_value = environment()->Pop();
2405         receiver_hint = ConvertReceiverMode::kNullOrUndefined;
2406         receiver_value = jsgraph()->UndefinedConstant();
2407         break;
2408     }
2409   }
2410 
2411   // The callee and the receiver both have to be pushed onto the operand stack
2412   // before arguments are being evaluated.
2413   environment()->Push(callee_value);
2414   environment()->Push(receiver_value);
2415 
2416   // Evaluate all arguments to the function call,
2417   ZoneList<Expression*>* args = expr->arguments();
2418   VisitForValues(args);
2419 
2420   // Resolve callee for a potential direct eval call. This block will mutate the
2421   // callee value pushed onto the environment.
2422   if (expr->is_possibly_eval() && args->length() > 0) {
2423     int arg_count = args->length();
2424 
2425     // Extract callee and source string from the environment.
2426     Node* callee = environment()->Peek(arg_count + 1);
2427     Node* source = environment()->Peek(arg_count - 1);
2428 
2429     // Create node to ask for help resolving potential eval call. This will
2430     // provide a fully resolved callee to patch into the environment.
2431     Node* function = GetFunctionClosure();
2432     Node* language = jsgraph()->Constant(language_mode());
2433     Node* eval_scope_position =
2434         jsgraph()->Constant(current_scope()->start_position());
2435     Node* eval_position = jsgraph()->Constant(expr->position());
2436     const Operator* op =
2437         javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval);
2438     Node* new_callee = NewNode(op, callee, source, function, language,
2439                                eval_scope_position, eval_position);
2440     PrepareFrameState(new_callee, expr->EvalId(),
2441                       OutputFrameStateCombine::PokeAt(arg_count + 1));
2442 
2443     // Patch callee on the environment.
2444     environment()->Poke(arg_count + 1, new_callee);
2445   }
2446 
2447   // Create node to perform the function call.
2448   float const frequency = ComputeCallFrequency(expr->CallFeedbackICSlot());
2449   VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
2450   const Operator* call =
2451       javascript()->CallFunction(args->length() + 2, frequency, feedback,
2452                                  receiver_hint, expr->tail_call_mode());
2453   PrepareEagerCheckpoint(expr->is_possibly_eval() ? expr->EvalId()
2454                                                   : expr->CallId());
2455   Node* value = ProcessArguments(call, args->length() + 2);
2456   // The callee passed to the call, we just need to push something here to
2457   // satisfy the bailout location contract. The fullcodegen code will not
2458   // ever look at this value, so we just push optimized_out here.
2459   environment()->Push(jsgraph()->OptimizedOutConstant());
2460   PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
2461   environment()->Drop(1);
2462   ast_context()->ProduceValue(expr, value);
2463 }
2464 
2465 
VisitCallSuper(Call * expr)2466 void AstGraphBuilder::VisitCallSuper(Call* expr) {
2467   SuperCallReference* super = expr->expression()->AsSuperCallReference();
2468   DCHECK_NOT_NULL(super);
2469 
2470   // Prepare the callee to the super call.
2471   VisitForValue(super->this_function_var());
2472   Node* this_function = environment()->Pop();
2473   const Operator* op =
2474       javascript()->CallRuntime(Runtime::kInlineGetSuperConstructor, 1);
2475   Node* super_function = NewNode(op, this_function);
2476   environment()->Push(super_function);
2477 
2478   // Evaluate all arguments to the super call.
2479   ZoneList<Expression*>* args = expr->arguments();
2480   VisitForValues(args);
2481 
2482   // The new target is loaded from the {new.target} variable.
2483   VisitForValue(super->new_target_var());
2484 
2485   // Create node to perform the super call.
2486   const Operator* call =
2487       javascript()->CallConstruct(args->length() + 2, 0.0f, VectorSlotPair());
2488   Node* value = ProcessArguments(call, args->length() + 2);
2489   PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
2490   ast_context()->ProduceValue(expr, value);
2491 }
2492 
2493 
VisitCallNew(CallNew * expr)2494 void AstGraphBuilder::VisitCallNew(CallNew* expr) {
2495   VisitForValue(expr->expression());
2496 
2497   // Evaluate all arguments to the construct call.
2498   ZoneList<Expression*>* args = expr->arguments();
2499   VisitForValues(args);
2500 
2501   // The new target is the same as the callee.
2502   environment()->Push(environment()->Peek(args->length()));
2503 
2504   // Create node to perform the construct call.
2505   float const frequency = ComputeCallFrequency(expr->CallNewFeedbackSlot());
2506   VectorSlotPair feedback = CreateVectorSlotPair(expr->CallNewFeedbackSlot());
2507   const Operator* call =
2508       javascript()->CallConstruct(args->length() + 2, frequency, feedback);
2509   Node* value = ProcessArguments(call, args->length() + 2);
2510   PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
2511   ast_context()->ProduceValue(expr, value);
2512 }
2513 
2514 
VisitCallJSRuntime(CallRuntime * expr)2515 void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
2516   // The callee and the receiver both have to be pushed onto the operand stack
2517   // before arguments are being evaluated.
2518   Node* callee_value = BuildLoadNativeContextField(expr->context_index());
2519   Node* receiver_value = jsgraph()->UndefinedConstant();
2520 
2521   environment()->Push(callee_value);
2522   environment()->Push(receiver_value);
2523 
2524   // Evaluate all arguments to the JS runtime call.
2525   ZoneList<Expression*>* args = expr->arguments();
2526   VisitForValues(args);
2527 
2528   // Create node to perform the JS runtime call.
2529   const Operator* call = javascript()->CallFunction(args->length() + 2);
2530   PrepareEagerCheckpoint(expr->CallId());
2531   Node* value = ProcessArguments(call, args->length() + 2);
2532   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2533   ast_context()->ProduceValue(expr, value);
2534 }
2535 
2536 
VisitCallRuntime(CallRuntime * expr)2537 void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
2538   // Handle calls to runtime functions implemented in JavaScript separately as
2539   // the call follows JavaScript ABI and the callee is statically unknown.
2540   if (expr->is_jsruntime()) {
2541     return VisitCallJSRuntime(expr);
2542   }
2543 
2544   // Evaluate all arguments to the runtime call.
2545   ZoneList<Expression*>* args = expr->arguments();
2546   VisitForValues(args);
2547 
2548   // Create node to perform the runtime call.
2549   Runtime::FunctionId functionId = expr->function()->function_id;
2550   const Operator* call = javascript()->CallRuntime(functionId, args->length());
2551   if (expr->function()->intrinsic_type == Runtime::IntrinsicType::RUNTIME ||
2552       expr->function()->function_id == Runtime::kInlineCall) {
2553     PrepareEagerCheckpoint(expr->CallId());
2554   }
2555   Node* value = ProcessArguments(call, args->length());
2556   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2557   ast_context()->ProduceValue(expr, value);
2558 }
2559 
2560 
VisitUnaryOperation(UnaryOperation * expr)2561 void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
2562   switch (expr->op()) {
2563     case Token::DELETE:
2564       return VisitDelete(expr);
2565     case Token::VOID:
2566       return VisitVoid(expr);
2567     case Token::TYPEOF:
2568       return VisitTypeof(expr);
2569     case Token::NOT:
2570       return VisitNot(expr);
2571     default:
2572       UNREACHABLE();
2573   }
2574 }
2575 
2576 
VisitCountOperation(CountOperation * expr)2577 void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
2578   DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
2579 
2580   // Left-hand side can only be a property, a global or a variable slot.
2581   Property* property = expr->expression()->AsProperty();
2582   LhsKind assign_type = Property::GetAssignType(property);
2583 
2584   // Reserve space for result of postfix operation.
2585   bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
2586   if (is_postfix && assign_type != VARIABLE) {
2587     environment()->Push(jsgraph()->ZeroConstant());
2588   }
2589 
2590   // Evaluate LHS expression and get old value.
2591   Node* old_value = nullptr;
2592   int stack_depth = -1;
2593   switch (assign_type) {
2594     case VARIABLE: {
2595       VariableProxy* proxy = expr->expression()->AsVariableProxy();
2596       VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
2597       PrepareEagerCheckpoint(BeforeId(proxy));
2598       old_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
2599                                     pair, OutputFrameStateCombine::Push());
2600       stack_depth = 0;
2601       break;
2602     }
2603     case NAMED_PROPERTY: {
2604       VisitForValue(property->obj());
2605       Node* object = environment()->Top();
2606       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2607       VectorSlotPair pair =
2608           CreateVectorSlotPair(property->PropertyFeedbackSlot());
2609       old_value = BuildNamedLoad(object, name, pair);
2610       PrepareFrameState(old_value, property->LoadId(),
2611                         OutputFrameStateCombine::Push());
2612       stack_depth = 1;
2613       break;
2614     }
2615     case KEYED_PROPERTY: {
2616       VisitForValue(property->obj());
2617       VisitForValue(property->key());
2618       Node* key = environment()->Top();
2619       Node* object = environment()->Peek(1);
2620       VectorSlotPair pair =
2621           CreateVectorSlotPair(property->PropertyFeedbackSlot());
2622       old_value = BuildKeyedLoad(object, key, pair);
2623       PrepareFrameState(old_value, property->LoadId(),
2624                         OutputFrameStateCombine::Push());
2625       stack_depth = 2;
2626       break;
2627     }
2628     case NAMED_SUPER_PROPERTY: {
2629       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2630       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2631       Node* home_object = environment()->Top();
2632       Node* receiver = environment()->Peek(1);
2633       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2634       VectorSlotPair pair =
2635           CreateVectorSlotPair(property->PropertyFeedbackSlot());
2636       old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2637       PrepareFrameState(old_value, property->LoadId(),
2638                         OutputFrameStateCombine::Push());
2639       stack_depth = 2;
2640       break;
2641     }
2642     case KEYED_SUPER_PROPERTY: {
2643       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2644       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2645       VisitForValue(property->key());
2646       Node* key = environment()->Top();
2647       Node* home_object = environment()->Peek(1);
2648       Node* receiver = environment()->Peek(2);
2649       VectorSlotPair pair =
2650           CreateVectorSlotPair(property->PropertyFeedbackSlot());
2651       old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2652       PrepareFrameState(old_value, property->LoadId(),
2653                         OutputFrameStateCombine::Push());
2654       stack_depth = 3;
2655       break;
2656     }
2657   }
2658 
2659   // Convert old value into a number.
2660   old_value = NewNode(javascript()->ToNumber(), old_value);
2661   PrepareFrameState(old_value, expr->ToNumberId(),
2662                     OutputFrameStateCombine::Push());
2663 
2664   // Create a proper eager frame state for the stores.
2665   environment()->Push(old_value);
2666   PrepareEagerCheckpoint(expr->ToNumberId());
2667   old_value = environment()->Pop();
2668 
2669   // Save result for postfix expressions at correct stack depth.
2670   if (is_postfix) {
2671     if (assign_type != VARIABLE) {
2672       environment()->Poke(stack_depth, old_value);
2673     } else {
2674       environment()->Push(old_value);
2675     }
2676   }
2677 
2678   // Create node to perform +1/-1 operation.
2679   Node* value = BuildBinaryOp(old_value, jsgraph()->OneConstant(),
2680                               expr->binary_op(), expr->CountBinOpFeedbackId());
2681   // This should never lazy deopt because we have converted to number before.
2682   PrepareFrameState(value, BailoutId::None());
2683 
2684   // Store the value.
2685   VectorSlotPair feedback = CreateVectorSlotPair(expr->CountSlot());
2686   switch (assign_type) {
2687     case VARIABLE: {
2688       Variable* variable = expr->expression()->AsVariableProxy()->var();
2689       environment()->Push(value);
2690       BuildVariableAssignment(variable, value, expr->op(), feedback,
2691                               expr->AssignmentId());
2692       environment()->Pop();
2693       break;
2694     }
2695     case NAMED_PROPERTY: {
2696       Node* object = environment()->Pop();
2697       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2698       Node* store = BuildNamedStore(object, name, value, feedback);
2699       PrepareFrameState(store, expr->AssignmentId(),
2700                         OutputFrameStateCombine::Push());
2701       break;
2702     }
2703     case KEYED_PROPERTY: {
2704       Node* key = environment()->Pop();
2705       Node* object = environment()->Pop();
2706       Node* store = BuildKeyedStore(object, key, value, feedback);
2707       PrepareFrameState(store, expr->AssignmentId(),
2708                         OutputFrameStateCombine::Push());
2709       break;
2710     }
2711     case NAMED_SUPER_PROPERTY: {
2712       Node* home_object = environment()->Pop();
2713       Node* receiver = environment()->Pop();
2714       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2715       Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
2716       PrepareFrameState(store, expr->AssignmentId(),
2717                         OutputFrameStateCombine::Push());
2718       break;
2719     }
2720     case KEYED_SUPER_PROPERTY: {
2721       Node* key = environment()->Pop();
2722       Node* home_object = environment()->Pop();
2723       Node* receiver = environment()->Pop();
2724       Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
2725       PrepareFrameState(store, expr->AssignmentId(),
2726                         OutputFrameStateCombine::Push());
2727       break;
2728     }
2729   }
2730 
2731   // Restore old value for postfix expressions.
2732   if (is_postfix) value = environment()->Pop();
2733 
2734   ast_context()->ProduceValue(expr, value);
2735 }
2736 
2737 
VisitBinaryOperation(BinaryOperation * expr)2738 void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
2739   switch (expr->op()) {
2740     case Token::COMMA:
2741       return VisitComma(expr);
2742     case Token::OR:
2743     case Token::AND:
2744       return VisitLogicalExpression(expr);
2745     default: {
2746       VisitForValue(expr->left());
2747       VisitForValue(expr->right());
2748       Node* right = environment()->Pop();
2749       Node* left = environment()->Pop();
2750       Node* value = BuildBinaryOp(left, right, expr->op(),
2751                                   expr->BinaryOperationFeedbackId());
2752       PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2753       ast_context()->ProduceValue(expr, value);
2754     }
2755   }
2756 }
2757 
VisitLiteralCompareNil(CompareOperation * expr,Expression * sub_expr,Node * nil_value)2758 void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr,
2759                                              Expression* sub_expr,
2760                                              Node* nil_value) {
2761   const Operator* op = nullptr;
2762   switch (expr->op()) {
2763     case Token::EQ:
2764       op = javascript()->Equal(CompareOperationHint::kAny);
2765       break;
2766     case Token::EQ_STRICT:
2767       op = javascript()->StrictEqual(CompareOperationHint::kAny);
2768       break;
2769     default:
2770       UNREACHABLE();
2771   }
2772   VisitForValue(sub_expr);
2773   Node* value_to_compare = environment()->Pop();
2774   Node* value = NewNode(op, value_to_compare, nil_value);
2775   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2776   return ast_context()->ProduceValue(expr, value);
2777 }
2778 
VisitLiteralCompareTypeof(CompareOperation * expr,Expression * sub_expr,Handle<String> check)2779 void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr,
2780                                                 Expression* sub_expr,
2781                                                 Handle<String> check) {
2782   VisitTypeofExpression(sub_expr);
2783   Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop());
2784   Node* value = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
2785                         typeof_arg, jsgraph()->Constant(check));
2786   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2787   return ast_context()->ProduceValue(expr, value);
2788 }
2789 
VisitCompareOperation(CompareOperation * expr)2790 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
2791   // Check for a few fast cases. The AST visiting behavior must be in sync
2792   // with the full codegen: We don't push both left and right values onto
2793   // the expression stack when one side is a special-case literal.
2794   Expression* sub_expr = nullptr;
2795   Handle<String> check;
2796   if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
2797     return VisitLiteralCompareTypeof(expr, sub_expr, check);
2798   }
2799   if (expr->IsLiteralCompareUndefined(&sub_expr)) {
2800     return VisitLiteralCompareNil(expr, sub_expr,
2801                                   jsgraph()->UndefinedConstant());
2802   }
2803   if (expr->IsLiteralCompareNull(&sub_expr)) {
2804     return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant());
2805   }
2806 
2807   CompareOperationHint hint;
2808   if (!type_hint_analysis_ ||
2809       !type_hint_analysis_->GetCompareOperationHint(
2810           expr->CompareOperationFeedbackId(), &hint)) {
2811     hint = CompareOperationHint::kAny;
2812   }
2813 
2814   const Operator* op;
2815   switch (expr->op()) {
2816     case Token::EQ:
2817       op = javascript()->Equal(hint);
2818       break;
2819     case Token::NE:
2820       op = javascript()->NotEqual(hint);
2821       break;
2822     case Token::EQ_STRICT:
2823       op = javascript()->StrictEqual(hint);
2824       break;
2825     case Token::NE_STRICT:
2826       op = javascript()->StrictNotEqual(hint);
2827       break;
2828     case Token::LT:
2829       op = javascript()->LessThan(hint);
2830       break;
2831     case Token::GT:
2832       op = javascript()->GreaterThan(hint);
2833       break;
2834     case Token::LTE:
2835       op = javascript()->LessThanOrEqual(hint);
2836       break;
2837     case Token::GTE:
2838       op = javascript()->GreaterThanOrEqual(hint);
2839       break;
2840     case Token::INSTANCEOF:
2841       op = javascript()->InstanceOf();
2842       break;
2843     case Token::IN:
2844       op = javascript()->HasProperty();
2845       break;
2846     default:
2847       op = nullptr;
2848       UNREACHABLE();
2849   }
2850   VisitForValue(expr->left());
2851   VisitForValue(expr->right());
2852   Node* right = environment()->Pop();
2853   Node* left = environment()->Pop();
2854   Node* value = NewNode(op, left, right);
2855   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2856   ast_context()->ProduceValue(expr, value);
2857 }
2858 
2859 
VisitSpread(Spread * expr)2860 void AstGraphBuilder::VisitSpread(Spread* expr) {
2861   // Handled entirely by the parser itself.
2862   UNREACHABLE();
2863 }
2864 
2865 
VisitEmptyParentheses(EmptyParentheses * expr)2866 void AstGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
2867   // Handled entirely by the parser itself.
2868   UNREACHABLE();
2869 }
2870 
2871 
VisitThisFunction(ThisFunction * expr)2872 void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
2873   Node* value = GetFunctionClosure();
2874   ast_context()->ProduceValue(expr, value);
2875 }
2876 
2877 
VisitSuperPropertyReference(SuperPropertyReference * expr)2878 void AstGraphBuilder::VisitSuperPropertyReference(
2879     SuperPropertyReference* expr) {
2880   Node* value = BuildThrowUnsupportedSuperError(expr->id());
2881   ast_context()->ProduceValue(expr, value);
2882 }
2883 
2884 
VisitSuperCallReference(SuperCallReference * expr)2885 void AstGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
2886   // Handled by VisitCall
2887   UNREACHABLE();
2888 }
2889 
2890 
VisitCaseClause(CaseClause * expr)2891 void AstGraphBuilder::VisitCaseClause(CaseClause* expr) {
2892   // Handled entirely in VisitSwitch.
2893   UNREACHABLE();
2894 }
2895 
VisitDeclarations(Declaration::List * declarations)2896 void AstGraphBuilder::VisitDeclarations(Declaration::List* declarations) {
2897   DCHECK(globals()->empty());
2898   AstVisitor<AstGraphBuilder>::VisitDeclarations(declarations);
2899   if (globals()->empty()) return;
2900   int array_index = 0;
2901   Handle<TypeFeedbackVector> feedback_vector(
2902       info()->closure()->feedback_vector());
2903   Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
2904       static_cast<int>(globals()->size()), TENURED);
2905   for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
2906   int encoded_flags = info()->GetDeclareGlobalsFlags();
2907   Node* flags = jsgraph()->Constant(encoded_flags);
2908   Node* pairs = jsgraph()->Constant(data);
2909   Node* vector = jsgraph()->Constant(feedback_vector);
2910   const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals);
2911   Node* call = NewNode(op, pairs, flags, vector);
2912   PrepareFrameState(call, BailoutId::Declarations());
2913   globals()->clear();
2914 }
2915 
2916 
VisitIfNotNull(Statement * stmt)2917 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
2918   if (stmt == nullptr) return;
2919   Visit(stmt);
2920 }
2921 
2922 
VisitInScope(Statement * stmt,Scope * s,Node * context)2923 void AstGraphBuilder::VisitInScope(Statement* stmt, Scope* s, Node* context) {
2924   ContextScope scope(this, s, context);
2925   DCHECK(s->declarations()->is_empty());
2926   Visit(stmt);
2927 }
2928 
VisitIterationBody(IterationStatement * stmt,LoopBuilder * loop,BailoutId stack_check_id)2929 void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
2930                                          LoopBuilder* loop,
2931                                          BailoutId stack_check_id) {
2932   ControlScopeForIteration scope(this, stmt, loop);
2933   if (FLAG_turbo_loop_stackcheck || !info()->shared_info()->asm_function()) {
2934     Node* node = NewNode(javascript()->StackCheck());
2935     PrepareFrameState(node, stack_check_id);
2936   }
2937   Visit(stmt->body());
2938 }
2939 
2940 
VisitDelete(UnaryOperation * expr)2941 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
2942   Node* value;
2943   if (expr->expression()->IsVariableProxy()) {
2944     // Delete of an unqualified identifier is disallowed in strict mode but
2945     // "delete this" is allowed.
2946     Variable* variable = expr->expression()->AsVariableProxy()->var();
2947     DCHECK(is_sloppy(language_mode()) || variable->is_this());
2948     value = BuildVariableDelete(variable, expr->id(),
2949                                 ast_context()->GetStateCombine());
2950   } else if (expr->expression()->IsProperty()) {
2951     Property* property = expr->expression()->AsProperty();
2952     VisitForValue(property->obj());
2953     VisitForValue(property->key());
2954     Node* key = environment()->Pop();
2955     Node* object = environment()->Pop();
2956     value = NewNode(javascript()->DeleteProperty(language_mode()), object, key);
2957     PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2958   } else {
2959     VisitForEffect(expr->expression());
2960     value = jsgraph()->TrueConstant();
2961   }
2962   ast_context()->ProduceValue(expr, value);
2963 }
2964 
2965 
VisitVoid(UnaryOperation * expr)2966 void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
2967   VisitForEffect(expr->expression());
2968   Node* value = jsgraph()->UndefinedConstant();
2969   ast_context()->ProduceValue(expr, value);
2970 }
2971 
VisitTypeofExpression(Expression * expr)2972 void AstGraphBuilder::VisitTypeofExpression(Expression* expr) {
2973   if (expr->IsVariableProxy()) {
2974     // Typeof does not throw a reference error on global variables, hence we
2975     // perform a non-contextual load in case the operand is a variable proxy.
2976     VariableProxy* proxy = expr->AsVariableProxy();
2977     VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
2978     PrepareEagerCheckpoint(BeforeId(proxy));
2979     Node* load =
2980         BuildVariableLoad(proxy->var(), expr->id(), pair,
2981                           OutputFrameStateCombine::Push(), INSIDE_TYPEOF);
2982     environment()->Push(load);
2983   } else {
2984     VisitForValue(expr);
2985   }
2986 }
2987 
VisitTypeof(UnaryOperation * expr)2988 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
2989   VisitTypeofExpression(expr->expression());
2990   Node* value = NewNode(javascript()->TypeOf(), environment()->Pop());
2991   ast_context()->ProduceValue(expr, value);
2992 }
2993 
2994 
VisitNot(UnaryOperation * expr)2995 void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
2996   VisitForTest(expr->expression());
2997   Node* input = environment()->Pop();
2998   Node* value = NewNode(common()->Select(MachineRepresentation::kTagged), input,
2999                         jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
3000   // Skip plugging AST evaluation contexts of the test kind. This is to stay in
3001   // sync with full codegen which doesn't prepare the proper bailout point (see
3002   // the implementation of FullCodeGenerator::VisitForControl).
3003   if (ast_context()->IsTest()) return environment()->Push(value);
3004   ast_context()->ProduceValue(expr, value);
3005 }
3006 
3007 
VisitComma(BinaryOperation * expr)3008 void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
3009   VisitForEffect(expr->left());
3010   Visit(expr->right());
3011   // Skip plugging AST evaluation contexts of the test kind. This is to stay in
3012   // sync with full codegen which doesn't prepare the proper bailout point (see
3013   // the implementation of FullCodeGenerator::VisitForControl).
3014   if (ast_context()->IsTest()) return;
3015   ast_context()->ReplaceValue(expr);
3016 }
3017 
3018 
VisitLogicalExpression(BinaryOperation * expr)3019 void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
3020   bool is_logical_and = expr->op() == Token::AND;
3021   IfBuilder compare_if(this);
3022   // Only use an AST evaluation context of the value kind when this expression
3023   // is evaluated as value as well. Otherwise stick to a test context which is
3024   // in sync with full codegen (see FullCodeGenerator::VisitLogicalExpression).
3025   Node* condition = nullptr;
3026   if (ast_context()->IsValue()) {
3027     VisitForValue(expr->left());
3028     Node* left = environment()->Top();
3029     condition = BuildToBoolean(left, expr->left()->test_id());
3030   } else {
3031     VisitForTest(expr->left());
3032     condition = environment()->Top();
3033   }
3034   compare_if.If(condition);
3035   compare_if.Then();
3036   if (is_logical_and) {
3037     environment()->Pop();
3038     Visit(expr->right());
3039   } else if (ast_context()->IsEffect()) {
3040     environment()->Pop();
3041   } else if (ast_context()->IsTest()) {
3042     environment()->Poke(0, jsgraph()->TrueConstant());
3043   }
3044   compare_if.Else();
3045   if (!is_logical_and) {
3046     environment()->Pop();
3047     Visit(expr->right());
3048   } else if (ast_context()->IsEffect()) {
3049     environment()->Pop();
3050   } else if (ast_context()->IsTest()) {
3051     environment()->Poke(0, jsgraph()->FalseConstant());
3052   }
3053   compare_if.End();
3054   // Skip plugging AST evaluation contexts of the test kind. This is to stay in
3055   // sync with full codegen which doesn't prepare the proper bailout point (see
3056   // the implementation of FullCodeGenerator::VisitForControl).
3057   if (ast_context()->IsTest()) return;
3058   ast_context()->ReplaceValue(expr);
3059 }
3060 
3061 
language_mode() const3062 LanguageMode AstGraphBuilder::language_mode() const {
3063   return current_scope()->language_mode();
3064 }
3065 
3066 
CreateVectorSlotPair(FeedbackVectorSlot slot) const3067 VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
3068     FeedbackVectorSlot slot) const {
3069   return VectorSlotPair(handle(info()->closure()->feedback_vector()), slot);
3070 }
3071 
3072 
VisitRewritableExpression(RewritableExpression * node)3073 void AstGraphBuilder::VisitRewritableExpression(RewritableExpression* node) {
3074   Visit(node->expression());
3075 }
3076 
3077 
3078 namespace {
3079 
3080 // Limit of context chain length to which inline check is possible.
3081 const int kMaxCheckDepth = 30;
3082 
3083 // Sentinel for {TryLoadDynamicVariable} disabling inline checks.
3084 const uint32_t kFullCheckRequired = -1;
3085 
3086 }  // namespace
3087 
3088 
ComputeBitsetForDynamicGlobal(Variable * variable)3089 uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) {
3090   DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode());
3091   uint32_t check_depths = 0;
3092   for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3093     if (!s->NeedsContext()) continue;
3094     if (!s->calls_sloppy_eval()) continue;
3095     int depth = current_scope()->ContextChainLength(s);
3096     if (depth > kMaxCheckDepth) return kFullCheckRequired;
3097     check_depths |= 1 << depth;
3098   }
3099   return check_depths;
3100 }
3101 
3102 
ComputeBitsetForDynamicContext(Variable * variable)3103 uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) {
3104   DCHECK_EQ(DYNAMIC_LOCAL, variable->mode());
3105   uint32_t check_depths = 0;
3106   for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3107     if (!s->NeedsContext()) continue;
3108     if (!s->calls_sloppy_eval() && s != variable->scope()) continue;
3109     int depth = current_scope()->ContextChainLength(s);
3110     if (depth > kMaxCheckDepth) return kFullCheckRequired;
3111     check_depths |= 1 << depth;
3112     if (s == variable->scope()) break;
3113   }
3114   return check_depths;
3115 }
3116 
ComputeCallFrequency(FeedbackVectorSlot slot) const3117 float AstGraphBuilder::ComputeCallFrequency(FeedbackVectorSlot slot) const {
3118   if (slot.IsInvalid()) return 0.0f;
3119   Handle<TypeFeedbackVector> feedback_vector(
3120       info()->closure()->feedback_vector(), isolate());
3121   CallICNexus nexus(feedback_vector, slot);
3122   return nexus.ComputeCallFrequency() * invocation_frequency_;
3123 }
3124 
ProcessArguments(const Operator * op,int arity)3125 Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
3126   DCHECK(environment()->stack_height() >= arity);
3127   Node** all = info()->zone()->NewArray<Node*>(arity);
3128   for (int i = arity - 1; i >= 0; --i) {
3129     all[i] = environment()->Pop();
3130   }
3131   Node* value = NewNode(op, arity, all);
3132   return value;
3133 }
3134 
3135 
BuildLocalActivationContext(Node * context)3136 Node* AstGraphBuilder::BuildLocalActivationContext(Node* context) {
3137   DeclarationScope* scope = info()->scope();
3138 
3139   // Allocate a new local context.
3140   Node* local_context = scope->is_script_scope()
3141                             ? BuildLocalScriptContext(scope)
3142                             : BuildLocalFunctionContext(scope);
3143 
3144   if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
3145     Node* receiver = environment()->RawParameterLookup(0);
3146     // Context variable (at bottom of the context chain).
3147     Variable* variable = scope->receiver();
3148     DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
3149     const Operator* op = javascript()->StoreContext(0, variable->index());
3150     NewNode(op, local_context, receiver);
3151   }
3152 
3153   // Copy parameters into context if necessary.
3154   int num_parameters = scope->num_parameters();
3155   for (int i = 0; i < num_parameters; i++) {
3156     Variable* variable = scope->parameter(i);
3157     if (!variable->IsContextSlot()) continue;
3158     Node* parameter = environment()->RawParameterLookup(i + 1);
3159     // Context variable (at bottom of the context chain).
3160     DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
3161     const Operator* op = javascript()->StoreContext(0, variable->index());
3162     NewNode(op, local_context, parameter);
3163   }
3164 
3165   return local_context;
3166 }
3167 
3168 
BuildLocalFunctionContext(Scope * scope)3169 Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) {
3170   DCHECK(scope->is_function_scope() || scope->is_eval_scope());
3171 
3172   // Allocate a new local context.
3173   int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
3174   const Operator* op = javascript()->CreateFunctionContext(slot_count);
3175   Node* local_context = NewNode(op, GetFunctionClosure());
3176 
3177   return local_context;
3178 }
3179 
3180 
BuildLocalScriptContext(Scope * scope)3181 Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) {
3182   DCHECK(scope->is_script_scope());
3183 
3184   // Allocate a new local context.
3185   Handle<ScopeInfo> scope_info = scope->scope_info();
3186   const Operator* op = javascript()->CreateScriptContext(scope_info);
3187   Node* local_context = NewNode(op, GetFunctionClosure());
3188   PrepareFrameState(local_context, BailoutId::ScriptContext(),
3189                     OutputFrameStateCombine::Push());
3190 
3191   return local_context;
3192 }
3193 
3194 
BuildLocalBlockContext(Scope * scope)3195 Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) {
3196   DCHECK(scope->is_block_scope());
3197 
3198   // Allocate a new local context.
3199   Handle<ScopeInfo> scope_info = scope->scope_info();
3200   const Operator* op = javascript()->CreateBlockContext(scope_info);
3201   Node* local_context = NewNode(op, GetFunctionClosureForContext());
3202 
3203   return local_context;
3204 }
3205 
3206 
BuildArgumentsObject(Variable * arguments)3207 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
3208   if (arguments == nullptr) return nullptr;
3209 
3210   // Allocate and initialize a new arguments object.
3211   CreateArgumentsType type =
3212       is_strict(language_mode()) || !info()->has_simple_parameters()
3213           ? CreateArgumentsType::kUnmappedArguments
3214           : CreateArgumentsType::kMappedArguments;
3215   const Operator* op = javascript()->CreateArguments(type);
3216   Node* object = NewNode(op, GetFunctionClosure());
3217   PrepareFrameState(object, BailoutId::None());
3218 
3219   // Assign the object to the {arguments} variable. This should never lazy
3220   // deopt, so it is fine to send invalid bailout id.
3221   DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
3222   BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair(),
3223                           BailoutId::None());
3224   return object;
3225 }
3226 
BuildRestArgumentsArray(Variable * rest)3227 Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest) {
3228   if (rest == nullptr) return nullptr;
3229 
3230   // Allocate and initialize a new arguments object.
3231   CreateArgumentsType type = CreateArgumentsType::kRestParameter;
3232   const Operator* op = javascript()->CreateArguments(type);
3233   Node* object = NewNode(op, GetFunctionClosure());
3234   PrepareFrameState(object, BailoutId::None());
3235 
3236   // Assign the object to the {rest} variable. This should never lazy
3237   // deopt, so it is fine to send invalid bailout id.
3238   DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
3239   BuildVariableAssignment(rest, object, Token::ASSIGN, VectorSlotPair(),
3240                           BailoutId::None());
3241   return object;
3242 }
3243 
3244 
BuildThisFunctionVariable(Variable * this_function_var)3245 Node* AstGraphBuilder::BuildThisFunctionVariable(Variable* this_function_var) {
3246   if (this_function_var == nullptr) return nullptr;
3247 
3248   // Retrieve the closure we were called with.
3249   Node* this_function = GetFunctionClosure();
3250 
3251   // Assign the object to the {.this_function} variable. This should never lazy
3252   // deopt, so it is fine to send invalid bailout id.
3253   BuildVariableAssignment(this_function_var, this_function, Token::INIT,
3254                           VectorSlotPair(), BailoutId::None());
3255   return this_function;
3256 }
3257 
3258 
BuildNewTargetVariable(Variable * new_target_var)3259 Node* AstGraphBuilder::BuildNewTargetVariable(Variable* new_target_var) {
3260   if (new_target_var == nullptr) return nullptr;
3261 
3262   // Retrieve the new target we were called with.
3263   Node* object = GetNewTarget();
3264 
3265   // Assign the object to the {new.target} variable. This should never lazy
3266   // deopt, so it is fine to send invalid bailout id.
3267   BuildVariableAssignment(new_target_var, object, Token::INIT, VectorSlotPair(),
3268                           BailoutId::None());
3269   return object;
3270 }
3271 
3272 
BuildHoleCheckThenThrow(Node * value,Variable * variable,Node * not_hole,BailoutId bailout_id)3273 Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
3274                                                Node* not_hole,
3275                                                BailoutId bailout_id) {
3276   IfBuilder hole_check(this);
3277   Node* the_hole = jsgraph()->TheHoleConstant();
3278   Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
3279                         value, the_hole);
3280   hole_check.If(check);
3281   hole_check.Then();
3282   Node* error = BuildThrowReferenceError(variable, bailout_id);
3283   environment()->Push(error);
3284   hole_check.Else();
3285   environment()->Push(not_hole);
3286   hole_check.End();
3287   return environment()->Pop();
3288 }
3289 
3290 
BuildHoleCheckElseThrow(Node * value,Variable * variable,Node * for_hole,BailoutId bailout_id)3291 Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
3292                                                Node* for_hole,
3293                                                BailoutId bailout_id) {
3294   IfBuilder hole_check(this);
3295   Node* the_hole = jsgraph()->TheHoleConstant();
3296   Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
3297                         value, the_hole);
3298   hole_check.If(check);
3299   hole_check.Then();
3300   environment()->Push(for_hole);
3301   hole_check.Else();
3302   Node* error = BuildThrowReferenceError(variable, bailout_id);
3303   environment()->Push(error);
3304   hole_check.End();
3305   return environment()->Pop();
3306 }
3307 
3308 
BuildThrowIfStaticPrototype(Node * name,BailoutId bailout_id)3309 Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name,
3310                                                    BailoutId bailout_id) {
3311   IfBuilder prototype_check(this);
3312   Node* prototype_string =
3313       jsgraph()->Constant(isolate()->factory()->prototype_string());
3314   Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
3315                         name, prototype_string);
3316   prototype_check.If(check);
3317   prototype_check.Then();
3318   Node* error = BuildThrowStaticPrototypeError(bailout_id);
3319   environment()->Push(error);
3320   prototype_check.Else();
3321   environment()->Push(name);
3322   prototype_check.End();
3323   return environment()->Pop();
3324 }
3325 
3326 
BuildVariableLoad(Variable * variable,BailoutId bailout_id,const VectorSlotPair & feedback,OutputFrameStateCombine combine,TypeofMode typeof_mode)3327 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
3328                                          BailoutId bailout_id,
3329                                          const VectorSlotPair& feedback,
3330                                          OutputFrameStateCombine combine,
3331                                          TypeofMode typeof_mode) {
3332   Node* the_hole = jsgraph()->TheHoleConstant();
3333   switch (variable->location()) {
3334     case VariableLocation::UNALLOCATED: {
3335       // Global var, const, or let variable.
3336       Handle<Name> name = variable->name();
3337       if (Node* node = TryLoadGlobalConstant(name)) return node;
3338       Node* value = BuildGlobalLoad(name, feedback, typeof_mode);
3339       PrepareFrameState(value, bailout_id, combine);
3340       return value;
3341     }
3342     case VariableLocation::PARAMETER:
3343     case VariableLocation::LOCAL: {
3344       // Local var, const, or let variable.
3345       Node* value = environment()->Lookup(variable);
3346       if (variable->binding_needs_init()) {
3347         // Perform check for uninitialized let/const variables.
3348         if (value->op() == the_hole->op()) {
3349           value = BuildThrowReferenceError(variable, bailout_id);
3350         } else if (value->opcode() == IrOpcode::kPhi) {
3351           value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
3352         }
3353       }
3354       return value;
3355     }
3356     case VariableLocation::CONTEXT: {
3357       // Context variable (potentially up the context chain).
3358       int depth = current_scope()->ContextChainLength(variable->scope());
3359       // TODO(mstarzinger): The {maybe_assigned} flag computed during variable
3360       // resolution is highly inaccurate and cannot be trusted. We are only
3361       // taking this information into account when asm.js compilation is used.
3362       bool immutable = variable->maybe_assigned() == kNotAssigned &&
3363                        info()->is_function_context_specializing();
3364       const Operator* op =
3365           javascript()->LoadContext(depth, variable->index(), immutable);
3366       Node* value = NewNode(op, current_context());
3367       // TODO(titzer): initialization checks are redundant for already
3368       // initialized immutable context loads, but only specialization knows.
3369       // Maybe specializer should be a parameter to the graph builder?
3370       if (variable->binding_needs_init()) {
3371         // Perform check for uninitialized let/const variables.
3372         value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
3373       }
3374       return value;
3375     }
3376     case VariableLocation::LOOKUP: {
3377       // Dynamic lookup of context variable (anywhere in the chain).
3378       Handle<String> name = variable->name();
3379       if (Node* node = TryLoadDynamicVariable(variable, name, bailout_id,
3380                                               feedback, combine, typeof_mode)) {
3381         return node;
3382       }
3383       Node* value = BuildDynamicLoad(name, typeof_mode);
3384       PrepareFrameState(value, bailout_id, combine);
3385       return value;
3386     }
3387     case VariableLocation::MODULE:
3388       UNREACHABLE();
3389   }
3390   UNREACHABLE();
3391   return nullptr;
3392 }
3393 
3394 
BuildVariableDelete(Variable * variable,BailoutId bailout_id,OutputFrameStateCombine combine)3395 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
3396                                            BailoutId bailout_id,
3397                                            OutputFrameStateCombine combine) {
3398   switch (variable->location()) {
3399     case VariableLocation::UNALLOCATED: {
3400       // Global var, const, or let variable.
3401       Node* global = BuildLoadGlobalObject();
3402       Node* name = jsgraph()->Constant(variable->name());
3403       const Operator* op = javascript()->DeleteProperty(language_mode());
3404       Node* result = NewNode(op, global, name);
3405       PrepareFrameState(result, bailout_id, combine);
3406       return result;
3407     }
3408     case VariableLocation::PARAMETER:
3409     case VariableLocation::LOCAL:
3410     case VariableLocation::CONTEXT: {
3411       // Local var, const, or let variable or context variable.
3412       return jsgraph()->BooleanConstant(variable->is_this());
3413     }
3414     case VariableLocation::LOOKUP: {
3415       // Dynamic lookup of context variable (anywhere in the chain).
3416       Node* name = jsgraph()->Constant(variable->name());
3417       const Operator* op =
3418           javascript()->CallRuntime(Runtime::kDeleteLookupSlot);
3419       Node* result = NewNode(op, name);
3420       PrepareFrameState(result, bailout_id, combine);
3421       return result;
3422     }
3423     case VariableLocation::MODULE:
3424       UNREACHABLE();
3425   }
3426   UNREACHABLE();
3427   return nullptr;
3428 }
3429 
BuildVariableAssignment(Variable * variable,Node * value,Token::Value op,const VectorSlotPair & feedback,BailoutId bailout_id,OutputFrameStateCombine combine)3430 Node* AstGraphBuilder::BuildVariableAssignment(
3431     Variable* variable, Node* value, Token::Value op,
3432     const VectorSlotPair& feedback, BailoutId bailout_id,
3433     OutputFrameStateCombine combine) {
3434   Node* the_hole = jsgraph()->TheHoleConstant();
3435   VariableMode mode = variable->mode();
3436   switch (variable->location()) {
3437     case VariableLocation::UNALLOCATED: {
3438       // Global var, const, or let variable.
3439       Handle<Name> name = variable->name();
3440       Node* store = BuildGlobalStore(name, value, feedback);
3441       PrepareFrameState(store, bailout_id, combine);
3442       return store;
3443     }
3444     case VariableLocation::PARAMETER:
3445     case VariableLocation::LOCAL:
3446       // Local var, const, or let variable.
3447       if (mode == LET && op == Token::INIT) {
3448         // No initialization check needed because scoping guarantees it. Note
3449         // that we still perform a lookup to keep the variable live, because
3450         // baseline code might contain debug code that inspects the variable.
3451         Node* current = environment()->Lookup(variable);
3452         CHECK_NOT_NULL(current);
3453       } else if (mode == LET && op != Token::INIT &&
3454                  variable->binding_needs_init()) {
3455         // Perform an initialization check for let declared variables.
3456         Node* current = environment()->Lookup(variable);
3457         if (current->op() == the_hole->op()) {
3458           return BuildThrowReferenceError(variable, bailout_id);
3459         } else if (current->opcode() == IrOpcode::kPhi) {
3460           BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3461         }
3462       } else if (mode == CONST && op == Token::INIT) {
3463         // Perform an initialization check for const {this} variables.
3464         // Note that the {this} variable is the only const variable being able
3465         // to trigger bind operations outside the TDZ, via {super} calls.
3466         Node* current = environment()->Lookup(variable);
3467         if (current->op() != the_hole->op() && variable->is_this()) {
3468           value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3469         }
3470       } else if (mode == CONST && op != Token::INIT &&
3471                  variable->is_sloppy_function_name()) {
3472         // Non-initializing assignment to sloppy function names is
3473         // - exception in strict mode.
3474         // - ignored in sloppy mode.
3475         DCHECK(!variable->binding_needs_init());
3476         if (variable->throw_on_const_assignment(language_mode())) {
3477           return BuildThrowConstAssignError(bailout_id);
3478         }
3479         return value;
3480       } else if (mode == CONST && op != Token::INIT) {
3481         if (variable->binding_needs_init()) {
3482           Node* current = environment()->Lookup(variable);
3483           if (current->op() == the_hole->op()) {
3484             return BuildThrowReferenceError(variable, bailout_id);
3485           } else if (current->opcode() == IrOpcode::kPhi) {
3486             BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3487           }
3488         }
3489         // Assignment to const is exception in all modes.
3490         return BuildThrowConstAssignError(bailout_id);
3491       }
3492       environment()->Bind(variable, value);
3493       return value;
3494     case VariableLocation::CONTEXT: {
3495       // Context variable (potentially up the context chain).
3496       int depth = current_scope()->ContextChainLength(variable->scope());
3497       if (mode == LET && op != Token::INIT && variable->binding_needs_init()) {
3498         // Perform an initialization check for let declared variables.
3499         const Operator* op =
3500             javascript()->LoadContext(depth, variable->index(), false);
3501         Node* current = NewNode(op, current_context());
3502         value = BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3503       } else if (mode == CONST && op == Token::INIT) {
3504         // Perform an initialization check for const {this} variables.
3505         // Note that the {this} variable is the only const variable being able
3506         // to trigger bind operations outside the TDZ, via {super} calls.
3507         if (variable->is_this()) {
3508           const Operator* op =
3509               javascript()->LoadContext(depth, variable->index(), false);
3510           Node* current = NewNode(op, current_context());
3511           value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3512         }
3513       } else if (mode == CONST && op != Token::INIT &&
3514                  variable->is_sloppy_function_name()) {
3515         // Non-initializing assignment to sloppy function names is
3516         // - exception in strict mode.
3517         // - ignored in sloppy mode.
3518         DCHECK(!variable->binding_needs_init());
3519         if (variable->throw_on_const_assignment(language_mode())) {
3520           return BuildThrowConstAssignError(bailout_id);
3521         }
3522         return value;
3523       } else if (mode == CONST && op != Token::INIT) {
3524         if (variable->binding_needs_init()) {
3525           const Operator* op =
3526               javascript()->LoadContext(depth, variable->index(), false);
3527           Node* current = NewNode(op, current_context());
3528           BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3529         }
3530         // Assignment to const is exception in all modes.
3531         return BuildThrowConstAssignError(bailout_id);
3532       }
3533       const Operator* op = javascript()->StoreContext(depth, variable->index());
3534       return NewNode(op, current_context(), value);
3535     }
3536     case VariableLocation::LOOKUP: {
3537       // Dynamic lookup of context variable (anywhere in the chain).
3538       Handle<Name> name = variable->name();
3539       Node* store = BuildDynamicStore(name, value);
3540       PrepareFrameState(store, bailout_id, combine);
3541       return store;
3542     }
3543     case VariableLocation::MODULE:
3544       UNREACHABLE();
3545   }
3546   UNREACHABLE();
3547   return nullptr;
3548 }
3549 
3550 
BuildKeyedLoad(Node * object,Node * key,const VectorSlotPair & feedback)3551 Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
3552                                       const VectorSlotPair& feedback) {
3553   const Operator* op = javascript()->LoadProperty(feedback);
3554   Node* node = NewNode(op, object, key, GetFunctionClosure());
3555   return node;
3556 }
3557 
3558 
BuildNamedLoad(Node * object,Handle<Name> name,const VectorSlotPair & feedback)3559 Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
3560                                       const VectorSlotPair& feedback) {
3561   const Operator* op = javascript()->LoadNamed(name, feedback);
3562   Node* node = NewNode(op, object, GetFunctionClosure());
3563   return node;
3564 }
3565 
3566 
BuildKeyedStore(Node * object,Node * key,Node * value,const VectorSlotPair & feedback)3567 Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
3568                                        const VectorSlotPair& feedback) {
3569   const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
3570   Node* node = NewNode(op, object, key, value, GetFunctionClosure());
3571   return node;
3572 }
3573 
3574 
BuildNamedStore(Node * object,Handle<Name> name,Node * value,const VectorSlotPair & feedback)3575 Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
3576                                        Node* value,
3577                                        const VectorSlotPair& feedback) {
3578   const Operator* op =
3579       javascript()->StoreNamed(language_mode(), name, feedback);
3580   Node* node = NewNode(op, object, value, GetFunctionClosure());
3581   return node;
3582 }
3583 
3584 
BuildNamedSuperLoad(Node * receiver,Node * home_object,Handle<Name> name,const VectorSlotPair & feedback)3585 Node* AstGraphBuilder::BuildNamedSuperLoad(Node* receiver, Node* home_object,
3586                                            Handle<Name> name,
3587                                            const VectorSlotPair& feedback) {
3588   Node* name_node = jsgraph()->Constant(name);
3589   const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper);
3590   Node* node = NewNode(op, receiver, home_object, name_node);
3591   return node;
3592 }
3593 
3594 
BuildKeyedSuperLoad(Node * receiver,Node * home_object,Node * key,const VectorSlotPair & feedback)3595 Node* AstGraphBuilder::BuildKeyedSuperLoad(Node* receiver, Node* home_object,
3596                                            Node* key,
3597                                            const VectorSlotPair& feedback) {
3598   const Operator* op = javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper);
3599   Node* node = NewNode(op, receiver, home_object, key);
3600   return node;
3601 }
3602 
3603 
BuildKeyedSuperStore(Node * receiver,Node * home_object,Node * key,Node * value)3604 Node* AstGraphBuilder::BuildKeyedSuperStore(Node* receiver, Node* home_object,
3605                                             Node* key, Node* value) {
3606   Runtime::FunctionId function_id = is_strict(language_mode())
3607                                         ? Runtime::kStoreKeyedToSuper_Strict
3608                                         : Runtime::kStoreKeyedToSuper_Sloppy;
3609   const Operator* op = javascript()->CallRuntime(function_id, 4);
3610   Node* node = NewNode(op, receiver, home_object, key, value);
3611   return node;
3612 }
3613 
3614 
BuildNamedSuperStore(Node * receiver,Node * home_object,Handle<Name> name,Node * value)3615 Node* AstGraphBuilder::BuildNamedSuperStore(Node* receiver, Node* home_object,
3616                                             Handle<Name> name, Node* value) {
3617   Node* name_node = jsgraph()->Constant(name);
3618   Runtime::FunctionId function_id = is_strict(language_mode())
3619                                         ? Runtime::kStoreToSuper_Strict
3620                                         : Runtime::kStoreToSuper_Sloppy;
3621   const Operator* op = javascript()->CallRuntime(function_id, 4);
3622   Node* node = NewNode(op, receiver, home_object, name_node, value);
3623   return node;
3624 }
3625 
3626 
BuildGlobalLoad(Handle<Name> name,const VectorSlotPair & feedback,TypeofMode typeof_mode)3627 Node* AstGraphBuilder::BuildGlobalLoad(Handle<Name> name,
3628                                        const VectorSlotPair& feedback,
3629                                        TypeofMode typeof_mode) {
3630   const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
3631   Node* node = NewNode(op, GetFunctionClosure());
3632   return node;
3633 }
3634 
3635 
BuildGlobalStore(Handle<Name> name,Node * value,const VectorSlotPair & feedback)3636 Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value,
3637                                         const VectorSlotPair& feedback) {
3638   const Operator* op =
3639       javascript()->StoreGlobal(language_mode(), name, feedback);
3640   Node* node = NewNode(op, value, GetFunctionClosure());
3641   return node;
3642 }
3643 
3644 
BuildDynamicLoad(Handle<Name> name,TypeofMode typeof_mode)3645 Node* AstGraphBuilder::BuildDynamicLoad(Handle<Name> name,
3646                                         TypeofMode typeof_mode) {
3647   Node* name_node = jsgraph()->Constant(name);
3648   const Operator* op =
3649       javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
3650                                     ? Runtime::kLoadLookupSlot
3651                                     : Runtime::kLoadLookupSlotInsideTypeof);
3652   Node* node = NewNode(op, name_node);
3653   return node;
3654 }
3655 
3656 
BuildDynamicStore(Handle<Name> name,Node * value)3657 Node* AstGraphBuilder::BuildDynamicStore(Handle<Name> name, Node* value) {
3658   Node* name_node = jsgraph()->Constant(name);
3659   const Operator* op = javascript()->CallRuntime(
3660       is_strict(language_mode()) ? Runtime::kStoreLookupSlot_Strict
3661                                  : Runtime::kStoreLookupSlot_Sloppy);
3662   Node* node = NewNode(op, name_node, value);
3663   return node;
3664 }
3665 
3666 
BuildLoadGlobalObject()3667 Node* AstGraphBuilder::BuildLoadGlobalObject() {
3668   return BuildLoadNativeContextField(Context::EXTENSION_INDEX);
3669 }
3670 
3671 
BuildLoadNativeContextField(int index)3672 Node* AstGraphBuilder::BuildLoadNativeContextField(int index) {
3673   const Operator* op =
3674       javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
3675   Node* native_context = NewNode(op, current_context());
3676   return NewNode(javascript()->LoadContext(0, index, true), native_context);
3677 }
3678 
3679 
BuildToBoolean(Node * input,TypeFeedbackId feedback_id)3680 Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) {
3681   if (Node* node = TryFastToBoolean(input)) return node;
3682   ToBooleanHints hints;
3683   if (!type_hint_analysis_ ||
3684       !type_hint_analysis_->GetToBooleanHints(feedback_id, &hints)) {
3685     hints = ToBooleanHint::kAny;
3686   }
3687   return NewNode(javascript()->ToBoolean(hints), input);
3688 }
3689 
3690 
BuildToName(Node * input,BailoutId bailout_id)3691 Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) {
3692   if (Node* node = TryFastToName(input)) return node;
3693   Node* name = NewNode(javascript()->ToName(), input);
3694   PrepareFrameState(name, bailout_id, OutputFrameStateCombine::Push());
3695   return name;
3696 }
3697 
3698 
BuildToObject(Node * input,BailoutId bailout_id)3699 Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
3700   Node* object = NewNode(javascript()->ToObject(), input);
3701   PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push());
3702   return object;
3703 }
3704 
BuildSetHomeObject(Node * value,Node * home_object,LiteralProperty * property,int slot_number)3705 Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
3706                                           LiteralProperty* property,
3707                                           int slot_number) {
3708   Expression* expr = property->value();
3709   if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
3710   Handle<Name> name = isolate()->factory()->home_object_symbol();
3711   VectorSlotPair feedback =
3712       CreateVectorSlotPair(property->GetSlot(slot_number));
3713   Node* store = BuildNamedStore(value, name, home_object, feedback);
3714   PrepareFrameState(store, BailoutId::None(),
3715                     OutputFrameStateCombine::Ignore());
3716   return store;
3717 }
3718 
3719 
BuildThrowError(Node * exception,BailoutId bailout_id)3720 Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) {
3721   const Operator* op = javascript()->CallRuntime(Runtime::kThrow);
3722   Node* call = NewNode(op, exception);
3723   PrepareFrameState(call, bailout_id);
3724   Node* control = NewNode(common()->Throw(), call);
3725   UpdateControlDependencyToLeaveFunction(control);
3726   return call;
3727 }
3728 
3729 
BuildThrowReferenceError(Variable * variable,BailoutId bailout_id)3730 Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
3731                                                 BailoutId bailout_id) {
3732   Node* variable_name = jsgraph()->Constant(variable->name());
3733   const Operator* op = javascript()->CallRuntime(Runtime::kThrowReferenceError);
3734   Node* call = NewNode(op, variable_name);
3735   PrepareFrameState(call, bailout_id);
3736   Node* control = NewNode(common()->Throw(), call);
3737   UpdateControlDependencyToLeaveFunction(control);
3738   return call;
3739 }
3740 
3741 
BuildThrowConstAssignError(BailoutId bailout_id)3742 Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
3743   const Operator* op =
3744       javascript()->CallRuntime(Runtime::kThrowConstAssignError);
3745   Node* call = NewNode(op);
3746   PrepareFrameState(call, bailout_id);
3747   Node* control = NewNode(common()->Throw(), call);
3748   UpdateControlDependencyToLeaveFunction(control);
3749   return call;
3750 }
3751 
3752 
BuildThrowStaticPrototypeError(BailoutId bailout_id)3753 Node* AstGraphBuilder::BuildThrowStaticPrototypeError(BailoutId bailout_id) {
3754   const Operator* op =
3755       javascript()->CallRuntime(Runtime::kThrowStaticPrototypeError);
3756   Node* call = NewNode(op);
3757   PrepareFrameState(call, bailout_id);
3758   Node* control = NewNode(common()->Throw(), call);
3759   UpdateControlDependencyToLeaveFunction(control);
3760   return call;
3761 }
3762 
3763 
BuildThrowUnsupportedSuperError(BailoutId bailout_id)3764 Node* AstGraphBuilder::BuildThrowUnsupportedSuperError(BailoutId bailout_id) {
3765   const Operator* op =
3766       javascript()->CallRuntime(Runtime::kThrowUnsupportedSuperError);
3767   Node* call = NewNode(op);
3768   PrepareFrameState(call, bailout_id);
3769   Node* control = NewNode(common()->Throw(), call);
3770   UpdateControlDependencyToLeaveFunction(control);
3771   return call;
3772 }
3773 
3774 
BuildReturn(Node * return_value)3775 Node* AstGraphBuilder::BuildReturn(Node* return_value) {
3776   // Emit tracing call if requested to do so.
3777   if (FLAG_trace) {
3778     return_value =
3779         NewNode(javascript()->CallRuntime(Runtime::kTraceExit), return_value);
3780   }
3781   Node* pop_node = jsgraph()->ZeroConstant();
3782   Node* control = NewNode(common()->Return(), pop_node, return_value);
3783   UpdateControlDependencyToLeaveFunction(control);
3784   return control;
3785 }
3786 
3787 
BuildThrow(Node * exception_value)3788 Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
3789   NewNode(javascript()->CallRuntime(Runtime::kReThrow), exception_value);
3790   Node* control = NewNode(common()->Throw(), exception_value);
3791   UpdateControlDependencyToLeaveFunction(control);
3792   return control;
3793 }
3794 
3795 
BuildBinaryOp(Node * left,Node * right,Token::Value op,TypeFeedbackId feedback_id)3796 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op,
3797                                      TypeFeedbackId feedback_id) {
3798   const Operator* js_op;
3799   BinaryOperationHint hint;
3800   if (!type_hint_analysis_ ||
3801       !type_hint_analysis_->GetBinaryOperationHint(feedback_id, &hint)) {
3802     hint = BinaryOperationHint::kAny;
3803   }
3804   switch (op) {
3805     case Token::BIT_OR:
3806       js_op = javascript()->BitwiseOr(hint);
3807       break;
3808     case Token::BIT_AND:
3809       js_op = javascript()->BitwiseAnd(hint);
3810       break;
3811     case Token::BIT_XOR:
3812       js_op = javascript()->BitwiseXor(hint);
3813       break;
3814     case Token::SHL:
3815       js_op = javascript()->ShiftLeft(hint);
3816       break;
3817     case Token::SAR:
3818       js_op = javascript()->ShiftRight(hint);
3819       break;
3820     case Token::SHR:
3821       js_op = javascript()->ShiftRightLogical(hint);
3822       break;
3823     case Token::ADD:
3824       js_op = javascript()->Add(hint);
3825       break;
3826     case Token::SUB:
3827       js_op = javascript()->Subtract(hint);
3828       break;
3829     case Token::MUL:
3830       js_op = javascript()->Multiply(hint);
3831       break;
3832     case Token::DIV:
3833       js_op = javascript()->Divide(hint);
3834       break;
3835     case Token::MOD:
3836       js_op = javascript()->Modulus(hint);
3837       break;
3838     default:
3839       UNREACHABLE();
3840       js_op = nullptr;
3841   }
3842   return NewNode(js_op, left, right);
3843 }
3844 
3845 
TryLoadGlobalConstant(Handle<Name> name)3846 Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) {
3847   // Optimize global constants like "undefined", "Infinity", and "NaN".
3848   Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name);
3849   if (!constant_value.is_null()) return jsgraph()->Constant(constant_value);
3850   return nullptr;
3851 }
3852 
TryLoadDynamicVariable(Variable * variable,Handle<String> name,BailoutId bailout_id,const VectorSlotPair & feedback,OutputFrameStateCombine combine,TypeofMode typeof_mode)3853 Node* AstGraphBuilder::TryLoadDynamicVariable(Variable* variable,
3854                                               Handle<String> name,
3855                                               BailoutId bailout_id,
3856                                               const VectorSlotPair& feedback,
3857                                               OutputFrameStateCombine combine,
3858                                               TypeofMode typeof_mode) {
3859   VariableMode mode = variable->mode();
3860 
3861   if (mode == DYNAMIC_GLOBAL) {
3862     uint32_t bitset = ComputeBitsetForDynamicGlobal(variable);
3863     if (bitset == kFullCheckRequired) return nullptr;
3864 
3865     // We are using two blocks to model fast and slow cases.
3866     BlockBuilder fast_block(this);
3867     BlockBuilder slow_block(this);
3868     environment()->Push(jsgraph()->TheHoleConstant());
3869     slow_block.BeginBlock();
3870     environment()->Pop();
3871     fast_block.BeginBlock();
3872 
3873     // Perform checks whether the fast mode applies, by looking for any
3874     // extension object which might shadow the optimistic declaration.
3875     for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3876       if ((bitset & 1) == 0) continue;
3877       Node* load = NewNode(
3878           javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3879           current_context());
3880       Node* check =
3881           NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), load,
3882                   jsgraph()->TheHoleConstant());
3883       fast_block.BreakUnless(check, BranchHint::kTrue);
3884     }
3885 
3886     // Fast case, because variable is not shadowed.
3887     if (Node* constant = TryLoadGlobalConstant(name)) {
3888       environment()->Push(constant);
3889     } else {
3890       // Perform global slot load.
3891       Node* fast = BuildGlobalLoad(name, feedback, typeof_mode);
3892       PrepareFrameState(fast, bailout_id, combine);
3893       environment()->Push(fast);
3894     }
3895     slow_block.Break();
3896     environment()->Pop();
3897     fast_block.EndBlock();
3898 
3899     // Slow case, because variable potentially shadowed. Perform dynamic lookup.
3900     Node* slow = BuildDynamicLoad(name, typeof_mode);
3901     PrepareFrameState(slow, bailout_id, combine);
3902     environment()->Push(slow);
3903     slow_block.EndBlock();
3904 
3905     return environment()->Pop();
3906   }
3907 
3908   if (mode == DYNAMIC_LOCAL) {
3909     uint32_t bitset = ComputeBitsetForDynamicContext(variable);
3910     if (bitset == kFullCheckRequired) return nullptr;
3911 
3912     // We are using two blocks to model fast and slow cases.
3913     BlockBuilder fast_block(this);
3914     BlockBuilder slow_block(this);
3915     environment()->Push(jsgraph()->TheHoleConstant());
3916     slow_block.BeginBlock();
3917     environment()->Pop();
3918     fast_block.BeginBlock();
3919 
3920     // Perform checks whether the fast mode applies, by looking for any
3921     // extension object which might shadow the optimistic declaration.
3922     for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3923       if ((bitset & 1) == 0) continue;
3924       Node* load = NewNode(
3925           javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3926           current_context());
3927       Node* check =
3928           NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), load,
3929                   jsgraph()->TheHoleConstant());
3930       fast_block.BreakUnless(check, BranchHint::kTrue);
3931     }
3932 
3933     // Fast case, because variable is not shadowed. Perform context slot load.
3934     Variable* local = variable->local_if_not_shadowed();
3935     DCHECK(local->location() == VariableLocation::CONTEXT);  // Must be context.
3936     Node* fast =
3937         BuildVariableLoad(local, bailout_id, feedback, combine, typeof_mode);
3938     environment()->Push(fast);
3939     slow_block.Break();
3940     environment()->Pop();
3941     fast_block.EndBlock();
3942 
3943     // Slow case, because variable potentially shadowed. Perform dynamic lookup.
3944     Node* slow = BuildDynamicLoad(name, typeof_mode);
3945     PrepareFrameState(slow, bailout_id, combine);
3946     environment()->Push(slow);
3947     slow_block.EndBlock();
3948 
3949     return environment()->Pop();
3950   }
3951 
3952   return nullptr;
3953 }
3954 
3955 
TryFastToBoolean(Node * input)3956 Node* AstGraphBuilder::TryFastToBoolean(Node* input) {
3957   switch (input->opcode()) {
3958     case IrOpcode::kNumberConstant: {
3959       NumberMatcher m(input);
3960       return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN());
3961     }
3962     case IrOpcode::kHeapConstant: {
3963       Handle<HeapObject> object = HeapObjectMatcher(input).Value();
3964       return jsgraph_->BooleanConstant(object->BooleanValue());
3965     }
3966     case IrOpcode::kJSEqual:
3967     case IrOpcode::kJSNotEqual:
3968     case IrOpcode::kJSStrictEqual:
3969     case IrOpcode::kJSStrictNotEqual:
3970     case IrOpcode::kJSLessThan:
3971     case IrOpcode::kJSLessThanOrEqual:
3972     case IrOpcode::kJSGreaterThan:
3973     case IrOpcode::kJSGreaterThanOrEqual:
3974     case IrOpcode::kJSToBoolean:
3975     case IrOpcode::kJSDeleteProperty:
3976     case IrOpcode::kJSHasProperty:
3977     case IrOpcode::kJSInstanceOf:
3978       return input;
3979     default:
3980       break;
3981   }
3982   return nullptr;
3983 }
3984 
3985 
TryFastToName(Node * input)3986 Node* AstGraphBuilder::TryFastToName(Node* input) {
3987   switch (input->opcode()) {
3988     case IrOpcode::kHeapConstant: {
3989       Handle<HeapObject> object = HeapObjectMatcher(input).Value();
3990       if (object->IsName()) return input;
3991       break;
3992     }
3993     case IrOpcode::kJSToString:
3994     case IrOpcode::kJSToName:
3995     case IrOpcode::kJSTypeOf:
3996       return input;
3997     default:
3998       break;
3999   }
4000   return nullptr;
4001 }
4002 
4003 
CheckOsrEntry(IterationStatement * stmt)4004 bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
4005   if (info()->osr_ast_id() == stmt->OsrEntryId()) {
4006     DCHECK_EQ(-1, info()->osr_expr_stack_height());
4007     info()->set_osr_expr_stack_height(environment()->stack_height());
4008     return true;
4009   }
4010   return false;
4011 }
4012 
4013 
PrepareFrameState(Node * node,BailoutId ast_id,OutputFrameStateCombine combine)4014 void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
4015                                         OutputFrameStateCombine combine) {
4016   if (OperatorProperties::HasFrameStateInput(node->op())) {
4017     DCHECK(ast_id.IsNone() || info()->shared_info()->VerifyBailoutId(ast_id));
4018     DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
4019     DCHECK_EQ(IrOpcode::kDead,
4020               NodeProperties::GetFrameStateInput(node)->opcode());
4021     bool has_exception = NodeProperties::IsExceptionalCall(node);
4022     Node* state = environment()->Checkpoint(ast_id, combine, has_exception);
4023     NodeProperties::ReplaceFrameStateInput(node, state);
4024   }
4025 }
4026 
PrepareEagerCheckpoint(BailoutId ast_id)4027 void AstGraphBuilder::PrepareEagerCheckpoint(BailoutId ast_id) {
4028   if (environment()->GetEffectDependency()->opcode() == IrOpcode::kCheckpoint) {
4029     // We skip preparing a checkpoint if there already is one the current effect
4030     // dependency. This is just an optimization and not need for correctness.
4031     return;
4032   }
4033   if (ast_id != BailoutId::None()) {
4034     DCHECK(info()->shared_info()->VerifyBailoutId(ast_id));
4035     Node* node = NewNode(common()->Checkpoint());
4036     DCHECK_EQ(IrOpcode::kDead,
4037               NodeProperties::GetFrameStateInput(node)->opcode());
4038     Node* state = environment()->Checkpoint(ast_id);
4039     NodeProperties::ReplaceFrameStateInput(node, state);
4040   }
4041 }
4042 
GetVariablesAssignedInLoop(IterationStatement * stmt)4043 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
4044     IterationStatement* stmt) {
4045   if (loop_assignment_analysis_ == nullptr) return nullptr;
4046   return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt);
4047 }
4048 
4049 
EnsureInputBufferSize(int size)4050 Node** AstGraphBuilder::EnsureInputBufferSize(int size) {
4051   if (size > input_buffer_size_) {
4052     size = size + kInputBufferSizeIncrement + input_buffer_size_;
4053     input_buffer_ = local_zone()->NewArray<Node*>(size);
4054     input_buffer_size_ = size;
4055   }
4056   return input_buffer_;
4057 }
4058 
4059 
MakeNode(const Operator * op,int value_input_count,Node ** value_inputs,bool incomplete)4060 Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
4061                                 Node** value_inputs, bool incomplete) {
4062   DCHECK_EQ(op->ValueInputCount(), value_input_count);
4063 
4064   bool has_context = OperatorProperties::HasContextInput(op);
4065   bool has_frame_state = OperatorProperties::HasFrameStateInput(op);
4066   bool has_control = op->ControlInputCount() == 1;
4067   bool has_effect = op->EffectInputCount() == 1;
4068 
4069   DCHECK(op->ControlInputCount() < 2);
4070   DCHECK(op->EffectInputCount() < 2);
4071 
4072   Node* result = nullptr;
4073   if (!has_context && !has_frame_state && !has_control && !has_effect) {
4074     result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
4075   } else {
4076     bool inside_try_scope = try_nesting_level_ > 0;
4077     int input_count_with_deps = value_input_count;
4078     if (has_context) ++input_count_with_deps;
4079     if (has_frame_state) ++input_count_with_deps;
4080     if (has_control) ++input_count_with_deps;
4081     if (has_effect) ++input_count_with_deps;
4082     Node** buffer = EnsureInputBufferSize(input_count_with_deps);
4083     memcpy(buffer, value_inputs, kPointerSize * value_input_count);
4084     Node** current_input = buffer + value_input_count;
4085     if (has_context) {
4086       *current_input++ = current_context();
4087     }
4088     if (has_frame_state) {
4089       // The frame state will be inserted later. Here we misuse
4090       // the {Dead} node as a sentinel to be later overwritten
4091       // with the real frame state.
4092       *current_input++ = jsgraph()->Dead();
4093     }
4094     if (has_effect) {
4095       *current_input++ = environment_->GetEffectDependency();
4096     }
4097     if (has_control) {
4098       *current_input++ = environment_->GetControlDependency();
4099     }
4100     result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
4101     if (!environment()->IsMarkedAsUnreachable()) {
4102       // Update the current control dependency for control-producing nodes.
4103       if (NodeProperties::IsControl(result)) {
4104         environment_->UpdateControlDependency(result);
4105       }
4106       // Update the current effect dependency for effect-producing nodes.
4107       if (result->op()->EffectOutputCount() > 0) {
4108         environment_->UpdateEffectDependency(result);
4109       }
4110       // Add implicit exception continuation for throwing nodes.
4111       if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) {
4112         // Copy the environment for the success continuation.
4113         Environment* success_env = environment()->CopyForConditional();
4114         const Operator* op = common()->IfException();
4115         Node* effect = environment()->GetEffectDependency();
4116         Node* on_exception = graph()->NewNode(op, effect, result);
4117         environment_->UpdateControlDependency(on_exception);
4118         environment_->UpdateEffectDependency(on_exception);
4119         execution_control()->ThrowValue(on_exception);
4120         set_environment(success_env);
4121       }
4122       // Add implicit success continuation for throwing nodes.
4123       if (!result->op()->HasProperty(Operator::kNoThrow)) {
4124         const Operator* op = common()->IfSuccess();
4125         Node* on_success = graph()->NewNode(op, result);
4126         environment_->UpdateControlDependency(on_success);
4127       }
4128     }
4129   }
4130 
4131   return result;
4132 }
4133 
4134 
UpdateControlDependencyToLeaveFunction(Node * exit)4135 void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
4136   if (environment()->IsMarkedAsUnreachable()) return;
4137   environment()->MarkAsUnreachable();
4138   exit_controls_.push_back(exit);
4139 }
4140 
4141 
Merge(Environment * other)4142 void AstGraphBuilder::Environment::Merge(Environment* other) {
4143   DCHECK(values_.size() == other->values_.size());
4144   DCHECK(contexts_.size() == other->contexts_.size());
4145 
4146   // Nothing to do if the other environment is dead.
4147   if (other->IsMarkedAsUnreachable()) return;
4148 
4149   // Resurrect a dead environment by copying the contents of the other one and
4150   // placing a singleton merge as the new control dependency.
4151   if (this->IsMarkedAsUnreachable()) {
4152     Node* other_control = other->control_dependency_;
4153     Node* inputs[] = {other_control};
4154     control_dependency_ =
4155         graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
4156     effect_dependency_ = other->effect_dependency_;
4157     values_ = other->values_;
4158     contexts_ = other->contexts_;
4159     if (IsLivenessAnalysisEnabled()) {
4160       liveness_block_ =
4161           builder_->liveness_analyzer()->NewBlock(other->liveness_block());
4162     }
4163     return;
4164   }
4165 
4166   // Record the merge for the local variable liveness calculation.
4167   // For loops, we are connecting a back edge into the existing block;
4168   // for merges, we create a new merged block.
4169   if (IsLivenessAnalysisEnabled()) {
4170     if (GetControlDependency()->opcode() != IrOpcode::kLoop) {
4171       liveness_block_ =
4172           builder_->liveness_analyzer()->NewBlock(liveness_block());
4173     }
4174     liveness_block()->AddPredecessor(other->liveness_block());
4175   }
4176 
4177   // Create a merge of the control dependencies of both environments and update
4178   // the current environment's control dependency accordingly.
4179   Node* control = builder_->MergeControl(this->GetControlDependency(),
4180                                          other->GetControlDependency());
4181   UpdateControlDependency(control);
4182 
4183   // Create a merge of the effect dependencies of both environments and update
4184   // the current environment's effect dependency accordingly.
4185   Node* effect = builder_->MergeEffect(this->GetEffectDependency(),
4186                                        other->GetEffectDependency(), control);
4187   UpdateEffectDependency(effect);
4188 
4189   // Introduce Phi nodes for values that have differing input at merge points,
4190   // potentially extending an existing Phi node if possible.
4191   for (int i = 0; i < static_cast<int>(values_.size()); ++i) {
4192     values_[i] = builder_->MergeValue(values_[i], other->values_[i], control);
4193   }
4194   for (int i = 0; i < static_cast<int>(contexts_.size()); ++i) {
4195     contexts_[i] =
4196         builder_->MergeValue(contexts_[i], other->contexts_[i], control);
4197   }
4198 }
4199 
PrepareForOsrEntry()4200 void AstGraphBuilder::Environment::PrepareForOsrEntry() {
4201   int size = static_cast<int>(values()->size());
4202   Graph* graph = builder_->graph();
4203 
4204   // Set the control and effect to the OSR loop entry.
4205   Node* osr_loop_entry = graph->NewNode(builder_->common()->OsrLoopEntry(),
4206                                         graph->start(), graph->start());
4207   UpdateControlDependency(osr_loop_entry);
4208   UpdateEffectDependency(osr_loop_entry);
4209 
4210   // Set OSR values.
4211   for (int i = 0; i < size; ++i) {
4212     values()->at(i) =
4213         graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry);
4214   }
4215 
4216   // Set the innermost context.
4217   const Operator* op_inner =
4218       builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex);
4219   contexts()->back() = graph->NewNode(op_inner, osr_loop_entry);
4220 
4221   // Create a checkpoint.
4222   Node* frame_state = Checkpoint(builder_->info()->osr_ast_id());
4223   Node* checkpoint = graph->NewNode(common()->Checkpoint(), frame_state,
4224                                     osr_loop_entry, osr_loop_entry);
4225   UpdateEffectDependency(checkpoint);
4226 
4227   // Create the OSR guard nodes.
4228   const Operator* guard_op =
4229       builder_->info()->is_deoptimization_enabled()
4230           ? builder_->common()->OsrGuard(OsrGuardType::kUninitialized)
4231           : builder_->common()->OsrGuard(OsrGuardType::kAny);
4232   Node* effect = checkpoint;
4233   for (int i = 0; i < size; ++i) {
4234     values()->at(i) = effect =
4235         graph->NewNode(guard_op, values()->at(i), effect, osr_loop_entry);
4236   }
4237   contexts()->back() = effect =
4238       graph->NewNode(guard_op, contexts()->back(), effect, osr_loop_entry);
4239 
4240   // The innermost context is the OSR value, and the outer contexts are
4241   // reconstructed by dynamically walking up the context chain.
4242   const Operator* load_op =
4243       builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true);
4244   Node* osr_context = effect = contexts()->back();
4245   int last = static_cast<int>(contexts()->size() - 1);
4246   for (int i = last - 1; i >= 0; i--) {
4247     osr_context = effect =
4248         graph->NewNode(load_op, osr_context, osr_context, effect);
4249     contexts()->at(i) = osr_context;
4250   }
4251   UpdateEffectDependency(effect);
4252 }
4253 
PrepareForLoop(BitVector * assigned)4254 void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned) {
4255   int size = static_cast<int>(values()->size());
4256 
4257   Node* control = builder_->NewLoop();
4258   if (assigned == nullptr) {
4259     // Assume that everything is updated in the loop.
4260     for (int i = 0; i < size; ++i) {
4261       values()->at(i) = builder_->NewPhi(1, values()->at(i), control);
4262     }
4263   } else {
4264     // Only build phis for those locals assigned in this loop.
4265     for (int i = 0; i < size; ++i) {
4266       if (i < assigned->length() && !assigned->Contains(i)) continue;
4267       Node* phi = builder_->NewPhi(1, values()->at(i), control);
4268       values()->at(i) = phi;
4269     }
4270   }
4271   Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control);
4272   UpdateEffectDependency(effect);
4273 
4274   // Connect the loop to end via Terminate if it's not marked as unreachable.
4275   if (!IsMarkedAsUnreachable()) {
4276     // Connect the Loop node to end via a Terminate node.
4277     Node* terminate = builder_->graph()->NewNode(
4278         builder_->common()->Terminate(), effect, control);
4279     builder_->exit_controls_.push_back(terminate);
4280   }
4281 
4282   if (builder_->info()->is_osr()) {
4283     // Introduce phis for all context values in the case of an OSR graph.
4284     for (size_t i = 0; i < contexts()->size(); ++i) {
4285       Node* context = contexts()->at(i);
4286       contexts()->at(i) = builder_->NewPhi(1, context, control);
4287     }
4288   }
4289 }
4290 
4291 
NewPhi(int count,Node * input,Node * control)4292 Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) {
4293   const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
4294   Node** buffer = EnsureInputBufferSize(count + 1);
4295   MemsetPointer(buffer, input, count);
4296   buffer[count] = control;
4297   return graph()->NewNode(phi_op, count + 1, buffer, true);
4298 }
4299 
4300 
NewEffectPhi(int count,Node * input,Node * control)4301 Node* AstGraphBuilder::NewEffectPhi(int count, Node* input, Node* control) {
4302   const Operator* phi_op = common()->EffectPhi(count);
4303   Node** buffer = EnsureInputBufferSize(count + 1);
4304   MemsetPointer(buffer, input, count);
4305   buffer[count] = control;
4306   return graph()->NewNode(phi_op, count + 1, buffer, true);
4307 }
4308 
4309 
MergeControl(Node * control,Node * other)4310 Node* AstGraphBuilder::MergeControl(Node* control, Node* other) {
4311   int inputs = control->op()->ControlInputCount() + 1;
4312   if (control->opcode() == IrOpcode::kLoop) {
4313     // Control node for loop exists, add input.
4314     const Operator* op = common()->Loop(inputs);
4315     control->AppendInput(graph_zone(), other);
4316     NodeProperties::ChangeOp(control, op);
4317   } else if (control->opcode() == IrOpcode::kMerge) {
4318     // Control node for merge exists, add input.
4319     const Operator* op = common()->Merge(inputs);
4320     control->AppendInput(graph_zone(), other);
4321     NodeProperties::ChangeOp(control, op);
4322   } else {
4323     // Control node is a singleton, introduce a merge.
4324     const Operator* op = common()->Merge(inputs);
4325     Node* inputs[] = {control, other};
4326     control = graph()->NewNode(op, arraysize(inputs), inputs, true);
4327   }
4328   return control;
4329 }
4330 
4331 
MergeEffect(Node * value,Node * other,Node * control)4332 Node* AstGraphBuilder::MergeEffect(Node* value, Node* other, Node* control) {
4333   int inputs = control->op()->ControlInputCount();
4334   if (value->opcode() == IrOpcode::kEffectPhi &&
4335       NodeProperties::GetControlInput(value) == control) {
4336     // Phi already exists, add input.
4337     value->InsertInput(graph_zone(), inputs - 1, other);
4338     NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
4339   } else if (value != other) {
4340     // Phi does not exist yet, introduce one.
4341     value = NewEffectPhi(inputs, value, control);
4342     value->ReplaceInput(inputs - 1, other);
4343   }
4344   return value;
4345 }
4346 
4347 
MergeValue(Node * value,Node * other,Node * control)4348 Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) {
4349   int inputs = control->op()->ControlInputCount();
4350   if (value->opcode() == IrOpcode::kPhi &&
4351       NodeProperties::GetControlInput(value) == control) {
4352     // Phi already exists, add input.
4353     value->InsertInput(graph_zone(), inputs - 1, other);
4354     NodeProperties::ChangeOp(
4355         value, common()->Phi(MachineRepresentation::kTagged, inputs));
4356   } else if (value != other) {
4357     // Phi does not exist yet, introduce one.
4358     value = NewPhi(inputs, value, control);
4359     value->ReplaceInput(inputs - 1, other);
4360   }
4361   return value;
4362 }
4363 
AstGraphBuilderWithPositions(Zone * local_zone,CompilationInfo * info,JSGraph * jsgraph,float invocation_frequency,LoopAssignmentAnalysis * loop_assignment,TypeHintAnalysis * type_hint_analysis,SourcePositionTable * source_positions,int inlining_id)4364 AstGraphBuilderWithPositions::AstGraphBuilderWithPositions(
4365     Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph,
4366     float invocation_frequency, LoopAssignmentAnalysis* loop_assignment,
4367     TypeHintAnalysis* type_hint_analysis, SourcePositionTable* source_positions,
4368     int inlining_id)
4369     : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency,
4370                       loop_assignment, type_hint_analysis),
4371       source_positions_(source_positions),
4372       start_position_(info->shared_info()->start_position(), inlining_id) {}
4373 
4374 }  // namespace compiler
4375 }  // namespace internal
4376 }  // namespace v8
4377