LCOV - code coverage report
Current view: top level - src/interpreter - bytecode-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2308 2390 96.6 %
Date: 2019-01-20 Functions: 179 213 84.0 %

          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     2432254 :   ContextScope(BytecodeGenerator* generator, Scope* scope)
      35             :       : generator_(generator),
      36             :         scope_(scope),
      37     2432254 :         outer_(generator_->execution_context()),
      38             :         register_(Register::current_context()),
      39     4864508 :         depth_(0) {
      40             :     DCHECK(scope->NeedsContext() || outer_ == nullptr);
      41     2432260 :     if (outer_) {
      42      322514 :       depth_ = outer_->depth_ + 1;
      43             : 
      44             :       // Push the outer context into a new context register.
      45             :       Register outer_context_reg =
      46      322514 :           generator_->register_allocator()->NewRegister();
      47      322527 :       outer_->set_register(outer_context_reg);
      48      322527 :       generator_->builder()->PushContext(outer_context_reg);
      49             :     }
      50     2432291 :     generator_->set_execution_context(this);
      51     2432291 :   }
      52             : 
      53     2432133 :   ~ContextScope() {
      54     2432133 :     if (outer_) {
      55             :       DCHECK_EQ(register_.index(), Register::current_context().index());
      56      322514 :       generator_->builder()->PopContext(outer_->reg());
      57      322510 :       outer_->set_register(register_);
      58             :     }
      59     2432129 :     generator_->set_execution_context(outer_);
      60     2432129 :   }
      61             : 
      62             :   // Returns the depth of the given |scope| for the current execution context.
      63             :   int ContextChainDepth(Scope* scope) {
      64     2785836 :     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     2746102 :     if (depth > depth_) {
      71             :       return nullptr;
      72             :     }
      73             : 
      74             :     ContextScope* previous = this;
      75       47940 :     for (int i = depth; i > 0; --i) {
      76       47940 :       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      645037 :   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    15555192 :   explicit ControlScope(BytecodeGenerator* generator)
     100             :       : generator_(generator),
     101             :         outer_(generator->execution_control()),
     102    23332788 :         context_(generator->execution_context()) {
     103             :     generator_->set_execution_control(this);
     104             :   }
     105     7777353 :   virtual ~ControlScope() { generator_->set_execution_control(outer()); }
     106             : 
     107             :   void Break(Statement* stmt) {
     108       47172 :     PerformCommand(CMD_BREAK, stmt, kNoSourcePosition);
     109             :   }
     110             :   void Continue(Statement* stmt) {
     111        3733 :     PerformCommand(CMD_CONTINUE, stmt, kNoSourcePosition);
     112             :   }
     113             :   void ReturnAccumulator(int source_position = kNoSourcePosition) {
     114     2061287 :     PerformCommand(CMD_RETURN, nullptr, source_position);
     115             :   }
     116             :   void AsyncReturnAccumulator(int source_position = kNoSourcePosition) {
     117        8348 :     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       88204 :   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       88204 :         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       88213 :     deferred_.push_back({CMD_RETHROW, nullptr, kRethrowToken});
     185       44111 :   }
     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      222424 :   void RecordCommand(Command command, Statement* statement) {
     198       55602 :     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       55603 :     if (CommandUsesAccumulator(command)) {
     206       55349 :       builder()->StoreAccumulatorInRegister(result_register_);
     207             :     }
     208       55604 :     builder()->LoadLiteral(Smi::FromInt(token));
     209       55613 :     builder()->StoreAccumulatorInRegister(token_register_);
     210       55614 :     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         256 :       builder()->StoreAccumulatorInRegister(result_register_);
     216             :     }
     217       55614 :   }
     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       44111 :     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      132321 :   void RecordFallThroughPath() {
     230       44097 :     builder()->LoadLiteral(Smi::FromInt(kFallthroughToken));
     231       44111 :     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       44113 :     builder()->StoreAccumulatorInRegister(result_register_);
     237       44114 :   }
     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      235460 :   void ApplyDeferredCommands() {
     242       88196 :     if (deferred_.size() == 0) return;
     243             : 
     244             :     BytecodeLabel fall_through;
     245             : 
     246       44098 :     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       83410 :           ->LoadLiteral(Smi::FromInt(entry.token))
     253       41718 :           .CompareReference(token_register_)
     254       41717 :           .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &fall_through);
     255             : 
     256       41713 :       if (CommandUsesAccumulator(entry.command)) {
     257       41712 :         builder()->LoadAccumulatorWithRegister(result_register_);
     258             :       }
     259             :       execution_control()->PerformCommand(entry.command, entry.statement,
     260       83436 :                                           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        4786 :           builder()->AllocateJumpTable(static_cast<int>(deferred_.size()), 0);
     267             :       builder()
     268        2392 :           ->LoadAccumulatorWithRegister(token_register_)
     269        2393 :           .SwitchOnSmiNoFeedback(jump_table)
     270        2393 :           .Jump(&fall_through);
     271       10648 :       for (const Entry& entry : deferred_) {
     272       11724 :         builder()->Bind(jump_table, entry.token);
     273             : 
     274        5863 :         if (CommandUsesAccumulator(entry.command)) {
     275        5607 :           builder()->LoadAccumulatorWithRegister(result_register_);
     276             :         }
     277             :         execution_control()->PerformCommand(entry.command, entry.statement,
     278       11726 :                                             kNoSourcePosition);
     279             :       }
     280             :     }
     281             : 
     282       44110 :     builder()->Bind(&fall_through);
     283             :   }
     284             : 
     285             :   BytecodeArrayBuilder* builder() { return generator_->builder(); }
     286       47581 :   ControlScope* execution_control() { return generator_->execution_control(); }
     287             : 
     288             :  private:
     289       55598 :   int GetTokenForCommand(Command command, Statement* statement) {
     290       55598 :     switch (command) {
     291             :       case CMD_RETURN:
     292        2077 :         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         255 :         return GetNewTokenForCommand(command, statement);
     301             :     }
     302             :   }
     303             : 
     304        2077 :   int GetReturnToken() {
     305        2077 :     if (return_token_ == -1) {
     306        1915 :       return_token_ = GetNewTokenForCommand(CMD_RETURN, nullptr);
     307             :     }
     308        2077 :     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        6940 :     int token = static_cast<int>(deferred_.size());
     320        6939 :     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     2109621 : class BytecodeGenerator::ControlScopeForTopLevel final
     336             :     : public BytecodeGenerator::ControlScope {
     337             :  public:
     338             :   explicit ControlScopeForTopLevel(BytecodeGenerator* generator)
     339     2109754 :       : ControlScope(generator) {}
     340             : 
     341             :  protected:
     342     2103691 :   bool Execute(Command command, Statement* statement,
     343             :                int source_position) override {
     344     2103691 :     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     2103795 :         generator()->BuildReturn(source_position);
     351     2061163 :         return true;
     352             :       case CMD_ASYNC_RETURN:
     353             :         // No need to pop contexts, execution leaves the method body.
     354        7131 :         generator()->BuildAsyncReturn(source_position);
     355        7131 :         return true;
     356             :       case CMD_RETHROW:
     357             :         // No need to pop contexts, execution leaves the method body.
     358             :         generator()->BuildReThrow();
     359       35886 :         return true;
     360             :     }
     361             :     return false;
     362             :   }
     363             : };
     364             : 
     365             : // Scoped class for enabling break inside blocks and switch blocks.
     366     5250534 : 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     5250646 :         control_builder_(control_builder) {}
     375             : 
     376             :  protected:
     377      407298 :   bool Execute(Command command, Statement* statement,
     378             :                int source_position) override {
     379      407298 :     if (statement != statement_) return false;
     380       26574 :     switch (command) {
     381             :       case CMD_BREAK:
     382       26575 :         PopContextToExpectedDepth();
     383       26575 :         control_builder_->Break();
     384       26575 :         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      262668 :         loop_builder_(loop_builder) {
     410      262668 :     generator->loop_depth_++;
     411             :   }
     412      262664 :   ~ControlScopeForIteration() override { generator()->loop_depth_--; }
     413             : 
     414             :  protected:
     415       67736 :   bool Execute(Command command, Statement* statement,
     416             :                int source_position) override {
     417       67736 :     if (statement != statement_) return false;
     418       24328 :     switch (command) {
     419             :       case CMD_BREAK:
     420       20595 :         PopContextToExpectedDepth();
     421       20595 :         loop_builder_->Break();
     422       20597 :         return true;
     423             :       case CMD_CONTINUE:
     424        3733 :         PopContextToExpectedDepth();
     425        3733 :         loop_builder_->Continue();
     426        3733 :         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      110424 : class BytecodeGenerator::ControlScopeForTryCatch final
     442             :     : public BytecodeGenerator::ControlScope {
     443             :  public:
     444             :   ControlScopeForTryCatch(BytecodeGenerator* generator,
     445             :                           TryCatchBuilder* try_catch_builder)
     446      110420 :       : ControlScope(generator) {}
     447             : 
     448             :  protected:
     449       14975 :   bool Execute(Command command, Statement* statement,
     450             :                int source_position) override {
     451       14975 :     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        1572 :         generator()->BuildReThrow();
     461        1572 :         return true;
     462             :     }
     463             :     return false;
     464             :   }
     465             : };
     466             : 
     467             : // Scoped class for enabling control flow through try-finally constructs.
     468       44110 : 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       44108 :         commands_(commands) {}
     477             : 
     478             :  protected:
     479       11498 :   bool Execute(Command command, Statement* statement,
     480             :                int source_position) override {
     481       11498 :     switch (command) {
     482             :       case CMD_BREAK:
     483             :       case CMD_CONTINUE:
     484             :       case CMD_RETURN:
     485             :       case CMD_ASYNC_RETURN:
     486             :       case CMD_RETHROW:
     487       11500 :         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       11500 :         commands_->RecordCommand(command, statement);
     494       11501 :         try_finally_builder_->LeaveTry();
     495       11501 :         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       19892 :   NaryCodeCoverageSlots(BytecodeGenerator* generator, NaryOperation* expr)
     509       19892 :       : generator_(generator) {
     510       39784 :     if (generator_->block_coverage_builder_ == nullptr) return;
     511         740 :     for (size_t i = 0; i < expr->subsequent_length(); i++) {
     512             :       coverage_slots_.push_back(
     513         915 :           generator_->AllocateNaryBlockCoverageSlotIfEnabled(expr, i));
     514             :     }
     515             :   }
     516             : 
     517             :   int GetSlotFor(size_t subsequent_expr_index) const {
     518       75133 :     if (generator_->block_coverage_builder_ == nullptr) {
     519             :       return BlockCoverageBuilder::kNoCoverageArraySlot;
     520             :     }
     521             :     DCHECK(coverage_slots_.size() > subsequent_expr_index);
     522         420 :     return coverage_slots_[subsequent_expr_index];
     523             :   }
     524             : 
     525             :  private:
     526             :   BytecodeGenerator* generator_;
     527             :   std::vector<int> coverage_slots_;
     528             : };
     529             : 
     530     2167762 : void BytecodeGenerator::ControlScope::PerformCommand(Command command,
     531             :                                                      Statement* statement,
     532             :                                                      int source_position) {
     533      437540 :   ControlScope* current = this;
     534      437540 :   do {
     535     2605302 :     if (current->Execute(command, statement, source_position)) {
     536     2168154 :       return;
     537             :     }
     538             :     current = current->outer();
     539             :   } while (current != nullptr);
     540           0 :   UNREACHABLE();
     541             : }
     542             : 
     543      124806 : 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      124806 :   if (generator()->execution_context() != context()) {
     547        9491 :     generator()->builder()->PopContext(context()->reg());
     548             :   }
     549       62403 : }
     550             : 
     551             : class BytecodeGenerator::RegisterAllocationScope final {
     552             :  public:
     553             :   explicit RegisterAllocationScope(BytecodeGenerator* generator)
     554             :       : generator_(generator),
     555             :         outer_next_register_index_(
     556    78335621 :             generator->register_allocator()->next_register_index()) {}
     557             : 
     558    78309960 :   ~RegisterAllocationScope() {
     559             :     generator_->register_allocator()->ReleaseRegisters(
     560    78309960 :         outer_next_register_index_);
     561    78309303 :   }
     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     2424013 :   explicit AccumulatorPreservingScope(BytecodeGenerator* generator,
     575             :                                       AccumulatorPreservingMode mode)
     576     2424013 :       : generator_(generator) {
     577     2424013 :     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     2424013 :   }
     584             : 
     585             :   ~AccumulatorPreservingScope() {
     586     2424124 :     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    44355179 :   ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind)
     604             :       : outer_(generator->execution_result()),
     605             :         allocator_(generator),
     606             :         kind_(kind),
     607    88710358 :         type_hint_(TypeHint::kAny) {
     608             :     generator->set_execution_result(this);
     609             :   }
     610             : 
     611    44354573 :   ~ExpressionResultScope() {
     612    44354573 :     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     1179231 :     type_hint_ = TypeHint::kBoolean;
     628             :   }
     629             : 
     630             :   void SetResultIsString() {
     631             :     DCHECK_EQ(type_hint_, TypeHint::kAny);
     632     1765909 :     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     1697529 : class BytecodeGenerator::ValueResultScope final : public ExpressionResultScope {
     658             :  public:
     659      848818 :   explicit ValueResultScope(BytecodeGenerator* generator)
     660     1697636 :       : 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      972473 :         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      300269 :   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      207721 :   void InvertControlFlow() {
     683             :     std::swap(then_labels_, else_labels_);
     684      207721 :     fallthrough_ = inverted_fallthrough();
     685             :   }
     686             : 
     687       21001 :   BytecodeLabel* NewThenLabel() { return then_labels_->New(); }
     688       15304 :   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      207721 :     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     2227232 :   explicit GlobalDeclarationsBuilder(Zone* zone)
     728             :       : declarations_(0, zone),
     729             :         constant_pool_entry_(0),
     730     2227249 :         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      499401 :     declarations_.push_back(Declaration(name, slot, literal_slot, func));
     737             :   }
     738             : 
     739             :   void AddUndefinedDeclaration(const AstRawString* name, FeedbackSlot slot) {
     740             :     DCHECK(!slot.IsInvalid());
     741     2481254 :     declarations_.push_back(Declaration(name, slot, nullptr));
     742             :   }
     743             : 
     744      107218 :   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      214436 :         static_cast<int>(declarations_.size() * 4), TENURED);
     751     1493659 :     for (const Declaration& declaration : declarations_) {
     752     1279223 :       FunctionLiteral* func = declaration.func;
     753             :       Handle<Object> initial_value;
     754     1279223 :       if (func == nullptr) {
     755             :         initial_value = isolate->factory()->undefined_value();
     756             :       } else {
     757      217194 :         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     1279223 :       if (initial_value.is_null()) return Handle<FixedArray>();
     763             : 
     764     3837669 :       data->set(array_index++, *declaration.name->string());
     765     1279223 :       data->set(array_index++, Smi::FromInt(declaration.slot.ToInt()));
     766             :       Object undefined_or_literal_slot;
     767     1279223 :       if (declaration.literal_slot.IsInvalid()) {
     768     1062029 :         undefined_or_literal_slot = ReadOnlyRoots(isolate).undefined_value();
     769             :       } else {
     770             :         undefined_or_literal_slot =
     771      217194 :             Smi::FromInt(declaration.literal_slot.ToInt());
     772             :       }
     773     2558446 :       data->set(array_index++, undefined_or_literal_slot);
     774     2558446 :       data->set(array_index++, *initial_value);
     775             :     }
     776      107218 :     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      117500 :     constant_pool_entry_ = constant_pool_entry;
     788      117500 :     has_constant_pool_entry_ = true;
     789             :   }
     790             : 
     791             :   bool empty() { return declarations_.empty(); }
     792             : 
     793             :  private:
     794             :   struct Declaration {
     795     4454464 :     Declaration() : slot(FeedbackSlot::Invalid()), func(nullptr) {}
     796             :     Declaration(const AstRawString* name, FeedbackSlot slot,
     797             :                 FeedbackSlot literal_slot, FunctionLiteral* func)
     798      249698 :         : 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     1240607 :           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     5353787 :   CurrentScope(BytecodeGenerator* generator, Scope* scope)
     819             :       : generator_(generator), outer_scope_(generator->current_scope()) {
     820     5353787 :     if (scope != nullptr) {
     821             :       DCHECK_EQ(outer_scope_, scope->outer_scope());
     822             :       generator_->set_current_scope(scope);
     823             :     }
     824             :   }
     825             :   ~CurrentScope() {
     826     5353940 :     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     9145618 :     return GetImpl(slot_kind, 0, variable);
     853             :   }
     854             :   FeedbackSlot Get(FeedbackSlotKind slot_kind, AstNode* node) const {
     855     2854753 :     return GetImpl(slot_kind, 0, node);
     856             :   }
     857             :   FeedbackSlot Get(FeedbackSlotKind slot_kind, int variable_index,
     858             :                    const AstRawString* name) const {
     859     3193182 :     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    15191951 :   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    15193007 :     if (iter != map_.end()) {
     877     7279134 :       return iter->second;
     878             :     }
     879     7913873 :     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     2109791 : BytecodeGenerator::BytecodeGenerator(
     917     4219576 :     UnoptimizedCompilationInfo* info,
     918             :     const AstStringConstants* ast_string_constants,
     919    21099026 :     std::vector<FunctionLiteral*>* eager_inner_literals)
     920             :     : zone_(info->zone()),
     921             :       builder_(zone(), info->num_parameters_including_this(),
     922     2109799 :                info->scope()->num_stack_slots(), info->feedback_vector_spec(),
     923             :                info->SourcePositionRecordingMode()),
     924             :       info_(info),
     925             :       ast_string_constants_(ast_string_constants),
     926     2109810 :       closure_scope_(info->scope()),
     927     2109808 :       current_scope_(info->scope()),
     928             :       eager_inner_literals_(eager_inner_literals),
     929             :       feedback_slot_cache_(new (zone()) FeedbackSlotCache(zone())),
     930     2109793 :       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    21097961 :       catch_prediction_(HandlerTable::UNCAUGHT) {
     948             :   DCHECK_EQ(closure_scope(), closure_scope()->GetClosureScope());
     949     2109785 :   if (info->has_source_range_map()) {
     950             :     block_coverage_builder_ = new (zone())
     951        1080 :         BlockCoverageBuilder(zone(), builder(), info->source_range_map());
     952             :   }
     953     2109785 : }
     954             : 
     955     2086359 : Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
     956     2087437 :     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             :   SaveContext save(isolate);
     962             :   isolate->set_context(Context());
     963             : #endif
     964             : 
     965     2086359 :   AllocateDeferredConstants(isolate, script);
     966             : 
     967     2086357 :   if (block_coverage_builder_) {
     968             :     info()->set_coverage_info(
     969        1080 :         isolate->factory()->NewCoverageInfo(block_coverage_builder_->slots()));
     970        1080 :     if (FLAG_trace_block_coverage) {
     971           0 :       info()->coverage_info()->Print(info()->literal()->GetDebugName());
     972             :     }
     973             :   }
     974             : 
     975     2086357 :   if (HasStackOverflow()) return Handle<BytecodeArray>();
     976     2086357 :   Handle<BytecodeArray> bytecode_array = builder()->ToBytecodeArray(isolate);
     977             : 
     978     2086383 :   if (incoming_new_target_or_generator_.is_valid()) {
     979             :     bytecode_array->set_incoming_new_target_or_generator_register(
     980      212292 :         incoming_new_target_or_generator_);
     981             :   }
     982             : 
     983     2086383 :   return bytecode_array;
     984             : }
     985             : 
     986     2086348 : void BytecodeGenerator::AllocateDeferredConstants(Isolate* isolate,
     987      107218 :                                                   Handle<Script> script) {
     988             :   // Build global declaration pair arrays.
     989     4387132 :   for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) {
     990             :     Handle<FixedArray> declarations =
     991      107218 :         globals_builder->AllocateDeclarations(info(), script, isolate);
     992      107218 :     if (declarations.is_null()) return SetStackOverflow();
     993             :     builder()->SetDeferredConstantPoolEntry(
     994      107218 :         globals_builder->constant_pool_entry(), declarations);
     995             :   }
     996             : 
     997             :   // Find or build shared function infos.
     998     6513097 :   for (std::pair<FunctionLiteral*, size_t> literal : function_literals_) {
     999             :     FunctionLiteral* expr = literal.first;
    1000             :     Handle<SharedFunctionInfo> shared_info =
    1001     2340388 :         Compiler::GetSharedFunctionInfo(expr, script, isolate);
    1002     2340406 :     if (shared_info.is_null()) return SetStackOverflow();
    1003     2340406 :     builder()->SetDeferredConstantPoolEntry(literal.second, shared_info);
    1004             :   }
    1005             : 
    1006             :   // Find or build shared function infos for the native function templates.
    1007     4174483 :   for (std::pair<NativeFunctionLiteral*, size_t> literal :
    1008        1761 :        native_function_literals_) {
    1009        5283 :     NativeFunctionLiteral* expr = literal.first;
    1010             :     v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
    1011             : 
    1012             :     // Compute the function template for the native function.
    1013             :     v8::Local<v8::FunctionTemplate> info =
    1014             :         expr->extension()->GetNativeFunctionTemplate(
    1015        3522 :             v8_isolate, Utils::ToLocal(expr->name()));
    1016             :     DCHECK(!info.IsEmpty());
    1017             : 
    1018             :     Handle<SharedFunctionInfo> shared_info =
    1019             :         FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
    1020        1761 :             isolate, Utils::OpenHandle(*info), expr->name());
    1021             :     DCHECK(!shared_info.is_null());
    1022        1761 :     builder()->SetDeferredConstantPoolEntry(literal.second, shared_info);
    1023             :   }
    1024             : 
    1025             :   // Build object literal constant properties
    1026     4360482 :   for (std::pair<ObjectLiteral*, size_t> literal : object_literals_) {
    1027      187753 :     ObjectLiteral* object_literal = literal.first;
    1028      187753 :     if (object_literal->properties_count() > 0) {
    1029             :       // If constant properties is an empty fixed array, we've already added it
    1030             :       // to the constant pool when visiting the object literal.
    1031             :       Handle<ObjectBoilerplateDescription> constant_properties =
    1032             :           object_literal->GetOrBuildBoilerplateDescription(isolate);
    1033             : 
    1034             :       builder()->SetDeferredConstantPoolEntry(literal.second,
    1035      187763 :                                               constant_properties);
    1036             :     }
    1037             :   }
    1038             : 
    1039             :   // Build array literal constant elements
    1040     4327147 :   for (std::pair<ArrayLiteral*, size_t> literal : array_literals_) {
    1041             :     ArrayLiteral* array_literal = literal.first;
    1042             :     Handle<ArrayBoilerplateDescription> constant_elements =
    1043             :         array_literal->GetOrBuildBoilerplateDescription(isolate);
    1044      154412 :     builder()->SetDeferredConstantPoolEntry(literal.second, constant_elements);
    1045             :   }
    1046             : 
    1047             :   // Build class literal boilerplates.
    1048     4211572 :   for (std::pair<ClassLiteral*, size_t> literal : class_literals_) {
    1049             :     ClassLiteral* class_literal = literal.first;
    1050             :     Handle<ClassBoilerplate> class_boilerplate =
    1051       38836 :         ClassBoilerplate::BuildClassBoilerplate(isolate, class_literal);
    1052       38836 :     builder()->SetDeferredConstantPoolEntry(literal.second, class_boilerplate);
    1053             :   }
    1054             : 
    1055             :   // Build template literals.
    1056     4174580 :   for (std::pair<GetTemplateObject*, size_t> literal : template_objects_) {
    1057             :     GetTemplateObject* get_template_object = literal.first;
    1058             :     Handle<TemplateObjectDescription> description =
    1059        1844 :         get_template_object->GetOrBuildDescription(isolate);
    1060        1844 :     builder()->SetDeferredConstantPoolEntry(literal.second, description);
    1061             :   }
    1062             : }
    1063             : 
    1064     8630688 : void BytecodeGenerator::GenerateBytecode(uintptr_t stack_limit) {
    1065             :   DisallowHeapAllocation no_allocation;
    1066             :   DisallowHandleAllocation no_handles;
    1067             :   DisallowHandleDereference no_deref;
    1068             : 
    1069             :   InitializeAstVisitor(stack_limit);
    1070             : 
    1071             :   // Initialize the incoming context.
    1072     2109753 :   ContextScope incoming_context(this, closure_scope());
    1073             : 
    1074             :   // Initialize control scope.
    1075             :   ControlScopeForTopLevel control(this);
    1076             : 
    1077     2109532 :   RegisterAllocationScope register_scope(this);
    1078             : 
    1079     2109754 :   AllocateTopLevelRegisters();
    1080             : 
    1081     4219576 :   if (info()->literal()->CanSuspend()) {
    1082        9177 :     BuildGeneratorPrologue();
    1083             :   }
    1084             : 
    1085     2109764 :   if (closure_scope()->NeedsContext()) {
    1086             :     // Push a new inner context scope for the function.
    1087      191636 :     BuildNewLocalActivationContext();
    1088      191630 :     ContextScope local_function_context(this, closure_scope());
    1089      191631 :     BuildLocalActivationContextInitialization();
    1090      191624 :     GenerateBytecodeBody();
    1091             :   } else {
    1092     1918128 :     GenerateBytecodeBody();
    1093             :   }
    1094             : 
    1095             :   // Check that we are not falling off the end.
    1096     2109621 :   DCHECK(!builder()->RequiresImplicitReturn());
    1097     2109647 : }
    1098             : 
    1099    21113919 : void BytecodeGenerator::GenerateBytecodeBody() {
    1100             :   // Build the arguments object if it is used.
    1101     2109721 :   VisitArgumentsObject(closure_scope()->arguments());
    1102             : 
    1103             :   // Build rest arguments array if it is used.
    1104             :   Variable* rest_parameter = closure_scope()->rest_parameter();
    1105     2109727 :   VisitRestArgumentsArray(rest_parameter);
    1106             : 
    1107             :   // Build assignment to the function name or {.this_function}
    1108             :   // variables if used.
    1109     2109741 :   VisitThisFunctionVariable(closure_scope()->function_var());
    1110     2109736 :   VisitThisFunctionVariable(closure_scope()->this_function_var());
    1111             : 
    1112             :   // Build assignment to {new.target} variable if it is used.
    1113     2109741 :   VisitNewTargetVariable(closure_scope()->new_target_var());
    1114             : 
    1115             :   // Create a generator object if necessary and initialize the
    1116             :   // {.generator_object} variable.
    1117     2109725 :   if (IsResumableFunction(info()->literal()->kind())) {
    1118       10864 :     BuildGeneratorObjectVariableInitialization();
    1119             :   }
    1120             : 
    1121             :   // Emit tracing call if requested to do so.
    1122     2109761 :   if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter);
    1123             : 
    1124             :   // Emit type profile call.
    1125     2109761 :   if (info()->collect_type_profile()) {
    1126          85 :     feedback_spec()->AddTypeProfileSlot();
    1127          85 :     int num_parameters = closure_scope()->num_parameters();
    1128         205 :     for (int i = 0; i < num_parameters; i++) {
    1129         120 :       Register parameter(builder()->Parameter(i));
    1130         120 :       builder()->LoadAccumulatorWithRegister(parameter).CollectTypeProfile(
    1131         240 :           closure_scope()->parameter(i)->initializer_position());
    1132             :     }
    1133             :   }
    1134             : 
    1135             :   // Visit declarations within the function scope.
    1136     2109761 :   VisitDeclarations(closure_scope()->declarations());
    1137             : 
    1138             :   // Emit initializing assignments for module namespace imports (if any).
    1139     2109641 :   VisitModuleNamespaceImports();
    1140             : 
    1141             :   // Perform a stack-check before the body.
    1142     2109672 :   builder()->StackCheck(info()->literal()->start_position());
    1143             : 
    1144             :   // The derived constructor case is handled in VisitCallSuper.
    1145     2126129 :   if (IsBaseConstructor(function_kind()) &&
    1146       16332 :       info()->literal()->requires_instance_members_initializer()) {
    1147             :     BuildInstanceMemberInitialization(Register::function_closure(),
    1148         516 :                                       builder()->Receiver());
    1149             :   }
    1150             : 
    1151             :   // Visit statements in the function body.
    1152     2109797 :   VisitStatements(info()->literal()->body());
    1153             : 
    1154             :   // Emit an implicit return instruction in case control flow can fall off the
    1155             :   // end of the function without an explicit return being present on all paths.
    1156     2109506 :   if (builder()->RequiresImplicitReturn()) {
    1157      373649 :     builder()->LoadUndefined();
    1158      373650 :     BuildReturn();
    1159             :   }
    1160     2109518 : }
    1161             : 
    1162     4219522 : void BytecodeGenerator::AllocateTopLevelRegisters() {
    1163     2109738 :   if (IsResumableFunction(info()->literal()->kind())) {
    1164             :     // Either directly use generator_object_var or allocate a new register for
    1165             :     // the incoming generator object.
    1166       10864 :     Variable* generator_object_var = closure_scope()->generator_object_var();
    1167       10864 :     if (generator_object_var->location() == VariableLocation::LOCAL) {
    1168             :       incoming_new_target_or_generator_ =
    1169       10864 :           GetRegisterForLocalVariable(generator_object_var);
    1170             :     } else {
    1171           0 :       incoming_new_target_or_generator_ = register_allocator()->NewRegister();
    1172             :     }
    1173     2098920 :   } else if (closure_scope()->new_target_var()) {
    1174             :     // Either directly use new_target_var or allocate a new register for
    1175             :     // the incoming new target object.
    1176      100313 :     Variable* new_target_var = closure_scope()->new_target_var();
    1177      100313 :     if (new_target_var->location() == VariableLocation::LOCAL) {
    1178             :       incoming_new_target_or_generator_ =
    1179        5449 :           GetRegisterForLocalVariable(new_target_var);
    1180             :     } else {
    1181       94864 :       incoming_new_target_or_generator_ = register_allocator()->NewRegister();
    1182             :     }
    1183             :   }
    1184     2109784 : }
    1185             : 
    1186        9177 : void BytecodeGenerator::BuildGeneratorPrologue() {
    1187             :   DCHECK_GT(info()->literal()->suspend_count(), 0);
    1188             :   DCHECK(generator_object().is_valid());
    1189             :   generator_jump_table_ =
    1190        9177 :       builder()->AllocateJumpTable(info()->literal()->suspend_count(), 0);
    1191             : 
    1192             :   // If the generator is not undefined, this is a resume, so perform state
    1193             :   // dispatch.
    1194        9177 :   builder()->SwitchOnGeneratorState(generator_object(), generator_jump_table_);
    1195             : 
    1196             :   // Otherwise, fall-through to the ordinary function prologue, after which we
    1197             :   // will run into the generator object creation and other extra code inserted
    1198             :   // by the parser.
    1199        9177 : }
    1200             : 
    1201    10505241 : void BytecodeGenerator::VisitBlock(Block* stmt) {
    1202             :   // Visit declarations and statements.
    1203             :   CurrentScope current_scope(this, stmt->scope());
    1204     5435920 :   if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) {
    1205       24810 :     BuildNewLocalBlockContext(stmt->scope());
    1206       24805 :     ContextScope scope(this, stmt->scope());
    1207       24810 :     VisitBlockDeclarationsAndStatements(stmt);
    1208             :   } else {
    1209     5215408 :     VisitBlockDeclarationsAndStatements(stmt);
    1210             :   }
    1211     5240357 : }
    1212             : 
    1213    10480412 : void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) {
    1214     5240206 :   BlockBuilder block_builder(builder(), block_coverage_builder_, stmt);
    1215             :   ControlScopeForBreakable execution_control(this, stmt, &block_builder);
    1216     5240206 :   if (stmt->scope() != nullptr) {
    1217      195705 :     VisitDeclarations(stmt->scope()->declarations());
    1218             :   }
    1219     5240214 :   VisitStatements(stmt->statements());
    1220     5240336 : }
    1221             : 
    1222     6532267 : void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
    1223     6817265 :   Variable* variable = decl->var();
    1224     4551038 :   switch (variable->location()) {
    1225             :     case VariableLocation::UNALLOCATED: {
    1226             :       DCHECK(!variable->binding_needs_init());
    1227             :       FeedbackSlot slot =
    1228     1240524 :           GetCachedLoadGlobalICSlot(NOT_INSIDE_TYPEOF, variable);
    1229             :       globals_builder()->AddUndefinedDeclaration(variable->raw_name(), slot);
    1230             :       break;
    1231             :     }
    1232             :     case VariableLocation::LOCAL:
    1233     1526758 :       if (variable->binding_needs_init()) {
    1234        3190 :         Register destination(builder()->Local(variable->index()));
    1235        3190 :         builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
    1236             :       }
    1237             :       break;
    1238             :     case VariableLocation::PARAMETER:
    1239         586 :       if (variable->binding_needs_init()) {
    1240           0 :         Register destination(builder()->Parameter(variable->index()));
    1241           0 :         builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
    1242             :       }
    1243             :       break;
    1244             :     case VariableLocation::CONTEXT:
    1245     1483876 :       if (variable->binding_needs_init()) {
    1246             :         DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
    1247      740622 :         builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(),
    1248      740689 :                                                   variable->index(), 0);
    1249             :       }
    1250             :       break;
    1251             :     case VariableLocation::LOOKUP: {
    1252             :       DCHECK_EQ(VariableMode::kDynamic, variable->mode());
    1253             :       DCHECK(!variable->binding_needs_init());
    1254             : 
    1255      281808 :       Register name = register_allocator()->NewRegister();
    1256             : 
    1257             :       builder()
    1258      281808 :           ->LoadLiteral(variable->raw_name())
    1259      281808 :           .StoreAccumulatorInRegister(name)
    1260      281808 :           .CallRuntime(Runtime::kDeclareEvalVar, name);
    1261             :       break;
    1262             :     }
    1263             :     case VariableLocation::MODULE:
    1264       17646 :       if (variable->IsExport() && variable->binding_needs_init()) {
    1265       17039 :         builder()->LoadTheHole();
    1266       17039 :         BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
    1267             :       }
    1268             :       // Nothing to do for imports.
    1269             :       break;
    1270             :   }
    1271     4551143 : }
    1272             : 
    1273     1968909 : void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
    1274      974436 :   Variable* variable = decl->var();
    1275             :   DCHECK(variable->mode() == VariableMode::kLet ||
    1276             :          variable->mode() == VariableMode::kVar ||
    1277             :          variable->mode() == VariableMode::kDynamic);
    1278      502260 :   switch (variable->location()) {
    1279             :     case VariableLocation::UNALLOCATED: {
    1280             :       FeedbackSlot slot =
    1281      249649 :           GetCachedLoadGlobalICSlot(NOT_INSIDE_TYPEOF, variable);
    1282      249680 :       FeedbackSlot literal_slot = GetCachedCreateClosureSlot(decl->fun());
    1283             :       globals_builder()->AddFunctionDeclaration(variable->raw_name(), slot,
    1284             :                                                 literal_slot, decl->fun());
    1285      249703 :       AddToEagerLiteralsIfEager(decl->fun());
    1286             :       break;
    1287             :     }
    1288             :     case VariableLocation::PARAMETER:
    1289             :     case VariableLocation::LOCAL: {
    1290       29804 :       VisitFunctionLiteral(decl->fun());
    1291       29804 :       BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
    1292       29804 :       break;
    1293             :     }
    1294             :     case VariableLocation::CONTEXT: {
    1295             :       DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
    1296      215248 :       VisitFunctionLiteral(decl->fun());
    1297             :       builder()->StoreContextSlot(execution_context()->reg(), variable->index(),
    1298      215246 :                                   0);
    1299      215249 :       break;
    1300             :     }
    1301             :     case VariableLocation::LOOKUP: {
    1302        7232 :       RegisterList args = register_allocator()->NewRegisterList(2);
    1303             :       builder()
    1304        7232 :           ->LoadLiteral(variable->raw_name())
    1305        7232 :           .StoreAccumulatorInRegister(args[0]);
    1306        7232 :       VisitFunctionLiteral(decl->fun());
    1307        7232 :       builder()->StoreAccumulatorInRegister(args[1]).CallRuntime(
    1308        7232 :           Runtime::kDeclareEvalFunction, args);
    1309             :       break;
    1310             :     }
    1311             :     case VariableLocation::MODULE:
    1312             :       DCHECK_EQ(variable->mode(), VariableMode::kLet);
    1313             :       DCHECK(variable->IsExport());
    1314         340 :       VisitForAccumulatorValue(decl->fun());
    1315         340 :       BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
    1316         340 :       break;
    1317             :   }
    1318             :   DCHECK_IMPLIES(decl->fun()->ShouldEagerCompile(),
    1319             :                  IsInEagerLiterals(decl->fun(), *eager_inner_literals_));
    1320      502302 : }
    1321             : 
    1322     2110866 : void BytecodeGenerator::VisitModuleNamespaceImports() {
    1323     4218178 :   if (!closure_scope()->is_module_scope()) return;
    1324             : 
    1325             :   RegisterAllocationScope register_scope(this);
    1326        1098 :   Register module_request = register_allocator()->NewRegister();
    1327             : 
    1328        1098 :   ModuleDescriptor* descriptor = closure_scope()->AsModuleScope()->module();
    1329        2326 :   for (auto entry : descriptor->namespace_imports()) {
    1330             :     builder()
    1331         260 :         ->LoadLiteral(Smi::FromInt(entry->module_request))
    1332         130 :         .StoreAccumulatorInRegister(module_request)
    1333         130 :         .CallRuntime(Runtime::kGetModuleNamespace, module_request);
    1334         130 :     Variable* var = closure_scope()->LookupInModule(entry->local_name);
    1335         130 :     BuildVariableAssignment(var, Token::INIT, HoleCheckMode::kElided);
    1336        1098 :   }
    1337             : }
    1338             : 
    1339     5280333 : void BytecodeGenerator::VisitDeclarations(Declaration::List* declarations) {
    1340             :   RegisterAllocationScope register_scope(this);
    1341             :   DCHECK(globals_builder()->empty());
    1342     9746143 :   for (Declaration* decl : *declarations) {
    1343             :     RegisterAllocationScope register_scope(this);
    1344     5053262 :     Visit(decl);
    1345     5053379 :   }
    1346     4575467 :   if (globals_builder()->empty()) return;
    1347             : 
    1348             :   globals_builder()->set_constant_pool_entry(
    1349      117487 :       builder()->AllocateDeferredConstantPoolEntry());
    1350      117500 :   int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
    1351      117500 :                       DeclareGlobalsNativeFlag::encode(info()->is_native());
    1352             : 
    1353             :   // Emit code to declare globals.
    1354      117500 :   RegisterList args = register_allocator()->NewRegisterList(3);
    1355             :   builder()
    1356      117495 :       ->LoadConstantPoolEntry(globals_builder()->constant_pool_entry())
    1357      117489 :       .StoreAccumulatorInRegister(args[0])
    1358      117496 :       .LoadLiteral(Smi::FromInt(encoded_flags))
    1359      117434 :       .StoreAccumulatorInRegister(args[1])
    1360      234966 :       .MoveRegister(Register::function_closure(), args[2])
    1361      117428 :       .CallRuntime(Runtime::kDeclareGlobals, args);
    1362             : 
    1363             :   // Push and reset globals builder.
    1364      234957 :   global_declarations_.push_back(globals_builder());
    1365      117452 :   globals_builder_ = new (zone()) GlobalDeclarationsBuilder(zone());
    1366             : }
    1367             : 
    1368     7429435 : void BytecodeGenerator::VisitStatements(
    1369    22673419 :     const ZonePtrList<Statement>* statements) {
    1370    45346838 :   for (int i = 0; i < statements->length(); i++) {
    1371             :     // Allocate an outer register allocations scope for the statement.
    1372             :     RegisterAllocationScope allocation_scope(this);
    1373    17192589 :     Statement* stmt = statements->at(i);
    1374    17192589 :     Visit(stmt);
    1375    17191593 :     if (builder()->RemainderOfBlockIsDead()) break;
    1376    15244080 :   }
    1377     7428383 : }
    1378             : 
    1379    20310700 : void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
    1380             :   builder()->SetStatementPosition(stmt);
    1381    10155350 :   VisitForEffect(stmt->expression());
    1382    10154548 : }
    1383             : 
    1384           0 : void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {}
    1385             : 
    1386     3343515 : void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
    1387             :   ConditionalControlFlowBuilder conditional_builder(
    1388      550542 :       builder(), block_coverage_builder_, stmt);
    1389             :   builder()->SetStatementPosition(stmt);
    1390             : 
    1391      550542 :   if (stmt->condition()->ToBooleanIsTrue()) {
    1392             :     // Generate then block unconditionally as always true.
    1393         442 :     conditional_builder.Then();
    1394         442 :     Visit(stmt->then_statement());
    1395      550101 :   } else if (stmt->condition()->ToBooleanIsFalse()) {
    1396             :     // Generate else block unconditionally if it exists.
    1397        8312 :     if (stmt->HasElseStatement()) {
    1398        7048 :       conditional_builder.Else();
    1399        7048 :       Visit(stmt->else_statement());
    1400             :     }
    1401             :   } else {
    1402             :     // TODO(oth): If then statement is BreakStatement or
    1403             :     // ContinueStatement we can reduce number of generated
    1404             :     // jump/jump_ifs here. See BasicLoops test.
    1405             :     VisitForTest(stmt->condition(), conditional_builder.then_labels(),
    1406      541794 :                  conditional_builder.else_labels(), TestFallthrough::kThen);
    1407             : 
    1408      541805 :     conditional_builder.Then();
    1409      541799 :     Visit(stmt->then_statement());
    1410             : 
    1411      541810 :     if (stmt->HasElseStatement()) {
    1412       51132 :       conditional_builder.JumpToEnd();
    1413       51131 :       conditional_builder.Else();
    1414       51128 :       Visit(stmt->else_statement());
    1415             :     }
    1416      550562 :   }
    1417      550559 : }
    1418             : 
    1419        3071 : void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
    1420        3071 :     SloppyBlockFunctionStatement* stmt) {
    1421        3071 :   Visit(stmt->statement());
    1422        3072 : }
    1423             : 
    1424        7466 : void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
    1425             :   AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
    1426             :   builder()->SetStatementPosition(stmt);
    1427             :   execution_control()->Continue(stmt->target());
    1428        3733 : }
    1429             : 
    1430       94343 : void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
    1431             :   AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
    1432             :   builder()->SetStatementPosition(stmt);
    1433             :   execution_control()->Break(stmt->target());
    1434       47171 : }
    1435             : 
    1436     6182065 : void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
    1437             :   AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
    1438             :   builder()->SetStatementPosition(stmt);
    1439     2060592 :   VisitForAccumulatorValue(stmt->expression());
    1440     2060949 :   if (stmt->is_async_return()) {
    1441             :     execution_control()->AsyncReturnAccumulator(stmt->end_position());
    1442             :   } else {
    1443             :     execution_control()->ReturnAccumulator(stmt->end_position());
    1444             :   }
    1445     2060986 : }
    1446             : 
    1447       11822 : void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
    1448             :   builder()->SetStatementPosition(stmt);
    1449        2955 :   VisitForAccumulatorValue(stmt->expression());
    1450        2956 :   BuildNewLocalWithContext(stmt->scope());
    1451        2956 :   VisitInScope(stmt->statement(), stmt->scope());
    1452        2956 : }
    1453             : 
    1454       20880 : void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
    1455             :   // We need this scope because we visit for register values. We have to
    1456             :   // maintain a execution result scope where registers can be allocated.
    1457      199970 :   ZonePtrList<CaseClause>* clauses = stmt->cases();
    1458             :   SwitchBuilder switch_builder(builder(), block_coverage_builder_, stmt,
    1459       10440 :                                clauses->length());
    1460             :   ControlScopeForBreakable scope(this, stmt, &switch_builder);
    1461             :   int default_index = -1;
    1462             : 
    1463             :   builder()->SetStatementPosition(stmt);
    1464             : 
    1465             :   // Keep the switch value in a register until a case matches.
    1466       10440 :   Register tag = VisitForRegisterValue(stmt->tag());
    1467             :   FeedbackSlot slot = clauses->length() > 0
    1468       10412 :                           ? feedback_spec()->AddCompareICSlot()
    1469       10440 :                           : FeedbackSlot::Invalid();
    1470             : 
    1471             :   // Iterate over all cases and create nodes for label comparison.
    1472      179090 :   for (int i = 0; i < clauses->length(); i++) {
    1473       79105 :     CaseClause* clause = clauses->at(i);
    1474             : 
    1475             :     // The default is not a test, remember index.
    1476       79105 :     if (clause->is_default()) {
    1477             :       default_index = i;
    1478             :       continue;
    1479             :     }
    1480             : 
    1481             :     // Perform label comparison as if via '===' with tag.
    1482       71853 :     VisitForAccumulatorValue(clause->label());
    1483             :     builder()->CompareOperation(Token::Value::EQ_STRICT, tag,
    1484       71853 :                                 feedback_index(slot));
    1485       71852 :     switch_builder.Case(ToBooleanMode::kAlreadyBoolean, i);
    1486             :   }
    1487             : 
    1488       10440 :   if (default_index >= 0) {
    1489             :     // Emit default jump if there is a default case.
    1490        7252 :     switch_builder.DefaultAt(default_index);
    1491             :   } else {
    1492             :     // Otherwise if we have reached here none of the cases matched, so jump to
    1493             :     // the end.
    1494             :     switch_builder.Break();
    1495             :   }
    1496             : 
    1497             :   // Iterate over all cases and create the case bodies.
    1498      168649 :   for (int i = 0; i < clauses->length(); i++) {
    1499       79105 :     CaseClause* clause = clauses->at(i);
    1500       79105 :     switch_builder.SetCaseTarget(i, clause);
    1501       79105 :     VisitStatements(clause->statements());
    1502       10440 :   }
    1503       10440 : }
    1504             : 
    1505             : template <typename TryBodyFunc, typename CatchBodyFunc>
    1506      110417 : void BytecodeGenerator::BuildTryCatch(
    1507             :     TryBodyFunc try_body_func, CatchBodyFunc catch_body_func,
    1508             :     HandlerTable::CatchPrediction catch_prediction,
    1509             :     TryCatchStatement* stmt_for_coverage) {
    1510             :   TryCatchBuilder try_control_builder(
    1511             :       builder(),
    1512             :       stmt_for_coverage == nullptr ? nullptr : block_coverage_builder_,
    1513      110417 :       stmt_for_coverage, catch_prediction);
    1514             : 
    1515             :   // Preserve the context in a dedicated register, so that it can be restored
    1516             :   // when the handler is entered by the stack-unwinding machinery.
    1517             :   // TODO(mstarzinger): Be smarter about register allocation.
    1518      110421 :   Register context = register_allocator()->NewRegister();
    1519      110425 :   builder()->MoveRegister(Register::current_context(), context);
    1520             : 
    1521             :   // Evaluate the try-block inside a control scope. This simulates a handler
    1522             :   // that is intercepting 'throw' control commands.
    1523      110431 :   try_control_builder.BeginTry(context);
    1524             :   {
    1525             :     ControlScopeForTryCatch scope(this, &try_control_builder);
    1526      110420 :     try_body_func();
    1527             :   }
    1528      110424 :   try_control_builder.EndTry();
    1529             : 
    1530      110400 :   catch_body_func(context);
    1531             : 
    1532      110415 :   try_control_builder.EndCatch();
    1533      110388 : }
    1534             : 
    1535             : template <typename TryBodyFunc, typename FinallyBodyFunc>
    1536       44101 : void BytecodeGenerator::BuildTryFinally(
    1537             :     TryBodyFunc try_body_func, FinallyBodyFunc finally_body_func,
    1538             :     HandlerTable::CatchPrediction catch_prediction,
    1539             :     TryFinallyStatement* stmt_for_coverage) {
    1540             :   // We can't know whether the finally block will override ("catch") an
    1541             :   // exception thrown in the try block, so we just adopt the outer prediction.
    1542             :   TryFinallyBuilder try_control_builder(
    1543             :       builder(),
    1544             :       stmt_for_coverage == nullptr ? nullptr : block_coverage_builder_,
    1545       44101 :       stmt_for_coverage, catch_prediction);
    1546             : 
    1547             :   // We keep a record of all paths that enter the finally-block to be able to
    1548             :   // dispatch to the correct continuation point after the statements in the
    1549             :   // finally-block have been evaluated.
    1550             :   //
    1551             :   // The try-finally construct can enter the finally-block in three ways:
    1552             :   // 1. By exiting the try-block normally, falling through at the end.
    1553             :   // 2. By exiting the try-block with a function-local control flow transfer
    1554             :   //    (i.e. through break/continue/return statements).
    1555             :   // 3. By exiting the try-block with a thrown exception.
    1556             :   //
    1557             :   // The result register semantics depend on how the block was entered:
    1558             :   //  - ReturnStatement: It represents the return value being returned.
    1559             :   //  - ThrowStatement: It represents the exception being thrown.
    1560             :   //  - BreakStatement/ContinueStatement: Undefined and not used.
    1561             :   //  - Falling through into finally-block: Undefined and not used.
    1562       44102 :   Register token = register_allocator()->NewRegister();
    1563       44111 :   Register result = register_allocator()->NewRegister();
    1564       44109 :   ControlScope::DeferredCommands commands(this, token, result);
    1565             : 
    1566             :   // Preserve the context in a dedicated register, so that it can be restored
    1567             :   // when the handler is entered by the stack-unwinding machinery.
    1568             :   // TODO(mstarzinger): Be smarter about register allocation.
    1569       44111 :   Register context = register_allocator()->NewRegister();
    1570       44112 :   builder()->MoveRegister(Register::current_context(), context);
    1571             : 
    1572             :   // Evaluate the try-block inside a control scope. This simulates a handler
    1573             :   // that is intercepting all control commands.
    1574       44114 :   try_control_builder.BeginTry(context);
    1575             :   {
    1576             :     ControlScopeForTryFinally scope(this, &try_control_builder, &commands);
    1577       40737 :     try_body_func();
    1578             :   }
    1579       44110 :   try_control_builder.EndTry();
    1580             : 
    1581             :   // Record fall-through and exception cases.
    1582       44110 :   commands.RecordFallThroughPath();
    1583       44111 :   try_control_builder.LeaveTry();
    1584       44112 :   try_control_builder.BeginHandler();
    1585             :   commands.RecordHandlerReThrowPath();
    1586             : 
    1587             :   // Pending message object is saved on entry.
    1588       44113 :   try_control_builder.BeginFinally();
    1589       44111 :   Register message = context;  // Reuse register.
    1590             : 
    1591             :   // Clear message object as we enter the finally block.
    1592       44111 :   builder()->LoadTheHole().SetPendingMessage().StoreAccumulatorInRegister(
    1593             :       message);
    1594             : 
    1595             :   // Evaluate the finally-block.
    1596             :   finally_body_func(token);
    1597       44109 :   try_control_builder.EndFinally();
    1598             : 
    1599             :   // Pending message object is restored on exit.
    1600       44106 :   builder()->LoadAccumulatorWithRegister(message).SetPendingMessage();
    1601             : 
    1602             :   // Dynamic dispatch after the finally-block.
    1603       44109 :   commands.ApplyDeferredCommands();
    1604       44109 : }
    1605             : 
    1606      525342 : void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
    1607             :                                            LoopBuilder* loop_builder) {
    1608      262640 :   loop_builder->LoopBody();
    1609             :   ControlScopeForIteration execution_control(this, stmt, loop_builder);
    1610      262668 :   builder()->StackCheck(stmt->position());
    1611      262702 :   Visit(stmt->body());
    1612      262690 :   loop_builder->BindContinueTarget();
    1613      262664 : }
    1614             : 
    1615        5164 : void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
    1616        1215 :   LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
    1617        1216 :   if (stmt->cond()->ToBooleanIsFalse()) {
    1618         364 :     VisitIterationBody(stmt, &loop_builder);
    1619         852 :   } else if (stmt->cond()->ToBooleanIsTrue()) {
    1620         225 :     loop_builder.LoopHeader();
    1621         225 :     VisitIterationBody(stmt, &loop_builder);
    1622         225 :     loop_builder.JumpToHeader(loop_depth_);
    1623             :   } else {
    1624         627 :     loop_builder.LoopHeader();
    1625         627 :     VisitIterationBody(stmt, &loop_builder);
    1626             :     builder()->SetExpressionAsStatementPosition(stmt->cond());
    1627             :     BytecodeLabels loop_backbranch(zone());
    1628             :     VisitForTest(stmt->cond(), &loop_backbranch, loop_builder.break_labels(),
    1629         627 :                  TestFallthrough::kThen);
    1630         627 :     loop_backbranch.Bind(builder());
    1631         627 :     loop_builder.JumpToHeader(loop_depth_);
    1632        1216 :   }
    1633        1217 : }
    1634             : 
    1635       76239 : void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
    1636       13970 :   LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
    1637             : 
    1638       13969 :   if (stmt->cond()->ToBooleanIsFalse()) {
    1639             :     // If the condition is false there is no need to generate the loop.
    1640         117 :     return;
    1641             :   }
    1642             : 
    1643       13854 :   loop_builder.LoopHeader();
    1644       13854 :   if (!stmt->cond()->ToBooleanIsTrue()) {
    1645             :     builder()->SetExpressionAsStatementPosition(stmt->cond());
    1646             :     BytecodeLabels loop_body(zone());
    1647             :     VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(),
    1648       11482 :                  TestFallthrough::kThen);
    1649       11483 :     loop_body.Bind(builder());
    1650             :   }
    1651       13856 :   VisitIterationBody(stmt, &loop_builder);
    1652       13855 :   loop_builder.JumpToHeader(loop_depth_);
    1653             : }
    1654             : 
    1655     1813724 : void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
    1656      220268 :   LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
    1657             : 
    1658      220267 :   if (stmt->init() != nullptr) {
    1659      159707 :     Visit(stmt->init());
    1660             :   }
    1661      220296 :   if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
    1662             :     // If the condition is known to be false there is no need to generate
    1663             :     // body, next or condition blocks. Init block should be generated.
    1664       15470 :     return;
    1665             :   }
    1666             : 
    1667      204814 :   loop_builder.LoopHeader();
    1668      204804 :   if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
    1669             :     builder()->SetExpressionAsStatementPosition(stmt->cond());
    1670             :     BytecodeLabels loop_body(zone());
    1671             :     VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(),
    1672      187884 :                  TestFallthrough::kThen);
    1673      187904 :     loop_body.Bind(builder());
    1674             :   }
    1675      204825 :   VisitIterationBody(stmt, &loop_builder);
    1676      204803 :   if (stmt->next() != nullptr) {
    1677             :     builder()->SetStatementPosition(stmt->next());
    1678      179634 :     Visit(stmt->next());
    1679             :   }
    1680      204816 :   loop_builder.JumpToHeader(loop_depth_);
    1681             : }
    1682             : 
    1683        4800 : void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
    1684       33326 :   if (stmt->subject()->IsNullLiteral() ||
    1685        4776 :       stmt->subject()->IsUndefinedLiteral()) {
    1686             :     // ForIn generates lots of code, skip if it wouldn't produce any effects.
    1687          51 :     return;
    1688             :   }
    1689             : 
    1690             :   BytecodeLabel subject_null_label, subject_undefined_label;
    1691        4749 :   FeedbackSlot slot = feedback_spec()->AddForInSlot();
    1692             : 
    1693             :   // Prepare the state for executing ForIn.
    1694             :   builder()->SetExpressionAsStatementPosition(stmt->subject());
    1695        4749 :   VisitForAccumulatorValue(stmt->subject());
    1696        4751 :   builder()->JumpIfUndefined(&subject_undefined_label);
    1697        4751 :   builder()->JumpIfNull(&subject_null_label);
    1698        4750 :   Register receiver = register_allocator()->NewRegister();
    1699        4751 :   builder()->ToObject(receiver);
    1700             : 
    1701             :   // Used as kRegTriple and kRegPair in ForInPrepare and ForInNext.
    1702        4750 :   RegisterList triple = register_allocator()->NewRegisterList(3);
    1703        4751 :   Register cache_length = triple[2];
    1704        4751 :   builder()->ForInEnumerate(receiver);
    1705        4751 :   builder()->ForInPrepare(triple, feedback_index(slot));
    1706             : 
    1707             :   // Set up loop counter
    1708        4751 :   Register index = register_allocator()->NewRegister();
    1709        4751 :   builder()->LoadLiteral(Smi::zero());
    1710        4751 :   builder()->StoreAccumulatorInRegister(index);
    1711             : 
    1712             :   // The loop
    1713             :   {
    1714        4751 :     LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
    1715        4749 :     loop_builder.LoopHeader();
    1716             :     builder()->SetExpressionAsStatementPosition(stmt->each());
    1717        4751 :     builder()->ForInContinue(index, cache_length);
    1718             :     loop_builder.BreakIfFalse(ToBooleanMode::kAlreadyBoolean);
    1719             :     builder()->ForInNext(receiver, index, triple.Truncate(2),
    1720        4751 :                          feedback_index(slot));
    1721             :     loop_builder.ContinueIfUndefined();
    1722             : 
    1723             :     // Assign accumulator value to the 'each' target.
    1724             :     {
    1725             :       EffectResultScope scope(this);
    1726             :       // Make sure to preserve the accumulator across the PrepareAssignmentLhs
    1727             :       // call.
    1728             :       AssignmentLhsData lhs_data = PrepareAssignmentLhs(
    1729        4751 :           stmt->each(), AccumulatorPreservingMode::kPreserve);
    1730             :       builder()->SetExpressionPosition(stmt->each());
    1731        4751 :       BuildAssignment(lhs_data, Token::ASSIGN, LookupHoistingMode::kNormal);
    1732             :     }
    1733             : 
    1734        4749 :     VisitIterationBody(stmt, &loop_builder);
    1735        4751 :     builder()->ForInStep(index);
    1736        4750 :     builder()->StoreAccumulatorInRegister(index);
    1737        4751 :     loop_builder.JumpToHeader(loop_depth_);
    1738             :   }
    1739        4751 :   builder()->Bind(&subject_null_label);
    1740        4751 :   builder()->Bind(&subject_undefined_label);
    1741             : }
    1742             : 
    1743             : // Desugar a for-of statement into an application of the iteration protocol.
    1744             : //
    1745             : // for (EACH of SUBJECT) BODY
    1746             : //
    1747             : //   becomes
    1748             : //
    1749             : // iterator = %GetIterator(SUBJECT)
    1750             : // try {
    1751             : //
    1752             : //   loop {
    1753             : //     // Make sure we are considered 'done' if .next(), .done or .value fail.
    1754             : //     done = true
    1755             : //     value = iterator.next()
    1756             : //     if (value.done) break;
    1757             : //     value = value.value
    1758             : //     done = false
    1759             : //
    1760             : //     EACH = value
    1761             : //     BODY
    1762             : //   }
    1763             : //   done = true
    1764             : //
    1765             : // } catch(e) {
    1766             : //   iteration_continuation = RETHROW
    1767             : // } finally {
    1768             : //   %FinalizeIteration(iterator, done, iteration_continuation)
    1769             : // }
    1770       38045 : void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
    1771             :   EffectResultScope effect_scope(this);
    1772             : 
    1773      114144 :   builder()->SetExpressionAsStatementPosition(stmt->subject());
    1774       38045 :   VisitForAccumulatorValue(stmt->subject());
    1775             : 
    1776             :   // Store the iterator in a dedicated register so that it can be closed on
    1777             :   // exit, and the 'done' value in a dedicated register so that it can be
    1778             :   // changed and accessed independently of the iteration result.
    1779       76108 :   IteratorRecord iterator = BuildGetIteratorRecord(stmt->type());
    1780       38054 :   Register done = register_allocator()->NewRegister();
    1781       38048 :   builder()->LoadFalse();
    1782       38051 :   builder()->StoreAccumulatorInRegister(done);
    1783             : 
    1784             :   BuildTryFinally(
    1785             :       // Try block.
    1786       38039 :       [&]() {
    1787      114144 :         Register next_result = register_allocator()->NewRegister();
    1788             : 
    1789       38048 :         LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
    1790       38043 :         loop_builder.LoopHeader();
    1791             : 
    1792       38046 :         builder()->LoadTrue().StoreAccumulatorInRegister(done);
    1793             : 
    1794             :         // Call the iterator's .next() method. Break from the loop if the `done`
    1795             :         // property is truthy, otherwise load the value from the iterator result
    1796             :         // and append the argument.
    1797       76105 :         builder()->SetExpressionAsStatementPosition(stmt->each());
    1798       38051 :         BuildIteratorNext(iterator, next_result);
    1799             :         builder()->LoadNamedProperty(
    1800             :             next_result, ast_string_constants()->done_string(),
    1801      152204 :             feedback_index(feedback_spec()->AddLoadICSlot()));
    1802             :         loop_builder.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
    1803             : 
    1804             :         builder()
    1805             :             // value = value.value
    1806             :             ->LoadNamedProperty(
    1807             :                 next_result, ast_string_constants()->value_string(),
    1808      152214 :                 feedback_index(feedback_spec()->AddLoadICSlot()));
    1809             :         // done = false, before the assignment to each happens, so that done is
    1810             :         // false if the assignment throws.
    1811             :         builder()
    1812       38045 :             ->StoreAccumulatorInRegister(next_result)
    1813       38046 :             .LoadFalse()
    1814       76099 :             .StoreAccumulatorInRegister(done);
    1815             : 
    1816             :         // Assign to the 'each' target.
    1817       76108 :         AssignmentLhsData lhs_data = PrepareAssignmentLhs(stmt->each());
    1818       38051 :         builder()->LoadAccumulatorWithRegister(next_result);
    1819       38054 :         BuildAssignment(lhs_data, Token::ASSIGN, LookupHoistingMode::kNormal);
    1820             : 
    1821       38051 :         VisitIterationBody(stmt, &loop_builder);
    1822             : 
    1823       38048 :         loop_builder.JumpToHeader(loop_depth_);
    1824       38052 :       },
    1825             :       // Finally block.
    1826             :       [&](Register iteration_continuation_token) {
    1827             :         // Finish the iteration in the finally block.
    1828       38049 :         BuildFinalizeIteration(iterator, done, iteration_continuation_token);
    1829             :       },
    1830       38051 :       HandlerTable::UNCAUGHT);
    1831       38051 : }
    1832             : 
    1833       69680 : void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
    1834             :   // Update catch prediction tracking. The updated catch_prediction value lasts
    1835             :   // until the end of the try_block in the AST node, and does not apply to the
    1836             :   // catch_block.
    1837       69680 :   HandlerTable::CatchPrediction outer_catch_prediction = catch_prediction();
    1838       69680 :   set_catch_prediction(stmt->GetCatchPrediction(outer_catch_prediction));
    1839             : 
    1840             :   BuildTryCatch(
    1841             :       // Try body.
    1842       69675 :       [&]() {
    1843       69675 :         Visit(stmt->try_block());
    1844       69680 :         set_catch_prediction(outer_catch_prediction);
    1845       69680 :       },
    1846             :       // Catch body.
    1847       69665 :       [&](Register context) {
    1848      278707 :         if (stmt->scope()) {
    1849             :           // Create a catch scope that binds the exception.
    1850       69602 :           BuildNewLocalCatchContext(stmt->scope());
    1851       69615 :           builder()->StoreAccumulatorInRegister(context);
    1852             :         }
    1853             : 
    1854             :         // If requested, clear message object as we enter the catch block.
    1855      139368 :         if (stmt->ShouldClearPendingException(outer_catch_prediction)) {
    1856       69684 :           builder()->LoadTheHole().SetPendingMessage();
    1857             :         }
    1858             : 
    1859             :         // Load the catch context into the accumulator.
    1860       69664 :         builder()->LoadAccumulatorWithRegister(context);
    1861             : 
    1862             :         // Evaluate the catch-block.
    1863      139358 :         if (stmt->scope()) {
    1864       69612 :           VisitInScope(stmt->catch_block(), stmt->scope());
    1865             :         } else {
    1866          67 :           VisitBlock(stmt->catch_block());
    1867             :         }
    1868       69675 :       },
    1869       69680 :       catch_prediction(), stmt);
    1870       69655 : }
    1871             : 
    1872        6742 : void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
    1873             :   BuildTryFinally(
    1874             :       // Try block.
    1875        3371 :       [&]() { Visit(stmt->try_block()); },
    1876             :       // Finally block.
    1877        3371 :       [&](Register body_continuation_token) { Visit(stmt->finally_block()); },
    1878        6742 :       catch_prediction(), stmt);
    1879        3370 : }
    1880             : 
    1881           0 : void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
    1882             :   builder()->SetStatementPosition(stmt);
    1883        6525 :   builder()->Debugger();
    1884           0 : }
    1885             : 
    1886     5210018 : void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
    1887             :   DCHECK(expr->scope()->outer_scope() == current_scope());
    1888             :   uint8_t flags = CreateClosureFlags::Encode(
    1889     5210018 :       expr->pretenure(), closure_scope()->is_function_scope(),
    1890     7815027 :       info()->might_always_opt());
    1891     2605013 :   size_t entry = builder()->AllocateDeferredConstantPoolEntry();
    1892     2605122 :   FeedbackSlot slot = GetCachedCreateClosureSlot(expr);
    1893     2605362 :   builder()->CreateClosure(entry, feedback_index(slot), flags);
    1894     5210241 :   function_literals_.push_back(std::make_pair(expr, entry));
    1895     2605064 :   AddToEagerLiteralsIfEager(expr);
    1896     2605125 : }
    1897             : 
    1898     2854714 : void BytecodeGenerator::AddToEagerLiteralsIfEager(FunctionLiteral* literal) {
    1899     2854714 :   if (eager_inner_literals_ && literal->ShouldEagerCompile()) {
    1900             :     DCHECK(!IsInEagerLiterals(literal, *eager_inner_literals_));
    1901      524426 :     eager_inner_literals_->push_back(literal);
    1902             :   }
    1903     2854731 : }
    1904             : 
    1905    21605169 : bool BytecodeGenerator::ShouldOptimizeAsOneShot() const {
    1906    10501151 :   if (!FLAG_enable_one_shot_optimization) return false;
    1907             : 
    1908    10484654 :   if (loop_depth_ > 0) return false;
    1909             : 
    1910             :   // A non-top-level iife is likely to be executed multiple times and so
    1911             :   // shouldn`t be optimized as one-shot.
    1912    21229403 :   bool is_toplevel_iife = info()->literal()->is_iife() &&
    1913      978633 :                           current_scope()->outer_scope()->is_script_scope();
    1914    10125385 :   return info()->literal()->is_toplevel() || is_toplevel_iife;
    1915             : }
    1916             : 
    1917       42689 : void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
    1918             :   size_t class_boilerplate_entry =
    1919       41012 :       builder()->AllocateDeferredConstantPoolEntry();
    1920       82032 :   class_literals_.push_back(std::make_pair(expr, class_boilerplate_entry));
    1921             : 
    1922      632687 :   VisitDeclarations(expr->scope()->declarations());
    1923       41025 :   Register class_constructor = register_allocator()->NewRegister();
    1924             : 
    1925             :   {
    1926             :     RegisterAllocationScope register_scope(this);
    1927       41024 :     RegisterList args = register_allocator()->NewGrowableRegisterList();
    1928             : 
    1929       41024 :     Register class_boilerplate = register_allocator()->GrowRegisterList(&args);
    1930             :     Register class_constructor_in_args =
    1931       41026 :         register_allocator()->GrowRegisterList(&args);
    1932       41025 :     Register super_class = register_allocator()->GrowRegisterList(&args);
    1933             :     DCHECK_EQ(ClassBoilerplate::kFirstDynamicArgumentIndex,
    1934             :               args.register_count());
    1935             : 
    1936       41025 :     VisitForAccumulatorValueOrTheHole(expr->extends());
    1937       41014 :     builder()->StoreAccumulatorInRegister(super_class);
    1938             : 
    1939       41019 :     VisitFunctionLiteral(expr->constructor());
    1940             :     builder()
    1941       41025 :         ->StoreAccumulatorInRegister(class_constructor)
    1942       41025 :         .MoveRegister(class_constructor, class_constructor_in_args)
    1943       41020 :         .LoadConstantPoolEntry(class_boilerplate_entry)
    1944       41023 :         .StoreAccumulatorInRegister(class_boilerplate);
    1945             : 
    1946             :     // Create computed names and method values nodes to store into the literal.
    1947      695104 :     for (int i = 0; i < expr->properties()->length(); i++) {
    1948      627003 :       ClassLiteral::Property* property = expr->properties()->at(i);
    1949      612125 :       if (property->is_computed_name()) {
    1950        6023 :         Register key = register_allocator()->GrowRegisterList(&args);
    1951             : 
    1952             :         builder()->SetExpressionAsStatementPosition(property->key());
    1953        6021 :         BuildLoadPropertyKey(property, key);
    1954        6020 :         if (property->is_static()) {
    1955             :           // The static prototype property is read only. We handle the non
    1956             :           // computed property name case in the parser. Since this is the only
    1957             :           // case where we need to check for an own read only property we
    1958             :           // special case this so we do not need to do this for every property.
    1959             : 
    1960             :           FeedbackSlot slot = GetDummyCompareICSlot();
    1961             :           BytecodeLabel done;
    1962             :           builder()
    1963        1671 :               ->LoadLiteral(ast_string_constants()->prototype_string())
    1964             :               .CompareOperation(Token::Value::EQ_STRICT, key,
    1965        1671 :                                 feedback_index(slot))
    1966        1671 :               .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &done)
    1967        1671 :               .CallRuntime(Runtime::kThrowStaticPrototypeError)
    1968        1671 :               .Bind(&done);
    1969             :         }
    1970             : 
    1971        6019 :         if (property->kind() == ClassLiteral::Property::FIELD) {
    1972             :           DCHECK(!property->is_private());
    1973             :           // Initialize field's name variable with the computed name.
    1974             :           DCHECK_NOT_NULL(property->computed_name_var());
    1975         403 :           builder()->LoadAccumulatorWithRegister(key);
    1976             :           BuildVariableAssignment(property->computed_name_var(), Token::INIT,
    1977         403 :                                   HoleCheckMode::kElided);
    1978             :         }
    1979             :       }
    1980             : 
    1981      306525 :       if (property->kind() == ClassLiteral::Property::FIELD) {
    1982         955 :         if (property->is_private()) {
    1983             :           RegisterAllocationScope private_name_register_scope(this);
    1984         552 :           Register private_name = register_allocator()->NewRegister();
    1985             :           VisitForRegisterValue(property->key(), private_name);
    1986             :           builder()
    1987        1104 :               ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
    1988         552 :               .StoreAccumulatorInRegister(private_name)
    1989         552 :               .CallRuntime(Runtime::kCreatePrivateNameSymbol, private_name);
    1990             :           DCHECK_NOT_NULL(property->private_name_var());
    1991             :           BuildVariableAssignment(property->private_name_var(), Token::INIT,
    1992         552 :                                   HoleCheckMode::kElided);
    1993             :         }
    1994             :         // We don't compute field's value here, but instead do it in the
    1995             :         // initializer function.
    1996         955 :         continue;
    1997             :       }
    1998             : 
    1999      305570 :       Register value = register_allocator()->GrowRegisterList(&args);
    2000             :       VisitForRegisterValue(property->value(), value);
    2001             :     }
    2002             : 
    2003       41023 :     builder()->CallRuntime(Runtime::kDefineClass, args);
    2004             :   }
    2005       41025 :   Register prototype = register_allocator()->NewRegister();
    2006       41026 :   builder()->StoreAccumulatorInRegister(prototype);
    2007             : 
    2008             :   // Assign to class variable.
    2009       41026 :   if (expr->class_variable() != nullptr) {
    2010             :     DCHECK(expr->class_variable()->IsStackLocal() ||
    2011             :            expr->class_variable()->IsContextSlot());
    2012       37097 :     builder()->LoadAccumulatorWithRegister(class_constructor);
    2013             :     BuildVariableAssignment(expr->class_variable(), Token::INIT,
    2014       37086 :                             HoleCheckMode::kElided);
    2015             :   }
    2016             : 
    2017       41010 :   if (expr->instance_members_initializer_function() != nullptr) {
    2018             :     Register initializer =
    2019         912 :         VisitForRegisterValue(expr->instance_members_initializer_function());
    2020             : 
    2021         912 :     if (FunctionLiteral::NeedsHomeObject(
    2022             :             expr->instance_members_initializer_function())) {
    2023          24 :       FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
    2024          24 :       builder()->LoadAccumulatorWithRegister(prototype).StoreHomeObjectProperty(
    2025          24 :           initializer, feedback_index(slot), language_mode());
    2026             :     }
    2027             : 
    2028         912 :     FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
    2029             :     builder()
    2030         912 :         ->LoadAccumulatorWithRegister(initializer)
    2031         912 :         .StoreClassFieldsInitializer(class_constructor, feedback_index(slot))
    2032         912 :         .LoadAccumulatorWithRegister(class_constructor);
    2033             :   }
    2034             : 
    2035       41010 :   if (expr->static_fields_initializer() != nullptr) {
    2036             :     // TODO(gsathya): This can be optimized away to be a part of the
    2037             :     // class boilerplate in the future. The name argument can be
    2038             :     // passed to the DefineClass runtime function and have it set
    2039             :     // there.
    2040         515 :     if (name.is_valid()) {
    2041           6 :       Register key = register_allocator()->NewRegister();
    2042             :       builder()
    2043           6 :           ->LoadLiteral(ast_string_constants()->name_string())
    2044           6 :           .StoreAccumulatorInRegister(key);
    2045             : 
    2046             :       DataPropertyInLiteralFlags data_property_flags =
    2047             :           DataPropertyInLiteralFlag::kNoFlags;
    2048             :       FeedbackSlot slot =
    2049           6 :           feedback_spec()->AddStoreDataPropertyInLiteralICSlot();
    2050           6 :       builder()->LoadAccumulatorWithRegister(name).StoreDataPropertyInLiteral(
    2051           6 :           class_constructor, key, data_property_flags, feedback_index(slot));
    2052             :     }
    2053             : 
    2054         515 :     RegisterList args = register_allocator()->NewRegisterList(1);
    2055             :     Register initializer =
    2056         515 :         VisitForRegisterValue(expr->static_fields_initializer());
    2057             : 
    2058         515 :     if (FunctionLiteral::NeedsHomeObject(expr->static_fields_initializer())) {
    2059          23 :       FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
    2060             :       builder()
    2061          23 :           ->LoadAccumulatorWithRegister(class_constructor)
    2062             :           .StoreHomeObjectProperty(initializer, feedback_index(slot),
    2063          23 :                                    language_mode());
    2064             :     }
    2065             : 
    2066             :     builder()
    2067         515 :         ->MoveRegister(class_constructor, args[0])
    2068             :         .CallProperty(initializer, args,
    2069        1030 :                       feedback_index(feedback_spec()->AddCallICSlot()));
    2070             :   }
    2071       41010 :   builder()->LoadAccumulatorWithRegister(class_constructor);
    2072       41014 : }
    2073             : 
    2074       41005 : void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
    2075       41005 :   VisitClassLiteral(expr, Register::invalid_value());
    2076       41013 : }
    2077             : 
    2078      115556 : void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr, Register name) {
    2079             :   CurrentScope current_scope(this, expr->scope());
    2080             :   DCHECK_NOT_NULL(expr->scope());
    2081       41020 :   if (expr->scope()->NeedsContext()) {
    2082       33523 :     BuildNewLocalBlockContext(expr->scope());
    2083       33516 :     ContextScope scope(this, expr->scope());
    2084       33528 :     BuildClassLiteral(expr, name);
    2085             :   } else {
    2086        7497 :     BuildClassLiteral(expr, name);
    2087             :   }
    2088       41019 : }
    2089             : 
    2090        1427 : void BytecodeGenerator::VisitInitializeClassMembersStatement(
    2091        3573 :     InitializeClassMembersStatement* stmt) {
    2092        1427 :   RegisterList args = register_allocator()->NewRegisterList(3);
    2093        2854 :   Register constructor = args[0], key = args[1], value = args[2];
    2094        1427 :   builder()->MoveRegister(builder()->Receiver(), constructor);
    2095             : 
    2096        7146 :   for (int i = 0; i < stmt->fields()->length(); i++) {
    2097       10879 :     ClassLiteral::Property* property = stmt->fields()->at(i);
    2098             : 
    2099        6438 :     if (property->is_computed_name()) {
    2100             :       DCHECK_EQ(property->kind(), ClassLiteral::Property::FIELD);
    2101             :       DCHECK(!property->is_private());
    2102             :       Variable* var = property->computed_name_var();
    2103             :       DCHECK_NOT_NULL(var);
    2104             :       // The computed name is already evaluated and stored in a
    2105             :       // variable at class definition time.
    2106         403 :       BuildVariableLoad(var, HoleCheckMode::kElided);
    2107         403 :       builder()->StoreAccumulatorInRegister(key);
    2108        3486 :     } else if (property->kind() == ClassLiteral::Property::FIELD &&
    2109             :                property->is_private()) {
    2110             :       Variable* private_name_var = property->private_name_var();
    2111             :       DCHECK_NOT_NULL(private_name_var);
    2112         552 :       BuildVariableLoad(private_name_var, HoleCheckMode::kElided);
    2113         552 :       builder()->StoreAccumulatorInRegister(key);
    2114             :     } else {
    2115        1191 :       BuildLoadPropertyKey(property, key);
    2116             :     }
    2117             : 
    2118             :     builder()->SetExpressionAsStatementPosition(property->value());
    2119             :     VisitForRegisterValue(property->value(), value);
    2120        2146 :     VisitSetHomeObject(value, constructor, property);
    2121             : 
    2122             :     Runtime::FunctionId function_id =
    2123        2146 :         property->kind() == ClassLiteral::Property::FIELD &&
    2124             :                 !property->is_private()
    2125             :             ? Runtime::kCreateDataProperty
    2126        2146 :             : Runtime::kAddPrivateField;
    2127        2146 :     builder()->CallRuntime(function_id, args);
    2128             :   }
    2129        1427 : }
    2130             : 
    2131         837 : void BytecodeGenerator::BuildInstanceMemberInitialization(Register constructor,
    2132             :                                                           Register instance) {
    2133         837 :   RegisterList args = register_allocator()->NewRegisterList(1);
    2134         837 :   Register initializer = register_allocator()->NewRegister();
    2135             : 
    2136         837 :   FeedbackSlot slot = feedback_spec()->AddLoadICSlot();
    2137             :   BytecodeLabel done;
    2138             : 
    2139             :   builder()
    2140         837 :       ->LoadClassFieldsInitializer(constructor, feedback_index(slot))
    2141             :       // TODO(gsathya): This jump can be elided for the base
    2142             :       // constructor and derived constructor. This is only required
    2143             :       // when called from an arrow function.
    2144         837 :       .JumpIfUndefined(&done)
    2145         837 :       .StoreAccumulatorInRegister(initializer)
    2146        1674 :       .MoveRegister(instance, args[0])
    2147             :       .CallProperty(initializer, args,
    2148        1674 :                     feedback_index(feedback_spec()->AddCallICSlot()))
    2149         837 :       .Bind(&done);
    2150         837 : }
    2151             : 
    2152        1761 : void BytecodeGenerator::VisitNativeFunctionLiteral(
    2153             :     NativeFunctionLiteral* expr) {
    2154        1761 :   size_t entry = builder()->AllocateDeferredConstantPoolEntry();
    2155        1761 :   FeedbackSlot slot = feedback_spec()->AddCreateClosureSlot();
    2156        1761 :   builder()->CreateClosure(entry, feedback_index(slot), NOT_TENURED);
    2157        3522 :   native_function_literals_.push_back(std::make_pair(expr, entry));
    2158        1761 : }
    2159             : 
    2160           0 : void BytecodeGenerator::VisitDoExpression(DoExpression* expr) {
    2161           0 :   VisitBlock(expr->block());
    2162           0 :   VisitVariableProxy(expr->result());
    2163           0 : }
    2164             : 
    2165      181256 : void BytecodeGenerator::VisitConditional(Conditional* expr) {
    2166             :   ConditionalControlFlowBuilder conditional_builder(
    2167       30359 :       builder(), block_coverage_builder_, expr);
    2168             : 
    2169       30358 :   if (expr->condition()->ToBooleanIsTrue()) {
    2170             :     // Generate then block unconditionally as always true.
    2171         230 :     conditional_builder.Then();
    2172         230 :     VisitForAccumulatorValue(expr->then_expression());
    2173       30129 :   } else if (expr->condition()->ToBooleanIsFalse()) {
    2174             :     // Generate else block unconditionally if it exists.
    2175         107 :     conditional_builder.Else();
    2176         107 :     VisitForAccumulatorValue(expr->else_expression());
    2177             :   } else {
    2178             :     VisitForTest(expr->condition(), conditional_builder.then_labels(),
    2179       30023 :                  conditional_builder.else_labels(), TestFallthrough::kThen);
    2180             : 
    2181       30024 :     conditional_builder.Then();
    2182       30023 :     VisitForAccumulatorValue(expr->then_expression());
    2183       30028 :     conditional_builder.JumpToEnd();
    2184             : 
    2185       30027 :     conditional_builder.Else();
    2186       30027 :     VisitForAccumulatorValue(expr->else_expression());
    2187       30365 :   }
    2188       30365 : }
    2189             : 
    2190    29971600 : void BytecodeGenerator::VisitLiteral(Literal* expr) {
    2191    20636867 :   if (execution_result()->IsEffect()) return;
    2192     9193281 :   switch (expr->type()) {
    2193             :     case Literal::kSmi:
    2194     6780259 :       builder()->LoadLiteral(expr->AsSmiLiteral());
    2195     6780212 :       break;
    2196             :     case Literal::kHeapNumber:
    2197      273825 :       builder()->LoadLiteral(expr->AsNumber());
    2198      273824 :       break;
    2199             :     case Literal::kUndefined:
    2200      111156 :       builder()->LoadUndefined();
    2201      111153 :       break;
    2202             :     case Literal::kBoolean:
    2203      313600 :       builder()->LoadBoolean(expr->ToBooleanIsTrue());
    2204             :       execution_result()->SetResultIsBoolean();
    2205             :       break;
    2206             :     case Literal::kNull:
    2207       21620 :       builder()->LoadNull();
    2208       21615 :       break;
    2209             :     case Literal::kTheHole:
    2210           0 :       builder()->LoadTheHole();
    2211           0 :       break;
    2212             :     case Literal::kString:
    2213     1682018 :       builder()->LoadLiteral(expr->AsRawString());
    2214             :       execution_result()->SetResultIsString();
    2215             :       break;
    2216             :     case Literal::kSymbol:
    2217        1981 :       builder()->LoadLiteral(expr->AsSymbol());
    2218        1981 :       break;
    2219             :     case Literal::kBigInt:
    2220        8986 :       builder()->LoadLiteral(expr->AsBigInt());
    2221        8986 :       break;
    2222             :   }
    2223             : }
    2224             : 
    2225       89997 : void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
    2226             :   // Materialize a regular expression literal.
    2227             :   builder()->CreateRegExpLiteral(
    2228             :       expr->raw_pattern(), feedback_index(feedback_spec()->AddLiteralSlot()),
    2229       89997 :       expr->flags());
    2230       45001 : }
    2231             : 
    2232      201532 : void BytecodeGenerator::BuildCreateObjectLiteral(Register literal,
    2233             :                                                  uint8_t flags, size_t entry) {
    2234      201532 :   if (ShouldOptimizeAsOneShot()) {
    2235      114124 :     RegisterList args = register_allocator()->NewRegisterList(2);
    2236             :     builder()
    2237      114142 :         ->LoadConstantPoolEntry(entry)
    2238      114158 :         .StoreAccumulatorInRegister(args[0])
    2239      114163 :         .LoadLiteral(Smi::FromInt(flags))
    2240      114156 :         .StoreAccumulatorInRegister(args[1])
    2241      114153 :         .CallRuntime(Runtime::kCreateObjectLiteralWithoutAllocationSite, args)
    2242      114141 :         .StoreAccumulatorInRegister(literal);
    2243             : 
    2244             :   } else {
    2245             :     // TODO(cbruni): Directly generate runtime call for literals we cannot
    2246             :     // optimize once the CreateShallowObjectLiteral stub is in sync with the TF
    2247             :     // optimizations.
    2248       87526 :     int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
    2249             :     builder()
    2250       87523 :         ->CreateObjectLiteral(entry, literal_index, flags)
    2251       87527 :         .StoreAccumulatorInRegister(literal);
    2252             :   }
    2253      201684 : }
    2254             : 
    2255      432150 : void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
    2256      431456 :   expr->InitDepthAndFlags();
    2257             : 
    2258             :   // Fast path for the empty object literal which doesn't need an
    2259             :   // AllocationSite.
    2260      230070 :   if (expr->IsEmptyObjectLiteral()) {
    2261             :     DCHECK(expr->IsFastCloningSupported());
    2262       28160 :     builder()->CreateEmptyObjectLiteral();
    2263      258193 :     return;
    2264             :   }
    2265             : 
    2266             :   // Deep-copy the literal boilerplate.
    2267             :   uint8_t flags = CreateObjectLiteralFlags::Encode(
    2268      201885 :       expr->ComputeFlags(), expr->IsFastCloningSupported());
    2269             : 
    2270      201846 :   Register literal = register_allocator()->NewRegister();
    2271             : 
    2272             :   // Create literal object.
    2273             :   int property_index = 0;
    2274             :   bool clone_object_spread =
    2275      201776 :       expr->properties()->first()->kind() == ObjectLiteral::Property::SPREAD;
    2276      201776 :   if (clone_object_spread) {
    2277             :     // Avoid the slow path for spreads in the following common cases:
    2278             :     //   1) `let obj = { ...source }`
    2279             :     //   2) `let obj = { ...source, override: 1 }`
    2280             :     //   3) `let obj = { ...source, ...overrides }`
    2281             :     RegisterAllocationScope register_scope(this);
    2282         262 :     Expression* property = expr->properties()->first()->value();
    2283         262 :     Register from_value = VisitForRegisterValue(property);
    2284             : 
    2285             :     BytecodeLabels clone_object(zone());
    2286         262 :     builder()->JumpIfUndefined(clone_object.New());
    2287         262 :     builder()->JumpIfNull(clone_object.New());
    2288         262 :     builder()->ToObject(from_value);
    2289             : 
    2290         261 :     clone_object.Bind(builder());
    2291         262 :     int clone_index = feedback_index(feedback_spec()->AddCloneObjectSlot());
    2292         262 :     builder()->CloneObject(from_value, flags, clone_index);
    2293         262 :     builder()->StoreAccumulatorInRegister(literal);
    2294         262 :     property_index++;
    2295             :   } else {
    2296             :     size_t entry;
    2297             :     // If constant properties is an empty fixed array, use a cached empty fixed
    2298             :     // array to ensure it's only added to the constant pool once.
    2299      201514 :     if (expr->properties_count() == 0) {
    2300        2247 :       entry = builder()->EmptyObjectBoilerplateDescriptionConstantPoolEntry();
    2301             :     } else {
    2302      199267 :       entry = builder()->AllocateDeferredConstantPoolEntry();
    2303      398668 :       object_literals_.push_back(std::make_pair(expr, entry));
    2304             :     }
    2305      201625 :     BuildCreateObjectLiteral(literal, flags, entry);
    2306             :   }
    2307             : 
    2308             :   // Store computed values into the literal.
    2309             :   AccessorTable accessor_table(zone());
    2310     2017143 :   for (; property_index < expr->properties()->length(); property_index++) {
    2311     2274473 :     ObjectLiteral::Property* property = expr->properties()->at(property_index);
    2312     2758175 :     if (property->is_computed_name()) break;
    2313     3778855 :     if (!clone_object_spread && property->IsCompileTimeValue()) continue;
    2314             : 
    2315             :     RegisterAllocationScope inner_register_scope(this);
    2316      500420 :     Literal* key = property->key()->AsLiteral();
    2317      255382 :     switch (property->kind()) {
    2318             :       case ObjectLiteral::Property::SPREAD:
    2319           0 :         UNREACHABLE();
    2320             :       case ObjectLiteral::Property::CONSTANT:
    2321             :       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
    2322             :         DCHECK(clone_object_spread || !property->value()->IsCompileTimeValue());
    2323             :         V8_FALLTHROUGH;
    2324             :       case ObjectLiteral::Property::COMPUTED: {
    2325             :         // It is safe to use [[Put]] here because the boilerplate already
    2326             :         // contains computed properties with an uninitialized value.
    2327      245752 :         if (key->IsStringLiteral()) {
    2328             :           DCHECK(key->IsPropertyName());
    2329      245194 :           if (property->emit_store()) {
    2330             :             builder()->SetExpressionPosition(property->value());
    2331      245048 :             VisitForAccumulatorValue(property->value());
    2332      245060 :             FeedbackSlot slot = feedback_spec()->AddStoreOwnICSlot();
    2333      245060 :             if (FunctionLiteral::NeedsHomeObject(property->value())) {
    2334             :               RegisterAllocationScope register_scope(this);
    2335         546 :               Register value = register_allocator()->NewRegister();
    2336         546 :               builder()->StoreAccumulatorInRegister(value);
    2337             :               builder()->StoreNamedOwnProperty(
    2338         546 :                   literal, key->AsRawPropertyName(), feedback_index(slot));
    2339         546 :               VisitSetHomeObject(value, literal, property);
    2340             :             } else {
    2341             :               builder()->StoreNamedOwnProperty(
    2342      244493 :                   literal, key->AsRawPropertyName(), feedback_index(slot));
    2343             :             }
    2344             :           } else {
    2345             :             builder()->SetExpressionPosition(property->value());
    2346         151 :             VisitForEffect(property->value());
    2347             :           }
    2348             :         } else {
    2349         559 :           RegisterList args = register_allocator()->NewRegisterList(4);
    2350             : 
    2351         559 :           builder()->MoveRegister(literal, args[0]);
    2352             :           builder()->SetExpressionPosition(property->key());
    2353             :           VisitForRegisterValue(property->key(), args[1]);
    2354             :           builder()->SetExpressionPosition(property->value());
    2355             :           VisitForRegisterValue(property->value(), args[2]);
    2356         559 :           if (property->emit_store()) {
    2357             :             builder()
    2358         527 :                 ->LoadLiteral(Smi::FromEnum(LanguageMode::kSloppy))
    2359         527 :                 .StoreAccumulatorInRegister(args[3])
    2360         527 :                 .CallRuntime(Runtime::kSetKeyedProperty, args);
    2361         527 :             Register value = args[2];
    2362         527 :             VisitSetHomeObject(value, literal, property);
    2363             :           }
    2364             :         }
    2365             :         break;
    2366             :       }
    2367             :       case ObjectLiteral::Property::PROTOTYPE: {
    2368             :         // __proto__:null is handled by CreateObjectLiteral.
    2369        4085 :         if (property->IsNullPrototype()) break;
    2370             :         DCHECK(property->emit_store());
    2371             :         DCHECK(!property->NeedsSetFunctionName());
    2372        1254 :         RegisterList args = register_allocator()->NewRegisterList(2);
    2373        1254 :         builder()->MoveRegister(literal, args[0]);
    2374             :         builder()->SetExpressionPosition(property->value());
    2375             :         VisitForRegisterValue(property->value(), args[1]);
    2376        1253 :         builder()->CallRuntime(Runtime::kInternalSetPrototype, args);
    2377        1254 :         break;
    2378             :       }
    2379             :       case ObjectLiteral::Property::GETTER:
    2380        3557 :         if (property->emit_store()) {
    2381        3456 :           accessor_table.lookup(key)->second->getter = property;
    2382             :         }
    2383             :         break;
    2384             :       case ObjectLiteral::Property::SETTER:
    2385        1981 :         if (property->emit_store()) {
    2386        1885 :           accessor_table.lookup(key)->second->setter = property;
    2387             :         }
    2388             :         break;
    2389             :     }
    2390      255401 :   }
    2391             : 
    2392             :   // Define accessors, using only a single call to the runtime for each pair of
    2393             :   // corresponding getters and setters.
    2394      408168 :   for (AccessorTable::Iterator it = accessor_table.begin();
    2395             :        it != accessor_table.end(); ++it) {
    2396             :     RegisterAllocationScope inner_register_scope(this);
    2397        4629 :     RegisterList args = register_allocator()->NewRegisterList(5);
    2398        4631 :     builder()->MoveRegister(literal, args[0]);
    2399        4631 :     VisitForRegisterValue(it->first, args[1]);
    2400        4631 :     VisitObjectLiteralAccessor(literal, it->second->getter, args[2]);
    2401        4629 :     VisitObjectLiteralAccessor(literal, it->second->setter, args[3]);
    2402             :     builder()
    2403        4629 :         ->LoadLiteral(Smi::FromInt(NONE))
    2404        4630 :         .StoreAccumulatorInRegister(args[4])
    2405        4630 :         .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, args);
    2406        4631 :   }
    2407             : 
    2408             :   // Object literals have two parts. The "static" part on the left contains no
    2409             :   // computed property names, and so we can compute its map ahead of time; see
    2410             :   // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
    2411             :   // with the first computed property name and continues with all properties to
    2412             :   // its right. All the code from above initializes the static component of the
    2413             :   // object literal, and arranges for the map of the result to reflect the
    2414             :   // static order in which the keys appear. For the dynamic properties, we
    2415             :   // compile them into a series of "SetOwnProperty" runtime calls. This will
    2416             :   // preserve insertion order.
    2417        2868 :   for (; property_index < expr->properties()->length(); property_index++) {
    2418        3203 :     ObjectLiteral::Property* property = expr->properties()->at(property_index);
    2419             :     RegisterAllocationScope inner_register_scope(this);
    2420             : 
    2421        2867 :     if (property->IsPrototype()) {
    2422             :       // __proto__:null is handled by CreateObjectLiteral.
    2423          36 :       if (property->IsNullPrototype()) continue;
    2424             :       DCHECK(property->emit_store());
    2425             :       DCHECK(!property->NeedsSetFunctionName());
    2426          31 :       RegisterList args = register_allocator()->NewRegisterList(2);
    2427          31 :       builder()->MoveRegister(literal, args[0]);
    2428        5730 :       builder()->SetExpressionPosition(property->value());
    2429             :       VisitForRegisterValue(property->value(), args[1]);
    2430          31 :       builder()->CallRuntime(Runtime::kInternalSetPrototype, args);
    2431          31 :       continue;
    2432             :     }
    2433             : 
    2434        2831 :     switch (property->kind()) {
    2435             :       case ObjectLiteral::Property::CONSTANT:
    2436             :       case ObjectLiteral::Property::COMPUTED:
    2437             :       case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
    2438        2398 :         Register key = register_allocator()->NewRegister();
    2439        2400 :         BuildLoadPropertyKey(property, key);
    2440             :         builder()->SetExpressionPosition(property->value());
    2441             :         Register value;
    2442             : 
    2443             :         // Static class fields require the name property to be set on
    2444             :         // the class, meaning we can't wait until the
    2445             :         // StoreDataPropertyInLiteral call later to set the name.
    2446        2413 :         if (property->value()->IsClassLiteral() &&
    2447          24 :             property->value()->AsClassLiteral()->static_fields_initializer() !=
    2448             :                 nullptr) {
    2449           6 :           value = register_allocator()->NewRegister();
    2450          12 :           VisitClassLiteral(property->value()->AsClassLiteral(), key);
    2451           6 :           builder()->StoreAccumulatorInRegister(value);
    2452             :         } else {
    2453        2395 :           value = VisitForRegisterValue(property->value());
    2454             :         }
    2455        2400 :         VisitSetHomeObject(value, literal, property);
    2456             : 
    2457             :         DataPropertyInLiteralFlags data_property_flags =
    2458             :             DataPropertyInLiteralFlag::kNoFlags;
    2459        2398 :         if (property->NeedsSetFunctionName()) {
    2460             :           data_property_flags |= DataPropertyInLiteralFlag::kSetFunctionName;
    2461             :         }
    2462             : 
    2463             :         FeedbackSlot slot =
    2464        2400 :             feedback_spec()->AddStoreDataPropertyInLiteralICSlot();
    2465             :         builder()
    2466        2400 :             ->LoadAccumulatorWithRegister(value)
    2467             :             .StoreDataPropertyInLiteral(literal, key, data_property_flags,
    2468        2400 :                                         feedback_index(slot));
    2469             :         break;
    2470             :       }
    2471             :       case ObjectLiteral::Property::GETTER:
    2472             :       case ObjectLiteral::Property::SETTER: {
    2473         336 :         RegisterList args = register_allocator()->NewRegisterList(4);
    2474         336 :         builder()->MoveRegister(literal, args[0]);
    2475         336 :         BuildLoadPropertyKey(property, args[1]);
    2476             :         builder()->SetExpressionPosition(property->value());
    2477             :         VisitForRegisterValue(property->value(), args[2]);
    2478         336 :         VisitSetHomeObject(args[2], literal, property);
    2479             :         builder()
    2480         336 :             ->LoadLiteral(Smi::FromInt(NONE))
    2481         336 :             .StoreAccumulatorInRegister(args[3]);
    2482             :         Runtime::FunctionId function_id =
    2483             :             property->kind() == ObjectLiteral::Property::GETTER
    2484             :                 ? Runtime::kDefineGetterPropertyUnchecked
    2485         336 :                 : Runtime::kDefineSetterPropertyUnchecked;
    2486         336 :         builder()->CallRuntime(function_id, args);
    2487             :         break;
    2488             :       }
    2489             :       case ObjectLiteral::Property::SPREAD: {
    2490          96 :         RegisterList args = register_allocator()->NewRegisterList(2);
    2491          96 :         builder()->MoveRegister(literal, args[0]);
    2492             :         builder()->SetExpressionPosition(property->value());
    2493             :         VisitForRegisterValue(property->value(), args[1]);
    2494          96 :         builder()->CallRuntime(Runtime::kCopyDataProperties, args);
    2495             :         break;
    2496             :       }
    2497             :       case ObjectLiteral::Property::PROTOTYPE:
    2498           0 :         UNREACHABLE();  // Handled specially above.
    2499             :         break;
    2500             :     }
    2501        2833 :   }
    2502             : 
    2503      201771 :   builder()->LoadAccumulatorWithRegister(literal);
    2504             : }
    2505             : 
    2506             : // Fill an array with values from an iterator, starting at a given index. It is
    2507             : // guaranteed that the loop will only terminate if the iterator is exhausted, or
    2508             : // if one of iterator.next(), value.done, or value.value fail.
    2509             : //
    2510             : // In pseudocode:
    2511             : //
    2512             : // loop {
    2513             : //   value = iterator.next()
    2514             : //   if (value.done) break;
    2515             : //   value = value.value
    2516             : //   array[index++] = value
    2517             : // }
    2518        2243 : void BytecodeGenerator::BuildFillArrayWithIterator(
    2519             :     IteratorRecord iterator, Register array, Register index, Register value,
    2520             :     FeedbackSlot next_value_slot, FeedbackSlot next_done_slot,
    2521        4490 :     FeedbackSlot index_slot, FeedbackSlot element_slot) {
    2522             :   DCHECK(array.is_valid());
    2523             :   DCHECK(index.is_valid());
    2524             :   DCHECK(value.is_valid());
    2525             : 
    2526        2243 :   LoopBuilder loop_builder(builder(), nullptr, nullptr);
    2527        2243 :   loop_builder.LoopHeader();
    2528             : 
    2529             :   // Call the iterator's .next() method. Break from the loop if the `done`
    2530             :   // property is truthy, otherwise load the value from the iterator result and
    2531             :   // append the argument.
    2532        2244 :   BuildIteratorNext(iterator, value);
    2533             :   builder()->LoadNamedProperty(
    2534             :       value, ast_string_constants()->done_string(),
    2535        4490 :       feedback_index(feedback_spec()->AddLoadICSlot()));
    2536             :   loop_builder.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
    2537             : 
    2538        2245 :   loop_builder.LoopBody();
    2539             :   builder()
    2540             :       // value = value.value
    2541             :       ->LoadNamedProperty(value, ast_string_constants()->value_string(),
    2542        2245 :                           feedback_index(next_value_slot))
    2543             :       // array[index] = value
    2544        2243 :       .StoreInArrayLiteral(array, index, feedback_index(element_slot))
    2545             :       // index++
    2546        2243 :       .LoadAccumulatorWithRegister(index)
    2547        2245 :       .UnaryOperation(Token::INC, feedback_index(index_slot))
    2548        2244 :       .StoreAccumulatorInRegister(index);
    2549        2244 :   loop_builder.BindContinueTarget();
    2550        2243 :   loop_builder.JumpToHeader(loop_depth_);
    2551        2243 : }
    2552             : 
    2553      379582 : void BytecodeGenerator::BuildCreateArrayLiteral(
    2554      380263 :     const ZonePtrList<Expression>* elements, ArrayLiteral* expr) {
    2555             :   RegisterAllocationScope register_scope(this);
    2556      379582 :   Register index = register_allocator()->NewRegister();
    2557      379605 :   Register array = register_allocator()->NewRegister();
    2558             :   SharedFeedbackSlot element_slot(feedback_spec(),
    2559      379599 :                                   FeedbackSlotKind::kStoreInArrayLiteral);
    2560             :   ZonePtrList<Expression>::iterator current = elements->begin();
    2561             :   ZonePtrList<Expression>::iterator end = elements->end();
    2562             :   bool is_empty = elements->is_empty();
    2563             : 
    2564      557964 :   if (!is_empty && (*current)->IsSpread()) {
    2565             :     // If we have a leading spread, use CreateArrayFromIterable to create
    2566             :     // an array from it and then add the remaining components to that array.
    2567        2112 :     VisitForAccumulatorValue(*current);
    2568        2114 :     builder()->CreateArrayFromIterable().StoreAccumulatorInRegister(array);
    2569             : 
    2570        2113 :     if (++current != end) {
    2571             :       // If there are remaning elements, prepare the index register that is
    2572             :       // used for adding those elements. The next index is the length of the
    2573             :       // newly created array.
    2574         608 :       auto length = ast_string_constants()->length_string();
    2575         608 :       int length_load_slot = feedback_index(feedback_spec()->AddLoadICSlot());
    2576             :       builder()
    2577         608 :           ->LoadNamedProperty(array, length, length_load_slot)
    2578         608 :           .StoreAccumulatorInRegister(index);
    2579             :     }
    2580      754934 :   } else if (expr != nullptr) {
    2581             :     // There are some elements before the first (if any) spread, and we can
    2582             :     // use a boilerplate when creating the initial array from those elements.
    2583             : 
    2584             :     // First, allocate a constant pool entry for the boilerplate that will
    2585             :     // be created during finalization, and will contain all the constant
    2586             :     // elements before the first spread. This also handle the empty array case
    2587             :     // and one-shot optimization.
    2588             :     uint8_t flags = CreateArrayLiteralFlags::Encode(
    2589      377468 :         expr->IsFastCloningSupported(), expr->ComputeFlags());
    2590      377456 :     bool optimize_as_one_shot = ShouldOptimizeAsOneShot();
    2591             :     size_t entry;
    2592      377466 :     if (is_empty && optimize_as_one_shot) {
    2593       47360 :       entry = builder()->EmptyArrayBoilerplateDescriptionConstantPoolEntry();
    2594      330106 :     } else if (!is_empty) {
    2595      176215 :       entry = builder()->AllocateDeferredConstantPoolEntry();
    2596      352440 :       array_literals_.push_back(std::make_pair(expr, entry));
    2597             :     }
    2598             : 
    2599      377460 :     if (optimize_as_one_shot) {
    2600      191605 :       RegisterList args = register_allocator()->NewRegisterList(2);
    2601             :       builder()
    2602      191615 :           ->LoadConstantPoolEntry(entry)
    2603      191632 :           .StoreAccumulatorInRegister(args[0])
    2604      191634 :           .LoadLiteral(Smi::FromInt(flags))
    2605      191619 :           .StoreAccumulatorInRegister(args[1])
    2606      191626 :           .CallRuntime(Runtime::kCreateArrayLiteralWithoutAllocationSite, args);
    2607      185855 :     } else if (is_empty) {
    2608             :       // Empty array literal fast-path.
    2609      153894 :       int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
    2610             :       DCHECK(expr->IsFastCloningSupported());
    2611      153895 :       builder()->CreateEmptyArrayLiteral(literal_index);
    2612             :     } else {
    2613             :       // Create array literal from boilerplate.
    2614       31961 :       int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
    2615       31955 :       builder()->CreateArrayLiteral(entry, literal_index, flags);
    2616             :     }
    2617      377473 :     builder()->StoreAccumulatorInRegister(array);
    2618             : 
    2619             :     // Insert the missing non-constant elements, up until the first spread
    2620             :     // index, into the initial array (the remaining elements will be inserted
    2621             :     // below).
    2622             :     DCHECK_EQ(current, elements->begin());
    2623             :     ZonePtrList<Expression>::iterator first_spread_or_end =
    2624         463 :         expr->first_spread_index() >= 0 ? current + expr->first_spread_index()
    2625      377909 :                                         : end;
    2626             :     int array_index = 0;
    2627     7613883 :     for (; current != first_spread_or_end; ++current, array_index++) {
    2628     7236419 :       Expression* subexpr = *current;
    2629             :       DCHECK(!subexpr->IsSpread());
    2630             :       // Skip the constants.
    2631     7236419 :       if (subexpr->IsCompileTimeValue()) continue;
    2632             : 
    2633             :       builder()
    2634      238595 :           ->LoadLiteral(Smi::FromInt(array_index))
    2635      238602 :           .StoreAccumulatorInRegister(index);
    2636      238628 :       VisitForAccumulatorValue(subexpr);
    2637             :       builder()->StoreInArrayLiteral(array, index,
    2638      238594 :                                      feedback_index(element_slot.Get()));
    2639             :     }
    2640             : 
    2641      377464 :     if (current != end) {
    2642             :       // If there are remaining elements, prepare the index register
    2643             :       // to store the next element, which comes from the first spread.
    2644         463 :       builder()->LoadLiteral(array_index).StoreAccumulatorInRegister(index);
    2645             :     }
    2646             :   } else {
    2647             :     // In other cases, we prepare an empty array to be filled in below.
    2648             :     DCHECK(!elements->is_empty());
    2649             :     int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
    2650             :     builder()
    2651          20 :         ->CreateEmptyArrayLiteral(literal_index)
    2652          20 :         .StoreAccumulatorInRegister(array);
    2653             :     // Prepare the index for the first element.
    2654          20 :     builder()->LoadLiteral(Smi::FromInt(0)).StoreAccumulatorInRegister(index);
    2655             :   }
    2656             : 
    2657             :   // Now build insertions for the remaining elements from current to end.
    2658      379562 :   SharedFeedbackSlot index_slot(feedback_spec(), FeedbackSlotKind::kBinaryOp);
    2659             :   SharedFeedbackSlot length_slot(
    2660             :       feedback_spec(), feedback_spec()->GetStoreICSlot(LanguageMode::kStrict));
    2661        3431 :   for (; current != end; ++current) {
    2662        3428 :     Expression* subexpr = *current;
    2663        3429 :     if (subexpr->IsSpread()) {
    2664             :       RegisterAllocationScope scope(this);
    2665             :       builder()->SetExpressionAsStatementPosition(
    2666        3320 :           subexpr->AsSpread()->expression());
    2667        1661 :       VisitForAccumulatorValue(subexpr->AsSpread()->expression());
    2668        1661 :       IteratorRecord iterator = BuildGetIteratorRecord(IteratorType::kNormal);
    2669             : 
    2670        1662 :       Register value = register_allocator()->NewRegister();
    2671        3324 :       FeedbackSlot next_value_load_slot = feedback_spec()->AddLoadICSlot();
    2672        3324 :       FeedbackSlot next_done_load_slot = feedback_spec()->AddLoadICSlot();
    2673        1662 :       FeedbackSlot real_index_slot = index_slot.Get();
    2674        1662 :       FeedbackSlot real_element_slot = element_slot.Get();
    2675             :       BuildFillArrayWithIterator(iterator, array, index, value,
    2676             :                                  next_value_load_slot, next_done_load_slot,
    2677        1662 :                                  real_index_slot, real_element_slot);
    2678        1769 :     } else if (!subexpr->IsTheHoleLiteral()) {
    2679             :       // literal[index++] = subexpr
    2680        1714 :       VisitForAccumulatorValue(subexpr);
    2681             :       builder()
    2682             :           ->StoreInArrayLiteral(array, index,
    2683        1713 :                                 feedback_index(element_slot.Get()))
    2684        1713 :           .LoadAccumulatorWithRegister(index);
    2685             :       // Only increase the index if we are not the last element.
    2686        1714 :       if (current + 1 != end) {
    2687             :         builder()
    2688        1096 :             ->UnaryOperation(Token::INC, feedback_index(index_slot.Get()))
    2689        1097 :             .StoreAccumulatorInRegister(index);
    2690             :       }
    2691             :     } else {
    2692             :       // literal.length = ++index
    2693             :       // length_slot is only used when there are holes.
    2694          56 :       auto length = ast_string_constants()->length_string();
    2695             :       builder()
    2696          56 :           ->LoadAccumulatorWithRegister(index)
    2697         112 :           .UnaryOperation(Token::INC, feedback_index(index_slot.Get()))
    2698          56 :           .StoreAccumulatorInRegister(index)
    2699             :           .StoreNamedProperty(array, length, feedback_index(length_slot.Get()),
    2700         112 :                               LanguageMode::kStrict);
    2701             :     }
    2702             :   }
    2703             : 
    2704      379565 :   builder()->LoadAccumulatorWithRegister(array);
    2705      379617 : }
    2706             : 
    2707      379551 : void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
    2708      379551 :   expr->InitDepthAndFlags();
    2709      379566 :   BuildCreateArrayLiteral(expr->values(), expr);
    2710      379590 : }
    2711             : 
    2712           0 : void BytecodeGenerator::VisitStoreInArrayLiteral(StoreInArrayLiteral* expr) {
    2713             :   builder()->SetExpressionAsStatementPosition(expr);
    2714             :   RegisterAllocationScope register_scope(this);
    2715           0 :   Register array = register_allocator()->NewRegister();
    2716           0 :   Register index = register_allocator()->NewRegister();
    2717             :   VisitForRegisterValue(expr->array(), array);
    2718             :   VisitForRegisterValue(expr->index(), index);
    2719           0 :   VisitForAccumulatorValue(expr->value());
    2720             :   builder()->StoreInArrayLiteral(
    2721             :       array, index,
    2722           0 :       feedback_index(feedback_spec()->AddStoreInArrayLiteralICSlot()));
    2723           0 : }
    2724             : 
    2725    27482127 : void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
    2726             :   builder()->SetExpressionPosition(proxy);
    2727     9160709 :   BuildVariableLoad(proxy->var(), proxy->hole_check_mode());
    2728     9161115 : }
    2729             : 
    2730    34764669 : void BytecodeGenerator::BuildVariableLoad(Variable* variable,
    2731             :                                           HoleCheckMode hole_check_mode,
    2732     8330484 :                                           TypeofMode typeof_mode) {
    2733    13443502 :   switch (variable->location()) {
    2734             :     case VariableLocation::LOCAL: {
    2735     2417320 :       Register source(builder()->Local(variable->index()));
    2736             :       // We need to load the variable into the accumulator, even when in a
    2737             :       // VisitForRegisterScope, in order to avoid register aliasing if
    2738             :       // subsequent expressions assign to the same variable.
    2739     2417362 :       builder()->LoadAccumulatorWithRegister(source);
    2740     2417498 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    2741        2538 :         BuildThrowIfHole(variable);
    2742             :       }
    2743             :       break;
    2744             :     }
    2745             :     case VariableLocation::PARAMETER: {
    2746             :       Register source;
    2747     3675027 :       if (variable->IsReceiver()) {
    2748     2386311 :         source = builder()->Receiver();
    2749             :       } else {
    2750     1288716 :         source = builder()->Parameter(variable->index());
    2751             :       }
    2752             :       // We need to load the variable into the accumulator, even when in a
    2753             :       // VisitForRegisterScope, in order to avoid register aliasing if
    2754             :       // subsequent expressions assign to the same variable.
    2755     3675027 :       builder()->LoadAccumulatorWithRegister(source);
    2756     3675035 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    2757     2170311 :         BuildThrowIfHole(variable);
    2758             :       }
    2759             :       break;
    2760             :     }
    2761             :     case VariableLocation::UNALLOCATED: {
    2762             :       // The global identifier "undefined" is immutable. Everything
    2763             :       // else could be reassigned. For performance, we do a pointer comparison
    2764             :       // rather than checking if the raw_name is really "undefined".
    2765     5943296 :       if (variable->raw_name() == ast_string_constants()->undefined_string()) {
    2766       81114 :         builder()->LoadUndefined();
    2767             :       } else {
    2768     5862182 :         FeedbackSlot slot = GetCachedLoadGlobalICSlot(typeof_mode, variable);
    2769             :         builder()->LoadGlobal(variable->raw_name(), feedback_index(slot),
    2770     5862622 :                               typeof_mode);
    2771             :       }
    2772             :       break;
    2773             :     }
    2774             :     case VariableLocation::CONTEXT: {
    2775     1004860 :       int depth = execution_context()->ContextChainDepth(variable->scope());
    2776             :       ContextScope* context = execution_context()->Previous(depth);
    2777             :       Register context_reg;
    2778     1004850 :       if (context) {
    2779      971598 :         context_reg = context->reg();
    2780             :         depth = 0;
    2781             :       } else {
    2782       33252 :         context_reg = execution_context()->reg();
    2783             :       }
    2784             : 
    2785             :       BytecodeArrayBuilder::ContextSlotMutability immutable =
    2786             :           (variable->maybe_assigned() == kNotAssigned)
    2787             :               ? BytecodeArrayBuilder::kImmutableSlot
    2788     1004850 :               : BytecodeArrayBuilder::kMutableSlot;
    2789             : 
    2790             :       builder()->LoadContextSlot(context_reg, variable->index(), depth,
    2791     1004850 :                                  immutable);
    2792     1004828 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    2793      241555 :         BuildThrowIfHole(variable);
    2794             :       }
    2795             :       break;
    2796             :     }
    2797             :     case VariableLocation::LOOKUP: {
    2798      401970 :       switch (variable->mode()) {
    2799             :         case VariableMode::kDynamicLocal: {
    2800        7294 :           Variable* local_variable = variable->local_if_not_shadowed();
    2801             :           int depth =
    2802        3647 :               execution_context()->ContextChainDepth(local_variable->scope());
    2803             :           builder()->LoadLookupContextSlot(variable->raw_name(), typeof_mode,
    2804        3647 :                                            local_variable->index(), depth);
    2805        3647 :           if (hole_check_mode == HoleCheckMode::kRequired) {
    2806        1531 :             BuildThrowIfHole(variable);
    2807             :           }
    2808             :           break;
    2809             :         }
    2810             :         case VariableMode::kDynamicGlobal: {
    2811             :           int depth =
    2812      372469 :               current_scope()->ContextChainLengthUntilOutermostSloppyEval();
    2813      372469 :           FeedbackSlot slot = GetCachedLoadGlobalICSlot(typeof_mode, variable);
    2814             :           builder()->LoadLookupGlobalSlot(variable->raw_name(), typeof_mode,
    2815      372470 :                                           feedback_index(slot), depth);
    2816             :           break;
    2817             :         }
    2818             :         default:
    2819       25854 :           builder()->LoadLookupSlot(variable->raw_name(), typeof_mode);
    2820             :       }
    2821             :       break;
    2822             :     }
    2823             :     case VariableLocation::MODULE: {
    2824        1362 :       int depth = execution_context()->ContextChainDepth(variable->scope());
    2825        1362 :       builder()->LoadModuleVariable(variable->index(), depth);
    2826        1362 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    2827         849 :         BuildThrowIfHole(variable);
    2828             :       }
    2829             :       break;
    2830             :     }
    2831             :   }
    2832    13444038 : }
    2833             : 
    2834     4201028 : void BytecodeGenerator::BuildVariableLoadForAccumulatorValue(
    2835             :     Variable* variable, HoleCheckMode hole_check_mode, TypeofMode typeof_mode) {
    2836             :   ValueResultScope accumulator_result(this);
    2837     4201028 :   BuildVariableLoad(variable, hole_check_mode, typeof_mode);
    2838     4201124 : }
    2839             : 
    2840     7324479 : void BytecodeGenerator::BuildReturn(int source_position) {
    2841     2441493 :   if (FLAG_trace) {
    2842             :     RegisterAllocationScope register_scope(this);
    2843           0 :     Register result = register_allocator()->NewRegister();
    2844             :     // Runtime returns {result} value, preserving accumulator.
    2845           0 :     builder()->StoreAccumulatorInRegister(result).CallRuntime(
    2846           0 :         Runtime::kTraceExit, result);
    2847             :   }
    2848     2441493 :   if (info()->collect_type_profile()) {
    2849          85 :     builder()->CollectTypeProfile(info()->literal()->return_position());
    2850             :   }
    2851     2441493 :   builder()->SetReturnPosition(source_position, info()->literal());
    2852     2441727 :   builder()->Return();
    2853     2441954 : }
    2854             : 
    2855       20338 : void BytecodeGenerator::BuildAsyncReturn(int source_position) {
    2856             :   RegisterAllocationScope register_scope(this);
    2857             : 
    2858       14262 :   if (IsAsyncGeneratorFunction(info()->literal()->kind())) {
    2859        1055 :     RegisterList args = register_allocator()->NewRegisterList(3);
    2860             :     builder()
    2861        1055 :         ->MoveRegister(generator_object(), args[0])  // generator
    2862        1055 :         .StoreAccumulatorInRegister(args[1])         // value
    2863        1055 :         .LoadTrue()
    2864        1055 :         .StoreAccumulatorInRegister(args[2])  // done
    2865        1055 :         .CallRuntime(Runtime::kInlineAsyncGeneratorResolve, args);
    2866             :   } else {
    2867             :     DCHECK(IsAsyncFunction(info()->literal()->kind()));
    2868        6076 :     RegisterList args = register_allocator()->NewRegisterList(3);
    2869             :     builder()
    2870        6076 :         ->MoveRegister(generator_object(), args[0])  // generator
    2871        6076 :         .StoreAccumulatorInRegister(args[1])         // value
    2872       18228 :         .LoadBoolean(info()->literal()->CanSuspend())
    2873        6076 :         .StoreAccumulatorInRegister(args[2])  // can_suspend
    2874        6076 :         .CallRuntime(Runtime::kInlineAsyncFunctionResolve, args);
    2875             :   }
    2876             : 
    2877        7131 :   BuildReturn(source_position);
    2878        7131 : }
    2879             : 
    2880       37448 : void BytecodeGenerator::BuildReThrow() { builder()->ReThrow(); }
    2881             : 
    2882     2735793 : void BytecodeGenerator::BuildThrowIfHole(Variable* variable) {
    2883     2453145 :   if (variable->is_this()) {
    2884             :     DCHECK(variable->mode() == VariableMode::kConst);
    2885     2170497 :     builder()->ThrowSuperNotCalledIfHole();
    2886             :   } else {
    2887      282648 :     builder()->ThrowReferenceErrorIfHole(variable->raw_name());
    2888             :   }
    2889     2453151 : }
    2890             : 
    2891       38900 : void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
    2892             :                                                             Token::Value op) {
    2893       41431 :   if (variable->is_this() && variable->mode() == VariableMode::kConst &&
    2894             :       op == Token::INIT) {
    2895             :     // Perform an initialization check for 'this'. 'this' variable is the
    2896             :     // only variable able to trigger bind operations outside the TDZ
    2897             :     // via 'super' calls.
    2898        2531 :     builder()->ThrowSuperAlreadyCalledIfNotHole();
    2899             :   } else {
    2900             :     // Perform an initialization check for let/const declared variables.
    2901             :     // E.g. let x = (x = 20); is not allowed.
    2902             :     DCHECK(IsLexicalVariableMode(variable->mode()));
    2903       36369 :     BuildThrowIfHole(variable);
    2904             :   }
    2905       38900 : }
    2906             : 
    2907     5726329 : void BytecodeGenerator::BuildVariableAssignment(
    2908    13234512 :     Variable* variable, Token::Value op, HoleCheckMode hole_check_mode,
    2909     3517219 :     LookupHoistingMode lookup_hoisting_mode) {
    2910             :   VariableMode mode = variable->mode();
    2911             :   RegisterAllocationScope assignment_register_scope(this);
    2912             :   BytecodeLabel end_label;
    2913     5726329 :   switch (variable->location()) {
    2914             :     case VariableLocation::PARAMETER:
    2915             :     case VariableLocation::LOCAL: {
    2916             :       Register destination;
    2917     2491568 :       if (VariableLocation::PARAMETER == variable->location()) {
    2918       30303 :         if (variable->IsReceiver()) {
    2919        2375 :           destination = builder()->Receiver();
    2920             :         } else {
    2921       27928 :           destination = builder()->Parameter(variable->index());
    2922             :         }
    2923             :       } else {
    2924     2461265 :         destination = builder()->Local(variable->index());
    2925             :       }
    2926             : 
    2927     2491641 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    2928             :         // Load destination to check for hole.
    2929        4960 :         Register value_temp = register_allocator()->NewRegister();
    2930             :         builder()
    2931        4960 :             ->StoreAccumulatorInRegister(value_temp)
    2932        4960 :             .LoadAccumulatorWithRegister(destination);
    2933             : 
    2934        4960 :         BuildHoleCheckForVariableAssignment(variable, op);
    2935        4960 :         builder()->LoadAccumulatorWithRegister(value_temp);
    2936             :       }
    2937             : 
    2938     2491641 :       if (mode != VariableMode::kConst || op == Token::INIT) {
    2939     2486771 :         builder()->StoreAccumulatorInRegister(destination);
    2940        4870 :       } else if (variable->throw_on_const_assignment(language_mode())) {
    2941        4837 :         builder()->CallRuntime(Runtime::kThrowConstAssignError);
    2942             :       }
    2943             :       break;
    2944             :     }
    2945             :     case VariableLocation::UNALLOCATED: {
    2946     1421094 :       FeedbackSlot slot = GetCachedStoreGlobalICSlot(language_mode(), variable);
    2947     1421251 :       builder()->StoreGlobal(variable->raw_name(), feedback_index(slot));
    2948             :       break;
    2949             :     }
    2950             :     case VariableLocation::CONTEXT: {
    2951     1741232 :       int depth = execution_context()->ContextChainDepth(variable->scope());
    2952             :       ContextScope* context = execution_context()->Previous(depth);
    2953             :       Register context_reg;
    2954             : 
    2955     1741252 :       if (context) {
    2956     1729213 :         context_reg = context->reg();
    2957             :         depth = 0;
    2958             :       } else {
    2959       12039 :         context_reg = execution_context()->reg();
    2960             :       }
    2961             : 
    2962     1741252 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    2963             :         // Load destination to check for hole.
    2964       33870 :         Register value_temp = register_allocator()->NewRegister();
    2965             :         builder()
    2966       33870 :             ->StoreAccumulatorInRegister(value_temp)
    2967             :             .LoadContextSlot(context_reg, variable->index(), depth,
    2968       33870 :                              BytecodeArrayBuilder::kMutableSlot);
    2969             : 
    2970       33870 :         BuildHoleCheckForVariableAssignment(variable, op);
    2971       33870 :         builder()->LoadAccumulatorWithRegister(value_temp);
    2972             :       }
    2973             : 
    2974     1741252 :       if (mode != VariableMode::kConst || op == Token::INIT) {
    2975     1713179 :         builder()->StoreContextSlot(context_reg, variable->index(), depth);
    2976       28073 :       } else if (variable->throw_on_const_assignment(language_mode())) {
    2977       28051 :         builder()->CallRuntime(Runtime::kThrowConstAssignError);
    2978             :       }
    2979             :       break;
    2980             :     }
    2981             :     case VariableLocation::LOOKUP: {
    2982             :       builder()->StoreLookupSlot(variable->raw_name(), language_mode(),
    2983       37543 :                                  lookup_hoisting_mode);
    2984       37542 :       break;
    2985             :     }
    2986             :     case VariableLocation::MODULE: {
    2987             :       DCHECK(IsDeclaredVariableMode(mode));
    2988             : 
    2989       34845 :       if (mode == VariableMode::kConst && op != Token::INIT) {
    2990         110 :         builder()->CallRuntime(Runtime::kThrowConstAssignError);
    2991         110 :         break;
    2992             :       }
    2993             : 
    2994             :       // If we don't throw above, we know that we're dealing with an
    2995             :       // export because imports are const and we do not generate initializing
    2996             :       // assignments for them.
    2997             :       DCHECK(variable->IsExport());
    2998             : 
    2999       34735 :       int depth = execution_context()->ContextChainDepth(variable->scope());
    3000       34735 :       if (hole_check_mode == HoleCheckMode::kRequired) {
    3001          70 :         Register value_temp = register_allocator()->NewRegister();
    3002             :         builder()
    3003          70 :             ->StoreAccumulatorInRegister(value_temp)
    3004          70 :             .LoadModuleVariable(variable->index(), depth);
    3005          70 :         BuildHoleCheckForVariableAssignment(variable, op);
    3006          70 :         builder()->LoadAccumulatorWithRegister(value_temp);
    3007             :       }
    3008       34735 :       builder()->StoreModuleVariable(variable->index(), depth);
    3009       34735 :       break;
    3010             :     }
    3011     5726761 :   }
    3012     5726094 : }
    3013             : 
    3014     2369088 : void BytecodeGenerator::BuildLoadNamedProperty(const Expression* object_expr,
    3015             :                                                Register object,
    3016             :                                                const AstRawString* name) {
    3017     2369088 :   if (ShouldOptimizeAsOneShot()) {
    3018     1257013 :     builder()->LoadNamedPropertyNoFeedback(object, name);
    3019             :   } else {
    3020     1112216 :     FeedbackSlot slot = GetCachedLoadICSlot(object_expr, name);
    3021     1112200 :     builder()->LoadNamedProperty(object, name, feedback_index(slot));
    3022             :   }
    3023     2369285 : }
    3024             : 
    3025     2391720 : void BytecodeGenerator::BuildStoreNamedProperty(const Expression* object_expr,
    3026             :                                                 Register object,
    3027     4783535 :                                                 const AstRawString* name) {
    3028             :   Register value;
    3029     2391720 :   if (!execution_result()->IsEffect()) {
    3030        8514 :     value = register_allocator()->NewRegister();
    3031        8515 :     builder()->StoreAccumulatorInRegister(value);
    3032             :   }
    3033             : 
    3034     2391721 :   if (ShouldOptimizeAsOneShot()) {
    3035      114700 :     builder()->StoreNamedPropertyNoFeedback(object, name, language_mode());
    3036             :   } else {
    3037     2277056 :     FeedbackSlot slot = GetCachedStoreICSlot(object_expr, name);
    3038             :     builder()->StoreNamedProperty(object, name, feedback_index(slot),
    3039     2277059 :                                   language_mode());
    3040             :   }
    3041             : 
    3042     2391815 :   if (!execution_result()->IsEffect()) {
    3043        8515 :     builder()->LoadAccumulatorWithRegister(value);
    3044             :   }
    3045     2391815 : }
    3046             : 
    3047             : // static
    3048             : BytecodeGenerator::AssignmentLhsData
    3049           0 : BytecodeGenerator::AssignmentLhsData::NonProperty(Expression* expr) {
    3050             :   return AssignmentLhsData(NON_PROPERTY, expr, RegisterList(), Register(),
    3051           0 :                            Register(), nullptr, nullptr);
    3052             : }
    3053             : // static
    3054             : BytecodeGenerator::AssignmentLhsData
    3055           0 : BytecodeGenerator::AssignmentLhsData::NamedProperty(Expression* object_expr,
    3056             :                                                     Register object,
    3057             :                                                     const AstRawString* name) {
    3058             :   return AssignmentLhsData(NAMED_PROPERTY, nullptr, RegisterList(), object,
    3059           0 :                            Register(), object_expr, name);
    3060             : }
    3061             : // static
    3062             : BytecodeGenerator::AssignmentLhsData
    3063           0 : BytecodeGenerator::AssignmentLhsData::KeyedProperty(Register object,
    3064             :                                                     Register key) {
    3065             :   return AssignmentLhsData(KEYED_PROPERTY, nullptr, RegisterList(), object, key,
    3066           0 :                            nullptr, nullptr);
    3067             : }
    3068             : // static
    3069             : BytecodeGenerator::AssignmentLhsData
    3070           0 : BytecodeGenerator::AssignmentLhsData::NamedSuperProperty(
    3071             :     RegisterList super_property_args) {
    3072             :   return AssignmentLhsData(NAMED_SUPER_PROPERTY, nullptr, super_property_args,
    3073           0 :                            Register(), Register(), nullptr, nullptr);
    3074             : }
    3075             : // static
    3076             : BytecodeGenerator::AssignmentLhsData
    3077           0 : BytecodeGenerator::AssignmentLhsData::KeyedSuperProperty(
    3078             :     RegisterList super_property_args) {
    3079             :   return AssignmentLhsData(KEYED_SUPER_PROPERTY, nullptr, super_property_args,
    3080           0 :                            Register(), Register(), nullptr, nullptr);
    3081             : }
    3082             : 
    3083     7608061 : BytecodeGenerator::AssignmentLhsData BytecodeGenerator::PrepareAssignmentLhs(
    3084             :     Expression* lhs, AccumulatorPreservingMode accumulator_preserving_mode) {
    3085             :   // Left-hand side can only be a property, a global or a variable slot.
    3086    14848065 :   Property* property = lhs->AsProperty();
    3087     7608112 :   AssignType assign_type = Property::GetAssignType(property);
    3088             : 
    3089             :   // Evaluate LHS expression.
    3090     7608111 :   switch (assign_type) {
    3091             :     case NON_PROPERTY:
    3092             :       return AssignmentLhsData::NonProperty(lhs);
    3093             :     case NAMED_PROPERTY: {
    3094     2391763 :       AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
    3095     2391766 :       Register object = VisitForRegisterValue(property->obj());
    3096             :       const AstRawString* name =
    3097     4783719 :           property->key()->AsLiteral()->AsRawPropertyName();
    3098             :       return AssignmentLhsData::NamedProperty(property->obj(), object, name);
    3099             :     }
    3100             :     case KEYED_PROPERTY: {
    3101       31692 :       AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
    3102       31701 :       Register object = VisitForRegisterValue(property->obj());
    3103       31698 :       Register key = VisitForRegisterValue(property->key());
    3104             :       return AssignmentLhsData::KeyedProperty(object, key);
    3105             :     }
    3106             :     case NAMED_SUPER_PROPERTY: {
    3107         220 :       AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
    3108             :       RegisterList super_property_args =
    3109         220 :           register_allocator()->NewRegisterList(4);
    3110         440 :       SuperPropertyReference* super_property =
    3111         220 :           property->obj()->AsSuperPropertyReference();
    3112             :       VisitForRegisterValue(super_property->this_var(), 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         680 :       SuperPropertyReference* super_property =
    3125         340 :           property->obj()->AsSuperPropertyReference();
    3126             :       VisitForRegisterValue(super_property->this_var(), super_property_args[0]);
    3127             :       VisitForRegisterValue(super_property->home_object(),
    3128             :                             super_property_args[1]);
    3129             :       VisitForRegisterValue(property->key(), super_property_args[2]);
    3130             :       return AssignmentLhsData::KeyedSuperProperty(super_property_args);
    3131             :     }
    3132             :   }
    3133           0 :   UNREACHABLE();
    3134             : }
    3135             : 
    3136             : // Build the iteration finalizer called in the finally block of an iteration
    3137             : // protocol execution. This closes the iterator if needed, and suppresses any
    3138             : // exception it throws if necessary.
    3139             : //
    3140             : // In pseudo-code, this builds:
    3141             : //
    3142             : // if (!done) {
    3143             : //   let method = iterator.return
    3144             : //   if (method !== null && method !== undefined) {
    3145             : //     if (typeof(method) !== "function") throw TypeError
    3146             : //     try {
    3147             : //       let return_val = method.call(iterator)
    3148             : //       if (!%IsObject(return_val)) throw TypeError
    3149             : //     } catch (e) {
    3150             : //       if (iteration_continuation != RETHROW)
    3151             : //         rethrow e
    3152             : //     }
    3153             : //   }
    3154             : // }
    3155             : //
    3156             : // For async iterators, iterator.close() becomes await iterator.close().
    3157       40729 : void BytecodeGenerator::BuildFinalizeIteration(
    3158             :     IteratorRecord iterator, Register done,
    3159      122211 :     Register iteration_continuation_token) {
    3160             :   RegisterAllocationScope register_scope(this);
    3161             :   BytecodeLabels iterator_is_done(zone());
    3162             : 
    3163             :   // if (!done) {
    3164       40737 :   builder()->LoadAccumulatorWithRegister(done).JumpIfTrue(
    3165       81470 :       ToBooleanMode::kConvertToBoolean, iterator_is_done.New());
    3166             : 
    3167             :   //   method = iterator.return
    3168             :   //   if (method !== null && method !== undefined) {
    3169       40741 :   Register method = register_allocator()->NewRegister();
    3170             :   builder()
    3171             :       ->LoadNamedProperty(iterator.object(),
    3172             :                           ast_string_constants()->return_string(),
    3173       81480 :                           feedback_index(feedback_spec()->AddLoadICSlot()))
    3174       40739 :       .StoreAccumulatorInRegister(method)
    3175       81475 :       .JumpIfUndefined(iterator_is_done.New())
    3176       81480 :       .JumpIfNull(iterator_is_done.New());
    3177             : 
    3178             :   //     if (typeof(method) !== "function") throw TypeError
    3179             :   BytecodeLabel if_callable;
    3180             :   builder()
    3181       40739 :       ->CompareTypeOf(TestTypeOfFlags::LiteralFlag::kFunction)
    3182       40741 :       .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &if_callable);
    3183             :   {
    3184             :     // throw %NewTypeError(kReturnMethodNotCallable)
    3185             :     RegisterAllocationScope register_scope(this);
    3186       40741 :     RegisterList new_type_error_args = register_allocator()->NewRegisterList(2);
    3187             :     builder()
    3188       40741 :         ->LoadLiteral(Smi::FromEnum(MessageTemplate::kReturnMethodNotCallable))
    3189       40739 :         .StoreAccumulatorInRegister(new_type_error_args[0])
    3190       81480 :         .LoadLiteral(ast_string_constants()->empty_string())
    3191       40740 :         .StoreAccumulatorInRegister(new_type_error_args[1])
    3192       40740 :         .CallRuntime(Runtime::kNewTypeError, new_type_error_args)
    3193       40742 :         .Throw();
    3194             :   }
    3195       40739 :   builder()->Bind(&if_callable);
    3196             : 
    3197             :   {
    3198             :     RegisterAllocationScope register_scope(this);
    3199             :     BuildTryCatch(
    3200             :         // try {
    3201             :         //   let return_val = method.call(iterator)
    3202             :         //   if (!%IsObject(return_val)) throw TypeError
    3203             :         // }
    3204       40732 :         [&]() {
    3205       81473 :           RegisterList args(iterator.object());
    3206             :           builder()->CallProperty(
    3207      122200 :               method, args, feedback_index(feedback_spec()->AddCallICSlot()));
    3208       81482 :           if (iterator.type() == IteratorType::kAsync) {
    3209         337 :             BuildAwait();
    3210             :           }
    3211       40741 :           builder()->JumpIfJSReceiver(iterator_is_done.New());
    3212             :           {
    3213             :             // Throw this exception inside the try block so that it is
    3214             :             // suppressed by the iteration continuation if necessary.
    3215       40743 :             RegisterAllocationScope register_scope(this);
    3216       40743 :             Register return_result = register_allocator()->NewRegister();
    3217             :             builder()
    3218       40739 :                 ->StoreAccumulatorInRegister(return_result)
    3219             :                 .CallRuntime(Runtime::kThrowIteratorResultNotAnObject,
    3220       40741 :                              return_result);
    3221             :           }
    3222       40742 :         },
    3223             : 
    3224             :         // catch (e) {
    3225             :         //   if (iteration_continuation != RETHROW)
    3226             :         //     rethrow e
    3227             :         // }
    3228       40733 :         [&](Register context) {
    3229             :           // Reuse context register to store the exception.
    3230       40733 :           Register close_exception = context;
    3231       40733 :           builder()->StoreAccumulatorInRegister(close_exception);
    3232             : 
    3233             :           BytecodeLabel suppress_close_exception;
    3234             :           builder()
    3235             :               ->LoadLiteral(
    3236       40738 :                   Smi::FromInt(ControlScope::DeferredCommands::kRethrowToken))
    3237       81478 :               .CompareReference(iteration_continuation_token)
    3238             :               .JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
    3239       40742 :                           &suppress_close_exception)
    3240       40742 :               .LoadAccumulatorWithRegister(close_exception)
    3241       40743 :               .ReThrow()
    3242       40741 :               .Bind(&suppress_close_exception);
    3243       40740 :         },
    3244       40740 :         HandlerTable::UNCAUGHT);
    3245             :   }
    3246             : 
    3247       81480 :   iterator_is_done.Bind(builder());
    3248       40741 : }
    3249             : 
    3250             : // Get the default value of a destructuring target. Will mutate the
    3251             : // destructuring target expression if there is a default value.
    3252             : //
    3253             : // For
    3254             : //   a = b
    3255             : // in
    3256             : //   let {a = b} = c
    3257             : // returns b and mutates the input into a.
    3258       22553 : Expression* BytecodeGenerator::GetDestructuringDefaultValue(
    3259             :     Expression** target) {
    3260             :   Expression* default_value = nullptr;
    3261       45106 :   if ((*target)->IsAssignment()) {
    3262        3792 :     Assignment* default_init = (*target)->AsAssignment();
    3263             :     DCHECK_EQ(default_init->op(), Token::ASSIGN);
    3264             :     default_value = default_init->value();
    3265        1896 :     *target = default_init->target();
    3266             :     DCHECK((*target)->IsValidReferenceExpression() || (*target)->IsPattern());
    3267             :   }
    3268       22553 :   return default_value;
    3269             : }
    3270             : 
    3271             : // Convert a destructuring assignment to an array literal into a sequence of
    3272             : // iterator accesses into the value being assigned (in the accumulator).
    3273             : //
    3274             : // [a().x, ...b] = accumulator
    3275             : //
    3276             : //   becomes
    3277             : //
    3278             : // iterator = %GetIterator(accumulator)
    3279             : // try {
    3280             : //
    3281             : //   // Individual assignments read off the value from iterator.next() This gets
    3282             : //   // repeated per destructuring element.
    3283             : //   if (!done) {
    3284             : //     // Make sure we are considered 'done' if .next(), .done or .value fail.
    3285             : //     done = true
    3286             : //     var next_result = iterator.next()
    3287             : //     var tmp_done = next_result.done
    3288             : //     if (!tmp_done) {
    3289             : //       value = next_result.value
    3290             : //       done = false
    3291             : //     }
    3292             : //   }
    3293             : //   if (done)
    3294             : //     value = undefined
    3295             : //   a().x = value
    3296             : //
    3297             : //   // A spread receives the remaining items in the iterator.
    3298             : //   var array = []
    3299             : //   var index = 0
    3300             : //   %FillArrayWithIterator(iterator, array, index, done)
    3301             : //   done = true
    3302             : //   b = array
    3303             : //
    3304             : // } catch(e) {
    3305             : //   iteration_continuation = RETHROW
    3306             : // } finally {
    3307             : //   %FinalizeIteration(iterator, done, iteration_continuation)
    3308             : // }
    3309        2689 : void BytecodeGenerator::BuildDestructuringArrayAssignment(
    3310             :     ArrayLiteral* pattern, Token::Value op,
    3311        2689 :     LookupHoistingMode lookup_hoisting_mode) {
    3312             :   RegisterAllocationScope scope(this);
    3313             : 
    3314        2689 :   Register value = register_allocator()->NewRegister();
    3315        2689 :   builder()->StoreAccumulatorInRegister(value);
    3316             : 
    3317             :   // Store the iterator in a dedicated register so that it can be closed on
    3318             :   // exit, and the 'done' value in a dedicated register so that it can be
    3319             :   // changed and accessed independently of the iteration result.
    3320        2689 :   IteratorRecord iterator = BuildGetIteratorRecord(IteratorType::kNormal);
    3321        2689 :   Register done = register_allocator()->NewRegister();
    3322        2689 :   builder()->LoadFalse();
    3323        2689 :   builder()->StoreAccumulatorInRegister(done);
    3324             : 
    3325             :   BuildTryFinally(
    3326             :       // Try block.
    3327        2689 :       [&]() {
    3328       13297 :         Register next_result = register_allocator()->NewRegister();
    3329        5378 :         FeedbackSlot next_value_load_slot = feedback_spec()->AddLoadICSlot();
    3330        5378 :         FeedbackSlot next_done_load_slot = feedback_spec()->AddLoadICSlot();
    3331             : 
    3332         583 :         Spread* spread = nullptr;
    3333        8914 :         for (Expression* target : *pattern->values()) {
    3334        4119 :           if (target->IsSpread()) {
    3335         583 :             spread = target->AsSpread();
    3336         583 :             break;
    3337             :           }
    3338             : 
    3339        3536 :           Expression* default_value = GetDestructuringDefaultValue(&target);
    3340        7072 :           if (!target->IsPattern()) {
    3341        3190 :             builder()->SetExpressionAsStatementPosition(target);
    3342             :           }
    3343             : 
    3344        3536 :           AssignmentLhsData lhs_data = PrepareAssignmentLhs(target);
    3345             : 
    3346             :           // if (!done) {
    3347             :           //   // Make sure we are considered done if .next(), .done or .value
    3348             :           //   // fail.
    3349             :           //   done = true
    3350             :           //   var next_result = iterator.next()
    3351             :           //   var tmp_done = next_result.done
    3352             :           //   if (!tmp_done) {
    3353             :           //     value = next_result.value
    3354             :           //     done = false
    3355             :           //   }
    3356             :           // }
    3357             :           // if (done)
    3358             :           //   value = undefined
    3359        3536 :           BytecodeLabels is_done(zone());
    3360             : 
    3361        3536 :           builder()->LoadAccumulatorWithRegister(done);
    3362             :           builder()->JumpIfTrue(ToBooleanMode::kConvertToBoolean,
    3363        3536 :                                 is_done.New());
    3364             : 
    3365        3535 :           builder()->LoadTrue().StoreAccumulatorInRegister(done);
    3366        3536 :           BuildIteratorNext(iterator, next_result);
    3367             :           builder()
    3368             :               ->LoadNamedProperty(next_result,
    3369             :                                   ast_string_constants()->done_string(),
    3370        7072 :                                   feedback_index(next_done_load_slot))
    3371        7072 :               .JumpIfTrue(ToBooleanMode::kConvertToBoolean, is_done.New())
    3372             :               .LoadNamedProperty(next_result,
    3373             :                                  ast_string_constants()->value_string(),
    3374       10608 :                                  feedback_index(next_value_load_slot))
    3375        3536 :               .StoreAccumulatorInRegister(next_result)
    3376        3536 :               .LoadFalse()
    3377        7072 :               .StoreAccumulatorInRegister(done)
    3378        3536 :               .LoadAccumulatorWithRegister(next_result);
    3379             : 
    3380             :           // Only do the assignment if this is not a hole (i.e. 'elided').
    3381        3536 :           if (!target->IsTheHoleLiteral()) {
    3382             :             // [<pattern> = <init>] = <value>
    3383             :             //   becomes (roughly)
    3384             :             // temp = <value>.next();
    3385             :             // <pattern> = temp === undefined ? <init> : temp;
    3386             :             BytecodeLabel do_assignment;
    3387        3425 :             if (default_value) {
    3388         461 :               builder()->JumpIfNotUndefined(&do_assignment);
    3389             :               // Since done == true => temp == undefined, jump directly to using
    3390             :               // the default value for that case.
    3391         461 :               is_done.Bind(builder());
    3392         461 :               VisitForAccumulatorValue(default_value);
    3393             :             } else {
    3394        2964 :               builder()->Jump(&do_assignment);
    3395        2964 :               is_done.Bind(builder());
    3396        2964 :               builder()->LoadUndefined();
    3397             :             }
    3398        3425 :             builder()->Bind(&do_assignment);
    3399             : 
    3400        3425 :             BuildAssignment(lhs_data, op, lookup_hoisting_mode);
    3401             :           } else {
    3402             :             DCHECK_EQ(lhs_data.assign_type(), NON_PROPERTY);
    3403         111 :             is_done.Bind(builder());
    3404             :           }
    3405             :         }
    3406             : 
    3407        2689 :         if (spread) {
    3408         583 :           RegisterAllocationScope scope(this);
    3409             : 
    3410             :           // A spread is turned into a loop over the remainer of the iterator.
    3411             :           Expression* target = spread->expression();
    3412             : 
    3413         583 :           if (!target->IsPattern()) {
    3414             :             builder()->SetExpressionAsStatementPosition(spread);
    3415             :           }
    3416             : 
    3417         583 :           AssignmentLhsData lhs_data = PrepareAssignmentLhs(target);
    3418             : 
    3419             :           // var array = [];
    3420         583 :           Register array = register_allocator()->NewRegister();
    3421             :           builder()->CreateEmptyArrayLiteral(
    3422        1749 :               feedback_index(feedback_spec()->AddLiteralSlot()));
    3423         583 :           builder()->StoreAccumulatorInRegister(array);
    3424             : 
    3425             :           // var index = 0;
    3426         583 :           Register index = register_allocator()->NewRegister();
    3427         583 :           builder()->LoadLiteral(Smi::zero());
    3428         583 :           builder()->StoreAccumulatorInRegister(index);
    3429             : 
    3430             :           // Set done to true, since it's guaranteed to be true by the time the
    3431             :           // array fill completes.
    3432         583 :           builder()->LoadTrue().StoreAccumulatorInRegister(done);
    3433             : 
    3434             :           // Fill the array with the iterator.
    3435             :           FeedbackSlot element_slot =
    3436        1749 :               feedback_spec()->AddStoreInArrayLiteralICSlot();
    3437        1749 :           FeedbackSlot index_slot = feedback_spec()->AddBinaryOpICSlot();
    3438             :           BuildFillArrayWithIterator(iterator, array, index, next_result,
    3439             :                                      next_value_load_slot, next_done_load_slot,
    3440         583 :                                      index_slot, element_slot);
    3441             : 
    3442             :           // Assign the array to the LHS.
    3443         583 :           builder()->LoadAccumulatorWithRegister(array);
    3444         583 :           BuildAssignment(lhs_data, op, lookup_hoisting_mode);
    3445             :         }
    3446        2689 :       },
    3447             :       // Finally block.
    3448             :       [&](Register iteration_continuation_token) {
    3449             :         // Finish the iteration in the finally block.
    3450        2689 :         BuildFinalizeIteration(iterator, done, iteration_continuation_token);
    3451             :       },
    3452        2689 :       HandlerTable::UNCAUGHT);
    3453             : 
    3454        2689 :   if (!execution_result()->IsEffect()) {
    3455         266 :     builder()->LoadAccumulatorWithRegister(value);
    3456        2689 :   }
    3457        2689 : }
    3458             : 
    3459             : // Convert a destructuring assignment to an object literal into a sequence of
    3460             : // property accesses into the value being assigned (in the accumulator).
    3461             : //
    3462             : // { y, [x++]: a(), ...b.c } = value
    3463             : //
    3464             : //   becomes
    3465             : //
    3466             : // var rest_runtime_callargs = new Array(3);
    3467             : // rest_runtime_callargs[0] = value;
    3468             : //
    3469             : // rest_runtime_callargs[1] = value;
    3470             : // y = value.y;
    3471             : //
    3472             : // var temp1 = %ToName(x++);
    3473             : // rest_runtime_callargs[2] = temp1;
    3474             : // a() = value[temp1];
    3475             : //
    3476             : // b.c = %CopyDataPropertiesWithExcludedProperties.call(rest_runtime_callargs);
    3477       10991 : void BytecodeGenerator::BuildDestructuringObjectAssignment(
    3478       29803 :     ObjectLiteral* pattern, Token::Value op,
    3479       10992 :     LookupHoistingMode lookup_hoisting_mode) {
    3480             :   RegisterAllocationScope scope(this);
    3481             : 
    3482             :   // if (value === null || value === undefined)
    3483             :   //   throw new TypeError(kNonCoercible);
    3484             :   //
    3485             :   // TODO(leszeks): Eliminate check if value is known to be non-null (e.g.
    3486             :   // an object literal).
    3487             :   BytecodeLabel is_null_or_undefined, not_null_or_undefined;
    3488             :   builder()
    3489       10991 :       ->JumpIfNull(&is_null_or_undefined)
    3490       10991 :       .JumpIfNotUndefined(&not_null_or_undefined);
    3491             : 
    3492             :   {
    3493       10992 :     builder()->Bind(&is_null_or_undefined);
    3494             :     builder()->SetExpressionPosition(pattern);
    3495       10992 :     builder()->CallRuntime(Runtime::kThrowPatternAssignmentNonCoercible);
    3496             :   }
    3497             : 
    3498             :   // Store the assignment value in a register.
    3499             :   Register value;
    3500             :   RegisterList rest_runtime_callargs;
    3501       10991 :   if (pattern->has_rest_property()) {
    3502             :     rest_runtime_callargs =
    3503         205 :         register_allocator()->NewRegisterList(pattern->properties()->length());
    3504         205 :     value = rest_runtime_callargs[0];
    3505             :   } else {
    3506       10786 :     value = register_allocator()->NewRegister();
    3507             :   }
    3508       10992 :   builder()->Bind(&not_null_or_undefined).StoreAccumulatorInRegister(value);
    3509             : 
    3510             :   int i = 0;
    3511       79035 :   for (ObjectLiteralProperty* pattern_property : *pattern->properties()) {
    3512             :     RegisterAllocationScope scope(this);
    3513             : 
    3514             :     // The key of the pattern becomes the key into the RHS value, and the value
    3515             :     // of the pattern becomes the target of the assignment.
    3516             :     //
    3517             :     // e.g. { a: b } = o becomes b = o.a
    3518       19017 :     Expression* pattern_key = pattern_property->key();
    3519       19017 :     Expression* target = pattern_property->value();
    3520       19017 :     Expression* default_value = GetDestructuringDefaultValue(&target);
    3521             : 
    3522       38034 :     if (!target->IsPattern()) {
    3523             :       builder()->SetExpressionAsStatementPosition(target);
    3524             :     }
    3525             : 
    3526             :     // Calculate this property's key into the assignment RHS value, additionally
    3527             :     // storing the key for rest_runtime_callargs if needed.
    3528             :     //
    3529             :     // The RHS is accessed using the key either by LoadNamedProperty (if
    3530             :     // value_name is valid) or by LoadKeyedProperty (otherwise).
    3531             :     const AstRawString* value_name = nullptr;
    3532             :     Register value_key;
    3533             : 
    3534       19017 :     if (pattern_property->kind() != ObjectLiteralProperty::Kind::SPREAD) {
    3535       18812 :       if (pattern_key->IsPropertyName()) {
    3536       37008 :         value_name = pattern_key->AsLiteral()->AsRawPropertyName();
    3537             :       }
    3538       18812 :       if (pattern->has_rest_property() || !value_name) {
    3539         371 :         if (pattern->has_rest_property()) {
    3540         129 :           value_key = rest_runtime_callargs[i + 1];
    3541             :         } else {
    3542         242 :           value_key = register_allocator()->NewRegister();
    3543             :         }
    3544         371 :         if (pattern_property->is_computed_name()) {
    3545             :           // { [a()]: b().x } = c
    3546             :           // becomes
    3547             :           // var tmp = a()
    3548             :           // b().x = c[tmp]
    3549             :           DCHECK(!pattern_key->IsPropertyName() ||
    3550             :                  !pattern_key->IsNumberLiteral());
    3551         264 :           VisitForAccumulatorValue(pattern_key);
    3552         264 :           builder()->ToName(value_key);
    3553             :         } else {
    3554             :           // We only need the key for non-computed properties when it is numeric
    3555             :           // or is being saved for the rest_runtime_callargs.
    3556             :           DCHECK(
    3557             :               pattern_key->IsNumberLiteral() ||
    3558             :               (pattern->has_rest_property() && pattern_key->IsPropertyName()));
    3559             :           VisitForRegisterValue(pattern_key, value_key);
    3560             :         }
    3561             :       }
    3562             :     }
    3563             : 
    3564       19017 :     AssignmentLhsData lhs_data = PrepareAssignmentLhs(target);
    3565             : 
    3566             :     // Get the value from the RHS.
    3567       19018 :     if (pattern_property->kind() == ObjectLiteralProperty::Kind::SPREAD) {
    3568             :       DCHECK_EQ(i, pattern->properties()->length() - 1);
    3569             :       DCHECK(!value_key.is_valid());
    3570             :       DCHECK_NULL(value_name);
    3571             :       builder()->CallRuntime(Runtime::kCopyDataPropertiesWithExcludedProperties,
    3572         205 :                              rest_runtime_callargs);
    3573       18813 :     } else if (value_name) {
    3574             :       builder()->LoadNamedProperty(
    3575       37010 :           value, value_name, feedback_index(feedback_spec()->AddLoadICSlot()));
    3576             :     } else {
    3577             :       DCHECK(value_key.is_valid());
    3578         308 :       builder()->LoadAccumulatorWithRegister(value_key).LoadKeyedProperty(
    3579         616 :           value, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
    3580             :     }
    3581             : 
    3582             :     // {<pattern> = <init>} = <value>
    3583             :     //   becomes
    3584             :     // temp = <value>;
    3585             :     // <pattern> = temp === undefined ? <init> : temp;
    3586       19018 :     if (default_value) {
    3587             :       BytecodeLabel value_not_undefined;
    3588        1435 :       builder()->JumpIfNotUndefined(&value_not_undefined);
    3589        1435 :       VisitForAccumulatorValue(default_value);
    3590        1435 :       builder()->Bind(&value_not_undefined);
    3591             :     }
    3592             : 
    3593       19018 :     BuildAssignment(lhs_data, op, lookup_hoisting_mode);
    3594             : 
    3595       19018 :     i++;
    3596       19018 :   }
    3597             : 
    3598       10992 :   if (!execution_result()->IsEffect()) {
    3599         193 :     builder()->LoadAccumulatorWithRegister(value);
    3600       10992 :   }
    3601       10991 : }
    3602             : 
    3603     7607618 : void BytecodeGenerator::BuildAssignment(
    3604    15183030 :     const AssignmentLhsData& lhs_data, Token::Value op,
    3605       63411 :     LookupHoistingMode lookup_hoisting_mode) {
    3606             :   // Assign the value to the LHS.
    3607     7607618 :   switch (lhs_data.assign_type()) {
    3608             :     case NON_PROPERTY: {
    3609    10367308 :       if (ObjectLiteral* pattern = lhs_data.expr()->AsObjectLiteral()) {
    3610             :         // Split object literals into destructuring.
    3611       10992 :         BuildDestructuringObjectAssignment(pattern, op, lookup_hoisting_mode);
    3612     5172660 :       } else if (ArrayLiteral* pattern = lhs_data.expr()->AsArrayLiteral()) {
    3613             :         // Split object literals into destructuring.
    3614        2689 :         BuildDestructuringArrayAssignment(pattern, op, lookup_hoisting_mode);
    3615             :       } else {
    3616             :         DCHECK(lhs_data.expr()->IsVariableProxy());
    3617    10339942 :         VariableProxy* proxy = lhs_data.expr()->AsVariableProxy();
    3618             :         BuildVariableAssignment(proxy->var(), op, proxy->hole_check_mode(),
    3619    10339942 :                                 lookup_hoisting_mode);
    3620             :       }
    3621             :       break;
    3622             :     }
    3623             :     case NAMED_PROPERTY: {
    3624             :       BuildStoreNamedProperty(lhs_data.object_expr(), lhs_data.object(),
    3625     2391756 :                               lhs_data.name());
    3626     2391804 :       break;
    3627             :     }
    3628             :     case KEYED_PROPERTY: {
    3629       31701 :       FeedbackSlot slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
    3630             :       Register value;
    3631       31704 :       if (!execution_result()->IsEffect()) {
    3632        1976 :         value = register_allocator()->NewRegister();
    3633        1976 :         builder()->StoreAccumulatorInRegister(value);
    3634             :       }
    3635             :       builder()->StoreKeyedProperty(lhs_data.object(), lhs_data.key(),
    3636       31695 :                                     feedback_index(slot), language_mode());
    3637       31707 :       if (!execution_result()->IsEffect()) {
    3638        1976 :         builder()->LoadAccumulatorWithRegister(value);
    3639             :       }
    3640             :       break;
    3641             :     }
    3642             :     case NAMED_SUPER_PROPERTY: {
    3643             :       builder()
    3644         220 :           ->StoreAccumulatorInRegister(lhs_data.super_property_args()[3])
    3645         220 :           .CallRuntime(StoreToSuperRuntimeId(), lhs_data.super_property_args());
    3646         220 :       break;
    3647             :     }
    3648             :     case KEYED_SUPER_PROPERTY: {
    3649             :       builder()
    3650         340 :           ->StoreAccumulatorInRegister(lhs_data.super_property_args()[3])
    3651             :           .CallRuntime(StoreKeyedToSuperRuntimeId(),
    3652         340 :                        lhs_data.super_property_args());
    3653         340 :       break;
    3654             :     }
    3655             :   }
    3656     7607431 : }
    3657             : 
    3658    22378789 : void BytecodeGenerator::VisitAssignment(Assignment* expr) {
    3659     7459596 :   AssignmentLhsData lhs_data = PrepareAssignmentLhs(expr->target());
    3660             : 
    3661     7459794 :   VisitForAccumulatorValue(expr->value());
    3662             : 
    3663             :   builder()->SetExpressionPosition(expr);
    3664     7459399 :   BuildAssignment(lhs_data, expr->op(), expr->lookup_hoisting_mode());
    3665     7459086 : }
    3666             : 
    3667       82566 : void BytecodeGenerator::VisitCompoundAssignment(CompoundAssignment* expr) {
    3668      411435 :   AssignmentLhsData lhs_data = PrepareAssignmentLhs(expr->target());
    3669             : 
    3670             :   // Evaluate the value and potentially handle compound assignments by loading
    3671             :   // the left-hand side value and performing a binary operation.
    3672       82568 :   switch (lhs_data.assign_type()) {
    3673             :     case NON_PROPERTY: {
    3674      243481 :       VariableProxy* proxy = expr->target()->AsVariableProxy();
    3675       81162 :       BuildVariableLoad(proxy->var(), proxy->hole_check_mode());
    3676       81163 :       break;
    3677             :     }
    3678             :     case NAMED_PROPERTY: {
    3679         527 :       BuildLoadNamedProperty(lhs_data.object_expr(), lhs_data.object(),
    3680        1054 :                              lhs_data.name());
    3681         527 :       break;
    3682             :     }
    3683             :     case KEYED_PROPERTY: {
    3684         821 :       FeedbackSlot slot = feedback_spec()->AddKeyedLoadICSlot();
    3685             :       builder()
    3686         821 :           ->LoadAccumulatorWithRegister(lhs_data.key())
    3687         821 :           .LoadKeyedProperty(lhs_data.object(), feedback_index(slot));
    3688             :       break;
    3689             :     }
    3690             :     case NAMED_SUPER_PROPERTY: {
    3691             :       builder()->CallRuntime(Runtime::kLoadFromSuper,
    3692          20 :                              lhs_data.super_property_args().Truncate(3));
    3693          20 :       break;
    3694             :     }
    3695             :     case KEYED_SUPER_PROPERTY: {
    3696             :       builder()->CallRuntime(Runtime::kLoadKeyedFromSuper,
    3697          40 :                              lhs_data.super_property_args().Truncate(3));
    3698          40 :       break;
    3699             :     }
    3700             :   }
    3701      247715 :   BinaryOperation* binop = expr->AsCompoundAssignment()->binary_operation();
    3702       82570 :   FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
    3703       82570 :   if (expr->value()->IsSmiLiteral()) {
    3704             :     builder()->BinaryOperationSmiLiteral(
    3705             :         binop->op(), expr->value()->AsLiteral()->AsSmiLiteral(),
    3706       63788 :         feedback_index(slot));
    3707             :   } else {
    3708       61306 :     Register old_value = register_allocator()->NewRegister();
    3709       61307 :     builder()->StoreAccumulatorInRegister(old_value);
    3710       61309 :     VisitForAccumulatorValue(expr->value());
    3711       61307 :     builder()->BinaryOperation(binop->op(), old_value, feedback_index(slot));
    3712             :   }
    3713             : 
    3714             :   builder()->SetExpressionPosition(expr);
    3715       82571 :   BuildAssignment(lhs_data, expr->op(), expr->lookup_hoisting_mode());
    3716       82572 : }
    3717             : 
    3718             : // Suspends the generator to resume at the next suspend_id, with output stored
    3719             : // in the accumulator. When the generator is resumed, the sent value is loaded
    3720             : // in the accumulator.
    3721       23635 : void BytecodeGenerator::BuildSuspendPoint(int position) {
    3722       23635 :   const int suspend_id = suspend_count_++;
    3723             : 
    3724       23635 :   RegisterList registers = register_allocator()->AllLiveRegisters();
    3725             : 
    3726             :   // Save context, registers, and state. This bytecode then returns the value
    3727             :   // in the accumulator.
    3728             :   builder()->SetExpressionPosition(position);
    3729       23635 :   builder()->SuspendGenerator(generator_object(), registers, suspend_id);
    3730             : 
    3731             :   // Upon resume, we continue here.
    3732       23635 :   builder()->Bind(generator_jump_table_, suspend_id);
    3733             : 
    3734             :   // Clobbers all registers and sets the accumulator to the
    3735             :   // [[input_or_debug_pos]] slot of the generator object.
    3736       23635 :   builder()->ResumeGenerator(generator_object(), registers);
    3737       23634 : }
    3738             : 
    3739       16956 : void BytecodeGenerator::VisitYield(Yield* expr) {
    3740             :   builder()->SetExpressionPosition(expr);
    3741       16572 :   VisitForAccumulatorValue(expr->expression());
    3742             : 
    3743             :   // If this is not the first yield
    3744        8286 :   if (suspend_count_ > 0) {
    3745        3449 :     if (IsAsyncGeneratorFunction(function_kind())) {
    3746             :       // AsyncGenerator yields (with the exception of the initial yield)
    3747             :       // delegate work to the AsyncGeneratorYield stub, which Awaits the operand
    3748             :       // and on success, wraps the value in an IteratorResult.
    3749             :       RegisterAllocationScope register_scope(this);
    3750         384 :       RegisterList args = register_allocator()->NewRegisterList(3);
    3751             :       builder()
    3752         384 :           ->MoveRegister(generator_object(), args[0])  // generator
    3753         384 :           .StoreAccumulatorInRegister(args[1])         // value
    3754         768 :           .LoadBoolean(catch_prediction() != HandlerTable::ASYNC_AWAIT)
    3755         384 :           .StoreAccumulatorInRegister(args[2])  // is_caught
    3756         384 :           .CallRuntime(Runtime::kInlineAsyncGeneratorYield, args);
    3757             :     } else {
    3758             :       // Generator yields (with the exception of the initial yield) wrap the
    3759             :       // value into IteratorResult.
    3760             :       RegisterAllocationScope register_scope(this);
    3761        3065 :       RegisterList args = register_allocator()->NewRegisterList(2);
    3762             :       builder()
    3763        3065 :           ->StoreAccumulatorInRegister(args[0])  // value
    3764        3065 :           .LoadFalse()
    3765        3065 :           .StoreAccumulatorInRegister(args[1])  // done
    3766        3065 :           .CallRuntime(Runtime::kInlineCreateIterResultObject, args);
    3767             :     }
    3768             :   }
    3769             : 
    3770        8286 :   BuildSuspendPoint(expr->position());
    3771             :   // At this point, the generator has been resumed, with the received value in
    3772             :   // the accumulator.
    3773             : 
    3774             :   // TODO(caitp): remove once yield* desugaring for async generators is handled
    3775             :   // in BytecodeGenerator.
    3776        8286 :   if (expr->on_abrupt_resume() == Yield::kNoControl) {
    3777             :     DCHECK(IsAsyncGeneratorFunction(function_kind()));
    3778           0 :     return;
    3779             :   }
    3780             : 
    3781        8286 :   Register input = register_allocator()->NewRegister();
    3782        8286 :   builder()->StoreAccumulatorInRegister(input).CallRuntime(
    3783        8286 :       Runtime::kInlineGeneratorGetResumeMode, generator_object());
    3784             : 
    3785             :   // Now dispatch on resume mode.
    3786             :   STATIC_ASSERT(JSGeneratorObject::kNext + 1 == JSGeneratorObject::kReturn);
    3787             :   BytecodeJumpTable* jump_table =
    3788        8286 :       builder()->AllocateJumpTable(2, JSGeneratorObject::kNext);
    3789             : 
    3790        8286 :   builder()->SwitchOnSmiNoFeedback(jump_table);
    3791             : 
    3792             :   {
    3793             :     // Resume with throw (switch fallthrough).
    3794             :     // TODO(leszeks): Add a debug-only check that the accumulator is
    3795             :     // JSGeneratorObject::kThrow.
    3796             :     builder()->SetExpressionPosition(expr);
    3797        8286 :     builder()->LoadAccumulatorWithRegister(input);
    3798        8286 :     builder()->Throw();
    3799             :   }
    3800             : 
    3801             :   {
    3802             :     // Resume with return.
    3803        8286 :     builder()->Bind(jump_table, JSGeneratorObject::kReturn);
    3804        8286 :     builder()->LoadAccumulatorWithRegister(input);
    3805        8286 :     if (IsAsyncGeneratorFunction(function_kind())) {
    3806             :       execution_control()->AsyncReturnAccumulator();
    3807             :     } else {
    3808             :       execution_control()->ReturnAccumulator();
    3809             :     }
    3810             :   }
    3811             : 
    3812             :   {
    3813             :     // Resume with next.
    3814        8286 :     builder()->Bind(jump_table, JSGeneratorObject::kNext);
    3815             :     BuildIncrementBlockCoverageCounterIfEnabled(expr,
    3816             :                                                 SourceRangeKind::kContinuation);
    3817        8286 :     builder()->LoadAccumulatorWithRegister(input);
    3818             :   }
    3819             : }
    3820             : 
    3821             : // Desugaring of (yield* iterable)
    3822             : //
    3823             : //   do {
    3824             : //     const kNext = 0;
    3825             : //     const kReturn = 1;
    3826             : //     const kThrow = 2;
    3827             : //
    3828             : //     let output; // uninitialized
    3829             : //
    3830             : //     let iteratorRecord = GetIterator(iterable);
    3831             : //     let iterator = iteratorRecord.[[Iterator]];
    3832             : //     let next = iteratorRecord.[[NextMethod]];
    3833             : //     let input = undefined;
    3834             : //     let resumeMode = kNext;
    3835             : //
    3836             : //     while (true) {
    3837             : //       // From the generator to the iterator:
    3838             : //       // Forward input according to resumeMode and obtain output.
    3839             : //       switch (resumeMode) {
    3840             : //         case kNext:
    3841             : //           output = next.[[Call]](iterator, « »);;
    3842             : //           break;
    3843             : //         case kReturn:
    3844             : //           let iteratorReturn = iterator.return;
    3845             : //           if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input;
    3846             : //           output = iteratorReturn.[[Call]](iterator, «input»);
    3847             : //           break;
    3848             : //         case kThrow:
    3849             : //           let iteratorThrow = iterator.throw;
    3850             : //           if (IS_NULL_OR_UNDEFINED(iteratorThrow)) {
    3851             : //             let iteratorReturn = iterator.return;
    3852             : //             if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
    3853             : //               output = iteratorReturn.[[Call]](iterator, « »);
    3854             : //               if (IS_ASYNC_GENERATOR) output = await output;
    3855             : //               if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
    3856             : //             }
    3857             : //             throw MakeTypeError(kThrowMethodMissing);
    3858             : //           }
    3859             : //           output = iteratorThrow.[[Call]](iterator, «input»);
    3860             : //           break;
    3861             : //       }
    3862             : //
    3863             : //       if (IS_ASYNC_GENERATOR) output = await output;
    3864             : //       if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
    3865             : //       if (output.done) break;
    3866             : //
    3867             : //       // From the generator to its user:
    3868             : //       // Forward output, receive new input, and determine resume mode.
    3869             : //       if (IS_ASYNC_GENERATOR) {
    3870             : //         // AsyncGeneratorYield abstract operation awaits the operand before
    3871             : //         // resolving the promise for the current AsyncGeneratorRequest.
    3872             : //         %_AsyncGeneratorYield(output.value)
    3873             : //       }
    3874             : //       input = Suspend(output);
    3875             : //       resumeMode = %GeneratorGetResumeMode();
    3876             : //     }
    3877             : //
    3878             : //     if (resumeMode === kReturn) {
    3879             : //       return output.value;
    3880             : //     }
    3881             : //     output.value
    3882             : //   }
    3883        2020 : void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
    3884         200 :   Register output = register_allocator()->NewRegister();
    3885         200 :   Register resume_mode = register_allocator()->NewRegister();
    3886             :   IteratorType iterator_type = IsAsyncGeneratorFunction(function_kind())
    3887             :                                    ? IteratorType::kAsync
    3888         200 :                                    : IteratorType::kNormal;
    3889             : 
    3890             :   {
    3891             :     RegisterAllocationScope register_scope(this);
    3892         200 :     RegisterList iterator_and_input = register_allocator()->NewRegisterList(2);
    3893         200 :     VisitForAccumulatorValue(expr->expression());
    3894             :     IteratorRecord iterator = BuildGetIteratorRecord(
    3895             :         register_allocator()->NewRegister() /* next method */,
    3896         200 :         iterator_and_input[0], iterator_type);
    3897             : 
    3898         200 :     Register input = iterator_and_input[1];
    3899         200 :     builder()->LoadUndefined().StoreAccumulatorInRegister(input);
    3900             :     builder()
    3901         200 :         ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
    3902         200 :         .StoreAccumulatorInRegister(resume_mode);
    3903             : 
    3904             :     {
    3905             :       // This loop builder does not construct counters as the loop is not
    3906             :       // visible to the user, and we therefore neither pass the block coverage
    3907             :       // builder nor the expression.
    3908             :       //
    3909             :       // In addition to the normal suspend for yield*, a yield* in an async
    3910             :       // generator has 2 additional suspends:
    3911             :       //   - One for awaiting the iterator result of closing the generator when
    3912             :       //     resumed with a "throw" completion, and a throw method is not
    3913             :       //     present on the delegated iterator
    3914             :       //   - One for awaiting the iterator result yielded by the delegated
    3915             :       //     iterator
    3916             : 
    3917         200 :       LoopBuilder loop(builder(), nullptr, nullptr);
    3918         200 :       loop.LoopHeader();
    3919             : 
    3920             :       {
    3921             :         BytecodeLabels after_switch(zone());
    3922             :         BytecodeJumpTable* switch_jump_table =
    3923         200 :             builder()->AllocateJumpTable(2, 1);
    3924             : 
    3925             :         builder()
    3926         200 :             ->LoadAccumulatorWithRegister(resume_mode)
    3927         200 :             .SwitchOnSmiNoFeedback(switch_jump_table);
    3928             : 
    3929             :         // Fallthrough to default case.
    3930             :         // TODO(tebbi): Add debug code to check that {resume_mode} really is
    3931             :         // {JSGeneratorObject::kNext} in this case.
    3932             :         STATIC_ASSERT(JSGeneratorObject::kNext == 0);
    3933             :         {
    3934         200 :           FeedbackSlot slot = feedback_spec()->AddCallICSlot();
    3935             :           builder()->CallProperty(iterator.next(), iterator_and_input,
    3936         200 :                                   feedback_index(slot));
    3937         200 :           builder()->Jump(after_switch.New());
    3938             :         }
    3939             : 
    3940             :         STATIC_ASSERT(JSGeneratorObject::kReturn == 1);
    3941         200 :         builder()->Bind(switch_jump_table, JSGeneratorObject::kReturn);
    3942             :         {
    3943             :           const AstRawString* return_string =
    3944         200 :               ast_string_constants()->return_string();
    3945             :           BytecodeLabels no_return_method(zone());
    3946             : 
    3947             :           BuildCallIteratorMethod(iterator.object(), return_string,
    3948             :                                   iterator_and_input, after_switch.New(),
    3949         200 :                                   &no_return_method);
    3950         200 :           no_return_method.Bind(builder());
    3951         200 :           builder()->LoadAccumulatorWithRegister(input);
    3952         200 :           if (iterator_type == IteratorType::kAsync) {
    3953             :             execution_control()->AsyncReturnAccumulator();
    3954             :           } else {
    3955             :             execution_control()->ReturnAccumulator();
    3956             :           }
    3957             :         }
    3958             : 
    3959             :         STATIC_ASSERT(JSGeneratorObject::kThrow == 2);
    3960         200 :         builder()->Bind(switch_jump_table, JSGeneratorObject::kThrow);
    3961             :         {
    3962             :           const AstRawString* throw_string =
    3963         200 :               ast_string_constants()->throw_string();
    3964             :           BytecodeLabels no_throw_method(zone());
    3965             :           BuildCallIteratorMethod(iterator.object(), throw_string,
    3966             :                                   iterator_and_input, after_switch.New(),
    3967         200 :                                   &no_throw_method);
    3968             : 
    3969             :           // If there is no "throw" method, perform IteratorClose, and finally
    3970             :           // throw a TypeError.
    3971         200 :           no_throw_method.Bind(builder());
    3972         200 :           BuildIteratorClose(iterator, expr);
    3973         200 :           builder()->CallRuntime(Runtime::kThrowThrowMethodMissing);
    3974             :         }
    3975             : 
    3976         200 :         after_switch.Bind(builder());
    3977             :       }
    3978             : 
    3979         200 :       if (iterator_type == IteratorType::kAsync) {
    3980             :         // Await the result of the method invocation.
    3981         210 :         BuildAwait(expr->position());
    3982             :       }
    3983             : 
    3984             :       // Check that output is an object.
    3985             :       BytecodeLabel check_if_done;
    3986             :       builder()
    3987         200 :           ->StoreAccumulatorInRegister(output)
    3988         200 :           .JumpIfJSReceiver(&check_if_done)
    3989         200 :           .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, output);
    3990             : 
    3991         200 :       builder()->Bind(&check_if_done);
    3992             :       // Break once output.done is true.
    3993             :       builder()->LoadNamedProperty(
    3994             :           output, ast_string_constants()->done_string(),
    3995         400 :           feedback_index(feedback_spec()->AddLoadICSlot()));
    3996             : 
    3997             :       loop.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
    3998             : 
    3999             :       // Suspend the current generator.
    4000         200 :       if (iterator_type == IteratorType::kNormal) {
    4001         190 :         builder()->LoadAccumulatorWithRegister(output);
    4002             :       } else {
    4003             :         RegisterAllocationScope register_scope(this);
    4004             :         DCHECK_EQ(iterator_type, IteratorType::kAsync);
    4005             :         // If generatorKind is async, perform AsyncGeneratorYield(output.value),
    4006             :         // which will await `output.value` before resolving the current
    4007             :         // AsyncGeneratorRequest's promise.
    4008             :         builder()->LoadNamedProperty(
    4009             :             output, ast_string_constants()->value_string(),
    4010          20 :             feedback_index(feedback_spec()->AddLoadICSlot()));
    4011             : 
    4012          10 :         RegisterList args = register_allocator()->NewRegisterList(3);
    4013             :         builder()
    4014          10 :             ->MoveRegister(generator_object(), args[0])  // generator
    4015          10 :             .StoreAccumulatorInRegister(args[1])         // value
    4016          20 :             .LoadBoolean(catch_prediction() != HandlerTable::ASYNC_AWAIT)
    4017          10 :             .StoreAccumulatorInRegister(args[2])  // is_caught
    4018          10 :             .CallRuntime(Runtime::kInlineAsyncGeneratorYield, args);
    4019             :       }
    4020             : 
    4021         200 :       BuildSuspendPoint(expr->position());
    4022         200 :       builder()->StoreAccumulatorInRegister(input);
    4023             :       builder()
    4024             :           ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode,
    4025         200 :                         generator_object())
    4026         200 :           .StoreAccumulatorInRegister(resume_mode);
    4027             : 
    4028         200 :       loop.BindContinueTarget();
    4029         200 :       loop.JumpToHeader(loop_depth_);
    4030         200 :     }
    4031             :   }
    4032             : 
    4033             :   // Decide if we trigger a return or if the yield* expression should just
    4034             :   // produce a value.
    4035             :   BytecodeLabel completion_is_output_value;
    4036         200 :   Register output_value = register_allocator()->NewRegister();
    4037             :   builder()
    4038             :       ->LoadNamedProperty(output, ast_string_constants()->value_string(),
    4039         400 :                           feedback_index(feedback_spec()->AddLoadICSlot()))
    4040         200 :       .StoreAccumulatorInRegister(output_value)
    4041         200 :       .LoadLiteral(Smi::FromInt(JSGeneratorObject::kReturn))
    4042         200 :       .CompareReference(resume_mode)
    4043         200 :       .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &completion_is_output_value)
    4044         200 :       .LoadAccumulatorWithRegister(output_value);
    4045         200 :   if (iterator_type == IteratorType::kAsync) {
    4046             :     execution_control()->AsyncReturnAccumulator();
    4047             :   } else {
    4048             :     execution_control()->ReturnAccumulator();
    4049             :   }
    4050             : 
    4051         200 :   builder()->Bind(&completion_is_output_value);
    4052             :   BuildIncrementBlockCoverageCounterIfEnabled(expr,
    4053             :                                               SourceRangeKind::kContinuation);
    4054         200 :   builder()->LoadAccumulatorWithRegister(output_value);
    4055         200 : }
    4056             : 
    4057       30298 : void BytecodeGenerator::BuildAwait(int position) {
    4058             :   // Rather than HandlerTable::UNCAUGHT, async functions use
    4059             :   // HandlerTable::ASYNC_AWAIT to communicate that top-level exceptions are
    4060             :   // transformed into promise rejections. This is necessary to prevent emitting
    4061             :   // multiple debug events for the same uncaught exception. There is no point
    4062             :   // in the body of an async function where catch prediction is
    4063             :   // HandlerTable::UNCAUGHT.
    4064             :   DCHECK(catch_prediction() != HandlerTable::UNCAUGHT);
    4065             : 
    4066             :   {
    4067             :     // Await(operand) and suspend.
    4068             :     RegisterAllocationScope register_scope(this);
    4069             : 
    4070             :     Runtime::FunctionId await_intrinsic_id;
    4071       15149 :     if (IsAsyncGeneratorFunction(function_kind())) {
    4072             :       await_intrinsic_id = catch_prediction() == HandlerTable::ASYNC_AWAIT
    4073             :                                ? Runtime::kInlineAsyncGeneratorAwaitUncaught
    4074        1308 :                                : Runtime::kInlineAsyncGeneratorAwaitCaught;
    4075             :     } else {
    4076             :       await_intrinsic_id = catch_prediction() == HandlerTable::ASYNC_AWAIT
    4077             :                                ? Runtime::kInlineAsyncFunctionAwaitUncaught
    4078       13841 :                                : Runtime::kInlineAsyncFunctionAwaitCaught;
    4079             :     }
    4080       15149 :     RegisterList args = register_allocator()->NewRegisterList(2);
    4081             :     builder()
    4082       15149 :         ->MoveRegister(generator_object(), args[0])
    4083       15149 :         .StoreAccumulatorInRegister(args[1])
    4084       15149 :         .CallRuntime(await_intrinsic_id, args);
    4085             :   }
    4086             : 
    4087       15149 :   BuildSuspendPoint(position);
    4088             : 
    4089       15148 :   Register input = register_allocator()->NewRegister();
    4090       15149 :   Register resume_mode = register_allocator()->NewRegister();
    4091             : 
    4092             :   // Now dispatch on resume mode.
    4093             :   BytecodeLabel resume_next;
    4094             :   builder()
    4095       15149 :       ->StoreAccumulatorInRegister(input)
    4096       15148 :       .CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator_object())
    4097       15148 :       .StoreAccumulatorInRegister(resume_mode)
    4098       15148 :       .LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
    4099       15148 :       .CompareReference(resume_mode)
    4100       15148 :       .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &resume_next);
    4101             : 
    4102             :   // Resume with "throw" completion (rethrow the received value).
    4103             :   // TODO(leszeks): Add a debug-only check that the accumulator is
    4104             :   // JSGeneratorObject::kThrow.
    4105       15148 :   builder()->LoadAccumulatorWithRegister(input).ReThrow();
    4106             : 
    4107             :   // Resume with next.
    4108       15148 :   builder()->Bind(&resume_next);
    4109       15149 :   builder()->LoadAccumulatorWithRegister(input);
    4110       15149 : }
    4111             : 
    4112       14455 : void BytecodeGenerator::VisitAwait(Await* expr) {
    4113             :   builder()->SetExpressionPosition(expr);
    4114       14455 :   VisitForAccumulatorValue(expr->expression());
    4115       14455 :   BuildAwait(expr->position());
    4116             :   BuildIncrementBlockCoverageCounterIfEnabled(expr,
    4117             :                                               SourceRangeKind::kContinuation);
    4118       14455 : }
    4119             : 
    4120       38720 : void BytecodeGenerator::VisitThrow(Throw* expr) {
    4121             :   AllocateBlockCoverageSlotIfEnabled(expr, SourceRangeKind::kContinuation);
    4122       19360 :   VisitForAccumulatorValue(expr->exception());
    4123             :   builder()->SetExpressionPosition(expr);
    4124       19363 :   builder()->Throw();
    4125       19365 : }
    4126             : 
    4127     7377985 : void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) {
    4128     2504987 :   AssignType property_kind = Property::GetAssignType(property);
    4129     2505128 :   switch (property_kind) {
    4130             :     case NON_PROPERTY:
    4131           0 :       UNREACHABLE();
    4132             :     case NAMED_PROPERTY: {
    4133             :       builder()->SetExpressionPosition(property);
    4134             :       const AstRawString* name =
    4135     4737343 :           property->key()->AsLiteral()->AsRawPropertyName();
    4136     2368628 :       BuildLoadNamedProperty(property->obj(), obj, name);
    4137     2368754 :       break;
    4138             :     }
    4139             :     case KEYED_PROPERTY: {
    4140      135655 :       VisitForAccumulatorValue(property->key());
    4141             :       builder()->SetExpressionPosition(property);
    4142             :       builder()->LoadKeyedProperty(
    4143      271313 :           obj, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
    4144      135654 :       break;
    4145             :     }
    4146             :     case NAMED_SUPER_PROPERTY:
    4147         417 :       VisitNamedSuperPropertyLoad(property, Register::invalid_value());
    4148         417 :       break;
    4149             :     case KEYED_SUPER_PROPERTY:
    4150         360 :       VisitKeyedSuperPropertyLoad(property, Register::invalid_value());
    4151         360 :       break;
    4152             :   }
    4153     2505166 : }
    4154             : 
    4155      805388 : void BytecodeGenerator::VisitPropertyLoadForRegister(Register obj,
    4156             :                                                      Property* expr,
    4157             :                                                      Register destination) {
    4158             :   ValueResultScope result_scope(this);
    4159      805388 :   VisitPropertyLoad(obj, expr);
    4160      805446 :   builder()->StoreAccumulatorInRegister(destination);
    4161      805445 : }
    4162             : 
    4163        2658 : void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
    4164             :                                                     Register opt_receiver_out) {
    4165             :   RegisterAllocationScope register_scope(this);
    4166        1772 :   SuperPropertyReference* super_property =
    4167         886 :       property->obj()->AsSuperPropertyReference();
    4168         886 :   RegisterList args = register_allocator()->NewRegisterList(3);
    4169             :   VisitForRegisterValue(super_property->this_var(), args[0]);
    4170             :   VisitForRegisterValue(super_property->home_object(), args[1]);
    4171             : 
    4172             :   builder()->SetExpressionPosition(property);
    4173             :   builder()
    4174        1772 :       ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
    4175         886 :       .StoreAccumulatorInRegister(args[2])
    4176         886 :       .CallRuntime(Runtime::kLoadFromSuper, args);
    4177             : 
    4178         886 :   if (opt_receiver_out.is_valid()) {
    4179         469 :     builder()->MoveRegister(args[0], opt_receiver_out);
    4180         886 :   }
    4181         886 : }
    4182             : 
    4183        1200 : void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property,
    4184             :                                                     Register opt_receiver_out) {
    4185             :   RegisterAllocationScope register_scope(this);
    4186         800 :   SuperPropertyReference* super_property =
    4187         400 :       property->obj()->AsSuperPropertyReference();
    4188         400 :   RegisterList args = register_allocator()->NewRegisterList(3);
    4189             :   VisitForRegisterValue(super_property->this_var(), args[0]);
    4190             :   VisitForRegisterValue(super_property->home_object(), args[1]);
    4191             :   VisitForRegisterValue(property->key(), args[2]);
    4192             : 
    4193             :   builder()->SetExpressionPosition(property);
    4194         400 :   builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, args);
    4195             : 
    4196         400 :   if (opt_receiver_out.is_valid()) {
    4197          40 :     builder()->MoveRegister(args[0], opt_receiver_out);
    4198         400 :   }
    4199         400 : }
    4200             : 
    4201     3398440 : void BytecodeGenerator::VisitProperty(Property* expr) {
    4202     1699574 :   AssignType property_kind = Property::GetAssignType(expr);
    4203     1699643 :   if (property_kind != NAMED_SUPER_PROPERTY &&
    4204             :       property_kind != KEYED_SUPER_PROPERTY) {
    4205     1698866 :     Register obj = VisitForRegisterValue(expr->obj());
    4206     1699013 :     VisitPropertyLoad(obj, expr);
    4207             :   } else {
    4208         777 :     VisitPropertyLoad(Register::invalid_value(), expr);
    4209             :   }
    4210     1699765 : }
    4211             : 
    4212           0 : void BytecodeGenerator::VisitResolvedProperty(ResolvedProperty* expr) {
    4213             :   // Handled by VisitCall().
    4214           0 :   UNREACHABLE();
    4215             : }
    4216             : 
    4217    16908009 : void BytecodeGenerator::VisitArguments(const ZonePtrList<Expression>* args,
    4218             :                                        RegisterList* arg_regs) {
    4219             :   // Visit arguments.
    4220    23083120 :   for (int i = 0; i < static_cast<int>(args->length()); i++) {
    4221     6175065 :     VisitAndPushIntoRegisterList(args->at(i), arg_regs);
    4222             :   }
    4223     5366495 : }
    4224             : 
    4225    10436281 : void BytecodeGenerator::VisitCall(Call* expr) {
    4226             :   Expression* callee_expr = expr->expression();
    4227     5167262 :   Call::CallType call_type = expr->GetCallType();
    4228             : 
    4229     5167271 :   if (call_type == Call::SUPER_CALL) {
    4230     5172596 :     return VisitCallSuper(expr);
    4231             :   }
    4232             : 
    4233             :   // Grow the args list as we visit receiver / arguments to avoid allocating all
    4234             :   // the registers up-front. Otherwise these registers are unavailable during
    4235             :   // receiver / argument visiting and we can end up with memory leaks due to
    4236             :   // registers keeping objects alive.
    4237     5161982 :   Register callee = register_allocator()->NewRegister();
    4238     5161917 :   RegisterList args = register_allocator()->NewGrowableRegisterList();
    4239             : 
    4240             :   bool implicit_undefined_receiver = false;
    4241             :   // When a call contains a spread, a Call AST node is only created if there is
    4242             :   // exactly one spread, and it is the last argument.
    4243     5161917 :   bool is_spread_call = expr->only_last_arg_is_spread();
    4244     5161923 :   bool optimize_as_one_shot = ShouldOptimizeAsOneShot();
    4245             : 
    4246             :   // TODO(petermarshall): We have a lot of call bytecodes that are very similar,
    4247             :   // see if we can reduce the number by adding a separate argument which
    4248             :   // specifies the call type (e.g., property, spread, tailcall, etc.).
    4249             : 
    4250             :   // Prepare the callee and the receiver to the function call. This depends on
    4251             :   // the semantics of the underlying call type.
    4252     5162012 :   switch (call_type) {
    4253             :     case Call::NAMED_PROPERTY_CALL:
    4254             :     case Call::KEYED_PROPERTY_CALL: {
    4255     1610759 :       Property* property = callee_expr->AsProperty();
    4256      805371 :       VisitAndPushIntoRegisterList(property->obj(), &args);
    4257      805431 :       VisitPropertyLoadForRegister(args.last_register(), property, callee);
    4258      805408 :       break;
    4259             :     }
    4260             :     case Call::RESOLVED_PROPERTY_CALL: {
    4261           0 :       ResolvedProperty* resolved = callee_expr->AsResolvedProperty();
    4262           0 :       VisitAndPushIntoRegisterList(resolved->object(), &args);
    4263           0 :       VisitForAccumulatorValue(resolved->property());
    4264           0 :       builder()->StoreAccumulatorInRegister(callee);
    4265           0 :       break;
    4266             :     }
    4267             :     case Call::GLOBAL_CALL: {
    4268             :       // Receiver is undefined for global calls.
    4269     3829291 :       if (!is_spread_call && !optimize_as_one_shot) {
    4270             :         implicit_undefined_receiver = true;
    4271             :       } else {
    4272             :         // TODO(leszeks): There's no special bytecode for tail calls or spread
    4273             :         // calls with an undefined receiver, so just push undefined ourselves.
    4274      715480 :         BuildPushUndefinedIntoRegisterList(&args);
    4275             :       }
    4276             :       // Load callee as a global variable.
    4277    11488078 :       VariableProxy* proxy = callee_expr->AsVariableProxy();
    4278             :       BuildVariableLoadForAccumulatorValue(proxy->var(),
    4279     3829328 :                                            proxy->hole_check_mode());
    4280     3829206 :       builder()->StoreAccumulatorInRegister(callee);
    4281     3829306 :       break;
    4282             :     }
    4283             :     case Call::WITH_CALL: {
    4284        4587 :       Register receiver = register_allocator()->GrowRegisterList(&args);
    4285             :       DCHECK(callee_expr->AsVariableProxy()->var()->IsLookupSlot());
    4286             :       {
    4287             :         RegisterAllocationScope inner_register_scope(this);
    4288        4587 :         Register name = register_allocator()->NewRegister();
    4289             : 
    4290             :         // Call %LoadLookupSlotForCall to get the callee and receiver.
    4291        4587 :         RegisterList result_pair = register_allocator()->NewRegisterList(2);
    4292       13761 :         Variable* variable = callee_expr->AsVariableProxy()->var();
    4293             :         builder()
    4294        4587 :             ->LoadLiteral(variable->raw_name())
    4295        4587 :             .StoreAccumulatorInRegister(name)
    4296             :             .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name,
    4297        4587 :                                 result_pair)
    4298        4587 :             .MoveRegister(result_pair[0], callee)
    4299        4587 :             .MoveRegister(result_pair[1], receiver);
    4300             :       }
    4301             :       break;
    4302             :     }
    4303             :     case Call::OTHER_CALL: {
    4304             :       // Receiver is undefined for other calls.
    4305      522355 :       if (!is_spread_call && !optimize_as_one_shot) {
    4306             :         implicit_undefined_receiver = true;
    4307             :       } else {
    4308             :         // TODO(leszeks): There's no special bytecode for tail calls or spread
    4309             :         // calls with an undefined receiver, so just push undefined ourselves.
    4310      224825 :         BuildPushUndefinedIntoRegisterList(&args);
    4311             :       }
    4312             :       VisitForRegisterValue(callee_expr, callee);
    4313             :       break;
    4314             :     }
    4315             :     case Call::NAMED_SUPER_PROPERTY_CALL: {
    4316         469 :       Register receiver = register_allocator()->GrowRegisterList(&args);
    4317         469 :       Property* property = callee_expr->AsProperty();
    4318         469 :       VisitNamedSuperPropertyLoad(property, receiver);
    4319         469 :       builder()->StoreAccumulatorInRegister(callee);
    4320             :       break;
    4321             :     }
    4322             :     case Call::KEYED_SUPER_PROPERTY_CALL: {
    4323          40 :       Register receiver = register_allocator()->GrowRegisterList(&args);
    4324          40 :       Property* property = callee_expr->AsProperty();
    4325          40 :       VisitKeyedSuperPropertyLoad(property, receiver);
    4326          40 :       builder()->StoreAccumulatorInRegister(callee);
    4327             :       break;
    4328             :     }
    4329             :     case Call::SUPER_CALL:
    4330           0 :       UNREACHABLE();
    4331             :       break;
    4332             :   }
    4333             : 
    4334             :   // Evaluate all arguments to the function call and store in sequential args
    4335             :   // registers.
    4336     5162166 :   VisitArguments(expr->arguments(), &args);
    4337     5161980 :   int reciever_arg_count = implicit_undefined_receiver ? 0 : 1;
    4338     5161980 :   CHECK_EQ(reciever_arg_count + expr->arguments()->length(),
    4339             :            args.register_count());
    4340             : 
    4341             :   // Resolve callee for a potential direct eval call. This block will mutate the
    4342             :   // callee value.
    4343     5161980 :   if (expr->is_possibly_eval() && expr->arguments()->length() > 0) {
    4344             :     RegisterAllocationScope inner_register_scope(this);
    4345             :     // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
    4346             :     // strings and function closure, and loading language and
    4347             :     // position.
    4348      214076 :     Register first_arg = args[reciever_arg_count];
    4349      107038 :     RegisterList runtime_call_args = register_allocator()->NewRegisterList(6);
    4350             :     builder()
    4351      107040 :         ->MoveRegister(callee, runtime_call_args[0])
    4352      107040 :         .MoveRegister(first_arg, runtime_call_args[1])
    4353      214079 :         .MoveRegister(Register::function_closure(), runtime_call_args[2])
    4354      107040 :         .LoadLiteral(Smi::FromEnum(language_mode()))
    4355      107039 :         .StoreAccumulatorInRegister(runtime_call_args[3])
    4356      214078 :         .LoadLiteral(Smi::FromInt(current_scope()->start_position()))
    4357      107038 :         .StoreAccumulatorInRegister(runtime_call_args[4])
    4358      214077 :         .LoadLiteral(Smi::FromInt(expr->position()))
    4359      107037 :         .StoreAccumulatorInRegister(runtime_call_args[5]);
    4360             : 
    4361             :     // Call ResolvePossiblyDirectEval and modify the callee.
    4362             :     builder()
    4363      107038 :         ->CallRuntime(Runtime::kResolvePossiblyDirectEval, runtime_call_args)
    4364      107039 :         .StoreAccumulatorInRegister(callee);
    4365             :   }
    4366             : 
    4367             :   builder()->SetExpressionPosition(expr);
    4368             : 
    4369     5161981 :   if (is_spread_call) {
    4370             :     DCHECK(!implicit_undefined_receiver);
    4371             :     builder()->CallWithSpread(callee, args,
    4372        3620 :                               feedback_index(feedback_spec()->AddCallICSlot()));
    4373     5160171 :   } else if (optimize_as_one_shot) {
    4374             :     DCHECK(!implicit_undefined_receiver);
    4375     1247187 :     builder()->CallNoFeedback(callee, args);
    4376     7825968 :   } else if (call_type == Call::NAMED_PROPERTY_CALL ||
    4377     3912984 :              call_type == Call::KEYED_PROPERTY_CALL ||
    4378     3912984 :              call_type == Call::RESOLVED_PROPERTY_CALL) {
    4379             :     DCHECK(!implicit_undefined_receiver);
    4380             :     builder()->CallProperty(callee, args,
    4381      996811 :                             feedback_index(feedback_spec()->AddCallICSlot()));
    4382     3414581 :   } else if (implicit_undefined_receiver) {
    4383             :     builder()->CallUndefinedReceiver(
    4384     6822470 :         callee, args, feedback_index(feedback_spec()->AddCallICSlot()));
    4385             :   } else {
    4386             :     builder()->CallAnyReceiver(
    4387        6706 :         callee, args, feedback_index(feedback_spec()->AddCallICSlot()));
    4388             :   }
    4389             : }
    4390             : 
    4391       21157 : void BytecodeGenerator::VisitCallSuper(Call* expr) {
    4392             :   RegisterAllocationScope register_scope(this);
    4393       18399 :   SuperCallReference* super = expr->expression()->AsSuperCallReference();
    4394       11189 :   const ZonePtrList<Expression>* args = expr->arguments();
    4395             : 
    4396             :   int first_spread_index = 0;
    4397       11800 :   for (; first_spread_index < args->length(); first_spread_index++) {
    4398        9148 :     if (args->at(first_spread_index)->IsSpread()) break;
    4399             :   }
    4400             : 
    4401             :   // Prepare the constructor to the super call.
    4402        5289 :   Register this_function = VisitForRegisterValue(super->this_function_var());
    4403        5290 :   Register constructor = register_allocator()->NewRegister();
    4404             :   builder()
    4405        5290 :       ->LoadAccumulatorWithRegister(this_function)
    4406        5290 :       .GetSuperConstructor(constructor);
    4407             : 
    4408        5290 :   if (first_spread_index < expr->arguments()->length() - 1) {
    4409             :     // We rewrite something like
    4410             :     //    super(1, ...x, 2)
    4411             :     // to
    4412             :     //    %reflect_construct(constructor, [1, ...x, 2], new_target)
    4413             :     // That is, we implement (non-last-arg) spreads in super calls via our
    4414             :     // mechanism for spreads in array literals.
    4415             : 
    4416             :     // First generate the array containing all arguments.
    4417          30 :     BuildCreateArrayLiteral(args, nullptr);
    4418             : 
    4419             :     // Now pass that array to %reflect_construct.
    4420          30 :     RegisterList construct_args = register_allocator()->NewRegisterList(3);
    4421          30 :     builder()->StoreAccumulatorInRegister(construct_args[1]);
    4422          30 :     builder()->MoveRegister(constructor, construct_args[0]);
    4423             :     VisitForRegisterValue(super->new_target_var(), construct_args[2]);
    4424          30 :     builder()->CallJSRuntime(Context::REFLECT_CONSTRUCT_INDEX, construct_args);
    4425             :   } else {
    4426        5260 :     RegisterList args_regs = register_allocator()->NewGrowableRegisterList();
    4427        5260 :     VisitArguments(args, &args_regs);
    4428             :     // The new target is loaded into the accumulator from the
    4429             :     // {new.target} variable.
    4430        5260 :     VisitForAccumulatorValue(super->new_target_var());
    4431             :     builder()->SetExpressionPosition(expr);
    4432             : 
    4433        5260 :     int feedback_slot_index = feedback_index(feedback_spec()->AddCallICSlot());
    4434             : 
    4435        5260 :     if (first_spread_index == expr->arguments()->length() - 1) {
    4436             :       builder()->ConstructWithSpread(constructor, args_regs,
    4437        3934 :                                      feedback_slot_index);
    4438             :     } else {
    4439             :       DCHECK_EQ(first_spread_index, expr->arguments()->length());
    4440             :       // Call construct.
    4441             :       // TODO(turbofan): For now we do gather feedback on super constructor
    4442             :       // calls, utilizing the existing machinery to inline the actual call
    4443             :       // target and the JSCreate for the implicit receiver allocation. This
    4444             :       // is not an ideal solution for super constructor calls, but it gets
    4445             :       // the job done for now. In the long run we might want to revisit this
    4446             :       // and come up with a better way.
    4447        1326 :       builder()->Construct(constructor, args_regs, feedback_slot_index);
    4448             :     }
    4449             :   }
    4450             : 
    4451             :   // Explicit calls to the super constructor using super() perform an
    4452             :   // implicit binding assignment to the 'this' variable.
    4453             :   //
    4454             :   // Default constructors don't need have to do the assignment because
    4455             :   // 'this' isn't accessed in default constructors.
    4456       10578 :   if (!IsDefaultConstructor(info()->literal()->kind())) {
    4457             :     BuildVariableAssignment(super->this_var()->var(), Token::INIT,
    4458        2531 :                             HoleCheckMode::kRequired);
    4459             :   }
    4460             : 
    4461             :   // The derived constructor has the correct bit set always, so we
    4462             :   // don't emit code to load and call the initializer if not
    4463             :   // required.
    4464             :   //
    4465             :   // For the arrow function or eval case, we always emit code to load
    4466             :   // and call the initializer.
    4467             :   //
    4468             :   // TODO(gsathya): In the future, we could tag nested arrow functions
    4469             :   // or eval with the correct bit so that we do the load conditionally
    4470             :   // if required.
    4471       15680 :   if (info()->literal()->requires_instance_members_initializer() ||
    4472        5100 :       !IsDerivedConstructor(info()->literal()->kind())) {
    4473         321 :     Register instance = register_allocator()->NewRegister();
    4474         321 :     builder()->StoreAccumulatorInRegister(instance);
    4475         321 :     BuildInstanceMemberInitialization(this_function, instance);
    4476         321 :     builder()->LoadAccumulatorWithRegister(instance);
    4477        5290 :   }
    4478        5290 : }
    4479             : 
    4480      142230 : void BytecodeGenerator::VisitCallNew(CallNew* expr) {
    4481      142230 :   Register constructor = VisitForRegisterValue(expr->expression());
    4482      142291 :   RegisterList args = register_allocator()->NewGrowableRegisterList();
    4483      142291 :   VisitArguments(expr->arguments(), &args);
    4484             : 
    4485             :   // The accumulator holds new target which is the same as the
    4486             :   // constructor for CallNew.
    4487             :   builder()->SetExpressionPosition(expr);
    4488      142264 :   builder()->LoadAccumulatorWithRegister(constructor);
    4489             : 
    4490      142283 :   int feedback_slot_index = feedback_index(feedback_spec()->AddCallICSlot());
    4491      142286 :   if (expr->only_last_arg_is_spread()) {
    4492         169 :     builder()->ConstructWithSpread(constructor, args, feedback_slot_index);
    4493             :   } else {
    4494      142063 :     builder()->Construct(constructor, args, feedback_slot_index);
    4495             :   }
    4496      142283 : }
    4497             : 
    4498      113819 : void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
    4499       56912 :   if (expr->is_jsruntime()) {
    4500         383 :     RegisterList args = register_allocator()->NewGrowableRegisterList();
    4501         383 :     VisitArguments(expr->arguments(), &args);
    4502         383 :     builder()->CallJSRuntime(expr->context_index(), args);
    4503             :   } else {
    4504             :     // Evaluate all arguments to the runtime call.
    4505       56529 :     RegisterList args = register_allocator()->NewGrowableRegisterList();
    4506       56529 :     VisitArguments(expr->arguments(), &args);
    4507       56524 :     Runtime::FunctionId function_id = expr->function()->function_id;
    4508       56524 :     builder()->CallRuntime(function_id, args);
    4509             :   }
    4510       56951 : }
    4511             : 
    4512        3310 : void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
    4513        3310 :   VisitForEffect(expr->expression());
    4514        3310 :   builder()->LoadUndefined();
    4515           0 : }
    4516             : 
    4517      144216 : void BytecodeGenerator::VisitForTypeOfValue(Expression* expr) {
    4518      144217 :   if (expr->IsVariableProxy()) {
    4519             :     // Typeof does not throw a reference error on global variables, hence we
    4520             :     // perform a non-contextual load in case the operand is a variable proxy.
    4521      415707 :     VariableProxy* proxy = expr->AsVariableProxy();
    4522             :     BuildVariableLoadForAccumulatorValue(proxy->var(), proxy->hole_check_mode(),
    4523      138569 :                                          INSIDE_TYPEOF);
    4524             :   } else {
    4525        5648 :     VisitForAccumulatorValue(expr);
    4526             :   }
    4527      144218 : }
    4528             : 
    4529       51626 : void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
    4530       51626 :   VisitForTypeOfValue(expr->expression());
    4531       51628 :   builder()->TypeOf();
    4532           0 : }
    4533             : 
    4534      491193 : void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
    4535      233026 :   if (execution_result()->IsEffect()) {
    4536         165 :     VisitForEffect(expr->expression());
    4537      232861 :   } else if (execution_result()->IsTest()) {
    4538             :     // No actual logical negation happening, we just swap the control flow, by
    4539             :     // swapping the target labels and the fallthrough branch, and visit in the
    4540             :     // same test result context.
    4541             :     TestResultScope* test_result = execution_result()->AsTest();
    4542             :     test_result->InvertControlFlow();
    4543      207721 :     VisitInSameTestExecutionScope(expr->expression());
    4544             :   } else {
    4545       25140 :     TypeHint type_hint = VisitForAccumulatorValue(expr->expression());
    4546       25141 :     builder()->LogicalNot(ToBooleanModeFromTypeHint(type_hint));
    4547             :     // Always returns a boolean value.
    4548             :     execution_result()->SetResultIsBoolean();
    4549             :   }
    4550      233035 : }
    4551             : 
    4552      481566 : void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
    4553      356431 :   switch (expr->op()) {
    4554             :     case Token::Value::NOT:
    4555      233026 :       VisitNot(expr);
    4556      233033 :       break;
    4557             :     case Token::Value::TYPEOF:
    4558             :       VisitTypeOf(expr);
    4559             :       break;
    4560             :     case Token::Value::VOID:
    4561             :       VisitVoid(expr);
    4562             :       break;
    4563             :     case Token::Value::DELETE:
    4564        5903 :       VisitDelete(expr);
    4565        5903 :       break;
    4566             :     case Token::Value::ADD:
    4567             :     case Token::Value::SUB:
    4568             :     case Token::Value::BIT_NOT:
    4569       62566 :       VisitForAccumulatorValue(expr->expression());
    4570             :       builder()->SetExpressionPosition(expr);
    4571             :       builder()->UnaryOperation(
    4572      125138 :           expr->op(), feedback_index(feedback_spec()->AddBinaryOpICSlot()));
    4573       62569 :       break;
    4574             :     default:
    4575           0 :       UNREACHABLE();
    4576             :   }
    4577      356444 : }
    4578             : 
    4579        5903 : void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
    4580        5903 :   if (expr->expression()->IsProperty()) {
    4581             :     // Delete of an object property is allowed both in sloppy
    4582             :     // and strict modes.
    4583       13095 :     Property* property = expr->expression()->AsProperty();
    4584        4364 :     Register object = VisitForRegisterValue(property->obj());
    4585        4367 :     VisitForAccumulatorValue(property->key());
    4586        4367 :     builder()->Delete(object, language_mode());
    4587        1539 :   } else if (expr->expression()->IsVariableProxy()) {
    4588             :     // Delete of an unqualified identifier is allowed in sloppy mode but is
    4589             :     // not allowed in strict mode. Deleting 'this' and 'new.target' is allowed
    4590             :     // in both modes.
    4591        2569 :     VariableProxy* proxy = expr->expression()->AsVariableProxy();
    4592             :     DCHECK(is_sloppy(language_mode()) || proxy->is_this() ||
    4593             :            proxy->is_new_target());
    4594        1698 :     if (proxy->is_this() || proxy->is_new_target()) {
    4595          80 :       builder()->LoadTrue();
    4596             :     } else {
    4597        1437 :       Variable* variable = proxy->var();
    4598         803 :       switch (variable->location()) {
    4599             :         case VariableLocation::PARAMETER:
    4600             :         case VariableLocation::LOCAL:
    4601             :         case VariableLocation::CONTEXT: {
    4602             :           // Deleting local var/let/const, context variables, and arguments
    4603             :           // does not have any effect.
    4604         169 :           builder()->LoadFalse();
    4605         169 :           break;
    4606             :         }
    4607             :         case VariableLocation::UNALLOCATED:
    4608             :         // TODO(adamk): Falling through to the runtime results in correct
    4609             :         // behavior, but does unnecessary context-walking (since scope
    4610             :         // analysis has already proven that the variable doesn't exist in
    4611             :         // any non-global scope). Consider adding a DeleteGlobal bytecode
    4612             :         // that knows how to deal with ScriptContexts as well as global
    4613             :         // object properties.
    4614             :         case VariableLocation::LOOKUP: {
    4615         634 :           Register name_reg = register_allocator()->NewRegister();
    4616             :           builder()
    4617         634 :               ->LoadLiteral(variable->raw_name())
    4618         635 :               .StoreAccumulatorInRegister(name_reg)
    4619         635 :               .CallRuntime(Runtime::kDeleteLookupSlot, name_reg);
    4620             :           break;
    4621             :         }
    4622             :         default:
    4623           0 :           UNREACHABLE();
    4624             :       }
    4625             :     }
    4626             :   } else {
    4627             :     // Delete of an unresolvable reference returns true.
    4628         656 :     VisitForEffect(expr->expression());
    4629         656 :     builder()->LoadTrue();
    4630             :   }
    4631        5905 : }
    4632             : 
    4633     1381369 : void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
    4634             :   DCHECK(expr->expression()->IsValidReferenceExpression());
    4635             : 
    4636             :   // Left-hand side can only be a property, a global or a variable slot.
    4637      266055 :   Property* property = expr->expression()->AsProperty();
    4638      240939 :   AssignType assign_type = Property::GetAssignType(property);
    4639             : 
    4640      425666 :   bool is_postfix = expr->is_postfix() && !execution_result()->IsEffect();
    4641             : 
    4642             :   // Evaluate LHS expression and get old value.
    4643             :   Register object, key, old_value;
    4644             :   RegisterList super_property_args;
    4645             :   const AstRawString* name;
    4646      240954 :   switch (assign_type) {
    4647             :     case NON_PROPERTY: {
    4648      699736 :       VariableProxy* proxy = expr->expression()->AsVariableProxy();
    4649             :       BuildVariableLoadForAccumulatorValue(proxy->var(),
    4650      233254 :                                            proxy->hole_check_mode());
    4651      233275 :       break;
    4652             :     }
    4653             :     case NAMED_PROPERTY: {
    4654        4871 :       object = VisitForRegisterValue(property->obj());
    4655        9744 :       name = property->key()->AsLiteral()->AsRawPropertyName();
    4656             :       builder()->LoadNamedProperty(
    4657             :           object, name,
    4658        4872 :           feedback_index(GetCachedLoadICSlot(property->obj(), name)));
    4659        4872 :       break;
    4660             :     }
    4661             :     case KEYED_PROPERTY: {
    4662        2691 :       object = VisitForRegisterValue(property->obj());
    4663             :       // Use visit for accumulator here since we need the key in the accumulator
    4664             :       // for the LoadKeyedProperty.
    4665        2691 :       key = register_allocator()->NewRegister();
    4666        2691 :       VisitForAccumulatorValue(property->key());
    4667        2692 :       builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty(
    4668        5383 :           object, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
    4669        2692 :       break;
    4670             :     }
    4671             :     case NAMED_SUPER_PROPERTY: {
    4672          45 :       super_property_args = register_allocator()->NewRegisterList(4);
    4673          45 :       RegisterList load_super_args = super_property_args.Truncate(3);
    4674          90 :       SuperPropertyReference* super_property =
    4675          45 :           property->obj()->AsSuperPropertyReference();
    4676             :       VisitForRegisterValue(super_property->this_var(), load_super_args[0]);
    4677             :       VisitForRegisterValue(super_property->home_object(), load_super_args[1]);
    4678             :       builder()
    4679          90 :           ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
    4680          45 :           .StoreAccumulatorInRegister(load_super_args[2])
    4681          45 :           .CallRuntime(Runtime::kLoadFromSuper, load_super_args);
    4682             :       break;
    4683             :     }
    4684             :     case KEYED_SUPER_PROPERTY: {
    4685          90 :       super_property_args = register_allocator()->NewRegisterList(4);
    4686          90 :       RegisterList load_super_args = super_property_args.Truncate(3);
    4687         180 :       SuperPropertyReference* super_property =
    4688          90 :           property->obj()->AsSuperPropertyReference();
    4689             :       VisitForRegisterValue(super_property->this_var(), 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      241003 :   FeedbackSlot count_slot = feedback_spec()->AddBinaryOpICSlot();
    4699      240919 :   if (is_postfix) {
    4700       26919 :     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       26919 :         ->ToNumeric(feedback_index(count_slot))
    4706       26920 :         .StoreAccumulatorInRegister(old_value);
    4707             :   }
    4708             : 
    4709             :   // Perform +1/-1 operation.
    4710      240920 :   builder()->UnaryOperation(expr->op(), feedback_index(count_slot));
    4711             : 
    4712             :   // Store the value.
    4713             :   builder()->SetExpressionPosition(expr);
    4714      240949 :   switch (assign_type) {
    4715             :     case NON_PROPERTY: {
    4716      699699 :       VariableProxy* proxy = expr->expression()->AsVariableProxy();
    4717             :       BuildVariableAssignment(proxy->var(), expr->op(),
    4718      466466 :                               proxy->hole_check_mode());
    4719      233278 :       break;
    4720             :     }
    4721             :     case NAMED_PROPERTY: {
    4722        4872 :       FeedbackSlot slot = GetCachedStoreICSlot(property->obj(), name);
    4723             :       Register value;
    4724        4872 :       if (!execution_result()->IsEffect()) {
    4725        4465 :         value = register_allocator()->NewRegister();
    4726        4465 :         builder()->StoreAccumulatorInRegister(value);
    4727             :       }
    4728             :       builder()->StoreNamedProperty(object, name, feedback_index(slot),
    4729        4872 :                                     language_mode());
    4730        4872 :       if (!execution_result()->IsEffect()) {
    4731        4466 :         builder()->LoadAccumulatorWithRegister(value);
    4732             :       }
    4733             :       break;
    4734             :     }
    4735             :     case KEYED_PROPERTY: {
    4736        2691 :       FeedbackSlot slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
    4737             :       Register value;
    4738        2691 :       if (!execution_result()->IsEffect()) {
    4739         481 :         value = register_allocator()->NewRegister();
    4740         481 :         builder()->StoreAccumulatorInRegister(value);
    4741             :       }
    4742             :       builder()->StoreKeyedProperty(object, key, feedback_index(slot),
    4743        2691 :                                     language_mode());
    4744        2692 :       if (!execution_result()->IsEffect()) {
    4745         481 :         builder()->LoadAccumulatorWithRegister(value);
    4746             :       }
    4747             :       break;
    4748             :     }
    4749             :     case NAMED_SUPER_PROPERTY: {
    4750             :       builder()
    4751          45 :           ->StoreAccumulatorInRegister(super_property_args[3])
    4752          45 :           .CallRuntime(StoreToSuperRuntimeId(), super_property_args);
    4753          45 :       break;
    4754             :     }
    4755             :     case KEYED_SUPER_PROPERTY: {
    4756             :       builder()
    4757          90 :           ->StoreAccumulatorInRegister(super_property_args[3])
    4758          90 :           .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args);
    4759          90 :       break;
    4760             :     }
    4761             :   }
    4762             : 
    4763             :   // Restore old value for postfix expressions.
    4764      240995 :   if (is_postfix) {
    4765       26920 :     builder()->LoadAccumulatorWithRegister(old_value);
    4766             :   }
    4767      240995 : }
    4768             : 
    4769      504550 : void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
    4770      504550 :   switch (binop->op()) {
    4771             :     case Token::COMMA:
    4772       37686 :       VisitCommaExpression(binop);
    4773       37686 :       break;
    4774             :     case Token::OR:
    4775       40775 :       VisitLogicalOrExpression(binop);
    4776       40774 :       break;
    4777             :     case Token::AND:
    4778       68726 :       VisitLogicalAndExpression(binop);
    4779       68726 :       break;
    4780             :     default:
    4781      357363 :       VisitArithmeticExpression(binop);
    4782      357366 :       break;
    4783             :   }
    4784      504552 : }
    4785             : 
    4786      104638 : void BytecodeGenerator::VisitNaryOperation(NaryOperation* expr) {
    4787      104638 :   switch (expr->op()) {
    4788             :     case Token::COMMA:
    4789         332 :       VisitNaryCommaExpression(expr);
    4790         332 :       break;
    4791             :     case Token::OR:
    4792       19271 :       VisitNaryLogicalOrExpression(expr);
    4793       19272 :       break;
    4794             :     case Token::AND:
    4795         621 :       VisitNaryLogicalAndExpression(expr);
    4796         621 :       break;
    4797             :     default:
    4798       84414 :       VisitNaryArithmeticExpression(expr);
    4799       84418 :       break;
    4800             :   }
    4801      104643 : }
    4802             : 
    4803       44272 : void BytecodeGenerator::BuildLiteralCompareNil(
    4804       44272 :     Token::Value op, BytecodeArrayBuilder::NilValue nil) {
    4805       44272 :   if (execution_result()->IsTest()) {
    4806       63910 :     TestResultScope* test_result = execution_result()->AsTest();
    4807       31955 :     switch (test_result->fallthrough()) {
    4808             :       case TestFallthrough::kThen:
    4809       30589 :         builder()->JumpIfNotNil(test_result->NewElseLabel(), op, nil);
    4810       15294 :         break;
    4811             :       case TestFallthrough::kElse:
    4812       33322 :         builder()->JumpIfNil(test_result->NewThenLabel(), op, nil);
    4813       16662 :         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       12317 :     builder()->CompareNil(op, nil);
    4822             :   }
    4823       44274 : }
    4824             : 
    4825     4629709 : void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
    4826             :   Expression* sub_expr;
    4827             :   Literal* literal;
    4828      840423 :   if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
    4829             :     // Emit a fast literal comparion for expressions of the form:
    4830             :     // typeof(x) === 'string'.
    4831       92593 :     VisitForTypeOfValue(sub_expr);
    4832             :     builder()->SetExpressionPosition(expr);
    4833             :     TestTypeOfFlags::LiteralFlag literal_flag =
    4834      185178 :         TestTypeOfFlags::GetFlagForLiteral(ast_string_constants(), literal);
    4835       92588 :     if (literal_flag == TestTypeOfFlags::LiteralFlag::kOther) {
    4836         231 :       builder()->LoadFalse();
    4837             :     } else {
    4838       92357 :       builder()->CompareTypeOf(literal_flag);
    4839             :     }
    4840      747875 :   } else if (expr->IsLiteralCompareUndefined(&sub_expr)) {
    4841       39281 :     VisitForAccumulatorValue(sub_expr);
    4842             :     builder()->SetExpressionPosition(expr);
    4843       39282 :     BuildLiteralCompareNil(expr->op(), BytecodeArrayBuilder::kUndefinedValue);
    4844      708568 :   } else if (expr->IsLiteralCompareNull(&sub_expr)) {
    4845        4991 :     VisitForAccumulatorValue(sub_expr);
    4846             :     builder()->SetExpressionPosition(expr);
    4847        4993 :     BuildLiteralCompareNil(expr->op(), BytecodeArrayBuilder::kNullValue);
    4848             :   } else {
    4849      703579 :     Register lhs = VisitForRegisterValue(expr->left());
    4850      703594 :     VisitForAccumulatorValue(expr->right());
    4851             :     builder()->SetExpressionPosition(expr);
    4852      703615 :     if (expr->op() == Token::IN) {
    4853        2404 :       builder()->CompareOperation(expr->op(), lhs);
    4854      701211 :     } else if (expr->op() == Token::INSTANCEOF) {
    4855       14248 :       FeedbackSlot slot = feedback_spec()->AddInstanceOfSlot();
    4856       14243 :       builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
    4857             :     } else {
    4858      686963 :       FeedbackSlot slot = feedback_spec()->AddCompareICSlot();
    4859      686923 :       builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
    4860             :     }
    4861             :   }
    4862             :   // Always returns a boolean value.
    4863             :   execution_result()->SetResultIsBoolean();
    4864      840468 : }
    4865             : 
    4866     1582870 : void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
    4867      357363 :   FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
    4868             :   Expression* subexpr;
    4869      357368 :   Smi literal;
    4870      357368 :   if (expr->IsSmiLiteralOperation(&subexpr, &literal)) {
    4871      125949 :     TypeHint type_hint = VisitForAccumulatorValue(subexpr);
    4872             :     builder()->SetExpressionPosition(expr);
    4873             :     builder()->BinaryOperationSmiLiteral(expr->op(), literal,
    4874      125962 :                                          feedback_index(slot));
    4875      125957 :     if (expr->op() == Token::ADD && type_hint == TypeHint::kString) {
    4876             :       execution_result()->SetResultIsString();
    4877             :     }
    4878             :   } else {
    4879      231434 :     TypeHint lhs_type = VisitForAccumulatorValue(expr->left());
    4880      231431 :     Register lhs = register_allocator()->NewRegister();
    4881      231434 :     builder()->StoreAccumulatorInRegister(lhs);
    4882      231442 :     TypeHint rhs_type = VisitForAccumulatorValue(expr->right());
    4883      332564 :     if (expr->op() == Token::ADD &&
    4884      101123 :         (lhs_type == TypeHint::kString || rhs_type == TypeHint::kString)) {
    4885             :       execution_result()->SetResultIsString();
    4886             :     }
    4887             : 
    4888             :     builder()->SetExpressionPosition(expr);
    4889      231441 :     builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot));
    4890             :   }
    4891      357393 : }
    4892             : 
    4893      461197 : void BytecodeGenerator::VisitNaryArithmeticExpression(NaryOperation* expr) {
    4894             :   // TODO(leszeks): Add support for lhs smi in commutative ops.
    4895       84414 :   TypeHint type_hint = VisitForAccumulatorValue(expr->first());
    4896             : 
    4897      777944 :   for (size_t i = 0; i < expr->subsequent_length(); ++i) {
    4898             :     RegisterAllocationScope register_scope(this);
    4899      304546 :     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      178392 :           feedback_index(feedback_spec()->AddBinaryOpICSlot()));
    4904             :     } else {
    4905      259951 :       Register lhs = register_allocator()->NewRegister();
    4906      259947 :       builder()->StoreAccumulatorInRegister(lhs);
    4907      259950 :       TypeHint rhs_hint = VisitForAccumulatorValue(expr->subsequent(i));
    4908      259951 :       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      519894 :           feedback_index(feedback_spec()->AddBinaryOpICSlot()));
    4913             :     }
    4914      304544 :   }
    4915             : 
    4916      120548 :   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       84426 : }
    4921             : 
    4922             : // Note: the actual spreading is performed by the surrounding expression's
    4923             : // visitor.
    4924        8021 : 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       42589 : void BytecodeGenerator::BuildGetIterator(IteratorType hint) {
    4939       42589 :   RegisterList args = register_allocator()->NewRegisterList(1);
    4940       42602 :   Register method = register_allocator()->NewRegister();
    4941       42603 :   Register obj = args[0];
    4942             : 
    4943       42603 :   if (hint == IteratorType::kAsync) {
    4944             :     // Set method to GetMethod(obj, @@asyncIterator)
    4945         347 :     builder()->StoreAccumulatorInRegister(obj).LoadAsyncIteratorProperty(
    4946         694 :         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         347 :     builder()->JumpIfUndefined(&async_iterator_undefined);
    4951         347 :     builder()->JumpIfNull(&async_iterator_null);
    4952             : 
    4953             :     // Let iterator be Call(method, obj)
    4954         347 :     builder()->StoreAccumulatorInRegister(method).CallProperty(
    4955         694 :         method, args, feedback_index(feedback_spec()->AddCallICSlot()));
    4956             : 
    4957             :     // If Type(iterator) is not Object, throw a TypeError exception.
    4958         347 :     builder()->JumpIfJSReceiver(&done);
    4959         347 :     builder()->CallRuntime(Runtime::kThrowSymbolAsyncIteratorInvalid);
    4960             : 
    4961         347 :     builder()->Bind(&async_iterator_undefined);
    4962         347 :     builder()->Bind(&async_iterator_null);
    4963             :     // If method is undefined,
    4964             :     //     Let syncMethod be GetMethod(obj, @@iterator)
    4965             :     builder()
    4966             :         ->LoadIteratorProperty(obj,
    4967         694 :                                feedback_index(feedback_spec()->AddLoadICSlot()))
    4968         347 :         .StoreAccumulatorInRegister(method);
    4969             : 
    4970             :     //     Let syncIterator be Call(syncMethod, obj)
    4971             :     builder()->CallProperty(method, args,
    4972         694 :                             feedback_index(feedback_spec()->AddCallICSlot()));
    4973             : 
    4974             :     // Return CreateAsyncFromSyncIterator(syncIterator)
    4975             :     // alias `method` register as it's no longer used
    4976         347 :     Register sync_iter = method;
    4977         347 :     builder()->StoreAccumulatorInRegister(sync_iter).CallRuntime(
    4978         347 :         Runtime::kInlineCreateAsyncFromSyncIterator, sync_iter);
    4979             : 
    4980         347 :     builder()->Bind(&done);
    4981             :   } else {
    4982             :     // Let method be GetMethod(obj, @@iterator).
    4983             :     builder()
    4984       42253 :         ->StoreAccumulatorInRegister(obj)
    4985             :         .LoadIteratorProperty(obj,
    4986       84511 :                               feedback_index(feedback_spec()->AddLoadICSlot()))
    4987       42256 :         .StoreAccumulatorInRegister(method);
    4988             : 
    4989             :     // Let iterator be Call(method, obj).
    4990             :     builder()->CallProperty(method, args,
    4991       84514 :                             feedback_index(feedback_spec()->AddCallICSlot()));
    4992             : 
    4993             :     // If Type(iterator) is not Object, throw a TypeError exception.
    4994             :     BytecodeLabel no_type_error;
    4995       42257 :     builder()->JumpIfJSReceiver(&no_type_error);
    4996       42251 :     builder()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid);
    4997       42256 :     builder()->Bind(&no_type_error);
    4998             :   }
    4999       42597 : }
    5000             : 
    5001             : // Returns an IteratorRecord which is valid for the lifetime of the current
    5002             : // register_allocation_scope.
    5003       42594 : BytecodeGenerator::IteratorRecord BytecodeGenerator::BuildGetIteratorRecord(
    5004       42602 :     Register next, Register object, IteratorType hint) {
    5005             :   DCHECK(next.is_valid() && object.is_valid());
    5006       42594 :   BuildGetIterator(hint);
    5007             : 
    5008             :   builder()
    5009       42602 :       ->StoreAccumulatorInRegister(object)
    5010             :       .LoadNamedProperty(object, ast_string_constants()->next_string(),
    5011      127807 :                          feedback_index(feedback_spec()->AddLoadICSlot()))
    5012       42604 :       .StoreAccumulatorInRegister(next);
    5013       42605 :   return IteratorRecord(object, next, hint);
    5014             : }
    5015             : 
    5016       42395 : BytecodeGenerator::IteratorRecord BytecodeGenerator::BuildGetIteratorRecord(
    5017             :     IteratorType hint) {
    5018       42395 :   Register next = register_allocator()->NewRegister();
    5019       42396 :   Register object = register_allocator()->NewRegister();
    5020       42404 :   return BuildGetIteratorRecord(next, object, hint);
    5021             : }
    5022             : 
    5023       87654 : 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       87645 :                           feedback_index(feedback_spec()->AddCallICSlot()));
    5028             : 
    5029       43835 :   if (iterator.type() == IteratorType::kAsync) {
    5030         337 :     BuildAwait();
    5031             :   }
    5032             : 
    5033             :   BytecodeLabel is_object;
    5034             :   builder()
    5035       43835 :       ->StoreAccumulatorInRegister(next_result)
    5036       43835 :       .JumpIfJSReceiver(&is_object)
    5037       43835 :       .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, next_result)
    5038       43834 :       .Bind(&is_object);
    5039       43831 : }
    5040             : 
    5041         600 : 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         600 :   Register method = register_allocator()->NewRegister();
    5049         600 :   FeedbackSlot slot = feedback_spec()->AddLoadICSlot();
    5050             :   builder()
    5051         600 :       ->LoadNamedProperty(iterator, method_name, feedback_index(slot))
    5052        1200 :       .JumpIfUndefined(if_notcalled->New())
    5053        1200 :       .JumpIfNull(if_notcalled->New())
    5054         600 :       .StoreAccumulatorInRegister(method)
    5055             :       .CallProperty(method, receiver_and_args,
    5056        1200 :                     feedback_index(feedback_spec()->AddCallICSlot()))
    5057         600 :       .Jump(if_called);
    5058         600 : }
    5059             : 
    5060         400 : void BytecodeGenerator::BuildIteratorClose(const IteratorRecord& iterator,
    5061         400 :                                            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         200 :                           &if_called, &done);
    5069         200 :   builder()->Bind(&if_called);
    5070             : 
    5071         200 :   if (iterator.type() == IteratorType::kAsync) {
    5072             :     DCHECK_NOT_NULL(expr);
    5073          10 :     BuildAwait(expr->position());
    5074             :   }
    5075             : 
    5076         200 :   builder()->JumpIfJSReceiver(done.New());
    5077             :   {
    5078             :     RegisterAllocationScope register_scope(this);
    5079         200 :     Register return_result = register_allocator()->NewRegister();
    5080             :     builder()
    5081         200 :         ->StoreAccumulatorInRegister(return_result)
    5082         200 :         .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, return_result);
    5083             :   }
    5084             : 
    5085         400 :   done.Bind(builder());
    5086         200 : }
    5087             : 
    5088        2043 : void BytecodeGenerator::VisitGetTemplateObject(GetTemplateObject* expr) {
    5089             :   builder()->SetExpressionPosition(expr);
    5090        2043 :   size_t entry = builder()->AllocateDeferredConstantPoolEntry();
    5091        4086 :   template_objects_.push_back(std::make_pair(expr, entry));
    5092        2043 :   FeedbackSlot literal_slot = feedback_spec()->AddLiteralSlot();
    5093        2043 :   builder()->GetTemplateObject(entry, feedback_index(literal_slot));
    5094        2043 : }
    5095             : 
    5096        7145 : void BytecodeGenerator::VisitTemplateLiteral(TemplateLiteral* expr) {
    5097       10601 :   const ZonePtrList<const AstRawString>& parts = *expr->string_parts();
    5098       28350 :   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        7145 :   FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
    5107        7145 :   Register last_part = register_allocator()->NewRegister();
    5108             :   bool last_part_valid = false;
    5109             : 
    5110             :   builder()->SetExpressionPosition(expr);
    5111       28347 :   for (int i = 0; i < substitutions.length(); ++i) {
    5112       10601 :     if (i != 0) {
    5113        3456 :       builder()->StoreAccumulatorInRegister(last_part);
    5114             :       last_part_valid = true;
    5115             :     }
    5116             : 
    5117       21202 :     if (!parts[i]->IsEmpty()) {
    5118        7335 :       builder()->LoadLiteral(parts[i]);
    5119        7337 :       if (last_part_valid) {
    5120        3385 :         builder()->BinaryOperation(Token::ADD, last_part, feedback_index(slot));
    5121             :       }
    5122        7337 :       builder()->StoreAccumulatorInRegister(last_part);
    5123             :       last_part_valid = true;
    5124             :     }
    5125             : 
    5126       10604 :     TypeHint type_hint = VisitForAccumulatorValue(substitutions[i]);
    5127       10604 :     if (type_hint != TypeHint::kString) {
    5128       10592 :       builder()->ToString();
    5129             :     }
    5130       10603 :     if (last_part_valid) {
    5131        7408 :       builder()->BinaryOperation(Token::ADD, last_part, feedback_index(slot));
    5132             :     }
    5133             :     last_part_valid = false;
    5134             :   }
    5135             : 
    5136       14290 :   if (!parts.last()->IsEmpty()) {
    5137        2904 :     builder()->StoreAccumulatorInRegister(last_part);
    5138        2904 :     builder()->LoadLiteral(parts.last());
    5139        2904 :     builder()->BinaryOperation(Token::ADD, last_part, feedback_index(slot));
    5140             :   }
    5141        7145 : }
    5142             : 
    5143           0 : void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
    5144           0 :   builder()->LoadAccumulatorWithRegister(Register::function_closure());
    5145           0 : }
    5146             : 
    5147           0 : void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
    5148             :   // Handled by VisitCall().
    5149           0 :   UNREACHABLE();
    5150             : }
    5151             : 
    5152           0 : void BytecodeGenerator::VisitSuperPropertyReference(
    5153             :     SuperPropertyReference* expr) {
    5154          17 :   builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError);
    5155           0 : }
    5156             : 
    5157       75372 : void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
    5158       37686 :   VisitForEffect(binop->left());
    5159       37686 :   Visit(binop->right());
    5160       37686 : }
    5161             : 
    5162         332 : void BytecodeGenerator::VisitNaryCommaExpression(NaryOperation* expr) {
    5163             :   DCHECK_GT(expr->subsequent_length(), 0);
    5164             : 
    5165         332 :   VisitForEffect(expr->first());
    5166     5221144 :   for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
    5167     2610240 :     VisitForEffect(expr->subsequent(i));
    5168             :   }
    5169         332 :   Visit(expr->subsequent(expr->subsequent_length() - 1));
    5170         332 : }
    5171             : 
    5172      127458 : void BytecodeGenerator::VisitLogicalTestSubExpression(
    5173             :     Token::Value token, Expression* expr, BytecodeLabels* then_labels,
    5174      127458 :     BytecodeLabels* else_labels, int coverage_slot) {
    5175             :   DCHECK(token == Token::OR || token == Token::AND);
    5176             : 
    5177             :   BytecodeLabels test_next(zone());
    5178      127458 :   if (token == Token::OR) {
    5179       87913 :     VisitForTest(expr, then_labels, &test_next, TestFallthrough::kElse);
    5180             :   } else {
    5181             :     DCHECK_EQ(Token::AND, token);
    5182       39545 :     VisitForTest(expr, &test_next, else_labels, TestFallthrough::kThen);
    5183             :   }
    5184      127461 :   test_next.Bind(builder());
    5185             : 
    5186      127461 :   BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
    5187      127461 : }
    5188             : 
    5189       53905 : void BytecodeGenerator::VisitLogicalTest(Token::Value token, Expression* left,
    5190             :                                          Expression* right,
    5191       53905 :                                          int right_coverage_slot) {
    5192             :   DCHECK(token == Token::OR || token == Token::AND);
    5193       53905 :   TestResultScope* test_result = execution_result()->AsTest();
    5194             :   BytecodeLabels* then_labels = test_result->then_labels();
    5195             :   BytecodeLabels* else_labels = test_result->else_labels();
    5196             :   TestFallthrough fallthrough = test_result->fallthrough();
    5197             : 
    5198             :   VisitLogicalTestSubExpression(token, left, then_labels, else_labels,
    5199       53905 :                                 right_coverage_slot);
    5200             :   // The last test has the same then, else and fallthrough as the parent test.
    5201       53907 :   VisitForTest(right, then_labels, else_labels, fallthrough);
    5202       53906 : }
    5203             : 
    5204       19306 : void BytecodeGenerator::VisitNaryLogicalTest(
    5205       19306 :     Token::Value token, NaryOperation* expr,
    5206       19306 :     const NaryCodeCoverageSlots* coverage_slots) {
    5207             :   DCHECK(token == Token::OR || token == Token::AND);
    5208             :   DCHECK_GT(expr->subsequent_length(), 0);
    5209             : 
    5210       19306 :   TestResultScope* test_result = execution_result()->AsTest();
    5211             :   BytecodeLabels* then_labels = test_result->then_labels();
    5212             :   BytecodeLabels* else_labels = test_result->else_labels();
    5213             :   TestFallthrough fallthrough = test_result->fallthrough();
    5214             : 
    5215             :   VisitLogicalTestSubExpression(token, expr->first(), then_labels, else_labels,
    5216       19306 :                                 coverage_slots->GetSlotFor(0));
    5217       92859 :   for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
    5218             :     VisitLogicalTestSubExpression(token, expr->subsequent(i), then_labels,
    5219             :                                   else_labels,
    5220      108494 :                                   coverage_slots->GetSlotFor(i + 1));
    5221             :   }
    5222             :   // The last test has the same then, else and fallthrough as the parent test.
    5223             :   VisitForTest(expr->subsequent(expr->subsequent_length() - 1), then_labels,
    5224       19306 :                else_labels, fallthrough);
    5225       19306 : }
    5226             : 
    5227       21960 : bool BytecodeGenerator::VisitLogicalOrSubExpression(Expression* expr,
    5228             :                                                     BytecodeLabels* end_labels,
    5229             :                                                     int coverage_slot) {
    5230       21960 :   if (expr->ToBooleanIsTrue()) {
    5231        1730 :     VisitForAccumulatorValue(expr);
    5232        1730 :     end_labels->Bind(builder());
    5233        1730 :     return true;
    5234       20231 :   } else if (!expr->ToBooleanIsFalse()) {
    5235       20040 :     TypeHint type_hint = VisitForAccumulatorValue(expr);
    5236             :     builder()->JumpIfTrue(ToBooleanModeFromTypeHint(type_hint),
    5237       40085 :                           end_labels->New());
    5238             :   }
    5239             : 
    5240       20233 :   BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
    5241             : 
    5242       20233 :   return false;
    5243             : }
    5244             : 
    5245       30861 : bool BytecodeGenerator::VisitLogicalAndSubExpression(Expression* expr,
    5246             :                                                      BytecodeLabels* end_labels,
    5247             :                                                      int coverage_slot) {
    5248       30861 :   if (expr->ToBooleanIsFalse()) {
    5249         175 :     VisitForAccumulatorValue(expr);
    5250         175 :     end_labels->Bind(builder());
    5251         175 :     return true;
    5252       30686 :   } else if (!expr->ToBooleanIsTrue()) {
    5253       28944 :     TypeHint type_hint = VisitForAccumulatorValue(expr);
    5254             :     builder()->JumpIfFalse(ToBooleanModeFromTypeHint(type_hint),
    5255       57886 :                            end_labels->New());
    5256             :   }
    5257             : 
    5258       30686 :   BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
    5259             : 
    5260       30686 :   return false;
    5261             : }
    5262             : 
    5263      103210 : void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
    5264             :   Expression* left = binop->left();
    5265             :   Expression* right = binop->right();
    5266             : 
    5267             :   int right_coverage_slot =
    5268             :       AllocateBlockCoverageSlotIfEnabled(binop, SourceRangeKind::kRight);
    5269             : 
    5270       40776 :   if (execution_result()->IsTest()) {
    5271        4340 :     TestResultScope* test_result = execution_result()->AsTest();
    5272       19115 :     if (left->ToBooleanIsTrue()) {
    5273        4340 :       builder()->Jump(test_result->NewThenLabel());
    5274       14774 :     } else if (left->ToBooleanIsFalse() && right->ToBooleanIsFalse()) {
    5275           0 :       BuildIncrementBlockCoverageCounterIfEnabled(right_coverage_slot);
    5276           0 :       builder()->Jump(test_result->NewElseLabel());
    5277             :     } else {
    5278       14774 :       VisitLogicalTest(Token::OR, left, right, right_coverage_slot);
    5279             :     }
    5280             :     test_result->SetResultConsumedByTest();
    5281             :   } else {
    5282             :     BytecodeLabels end_labels(zone());
    5283       21661 :     if (VisitLogicalOrSubExpression(left, &end_labels, right_coverage_slot)) {
    5284       40775 :       return;
    5285             :     }
    5286       19967 :     VisitForAccumulatorValue(right);
    5287       19970 :     end_labels.Bind(builder());
    5288             :   }
    5289             : }
    5290             : 
    5291       38691 : void BytecodeGenerator::VisitNaryLogicalOrExpression(NaryOperation* expr) {
    5292             :   Expression* first = expr->first();
    5293             :   DCHECK_GT(expr->subsequent_length(), 0);
    5294             : 
    5295       19271 :   NaryCodeCoverageSlots coverage_slots(this, expr);
    5296             : 
    5297       19271 :   if (execution_result()->IsTest()) {
    5298           0 :     TestResultScope* test_result = execution_result()->AsTest();
    5299       19122 :     if (first->ToBooleanIsTrue()) {
    5300           0 :       builder()->Jump(test_result->NewThenLabel());
    5301             :     } else {
    5302       19123 :       VisitNaryLogicalTest(Token::OR, expr, &coverage_slots);
    5303             :     }
    5304             :     test_result->SetResultConsumedByTest();
    5305             :   } else {
    5306             :     BytecodeLabels end_labels(zone());
    5307         149 :     if (VisitLogicalOrSubExpression(first, &end_labels,
    5308             :                                     coverage_slots.GetSlotFor(0))) {
    5309             :       return;
    5310             :     }
    5311         264 :     for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
    5312         151 :       if (VisitLogicalOrSubExpression(expr->subsequent(i), &end_labels,
    5313         151 :                                       coverage_slots.GetSlotFor(i + 1))) {
    5314             :         return;
    5315             :       }
    5316             :     }
    5317             :     // We have to visit the last value even if it's true, because we need its
    5318             :     // actual value.
    5319         113 :     VisitForAccumulatorValue(expr->subsequent(expr->subsequent_length() - 1));
    5320         113 :     end_labels.Bind(builder());
    5321             :   }
    5322             : }
    5323             : 
    5324      167032 : void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
    5325             :   Expression* left = binop->left();
    5326             :   Expression* right = binop->right();
    5327             : 
    5328             :   int right_coverage_slot =
    5329             :       AllocateBlockCoverageSlotIfEnabled(binop, SourceRangeKind::kRight);
    5330             : 
    5331       68725 :   if (execution_result()->IsTest()) {
    5332          10 :     TestResultScope* test_result = execution_result()->AsTest();
    5333       39143 :     if (left->ToBooleanIsFalse()) {
    5334          10 :       builder()->Jump(test_result->NewElseLabel());
    5335       39133 :     } else if (left->ToBooleanIsTrue() && right->ToBooleanIsTrue()) {
    5336           0 :       BuildIncrementBlockCoverageCounterIfEnabled(right_coverage_slot);
    5337           0 :       builder()->Jump(test_result->NewThenLabel());
    5338             :     } else {
    5339       39133 :       VisitLogicalTest(Token::AND, left, right, right_coverage_slot);
    5340             :     }
    5341             :     test_result->SetResultConsumedByTest();
    5342             :   } else {
    5343             :     BytecodeLabels end_labels(zone());
    5344       29582 :     if (VisitLogicalAndSubExpression(left, &end_labels, right_coverage_slot)) {
    5345       68726 :       return;
    5346             :     }
    5347       29426 :     VisitForAccumulatorValue(right);
    5348       29427 :     end_labels.Bind(builder());
    5349             :   }
    5350             : }
    5351             : 
    5352        1680 : void BytecodeGenerator::VisitNaryLogicalAndExpression(NaryOperation* expr) {
    5353             :   Expression* first = expr->first();
    5354             :   DCHECK_GT(expr->subsequent_length(), 0);
    5355             : 
    5356         621 :   NaryCodeCoverageSlots coverage_slots(this, expr);
    5357             : 
    5358         621 :   if (execution_result()->IsTest()) {
    5359           0 :     TestResultScope* test_result = execution_result()->AsTest();
    5360         183 :     if (first->ToBooleanIsFalse()) {
    5361           0 :       builder()->Jump(test_result->NewElseLabel());
    5362             :     } else {
    5363         183 :       VisitNaryLogicalTest(Token::AND, expr, &coverage_slots);
    5364             :     }
    5365             :     test_result->SetResultConsumedByTest();
    5366             :   } else {
    5367             :     BytecodeLabels end_labels(zone());
    5368         438 :     if (VisitLogicalAndSubExpression(first, &end_labels,
    5369             :                                      coverage_slots.GetSlotFor(0))) {
    5370             :       return;
    5371             :     }
    5372        1260 :     for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
    5373         842 :       if (VisitLogicalAndSubExpression(expr->subsequent(i), &end_labels,
    5374         842 :                                        coverage_slots.GetSlotFor(i + 1))) {
    5375             :         return;
    5376             :       }
    5377             :     }
    5378             :     // We have to visit the last value even if it's false, because we need its
    5379             :     // actual value.
    5380         418 :     VisitForAccumulatorValue(expr->subsequent(expr->subsequent_length() - 1));
    5381         418 :     end_labels.Bind(builder());
    5382             :   }
    5383             : }
    5384             : 
    5385      383272 : void BytecodeGenerator::BuildNewLocalActivationContext() {
    5386             :   ValueResultScope value_execution_result(this);
    5387      368596 :   Scope* scope = closure_scope();
    5388             :   DCHECK_EQ(current_scope(), closure_scope());
    5389             : 
    5390             :   // Create the appropriate context.
    5391      191636 :   if (scope->is_script_scope()) {
    5392       13578 :     Register scope_reg = register_allocator()->NewRegister();
    5393             :     builder()
    5394       13579 :         ->LoadLiteral(scope)
    5395       13578 :         .StoreAccumulatorInRegister(scope_reg)
    5396       13578 :         .CallRuntime(Runtime::kNewScriptContext, scope_reg);
    5397      178058 :   } else if (scope->is_module_scope()) {
    5398             :     // We don't need to do anything for the outer script scope.
    5399             :     DCHECK(scope->outer_scope()->is_script_scope());
    5400             : 
    5401             :     // A JSFunction representing a module is called with the module object as
    5402             :     // its sole argument.
    5403        1098 :     RegisterList args = register_allocator()->NewRegisterList(2);
    5404             :     builder()
    5405        1098 :         ->MoveRegister(builder()->Parameter(0), args[0])
    5406        1098 :         .LoadLiteral(scope)
    5407        1098 :         .StoreAccumulatorInRegister(args[1])
    5408        1098 :         .CallRuntime(Runtime::kPushModuleContext, args);
    5409             :   } else {
    5410             :     DCHECK(scope->is_function_scope() || scope->is_eval_scope());
    5411      176960 :     int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
    5412      176960 :     if (slot_count <= ConstructorBuiltins::MaximumFunctionContextSlots()) {
    5413      176943 :       switch (scope->scope_type()) {
    5414             :         case EVAL_SCOPE:
    5415       42320 :           builder()->CreateEvalContext(scope, slot_count);
    5416       42320 :           break;
    5417             :         case FUNCTION_SCOPE:
    5418      134623 :           builder()->CreateFunctionContext(scope, slot_count);
    5419      134622 :           break;
    5420             :         default:
    5421           0 :           UNREACHABLE();
    5422             :       }
    5423             :     } else {
    5424          17 :       Register arg = register_allocator()->NewRegister();
    5425          17 :       builder()->LoadLiteral(scope).StoreAccumulatorInRegister(arg).CallRuntime(
    5426          17 :           Runtime::kNewFunctionContext, arg);
    5427             :     }
    5428             :   }
    5429      191630 : }
    5430             : 
    5431      338551 : void BytecodeGenerator::BuildLocalActivationContextInitialization() {
    5432      428483 :   DeclarationScope* scope = closure_scope();
    5433             : 
    5434      322729 :   if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
    5435      105752 :     Variable* variable = scope->receiver();
    5436      105752 :     Register receiver(builder()->Receiver());
    5437             :     // Context variable (at bottom of the context chain).
    5438             :     DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
    5439      105752 :     builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot(
    5440      105754 :         execution_context()->reg(), variable->index(), 0);
    5441             :   }
    5442             : 
    5443             :   // Copy parameters into context if necessary.
    5444             :   int num_parameters = scope->num_parameters();
    5445      259412 :   for (int i = 0; i < num_parameters; i++) {
    5446       41180 :     Variable* variable = scope->parameter(i);
    5447       94400 :     if (!variable->IsContextSlot()) continue;
    5448             : 
    5449       41180 :     Register parameter(builder()->Parameter(i));
    5450             :     // Context variable (at bottom of the context chain).
    5451             :     DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
    5452       41180 :     builder()->LoadAccumulatorWithRegister(parameter).StoreContextSlot(
    5453       41180 :         execution_context()->reg(), variable->index(), 0);
    5454             :   }
    5455      191622 : }
    5456             : 
    5457       58330 : void BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) {
    5458             :   ValueResultScope value_execution_result(this);
    5459             :   DCHECK(scope->is_block_scope());
    5460             : 
    5461       58330 :   builder()->CreateBlockContext(scope);
    5462       58320 : }
    5463             : 
    5464        2955 : void BytecodeGenerator::BuildNewLocalWithContext(Scope* scope) {
    5465             :   ValueResultScope value_execution_result(this);
    5466             : 
    5467        2955 :   Register extension_object = register_allocator()->NewRegister();
    5468             : 
    5469        2955 :   builder()->ToObject(extension_object);
    5470        2956 :   builder()->CreateWithContext(extension_object, scope);
    5471        2956 : }
    5472             : 
    5473       69598 : void BytecodeGenerator::BuildNewLocalCatchContext(Scope* scope) {
    5474             :   ValueResultScope value_execution_result(this);
    5475             :   DCHECK(scope->catch_variable()->IsContextSlot());
    5476             : 
    5477       69598 :   Register exception = register_allocator()->NewRegister();
    5478       69606 :   builder()->StoreAccumulatorInRegister(exception);
    5479       69619 :   builder()->CreateCatchContext(exception, scope);
    5480       69614 : }
    5481             : 
    5482        9259 : void BytecodeGenerator::VisitObjectLiteralAccessor(
    5483             :     Register home_object, ObjectLiteralProperty* property, Register value_out) {
    5484        9259 :   if (property == nullptr) {
    5485        3918 :     builder()->LoadNull().StoreAccumulatorInRegister(value_out);
    5486             :   } else {
    5487        5341 :     VisitForRegisterValue(property->value(), value_out);
    5488        5342 :     VisitSetHomeObject(value_out, home_object, property);
    5489             :   }
    5490        9259 : }
    5491             : 
    5492       11292 : void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
    5493       11292 :                                            LiteralProperty* property) {
    5494             :   Expression* expr = property->value();
    5495       11292 :   if (FunctionLiteral::NeedsHomeObject(expr)) {
    5496         659 :     FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
    5497             :     builder()
    5498         659 :         ->LoadAccumulatorWithRegister(home_object)
    5499         659 :         .StoreHomeObjectProperty(value, feedback_index(slot), language_mode());
    5500             :   }
    5501       11294 : }
    5502             : 
    5503     2210370 : void BytecodeGenerator::VisitArgumentsObject(Variable* variable) {
    5504     4219444 :   if (variable == nullptr) return;
    5505             : 
    5506             :   DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
    5507             : 
    5508             :   // Allocate and initialize a new arguments object and assign to the
    5509             :   // {arguments} variable.
    5510      100648 :   builder()->CreateArguments(closure_scope()->GetArgumentsType());
    5511      100647 :   BuildVariableAssignment(variable, Token::ASSIGN, HoleCheckMode::kElided);
    5512             : }
    5513             : 
    5514     2109727 : void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) {
    5515     4219454 :   if (rest == nullptr) return;
    5516             : 
    5517             :   // Allocate and initialize a new rest parameter and assign to the {rest}
    5518             :   // variable.
    5519        5166 :   builder()->CreateArguments(CreateArgumentsType::kRestParameter);
    5520             :   DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
    5521        5166 :   BuildVariableAssignment(rest, Token::ASSIGN, HoleCheckMode::kElided);
    5522             : }
    5523             : 
    5524     4219459 : void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
    5525     8438918 :   if (variable == nullptr) return;
    5526             : 
    5527             :   // Store the closure we were called with in the given variable.
    5528       34588 :   builder()->LoadAccumulatorWithRegister(Register::function_closure());
    5529       34588 :   BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
    5530             : }
    5531             : 
    5532     2310863 : void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
    5533     2109723 :   if (variable == nullptr) return;
    5534             : 
    5535             :   // The generator resume trampoline abuses the new.target register
    5536             :   // to pass in the generator object.  In ordinary calls, new.target is always
    5537             :   // undefined because generator functions are non-constructible, so don't
    5538             :   // assign anything to the new.target variable.
    5539      100827 :   if (IsResumableFunction(info()->literal()->kind())) return;
    5540             : 
    5541      100313 :   if (variable->location() == VariableLocation::LOCAL) {
    5542             :     // The new.target register was already assigned by entry trampoline.
    5543             :     DCHECK_EQ(incoming_new_target_or_generator_.index(),
    5544             :               GetRegisterForLocalVariable(variable).index());
    5545             :     return;
    5546             :   }
    5547             : 
    5548             :   // Store the new target we were called with in the given variable.
    5549       94864 :   builder()->LoadAccumulatorWithRegister(incoming_new_target_or_generator_);
    5550       94864 :   BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
    5551             : }
    5552             : 
    5553       28810 : void BytecodeGenerator::BuildGeneratorObjectVariableInitialization() {
    5554             :   DCHECK(IsResumableFunction(info()->literal()->kind()));
    5555             : 
    5556       10864 :   Variable* generator_object_var = closure_scope()->generator_object_var();
    5557             :   RegisterAllocationScope register_scope(this);
    5558       10864 :   RegisterList args = register_allocator()->NewRegisterList(2);
    5559             :   Runtime::FunctionId function_id =
    5560       17946 :       (IsAsyncFunction(info()->literal()->kind()) &&
    5561        7082 :        !IsAsyncGeneratorFunction(info()->literal()->kind()))
    5562             :           ? Runtime::kInlineAsyncFunctionEnter
    5563       10864 :           : Runtime::kInlineCreateJSGeneratorObject;
    5564             :   builder()
    5565       10864 :       ->MoveRegister(Register::function_closure(), args[0])
    5566       21728 :       .MoveRegister(builder()->Receiver(), args[1])
    5567       10864 :       .CallRuntime(function_id, args)
    5568       10864 :       .StoreAccumulatorInRegister(generator_object());
    5569             : 
    5570       10864 :   if (generator_object_var->location() == VariableLocation::LOCAL) {
    5571             :     // The generator object register is already set to the variable's local
    5572             :     // register.
    5573             :     DCHECK_EQ(generator_object().index(),
    5574             :               GetRegisterForLocalVariable(generator_object_var).index());
    5575             :   } else {
    5576             :     BuildVariableAssignment(generator_object_var, Token::INIT,
    5577           0 :                             HoleCheckMode::kElided);
    5578       10864 :   }
    5579       10864 : }
    5580             : 
    5581      940230 : void BytecodeGenerator::BuildPushUndefinedIntoRegisterList(
    5582             :     RegisterList* reg_list) {
    5583      940230 :   Register reg = register_allocator()->GrowRegisterList(reg_list);
    5584      940378 :   builder()->LoadUndefined().StoreAccumulatorInRegister(reg);
    5585      940582 : }
    5586             : 
    5587        9946 : void BytecodeGenerator::BuildLoadPropertyKey(LiteralProperty* property,
    5588             :                                              Register out_reg) {
    5589        9946 :   if (property->key()->IsStringLiteral()) {
    5590             :     builder()
    5591        4348 :         ->LoadLiteral(property->key()->AsLiteral()->AsRawString())
    5592        2174 :         .StoreAccumulatorInRegister(out_reg);
    5593             :   } else {
    5594        7774 :     VisitForAccumulatorValue(property->key());
    5595        7774 :     builder()->ToName(out_reg);
    5596             :   }
    5597        9947 : }
    5598             : 
    5599           0 : int BytecodeGenerator::AllocateBlockCoverageSlotIfEnabled(
    5600             :     AstNode* node, SourceRangeKind kind) {
    5601     2240286 :   return (block_coverage_builder_ == nullptr)
    5602             :              ? BlockCoverageBuilder::kNoCoverageArraySlot
    5603     2240286 :              : block_coverage_builder_->AllocateBlockCoverageSlot(node, kind);
    5604             : }
    5605             : 
    5606           0 : int BytecodeGenerator::AllocateNaryBlockCoverageSlotIfEnabled(
    5607             :     NaryOperation* node, size_t index) {
    5608         305 :   return (block_coverage_builder_ == nullptr)
    5609             :              ? BlockCoverageBuilder::kNoCoverageArraySlot
    5610             :              : block_coverage_builder_->AllocateNaryBlockCoverageSlot(node,
    5611         305 :                                                                       index);
    5612             : }
    5613             : 
    5614           0 : void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
    5615             :     AstNode* node, SourceRangeKind kind) {
    5616       22941 :   if (block_coverage_builder_ == nullptr) return;
    5617         190 :   block_coverage_builder_->IncrementBlockCounter(node, kind);
    5618             : }
    5619             : 
    5620      178379 : void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
    5621             :     int coverage_array_slot) {
    5622      178379 :   if (block_coverage_builder_ != nullptr) {
    5623             :     block_coverage_builder_->IncrementBlockCounter(coverage_array_slot);
    5624             :   }
    5625      178379 : }
    5626             : 
    5627             : // Visits the expression |expr| and places the result in the accumulator.
    5628    17374227 : BytecodeGenerator::TypeHint BytecodeGenerator::VisitForAccumulatorValue(
    5629             :     Expression* expr) {
    5630             :   ValueResultScope accumulator_scope(this);
    5631    17374227 :   Visit(expr);
    5632    34748535 :   return accumulator_scope.type_hint();
    5633             : }
    5634             : 
    5635       41021 : void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) {
    5636       41021 :   if (expr == nullptr) {
    5637       33066 :     builder()->LoadTheHole();
    5638             :   } else {
    5639        7955 :     VisitForAccumulatorValue(expr);
    5640             :   }
    5641       41024 : }
    5642             : 
    5643             : // Visits the expression |expr| and discards the result.
    5644    12807917 : void BytecodeGenerator::VisitForEffect(Expression* expr) {
    5645             :   EffectResultScope effect_scope(this);
    5646    12807917 :   Visit(expr);
    5647    12807108 : }
    5648             : 
    5649             : // Visits the expression |expr| and returns the register containing
    5650             : // the expression result.
    5651     5031512 : Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
    5652     5031512 :   VisitForAccumulatorValue(expr);
    5653     5031804 :   Register result = register_allocator()->NewRegister();
    5654     5031794 :   builder()->StoreAccumulatorInRegister(result);
    5655     5031879 :   return result;
    5656             : }
    5657             : 
    5658             : // Visits the expression |expr| and stores the expression result in
    5659             : // |destination|.
    5660             : void BytecodeGenerator::VisitForRegisterValue(Expression* expr,
    5661             :                                               Register destination) {
    5662      848844 :   ValueResultScope register_scope(this);
    5663      848817 :   Visit(expr);
    5664      848783 :   builder()->StoreAccumulatorInRegister(destination);
    5665             : }
    5666             : 
    5667             : // Visits the expression |expr| and pushes the result into a new register
    5668             : // added to the end of |reg_list|.
    5669     6980013 : void BytecodeGenerator::VisitAndPushIntoRegisterList(Expression* expr,
    5670             :                                                      RegisterList* reg_list) {
    5671             :   {
    5672             :     ValueResultScope register_scope(this);
    5673     6980013 :     Visit(expr);
    5674             :   }
    5675             :   // Grow the register list after visiting the expression to avoid reserving
    5676             :   // the register across the expression evaluation, which could cause memory
    5677             :   // leaks for deep expressions due to dead objects being kept alive by pointers
    5678             :   // in registers.
    5679     6980065 :   Register destination = register_allocator()->GrowRegisterList(reg_list);
    5680     6979991 :   builder()->StoreAccumulatorInRegister(destination);
    5681     6980130 : }
    5682             : 
    5683      862981 : void BytecodeGenerator::BuildTest(ToBooleanMode mode,
    5684             :                                   BytecodeLabels* then_labels,
    5685             :                                   BytecodeLabels* else_labels,
    5686             :                                   TestFallthrough fallthrough) {
    5687      862981 :   switch (fallthrough) {
    5688             :     case TestFallthrough::kThen:
    5689      599414 :       builder()->JumpIfFalse(mode, else_labels->New());
    5690      599428 :       break;
    5691             :     case TestFallthrough::kElse:
    5692      263571 :       builder()->JumpIfTrue(mode, then_labels->New());
    5693      263575 :       break;
    5694             :     case TestFallthrough::kNone:
    5695           0 :       builder()->JumpIfTrue(mode, then_labels->New());
    5696           0 :       builder()->Jump(else_labels->New());
    5697           0 :       break;
    5698             :   }
    5699      862999 : }
    5700             : 
    5701             : // Visits the expression |expr| for testing its boolean value and jumping to the
    5702             : // |then| or |other| label depending on value and short-circuit semantics
    5703      972473 : void BytecodeGenerator::VisitForTest(Expression* expr,
    5704             :                                      BytecodeLabels* then_labels,
    5705             :                                      BytecodeLabels* else_labels,
    5706             :                                      TestFallthrough fallthrough) {
    5707             :   bool result_consumed;
    5708             :   TypeHint type_hint;
    5709             :   {
    5710             :     // To make sure that all temporary registers are returned before generating
    5711             :     // jumps below, we ensure that the result scope is deleted before doing so.
    5712             :     // Dead registers might be materialized otherwise.
    5713             :     TestResultScope test_result(this, then_labels, else_labels, fallthrough);
    5714      972473 :     Visit(expr);
    5715      972511 :     result_consumed = test_result.result_consumed_by_test();
    5716      972511 :     type_hint = test_result.type_hint();
    5717             :     // Labels and fallthrough might have been mutated, so update based on
    5718             :     // TestResultScope.
    5719      972511 :     then_labels = test_result.then_labels();
    5720      972511 :     else_labels = test_result.else_labels();
    5721      972511 :     fallthrough = test_result.fallthrough();
    5722             :   }
    5723      972517 :   if (!result_consumed) {
    5724             :     BuildTest(ToBooleanModeFromTypeHint(type_hint), then_labels, else_labels,
    5725      672250 :               fallthrough);
    5726             :   }
    5727      972520 : }
    5728             : 
    5729      415450 : void BytecodeGenerator::VisitInSameTestExecutionScope(Expression* expr) {
    5730             :   DCHECK(execution_result()->IsTest());
    5731             :   {
    5732             :     RegisterAllocationScope reg_scope(this);
    5733      207721 :     Visit(expr);
    5734             :   }
    5735      207729 :   if (!execution_result()->AsTest()->result_consumed_by_test()) {
    5736      190750 :     TestResultScope* result_scope = execution_result()->AsTest();
    5737             :     BuildTest(ToBooleanModeFromTypeHint(result_scope->type_hint()),
    5738             :               result_scope->then_labels(), result_scope->else_labels(),
    5739      381500 :               result_scope->fallthrough());
    5740             :     result_scope->SetResultConsumedByTest();
    5741             :   }
    5742      207729 : }
    5743             : 
    5744       72549 : void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) {
    5745             :   DCHECK(scope->declarations()->is_empty());
    5746             :   CurrentScope current_scope(this, scope);
    5747      145125 :   ContextScope context_scope(this, scope);
    5748       72575 :   Visit(stmt);
    5749       72564 : }
    5750             : 
    5751       16313 : Register BytecodeGenerator::GetRegisterForLocalVariable(Variable* variable) {
    5752             :   DCHECK_EQ(VariableLocation::LOCAL, variable->location());
    5753       16313 :   return builder()->Local(variable->index());
    5754             : }
    5755             : 
    5756     2136859 : FunctionKind BytecodeGenerator::function_kind() const {
    5757     2136859 :   return info()->literal()->kind();
    5758             : }
    5759             : 
    5760     6425926 : LanguageMode BytecodeGenerator::language_mode() const {
    5761             :   return current_scope()->language_mode();
    5762             : }
    5763             : 
    5764             : Register BytecodeGenerator::generator_object() const {
    5765             :   DCHECK(IsResumableFunction(info()->literal()->kind()));
    5766             :   return incoming_new_target_or_generator_;
    5767             : }
    5768             : 
    5769    17934869 : FeedbackVectorSpec* BytecodeGenerator::feedback_spec() {
    5770             :   return info()->feedback_vector_spec();
    5771             : }
    5772             : 
    5773             : int BytecodeGenerator::feedback_index(FeedbackSlot slot) const {
    5774             :   DCHECK(!slot.IsInvalid());
    5775             :   return FeedbackVector::GetIndex(slot);
    5776             : }
    5777             : 
    5778     7724567 : FeedbackSlot BytecodeGenerator::GetCachedLoadGlobalICSlot(
    5779    10823546 :     TypeofMode typeof_mode, Variable* variable) {
    5780             :   FeedbackSlotKind slot_kind =
    5781             :       typeof_mode == INSIDE_TYPEOF
    5782             :           ? FeedbackSlotKind::kLoadGlobalInsideTypeof
    5783     7724567 :           : FeedbackSlotKind::kLoadGlobalNotInsideTypeof;
    5784             :   FeedbackSlot slot = feedback_slot_cache()->Get(slot_kind, variable);
    5785     7725047 :   if (!slot.IsInvalid()) {
    5786     4626095 :     return slot;
    5787             :   }
    5788     3098952 :   slot = feedback_spec()->AddLoadGlobalICSlot(typeof_mode);
    5789             :   feedback_slot_cache()->Put(slot_kind, variable, slot);
    5790     3099269 :   return slot;
    5791             : }
    5792             : 
    5793     1421051 : FeedbackSlot BytecodeGenerator::GetCachedStoreGlobalICSlot(
    5794     2577168 :     LanguageMode language_mode, Variable* variable) {
    5795             :   FeedbackSlotKind slot_kind = is_strict(language_mode)
    5796             :                                    ? FeedbackSlotKind::kStoreGlobalStrict
    5797     1421051 :                                    : FeedbackSlotKind::kStoreGlobalSloppy;
    5798             :   FeedbackSlot slot = feedback_slot_cache()->Get(slot_kind, variable);
    5799     1421231 :   if (!slot.IsInvalid()) {
    5800      265162 :     return slot;
    5801             :   }
    5802     1156069 :   slot = feedback_spec()->AddStoreGlobalICSlot(language_mode);
    5803             :   feedback_slot_cache()->Put(slot_kind, variable, slot);
    5804     1156093 :   return slot;
    5805             : }
    5806             : 
    5807     1117062 : FeedbackSlot BytecodeGenerator::GetCachedLoadICSlot(const Expression* expr,
    5808     1539183 :                                                     const AstRawString* name) {
    5809     1117062 :   if (!FLAG_ignition_share_named_property_feedback) {
    5810           0 :     return feedback_spec()->AddLoadICSlot();
    5811             :   }
    5812             :   FeedbackSlotKind slot_kind = FeedbackSlotKind::kLoadProperty;
    5813     1117074 :   if (!expr->IsVariableProxy()) {
    5814      203504 :     return feedback_spec()->AddLoadICSlot();
    5815             :   }
    5816     2452753 :   const VariableProxy* proxy = expr->AsVariableProxy();
    5817             :   FeedbackSlot slot =
    5818      913570 :       feedback_slot_cache()->Get(slot_kind, proxy->var()->index(), name);
    5819      913569 :   if (!slot.IsInvalid()) {
    5820      287961 :     return slot;
    5821             :   }
    5822      625608 :   slot = feedback_spec()->AddLoadICSlot();
    5823      625613 :   feedback_slot_cache()->Put(slot_kind, proxy->var()->index(), name, slot);
    5824      625601 :   return slot;
    5825             : }
    5826             : 
    5827     2281928 : FeedbackSlot BytecodeGenerator::GetCachedStoreICSlot(const Expression* expr,
    5828     2459236 :                                                      const AstRawString* name) {
    5829     2281928 :   if (!FLAG_ignition_share_named_property_feedback) {
    5830           0 :     return feedback_spec()->AddStoreICSlot(language_mode());
    5831             :   }
    5832             :   FeedbackSlotKind slot_kind = is_strict(language_mode())
    5833             :                                    ? FeedbackSlotKind::kStoreNamedStrict
    5834     2281928 :                                    : FeedbackSlotKind::kStoreNamedSloppy;
    5835     2281926 :   if (!expr->IsVariableProxy()) {
    5836        2314 :     return feedback_spec()->AddStoreICSlot(language_mode());
    5837             :   }
    5838     4738848 :   const VariableProxy* proxy = expr->AsVariableProxy();
    5839             :   FeedbackSlot slot =
    5840     2279612 :       feedback_slot_cache()->Get(slot_kind, proxy->var()->index(), name);
    5841     2279616 :   if (!slot.IsInvalid()) {
    5842     2099993 :     return slot;
    5843             :   }
    5844      179623 :   slot = feedback_spec()->AddStoreICSlot(language_mode());
    5845      179624 :   feedback_slot_cache()->Put(slot_kind, proxy->var()->index(), name, slot);
    5846      179623 :   return slot;
    5847             : }
    5848             : 
    5849     2854753 : FeedbackSlot BytecodeGenerator::GetCachedCreateClosureSlot(
    5850     5709678 :     FunctionLiteral* literal) {
    5851             :   FeedbackSlotKind slot_kind = FeedbackSlotKind::kCreateClosure;
    5852             :   FeedbackSlot slot = feedback_slot_cache()->Get(slot_kind, literal);
    5853     2854842 :   if (!slot.IsInvalid()) {
    5854           0 :     return slot;
    5855             :   }
    5856     2854842 :   slot = feedback_spec()->AddCreateClosureSlot();
    5857             :   feedback_slot_cache()->Put(slot_kind, literal, slot);
    5858     2855031 :   return slot;
    5859             : }
    5860             : 
    5861           0 : FeedbackSlot BytecodeGenerator::GetDummyCompareICSlot() {
    5862        1671 :   return dummy_feedback_slot_.Get();
    5863             : }
    5864             : 
    5865             : Runtime::FunctionId BytecodeGenerator::StoreToSuperRuntimeId() {
    5866             :   return is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict
    5867         265 :                                     : Runtime::kStoreToSuper_Sloppy;
    5868             : }
    5869             : 
    5870             : Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() {
    5871             :   return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict
    5872         430 :                                     : Runtime::kStoreKeyedToSuper_Sloppy;
    5873             : }
    5874             : 
    5875             : }  // namespace interpreter
    5876             : }  // namespace internal
    5877      183867 : }  // namespace v8

Generated by: LCOV version 1.10