LCOV - code coverage report
Current view: top level - src/compiler - ast-graph-builder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1066 1346 79.2 %
Date: 2017-04-26 Functions: 119 180 66.1 %

          Line data    Source code
       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/feedback-vector.h"
      21             : #include "src/objects-inl.h"
      22             : #include "src/objects/literal-objects.h"
      23             : 
      24             : namespace v8 {
      25             : namespace internal {
      26             : namespace compiler {
      27             : 
      28             : 
      29             : // Each expression in the AST is evaluated in a specific context. This context
      30             : // decides how the evaluation result is passed up the visitor.
      31             : class AstGraphBuilder::AstContext BASE_EMBEDDED {
      32             :  public:
      33             :   bool IsEffect() const { return kind_ == Expression::kEffect; }
      34             :   bool IsValue() const { return kind_ == Expression::kValue; }
      35             :   bool IsTest() const { return kind_ == Expression::kTest; }
      36             : 
      37             :   // Determines how to combine the frame state with the value
      38             :   // that is about to be plugged into this AstContext.
      39      115289 :   OutputFrameStateCombine GetStateCombine() {
      40             :     return IsEffect() ? OutputFrameStateCombine::Ignore()
      41      115289 :                       : OutputFrameStateCombine::Push();
      42             :   }
      43             : 
      44             :   // Plug a node into this expression context.  Call this function in tail
      45             :   // position in the Visit functions for expressions.
      46             :   virtual void ProduceValue(Expression* expr, Node* value) = 0;
      47             : 
      48             :   // Unplugs a node from this expression context.  Call this to retrieve the
      49             :   // result of another Visit function that already plugged the context.
      50             :   virtual Node* ConsumeValue() = 0;
      51             : 
      52             :   // Shortcut for "context->ProduceValue(context->ConsumeValue())".
      53         537 :   void ReplaceValue(Expression* expr) { ProduceValue(expr, ConsumeValue()); }
      54             : 
      55             :  protected:
      56             :   AstContext(AstGraphBuilder* owner, Expression::Context kind);
      57             :   virtual ~AstContext();
      58             : 
      59             :   AstGraphBuilder* owner() const { return owner_; }
      60      159472 :   Environment* environment() const { return owner_->environment(); }
      61             : 
      62             : // We want to be able to assert, in a context-specific way, that the stack
      63             : // height makes sense when the context is filled.
      64             : #ifdef DEBUG
      65             :   int original_height_;
      66             : #endif
      67             : 
      68             :  private:
      69             :   Expression::Context kind_;
      70             :   AstGraphBuilder* owner_;
      71             :   AstContext* outer_;
      72             : };
      73             : 
      74             : 
      75             : // Context to evaluate expression for its side effects only.
      76             : class AstGraphBuilder::AstEffectContext final : public AstContext {
      77             :  public:
      78             :   explicit AstEffectContext(AstGraphBuilder* owner)
      79       22453 :       : AstContext(owner, Expression::kEffect) {}
      80             :   ~AstEffectContext() final;
      81             :   void ProduceValue(Expression* expr, Node* value) final;
      82             :   Node* ConsumeValue() final;
      83             : };
      84             : 
      85             : 
      86             : // Context to evaluate expression for its value (and side effects).
      87             : class AstGraphBuilder::AstValueContext final : public AstContext {
      88             :  public:
      89             :   explicit AstValueContext(AstGraphBuilder* owner)
      90      153632 :       : AstContext(owner, Expression::kValue) {}
      91             :   ~AstValueContext() final;
      92             :   void ProduceValue(Expression* expr, Node* value) final;
      93             :   Node* ConsumeValue() final;
      94             : };
      95             : 
      96             : 
      97             : // Context to evaluate expression for a condition value (and side effects).
      98             : class AstGraphBuilder::AstTestContext final : public AstContext {
      99             :  public:
     100             :   AstTestContext(AstGraphBuilder* owner, TypeFeedbackId feedback_id)
     101        5307 :       : AstContext(owner, Expression::kTest), feedback_id_(feedback_id) {}
     102             :   ~AstTestContext() final;
     103             :   void ProduceValue(Expression* expr, Node* value) final;
     104             :   Node* ConsumeValue() final;
     105             : 
     106             :  private:
     107             :   TypeFeedbackId const feedback_id_;
     108             : };
     109             : 
     110             : 
     111             : // Scoped class tracking context objects created by the visitor. Represents
     112             : // mutations of the context chain within the function body and allows to
     113             : // change the current {scope} and {context} during visitation.
     114             : class AstGraphBuilder::ContextScope BASE_EMBEDDED {
     115             :  public:
     116        5110 :   ContextScope(AstGraphBuilder* builder, Scope* scope, Node* context)
     117             :       : builder_(builder),
     118             :         outer_(builder->execution_context()),
     119             :         scope_(scope),
     120        7665 :         depth_(builder_->environment()->context_chain_length()) {
     121             :     builder_->environment()->PushContext(context);  // Push.
     122        2555 :     builder_->set_execution_context(this);
     123        2555 :   }
     124             : 
     125        2555 :   ~ContextScope() {
     126        7665 :     builder_->set_execution_context(outer_);  // Pop.
     127        2555 :     builder_->environment()->PopContext();
     128        5110 :     CHECK_EQ(depth_, builder_->environment()->context_chain_length());
     129        2555 :   }
     130             : 
     131             :   // Current scope during visitation.
     132             :   Scope* scope() const { return scope_; }
     133             : 
     134             :  private:
     135             :   AstGraphBuilder* builder_;
     136             :   ContextScope* outer_;
     137             :   Scope* scope_;
     138             :   int depth_;
     139             : };
     140             : 
     141             : 
     142             : // Scoped class tracking control statements entered by the visitor. There are
     143             : // different types of statements participating in this stack to properly track
     144             : // local as well as non-local control flow:
     145             : //  - IterationStatement : Allows proper 'break' and 'continue' behavior.
     146             : //  - BreakableStatement : Allows 'break' from block and switch statements.
     147             : //  - TryCatchStatement  : Intercepts 'throw' and implicit exceptional edges.
     148             : //  - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'.
     149             : class AstGraphBuilder::ControlScope BASE_EMBEDDED {
     150             :  public:
     151       27084 :   explicit ControlScope(AstGraphBuilder* builder)
     152             :       : builder_(builder),
     153             :         outer_(builder->execution_control()),
     154             :         context_length_(builder->environment()->context_chain_length()),
     155       36112 :         stack_height_(builder->environment()->stack_height()) {
     156             :     builder_->set_execution_control(this);  // Push.
     157        9028 :   }
     158             : 
     159        9028 :   virtual ~ControlScope() {
     160        9028 :     builder_->set_execution_control(outer_);  // Pop.
     161           0 :   }
     162             : 
     163             :   // Either 'break' or 'continue' to the target statement.
     164             :   void BreakTo(BreakableStatement* target);
     165             :   void ContinueTo(BreakableStatement* target);
     166             : 
     167             :   // Either 'return' or 'throw' the given value.
     168             :   void ReturnValue(Node* return_value);
     169             :   void ThrowValue(Node* exception_value);
     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.
     182        5312 :   virtual bool Execute(Command cmd, Statement* target, Node** value) {
     183             :     // For function-level control.
     184        2656 :     switch (cmd) {
     185             :       case CMD_THROW:
     186           0 :         builder()->BuildThrow(*value);
     187           0 :         return true;
     188             :       case CMD_RETURN:
     189        5312 :         builder()->BuildReturn(*value);
     190        2656 :         return true;
     191             :       case CMD_BREAK:
     192             :       case CMD_CONTINUE:
     193             :         break;
     194             :     }
     195             :     return false;
     196             :   }
     197             : 
     198       22480 :   Environment* environment() { return builder_->environment(); }
     199             :   AstGraphBuilder* builder() const { return builder_; }
     200             :   int context_length() const { return context_length_; }
     201             :   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             : 
     211             : // Control scope implementation for a BreakableStatement.
     212        5687 : class AstGraphBuilder::ControlScopeForBreakable : public ControlScope {
     213             :  public:
     214             :   ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target,
     215             :                            ControlBuilder* control)
     216        5687 :       : ControlScope(owner), target_(target), control_(control) {}
     217             : 
     218             :  protected:
     219        5132 :   bool Execute(Command cmd, Statement* target, Node** value) override {
     220        5132 :     if (target != target_) return false;  // We are not the command target.
     221         161 :     switch (cmd) {
     222             :       case CMD_BREAK:
     223         161 :         control_->Break();
     224         161 :         return true;
     225             :       case CMD_CONTINUE:
     226             :       case CMD_THROW:
     227             :       case CMD_RETURN:
     228             :         break;
     229             :     }
     230             :     return false;
     231             :   }
     232             : 
     233             :  private:
     234             :   BreakableStatement* target_;
     235             :   ControlBuilder* control_;
     236             : };
     237             : 
     238             : 
     239             : // Control scope implementation for an IterationStatement.
     240         834 : class AstGraphBuilder::ControlScopeForIteration : public ControlScope {
     241             :  public:
     242             :   ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target,
     243             :                            LoopBuilder* control)
     244         834 :       : ControlScope(owner), target_(target), control_(control) {}
     245             : 
     246             :  protected:
     247        1500 :   bool Execute(Command cmd, Statement* target, Node** value) override {
     248        1500 :     if (target != target_) {
     249         413 :       control_->ExitLoop(value);
     250         413 :       return false;
     251             :     }
     252        1087 :     switch (cmd) {
     253             :       case CMD_BREAK:
     254         986 :         control_->Break();
     255         986 :         return true;
     256             :       case CMD_CONTINUE:
     257         101 :         control_->Continue();
     258         101 :         return true;
     259             :       case CMD_THROW:
     260             :       case CMD_RETURN:
     261             :         break;
     262             :     }
     263             :     return false;
     264             :   }
     265             : 
     266             :  private:
     267             :   BreakableStatement* target_;
     268             :   LoopBuilder* control_;
     269             : };
     270             : 
     271             : 
     272        7521 : AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
     273             :                                  JSGraph* jsgraph, float invocation_frequency,
     274        2507 :                                  LoopAssignmentAnalysis* loop)
     275             :     : isolate_(info->isolate()),
     276             :       local_zone_(local_zone),
     277             :       info_(info),
     278             :       jsgraph_(jsgraph),
     279             :       invocation_frequency_(invocation_frequency),
     280             :       environment_(nullptr),
     281             :       ast_context_(nullptr),
     282             :       globals_(0, local_zone),
     283             :       execution_control_(nullptr),
     284             :       execution_context_(nullptr),
     285             :       input_buffer_size_(0),
     286             :       input_buffer_(nullptr),
     287             :       exit_controls_(local_zone),
     288             :       loop_assignment_analysis_(loop),
     289             :       state_values_cache_(jsgraph),
     290        2507 :       liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()),
     291             :                          false, local_zone),
     292             :       frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
     293        2507 :           FrameStateType::kJavaScriptFunction, info->num_parameters() + 1,
     294       20056 :           info->scope()->num_stack_slots(), info->shared_info())) {
     295             :   InitializeAstVisitor(info->isolate());
     296        2507 : }
     297             : 
     298             : 
     299           0 : Node* AstGraphBuilder::GetFunctionClosureForContext() {
     300           0 :   DeclarationScope* closure_scope = current_scope()->GetClosureScope();
     301           0 :   if (closure_scope->is_script_scope() ||
     302             :       closure_scope->is_module_scope()) {
     303             :     // Contexts nested in the native context have a canonical empty function as
     304             :     // their closure, not the anonymous closure containing the global code.
     305           0 :     return BuildLoadNativeContextField(Context::CLOSURE_INDEX);
     306           0 :   } else if (closure_scope->is_eval_scope()) {
     307             :     // Contexts nested inside eval code have the same closure as the context
     308             :     // calling eval, not the anonymous closure containing the eval code.
     309             :     const Operator* op =
     310           0 :         javascript()->LoadContext(0, Context::CLOSURE_INDEX, false);
     311           0 :     return NewNode(op);
     312             :   } else {
     313             :     DCHECK(closure_scope->is_function_scope());
     314           0 :     return GetFunctionClosure();
     315             :   }
     316             : }
     317             : 
     318             : 
     319        2712 : Node* AstGraphBuilder::GetFunctionClosure() {
     320        1768 :   if (!function_closure_.is_set()) {
     321             :     int index = Linkage::kJSCallClosureParamIndex;
     322         472 :     const Operator* op = common()->Parameter(index, "%closure");
     323         472 :     Node* node = NewNode(op, graph()->start());
     324             :     function_closure_.set(node);
     325             :   }
     326        1768 :   return function_closure_.get();
     327             : }
     328             : 
     329             : 
     330       10076 : Node* AstGraphBuilder::GetFunctionContext() {
     331        2555 :   if (!function_context_.is_set()) {
     332        2507 :     int params = info()->num_parameters_including_this();
     333             :     int index = Linkage::GetJSCallContextParamIndex(params);
     334        2507 :     const Operator* op = common()->Parameter(index, "%context");
     335        2507 :     Node* node = NewNode(op, graph()->start());
     336             :     function_context_.set(node);
     337             :   }
     338        2555 :   return function_context_.get();
     339             : }
     340             : 
     341      161538 : Node* AstGraphBuilder::GetEmptyFrameState() {
     342      147055 :   if (!empty_frame_state_.is_set()) {
     343             :     const Operator* op = common()->FrameState(
     344        2069 :         BailoutId::None(), OutputFrameStateCombine::Ignore(), nullptr);
     345             :     Node* node = graph()->NewNode(
     346             :         op, jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
     347             :         jsgraph()->EmptyStateValues(), jsgraph()->NoContextConstant(),
     348        8276 :         jsgraph()->UndefinedConstant(), graph()->start());
     349             :     empty_frame_state_.set(node);
     350             :   }
     351      147055 :   return empty_frame_state_.get();
     352             : }
     353             : 
     354       27645 : bool AstGraphBuilder::CreateGraph(bool stack_check) {
     355        5012 :   DeclarationScope* scope = info()->scope();
     356             :   DCHECK_NOT_NULL(graph());
     357             : 
     358             :   // Set up the basic structure of the graph. Outputs for {Start} are the formal
     359             :   // parameters (including the receiver) plus new target, number of arguments,
     360             :   // context and closure.
     361        2507 :   int actual_parameter_count = info()->num_parameters_including_this() + 4;
     362        2507 :   graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
     363             : 
     364             :   // Initialize the top-level environment.
     365        2507 :   Environment env(this, scope, graph()->start());
     366             :   set_environment(&env);
     367             : 
     368        2507 :   if (info()->is_osr()) {
     369             :     // Use OSR normal entry as the start of the top-level environment.
     370             :     // It will be replaced with {Dead} after typing and optimizations.
     371          68 :     NewNode(common()->OsrNormalEntry());
     372             :   }
     373             : 
     374             :   // Initialize the incoming context.
     375        5014 :   ContextScope incoming(this, scope, GetFunctionContext());
     376             : 
     377             :   // Initialize control scope.
     378        2507 :   ControlScope control(this);
     379             : 
     380             :   // TODO(mstarzinger): For now we cannot assume that the {this} parameter is
     381             :   // not {the_hole}, because for derived classes {this} has a TDZ and the
     382             :   // JSConstructStubForDerived magically passes {the_hole} as a receiver.
     383        7517 :   if (scope->has_this_declaration() && scope->receiver()->mode() == CONST) {
     384           0 :     env.RawParameterBind(0, jsgraph()->TheHoleConstant());
     385             :   }
     386             : 
     387        2507 :   if (scope->NeedsContext()) {
     388             :     // Push a new inner context scope for the current activation.
     389          48 :     Node* inner_context = BuildLocalActivationContext(GetFunctionContext());
     390          48 :     ContextScope top_context(this, scope, inner_context);
     391          48 :     CreateGraphBody(stack_check);
     392             :   } else {
     393             :     // Simply use the outer function context in building the graph.
     394        2459 :     CreateGraphBody(stack_check);
     395             :   }
     396             : 
     397             :   // Finish the basic structure of the graph.
     398             :   DCHECK_NE(0u, exit_controls_.size());
     399        5014 :   int const input_count = static_cast<int>(exit_controls_.size());
     400             :   Node** const inputs = &exit_controls_.front();
     401        7521 :   Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
     402             :   graph()->SetEnd(end);
     403             : 
     404             :   // Compute local variable liveness information and use it to relax
     405             :   // frame states.
     406        2507 :   ClearNonLiveSlotsInFrameStates();
     407             : 
     408             :   // Failures indicated by stack overflow.
     409        5014 :   return !HasStackOverflow();
     410             : }
     411             : 
     412             : 
     413       10028 : void AstGraphBuilder::CreateGraphBody(bool stack_check) {
     414        2507 :   DeclarationScope* scope = info()->scope();
     415             : 
     416             :   // Build the arguments object if it is used.
     417        2507 :   BuildArgumentsObject(scope->arguments());
     418             : 
     419             :   // We don't support new.target and rest parameters here.
     420             :   DCHECK_NULL(scope->new_target_var());
     421             :   DCHECK_NULL(scope->rest_parameter());
     422             :   DCHECK_NULL(scope->this_function_var());
     423             : 
     424             :   // Emit tracing call if requested to do so.
     425        2507 :   if (FLAG_trace) {
     426           0 :     NewNode(javascript()->CallRuntime(Runtime::kTraceEnter));
     427             :   }
     428             : 
     429             :   // Visit declarations within the function scope.
     430        2507 :   VisitDeclarations(scope->declarations());
     431             : 
     432             :   // Build a stack-check before the body.
     433        2507 :   if (stack_check) {
     434        2507 :     Node* node = NewNode(javascript()->StackCheck());
     435        2507 :     PrepareFrameState(node, BailoutId::FunctionEntry());
     436             :   }
     437             : 
     438             :   // Visit statements in the function body.
     439        2507 :   VisitStatements(info()->literal()->body());
     440             : 
     441             :   // Return 'undefined' in case we can fall off the end.
     442        2507 :   BuildReturn(jsgraph()->UndefinedConstant());
     443        2507 : }
     444             : 
     445             : 
     446        6328 : void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
     447        5014 :   if (!FLAG_analyze_environment_liveness ||
     448             :       !info()->is_deoptimization_enabled()) {
     449        2069 :     return;
     450             :   }
     451             : 
     452             :   NonLiveFrameStateSlotReplacer replacer(
     453             :       &state_values_cache_, jsgraph()->OptimizedOutConstant(),
     454         876 :       liveness_analyzer()->local_count(), false, local_zone());
     455         442 :   Variable* arguments = info()->scope()->arguments();
     456         442 :   if (arguments != nullptr && arguments->IsStackAllocated()) {
     457             :     replacer.MarkPermanentlyLive(arguments->index());
     458             :   }
     459         438 :   liveness_analyzer()->Run(&replacer);
     460         438 :   if (FLAG_trace_environment_liveness) {
     461           0 :     OFStream os(stdout);
     462           0 :     liveness_analyzer()->Print(os);
     463             :   }
     464             : }
     465             : 
     466             : 
     467             : // Gets the bailout id just before reading a variable proxy, but only for
     468             : // unallocated variables.
     469       46754 : static BailoutId BeforeId(VariableProxy* proxy) {
     470       46754 :   return proxy->var()->IsUnallocated() ? proxy->BeforeId() : BailoutId::None();
     471             : }
     472             : 
     473             : static const char* GetDebugParameterName(Zone* zone, DeclarationScope* scope,
     474             :                                          int index) {
     475             : #if DEBUG
     476             :   const AstRawString* name = scope->parameter(index)->raw_name();
     477             :   if (name && name->length() > 0) {
     478             :     char* data = zone->NewArray<char>(name->length() + 1);
     479             :     data[name->length()] = 0;
     480             :     memcpy(data, name->raw_data(), name->length());
     481             :     return data;
     482             :   }
     483             : #endif
     484             :   return nullptr;
     485             : }
     486             : 
     487       13065 : AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
     488             :                                           DeclarationScope* scope,
     489        8051 :                                           Node* control_dependency)
     490             :     : builder_(builder),
     491        2507 :       parameters_count_(scope->num_parameters() + 1),
     492        2507 :       locals_count_(scope->num_stack_slots()),
     493             :       liveness_block_(IsLivenessAnalysisEnabled()
     494        5452 :                           ? builder_->liveness_analyzer()->NewBlock()
     495             :                           : nullptr),
     496             :       values_(builder_->local_zone()),
     497             :       contexts_(builder_->local_zone()),
     498             :       control_dependency_(control_dependency),
     499             :       effect_dependency_(control_dependency),
     500             :       parameters_node_(nullptr),
     501             :       locals_node_(nullptr),
     502       12973 :       stack_node_(nullptr) {
     503             :   DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
     504             : 
     505             :   // Bind the receiver variable.
     506             :   int param_num = 0;
     507        2507 :   if (builder->info()->is_this_defined()) {
     508        2507 :     const Operator* op = common()->Parameter(param_num++, "%this");
     509        5014 :     Node* receiver = builder->graph()->NewNode(op, builder->graph()->start());
     510        2507 :     values()->push_back(receiver);
     511             :   } else {
     512           0 :     values()->push_back(builder->jsgraph()->UndefinedConstant());
     513             :   }
     514             : 
     515             :   // Bind all parameter variables. The parameter indices are shifted by 1
     516             :   // (receiver is variable index -1 but {Parameter} node index 0 and located at
     517             :   // index 0 in the environment).
     518        8581 :   for (int i = 0; i < scope->num_parameters(); ++i) {
     519             :     const char* debug_name = GetDebugParameterName(graph()->zone(), scope, i);
     520        6074 :     const Operator* op = common()->Parameter(param_num++, debug_name);
     521        6074 :     Node* parameter = builder->graph()->NewNode(op, builder->graph()->start());
     522        3037 :     values()->push_back(parameter);
     523             :   }
     524             : 
     525             :   // Bind all local variables to undefined.
     526        2507 :   Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
     527        5014 :   values()->insert(values()->end(), locals_count(), undefined_constant);
     528        2507 : }
     529             : 
     530             : 
     531       34764 : AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy,
     532             :                                           LivenessAnalyzerBlock* liveness_block)
     533             :     : builder_(copy->builder_),
     534             :       parameters_count_(copy->parameters_count_),
     535             :       locals_count_(copy->locals_count_),
     536             :       liveness_block_(liveness_block),
     537             :       values_(copy->zone()),
     538             :       contexts_(copy->zone()),
     539             :       control_dependency_(copy->control_dependency_),
     540             :       effect_dependency_(copy->effect_dependency_),
     541             :       parameters_node_(copy->parameters_node_),
     542             :       locals_node_(copy->locals_node_),
     543       23176 :       stack_node_(copy->stack_node_) {
     544             :   const size_t kStackEstimate = 7;  // optimum from experimentation!
     545       23176 :   values_.reserve(copy->values_.size() + kStackEstimate);
     546       11588 :   values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end());
     547       23176 :   contexts_.reserve(copy->contexts_.size());
     548             :   contexts_.insert(contexts_.begin(), copy->contexts_.begin(),
     549       11588 :                    copy->contexts_.end());
     550       11588 : }
     551             : 
     552             : 
     553       47585 : void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) {
     554             :   DCHECK(variable->IsStackAllocated());
     555       16726 :   if (variable->IsParameter()) {
     556             :     // The parameter indices are shifted by 1 (receiver is variable
     557             :     // index -1 but located at index 0 in the environment).
     558        5494 :     values()->at(variable->index() + 1) = node;
     559             :   } else {
     560             :     DCHECK(variable->IsStackLocal());
     561       27958 :     values()->at(variable->index() + parameters_count_) = node;
     562             :     DCHECK(IsLivenessBlockConsistent());
     563       13979 :     if (liveness_block() != nullptr) {
     564             :       liveness_block()->Bind(variable->index());
     565             :     }
     566             :   }
     567       16726 : }
     568             : 
     569             : 
     570       94865 : Node* AstGraphBuilder::Environment::Lookup(Variable* variable) {
     571             :   DCHECK(variable->IsStackAllocated());
     572       34536 :   if (variable->IsParameter()) {
     573             :     // The parameter indices are shifted by 1 (receiver is variable
     574             :     // index -1 but located at index 0 in the environment).
     575       17734 :     return values()->at(variable->index() + 1);
     576             :   } else {
     577             :     DCHECK(variable->IsStackLocal());
     578             :     DCHECK(IsLivenessBlockConsistent());
     579       25669 :     if (liveness_block() != nullptr) {
     580             :       liveness_block()->Lookup(variable->index());
     581             :     }
     582       51338 :     return values()->at(variable->index() + parameters_count_);
     583             :   }
     584             : }
     585             : 
     586             : 
     587           0 : void AstGraphBuilder::Environment::MarkAllLocalsLive() {
     588             :   DCHECK(IsLivenessBlockConsistent());
     589           0 :   if (liveness_block() != nullptr) {
     590           0 :     for (int i = 0; i < locals_count_; i++) {
     591             :       liveness_block()->Lookup(i);
     592             :     }
     593             :   }
     594           0 : }
     595             : 
     596             : 
     597           0 : void AstGraphBuilder::Environment::RawParameterBind(int index, Node* node) {
     598             :   DCHECK_LT(index, parameters_count());
     599           0 :   values()->at(index) = node;
     600           0 : }
     601             : 
     602             : 
     603           6 : Node* AstGraphBuilder::Environment::RawParameterLookup(int index) {
     604             :   DCHECK_LT(index, parameters_count());
     605          12 :   return values()->at(index);
     606             : }
     607             : 
     608             : 
     609             : AstGraphBuilder::Environment*
     610        9798 : AstGraphBuilder::Environment::CopyForConditional() {
     611             :   LivenessAnalyzerBlock* copy_liveness_block = nullptr;
     612        4821 :   if (liveness_block() != nullptr) {
     613             :     copy_liveness_block =
     614         156 :         builder_->liveness_analyzer()->NewBlock(liveness_block());
     615         156 :     liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
     616             :   }
     617        4821 :   return new (zone()) Environment(this, copy_liveness_block);
     618             : }
     619             : 
     620             : 
     621             : AstGraphBuilder::Environment*
     622        5865 : AstGraphBuilder::Environment::CopyAsUnreachable() {
     623        5865 :   Environment* env = new (zone()) Environment(this, nullptr);
     624             :   env->MarkAsUnreachable();
     625        5865 :   return env;
     626             : }
     627             : 
     628         136 : AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForOsrEntry() {
     629             :   LivenessAnalyzerBlock* copy_block =
     630             :       liveness_block() == nullptr ? nullptr
     631          68 :                                   : builder_->liveness_analyzer()->NewBlock();
     632          68 :   return new (zone()) Environment(this, copy_block);
     633             : }
     634             : 
     635             : AstGraphBuilder::Environment*
     636        1668 : AstGraphBuilder::Environment::CopyAndShareLiveness() {
     637         834 :   if (liveness_block() != nullptr) {
     638             :     // Finish the current liveness block before copying.
     639          26 :     liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
     640             :   }
     641         834 :   Environment* env = new (zone()) Environment(this, liveness_block());
     642         834 :   return env;
     643             : }
     644             : 
     645             : 
     646         834 : AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
     647             :     BitVector* assigned, bool is_osr) {
     648         834 :   PrepareForLoop(assigned);
     649         834 :   Environment* loop = CopyAndShareLiveness();
     650         834 :   if (is_osr) {
     651             :     // Create and merge the OSR entry if necessary.
     652          68 :     Environment* osr_env = CopyForOsrEntry();
     653          68 :     osr_env->PrepareForOsrEntry();
     654          68 :     loop->Merge(osr_env);
     655             :   }
     656         834 :   return loop;
     657             : }
     658             : 
     659             : 
     660        4992 : void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
     661        4796 :                                                      int offset, int count) {
     662             :   bool should_update = false;
     663        4992 :   Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
     664        8670 :   if (*state_values == nullptr || (*state_values)->InputCount() != count) {
     665             :     should_update = true;
     666             :   } else {
     667             :     DCHECK(static_cast<size_t>(offset + count) <= values()->size());
     668        3800 :     for (int i = 0; i < count; i++) {
     669        4030 :       if ((*state_values)->InputAt(i) != env_values[i]) {
     670             :         should_update = true;
     671             :         break;
     672             :       }
     673             :     }
     674             :   }
     675        4992 :   if (should_update) {
     676        2398 :     const Operator* op = common()->StateValues(count, SparseInputMask::Dense());
     677        2398 :     (*state_values) = graph()->NewNode(op, count, env_values);
     678             :   }
     679        4992 : }
     680             : 
     681             : 
     682      148719 : Node* AstGraphBuilder::Environment::Checkpoint(BailoutId ast_id,
     683             :                                                OutputFrameStateCombine combine,
     684      158703 :                                                bool owner_has_exception) {
     685      297438 :   if (!builder()->info()->is_deoptimization_enabled()) {
     686      147055 :     return builder()->GetEmptyFrameState();
     687             :   }
     688             : 
     689        1664 :   UpdateStateValues(&parameters_node_, 0, parameters_count());
     690        1664 :   UpdateStateValues(&locals_node_, parameters_count(), locals_count());
     691             :   UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
     692        1664 :                     stack_height());
     693             : 
     694             :   const Operator* op = common()->FrameState(
     695        3328 :       ast_id, combine, builder()->frame_state_function_info());
     696             : 
     697             :   Node* result = graph()->NewNode(op, parameters_node_, locals_node_,
     698             :                                   stack_node_, builder()->current_context(),
     699             :                                   builder()->GetFunctionClosure(),
     700        4992 :                                   builder()->graph()->start());
     701             : 
     702             :   DCHECK(IsLivenessBlockConsistent());
     703        1664 :   if (liveness_block() != nullptr) {
     704             :     // If the owning node has an exception, register the checkpoint to the
     705             :     // predecessor so that the checkpoint is used for both the normal and the
     706             :     // exceptional paths. Yes, this is a terrible hack and we might want
     707             :     // to use an explicit frame state for the exceptional path.
     708        1616 :     if (owner_has_exception) {
     709           0 :       liveness_block()->GetPredecessor()->Checkpoint(result);
     710             :     } else {
     711             :       liveness_block()->Checkpoint(result);
     712             :     }
     713             :   }
     714        1664 :   return result;
     715             : }
     716             : 
     717        1247 : void AstGraphBuilder::Environment::PrepareForLoopExit(
     718      107519 :     Node* loop, BitVector* assigned_variables) {
     719        2494 :   if (IsMarkedAsUnreachable()) return;
     720             : 
     721             :   DCHECK_EQ(loop->opcode(), IrOpcode::kLoop);
     722             : 
     723             :   Node* control = GetControlDependency();
     724             : 
     725             :   // Create the loop exit node.
     726        1245 :   Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop);
     727             :   UpdateControlDependency(loop_exit);
     728             : 
     729             :   // Rename the environmnent values.
     730       86350 :   for (size_t i = 0; i < values()->size(); i++) {
     731       83860 :     if (assigned_variables == nullptr ||
     732       83447 :         static_cast<int>(i) >= assigned_variables->length() ||
     733             :         assigned_variables->Contains(static_cast<int>(i))) {
     734             :       Node* rename = graph()->NewNode(common()->LoopExitValue(), (*values())[i],
     735       19092 :                                       loop_exit);
     736       19092 :       (*values())[i] = rename;
     737             :     }
     738             :   }
     739             : 
     740             :   // Rename the effect.
     741             :   Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(),
     742        1245 :                                          GetEffectDependency(), loop_exit);
     743             :   UpdateEffectDependency(effect_rename);
     744             : }
     745             : 
     746        7258 : bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() {
     747       19530 :   return FLAG_analyze_environment_liveness &&
     748        9765 :          builder()->info()->is_deoptimization_enabled();
     749             : }
     750             : 
     751             : 
     752           0 : bool AstGraphBuilder::Environment::IsLivenessBlockConsistent() {
     753           0 :   return (!IsLivenessAnalysisEnabled() || IsMarkedAsUnreachable()) ==
     754           0 :          (liveness_block() == nullptr);
     755             : }
     756             : 
     757             : 
     758      181392 : AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
     759             :                                         Expression::Context kind)
     760      362784 :     : kind_(kind), owner_(own), outer_(own->ast_context()) {
     761             :   owner()->set_ast_context(this);  // Push.
     762             : #ifdef DEBUG
     763             :   original_height_ = environment()->stack_height();
     764             : #endif
     765           0 : }
     766             : 
     767             : 
     768      362784 : AstGraphBuilder::AstContext::~AstContext() {
     769      181392 :   owner()->set_ast_context(outer_);  // Pop.
     770           0 : }
     771             : 
     772             : 
     773       22453 : AstGraphBuilder::AstEffectContext::~AstEffectContext() {
     774             :   DCHECK(environment()->stack_height() == original_height_);
     775           0 : }
     776             : 
     777             : 
     778      153632 : AstGraphBuilder::AstValueContext::~AstValueContext() {
     779             :   DCHECK(environment()->stack_height() == original_height_ + 1);
     780           0 : }
     781             : 
     782             : 
     783        5307 : AstGraphBuilder::AstTestContext::~AstTestContext() {
     784             :   DCHECK(environment()->stack_height() == original_height_ + 1);
     785           0 : }
     786             : 
     787       22571 : void AstGraphBuilder::AstEffectContext::ProduceValue(Expression* expr,
     788             :                                                      Node* value) {
     789             :   // The value is ignored.
     790       22571 :   owner()->PrepareEagerCheckpoint(expr->id());
     791       22571 : }
     792             : 
     793      154414 : void AstGraphBuilder::AstValueContext::ProduceValue(Expression* expr,
     794             :                                                     Node* value) {
     795      308828 :   environment()->Push(value);
     796      154414 :   owner()->PrepareEagerCheckpoint(expr->id());
     797      154414 : }
     798             : 
     799        4639 : void AstGraphBuilder::AstTestContext::ProduceValue(Expression* expr,
     800             :                                                    Node* value) {
     801        9278 :   environment()->Push(owner()->BuildToBoolean(value, feedback_id_));
     802        4639 :   owner()->PrepareEagerCheckpoint(expr->id());
     803        4639 : }
     804             : 
     805             : 
     806         118 : Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return nullptr; }
     807             : 
     808             : 
     809         419 : Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
     810         838 :   return environment()->Pop();
     811             : }
     812             : 
     813             : 
     814           0 : Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
     815           0 :   return environment()->Pop();
     816             : }
     817             : 
     818             : 
     819           0 : Scope* AstGraphBuilder::current_scope() const {
     820       17065 :   return execution_context_->scope();
     821             : }
     822             : 
     823             : 
     824       82601 : Node* AstGraphBuilder::current_context() const {
     825           0 :   return environment()->Context();
     826             : }
     827             : 
     828             : 
     829        3904 : void AstGraphBuilder::ControlScope::PerformCommand(Command command,
     830             :                                                    Statement* target,
     831       26384 :                                                    Node* value) {
     832        3904 :   Environment* env = environment()->CopyAsUnreachable();
     833       18576 :   ControlScope* current = this;
     834       13192 :   while (current != nullptr) {
     835        9288 :     environment()->TrimStack(current->stack_height());
     836             :     environment()->TrimContextChain(current->context_length());
     837        9288 :     if (current->Execute(command, target, &value)) break;
     838        5384 :     current = current->outer_;
     839             :   }
     840             :   builder()->set_environment(env);
     841             :   DCHECK_NOT_NULL(current);  // Always handled (unless stack is malformed).
     842        3904 : }
     843             : 
     844             : 
     845        1147 : void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) {
     846        1147 :   PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant());
     847        1147 : }
     848             : 
     849             : 
     850         101 : void AstGraphBuilder::ControlScope::ContinueTo(BreakableStatement* stmt) {
     851         101 :   PerformCommand(CMD_CONTINUE, stmt, builder()->jsgraph()->TheHoleConstant());
     852         101 : }
     853             : 
     854             : 
     855           0 : void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) {
     856        2656 :   PerformCommand(CMD_RETURN, nullptr, return_value);
     857           0 : }
     858             : 
     859             : 
     860           0 : void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) {
     861           0 :   PerformCommand(CMD_THROW, nullptr, exception_value);
     862           0 : }
     863             : 
     864             : 
     865           6 : void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
     866           2 :   if (expr == nullptr) {
     867           4 :     return environment()->Push(jsgraph()->NullConstant());
     868             :   }
     869           0 :   VisitForValue(expr);
     870             : }
     871             : 
     872             : 
     873           0 : void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) {
     874           0 :   if (expr == nullptr) {
     875           0 :     return environment()->Push(jsgraph()->TheHoleConstant());
     876             :   }
     877           0 :   VisitForValue(expr);
     878             : }
     879             : 
     880             : 
     881        1547 : void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
     882       10868 :   for (int i = 0; i < exprs->length(); ++i) {
     883        9321 :     VisitForValue(exprs->at(i));
     884             :   }
     885        1547 : }
     886             : 
     887             : 
     888      307264 : void AstGraphBuilder::VisitForValue(Expression* expr) {
     889             :   AstValueContext for_value(this);
     890      153632 :   if (!CheckStackOverflow()) {
     891      153632 :     VisitNoStackOverflowCheck(expr);
     892             :   } else {
     893           0 :     ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
     894             :   }
     895      153632 : }
     896             : 
     897             : 
     898       44906 : void AstGraphBuilder::VisitForEffect(Expression* expr) {
     899             :   AstEffectContext for_effect(this);
     900       22453 :   if (!CheckStackOverflow()) {
     901       22453 :     VisitNoStackOverflowCheck(expr);
     902             :   } else {
     903           0 :     ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
     904             :   }
     905       22453 : }
     906             : 
     907             : 
     908       10614 : void AstGraphBuilder::VisitForTest(Expression* expr) {
     909             :   AstTestContext for_condition(this, expr->test_id());
     910        5307 :   if (!CheckStackOverflow()) {
     911        5307 :     VisitNoStackOverflowCheck(expr);
     912             :   } else {
     913           0 :     ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
     914             :   }
     915        5307 : }
     916             : 
     917             : 
     918        1331 : void AstGraphBuilder::Visit(Expression* expr) {
     919             :   // Reuses enclosing AstContext.
     920        1331 :   if (!CheckStackOverflow()) {
     921        1331 :     VisitNoStackOverflowCheck(expr);
     922             :   } else {
     923           0 :     ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
     924             :   }
     925        1331 : }
     926             : 
     927             : 
     928        2952 : void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
     929        2870 :   Variable* variable = decl->proxy()->var();
     930        2848 :   switch (variable->location()) {
     931             :     case VariableLocation::UNALLOCATED: {
     932             :       DCHECK(!variable->binding_needs_init());
     933           0 :       globals()->push_back(variable->name());
     934             :       FeedbackSlot slot = decl->proxy()->VariableFeedbackSlot();
     935             :       DCHECK(!slot.IsInvalid());
     936           0 :       globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
     937           0 :       globals()->push_back(isolate()->factory()->undefined_value());
     938           0 :       globals()->push_back(isolate()->factory()->undefined_value());
     939             :       break;
     940             :     }
     941             :     case VariableLocation::PARAMETER:
     942             :     case VariableLocation::LOCAL:
     943        2806 :       if (variable->binding_needs_init()) {
     944          30 :         Node* value = jsgraph()->TheHoleConstant();
     945          30 :         environment()->Bind(variable, value);
     946             :       }
     947             :       break;
     948             :     case VariableLocation::CONTEXT:
     949          42 :       if (variable->binding_needs_init()) {
     950          22 :         Node* value = jsgraph()->TheHoleConstant();
     951          44 :         const Operator* op = javascript()->StoreContext(0, variable->index());
     952             :         NewNode(op, value);
     953             :       }
     954             :       break;
     955             :     case VariableLocation::LOOKUP:
     956             :     case VariableLocation::MODULE:
     957           0 :       UNREACHABLE();
     958             :   }
     959        2848 : }
     960             : 
     961             : 
     962         176 : void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
     963          48 :   Variable* variable = decl->proxy()->var();
     964          44 :   switch (variable->location()) {
     965             :     case VariableLocation::UNALLOCATED: {
     966             :       Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
     967           0 :           decl->fun(), info()->script(), info());
     968             :       // Check for stack-overflow exception.
     969          44 :       if (function.is_null()) return SetStackOverflow();
     970           0 :       globals()->push_back(variable->name());
     971             :       FeedbackSlot slot = decl->proxy()->VariableFeedbackSlot();
     972             :       DCHECK(!slot.IsInvalid());
     973           0 :       globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
     974             : 
     975             :       // We need the slot where the literals array lives, too.
     976             :       slot = decl->fun()->LiteralFeedbackSlot();
     977             :       DCHECK(!slot.IsInvalid());
     978           0 :       globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
     979             : 
     980           0 :       globals()->push_back(function);
     981           0 :       break;
     982             :     }
     983             :     case VariableLocation::PARAMETER:
     984             :     case VariableLocation::LOCAL: {
     985          40 :       VisitForValue(decl->fun());
     986             :       Node* value = environment()->Pop();
     987          40 :       environment()->Bind(variable, value);
     988          40 :       break;
     989             :     }
     990             :     case VariableLocation::CONTEXT: {
     991           4 :       VisitForValue(decl->fun());
     992             :       Node* value = environment()->Pop();
     993           8 :       const Operator* op = javascript()->StoreContext(0, variable->index());
     994             :       NewNode(op, value);
     995             :       break;
     996             :     }
     997             :     case VariableLocation::LOOKUP:
     998             :     case VariableLocation::MODULE:
     999           0 :       UNREACHABLE();
    1000             :   }
    1001             : }
    1002             : 
    1003             : 
    1004       11222 : void AstGraphBuilder::VisitBlock(Block* stmt) {
    1005             :   BlockBuilder block(this);
    1006             :   ControlScopeForBreakable scope(this, stmt, &block);
    1007       11222 :   if (stmt->labels() != nullptr) block.BeginBlock();
    1008        5611 :   if (stmt->scope() == nullptr) {
    1009             :     // Visit statements in the same scope, no declarations.
    1010        5605 :     VisitStatements(stmt->statements());
    1011             :   } else {
    1012             :     // Visit declarations and statements in a block scope.
    1013           6 :     if (stmt->scope()->NeedsContext()) {
    1014           0 :       Node* context = BuildLocalBlockContext(stmt->scope());
    1015           0 :       ContextScope scope(this, stmt->scope(), context);
    1016           0 :       VisitDeclarations(stmt->scope()->declarations());
    1017           0 :       VisitStatements(stmt->statements());
    1018             :     } else {
    1019           6 :       VisitDeclarations(stmt->scope()->declarations());
    1020           6 :       VisitStatements(stmt->statements());
    1021             :     }
    1022             :   }
    1023        5611 :   if (stmt->labels() != nullptr) block.EndBlock();
    1024        5611 : }
    1025             : 
    1026             : 
    1027       22243 : void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
    1028       22243 :   VisitForEffect(stmt->expression());
    1029       22243 : }
    1030             : 
    1031             : 
    1032        1751 : void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
    1033             :   // Do nothing.
    1034        1751 : }
    1035             : 
    1036             : 
    1037           0 : void AstGraphBuilder::VisitSloppyBlockFunctionStatement(
    1038           0 :     SloppyBlockFunctionStatement* stmt) {
    1039           0 :   Visit(stmt->statement());
    1040           0 : }
    1041             : 
    1042             : 
    1043       14875 : void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
    1044             :   IfBuilder compare_if(this);
    1045        2975 :   VisitForTest(stmt->condition());
    1046             :   Node* condition = environment()->Pop();
    1047        2975 :   compare_if.If(condition);
    1048        2975 :   compare_if.Then();
    1049        2975 :   Visit(stmt->then_statement());
    1050        2975 :   compare_if.Else();
    1051        2975 :   Visit(stmt->else_statement());
    1052        2975 :   compare_if.End();
    1053        2975 : }
    1054             : 
    1055             : 
    1056         101 : void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
    1057         101 :   execution_control()->ContinueTo(stmt->target());
    1058         101 : }
    1059             : 
    1060             : 
    1061        1147 : void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
    1062        1147 :   execution_control()->BreakTo(stmt->target());
    1063        1147 : }
    1064             : 
    1065             : 
    1066        7968 : void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
    1067        2656 :   VisitForValue(stmt->expression());
    1068             :   Node* result = environment()->Pop();
    1069             :   execution_control()->ReturnValue(result);
    1070        2656 : }
    1071             : 
    1072             : 
    1073           0 : void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
    1074             :   // Dynamic scoping is supported only by going through Ignition first.
    1075           0 :   UNREACHABLE();
    1076             : }
    1077             : 
    1078             : 
    1079        1788 : void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
    1080             :   ZoneList<CaseClause*>* clauses = stmt->cases();
    1081        1130 :   SwitchBuilder compare_switch(this, clauses->length());
    1082             :   ControlScopeForBreakable scope(this, stmt, &compare_switch);
    1083          76 :   compare_switch.BeginSwitch();
    1084             :   int default_index = -1;
    1085             : 
    1086             :   // Keep the switch value on the stack until a case matches.
    1087          76 :   VisitForValue(stmt->tag());
    1088             : 
    1089             :   // Iterate over all cases and create nodes for label comparison.
    1090        1054 :   for (int i = 0; i < clauses->length(); i++) {
    1091         451 :     CaseClause* clause = clauses->at(i);
    1092             : 
    1093             :     // The default is not a test, remember index.
    1094         451 :     if (clause->is_default()) {
    1095             :       default_index = i;
    1096             :       continue;
    1097             :     }
    1098             : 
    1099             :     // Create nodes to perform label comparison as if via '==='. The switch
    1100             :     // value is still on the operand stack while the label is evaluated.
    1101         390 :     VisitForValue(clause->label());
    1102             :     Node* label = environment()->Pop();
    1103             :     Node* tag = environment()->Top();
    1104             : 
    1105             :     CompareOperationHint hint = CompareOperationHint::kAny;
    1106         390 :     const Operator* op = javascript()->StrictEqual(hint);
    1107             :     Node* condition = NewNode(op, tag, label);
    1108         390 :     compare_switch.BeginLabel(i, condition);
    1109             : 
    1110             :     // Discard the switch value at label match.
    1111             :     environment()->Pop();
    1112         390 :     compare_switch.EndLabel();
    1113             :   }
    1114             : 
    1115             :   // Discard the switch value and mark the default case.
    1116             :   environment()->Pop();
    1117          76 :   if (default_index >= 0) {
    1118          61 :     compare_switch.DefaultAt(default_index);
    1119             :   }
    1120             : 
    1121             :   // Iterate over all cases and create nodes for case bodies.
    1122         978 :   for (int i = 0; i < clauses->length(); i++) {
    1123         902 :     CaseClause* clause = clauses->at(i);
    1124         451 :     compare_switch.BeginCase(i);
    1125         451 :     VisitStatements(clause->statements());
    1126         451 :     compare_switch.EndCase();
    1127             :   }
    1128             : 
    1129          76 :   compare_switch.EndSwitch();
    1130          76 : }
    1131             : 
    1132             : 
    1133        1326 : void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
    1134             :   LoopBuilder while_loop(this);
    1135         884 :   while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
    1136         442 :   VisitIterationBody(stmt, &while_loop, stmt->StackCheckId());
    1137         442 :   while_loop.EndBody();
    1138         442 :   VisitForTest(stmt->cond());
    1139             :   Node* condition = environment()->Pop();
    1140         442 :   while_loop.BreakUnless(condition);
    1141         442 :   while_loop.EndLoop();
    1142         442 : }
    1143             : 
    1144             : 
    1145        1017 : void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
    1146             :   LoopBuilder while_loop(this);
    1147         678 :   while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
    1148         339 :   VisitForTest(stmt->cond());
    1149             :   Node* condition = environment()->Pop();
    1150         339 :   while_loop.BreakUnless(condition);
    1151         339 :   VisitIterationBody(stmt, &while_loop, stmt->StackCheckId());
    1152         339 :   while_loop.EndBody();
    1153         339 :   while_loop.EndLoop();
    1154         339 : }
    1155             : 
    1156             : 
    1157         265 : void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
    1158             :   LoopBuilder for_loop(this);
    1159             :   VisitIfNotNull(stmt->init());
    1160         106 :   for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
    1161          53 :   if (stmt->cond() != nullptr) {
    1162          51 :     VisitForTest(stmt->cond());
    1163             :     Node* condition = environment()->Pop();
    1164          51 :     for_loop.BreakUnless(condition);
    1165             :   } else {
    1166           2 :     for_loop.BreakUnless(jsgraph()->TrueConstant());
    1167             :   }
    1168          53 :   VisitIterationBody(stmt, &for_loop, stmt->StackCheckId());
    1169          53 :   for_loop.EndBody();
    1170             :   VisitIfNotNull(stmt->next());
    1171          53 :   for_loop.EndLoop();
    1172          53 : }
    1173             : 
    1174             : 
    1175           0 : void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
    1176             :   // Only the BytecodeGraphBuilder supports for-in.
    1177           0 :   return SetStackOverflow();
    1178             : }
    1179             : 
    1180             : 
    1181           0 : void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
    1182             :   // Iterator looping is supported only by going through Ignition first.
    1183           0 :   UNREACHABLE();
    1184             : }
    1185             : 
    1186             : 
    1187           0 : void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
    1188             :   // Exception handling is supported only by going through Ignition first.
    1189           0 :   UNREACHABLE();
    1190             : }
    1191             : 
    1192             : 
    1193           0 : void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
    1194             :   // Exception handling is supported only by going through Ignition first.
    1195           0 :   UNREACHABLE();
    1196             : }
    1197             : 
    1198             : 
    1199           0 : void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
    1200             :   // Debugger statement is supported only by going through Ignition first.
    1201           0 :   UNREACHABLE();
    1202             : }
    1203             : 
    1204             : 
    1205         208 : void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
    1206             :   // Find or build a shared function info.
    1207             :   Handle<SharedFunctionInfo> shared_info =
    1208          52 :       Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
    1209          52 :   CHECK(!shared_info.is_null());  // TODO(mstarzinger): Set stack overflow?
    1210             : 
    1211             :   // Create node to instantiate a new closure.
    1212          52 :   PretenureFlag pretenure = expr->pretenure() ? TENURED : NOT_TENURED;
    1213          52 :   VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
    1214             :   const Operator* op =
    1215          52 :       javascript()->CreateClosure(shared_info, pair, pretenure);
    1216             :   Node* value = NewNode(op);
    1217          52 :   ast_context()->ProduceValue(expr, value);
    1218          52 : }
    1219             : 
    1220           0 : void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) { UNREACHABLE(); }
    1221             : 
    1222           0 : void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
    1223           0 :   UNREACHABLE();
    1224             : }
    1225             : 
    1226             : 
    1227           0 : void AstGraphBuilder::VisitDoExpression(DoExpression* expr) {
    1228           0 :   VisitBlock(expr->block());
    1229           0 :   VisitVariableProxy(expr->result());
    1230             :   ast_context()->ReplaceValue(expr);
    1231           0 : }
    1232             : 
    1233             : 
    1234        3294 : void AstGraphBuilder::VisitConditional(Conditional* expr) {
    1235             :   IfBuilder compare_if(this);
    1236         549 :   VisitForTest(expr->condition());
    1237             :   Node* condition = environment()->Pop();
    1238         549 :   compare_if.If(condition);
    1239         549 :   compare_if.Then();
    1240         549 :   Visit(expr->then_expression());
    1241         549 :   compare_if.Else();
    1242         549 :   Visit(expr->else_expression());
    1243         549 :   compare_if.End();
    1244             :   // Skip plugging AST evaluation contexts of the test kind. This is to stay in
    1245             :   // sync with full codegen which doesn't prepare the proper bailout point (see
    1246             :   // the implementation of FullCodeGenerator::VisitForControl).
    1247        1098 :   if (ast_context()->IsTest()) return;
    1248             :   ast_context()->ReplaceValue(expr);
    1249             : }
    1250             : 
    1251             : 
    1252      186660 : void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
    1253       46665 :   VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
    1254       46665 :   PrepareEagerCheckpoint(BeforeId(expr));
    1255             :   Node* value = BuildVariableLoad(expr->var(), expr->id(), pair,
    1256       46665 :                                   ast_context()->GetStateCombine());
    1257       46665 :   ast_context()->ProduceValue(expr, value);
    1258       46665 : }
    1259             : 
    1260             : 
    1261      160728 : void AstGraphBuilder::VisitLiteral(Literal* expr) {
    1262       53576 :   Node* value = jsgraph()->Constant(expr->value());
    1263       53576 :   ast_context()->ProduceValue(expr, value);
    1264       53576 : }
    1265             : 
    1266             : 
    1267          10 : void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
    1268           2 :   Node* closure = GetFunctionClosure();
    1269             : 
    1270             :   // Create node to materialize a regular expression literal.
    1271             :   const Operator* op = javascript()->CreateLiteralRegExp(
    1272             :       expr->pattern(), expr->flags(),
    1273           2 :       FeedbackVector::GetIndex(expr->literal_slot()));
    1274             :   Node* literal = NewNode(op, closure);
    1275           2 :   PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
    1276           2 :   ast_context()->ProduceValue(expr, literal);
    1277           2 : }
    1278             : 
    1279             : 
    1280         122 : void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
    1281           8 :   Node* closure = GetFunctionClosure();
    1282             : 
    1283             :   // Create node to deep-copy the literal boilerplate.
    1284             :   const Operator* op = javascript()->CreateLiteralObject(
    1285             :       expr->GetOrBuildConstantProperties(isolate()), expr->ComputeFlags(true),
    1286          16 :       FeedbackVector::GetIndex(expr->literal_slot()), expr->properties_count());
    1287             :   Node* literal = NewNode(op, closure);
    1288             :   PrepareFrameState(literal, expr->CreateLiteralId(),
    1289           8 :                     OutputFrameStateCombine::Push());
    1290             : 
    1291             :   // The object is expected on the operand stack during computation of the
    1292             :   // property values and is the value of the entire expression.
    1293             :   environment()->Push(literal);
    1294             : 
    1295             :   // Create nodes to store computed values into the literal.
    1296             :   AccessorTable accessor_table(local_zone());
    1297          32 :   for (int i = 0; i < expr->properties()->length(); i++) {
    1298          16 :     ObjectLiteral::Property* property = expr->properties()->at(i);
    1299             :     DCHECK(!property->is_computed_name());
    1300           8 :     if (property->IsCompileTimeValue()) continue;
    1301             : 
    1302          16 :     Literal* key = property->key()->AsLiteral();
    1303           8 :     switch (property->kind()) {
    1304             :       case ObjectLiteral::Property::SPREAD:
    1305             :       case ObjectLiteral::Property::CONSTANT:
    1306           0 :         UNREACHABLE();
    1307             :       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
    1308             :         DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
    1309             :       // Fall through.
    1310             :       case ObjectLiteral::Property::COMPUTED: {
    1311             :         // It is safe to use [[Put]] here because the boilerplate already
    1312             :         // contains computed properties with an uninitialized value.
    1313           4 :         if (key->IsStringLiteral()) {
    1314             :           DCHECK(key->IsPropertyName());
    1315           2 :           if (property->emit_store()) {
    1316           2 :             VisitForValue(property->value());
    1317             :             Node* value = environment()->Pop();
    1318             :             Node* literal = environment()->Top();
    1319             :             Handle<Name> name = key->AsPropertyName();
    1320             :             VectorSlotPair feedback =
    1321           2 :                 CreateVectorSlotPair(property->GetSlot(0));
    1322           2 :             Node* store = BuildNamedStoreOwn(literal, name, value, feedback);
    1323             :             PrepareFrameState(store, key->id(),
    1324           2 :                               OutputFrameStateCombine::Ignore());
    1325           2 :             BuildSetHomeObject(value, literal, property, 1);
    1326             :           } else {
    1327           0 :             VisitForEffect(property->value());
    1328             :           }
    1329             :           break;
    1330             :         }
    1331             :         environment()->Push(environment()->Top());  // Duplicate receiver.
    1332           2 :         VisitForValue(property->key());
    1333           2 :         VisitForValue(property->value());
    1334             :         Node* value = environment()->Pop();
    1335             :         Node* key = environment()->Pop();
    1336             :         Node* receiver = environment()->Pop();
    1337           2 :         if (property->emit_store()) {
    1338           2 :           Node* language = jsgraph()->Constant(SLOPPY);
    1339           2 :           const Operator* op = javascript()->CallRuntime(Runtime::kSetProperty);
    1340             :           Node* set_property = NewNode(op, receiver, key, value, language);
    1341             :           // SetProperty should not lazy deopt on an object literal.
    1342           2 :           PrepareFrameState(set_property, BailoutId::None());
    1343           2 :           BuildSetHomeObject(value, receiver, property);
    1344             :         }
    1345             :         break;
    1346             :       }
    1347             :       case ObjectLiteral::Property::PROTOTYPE: {
    1348             :         environment()->Push(environment()->Top());  // Duplicate receiver.
    1349           2 :         VisitForValue(property->value());
    1350             :         Node* value = environment()->Pop();
    1351             :         Node* receiver = environment()->Pop();
    1352             :         DCHECK(property->emit_store());
    1353             :         const Operator* op =
    1354           2 :             javascript()->CallRuntime(Runtime::kInternalSetPrototype);
    1355             :         Node* set_prototype = NewNode(op, receiver, value);
    1356             :         // SetPrototype should not lazy deopt on an object literal.
    1357           2 :         PrepareFrameState(set_prototype, expr->GetIdForPropertySet(i));
    1358           2 :         break;
    1359             :       }
    1360             :       case ObjectLiteral::Property::GETTER:
    1361           2 :         if (property->emit_store()) {
    1362           2 :           AccessorTable::Iterator it = accessor_table.lookup(key);
    1363           4 :           it->second->bailout_id = expr->GetIdForPropertySet(i);
    1364           2 :           it->second->getter = property;
    1365             :         }
    1366             :         break;
    1367             :       case ObjectLiteral::Property::SETTER:
    1368           0 :         if (property->emit_store()) {
    1369           0 :           AccessorTable::Iterator it = accessor_table.lookup(key);
    1370           0 :           it->second->bailout_id = expr->GetIdForPropertySet(i);
    1371           0 :           it->second->setter = property;
    1372             :         }
    1373             :         break;
    1374             :     }
    1375             :   }
    1376             : 
    1377             :   // Create nodes to define accessors, using only a single call to the runtime
    1378             :   // for each pair of corresponding getters and setters.
    1379             :   literal = environment()->Top();  // Reload from operand stack.
    1380          18 :   for (AccessorTable::Iterator it = accessor_table.begin();
    1381             :        it != accessor_table.end(); ++it) {
    1382           2 :     VisitForValue(it->first);
    1383           2 :     VisitObjectLiteralAccessor(literal, it->second->getter);
    1384           2 :     VisitObjectLiteralAccessor(literal, it->second->setter);
    1385             :     Node* setter = environment()->Pop();
    1386             :     Node* getter = environment()->Pop();
    1387             :     Node* name = environment()->Pop();
    1388           2 :     Node* attr = jsgraph()->Constant(NONE);
    1389             :     const Operator* op =
    1390           2 :         javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked);
    1391             :     Node* call = NewNode(op, literal, name, getter, setter, attr);
    1392           2 :     PrepareFrameState(call, it->second->bailout_id);
    1393             :   }
    1394          16 :   ast_context()->ProduceValue(expr, environment()->Pop());
    1395           8 : }
    1396             : 
    1397             : 
    1398           4 : void AstGraphBuilder::VisitObjectLiteralAccessor(
    1399           2 :     Node* home_object, ObjectLiteralProperty* property) {
    1400           4 :   if (property == nullptr) {
    1401           2 :     VisitForValueOrNull(nullptr);
    1402             :   } else {
    1403           2 :     VisitForValue(property->value());
    1404           2 :     BuildSetHomeObject(environment()->Top(), home_object, property);
    1405             :   }
    1406           4 : }
    1407             : 
    1408             : 
    1409          28 : void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
    1410           2 :   Node* closure = GetFunctionClosure();
    1411             : 
    1412             :   // Create node to deep-copy the literal boilerplate.
    1413             :   const Operator* op = javascript()->CreateLiteralArray(
    1414             :       expr->GetOrBuildConstantElements(isolate()), expr->ComputeFlags(true),
    1415           4 :       FeedbackVector::GetIndex(expr->literal_slot()), expr->values()->length());
    1416             :   Node* literal = NewNode(op, closure);
    1417             :   PrepareFrameState(literal, expr->CreateLiteralId(),
    1418           2 :                     OutputFrameStateCombine::Push());
    1419             : 
    1420             :   // The array is expected on the operand stack during computation of the
    1421             :   // element values.
    1422             :   environment()->Push(literal);
    1423             : 
    1424             :   // Create nodes to evaluate all the non-constant subexpressions and to store
    1425             :   // them into the newly cloned array.
    1426          16 :   for (int array_index = 0; array_index < expr->values()->length();
    1427             :        array_index++) {
    1428           6 :     Expression* subexpr = expr->values()->at(array_index);
    1429             :     DCHECK(!subexpr->IsSpread());
    1430          10 :     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
    1431             : 
    1432           2 :     VisitForValue(subexpr);
    1433           2 :     VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
    1434             :     Node* value = environment()->Pop();
    1435           2 :     Node* index = jsgraph()->Constant(array_index);
    1436             :     Node* literal = environment()->Top();
    1437           2 :     Node* store = BuildKeyedStore(literal, index, value, pair);
    1438             :     PrepareFrameState(store, expr->GetIdForElement(array_index),
    1439           2 :                       OutputFrameStateCombine::Ignore());
    1440             :   }
    1441             : 
    1442           4 :   ast_context()->ProduceValue(expr, environment()->Pop());
    1443           2 : }
    1444             : 
    1445      162951 : void AstGraphBuilder::VisitAssignment(Assignment* expr) {
    1446             :   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
    1447             : 
    1448             :   // Left-hand side can only be a property, a global or a variable slot.
    1449       29756 :   Property* property = expr->target()->AsProperty();
    1450       21396 :   LhsKind assign_type = Property::GetAssignType(property);
    1451             :   bool needs_frame_state_before = true;
    1452             : 
    1453             :   // Evaluate LHS expression.
    1454       21396 :   switch (assign_type) {
    1455             :     case VARIABLE: {
    1456       34432 :       Variable* variable = expr->target()->AsVariableProxy()->var();
    1457       31695 :       if (variable->location() == VariableLocation::PARAMETER ||
    1458       17831 :           variable->location() == VariableLocation::LOCAL ||
    1459             :           variable->location() == VariableLocation::CONTEXT) {
    1460             :         needs_frame_state_before = false;
    1461             :       }
    1462             :       break;
    1463             :     }
    1464             :     case NAMED_PROPERTY:
    1465          17 :       VisitForValue(property->obj());
    1466          17 :       break;
    1467             :     case KEYED_PROPERTY:
    1468        4163 :       VisitForValue(property->obj());
    1469        4163 :       VisitForValue(property->key());
    1470        4163 :       break;
    1471             :     case NAMED_SUPER_PROPERTY:
    1472             :     case KEYED_SUPER_PROPERTY:
    1473           0 :       UNREACHABLE();
    1474             :       break;
    1475             :   }
    1476             : 
    1477             :   // Evaluate the value and potentially handle compound assignments by loading
    1478             :   // the left-hand side value and performing a binary operation.
    1479       21396 :   if (expr->is_compound()) {
    1480             :     Node* old_value = nullptr;
    1481          20 :     switch (assign_type) {
    1482             :       case VARIABLE: {
    1483          28 :         VariableProxy* proxy = expr->target()->AsVariableProxy();
    1484             :         VectorSlotPair pair =
    1485          14 :             CreateVectorSlotPair(proxy->VariableFeedbackSlot());
    1486          14 :         PrepareEagerCheckpoint(BeforeId(proxy));
    1487             :         old_value = BuildVariableLoad(proxy->var(), expr->target()->id(), pair,
    1488          14 :                                       OutputFrameStateCombine::Push());
    1489             :         break;
    1490             :       }
    1491             :       case NAMED_PROPERTY: {
    1492             :         Node* object = environment()->Top();
    1493           0 :         Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
    1494             :         VectorSlotPair pair =
    1495           0 :             CreateVectorSlotPair(property->PropertyFeedbackSlot());
    1496           0 :         old_value = BuildNamedLoad(object, name, pair);
    1497             :         PrepareFrameState(old_value, property->LoadId(),
    1498           0 :                           OutputFrameStateCombine::Push());
    1499             :         break;
    1500             :       }
    1501             :       case KEYED_PROPERTY: {
    1502             :         Node* key = environment()->Top();
    1503           6 :         Node* object = environment()->Peek(1);
    1504             :         VectorSlotPair pair =
    1505           6 :             CreateVectorSlotPair(property->PropertyFeedbackSlot());
    1506           6 :         old_value = BuildKeyedLoad(object, key, pair);
    1507             :         PrepareFrameState(old_value, property->LoadId(),
    1508           6 :                           OutputFrameStateCombine::Push());
    1509             :         break;
    1510             :       }
    1511             :       case NAMED_SUPER_PROPERTY:
    1512             :       case KEYED_SUPER_PROPERTY:
    1513           0 :         UNREACHABLE();
    1514             :         break;
    1515             :     }
    1516             :     environment()->Push(old_value);
    1517          20 :     VisitForValue(expr->value());
    1518             :     Node* right = environment()->Pop();
    1519             :     Node* left = environment()->Pop();
    1520             :     Node* value =
    1521             :         BuildBinaryOp(left, right, expr->binary_op(),
    1522          20 :                       expr->binary_operation()->BinaryOperationFeedbackId());
    1523             :     PrepareFrameState(value, expr->binary_operation()->id(),
    1524          20 :                       OutputFrameStateCombine::Push());
    1525             :     environment()->Push(value);
    1526          20 :     if (needs_frame_state_before) {
    1527           6 :       PrepareEagerCheckpoint(expr->binary_operation()->id());
    1528             :     }
    1529             :   } else {
    1530       21376 :     VisitForValue(expr->value());
    1531             :   }
    1532             : 
    1533             :   // Store the value.
    1534             :   Node* value = environment()->Pop();
    1535       21396 :   VectorSlotPair feedback = CreateVectorSlotPair(expr->AssignmentSlot());
    1536       21396 :   switch (assign_type) {
    1537             :     case VARIABLE: {
    1538       34432 :       Variable* variable = expr->target()->AsVariableProxy()->var();
    1539             :       BuildVariableAssignment(variable, value, expr->op(), feedback, expr->id(),
    1540       17216 :                               ast_context()->GetStateCombine());
    1541       17216 :       break;
    1542             :     }
    1543             :     case NAMED_PROPERTY: {
    1544             :       Node* object = environment()->Pop();
    1545          17 :       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
    1546          17 :       Node* store = BuildNamedStore(object, name, value, feedback);
    1547             :       PrepareFrameState(store, expr->AssignmentId(),
    1548          17 :                         OutputFrameStateCombine::Push());
    1549             :       break;
    1550             :     }
    1551             :     case KEYED_PROPERTY: {
    1552             :       Node* key = environment()->Pop();
    1553             :       Node* object = environment()->Pop();
    1554        4163 :       Node* store = BuildKeyedStore(object, key, value, feedback);
    1555             :       PrepareFrameState(store, expr->AssignmentId(),
    1556        4163 :                         OutputFrameStateCombine::Push());
    1557        4163 :       break;
    1558             :     }
    1559             :     case NAMED_SUPER_PROPERTY:
    1560             :     case KEYED_SUPER_PROPERTY:
    1561           0 :       UNREACHABLE();
    1562             :       break;
    1563             :   }
    1564             : 
    1565       21396 :   ast_context()->ProduceValue(expr, value);
    1566       21396 : }
    1567             : 
    1568           0 : void AstGraphBuilder::VisitSuspend(Suspend* expr) {
    1569             :   // Generator functions are supported only by going through Ignition first.
    1570           0 :   UNREACHABLE();
    1571             : }
    1572             : 
    1573             : 
    1574          48 : void AstGraphBuilder::VisitThrow(Throw* expr) {
    1575          16 :   VisitForValue(expr->exception());
    1576             :   Node* exception = environment()->Pop();
    1577          16 :   Node* value = BuildThrowError(exception, expr->id());
    1578          16 :   ast_context()->ProduceValue(expr, value);
    1579          16 : }
    1580             : 
    1581             : 
    1582       37638 : void AstGraphBuilder::VisitProperty(Property* expr) {
    1583             :   Node* value = nullptr;
    1584        6276 :   LhsKind property_kind = Property::GetAssignType(expr);
    1585        6276 :   VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
    1586        6276 :   switch (property_kind) {
    1587             :     case VARIABLE:
    1588           0 :       UNREACHABLE();
    1589             :       break;
    1590             :     case NAMED_PROPERTY: {
    1591          18 :       VisitForValue(expr->obj());
    1592             :       Node* object = environment()->Pop();
    1593          18 :       Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
    1594          18 :       value = BuildNamedLoad(object, name, pair);
    1595          18 :       PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
    1596             :       break;
    1597             :     }
    1598             :     case KEYED_PROPERTY: {
    1599        6258 :       VisitForValue(expr->obj());
    1600        6258 :       VisitForValue(expr->key());
    1601             :       Node* key = environment()->Pop();
    1602             :       Node* object = environment()->Pop();
    1603        6258 :       value = BuildKeyedLoad(object, key, pair);
    1604        6258 :       PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
    1605        6258 :       break;
    1606             :     }
    1607             :     case NAMED_SUPER_PROPERTY:
    1608             :     case KEYED_SUPER_PROPERTY:
    1609           0 :       UNREACHABLE();
    1610             :       break;
    1611             :   }
    1612        6276 :   ast_context()->ProduceValue(expr, value);
    1613        6276 : }
    1614             : 
    1615             : 
    1616       19557 : void AstGraphBuilder::VisitCall(Call* expr) {
    1617             :   Expression* callee = expr->expression();
    1618        1498 :   Call::CallType call_type = expr->GetCallType();
    1619        1498 :   CHECK(!expr->is_possibly_eval());
    1620             : 
    1621             :   // Prepare the callee and the receiver to the function call. This depends on
    1622             :   // the semantics of the underlying call type.
    1623             :   ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
    1624             :   Node* receiver_value = nullptr;
    1625             :   Node* callee_value = nullptr;
    1626        1498 :   switch (call_type) {
    1627             :     case Call::GLOBAL_CALL: {
    1628          44 :       VariableProxy* proxy = callee->AsVariableProxy();
    1629          22 :       VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
    1630          22 :       PrepareEagerCheckpoint(BeforeId(proxy));
    1631             :       callee_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
    1632          22 :                                        pair, OutputFrameStateCombine::Push());
    1633             :       receiver_hint = ConvertReceiverMode::kNullOrUndefined;
    1634          22 :       receiver_value = jsgraph()->UndefinedConstant();
    1635             :       break;
    1636             :     }
    1637             :     case Call::NAMED_PROPERTY_CALL: {
    1638          24 :       Property* property = callee->AsProperty();
    1639             :       VectorSlotPair feedback =
    1640           8 :           CreateVectorSlotPair(property->PropertyFeedbackSlot());
    1641           8 :       VisitForValue(property->obj());
    1642           8 :       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
    1643             :       Node* object = environment()->Top();
    1644           8 :       callee_value = BuildNamedLoad(object, name, feedback);
    1645             :       PrepareFrameState(callee_value, property->LoadId(),
    1646           8 :                         OutputFrameStateCombine::Push());
    1647             :       // Note that a property call requires the receiver to be wrapped into
    1648             :       // an object for sloppy callees. However the receiver is guaranteed
    1649             :       // not to be null or undefined at this point.
    1650             :       receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
    1651             :       receiver_value = environment()->Pop();
    1652             :       break;
    1653             :     }
    1654             :     case Call::KEYED_PROPERTY_CALL: {
    1655         249 :       Property* property = callee->AsProperty();
    1656             :       VectorSlotPair feedback =
    1657          83 :           CreateVectorSlotPair(property->PropertyFeedbackSlot());
    1658          83 :       VisitForValue(property->obj());
    1659          83 :       VisitForValue(property->key());
    1660             :       Node* key = environment()->Pop();
    1661             :       Node* object = environment()->Top();
    1662          83 :       callee_value = BuildKeyedLoad(object, key, feedback);
    1663             :       PrepareFrameState(callee_value, property->LoadId(),
    1664          83 :                         OutputFrameStateCombine::Push());
    1665             :       // Note that a property call requires the receiver to be wrapped into
    1666             :       // an object for sloppy callees. However the receiver is guaranteed
    1667             :       // not to be null or undefined at this point.
    1668             :       receiver_hint = ConvertReceiverMode::kNotNullOrUndefined;
    1669             :       receiver_value = environment()->Pop();
    1670             :       break;
    1671             :     }
    1672             :     case Call::OTHER_CALL:
    1673        1385 :       VisitForValue(callee);
    1674             :       callee_value = environment()->Pop();
    1675             :       receiver_hint = ConvertReceiverMode::kNullOrUndefined;
    1676        1385 :       receiver_value = jsgraph()->UndefinedConstant();
    1677        1385 :       break;
    1678             :     case Call::NAMED_SUPER_PROPERTY_CALL:
    1679             :     case Call::KEYED_SUPER_PROPERTY_CALL:
    1680             :     case Call::SUPER_CALL:
    1681             :     case Call::WITH_CALL:
    1682           0 :       UNREACHABLE();
    1683             :   }
    1684             : 
    1685             :   // The callee and the receiver both have to be pushed onto the operand stack
    1686             :   // before arguments are being evaluated.
    1687             :   environment()->Push(callee_value);
    1688             :   environment()->Push(receiver_value);
    1689             : 
    1690             :   // Evaluate all arguments to the function call,
    1691             :   ZoneList<Expression*>* args = expr->arguments();
    1692        1498 :   VisitForValues(args);
    1693             : 
    1694             :   // Create node to perform the function call.
    1695        1498 :   float const frequency = ComputeCallFrequency(expr->CallFeedbackICSlot());
    1696        1498 :   VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
    1697             :   const Operator* call =
    1698        2996 :       javascript()->Call(args->length() + 2, frequency, feedback, receiver_hint,
    1699        2996 :                          expr->tail_call_mode());
    1700        1498 :   PrepareEagerCheckpoint(expr->CallId());
    1701        1498 :   Node* value = ProcessArguments(call, args->length() + 2);
    1702             :   // The callee passed to the call, we just need to push something here to
    1703             :   // satisfy the bailout location contract. The fullcodegen code will not
    1704             :   // ever look at this value, so we just push optimized_out here.
    1705        1498 :   environment()->Push(jsgraph()->OptimizedOutConstant());
    1706        1498 :   PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
    1707        1498 :   environment()->Drop(1);
    1708        1498 :   ast_context()->ProduceValue(expr, value);
    1709        1498 : }
    1710             : 
    1711             : 
    1712          20 : void AstGraphBuilder::VisitCallNew(CallNew* expr) {
    1713           4 :   VisitForValue(expr->expression());
    1714             : 
    1715             :   // Evaluate all arguments to the construct call.
    1716             :   ZoneList<Expression*>* args = expr->arguments();
    1717           4 :   VisitForValues(args);
    1718             : 
    1719             :   // The new target is the same as the callee.
    1720          16 :   environment()->Push(environment()->Peek(args->length()));
    1721             : 
    1722             :   // Create node to perform the construct call.
    1723           4 :   float const frequency = ComputeCallFrequency(expr->CallNewFeedbackSlot());
    1724           4 :   VectorSlotPair feedback = CreateVectorSlotPair(expr->CallNewFeedbackSlot());
    1725             :   const Operator* call =
    1726           8 :       javascript()->Construct(args->length() + 2, frequency, feedback);
    1727           4 :   Node* value = ProcessArguments(call, args->length() + 2);
    1728           4 :   PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
    1729           4 :   ast_context()->ProduceValue(expr, value);
    1730           4 : }
    1731             : 
    1732             : 
    1733           0 : void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
    1734             :   // The callee and the receiver both have to be pushed onto the operand stack
    1735             :   // before arguments are being evaluated.
    1736           0 :   Node* callee_value = BuildLoadNativeContextField(expr->context_index());
    1737           0 :   Node* receiver_value = jsgraph()->UndefinedConstant();
    1738             : 
    1739             :   environment()->Push(callee_value);
    1740             :   environment()->Push(receiver_value);
    1741             : 
    1742             :   // Evaluate all arguments to the JS runtime call.
    1743             :   ZoneList<Expression*>* args = expr->arguments();
    1744           0 :   VisitForValues(args);
    1745             : 
    1746             :   // Create node to perform the JS runtime call.
    1747           0 :   const Operator* call = javascript()->Call(args->length() + 2);
    1748           0 :   PrepareEagerCheckpoint(expr->CallId());
    1749           0 :   Node* value = ProcessArguments(call, args->length() + 2);
    1750           0 :   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
    1751           0 :   ast_context()->ProduceValue(expr, value);
    1752           0 : }
    1753             : 
    1754             : 
    1755         315 : void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
    1756             :   // Handle calls to runtime functions implemented in JavaScript separately as
    1757             :   // the call follows JavaScript ABI and the callee is statically unknown.
    1758          45 :   if (expr->is_jsruntime()) {
    1759          45 :     return VisitCallJSRuntime(expr);
    1760             :   }
    1761             : 
    1762             :   // Evaluate all arguments to the runtime call.
    1763             :   ZoneList<Expression*>* args = expr->arguments();
    1764          45 :   VisitForValues(args);
    1765             : 
    1766             :   // Create node to perform the runtime call.
    1767          45 :   Runtime::FunctionId functionId = expr->function()->function_id;
    1768         135 :   const Operator* call = javascript()->CallRuntime(functionId, args->length());
    1769          67 :   if (expr->function()->intrinsic_type == Runtime::IntrinsicType::RUNTIME ||
    1770          22 :       expr->function()->function_id == Runtime::kInlineCall) {
    1771          25 :     PrepareEagerCheckpoint(expr->CallId());
    1772             :   }
    1773          45 :   Node* value = ProcessArguments(call, args->length());
    1774          45 :   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
    1775          45 :   ast_context()->ProduceValue(expr, value);
    1776             : }
    1777             : 
    1778             : 
    1779         965 : void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
    1780         965 :   switch (expr->op()) {
    1781             :     case Token::DELETE:
    1782          18 :       return VisitDelete(expr);
    1783             :     case Token::VOID:
    1784           0 :       return VisitVoid(expr);
    1785             :     case Token::TYPEOF:
    1786           0 :       return VisitTypeof(expr);
    1787             :     case Token::NOT:
    1788         947 :       return VisitNot(expr);
    1789             :     default:
    1790           0 :       UNREACHABLE();
    1791             :   }
    1792             : }
    1793             : 
    1794             : 
    1795         648 : void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
    1796             :   DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
    1797             : 
    1798             :   // Left-hand side can only be a property, a global or a variable slot.
    1799          53 :   Property* property = expr->expression()->AsProperty();
    1800          53 :   LhsKind assign_type = Property::GetAssignType(property);
    1801             : 
    1802             :   // Reserve space for result of postfix operation.
    1803          61 :   bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
    1804          53 :   if (is_postfix && assign_type != VARIABLE) {
    1805           0 :     environment()->Push(jsgraph()->ZeroConstant());
    1806             :   }
    1807             : 
    1808             :   // Evaluate LHS expression and get old value.
    1809             :   Node* old_value = nullptr;
    1810             :   int stack_depth = -1;
    1811          53 :   switch (assign_type) {
    1812             :     case VARIABLE: {
    1813         106 :       VariableProxy* proxy = expr->expression()->AsVariableProxy();
    1814          53 :       VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
    1815          53 :       PrepareEagerCheckpoint(BeforeId(proxy));
    1816             :       old_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
    1817          53 :                                     pair, OutputFrameStateCombine::Push());
    1818             :       stack_depth = 0;
    1819             :       break;
    1820             :     }
    1821             :     case NAMED_PROPERTY: {
    1822           0 :       VisitForValue(property->obj());
    1823             :       Node* object = environment()->Top();
    1824           0 :       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
    1825             :       VectorSlotPair pair =
    1826           0 :           CreateVectorSlotPair(property->PropertyFeedbackSlot());
    1827           0 :       old_value = BuildNamedLoad(object, name, pair);
    1828             :       PrepareFrameState(old_value, property->LoadId(),
    1829           0 :                         OutputFrameStateCombine::Push());
    1830             :       stack_depth = 1;
    1831             :       break;
    1832             :     }
    1833             :     case KEYED_PROPERTY: {
    1834           0 :       VisitForValue(property->obj());
    1835           0 :       VisitForValue(property->key());
    1836             :       Node* key = environment()->Top();
    1837           0 :       Node* object = environment()->Peek(1);
    1838             :       VectorSlotPair pair =
    1839           0 :           CreateVectorSlotPair(property->PropertyFeedbackSlot());
    1840           0 :       old_value = BuildKeyedLoad(object, key, pair);
    1841             :       PrepareFrameState(old_value, property->LoadId(),
    1842           0 :                         OutputFrameStateCombine::Push());
    1843             :       stack_depth = 2;
    1844             :       break;
    1845             :     }
    1846             :     case NAMED_SUPER_PROPERTY:
    1847             :     case KEYED_SUPER_PROPERTY:
    1848           0 :       UNREACHABLE();
    1849             :       break;
    1850             :   }
    1851             : 
    1852             :   // Convert old value into a number.
    1853          53 :   old_value = NewNode(javascript()->ToNumber(), old_value);
    1854             :   PrepareFrameState(old_value, expr->ToNumberId(),
    1855          53 :                     OutputFrameStateCombine::Push());
    1856             : 
    1857             :   // Create a proper eager frame state for the stores.
    1858             :   environment()->Push(old_value);
    1859          53 :   PrepareEagerCheckpoint(expr->ToNumberId());
    1860             :   old_value = environment()->Pop();
    1861             : 
    1862             :   // Save result for postfix expressions at correct stack depth.
    1863          53 :   if (is_postfix) {
    1864           2 :     if (assign_type != VARIABLE) {
    1865           0 :       environment()->Poke(stack_depth, old_value);
    1866             :     } else {
    1867             :       environment()->Push(old_value);
    1868             :     }
    1869             :   }
    1870             : 
    1871             :   // Create node to perform +1/-1 operation.
    1872             :   Node* value = BuildBinaryOp(old_value, jsgraph()->OneConstant(),
    1873          53 :                               expr->binary_op(), expr->CountBinOpFeedbackId());
    1874             :   // This should never lazy deopt because we have converted to number before.
    1875          53 :   PrepareFrameState(value, BailoutId::None());
    1876             : 
    1877             :   // Store the value.
    1878          53 :   VectorSlotPair feedback = CreateVectorSlotPair(expr->CountSlot());
    1879          53 :   switch (assign_type) {
    1880             :     case VARIABLE: {
    1881         106 :       Variable* variable = expr->expression()->AsVariableProxy()->var();
    1882             :       environment()->Push(value);
    1883             :       BuildVariableAssignment(variable, value, expr->op(), feedback,
    1884          53 :                               expr->AssignmentId());
    1885             :       environment()->Pop();
    1886             :       break;
    1887             :     }
    1888             :     case NAMED_PROPERTY: {
    1889             :       Node* object = environment()->Pop();
    1890           0 :       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
    1891           0 :       Node* store = BuildNamedStore(object, name, value, feedback);
    1892             :       PrepareFrameState(store, expr->AssignmentId(),
    1893           0 :                         OutputFrameStateCombine::Push());
    1894             :       break;
    1895             :     }
    1896             :     case KEYED_PROPERTY: {
    1897             :       Node* key = environment()->Pop();
    1898             :       Node* object = environment()->Pop();
    1899           0 :       Node* store = BuildKeyedStore(object, key, value, feedback);
    1900             :       PrepareFrameState(store, expr->AssignmentId(),
    1901           0 :                         OutputFrameStateCombine::Push());
    1902           0 :       break;
    1903             :     }
    1904             :     case NAMED_SUPER_PROPERTY:
    1905             :     case KEYED_SUPER_PROPERTY:
    1906           0 :       UNREACHABLE();
    1907             :       break;
    1908             :   }
    1909             : 
    1910             :   // Restore old value for postfix expressions.
    1911          53 :   if (is_postfix) value = environment()->Pop();
    1912             : 
    1913          53 :   ast_context()->ProduceValue(expr, value);
    1914          53 : }
    1915             : 
    1916             : 
    1917      380449 : void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
    1918       47760 :   switch (expr->op()) {
    1919             :     case Token::COMMA:
    1920         210 :       return VisitComma(expr);
    1921             :     case Token::OR:
    1922             :     case Token::AND:
    1923          23 :       return VisitLogicalExpression(expr);
    1924             :     default: {
    1925       47527 :       VisitForValue(expr->left());
    1926       47527 :       VisitForValue(expr->right());
    1927             :       Node* right = environment()->Pop();
    1928             :       Node* left = environment()->Pop();
    1929             :       Node* value = BuildBinaryOp(left, right, expr->op(),
    1930       47527 :                                   expr->BinaryOperationFeedbackId());
    1931       47527 :       PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
    1932       47527 :       ast_context()->ProduceValue(expr, value);
    1933             :     }
    1934             :   }
    1935             : }
    1936             : 
    1937           0 : void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr,
    1938             :                                              Expression* sub_expr,
    1939           0 :                                              Node* nil_value) {
    1940             :   const Operator* op = nullptr;
    1941           0 :   switch (expr->op()) {
    1942             :     case Token::EQ:
    1943           0 :       op = javascript()->Equal(CompareOperationHint::kAny);
    1944           0 :       break;
    1945             :     case Token::EQ_STRICT:
    1946           0 :       op = javascript()->StrictEqual(CompareOperationHint::kAny);
    1947           0 :       break;
    1948             :     default:
    1949           0 :       UNREACHABLE();
    1950             :   }
    1951           0 :   VisitForValue(sub_expr);
    1952             :   Node* value_to_compare = environment()->Pop();
    1953             :   Node* value = NewNode(op, value_to_compare, nil_value);
    1954           0 :   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
    1955           0 :   return ast_context()->ProduceValue(expr, value);
    1956             : }
    1957             : 
    1958           0 : void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr,
    1959             :                                                 Expression* sub_expr,
    1960           0 :                                                 Handle<String> check) {
    1961           0 :   VisitTypeofExpression(sub_expr);
    1962           0 :   Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop());
    1963             :   Node* value = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
    1964           0 :                         typeof_arg, jsgraph()->Constant(check));
    1965           0 :   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
    1966           0 :   return ast_context()->ProduceValue(expr, value);
    1967             : }
    1968             : 
    1969       34344 : void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
    1970             :   // Check for a few fast cases. The AST visiting behavior must be in sync
    1971             :   // with the full codegen: We don't push both left and right values onto
    1972             :   // the expression stack when one side is a special-case literal.
    1973        3816 :   Expression* sub_expr = nullptr;
    1974             :   Literal* literal;
    1975        3816 :   if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
    1976             :     return VisitLiteralCompareTypeof(expr, sub_expr,
    1977           0 :                                      Handle<String>::cast(literal->value()));
    1978             :   }
    1979        3816 :   if (expr->IsLiteralCompareUndefined(&sub_expr)) {
    1980             :     return VisitLiteralCompareNil(expr, sub_expr,
    1981           0 :                                   jsgraph()->UndefinedConstant());
    1982             :   }
    1983        3816 :   if (expr->IsLiteralCompareNull(&sub_expr)) {
    1984           0 :     return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant());
    1985             :   }
    1986             : 
    1987             :   CompareOperationHint hint = CompareOperationHint::kAny;
    1988             :   const Operator* op;
    1989        3816 :   switch (expr->op()) {
    1990             :     case Token::EQ:
    1991        2078 :       op = javascript()->Equal(hint);
    1992        2078 :       break;
    1993             :     case Token::EQ_STRICT:
    1994           2 :       op = javascript()->StrictEqual(hint);
    1995           2 :       break;
    1996             :     case Token::LT:
    1997         829 :       op = javascript()->LessThan(hint);
    1998         829 :       break;
    1999             :     case Token::GT:
    2000         598 :       op = javascript()->GreaterThan(hint);
    2001         598 :       break;
    2002             :     case Token::LTE:
    2003         126 :       op = javascript()->LessThanOrEqual(hint);
    2004         126 :       break;
    2005             :     case Token::GTE:
    2006         179 :       op = javascript()->GreaterThanOrEqual(hint);
    2007         179 :       break;
    2008             :     case Token::INSTANCEOF:
    2009           2 :       op = javascript()->InstanceOf();
    2010           2 :       break;
    2011             :     case Token::IN:
    2012           2 :       op = javascript()->HasProperty();
    2013           2 :       break;
    2014             :     default:
    2015             :       op = nullptr;
    2016           0 :       UNREACHABLE();
    2017             :   }
    2018        3816 :   VisitForValue(expr->left());
    2019        3816 :   VisitForValue(expr->right());
    2020             :   Node* right = environment()->Pop();
    2021             :   Node* left = environment()->Pop();
    2022             :   Node* value = NewNode(op, left, right);
    2023        3816 :   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
    2024        3816 :   ast_context()->ProduceValue(expr, value);
    2025             : }
    2026             : 
    2027             : 
    2028           0 : void AstGraphBuilder::VisitSpread(Spread* expr) {
    2029             :   // Handled entirely by the parser itself.
    2030           0 :   UNREACHABLE();
    2031             : }
    2032             : 
    2033             : 
    2034           0 : void AstGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
    2035             :   // Handled entirely by the parser itself.
    2036           0 :   UNREACHABLE();
    2037             : }
    2038             : 
    2039           0 : void AstGraphBuilder::VisitGetIterator(GetIterator* expr) {
    2040             :   // GetIterator is supported only by going through Ignition first.
    2041           0 :   UNREACHABLE();
    2042             : }
    2043             : 
    2044           0 : void AstGraphBuilder::VisitImportCallExpression(ImportCallExpression* expr) {
    2045             :   // ImportCallExpression is supported only by going through Ignition first.
    2046           0 :   UNREACHABLE();
    2047             : }
    2048             : 
    2049          80 : void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
    2050          40 :   Node* value = GetFunctionClosure();
    2051          40 :   ast_context()->ProduceValue(expr, value);
    2052          40 : }
    2053             : 
    2054             : 
    2055           0 : void AstGraphBuilder::VisitSuperPropertyReference(
    2056             :     SuperPropertyReference* expr) {
    2057           0 :   UNREACHABLE();
    2058             : }
    2059             : 
    2060             : 
    2061           0 : void AstGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
    2062             :   // Handled by VisitCall
    2063           0 :   UNREACHABLE();
    2064             : }
    2065             : 
    2066             : 
    2067           0 : void AstGraphBuilder::VisitCaseClause(CaseClause* expr) {
    2068             :   // Handled entirely in VisitSwitch.
    2069           0 :   UNREACHABLE();
    2070             : }
    2071             : 
    2072        2513 : void AstGraphBuilder::VisitDeclarations(Declaration::List* declarations) {
    2073             :   DCHECK(globals()->empty());
    2074             :   AstVisitor<AstGraphBuilder>::VisitDeclarations(declarations);
    2075        5026 :   if (globals()->empty()) return;
    2076             :   int array_index = 0;
    2077             :   Handle<FeedbackVector> feedback_vector(info()->closure()->feedback_vector());
    2078             :   Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
    2079           0 :       static_cast<int>(globals()->size()), TENURED);
    2080           0 :   for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
    2081           0 :   int encoded_flags = info()->GetDeclareGlobalsFlags();
    2082           0 :   Node* flags = jsgraph()->Constant(encoded_flags);
    2083           0 :   Node* decls = jsgraph()->Constant(data);
    2084           0 :   Node* vector = jsgraph()->Constant(feedback_vector);
    2085           0 :   const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals);
    2086             :   Node* call = NewNode(op, decls, flags, vector);
    2087           0 :   PrepareFrameState(call, BailoutId::Declarations());
    2088             :   globals()->clear();
    2089             : }
    2090             : 
    2091             : 
    2092           0 : void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
    2093         106 :   if (stmt == nullptr) return;
    2094          94 :   Visit(stmt);
    2095             : }
    2096             : 
    2097             : 
    2098        1668 : void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
    2099             :                                          LoopBuilder* loop,
    2100         834 :                                          BailoutId stack_check_id) {
    2101             :   ControlScopeForIteration scope(this, stmt, loop);
    2102         834 :   Node* node = NewNode(javascript()->StackCheck());
    2103         834 :   PrepareFrameState(node, stack_check_id);
    2104         834 :   Visit(stmt->body());
    2105         834 : }
    2106             : 
    2107             : 
    2108          92 : void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
    2109             :   Node* value;
    2110          18 :   if (expr->expression()->IsVariableProxy()) {
    2111             :     // Delete of an unqualified identifier is disallowed in strict mode but
    2112             :     // "delete this" is allowed.
    2113          28 :     Variable* variable = expr->expression()->AsVariableProxy()->var();
    2114             :     DCHECK(is_sloppy(language_mode()) || variable->is_this());
    2115             :     value = BuildVariableDelete(variable, expr->id(),
    2116          14 :                                 ast_context()->GetStateCombine());
    2117           4 :   } else if (expr->expression()->IsProperty()) {
    2118          12 :     Property* property = expr->expression()->AsProperty();
    2119           4 :     VisitForValue(property->obj());
    2120           4 :     VisitForValue(property->key());
    2121             :     Node* key = environment()->Pop();
    2122             :     Node* object = environment()->Pop();
    2123           8 :     Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode()));
    2124           4 :     value = NewNode(javascript()->DeleteProperty(), object, key, mode);
    2125           4 :     PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
    2126             :   } else {
    2127           0 :     VisitForEffect(expr->expression());
    2128           0 :     value = jsgraph()->TrueConstant();
    2129             :   }
    2130          18 :   ast_context()->ProduceValue(expr, value);
    2131          18 : }
    2132             : 
    2133             : 
    2134           0 : void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
    2135           0 :   VisitForEffect(expr->expression());
    2136           0 :   Node* value = jsgraph()->UndefinedConstant();
    2137           0 :   ast_context()->ProduceValue(expr, value);
    2138           0 : }
    2139             : 
    2140           0 : void AstGraphBuilder::VisitTypeofExpression(Expression* expr) {
    2141           0 :   if (expr->IsVariableProxy()) {
    2142             :     // Typeof does not throw a reference error on global variables, hence we
    2143             :     // perform a non-contextual load in case the operand is a variable proxy.
    2144           0 :     VariableProxy* proxy = expr->AsVariableProxy();
    2145           0 :     VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
    2146           0 :     PrepareEagerCheckpoint(BeforeId(proxy));
    2147             :     Node* load =
    2148             :         BuildVariableLoad(proxy->var(), expr->id(), pair,
    2149           0 :                           OutputFrameStateCombine::Push(), INSIDE_TYPEOF);
    2150             :     environment()->Push(load);
    2151             :   } else {
    2152           0 :     VisitForValue(expr);
    2153             :   }
    2154           0 : }
    2155             : 
    2156           0 : void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
    2157           0 :   VisitTypeofExpression(expr->expression());
    2158           0 :   Node* value = NewNode(javascript()->TypeOf(), environment()->Pop());
    2159           0 :   ast_context()->ProduceValue(expr, value);
    2160           0 : }
    2161             : 
    2162             : 
    2163        6536 : void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
    2164         947 :   VisitForTest(expr->expression());
    2165             :   Node* input = environment()->Pop();
    2166             :   Node* value = NewNode(common()->Select(MachineRepresentation::kTagged), input,
    2167        2841 :                         jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
    2168             :   // Skip plugging AST evaluation contexts of the test kind. This is to stay in
    2169             :   // sync with full codegen which doesn't prepare the proper bailout point (see
    2170             :   // the implementation of FullCodeGenerator::VisitForControl).
    2171        1894 :   if (ast_context()->IsTest()) return environment()->Push(value);
    2172          93 :   ast_context()->ProduceValue(expr, value);
    2173             : }
    2174             : 
    2175             : 
    2176         630 : void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
    2177         210 :   VisitForEffect(expr->left());
    2178         210 :   Visit(expr->right());
    2179             :   // Skip plugging AST evaluation contexts of the test kind. This is to stay in
    2180             :   // sync with full codegen which doesn't prepare the proper bailout point (see
    2181             :   // the implementation of FullCodeGenerator::VisitForControl).
    2182         420 :   if (ast_context()->IsTest()) return;
    2183             :   ast_context()->ReplaceValue(expr);
    2184             : }
    2185             : 
    2186             : 
    2187         209 : void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
    2188          23 :   bool is_logical_and = expr->op() == Token::AND;
    2189             :   IfBuilder compare_if(this);
    2190             :   // Only use an AST evaluation context of the value kind when this expression
    2191             :   // is evaluated as value as well. Otherwise stick to a test context which is
    2192             :   // in sync with full codegen (see FullCodeGenerator::VisitLogicalExpression).
    2193             :   Node* condition = nullptr;
    2194          23 :   if (ast_context()->IsValue()) {
    2195          19 :     VisitForValue(expr->left());
    2196             :     Node* left = environment()->Top();
    2197          19 :     condition = BuildToBoolean(left, expr->left()->test_id());
    2198             :   } else {
    2199           4 :     VisitForTest(expr->left());
    2200             :     condition = environment()->Top();
    2201             :   }
    2202          23 :   compare_if.If(condition);
    2203          23 :   compare_if.Then();
    2204          23 :   if (is_logical_and) {
    2205             :     environment()->Pop();
    2206           4 :     Visit(expr->right());
    2207          19 :   } else if (ast_context()->IsEffect()) {
    2208             :     environment()->Pop();
    2209          19 :   } else if (ast_context()->IsTest()) {
    2210           4 :     environment()->Poke(0, jsgraph()->TrueConstant());
    2211             :   }
    2212          23 :   compare_if.Else();
    2213          23 :   if (!is_logical_and) {
    2214             :     environment()->Pop();
    2215          19 :     Visit(expr->right());
    2216           4 :   } else if (ast_context()->IsEffect()) {
    2217             :     environment()->Pop();
    2218           2 :   } else if (ast_context()->IsTest()) {
    2219           0 :     environment()->Poke(0, jsgraph()->FalseConstant());
    2220             :   }
    2221          23 :   compare_if.End();
    2222             :   // Skip plugging AST evaluation contexts of the test kind. This is to stay in
    2223             :   // sync with full codegen which doesn't prepare the proper bailout point (see
    2224             :   // the implementation of FullCodeGenerator::VisitForControl).
    2225          46 :   if (ast_context()->IsTest()) return;
    2226             :   ast_context()->ReplaceValue(expr);
    2227             : }
    2228             : 
    2229             : 
    2230           0 : LanguageMode AstGraphBuilder::language_mode() const {
    2231           0 :   return current_scope()->language_mode();
    2232             : }
    2233             : 
    2234       76134 : VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(FeedbackSlot slot) const {
    2235       76134 :   return VectorSlotPair(handle(info()->closure()->feedback_vector()), slot);
    2236             : }
    2237             : 
    2238             : 
    2239           0 : void AstGraphBuilder::VisitRewritableExpression(RewritableExpression* node) {
    2240           0 :   Visit(node->expression());
    2241           0 : }
    2242             : 
    2243        3004 : float AstGraphBuilder::ComputeCallFrequency(FeedbackSlot slot) const {
    2244        1502 :   if (slot.IsInvalid()) return 0.0f;
    2245             :   Handle<FeedbackVector> feedback_vector(info()->closure()->feedback_vector(),
    2246             :                                          isolate());
    2247             :   CallICNexus nexus(feedback_vector, slot);
    2248        1502 :   return nexus.ComputeCallFrequency() * invocation_frequency_;
    2249             : }
    2250             : 
    2251        9985 : Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
    2252             :   DCHECK(environment()->stack_height() >= arity);
    2253        3094 :   Node** all = info()->zone()->NewArray<Node*>(arity);
    2254        8438 :   for (int i = arity - 1; i >= 0; --i) {
    2255       13782 :     all[i] = environment()->Pop();
    2256             :   }
    2257             :   Node* value = NewNode(op, arity, all);
    2258        1547 :   return value;
    2259             : }
    2260             : 
    2261             : 
    2262          60 : Node* AstGraphBuilder::BuildLocalActivationContext(Node* context) {
    2263          96 :   DeclarationScope* scope = info()->scope();
    2264             : 
    2265             :   // Allocate a new local context.
    2266          48 :   Node* local_context = scope->is_script_scope()
    2267             :                             ? BuildLocalScriptContext(scope)
    2268          48 :                             : BuildLocalFunctionContext(scope);
    2269             : 
    2270          96 :   if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
    2271           0 :     Node* receiver = environment()->RawParameterLookup(0);
    2272             :     // Context variable (at bottom of the context chain).
    2273           0 :     Variable* variable = scope->receiver();
    2274             :     DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
    2275           0 :     const Operator* op = javascript()->StoreContext(0, variable->index());
    2276             :     Node* node = NewNode(op, receiver);
    2277           0 :     NodeProperties::ReplaceContextInput(node, local_context);
    2278             :   }
    2279             : 
    2280             :   // Copy parameters into context if necessary.
    2281             :   int num_parameters = scope->num_parameters();
    2282         142 :   for (int i = 0; i < num_parameters; i++) {
    2283           6 :     Variable* variable = scope->parameter(i);
    2284          94 :     if (!variable->IsContextSlot()) continue;
    2285          12 :     Node* parameter = environment()->RawParameterLookup(i + 1);
    2286             :     // Context variable (at bottom of the context chain).
    2287             :     DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
    2288          12 :     const Operator* op = javascript()->StoreContext(0, variable->index());
    2289             :     Node* node = NewNode(op, parameter);
    2290           6 :     NodeProperties::ReplaceContextInput(node, local_context);
    2291             :   }
    2292             : 
    2293          48 :   return local_context;
    2294             : }
    2295             : 
    2296             : 
    2297         144 : Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) {
    2298             :   DCHECK(scope->is_function_scope() || scope->is_eval_scope());
    2299             : 
    2300             :   // Allocate a new local context.
    2301          48 :   int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
    2302             :   const Operator* op =
    2303          96 :       javascript()->CreateFunctionContext(slot_count, scope->scope_type());
    2304          48 :   Node* local_context = NewNode(op, GetFunctionClosure());
    2305             : 
    2306          48 :   return local_context;
    2307             : }
    2308             : 
    2309             : 
    2310           0 : Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) {
    2311             :   DCHECK(scope->is_script_scope());
    2312             : 
    2313             :   // Allocate a new local context.
    2314           0 :   Handle<ScopeInfo> scope_info = scope->scope_info();
    2315           0 :   const Operator* op = javascript()->CreateScriptContext(scope_info);
    2316           0 :   Node* local_context = NewNode(op, GetFunctionClosure());
    2317             :   PrepareFrameState(local_context, BailoutId::ScriptContext(),
    2318           0 :                     OutputFrameStateCombine::Push());
    2319             : 
    2320           0 :   return local_context;
    2321             : }
    2322             : 
    2323             : 
    2324           0 : Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) {
    2325             :   DCHECK(scope->is_block_scope());
    2326             : 
    2327             :   // Allocate a new local context.
    2328           0 :   Handle<ScopeInfo> scope_info = scope->scope_info();
    2329           0 :   const Operator* op = javascript()->CreateBlockContext(scope_info);
    2330           0 :   Node* local_context = NewNode(op, GetFunctionClosureForContext());
    2331             : 
    2332           0 :   return local_context;
    2333             : }
    2334             : 
    2335             : 
    2336        2513 : Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
    2337        2507 :   if (arguments == nullptr) return nullptr;
    2338             : 
    2339             :   // Allocate and initialize a new arguments object.
    2340             :   CreateArgumentsType type =
    2341           2 :       is_strict(language_mode()) || !info()->has_simple_parameters()
    2342             :           ? CreateArgumentsType::kUnmappedArguments
    2343           4 :           : CreateArgumentsType::kMappedArguments;
    2344           4 :   const Operator* op = javascript()->CreateArguments(type);
    2345           4 :   Node* object = NewNode(op, GetFunctionClosure());
    2346           4 :   PrepareFrameState(object, BailoutId::None());
    2347             : 
    2348             :   // Assign the object to the {arguments} variable. This should never lazy
    2349             :   // deopt, so it is fine to send invalid bailout id.
    2350             :   DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
    2351             :   BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair(),
    2352           4 :                           BailoutId::None());
    2353           4 :   return object;
    2354             : }
    2355             : 
    2356          50 : Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
    2357             :                                                Node* not_hole,
    2358         250 :                                                BailoutId bailout_id) {
    2359             :   IfBuilder hole_check(this);
    2360          50 :   Node* the_hole = jsgraph()->TheHoleConstant();
    2361             :   Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
    2362          50 :                         value, the_hole);
    2363          50 :   hole_check.If(check);
    2364          50 :   hole_check.Then();
    2365          50 :   Node* error = BuildThrowReferenceError(variable, bailout_id);
    2366             :   environment()->Push(error);
    2367          50 :   hole_check.Else();
    2368             :   environment()->Push(not_hole);
    2369          50 :   hole_check.End();
    2370          50 :   return environment()->Pop();
    2371             : }
    2372             : 
    2373             : 
    2374           0 : Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
    2375             :                                                Node* for_hole,
    2376           0 :                                                BailoutId bailout_id) {
    2377             :   IfBuilder hole_check(this);
    2378           0 :   Node* the_hole = jsgraph()->TheHoleConstant();
    2379             :   Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
    2380           0 :                         value, the_hole);
    2381           0 :   hole_check.If(check);
    2382           0 :   hole_check.Then();
    2383             :   environment()->Push(for_hole);
    2384           0 :   hole_check.Else();
    2385           0 :   Node* error = BuildThrowReferenceError(variable, bailout_id);
    2386             :   environment()->Push(error);
    2387           0 :   hole_check.End();
    2388           0 :   return environment()->Pop();
    2389             : }
    2390             : 
    2391      130294 : Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
    2392             :                                          BailoutId bailout_id,
    2393             :                                          const VectorSlotPair& feedback,
    2394             :                                          OutputFrameStateCombine combine,
    2395      105423 :                                          TypeofMode typeof_mode) {
    2396       46782 :   Node* the_hole = jsgraph()->TheHoleConstant();
    2397       46754 :   switch (variable->location()) {
    2398             :     case VariableLocation::UNALLOCATED: {
    2399             :       // Global var, const, or let variable.
    2400             :       Handle<Name> name = variable->name();
    2401          48 :       if (Node* node = TryLoadGlobalConstant(name)) return node;
    2402          48 :       Node* value = BuildGlobalLoad(name, feedback, typeof_mode);
    2403          48 :       PrepareFrameState(value, bailout_id, combine);
    2404          48 :       return value;
    2405             :     }
    2406             :     case VariableLocation::PARAMETER:
    2407             :     case VariableLocation::LOCAL: {
    2408             :       // Local var, const, or let variable.
    2409       34488 :       Node* value = environment()->Lookup(variable);
    2410       34460 :       if (variable->binding_needs_init()) {
    2411             :         // Perform check for uninitialized let/const variables.
    2412          28 :         if (value->op() == the_hole->op()) {
    2413           4 :           value = BuildThrowReferenceError(variable, bailout_id);
    2414          24 :         } else if (value->opcode() == IrOpcode::kPhi) {
    2415           6 :           value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
    2416             :         }
    2417             :       }
    2418       34460 :       return value;
    2419             :     }
    2420             :     case VariableLocation::CONTEXT: {
    2421             :       // Context variable (potentially up the context chain).
    2422       12246 :       int depth = current_scope()->ContextChainLength(variable->scope());
    2423             :       // TODO(mstarzinger): The {maybe_assigned} flag computed during variable
    2424             :       // resolution is highly inaccurate and cannot be trusted. We are only
    2425             :       // taking this information into account when asm.js compilation is used.
    2426       24209 :       bool immutable = variable->maybe_assigned() == kNotAssigned &&
    2427             :                        info()->is_function_context_specializing();
    2428             :       const Operator* op =
    2429       36738 :           javascript()->LoadContext(depth, variable->index(), immutable);
    2430             :       Node* value = NewNode(op);
    2431             :       // TODO(titzer): initialization checks are redundant for already
    2432             :       // initialized immutable context loads, but only specialization knows.
    2433             :       // Maybe specializer should be a parameter to the graph builder?
    2434       12246 :       if (variable->binding_needs_init()) {
    2435             :         // Perform check for uninitialized let/const variables.
    2436          32 :         value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
    2437             :       }
    2438       12246 :       return value;
    2439             :     }
    2440             :     case VariableLocation::LOOKUP:
    2441             :     case VariableLocation::MODULE:
    2442           0 :       UNREACHABLE();
    2443             :   }
    2444           0 :   UNREACHABLE();
    2445             :   return nullptr;
    2446             : }
    2447             : 
    2448             : 
    2449          28 : Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
    2450             :                                            BailoutId bailout_id,
    2451          42 :                                            OutputFrameStateCombine combine) {
    2452          14 :   switch (variable->location()) {
    2453             :     case VariableLocation::UNALLOCATED: {
    2454             :       // Global var, const, or let variable.
    2455             :       Node* global = BuildLoadGlobalObject();
    2456          14 :       Node* name = jsgraph()->Constant(variable->name());
    2457          28 :       Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode()));
    2458          14 :       const Operator* op = javascript()->DeleteProperty();
    2459             :       Node* result = NewNode(op, global, name, mode);
    2460          14 :       PrepareFrameState(result, bailout_id, combine);
    2461          14 :       return result;
    2462             :     }
    2463             :     case VariableLocation::PARAMETER:
    2464             :     case VariableLocation::LOCAL:
    2465             :     case VariableLocation::CONTEXT: {
    2466             :       // Local var, const, or let variable or context variable.
    2467           0 :       return jsgraph()->BooleanConstant(variable->is_this());
    2468             :     }
    2469             :     case VariableLocation::LOOKUP:
    2470             :     case VariableLocation::MODULE:
    2471           0 :       UNREACHABLE();
    2472             :   }
    2473           0 :   UNREACHABLE();
    2474             :   return nullptr;
    2475             : }
    2476             : 
    2477       17273 : Node* AstGraphBuilder::BuildVariableAssignment(
    2478       18491 :     Variable* variable, Node* value, Token::Value op,
    2479             :     const VectorSlotPair& feedback, BailoutId bailout_id,
    2480       34608 :     OutputFrameStateCombine combine) {
    2481       17329 :   Node* the_hole = jsgraph()->TheHoleConstant();
    2482             :   VariableMode mode = variable->mode();
    2483       17273 :   switch (variable->location()) {
    2484             :     case VariableLocation::UNALLOCATED: {
    2485             :       // Global var, const, or let variable.
    2486             :       Handle<Name> name = variable->name();
    2487          18 :       Node* store = BuildGlobalStore(name, value, feedback);
    2488          18 :       PrepareFrameState(store, bailout_id, combine);
    2489             :       return store;
    2490             :     }
    2491             :     case VariableLocation::PARAMETER:
    2492             :     case VariableLocation::LOCAL:
    2493             :       // Local var, const, or let variable.
    2494       16658 :       if (mode == LET && op == Token::INIT) {
    2495             :         // No initialization check needed because scoping guarantees it. Note
    2496             :         // that we still perform a lookup to keep the variable live, because
    2497             :         // baseline code might contain debug code that inspects the variable.
    2498          20 :         Node* current = environment()->Lookup(variable);
    2499          20 :         CHECK_NOT_NULL(current);
    2500       16644 :       } else if (mode == LET && op != Token::INIT &&
    2501             :                  variable->binding_needs_init()) {
    2502             :         // Perform an initialization check for let declared variables.
    2503           6 :         Node* current = environment()->Lookup(variable);
    2504           6 :         if (current->op() == the_hole->op()) {
    2505           2 :           return BuildThrowReferenceError(variable, bailout_id);
    2506           4 :         } else if (current->opcode() == IrOpcode::kPhi) {
    2507           2 :           BuildHoleCheckThenThrow(current, variable, value, bailout_id);
    2508             :         }
    2509       16632 :       } else if (mode == CONST && op == Token::INIT) {
    2510             :         // Perform an initialization check for const {this} variables.
    2511             :         // Note that the {this} variable is the only const variable being able
    2512             :         // to trigger bind operations outside the TDZ, via {super} calls.
    2513          50 :         Node* current = environment()->Lookup(variable);
    2514          90 :         if (current->op() != the_hole->op() && variable->is_this()) {
    2515           0 :           value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
    2516             :         }
    2517       16582 :       } else if (mode == CONST && op != Token::INIT &&
    2518             :                  variable->is_sloppy_function_name()) {
    2519             :         // Non-initializing assignment to sloppy function names is
    2520             :         // - exception in strict mode.
    2521             :         // - ignored in sloppy mode.
    2522             :         DCHECK(!variable->binding_needs_init());
    2523           0 :         if (variable->throw_on_const_assignment(language_mode())) {
    2524           0 :           return BuildThrowConstAssignError(bailout_id);
    2525             :         }
    2526             :         return value;
    2527       16582 :       } else if (mode == CONST && op != Token::INIT) {
    2528           0 :         if (variable->binding_needs_init()) {
    2529           0 :           Node* current = environment()->Lookup(variable);
    2530           0 :           if (current->op() == the_hole->op()) {
    2531           0 :             return BuildThrowReferenceError(variable, bailout_id);
    2532           0 :           } else if (current->opcode() == IrOpcode::kPhi) {
    2533           0 :             BuildHoleCheckThenThrow(current, variable, value, bailout_id);
    2534             :           }
    2535             :         }
    2536             :         // Assignment to const is exception in all modes.
    2537           0 :         return BuildThrowConstAssignError(bailout_id);
    2538             :       }
    2539       16656 :       environment()->Bind(variable, value);
    2540       16656 :       return value;
    2541             :     case VariableLocation::CONTEXT: {
    2542             :       // Context variable (potentially up the context chain).
    2543         597 :       int depth = current_scope()->ContextChainLength(variable->scope());
    2544         603 :       if (mode == LET && op != Token::INIT && variable->binding_needs_init()) {
    2545             :         // Perform an initialization check for let declared variables.
    2546             :         const Operator* op =
    2547          12 :             javascript()->LoadContext(depth, variable->index(), false);
    2548             :         Node* current = NewNode(op);
    2549           6 :         value = BuildHoleCheckThenThrow(current, variable, value, bailout_id);
    2550         591 :       } else if (mode == CONST && op == Token::INIT) {
    2551             :         // Perform an initialization check for const {this} variables.
    2552             :         // Note that the {this} variable is the only const variable being able
    2553             :         // to trigger bind operations outside the TDZ, via {super} calls.
    2554          10 :         if (variable->is_this()) {
    2555             :           const Operator* op =
    2556           0 :               javascript()->LoadContext(depth, variable->index(), false);
    2557             :           Node* current = NewNode(op);
    2558           0 :           value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
    2559             :         }
    2560         585 :       } else if (mode == CONST && op != Token::INIT &&
    2561             :                  variable->is_sloppy_function_name()) {
    2562             :         // Non-initializing assignment to sloppy function names is
    2563             :         // - exception in strict mode.
    2564             :         // - ignored in sloppy mode.
    2565             :         DCHECK(!variable->binding_needs_init());
    2566           0 :         if (variable->throw_on_const_assignment(language_mode())) {
    2567           0 :           return BuildThrowConstAssignError(bailout_id);
    2568             :         }
    2569             :         return value;
    2570         581 :       } else if (mode == CONST && op != Token::INIT) {
    2571           4 :         if (variable->binding_needs_init()) {
    2572             :           const Operator* op =
    2573           8 :               javascript()->LoadContext(depth, variable->index(), false);
    2574             :           Node* current = NewNode(op);
    2575           4 :           BuildHoleCheckThenThrow(current, variable, value, bailout_id);
    2576             :         }
    2577             :         // Assignment to const is exception in all modes.
    2578           4 :         return BuildThrowConstAssignError(bailout_id);
    2579             :       }
    2580        1186 :       const Operator* op = javascript()->StoreContext(depth, variable->index());
    2581         593 :       return NewNode(op, value);
    2582             :     }
    2583             :     case VariableLocation::LOOKUP:
    2584             :     case VariableLocation::MODULE:
    2585           0 :       UNREACHABLE();
    2586             :   }
    2587           0 :   UNREACHABLE();
    2588             :   return nullptr;
    2589             : }
    2590             : 
    2591             : 
    2592        6347 : Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
    2593        6347 :                                       const VectorSlotPair& feedback) {
    2594        6347 :   const Operator* op = javascript()->LoadProperty(feedback);
    2595             :   Node* node = NewNode(op, object, key);
    2596        6347 :   return node;
    2597             : }
    2598             : 
    2599             : 
    2600          26 : Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
    2601          26 :                                       const VectorSlotPair& feedback) {
    2602          26 :   const Operator* op = javascript()->LoadNamed(name, feedback);
    2603             :   Node* node = NewNode(op, object);
    2604          26 :   return node;
    2605             : }
    2606             : 
    2607             : 
    2608        4165 : Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
    2609        4165 :                                        const VectorSlotPair& feedback) {
    2610             :   DCHECK_EQ(feedback.vector()->GetLanguageMode(feedback.slot()),
    2611             :             language_mode());
    2612        4165 :   const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
    2613             :   Node* node = NewNode(op, object, key, value);
    2614        4165 :   return node;
    2615             : }
    2616             : 
    2617             : 
    2618          17 : Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
    2619             :                                        Node* value,
    2620          17 :                                        const VectorSlotPair& feedback) {
    2621             :   DCHECK_EQ(feedback.vector()->GetLanguageMode(feedback.slot()),
    2622             :             language_mode());
    2623             :   const Operator* op =
    2624          17 :       javascript()->StoreNamed(language_mode(), name, feedback);
    2625             :   Node* node = NewNode(op, object, value);
    2626          17 :   return node;
    2627             : }
    2628             : 
    2629           2 : Node* AstGraphBuilder::BuildNamedStoreOwn(Node* object, Handle<Name> name,
    2630             :                                           Node* value,
    2631           2 :                                           const VectorSlotPair& feedback) {
    2632             :   DCHECK_EQ(FeedbackSlotKind::kStoreOwnNamed,
    2633             :             feedback.vector()->GetKind(feedback.slot()));
    2634           2 :   const Operator* op = javascript()->StoreNamedOwn(name, feedback);
    2635             :   Node* node = NewNode(op, object, value);
    2636           2 :   return node;
    2637             : }
    2638             : 
    2639          48 : Node* AstGraphBuilder::BuildGlobalLoad(Handle<Name> name,
    2640             :                                        const VectorSlotPair& feedback,
    2641          48 :                                        TypeofMode typeof_mode) {
    2642             :   DCHECK_EQ(feedback.vector()->GetTypeofMode(feedback.slot()), typeof_mode);
    2643          48 :   const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
    2644             :   Node* node = NewNode(op);
    2645          48 :   return node;
    2646             : }
    2647             : 
    2648             : 
    2649          18 : Node* AstGraphBuilder::BuildGlobalStore(Handle<Name> name, Node* value,
    2650          18 :                                         const VectorSlotPair& feedback) {
    2651             :   const Operator* op =
    2652          18 :       javascript()->StoreGlobal(language_mode(), name, feedback);
    2653             :   Node* node = NewNode(op, value);
    2654          18 :   return node;
    2655             : }
    2656             : 
    2657           0 : Node* AstGraphBuilder::BuildLoadGlobalObject() {
    2658          14 :   return BuildLoadNativeContextField(Context::EXTENSION_INDEX);
    2659             : }
    2660             : 
    2661             : 
    2662          28 : Node* AstGraphBuilder::BuildLoadNativeContextField(int index) {
    2663             :   const Operator* op =
    2664          14 :       javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
    2665             :   Node* native_context = NewNode(op);
    2666          28 :   Node* result = NewNode(javascript()->LoadContext(0, index, true));
    2667          14 :   NodeProperties::ReplaceContextInput(result, native_context);
    2668          14 :   return result;
    2669             : }
    2670             : 
    2671             : 
    2672        5050 : Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) {
    2673        4658 :   if (Node* node = TryFastToBoolean(input)) return node;
    2674             :   ToBooleanHints hints = ToBooleanHint::kAny;
    2675         784 :   return NewNode(javascript()->ToBoolean(hints), input);
    2676             : }
    2677             : 
    2678             : 
    2679           0 : Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
    2680           0 :   Node* object = NewNode(javascript()->ToObject(), input);
    2681           0 :   PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push());
    2682           0 :   return object;
    2683             : }
    2684             : 
    2685           6 : Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
    2686           6 :                                           LiteralProperty* property,
    2687           0 :                                           int slot_number) {
    2688             :   Expression* expr = property->value();
    2689           6 :   if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
    2690             :   Handle<Name> name = isolate()->factory()->home_object_symbol();
    2691             :   VectorSlotPair feedback =
    2692           0 :       CreateVectorSlotPair(property->GetSlot(slot_number));
    2693           0 :   Node* store = BuildNamedStore(value, name, home_object, feedback);
    2694             :   PrepareFrameState(store, BailoutId::None(),
    2695           0 :                     OutputFrameStateCombine::Ignore());
    2696           0 :   return store;
    2697             : }
    2698             : 
    2699             : 
    2700          32 : Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) {
    2701          16 :   const Operator* op = javascript()->CallRuntime(Runtime::kThrow);
    2702             :   Node* call = NewNode(op, exception);
    2703          16 :   PrepareFrameState(call, bailout_id);
    2704          16 :   Node* control = NewNode(common()->Throw());
    2705          16 :   UpdateControlDependencyToLeaveFunction(control);
    2706          16 :   return call;
    2707             : }
    2708             : 
    2709             : 
    2710          56 : Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
    2711         168 :                                                 BailoutId bailout_id) {
    2712          56 :   Node* variable_name = jsgraph()->Constant(variable->name());
    2713          56 :   const Operator* op = javascript()->CallRuntime(Runtime::kThrowReferenceError);
    2714             :   Node* call = NewNode(op, variable_name);
    2715          56 :   PrepareFrameState(call, bailout_id);
    2716          56 :   Node* control = NewNode(common()->Throw());
    2717          56 :   UpdateControlDependencyToLeaveFunction(control);
    2718          56 :   return call;
    2719             : }
    2720             : 
    2721             : 
    2722           8 : Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
    2723             :   const Operator* op =
    2724           4 :       javascript()->CallRuntime(Runtime::kThrowConstAssignError);
    2725             :   Node* call = NewNode(op);
    2726           4 :   PrepareFrameState(call, bailout_id);
    2727           4 :   Node* control = NewNode(common()->Throw());
    2728           4 :   UpdateControlDependencyToLeaveFunction(control);
    2729           4 :   return call;
    2730             : }
    2731             : 
    2732             : 
    2733       15489 : Node* AstGraphBuilder::BuildReturn(Node* return_value) {
    2734             :   // Emit tracing call if requested to do so.
    2735        5163 :   if (FLAG_trace) {
    2736             :     return_value =
    2737           0 :         NewNode(javascript()->CallRuntime(Runtime::kTraceExit), return_value);
    2738             :   }
    2739        5163 :   Node* pop_node = jsgraph()->ZeroConstant();
    2740        5163 :   Node* control = NewNode(common()->Return(), pop_node, return_value);
    2741        5163 :   UpdateControlDependencyToLeaveFunction(control);
    2742        5163 :   return control;
    2743             : }
    2744             : 
    2745             : 
    2746           0 : Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
    2747           0 :   NewNode(javascript()->CallRuntime(Runtime::kReThrow), exception_value);
    2748           0 :   Node* control = NewNode(common()->Throw());
    2749           0 :   UpdateControlDependencyToLeaveFunction(control);
    2750           0 :   return control;
    2751             : }
    2752             : 
    2753             : 
    2754       47600 : Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op,
    2755       47600 :                                      TypeFeedbackId feedback_id) {
    2756             :   const Operator* js_op;
    2757             :   BinaryOperationHint hint = BinaryOperationHint::kAny;
    2758       47600 :   switch (op) {
    2759             :     case Token::BIT_OR:
    2760       16873 :       js_op = javascript()->BitwiseOr();
    2761       16873 :       break;
    2762             :     case Token::BIT_AND:
    2763        1203 :       js_op = javascript()->BitwiseAnd();
    2764        1203 :       break;
    2765             :     case Token::BIT_XOR:
    2766          65 :       js_op = javascript()->BitwiseXor();
    2767          65 :       break;
    2768             :     case Token::SHL:
    2769        1231 :       js_op = javascript()->ShiftLeft();
    2770        1231 :       break;
    2771             :     case Token::SAR:
    2772        9048 :       js_op = javascript()->ShiftRight();
    2773        9048 :       break;
    2774             :     case Token::SHR:
    2775        1757 :       js_op = javascript()->ShiftRightLogical();
    2776        1757 :       break;
    2777             :     case Token::ADD:
    2778       10713 :       js_op = javascript()->Add(hint);
    2779       10713 :       break;
    2780             :     case Token::SUB:
    2781        1109 :       js_op = javascript()->Subtract();
    2782        1109 :       break;
    2783             :     case Token::MUL:
    2784        4425 :       js_op = javascript()->Multiply();
    2785        4425 :       break;
    2786             :     case Token::DIV:
    2787         564 :       js_op = javascript()->Divide();
    2788         564 :       break;
    2789             :     case Token::MOD:
    2790         612 :       js_op = javascript()->Modulus();
    2791         612 :       break;
    2792             :     default:
    2793           0 :       UNREACHABLE();
    2794             :       js_op = nullptr;
    2795             :   }
    2796       47600 :   return NewNode(js_op, left, right);
    2797             : }
    2798             : 
    2799             : 
    2800          48 : Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) {
    2801             :   // Optimize global constants like "undefined", "Infinity", and "NaN".
    2802          48 :   Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name);
    2803          48 :   if (!constant_value.is_null()) return jsgraph()->Constant(constant_value);
    2804             :   return nullptr;
    2805             : }
    2806             : 
    2807        4658 : Node* AstGraphBuilder::TryFastToBoolean(Node* input) {
    2808        4658 :   switch (input->opcode()) {
    2809             :     case IrOpcode::kNumberConstant: {
    2810             :       NumberMatcher m(input);
    2811         968 :       return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN());
    2812             :     }
    2813             :     case IrOpcode::kHeapConstant: {
    2814             :       Handle<HeapObject> object = HeapObjectMatcher(input).Value();
    2815          37 :       return jsgraph_->BooleanConstant(object->BooleanValue());
    2816             :     }
    2817             :     case IrOpcode::kJSEqual:
    2818             :     case IrOpcode::kJSStrictEqual:
    2819             :     case IrOpcode::kJSLessThan:
    2820             :     case IrOpcode::kJSLessThanOrEqual:
    2821             :     case IrOpcode::kJSGreaterThan:
    2822             :     case IrOpcode::kJSGreaterThanOrEqual:
    2823             :     case IrOpcode::kJSToBoolean:
    2824             :     case IrOpcode::kJSDeleteProperty:
    2825             :     case IrOpcode::kJSHasProperty:
    2826             :     case IrOpcode::kJSInstanceOf:
    2827        3557 :       return input;
    2828             :     default:
    2829             :       break;
    2830             :   }
    2831             :   return nullptr;
    2832             : }
    2833             : 
    2834             : 
    2835         902 : bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
    2836         834 :   if (info()->osr_ast_id() == stmt->OsrEntryId()) {
    2837             :     DCHECK_EQ(-1, info()->osr_expr_stack_height());
    2838             :     info()->set_osr_expr_stack_height(environment()->stack_height());
    2839           0 :     return true;
    2840             :   }
    2841             :   return false;
    2842             : }
    2843             : 
    2844             : 
    2845       67096 : void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
    2846       67086 :                                         OutputFrameStateCombine combine) {
    2847       67096 :   if (OperatorProperties::HasFrameStateInput(node->op())) {
    2848             :     DCHECK(ast_id.IsNone() || info()->shared_info()->VerifyBailoutId(ast_id));
    2849             :     DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
    2850             :     DCHECK_EQ(IrOpcode::kDead,
    2851             :               NodeProperties::GetFrameStateInput(node)->opcode());
    2852       67086 :     bool has_exception = NodeProperties::IsExceptionalCall(node);
    2853      134172 :     Node* state = environment()->Checkpoint(ast_id, combine, has_exception);
    2854       67086 :     NodeProperties::ReplaceFrameStateInput(node, state);
    2855             :   }
    2856       67096 : }
    2857             : 
    2858      393090 : void AstGraphBuilder::PrepareEagerCheckpoint(BailoutId ast_id) {
    2859      459920 :   if (environment()->GetEffectDependency()->opcode() == IrOpcode::kCheckpoint) {
    2860             :     // We skip preparing a checkpoint if there already is one the current effect
    2861             :     // dependency. This is just an optimization and not need for correctness.
    2862      229960 :     return;
    2863             :   }
    2864       86508 :   if (ast_id != BailoutId::None()) {
    2865             :     DCHECK(info()->shared_info()->VerifyBailoutId(ast_id));
    2866       81565 :     Node* node = NewNode(common()->Checkpoint());
    2867             :     DCHECK_EQ(IrOpcode::kDead,
    2868             :               NodeProperties::GetFrameStateInput(node)->opcode());
    2869       81565 :     Node* state = environment()->Checkpoint(ast_id);
    2870       81565 :     NodeProperties::ReplaceFrameStateInput(node, state);
    2871             :   }
    2872             : }
    2873             : 
    2874           0 : BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
    2875             :     IterationStatement* stmt) {
    2876         834 :   if (loop_assignment_analysis_ == nullptr) return nullptr;
    2877         834 :   return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt);
    2878             : }
    2879             : 
    2880             : 
    2881      207199 : Node** AstGraphBuilder::EnsureInputBufferSize(int size) {
    2882      204690 :   if (size > input_buffer_size_) {
    2883        2509 :     size = size + kInputBufferSizeIncrement + input_buffer_size_;
    2884        5018 :     input_buffer_ = local_zone()->NewArray<Node*>(size);
    2885        2509 :     input_buffer_size_ = size;
    2886             :   }
    2887      204690 :   return input_buffer_;
    2888             : }
    2889             : 
    2890             : 
    2891      574389 : Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
    2892      527651 :                                 Node** value_inputs, bool incomplete) {
    2893             :   DCHECK_EQ(op->ValueInputCount(), value_input_count);
    2894             : 
    2895      191463 :   bool has_context = OperatorProperties::HasContextInput(op);
    2896      191463 :   bool has_frame_state = OperatorProperties::HasFrameStateInput(op);
    2897      191463 :   bool has_control = op->ControlInputCount() == 1;
    2898      191463 :   bool has_effect = op->EffectInputCount() == 1;
    2899             : 
    2900             :   DCHECK(op->ControlInputCount() < 2);
    2901             :   DCHECK(op->EffectInputCount() < 2);
    2902             : 
    2903      367908 :   Node* result = nullptr;
    2904      191463 :   if (!has_context && !has_frame_state && !has_control && !has_effect) {
    2905        7852 :     result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
    2906             :   } else {
    2907             :     int input_count_with_deps = value_input_count;
    2908      187537 :     if (has_context) ++input_count_with_deps;
    2909      187537 :     if (has_frame_state) ++input_count_with_deps;
    2910      187537 :     if (has_control) ++input_count_with_deps;
    2911      187537 :     if (has_effect) ++input_count_with_deps;
    2912      187537 :     Node** buffer = EnsureInputBufferSize(input_count_with_deps);
    2913      187537 :     memcpy(buffer, value_inputs, kPointerSize * value_input_count);
    2914      187537 :     Node** current_input = buffer + value_input_count;
    2915      187537 :     if (has_context) {
    2916      161874 :       *current_input++ = current_context();
    2917             :     }
    2918      187537 :     if (has_frame_state) {
    2919             :       // The frame state will be inserted later. Here we misuse
    2920             :       // the {Dead} node as a sentinel to be later overwritten
    2921             :       // with the real frame state.
    2922      297302 :       *current_input++ = jsgraph()->Dead();
    2923             :     }
    2924      187537 :     if (has_effect) {
    2925      342274 :       *current_input++ = environment_->GetEffectDependency();
    2926             :     }
    2927      187537 :     if (has_control) {
    2928      349714 :       *current_input++ = environment_->GetControlDependency();
    2929             :     }
    2930      375074 :     result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
    2931      187537 :     if (!environment()->IsMarkedAsUnreachable()) {
    2932             :       // Update the current control dependency for control-producing nodes.
    2933      367908 :       if (result->op()->ControlOutputCount() > 0) {
    2934             :         environment_->UpdateControlDependency(result);
    2935             :       }
    2936             :       // Update the current effect dependency for effect-producing nodes.
    2937      367908 :       if (result->op()->EffectOutputCount() > 0) {
    2938      162100 :         environment_->UpdateEffectDependency(result);
    2939             :       }
    2940             :     }
    2941             :   }
    2942             : 
    2943      191463 :   return result;
    2944             : }
    2945             : 
    2946             : 
    2947        5239 : void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
    2948       10478 :   if (environment()->IsMarkedAsUnreachable()) return;
    2949             :   environment()->MarkAsUnreachable();
    2950        3008 :   exit_controls_.push_back(exit);
    2951             : }
    2952             : 
    2953             : 
    2954       23622 : void AstGraphBuilder::Environment::Merge(Environment* other) {
    2955             :   DCHECK(values_.size() == other->values_.size());
    2956             :   DCHECK(contexts_.size() == other->contexts_.size());
    2957             : 
    2958             :   // Nothing to do if the other environment is dead.
    2959        8856 :   if (other->IsMarkedAsUnreachable()) return;
    2960             : 
    2961             :   // Resurrect a dead environment by copying the contents of the other one and
    2962             :   // placing a singleton merge as the new control dependency.
    2963        7258 :   if (this->IsMarkedAsUnreachable()) {
    2964             :     Node* other_control = other->control_dependency_;
    2965        2872 :     Node* inputs[] = {other_control};
    2966             :     control_dependency_ =
    2967        5744 :         graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
    2968        2872 :     effect_dependency_ = other->effect_dependency_;
    2969             :     values_ = other->values_;
    2970             :     contexts_ = other->contexts_;
    2971        2872 :     if (IsLivenessAnalysisEnabled()) {
    2972             :       liveness_block_ =
    2973         106 :           builder_->liveness_analyzer()->NewBlock(other->liveness_block());
    2974             :     }
    2975             :     return;
    2976             :   }
    2977             : 
    2978             :   // Record the merge for the local variable liveness calculation.
    2979             :   // For loops, we are connecting a back edge into the existing block;
    2980             :   // for merges, we create a new merged block.
    2981        4386 :   if (IsLivenessAnalysisEnabled()) {
    2982          80 :     if (GetControlDependency()->opcode() != IrOpcode::kLoop) {
    2983             :       liveness_block_ =
    2984          64 :           builder_->liveness_analyzer()->NewBlock(liveness_block());
    2985             :     }
    2986             :     liveness_block()->AddPredecessor(other->liveness_block());
    2987             :   }
    2988             : 
    2989             :   // Create a merge of the control dependencies of both environments and update
    2990             :   // the current environment's control dependency accordingly.
    2991             :   Node* control = builder_->MergeControl(this->GetControlDependency(),
    2992        4386 :                                          other->GetControlDependency());
    2993             :   UpdateControlDependency(control);
    2994             : 
    2995             :   // Create a merge of the effect dependencies of both environments and update
    2996             :   // the current environment's effect dependency accordingly.
    2997             :   Node* effect = builder_->MergeEffect(this->GetEffectDependency(),
    2998        4386 :                                        other->GetEffectDependency(), control);
    2999             :   UpdateEffectDependency(effect);
    3000             : 
    3001             :   // Introduce Phi nodes for values that have differing input at merge points,
    3002             :   // potentially extending an existing Phi node if possible.
    3003      281096 :   for (int i = 0; i < static_cast<int>(values_.size()); ++i) {
    3004      549034 :     values_[i] = builder_->MergeValue(values_[i], other->values_[i], control);
    3005             :   }
    3006       13190 :   for (int i = 0; i < static_cast<int>(contexts_.size()); ++i) {
    3007       13190 :     contexts_[i] =
    3008        8804 :         builder_->MergeValue(contexts_[i], other->contexts_[i], control);
    3009             :   }
    3010             : }
    3011             : 
    3012         136 : void AstGraphBuilder::Environment::PrepareForOsrEntry() {
    3013         136 :   int size = static_cast<int>(values()->size());
    3014        1320 :   Graph* graph = builder_->graph();
    3015             : 
    3016             :   // Set the control and effect to the OSR loop entry.
    3017             :   Node* osr_loop_entry = graph->NewNode(builder_->common()->OsrLoopEntry(),
    3018          68 :                                         graph->start(), graph->start());
    3019             :   UpdateControlDependency(osr_loop_entry);
    3020             :   UpdateEffectDependency(osr_loop_entry);
    3021             : 
    3022             :   // Set OSR values.
    3023         912 :   for (int i = 0; i < size; ++i) {
    3024         844 :     values()->at(i) =
    3025        2532 :         graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry);
    3026             :   }
    3027             : 
    3028             :   // Set the innermost context.
    3029             :   const Operator* op_inner =
    3030         136 :       builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex);
    3031          68 :   contexts()->back() = graph->NewNode(op_inner, osr_loop_entry);
    3032             : 
    3033             :   // Create a checkpoint.
    3034         136 :   Node* frame_state = Checkpoint(builder_->info()->osr_ast_id());
    3035             :   Node* checkpoint = graph->NewNode(common()->Checkpoint(), frame_state,
    3036          68 :                                     osr_loop_entry, osr_loop_entry);
    3037             :   UpdateEffectDependency(checkpoint);
    3038             : 
    3039             :   // Create the OSR guard nodes.
    3040             :   const Operator* guard_op =
    3041          68 :       builder_->info()->is_deoptimization_enabled()
    3042             :           ? builder_->common()->OsrGuard(OsrGuardType::kUninitialized)
    3043         136 :           : builder_->common()->OsrGuard(OsrGuardType::kAny);
    3044             :   Node* effect = checkpoint;
    3045         912 :   for (int i = 0; i < size; ++i) {
    3046         844 :     values()->at(i) = effect =
    3047        1688 :         graph->NewNode(guard_op, values()->at(i), effect, osr_loop_entry);
    3048             :   }
    3049             :   contexts()->back() = effect =
    3050         136 :       graph->NewNode(guard_op, contexts()->back(), effect, osr_loop_entry);
    3051             : 
    3052             :   // The innermost context is the OSR value, and the outer contexts are
    3053             :   // reconstructed by dynamically walking up the context chain.
    3054             :   const Operator* load_op =
    3055         136 :       builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true);
    3056          68 :   Node* osr_context = effect = contexts()->back();
    3057         136 :   int last = static_cast<int>(contexts()->size() - 1);
    3058          68 :   for (int i = last - 1; i >= 0; i--) {
    3059             :     osr_context = effect = graph->NewNode(load_op, osr_context, effect);
    3060           0 :     contexts()->at(i) = osr_context;
    3061             :   }
    3062             :   UpdateEffectDependency(effect);
    3063          68 : }
    3064             : 
    3065       48768 : void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned) {
    3066        1668 :   int size = static_cast<int>(values()->size());
    3067             : 
    3068        3336 :   Node* control = builder_->NewLoop();
    3069         834 :   if (assigned == nullptr) {
    3070             :     // Assume that everything is updated in the loop.
    3071           0 :     for (int i = 0; i < size; ++i) {
    3072           0 :       values()->at(i) = builder_->NewPhi(1, values()->at(i), control);
    3073             :     }
    3074             :   } else {
    3075             :     // Only build phis for those locals assigned in this loop.
    3076       23550 :     for (int i = 0; i < size; ++i) {
    3077       47100 :       if (i < assigned->length() && !assigned->Contains(i)) continue;
    3078       10152 :       Node* phi = builder_->NewPhi(1, values()->at(i), control);
    3079        5076 :       values()->at(i) = phi;
    3080             :     }
    3081             :   }
    3082         834 :   Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control);
    3083             :   UpdateEffectDependency(effect);
    3084             : 
    3085             :   // Connect the loop to end via Terminate if it's not marked as unreachable.
    3086         834 :   if (!IsMarkedAsUnreachable()) {
    3087             :     // Connect the Loop node to end via a Terminate node.
    3088             :     Node* terminate = builder_->graph()->NewNode(
    3089        2502 :         builder_->common()->Terminate(), effect, control);
    3090         834 :     builder_->exit_controls_.push_back(terminate);
    3091             :   }
    3092             : 
    3093        1668 :   if (builder_->info()->is_osr()) {
    3094             :     // Introduce phis for all context values in the case of an OSR graph.
    3095         609 :     for (size_t i = 0; i < contexts()->size(); ++i) {
    3096         203 :       Node* context = contexts()->at(i);
    3097         203 :       contexts()->at(i) = builder_->NewPhi(1, context, control);
    3098             :     }
    3099             :   }
    3100         834 : }
    3101             : 
    3102             : 
    3103       27744 : Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) {
    3104       13872 :   const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
    3105       13872 :   Node** buffer = EnsureInputBufferSize(count + 1);
    3106             :   MemsetPointer(buffer, input, count);
    3107       13872 :   buffer[count] = control;
    3108       13872 :   return graph()->NewNode(phi_op, count + 1, buffer, true);
    3109             : }
    3110             : 
    3111             : 
    3112        6562 : Node* AstGraphBuilder::NewEffectPhi(int count, Node* input, Node* control) {
    3113        3281 :   const Operator* phi_op = common()->EffectPhi(count);
    3114        3281 :   Node** buffer = EnsureInputBufferSize(count + 1);
    3115             :   MemsetPointer(buffer, input, count);
    3116        3281 :   buffer[count] = control;
    3117        3281 :   return graph()->NewNode(phi_op, count + 1, buffer, true);
    3118             : }
    3119             : 
    3120             : 
    3121        8867 : Node* AstGraphBuilder::MergeControl(Node* control, Node* other) {
    3122        8772 :   int inputs = control->op()->ControlInputCount() + 1;
    3123        4386 :   if (control->opcode() == IrOpcode::kLoop) {
    3124             :     // Control node for loop exists, add input.
    3125         892 :     const Operator* op = common()->Loop(inputs);
    3126         892 :     control->AppendInput(graph_zone(), other);
    3127         892 :     NodeProperties::ChangeOp(control, op);
    3128        3494 :   } else if (control->opcode() == IrOpcode::kMerge) {
    3129             :     // Control node for merge exists, add input.
    3130        3399 :     const Operator* op = common()->Merge(inputs);
    3131        3399 :     control->AppendInput(graph_zone(), other);
    3132        3399 :     NodeProperties::ChangeOp(control, op);
    3133             :   } else {
    3134             :     // Control node is a singleton, introduce a merge.
    3135          95 :     const Operator* op = common()->Merge(inputs);
    3136          95 :     Node* inputs[] = {control, other};
    3137          95 :     control = graph()->NewNode(op, arraysize(inputs), inputs, true);
    3138             :   }
    3139        4386 :   return control;
    3140             : }
    3141             : 
    3142             : 
    3143       10339 : Node* AstGraphBuilder::MergeEffect(Node* value, Node* other, Node* control) {
    3144        4386 :   int inputs = control->op()->ControlInputCount();
    3145        6128 :   if (value->opcode() == IrOpcode::kEffectPhi &&
    3146        1742 :       NodeProperties::GetControlInput(value) == control) {
    3147             :     // Phi already exists, add input.
    3148        3134 :     value->InsertInput(graph_zone(), inputs - 1, other);
    3149        1567 :     NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
    3150        2819 :   } else if (value != other) {
    3151             :     // Phi does not exist yet, introduce one.
    3152        2447 :     value = NewEffectPhi(inputs, value, control);
    3153        2447 :     value->ReplaceInput(inputs - 1, other);
    3154             :   }
    3155        4386 :   return value;
    3156             : }
    3157             : 
    3158             : 
    3159      293821 : Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) {
    3160      140564 :   int inputs = control->op()->ControlInputCount();
    3161      183878 :   if (value->opcode() == IrOpcode::kPhi &&
    3162       43314 :       NodeProperties::GetControlInput(value) == control) {
    3163             :     // Phi already exists, add input.
    3164       25386 :     value->InsertInput(graph_zone(), inputs - 1, other);
    3165             :     NodeProperties::ChangeOp(
    3166       12693 :         value, common()->Phi(MachineRepresentation::kTagged, inputs));
    3167      127871 :   } else if (value != other) {
    3168             :     // Phi does not exist yet, introduce one.
    3169        8593 :     value = NewPhi(inputs, value, control);
    3170        8593 :     value->ReplaceInput(inputs - 1, other);
    3171             :   }
    3172      140564 :   return value;
    3173             : }
    3174             : 
    3175        2507 : AstGraphBuilderWithPositions::AstGraphBuilderWithPositions(
    3176             :     Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph,
    3177             :     float invocation_frequency, LoopAssignmentAnalysis* loop_assignment,
    3178             :     SourcePositionTable* source_positions, int inlining_id)
    3179             :     : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency,
    3180             :                       loop_assignment),
    3181             :       source_positions_(source_positions),
    3182        5014 :       start_position_(info->shared_info()->start_position(), inlining_id) {}
    3183             : 
    3184             : }  // namespace compiler
    3185             : }  // namespace internal
    3186             : }  // namespace v8

Generated by: LCOV version 1.10