LCOV - code coverage report
Current view: top level - src/interpreter - bytecode-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2320 2401 96.6 %
Date: 2019-02-19 Functions: 180 214 84.1 %

          Line data    Source code
       1             : // Copyright 2015 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/interpreter/bytecode-generator.h"
       6             : 
       7             : #include "src/api-inl.h"
       8             : #include "src/ast/ast-source-ranges.h"
       9             : #include "src/ast/scopes.h"
      10             : #include "src/builtins/builtins-constructor.h"
      11             : #include "src/compiler.h"
      12             : #include "src/interpreter/bytecode-flags.h"
      13             : #include "src/interpreter/bytecode-jump-table.h"
      14             : #include "src/interpreter/bytecode-label.h"
      15             : #include "src/interpreter/bytecode-register-allocator.h"
      16             : #include "src/interpreter/control-flow-builders.h"
      17             : #include "src/objects-inl.h"
      18             : #include "src/objects/debug-objects.h"
      19             : #include "src/objects/literal-objects-inl.h"
      20             : #include "src/objects/smi.h"
      21             : #include "src/parsing/parse-info.h"
      22             : #include "src/parsing/token.h"
      23             : #include "src/unoptimized-compilation-info.h"
      24             : 
      25             : namespace v8 {
      26             : namespace internal {
      27             : namespace interpreter {
      28             : 
      29             : // Scoped class tracking context objects created by the visitor. Represents
      30             : // mutations of the context chain within the function body, allowing pushing and
      31             : // popping of the current {context_register} during visitation.
      32             : class BytecodeGenerator::ContextScope {
      33             :  public:
      34     2406655 :   ContextScope(BytecodeGenerator* generator, Scope* scope)
      35             :       : generator_(generator),
      36             :         scope_(scope),
      37     2406655 :         outer_(generator_->execution_context()),
      38             :         register_(Register::current_context()),
      39     4813310 :         depth_(0) {
      40             :     DCHECK(scope->NeedsContext() || outer_ == nullptr);
      41     2406654 :     if (outer_) {
      42      319576 :       depth_ = outer_->depth_ + 1;
      43             : 
      44             :       // Push the outer context into a new context register.
      45             :       Register outer_context_reg =
      46      319576 :           generator_->register_allocator()->NewRegister();
      47      319582 :       outer_->set_register(outer_context_reg);
      48      319582 :       generator_->builder()->PushContext(outer_context_reg);
      49             :     }
      50     2406658 :     generator_->set_execution_context(this);
      51     2406658 :   }
      52             : 
      53     2406477 :   ~ContextScope() {
      54     2406477 :     if (outer_) {
      55             :       DCHECK_EQ(register_.index(), Register::current_context().index());
      56      319574 :       generator_->builder()->PopContext(outer_->reg());
      57      319588 :       outer_->set_register(register_);
      58             :     }
      59     2406491 :     generator_->set_execution_context(outer_);
      60     2406491 :   }
      61             : 
      62             :   // Returns the depth of the given |scope| for the current execution context.
      63             :   int ContextChainDepth(Scope* scope) {
      64     2699207 :     return scope_->ContextChainLength(scope);
      65             :   }
      66             : 
      67             :   // Returns the execution context at |depth| in the current context chain if it
      68             :   // is a function local execution context, otherwise returns nullptr.
      69             :   ContextScope* Previous(int depth) {
      70     2659653 :     if (depth > depth_) {
      71             :       return nullptr;
      72             :     }
      73             : 
      74             :     ContextScope* previous = this;
      75       22522 :     for (int i = depth; i > 0; --i) {
      76       22522 :       previous = previous->outer_;
      77             :     }
      78             :     return previous;
      79             :   }
      80             : 
      81             :   Register reg() const { return register_; }
      82             : 
      83             :  private:
      84             :   const BytecodeArrayBuilder* builder() const { return generator_->builder(); }
      85             : 
      86      639170 :   void set_register(Register reg) { register_ = reg; }
      87             : 
      88             :   BytecodeGenerator* generator_;
      89             :   Scope* scope_;
      90             :   ContextScope* outer_;
      91             :   Register register_;
      92             :   int depth_;
      93             : };
      94             : 
      95             : // Scoped class for tracking control statements entered by the
      96             : // visitor. The pattern derives AstGraphBuilder::ControlScope.
      97             : class BytecodeGenerator::ControlScope {
      98             :  public:
      99    15198894 :   explicit ControlScope(BytecodeGenerator* generator)
     100             :       : generator_(generator),
     101             :         outer_(generator->execution_control()),
     102    22798341 :         context_(generator->execution_context()) {
     103             :     generator_->set_execution_control(this);
     104             :   }
     105     7599312 :   virtual ~ControlScope() { generator_->set_execution_control(outer()); }
     106             : 
     107             :   void Break(Statement* stmt) {
     108       47165 :     PerformCommand(CMD_BREAK, stmt, kNoSourcePosition);
     109             :   }
     110             :   void Continue(Statement* stmt) {
     111        3541 :     PerformCommand(CMD_CONTINUE, stmt, kNoSourcePosition);
     112             :   }
     113             :   void ReturnAccumulator(int source_position = kNoSourcePosition) {
     114     2053930 :     PerformCommand(CMD_RETURN, nullptr, source_position);
     115             :   }
     116             :   void AsyncReturnAccumulator(int source_position = kNoSourcePosition) {
     117        8273 :     PerformCommand(CMD_ASYNC_RETURN, nullptr, source_position);
     118             :   }
     119             : 
     120             :   class DeferredCommands;
     121             : 
     122             :  protected:
     123             :   enum Command {
     124             :     CMD_BREAK,
     125             :     CMD_CONTINUE,
     126             :     CMD_RETURN,
     127             :     CMD_ASYNC_RETURN,
     128             :     CMD_RETHROW
     129             :   };
     130             :   static constexpr bool CommandUsesAccumulator(Command command) {
     131             :     return command != CMD_BREAK && command != CMD_CONTINUE;
     132             :   }
     133             : 
     134             :   void PerformCommand(Command command, Statement* statement,
     135             :                       int source_position);
     136             :   virtual bool Execute(Command command, Statement* statement,
     137             :                        int source_position) = 0;
     138             : 
     139             :   // Helper to pop the context chain to a depth expected by this control scope.
     140             :   // Note that it is the responsibility of each individual {Execute} method to
     141             :   // trigger this when commands are handled and control-flow continues locally.
     142             :   void PopContextToExpectedDepth();
     143             : 
     144             :   BytecodeGenerator* generator() const { return generator_; }
     145             :   ControlScope* outer() const { return outer_; }
     146             :   ContextScope* context() const { return context_; }
     147             : 
     148             :  private:
     149             :   BytecodeGenerator* generator_;
     150             :   ControlScope* outer_;
     151             :   ContextScope* context_;
     152             : 
     153             :   DISALLOW_COPY_AND_ASSIGN(ControlScope);
     154             : };
     155             : 
     156             : // Helper class for a try-finally control scope. It can record intercepted
     157             : // control-flow commands that cause entry into a finally-block, and re-apply
     158             : // them after again leaving that block. Special tokens are used to identify
     159             : // paths going through the finally-block to dispatch after leaving the block.
     160             : class BytecodeGenerator::ControlScope::DeferredCommands final {
     161             :  public:
     162             :   // Fixed value tokens for paths we know we need.
     163             :   // Fallthrough is set to -1 to make it the fallthrough case of the jump table,
     164             :   // where the remaining cases start at 0.
     165             :   static const int kFallthroughToken = -1;
     166             :   // TODO(leszeks): Rethrow being 0 makes it use up a valuable LdaZero, which
     167             :   // means that other commands (such as break or return) have to use LdaSmi.
     168             :   // This can very slightly bloat bytecode, so perhaps token values should all
     169             :   // be shifted down by 1.
     170             :   static const int kRethrowToken = 0;
     171             : 
     172       83196 :   DeferredCommands(BytecodeGenerator* generator, Register token_register,
     173             :                    Register result_register)
     174             :       : generator_(generator),
     175             :         deferred_(generator->zone()),
     176             :         token_register_(token_register),
     177             :         result_register_(result_register),
     178             :         return_token_(-1),
     179       83196 :         async_return_token_(-1) {
     180             :     // There's always a rethrow path.
     181             :     // TODO(leszeks): We could decouple deferred_ index and token to allow us
     182             :     // to still push this lazily.
     183             :     STATIC_ASSERT(kRethrowToken == 0);
     184       83197 :     deferred_.push_back({CMD_RETHROW, nullptr, kRethrowToken});
     185       41599 :   }
     186             : 
     187             :   // One recorded control-flow command.
     188             :   struct Entry {
     189             :     Command command;       // The command type being applied on this path.
     190             :     Statement* statement;  // The target statement for the command or {nullptr}.
     191             :     int token;             // A token identifying this particular path.
     192             :   };
     193             : 
     194             :   // Records a control-flow command while entering the finally-block. This also
     195             :   // generates a new dispatch token that identifies one particular path. This
     196             :   // expects the result to be in the accumulator.
     197      209681 :   void RecordCommand(Command command, Statement* statement) {
     198       52421 :     int token = GetTokenForCommand(command, statement);
     199             : 
     200             :     DCHECK_LT(token, deferred_.size());
     201             :     DCHECK_EQ(deferred_[token].command, command);
     202             :     DCHECK_EQ(deferred_[token].statement, statement);
     203             :     DCHECK_EQ(deferred_[token].token, token);
     204             : 
     205       52417 :     if (CommandUsesAccumulator(command)) {
     206       52166 :       builder()->StoreAccumulatorInRegister(result_register_);
     207             :     }
     208       52419 :     builder()->LoadLiteral(Smi::FromInt(token));
     209       52422 :     builder()->StoreAccumulatorInRegister(token_register_);
     210       52422 :     if (!CommandUsesAccumulator(command)) {
     211             :       // If we're not saving the accumulator in the result register, shove a
     212             :       // harmless value there instead so that it is still considered "killed" in
     213             :       // the liveness analysis. Normally we would LdaUndefined first, but the
     214             :       // Smi token value is just as good, and by reusing it we save a bytecode.
     215         253 :       builder()->StoreAccumulatorInRegister(result_register_);
     216             :     }
     217       52422 :   }
     218             : 
     219             :   // Records the dispatch token to be used to identify the re-throw path when
     220             :   // the finally-block has been entered through the exception handler. This
     221             :   // expects the exception to be in the accumulator.
     222             :   void RecordHandlerReThrowPath() {
     223             :     // The accumulator contains the exception object.
     224       41605 :     RecordCommand(CMD_RETHROW, nullptr);
     225             :   }
     226             : 
     227             :   // Records the dispatch token to be used to identify the implicit fall-through
     228             :   // path at the end of a try-block into the corresponding finally-block.
     229      124808 :   void RecordFallThroughPath() {
     230       41599 :     builder()->LoadLiteral(Smi::FromInt(kFallthroughToken));
     231       41605 :     builder()->StoreAccumulatorInRegister(token_register_);
     232             :     // Since we're not saving the accumulator in the result register, shove a
     233             :     // harmless value there instead so that it is still considered "killed" in
     234             :     // the liveness analysis. Normally we would LdaUndefined first, but the Smi
     235             :     // token value is just as good, and by reusing it we save a bytecode.
     236       41604 :     builder()->StoreAccumulatorInRegister(result_register_);
     237       41605 :   }
     238             : 
     239             :   // Applies all recorded control-flow commands after the finally-block again.
     240             :   // This generates a dynamic dispatch on the token from the entry point.
     241      222841 :   void ApplyDeferredCommands() {
     242       83192 :     if (deferred_.size() == 0) return;
     243             : 
     244             :     BytecodeLabel fall_through;
     245             : 
     246       41596 :     if (deferred_.size() == 1) {
     247             :       // For a single entry, just jump to the fallthrough if we don't match the
     248             :       // entry token.
     249             :       const Entry& entry = deferred_[0];
     250             : 
     251             :       builder()
     252       78448 :           ->LoadLiteral(Smi::FromInt(entry.token))
     253       39233 :           .CompareReference(token_register_)
     254       39233 :           .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &fall_through);
     255             : 
     256       39233 :       if (CommandUsesAccumulator(entry.command)) {
     257       39233 :         builder()->LoadAccumulatorWithRegister(result_register_);
     258             :       }
     259             :       execution_control()->PerformCommand(entry.command, entry.statement,
     260       78466 :                                           kNoSourcePosition);
     261             :     } else {
     262             :       // For multiple entries, build a jump table and switch on the token,
     263             :       // jumping to the fallthrough if none of them match.
     264             : 
     265             :       BytecodeJumpTable* jump_table =
     266        4744 :           builder()->AllocateJumpTable(static_cast<int>(deferred_.size()), 0);
     267             :       builder()
     268        2372 :           ->LoadAccumulatorWithRegister(token_register_)
     269        2372 :           .SwitchOnSmiNoFeedback(jump_table)
     270        2372 :           .Jump(&fall_through);
     271       10564 :       for (const Entry& entry : deferred_) {
     272       11640 :         builder()->Bind(jump_table, entry.token);
     273             : 
     274        5820 :         if (CommandUsesAccumulator(entry.command)) {
     275        5567 :           builder()->LoadAccumulatorWithRegister(result_register_);
     276             :         }
     277             :         execution_control()->PerformCommand(entry.command, entry.statement,
     278       11640 :                                             kNoSourcePosition);
     279             :       }
     280             :     }
     281             : 
     282       41604 :     builder()->Bind(&fall_through);
     283             :   }
     284             : 
     285             :   BytecodeArrayBuilder* builder() { return generator_->builder(); }
     286       45053 :   ControlScope* execution_control() { return generator_->execution_control(); }
     287             : 
     288             :  private:
     289       52414 :   int GetTokenForCommand(Command command, Statement* statement) {
     290       52414 :     switch (command) {
     291             :       case CMD_RETURN:
     292        2045 :         return GetReturnToken();
     293             :       case CMD_ASYNC_RETURN:
     294        2516 :         return GetAsyncReturnToken();
     295             :       case CMD_RETHROW:
     296             :         return kRethrowToken;
     297             :       default:
     298             :         // TODO(leszeks): We could also search for entries with the same
     299             :         // command and statement.
     300         253 :         return GetNewTokenForCommand(command, statement);
     301             :     }
     302             :   }
     303             : 
     304        2045 :   int GetReturnToken() {
     305        2045 :     if (return_token_ == -1) {
     306        1896 :       return_token_ = GetNewTokenForCommand(CMD_RETURN, nullptr);
     307             :     }
     308        2045 :     return return_token_;
     309             :   }
     310             : 
     311        2516 :   int GetAsyncReturnToken() {
     312        2516 :     if (async_return_token_ == -1) {
     313        1299 :       async_return_token_ = GetNewTokenForCommand(CMD_ASYNC_RETURN, nullptr);
     314             :     }
     315        2516 :     return async_return_token_;
     316             :   }
     317             : 
     318             :   int GetNewTokenForCommand(Command command, Statement* statement) {
     319        6896 :     int token = static_cast<int>(deferred_.size());
     320        6896 :     deferred_.push_back({command, statement, token});
     321             :     return token;
     322             :   }
     323             : 
     324             :   BytecodeGenerator* generator_;
     325             :   ZoneVector<Entry> deferred_;
     326             :   Register token_register_;
     327             :   Register result_register_;
     328             : 
     329             :   // Tokens for commands that don't need a statement.
     330             :   int return_token_;
     331             :   int async_return_token_;
     332             : };
     333             : 
     334             : // Scoped class for dealing with control flow reaching the function level.
     335     2087013 : class BytecodeGenerator::ControlScopeForTopLevel final
     336             :     : public BytecodeGenerator::ControlScope {
     337             :  public:
     338             :   explicit ControlScopeForTopLevel(BytecodeGenerator* generator)
     339     2087089 :       : ControlScope(generator) {}
     340             : 
     341             :  protected:
     342     2094657 :   bool Execute(Command command, Statement* statement,
     343             :                int source_position) override {
     344     2094657 :     switch (command) {
     345             :       case CMD_BREAK:  // We should never see break/continue in top-level.
     346             :       case CMD_CONTINUE:
     347           0 :         UNREACHABLE();
     348             :       case CMD_RETURN:
     349             :         // No need to pop contexts, execution leaves the method body.
     350     2094733 :         generator()->BuildReturn(source_position);
     351     2053748 :         return true;
     352             :       case CMD_ASYNC_RETURN:
     353             :         // No need to pop contexts, execution leaves the method body.
     354        7057 :         generator()->BuildAsyncReturn(source_position);
     355        7057 :         return true;
     356             :       case CMD_RETHROW:
     357             :         // No need to pop contexts, execution leaves the method body.
     358             :         generator()->BuildReThrow();
     359       34048 :         return true;
     360             :     }
     361             :     return false;
     362             :   }
     363             : };
     364             : 
     365             : // Scoped class for enabling break inside blocks and switch blocks.
     366     5104139 : class BytecodeGenerator::ControlScopeForBreakable final
     367             :     : public BytecodeGenerator::ControlScope {
     368             :  public:
     369             :   ControlScopeForBreakable(BytecodeGenerator* generator,
     370             :                            BreakableStatement* statement,
     371             :                            BreakableControlFlowBuilder* control_builder)
     372             :       : ControlScope(generator),
     373             :         statement_(statement),
     374     5104198 :         control_builder_(control_builder) {}
     375             : 
     376             :  protected:
     377      409290 :   bool Execute(Command command, Statement* statement,
     378             :                int source_position) override {
     379      409290 :     if (statement != statement_) return false;
     380       26807 :     switch (command) {
     381             :       case CMD_BREAK:
     382       26807 :         PopContextToExpectedDepth();
     383       26807 :         control_builder_->Break();
     384       26807 :         return true;
     385             :       case CMD_CONTINUE:
     386             :       case CMD_RETURN:
     387             :       case CMD_ASYNC_RETURN:
     388             :       case CMD_RETHROW:
     389             :         break;
     390             :     }
     391             :     return false;
     392             :   }
     393             : 
     394             :  private:
     395             :   Statement* statement_;
     396             :   BreakableControlFlowBuilder* control_builder_;
     397             : };
     398             : 
     399             : // Scoped class for enabling 'break' and 'continue' in iteration
     400             : // constructs, e.g. do...while, while..., for...
     401             : class BytecodeGenerator::ControlScopeForIteration final
     402             :     : public BytecodeGenerator::ControlScope {
     403             :  public:
     404             :   ControlScopeForIteration(BytecodeGenerator* generator,
     405             :                            IterationStatement* statement,
     406             :                            LoopBuilder* loop_builder)
     407             :       : ControlScope(generator),
     408             :         statement_(statement),
     409      259472 :         loop_builder_(loop_builder) {
     410      259472 :     generator->loop_depth_++;
     411             :   }
     412      259470 :   ~ControlScopeForIteration() override { generator()->loop_depth_--; }
     413             : 
     414             :  protected:
     415       67661 :   bool Execute(Command command, Statement* statement,
     416             :                int source_position) override {
     417       67661 :     if (statement != statement_) return false;
     418       23900 :     switch (command) {
     419             :       case CMD_BREAK:
     420       20358 :         PopContextToExpectedDepth();
     421       20358 :         loop_builder_->Break();
     422       20360 :         return true;
     423             :       case CMD_CONTINUE:
     424        3541 :         PopContextToExpectedDepth();
     425        3541 :         loop_builder_->Continue();
     426        3541 :         return true;
     427             :       case CMD_RETURN:
     428             :       case CMD_ASYNC_RETURN:
     429             :       case CMD_RETHROW:
     430             :         break;
     431             :     }
     432             :     return false;
     433             :   }
     434             : 
     435             :  private:
     436             :   Statement* statement_;
     437             :   LoopBuilder* loop_builder_;
     438             : };
     439             : 
     440             : // Scoped class for enabling 'throw' in try-catch constructs.
     441      107089 : class BytecodeGenerator::ControlScopeForTryCatch final
     442             :     : public BytecodeGenerator::ControlScope {
     443             :  public:
     444             :   ControlScopeForTryCatch(BytecodeGenerator* generator,
     445             :                           TryCatchBuilder* try_catch_builder)
     446      107087 :       : ControlScope(generator) {}
     447             : 
     448             :  protected:
     449       13978 :   bool Execute(Command command, Statement* statement,
     450             :                int source_position) override {
     451       13978 :     switch (command) {
     452             :       case CMD_BREAK:
     453             :       case CMD_CONTINUE:
     454             :       case CMD_RETURN:
     455             :       case CMD_ASYNC_RETURN:
     456             :         break;
     457             :       case CMD_RETHROW:
     458             :         // No need to pop contexts, execution re-enters the method body via the
     459             :         // stack unwinding mechanism which itself restores contexts correctly.
     460        1553 :         generator()->BuildReThrow();
     461        1553 :         return true;
     462             :     }
     463             :     return false;
     464             :   }
     465             : };
     466             : 
     467             : // Scoped class for enabling control flow through try-finally constructs.
     468       41601 : class BytecodeGenerator::ControlScopeForTryFinally final
     469             :     : public BytecodeGenerator::ControlScope {
     470             :  public:
     471             :   ControlScopeForTryFinally(BytecodeGenerator* generator,
     472             :                             TryFinallyBuilder* try_finally_builder,
     473             :                             DeferredCommands* commands)
     474             :       : ControlScope(generator),
     475             :         try_finally_builder_(try_finally_builder),
     476       41601 :         commands_(commands) {}
     477             : 
     478             :  protected:
     479       10814 :   bool Execute(Command command, Statement* statement,
     480             :                int source_position) override {
     481       10814 :     switch (command) {
     482             :       case CMD_BREAK:
     483             :       case CMD_CONTINUE:
     484             :       case CMD_RETURN:
     485             :       case CMD_ASYNC_RETURN:
     486             :       case CMD_RETHROW:
     487       10814 :         PopContextToExpectedDepth();
     488             :         // We don't record source_position here since we don't generate return
     489             :         // bytecode right here and will generate it later as part of finally
     490             :         // block. Each return bytecode generated in finally block will get own
     491             :         // return source position from corresponded return statement or we'll
     492             :         // use end of function if no return statement is presented.
     493       10816 :         commands_->RecordCommand(command, statement);
     494       10817 :         try_finally_builder_->LeaveTry();
     495       10817 :         return true;
     496             :     }
     497             :     return false;
     498             :   }
     499             : 
     500             :  private:
     501             :   TryFinallyBuilder* try_finally_builder_;
     502             :   DeferredCommands* commands_;
     503             : };
     504             : 
     505             : // Allocate and fetch the coverage indices tracking NaryLogical Expressions.
     506             : class BytecodeGenerator::NaryCodeCoverageSlots {
     507             :  public:
     508       20848 :   NaryCodeCoverageSlots(BytecodeGenerator* generator, NaryOperation* expr)
     509       20848 :       : generator_(generator) {
     510       41696 :     if (generator_->block_coverage_builder_ == nullptr) return;
     511         592 :     for (size_t i = 0; i < expr->subsequent_length(); i++) {
     512             :       coverage_slots_.push_back(
     513         732 :           generator_->AllocateNaryBlockCoverageSlotIfEnabled(expr, i));
     514             :     }
     515             :   }
     516             : 
     517             :   int GetSlotFor(size_t subsequent_expr_index) const {
     518       79182 :     if (generator_->block_coverage_builder_ == nullptr) {
     519             :       return BlockCoverageBuilder::kNoCoverageArraySlot;
     520             :     }
     521             :     DCHECK(coverage_slots_.size() > subsequent_expr_index);
     522         336 :     return coverage_slots_[subsequent_expr_index];
     523             :   }
     524             : 
     525             :  private:
     526             :   BytecodeGenerator* generator_;
     527             :   std::vector<int> coverage_slots_;
     528             : };
     529             : 
     530     2157779 : void BytecodeGenerator::ControlScope::PerformCommand(Command command,
     531             :                                                      Statement* statement,
     532             :                                                      int source_position) {
     533      438664 :   ControlScope* current = this;
     534      438664 :   do {
     535     2596443 :     if (current->Execute(command, statement, source_position)) {
     536     2157934 :       return;
     537             :     }
     538             :     current = current->outer();
     539             :   } while (current != nullptr);
     540           0 :   UNREACHABLE();
     541             : }
     542             : 
     543      123042 : void BytecodeGenerator::ControlScope::PopContextToExpectedDepth() {
     544             :   // Pop context to the expected depth. Note that this can in fact pop multiple
     545             :   // contexts at once because the {PopContext} bytecode takes a saved register.
     546      123042 :   if (generator()->execution_context() != context()) {
     547        9457 :     generator()->builder()->PopContext(context()->reg());
     548             :   }
     549       61522 : }
     550             : 
     551             : class BytecodeGenerator::RegisterAllocationScope final {
     552             :  public:
     553             :   explicit RegisterAllocationScope(BytecodeGenerator* generator)
     554             :       : generator_(generator),
     555             :         outer_next_register_index_(
     556    79694387 :             generator->register_allocator()->next_register_index()) {}
     557             : 
     558    79678744 :   ~RegisterAllocationScope() {
     559             :     generator_->register_allocator()->ReleaseRegisters(
     560    79678744 :         outer_next_register_index_);
     561    79678047 :   }
     562             : 
     563             :   BytecodeGenerator* generator() const { return generator_; }
     564             : 
     565             :  private:
     566             :   BytecodeGenerator* generator_;
     567             :   int outer_next_register_index_;
     568             : 
     569             :   DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope);
     570             : };
     571             : 
     572             : class BytecodeGenerator::AccumulatorPreservingScope final {
     573             :  public:
     574     2417117 :   explicit AccumulatorPreservingScope(BytecodeGenerator* generator,
     575             :                                       AccumulatorPreservingMode mode)
     576     2417117 :       : generator_(generator) {
     577     2417117 :     if (mode == AccumulatorPreservingMode::kPreserve) {
     578             :       saved_accumulator_register_ =
     579         144 :           generator_->register_allocator()->NewRegister();
     580             :       generator_->builder()->StoreAccumulatorInRegister(
     581         144 :           saved_accumulator_register_);
     582             :     }
     583     2417117 :   }
     584             : 
     585             :   ~AccumulatorPreservingScope() {
     586     2417145 :     if (saved_accumulator_register_.is_valid()) {
     587             :       generator_->builder()->LoadAccumulatorWithRegister(
     588         144 :           saved_accumulator_register_);
     589             :     }
     590             :   }
     591             : 
     592             :  private:
     593             :   BytecodeGenerator* generator_;
     594             :   Register saved_accumulator_register_;
     595             : 
     596             :   DISALLOW_COPY_AND_ASSIGN(AccumulatorPreservingScope);
     597             : };
     598             : 
     599             : // Scoped base class for determining how the result of an expression will be
     600             : // used.
     601             : class BytecodeGenerator::ExpressionResultScope {
     602             :  public:
     603    43948281 :   ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind)
     604             :       : outer_(generator->execution_result()),
     605             :         allocator_(generator),
     606             :         kind_(kind),
     607    87896562 :         type_hint_(TypeHint::kAny) {
     608             :     generator->set_execution_result(this);
     609             :   }
     610             : 
     611    43948174 :   ~ExpressionResultScope() {
     612    43948174 :     allocator_.generator()->set_execution_result(outer_);
     613             :   }
     614             : 
     615             :   bool IsEffect() const { return kind_ == Expression::kEffect; }
     616             :   bool IsValue() const { return kind_ == Expression::kValue; }
     617             :   bool IsTest() const { return kind_ == Expression::kTest; }
     618             : 
     619             :   TestResultScope* AsTest() {
     620             :     DCHECK(IsTest());
     621             :     return reinterpret_cast<TestResultScope*>(this);
     622             :   }
     623             : 
     624             :   // Specify expression always returns a Boolean result value.
     625             :   void SetResultIsBoolean() {
     626             :     DCHECK_EQ(type_hint_, TypeHint::kAny);
     627     1228412 :     type_hint_ = TypeHint::kBoolean;
     628             :   }
     629             : 
     630             :   void SetResultIsString() {
     631             :     DCHECK_EQ(type_hint_, TypeHint::kAny);
     632     1742385 :     type_hint_ = TypeHint::kString;
     633             :   }
     634             : 
     635             :   TypeHint type_hint() const { return type_hint_; }
     636             : 
     637             :  private:
     638             :   ExpressionResultScope* outer_;
     639             :   RegisterAllocationScope allocator_;
     640             :   Expression::Context kind_;
     641             :   TypeHint type_hint_;
     642             : 
     643             :   DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
     644             : };
     645             : 
     646             : // Scoped class used when the result of the current expression is not
     647             : // expected to produce a result.
     648             : class BytecodeGenerator::EffectResultScope final
     649             :     : public ExpressionResultScope {
     650             :  public:
     651             :   explicit EffectResultScope(BytecodeGenerator* generator)
     652             :       : ExpressionResultScope(generator, Expression::kEffect) {}
     653             : };
     654             : 
     655             : // Scoped class used when the result of the current expression to be
     656             : // evaluated should go into the interpreter's accumulator.
     657     1686352 : class BytecodeGenerator::ValueResultScope final : public ExpressionResultScope {
     658             :  public:
     659      843181 :   explicit ValueResultScope(BytecodeGenerator* generator)
     660     1686362 :       : ExpressionResultScope(generator, Expression::kValue) {}
     661             : };
     662             : 
     663             : // Scoped class used when the result of the current expression to be
     664             : // evaluated is only tested with jumps to two branches.
     665             : class BytecodeGenerator::TestResultScope final : public ExpressionResultScope {
     666             :  public:
     667             :   TestResultScope(BytecodeGenerator* generator, BytecodeLabels* then_labels,
     668             :                   BytecodeLabels* else_labels, TestFallthrough fallthrough)
     669             :       : ExpressionResultScope(generator, Expression::kTest),
     670             :         result_consumed_by_test_(false),
     671             :         fallthrough_(fallthrough),
     672             :         then_labels_(then_labels),
     673     1019705 :         else_labels_(else_labels) {}
     674             : 
     675             :   // Used when code special cases for TestResultScope and consumes any
     676             :   // possible value by testing and jumping to a then/else label.
     677      348398 :   void SetResultConsumedByTest() { result_consumed_by_test_ = true; }
     678             :   bool result_consumed_by_test() { return result_consumed_by_test_; }
     679             : 
     680             :   // Inverts the control flow of the operation, swapping the then and else
     681             :   // labels and the fallthrough.
     682      242216 :   void InvertControlFlow() {
     683             :     std::swap(then_labels_, else_labels_);
     684      242216 :     fallthrough_ = inverted_fallthrough();
     685             :   }
     686             : 
     687       43306 :   BytecodeLabel* NewThenLabel() { return then_labels_->New(); }
     688       14441 :   BytecodeLabel* NewElseLabel() { return else_labels_->New(); }
     689             : 
     690             :   BytecodeLabels* then_labels() const { return then_labels_; }
     691             :   BytecodeLabels* else_labels() const { return else_labels_; }
     692             : 
     693             :   void set_then_labels(BytecodeLabels* then_labels) {
     694             :     then_labels_ = then_labels;
     695             :   }
     696             :   void set_else_labels(BytecodeLabels* else_labels) {
     697             :     else_labels_ = else_labels;
     698             :   }
     699             : 
     700             :   TestFallthrough fallthrough() const { return fallthrough_; }
     701             :   TestFallthrough inverted_fallthrough() const {
     702      242216 :     switch (fallthrough_) {
     703             :       case TestFallthrough::kThen:
     704             :         return TestFallthrough::kElse;
     705             :       case TestFallthrough::kElse:
     706             :         return TestFallthrough::kThen;
     707             :       default:
     708             :         return TestFallthrough::kNone;
     709             :     }
     710             :   }
     711             :   void set_fallthrough(TestFallthrough fallthrough) {
     712             :     fallthrough_ = fallthrough;
     713             :   }
     714             : 
     715             :  private:
     716             :   bool result_consumed_by_test_;
     717             :   TestFallthrough fallthrough_;
     718             :   BytecodeLabels* then_labels_;
     719             :   BytecodeLabels* else_labels_;
     720             : 
     721             :   DISALLOW_COPY_AND_ASSIGN(TestResultScope);
     722             : };
     723             : 
     724             : // Used to build a list of global declaration initial value pairs.
     725             : class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject {
     726             :  public:
     727     2203662 :   explicit GlobalDeclarationsBuilder(Zone* zone)
     728             :       : declarations_(0, zone),
     729             :         constant_pool_entry_(0),
     730     2203658 :         has_constant_pool_entry_(false) {}
     731             : 
     732             :   void AddFunctionDeclaration(const AstRawString* name, FeedbackSlot slot,
     733             :                               FeedbackSlot literal_slot,
     734             :                               FunctionLiteral* func) {
     735             :     DCHECK(!slot.IsInvalid());
     736      489620 :     declarations_.push_back(Declaration(name, slot, literal_slot, func));
     737             :   }
     738             : 
     739             :   void AddUndefinedDeclaration(const AstRawString* name, FeedbackSlot slot) {
     740             :     DCHECK(!slot.IsInvalid());
     741     2518165 :     declarations_.push_back(Declaration(name, slot, nullptr));
     742             :   }
     743             : 
     744      106125 :   Handle<FixedArray> AllocateDeclarations(UnoptimizedCompilationInfo* info,
     745             :                                           Handle<Script> script,
     746             :                                           Isolate* isolate) {
     747             :     DCHECK(has_constant_pool_entry_);
     748             :     int array_index = 0;
     749             :     Handle<FixedArray> data = isolate->factory()->NewFixedArray(
     750      212250 :         static_cast<int>(declarations_.size() * 4), TENURED);
     751     1497571 :     for (const Declaration& declaration : declarations_) {
     752     1285320 :       FunctionLiteral* func = declaration.func;
     753             :       Handle<Object> initial_value;
     754     1285320 :       if (func == nullptr) {
     755             :         initial_value = isolate->factory()->undefined_value();
     756             :       } else {
     757      211852 :         initial_value = Compiler::GetSharedFunctionInfo(func, script, isolate);
     758             :       }
     759             : 
     760             :       // Return a null handle if any initial values can't be created. Caller
     761             :       // will set stack overflow.
     762     1285321 :       if (initial_value.is_null()) return Handle<FixedArray>();
     763             : 
     764     3855963 :       data->set(array_index++, *declaration.name->string());
     765     1285321 :       data->set(array_index++, Smi::FromInt(declaration.slot.ToInt()));
     766             :       Object undefined_or_literal_slot;
     767     1285321 :       if (declaration.literal_slot.IsInvalid()) {
     768     1073468 :         undefined_or_literal_slot = ReadOnlyRoots(isolate).undefined_value();
     769             :       } else {
     770             :         undefined_or_literal_slot =
     771      211853 :             Smi::FromInt(declaration.literal_slot.ToInt());
     772             :       }
     773     2570641 :       data->set(array_index++, undefined_or_literal_slot);
     774     2570642 :       data->set(array_index++, *initial_value);
     775             :     }
     776      106126 :     return data;
     777             :   }
     778             : 
     779             :   size_t constant_pool_entry() {
     780             :     DCHECK(has_constant_pool_entry_);
     781             :     return constant_pool_entry_;
     782             :   }
     783             : 
     784             :   void set_constant_pool_entry(size_t constant_pool_entry) {
     785             :     DCHECK(!empty());
     786             :     DCHECK(!has_constant_pool_entry_);
     787      116567 :     constant_pool_entry_ = constant_pool_entry;
     788      116567 :     has_constant_pool_entry_ = true;
     789             :   }
     790             : 
     791             :   bool empty() { return declarations_.empty(); }
     792             : 
     793             :  private:
     794             :   struct Declaration {
     795     4407324 :     Declaration() : slot(FeedbackSlot::Invalid()), func(nullptr) {}
     796             :     Declaration(const AstRawString* name, FeedbackSlot slot,
     797             :                 FeedbackSlot literal_slot, FunctionLiteral* func)
     798      244801 :         : name(name), slot(slot), literal_slot(literal_slot), func(func) {}
     799             :     Declaration(const AstRawString* name, FeedbackSlot slot,
     800             :                 FunctionLiteral* func)
     801             :         : name(name),
     802             :           slot(slot),
     803             :           literal_slot(FeedbackSlot::Invalid()),
     804     1259068 :           func(func) {}
     805             : 
     806             :     const AstRawString* name;
     807             :     FeedbackSlot slot;
     808             :     FeedbackSlot literal_slot;
     809             :     FunctionLiteral* func;
     810             :   };
     811             :   ZoneVector<Declaration> declarations_;
     812             :   size_t constant_pool_entry_;
     813             :   bool has_constant_pool_entry_;
     814             : };
     815             : 
     816             : class BytecodeGenerator::CurrentScope final {
     817             :  public:
     818     5207354 :   CurrentScope(BytecodeGenerator* generator, Scope* scope)
     819             :       : generator_(generator), outer_scope_(generator->current_scope()) {
     820     5207354 :     if (scope != nullptr) {
     821             :       DCHECK_EQ(outer_scope_, scope->outer_scope());
     822             :       generator_->set_current_scope(scope);
     823             :     }
     824             :   }
     825             :   ~CurrentScope() {
     826     5207438 :     if (outer_scope_ != generator_->current_scope()) {
     827             :       generator_->set_current_scope(outer_scope_);
     828             :     }
     829             :   }
     830             : 
     831             :  private:
     832             :   BytecodeGenerator* generator_;
     833             :   Scope* outer_scope_;
     834             : };
     835             : 
     836             : class BytecodeGenerator::FeedbackSlotCache : public ZoneObject {
     837             :  public:
     838             :   explicit FeedbackSlotCache(Zone* zone) : map_(zone) {}
     839             : 
     840             :   void Put(FeedbackSlotKind slot_kind, Variable* variable, FeedbackSlot slot) {
     841             :     PutImpl(slot_kind, 0, variable, slot);
     842             :   }
     843             :   void Put(FeedbackSlotKind slot_kind, AstNode* node, FeedbackSlot slot) {
     844             :     PutImpl(slot_kind, 0, node, slot);
     845             :   }
     846             :   void Put(FeedbackSlotKind slot_kind, int variable_index,
     847             :            const AstRawString* name, FeedbackSlot slot) {
     848             :     PutImpl(slot_kind, variable_index, name, slot);
     849             :   }
     850             : 
     851             :   FeedbackSlot Get(FeedbackSlotKind slot_kind, Variable* variable) const {
     852     9063556 :     return GetImpl(slot_kind, 0, variable);
     853             :   }
     854             :   FeedbackSlot Get(FeedbackSlotKind slot_kind, AstNode* node) const {
     855     2894961 :     return GetImpl(slot_kind, 0, node);
     856             :   }
     857             :   FeedbackSlot Get(FeedbackSlotKind slot_kind, int variable_index,
     858             :                    const AstRawString* name) const {
     859      772543 :     return GetImpl(slot_kind, variable_index, name);
     860             :   }
     861             : 
     862             :  private:
     863             :   typedef std::tuple<FeedbackSlotKind, int, const void*> Key;
     864             : 
     865             :   void PutImpl(FeedbackSlotKind slot_kind, int index, const void* node,
     866             :                FeedbackSlot slot) {
     867             :     Key key = std::make_tuple(slot_kind, index, node);
     868             :     auto entry = std::make_pair(key, slot);
     869             :     map_.insert(entry);
     870             :   }
     871             : 
     872    12729820 :   FeedbackSlot GetImpl(FeedbackSlotKind slot_kind, int index,
     873             :                        const void* node) const {
     874             :     Key key = std::make_tuple(slot_kind, index, node);
     875             :     auto iter = map_.find(key);
     876    12730991 :     if (iter != map_.end()) {
     877     5115439 :       return iter->second;
     878             :     }
     879     7615552 :     return FeedbackSlot();
     880             :   }
     881             : 
     882             :   ZoneMap<Key, FeedbackSlot> map_;
     883             : };
     884             : 
     885             : class BytecodeGenerator::IteratorRecord final {
     886             :  public:
     887             :   IteratorRecord(Register object_register, Register next_register,
     888             :                  IteratorType type = IteratorType::kNormal)
     889             :       : type_(type), object_(object_register), next_(next_register) {
     890             :     DCHECK(object_.is_valid() && next_.is_valid());
     891             :   }
     892             : 
     893             :   inline IteratorType type() const { return type_; }
     894             :   inline Register object() const { return object_; }
     895             :   inline Register next() const { return next_; }
     896             : 
     897             :  private:
     898             :   IteratorType type_;
     899             :   Register object_;
     900             :   Register next_;
     901             : };
     902             : 
     903             : #ifdef DEBUG
     904             : 
     905             : static bool IsInEagerLiterals(
     906             :     FunctionLiteral* literal,
     907             :     const std::vector<FunctionLiteral*>& eager_literals) {
     908             :   for (FunctionLiteral* eager_literal : eager_literals) {
     909             :     if (literal == eager_literal) return true;
     910             :   }
     911             :   return false;
     912             : }
     913             : 
     914             : #endif  // DEBUG
     915             : 
     916     2087099 : BytecodeGenerator::BytecodeGenerator(
     917     4174200 :     UnoptimizedCompilationInfo* info,
     918             :     const AstStringConstants* ast_string_constants,
     919    20871907 :     std::vector<FunctionLiteral*>* eager_inner_literals)
     920             :     : zone_(info->zone()),
     921             :       builder_(zone(), info->num_parameters_including_this(),
     922     2087101 :                info->scope()->num_stack_slots(), info->feedback_vector_spec(),
     923             :                info->SourcePositionRecordingMode()),
     924             :       info_(info),
     925             :       ast_string_constants_(ast_string_constants),
     926     2087110 :       closure_scope_(info->scope()),
     927     2087109 :       current_scope_(info->scope()),
     928             :       eager_inner_literals_(eager_inner_literals),
     929             :       feedback_slot_cache_(new (zone()) FeedbackSlotCache(zone())),
     930     2087101 :       globals_builder_(new (zone()) GlobalDeclarationsBuilder(zone())),
     931             :       block_coverage_builder_(nullptr),
     932             :       global_declarations_(0, zone()),
     933             :       function_literals_(0, zone()),
     934             :       native_function_literals_(0, zone()),
     935             :       object_literals_(0, zone()),
     936             :       array_literals_(0, zone()),
     937             :       class_literals_(0, zone()),
     938             :       template_objects_(0, zone()),
     939             :       execution_control_(nullptr),
     940             :       execution_context_(nullptr),
     941             :       execution_result_(nullptr),
     942             :       incoming_new_target_or_generator_(),
     943             :       dummy_feedback_slot_(feedback_spec(), FeedbackSlotKind::kCompareOp),
     944             :       generator_jump_table_(nullptr),
     945             :       suspend_count_(0),
     946             :       loop_depth_(0),
     947    20871035 :       catch_prediction_(HandlerTable::UNCAUGHT) {
     948             :   DCHECK_EQ(closure_scope(), closure_scope()->GetClosureScope());
     949     2087101 :   if (info->has_source_range_map()) {
     950             :     block_coverage_builder_ = new (zone())
     951         884 :         BlockCoverageBuilder(zone(), builder(), info->source_range_map());
     952             :   }
     953     2087101 : }
     954             : 
     955     2063523 : Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
     956     2064408 :     Isolate* isolate, Handle<Script> script) {
     957             :   DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
     958             : #ifdef DEBUG
     959             :   // Unoptimized compilation should be context-independent. Verify that we don't
     960             :   // access the native context by nulling it out during finalization.
     961             :   SaveAndSwitchContext save(isolate, Context());
     962             : #endif
     963             : 
     964     2063523 :   AllocateDeferredConstants(isolate, script);
     965             : 
     966     2063524 :   if (block_coverage_builder_) {
     967             :     info()->set_coverage_info(
     968         884 :         isolate->factory()->NewCoverageInfo(block_coverage_builder_->slots()));
     969         884 :     if (FLAG_trace_block_coverage) {
     970           0 :       info()->coverage_info()->Print(info()->literal()->GetDebugName());
     971             :     }
     972             :   }
     973             : 
     974     2063524 :   if (HasStackOverflow()) return Handle<BytecodeArray>();
     975     2063524 :   Handle<BytecodeArray> bytecode_array = builder()->ToBytecodeArray(isolate);
     976             : 
     977     2063531 :   if (incoming_new_target_or_generator_.is_valid()) {
     978             :     bytecode_array->set_incoming_new_target_or_generator_register(
     979      211048 :         incoming_new_target_or_generator_);
     980             :   }
     981             : 
     982     2063531 :   return bytecode_array;
     983             : }
     984             : 
     985     2063521 : void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate,
     986      106125 :                                                   Handle<Script> script) {
     987             :   // Build global declaration pair arrays.
     988     4339293 :   for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) {
     989             :     Handle<FixedArray> declarations =
     990      106125 :         globals_builder->AllocateDeclarations(info(), script, isolate);
     991      106126 :     if (declarations.is_null()) return SetStackOverflow();
     992             :     builder()->SetDeferredConstantPoolEntry(
     993      106126 :         globals_builder->constant_pool_entry(), declarations);
     994             :   }
     995             : 
     996             :   // Find or build shared function infos.
     997     6493537 :   for (std::pair<FunctionLiteral*, size_t> literal : function_literals_) {
     998             :     FunctionLiteral* expr = literal.first;
     999             :     Handle<SharedFunctionInfo> shared_info =
    1000     2366491 :         Compiler::GetSharedFunctionInfo(expr, script, isolate);
    1001     2366494 :     if (shared_info.is_null()) return SetStackOverflow();
    1002     2366494 :     builder()->SetDeferredConstantPoolEntry(literal.second, shared_info);
    1003             :   }
    1004             : 
    1005             :   // Find or build shared function infos for the native function templates.
    1006     4128784 :   for (std::pair<NativeFunctionLiteral*, size_t> literal :
    1007        1734 :        native_function_literals_) {
    1008        5202 :     NativeFunctionLiteral* expr = literal.first;
    1009             :     v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
    1010             : 
    1011             :     // Compute the function template for the native function.
    1012             :     v8::Local<v8::FunctionTemplate> info =
    1013             :         expr->extension()->GetNativeFunctionTemplate(
    1014        3468 :             v8_isolate, Utils::ToLocal(expr->name()));
    1015             :     DCHECK(!info.IsEmpty());
    1016             : 
    1017             :     Handle<SharedFunctionInfo> shared_info =
    1018             :         FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
    1019        1734 :             isolate, Utils::OpenHandle(*info), expr->name());
    1020             :     DCHECK(!shared_info.is_null());
    1021        1734 :     builder()->SetDeferredConstantPoolEntry(literal.second, shared_info);
    1022             :   }
    1023             : 
    1024             :   // Build object literal constant properties
    1025     4312390 :   for (std::pair<ObjectLiteral*, size_t> literal : object_literals_) {
    1026      185338 :     ObjectLiteral* object_literal = literal.first;
    1027      185338 :     if (object_literal->properties_count() > 0) {
    1028             :       // If constant properties is an empty fixed array, we've already added it
    1029             :       // to the constant pool when visiting the object literal.
    1030             :       Handle<ObjectBoilerplateDescription> constant_properties =
    1031             :           object_literal->GetOrBuildBoilerplateDescription(isolate);
    1032             : 
    1033             :       builder()->SetDeferredConstantPoolEntry(literal.second,
    1034      185341 :                                               constant_properties);
    1035             :     }
    1036             :   }
    1037             : 
    1038             :   // Build array literal constant elements
    1039     4267824 :   for (std::pair<ArrayLiteral*, size_t> literal : array_literals_) {
    1040             :     ArrayLiteral* array_literal = literal.first;
    1041             :     Handle<ArrayBoilerplateDescription> constant_elements =
    1042             :         array_literal->GetOrBuildBoilerplateDescription(isolate);
    1043      140770 :     builder()->SetDeferredConstantPoolEntry(literal.second, constant_elements);
    1044             :   }
    1045             : 
    1046             :   // Build class literal boilerplates.
    1047     4166488 :   for (std::pair<ClassLiteral*, size_t> literal : class_literals_) {
    1048             :     ClassLiteral* class_literal = literal.first;
    1049             :     Handle<ClassBoilerplate> class_boilerplate =
    1050       39434 :         ClassBoilerplate::BuildClassBoilerplate(isolate, class_literal);
    1051       39434 :     builder()->SetDeferredConstantPoolEntry(literal.second, class_boilerplate);
    1052             :   }
    1053             : 
    1054             :   // Build template literals.
    1055     4128772 :   for (std::pair<GetTemplateObject*, size_t> literal : template_objects_) {
    1056             :     GetTemplateObject* get_template_object = literal.first;
    1057             :     Handle<TemplateObjectDescription> description =
    1058        1718 :         get_template_object->GetOrBuildDescription(isolate);
    1059        1718 :     builder()->SetDeferredConstantPoolEntry(literal.second, description);
    1060             :   }
    1061             : }
    1062             : 
    1063     8537638 : void BytecodeGenerator::GenerateBytecode(uintptr_t stack_limit) {
    1064             :   DisallowHeapAllocation no_allocation;
    1065             :   DisallowHandleAllocation no_handles;
    1066             :   DisallowHandleDereference no_deref;
    1067             : 
    1068             :   InitializeAstVisitor(stack_limit);
    1069             : 
    1070             :   // Initialize the incoming context.
    1071     2087087 :   ContextScope incoming_context(this, closure_scope());
    1072             : 
    1073             :   // Initialize control scope.
    1074             :   ControlScopeForTopLevel control(this);
    1075             : 
    1076     2086944 :   RegisterAllocationScope register_scope(this);
    1077             : 
    1078     2087089 :   AllocateTopLevelRegisters();
    1079             : 
    1080     4174178 :   if (info()->literal()->CanSuspend()) {
    1081        9267 :     BuildGeneratorPrologue();
    1082             :   }
    1083             : 
    1084     2087088 :   if (closure_scope()->NeedsContext()) {
    1085             :     // Push a new inner context scope for the function.
    1086      189290 :     BuildNewLocalActivationContext();
    1087      189287 :     ContextScope local_function_context(this, closure_scope());
    1088      189290 :     BuildLocalActivationContextInitialization();
    1089      189286 :     GenerateBytecodeBody();
    1090             :   } else {
    1091     1897798 :     GenerateBytecodeBody();
    1092             :   }
    1093             : 
    1094             :   // Check that we are not falling off the end.
    1095     2087013 :   DCHECK(!builder()->RequiresImplicitReturn());
    1096     2086962 : }
    1097             : 
    1098    20887126 : void BytecodeGenerator::GenerateBytecodeBody() {
    1099             :   // Build the arguments object if it is used.
    1100     2087075 :   VisitArgumentsObject(closure_scope()->arguments());
    1101             : 
    1102             :   // Build rest arguments array if it is used.
    1103             :   Variable* rest_parameter = closure_scope()->rest_parameter();
    1104     2087080 :   VisitRestArgumentsArray(rest_parameter);
    1105             : 
    1106             :   // Build assignment to the function name or {.this_function}
    1107             :   // variables if used.
    1108     2087079 :   VisitThisFunctionVariable(closure_scope()->function_var());
    1109     2087077 :   VisitThisFunctionVariable(closure_scope()->this_function_var());
    1110             : 
    1111             :   // Build assignment to {new.target} variable if it is used.
    1112     2087078 :   VisitNewTargetVariable(closure_scope()->new_target_var());
    1113             : 
    1114             :   // Create a generator object if necessary and initialize the
    1115             :   // {.generator_object} variable.
    1116     4174150 :   if (IsResumableFunction(info()->literal()->kind())) {
    1117       10941 :     BuildGeneratorObjectVariableInitialization();
    1118             :   }
    1119             : 
    1120             :   // Emit tracing call if requested to do so.
    1121     2087075 :   if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter);
    1122             : 
    1123             :   // Emit type profile call.
    1124     2087075 :   if (info()->collect_type_profile()) {
    1125          68 :     feedback_spec()->AddTypeProfileSlot();
    1126          68 :     int num_parameters = closure_scope()->num_parameters();
    1127         164 :     for (int i = 0; i < num_parameters; i++) {
    1128          96 :       Register parameter(builder()->Parameter(i));
    1129          96 :       builder()->LoadAccumulatorWithRegister(parameter).CollectTypeProfile(
    1130         192 :           closure_scope()->parameter(i)->initializer_position());
    1131             :     }
    1132             :   }
    1133             : 
    1134             :   // Visit declarations within the function scope.
    1135     2087075 :   VisitDeclarations(closure_scope()->declarations());
    1136             : 
    1137             :   // Emit initializing assignments for module namespace imports (if any).
    1138     2087067 :   VisitModuleNamespaceImports();
    1139             : 
    1140             :   // Perform a stack-check before the body.
    1141     2087071 :   builder()->StackCheck(info()->literal()->start_position());
    1142             : 
    1143             :   // The derived constructor case is handled in VisitCallSuper.
    1144     2103279 :   if (IsBaseConstructor(function_kind()) &&
    1145       16180 :       info()->literal()->requires_instance_members_initializer()) {
    1146             :     BuildInstanceMemberInitialization(Register::function_closure(),
    1147         530 :                                       builder()->Receiver());
    1148             :   }
    1149             : 
    1150             :   // Visit statements in the function body.
    1151     2087099 :   VisitStatements(info()->literal()->body());
    1152             : 
    1153             :   // Emit an implicit return instruction in case control flow can fall off the
    1154             :   // end of the function without an explicit return being present on all paths.
    1155     2087014 :   if (builder()->RequiresImplicitReturn()) {
    1156      378801 :     builder()->LoadUndefined();
    1157      378797 :     BuildReturn();
    1158             :   }
    1159     2087014 : }
    1160             : 
    1161     4174174 : void BytecodeGenerator::AllocateTopLevelRegisters() {
    1162     4174174 :   if (IsResumableFunction(info()->literal()->kind())) {
    1163             :     // Either directly use generator_object_var or allocate a new register for
    1164             :     // the incoming generator object.
    1165       10941 :     Variable* generator_object_var = closure_scope()->generator_object_var();
    1166       10941 :     if (generator_object_var->location() == VariableLocation::LOCAL) {
    1167             :       incoming_new_target_or_generator_ =
    1168       10941 :           GetRegisterForLocalVariable(generator_object_var);
    1169             :     } else {
    1170           0 :       incoming_new_target_or_generator_ = register_allocator()->NewRegister();
    1171             :     }
    1172     2076150 :   } else if (closure_scope()->new_target_var()) {
    1173             :     // Either directly use new_target_var or allocate a new register for
    1174             :     // the incoming new target object.
    1175       99650 :     Variable* new_target_var = closure_scope()->new_target_var();
    1176       99650 :     if (new_target_var->location() == VariableLocation::LOCAL) {
    1177             :       incoming_new_target_or_generator_ =
    1178        5449 :           GetRegisterForLocalVariable(new_target_var);
    1179             :     } else {
    1180       94200 :       incoming_new_target_or_generator_ = register_allocator()->NewRegister();
    1181             :     }
    1182             :   }
    1183     2087090 : }
    1184             : 
    1185        9267 : void BytecodeGenerator::BuildGeneratorPrologue() {
    1186             :   DCHECK_GT(info()->literal()->suspend_count(), 0);
    1187             :   DCHECK(generator_object().is_valid());
    1188             :   generator_jump_table_ =
    1189        9267 :       builder()->AllocateJumpTable(info()->literal()->suspend_count(), 0);
    1190             : 
    1191             :   // If the generator is not undefined, this is a resume, so perform state
    1192             :   // dispatch.
    1193        9267 :   builder()->SwitchOnGeneratorState(generator_object(), generator_jump_table_);
    1194             : 
    1195             :   // Otherwise, fall-through to the ordinary function prologue, after which we
    1196             :   // will run into the generator object creation and other extra code inserted
    1197             :   // by the parser.
    1198        9267 : }
    1199             : 
    1200    10211437 : void BytecodeGenerator::VisitBlock(Block* stmt) {
    1201             :   // Visit declarations and statements.
    1202             :   CurrentScope current_scope(this, stmt->scope());
    1203     5282613 :   if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) {
    1204       24227 :     BuildNewLocalBlockContext(stmt->scope());
    1205       24227 :     ContextScope scope(this, stmt->scope());
    1206       24226 :     VisitBlockDeclarationsAndStatements(stmt);
    1207             :   } else {
    1208     5069378 :     VisitBlockDeclarationsAndStatements(stmt);
    1209             :   }
    1210     5093674 : }
    1211             : 
    1212    10187172 : void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) {
    1213     5093586 :   BlockBuilder block_builder(builder(), block_coverage_builder_, stmt);
    1214             :   ControlScopeForBreakable execution_control(this, stmt, &block_builder);
    1215     5093586 :   if (stmt->scope() != nullptr) {
    1216      189007 :     VisitDeclarations(stmt->scope()->declarations());
    1217             :   }
    1218     5093586 :   VisitStatements(stmt->statements());
    1219     5093662 : }
    1220             : 
    1221     8672495 : void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
    1222     8957646 :   Variable* variable = decl->var();
    1223             :   // Unused variables don't need to be visited.
    1224    13480738 :   if (!variable->is_used()) return;
    1225             : 
    1226     6321017 :   switch (variable->location()) {
    1227             :     case VariableLocation::UNALLOCATED: {
    1228             :       DCHECK(!variable->binding_needs_init());
    1229             :       FeedbackSlot slot =
    1230     1259024 :           GetCachedLoadGlobalICSlot(NOT_INSIDE_TYPEOF, variable);
    1231             :       globals_builder()->AddUndefinedDeclaration(variable->raw_name(), slot);
    1232             :       break;
    1233             :     }
    1234             :     case VariableLocation::LOCAL:
    1235     1034169 :       if (variable->binding_needs_init()) {
    1236        3266 :         Register destination(builder()->Local(variable->index()));
    1237        3266 :         builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
    1238             :       }
    1239             :       break;
    1240             :     case VariableLocation::PARAMETER:
    1241     2283442 :       if (variable->binding_needs_init()) {
    1242           0 :         Register destination(builder()->Parameter(variable->index()));
    1243           0 :         builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
    1244             :       }
    1245             :       break;
    1246             :     case VariableLocation::CONTEXT:
    1247     1444827 :       if (variable->binding_needs_init()) {
    1248             :         DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
    1249      673088 :         builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(),
    1250      673082 :                                                   variable->index(), 0);
    1251             :       }
    1252             :       break;
    1253             :     case VariableLocation::LOOKUP: {
    1254             :       DCHECK_EQ(VariableMode::kDynamic, variable->mode());
    1255             :       DCHECK(!variable->binding_needs_init());
    1256             : 
    1257      281885 :       Register name = register_allocator()->NewRegister();
    1258             : 
    1259             :       builder()
    1260      281885 :           ->LoadLiteral(variable->raw_name())
    1261      281885 :           .StoreAccumulatorInRegister(name)
    1262      281885 :           .CallRuntime(Runtime::kDeclareEvalVar, name);
    1263             :       break;
    1264             :     }
    1265             :     case VariableLocation::MODULE:
    1266       17745 :       if (variable->IsExport() && variable->binding_needs_init()) {
    1267       17063 :         builder()->LoadTheHole();
    1268       17063 :         BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
    1269             :       }
    1270             :       // Nothing to do for imports.
    1271             :       break;
    1272             :   }
    1273             : }
    1274             : 
    1275     2107332 : void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
    1276     1077079 :   Variable* variable = decl->var();
    1277             :   DCHECK(variable->mode() == VariableMode::kLet ||
    1278             :          variable->mode() == VariableMode::kVar ||
    1279             :          variable->mode() == VariableMode::kDynamic);
    1280             :   // Unused variables don't need to be visited.
    1281     1106656 :   if (!variable->is_used()) return;
    1282             : 
    1283      547780 :   switch (variable->location()) {
    1284             :     case VariableLocation::UNALLOCATED: {
    1285             :       FeedbackSlot slot =
    1286      244778 :           GetCachedLoadGlobalICSlot(NOT_INSIDE_TYPEOF, variable);
    1287      244806 :       FeedbackSlot literal_slot = GetCachedCreateClosureSlot(decl->fun());
    1288             :       globals_builder()->AddFunctionDeclaration(variable->raw_name(), slot,
    1289             :                                                 literal_slot, decl->fun());
    1290      244819 :       AddToEagerLiteralsIfEager(decl->fun());
    1291             :       break;
    1292             :     }
    1293             :     case VariableLocation::PARAMETER:
    1294             :     case VariableLocation::LOCAL: {
    1295       23672 :       VisitFunctionLiteral(decl->fun());
    1296       23676 :       BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
    1297       23676 :       break;
    1298             :     }
    1299             :     case VariableLocation::CONTEXT: {
    1300             :       DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
    1301      271785 :       VisitFunctionLiteral(decl->fun());
    1302             :       builder()->StoreContextSlot(execution_context()->reg(), variable->index(),
    1303      271786 :                                   0);
    1304      271786 :       break;
    1305             :     }
    1306             :     case VariableLocation::LOOKUP: {
    1307        7177 :       RegisterList args = register_allocator()->NewRegisterList(2);
    1308             :       builder()
    1309        7177 :           ->LoadLiteral(variable->raw_name())
    1310        7177 :           .StoreAccumulatorInRegister(args[0]);
    1311        7177 :       VisitFunctionLiteral(decl->fun());
    1312        7177 :       builder()->StoreAccumulatorInRegister(args[1]).CallRuntime(
    1313        7177 :           Runtime::kDeclareEvalFunction, args);
    1314             :       break;
    1315             :     }
    1316             :     case VariableLocation::MODULE:
    1317             :       DCHECK_EQ(variable->mode(), VariableMode::kLet);
    1318             :       DCHECK(variable->IsExport());
    1319         370 :       VisitForAccumulatorValue(decl->fun());
    1320         370 :       BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
    1321         370 :       break;
    1322             :   }
    1323             :   DCHECK_IMPLIES(decl->fun()->ShouldEagerCompile(),
    1324             :                  IsInEagerLiterals(decl->fun(), *eager_inner_literals_));
    1325             : }
    1326             : 
    1327     2088440 : void BytecodeGenerator::VisitModuleNamespaceImports() {
    1328     4172894 :   if (!closure_scope()->is_module_scope()) return;
    1329             : 
    1330             :   RegisterAllocationScope register_scope(this);
    1331        1242 :   Register module_request = register_allocator()->NewRegister();
    1332             : 
    1333        1242 :   ModuleDescriptor* descriptor = closure_scope()->AsModuleScope()->module();
    1334        2614 :   for (auto entry : descriptor->namespace_imports()) {
    1335             :     builder()
    1336         260 :         ->LoadLiteral(Smi::FromInt(entry->module_request))
    1337         130 :         .StoreAccumulatorInRegister(module_request)
    1338         130 :         .CallRuntime(Runtime::kGetModuleNamespace, module_request);
    1339         130 :     Variable* var = closure_scope()->LookupInModule(entry->local_name);
    1340         130 :     BuildVariableAssignment(var, Token::INIT, HoleCheckMode::kElided);
    1341        1242 :   }
    1342             : }
    1343             : 
    1344     5218910 : void BytecodeGenerator::VisitDeclarations(Declaration::List* declarations) {
    1345             :   RegisterAllocationScope register_scope(this);
    1346             :   DCHECK(globals_builder()->empty());
    1347    11929669 :   for (Declaration* decl : *declarations) {
    1348             :     RegisterAllocationScope register_scope(this);
    1349     7293588 :     Visit(decl);
    1350     7293699 :   }
    1351     4519565 :   if (globals_builder()->empty()) return;
    1352             : 
    1353             :   globals_builder()->set_constant_pool_entry(
    1354      116569 :       builder()->AllocateDeferredConstantPoolEntry());
    1355      116567 :   int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
    1356      116567 :                       DeclareGlobalsNativeFlag::encode(info()->is_native());
    1357             : 
    1358             :   // Emit code to declare globals.
    1359      116567 :   RegisterList args = register_allocator()->NewRegisterList(3);
    1360             :   builder()
    1361      116563 :       ->LoadConstantPoolEntry(globals_builder()->constant_pool_entry())
    1362      116565 :       .StoreAccumulatorInRegister(args[0])
    1363      116558 :       .LoadLiteral(Smi::FromInt(encoded_flags))
    1364      116551 :       .StoreAccumulatorInRegister(args[1])
    1365      233120 :       .MoveRegister(Register::function_closure(), args[2])
    1366      116547 :       .CallRuntime(Runtime::kDeclareGlobals, args);
    1367             : 
    1368             :   // Push and reset globals builder.
    1369      233132 :   global_declarations_.push_back(globals_builder());
    1370      116566 :   globals_builder_ = new (zone()) GlobalDeclarationsBuilder(zone());
    1371             : }
    1372             : 
    1373     7260809 : void BytecodeGenerator::VisitStatements(
    1374    22225242 :     const ZonePtrList<Statement>* statements) {
    1375    44450484 :   for (int i = 0; i < statements->length(); i++) {
    1376             :     // Allocate an outer register allocations scope for the statement.
    1377             :     RegisterAllocationScope allocation_scope(this);
    1378    16886635 :     Statement* stmt = statements->at(i);
    1379    16886635 :     Visit(stmt);
    1380    16886416 :     if (builder()->RemainderOfBlockIsDead()) break;
    1381    14964616 :   }
    1382     7260426 : }
    1383             : 
    1384    19986168 : void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
    1385             :   builder()->SetStatementPosition(stmt);
    1386     9993084 :   VisitForEffect(stmt->expression());
    1387     9992701 : }
    1388             : 
    1389           0 : void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {}
    1390             : 
    1391     3433237 : void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
    1392             :   ConditionalControlFlowBuilder conditional_builder(
    1393      567151 :       builder(), block_coverage_builder_, stmt);
    1394             :   builder()->SetStatementPosition(stmt);
    1395             : 
    1396      567152 :   if (stmt->condition()->ToBooleanIsTrue()) {
    1397             :     // Generate then block unconditionally as always true.
    1398         429 :     conditional_builder.Then();
    1399         429 :     Visit(stmt->then_statement());
    1400      566725 :   } else if (stmt->condition()->ToBooleanIsFalse()) {
    1401             :     // Generate else block unconditionally if it exists.
    1402        8301 :     if (stmt->HasElseStatement()) {
    1403        7043 :       conditional_builder.Else();
    1404        7043 :       Visit(stmt->else_statement());
    1405             :     }
    1406             :   } else {
    1407             :     // TODO(oth): If then statement is BreakStatement or
    1408             :     // ContinueStatement we can reduce number of generated
    1409             :     // jump/jump_ifs here. See BasicLoops test.
    1410             :     VisitForTest(stmt->condition(), conditional_builder.then_labels(),
    1411      558425 :                  conditional_builder.else_labels(), TestFallthrough::kThen);
    1412             : 
    1413      558430 :     conditional_builder.Then();
    1414      558432 :     Visit(stmt->then_statement());
    1415             : 
    1416      558433 :     if (stmt->HasElseStatement()) {
    1417       41147 :       conditional_builder.JumpToEnd();
    1418       41147 :       conditional_builder.Else();
    1419       41146 :       Visit(stmt->else_statement());
    1420             :     }
    1421      567163 :   }
    1422      567151 : }
    1423             : 
    1424        3086 : void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
    1425        3086 :     SloppyBlockFunctionStatement* stmt) {
    1426        3086 :   Visit(stmt->statement());
    1427        3088 : }
    1428             : 
    1429        7082 : void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
    1430             :   AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
    1431             :   builder()->SetStatementPosition(stmt);
    1432             :   execution_control()->Continue(stmt->target());
    1433        3541 : }
    1434             : 
    1435       94330 : void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
    1436             :   AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
    1437             :   builder()->SetStatementPosition(stmt);
    1438             :   execution_control()->Break(stmt->target());
    1439       47167 : }
    1440             : 
    1441     6159845 : void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
    1442             :   AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
    1443             :   builder()->SetStatementPosition(stmt);
    1444     2053239 :   VisitForAccumulatorValue(stmt->expression());
    1445     2053395 :   if (stmt->is_async_return()) {
    1446             :     execution_control()->AsyncReturnAccumulator(stmt->end_position());
    1447             :   } else {
    1448             :     execution_control()->ReturnAccumulator(stmt->end_position());
    1449             :   }
    1450     2053374 : }
    1451             : 
    1452       11819 : void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
    1453             :   builder()->SetStatementPosition(stmt);
    1454        2954 :   VisitForAccumulatorValue(stmt->expression());
    1455        2956 :   BuildNewLocalWithContext(stmt->scope());
    1456        2955 :   VisitInScope(stmt->statement(), stmt->scope());
    1457        2956 : }
    1458             : 
    1459       21224 : void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
    1460             :   // We need this scope because we visit for register values. We have to
    1461             :   // maintain a execution result scope where registers can be allocated.
    1462      202634 :   ZonePtrList<CaseClause>* clauses = stmt->cases();
    1463             :   SwitchBuilder switch_builder(builder(), block_coverage_builder_, stmt,
    1464       10612 :                                clauses->length());
    1465             :   ControlScopeForBreakable scope(this, stmt, &switch_builder);
    1466             :   int default_index = -1;
    1467             : 
    1468             :   builder()->SetStatementPosition(stmt);
    1469             : 
    1470             :   // Keep the switch value in a register until a case matches.
    1471       10612 :   Register tag = VisitForRegisterValue(stmt->tag());
    1472             :   FeedbackSlot slot = clauses->length() > 0
    1473       10584 :                           ? feedback_spec()->AddCompareICSlot()
    1474       10612 :                           : FeedbackSlot::Invalid();
    1475             : 
    1476             :   // Iterate over all cases and create nodes for label comparison.
    1477      181410 :   for (int i = 0; i < clauses->length(); i++) {
    1478       80093 :     CaseClause* clause = clauses->at(i);
    1479             : 
    1480             :     // The default is not a test, remember index.
    1481       80093 :     if (clause->is_default()) {
    1482             :       default_index = i;
    1483             :       continue;
    1484             :     }
    1485             : 
    1486             :     // Perform label comparison as if via '===' with tag.
    1487       72643 :     VisitForAccumulatorValue(clause->label());
    1488             :     builder()->CompareOperation(Token::Value::EQ_STRICT, tag,
    1489       72643 :                                 feedback_index(slot));
    1490       72643 :     switch_builder.Case(ToBooleanMode::kAlreadyBoolean, i);
    1491             :   }
    1492             : 
    1493       10612 :   if (default_index >= 0) {
    1494             :     // Emit default jump if there is a default case.
    1495        7450 :     switch_builder.DefaultAt(default_index);
    1496             :   } else {
    1497             :     // Otherwise if we have reached here none of the cases matched, so jump to
    1498             :     // the end.
    1499             :     switch_builder.Break();
    1500             :   }
    1501             : 
    1502             :   // Iterate over all cases and create the case bodies.
    1503      170798 :   for (int i = 0; i < clauses->length(); i++) {
    1504       80093 :     CaseClause* clause = clauses->at(i);
    1505       80093 :     switch_builder.SetCaseTarget(i, clause);
    1506       80093 :     VisitStatements(clause->statements());
    1507       10612 :   }
    1508       10612 : }
    1509             : 
    1510             : template <typename TryBodyFunc, typename CatchBodyFunc>
    1511      107075 : void BytecodeGenerator::BuildTryCatch(
    1512             :     TryBodyFunc try_body_func, CatchBodyFunc catch_body_func,
    1513             :     HandlerTable::CatchPrediction catch_prediction,
    1514             :     TryCatchStatement* stmt_for_coverage) {
    1515             :   TryCatchBuilder try_control_builder(
    1516             :       builder(),
    1517             :       stmt_for_coverage == nullptr ? nullptr : block_coverage_builder_,
    1518      107075 :       stmt_for_coverage, catch_prediction);
    1519             : 
    1520             :   // Preserve the context in a dedicated register, so that it can be restored
    1521             :   // when the handler is entered by the stack-unwinding machinery.
    1522             :   // TODO(mstarzinger): Be smarter about register allocation.
    1523      107081 :   Register context = register_allocator()->NewRegister();
    1524      107088 :   builder()->MoveRegister(Register::current_context(), context);
    1525             : 
    1526             :   // Evaluate the try-block inside a control scope. This simulates a handler
    1527             :   // that is intercepting 'throw' control commands.
    1528      107089 :   try_control_builder.BeginTry(context);
    1529             :   {
    1530             :     ControlScopeForTryCatch scope(this, &try_control_builder);
    1531      107087 :     try_body_func();
    1532             :   }
    1533      107089 :   try_control_builder.EndTry();
    1534             : 
    1535      107074 :   catch_body_func(context);
    1536             : 
    1537      107091 :   try_control_builder.EndCatch();
    1538      107068 : }
    1539             : 
    1540             : template <typename TryBodyFunc, typename FinallyBodyFunc>
    1541       41598 : void BytecodeGenerator::BuildTryFinally(
    1542             :     TryBodyFunc try_body_func, FinallyBodyFunc finally_body_func,
    1543             :     HandlerTable::CatchPrediction catch_prediction,
    1544             :     TryFinallyStatement* stmt_for_coverage) {
    1545             :   // We can't know whether the finally block will override ("catch") an
    1546             :   // exception thrown in the try block, so we just adopt the outer prediction.
    1547             :   TryFinallyBuilder try_control_builder(
    1548             :       builder(),
    1549             :       stmt_for_coverage == nullptr ? nullptr : block_coverage_builder_,
    1550       41598 :       stmt_for_coverage, catch_prediction);
    1551             : 
    1552             :   // We keep a record of all paths that enter the finally-block to be able to
    1553             :   // dispatch to the correct continuation point after the statements in the
    1554             :   // finally-block have been evaluated.
    1555             :   //
    1556             :   // The try-finally construct can enter the finally-block in three ways:
    1557             :   // 1. By exiting the try-block normally, falling through at the end.
    1558             :   // 2. By exiting the try-block with a function-local control flow transfer
    1559             :   //    (i.e. through break/continue/return statements).
    1560             :   // 3. By exiting the try-block with a thrown exception.
    1561             :   //
    1562             :   // The result register semantics depend on how the block was entered:
    1563             :   //  - ReturnStatement: It represents the return value being returned.
    1564             :   //  - ThrowStatement: It represents the exception being thrown.
    1565             :   //  - BreakStatement/ContinueStatement: Undefined and not used.
    1566             :   //  - Falling through into finally-block: Undefined and not used.
    1567       41600 :   Register token = register_allocator()->NewRegister();
    1568       41605 :   Register result = register_allocator()->NewRegister();
    1569       41599 :   ControlScope::DeferredCommands commands(this, token, result);
    1570             : 
    1571             :   // Preserve the context in a dedicated register, so that it can be restored
    1572             :   // when the handler is entered by the stack-unwinding machinery.
    1573             :   // TODO(mstarzinger): Be smarter about register allocation.
    1574       41599 :   Register context = register_allocator()->NewRegister();
    1575       41604 :   builder()->MoveRegister(Register::current_context(), context);
    1576             : 
    1577             :   // Evaluate the try-block inside a control scope. This simulates a handler
    1578             :   // that is intercepting all control commands.
    1579       41602 :   try_control_builder.BeginTry(context);
    1580             :   {
    1581             :     ControlScopeForTryFinally scope(this, &try_control_builder, &commands);
    1582       38173 :     try_body_func();
    1583             :   }
    1584       41601 :   try_control_builder.EndTry();
    1585             : 
    1586             :   // Record fall-through and exception cases.
    1587       41605 :   commands.RecordFallThroughPath();
    1588       41602 :   try_control_builder.LeaveTry();
    1589       41605 :   try_control_builder.BeginHandler();
    1590             :   commands.RecordHandlerReThrowPath();
    1591             : 
    1592             :   // Pending message object is saved on entry.
    1593       41605 :   try_control_builder.BeginFinally();
    1594       41600 :   Register message = context;  // Reuse register.
    1595             : 
    1596             :   // Clear message object as we enter the finally block.
    1597       41600 :   builder()->LoadTheHole().SetPendingMessage().StoreAccumulatorInRegister(
    1598             :       message);
    1599             : 
    1600             :   // Evaluate the finally-block.
    1601             :   finally_body_func(token);
    1602       41601 :   try_control_builder.EndFinally();
    1603             : 
    1604             :   // Pending message object is restored on exit.
    1605       41601 :   builder()->LoadAccumulatorWithRegister(message).SetPendingMessage();
    1606             : 
    1607             :   // Dynamic dispatch after the finally-block.
    1608       41604 :   commands.ApplyDeferredCommands();
    1609       41600 : }
    1610             : 
    1611      518946 : void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
    1612             :                                            LoopBuilder* loop_builder) {
    1613      259453 :   loop_builder->LoopBody();
    1614             :   ControlScopeForIteration execution_control(this, stmt, loop_builder);
    1615      259472 :   builder()->StackCheck(stmt->position());
    1616      259493 :   Visit(stmt->body());
    1617      259482 :   loop_builder->BindContinueTarget();
    1618      259470 : }
    1619             : 
    1620        4970 : void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
    1621        1169 :   LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
    1622        1169 :   if (stmt->cond()->ToBooleanIsFalse()) {
    1623         346 :     VisitIterationBody(stmt, &loop_builder);
    1624         823 :   } else if (stmt->cond()->ToBooleanIsTrue()) {
    1625         220 :     loop_builder.LoopHeader();
    1626         220 :     VisitIterationBody(stmt, &loop_builder);
    1627         220 :     loop_builder.JumpToHeader(loop_depth_);
    1628             :   } else {
    1629         603 :     loop_builder.LoopHeader();
    1630         603 :     VisitIterationBody(stmt, &loop_builder);
    1631             :     builder()->SetExpressionAsStatementPosition(stmt->cond());
    1632             :     BytecodeLabels loop_backbranch(zone());
    1633             :     VisitForTest(stmt->cond(), &loop_backbranch, loop_builder.break_labels(),
    1634         603 :                  TestFallthrough::kThen);
    1635         603 :     loop_backbranch.Bind(builder());
    1636         603 :     loop_builder.JumpToHeader(loop_depth_);
    1637        1170 :   }
    1638        1170 : }
    1639             : 
    1640       74416 : void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
    1641       13569 :   LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
    1642             : 
    1643       13569 :   if (stmt->cond()->ToBooleanIsFalse()) {
    1644             :     // If the condition is false there is no need to generate the loop.
    1645         111 :     return;
    1646             :   }
    1647             : 
    1648       13459 :   loop_builder.LoopHeader();
    1649       13459 :   if (!stmt->cond()->ToBooleanIsTrue()) {
    1650             :     builder()->SetExpressionAsStatementPosition(stmt->cond());
    1651             :     BytecodeLabels loop_body(zone());
    1652             :     VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(),
    1653       11273 :                  TestFallthrough::kThen);
    1654       11273 :     loop_body.Bind(builder());
    1655             :   }
    1656       13458 :   VisitIterationBody(stmt, &loop_builder);
    1657       13459 :   loop_builder.JumpToHeader(loop_depth_);
    1658             : }
    1659             : 
    1660     1812397 : void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
    1661      220105 :   LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
    1662             : 
    1663      220102 :   if (stmt->init() != nullptr) {
    1664      160105 :     Visit(stmt->init());
    1665             :   }
    1666      220121 :   if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
    1667             :     // If the condition is known to be false there is no need to generate
    1668             :     // body, next or condition blocks. Init block should be generated.
    1669       15467 :     return;
    1670             :   }
    1671             : 
    1672      204644 :   loop_builder.LoopHeader();
    1673      204650 :   if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
    1674             :     builder()->SetExpressionAsStatementPosition(stmt->cond());
    1675             :     BytecodeLabels loop_body(zone());
    1676             :     VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(),
    1677      187751 :                  TestFallthrough::kThen);
    1678      187761 :     loop_body.Bind(builder());
    1679             :   }
    1680      204661 :   VisitIterationBody(stmt, &loop_builder);
    1681      204650 :   if (stmt->next() != nullptr) {
    1682             :     builder()->SetStatementPosition(stmt->next());
    1683      179516 :     Visit(stmt->next());
    1684             :   }
    1685      204645 :   loop_builder.JumpToHeader(loop_depth_);
    1686             : }
    1687             : 
    1688        4787 : void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
    1689       33258 :   if (stmt->subject()->IsNullLiteral() ||
    1690        4762 :       stmt->subject()->IsUndefinedLiteral()) {
    1691             :     // ForIn generates lots of code, skip if it wouldn't produce any effects.
    1692          51 :     return;
    1693             :   }
    1694             : 
    1695             :   BytecodeLabel subject_null_label, subject_undefined_label;
    1696        4741 :   FeedbackSlot slot = feedback_spec()->AddForInSlot();
    1697             : 
    1698             :   // Prepare the state for executing ForIn.
    1699             :   builder()->SetExpressionAsStatementPosition(stmt->subject());
    1700        4741 :   VisitForAccumulatorValue(stmt->subject());
    1701        4742 :   builder()->JumpIfUndefined(&subject_undefined_label);
    1702        4740 :   builder()->JumpIfNull(&subject_null_label);
    1703        4741 :   Register receiver = register_allocator()->NewRegister();
    1704        4741 :   builder()->ToObject(receiver);
    1705             : 
    1706             :   // Used as kRegTriple and kRegPair in ForInPrepare and ForInNext.
    1707        4741 :   RegisterList triple = register_allocator()->NewRegisterList(3);
    1708        4738 :   Register cache_length = triple[2];
    1709        4738 :   builder()->ForInEnumerate(receiver);
    1710        4742 :   builder()->ForInPrepare(triple, feedback_index(slot));
    1711             : 
    1712             :   // Set up loop counter
    1713        4742 :   Register index = register_allocator()->NewRegister();
    1714        4742 :   builder()->LoadLiteral(Smi::zero());
    1715        4742 :   builder()->StoreAccumulatorInRegister(index);
    1716             : 
    1717             :   // The loop
    1718             :   {
    1719        4742 :     LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
    1720        4739 :     loop_builder.LoopHeader();
    1721             :     builder()->SetExpressionAsStatementPosition(stmt->each());
    1722        4741 :     builder()->ForInContinue(index, cache_length);
    1723             :     loop_builder.BreakIfFalse(ToBooleanMode::kAlreadyBoolean);
    1724             :     builder()->ForInNext(receiver, index, triple.Truncate(2),
    1725        4742 :                          feedback_index(slot));
    1726             :     loop_builder.ContinueIfUndefined();
    1727             : 
    1728             :     // Assign accumulator value to the 'each' target.
    1729             :     {
    1730             :       EffectResultScope scope(this);
    1731             :       // Make sure to preserve the accumulator across the PrepareAssignmentLhs
    1732             :       // call.
    1733             :       AssignmentLhsData lhs_data = PrepareAssignmentLhs(
    1734        4742 :           stmt->each(), AccumulatorPreservingMode::kPreserve);
    1735             :       builder()->SetExpressionPosition(stmt->each());
    1736        4741 :       BuildAssignment(lhs_data, Token::ASSIGN, LookupHoistingMode::kNormal);
    1737             :     }
    1738             : 
    1739        4739 :     VisitIterationBody(stmt, &loop_builder);
    1740        4738 :     builder()->ForInStep(index);
    1741        4741 :     builder()->StoreAccumulatorInRegister(index);
    1742        4742 :     loop_builder.JumpToHeader(loop_depth_);
    1743             :   }
    1744        4742 :   builder()->Bind(&subject_null_label);
    1745        4741 :   builder()->Bind(&subject_undefined_label);
    1746             : }
    1747             : 
    1748             : // Desugar a for-of statement into an application of the iteration protocol.
    1749             : //
    1750             : // for (EACH of SUBJECT) BODY
    1751             : //
    1752             : //   becomes
    1753             : //
    1754             : // iterator = %GetIterator(SUBJECT)
    1755             : // try {
    1756             : //
    1757             : //   loop {
    1758             : //     // Make sure we are considered 'done' if .next(), .done or .value fail.
    1759             : //     done = true
    1760             : //     value = iterator.next()
    1761             : //     if (value.done) break;
    1762             : //     value = value.value
    1763             : //     done = false
    1764             : //
    1765             : //     EACH = value
    1766             : //     BODY
    1767             : //   }
    1768             : //   done = true
    1769             : //
    1770             : // } catch(e) {
    1771             : //   iteration_continuation = RETHROW
    1772             : // } finally {
    1773             : //   %FinalizeIteration(iterator, done, iteration_continuation)
    1774             : // }
    1775       35458 : void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
    1776             :   EffectResultScope effect_scope(this);
    1777             : 
    1778      106376 :   builder()->SetExpressionAsStatementPosition(stmt->subject());
    1779       35458 :   VisitForAccumulatorValue(stmt->subject());
    1780             : 
    1781             :   // Store the iterator in a dedicated register so that it can be closed on
    1782             :   // exit, and the 'done' value in a dedicated register so that it can be
    1783             :   // changed and accessed independently of the iteration result.
    1784       70920 :   IteratorRecord iterator = BuildGetIteratorRecord(stmt->type());
    1785       35460 :   Register done = register_allocator()->NewRegister();
    1786       35457 :   builder()->LoadFalse();
    1787       35459 :   builder()->StoreAccumulatorInRegister(done);
    1788             : 
    1789             :   BuildTryFinally(
    1790             :       // Try block.
    1791       35457 :       [&]() {
    1792      106376 :         Register next_result = register_allocator()->NewRegister();
    1793             : 
    1794       35460 :         LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
    1795       35458 :         loop_builder.LoopHeader();
    1796             : 
    1797       35456 :         builder()->LoadTrue().StoreAccumulatorInRegister(done);
    1798             : 
    1799             :         // Call the iterator's .next() method. Break from the loop if the `done`
    1800             :         // property is truthy, otherwise load the value from the iterator result
    1801             :         // and append the argument.
    1802       70920 :         builder()->SetExpressionAsStatementPosition(stmt->each());
    1803       35460 :         BuildIteratorNext(iterator, next_result);
    1804             :         builder()->LoadNamedProperty(
    1805             :             next_result, ast_string_constants()->done_string(),
    1806      141840 :             feedback_index(feedback_spec()->AddLoadICSlot()));
    1807             :         loop_builder.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
    1808             : 
    1809             :         builder()
    1810             :             // value = value.value
    1811             :             ->LoadNamedProperty(
    1812             :                 next_result, ast_string_constants()->value_string(),
    1813      141838 :                 feedback_index(feedback_spec()->AddLoadICSlot()));
    1814             :         // done = false, before the assignment to each happens, so that done is
    1815             :         // false if the assignment throws.
    1816             :         builder()
    1817       35459 :             ->StoreAccumulatorInRegister(next_result)
    1818       35460 :             .LoadFalse()
    1819       70919 :             .StoreAccumulatorInRegister(done);
    1820             : 
    1821             :         // Assign to the 'each' target.
    1822       70920 :         AssignmentLhsData lhs_data = PrepareAssignmentLhs(stmt->each());
    1823       35460 :         builder()->LoadAccumulatorWithRegister(next_result);
    1824       35460 :         BuildAssignment(lhs_data, Token::ASSIGN, LookupHoistingMode::kNormal);
    1825             : 
    1826       35460 :         VisitIterationBody(stmt, &loop_builder);
    1827             : 
    1828       35454 :         loop_builder.JumpToHeader(loop_depth_);
    1829       35459 :       },
    1830             :       // Finally block.
    1831             :       [&](Register iteration_continuation_token) {
    1832             :         // Finish the iteration in the finally block.
    1833       35459 :         BuildFinalizeIteration(iterator, done, iteration_continuation_token);
    1834             :       },
    1835       35460 :       HandlerTable::UNCAUGHT);
    1836       35460 : }
    1837             : 
    1838       68904 : void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
    1839             :   // Update catch prediction tracking. The updated catch_prediction value lasts
    1840             :   // until the end of the try_block in the AST node, and does not apply to the
    1841             :   // catch_block.
    1842       68904 :   HandlerTable::CatchPrediction outer_catch_prediction = catch_prediction();
    1843       68904 :   set_catch_prediction(stmt->GetCatchPrediction(outer_catch_prediction));
    1844             : 
    1845             :   BuildTryCatch(
    1846             :       // Try body.
    1847       68906 :       [&]() {
    1848       68906 :         Visit(stmt->try_block());
    1849       68912 :         set_catch_prediction(outer_catch_prediction);
    1850       68912 :       },
    1851             :       // Catch body.
    1852       68902 :       [&](Register context) {
    1853      275632 :         if (stmt->scope()) {
    1854             :           // Create a catch scope that binds the exception.
    1855       68832 :           BuildNewLocalCatchContext(stmt->scope());
    1856       68836 :           builder()->StoreAccumulatorInRegister(context);
    1857             :         }
    1858             : 
    1859             :         // If requested, clear message object as we enter the catch block.
    1860      137824 :         if (stmt->ShouldClearPendingException(outer_catch_prediction)) {
    1861       68912 :           builder()->LoadTheHole().SetPendingMessage();
    1862             :         }
    1863             : 
    1864             :         // Load the catch context into the accumulator.
    1865       68907 :         builder()->LoadAccumulatorWithRegister(context);
    1866             : 
    1867             :         // Evaluate the catch-block.
    1868      137818 :         if (stmt->scope()) {
    1869       68837 :           VisitInScope(stmt->catch_block(), stmt->scope());
    1870             :         } else {
    1871          72 :           VisitBlock(stmt->catch_block());
    1872             :         }
    1873       68914 :       },
    1874       68904 :       catch_prediction(), stmt);
    1875       68899 : }
    1876             : 
    1877        6856 : void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
    1878             :   BuildTryFinally(
    1879             :       // Try block.
    1880        3428 :       [&]() { Visit(stmt->try_block()); },
    1881             :       // Finally block.
    1882        3428 :       [&](Register body_continuation_token) { Visit(stmt->finally_block()); },
    1883        6856 :       catch_prediction(), stmt);
    1884        3427 : }
    1885             : 
    1886           0 : void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
    1887             :   builder()->SetStatementPosition(stmt);
    1888        6555 :   builder()->Debugger();
    1889           0 : }
    1890             : 
    1891     5300328 : void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
    1892             :   DCHECK(expr->scope()->outer_scope() == current_scope());
    1893             :   uint8_t flags = CreateClosureFlags::Encode(
    1894     5300328 :       expr->pretenure(), closure_scope()->is_function_scope(),
    1895     7950492 :       info()->might_always_opt());
    1896     2650177 :   size_t entry = builder()->AllocateDeferredConstantPoolEntry();
    1897     2650177 :   FeedbackSlot slot = GetCachedCreateClosureSlot(expr);
    1898     2650395 :   builder()->CreateClosure(entry, feedback_index(slot), flags);
    1899     5300468 :   function_literals_.push_back(std::make_pair(expr, entry));
    1900     2650232 :   AddToEagerLiteralsIfEager(expr);
    1901     2650249 : }
    1902             : 
    1903     2895018 : void BytecodeGenerator::AddToEagerLiteralsIfEager(FunctionLiteral* literal) {
    1904     2895018 :   if (eager_inner_literals_ && literal->ShouldEagerCompile()) {
    1905             :     DCHECK(!IsInEagerLiterals(literal, *eager_inner_literals_));
    1906      519332 :     eager_inner_literals_->push_back(literal);
    1907             :   }
    1908     2895019 : }
    1909             : 
    1910    20401032 : bool BytecodeGenerator::ShouldOptimizeAsOneShot() const {
    1911    10379343 :   if (!FLAG_enable_one_shot_optimization) return false;
    1912             : 
    1913    10362707 :   if (loop_depth_ > 0) return false;
    1914             : 
    1915    28120570 :   return info()->literal()->is_toplevel() ||
    1916    18098881 :          info()->literal()->is_oneshot_iife();
    1917             : }
    1918             : 
    1919       43643 : void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
    1920             :   size_t class_boilerplate_entry =
    1921       41963 :       builder()->AllocateDeferredConstantPoolEntry();
    1922       83929 :   class_literals_.push_back(std::make_pair(expr, class_boilerplate_entry));
    1923             : 
    1924      637955 :   VisitDeclarations(expr->scope()->declarations());
    1925       41966 :   Register class_constructor = register_allocator()->NewRegister();
    1926             : 
    1927             :   {
    1928             :     RegisterAllocationScope register_scope(this);
    1929       41965 :     RegisterList args = register_allocator()->NewGrowableRegisterList();
    1930             : 
    1931       41965 :     Register class_boilerplate = register_allocator()->GrowRegisterList(&args);
    1932             :     Register class_constructor_in_args =
    1933       41966 :         register_allocator()->GrowRegisterList(&args);
    1934       41966 :     Register super_class = register_allocator()->GrowRegisterList(&args);
    1935             :     DCHECK_EQ(ClassBoilerplate::kFirstDynamicArgumentIndex,
    1936             :               args.register_count());
    1937             : 
    1938       41966 :     VisitForAccumulatorValueOrTheHole(expr->extends());
    1939       41965 :     builder()->StoreAccumulatorInRegister(super_class);
    1940             : 
    1941       41965 :     VisitFunctionLiteral(expr->constructor());
    1942             :     builder()
    1943       41964 :         ->StoreAccumulatorInRegister(class_constructor)
    1944       41965 :         .MoveRegister(class_constructor, class_constructor_in_args)
    1945       41965 :         .LoadConstantPoolEntry(class_boilerplate_entry)
    1946       41965 :         .StoreAccumulatorInRegister(class_boilerplate);
    1947             : 
    1948             :     // Create computed names and method values nodes to store into the literal.
    1949      692750 :     for (int i = 0; i < expr->properties()->length(); i++) {
    1950      622883 :       ClassLiteral::Property* property = expr->properties()->at(i);
    1951      607836 :       if (property->is_computed_name()) {
    1952        6038 :         Register key = register_allocator()->GrowRegisterList(&args);
    1953             : 
    1954             :         builder()->SetExpressionAsStatementPosition(property->key());
    1955        6039 :         BuildLoadPropertyKey(property, key);
    1956        6039 :         if (property->is_static()) {
    1957             :           // The static prototype property is read only. We handle the non
    1958             :           // computed property name case in the parser. Since this is the only
    1959             :           // case where we need to check for an own read only property we
    1960             :           // special case this so we do not need to do this for every property.
    1961             : 
    1962             :           FeedbackSlot slot = GetDummyCompareICSlot();
    1963             :           BytecodeLabel done;
    1964             :           builder()
    1965        1674 :               ->LoadLiteral(ast_string_constants()->prototype_string())
    1966             :               .CompareOperation(Token::Value::EQ_STRICT, key,
    1967        1674 :                                 feedback_index(slot))
    1968        1674 :               .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &done)
    1969        1674 :               .CallRuntime(Runtime::kThrowStaticPrototypeError)
    1970        1674 :               .Bind(&done);
    1971             :         }
    1972             : 
    1973        6039 :         if (property->kind() == ClassLiteral::Property::FIELD) {
    1974             :           DCHECK(!property->is_private());
    1975             :           // Initialize field's name variable with the computed name.
    1976             :           DCHECK_NOT_NULL(property->computed_name_var());
    1977         407 :           builder()->LoadAccumulatorWithRegister(key);
    1978             :           BuildVariableAssignment(property->computed_name_var(), Token::INIT,
    1979         407 :                                   HoleCheckMode::kElided);
    1980             :         }
    1981             :       }
    1982             : 
    1983      304414 :       if (property->kind() == ClassLiteral::Property::FIELD) {
    1984         989 :         if (property->is_private()) {
    1985             :           RegisterAllocationScope private_name_register_scope(this);
    1986         582 :           Register private_name = register_allocator()->NewRegister();
    1987             :           VisitForRegisterValue(property->key(), private_name);
    1988             :           builder()
    1989        1163 :               ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
    1990         582 :               .StoreAccumulatorInRegister(private_name)
    1991         582 :               .CallRuntime(Runtime::kCreatePrivateNameSymbol, private_name);
    1992             :           DCHECK_NOT_NULL(property->private_name_var());
    1993             :           BuildVariableAssignment(property->private_name_var(), Token::INIT,
    1994         582 :                                   HoleCheckMode::kElided);
    1995             :         }
    1996             :         // We don't compute field's value here, but instead do it in the
    1997             :         // initializer function.
    1998         989 :         continue;
    1999             :       }
    2000             : 
    2001      303425 :       Register value = register_allocator()->GrowRegisterList(&args);
    2002             :       VisitForRegisterValue(property->value(), value);
    2003             :     }
    2004             : 
    2005       41962 :     builder()->CallRuntime(Runtime::kDefineClass, args);
    2006             :   }
    2007       41964 :   Register prototype = register_allocator()->NewRegister();
    2008       41963 :   builder()->StoreAccumulatorInRegister(prototype);
    2009             : 
    2010             :   // Assign to class variable.
    2011       41964 :   if (expr->class_variable() != nullptr) {
    2012             :     DCHECK(expr->class_variable()->IsStackLocal() ||
    2013             :            expr->class_variable()->IsContextSlot());
    2014       37813 :     builder()->LoadAccumulatorWithRegister(class_constructor);
    2015             :     BuildVariableAssignment(expr->class_variable(), Token::INIT,
    2016       37814 :                             HoleCheckMode::kElided);
    2017             :   }
    2018             : 
    2019       41962 :   if (expr->instance_members_initializer_function() != nullptr) {
    2020             :     Register initializer =
    2021         947 :         VisitForRegisterValue(expr->instance_members_initializer_function());
    2022             : 
    2023         947 :     if (FunctionLiteral::NeedsHomeObject(
    2024             :             expr->instance_members_initializer_function())) {
    2025          24 :       FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
    2026          24 :       builder()->LoadAccumulatorWithRegister(prototype).StoreHomeObjectProperty(
    2027          24 :           initializer, feedback_index(slot), language_mode());
    2028             :     }
    2029             : 
    2030         946 :     FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
    2031             :     builder()
    2032         947 :         ->LoadAccumulatorWithRegister(initializer)
    2033         946 :         .StoreClassFieldsInitializer(class_constructor, feedback_index(slot))
    2034         947 :         .LoadAccumulatorWithRegister(class_constructor);
    2035             :   }
    2036             : 
    2037       41962 :   if (expr->static_fields_initializer() != nullptr) {
    2038             :     // TODO(gsathya): This can be optimized away to be a part of the
    2039             :     // class boilerplate in the future. The name argument can be
    2040             :     // passed to the DefineClass runtime function and have it set
    2041             :     // there.
    2042         517 :     if (name.is_valid()) {
    2043           6 :       Register key = register_allocator()->NewRegister();
    2044             :       builder()
    2045           6 :           ->LoadLiteral(ast_string_constants()->name_string())
    2046           6 :           .StoreAccumulatorInRegister(key);
    2047             : 
    2048             :       DataPropertyInLiteralFlags data_property_flags =
    2049             :           DataPropertyInLiteralFlag::kNoFlags;
    2050             :       FeedbackSlot slot =
    2051           6 :           feedback_spec()->AddStoreDataPropertyInLiteralICSlot();
    2052           6 :       builder()->LoadAccumulatorWithRegister(name).StoreDataPropertyInLiteral(
    2053           6 :           class_constructor, key, data_property_flags, feedback_index(slot));
    2054             :     }
    2055             : 
    2056         517 :     RegisterList args = register_allocator()->NewRegisterList(1);
    2057             :     Register initializer =
    2058         517 :         VisitForRegisterValue(expr->static_fields_initializer());
    2059             : 
    2060         517 :     if (FunctionLiteral::NeedsHomeObject(expr->static_fields_initializer())) {
    2061          23 :       FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
    2062             :       builder()
    2063          23 :           ->LoadAccumulatorWithRegister(class_constructor)
    2064             :           .StoreHomeObjectProperty(initializer, feedback_index(slot),
    2065          23 :                                    language_mode());
    2066             :     }
    2067             : 
    2068             :     builder()
    2069         517 :         ->MoveRegister(class_constructor, args[0])
    2070             :         .CallProperty(initializer, args,
    2071        1034 :                       feedback_index(feedback_spec()->AddCallICSlot()));
    2072             :   }
    2073       41962 :   builder()->LoadAccumulatorWithRegister(class_constructor);
    2074       41963 : }
    2075             : 
    2076       41957 : void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
    2077       41957 :   VisitClassLiteral(expr, Register::invalid_value());
    2078       41960 : }
    2079             : 
    2080      118204 : void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr, Register name) {
    2081             :   CurrentScope current_scope(this, expr->scope());
    2082             :   DCHECK_NOT_NULL(expr->scope());
    2083       41965 :   if (expr->scope()->NeedsContext()) {
    2084       34274 :     BuildNewLocalBlockContext(expr->scope());
    2085       34274 :     ContextScope scope(this, expr->scope());
    2086       34274 :     BuildClassLiteral(expr, name);
    2087             :   } else {
    2088        7691 :     BuildClassLiteral(expr, name);
    2089             :   }
    2090       41966 : }
    2091             : 
    2092        1464 : void BytecodeGenerator::VisitInitializeClassMembersStatement(
    2093        3645 :     InitializeClassMembersStatement* stmt) {
    2094        1464 :   RegisterList args = register_allocator()->NewRegisterList(3);
    2095        2928 :   Register constructor = args[0], key = args[1], value = args[2];
    2096        1464 :   builder()->MoveRegister(builder()->Receiver(), constructor);
    2097             : 
    2098        7290 :   for (int i = 0; i < stmt->fields()->length(); i++) {
    2099       11080 :     ClassLiteral::Property* property = stmt->fields()->at(i);
    2100             : 
    2101        6543 :     if (property->is_computed_name()) {
    2102             :       DCHECK_EQ(property->kind(), ClassLiteral::Property::FIELD);
    2103             :       DCHECK(!property->is_private());
    2104             :       Variable* var = property->computed_name_var();
    2105             :       DCHECK_NOT_NULL(var);
    2106             :       // The computed name is already evaluated and stored in a
    2107             :       // variable at class definition time.
    2108         407 :       BuildVariableLoad(var, HoleCheckMode::kElided);
    2109         407 :       builder()->StoreAccumulatorInRegister(key);
    2110        3548 :     } else if (property->kind() == ClassLiteral::Property::FIELD &&
    2111             :                property->is_private()) {
    2112             :       Variable* private_name_var = property->private_name_var();
    2113             :       DCHECK_NOT_NULL(private_name_var);
    2114         582 :       BuildVariableLoad(private_name_var, HoleCheckMode::kElided);
    2115         582 :       builder()->StoreAccumulatorInRegister(key);
    2116             :     } else {
    2117        1192 :       BuildLoadPropertyKey(property, key);
    2118             :     }
    2119             : 
    2120             :     builder()->SetExpressionAsStatementPosition(property->value());
    2121             :     VisitForRegisterValue(property->value(), value);
    2122        2181 :     VisitSetHomeObject(value, constructor, property);
    2123             : 
    2124             :     Runtime::FunctionId function_id =
    2125        2181 :         property->kind() == ClassLiteral::Property::FIELD &&
    2126             :                 !property->is_private()
    2127             :             ? Runtime::kCreateDataProperty
    2128        2181 :             : Runtime::kAddPrivateField;
    2129        2181 :     builder()->CallRuntime(function_id, args);
    2130             :   }
    2131        1464 : }
    2132             : 
    2133         856 : void BytecodeGenerator::BuildInstanceMemberInitialization(Register constructor,
    2134             :                                                           Register instance) {
    2135         856 :   RegisterList args = register_allocator()->NewRegisterList(1);
    2136         856 :   Register initializer = register_allocator()->NewRegister();
    2137             : 
    2138         856 :   FeedbackSlot slot = feedback_spec()->AddLoadICSlot();
    2139             :   BytecodeLabel done;
    2140             : 
    2141             :   builder()
    2142         856 :       ->LoadClassFieldsInitializer(constructor, feedback_index(slot))
    2143             :       // TODO(gsathya): This jump can be elided for the base
    2144             :       // constructor and derived constructor. This is only required
    2145             :       // when called from an arrow function.
    2146         856 :       .JumpIfUndefined(&done)
    2147         856 :       .StoreAccumulatorInRegister(initializer)
    2148        1712 :       .MoveRegister(instance, args[0])
    2149             :       .CallProperty(initializer, args,
    2150        1712 :                     feedback_index(feedback_spec()->AddCallICSlot()))
    2151         856 :       .Bind(&done);
    2152         856 : }
    2153             : 
    2154        1734 : void BytecodeGenerator::VisitNativeFunctionLiteral(
    2155             :     NativeFunctionLiteral* expr) {
    2156        1734 :   size_t entry = builder()->AllocateDeferredConstantPoolEntry();
    2157        1734 :   FeedbackSlot slot = feedback_spec()->AddCreateClosureSlot();
    2158        1734 :   builder()->CreateClosure(entry, feedback_index(slot), NOT_TENURED);
    2159        3468 :   native_function_literals_.push_back(std::make_pair(expr, entry));
    2160        1734 : }
    2161             : 
    2162           0 : void BytecodeGenerator::VisitDoExpression(DoExpression* expr) {
    2163           0 :   VisitBlock(expr->block());
    2164           0 :   VisitVariableProxy(expr->result());
    2165           0 : }
    2166             : 
    2167      174222 : void BytecodeGenerator::VisitConditional(Conditional* expr) {
    2168             :   ConditionalControlFlowBuilder conditional_builder(
    2169       29191 :       builder(), block_coverage_builder_, expr);
    2170             : 
    2171       29191 :   if (expr->condition()->ToBooleanIsTrue()) {
    2172             :     // Generate then block unconditionally as always true.
    2173         234 :     conditional_builder.Then();
    2174         234 :     VisitForAccumulatorValue(expr->then_expression());
    2175       28958 :   } else if (expr->condition()->ToBooleanIsFalse()) {
    2176             :     // Generate else block unconditionally if it exists.
    2177         112 :     conditional_builder.Else();
    2178         112 :     VisitForAccumulatorValue(expr->else_expression());
    2179             :   } else {
    2180             :     VisitForTest(expr->condition(), conditional_builder.then_labels(),
    2181       28847 :                  conditional_builder.else_labels(), TestFallthrough::kThen);
    2182             : 
    2183       28846 :     conditional_builder.Then();
    2184       28845 :     VisitForAccumulatorValue(expr->then_expression());
    2185       28847 :     conditional_builder.JumpToEnd();
    2186             : 
    2187       28844 :     conditional_builder.Else();
    2188       28844 :     VisitForAccumulatorValue(expr->else_expression());
    2189       29193 :   }
    2190       29193 : }
    2191             : 
    2192    29487834 : void BytecodeGenerator::VisitLiteral(Literal* expr) {
    2193    20332702 :   if (execution_result()->IsEffect()) return;
    2194     9041466 :   switch (expr->type()) {
    2195             :     case Literal::kSmi:
    2196     6655346 :       builder()->LoadLiteral(expr->AsSmiLiteral());
    2197     6655301 :       break;
    2198             :     case Literal::kHeapNumber:
    2199      270918 :       builder()->LoadLiteral(expr->AsNumber());
    2200      270919 :       break;
    2201             :     case Literal::kUndefined:
    2202      110114 :       builder()->LoadUndefined();
    2203      110119 :       break;
    2204             :     case Literal::kBoolean:
    2205      322092 :       builder()->LoadBoolean(expr->ToBooleanIsTrue());
    2206             :       execution_result()->SetResultIsBoolean();
    2207             :       break;
    2208             :     case Literal::kNull:
    2209       21762 :       builder()->LoadNull();
    2210       21765 :       break;
    2211             :     case Literal::kTheHole:
    2212           0 :       builder()->LoadTheHole();
    2213           0 :       break;
    2214             :     case Literal::kString:
    2215     1650301 :       builder()->LoadLiteral(expr->AsRawString());
    2216             :       execution_result()->SetResultIsString();
    2217             :       break;
    2218             :     case Literal::kSymbol:
    2219        1981 :       builder()->LoadLiteral(expr->AsSymbol());
    2220        1981 :       break;
    2221             :     case Literal::kBigInt:
    2222        9011 :       builder()->LoadLiteral(expr->AsBigInt());
    2223        9005 :       break;
    2224             :   }
    2225             : }
    2226             : 
    2227       89778 : void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
    2228             :   // Materialize a regular expression literal.
    2229             :   builder()->CreateRegExpLiteral(
    2230             :       expr->raw_pattern(), feedback_index(feedback_spec()->AddLiteralSlot()),
    2231       89778 :       expr->flags());
    2232       44892 : }
    2233             : 
    2234      199277 : void BytecodeGenerator::BuildCreateObjectLiteral(Register literal,
    2235             :                                                  uint8_t flags, size_t entry) {
    2236      199277 :   if (ShouldOptimizeAsOneShot()) {
    2237      113008 :     RegisterList args = register_allocator()->NewRegisterList(2);
    2238             :     builder()
    2239      113024 :         ->LoadConstantPoolEntry(entry)
    2240      113028 :         .StoreAccumulatorInRegister(args[0])
    2241      113028 :         .LoadLiteral(Smi::FromInt(flags))
    2242      113033 :         .StoreAccumulatorInRegister(args[1])
    2243      113030 :         .CallRuntime(Runtime::kCreateObjectLiteralWithoutAllocationSite, args)
    2244      113022 :         .StoreAccumulatorInRegister(literal);
    2245             : 
    2246             :   } else {
    2247             :     // TODO(cbruni): Directly generate runtime call for literals we cannot
    2248             :     // optimize once the CreateShallowObjectLiteral stub is in sync with the TF
    2249             :     // optimizations.
    2250       86280 :     int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
    2251             :     builder()
    2252       86281 :         ->CreateObjectLiteral(entry, literal_index, flags)
    2253       86281 :         .StoreAccumulatorInRegister(literal);
    2254             :   }
    2255      199307 : }
    2256             : 
    2257      426998 : void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
    2258      426419 :   expr->InitDepthAndFlags();
    2259             : 
    2260             :   // Fast path for the empty object literal which doesn't need an
    2261             :   // AllocationSite.
    2262      227185 :   if (expr->IsEmptyObjectLiteral()) {
    2263             :     DCHECK(expr->IsFastCloningSupported());
    2264       27618 :     builder()->CreateEmptyObjectLiteral();
    2265      254805 :     return;
    2266             :   }
    2267             : 
    2268             :   // Deep-copy the literal boilerplate.
    2269             :   uint8_t flags = CreateObjectLiteralFlags::Encode(
    2270      199566 :       expr->ComputeFlags(), expr->IsFastCloningSupported());
    2271             : 
    2272      199553 :   Register literal = register_allocator()->NewRegister();
    2273             : 
    2274             :   // Create literal object.
    2275             :   int property_index = 0;
    2276             :   bool clone_object_spread =
    2277      199530 :       expr->properties()->first()->kind() == ObjectLiteral::Property::SPREAD;
    2278      199530 :   if (clone_object_spread) {
    2279             :     // Avoid the slow path for spreads in the following common cases:
    2280             :     //   1) `let obj = { ...source }`
    2281             :     //   2) `let obj = { ...source, override: 1 }`
    2282             :     //   3) `let obj = { ...source, ...overrides }`
    2283             :     RegisterAllocationScope register_scope(this);
    2284         267 :     Expression* property = expr->properties()->first()->value();
    2285         267 :     Register from_value = VisitForRegisterValue(property);
    2286             : 
    2287             :     BytecodeLabels clone_object(zone());
    2288         267 :     builder()->JumpIfUndefined(clone_object.New());
    2289         267 :     builder()->JumpIfNull(clone_object.New());
    2290         267 :     builder()->ToObject(from_value);
    2291             : 
    2292         267 :     clone_object.Bind(builder());
    2293         267 :     int clone_index = feedback_index(feedback_spec()->AddCloneObjectSlot());
    2294         267 :     builder()->CloneObject(from_value, flags, clone_index);
    2295         267 :     builder()->StoreAccumulatorInRegister(literal);
    2296         267 :     property_index++;
    2297             :   } else {
    2298             :     size_t entry;
    2299             :     // If constant properties is an empty fixed array, use a cached empty fixed
    2300             :     // array to ensure it's only added to the constant pool once.
    2301      199263 :     if (expr->properties_count() == 0) {
    2302        2192 :       entry = builder()->EmptyObjectBoilerplateDescriptionConstantPoolEntry();
    2303             :     } else {
    2304      197071 :       entry = builder()->AllocateDeferredConstantPoolEntry();
    2305      394187 :       object_literals_.push_back(std::make_pair(expr, entry));
    2306             :     }
    2307      199296 :     BuildCreateObjectLiteral(literal, flags, entry);
    2308             :   }
    2309             : 
    2310             :   // Store computed values into the literal.
    2311             :   AccessorTable accessor_table(zone());
    2312     2007393 :   for (; property_index < expr->properties()->length(); property_index++) {
    2313     2260726 :     ObjectLiteral::Property* property = expr->properties()->at(property_index);
    2314     2735522 :     if (property->is_computed_name()) break;
    2315     3763257 :     if (!clone_object_spread && property->IsCompileTimeValue()) continue;
    2316             : 
    2317             :     RegisterAllocationScope inner_register_scope(this);
    2318      492262 :     Literal* key = property->key()->AsLiteral();
    2319      251482 :     switch (property->kind()) {
    2320             :       case ObjectLiteral::Property::SPREAD:
    2321           0 :         UNREACHABLE();
    2322             :       case ObjectLiteral::Property::CONSTANT:
    2323             :       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
    2324             :         DCHECK(clone_object_spread || !property->value()->IsCompileTimeValue());
    2325             :         V8_FALLTHROUGH;
    2326             :       case ObjectLiteral::Property::COMPUTED: {
    2327             :         // It is safe to use [[Put]] here because the boilerplate already
    2328             :         // contains computed properties with an uninitialized value.
    2329      241488 :         if (key->IsStringLiteral()) {
    2330             :           DCHECK(key->IsPropertyName());
    2331      240931 :           if (property->emit_store()) {
    2332             :             builder()->SetExpressionPosition(property->value());
    2333      240785 :             VisitForAccumulatorValue(property->value());
    2334      240789 :             FeedbackSlot slot = feedback_spec()->AddStoreOwnICSlot();
    2335      240792 :             if (FunctionLiteral::NeedsHomeObject(property->value())) {
    2336             :               RegisterAllocationScope register_scope(this);
    2337         546 :               Register value = register_allocator()->NewRegister();
    2338         546 :               builder()->StoreAccumulatorInRegister(value);
    2339             :               builder()->StoreNamedOwnProperty(
    2340         546 :                   literal, key->AsRawPropertyName(), feedback_index(slot));
    2341         545 :               VisitSetHomeObject(value, literal, property);
    2342             :             } else {
    2343             :               builder()->StoreNamedOwnProperty(
    2344      240235 :                   literal, key->AsRawPropertyName(), feedback_index(slot));
    2345             :             }
    2346             :           } else {
    2347             :             builder()->SetExpressionPosition(property->value());
    2348         149 :             VisitForEffect(property->value());
    2349             :           }
    2350             :         } else {
    2351         554 :           RegisterList args = register_allocator()->NewRegisterList(3);
    2352             : 
    2353         554 :           builder()->MoveRegister(literal, args[0]);
    2354             :           builder()->SetExpressionPosition(property->key());
    2355             :           VisitForRegisterValue(property->key(), args[1]);
    2356             :           builder()->SetExpressionPosition(property->value());
    2357             :           VisitForRegisterValue(property->value(), args[2]);
    2358         554 :           if (property->emit_store()) {
    2359         521 :             builder()->CallRuntime(Runtime::kSetKeyedProperty, args);
    2360         522 :             Register value = args[2];
    2361         522 :             VisitSetHomeObject(value, literal, property);
    2362             :           }
    2363             :         }
    2364             :         break;
    2365             :       }
    2366             :       case ObjectLiteral::Property::PROTOTYPE: {
    2367             :         // __proto__:null is handled by CreateObjectLiteral.
    2368        4086 :         if (property->IsNullPrototype()) break;
    2369             :         DCHECK(property->emit_store());
    2370             :         DCHECK(!property->NeedsSetFunctionName());
    2371        1256 :         RegisterList args = register_allocator()->NewRegisterList(2);
    2372        1256 :         builder()->MoveRegister(literal, args[0]);
    2373             :         builder()->SetExpressionPosition(property->value());
    2374             :         VisitForRegisterValue(property->value(), args[1]);
    2375        1256 :         builder()->CallRuntime(Runtime::kInternalSetPrototype, args);
    2376        1256 :         break;
    2377             :       }
    2378             :       case ObjectLiteral::Property::GETTER:
    2379        3922 :         if (property->emit_store()) {
    2380        3820 :           accessor_table.lookup(key)->second->getter = property;
    2381             :         }
    2382             :         break;
    2383             :       case ObjectLiteral::Property::SETTER:
    2384        1981 :         if (property->emit_store()) {
    2385        1885 :           accessor_table.lookup(key)->second->setter = property;
    2386             :         }
    2387             :         break;
    2388             :     }
    2389      251489 :   }
    2390             : 
    2391             :   // Define accessors, using only a single call to the runtime for each pair of
    2392             :   // corresponding getters and setters.
    2393      404023 :   for (AccessorTable::Iterator it = accessor_table.begin();
    2394             :        it != accessor_table.end(); ++it) {
    2395             :     RegisterAllocationScope inner_register_scope(this);
    2396        4992 :     RegisterList args = register_allocator()->NewRegisterList(5);
    2397        4993 :     builder()->MoveRegister(literal, args[0]);
    2398        4992 :     VisitForRegisterValue(it->first, args[1]);
    2399        4992 :     VisitObjectLiteralAccessor(literal, it->second->getter, args[2]);
    2400        4991 :     VisitObjectLiteralAccessor(literal, it->second->setter, args[3]);
    2401             :     builder()
    2402        4993 :         ->LoadLiteral(Smi::FromInt(NONE))
    2403        4993 :         .StoreAccumulatorInRegister(args[4])
    2404        4993 :         .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, args);
    2405        4993 :   }
    2406             : 
    2407             :   // Object literals have two parts. The "static" part on the left contains no
    2408             :   // computed property names, and so we can compute its map ahead of time; see
    2409             :   // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
    2410             :   // with the first computed property name and continues with all properties to
    2411             :   // its right. All the code from above initializes the static component of the
    2412             :   // object literal, and arranges for the map of the result to reflect the
    2413             :   // static order in which the keys appear. For the dynamic properties, we
    2414             :   // compile them into a series of "SetOwnProperty" runtime calls. This will
    2415             :   // preserve insertion order.
    2416        2815 :   for (; property_index < expr->properties()->length(); property_index++) {
    2417        3150 :     ObjectLiteral::Property* property = expr->properties()->at(property_index);
    2418             :     RegisterAllocationScope inner_register_scope(this);
    2419             : 
    2420        2815 :     if (property->IsPrototype()) {
    2421             :       // __proto__:null is handled by CreateObjectLiteral.
    2422          36 :       if (property->IsNullPrototype()) continue;
    2423             :       DCHECK(property->emit_store());
    2424             :       DCHECK(!property->NeedsSetFunctionName());
    2425          30 :       RegisterList args = register_allocator()->NewRegisterList(2);
    2426          30 :       builder()->MoveRegister(literal, args[0]);
    2427        5624 :       builder()->SetExpressionPosition(property->value());
    2428             :       VisitForRegisterValue(property->value(), args[1]);
    2429          30 :       builder()->CallRuntime(Runtime::kInternalSetPrototype, args);
    2430          30 :       continue;
    2431             :     }
    2432             : 
    2433        2779 :     switch (property->kind()) {
    2434             :       case ObjectLiteral::Property::CONSTANT:
    2435             :       case ObjectLiteral::Property::COMPUTED:
    2436             :       case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
    2437        2348 :         Register key = register_allocator()->NewRegister();
    2438        2348 :         BuildLoadPropertyKey(property, key);
    2439             :         builder()->SetExpressionPosition(property->value());
    2440             :         Register value;
    2441             : 
    2442             :         // Static class fields require the name property to be set on
    2443             :         // the class, meaning we can't wait until the
    2444             :         // StoreDataPropertyInLiteral call later to set the name.
    2445        2359 :         if (property->value()->IsClassLiteral() &&
    2446          24 :             property->value()->AsClassLiteral()->static_fields_initializer() !=
    2447             :                 nullptr) {
    2448           6 :           value = register_allocator()->NewRegister();
    2449          12 :           VisitClassLiteral(property->value()->AsClassLiteral(), key);
    2450           6 :           builder()->StoreAccumulatorInRegister(value);
    2451             :         } else {
    2452        2341 :           value = VisitForRegisterValue(property->value());
    2453             :         }
    2454        2349 :         VisitSetHomeObject(value, literal, property);
    2455             : 
    2456             :         DataPropertyInLiteralFlags data_property_flags =
    2457             :             DataPropertyInLiteralFlag::kNoFlags;
    2458        2348 :         if (property->NeedsSetFunctionName()) {
    2459             :           data_property_flags |= DataPropertyInLiteralFlag::kSetFunctionName;
    2460             :         }
    2461             : 
    2462             :         FeedbackSlot slot =
    2463        2349 :             feedback_spec()->AddStoreDataPropertyInLiteralICSlot();
    2464             :         builder()
    2465        2349 :             ->LoadAccumulatorWithRegister(value)
    2466             :             .StoreDataPropertyInLiteral(literal, key, data_property_flags,
    2467        2349 :                                         feedback_index(slot));
    2468             :         break;
    2469             :       }
    2470             :       case ObjectLiteral::Property::GETTER:
    2471             :       case ObjectLiteral::Property::SETTER: {
    2472         335 :         RegisterList args = register_allocator()->NewRegisterList(4);
    2473         335 :         builder()->MoveRegister(literal, args[0]);
    2474         335 :         BuildLoadPropertyKey(property, args[1]);
    2475             :         builder()->SetExpressionPosition(property->value());
    2476             :         VisitForRegisterValue(property->value(), args[2]);
    2477         335 :         VisitSetHomeObject(args[2], literal, property);
    2478             :         builder()
    2479         335 :             ->LoadLiteral(Smi::FromInt(NONE))
    2480         335 :             .StoreAccumulatorInRegister(args[3]);
    2481             :         Runtime::FunctionId function_id =
    2482             :             property->kind() == ObjectLiteral::Property::GETTER
    2483             :                 ? Runtime::kDefineGetterPropertyUnchecked
    2484         335 :                 : Runtime::kDefineSetterPropertyUnchecked;
    2485         335 :         builder()->CallRuntime(function_id, args);
    2486             :         break;
    2487             :       }
    2488             :       case ObjectLiteral::Property::SPREAD: {
    2489          96 :         RegisterList args = register_allocator()->NewRegisterList(2);
    2490          96 :         builder()->MoveRegister(literal, args[0]);
    2491             :         builder()->SetExpressionPosition(property->value());
    2492             :         VisitForRegisterValue(property->value(), args[1]);
    2493          96 :         builder()->CallRuntime(Runtime::kCopyDataProperties, args);
    2494             :         break;
    2495             :       }
    2496             :       case ObjectLiteral::Property::PROTOTYPE:
    2497           0 :         UNREACHABLE();  // Handled specially above.
    2498             :         break;
    2499             :     }
    2500        2780 :   }
    2501             : 
    2502      199515 :   builder()->LoadAccumulatorWithRegister(literal);
    2503             : }
    2504             : 
    2505             : // Fill an array with values from an iterator, starting at a given index. It is
    2506             : // guaranteed that the loop will only terminate if the iterator is exhausted, or
    2507             : // if one of iterator.next(), value.done, or value.value fail.
    2508             : //
    2509             : // In pseudocode:
    2510             : //
    2511             : // loop {
    2512             : //   value = iterator.next()
    2513             : //   if (value.done) break;
    2514             : //   value = value.value
    2515             : //   array[index++] = value
    2516             : // }
    2517        2074 : void BytecodeGenerator::BuildFillArrayWithIterator(
    2518             :     IteratorRecord iterator, Register array, Register index, Register value,
    2519             :     FeedbackSlot next_value_slot, FeedbackSlot next_done_slot,
    2520        4150 :     FeedbackSlot index_slot, FeedbackSlot element_slot) {
    2521             :   DCHECK(array.is_valid());
    2522             :   DCHECK(index.is_valid());
    2523             :   DCHECK(value.is_valid());
    2524             : 
    2525        2074 :   LoopBuilder loop_builder(builder(), nullptr, nullptr);
    2526        2074 :   loop_builder.LoopHeader();
    2527             : 
    2528             :   // Call the iterator's .next() method. Break from the loop if the `done`
    2529             :   // property is truthy, otherwise load the value from the iterator result and
    2530             :   // append the argument.
    2531        2075 :   BuildIteratorNext(iterator, value);
    2532             :   builder()->LoadNamedProperty(
    2533             :       value, ast_string_constants()->done_string(),
    2534        4150 :       feedback_index(feedback_spec()->AddLoadICSlot()));
    2535             :   loop_builder.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
    2536             : 
    2537        2075 :   loop_builder.LoopBody();
    2538             :   builder()
    2539             :       // value = value.value
    2540             :       ->LoadNamedProperty(value, ast_string_constants()->value_string(),
    2541        2075 :                           feedback_index(next_value_slot))
    2542             :       // array[index] = value
    2543        2075 :       .StoreInArrayLiteral(array, index, feedback_index(element_slot))
    2544             :       // index++
    2545        2075 :       .LoadAccumulatorWithRegister(index)
    2546        2075 :       .UnaryOperation(Token::INC, feedback_index(index_slot))
    2547        2075 :       .StoreAccumulatorInRegister(index);
    2548        2075 :   loop_builder.BindContinueTarget();
    2549        2074 :   loop_builder.JumpToHeader(loop_depth_);
    2550        2075 : }
    2551             : 
    2552      356387 : void BytecodeGenerator::BuildCreateArrayLiteral(
    2553      356991 :     const ZonePtrList<Expression>* elements, ArrayLiteral* expr) {
    2554             :   RegisterAllocationScope register_scope(this);
    2555      356387 :   Register index = register_allocator()->NewRegister();
    2556      356403 :   Register array = register_allocator()->NewRegister();
    2557             :   SharedFeedbackSlot element_slot(feedback_spec(),
    2558      356393 :                                   FeedbackSlotKind::kStoreInArrayLiteral);
    2559             :   ZonePtrList<Expression>::iterator current = elements->begin();
    2560             :   ZonePtrList<Expression>::iterator end = elements->end();
    2561             :   bool is_empty = elements->is_empty();
    2562             : 
    2563      522188 :   if (!is_empty && (*current)->IsSpread()) {
    2564             :     // If we have a leading spread, use CreateArrayFromIterable to create
    2565             :     // an array from it and then add the remaining components to that array.
    2566        2051 :     VisitForAccumulatorValue(*current);
    2567        2053 :     builder()->CreateArrayFromIterable().StoreAccumulatorInRegister(array);
    2568             : 
    2569        2052 :     if (++current != end) {
    2570             :       // If there are remaning elements, prepare the index register that is
    2571             :       // used for adding those elements. The next index is the length of the
    2572             :       // newly created array.
    2573         542 :       auto length = ast_string_constants()->length_string();
    2574         542 :       int length_load_slot = feedback_index(feedback_spec()->AddLoadICSlot());
    2575             :       builder()
    2576         542 :           ->LoadNamedProperty(array, length, length_load_slot)
    2577         542 :           .StoreAccumulatorInRegister(index);
    2578             :     }
    2579      708671 :   } else if (expr != nullptr) {
    2580             :     // There are some elements before the first (if any) spread, and we can
    2581             :     // use a boilerplate when creating the initial array from those elements.
    2582             : 
    2583             :     // First, allocate a constant pool entry for the boilerplate that will
    2584             :     // be created during finalization, and will contain all the constant
    2585             :     // elements before the first spread. This also handle the empty array case
    2586             :     // and one-shot optimization.
    2587             :     uint8_t flags = CreateArrayLiteralFlags::Encode(
    2588      354324 :         expr->IsFastCloningSupported(), expr->ComputeFlags());
    2589      354323 :     bool optimize_as_one_shot = ShouldOptimizeAsOneShot();
    2590             :     size_t entry;
    2591      354328 :     if (is_empty && optimize_as_one_shot) {
    2592       52271 :       entry = builder()->EmptyArrayBoilerplateDescriptionConstantPoolEntry();
    2593      302057 :     } else if (!is_empty) {
    2594      163711 :       entry = builder()->AllocateDeferredConstantPoolEntry();
    2595      327429 :       array_literals_.push_back(std::make_pair(expr, entry));
    2596             :     }
    2597             : 
    2598      354326 :     if (optimize_as_one_shot) {
    2599      186343 :       RegisterList args = register_allocator()->NewRegisterList(2);
    2600             :       builder()
    2601      186351 :           ->LoadConstantPoolEntry(entry)
    2602      186350 :           .StoreAccumulatorInRegister(args[0])
    2603      186356 :           .LoadLiteral(Smi::FromInt(flags))
    2604      186348 :           .StoreAccumulatorInRegister(args[1])
    2605      186341 :           .CallRuntime(Runtime::kCreateArrayLiteralWithoutAllocationSite, args);
    2606      167983 :     } else if (is_empty) {
    2607             :       // Empty array literal fast-path.
    2608      138346 :       int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
    2609             :       DCHECK(expr->IsFastCloningSupported());
    2610      138346 :       builder()->CreateEmptyArrayLiteral(literal_index);
    2611             :     } else {
    2612             :       // Create array literal from boilerplate.
    2613       29637 :       int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
    2614       29637 :       builder()->CreateArrayLiteral(entry, literal_index, flags);
    2615             :     }
    2616      354330 :     builder()->StoreAccumulatorInRegister(array);
    2617             : 
    2618             :     // Insert the missing non-constant elements, up until the first spread
    2619             :     // index, into the initial array (the remaining elements will be inserted
    2620             :     // below).
    2621             :     DCHECK_EQ(current, elements->begin());
    2622             :     ZonePtrList<Expression>::iterator first_spread_or_end =
    2623         443 :         expr->first_spread_index() >= 0 ? current + expr->first_spread_index()
    2624      354770 :                                         : end;
    2625             :     int array_index = 0;
    2626     7521950 :     for (; current != first_spread_or_end; ++current, array_index++) {
    2627     7167619 :       Expression* subexpr = *current;
    2628             :       DCHECK(!subexpr->IsSpread());
    2629             :       // Skip the constants.
    2630     7167619 :       if (subexpr->IsCompileTimeValue()) continue;
    2631             : 
    2632             :       builder()
    2633      219089 :           ->LoadLiteral(Smi::FromInt(array_index))
    2634      219096 :           .StoreAccumulatorInRegister(index);
    2635      219095 :       VisitForAccumulatorValue(subexpr);
    2636             :       builder()->StoreInArrayLiteral(array, index,
    2637      219105 :                                      feedback_index(element_slot.Get()));
    2638             :     }
    2639             : 
    2640      354331 :     if (current != end) {
    2641             :       // If there are remaining elements, prepare the index register
    2642             :       // to store the next element, which comes from the first spread.
    2643         443 :       builder()->LoadLiteral(array_index).StoreAccumulatorInRegister(index);
    2644             :     }
    2645             :   } else {
    2646             :     // In other cases, we prepare an empty array to be filled in below.
    2647             :     DCHECK(!elements->is_empty());
    2648             :     int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
    2649             :     builder()
    2650          20 :         ->CreateEmptyArrayLiteral(literal_index)
    2651          20 :         .StoreAccumulatorInRegister(array);
    2652             :     // Prepare the index for the first element.
    2653          20 :     builder()->LoadLiteral(Smi::FromInt(0)).StoreAccumulatorInRegister(index);
    2654             :   }
    2655             : 
    2656             :   // Now build insertions for the remaining elements from current to end.
    2657      356389 :   SharedFeedbackSlot index_slot(feedback_spec(), FeedbackSlotKind::kBinaryOp);
    2658             :   SharedFeedbackSlot length_slot(
    2659             :       feedback_spec(), feedback_spec()->GetStoreICSlot(LanguageMode::kStrict));
    2660        3079 :   for (; current != end; ++current) {
    2661        3079 :     Expression* subexpr = *current;
    2662        3079 :     if (subexpr->IsSpread()) {
    2663             :       RegisterAllocationScope scope(this);
    2664             :       builder()->SetExpressionAsStatementPosition(
    2665        2982 :           subexpr->AsSpread()->expression());
    2666        1491 :       VisitForAccumulatorValue(subexpr->AsSpread()->expression());
    2667        1492 :       IteratorRecord iterator = BuildGetIteratorRecord(IteratorType::kNormal);
    2668             : 
    2669        1492 :       Register value = register_allocator()->NewRegister();
    2670        2984 :       FeedbackSlot next_value_load_slot = feedback_spec()->AddLoadICSlot();
    2671        2984 :       FeedbackSlot next_done_load_slot = feedback_spec()->AddLoadICSlot();
    2672        1492 :       FeedbackSlot real_index_slot = index_slot.Get();
    2673        1492 :       FeedbackSlot real_element_slot = element_slot.Get();
    2674             :       BuildFillArrayWithIterator(iterator, array, index, value,
    2675             :                                  next_value_load_slot, next_done_load_slot,
    2676        1492 :                                  real_index_slot, real_element_slot);
    2677        1588 :     } else if (!subexpr->IsTheHoleLiteral()) {
    2678             :       // literal[index++] = subexpr
    2679        1532 :       VisitForAccumulatorValue(subexpr);
    2680             :       builder()
    2681             :           ->StoreInArrayLiteral(array, index,
    2682        1532 :                                 feedback_index(element_slot.Get()))
    2683        1532 :           .LoadAccumulatorWithRegister(index);
    2684             :       // Only increase the index if we are not the last element.
    2685        1532 :       if (current + 1 != end) {
    2686             :         builder()
    2687         976 :             ->UnaryOperation(Token::INC, feedback_index(index_slot.Get()))
    2688         976 :             .StoreAccumulatorInRegister(index);
    2689             :       }
    2690             :     } else {
    2691             :       // literal.length = ++index
    2692             :       // length_slot is only used when there are holes.
    2693          56 :       auto length = ast_string_constants()->length_string();
    2694             :       builder()
    2695          56 :           ->LoadAccumulatorWithRegister(index)
    2696         112 :           .UnaryOperation(Token::INC, feedback_index(index_slot.Get()))
    2697          56 :           .StoreAccumulatorInRegister(index)
    2698             :           .StoreNamedProperty(array, length, feedback_index(length_slot.Get()),
    2699         112 :                               LanguageMode::kStrict);
    2700             :     }
    2701             :   }
    2702             : 
    2703      356389 :   builder()->LoadAccumulatorWithRegister(array);
    2704      356409 : }
    2705             : 
    2706      356366 : void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
    2707      356366 :   expr->InitDepthAndFlags();
    2708      356373 :   BuildCreateArrayLiteral(expr->values(), expr);
    2709      356367 : }
    2710             : 
    2711           0 : void BytecodeGenerator::VisitStoreInArrayLiteral(StoreInArrayLiteral* expr) {
    2712             :   builder()->SetExpressionAsStatementPosition(expr);
    2713             :   RegisterAllocationScope register_scope(this);
    2714           0 :   Register array = register_allocator()->NewRegister();
    2715           0 :   Register index = register_allocator()->NewRegister();
    2716             :   VisitForRegisterValue(expr->array(), array);
    2717             :   VisitForRegisterValue(expr->index(), index);
    2718           0 :   VisitForAccumulatorValue(expr->value());
    2719             :   builder()->StoreInArrayLiteral(
    2720             :       array, index,
    2721           0 :       feedback_index(feedback_spec()->AddStoreInArrayLiteralICSlot()));
    2722           0 : }
    2723             : 
    2724    20064138 : void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
    2725             :   builder()->SetExpressionPosition(proxy);
    2726     6688046 :   BuildVariableLoad(proxy->var(), proxy->hole_check_mode());
    2727     6688253 : }
    2728             : 
    2729    34535480 : void BytecodeGenerator::BuildVariableLoad(Variable* variable,
    2730             :                                           HoleCheckMode hole_check_mode,
    2731     8197769 :                                           TypeofMode typeof_mode) {
    2732    13385548 :   switch (variable->location()) {
    2733             :     case VariableLocation::LOCAL: {
    2734     2402627 :       Register source(builder()->Local(variable->index()));
    2735             :       // We need to load the variable into the accumulator, even when in a
    2736             :       // VisitForRegisterScope, in order to avoid register aliasing if
    2737             :       // subsequent expressions assign to the same variable.
    2738     2402537 :       builder()->LoadAccumulatorWithRegister(source);
    2739     2402653 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    2740        2630 :         BuildThrowIfHole(variable);
    2741             :       }
    2742             :       break;
    2743             :     }
    2744             :     case VariableLocation::PARAMETER: {
    2745             :       Register source;
    2746     3755470 :       if (variable->IsReceiver()) {
    2747     2378692 :         source = builder()->Receiver();
    2748             :       } else {
    2749     1376778 :         source = builder()->Parameter(variable->index());
    2750             :       }
    2751             :       // We need to load the variable into the accumulator, even when in a
    2752             :       // VisitForRegisterScope, in order to avoid register aliasing if
    2753             :       // subsequent expressions assign to the same variable.
    2754     3755477 :       builder()->LoadAccumulatorWithRegister(source);
    2755     3755468 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    2756     2169402 :         BuildThrowIfHole(variable);
    2757             :       }
    2758             :       break;
    2759             :     }
    2760             :     case VariableLocation::UNALLOCATED: {
    2761             :       // The global identifier "undefined" is immutable. Everything
    2762             :       // else could be reassigned. For performance, we do a pointer comparison
    2763             :       // rather than checking if the raw_name is really "undefined".
    2764     5846734 :       if (variable->raw_name() == ast_string_constants()->undefined_string()) {
    2765       79597 :         builder()->LoadUndefined();
    2766             :       } else {
    2767     5767137 :         FeedbackSlot slot = GetCachedLoadGlobalICSlot(typeof_mode, variable);
    2768             :         builder()->LoadGlobal(variable->raw_name(), feedback_index(slot),
    2769     5767513 :                               typeof_mode);
    2770             :       }
    2771             :       break;
    2772             :     }
    2773             :     case VariableLocation::CONTEXT: {
    2774      995990 :       int depth = execution_context()->ContextChainDepth(variable->scope());
    2775             :       ContextScope* context = execution_context()->Previous(depth);
    2776             :       Register context_reg;
    2777      995984 :       if (context) {
    2778      926370 :         context_reg = context->reg();
    2779             :         depth = 0;
    2780             :       } else {
    2781       69614 :         context_reg = execution_context()->reg();
    2782             :       }
    2783             : 
    2784             :       BytecodeArrayBuilder::ContextSlotMutability immutable =
    2785             :           (variable->maybe_assigned() == kNotAssigned)
    2786             :               ? BytecodeArrayBuilder::kImmutableSlot
    2787      995984 :               : BytecodeArrayBuilder::kMutableSlot;
    2788             : 
    2789             :       builder()->LoadContextSlot(context_reg, variable->index(), depth,
    2790      995984 :                                  immutable);
    2791      995977 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    2792      259270 :         BuildThrowIfHole(variable);
    2793             :       }
    2794             :       break;
    2795             :     }
    2796             :     case VariableLocation::LOOKUP: {
    2797      383531 :       switch (variable->mode()) {
    2798             :         case VariableMode::kDynamicLocal: {
    2799        6754 :           Variable* local_variable = variable->local_if_not_shadowed();
    2800             :           int depth =
    2801        3377 :               execution_context()->ContextChainDepth(local_variable->scope());
    2802             :           builder()->LoadLookupContextSlot(variable->raw_name(), typeof_mode,
    2803        3377 :                                            local_variable->index(), depth);
    2804        3377 :           if (hole_check_mode == HoleCheckMode::kRequired) {
    2805        1238 :             BuildThrowIfHole(variable);
    2806             :           }
    2807             :           break;
    2808             :         }
    2809             :         case VariableMode::kDynamicGlobal: {
    2810             :           int depth =
    2811      354324 :               current_scope()->ContextChainLengthUntilOutermostSloppyEval();
    2812      354324 :           FeedbackSlot slot = GetCachedLoadGlobalICSlot(typeof_mode, variable);
    2813             :           builder()->LoadLookupGlobalSlot(variable->raw_name(), typeof_mode,
    2814      354326 :                                           feedback_index(slot), depth);
    2815             :           break;
    2816             :         }
    2817             :         default:
    2818       25830 :           builder()->LoadLookupSlot(variable->raw_name(), typeof_mode);
    2819             :       }
    2820             :       break;
    2821             :     }
    2822             :     case VariableLocation::MODULE: {
    2823        1360 :       int depth = execution_context()->ContextChainDepth(variable->scope());
    2824        1360 :       builder()->LoadModuleVariable(variable->index(), depth);
    2825        1360 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    2826         848 :         BuildThrowIfHole(variable);
    2827             :       }
    2828             :       break;
    2829             :     }
    2830             :   }
    2831    13385772 : }
    2832             : 
    2833     4179002 : void BytecodeGenerator::BuildVariableLoadForAccumulatorValue(
    2834             :     Variable* variable, HoleCheckMode hole_check_mode, TypeofMode typeof_mode) {
    2835             :   ValueResultScope accumulator_result(this);
    2836     4179002 :   BuildVariableLoad(variable, hole_check_mode, typeof_mode);
    2837     4179106 : }
    2838             : 
    2839     7318380 : void BytecodeGenerator::BuildReturn(int source_position) {
    2840     2439460 :   if (FLAG_trace) {
    2841             :     RegisterAllocationScope register_scope(this);
    2842           0 :     Register result = register_allocator()->NewRegister();
    2843             :     // Runtime returns {result} value, preserving accumulator.
    2844           0 :     builder()->StoreAccumulatorInRegister(result).CallRuntime(
    2845           0 :         Runtime::kTraceExit, result);
    2846             :   }
    2847     2439460 :   if (info()->collect_type_profile()) {
    2848          68 :     builder()->CollectTypeProfile(info()->literal()->return_position());
    2849             :   }
    2850     2439460 :   builder()->SetReturnPosition(source_position, info()->literal());
    2851     2439551 :   builder()->Return();
    2852     2439605 : }
    2853             : 
    2854       20114 : void BytecodeGenerator::BuildAsyncReturn(int source_position) {
    2855             :   RegisterAllocationScope register_scope(this);
    2856             : 
    2857       14112 :   if (IsAsyncGeneratorFunction(info()->literal()->kind())) {
    2858        1055 :     RegisterList args = register_allocator()->NewRegisterList(3);
    2859             :     builder()
    2860        1055 :         ->MoveRegister(generator_object(), args[0])  // generator
    2861        1055 :         .StoreAccumulatorInRegister(args[1])         // value
    2862        1055 :         .LoadTrue()
    2863        1055 :         .StoreAccumulatorInRegister(args[2])  // done
    2864        1055 :         .CallRuntime(Runtime::kInlineAsyncGeneratorResolve, args);
    2865             :   } else {
    2866             :     DCHECK(IsAsyncFunction(info()->literal()->kind()));
    2867        6001 :     RegisterList args = register_allocator()->NewRegisterList(3);
    2868             :     builder()
    2869        6002 :         ->MoveRegister(generator_object(), args[0])  // generator
    2870        6002 :         .StoreAccumulatorInRegister(args[1])         // value
    2871       18006 :         .LoadBoolean(info()->literal()->CanSuspend())
    2872        6002 :         .StoreAccumulatorInRegister(args[2])  // can_suspend
    2873        6002 :         .CallRuntime(Runtime::kInlineAsyncFunctionResolve, args);
    2874             :   }
    2875             : 
    2876        7057 :   BuildReturn(source_position);
    2877        7057 : }
    2878             : 
    2879       35595 : void BytecodeGenerator::BuildReThrow() { builder()->ReThrow(); }
    2880             : 
    2881     2770252 : void BytecodeGenerator::BuildThrowIfHole(Variable* variable) {
    2882     2469920 :   if (variable->is_this()) {
    2883             :     DCHECK(variable->mode() == VariableMode::kConst);
    2884     2169588 :     builder()->ThrowSuperNotCalledIfHole();
    2885             :   } else {
    2886      300332 :     builder()->ThrowReferenceErrorIfHole(variable->raw_name());
    2887             :   }
    2888     2469921 : }
    2889             : 
    2890       39056 : void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
    2891             :                                                             Token::Value op) {
    2892       41579 :   if (variable->is_this() && variable->mode() == VariableMode::kConst &&
    2893             :       op == Token::INIT) {
    2894             :     // Perform an initialization check for 'this'. 'this' variable is the
    2895             :     // only variable able to trigger bind operations outside the TDZ
    2896             :     // via 'super' calls.
    2897        2523 :     builder()->ThrowSuperAlreadyCalledIfNotHole();
    2898             :   } else {
    2899             :     // Perform an initialization check for let/const declared variables.
    2900             :     // E.g. let x = (x = 20); is not allowed.
    2901             :     DCHECK(IsLexicalVariableMode(variable->mode()));
    2902       36533 :     BuildThrowIfHole(variable);
    2903             :   }
    2904       39056 : }
    2905             : 
    2906     5585213 : void BytecodeGenerator::BuildVariableAssignment(
    2907    12874936 :     Variable* variable, Token::Value op, HoleCheckMode hole_check_mode,
    2908     3362149 :     LookupHoistingMode lookup_hoisting_mode) {
    2909             :   VariableMode mode = variable->mode();
    2910             :   RegisterAllocationScope assignment_register_scope(this);
    2911             :   BytecodeLabel end_label;
    2912     5585213 :   switch (variable->location()) {
    2913             :     case VariableLocation::PARAMETER:
    2914             :     case VariableLocation::LOCAL: {
    2915             :       Register destination;
    2916     2410897 :       if (VariableLocation::PARAMETER == variable->location()) {
    2917       27040 :         if (variable->IsReceiver()) {
    2918        2367 :           destination = builder()->Receiver();
    2919             :         } else {
    2920       24673 :           destination = builder()->Parameter(variable->index());
    2921             :         }
    2922             :       } else {
    2923     2383857 :         destination = builder()->Local(variable->index());
    2924             :       }
    2925             : 
    2926     2410897 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    2927             :         // Load destination to check for hole.
    2928        4932 :         Register value_temp = register_allocator()->NewRegister();
    2929             :         builder()
    2930        4932 :             ->StoreAccumulatorInRegister(value_temp)
    2931        4932 :             .LoadAccumulatorWithRegister(destination);
    2932             : 
    2933        4932 :         BuildHoleCheckForVariableAssignment(variable, op);
    2934        4932 :         builder()->LoadAccumulatorWithRegister(value_temp);
    2935             :       }
    2936             : 
    2937     2410897 :       if (mode != VariableMode::kConst || op == Token::INIT) {
    2938     2406035 :         builder()->StoreAccumulatorInRegister(destination);
    2939        4862 :       } else if (variable->throw_on_const_assignment(language_mode())) {
    2940        4829 :         builder()->CallRuntime(Runtime::kThrowConstAssignError);
    2941             :       }
    2942             :       break;
    2943             :     }
    2944             :     case VariableLocation::UNALLOCATED: {
    2945     1438519 :       FeedbackSlot slot = GetCachedStoreGlobalICSlot(language_mode(), variable);
    2946     1438572 :       builder()->StoreGlobal(variable->raw_name(), feedback_index(slot));
    2947             :       break;
    2948             :     }
    2949             :     case VariableLocation::CONTEXT: {
    2950     1663668 :       int depth = execution_context()->ContextChainDepth(variable->scope());
    2951             :       ContextScope* context = execution_context()->Previous(depth);
    2952             :       Register context_reg;
    2953             : 
    2954     1663669 :       if (context) {
    2955     1651639 :         context_reg = context->reg();
    2956             :         depth = 0;
    2957             :       } else {
    2958       12030 :         context_reg = execution_context()->reg();
    2959             :       }
    2960             : 
    2961     1663669 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    2962             :         // Load destination to check for hole.
    2963       34055 :         Register value_temp = register_allocator()->NewRegister();
    2964             :         builder()
    2965       34055 :             ->StoreAccumulatorInRegister(value_temp)
    2966             :             .LoadContextSlot(context_reg, variable->index(), depth,
    2967       34055 :                              BytecodeArrayBuilder::kMutableSlot);
    2968             : 
    2969       34055 :         BuildHoleCheckForVariableAssignment(variable, op);
    2970       34055 :         builder()->LoadAccumulatorWithRegister(value_temp);
    2971             :       }
    2972             : 
    2973     1663669 :       if (mode != VariableMode::kConst || op == Token::INIT) {
    2974     1635599 :         builder()->StoreContextSlot(context_reg, variable->index(), depth);
    2975       28070 :       } else if (variable->throw_on_const_assignment(language_mode())) {
    2976       28048 :         builder()->CallRuntime(Runtime::kThrowConstAssignError);
    2977             :       }
    2978             :       break;
    2979             :     }
    2980             :     case VariableLocation::LOOKUP: {
    2981             :       builder()->StoreLookupSlot(variable->raw_name(), language_mode(),
    2982       37239 :                                  lookup_hoisting_mode);
    2983       37240 :       break;
    2984             :     }
    2985             :     case VariableLocation::MODULE: {
    2986             :       DCHECK(IsDeclaredVariableMode(mode));
    2987             : 
    2988       34922 :       if (mode == VariableMode::kConst && op != Token::INIT) {
    2989         110 :         builder()->CallRuntime(Runtime::kThrowConstAssignError);
    2990         110 :         break;
    2991             :       }
    2992             : 
    2993             :       // If we don't throw above, we know that we're dealing with an
    2994             :       // export because imports are const and we do not generate initializing
    2995             :       // assignments for them.
    2996             :       DCHECK(variable->IsExport());
    2997             : 
    2998       34812 :       int depth = execution_context()->ContextChainDepth(variable->scope());
    2999       34812 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    3000          69 :         Register value_temp = register_allocator()->NewRegister();
    3001             :         builder()
    3002          69 :             ->StoreAccumulatorInRegister(value_temp)
    3003          69 :             .LoadModuleVariable(variable->index(), depth);
    3004          69 :         BuildHoleCheckForVariableAssignment(variable, op);
    3005          69 :         builder()->LoadAccumulatorWithRegister(value_temp);
    3006             :       }
    3007       34812 :       builder()->StoreModuleVariable(variable->index(), depth);
    3008       34812 :       break;
    3009             :     }
    3010     5585408 :   }
    3011     5585180 : }
    3012             : 
    3013     2336329 : void BytecodeGenerator::BuildLoadNamedProperty(const Expression* object_expr,
    3014             :                                                Register object,
    3015             :                                                const AstRawString* name) {
    3016     2336329 :   if (ShouldOptimizeAsOneShot()) {
    3017     1248916 :     builder()->LoadNamedPropertyNoFeedback(object, name);
    3018             :   } else {
    3019     1087470 :     FeedbackSlot slot = GetCachedLoadICSlot(object_expr, name);
    3020     1087466 :     builder()->LoadNamedProperty(object, name, feedback_index(slot));
    3021             :   }
    3022     2336387 : }
    3023             : 
    3024     2385525 : void BytecodeGenerator::BuildStoreNamedProperty(const Expression* object_expr,
    3025             :                                                 Register object,
    3026     4771078 :                                                 const AstRawString* name) {
    3027             :   Register value;
    3028     2385525 :   if (!execution_result()->IsEffect()) {
    3029        8305 :     value = register_allocator()->NewRegister();
    3030        8305 :     builder()->StoreAccumulatorInRegister(value);
    3031             :   }
    3032             : 
    3033     2385525 :   if (ShouldOptimizeAsOneShot()) {
    3034      112869 :     builder()->StoreNamedPropertyNoFeedback(object, name, language_mode());
    3035             :   } else {
    3036     2272664 :     FeedbackSlot slot = GetCachedStoreICSlot(object_expr, name);
    3037             :     builder()->StoreNamedProperty(object, name, feedback_index(slot),
    3038     2272663 :                                   language_mode());
    3039             :   }
    3040             : 
    3041     2385553 :   if (!execution_result()->IsEffect()) {
    3042        8305 :     builder()->LoadAccumulatorWithRegister(value);
    3043             :   }
    3044     2385552 : }
    3045             : 
    3046             : // static
    3047             : BytecodeGenerator::AssignmentLhsData
    3048           0 : BytecodeGenerator::AssignmentLhsData::NonProperty(Expression* expr) {
    3049             :   return AssignmentLhsData(NON_PROPERTY, expr, RegisterList(), Register(),
    3050           0 :                            Register(), nullptr, nullptr);
    3051             : }
    3052             : // static
    3053             : BytecodeGenerator::AssignmentLhsData
    3054           0 : BytecodeGenerator::AssignmentLhsData::NamedProperty(Expression* object_expr,
    3055             :                                                     Register object,
    3056             :                                                     const AstRawString* name) {
    3057             :   return AssignmentLhsData(NAMED_PROPERTY, nullptr, RegisterList(), object,
    3058           0 :                            Register(), object_expr, name);
    3059             : }
    3060             : // static
    3061             : BytecodeGenerator::AssignmentLhsData
    3062           0 : BytecodeGenerator::AssignmentLhsData::KeyedProperty(Register object,
    3063             :                                                     Register key) {
    3064             :   return AssignmentLhsData(KEYED_PROPERTY, nullptr, RegisterList(), object, key,
    3065           0 :                            nullptr, nullptr);
    3066             : }
    3067             : // static
    3068             : BytecodeGenerator::AssignmentLhsData
    3069           0 : BytecodeGenerator::AssignmentLhsData::NamedSuperProperty(
    3070             :     RegisterList super_property_args) {
    3071             :   return AssignmentLhsData(NAMED_SUPER_PROPERTY, nullptr, super_property_args,
    3072           0 :                            Register(), Register(), nullptr, nullptr);
    3073             : }
    3074             : // static
    3075             : BytecodeGenerator::AssignmentLhsData
    3076           0 : BytecodeGenerator::AssignmentLhsData::KeyedSuperProperty(
    3077             :     RegisterList super_property_args) {
    3078             :   return AssignmentLhsData(KEYED_SUPER_PROPERTY, nullptr, super_property_args,
    3079           0 :                            Register(), Register(), nullptr, nullptr);
    3080             : }
    3081             : 
    3082     7470875 : BytecodeGenerator::AssignmentLhsData BytecodeGenerator::PrepareAssignmentLhs(
    3083             :     Expression* lhs, AccumulatorPreservingMode accumulator_preserving_mode) {
    3084             :   // Left-hand side can only be a property, a global or a variable slot.
    3085    14690684 :   Property* property = lhs->AsProperty();
    3086     7470912 :   AssignType assign_type = Property::GetAssignType(property);
    3087             : 
    3088             :   // Evaluate LHS expression.
    3089     7470878 :   switch (assign_type) {
    3090             :     case NON_PROPERTY:
    3091             :       return AssignmentLhsData::NonProperty(lhs);
    3092             :     case NAMED_PROPERTY: {
    3093     2385537 :       AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
    3094     2385534 :       Register object = VisitForRegisterValue(property->obj());
    3095             :       const AstRawString* name =
    3096     4771101 :           property->key()->AsLiteral()->AsRawPropertyName();
    3097             :       return AssignmentLhsData::NamedProperty(property->obj(), object, name);
    3098             :     }
    3099             :     case KEYED_PROPERTY: {
    3100       31017 :       AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
    3101       31020 :       Register object = VisitForRegisterValue(property->obj());
    3102       31034 :       Register key = VisitForRegisterValue(property->key());
    3103             :       return AssignmentLhsData::KeyedProperty(object, key);
    3104             :     }
    3105             :     case NAMED_SUPER_PROPERTY: {
    3106         220 :       AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
    3107             :       RegisterList super_property_args =
    3108         220 :           register_allocator()->NewRegisterList(4);
    3109         220 :       SuperPropertyReference* super_property =
    3110         220 :           property->obj()->AsSuperPropertyReference();
    3111         220 :       BuildThisVariableLoad();
    3112         220 :       builder()->StoreAccumulatorInRegister(super_property_args[0]);
    3113             :       VisitForRegisterValue(super_property->home_object(),
    3114             :                             super_property_args[1]);
    3115             :       builder()
    3116         440 :           ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
    3117         220 :           .StoreAccumulatorInRegister(super_property_args[2]);
    3118             :       return AssignmentLhsData::NamedSuperProperty(super_property_args);
    3119             :     }
    3120             :     case KEYED_SUPER_PROPERTY: {
    3121         340 :       AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
    3122             :       RegisterList super_property_args =
    3123         340 :           register_allocator()->NewRegisterList(4);
    3124         340 :       SuperPropertyReference* super_property =
    3125         340 :           property->obj()->AsSuperPropertyReference();
    3126         340 :       BuildThisVariableLoad();
    3127         340 :       builder()->StoreAccumulatorInRegister(super_property_args[0]);
    3128             :       VisitForRegisterValue(super_property->home_object(),
    3129             :                             super_property_args[1]);
    3130             :       VisitForRegisterValue(property->key(), super_property_args[2]);
    3131             :       return AssignmentLhsData::KeyedSuperProperty(super_property_args);
    3132             :     }
    3133             :   }
    3134           0 :   UNREACHABLE();
    3135             : }
    3136             : 
    3137             : // Build the iteration finalizer called in the finally block of an iteration
    3138             : // protocol execution. This closes the iterator if needed, and suppresses any
    3139             : // exception it throws if necessary.
    3140             : //
    3141             : // In pseudo-code, this builds:
    3142             : //
    3143             : // if (!done) {
    3144             : //   let method = iterator.return
    3145             : //   if (method !== null && method !== undefined) {
    3146             : //     if (typeof(method) !== "function") throw TypeError
    3147             : //     try {
    3148             : //       let return_val = method.call(iterator)
    3149             : //       if (!%IsObject(return_val)) throw TypeError
    3150             : //     } catch (e) {
    3151             : //       if (iteration_continuation != RETHROW)
    3152             : //         rethrow e
    3153             : //     }
    3154             : //   }
    3155             : // }
    3156             : //
    3157             : // For async iterators, iterator.close() becomes await iterator.close().
    3158       38168 : void BytecodeGenerator::BuildFinalizeIteration(
    3159             :     IteratorRecord iterator, Register done,
    3160      114519 :     Register iteration_continuation_token) {
    3161             :   RegisterAllocationScope register_scope(this);
    3162             :   BytecodeLabels iterator_is_done(zone());
    3163             : 
    3164             :   // if (!done) {
    3165       38175 :   builder()->LoadAccumulatorWithRegister(done).JumpIfTrue(
    3166       76345 :       ToBooleanMode::kConvertToBoolean, iterator_is_done.New());
    3167             : 
    3168             :   //   method = iterator.return
    3169             :   //   if (method !== null && method !== undefined) {
    3170       38176 :   Register method = register_allocator()->NewRegister();
    3171             :   builder()
    3172             :       ->LoadNamedProperty(iterator.object(),
    3173             :                           ast_string_constants()->return_string(),
    3174       76349 :                           feedback_index(feedback_spec()->AddLoadICSlot()))
    3175       38175 :       .StoreAccumulatorInRegister(method)
    3176       76351 :       .JumpIfUndefined(iterator_is_done.New())
    3177       76351 :       .JumpIfNull(iterator_is_done.New());
    3178             : 
    3179             :   //     if (typeof(method) !== "function") throw TypeError
    3180             :   BytecodeLabel if_callable;
    3181             :   builder()
    3182       38177 :       ->CompareTypeOf(TestTypeOfFlags::LiteralFlag::kFunction)
    3183       38175 :       .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &if_callable);
    3184             :   {
    3185             :     // throw %NewTypeError(kReturnMethodNotCallable)
    3186             :     RegisterAllocationScope register_scope(this);
    3187       38176 :     RegisterList new_type_error_args = register_allocator()->NewRegisterList(2);
    3188             :     builder()
    3189       38175 :         ->LoadLiteral(Smi::FromEnum(MessageTemplate::kReturnMethodNotCallable))
    3190       38176 :         .StoreAccumulatorInRegister(new_type_error_args[0])
    3191       76350 :         .LoadLiteral(ast_string_constants()->empty_string())
    3192       38177 :         .StoreAccumulatorInRegister(new_type_error_args[1])
    3193       38177 :         .CallRuntime(Runtime::kNewTypeError, new_type_error_args)
    3194       38177 :         .Throw();
    3195             :   }
    3196       38177 :   builder()->Bind(&if_callable);
    3197             : 
    3198             :   {
    3199             :     RegisterAllocationScope register_scope(this);
    3200             :     BuildTryCatch(
    3201             :         // try {
    3202             :         //   let return_val = method.call(iterator)
    3203             :         //   if (!%IsObject(return_val)) throw TypeError
    3204             :         // }
    3205       38173 :         [&]() {
    3206       76350 :           RegisterList args(iterator.object());
    3207             :           builder()->CallProperty(
    3208      114519 :               method, args, feedback_index(feedback_spec()->AddCallICSlot()));
    3209       76354 :           if (iterator.type() == IteratorType::kAsync) {
    3210         335 :             BuildAwait();
    3211             :           }
    3212       38178 :           builder()->JumpIfJSReceiver(iterator_is_done.New());
    3213             :           {
    3214             :             // Throw this exception inside the try block so that it is
    3215             :             // suppressed by the iteration continuation if necessary.
    3216       38177 :             RegisterAllocationScope register_scope(this);
    3217       38177 :             Register return_result = register_allocator()->NewRegister();
    3218             :             builder()
    3219       38177 :                 ->StoreAccumulatorInRegister(return_result)
    3220             :                 .CallRuntime(Runtime::kThrowIteratorResultNotAnObject,
    3221       38176 :                              return_result);
    3222             :           }
    3223       38177 :         },
    3224             : 
    3225             :         // catch (e) {
    3226             :         //   if (iteration_continuation != RETHROW)
    3227             :         //     rethrow e
    3228             :         // }
    3229       38171 :         [&](Register context) {
    3230             :           // Reuse context register to store the exception.
    3231       38171 :           Register close_exception = context;
    3232       38171 :           builder()->StoreAccumulatorInRegister(close_exception);
    3233             : 
    3234             :           BytecodeLabel suppress_close_exception;
    3235             :           builder()
    3236             :               ->LoadLiteral(
    3237       38177 :                   Smi::FromInt(ControlScope::DeferredCommands::kRethrowToken))
    3238       76354 :               .CompareReference(iteration_continuation_token)
    3239             :               .JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
    3240       38174 :                           &suppress_close_exception)
    3241       38177 :               .LoadAccumulatorWithRegister(close_exception)
    3242       38177 :               .ReThrow()
    3243       38175 :               .Bind(&suppress_close_exception);
    3244       38177 :         },
    3245       38177 :         HandlerTable::UNCAUGHT);
    3246             :   }
    3247             : 
    3248       76348 :   iterator_is_done.Bind(builder());
    3249       38177 : }
    3250             : 
    3251             : // Get the default value of a destructuring target. Will mutate the
    3252             : // destructuring target expression if there is a default value.
    3253             : //
    3254             : // For
    3255             : //   a = b
    3256             : // in
    3257             : //   let {a = b} = c
    3258             : // returns b and mutates the input into a.
    3259       22554 : Expression* BytecodeGenerator::GetDestructuringDefaultValue(
    3260             :     Expression** target) {
    3261             :   Expression* default_value = nullptr;
    3262       45109 :   if ((*target)->IsAssignment()) {
    3263        3778 :     Assignment* default_init = (*target)->AsAssignment();
    3264             :     DCHECK_EQ(default_init->op(), Token::ASSIGN);
    3265             :     default_value = default_init->value();
    3266        1889 :     *target = default_init->target();
    3267             :     DCHECK((*target)->IsValidReferenceExpression() || (*target)->IsPattern());
    3268             :   }
    3269       22555 :   return default_value;
    3270             : }
    3271             : 
    3272             : // Convert a destructuring assignment to an array literal into a sequence of
    3273             : // iterator accesses into the value being assigned (in the accumulator).
    3274             : //
    3275             : // [a().x, ...b] = accumulator
    3276             : //
    3277             : //   becomes
    3278             : //
    3279             : // iterator = %GetIterator(accumulator)
    3280             : // try {
    3281             : //
    3282             : //   // Individual assignments read off the value from iterator.next() This gets
    3283             : //   // repeated per destructuring element.
    3284             : //   if (!done) {
    3285             : //     // Make sure we are considered 'done' if .next(), .done or .value fail.
    3286             : //     done = true
    3287             : //     var next_result = iterator.next()
    3288             : //     var tmp_done = next_result.done
    3289             : //     if (!tmp_done) {
    3290             : //       value = next_result.value
    3291             : //       done = false
    3292             : //     }
    3293             : //   }
    3294             : //   if (done)
    3295             : //     value = undefined
    3296             : //   a().x = value
    3297             : //
    3298             : //   // A spread receives the remaining items in the iterator.
    3299             : //   var array = []
    3300             : //   var index = 0
    3301             : //   %FillArrayWithIterator(iterator, array, index, done)
    3302             : //   done = true
    3303             : //   b = array
    3304             : //
    3305             : // } catch(e) {
    3306             : //   iteration_continuation = RETHROW
    3307             : // } finally {
    3308             : //   %FinalizeIteration(iterator, done, iteration_continuation)
    3309             : // }
    3310        2714 : void BytecodeGenerator::BuildDestructuringArrayAssignment(
    3311             :     ArrayLiteral* pattern, Token::Value op,
    3312        2716 :     LookupHoistingMode lookup_hoisting_mode) {
    3313             :   RegisterAllocationScope scope(this);
    3314             : 
    3315        2714 :   Register value = register_allocator()->NewRegister();
    3316        2715 :   builder()->StoreAccumulatorInRegister(value);
    3317             : 
    3318             :   // Store the iterator in a dedicated register so that it can be closed on
    3319             :   // exit, and the 'done' value in a dedicated register so that it can be
    3320             :   // changed and accessed independently of the iteration result.
    3321        2717 :   IteratorRecord iterator = BuildGetIteratorRecord(IteratorType::kNormal);
    3322        2717 :   Register done = register_allocator()->NewRegister();
    3323        2714 :   builder()->LoadFalse();
    3324        2716 :   builder()->StoreAccumulatorInRegister(done);
    3325             : 
    3326             :   BuildTryFinally(
    3327             :       // Try block.
    3328        2714 :       [&]() {
    3329       13286 :         Register next_result = register_allocator()->NewRegister();
    3330        5434 :         FeedbackSlot next_value_load_slot = feedback_spec()->AddLoadICSlot();
    3331        5432 :         FeedbackSlot next_done_load_slot = feedback_spec()->AddLoadICSlot();
    3332             : 
    3333         582 :         Spread* spread = nullptr;
    3334        8956 :         for (Expression* target : *pattern->values()) {
    3335        4105 :           if (target->IsSpread()) {
    3336         582 :             spread = target->AsSpread();
    3337         582 :             break;
    3338             :           }
    3339             : 
    3340        3523 :           Expression* default_value = GetDestructuringDefaultValue(&target);
    3341        7044 :           if (!target->IsPattern()) {
    3342        3183 :             builder()->SetExpressionAsStatementPosition(target);
    3343             :           }
    3344             : 
    3345        3522 :           AssignmentLhsData lhs_data = PrepareAssignmentLhs(target);
    3346             : 
    3347             :           // if (!done) {
    3348             :           //   // Make sure we are considered done if .next(), .done or .value
    3349             :           //   // fail.
    3350             :           //   done = true
    3351             :           //   var next_result = iterator.next()
    3352             :           //   var tmp_done = next_result.done
    3353             :           //   if (!tmp_done) {
    3354             :           //     value = next_result.value
    3355             :           //     done = false
    3356             :           //   }
    3357             :           // }
    3358             :           // if (done)
    3359             :           //   value = undefined
    3360        3524 :           BytecodeLabels is_done(zone());
    3361             : 
    3362        3524 :           builder()->LoadAccumulatorWithRegister(done);
    3363             :           builder()->JumpIfTrue(ToBooleanMode::kConvertToBoolean,
    3364        3524 :                                 is_done.New());
    3365             : 
    3366        3524 :           builder()->LoadTrue().StoreAccumulatorInRegister(done);
    3367        3524 :           BuildIteratorNext(iterator, next_result);
    3368             :           builder()
    3369             :               ->LoadNamedProperty(next_result,
    3370             :                                   ast_string_constants()->done_string(),
    3371        7048 :                                   feedback_index(next_done_load_slot))
    3372        7048 :               .JumpIfTrue(ToBooleanMode::kConvertToBoolean, is_done.New())
    3373             :               .LoadNamedProperty(next_result,
    3374             :                                  ast_string_constants()->value_string(),
    3375       10572 :                                  feedback_index(next_value_load_slot))
    3376        3524 :               .StoreAccumulatorInRegister(next_result)
    3377        3524 :               .LoadFalse()
    3378        7048 :               .StoreAccumulatorInRegister(done)
    3379        3524 :               .LoadAccumulatorWithRegister(next_result);
    3380             : 
    3381             :           // Only do the assignment if this is not a hole (i.e. 'elided').
    3382        3521 :           if (!target->IsTheHoleLiteral()) {
    3383             :             // [<pattern> = <init>] = <value>
    3384             :             //   becomes (roughly)
    3385             :             // temp = <value>.next();
    3386             :             // <pattern> = temp === undefined ? <init> : temp;
    3387             :             BytecodeLabel do_assignment;
    3388        3412 :             if (default_value) {
    3389         454 :               builder()->JumpIfNotUndefined(&do_assignment);
    3390             :               // Since done == true => temp == undefined, jump directly to using
    3391             :               // the default value for that case.
    3392         454 :               is_done.Bind(builder());
    3393         454 :               VisitForAccumulatorValue(default_value);
    3394             :             } else {
    3395        2958 :               builder()->Jump(&do_assignment);
    3396        2960 :               is_done.Bind(builder());
    3397        2961 :               builder()->LoadUndefined();
    3398             :             }
    3399        3414 :             builder()->Bind(&do_assignment);
    3400             : 
    3401        3415 :             BuildAssignment(lhs_data, op, lookup_hoisting_mode);
    3402             :           } else {
    3403             :             DCHECK_EQ(lhs_data.assign_type(), NON_PROPERTY);
    3404         109 :             is_done.Bind(builder());
    3405             :           }
    3406             :         }
    3407             : 
    3408        2718 :         if (spread) {
    3409         582 :           RegisterAllocationScope scope(this);
    3410             : 
    3411             :           // A spread is turned into a loop over the remainer of the iterator.
    3412             :           Expression* target = spread->expression();
    3413             : 
    3414         582 :           if (!target->IsPattern()) {
    3415             :             builder()->SetExpressionAsStatementPosition(spread);
    3416             :           }
    3417             : 
    3418         582 :           AssignmentLhsData lhs_data = PrepareAssignmentLhs(target);
    3419             : 
    3420             :           // var array = [];
    3421         582 :           Register array = register_allocator()->NewRegister();
    3422             :           builder()->CreateEmptyArrayLiteral(
    3423        1746 :               feedback_index(feedback_spec()->AddLiteralSlot()));
    3424         583 :           builder()->StoreAccumulatorInRegister(array);
    3425             : 
    3426             :           // var index = 0;
    3427         583 :           Register index = register_allocator()->NewRegister();
    3428         583 :           builder()->LoadLiteral(Smi::zero());
    3429         583 :           builder()->StoreAccumulatorInRegister(index);
    3430             : 
    3431             :           // Set done to true, since it's guaranteed to be true by the time the
    3432             :           // array fill completes.
    3433         583 :           builder()->LoadTrue().StoreAccumulatorInRegister(done);
    3434             : 
    3435             :           // Fill the array with the iterator.
    3436             :           FeedbackSlot element_slot =
    3437        1749 :               feedback_spec()->AddStoreInArrayLiteralICSlot();
    3438        1749 :           FeedbackSlot index_slot = feedback_spec()->AddBinaryOpICSlot();
    3439             :           BuildFillArrayWithIterator(iterator, array, index, next_result,
    3440             :                                      next_value_load_slot, next_done_load_slot,
    3441         583 :                                      index_slot, element_slot);
    3442             : 
    3443             :           // Assign the array to the LHS.
    3444         583 :           builder()->LoadAccumulatorWithRegister(array);
    3445         583 :           BuildAssignment(lhs_data, op, lookup_hoisting_mode);
    3446             :         }
    3447        2719 :       },
    3448             :       // Finally block.
    3449             :       [&](Register iteration_continuation_token) {
    3450             :         // Finish the iteration in the finally block.
    3451        2717 :         BuildFinalizeIteration(iterator, done, iteration_continuation_token);
    3452             :       },
    3453        2716 :       HandlerTable::UNCAUGHT);
    3454             : 
    3455        2716 :   if (!execution_result()->IsEffect()) {
    3456         266 :     builder()->LoadAccumulatorWithRegister(value);
    3457        2716 :   }
    3458        2717 : }
    3459             : 
    3460             : // Convert a destructuring assignment to an object literal into a sequence of
    3461             : // property accesses into the value being assigned (in the accumulator).
    3462             : //
    3463             : // { y, [x++]: a(), ...b.c } = value
    3464             : //
    3465             : //   becomes
    3466             : //
    3467             : // var rest_runtime_callargs = new Array(3);
    3468             : // rest_runtime_callargs[0] = value;
    3469             : //
    3470             : // rest_runtime_callargs[1] = value;
    3471             : // y = value.y;
    3472             : //
    3473             : // var temp1 = %ToName(x++);
    3474             : // rest_runtime_callargs[2] = temp1;
    3475             : // a() = value[temp1];
    3476             : //
    3477             : // b.c = %CopyDataPropertiesWithExcludedProperties.call(rest_runtime_callargs);
    3478       11004 : void BytecodeGenerator::BuildDestructuringObjectAssignment(
    3479       29832 :     ObjectLiteral* pattern, Token::Value op,
    3480       11004 :     LookupHoistingMode lookup_hoisting_mode) {
    3481             :   RegisterAllocationScope scope(this);
    3482             : 
    3483             :   // if (value === null || value === undefined)
    3484             :   //   throw new TypeError(kNonCoercible);
    3485             :   //
    3486             :   // TODO(leszeks): Eliminate check if value is known to be non-null (e.g.
    3487             :   // an object literal).
    3488             :   BytecodeLabel is_null_or_undefined, not_null_or_undefined;
    3489             :   builder()
    3490       11004 :       ->JumpIfNull(&is_null_or_undefined)
    3491       11005 :       .JumpIfNotUndefined(&not_null_or_undefined);
    3492             : 
    3493             :   {
    3494       11005 :     builder()->Bind(&is_null_or_undefined);
    3495             :     builder()->SetExpressionPosition(pattern);
    3496       11005 :     builder()->CallRuntime(Runtime::kThrowPatternAssignmentNonCoercible);
    3497             :   }
    3498             : 
    3499             :   // Store the assignment value in a register.
    3500             :   Register value;
    3501             :   RegisterList rest_runtime_callargs;
    3502       11004 :   if (pattern->has_rest_property()) {
    3503             :     rest_runtime_callargs =
    3504         205 :         register_allocator()->NewRegisterList(pattern->properties()->length());
    3505         205 :     value = rest_runtime_callargs[0];
    3506             :   } else {
    3507       10799 :     value = register_allocator()->NewRegister();
    3508             :   }
    3509       11004 :   builder()->Bind(&not_null_or_undefined).StoreAccumulatorInRegister(value);
    3510             : 
    3511             :   int i = 0;
    3512       79110 :   for (ObjectLiteralProperty* pattern_property : *pattern->properties()) {
    3513             :     RegisterAllocationScope scope(this);
    3514             : 
    3515             :     // The key of the pattern becomes the key into the RHS value, and the value
    3516             :     // of the pattern becomes the target of the assignment.
    3517             :     //
    3518             :     // e.g. { a: b } = o becomes b = o.a
    3519       19033 :     Expression* pattern_key = pattern_property->key();
    3520       19033 :     Expression* target = pattern_property->value();
    3521       19033 :     Expression* default_value = GetDestructuringDefaultValue(&target);
    3522             : 
    3523       38066 :     if (!target->IsPattern()) {
    3524             :       builder()->SetExpressionAsStatementPosition(target);
    3525             :     }
    3526             : 
    3527             :     // Calculate this property's key into the assignment RHS value, additionally
    3528             :     // storing the key for rest_runtime_callargs if needed.
    3529             :     //
    3530             :     // The RHS is accessed using the key either by LoadNamedProperty (if
    3531             :     // value_name is valid) or by LoadKeyedProperty (otherwise).
    3532             :     const AstRawString* value_name = nullptr;
    3533             :     Register value_key;
    3534             : 
    3535       19033 :     if (pattern_property->kind() != ObjectLiteralProperty::Kind::SPREAD) {
    3536       18828 :       if (pattern_key->IsPropertyName()) {
    3537       37016 :         value_name = pattern_key->AsLiteral()->AsRawPropertyName();
    3538             :       }
    3539       18828 :       if (pattern->has_rest_property() || !value_name) {
    3540         383 :         if (pattern->has_rest_property()) {
    3541         129 :           value_key = rest_runtime_callargs[i + 1];
    3542             :         } else {
    3543         254 :           value_key = register_allocator()->NewRegister();
    3544             :         }
    3545         383 :         if (pattern_property->is_computed_name()) {
    3546             :           // { [a()]: b().x } = c
    3547             :           // becomes
    3548             :           // var tmp = a()
    3549             :           // b().x = c[tmp]
    3550             :           DCHECK(!pattern_key->IsPropertyName() ||
    3551             :                  !pattern_key->IsNumberLiteral());
    3552         270 :           VisitForAccumulatorValue(pattern_key);
    3553         270 :           builder()->ToName(value_key);
    3554             :         } else {
    3555             :           // We only need the key for non-computed properties when it is numeric
    3556             :           // or is being saved for the rest_runtime_callargs.
    3557             :           DCHECK(
    3558             :               pattern_key->IsNumberLiteral() ||
    3559             :               (pattern->has_rest_property() && pattern_key->IsPropertyName()));
    3560             :           VisitForRegisterValue(pattern_key, value_key);
    3561             :         }
    3562             :       }
    3563             :     }
    3564             : 
    3565       19033 :     AssignmentLhsData lhs_data = PrepareAssignmentLhs(target);
    3566             : 
    3567             :     // Get the value from the RHS.
    3568       19034 :     if (pattern_property->kind() == ObjectLiteralProperty::Kind::SPREAD) {
    3569             :       DCHECK_EQ(i, pattern->properties()->length() - 1);
    3570             :       DCHECK(!value_key.is_valid());
    3571             :       DCHECK_NULL(value_name);
    3572             :       builder()->CallRuntime(Runtime::kCopyDataPropertiesWithExcludedProperties,
    3573         205 :                              rest_runtime_callargs);
    3574       18829 :     } else if (value_name) {
    3575             :       builder()->LoadNamedProperty(
    3576       37018 :           value, value_name, feedback_index(feedback_spec()->AddLoadICSlot()));
    3577             :     } else {
    3578             :       DCHECK(value_key.is_valid());
    3579         320 :       builder()->LoadAccumulatorWithRegister(value_key).LoadKeyedProperty(
    3580         640 :           value, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
    3581             :     }
    3582             : 
    3583             :     // {<pattern> = <init>} = <value>
    3584             :     //   becomes
    3585             :     // temp = <value>;
    3586             :     // <pattern> = temp === undefined ? <init> : temp;
    3587       19032 :     if (default_value) {
    3588             :       BytecodeLabel value_not_undefined;
    3589        1435 :       builder()->JumpIfNotUndefined(&value_not_undefined);
    3590        1435 :       VisitForAccumulatorValue(default_value);
    3591        1435 :       builder()->Bind(&value_not_undefined);
    3592             :     }
    3593             : 
    3594       19032 :     BuildAssignment(lhs_data, op, lookup_hoisting_mode);
    3595             : 
    3596       19032 :     i++;
    3597       19032 :   }
    3598             : 
    3599       11004 :   if (!execution_result()->IsEffect()) {
    3600         193 :     builder()->LoadAccumulatorWithRegister(value);
    3601       11004 :   }
    3602       11004 : }
    3603             : 
    3604     7470576 : void BytecodeGenerator::BuildAssignment(
    3605    14909611 :     const AssignmentLhsData& lhs_data, Token::Value op,
    3606       62065 :     LookupHoistingMode lookup_hoisting_mode) {
    3607             :   // Assign the value to the LHS.
    3608     7470576 :   switch (lhs_data.assign_type()) {
    3609             :     case NON_PROPERTY: {
    3610    10106963 :       if (ObjectLiteral* pattern = lhs_data.expr()->AsObjectLiteral()) {
    3611             :         // Split object literals into destructuring.
    3612       11005 :         BuildDestructuringObjectAssignment(pattern, op, lookup_hoisting_mode);
    3613     5042466 :       } else if (ArrayLiteral* pattern = lhs_data.expr()->AsArrayLiteral()) {
    3614             :         // Split object literals into destructuring.
    3615        2716 :         BuildDestructuringArrayAssignment(pattern, op, lookup_hoisting_mode);
    3616             :       } else {
    3617             :         DCHECK(lhs_data.expr()->IsVariableProxy());
    3618    10079500 :         VariableProxy* proxy = lhs_data.expr()->AsVariableProxy();
    3619             :         BuildVariableAssignment(proxy->var(), op, proxy->hole_check_mode(),
    3620    10079500 :                                 lookup_hoisting_mode);
    3621             :       }
    3622             :       break;
    3623             :     }
    3624             :     case NAMED_PROPERTY: {
    3625             :       BuildStoreNamedProperty(lhs_data.object_expr(), lhs_data.object(),
    3626     2385543 :                               lhs_data.name());
    3627     2385545 :       break;
    3628             :     }
    3629             :     case KEYED_PROPERTY: {
    3630       31033 :       FeedbackSlot slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
    3631             :       Register value;
    3632       31033 :       if (!execution_result()->IsEffect()) {
    3633        1947 :         value = register_allocator()->NewRegister();
    3634        1947 :         builder()->StoreAccumulatorInRegister(value);
    3635             :       }
    3636             :       builder()->StoreKeyedProperty(lhs_data.object(), lhs_data.key(),
    3637       31021 :                                     feedback_index(slot), language_mode());
    3638       31032 :       if (!execution_result()->IsEffect()) {
    3639        1948 :         builder()->LoadAccumulatorWithRegister(value);
    3640             :       }
    3641             :       break;
    3642             :     }
    3643             :     case NAMED_SUPER_PROPERTY: {
    3644             :       builder()
    3645         220 :           ->StoreAccumulatorInRegister(lhs_data.super_property_args()[3])
    3646         220 :           .CallRuntime(Runtime::kStoreToSuper, lhs_data.super_property_args());
    3647         220 :       break;
    3648             :     }
    3649             :     case KEYED_SUPER_PROPERTY: {
    3650             :       builder()
    3651         340 :           ->StoreAccumulatorInRegister(lhs_data.super_property_args()[3])
    3652             :           .CallRuntime(Runtime::kStoreKeyedToSuper,
    3653         340 :                        lhs_data.super_property_args());
    3654         340 :       break;
    3655             :     }
    3656             :   }
    3657     7470549 : }
    3658             : 
    3659    21962648 : void BytecodeGenerator::VisitAssignment(Assignment* expr) {
    3660     7320922 :   AssignmentLhsData lhs_data = PrepareAssignmentLhs(expr->target());
    3661             : 
    3662     7320913 :   VisitForAccumulatorValue(expr->value());
    3663             : 
    3664             :   builder()->SetExpressionPosition(expr);
    3665     7320813 :   BuildAssignment(lhs_data, expr->op(), expr->lookup_hoisting_mode());
    3666     7320673 : }
    3667             : 
    3668       86637 : void BytecodeGenerator::VisitCompoundAssignment(CompoundAssignment* expr) {
    3669      431814 :   AssignmentLhsData lhs_data = PrepareAssignmentLhs(expr->target());
    3670             : 
    3671             :   // Evaluate the value and potentially handle compound assignments by loading
    3672             :   // the left-hand side value and performing a binary operation.
    3673       86637 :   switch (lhs_data.assign_type()) {
    3674             :     case NON_PROPERTY: {
    3675      255794 :       VariableProxy* proxy = expr->target()->AsVariableProxy();
    3676       85264 :       BuildVariableLoad(proxy->var(), proxy->hole_check_mode());
    3677       85266 :       break;
    3678             :     }
    3679             :     case NAMED_PROPERTY: {
    3680         507 :       BuildLoadNamedProperty(lhs_data.object_expr(), lhs_data.object(),
    3681        1014 :                              lhs_data.name());
    3682         507 :       break;
    3683             :     }
    3684             :     case KEYED_PROPERTY: {
    3685         804 :       FeedbackSlot slot = feedback_spec()->AddKeyedLoadICSlot();
    3686             :       builder()
    3687         804 :           ->LoadAccumulatorWithRegister(lhs_data.key())
    3688         804 :           .LoadKeyedProperty(lhs_data.object(), feedback_index(slot));
    3689             :       break;
    3690             :     }
    3691             :     case NAMED_SUPER_PROPERTY: {
    3692             :       builder()->CallRuntime(Runtime::kLoadFromSuper,
    3693          20 :                              lhs_data.super_property_args().Truncate(3));
    3694          20 :       break;
    3695             :     }
    3696             :     case KEYED_SUPER_PROPERTY: {
    3697             :       builder()->CallRuntime(Runtime::kLoadKeyedFromSuper,
    3698          40 :                              lhs_data.super_property_args().Truncate(3));
    3699          40 :       break;
    3700             :     }
    3701             :   }
    3702      259912 :   BinaryOperation* binop = expr->AsCompoundAssignment()->binary_operation();
    3703       86637 :   FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
    3704       86636 :   if (expr->value()->IsSmiLiteral()) {
    3705             :     builder()->BinaryOperationSmiLiteral(
    3706             :         binop->op(), expr->value()->AsLiteral()->AsSmiLiteral(),
    3707       63198 :         feedback_index(slot));
    3708             :   } else {
    3709       65569 :     Register old_value = register_allocator()->NewRegister();
    3710       65568 :     builder()->StoreAccumulatorInRegister(old_value);
    3711       65571 :     VisitForAccumulatorValue(expr->value());
    3712       65572 :     builder()->BinaryOperation(binop->op(), old_value, feedback_index(slot));
    3713             :   }
    3714             : 
    3715             :   builder()->SetExpressionPosition(expr);
    3716       86638 :   BuildAssignment(lhs_data, expr->op(), expr->lookup_hoisting_mode());
    3717       86639 : }
    3718             : 
    3719             : // Suspends the generator to resume at the next suspend_id, with output stored
    3720             : // in the accumulator. When the generator is resumed, the sent value is loaded
    3721             : // in the accumulator.
    3722       23606 : void BytecodeGenerator::BuildSuspendPoint(int position) {
    3723       23606 :   const int suspend_id = suspend_count_++;
    3724             : 
    3725       23606 :   RegisterList registers = register_allocator()->AllLiveRegisters();
    3726             : 
    3727             :   // Save context, registers, and state. This bytecode then returns the value
    3728             :   // in the accumulator.
    3729             :   builder()->SetExpressionPosition(position);
    3730       23606 :   builder()->SuspendGenerator(generator_object(), registers, suspend_id);
    3731             : 
    3732             :   // Upon resume, we continue here.
    3733       23607 :   builder()->Bind(generator_jump_table_, suspend_id);
    3734             : 
    3735             :   // Clobbers all registers and sets the accumulator to the
    3736             :   // [[input_or_debug_pos]] slot of the generator object.
    3737       23607 :   builder()->ResumeGenerator(generator_object(), registers);
    3738       23607 : }
    3739             : 
    3740       17224 : void BytecodeGenerator::VisitYield(Yield* expr) {
    3741             :   builder()->SetExpressionPosition(expr);
    3742       16840 :   VisitForAccumulatorValue(expr->expression());
    3743             : 
    3744             :   // If this is not the first yield
    3745        8420 :   if (suspend_count_ > 0) {
    3746        3438 :     if (IsAsyncGeneratorFunction(function_kind())) {
    3747             :       // AsyncGenerator yields (with the exception of the initial yield)
    3748             :       // delegate work to the AsyncGeneratorYield stub, which Awaits the operand
    3749             :       // and on success, wraps the value in an IteratorResult.
    3750             :       RegisterAllocationScope register_scope(this);
    3751         384 :       RegisterList args = register_allocator()->NewRegisterList(3);
    3752             :       builder()
    3753         384 :           ->MoveRegister(generator_object(), args[0])  // generator
    3754         384 :           .StoreAccumulatorInRegister(args[1])         // value
    3755         768 :           .LoadBoolean(catch_prediction() != HandlerTable::ASYNC_AWAIT)
    3756         384 :           .StoreAccumulatorInRegister(args[2])  // is_caught
    3757         384 :           .CallRuntime(Runtime::kInlineAsyncGeneratorYield, args);
    3758             :     } else {
    3759             :       // Generator yields (with the exception of the initial yield) wrap the
    3760             :       // value into IteratorResult.
    3761             :       RegisterAllocationScope register_scope(this);
    3762        3054 :       RegisterList args = register_allocator()->NewRegisterList(2);
    3763             :       builder()
    3764        3054 :           ->StoreAccumulatorInRegister(args[0])  // value
    3765        3054 :           .LoadFalse()
    3766        3054 :           .StoreAccumulatorInRegister(args[1])  // done
    3767        3054 :           .CallRuntime(Runtime::kInlineCreateIterResultObject, args);
    3768             :     }
    3769             :   }
    3770             : 
    3771        8420 :   BuildSuspendPoint(expr->position());
    3772             :   // At this point, the generator has been resumed, with the received value in
    3773             :   // the accumulator.
    3774             : 
    3775             :   // TODO(caitp): remove once yield* desugaring for async generators is handled
    3776             :   // in BytecodeGenerator.
    3777        8420 :   if (expr->on_abrupt_resume() == Yield::kNoControl) {
    3778             :     DCHECK(IsAsyncGeneratorFunction(function_kind()));
    3779           0 :     return;
    3780             :   }
    3781             : 
    3782        8420 :   Register input = register_allocator()->NewRegister();
    3783        8420 :   builder()->StoreAccumulatorInRegister(input).CallRuntime(
    3784        8420 :       Runtime::kInlineGeneratorGetResumeMode, generator_object());
    3785             : 
    3786             :   // Now dispatch on resume mode.
    3787             :   STATIC_ASSERT(JSGeneratorObject::kNext + 1 == JSGeneratorObject::kReturn);
    3788             :   BytecodeJumpTable* jump_table =
    3789        8420 :       builder()->AllocateJumpTable(2, JSGeneratorObject::kNext);
    3790             : 
    3791        8420 :   builder()->SwitchOnSmiNoFeedback(jump_table);
    3792             : 
    3793             :   {
    3794             :     // Resume with throw (switch fallthrough).
    3795             :     // TODO(leszeks): Add a debug-only check that the accumulator is
    3796             :     // JSGeneratorObject::kThrow.
    3797             :     builder()->SetExpressionPosition(expr);
    3798        8420 :     builder()->LoadAccumulatorWithRegister(input);
    3799        8420 :     builder()->Throw();
    3800             :   }
    3801             : 
    3802             :   {
    3803             :     // Resume with return.
    3804        8420 :     builder()->Bind(jump_table, JSGeneratorObject::kReturn);
    3805        8420 :     builder()->LoadAccumulatorWithRegister(input);
    3806        8420 :     if (IsAsyncGeneratorFunction(function_kind())) {
    3807             :       execution_control()->AsyncReturnAccumulator();
    3808             :     } else {
    3809             :       execution_control()->ReturnAccumulator();
    3810             :     }
    3811             :   }
    3812             : 
    3813             :   {
    3814             :     // Resume with next.
    3815        8420 :     builder()->Bind(jump_table, JSGeneratorObject::kNext);
    3816             :     BuildIncrementBlockCoverageCounterIfEnabled(expr,
    3817             :                                                 SourceRangeKind::kContinuation);
    3818        8420 :     builder()->LoadAccumulatorWithRegister(input);
    3819             :   }
    3820             : }
    3821             : 
    3822             : // Desugaring of (yield* iterable)
    3823             : //
    3824             : //   do {
    3825             : //     const kNext = 0;
    3826             : //     const kReturn = 1;
    3827             : //     const kThrow = 2;
    3828             : //
    3829             : //     let output; // uninitialized
    3830             : //
    3831             : //     let iteratorRecord = GetIterator(iterable);
    3832             : //     let iterator = iteratorRecord.[[Iterator]];
    3833             : //     let next = iteratorRecord.[[NextMethod]];
    3834             : //     let input = undefined;
    3835             : //     let resumeMode = kNext;
    3836             : //
    3837             : //     while (true) {
    3838             : //       // From the generator to the iterator:
    3839             : //       // Forward input according to resumeMode and obtain output.
    3840             : //       switch (resumeMode) {
    3841             : //         case kNext:
    3842             : //           output = next.[[Call]](iterator, « »);;
    3843             : //           break;
    3844             : //         case kReturn:
    3845             : //           let iteratorReturn = iterator.return;
    3846             : //           if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input;
    3847             : //           output = iteratorReturn.[[Call]](iterator, «input»);
    3848             : //           break;
    3849             : //         case kThrow:
    3850             : //           let iteratorThrow = iterator.throw;
    3851             : //           if (IS_NULL_OR_UNDEFINED(iteratorThrow)) {
    3852             : //             let iteratorReturn = iterator.return;
    3853             : //             if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
    3854             : //               output = iteratorReturn.[[Call]](iterator, « »);
    3855             : //               if (IS_ASYNC_GENERATOR) output = await output;
    3856             : //               if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
    3857             : //             }
    3858             : //             throw MakeTypeError(kThrowMethodMissing);
    3859             : //           }
    3860             : //           output = iteratorThrow.[[Call]](iterator, «input»);
    3861             : //           break;
    3862             : //       }
    3863             : //
    3864             : //       if (IS_ASYNC_GENERATOR) output = await output;
    3865             : //       if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
    3866             : //       if (output.done) break;
    3867             : //
    3868             : //       // From the generator to its user:
    3869             : //       // Forward output, receive new input, and determine resume mode.
    3870             : //       if (IS_ASYNC_GENERATOR) {
    3871             : //         // AsyncGeneratorYield abstract operation awaits the operand before
    3872             : //         // resolving the promise for the current AsyncGeneratorRequest.
    3873             : //         %_AsyncGeneratorYield(output.value)
    3874             : //       }
    3875             : //       input = Suspend(output);
    3876             : //       resumeMode = %GeneratorGetResumeMode();
    3877             : //     }
    3878             : //
    3879             : //     if (resumeMode === kReturn) {
    3880             : //       return output.value;
    3881             : //     }
    3882             : //     output.value
    3883             : //   }
    3884        1960 : void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
    3885         194 :   Register output = register_allocator()->NewRegister();
    3886         194 :   Register resume_mode = register_allocator()->NewRegister();
    3887             :   IteratorType iterator_type = IsAsyncGeneratorFunction(function_kind())
    3888             :                                    ? IteratorType::kAsync
    3889         194 :                                    : IteratorType::kNormal;
    3890             : 
    3891             :   {
    3892             :     RegisterAllocationScope register_scope(this);
    3893         194 :     RegisterList iterator_and_input = register_allocator()->NewRegisterList(2);
    3894         194 :     VisitForAccumulatorValue(expr->expression());
    3895             :     IteratorRecord iterator = BuildGetIteratorRecord(
    3896             :         register_allocator()->NewRegister() /* next method */,
    3897         194 :         iterator_and_input[0], iterator_type);
    3898             : 
    3899         194 :     Register input = iterator_and_input[1];
    3900         194 :     builder()->LoadUndefined().StoreAccumulatorInRegister(input);
    3901             :     builder()
    3902         194 :         ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
    3903         194 :         .StoreAccumulatorInRegister(resume_mode);
    3904             : 
    3905             :     {
    3906             :       // This loop builder does not construct counters as the loop is not
    3907             :       // visible to the user, and we therefore neither pass the block coverage
    3908             :       // builder nor the expression.
    3909             :       //
    3910             :       // In addition to the normal suspend for yield*, a yield* in an async
    3911             :       // generator has 2 additional suspends:
    3912             :       //   - One for awaiting the iterator result of closing the generator when
    3913             :       //     resumed with a "throw" completion, and a throw method is not
    3914             :       //     present on the delegated iterator
    3915             :       //   - One for awaiting the iterator result yielded by the delegated
    3916             :       //     iterator
    3917             : 
    3918         194 :       LoopBuilder loop(builder(), nullptr, nullptr);
    3919         194 :       loop.LoopHeader();
    3920             : 
    3921             :       {
    3922             :         BytecodeLabels after_switch(zone());
    3923             :         BytecodeJumpTable* switch_jump_table =
    3924         194 :             builder()->AllocateJumpTable(2, 1);
    3925             : 
    3926             :         builder()
    3927         194 :             ->LoadAccumulatorWithRegister(resume_mode)
    3928         194 :             .SwitchOnSmiNoFeedback(switch_jump_table);
    3929             : 
    3930             :         // Fallthrough to default case.
    3931             :         // TODO(tebbi): Add debug code to check that {resume_mode} really is
    3932             :         // {JSGeneratorObject::kNext} in this case.
    3933             :         STATIC_ASSERT(JSGeneratorObject::kNext == 0);
    3934             :         {
    3935         194 :           FeedbackSlot slot = feedback_spec()->AddCallICSlot();
    3936             :           builder()->CallProperty(iterator.next(), iterator_and_input,
    3937         194 :                                   feedback_index(slot));
    3938         194 :           builder()->Jump(after_switch.New());
    3939             :         }
    3940             : 
    3941             :         STATIC_ASSERT(JSGeneratorObject::kReturn == 1);
    3942         194 :         builder()->Bind(switch_jump_table, JSGeneratorObject::kReturn);
    3943             :         {
    3944             :           const AstRawString* return_string =
    3945         194 :               ast_string_constants()->return_string();
    3946             :           BytecodeLabels no_return_method(zone());
    3947             : 
    3948             :           BuildCallIteratorMethod(iterator.object(), return_string,
    3949             :                                   iterator_and_input, after_switch.New(),
    3950         194 :                                   &no_return_method);
    3951         194 :           no_return_method.Bind(builder());
    3952         194 :           builder()->LoadAccumulatorWithRegister(input);
    3953         194 :           if (iterator_type == IteratorType::kAsync) {
    3954             :             execution_control()->AsyncReturnAccumulator();
    3955             :           } else {
    3956             :             execution_control()->ReturnAccumulator();
    3957             :           }
    3958             :         }
    3959             : 
    3960             :         STATIC_ASSERT(JSGeneratorObject::kThrow == 2);
    3961         194 :         builder()->Bind(switch_jump_table, JSGeneratorObject::kThrow);
    3962             :         {
    3963             :           const AstRawString* throw_string =
    3964         194 :               ast_string_constants()->throw_string();
    3965             :           BytecodeLabels no_throw_method(zone());
    3966             :           BuildCallIteratorMethod(iterator.object(), throw_string,
    3967             :                                   iterator_and_input, after_switch.New(),
    3968         194 :                                   &no_throw_method);
    3969             : 
    3970             :           // If there is no "throw" method, perform IteratorClose, and finally
    3971             :           // throw a TypeError.
    3972         194 :           no_throw_method.Bind(builder());
    3973         194 :           BuildIteratorClose(iterator, expr);
    3974         194 :           builder()->CallRuntime(Runtime::kThrowThrowMethodMissing);
    3975             :         }
    3976             : 
    3977         194 :         after_switch.Bind(builder());
    3978             :       }
    3979             : 
    3980         194 :       if (iterator_type == IteratorType::kAsync) {
    3981             :         // Await the result of the method invocation.
    3982         204 :         BuildAwait(expr->position());
    3983             :       }
    3984             : 
    3985             :       // Check that output is an object.
    3986             :       BytecodeLabel check_if_done;
    3987             :       builder()
    3988         194 :           ->StoreAccumulatorInRegister(output)
    3989         194 :           .JumpIfJSReceiver(&check_if_done)
    3990         194 :           .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, output);
    3991             : 
    3992         194 :       builder()->Bind(&check_if_done);
    3993             :       // Break once output.done is true.
    3994             :       builder()->LoadNamedProperty(
    3995             :           output, ast_string_constants()->done_string(),
    3996         388 :           feedback_index(feedback_spec()->AddLoadICSlot()));
    3997             : 
    3998             :       loop.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
    3999             : 
    4000             :       // Suspend the current generator.
    4001         194 :       if (iterator_type == IteratorType::kNormal) {
    4002         184 :         builder()->LoadAccumulatorWithRegister(output);
    4003             :       } else {
    4004             :         RegisterAllocationScope register_scope(this);
    4005             :         DCHECK_EQ(iterator_type, IteratorType::kAsync);
    4006             :         // If generatorKind is async, perform AsyncGeneratorYield(output.value),
    4007             :         // which will await `output.value` before resolving the current
    4008             :         // AsyncGeneratorRequest's promise.
    4009             :         builder()->LoadNamedProperty(
    4010             :             output, ast_string_constants()->value_string(),
    4011          20 :             feedback_index(feedback_spec()->AddLoadICSlot()));
    4012             : 
    4013          10 :         RegisterList args = register_allocator()->NewRegisterList(3);
    4014             :         builder()
    4015          10 :             ->MoveRegister(generator_object(), args[0])  // generator
    4016          10 :             .StoreAccumulatorInRegister(args[1])         // value
    4017          20 :             .LoadBoolean(catch_prediction() != HandlerTable::ASYNC_AWAIT)
    4018          10 :             .StoreAccumulatorInRegister(args[2])  // is_caught
    4019          10 :             .CallRuntime(Runtime::kInlineAsyncGeneratorYield, args);
    4020             :       }
    4021             : 
    4022         194 :       BuildSuspendPoint(expr->position());
    4023         194 :       builder()->StoreAccumulatorInRegister(input);
    4024             :       builder()
    4025             :           ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode,
    4026         194 :                         generator_object())
    4027         194 :           .StoreAccumulatorInRegister(resume_mode);
    4028             : 
    4029         194 :       loop.BindContinueTarget();
    4030         194 :       loop.JumpToHeader(loop_depth_);
    4031         194 :     }
    4032             :   }
    4033             : 
    4034             :   // Decide if we trigger a return or if the yield* expression should just
    4035             :   // produce a value.
    4036             :   BytecodeLabel completion_is_output_value;
    4037         194 :   Register output_value = register_allocator()->NewRegister();
    4038             :   builder()
    4039             :       ->LoadNamedProperty(output, ast_string_constants()->value_string(),
    4040         388 :                           feedback_index(feedback_spec()->AddLoadICSlot()))
    4041         194 :       .StoreAccumulatorInRegister(output_value)
    4042         194 :       .LoadLiteral(Smi::FromInt(JSGeneratorObject::kReturn))
    4043         194 :       .CompareReference(resume_mode)
    4044         194 :       .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &completion_is_output_value)
    4045         194 :       .LoadAccumulatorWithRegister(output_value);
    4046         194 :   if (iterator_type == IteratorType::kAsync) {
    4047             :     execution_control()->AsyncReturnAccumulator();
    4048             :   } else {
    4049             :     execution_control()->ReturnAccumulator();
    4050             :   }
    4051             : 
    4052         194 :   builder()->Bind(&completion_is_output_value);
    4053             :   BuildIncrementBlockCoverageCounterIfEnabled(expr,
    4054             :                                               SourceRangeKind::kContinuation);
    4055         194 :   builder()->LoadAccumulatorWithRegister(output_value);
    4056         194 : }
    4057             : 
    4058       29982 : void BytecodeGenerator::BuildAwait(int position) {
    4059             :   // Rather than HandlerTable::UNCAUGHT, async functions use
    4060             :   // HandlerTable::ASYNC_AWAIT to communicate that top-level exceptions are
    4061             :   // transformed into promise rejections. This is necessary to prevent emitting
    4062             :   // multiple debug events for the same uncaught exception. There is no point
    4063             :   // in the body of an async function where catch prediction is
    4064             :   // HandlerTable::UNCAUGHT.
    4065             :   DCHECK(catch_prediction() != HandlerTable::UNCAUGHT);
    4066             : 
    4067             :   {
    4068             :     // Await(operand) and suspend.
    4069             :     RegisterAllocationScope register_scope(this);
    4070             : 
    4071             :     Runtime::FunctionId await_intrinsic_id;
    4072       14991 :     if (IsAsyncGeneratorFunction(function_kind())) {
    4073             :       await_intrinsic_id = catch_prediction() == HandlerTable::ASYNC_AWAIT
    4074             :                                ? Runtime::kInlineAsyncGeneratorAwaitUncaught
    4075        1308 :                                : Runtime::kInlineAsyncGeneratorAwaitCaught;
    4076             :     } else {
    4077             :       await_intrinsic_id = catch_prediction() == HandlerTable::ASYNC_AWAIT
    4078             :                                ? Runtime::kInlineAsyncFunctionAwaitUncaught
    4079       13683 :                                : Runtime::kInlineAsyncFunctionAwaitCaught;
    4080             :     }
    4081       14991 :     RegisterList args = register_allocator()->NewRegisterList(2);
    4082             :     builder()
    4083       14992 :         ->MoveRegister(generator_object(), args[0])
    4084       14993 :         .StoreAccumulatorInRegister(args[1])
    4085       14992 :         .CallRuntime(await_intrinsic_id, args);
    4086             :   }
    4087             : 
    4088       14992 :   BuildSuspendPoint(position);
    4089             : 
    4090       14993 :   Register input = register_allocator()->NewRegister();
    4091       14993 :   Register resume_mode = register_allocator()->NewRegister();
    4092             : 
    4093             :   // Now dispatch on resume mode.
    4094             :   BytecodeLabel resume_next;
    4095             :   builder()
    4096       14993 :       ->StoreAccumulatorInRegister(input)
    4097       14993 :       .CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator_object())
    4098       14993 :       .StoreAccumulatorInRegister(resume_mode)
    4099       14993 :       .LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
    4100       14993 :       .CompareReference(resume_mode)
    4101       14993 :       .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &resume_next);
    4102             : 
    4103             :   // Resume with "throw" completion (rethrow the received value).
    4104             :   // TODO(leszeks): Add a debug-only check that the accumulator is
    4105             :   // JSGeneratorObject::kThrow.
    4106       14993 :   builder()->LoadAccumulatorWithRegister(input).ReThrow();
    4107             : 
    4108             :   // Resume with next.
    4109       14993 :   builder()->Bind(&resume_next);
    4110       14993 :   builder()->LoadAccumulatorWithRegister(input);
    4111       14993 : }
    4112             : 
    4113       14300 : void BytecodeGenerator::VisitAwait(Await* expr) {
    4114             :   builder()->SetExpressionPosition(expr);
    4115       14300 :   VisitForAccumulatorValue(expr->expression());
    4116       14300 :   BuildAwait(expr->position());
    4117             :   BuildIncrementBlockCoverageCounterIfEnabled(expr,
    4118             :                                               SourceRangeKind::kContinuation);
    4119       14301 : }
    4120             : 
    4121       38290 : void BytecodeGenerator::VisitThrow(Throw* expr) {
    4122             :   AllocateBlockCoverageSlotIfEnabled(expr, SourceRangeKind::kContinuation);
    4123       19145 :   VisitForAccumulatorValue(expr->exception());
    4124             :   builder()->SetExpressionPosition(expr);
    4125       19146 :   builder()->Throw();
    4126       19147 : }
    4127             : 
    4128     7286967 : void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) {
    4129     2475911 :   AssignType property_kind = Property::GetAssignType(property);
    4130     2475991 :   switch (property_kind) {
    4131             :     case NON_PROPERTY:
    4132           0 :       UNREACHABLE();
    4133             :     case NAMED_PROPERTY: {
    4134             :       builder()->SetExpressionPosition(property);
    4135             :       const AstRawString* name =
    4136     4671700 :           property->key()->AsLiteral()->AsRawPropertyName();
    4137     2335837 :       BuildLoadNamedProperty(property->obj(), obj, name);
    4138     2335882 :       break;
    4139             :     }
    4140             :     case KEYED_PROPERTY: {
    4141      139356 :       VisitForAccumulatorValue(property->key());
    4142             :       builder()->SetExpressionPosition(property);
    4143             :       builder()->LoadKeyedProperty(
    4144      278714 :           obj, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
    4145      139363 :       break;
    4146             :     }
    4147             :     case NAMED_SUPER_PROPERTY:
    4148         417 :       VisitNamedSuperPropertyLoad(property, Register::invalid_value());
    4149         417 :       break;
    4150             :     case KEYED_SUPER_PROPERTY:
    4151         360 :       VisitKeyedSuperPropertyLoad(property, Register::invalid_value());
    4152         360 :       break;
    4153             :   }
    4154     2476017 : }
    4155             : 
    4156      789519 : void BytecodeGenerator::VisitPropertyLoadForRegister(Register obj,
    4157             :                                                      Property* expr,
    4158             :                                                      Register destination) {
    4159             :   ValueResultScope result_scope(this);
    4160      789519 :   VisitPropertyLoad(obj, expr);
    4161      789580 :   builder()->StoreAccumulatorInRegister(destination);
    4162      789585 : }
    4163             : 
    4164        2658 : void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
    4165             :                                                     Register opt_receiver_out) {
    4166             :   RegisterAllocationScope register_scope(this);
    4167         886 :   SuperPropertyReference* super_property =
    4168         886 :       property->obj()->AsSuperPropertyReference();
    4169         886 :   RegisterList args = register_allocator()->NewRegisterList(3);
    4170         886 :   BuildThisVariableLoad();
    4171         886 :   builder()->StoreAccumulatorInRegister(args[0]);
    4172             :   VisitForRegisterValue(super_property->home_object(), args[1]);
    4173             : 
    4174             :   builder()->SetExpressionPosition(property);
    4175             :   builder()
    4176        1772 :       ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
    4177         886 :       .StoreAccumulatorInRegister(args[2])
    4178         886 :       .CallRuntime(Runtime::kLoadFromSuper, args);
    4179             : 
    4180         886 :   if (opt_receiver_out.is_valid()) {
    4181         469 :     builder()->MoveRegister(args[0], opt_receiver_out);
    4182         886 :   }
    4183         886 : }
    4184             : 
    4185        1200 : void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property,
    4186             :                                                     Register opt_receiver_out) {
    4187             :   RegisterAllocationScope register_scope(this);
    4188         400 :   SuperPropertyReference* super_property =
    4189         400 :       property->obj()->AsSuperPropertyReference();
    4190         400 :   RegisterList args = register_allocator()->NewRegisterList(3);
    4191         400 :   BuildThisVariableLoad();
    4192         400 :   builder()->StoreAccumulatorInRegister(args[0]);
    4193             :   VisitForRegisterValue(super_property->home_object(), args[1]);
    4194             :   VisitForRegisterValue(property->key(), args[2]);
    4195             : 
    4196             :   builder()->SetExpressionPosition(property);
    4197         400 :   builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, args);
    4198             : 
    4199         400 :   if (opt_receiver_out.is_valid()) {
    4200          40 :     builder()->MoveRegister(args[0], opt_receiver_out);
    4201         400 :   }
    4202         400 : }
    4203             : 
    4204     3372021 : void BytecodeGenerator::VisitProperty(Property* expr) {
    4205     1686391 :   AssignType property_kind = Property::GetAssignType(expr);
    4206     1686407 :   if (property_kind != NAMED_SUPER_PROPERTY &&
    4207             :       property_kind != KEYED_SUPER_PROPERTY) {
    4208     1685630 :     Register obj = VisitForRegisterValue(expr->obj());
    4209     1685689 :     VisitPropertyLoad(obj, expr);
    4210             :   } else {
    4211         777 :     VisitPropertyLoad(Register::invalid_value(), expr);
    4212             :   }
    4213     1686445 : }
    4214             : 
    4215           0 : void BytecodeGenerator::VisitResolvedProperty(ResolvedProperty* expr) {
    4216             :   // Handled by VisitCall().
    4217           0 :   UNREACHABLE();
    4218             : }
    4219             : 
    4220    16663868 : void BytecodeGenerator::VisitArguments(const ZonePtrList<Expression>* args,
    4221             :                                        RegisterList* arg_regs) {
    4222             :   // Visit arguments.
    4223    22720192 :   for (int i = 0; i < static_cast<int>(args->length()); i++) {
    4224     6056283 :     VisitAndPushIntoRegisterList(args->at(i), arg_regs);
    4225             :   }
    4226     5303813 : }
    4227             : 
    4228    10320522 : void BytecodeGenerator::VisitCall(Call* expr) {
    4229             :   Expression* callee_expr = expr->expression();
    4230     5109610 :   Call::CallType call_type = expr->GetCallType();
    4231             : 
    4232     5109612 :   if (call_type == Call::SUPER_CALL) {
    4233     5115010 :     return VisitCallSuper(expr);
    4234             :   }
    4235             : 
    4236             :   // Grow the args list as we visit receiver / arguments to avoid allocating all
    4237             :   // the registers up-front. Otherwise these registers are unavailable during
    4238             :   // receiver / argument visiting and we can end up with memory leaks due to
    4239             :   // registers keeping objects alive.
    4240     5104323 :   Register callee = register_allocator()->NewRegister();
    4241     5104309 :   RegisterList args = register_allocator()->NewGrowableRegisterList();
    4242             : 
    4243             :   bool implicit_undefined_receiver = false;
    4244             :   // When a call contains a spread, a Call AST node is only created if there is
    4245             :   // exactly one spread, and it is the last argument.
    4246     5104309 :   bool is_spread_call = expr->only_last_arg_is_spread();
    4247     5104269 :   bool optimize_as_one_shot = ShouldOptimizeAsOneShot();
    4248             : 
    4249             :   // TODO(petermarshall): We have a lot of call bytecodes that are very similar,
    4250             :   // see if we can reduce the number by adding a separate argument which
    4251             :   // specifies the call type (e.g., property, spread, tailcall, etc.).
    4252             : 
    4253             :   // Prepare the callee and the receiver to the function call. This depends on
    4254             :   // the semantics of the underlying call type.
    4255     5104280 :   switch (call_type) {
    4256             :     case Call::NAMED_PROPERTY_CALL:
    4257             :     case Call::KEYED_PROPERTY_CALL: {
    4258     1579047 :       Property* property = callee_expr->AsProperty();
    4259      789530 :       VisitAndPushIntoRegisterList(property->obj(), &args);
    4260      789567 :       VisitPropertyLoadForRegister(args.last_register(), property, callee);
    4261      789553 :       break;
    4262             :     }
    4263             :     case Call::RESOLVED_PROPERTY_CALL: {
    4264           0 :       ResolvedProperty* resolved = callee_expr->AsResolvedProperty();
    4265           0 :       VisitAndPushIntoRegisterList(resolved->object(), &args);
    4266           0 :       VisitForAccumulatorValue(resolved->property());
    4267           0 :       builder()->StoreAccumulatorInRegister(callee);
    4268           0 :       break;
    4269             :     }
    4270             :     case Call::GLOBAL_CALL: {
    4271             :       // Receiver is undefined for global calls.
    4272     3789571 :       if (!is_spread_call && !optimize_as_one_shot) {
    4273             :         implicit_undefined_receiver = true;
    4274             :       } else {
    4275             :         // TODO(leszeks): There's no special bytecode for tail calls or spread
    4276             :         // calls with an undefined receiver, so just push undefined ourselves.
    4277      687768 :         BuildPushUndefinedIntoRegisterList(&args);
    4278             :       }
    4279             :       // Load callee as a global variable.
    4280    11368936 :       VariableProxy* proxy = callee_expr->AsVariableProxy();
    4281             :       BuildVariableLoadForAccumulatorValue(proxy->var(),
    4282     3789629 :                                            proxy->hole_check_mode());
    4283     3789640 :       builder()->StoreAccumulatorInRegister(callee);
    4284     3789672 :       break;
    4285             :     }
    4286             :     case Call::WITH_CALL: {
    4287        4522 :       Register receiver = register_allocator()->GrowRegisterList(&args);
    4288             :       DCHECK(callee_expr->AsVariableProxy()->var()->IsLookupSlot());
    4289             :       {
    4290             :         RegisterAllocationScope inner_register_scope(this);
    4291        4522 :         Register name = register_allocator()->NewRegister();
    4292             : 
    4293             :         // Call %LoadLookupSlotForCall to get the callee and receiver.
    4294        4523 :         RegisterList result_pair = register_allocator()->NewRegisterList(2);
    4295       13566 :         Variable* variable = callee_expr->AsVariableProxy()->var();
    4296             :         builder()
    4297        4522 :             ->LoadLiteral(variable->raw_name())
    4298        4523 :             .StoreAccumulatorInRegister(name)
    4299             :             .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name,
    4300        4523 :                                 result_pair)
    4301        4523 :             .MoveRegister(result_pair[0], callee)
    4302        4523 :             .MoveRegister(result_pair[1], receiver);
    4303             :       }
    4304             :       break;
    4305             :     }
    4306             :     case Call::OTHER_CALL: {
    4307             :       // Receiver is undefined for other calls.
    4308      520192 :       if (!is_spread_call && !optimize_as_one_shot) {
    4309             :         implicit_undefined_receiver = true;
    4310             :       } else {
    4311             :         // TODO(leszeks): There's no special bytecode for tail calls or spread
    4312             :         // calls with an undefined receiver, so just push undefined ourselves.
    4313      222196 :         BuildPushUndefinedIntoRegisterList(&args);
    4314             :       }
    4315             :       VisitForRegisterValue(callee_expr, callee);
    4316             :       break;
    4317             :     }
    4318             :     case Call::NAMED_SUPER_PROPERTY_CALL: {
    4319         469 :       Register receiver = register_allocator()->GrowRegisterList(&args);
    4320         469 :       Property* property = callee_expr->AsProperty();
    4321         469 :       VisitNamedSuperPropertyLoad(property, receiver);
    4322         469 :       builder()->StoreAccumulatorInRegister(callee);
    4323             :       break;
    4324             :     }
    4325             :     case Call::KEYED_SUPER_PROPERTY_CALL: {
    4326          40 :       Register receiver = register_allocator()->GrowRegisterList(&args);
    4327          40 :       Property* property = callee_expr->AsProperty();
    4328          40 :       VisitKeyedSuperPropertyLoad(property, receiver);
    4329          40 :       builder()->StoreAccumulatorInRegister(callee);
    4330             :       break;
    4331             :     }
    4332             :     case Call::SUPER_CALL:
    4333           0 :       UNREACHABLE();
    4334             :       break;
    4335             :   }
    4336             : 
    4337             :   // Evaluate all arguments to the function call and store in sequential args
    4338             :   // registers.
    4339     5104460 :   VisitArguments(expr->arguments(), &args);
    4340     5104370 :   int reciever_arg_count = implicit_undefined_receiver ? 0 : 1;
    4341     5104370 :   CHECK_EQ(reciever_arg_count + expr->arguments()->length(),
    4342             :            args.register_count());
    4343             : 
    4344             :   // Resolve callee for a potential direct eval call. This block will mutate the
    4345             :   // callee value.
    4346     5104370 :   if (expr->is_possibly_eval() && expr->arguments()->length() > 0) {
    4347             :     RegisterAllocationScope inner_register_scope(this);
    4348             :     // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
    4349             :     // strings and function closure, and loading language and
    4350             :     // position.
    4351      213084 :     Register first_arg = args[reciever_arg_count];
    4352      106542 :     RegisterList runtime_call_args = register_allocator()->NewRegisterList(6);
    4353             :     builder()
    4354      106543 :         ->MoveRegister(callee, runtime_call_args[0])
    4355      106543 :         .MoveRegister(first_arg, runtime_call_args[1])
    4356      213085 :         .MoveRegister(Register::function_closure(), runtime_call_args[2])
    4357      106543 :         .LoadLiteral(Smi::FromEnum(language_mode()))
    4358      106542 :         .StoreAccumulatorInRegister(runtime_call_args[3])
    4359      213085 :         .LoadLiteral(Smi::FromInt(current_scope()->start_position()))
    4360      106541 :         .StoreAccumulatorInRegister(runtime_call_args[4])
    4361      213083 :         .LoadLiteral(Smi::FromInt(expr->position()))
    4362      106543 :         .StoreAccumulatorInRegister(runtime_call_args[5]);
    4363             : 
    4364             :     // Call ResolvePossiblyDirectEval and modify the callee.
    4365             :     builder()
    4366      106542 :         ->CallRuntime(Runtime::kResolvePossiblyDirectEval, runtime_call_args)
    4367      106542 :         .StoreAccumulatorInRegister(callee);
    4368             :   }
    4369             : 
    4370             :   builder()->SetExpressionPosition(expr);
    4371             : 
    4372     5104370 :   if (is_spread_call) {
    4373             :     DCHECK(!implicit_undefined_receiver);
    4374             :     builder()->CallWithSpread(callee, args,
    4375        3418 :                               feedback_index(feedback_spec()->AddCallICSlot()));
    4376     5102661 :   } else if (optimize_as_one_shot) {
    4377             :     DCHECK(!implicit_undefined_receiver);
    4378     1215070 :     builder()->CallNoFeedback(callee, args);
    4379     7775182 :   } else if (call_type == Call::NAMED_PROPERTY_CALL ||
    4380     3887591 :              call_type == Call::KEYED_PROPERTY_CALL ||
    4381     3887591 :              call_type == Call::RESOLVED_PROPERTY_CALL) {
    4382             :     DCHECK(!implicit_undefined_receiver);
    4383             :     builder()->CallProperty(callee, args,
    4384      969155 :                             feedback_index(feedback_spec()->AddCallICSlot()));
    4385     3403018 :   } else if (implicit_undefined_receiver) {
    4386             :     builder()->CallUndefinedReceiver(
    4387     6799503 :         callee, args, feedback_index(feedback_spec()->AddCallICSlot()));
    4388             :   } else {
    4389             :     builder()->CallAnyReceiver(
    4390        6542 :         callee, args, feedback_index(feedback_spec()->AddCallICSlot()));
    4391             :   }
    4392             : }
    4393             : 
    4394       23680 : void BytecodeGenerator::VisitCallSuper(Call* expr) {
    4395             :   RegisterAllocationScope register_scope(this);
    4396       15867 :   SuperCallReference* super = expr->expression()->AsSuperCallReference();
    4397       11199 :   const ZonePtrList<Expression>* args = expr->arguments();
    4398             : 
    4399             :   int first_spread_index = 0;
    4400       11820 :   for (; first_spread_index < args->length(); first_spread_index++) {
    4401        9184 :     if (args->at(first_spread_index)->IsSpread()) break;
    4402             :   }
    4403             : 
    4404             :   // Prepare the constructor to the super call.
    4405        5289 :   Register this_function = VisitForRegisterValue(super->this_function_var());
    4406        5290 :   Register constructor = register_allocator()->NewRegister();
    4407             :   builder()
    4408        5290 :       ->LoadAccumulatorWithRegister(this_function)
    4409        5290 :       .GetSuperConstructor(constructor);
    4410             : 
    4411        5289 :   if (first_spread_index < expr->arguments()->length() - 1) {
    4412             :     // We rewrite something like
    4413             :     //    super(1, ...x, 2)
    4414             :     // to
    4415             :     //    %reflect_construct(constructor, [1, ...x, 2], new_target)
    4416             :     // That is, we implement (non-last-arg) spreads in super calls via our
    4417             :     // mechanism for spreads in array literals.
    4418             : 
    4419             :     // First generate the array containing all arguments.
    4420          30 :     BuildCreateArrayLiteral(args, nullptr);
    4421             : 
    4422             :     // Now pass that array to %reflect_construct.
    4423          30 :     RegisterList construct_args = register_allocator()->NewRegisterList(3);
    4424          30 :     builder()->StoreAccumulatorInRegister(construct_args[1]);
    4425          30 :     builder()->MoveRegister(constructor, construct_args[0]);
    4426             :     VisitForRegisterValue(super->new_target_var(), construct_args[2]);
    4427          30 :     builder()->CallJSRuntime(Context::REFLECT_CONSTRUCT_INDEX, construct_args);
    4428             :   } else {
    4429        5259 :     RegisterList args_regs = register_allocator()->NewGrowableRegisterList();
    4430        5259 :     VisitArguments(args, &args_regs);
    4431             :     // The new target is loaded into the accumulator from the
    4432             :     // {new.target} variable.
    4433        5259 :     VisitForAccumulatorValue(super->new_target_var());
    4434             :     builder()->SetExpressionPosition(expr);
    4435             : 
    4436        5260 :     int feedback_slot_index = feedback_index(feedback_spec()->AddCallICSlot());
    4437             : 
    4438        5260 :     if (first_spread_index == expr->arguments()->length() - 1) {
    4439             :       builder()->ConstructWithSpread(constructor, args_regs,
    4440        3942 :                                      feedback_slot_index);
    4441             :     } else {
    4442             :       DCHECK_EQ(first_spread_index, expr->arguments()->length());
    4443             :       // Call construct.
    4444             :       // TODO(turbofan): For now we do gather feedback on super constructor
    4445             :       // calls, utilizing the existing machinery to inline the actual call
    4446             :       // target and the JSCreate for the implicit receiver allocation. This
    4447             :       // is not an ideal solution for super constructor calls, but it gets
    4448             :       // the job done for now. In the long run we might want to revisit this
    4449             :       // and come up with a better way.
    4450        1318 :       builder()->Construct(constructor, args_regs, feedback_slot_index);
    4451             :     }
    4452             :   }
    4453             : 
    4454             :   // Explicit calls to the super constructor using super() perform an
    4455             :   // implicit binding assignment to the 'this' variable.
    4456             :   //
    4457             :   // Default constructors don't need have to do the assignment because
    4458             :   // 'this' isn't accessed in default constructors.
    4459       10580 :   if (!IsDefaultConstructor(info()->literal()->kind())) {
    4460        2523 :     Variable* var = closure_scope()->GetReceiverScope()->receiver();
    4461        2523 :     BuildVariableAssignment(var, Token::INIT, HoleCheckMode::kRequired);
    4462             :   }
    4463             : 
    4464             :   // The derived constructor has the correct bit set always, so we
    4465             :   // don't emit code to load and call the initializer if not
    4466             :   // required.
    4467             :   //
    4468             :   // For the arrow function or eval case, we always emit code to load
    4469             :   // and call the initializer.
    4470             :   //
    4471             :   // TODO(gsathya): In the future, we could tag nested arrow functions
    4472             :   // or eval with the correct bit so that we do the load conditionally
    4473             :   // if required.
    4474       15673 :   if (info()->literal()->requires_instance_members_initializer() ||
    4475        5094 :       !IsDerivedConstructor(info()->literal()->kind())) {
    4476         326 :     Register instance = register_allocator()->NewRegister();
    4477         326 :     builder()->StoreAccumulatorInRegister(instance);
    4478         326 :     BuildInstanceMemberInitialization(this_function, instance);
    4479         326 :     builder()->LoadAccumulatorWithRegister(instance);
    4480        5290 :   }
    4481        5290 : }
    4482             : 
    4483      137945 : void BytecodeGenerator::VisitCallNew(CallNew* expr) {
    4484      137945 :   Register constructor = VisitForRegisterValue(expr->expression());
    4485      137964 :   RegisterList args = register_allocator()->NewGrowableRegisterList();
    4486      137964 :   VisitArguments(expr->arguments(), &args);
    4487             : 
    4488             :   // The accumulator holds new target which is the same as the
    4489             :   // constructor for CallNew.
    4490             :   builder()->SetExpressionPosition(expr);
    4491      137956 :   builder()->LoadAccumulatorWithRegister(constructor);
    4492             : 
    4493      137963 :   int feedback_slot_index = feedback_index(feedback_spec()->AddCallICSlot());
    4494      137965 :   if (expr->only_last_arg_is_spread()) {
    4495         171 :     builder()->ConstructWithSpread(constructor, args, feedback_slot_index);
    4496             :   } else {
    4497      137789 :     builder()->Construct(constructor, args, feedback_slot_index);
    4498             :   }
    4499      137969 : }
    4500             : 
    4501      112418 : void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
    4502       56198 :   if (expr->is_jsruntime()) {
    4503         362 :     RegisterList args = register_allocator()->NewGrowableRegisterList();
    4504         362 :     VisitArguments(expr->arguments(), &args);
    4505         362 :     builder()->CallJSRuntime(expr->context_index(), args);
    4506             :   } else {
    4507             :     // Evaluate all arguments to the runtime call.
    4508       55836 :     RegisterList args = register_allocator()->NewGrowableRegisterList();
    4509       55836 :     VisitArguments(expr->arguments(), &args);
    4510       55858 :     Runtime::FunctionId function_id = expr->function()->function_id;
    4511       55858 :     builder()->CallRuntime(function_id, args);
    4512             :   }
    4513       56226 : }
    4514             : 
    4515        3335 : void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
    4516        3335 :   VisitForEffect(expr->expression());
    4517        3335 :   builder()->LoadUndefined();
    4518           0 : }
    4519             : 
    4520      162413 : void BytecodeGenerator::VisitForTypeOfValue(Expression* expr) {
    4521      162415 :   if (expr->IsVariableProxy()) {
    4522             :     // Typeof does not throw a reference error on global variables, hence we
    4523             :     // perform a non-contextual load in case the operand is a variable proxy.
    4524      470289 :     VariableProxy* proxy = expr->AsVariableProxy();
    4525             :     BuildVariableLoadForAccumulatorValue(proxy->var(), proxy->hole_check_mode(),
    4526      156763 :                                          INSIDE_TYPEOF);
    4527             :   } else {
    4528        5652 :     VisitForAccumulatorValue(expr);
    4529             :   }
    4530      162416 : }
    4531             : 
    4532       63024 : void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
    4533       63024 :   VisitForTypeOfValue(expr->expression());
    4534       63025 :   builder()->TypeOf();
    4535           0 : }
    4536             : 
    4537      572823 : void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
    4538      271731 :   if (execution_result()->IsEffect()) {
    4539         154 :     VisitForEffect(expr->expression());
    4540      271577 :   } else if (execution_result()->IsTest()) {
    4541             :     // No actual logical negation happening, we just swap the control flow, by
    4542             :     // swapping the target labels and the fallthrough branch, and visit in the
    4543             :     // same test result context.
    4544             :     TestResultScope* test_result = execution_result()->AsTest();
    4545             :     test_result->InvertControlFlow();
    4546      242216 :     VisitInSameTestExecutionScope(expr->expression());
    4547             :   } else {
    4548       29361 :     TypeHint type_hint = VisitForAccumulatorValue(expr->expression());
    4549       29361 :     builder()->LogicalNot(ToBooleanModeFromTypeHint(type_hint));
    4550             :     // Always returns a boolean value.
    4551             :     execution_result()->SetResultIsBoolean();
    4552             :   }
    4553      271732 : }
    4554             : 
    4555      537768 : void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
    4556      408594 :   switch (expr->op()) {
    4557             :     case Token::Value::NOT:
    4558      271733 :       VisitNot(expr);
    4559      271731 :       break;
    4560             :     case Token::Value::TYPEOF:
    4561             :       VisitTypeOf(expr);
    4562             :       break;
    4563             :     case Token::Value::VOID:
    4564             :       VisitVoid(expr);
    4565             :       break;
    4566             :     case Token::Value::DELETE:
    4567        5914 :       VisitDelete(expr);
    4568        5916 :       break;
    4569             :     case Token::Value::ADD:
    4570             :     case Token::Value::SUB:
    4571             :     case Token::Value::BIT_NOT:
    4572       64588 :       VisitForAccumulatorValue(expr->expression());
    4573             :       builder()->SetExpressionPosition(expr);
    4574             :       builder()->UnaryOperation(
    4575      129172 :           expr->op(), feedback_index(feedback_spec()->AddBinaryOpICSlot()));
    4576       64586 :       break;
    4577             :     default:
    4578           0 :       UNREACHABLE();
    4579             :   }
    4580      408593 : }
    4581             : 
    4582        5915 : void BytecodeGenerator::VisitDelete(UnaryOperation* unary) {
    4583             :   Expression* expr = unary->expression();
    4584        5917 :   if (expr->IsProperty()) {
    4585             :     // Delete of an object property is allowed both in sloppy
    4586             :     // and strict modes.
    4587       13134 :     Property* property = expr->AsProperty();
    4588        4378 :     Register object = VisitForRegisterValue(property->obj());
    4589        4378 :     VisitForAccumulatorValue(property->key());
    4590        4378 :     builder()->Delete(object, language_mode());
    4591        2349 :   } else if (expr->IsVariableProxy() &&
    4592        1620 :              !expr->AsVariableProxy()->is_new_target()) {
    4593             :     // Delete of an unqualified identifier is allowed in sloppy mode but is
    4594             :     // not allowed in strict mode.
    4595             :     DCHECK(is_sloppy(language_mode()));
    4596        2228 :     Variable* variable = expr->AsVariableProxy()->var();
    4597         798 :     switch (variable->location()) {
    4598             :       case VariableLocation::PARAMETER:
    4599             :       case VariableLocation::LOCAL:
    4600             :       case VariableLocation::CONTEXT: {
    4601             :         // Deleting local var/let/const, context variables, and arguments
    4602             :         // does not have any effect.
    4603         166 :         builder()->LoadFalse();
    4604         166 :         break;
    4605             :       }
    4606             :       case VariableLocation::UNALLOCATED:
    4607             :       // TODO(adamk): Falling through to the runtime results in correct
    4608             :       // behavior, but does unnecessary context-walking (since scope
    4609             :       // analysis has already proven that the variable doesn't exist in
    4610             :       // any non-global scope). Consider adding a DeleteGlobal bytecode
    4611             :       // that knows how to deal with ScriptContexts as well as global
    4612             :       // object properties.
    4613             :       case VariableLocation::LOOKUP: {
    4614         632 :         Register name_reg = register_allocator()->NewRegister();
    4615             :         builder()
    4616         632 :             ->LoadLiteral(variable->raw_name())
    4617         632 :             .StoreAccumulatorInRegister(name_reg)
    4618         632 :             .CallRuntime(Runtime::kDeleteLookupSlot, name_reg);
    4619             :         break;
    4620             :       }
    4621             :       default:
    4622           0 :         UNREACHABLE();
    4623             :     }
    4624             :   } else {
    4625             :     // Delete of an unresolvable reference, new.target, and this returns true.
    4626         741 :     VisitForEffect(expr);
    4627         741 :     builder()->LoadTrue();
    4628             :   }
    4629        5917 : }
    4630             : 
    4631     1378836 : void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
    4632             :   DCHECK(expr->expression()->IsValidReferenceExpression());
    4633             : 
    4634             :   // Left-hand side can only be a property, a global or a variable slot.
    4635      265647 :   Property* property = expr->expression()->AsProperty();
    4636      240429 :   AssignType assign_type = Property::GetAssignType(property);
    4637             : 
    4638      425158 :   bool is_postfix = expr->is_postfix() && !execution_result()->IsEffect();
    4639             : 
    4640             :   // Evaluate LHS expression and get old value.
    4641             :   Register object, key, old_value;
    4642             :   RegisterList super_property_args;
    4643             :   const AstRawString* name;
    4644      240438 :   switch (assign_type) {
    4645             :     case NON_PROPERTY: {
    4646      698004 :       VariableProxy* proxy = expr->expression()->AsVariableProxy();
    4647             :       BuildVariableLoadForAccumulatorValue(proxy->var(),
    4648      232668 :                                            proxy->hole_check_mode());
    4649      232704 :       break;
    4650             :     }
    4651             :     case NAMED_PROPERTY: {
    4652        4865 :       object = VisitForRegisterValue(property->obj());
    4653        9730 :       name = property->key()->AsLiteral()->AsRawPropertyName();
    4654             :       builder()->LoadNamedProperty(
    4655             :           object, name,
    4656        4865 :           feedback_index(GetCachedLoadICSlot(property->obj(), name)));
    4657        4865 :       break;
    4658             :     }
    4659             :     case KEYED_PROPERTY: {
    4660        2749 :       object = VisitForRegisterValue(property->obj());
    4661             :       // Use visit for accumulator here since we need the key in the accumulator
    4662             :       // for the LoadKeyedProperty.
    4663        2749 :       key = register_allocator()->NewRegister();
    4664        2749 :       VisitForAccumulatorValue(property->key());
    4665        2749 :       builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty(
    4666        5498 :           object, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
    4667        2749 :       break;
    4668             :     }
    4669             :     case NAMED_SUPER_PROPERTY: {
    4670          45 :       super_property_args = register_allocator()->NewRegisterList(4);
    4671          45 :       RegisterList load_super_args = super_property_args.Truncate(3);
    4672          45 :       SuperPropertyReference* super_property =
    4673          45 :           property->obj()->AsSuperPropertyReference();
    4674          45 :       BuildThisVariableLoad();
    4675          45 :       builder()->StoreAccumulatorInRegister(load_super_args[0]);
    4676             :       VisitForRegisterValue(super_property->home_object(), load_super_args[1]);
    4677             :       builder()
    4678          90 :           ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
    4679          45 :           .StoreAccumulatorInRegister(load_super_args[2])
    4680          45 :           .CallRuntime(Runtime::kLoadFromSuper, load_super_args);
    4681             :       break;
    4682             :     }
    4683             :     case KEYED_SUPER_PROPERTY: {
    4684          90 :       super_property_args = register_allocator()->NewRegisterList(4);
    4685          90 :       RegisterList load_super_args = super_property_args.Truncate(3);
    4686          90 :       SuperPropertyReference* super_property =
    4687          90 :           property->obj()->AsSuperPropertyReference();
    4688          90 :       BuildThisVariableLoad();
    4689          90 :       builder()->StoreAccumulatorInRegister(load_super_args[0]);
    4690             :       VisitForRegisterValue(super_property->home_object(), load_super_args[1]);
    4691             :       VisitForRegisterValue(property->key(), load_super_args[2]);
    4692          90 :       builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, load_super_args);
    4693             :       break;
    4694             :     }
    4695             :   }
    4696             : 
    4697             :   // Save result for postfix expressions.
    4698      240474 :   FeedbackSlot count_slot = feedback_spec()->AddBinaryOpICSlot();
    4699      240418 :   if (is_postfix) {
    4700       26824 :     old_value = register_allocator()->NewRegister();
    4701             :     // Convert old value into a number before saving it.
    4702             :     // TODO(ignition): Think about adding proper PostInc/PostDec bytecodes
    4703             :     // instead of this ToNumeric + Inc/Dec dance.
    4704             :     builder()
    4705       26824 :         ->ToNumeric(feedback_index(count_slot))
    4706       26824 :         .StoreAccumulatorInRegister(old_value);
    4707             :   }
    4708             : 
    4709             :   // Perform +1/-1 operation.
    4710      240418 :   builder()->UnaryOperation(expr->op(), feedback_index(count_slot));
    4711             : 
    4712             :   // Store the value.
    4713             :   builder()->SetExpressionPosition(expr);
    4714      240431 :   switch (assign_type) {
    4715             :     case NON_PROPERTY: {
    4716      698072 :       VariableProxy* proxy = expr->expression()->AsVariableProxy();
    4717             :       BuildVariableAssignment(proxy->var(), expr->op(),
    4718      465378 :                               proxy->hole_check_mode());
    4719      232705 :       break;
    4720             :     }
    4721             :     case NAMED_PROPERTY: {
    4722        4865 :       FeedbackSlot slot = GetCachedStoreICSlot(property->obj(), name);
    4723             :       Register value;
    4724        4865 :       if (!execution_result()->IsEffect()) {
    4725        4464 :         value = register_allocator()->NewRegister();
    4726        4464 :         builder()->StoreAccumulatorInRegister(value);
    4727             :       }
    4728             :       builder()->StoreNamedProperty(object, name, feedback_index(slot),
    4729        4865 :                                     language_mode());
    4730        4865 :       if (!execution_result()->IsEffect()) {
    4731        4464 :         builder()->LoadAccumulatorWithRegister(value);
    4732             :       }
    4733             :       break;
    4734             :     }
    4735             :     case KEYED_PROPERTY: {
    4736        2749 :       FeedbackSlot slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
    4737             :       Register value;
    4738        2749 :       if (!execution_result()->IsEffect()) {
    4739         478 :         value = register_allocator()->NewRegister();
    4740         478 :         builder()->StoreAccumulatorInRegister(value);
    4741             :       }
    4742             :       builder()->StoreKeyedProperty(object, key, feedback_index(slot),
    4743        2749 :                                     language_mode());
    4744        2749 :       if (!execution_result()->IsEffect()) {
    4745         478 :         builder()->LoadAccumulatorWithRegister(value);
    4746             :       }
    4747             :       break;
    4748             :     }
    4749             :     case NAMED_SUPER_PROPERTY: {
    4750             :       builder()
    4751          45 :           ->StoreAccumulatorInRegister(super_property_args[3])
    4752          45 :           .CallRuntime(Runtime::kStoreToSuper, super_property_args);
    4753          45 :       break;
    4754             :     }
    4755             :     case KEYED_SUPER_PROPERTY: {
    4756             :       builder()
    4757          90 :           ->StoreAccumulatorInRegister(super_property_args[3])
    4758          90 :           .CallRuntime(Runtime::kStoreKeyedToSuper, super_property_args);
    4759          90 :       break;
    4760             :     }
    4761             :   }
    4762             : 
    4763             :   // Restore old value for postfix expressions.
    4764      240442 :   if (is_postfix) {
    4765       26825 :     builder()->LoadAccumulatorWithRegister(old_value);
    4766             :   }
    4767      240442 : }
    4768             : 
    4769      518558 : void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
    4770      518558 :   switch (binop->op()) {
    4771             :     case Token::COMMA:
    4772       37648 :       VisitCommaExpression(binop);
    4773       37650 :       break;
    4774             :     case Token::OR:
    4775       40632 :       VisitLogicalOrExpression(binop);
    4776       40634 :       break;
    4777             :     case Token::AND:
    4778       83461 :       VisitLogicalAndExpression(binop);
    4779       83461 :       break;
    4780             :     default:
    4781      356817 :       VisitArithmeticExpression(binop);
    4782      356822 :       break;
    4783             :   }
    4784      518567 : }
    4785             : 
    4786      111820 : void BytecodeGenerator::VisitNaryOperation(NaryOperation* expr) {
    4787      111820 :   switch (expr->op()) {
    4788             :     case Token::COMMA:
    4789         325 :       VisitNaryCommaExpression(expr);
    4790         325 :       break;
    4791             :     case Token::OR:
    4792       20189 :       VisitNaryLogicalOrExpression(expr);
    4793       20190 :       break;
    4794             :     case Token::AND:
    4795         659 :       VisitNaryLogicalAndExpression(expr);
    4796         659 :       break;
    4797             :     default:
    4798       90647 :       VisitNaryArithmeticExpression(expr);
    4799       90651 :       break;
    4800             :   }
    4801      111825 : }
    4802             : 
    4803       65459 : void BytecodeGenerator::BuildLiteralCompareNil(
    4804       65459 :     Token::Value op, BytecodeArrayBuilder::NilValue nil) {
    4805       65459 :   if (execution_result()->IsTest()) {
    4806      106789 :     TestResultScope* test_result = execution_result()->AsTest();
    4807       53394 :     switch (test_result->fallthrough()) {
    4808             :       case TestFallthrough::kThen:
    4809       28860 :         builder()->JumpIfNotNil(test_result->NewElseLabel(), op, nil);
    4810       14430 :         break;
    4811             :       case TestFallthrough::kElse:
    4812       77930 :         builder()->JumpIfNil(test_result->NewThenLabel(), op, nil);
    4813       38965 :         break;
    4814             :       case TestFallthrough::kNone:
    4815             :         builder()
    4816           0 :             ->JumpIfNil(test_result->NewThenLabel(), op, nil)
    4817           0 :             .Jump(test_result->NewElseLabel());
    4818             :     }
    4819             :     test_result->SetResultConsumedByTest();
    4820             :   } else {
    4821       12065 :     builder()->CompareNil(op, nil);
    4822             :   }
    4823       65461 : }
    4824             : 
    4825     4764789 : void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
    4826             :   Expression* sub_expr;
    4827             :   Literal* literal;
    4828      876931 :   if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
    4829             :     // Emit a fast literal comparion for expressions of the form:
    4830             :     // typeof(x) === 'string'.
    4831       99389 :     VisitForTypeOfValue(sub_expr);
    4832             :     builder()->SetExpressionPosition(expr);
    4833             :     TestTypeOfFlags::LiteralFlag literal_flag =
    4834      198782 :         TestTypeOfFlags::GetFlagForLiteral(ast_string_constants(), literal);
    4835       99389 :     if (literal_flag == TestTypeOfFlags::LiteralFlag::kOther) {
    4836         242 :       builder()->LoadFalse();
    4837             :     } else {
    4838       99147 :       builder()->CompareTypeOf(literal_flag);
    4839             :     }
    4840      777569 :   } else if (expr->IsLiteralCompareUndefined(&sub_expr)) {
    4841       60391 :     VisitForAccumulatorValue(sub_expr);
    4842             :     builder()->SetExpressionPosition(expr);
    4843       60395 :     BuildLiteralCompareNil(expr->op(), BytecodeArrayBuilder::kUndefinedValue);
    4844      717166 :   } else if (expr->IsLiteralCompareNull(&sub_expr)) {
    4845        5069 :     VisitForAccumulatorValue(sub_expr);
    4846             :     builder()->SetExpressionPosition(expr);
    4847        5069 :     BuildLiteralCompareNil(expr->op(), BytecodeArrayBuilder::kNullValue);
    4848             :   } else {
    4849      712091 :     Register lhs = VisitForRegisterValue(expr->left());
    4850      712118 :     VisitForAccumulatorValue(expr->right());
    4851             :     builder()->SetExpressionPosition(expr);
    4852      712111 :     if (expr->op() == Token::IN) {
    4853        2379 :       builder()->CompareOperation(expr->op(), lhs);
    4854      709732 :     } else if (expr->op() == Token::INSTANCEOF) {
    4855       14759 :       FeedbackSlot slot = feedback_spec()->AddInstanceOfSlot();
    4856       14760 :       builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
    4857             :     } else {
    4858      694973 :       FeedbackSlot slot = feedback_spec()->AddCompareICSlot();
    4859      694974 :       builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
    4860             :     }
    4861             :   }
    4862             :   // Always returns a boolean value.
    4863             :   execution_result()->SetResultIsBoolean();
    4864      876949 : }
    4865             : 
    4866     1594874 : void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
    4867      356813 :   FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
    4868             :   Expression* subexpr;
    4869      356827 :   Smi literal;
    4870      356827 :   if (expr->IsSmiLiteralOperation(&subexpr, &literal)) {
    4871      119976 :     TypeHint type_hint = VisitForAccumulatorValue(subexpr);
    4872             :     builder()->SetExpressionPosition(expr);
    4873             :     builder()->BinaryOperationSmiLiteral(expr->op(), literal,
    4874      119976 :                                          feedback_index(slot));
    4875      119976 :     if (expr->op() == Token::ADD && type_hint == TypeHint::kString) {
    4876             :       execution_result()->SetResultIsString();
    4877             :     }
    4878             :   } else {
    4879      236855 :     TypeHint lhs_type = VisitForAccumulatorValue(expr->left());
    4880      236850 :     Register lhs = register_allocator()->NewRegister();
    4881      236847 :     builder()->StoreAccumulatorInRegister(lhs);
    4882      236856 :     TypeHint rhs_type = VisitForAccumulatorValue(expr->right());
    4883      342541 :     if (expr->op() == Token::ADD &&
    4884      105683 :         (lhs_type == TypeHint::kString || rhs_type == TypeHint::kString)) {
    4885             :       execution_result()->SetResultIsString();
    4886             :     }
    4887             : 
    4888             :     builder()->SetExpressionPosition(expr);
    4889      236858 :     builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot));
    4890             :   }
    4891      356823 : }
    4892             : 
    4893      503902 : void BytecodeGenerator::VisitNaryArithmeticExpression(NaryOperation* expr) {
    4894             :   // TODO(leszeks): Add support for lhs smi in commutative ops.
    4895       90647 :   TypeHint type_hint = VisitForAccumulatorValue(expr->first());
    4896             : 
    4897      841930 :   for (size_t i = 0; i < expr->subsequent_length(); ++i) {
    4898             :     RegisterAllocationScope register_scope(this);
    4899      330313 :     if (expr->subsequent(i)->IsSmiLiteral()) {
    4900             :       builder()->SetExpressionPosition(expr->subsequent_op_position(i));
    4901             :       builder()->BinaryOperationSmiLiteral(
    4902             :           expr->op(), expr->subsequent(i)->AsLiteral()->AsSmiLiteral(),
    4903      178149 :           feedback_index(feedback_spec()->AddBinaryOpICSlot()));
    4904             :     } else {
    4905      285796 :       Register lhs = register_allocator()->NewRegister();
    4906      285805 :       builder()->StoreAccumulatorInRegister(lhs);
    4907      285806 :       TypeHint rhs_hint = VisitForAccumulatorValue(expr->subsequent(i));
    4908      285790 :       if (rhs_hint == TypeHint::kString) type_hint = TypeHint::kString;
    4909             :       builder()->SetExpressionPosition(expr->subsequent_op_position(i));
    4910             :       builder()->BinaryOperation(
    4911             :           expr->op(), lhs,
    4912      571584 :           feedback_index(feedback_spec()->AddBinaryOpICSlot()));
    4913             :     }
    4914      330288 :   }
    4915             : 
    4916      132114 :   if (type_hint == TypeHint::kString && expr->op() == Token::ADD) {
    4917             :     // If any operand of an ADD is a String, a String is produced.
    4918             :     execution_result()->SetResultIsString();
    4919             :   }
    4920       90652 : }
    4921             : 
    4922             : // Note: the actual spreading is performed by the surrounding expression's
    4923             : // visitor.
    4924        7870 : void BytecodeGenerator::VisitSpread(Spread* expr) { Visit(expr->expression()); }
    4925             : 
    4926           0 : void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
    4927           0 :   UNREACHABLE();
    4928             : }
    4929             : 
    4930         566 : void BytecodeGenerator::VisitImportCallExpression(ImportCallExpression* expr) {
    4931         283 :   RegisterList args = register_allocator()->NewRegisterList(2);
    4932             :   VisitForRegisterValue(expr->argument(), args[1]);
    4933             :   builder()
    4934         283 :       ->MoveRegister(Register::function_closure(), args[0])
    4935         283 :       .CallRuntime(Runtime::kDynamicImportCall, args);
    4936         283 : }
    4937             : 
    4938       39860 : void BytecodeGenerator::BuildGetIterator(IteratorType hint) {
    4939       39860 :   RegisterList args = register_allocator()->NewRegisterList(1);
    4940       39862 :   Register method = register_allocator()->NewRegister();
    4941       39862 :   Register obj = args[0];
    4942             : 
    4943       39862 :   if (hint == IteratorType::kAsync) {
    4944             :     // Set method to GetMethod(obj, @@asyncIterator)
    4945         346 :     builder()->StoreAccumulatorInRegister(obj).LoadAsyncIteratorProperty(
    4946         692 :         obj, feedback_index(feedback_spec()->AddLoadICSlot()));
    4947             : 
    4948             :     BytecodeLabel async_iterator_undefined, async_iterator_null, done;
    4949             :     // TODO(ignition): Add a single opcode for JumpIfNullOrUndefined
    4950         346 :     builder()->JumpIfUndefined(&async_iterator_undefined);
    4951         346 :     builder()->JumpIfNull(&async_iterator_null);
    4952             : 
    4953             :     // Let iterator be Call(method, obj)
    4954         346 :     builder()->StoreAccumulatorInRegister(method).CallProperty(
    4955         692 :         method, args, feedback_index(feedback_spec()->AddCallICSlot()));
    4956             : 
    4957             :     // If Type(iterator) is not Object, throw a TypeError exception.
    4958         346 :     builder()->JumpIfJSReceiver(&done);
    4959         346 :     builder()->CallRuntime(Runtime::kThrowSymbolAsyncIteratorInvalid);
    4960             : 
    4961         346 :     builder()->Bind(&async_iterator_undefined);
    4962         346 :     builder()->Bind(&async_iterator_null);
    4963             :     // If method is undefined,
    4964             :     //     Let syncMethod be GetMethod(obj, @@iterator)
    4965             :     builder()
    4966             :         ->LoadIteratorProperty(obj,
    4967         692 :                                feedback_index(feedback_spec()->AddLoadICSlot()))
    4968         346 :         .StoreAccumulatorInRegister(method);
    4969             : 
    4970             :     //     Let syncIterator be Call(syncMethod, obj)
    4971             :     builder()->CallProperty(method, args,
    4972         692 :                             feedback_index(feedback_spec()->AddCallICSlot()));
    4973             : 
    4974             :     // Return CreateAsyncFromSyncIterator(syncIterator)
    4975             :     // alias `method` register as it's no longer used
    4976         346 :     Register sync_iter = method;
    4977         346 :     builder()->StoreAccumulatorInRegister(sync_iter).CallRuntime(
    4978         346 :         Runtime::kInlineCreateAsyncFromSyncIterator, sync_iter);
    4979             : 
    4980         346 :     builder()->Bind(&done);
    4981             :   } else {
    4982             :     // Let method be GetMethod(obj, @@iterator).
    4983             :     builder()
    4984       39513 :         ->StoreAccumulatorInRegister(obj)
    4985             :         .LoadIteratorProperty(obj,
    4986       79032 :                               feedback_index(feedback_spec()->AddLoadICSlot()))
    4987       39516 :         .StoreAccumulatorInRegister(method);
    4988             : 
    4989             :     // Let iterator be Call(method, obj).
    4990             :     builder()->CallProperty(method, args,
    4991       79027 :                             feedback_index(feedback_spec()->AddCallICSlot()));
    4992             : 
    4993             :     // If Type(iterator) is not Object, throw a TypeError exception.
    4994             :     BytecodeLabel no_type_error;
    4995       39516 :     builder()->JumpIfJSReceiver(&no_type_error);
    4996       39512 :     builder()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid);
    4997       39516 :     builder()->Bind(&no_type_error);
    4998             :   }
    4999       39859 : }
    5000             : 
    5001             : // Returns an IteratorRecord which is valid for the lifetime of the current
    5002             : // register_allocation_scope.
    5003       39860 : BytecodeGenerator::IteratorRecord BytecodeGenerator::BuildGetIteratorRecord(
    5004       39859 :     Register next, Register object, IteratorType hint) {
    5005             :   DCHECK(next.is_valid() && object.is_valid());
    5006       39860 :   BuildGetIterator(hint);
    5007             : 
    5008             :   builder()
    5009       39859 :       ->StoreAccumulatorInRegister(object)
    5010             :       .LoadNamedProperty(object, ast_string_constants()->next_string(),
    5011      119580 :                          feedback_index(feedback_spec()->AddLoadICSlot()))
    5012       39863 :       .StoreAccumulatorInRegister(next);
    5013       39863 :   return IteratorRecord(object, next, hint);
    5014             : }
    5015             : 
    5016       39664 : BytecodeGenerator::IteratorRecord BytecodeGenerator::BuildGetIteratorRecord(
    5017             :     IteratorType hint) {
    5018       39664 :   Register next = register_allocator()->NewRegister();
    5019       39668 :   Register object = register_allocator()->NewRegister();
    5020       39668 :   return BuildGetIteratorRecord(next, object, hint);
    5021             : }
    5022             : 
    5023       82110 : void BytecodeGenerator::BuildIteratorNext(const IteratorRecord& iterator,
    5024             :                                           Register next_result) {
    5025             :   DCHECK(next_result.is_valid());
    5026             :   builder()->CallProperty(iterator.next(), RegisterList(iterator.object()),
    5027       82111 :                           feedback_index(feedback_spec()->AddCallICSlot()));
    5028             : 
    5029       41058 :   if (iterator.type() == IteratorType::kAsync) {
    5030         336 :     BuildAwait();
    5031             :   }
    5032             : 
    5033             :   BytecodeLabel is_object;
    5034             :   builder()
    5035       41058 :       ->StoreAccumulatorInRegister(next_result)
    5036       41056 :       .JumpIfJSReceiver(&is_object)
    5037       41058 :       .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, next_result)
    5038       41059 :       .Bind(&is_object);
    5039       41059 : }
    5040             : 
    5041         582 : void BytecodeGenerator::BuildCallIteratorMethod(Register iterator,
    5042             :                                                 const AstRawString* method_name,
    5043             :                                                 RegisterList receiver_and_args,
    5044             :                                                 BytecodeLabel* if_called,
    5045             :                                                 BytecodeLabels* if_notcalled) {
    5046             :   RegisterAllocationScope register_scope(this);
    5047             : 
    5048         582 :   Register method = register_allocator()->NewRegister();
    5049         582 :   FeedbackSlot slot = feedback_spec()->AddLoadICSlot();
    5050             :   builder()
    5051         582 :       ->LoadNamedProperty(iterator, method_name, feedback_index(slot))
    5052        1164 :       .JumpIfUndefined(if_notcalled->New())
    5053        1164 :       .JumpIfNull(if_notcalled->New())
    5054         582 :       .StoreAccumulatorInRegister(method)
    5055             :       .CallProperty(method, receiver_and_args,
    5056        1164 :                     feedback_index(feedback_spec()->AddCallICSlot()))
    5057         582 :       .Jump(if_called);
    5058         582 : }
    5059             : 
    5060         388 : void BytecodeGenerator::BuildIteratorClose(const IteratorRecord& iterator,
    5061         388 :                                            Expression* expr) {
    5062             :   RegisterAllocationScope register_scope(this);
    5063             :   BytecodeLabels done(zone());
    5064             :   BytecodeLabel if_called;
    5065             :   RegisterList args = RegisterList(iterator.object());
    5066             :   BuildCallIteratorMethod(iterator.object(),
    5067             :                           ast_string_constants()->return_string(), args,
    5068         194 :                           &if_called, &done);
    5069         194 :   builder()->Bind(&if_called);
    5070             : 
    5071         194 :   if (iterator.type() == IteratorType::kAsync) {
    5072             :     DCHECK_NOT_NULL(expr);
    5073          10 :     BuildAwait(expr->position());
    5074             :   }
    5075             : 
    5076         194 :   builder()->JumpIfJSReceiver(done.New());
    5077             :   {
    5078             :     RegisterAllocationScope register_scope(this);
    5079         194 :     Register return_result = register_allocator()->NewRegister();
    5080             :     builder()
    5081         194 :         ->StoreAccumulatorInRegister(return_result)
    5082         194 :         .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, return_result);
    5083             :   }
    5084             : 
    5085         388 :   done.Bind(builder());
    5086         194 : }
    5087             : 
    5088        1917 : void BytecodeGenerator::VisitGetTemplateObject(GetTemplateObject* expr) {
    5089             :   builder()->SetExpressionPosition(expr);
    5090        1917 :   size_t entry = builder()->AllocateDeferredConstantPoolEntry();
    5091        3834 :   template_objects_.push_back(std::make_pair(expr, entry));
    5092        1917 :   FeedbackSlot literal_slot = feedback_spec()->AddLiteralSlot();
    5093        1917 :   builder()->GetTemplateObject(entry, feedback_index(literal_slot));
    5094        1917 : }
    5095             : 
    5096        6822 : void BytecodeGenerator::VisitTemplateLiteral(TemplateLiteral* expr) {
    5097       10187 :   const ZonePtrList<const AstRawString>& parts = *expr->string_parts();
    5098       27196 :   const ZonePtrList<Expression>& substitutions = *expr->substitutions();
    5099             :   // Template strings with no substitutions are turned into StringLiterals.
    5100             :   DCHECK_GT(substitutions.length(), 0);
    5101             :   DCHECK_EQ(parts.length(), substitutions.length() + 1);
    5102             : 
    5103             :   // Generate string concatenation
    5104             :   // TODO(caitp): Don't generate feedback slot if it's not used --- introduce
    5105             :   // a simple, concise, reusable mechanism to lazily create reusable slots.
    5106        6822 :   FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
    5107        6822 :   Register last_part = register_allocator()->NewRegister();
    5108             :   bool last_part_valid = false;
    5109             : 
    5110             :   builder()->SetExpressionPosition(expr);
    5111       27196 :   for (int i = 0; i < substitutions.length(); ++i) {
    5112       10187 :     if (i != 0) {
    5113        3365 :       builder()->StoreAccumulatorInRegister(last_part);
    5114             :       last_part_valid = true;
    5115             :     }
    5116             : 
    5117       20374 :     if (!parts[i]->IsEmpty()) {
    5118        7077 :       builder()->LoadLiteral(parts[i]);
    5119        7077 :       if (last_part_valid) {
    5120        3295 :         builder()->BinaryOperation(Token::ADD, last_part, feedback_index(slot));
    5121             :       }
    5122        7077 :       builder()->StoreAccumulatorInRegister(last_part);
    5123             :       last_part_valid = true;
    5124             :     }
    5125             : 
    5126       10187 :     TypeHint type_hint = VisitForAccumulatorValue(substitutions[i]);
    5127       10187 :     if (type_hint != TypeHint::kString) {
    5128       10177 :       builder()->ToString();
    5129             :     }
    5130       10187 :     if (last_part_valid) {
    5131        7147 :       builder()->BinaryOperation(Token::ADD, last_part, feedback_index(slot));
    5132             :     }
    5133             :     last_part_valid = false;
    5134             :   }
    5135             : 
    5136       13644 :   if (!parts.last()->IsEmpty()) {
    5137        2699 :     builder()->StoreAccumulatorInRegister(last_part);
    5138        2699 :     builder()->LoadLiteral(parts.last());
    5139        2699 :     builder()->BinaryOperation(Token::ADD, last_part, feedback_index(slot));
    5140             :   }
    5141        6822 : }
    5142             : 
    5143     2432305 : void BytecodeGenerator::BuildThisVariableLoad() {
    5144     2432305 :   DeclarationScope* receiver_scope = closure_scope()->GetReceiverScope();
    5145             :   Variable* var = receiver_scope->receiver();
    5146             :   // TODO(littledan): implement 'this' hole check elimination.
    5147             :   HoleCheckMode hole_check_mode =
    5148             :       IsDerivedConstructor(receiver_scope->function_kind())
    5149             :           ? HoleCheckMode::kRequired
    5150     2432310 :           : HoleCheckMode::kElided;
    5151     2432310 :   BuildVariableLoad(var, hole_check_mode);
    5152     2432316 : }
    5153             : 
    5154           0 : void BytecodeGenerator::VisitThisExpression(ThisExpression* expr) {
    5155     2430331 :   BuildThisVariableLoad();
    5156           0 : }
    5157             : 
    5158           0 : void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
    5159             :   // Handled by VisitCall().
    5160           0 :   UNREACHABLE();
    5161             : }
    5162             : 
    5163           0 : void BytecodeGenerator::VisitSuperPropertyReference(
    5164             :     SuperPropertyReference* expr) {
    5165          17 :   builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError);
    5166           0 : }
    5167             : 
    5168       75298 : void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
    5169       37648 :   VisitForEffect(binop->left());
    5170       37650 :   Visit(binop->right());
    5171       37650 : }
    5172             : 
    5173         325 : void BytecodeGenerator::VisitNaryCommaExpression(NaryOperation* expr) {
    5174             :   DCHECK_GT(expr->subsequent_length(), 0);
    5175             : 
    5176         325 :   VisitForEffect(expr->first());
    5177     5221118 :   for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
    5178     2610234 :     VisitForEffect(expr->subsequent(i));
    5179             :   }
    5180         325 :   Visit(expr->subsequent(expr->subsequent_length() - 1));
    5181         325 : }
    5182             : 
    5183      145104 : void BytecodeGenerator::VisitLogicalTestSubExpression(
    5184             :     Token::Value token, Expression* expr, BytecodeLabels* then_labels,
    5185      145104 :     BytecodeLabels* else_labels, int coverage_slot) {
    5186             :   DCHECK(token == Token::OR || token == Token::AND);
    5187             : 
    5188             :   BytecodeLabels test_next(zone());
    5189      145104 :   if (token == Token::OR) {
    5190       91577 :     VisitForTest(expr, then_labels, &test_next, TestFallthrough::kElse);
    5191             :   } else {
    5192             :     DCHECK_EQ(Token::AND, token);
    5193       53527 :     VisitForTest(expr, &test_next, else_labels, TestFallthrough::kThen);
    5194             :   }
    5195      145106 :   test_next.Bind(builder());
    5196             : 
    5197      145106 :   BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
    5198      145106 : }
    5199             : 
    5200       67416 : void BytecodeGenerator::VisitLogicalTest(Token::Value token, Expression* left,
    5201             :                                          Expression* right,
    5202       67416 :                                          int right_coverage_slot) {
    5203             :   DCHECK(token == Token::OR || token == Token::AND);
    5204       67416 :   TestResultScope* test_result = execution_result()->AsTest();
    5205             :   BytecodeLabels* then_labels = test_result->then_labels();
    5206             :   BytecodeLabels* else_labels = test_result->else_labels();
    5207             :   TestFallthrough fallthrough = test_result->fallthrough();
    5208             : 
    5209             :   VisitLogicalTestSubExpression(token, left, then_labels, else_labels,
    5210       67416 :                                 right_coverage_slot);
    5211             :   // The last test has the same then, else and fallthrough as the parent test.
    5212       67417 :   VisitForTest(right, then_labels, else_labels, fallthrough);
    5213       67417 : }
    5214             : 
    5215       20302 : void BytecodeGenerator::VisitNaryLogicalTest(
    5216       20302 :     Token::Value token, NaryOperation* expr,
    5217       20302 :     const NaryCodeCoverageSlots* coverage_slots) {
    5218             :   DCHECK(token == Token::OR || token == Token::AND);
    5219             :   DCHECK_GT(expr->subsequent_length(), 0);
    5220             : 
    5221       20302 :   TestResultScope* test_result = execution_result()->AsTest();
    5222             :   BytecodeLabels* then_labels = test_result->then_labels();
    5223             :   BytecodeLabels* else_labels = test_result->else_labels();
    5224             :   TestFallthrough fallthrough = test_result->fallthrough();
    5225             : 
    5226             :   VisitLogicalTestSubExpression(token, expr->first(), then_labels, else_labels,
    5227       20302 :                                 coverage_slots->GetSlotFor(0));
    5228       97992 :   for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
    5229             :     VisitLogicalTestSubExpression(token, expr->subsequent(i), then_labels,
    5230             :                                   else_labels,
    5231      114772 :                                   coverage_slots->GetSlotFor(i + 1));
    5232             :   }
    5233             :   // The last test has the same then, else and fallthrough as the parent test.
    5234             :   VisitForTest(expr->subsequent(expr->subsequent_length() - 1), then_labels,
    5235       20303 :                else_labels, fallthrough);
    5236       20303 : }
    5237             : 
    5238       22133 : bool BytecodeGenerator::VisitLogicalOrSubExpression(Expression* expr,
    5239             :                                                     BytecodeLabels* end_labels,
    5240             :                                                     int coverage_slot) {
    5241       22133 :   if (expr->ToBooleanIsTrue()) {
    5242        1720 :     VisitForAccumulatorValue(expr);
    5243        1721 :     end_labels->Bind(builder());
    5244        1721 :     return true;
    5245       20414 :   } else if (!expr->ToBooleanIsFalse()) {
    5246       20233 :     TypeHint type_hint = VisitForAccumulatorValue(expr);
    5247             :     builder()->JumpIfTrue(ToBooleanModeFromTypeHint(type_hint),
    5248       40466 :                           end_labels->New());
    5249             :   }
    5250             : 
    5251       20415 :   BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
    5252             : 
    5253       20415 :   return false;
    5254             : }
    5255             : 
    5256       31684 : bool BytecodeGenerator::VisitLogicalAndSubExpression(Expression* expr,
    5257             :                                                      BytecodeLabels* end_labels,
    5258             :                                                      int coverage_slot) {
    5259       31684 :   if (expr->ToBooleanIsFalse()) {
    5260         169 :     VisitForAccumulatorValue(expr);
    5261         169 :     end_labels->Bind(builder());
    5262         169 :     return true;
    5263       31515 :   } else if (!expr->ToBooleanIsTrue()) {
    5264       29781 :     TypeHint type_hint = VisitForAccumulatorValue(expr);
    5265             :     builder()->JumpIfFalse(ToBooleanModeFromTypeHint(type_hint),
    5266       59562 :                            end_labels->New());
    5267             :   }
    5268             : 
    5269       31516 :   BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
    5270             : 
    5271       31516 :   return false;
    5272             : }
    5273             : 
    5274      103119 : void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
    5275             :   Expression* left = binop->left();
    5276             :   Expression* right = binop->right();
    5277             : 
    5278             :   int right_coverage_slot =
    5279             :       AllocateBlockCoverageSlotIfEnabled(binop, SourceRangeKind::kRight);
    5280             : 
    5281       40633 :   if (execution_result()->IsTest()) {
    5282        4341 :     TestResultScope* test_result = execution_result()->AsTest();
    5283       18778 :     if (left->ToBooleanIsTrue()) {
    5284        4341 :       builder()->Jump(test_result->NewThenLabel());
    5285       14437 :     } else if (left->ToBooleanIsFalse() && right->ToBooleanIsFalse()) {
    5286           0 :       BuildIncrementBlockCoverageCounterIfEnabled(right_coverage_slot);
    5287           0 :       builder()->Jump(test_result->NewElseLabel());
    5288             :     } else {
    5289       14437 :       VisitLogicalTest(Token::OR, left, right, right_coverage_slot);
    5290             :     }
    5291             :     test_result->SetResultConsumedByTest();
    5292             :   } else {
    5293             :     BytecodeLabels end_labels(zone());
    5294       21855 :     if (VisitLogicalOrSubExpression(left, &end_labels, right_coverage_slot)) {
    5295       40634 :       return;
    5296             :     }
    5297       20165 :     VisitForAccumulatorValue(right);
    5298       20167 :     end_labels.Bind(builder());
    5299             :   }
    5300             : }
    5301             : 
    5302       40516 : void BytecodeGenerator::VisitNaryLogicalOrExpression(NaryOperation* expr) {
    5303             :   Expression* first = expr->first();
    5304             :   DCHECK_GT(expr->subsequent_length(), 0);
    5305             : 
    5306       20189 :   NaryCodeCoverageSlots coverage_slots(this, expr);
    5307             : 
    5308       20189 :   if (execution_result()->IsTest()) {
    5309           0 :     TestResultScope* test_result = execution_result()->AsTest();
    5310       20051 :     if (first->ToBooleanIsTrue()) {
    5311           0 :       builder()->Jump(test_result->NewThenLabel());
    5312             :     } else {
    5313       20051 :       VisitNaryLogicalTest(Token::OR, expr, &coverage_slots);
    5314             :     }
    5315             :     test_result->SetResultConsumedByTest();
    5316             :   } else {
    5317             :     BytecodeLabels end_labels(zone());
    5318         138 :     if (VisitLogicalOrSubExpression(first, &end_labels,
    5319             :                                     coverage_slots.GetSlotFor(0))) {
    5320             :       return;
    5321             :     }
    5322         248 :     for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
    5323         141 :       if (VisitLogicalOrSubExpression(expr->subsequent(i), &end_labels,
    5324         141 :                                       coverage_slots.GetSlotFor(i + 1))) {
    5325             :         return;
    5326             :       }
    5327             :     }
    5328             :     // We have to visit the last value even if it's true, because we need its
    5329             :     // actual value.
    5330         107 :     VisitForAccumulatorValue(expr->subsequent(expr->subsequent_length() - 1));
    5331         107 :     end_labels.Bind(builder());
    5332             :   }
    5333             : }
    5334             : 
    5335      197391 : void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
    5336             :   Expression* left = binop->left();
    5337             :   Expression* right = binop->right();
    5338             : 
    5339             :   int right_coverage_slot =
    5340             :       AllocateBlockCoverageSlotIfEnabled(binop, SourceRangeKind::kRight);
    5341             : 
    5342       83461 :   if (execution_result()->IsTest()) {
    5343          11 :     TestResultScope* test_result = execution_result()->AsTest();
    5344       52991 :     if (left->ToBooleanIsFalse()) {
    5345          11 :       builder()->Jump(test_result->NewElseLabel());
    5346       52980 :     } else if (left->ToBooleanIsTrue() && right->ToBooleanIsTrue()) {
    5347           0 :       BuildIncrementBlockCoverageCounterIfEnabled(right_coverage_slot);
    5348           0 :       builder()->Jump(test_result->NewThenLabel());
    5349             :     } else {
    5350       52980 :       VisitLogicalTest(Token::AND, left, right, right_coverage_slot);
    5351             :     }
    5352             :     test_result->SetResultConsumedByTest();
    5353             :   } else {
    5354             :     BytecodeLabels end_labels(zone());
    5355       30470 :     if (VisitLogicalAndSubExpression(left, &end_labels, right_coverage_slot)) {
    5356       83461 :       return;
    5357             :     }
    5358       30316 :     VisitForAccumulatorValue(right);
    5359       30317 :     end_labels.Bind(builder());
    5360             :   }
    5361             : }
    5362             : 
    5363        1726 : void BytecodeGenerator::VisitNaryLogicalAndExpression(NaryOperation* expr) {
    5364             :   Expression* first = expr->first();
    5365             :   DCHECK_GT(expr->subsequent_length(), 0);
    5366             : 
    5367         659 :   NaryCodeCoverageSlots coverage_slots(this, expr);
    5368             : 
    5369         659 :   if (execution_result()->IsTest()) {
    5370           0 :     TestResultScope* test_result = execution_result()->AsTest();
    5371         251 :     if (first->ToBooleanIsFalse()) {
    5372           0 :       builder()->Jump(test_result->NewElseLabel());
    5373             :     } else {
    5374         251 :       VisitNaryLogicalTest(Token::AND, expr, &coverage_slots);
    5375             :     }
    5376             :     test_result->SetResultConsumedByTest();
    5377             :   } else {
    5378             :     BytecodeLabels end_labels(zone());
    5379         408 :     if (VisitLogicalAndSubExpression(first, &end_labels,
    5380             :                                      coverage_slots.GetSlotFor(0))) {
    5381             :       return;
    5382             :     }
    5383        1199 :     for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
    5384         807 :       if (VisitLogicalAndSubExpression(expr->subsequent(i), &end_labels,
    5385         807 :                                        coverage_slots.GetSlotFor(i + 1))) {
    5386             :         return;
    5387             :       }
    5388             :     }
    5389             :     // We have to visit the last value even if it's false, because we need its
    5390             :     // actual value.
    5391         392 :     VisitForAccumulatorValue(expr->subsequent(expr->subsequent_length() - 1));
    5392         392 :     end_labels.Bind(builder());
    5393             :   }
    5394             : }
    5395             : 
    5396      378576 : void BytecodeGenerator::BuildNewLocalActivationContext() {
    5397             :   ValueResultScope value_execution_result(this);
    5398      365569 :   Scope* scope = closure_scope();
    5399             :   DCHECK_EQ(current_scope(), closure_scope());
    5400             : 
    5401             :   // Create the appropriate context.
    5402      189288 :   if (scope->is_script_scope()) {
    5403       11765 :     Register scope_reg = register_allocator()->NewRegister();
    5404             :     builder()
    5405       11766 :         ->LoadLiteral(scope)
    5406       11766 :         .StoreAccumulatorInRegister(scope_reg)
    5407       11766 :         .CallRuntime(Runtime::kNewScriptContext, scope_reg);
    5408      177523 :   } else if (scope->is_module_scope()) {
    5409             :     // We don't need to do anything for the outer script scope.
    5410             :     DCHECK(scope->outer_scope()->is_script_scope());
    5411             : 
    5412             :     // A JSFunction representing a module is called with the module object as
    5413             :     // its sole argument.
    5414        1242 :     RegisterList args = register_allocator()->NewRegisterList(2);
    5415             :     builder()
    5416        1242 :         ->MoveRegister(builder()->Parameter(0), args[0])
    5417        1242 :         .LoadLiteral(scope)
    5418        1242 :         .StoreAccumulatorInRegister(args[1])
    5419        1242 :         .CallRuntime(Runtime::kPushModuleContext, args);
    5420             :   } else {
    5421             :     DCHECK(scope->is_function_scope() || scope->is_eval_scope());
    5422      176281 :     int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
    5423      176281 :     if (slot_count <= ConstructorBuiltins::MaximumFunctionContextSlots()) {
    5424      176264 :       switch (scope->scope_type()) {
    5425             :         case EVAL_SCOPE:
    5426       42277 :           builder()->CreateEvalContext(scope, slot_count);
    5427       42277 :           break;
    5428             :         case FUNCTION_SCOPE:
    5429      133987 :           builder()->CreateFunctionContext(scope, slot_count);
    5430      133988 :           break;
    5431             :         default:
    5432           0 :           UNREACHABLE();
    5433             :       }
    5434             :     } else {
    5435          17 :       Register arg = register_allocator()->NewRegister();
    5436          17 :       builder()->LoadLiteral(scope).StoreAccumulatorInRegister(arg).CallRuntime(
    5437          17 :           Runtime::kNewFunctionContext, arg);
    5438             :     }
    5439             :   }
    5440      189287 : }
    5441             : 
    5442      326637 : void BytecodeGenerator::BuildLocalActivationContextInitialization() {
    5443      425267 :   DeclarationScope* scope = closure_scope();
    5444             : 
    5445      319862 :   if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
    5446      105405 :     Variable* variable = scope->receiver();
    5447      105405 :     Register receiver(builder()->Receiver());
    5448             :     // Context variable (at bottom of the context chain).
    5449             :     DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
    5450      105405 :     builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot(
    5451      105405 :         execution_context()->reg(), variable->index(), 0);
    5452             :   }
    5453             : 
    5454             :   // Copy parameters into context if necessary.
    5455             :   int num_parameters = scope->num_parameters();
    5456      247848 :   for (int i = 0; i < num_parameters; i++) {
    5457       31946 :     Variable* variable = scope->parameter(i);
    5458       85178 :     if (!variable->IsContextSlot()) continue;
    5459             : 
    5460       31946 :     Register parameter(builder()->Parameter(i));
    5461             :     // Context variable (at bottom of the context chain).
    5462             :     DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
    5463       31946 :     builder()->LoadAccumulatorWithRegister(parameter).StoreContextSlot(
    5464       31946 :         execution_context()->reg(), variable->index(), 0);
    5465             :   }
    5466      189286 : }
    5467             : 
    5468       58500 : void BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) {
    5469             :   ValueResultScope value_execution_result(this);
    5470             :   DCHECK(scope->is_block_scope());
    5471             : 
    5472       58500 :   builder()->CreateBlockContext(scope);
    5473       58501 : }
    5474             : 
    5475        2955 : void BytecodeGenerator::BuildNewLocalWithContext(Scope* scope) {
    5476             :   ValueResultScope value_execution_result(this);
    5477             : 
    5478        2955 :   Register extension_object = register_allocator()->NewRegister();
    5479             : 
    5480        2955 :   builder()->ToObject(extension_object);
    5481        2956 :   builder()->CreateWithContext(extension_object, scope);
    5482        2955 : }
    5483             : 
    5484       68828 : void BytecodeGenerator::BuildNewLocalCatchContext(Scope* scope) {
    5485             :   ValueResultScope value_execution_result(this);
    5486             :   DCHECK(scope->catch_variable()->IsContextSlot());
    5487             : 
    5488       68828 :   Register exception = register_allocator()->NewRegister();
    5489       68837 :   builder()->StoreAccumulatorInRegister(exception);
    5490       68841 :   builder()->CreateCatchContext(exception, scope);
    5491       68837 : }
    5492             : 
    5493        9981 : void BytecodeGenerator::VisitObjectLiteralAccessor(
    5494             :     Register home_object, ObjectLiteralProperty* property, Register value_out) {
    5495        9981 :   if (property == nullptr) {
    5496        4279 :     builder()->LoadNull().StoreAccumulatorInRegister(value_out);
    5497             :   } else {
    5498        5702 :     VisitForRegisterValue(property->value(), value_out);
    5499        5702 :     VisitSetHomeObject(value_out, home_object, property);
    5500             :   }
    5501        9984 : }
    5502             : 
    5503       11630 : void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
    5504       11630 :                                            LiteralProperty* property) {
    5505             :   Expression* expr = property->value();
    5506       11630 :   if (FunctionLiteral::NeedsHomeObject(expr)) {
    5507         659 :     FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
    5508             :     builder()
    5509         659 :         ->LoadAccumulatorWithRegister(home_object)
    5510         659 :         .StoreHomeObjectProperty(value, feedback_index(slot), language_mode());
    5511             :   }
    5512       11634 : }
    5513             : 
    5514     2186950 : void BytecodeGenerator::VisitArgumentsObject(Variable* variable) {
    5515     4174152 :   if (variable == nullptr) return;
    5516             : 
    5517             :   DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
    5518             : 
    5519             :   // Allocate and initialize a new arguments object and assign to the
    5520             :   // {arguments} variable.
    5521       99874 :   builder()->CreateArguments(closure_scope()->GetArgumentsType());
    5522       99873 :   BuildVariableAssignment(variable, Token::ASSIGN, HoleCheckMode::kElided);
    5523             : }
    5524             : 
    5525     2087076 : void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) {
    5526     4174153 :   if (rest == nullptr) return;
    5527             : 
    5528             :   // Allocate and initialize a new rest parameter and assign to the {rest}
    5529             :   // variable.
    5530        5172 :   builder()->CreateArguments(CreateArgumentsType::kRestParameter);
    5531             :   DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
    5532        5173 :   BuildVariableAssignment(rest, Token::ASSIGN, HoleCheckMode::kElided);
    5533             : }
    5534             : 
    5535     4174147 : void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
    5536     8348294 :   if (variable == nullptr) return;
    5537             : 
    5538             :   // Store the closure we were called with in the given variable.
    5539       30967 :   builder()->LoadAccumulatorWithRegister(Register::function_closure());
    5540       30967 :   BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
    5541             : }
    5542             : 
    5543     2286888 : void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
    5544     2087073 :   if (variable == nullptr) return;
    5545             : 
    5546             :   // The generator resume trampoline abuses the new.target register
    5547             :   // to pass in the generator object.  In ordinary calls, new.target is always
    5548             :   // undefined because generator functions are non-constructible, so don't
    5549             :   // assign anything to the new.target variable.
    5550      200331 :   if (IsResumableFunction(info()->literal()->kind())) return;
    5551             : 
    5552       99650 :   if (variable->location() == VariableLocation::LOCAL) {
    5553             :     // The new.target register was already assigned by entry trampoline.
    5554             :     DCHECK_EQ(incoming_new_target_or_generator_.index(),
    5555             :               GetRegisterForLocalVariable(variable).index());
    5556             :     return;
    5557             :   }
    5558             : 
    5559             :   // Store the new target we were called with in the given variable.
    5560       94200 :   builder()->LoadAccumulatorWithRegister(incoming_new_target_or_generator_);
    5561       94200 :   BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
    5562             : }
    5563             : 
    5564       28896 : void BytecodeGenerator::BuildGeneratorObjectVariableInitialization() {
    5565             :   DCHECK(IsResumableFunction(info()->literal()->kind()));
    5566             : 
    5567       10941 :   Variable* generator_object_var = closure_scope()->generator_object_var();
    5568             :   RegisterAllocationScope register_scope(this);
    5569       10941 :   RegisterList args = register_allocator()->NewRegisterList(2);
    5570             :   Runtime::FunctionId function_id =
    5571       17955 :       (IsAsyncFunction(info()->literal()->kind()) &&
    5572        7014 :        !IsAsyncGeneratorFunction(info()->literal()->kind()))
    5573             :           ? Runtime::kInlineAsyncFunctionEnter
    5574       10941 :           : Runtime::kInlineCreateJSGeneratorObject;
    5575             :   builder()
    5576       10941 :       ->MoveRegister(Register::function_closure(), args[0])
    5577       21882 :       .MoveRegister(builder()->Receiver(), args[1])
    5578       10941 :       .CallRuntime(function_id, args)
    5579       10941 :       .StoreAccumulatorInRegister(generator_object());
    5580             : 
    5581       10941 :   if (generator_object_var->location() == VariableLocation::LOCAL) {
    5582             :     // The generator object register is already set to the variable's local
    5583             :     // register.
    5584             :     DCHECK_EQ(generator_object().index(),
    5585             :               GetRegisterForLocalVariable(generator_object_var).index());
    5586             :   } else {
    5587             :     BuildVariableAssignment(generator_object_var, Token::INIT,
    5588           0 :                             HoleCheckMode::kElided);
    5589       10941 :   }
    5590       10941 : }
    5591             : 
    5592      909903 : void BytecodeGenerator::BuildPushUndefinedIntoRegisterList(
    5593             :     RegisterList* reg_list) {
    5594      909903 :   Register reg = register_allocator()->GrowRegisterList(reg_list);
    5595      909947 :   builder()->LoadUndefined().StoreAccumulatorInRegister(reg);
    5596      910101 : }
    5597             : 
    5598        9914 : void BytecodeGenerator::BuildLoadPropertyKey(LiteralProperty* property,
    5599             :                                              Register out_reg) {
    5600        9914 :   if (property->key()->IsStringLiteral()) {
    5601             :     builder()
    5602        4360 :         ->LoadLiteral(property->key()->AsLiteral()->AsRawString())
    5603        2180 :         .StoreAccumulatorInRegister(out_reg);
    5604             :   } else {
    5605        7734 :     VisitForAccumulatorValue(property->key());
    5606        7735 :     builder()->ToName(out_reg);
    5607             :   }
    5608        9914 : }
    5609             : 
    5610           0 : int BytecodeGenerator::AllocateBlockCoverageSlotIfEnabled(
    5611             :     AstNode* node, SourceRangeKind kind) {
    5612     2247153 :   return (block_coverage_builder_ == nullptr)
    5613             :              ? BlockCoverageBuilder::kNoCoverageArraySlot
    5614     2247153 :              : block_coverage_builder_->AllocateBlockCoverageSlot(node, kind);
    5615             : }
    5616             : 
    5617           0 : int BytecodeGenerator::AllocateNaryBlockCoverageSlotIfEnabled(
    5618             :     NaryOperation* node, size_t index) {
    5619         244 :   return (block_coverage_builder_ == nullptr)
    5620             :              ? BlockCoverageBuilder::kNoCoverageArraySlot
    5621             :              : block_coverage_builder_->AllocateNaryBlockCoverageSlot(node,
    5622         244 :                                                                       index);
    5623             : }
    5624             : 
    5625           0 : void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
    5626             :     AstNode* node, SourceRangeKind kind) {
    5627       22915 :   if (block_coverage_builder_ == nullptr) return;
    5628         152 :   block_coverage_builder_->IncrementBlockCounter(node, kind);
    5629             : }
    5630             : 
    5631      197037 : void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
    5632             :     int coverage_array_slot) {
    5633      197037 :   if (block_coverage_builder_ != nullptr) {
    5634             :     block_coverage_builder_->IncrementBlockCounter(coverage_array_slot);
    5635             :   }
    5636      197037 : }
    5637             : 
    5638             : // Visits the expression |expr| and places the result in the accumulator.
    5639    17265788 : BytecodeGenerator::TypeHint BytecodeGenerator::VisitForAccumulatorValue(
    5640             :     Expression* expr) {
    5641             :   ValueResultScope accumulator_scope(this);
    5642    17265788 :   Visit(expr);
    5643    34531678 :   return accumulator_scope.type_hint();
    5644             : }
    5645             : 
    5646       41966 : void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) {
    5647       41966 :   if (expr == nullptr) {
    5648       33990 :     builder()->LoadTheHole();
    5649             :   } else {
    5650        7976 :     VisitForAccumulatorValue(expr);
    5651             :   }
    5652       41965 : }
    5653             : 
    5654             : // Visits the expression |expr| and discards the result.
    5655    12645692 : void BytecodeGenerator::VisitForEffect(Expression* expr) {
    5656             :   EffectResultScope effect_scope(this);
    5657    12645692 :   Visit(expr);
    5658    12645304 : }
    5659             : 
    5660             : // Visits the expression |expr| and returns the register containing
    5661             : // the expression result.
    5662     5015186 : Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
    5663     5015186 :   VisitForAccumulatorValue(expr);
    5664     5015286 :   Register result = register_allocator()->NewRegister();
    5665     5015293 :   builder()->StoreAccumulatorInRegister(result);
    5666     5015335 :   return result;
    5667             : }
    5668             : 
    5669             : // Visits the expression |expr| and stores the expression result in
    5670             : // |destination|.
    5671             : void BytecodeGenerator::VisitForRegisterValue(Expression* expr,
    5672             :                                               Register destination) {
    5673      843183 :   ValueResultScope register_scope(this);
    5674      843188 :   Visit(expr);
    5675      843187 :   builder()->StoreAccumulatorInRegister(destination);
    5676             : }
    5677             : 
    5678             : // Visits the expression |expr| and pushes the result into a new register
    5679             : // added to the end of |reg_list|.
    5680     6845623 : void BytecodeGenerator::VisitAndPushIntoRegisterList(Expression* expr,
    5681             :                                                      RegisterList* reg_list) {
    5682             :   {
    5683             :     ValueResultScope register_scope(this);
    5684     6845623 :     Visit(expr);
    5685             :   }
    5686             :   // Grow the register list after visiting the expression to avoid reserving
    5687             :   // the register across the expression evaluation, which could cause memory
    5688             :   // leaks for deep expressions due to dead objects being kept alive by pointers
    5689             :   // in registers.
    5690     6845585 :   Register destination = register_allocator()->GrowRegisterList(reg_list);
    5691     6845561 :   builder()->StoreAccumulatorInRegister(destination);
    5692     6845711 : }
    5693             : 
    5694      874247 : void BytecodeGenerator::BuildTest(ToBooleanMode mode,
    5695             :                                   BytecodeLabels* then_labels,
    5696             :                                   BytecodeLabels* else_labels,
    5697             :                                   TestFallthrough fallthrough) {
    5698      874247 :   switch (fallthrough) {
    5699             :     case TestFallthrough::kThen:
    5700      594481 :       builder()->JumpIfFalse(mode, else_labels->New());
    5701      594503 :       break;
    5702             :     case TestFallthrough::kElse:
    5703      279771 :       builder()->JumpIfTrue(mode, then_labels->New());
    5704      279771 :       break;
    5705             :     case TestFallthrough::kNone:
    5706           0 :       builder()->JumpIfTrue(mode, then_labels->New());
    5707           0 :       builder()->Jump(else_labels->New());
    5708           0 :       break;
    5709             :   }
    5710      874269 : }
    5711             : 
    5712             : // Visits the expression |expr| for testing its boolean value and jumping to the
    5713             : // |then| or |other| label depending on value and short-circuit semantics
    5714     1019705 : void BytecodeGenerator::VisitForTest(Expression* expr,
    5715             :                                      BytecodeLabels* then_labels,
    5716             :                                      BytecodeLabels* else_labels,
    5717             :                                      TestFallthrough fallthrough) {
    5718             :   bool result_consumed;
    5719             :   TypeHint type_hint;
    5720             :   {
    5721             :     // To make sure that all temporary registers are returned before generating
    5722             :     // jumps below, we ensure that the result scope is deleted before doing so.
    5723             :     // Dead registers might be materialized otherwise.
    5724             :     TestResultScope test_result(this, then_labels, else_labels, fallthrough);
    5725     1019705 :     Visit(expr);
    5726     1019725 :     result_consumed = test_result.result_consumed_by_test();
    5727     1019725 :     type_hint = test_result.type_hint();
    5728             :     // Labels and fallthrough might have been mutated, so update based on
    5729             :     // TestResultScope.
    5730     1019725 :     then_labels = test_result.then_labels();
    5731     1019725 :     else_labels = test_result.else_labels();
    5732     1019725 :     fallthrough = test_result.fallthrough();
    5733             :   }
    5734     1019731 :   if (!result_consumed) {
    5735             :     BuildTest(ToBooleanModeFromTypeHint(type_hint), then_labels, else_labels,
    5736      671331 :               fallthrough);
    5737             :   }
    5738     1019744 : }
    5739             : 
    5740      484434 : void BytecodeGenerator::VisitInSameTestExecutionScope(Expression* expr) {
    5741             :   DCHECK(execution_result()->IsTest());
    5742             :   {
    5743             :     RegisterAllocationScope reg_scope(this);
    5744      242216 :     Visit(expr);
    5745             :   }
    5746      242218 :   if (!execution_result()->AsTest()->result_consumed_by_test()) {
    5747      202932 :     TestResultScope* result_scope = execution_result()->AsTest();
    5748             :     BuildTest(ToBooleanModeFromTypeHint(result_scope->type_hint()),
    5749             :               result_scope->then_labels(), result_scope->else_labels(),
    5750      405864 :               result_scope->fallthrough());
    5751             :     result_scope->SetResultConsumedByTest();
    5752             :   }
    5753      242217 : }
    5754             : 
    5755       71784 : void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) {
    5756             :   DCHECK(scope->declarations()->is_empty());
    5757             :   CurrentScope current_scope(this, scope);
    5758      143579 :   ContextScope context_scope(this, scope);
    5759       71790 :   Visit(stmt);
    5760       71798 : }
    5761             : 
    5762       16391 : Register BytecodeGenerator::GetRegisterForLocalVariable(Variable* variable) {
    5763             :   DCHECK_EQ(VariableLocation::LOCAL, variable->location());
    5764       16391 :   return builder()->Local(variable->index());
    5765             : }
    5766             : 
    5767     2114139 : FunctionKind BytecodeGenerator::function_kind() const {
    5768     2114139 :   return info()->literal()->kind();
    5769             : }
    5770             : 
    5771     6271135 : LanguageMode BytecodeGenerator::language_mode() const {
    5772             :   return current_scope()->language_mode();
    5773             : }
    5774             : 
    5775             : Register BytecodeGenerator::generator_object() const {
    5776             :   DCHECK(IsResumableFunction(info()->literal()->kind()));
    5777             :   return incoming_new_target_or_generator_;
    5778             : }
    5779             : 
    5780    19925552 : FeedbackVectorSpec* BytecodeGenerator::feedback_spec() {
    5781             :   return info()->feedback_vector_spec();
    5782             : }
    5783             : 
    5784             : int BytecodeGenerator::feedback_index(FeedbackSlot slot) const {
    5785             :   DCHECK(!slot.IsInvalid());
    5786             :   return FeedbackVector::GetIndex(slot);
    5787             : }
    5788             : 
    5789     7625048 : FeedbackSlot BytecodeGenerator::GetCachedLoadGlobalICSlot(
    5790    10656173 :     TypeofMode typeof_mode, Variable* variable) {
    5791             :   FeedbackSlotKind slot_kind =
    5792             :       typeof_mode == INSIDE_TYPEOF
    5793             :           ? FeedbackSlotKind::kLoadGlobalInsideTypeof
    5794     7625048 :           : FeedbackSlotKind::kLoadGlobalNotInsideTypeof;
    5795             :   FeedbackSlot slot = feedback_slot_cache()->Get(slot_kind, variable);
    5796     7625536 :   if (!slot.IsInvalid()) {
    5797     4594370 :     return slot;
    5798             :   }
    5799     3031166 :   slot = feedback_spec()->AddLoadGlobalICSlot(typeof_mode);
    5800             :   feedback_slot_cache()->Put(slot_kind, variable, slot);
    5801     3031325 :   return slot;
    5802             : }
    5803             : 
    5804     1438508 : FeedbackSlot BytecodeGenerator::GetCachedStoreGlobalICSlot(
    5805     2612902 :     LanguageMode language_mode, Variable* variable) {
    5806             :   FeedbackSlotKind slot_kind = is_strict(language_mode)
    5807             :                                    ? FeedbackSlotKind::kStoreGlobalStrict
    5808     1438508 :                                    : FeedbackSlotKind::kStoreGlobalSloppy;
    5809             :   FeedbackSlot slot = feedback_slot_cache()->Get(slot_kind, variable);
    5810     1438598 :   if (!slot.IsInvalid()) {
    5811      264212 :     return slot;
    5812             :   }
    5813     1174386 :   slot = feedback_spec()->AddStoreGlobalICSlot(language_mode);
    5814             :   feedback_slot_cache()->Put(slot_kind, variable, slot);
    5815     1174412 :   return slot;
    5816             : }
    5817             : 
    5818     1092326 : FeedbackSlot BytecodeGenerator::GetCachedLoadICSlot(const Expression* expr,
    5819     1245217 :                                                     const AstRawString* name) {
    5820     1092326 :   if (!FLAG_ignition_share_named_property_feedback) {
    5821           0 :     return feedback_spec()->AddLoadICSlot();
    5822             :   }
    5823             :   FeedbackSlotKind slot_kind = FeedbackSlotKind::kLoadProperty;
    5824     1092332 :   if (!expr->IsVariableProxy()) {
    5825      342531 :     return feedback_spec()->AddLoadICSlot();
    5826             :   }
    5827     1995018 :   const VariableProxy* proxy = expr->AsVariableProxy();
    5828             :   FeedbackSlot slot =
    5829      749801 :       feedback_slot_cache()->Get(slot_kind, proxy->var()->index(), name);
    5830      749803 :   if (!slot.IsInvalid()) {
    5831      254387 :     return slot;
    5832             :   }
    5833      495416 :   slot = feedback_spec()->AddLoadICSlot();
    5834      495416 :   feedback_slot_cache()->Put(slot_kind, proxy->var()->index(), name, slot);
    5835      495420 :   return slot;
    5836             : }
    5837             : 
    5838     2277528 : FeedbackSlot BytecodeGenerator::GetCachedStoreICSlot(const Expression* expr,
    5839       42974 :                                                      const AstRawString* name) {
    5840     2277528 :   if (!FLAG_ignition_share_named_property_feedback) {
    5841           0 :     return feedback_spec()->AddStoreICSlot(language_mode());
    5842             :   }
    5843             :   FeedbackSlotKind slot_kind = is_strict(language_mode())
    5844             :                                    ? FeedbackSlotKind::kStoreNamedStrict
    5845     2277528 :                                    : FeedbackSlotKind::kStoreNamedSloppy;
    5846     2277528 :   if (!expr->IsVariableProxy()) {
    5847     2254786 :     return feedback_spec()->AddStoreICSlot(language_mode());
    5848             :   }
    5849       65716 :   const VariableProxy* proxy = expr->AsVariableProxy();
    5850             :   FeedbackSlot slot =
    5851       22742 :       feedback_slot_cache()->Get(slot_kind, proxy->var()->index(), name);
    5852       22743 :   if (!slot.IsInvalid()) {
    5853        2511 :     return slot;
    5854             :   }
    5855       20232 :   slot = feedback_spec()->AddStoreICSlot(language_mode());
    5856       20232 :   feedback_slot_cache()->Put(slot_kind, proxy->var()->index(), name, slot);
    5857       20231 :   return slot;
    5858             : }
    5859             : 
    5860     2894961 : FeedbackSlot BytecodeGenerator::GetCachedCreateClosureSlot(
    5861     5790134 :     FunctionLiteral* literal) {
    5862             :   FeedbackSlotKind slot_kind = FeedbackSlotKind::kCreateClosure;
    5863             :   FeedbackSlot slot = feedback_slot_cache()->Get(slot_kind, literal);
    5864     2895166 :   if (!slot.IsInvalid()) {
    5865           0 :     return slot;
    5866             :   }
    5867     2895166 :   slot = feedback_spec()->AddCreateClosureSlot();
    5868             :   feedback_slot_cache()->Put(slot_kind, literal, slot);
    5869     2895179 :   return slot;
    5870             : }
    5871             : 
    5872           0 : FeedbackSlot BytecodeGenerator::GetDummyCompareICSlot() {
    5873        1674 :   return dummy_feedback_slot_.Get();
    5874             : }
    5875             : 
    5876             : }  // namespace interpreter
    5877             : }  // namespace internal
    5878      178779 : }  // namespace v8

Generated by: LCOV version 1.10