11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-generator.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <map>
81cb0ef41Sopenharmony_ci#include <unordered_map>
91cb0ef41Sopenharmony_ci#include <unordered_set>
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci#include "include/v8-extension.h"
121cb0ef41Sopenharmony_ci#include "src/api/api-inl.h"
131cb0ef41Sopenharmony_ci#include "src/ast/ast-source-ranges.h"
141cb0ef41Sopenharmony_ci#include "src/ast/ast.h"
151cb0ef41Sopenharmony_ci#include "src/ast/scopes.h"
161cb0ef41Sopenharmony_ci#include "src/builtins/builtins-constructor.h"
171cb0ef41Sopenharmony_ci#include "src/codegen/compiler.h"
181cb0ef41Sopenharmony_ci#include "src/codegen/unoptimized-compilation-info.h"
191cb0ef41Sopenharmony_ci#include "src/common/globals.h"
201cb0ef41Sopenharmony_ci#include "src/compiler-dispatcher/lazy-compile-dispatcher.h"
211cb0ef41Sopenharmony_ci#include "src/heap/parked-scope.h"
221cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-flags.h"
231cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-jump-table.h"
241cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-label.h"
251cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-register-allocator.h"
261cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-register.h"
271cb0ef41Sopenharmony_ci#include "src/interpreter/control-flow-builders.h"
281cb0ef41Sopenharmony_ci#include "src/logging/local-logger.h"
291cb0ef41Sopenharmony_ci#include "src/logging/log.h"
301cb0ef41Sopenharmony_ci#include "src/numbers/conversions.h"
311cb0ef41Sopenharmony_ci#include "src/objects/debug-objects.h"
321cb0ef41Sopenharmony_ci#include "src/objects/literal-objects-inl.h"
331cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
341cb0ef41Sopenharmony_ci#include "src/objects/smi.h"
351cb0ef41Sopenharmony_ci#include "src/objects/template-objects-inl.h"
361cb0ef41Sopenharmony_ci#include "src/parsing/parse-info.h"
371cb0ef41Sopenharmony_ci#include "src/parsing/token.h"
381cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h"
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_cinamespace v8 {
411cb0ef41Sopenharmony_cinamespace internal {
421cb0ef41Sopenharmony_cinamespace interpreter {
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci// Scoped class tracking context objects created by the visitor. Represents
451cb0ef41Sopenharmony_ci// mutations of the context chain within the function body, allowing pushing and
461cb0ef41Sopenharmony_ci// popping of the current {context_register} during visitation.
471cb0ef41Sopenharmony_ciclass V8_NODISCARD BytecodeGenerator::ContextScope {
481cb0ef41Sopenharmony_ci public:
491cb0ef41Sopenharmony_ci  ContextScope(BytecodeGenerator* generator, Scope* scope,
501cb0ef41Sopenharmony_ci               Register outer_context_reg = Register())
511cb0ef41Sopenharmony_ci      : generator_(generator),
521cb0ef41Sopenharmony_ci        scope_(scope),
531cb0ef41Sopenharmony_ci        outer_(generator_->execution_context()),
541cb0ef41Sopenharmony_ci        register_(Register::current_context()),
551cb0ef41Sopenharmony_ci        depth_(0) {
561cb0ef41Sopenharmony_ci    DCHECK(scope->NeedsContext() || outer_ == nullptr);
571cb0ef41Sopenharmony_ci    if (outer_) {
581cb0ef41Sopenharmony_ci      depth_ = outer_->depth_ + 1;
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci      // Push the outer context into a new context register.
611cb0ef41Sopenharmony_ci      if (!outer_context_reg.is_valid()) {
621cb0ef41Sopenharmony_ci        outer_context_reg = generator_->register_allocator()->NewRegister();
631cb0ef41Sopenharmony_ci      }
641cb0ef41Sopenharmony_ci      outer_->set_register(outer_context_reg);
651cb0ef41Sopenharmony_ci      generator_->builder()->PushContext(outer_context_reg);
661cb0ef41Sopenharmony_ci    }
671cb0ef41Sopenharmony_ci    generator_->set_execution_context(this);
681cb0ef41Sopenharmony_ci  }
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  ~ContextScope() {
711cb0ef41Sopenharmony_ci    if (outer_) {
721cb0ef41Sopenharmony_ci      DCHECK_EQ(register_.index(), Register::current_context().index());
731cb0ef41Sopenharmony_ci      generator_->builder()->PopContext(outer_->reg());
741cb0ef41Sopenharmony_ci      outer_->set_register(register_);
751cb0ef41Sopenharmony_ci    }
761cb0ef41Sopenharmony_ci    generator_->set_execution_context(outer_);
771cb0ef41Sopenharmony_ci  }
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  ContextScope(const ContextScope&) = delete;
801cb0ef41Sopenharmony_ci  ContextScope& operator=(const ContextScope&) = delete;
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  // Returns the depth of the given |scope| for the current execution context.
831cb0ef41Sopenharmony_ci  int ContextChainDepth(Scope* scope) {
841cb0ef41Sopenharmony_ci    return scope_->ContextChainLength(scope);
851cb0ef41Sopenharmony_ci  }
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  // Returns the execution context at |depth| in the current context chain if it
881cb0ef41Sopenharmony_ci  // is a function local execution context, otherwise returns nullptr.
891cb0ef41Sopenharmony_ci  ContextScope* Previous(int depth) {
901cb0ef41Sopenharmony_ci    if (depth > depth_) {
911cb0ef41Sopenharmony_ci      return nullptr;
921cb0ef41Sopenharmony_ci    }
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci    ContextScope* previous = this;
951cb0ef41Sopenharmony_ci    for (int i = depth; i > 0; --i) {
961cb0ef41Sopenharmony_ci      previous = previous->outer_;
971cb0ef41Sopenharmony_ci    }
981cb0ef41Sopenharmony_ci    return previous;
991cb0ef41Sopenharmony_ci  }
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  Register reg() const { return register_; }
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci private:
1041cb0ef41Sopenharmony_ci  const BytecodeArrayBuilder* builder() const { return generator_->builder(); }
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  void set_register(Register reg) { register_ = reg; }
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  BytecodeGenerator* generator_;
1091cb0ef41Sopenharmony_ci  Scope* scope_;
1101cb0ef41Sopenharmony_ci  ContextScope* outer_;
1111cb0ef41Sopenharmony_ci  Register register_;
1121cb0ef41Sopenharmony_ci  int depth_;
1131cb0ef41Sopenharmony_ci};
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci// Scoped class for tracking control statements entered by the
1161cb0ef41Sopenharmony_ci// visitor.
1171cb0ef41Sopenharmony_ciclass V8_NODISCARD BytecodeGenerator::ControlScope {
1181cb0ef41Sopenharmony_ci public:
1191cb0ef41Sopenharmony_ci  explicit ControlScope(BytecodeGenerator* generator)
1201cb0ef41Sopenharmony_ci      : generator_(generator),
1211cb0ef41Sopenharmony_ci        outer_(generator->execution_control()),
1221cb0ef41Sopenharmony_ci        context_(generator->execution_context()) {
1231cb0ef41Sopenharmony_ci    generator_->set_execution_control(this);
1241cb0ef41Sopenharmony_ci  }
1251cb0ef41Sopenharmony_ci  ~ControlScope() { generator_->set_execution_control(outer()); }
1261cb0ef41Sopenharmony_ci  ControlScope(const ControlScope&) = delete;
1271cb0ef41Sopenharmony_ci  ControlScope& operator=(const ControlScope&) = delete;
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci  void Break(Statement* stmt) {
1301cb0ef41Sopenharmony_ci    PerformCommand(CMD_BREAK, stmt, kNoSourcePosition);
1311cb0ef41Sopenharmony_ci  }
1321cb0ef41Sopenharmony_ci  void Continue(Statement* stmt) {
1331cb0ef41Sopenharmony_ci    PerformCommand(CMD_CONTINUE, stmt, kNoSourcePosition);
1341cb0ef41Sopenharmony_ci  }
1351cb0ef41Sopenharmony_ci  void ReturnAccumulator(int source_position) {
1361cb0ef41Sopenharmony_ci    PerformCommand(CMD_RETURN, nullptr, source_position);
1371cb0ef41Sopenharmony_ci  }
1381cb0ef41Sopenharmony_ci  void AsyncReturnAccumulator(int source_position) {
1391cb0ef41Sopenharmony_ci    PerformCommand(CMD_ASYNC_RETURN, nullptr, source_position);
1401cb0ef41Sopenharmony_ci  }
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  class DeferredCommands;
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci protected:
1451cb0ef41Sopenharmony_ci  enum Command {
1461cb0ef41Sopenharmony_ci    CMD_BREAK,
1471cb0ef41Sopenharmony_ci    CMD_CONTINUE,
1481cb0ef41Sopenharmony_ci    CMD_RETURN,
1491cb0ef41Sopenharmony_ci    CMD_ASYNC_RETURN,
1501cb0ef41Sopenharmony_ci    CMD_RETHROW
1511cb0ef41Sopenharmony_ci  };
1521cb0ef41Sopenharmony_ci  static constexpr bool CommandUsesAccumulator(Command command) {
1531cb0ef41Sopenharmony_ci    return command != CMD_BREAK && command != CMD_CONTINUE;
1541cb0ef41Sopenharmony_ci  }
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci  void PerformCommand(Command command, Statement* statement,
1571cb0ef41Sopenharmony_ci                      int source_position);
1581cb0ef41Sopenharmony_ci  virtual bool Execute(Command command, Statement* statement,
1591cb0ef41Sopenharmony_ci                       int source_position) = 0;
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  // Helper to pop the context chain to a depth expected by this control scope.
1621cb0ef41Sopenharmony_ci  // Note that it is the responsibility of each individual {Execute} method to
1631cb0ef41Sopenharmony_ci  // trigger this when commands are handled and control-flow continues locally.
1641cb0ef41Sopenharmony_ci  void PopContextToExpectedDepth();
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci  BytecodeGenerator* generator() const { return generator_; }
1671cb0ef41Sopenharmony_ci  ControlScope* outer() const { return outer_; }
1681cb0ef41Sopenharmony_ci  ContextScope* context() const { return context_; }
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci private:
1711cb0ef41Sopenharmony_ci  BytecodeGenerator* generator_;
1721cb0ef41Sopenharmony_ci  ControlScope* outer_;
1731cb0ef41Sopenharmony_ci  ContextScope* context_;
1741cb0ef41Sopenharmony_ci};
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci// Helper class for a try-finally control scope. It can record intercepted
1771cb0ef41Sopenharmony_ci// control-flow commands that cause entry into a finally-block, and re-apply
1781cb0ef41Sopenharmony_ci// them after again leaving that block. Special tokens are used to identify
1791cb0ef41Sopenharmony_ci// paths going through the finally-block to dispatch after leaving the block.
1801cb0ef41Sopenharmony_ciclass V8_NODISCARD BytecodeGenerator::ControlScope::DeferredCommands final {
1811cb0ef41Sopenharmony_ci public:
1821cb0ef41Sopenharmony_ci  // Fixed value tokens for paths we know we need.
1831cb0ef41Sopenharmony_ci  // Fallthrough is set to -1 to make it the fallthrough case of the jump table,
1841cb0ef41Sopenharmony_ci  // where the remaining cases start at 0.
1851cb0ef41Sopenharmony_ci  static const int kFallthroughToken = -1;
1861cb0ef41Sopenharmony_ci  // TODO(leszeks): Rethrow being 0 makes it use up a valuable LdaZero, which
1871cb0ef41Sopenharmony_ci  // means that other commands (such as break or return) have to use LdaSmi.
1881cb0ef41Sopenharmony_ci  // This can very slightly bloat bytecode, so perhaps token values should all
1891cb0ef41Sopenharmony_ci  // be shifted down by 1.
1901cb0ef41Sopenharmony_ci  static const int kRethrowToken = 0;
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci  DeferredCommands(BytecodeGenerator* generator, Register token_register,
1931cb0ef41Sopenharmony_ci                   Register result_register)
1941cb0ef41Sopenharmony_ci      : generator_(generator),
1951cb0ef41Sopenharmony_ci        deferred_(generator->zone()),
1961cb0ef41Sopenharmony_ci        token_register_(token_register),
1971cb0ef41Sopenharmony_ci        result_register_(result_register),
1981cb0ef41Sopenharmony_ci        return_token_(-1),
1991cb0ef41Sopenharmony_ci        async_return_token_(-1) {
2001cb0ef41Sopenharmony_ci    // There's always a rethrow path.
2011cb0ef41Sopenharmony_ci    // TODO(leszeks): We could decouple deferred_ index and token to allow us
2021cb0ef41Sopenharmony_ci    // to still push this lazily.
2031cb0ef41Sopenharmony_ci    STATIC_ASSERT(kRethrowToken == 0);
2041cb0ef41Sopenharmony_ci    deferred_.push_back({CMD_RETHROW, nullptr, kRethrowToken});
2051cb0ef41Sopenharmony_ci  }
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ci  // One recorded control-flow command.
2081cb0ef41Sopenharmony_ci  struct Entry {
2091cb0ef41Sopenharmony_ci    Command command;       // The command type being applied on this path.
2101cb0ef41Sopenharmony_ci    Statement* statement;  // The target statement for the command or {nullptr}.
2111cb0ef41Sopenharmony_ci    int token;             // A token identifying this particular path.
2121cb0ef41Sopenharmony_ci  };
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci  // Records a control-flow command while entering the finally-block. This also
2151cb0ef41Sopenharmony_ci  // generates a new dispatch token that identifies one particular path. This
2161cb0ef41Sopenharmony_ci  // expects the result to be in the accumulator.
2171cb0ef41Sopenharmony_ci  void RecordCommand(Command command, Statement* statement) {
2181cb0ef41Sopenharmony_ci    int token = GetTokenForCommand(command, statement);
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci    DCHECK_LT(token, deferred_.size());
2211cb0ef41Sopenharmony_ci    DCHECK_EQ(deferred_[token].command, command);
2221cb0ef41Sopenharmony_ci    DCHECK_EQ(deferred_[token].statement, statement);
2231cb0ef41Sopenharmony_ci    DCHECK_EQ(deferred_[token].token, token);
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci    if (CommandUsesAccumulator(command)) {
2261cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(result_register_);
2271cb0ef41Sopenharmony_ci    }
2281cb0ef41Sopenharmony_ci    builder()->LoadLiteral(Smi::FromInt(token));
2291cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(token_register_);
2301cb0ef41Sopenharmony_ci    if (!CommandUsesAccumulator(command)) {
2311cb0ef41Sopenharmony_ci      // If we're not saving the accumulator in the result register, shove a
2321cb0ef41Sopenharmony_ci      // harmless value there instead so that it is still considered "killed" in
2331cb0ef41Sopenharmony_ci      // the liveness analysis. Normally we would LdaUndefined first, but the
2341cb0ef41Sopenharmony_ci      // Smi token value is just as good, and by reusing it we save a bytecode.
2351cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(result_register_);
2361cb0ef41Sopenharmony_ci    }
2371cb0ef41Sopenharmony_ci  }
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci  // Records the dispatch token to be used to identify the re-throw path when
2401cb0ef41Sopenharmony_ci  // the finally-block has been entered through the exception handler. This
2411cb0ef41Sopenharmony_ci  // expects the exception to be in the accumulator.
2421cb0ef41Sopenharmony_ci  void RecordHandlerReThrowPath() {
2431cb0ef41Sopenharmony_ci    // The accumulator contains the exception object.
2441cb0ef41Sopenharmony_ci    RecordCommand(CMD_RETHROW, nullptr);
2451cb0ef41Sopenharmony_ci  }
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci  // Records the dispatch token to be used to identify the implicit fall-through
2481cb0ef41Sopenharmony_ci  // path at the end of a try-block into the corresponding finally-block.
2491cb0ef41Sopenharmony_ci  void RecordFallThroughPath() {
2501cb0ef41Sopenharmony_ci    builder()->LoadLiteral(Smi::FromInt(kFallthroughToken));
2511cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(token_register_);
2521cb0ef41Sopenharmony_ci    // Since we're not saving the accumulator in the result register, shove a
2531cb0ef41Sopenharmony_ci    // harmless value there instead so that it is still considered "killed" in
2541cb0ef41Sopenharmony_ci    // the liveness analysis. Normally we would LdaUndefined first, but the Smi
2551cb0ef41Sopenharmony_ci    // token value is just as good, and by reusing it we save a bytecode.
2561cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(result_register_);
2571cb0ef41Sopenharmony_ci  }
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci  // Applies all recorded control-flow commands after the finally-block again.
2601cb0ef41Sopenharmony_ci  // This generates a dynamic dispatch on the token from the entry point.
2611cb0ef41Sopenharmony_ci  void ApplyDeferredCommands() {
2621cb0ef41Sopenharmony_ci    if (deferred_.size() == 0) return;
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_ci    BytecodeLabel fall_through;
2651cb0ef41Sopenharmony_ci
2661cb0ef41Sopenharmony_ci    if (deferred_.size() == 1) {
2671cb0ef41Sopenharmony_ci      // For a single entry, just jump to the fallthrough if we don't match the
2681cb0ef41Sopenharmony_ci      // entry token.
2691cb0ef41Sopenharmony_ci      const Entry& entry = deferred_[0];
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci      builder()
2721cb0ef41Sopenharmony_ci          ->LoadLiteral(Smi::FromInt(entry.token))
2731cb0ef41Sopenharmony_ci          .CompareReference(token_register_)
2741cb0ef41Sopenharmony_ci          .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &fall_through);
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci      if (CommandUsesAccumulator(entry.command)) {
2771cb0ef41Sopenharmony_ci        builder()->LoadAccumulatorWithRegister(result_register_);
2781cb0ef41Sopenharmony_ci      }
2791cb0ef41Sopenharmony_ci      execution_control()->PerformCommand(entry.command, entry.statement,
2801cb0ef41Sopenharmony_ci                                          kNoSourcePosition);
2811cb0ef41Sopenharmony_ci    } else {
2821cb0ef41Sopenharmony_ci      // For multiple entries, build a jump table and switch on the token,
2831cb0ef41Sopenharmony_ci      // jumping to the fallthrough if none of them match.
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci      BytecodeJumpTable* jump_table =
2861cb0ef41Sopenharmony_ci          builder()->AllocateJumpTable(static_cast<int>(deferred_.size()), 0);
2871cb0ef41Sopenharmony_ci      builder()
2881cb0ef41Sopenharmony_ci          ->LoadAccumulatorWithRegister(token_register_)
2891cb0ef41Sopenharmony_ci          .SwitchOnSmiNoFeedback(jump_table)
2901cb0ef41Sopenharmony_ci          .Jump(&fall_through);
2911cb0ef41Sopenharmony_ci      for (const Entry& entry : deferred_) {
2921cb0ef41Sopenharmony_ci        builder()->Bind(jump_table, entry.token);
2931cb0ef41Sopenharmony_ci
2941cb0ef41Sopenharmony_ci        if (CommandUsesAccumulator(entry.command)) {
2951cb0ef41Sopenharmony_ci          builder()->LoadAccumulatorWithRegister(result_register_);
2961cb0ef41Sopenharmony_ci        }
2971cb0ef41Sopenharmony_ci        execution_control()->PerformCommand(entry.command, entry.statement,
2981cb0ef41Sopenharmony_ci                                            kNoSourcePosition);
2991cb0ef41Sopenharmony_ci      }
3001cb0ef41Sopenharmony_ci    }
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci    builder()->Bind(&fall_through);
3031cb0ef41Sopenharmony_ci  }
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_ci  BytecodeArrayBuilder* builder() { return generator_->builder(); }
3061cb0ef41Sopenharmony_ci  ControlScope* execution_control() { return generator_->execution_control(); }
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci private:
3091cb0ef41Sopenharmony_ci  int GetTokenForCommand(Command command, Statement* statement) {
3101cb0ef41Sopenharmony_ci    switch (command) {
3111cb0ef41Sopenharmony_ci      case CMD_RETURN:
3121cb0ef41Sopenharmony_ci        return GetReturnToken();
3131cb0ef41Sopenharmony_ci      case CMD_ASYNC_RETURN:
3141cb0ef41Sopenharmony_ci        return GetAsyncReturnToken();
3151cb0ef41Sopenharmony_ci      case CMD_RETHROW:
3161cb0ef41Sopenharmony_ci        return kRethrowToken;
3171cb0ef41Sopenharmony_ci      default:
3181cb0ef41Sopenharmony_ci        // TODO(leszeks): We could also search for entries with the same
3191cb0ef41Sopenharmony_ci        // command and statement.
3201cb0ef41Sopenharmony_ci        return GetNewTokenForCommand(command, statement);
3211cb0ef41Sopenharmony_ci    }
3221cb0ef41Sopenharmony_ci  }
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci  int GetReturnToken() {
3251cb0ef41Sopenharmony_ci    if (return_token_ == -1) {
3261cb0ef41Sopenharmony_ci      return_token_ = GetNewTokenForCommand(CMD_RETURN, nullptr);
3271cb0ef41Sopenharmony_ci    }
3281cb0ef41Sopenharmony_ci    return return_token_;
3291cb0ef41Sopenharmony_ci  }
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_ci  int GetAsyncReturnToken() {
3321cb0ef41Sopenharmony_ci    if (async_return_token_ == -1) {
3331cb0ef41Sopenharmony_ci      async_return_token_ = GetNewTokenForCommand(CMD_ASYNC_RETURN, nullptr);
3341cb0ef41Sopenharmony_ci    }
3351cb0ef41Sopenharmony_ci    return async_return_token_;
3361cb0ef41Sopenharmony_ci  }
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_ci  int GetNewTokenForCommand(Command command, Statement* statement) {
3391cb0ef41Sopenharmony_ci    int token = static_cast<int>(deferred_.size());
3401cb0ef41Sopenharmony_ci    deferred_.push_back({command, statement, token});
3411cb0ef41Sopenharmony_ci    return token;
3421cb0ef41Sopenharmony_ci  }
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ci  BytecodeGenerator* generator_;
3451cb0ef41Sopenharmony_ci  ZoneVector<Entry> deferred_;
3461cb0ef41Sopenharmony_ci  Register token_register_;
3471cb0ef41Sopenharmony_ci  Register result_register_;
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ci  // Tokens for commands that don't need a statement.
3501cb0ef41Sopenharmony_ci  int return_token_;
3511cb0ef41Sopenharmony_ci  int async_return_token_;
3521cb0ef41Sopenharmony_ci};
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci// Scoped class for dealing with control flow reaching the function level.
3551cb0ef41Sopenharmony_ciclass BytecodeGenerator::ControlScopeForTopLevel final
3561cb0ef41Sopenharmony_ci    : public BytecodeGenerator::ControlScope {
3571cb0ef41Sopenharmony_ci public:
3581cb0ef41Sopenharmony_ci  explicit ControlScopeForTopLevel(BytecodeGenerator* generator)
3591cb0ef41Sopenharmony_ci      : ControlScope(generator) {}
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci protected:
3621cb0ef41Sopenharmony_ci  bool Execute(Command command, Statement* statement,
3631cb0ef41Sopenharmony_ci               int source_position) override {
3641cb0ef41Sopenharmony_ci    switch (command) {
3651cb0ef41Sopenharmony_ci      case CMD_BREAK:  // We should never see break/continue in top-level.
3661cb0ef41Sopenharmony_ci      case CMD_CONTINUE:
3671cb0ef41Sopenharmony_ci        UNREACHABLE();
3681cb0ef41Sopenharmony_ci      case CMD_RETURN:
3691cb0ef41Sopenharmony_ci        // No need to pop contexts, execution leaves the method body.
3701cb0ef41Sopenharmony_ci        generator()->BuildReturn(source_position);
3711cb0ef41Sopenharmony_ci        return true;
3721cb0ef41Sopenharmony_ci      case CMD_ASYNC_RETURN:
3731cb0ef41Sopenharmony_ci        // No need to pop contexts, execution leaves the method body.
3741cb0ef41Sopenharmony_ci        generator()->BuildAsyncReturn(source_position);
3751cb0ef41Sopenharmony_ci        return true;
3761cb0ef41Sopenharmony_ci      case CMD_RETHROW:
3771cb0ef41Sopenharmony_ci        // No need to pop contexts, execution leaves the method body.
3781cb0ef41Sopenharmony_ci        generator()->BuildReThrow();
3791cb0ef41Sopenharmony_ci        return true;
3801cb0ef41Sopenharmony_ci    }
3811cb0ef41Sopenharmony_ci    return false;
3821cb0ef41Sopenharmony_ci  }
3831cb0ef41Sopenharmony_ci};
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ci// Scoped class for enabling break inside blocks and switch blocks.
3861cb0ef41Sopenharmony_ciclass BytecodeGenerator::ControlScopeForBreakable final
3871cb0ef41Sopenharmony_ci    : public BytecodeGenerator::ControlScope {
3881cb0ef41Sopenharmony_ci public:
3891cb0ef41Sopenharmony_ci  ControlScopeForBreakable(BytecodeGenerator* generator,
3901cb0ef41Sopenharmony_ci                           BreakableStatement* statement,
3911cb0ef41Sopenharmony_ci                           BreakableControlFlowBuilder* control_builder)
3921cb0ef41Sopenharmony_ci      : ControlScope(generator),
3931cb0ef41Sopenharmony_ci        statement_(statement),
3941cb0ef41Sopenharmony_ci        control_builder_(control_builder) {}
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_ci protected:
3971cb0ef41Sopenharmony_ci  bool Execute(Command command, Statement* statement,
3981cb0ef41Sopenharmony_ci               int source_position) override {
3991cb0ef41Sopenharmony_ci    if (statement != statement_) return false;
4001cb0ef41Sopenharmony_ci    switch (command) {
4011cb0ef41Sopenharmony_ci      case CMD_BREAK:
4021cb0ef41Sopenharmony_ci        PopContextToExpectedDepth();
4031cb0ef41Sopenharmony_ci        control_builder_->Break();
4041cb0ef41Sopenharmony_ci        return true;
4051cb0ef41Sopenharmony_ci      case CMD_CONTINUE:
4061cb0ef41Sopenharmony_ci      case CMD_RETURN:
4071cb0ef41Sopenharmony_ci      case CMD_ASYNC_RETURN:
4081cb0ef41Sopenharmony_ci      case CMD_RETHROW:
4091cb0ef41Sopenharmony_ci        break;
4101cb0ef41Sopenharmony_ci    }
4111cb0ef41Sopenharmony_ci    return false;
4121cb0ef41Sopenharmony_ci  }
4131cb0ef41Sopenharmony_ci
4141cb0ef41Sopenharmony_ci private:
4151cb0ef41Sopenharmony_ci  Statement* statement_;
4161cb0ef41Sopenharmony_ci  BreakableControlFlowBuilder* control_builder_;
4171cb0ef41Sopenharmony_ci};
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci// Scoped class for enabling 'break' and 'continue' in iteration
4201cb0ef41Sopenharmony_ci// constructs, e.g. do...while, while..., for...
4211cb0ef41Sopenharmony_ciclass BytecodeGenerator::ControlScopeForIteration final
4221cb0ef41Sopenharmony_ci    : public BytecodeGenerator::ControlScope {
4231cb0ef41Sopenharmony_ci public:
4241cb0ef41Sopenharmony_ci  ControlScopeForIteration(BytecodeGenerator* generator,
4251cb0ef41Sopenharmony_ci                           IterationStatement* statement,
4261cb0ef41Sopenharmony_ci                           LoopBuilder* loop_builder)
4271cb0ef41Sopenharmony_ci      : ControlScope(generator),
4281cb0ef41Sopenharmony_ci        statement_(statement),
4291cb0ef41Sopenharmony_ci        loop_builder_(loop_builder) {}
4301cb0ef41Sopenharmony_ci
4311cb0ef41Sopenharmony_ci protected:
4321cb0ef41Sopenharmony_ci  bool Execute(Command command, Statement* statement,
4331cb0ef41Sopenharmony_ci               int source_position) override {
4341cb0ef41Sopenharmony_ci    if (statement != statement_) return false;
4351cb0ef41Sopenharmony_ci    switch (command) {
4361cb0ef41Sopenharmony_ci      case CMD_BREAK:
4371cb0ef41Sopenharmony_ci        PopContextToExpectedDepth();
4381cb0ef41Sopenharmony_ci        loop_builder_->Break();
4391cb0ef41Sopenharmony_ci        return true;
4401cb0ef41Sopenharmony_ci      case CMD_CONTINUE:
4411cb0ef41Sopenharmony_ci        PopContextToExpectedDepth();
4421cb0ef41Sopenharmony_ci        loop_builder_->Continue();
4431cb0ef41Sopenharmony_ci        return true;
4441cb0ef41Sopenharmony_ci      case CMD_RETURN:
4451cb0ef41Sopenharmony_ci      case CMD_ASYNC_RETURN:
4461cb0ef41Sopenharmony_ci      case CMD_RETHROW:
4471cb0ef41Sopenharmony_ci        break;
4481cb0ef41Sopenharmony_ci    }
4491cb0ef41Sopenharmony_ci    return false;
4501cb0ef41Sopenharmony_ci  }
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_ci private:
4531cb0ef41Sopenharmony_ci  Statement* statement_;
4541cb0ef41Sopenharmony_ci  LoopBuilder* loop_builder_;
4551cb0ef41Sopenharmony_ci};
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ci// Scoped class for enabling 'throw' in try-catch constructs.
4581cb0ef41Sopenharmony_ciclass BytecodeGenerator::ControlScopeForTryCatch final
4591cb0ef41Sopenharmony_ci    : public BytecodeGenerator::ControlScope {
4601cb0ef41Sopenharmony_ci public:
4611cb0ef41Sopenharmony_ci  ControlScopeForTryCatch(BytecodeGenerator* generator,
4621cb0ef41Sopenharmony_ci                          TryCatchBuilder* try_catch_builder)
4631cb0ef41Sopenharmony_ci      : ControlScope(generator) {}
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ci protected:
4661cb0ef41Sopenharmony_ci  bool Execute(Command command, Statement* statement,
4671cb0ef41Sopenharmony_ci               int source_position) override {
4681cb0ef41Sopenharmony_ci    switch (command) {
4691cb0ef41Sopenharmony_ci      case CMD_BREAK:
4701cb0ef41Sopenharmony_ci      case CMD_CONTINUE:
4711cb0ef41Sopenharmony_ci      case CMD_RETURN:
4721cb0ef41Sopenharmony_ci      case CMD_ASYNC_RETURN:
4731cb0ef41Sopenharmony_ci        break;
4741cb0ef41Sopenharmony_ci      case CMD_RETHROW:
4751cb0ef41Sopenharmony_ci        // No need to pop contexts, execution re-enters the method body via the
4761cb0ef41Sopenharmony_ci        // stack unwinding mechanism which itself restores contexts correctly.
4771cb0ef41Sopenharmony_ci        generator()->BuildReThrow();
4781cb0ef41Sopenharmony_ci        return true;
4791cb0ef41Sopenharmony_ci    }
4801cb0ef41Sopenharmony_ci    return false;
4811cb0ef41Sopenharmony_ci  }
4821cb0ef41Sopenharmony_ci};
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_ci// Scoped class for enabling control flow through try-finally constructs.
4851cb0ef41Sopenharmony_ciclass BytecodeGenerator::ControlScopeForTryFinally final
4861cb0ef41Sopenharmony_ci    : public BytecodeGenerator::ControlScope {
4871cb0ef41Sopenharmony_ci public:
4881cb0ef41Sopenharmony_ci  ControlScopeForTryFinally(BytecodeGenerator* generator,
4891cb0ef41Sopenharmony_ci                            TryFinallyBuilder* try_finally_builder,
4901cb0ef41Sopenharmony_ci                            DeferredCommands* commands)
4911cb0ef41Sopenharmony_ci      : ControlScope(generator),
4921cb0ef41Sopenharmony_ci        try_finally_builder_(try_finally_builder),
4931cb0ef41Sopenharmony_ci        commands_(commands) {}
4941cb0ef41Sopenharmony_ci
4951cb0ef41Sopenharmony_ci protected:
4961cb0ef41Sopenharmony_ci  bool Execute(Command command, Statement* statement,
4971cb0ef41Sopenharmony_ci               int source_position) override {
4981cb0ef41Sopenharmony_ci    switch (command) {
4991cb0ef41Sopenharmony_ci      case CMD_BREAK:
5001cb0ef41Sopenharmony_ci      case CMD_CONTINUE:
5011cb0ef41Sopenharmony_ci      case CMD_RETURN:
5021cb0ef41Sopenharmony_ci      case CMD_ASYNC_RETURN:
5031cb0ef41Sopenharmony_ci      case CMD_RETHROW:
5041cb0ef41Sopenharmony_ci        PopContextToExpectedDepth();
5051cb0ef41Sopenharmony_ci        // We don't record source_position here since we don't generate return
5061cb0ef41Sopenharmony_ci        // bytecode right here and will generate it later as part of finally
5071cb0ef41Sopenharmony_ci        // block. Each return bytecode generated in finally block will get own
5081cb0ef41Sopenharmony_ci        // return source position from corresponded return statement or we'll
5091cb0ef41Sopenharmony_ci        // use end of function if no return statement is presented.
5101cb0ef41Sopenharmony_ci        commands_->RecordCommand(command, statement);
5111cb0ef41Sopenharmony_ci        try_finally_builder_->LeaveTry();
5121cb0ef41Sopenharmony_ci        return true;
5131cb0ef41Sopenharmony_ci    }
5141cb0ef41Sopenharmony_ci    return false;
5151cb0ef41Sopenharmony_ci  }
5161cb0ef41Sopenharmony_ci
5171cb0ef41Sopenharmony_ci private:
5181cb0ef41Sopenharmony_ci  TryFinallyBuilder* try_finally_builder_;
5191cb0ef41Sopenharmony_ci  DeferredCommands* commands_;
5201cb0ef41Sopenharmony_ci};
5211cb0ef41Sopenharmony_ci
5221cb0ef41Sopenharmony_ci// Allocate and fetch the coverage indices tracking NaryLogical Expressions.
5231cb0ef41Sopenharmony_ciclass BytecodeGenerator::NaryCodeCoverageSlots {
5241cb0ef41Sopenharmony_ci public:
5251cb0ef41Sopenharmony_ci  NaryCodeCoverageSlots(BytecodeGenerator* generator, NaryOperation* expr)
5261cb0ef41Sopenharmony_ci      : generator_(generator) {
5271cb0ef41Sopenharmony_ci    if (generator_->block_coverage_builder_ == nullptr) return;
5281cb0ef41Sopenharmony_ci    for (size_t i = 0; i < expr->subsequent_length(); i++) {
5291cb0ef41Sopenharmony_ci      coverage_slots_.push_back(
5301cb0ef41Sopenharmony_ci          generator_->AllocateNaryBlockCoverageSlotIfEnabled(expr, i));
5311cb0ef41Sopenharmony_ci    }
5321cb0ef41Sopenharmony_ci  }
5331cb0ef41Sopenharmony_ci
5341cb0ef41Sopenharmony_ci  int GetSlotFor(size_t subsequent_expr_index) const {
5351cb0ef41Sopenharmony_ci    if (generator_->block_coverage_builder_ == nullptr) {
5361cb0ef41Sopenharmony_ci      return BlockCoverageBuilder::kNoCoverageArraySlot;
5371cb0ef41Sopenharmony_ci    }
5381cb0ef41Sopenharmony_ci    DCHECK(coverage_slots_.size() > subsequent_expr_index);
5391cb0ef41Sopenharmony_ci    return coverage_slots_[subsequent_expr_index];
5401cb0ef41Sopenharmony_ci  }
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_ci private:
5431cb0ef41Sopenharmony_ci  BytecodeGenerator* generator_;
5441cb0ef41Sopenharmony_ci  std::vector<int> coverage_slots_;
5451cb0ef41Sopenharmony_ci};
5461cb0ef41Sopenharmony_ci
5471cb0ef41Sopenharmony_civoid BytecodeGenerator::ControlScope::PerformCommand(Command command,
5481cb0ef41Sopenharmony_ci                                                     Statement* statement,
5491cb0ef41Sopenharmony_ci                                                     int source_position) {
5501cb0ef41Sopenharmony_ci  ControlScope* current = this;
5511cb0ef41Sopenharmony_ci  do {
5521cb0ef41Sopenharmony_ci    if (current->Execute(command, statement, source_position)) {
5531cb0ef41Sopenharmony_ci      return;
5541cb0ef41Sopenharmony_ci    }
5551cb0ef41Sopenharmony_ci    current = current->outer();
5561cb0ef41Sopenharmony_ci  } while (current != nullptr);
5571cb0ef41Sopenharmony_ci  UNREACHABLE();
5581cb0ef41Sopenharmony_ci}
5591cb0ef41Sopenharmony_ci
5601cb0ef41Sopenharmony_civoid BytecodeGenerator::ControlScope::PopContextToExpectedDepth() {
5611cb0ef41Sopenharmony_ci  // Pop context to the expected depth. Note that this can in fact pop multiple
5621cb0ef41Sopenharmony_ci  // contexts at once because the {PopContext} bytecode takes a saved register.
5631cb0ef41Sopenharmony_ci  if (generator()->execution_context() != context()) {
5641cb0ef41Sopenharmony_ci    generator()->builder()->PopContext(context()->reg());
5651cb0ef41Sopenharmony_ci  }
5661cb0ef41Sopenharmony_ci}
5671cb0ef41Sopenharmony_ci
5681cb0ef41Sopenharmony_ciclass V8_NODISCARD BytecodeGenerator::RegisterAllocationScope final {
5691cb0ef41Sopenharmony_ci public:
5701cb0ef41Sopenharmony_ci  explicit RegisterAllocationScope(BytecodeGenerator* generator)
5711cb0ef41Sopenharmony_ci      : generator_(generator),
5721cb0ef41Sopenharmony_ci        outer_next_register_index_(
5731cb0ef41Sopenharmony_ci            generator->register_allocator()->next_register_index()) {}
5741cb0ef41Sopenharmony_ci
5751cb0ef41Sopenharmony_ci  ~RegisterAllocationScope() {
5761cb0ef41Sopenharmony_ci    generator_->register_allocator()->ReleaseRegisters(
5771cb0ef41Sopenharmony_ci        outer_next_register_index_);
5781cb0ef41Sopenharmony_ci  }
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ci  RegisterAllocationScope(const RegisterAllocationScope&) = delete;
5811cb0ef41Sopenharmony_ci  RegisterAllocationScope& operator=(const RegisterAllocationScope&) = delete;
5821cb0ef41Sopenharmony_ci
5831cb0ef41Sopenharmony_ci  BytecodeGenerator* generator() const { return generator_; }
5841cb0ef41Sopenharmony_ci
5851cb0ef41Sopenharmony_ci private:
5861cb0ef41Sopenharmony_ci  BytecodeGenerator* generator_;
5871cb0ef41Sopenharmony_ci  int outer_next_register_index_;
5881cb0ef41Sopenharmony_ci};
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ciclass V8_NODISCARD BytecodeGenerator::AccumulatorPreservingScope final {
5911cb0ef41Sopenharmony_ci public:
5921cb0ef41Sopenharmony_ci  explicit AccumulatorPreservingScope(BytecodeGenerator* generator,
5931cb0ef41Sopenharmony_ci                                      AccumulatorPreservingMode mode)
5941cb0ef41Sopenharmony_ci      : generator_(generator) {
5951cb0ef41Sopenharmony_ci    if (mode == AccumulatorPreservingMode::kPreserve) {
5961cb0ef41Sopenharmony_ci      saved_accumulator_register_ =
5971cb0ef41Sopenharmony_ci          generator_->register_allocator()->NewRegister();
5981cb0ef41Sopenharmony_ci      generator_->builder()->StoreAccumulatorInRegister(
5991cb0ef41Sopenharmony_ci          saved_accumulator_register_);
6001cb0ef41Sopenharmony_ci    }
6011cb0ef41Sopenharmony_ci  }
6021cb0ef41Sopenharmony_ci
6031cb0ef41Sopenharmony_ci  ~AccumulatorPreservingScope() {
6041cb0ef41Sopenharmony_ci    if (saved_accumulator_register_.is_valid()) {
6051cb0ef41Sopenharmony_ci      generator_->builder()->LoadAccumulatorWithRegister(
6061cb0ef41Sopenharmony_ci          saved_accumulator_register_);
6071cb0ef41Sopenharmony_ci    }
6081cb0ef41Sopenharmony_ci  }
6091cb0ef41Sopenharmony_ci
6101cb0ef41Sopenharmony_ci  AccumulatorPreservingScope(const AccumulatorPreservingScope&) = delete;
6111cb0ef41Sopenharmony_ci  AccumulatorPreservingScope& operator=(const AccumulatorPreservingScope&) =
6121cb0ef41Sopenharmony_ci      delete;
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci private:
6151cb0ef41Sopenharmony_ci  BytecodeGenerator* generator_;
6161cb0ef41Sopenharmony_ci  Register saved_accumulator_register_;
6171cb0ef41Sopenharmony_ci};
6181cb0ef41Sopenharmony_ci
6191cb0ef41Sopenharmony_ci// Scoped base class for determining how the result of an expression will be
6201cb0ef41Sopenharmony_ci// used.
6211cb0ef41Sopenharmony_ciclass V8_NODISCARD BytecodeGenerator::ExpressionResultScope {
6221cb0ef41Sopenharmony_ci public:
6231cb0ef41Sopenharmony_ci  ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind)
6241cb0ef41Sopenharmony_ci      : outer_(generator->execution_result()),
6251cb0ef41Sopenharmony_ci        allocator_(generator),
6261cb0ef41Sopenharmony_ci        kind_(kind),
6271cb0ef41Sopenharmony_ci        type_hint_(TypeHint::kAny) {
6281cb0ef41Sopenharmony_ci    generator->set_execution_result(this);
6291cb0ef41Sopenharmony_ci  }
6301cb0ef41Sopenharmony_ci
6311cb0ef41Sopenharmony_ci  ~ExpressionResultScope() {
6321cb0ef41Sopenharmony_ci    allocator_.generator()->set_execution_result(outer_);
6331cb0ef41Sopenharmony_ci  }
6341cb0ef41Sopenharmony_ci
6351cb0ef41Sopenharmony_ci  ExpressionResultScope(const ExpressionResultScope&) = delete;
6361cb0ef41Sopenharmony_ci  ExpressionResultScope& operator=(const ExpressionResultScope&) = delete;
6371cb0ef41Sopenharmony_ci
6381cb0ef41Sopenharmony_ci  bool IsEffect() const { return kind_ == Expression::kEffect; }
6391cb0ef41Sopenharmony_ci  bool IsValue() const { return kind_ == Expression::kValue; }
6401cb0ef41Sopenharmony_ci  bool IsTest() const { return kind_ == Expression::kTest; }
6411cb0ef41Sopenharmony_ci
6421cb0ef41Sopenharmony_ci  TestResultScope* AsTest() {
6431cb0ef41Sopenharmony_ci    DCHECK(IsTest());
6441cb0ef41Sopenharmony_ci    return reinterpret_cast<TestResultScope*>(this);
6451cb0ef41Sopenharmony_ci  }
6461cb0ef41Sopenharmony_ci
6471cb0ef41Sopenharmony_ci  // Specify expression always returns a Boolean result value.
6481cb0ef41Sopenharmony_ci  void SetResultIsBoolean() {
6491cb0ef41Sopenharmony_ci    DCHECK_EQ(type_hint_, TypeHint::kAny);
6501cb0ef41Sopenharmony_ci    type_hint_ = TypeHint::kBoolean;
6511cb0ef41Sopenharmony_ci  }
6521cb0ef41Sopenharmony_ci
6531cb0ef41Sopenharmony_ci  void SetResultIsString() {
6541cb0ef41Sopenharmony_ci    DCHECK_EQ(type_hint_, TypeHint::kAny);
6551cb0ef41Sopenharmony_ci    type_hint_ = TypeHint::kString;
6561cb0ef41Sopenharmony_ci  }
6571cb0ef41Sopenharmony_ci
6581cb0ef41Sopenharmony_ci  TypeHint type_hint() const { return type_hint_; }
6591cb0ef41Sopenharmony_ci
6601cb0ef41Sopenharmony_ci private:
6611cb0ef41Sopenharmony_ci  ExpressionResultScope* outer_;
6621cb0ef41Sopenharmony_ci  RegisterAllocationScope allocator_;
6631cb0ef41Sopenharmony_ci  Expression::Context kind_;
6641cb0ef41Sopenharmony_ci  TypeHint type_hint_;
6651cb0ef41Sopenharmony_ci};
6661cb0ef41Sopenharmony_ci
6671cb0ef41Sopenharmony_ci// Scoped class used when the result of the current expression is not
6681cb0ef41Sopenharmony_ci// expected to produce a result.
6691cb0ef41Sopenharmony_ciclass BytecodeGenerator::EffectResultScope final
6701cb0ef41Sopenharmony_ci    : public ExpressionResultScope {
6711cb0ef41Sopenharmony_ci public:
6721cb0ef41Sopenharmony_ci  explicit EffectResultScope(BytecodeGenerator* generator)
6731cb0ef41Sopenharmony_ci      : ExpressionResultScope(generator, Expression::kEffect) {}
6741cb0ef41Sopenharmony_ci};
6751cb0ef41Sopenharmony_ci
6761cb0ef41Sopenharmony_ci// Scoped class used when the result of the current expression to be
6771cb0ef41Sopenharmony_ci// evaluated should go into the interpreter's accumulator.
6781cb0ef41Sopenharmony_ciclass V8_NODISCARD BytecodeGenerator::ValueResultScope final
6791cb0ef41Sopenharmony_ci    : public ExpressionResultScope {
6801cb0ef41Sopenharmony_ci public:
6811cb0ef41Sopenharmony_ci  explicit ValueResultScope(BytecodeGenerator* generator)
6821cb0ef41Sopenharmony_ci      : ExpressionResultScope(generator, Expression::kValue) {}
6831cb0ef41Sopenharmony_ci};
6841cb0ef41Sopenharmony_ci
6851cb0ef41Sopenharmony_ci// Scoped class used when the result of the current expression to be
6861cb0ef41Sopenharmony_ci// evaluated is only tested with jumps to two branches.
6871cb0ef41Sopenharmony_ciclass V8_NODISCARD BytecodeGenerator::TestResultScope final
6881cb0ef41Sopenharmony_ci    : public ExpressionResultScope {
6891cb0ef41Sopenharmony_ci public:
6901cb0ef41Sopenharmony_ci  TestResultScope(BytecodeGenerator* generator, BytecodeLabels* then_labels,
6911cb0ef41Sopenharmony_ci                  BytecodeLabels* else_labels, TestFallthrough fallthrough)
6921cb0ef41Sopenharmony_ci      : ExpressionResultScope(generator, Expression::kTest),
6931cb0ef41Sopenharmony_ci        result_consumed_by_test_(false),
6941cb0ef41Sopenharmony_ci        fallthrough_(fallthrough),
6951cb0ef41Sopenharmony_ci        then_labels_(then_labels),
6961cb0ef41Sopenharmony_ci        else_labels_(else_labels) {}
6971cb0ef41Sopenharmony_ci
6981cb0ef41Sopenharmony_ci  TestResultScope(const TestResultScope&) = delete;
6991cb0ef41Sopenharmony_ci  TestResultScope& operator=(const TestResultScope&) = delete;
7001cb0ef41Sopenharmony_ci
7011cb0ef41Sopenharmony_ci  // Used when code special cases for TestResultScope and consumes any
7021cb0ef41Sopenharmony_ci  // possible value by testing and jumping to a then/else label.
7031cb0ef41Sopenharmony_ci  void SetResultConsumedByTest() { result_consumed_by_test_ = true; }
7041cb0ef41Sopenharmony_ci  bool result_consumed_by_test() { return result_consumed_by_test_; }
7051cb0ef41Sopenharmony_ci
7061cb0ef41Sopenharmony_ci  // Inverts the control flow of the operation, swapping the then and else
7071cb0ef41Sopenharmony_ci  // labels and the fallthrough.
7081cb0ef41Sopenharmony_ci  void InvertControlFlow() {
7091cb0ef41Sopenharmony_ci    std::swap(then_labels_, else_labels_);
7101cb0ef41Sopenharmony_ci    fallthrough_ = inverted_fallthrough();
7111cb0ef41Sopenharmony_ci  }
7121cb0ef41Sopenharmony_ci
7131cb0ef41Sopenharmony_ci  BytecodeLabel* NewThenLabel() { return then_labels_->New(); }
7141cb0ef41Sopenharmony_ci  BytecodeLabel* NewElseLabel() { return else_labels_->New(); }
7151cb0ef41Sopenharmony_ci
7161cb0ef41Sopenharmony_ci  BytecodeLabels* then_labels() const { return then_labels_; }
7171cb0ef41Sopenharmony_ci  BytecodeLabels* else_labels() const { return else_labels_; }
7181cb0ef41Sopenharmony_ci
7191cb0ef41Sopenharmony_ci  void set_then_labels(BytecodeLabels* then_labels) {
7201cb0ef41Sopenharmony_ci    then_labels_ = then_labels;
7211cb0ef41Sopenharmony_ci  }
7221cb0ef41Sopenharmony_ci  void set_else_labels(BytecodeLabels* else_labels) {
7231cb0ef41Sopenharmony_ci    else_labels_ = else_labels;
7241cb0ef41Sopenharmony_ci  }
7251cb0ef41Sopenharmony_ci
7261cb0ef41Sopenharmony_ci  TestFallthrough fallthrough() const { return fallthrough_; }
7271cb0ef41Sopenharmony_ci  TestFallthrough inverted_fallthrough() const {
7281cb0ef41Sopenharmony_ci    switch (fallthrough_) {
7291cb0ef41Sopenharmony_ci      case TestFallthrough::kThen:
7301cb0ef41Sopenharmony_ci        return TestFallthrough::kElse;
7311cb0ef41Sopenharmony_ci      case TestFallthrough::kElse:
7321cb0ef41Sopenharmony_ci        return TestFallthrough::kThen;
7331cb0ef41Sopenharmony_ci      default:
7341cb0ef41Sopenharmony_ci        return TestFallthrough::kNone;
7351cb0ef41Sopenharmony_ci    }
7361cb0ef41Sopenharmony_ci  }
7371cb0ef41Sopenharmony_ci  void set_fallthrough(TestFallthrough fallthrough) {
7381cb0ef41Sopenharmony_ci    fallthrough_ = fallthrough;
7391cb0ef41Sopenharmony_ci  }
7401cb0ef41Sopenharmony_ci
7411cb0ef41Sopenharmony_ci private:
7421cb0ef41Sopenharmony_ci  bool result_consumed_by_test_;
7431cb0ef41Sopenharmony_ci  TestFallthrough fallthrough_;
7441cb0ef41Sopenharmony_ci  BytecodeLabels* then_labels_;
7451cb0ef41Sopenharmony_ci  BytecodeLabels* else_labels_;
7461cb0ef41Sopenharmony_ci};
7471cb0ef41Sopenharmony_ci
7481cb0ef41Sopenharmony_ci// Used to build a list of toplevel declaration data.
7491cb0ef41Sopenharmony_ciclass BytecodeGenerator::TopLevelDeclarationsBuilder final : public ZoneObject {
7501cb0ef41Sopenharmony_ci public:
7511cb0ef41Sopenharmony_ci  template <typename IsolateT>
7521cb0ef41Sopenharmony_ci  Handle<FixedArray> AllocateDeclarations(UnoptimizedCompilationInfo* info,
7531cb0ef41Sopenharmony_ci                                          BytecodeGenerator* generator,
7541cb0ef41Sopenharmony_ci                                          Handle<Script> script,
7551cb0ef41Sopenharmony_ci                                          IsolateT* isolate) {
7561cb0ef41Sopenharmony_ci    DCHECK(has_constant_pool_entry_);
7571cb0ef41Sopenharmony_ci
7581cb0ef41Sopenharmony_ci    Handle<FixedArray> data =
7591cb0ef41Sopenharmony_ci        isolate->factory()->NewFixedArray(entry_slots_, AllocationType::kOld);
7601cb0ef41Sopenharmony_ci
7611cb0ef41Sopenharmony_ci    int array_index = 0;
7621cb0ef41Sopenharmony_ci    if (info->scope()->is_module_scope()) {
7631cb0ef41Sopenharmony_ci      for (Declaration* decl : *info->scope()->declarations()) {
7641cb0ef41Sopenharmony_ci        Variable* var = decl->var();
7651cb0ef41Sopenharmony_ci        if (!var->is_used()) continue;
7661cb0ef41Sopenharmony_ci        if (var->location() != VariableLocation::MODULE) continue;
7671cb0ef41Sopenharmony_ci#ifdef DEBUG
7681cb0ef41Sopenharmony_ci        int start = array_index;
7691cb0ef41Sopenharmony_ci#endif
7701cb0ef41Sopenharmony_ci        if (decl->IsFunctionDeclaration()) {
7711cb0ef41Sopenharmony_ci          FunctionLiteral* f = static_cast<FunctionDeclaration*>(decl)->fun();
7721cb0ef41Sopenharmony_ci          Handle<SharedFunctionInfo> sfi(
7731cb0ef41Sopenharmony_ci              Compiler::GetSharedFunctionInfo(f, script, isolate));
7741cb0ef41Sopenharmony_ci          // Return a null handle if any initial values can't be created. Caller
7751cb0ef41Sopenharmony_ci          // will set stack overflow.
7761cb0ef41Sopenharmony_ci          if (sfi.is_null()) return Handle<FixedArray>();
7771cb0ef41Sopenharmony_ci          data->set(array_index++, *sfi);
7781cb0ef41Sopenharmony_ci          int literal_index = generator->GetCachedCreateClosureSlot(f);
7791cb0ef41Sopenharmony_ci          data->set(array_index++, Smi::FromInt(literal_index));
7801cb0ef41Sopenharmony_ci          DCHECK(var->IsExport());
7811cb0ef41Sopenharmony_ci          data->set(array_index++, Smi::FromInt(var->index()));
7821cb0ef41Sopenharmony_ci          DCHECK_EQ(start + kModuleFunctionDeclarationSize, array_index);
7831cb0ef41Sopenharmony_ci        } else if (var->IsExport() && var->binding_needs_init()) {
7841cb0ef41Sopenharmony_ci          data->set(array_index++, Smi::FromInt(var->index()));
7851cb0ef41Sopenharmony_ci          DCHECK_EQ(start + kModuleVariableDeclarationSize, array_index);
7861cb0ef41Sopenharmony_ci        }
7871cb0ef41Sopenharmony_ci      }
7881cb0ef41Sopenharmony_ci    } else {
7891cb0ef41Sopenharmony_ci      for (Declaration* decl : *info->scope()->declarations()) {
7901cb0ef41Sopenharmony_ci        Variable* var = decl->var();
7911cb0ef41Sopenharmony_ci        if (!var->is_used()) continue;
7921cb0ef41Sopenharmony_ci        if (var->location() != VariableLocation::UNALLOCATED) continue;
7931cb0ef41Sopenharmony_ci#ifdef DEBUG
7941cb0ef41Sopenharmony_ci        int start = array_index;
7951cb0ef41Sopenharmony_ci#endif
7961cb0ef41Sopenharmony_ci        if (decl->IsVariableDeclaration()) {
7971cb0ef41Sopenharmony_ci          data->set(array_index++, *var->raw_name()->string());
7981cb0ef41Sopenharmony_ci          DCHECK_EQ(start + kGlobalVariableDeclarationSize, array_index);
7991cb0ef41Sopenharmony_ci        } else {
8001cb0ef41Sopenharmony_ci          FunctionLiteral* f = static_cast<FunctionDeclaration*>(decl)->fun();
8011cb0ef41Sopenharmony_ci          Handle<SharedFunctionInfo> sfi(
8021cb0ef41Sopenharmony_ci              Compiler::GetSharedFunctionInfo(f, script, isolate));
8031cb0ef41Sopenharmony_ci          // Return a null handle if any initial values can't be created. Caller
8041cb0ef41Sopenharmony_ci          // will set stack overflow.
8051cb0ef41Sopenharmony_ci          if (sfi.is_null()) return Handle<FixedArray>();
8061cb0ef41Sopenharmony_ci          data->set(array_index++, *sfi);
8071cb0ef41Sopenharmony_ci          int literal_index = generator->GetCachedCreateClosureSlot(f);
8081cb0ef41Sopenharmony_ci          data->set(array_index++, Smi::FromInt(literal_index));
8091cb0ef41Sopenharmony_ci          DCHECK_EQ(start + kGlobalFunctionDeclarationSize, array_index);
8101cb0ef41Sopenharmony_ci        }
8111cb0ef41Sopenharmony_ci      }
8121cb0ef41Sopenharmony_ci    }
8131cb0ef41Sopenharmony_ci    DCHECK_EQ(array_index, data->length());
8141cb0ef41Sopenharmony_ci    return data;
8151cb0ef41Sopenharmony_ci  }
8161cb0ef41Sopenharmony_ci
8171cb0ef41Sopenharmony_ci  size_t constant_pool_entry() {
8181cb0ef41Sopenharmony_ci    DCHECK(has_constant_pool_entry_);
8191cb0ef41Sopenharmony_ci    return constant_pool_entry_;
8201cb0ef41Sopenharmony_ci  }
8211cb0ef41Sopenharmony_ci
8221cb0ef41Sopenharmony_ci  void set_constant_pool_entry(size_t constant_pool_entry) {
8231cb0ef41Sopenharmony_ci    DCHECK(has_top_level_declaration());
8241cb0ef41Sopenharmony_ci    DCHECK(!has_constant_pool_entry_);
8251cb0ef41Sopenharmony_ci    constant_pool_entry_ = constant_pool_entry;
8261cb0ef41Sopenharmony_ci    has_constant_pool_entry_ = true;
8271cb0ef41Sopenharmony_ci  }
8281cb0ef41Sopenharmony_ci
8291cb0ef41Sopenharmony_ci  void record_global_variable_declaration() {
8301cb0ef41Sopenharmony_ci    entry_slots_ += kGlobalVariableDeclarationSize;
8311cb0ef41Sopenharmony_ci  }
8321cb0ef41Sopenharmony_ci  void record_global_function_declaration() {
8331cb0ef41Sopenharmony_ci    entry_slots_ += kGlobalFunctionDeclarationSize;
8341cb0ef41Sopenharmony_ci  }
8351cb0ef41Sopenharmony_ci  void record_module_variable_declaration() {
8361cb0ef41Sopenharmony_ci    entry_slots_ += kModuleVariableDeclarationSize;
8371cb0ef41Sopenharmony_ci  }
8381cb0ef41Sopenharmony_ci  void record_module_function_declaration() {
8391cb0ef41Sopenharmony_ci    entry_slots_ += kModuleFunctionDeclarationSize;
8401cb0ef41Sopenharmony_ci  }
8411cb0ef41Sopenharmony_ci  bool has_top_level_declaration() { return entry_slots_ > 0; }
8421cb0ef41Sopenharmony_ci  bool processed() { return processed_; }
8431cb0ef41Sopenharmony_ci  void mark_processed() { processed_ = true; }
8441cb0ef41Sopenharmony_ci
8451cb0ef41Sopenharmony_ci private:
8461cb0ef41Sopenharmony_ci  const int kGlobalVariableDeclarationSize = 1;
8471cb0ef41Sopenharmony_ci  const int kGlobalFunctionDeclarationSize = 2;
8481cb0ef41Sopenharmony_ci  const int kModuleVariableDeclarationSize = 1;
8491cb0ef41Sopenharmony_ci  const int kModuleFunctionDeclarationSize = 3;
8501cb0ef41Sopenharmony_ci
8511cb0ef41Sopenharmony_ci  size_t constant_pool_entry_ = 0;
8521cb0ef41Sopenharmony_ci  int entry_slots_ = 0;
8531cb0ef41Sopenharmony_ci  bool has_constant_pool_entry_ = false;
8541cb0ef41Sopenharmony_ci  bool processed_ = false;
8551cb0ef41Sopenharmony_ci};
8561cb0ef41Sopenharmony_ci
8571cb0ef41Sopenharmony_ciclass V8_NODISCARD BytecodeGenerator::CurrentScope final {
8581cb0ef41Sopenharmony_ci public:
8591cb0ef41Sopenharmony_ci  CurrentScope(BytecodeGenerator* generator, Scope* scope)
8601cb0ef41Sopenharmony_ci      : generator_(generator), outer_scope_(generator->current_scope()) {
8611cb0ef41Sopenharmony_ci    if (scope != nullptr) {
8621cb0ef41Sopenharmony_ci      DCHECK_EQ(outer_scope_, scope->outer_scope());
8631cb0ef41Sopenharmony_ci      generator_->set_current_scope(scope);
8641cb0ef41Sopenharmony_ci    }
8651cb0ef41Sopenharmony_ci  }
8661cb0ef41Sopenharmony_ci  ~CurrentScope() {
8671cb0ef41Sopenharmony_ci    if (outer_scope_ != generator_->current_scope()) {
8681cb0ef41Sopenharmony_ci      generator_->set_current_scope(outer_scope_);
8691cb0ef41Sopenharmony_ci    }
8701cb0ef41Sopenharmony_ci  }
8711cb0ef41Sopenharmony_ci  CurrentScope(const CurrentScope&) = delete;
8721cb0ef41Sopenharmony_ci  CurrentScope& operator=(const CurrentScope&) = delete;
8731cb0ef41Sopenharmony_ci
8741cb0ef41Sopenharmony_ci private:
8751cb0ef41Sopenharmony_ci  BytecodeGenerator* generator_;
8761cb0ef41Sopenharmony_ci  Scope* outer_scope_;
8771cb0ef41Sopenharmony_ci};
8781cb0ef41Sopenharmony_ci
8791cb0ef41Sopenharmony_ciclass V8_NODISCARD BytecodeGenerator::MultipleEntryBlockContextScope {
8801cb0ef41Sopenharmony_ci public:
8811cb0ef41Sopenharmony_ci  MultipleEntryBlockContextScope(BytecodeGenerator* generator, Scope* scope)
8821cb0ef41Sopenharmony_ci      : generator_(generator), scope_(scope), is_in_scope_(false) {
8831cb0ef41Sopenharmony_ci    if (scope) {
8841cb0ef41Sopenharmony_ci      inner_context_ = generator->register_allocator()->NewRegister();
8851cb0ef41Sopenharmony_ci      outer_context_ = generator->register_allocator()->NewRegister();
8861cb0ef41Sopenharmony_ci      generator->BuildNewLocalBlockContext(scope_);
8871cb0ef41Sopenharmony_ci      generator->builder()->StoreAccumulatorInRegister(inner_context_);
8881cb0ef41Sopenharmony_ci    }
8891cb0ef41Sopenharmony_ci  }
8901cb0ef41Sopenharmony_ci
8911cb0ef41Sopenharmony_ci  void SetEnteredIf(bool condition) {
8921cb0ef41Sopenharmony_ci    RegisterAllocationScope register_scope(generator_);
8931cb0ef41Sopenharmony_ci    if (condition && scope_ != nullptr && !is_in_scope_) {
8941cb0ef41Sopenharmony_ci      EnterScope();
8951cb0ef41Sopenharmony_ci    } else if (!condition && is_in_scope_) {
8961cb0ef41Sopenharmony_ci      ExitScope();
8971cb0ef41Sopenharmony_ci    }
8981cb0ef41Sopenharmony_ci  }
8991cb0ef41Sopenharmony_ci
9001cb0ef41Sopenharmony_ci  MultipleEntryBlockContextScope(const MultipleEntryBlockContextScope&) =
9011cb0ef41Sopenharmony_ci      delete;
9021cb0ef41Sopenharmony_ci  MultipleEntryBlockContextScope& operator=(
9031cb0ef41Sopenharmony_ci      const MultipleEntryBlockContextScope&) = delete;
9041cb0ef41Sopenharmony_ci
9051cb0ef41Sopenharmony_ci private:
9061cb0ef41Sopenharmony_ci  void EnterScope() {
9071cb0ef41Sopenharmony_ci    DCHECK(inner_context_.is_valid());
9081cb0ef41Sopenharmony_ci    DCHECK(outer_context_.is_valid());
9091cb0ef41Sopenharmony_ci    DCHECK(!is_in_scope_);
9101cb0ef41Sopenharmony_ci    Register temp = generator_->register_allocator()->NewRegister();
9111cb0ef41Sopenharmony_ci    generator_->builder()->StoreAccumulatorInRegister(temp);
9121cb0ef41Sopenharmony_ci    generator_->builder()->LoadAccumulatorWithRegister(inner_context_);
9131cb0ef41Sopenharmony_ci    current_scope_.emplace(generator_, scope_);
9141cb0ef41Sopenharmony_ci    context_scope_.emplace(generator_, scope_, outer_context_);
9151cb0ef41Sopenharmony_ci    generator_->builder()->LoadAccumulatorWithRegister(temp);
9161cb0ef41Sopenharmony_ci    is_in_scope_ = true;
9171cb0ef41Sopenharmony_ci  }
9181cb0ef41Sopenharmony_ci
9191cb0ef41Sopenharmony_ci  void ExitScope() {
9201cb0ef41Sopenharmony_ci    DCHECK(inner_context_.is_valid());
9211cb0ef41Sopenharmony_ci    DCHECK(outer_context_.is_valid());
9221cb0ef41Sopenharmony_ci    DCHECK(is_in_scope_);
9231cb0ef41Sopenharmony_ci    Register temp = generator_->register_allocator()->NewRegister();
9241cb0ef41Sopenharmony_ci    generator_->builder()->StoreAccumulatorInRegister(temp);
9251cb0ef41Sopenharmony_ci    context_scope_ = base::nullopt;
9261cb0ef41Sopenharmony_ci    current_scope_ = base::nullopt;
9271cb0ef41Sopenharmony_ci    generator_->builder()->LoadAccumulatorWithRegister(temp);
9281cb0ef41Sopenharmony_ci    is_in_scope_ = false;
9291cb0ef41Sopenharmony_ci  }
9301cb0ef41Sopenharmony_ci
9311cb0ef41Sopenharmony_ci  BytecodeGenerator* generator_;
9321cb0ef41Sopenharmony_ci  Scope* scope_;
9331cb0ef41Sopenharmony_ci  Register inner_context_;
9341cb0ef41Sopenharmony_ci  Register outer_context_;
9351cb0ef41Sopenharmony_ci  bool is_in_scope_;
9361cb0ef41Sopenharmony_ci  base::Optional<CurrentScope> current_scope_;
9371cb0ef41Sopenharmony_ci  base::Optional<ContextScope> context_scope_;
9381cb0ef41Sopenharmony_ci};
9391cb0ef41Sopenharmony_ci
9401cb0ef41Sopenharmony_ciclass BytecodeGenerator::FeedbackSlotCache : public ZoneObject {
9411cb0ef41Sopenharmony_ci public:
9421cb0ef41Sopenharmony_ci  enum class SlotKind {
9431cb0ef41Sopenharmony_ci    kStoreGlobalSloppy,
9441cb0ef41Sopenharmony_ci    kStoreGlobalStrict,
9451cb0ef41Sopenharmony_ci    kSetNamedStrict,
9461cb0ef41Sopenharmony_ci    kSetNamedSloppy,
9471cb0ef41Sopenharmony_ci    kLoadProperty,
9481cb0ef41Sopenharmony_ci    kLoadSuperProperty,
9491cb0ef41Sopenharmony_ci    kLoadGlobalNotInsideTypeof,
9501cb0ef41Sopenharmony_ci    kLoadGlobalInsideTypeof,
9511cb0ef41Sopenharmony_ci    kClosureFeedbackCell
9521cb0ef41Sopenharmony_ci  };
9531cb0ef41Sopenharmony_ci
9541cb0ef41Sopenharmony_ci  explicit FeedbackSlotCache(Zone* zone) : map_(zone) {}
9551cb0ef41Sopenharmony_ci
9561cb0ef41Sopenharmony_ci  void Put(SlotKind slot_kind, Variable* variable, int slot_index) {
9571cb0ef41Sopenharmony_ci    PutImpl(slot_kind, 0, variable, slot_index);
9581cb0ef41Sopenharmony_ci  }
9591cb0ef41Sopenharmony_ci  void Put(SlotKind slot_kind, AstNode* node, int slot_index) {
9601cb0ef41Sopenharmony_ci    PutImpl(slot_kind, 0, node, slot_index);
9611cb0ef41Sopenharmony_ci  }
9621cb0ef41Sopenharmony_ci  void Put(SlotKind slot_kind, int variable_index, const AstRawString* name,
9631cb0ef41Sopenharmony_ci           int slot_index) {
9641cb0ef41Sopenharmony_ci    PutImpl(slot_kind, variable_index, name, slot_index);
9651cb0ef41Sopenharmony_ci  }
9661cb0ef41Sopenharmony_ci  void Put(SlotKind slot_kind, const AstRawString* name, int slot_index) {
9671cb0ef41Sopenharmony_ci    PutImpl(slot_kind, 0, name, slot_index);
9681cb0ef41Sopenharmony_ci  }
9691cb0ef41Sopenharmony_ci
9701cb0ef41Sopenharmony_ci  int Get(SlotKind slot_kind, Variable* variable) const {
9711cb0ef41Sopenharmony_ci    return GetImpl(slot_kind, 0, variable);
9721cb0ef41Sopenharmony_ci  }
9731cb0ef41Sopenharmony_ci  int Get(SlotKind slot_kind, AstNode* node) const {
9741cb0ef41Sopenharmony_ci    return GetImpl(slot_kind, 0, node);
9751cb0ef41Sopenharmony_ci  }
9761cb0ef41Sopenharmony_ci  int Get(SlotKind slot_kind, int variable_index,
9771cb0ef41Sopenharmony_ci          const AstRawString* name) const {
9781cb0ef41Sopenharmony_ci    return GetImpl(slot_kind, variable_index, name);
9791cb0ef41Sopenharmony_ci  }
9801cb0ef41Sopenharmony_ci  int Get(SlotKind slot_kind, const AstRawString* name) const {
9811cb0ef41Sopenharmony_ci    return GetImpl(slot_kind, 0, name);
9821cb0ef41Sopenharmony_ci  }
9831cb0ef41Sopenharmony_ci
9841cb0ef41Sopenharmony_ci private:
9851cb0ef41Sopenharmony_ci  using Key = std::tuple<SlotKind, int, const void*>;
9861cb0ef41Sopenharmony_ci
9871cb0ef41Sopenharmony_ci  void PutImpl(SlotKind slot_kind, int index, const void* node,
9881cb0ef41Sopenharmony_ci               int slot_index) {
9891cb0ef41Sopenharmony_ci    Key key = std::make_tuple(slot_kind, index, node);
9901cb0ef41Sopenharmony_ci    auto entry = std::make_pair(key, slot_index);
9911cb0ef41Sopenharmony_ci    map_.insert(entry);
9921cb0ef41Sopenharmony_ci  }
9931cb0ef41Sopenharmony_ci
9941cb0ef41Sopenharmony_ci  int GetImpl(SlotKind slot_kind, int index, const void* node) const {
9951cb0ef41Sopenharmony_ci    Key key = std::make_tuple(slot_kind, index, node);
9961cb0ef41Sopenharmony_ci    auto iter = map_.find(key);
9971cb0ef41Sopenharmony_ci    if (iter != map_.end()) {
9981cb0ef41Sopenharmony_ci      return iter->second;
9991cb0ef41Sopenharmony_ci    }
10001cb0ef41Sopenharmony_ci    return -1;
10011cb0ef41Sopenharmony_ci  }
10021cb0ef41Sopenharmony_ci
10031cb0ef41Sopenharmony_ci  ZoneMap<Key, int> map_;
10041cb0ef41Sopenharmony_ci};
10051cb0ef41Sopenharmony_ci
10061cb0ef41Sopenharmony_ciclass BytecodeGenerator::IteratorRecord final {
10071cb0ef41Sopenharmony_ci public:
10081cb0ef41Sopenharmony_ci  IteratorRecord(Register object_register, Register next_register,
10091cb0ef41Sopenharmony_ci                 IteratorType type = IteratorType::kNormal)
10101cb0ef41Sopenharmony_ci      : type_(type), object_(object_register), next_(next_register) {
10111cb0ef41Sopenharmony_ci    DCHECK(object_.is_valid() && next_.is_valid());
10121cb0ef41Sopenharmony_ci  }
10131cb0ef41Sopenharmony_ci
10141cb0ef41Sopenharmony_ci  inline IteratorType type() const { return type_; }
10151cb0ef41Sopenharmony_ci  inline Register object() const { return object_; }
10161cb0ef41Sopenharmony_ci  inline Register next() const { return next_; }
10171cb0ef41Sopenharmony_ci
10181cb0ef41Sopenharmony_ci private:
10191cb0ef41Sopenharmony_ci  IteratorType type_;
10201cb0ef41Sopenharmony_ci  Register object_;
10211cb0ef41Sopenharmony_ci  Register next_;
10221cb0ef41Sopenharmony_ci};
10231cb0ef41Sopenharmony_ci
10241cb0ef41Sopenharmony_ciclass V8_NODISCARD BytecodeGenerator::OptionalChainNullLabelScope final {
10251cb0ef41Sopenharmony_ci public:
10261cb0ef41Sopenharmony_ci  explicit OptionalChainNullLabelScope(BytecodeGenerator* bytecode_generator)
10271cb0ef41Sopenharmony_ci      : bytecode_generator_(bytecode_generator),
10281cb0ef41Sopenharmony_ci        labels_(bytecode_generator->zone()) {
10291cb0ef41Sopenharmony_ci    prev_ = bytecode_generator_->optional_chaining_null_labels_;
10301cb0ef41Sopenharmony_ci    bytecode_generator_->optional_chaining_null_labels_ = &labels_;
10311cb0ef41Sopenharmony_ci  }
10321cb0ef41Sopenharmony_ci
10331cb0ef41Sopenharmony_ci  ~OptionalChainNullLabelScope() {
10341cb0ef41Sopenharmony_ci    bytecode_generator_->optional_chaining_null_labels_ = prev_;
10351cb0ef41Sopenharmony_ci  }
10361cb0ef41Sopenharmony_ci
10371cb0ef41Sopenharmony_ci  BytecodeLabels* labels() { return &labels_; }
10381cb0ef41Sopenharmony_ci
10391cb0ef41Sopenharmony_ci private:
10401cb0ef41Sopenharmony_ci  BytecodeGenerator* bytecode_generator_;
10411cb0ef41Sopenharmony_ci  BytecodeLabels labels_;
10421cb0ef41Sopenharmony_ci  BytecodeLabels* prev_;
10431cb0ef41Sopenharmony_ci};
10441cb0ef41Sopenharmony_ci
10451cb0ef41Sopenharmony_ci// LoopScope delimits the scope of {loop}, from its header to its final jump.
10461cb0ef41Sopenharmony_ci// It should be constructed iff a (conceptual) back edge should be produced. In
10471cb0ef41Sopenharmony_ci// the case of creating a LoopBuilder but never emitting the loop, it is valid
10481cb0ef41Sopenharmony_ci// to skip the creation of LoopScope.
10491cb0ef41Sopenharmony_ciclass V8_NODISCARD BytecodeGenerator::LoopScope final {
10501cb0ef41Sopenharmony_ci public:
10511cb0ef41Sopenharmony_ci  explicit LoopScope(BytecodeGenerator* bytecode_generator, LoopBuilder* loop)
10521cb0ef41Sopenharmony_ci      : bytecode_generator_(bytecode_generator),
10531cb0ef41Sopenharmony_ci        parent_loop_scope_(bytecode_generator_->current_loop_scope()),
10541cb0ef41Sopenharmony_ci        loop_builder_(loop) {
10551cb0ef41Sopenharmony_ci    loop_builder_->LoopHeader();
10561cb0ef41Sopenharmony_ci    bytecode_generator_->set_current_loop_scope(this);
10571cb0ef41Sopenharmony_ci    bytecode_generator_->loop_depth_++;
10581cb0ef41Sopenharmony_ci  }
10591cb0ef41Sopenharmony_ci
10601cb0ef41Sopenharmony_ci  ~LoopScope() {
10611cb0ef41Sopenharmony_ci    bytecode_generator_->loop_depth_--;
10621cb0ef41Sopenharmony_ci    bytecode_generator_->set_current_loop_scope(parent_loop_scope_);
10631cb0ef41Sopenharmony_ci    DCHECK_GE(bytecode_generator_->loop_depth_, 0);
10641cb0ef41Sopenharmony_ci    loop_builder_->JumpToHeader(
10651cb0ef41Sopenharmony_ci        bytecode_generator_->loop_depth_,
10661cb0ef41Sopenharmony_ci        parent_loop_scope_ ? parent_loop_scope_->loop_builder_ : nullptr);
10671cb0ef41Sopenharmony_ci  }
10681cb0ef41Sopenharmony_ci
10691cb0ef41Sopenharmony_ci private:
10701cb0ef41Sopenharmony_ci  BytecodeGenerator* const bytecode_generator_;
10711cb0ef41Sopenharmony_ci  LoopScope* const parent_loop_scope_;
10721cb0ef41Sopenharmony_ci  LoopBuilder* const loop_builder_;
10731cb0ef41Sopenharmony_ci};
10741cb0ef41Sopenharmony_ci
10751cb0ef41Sopenharmony_cinamespace {
10761cb0ef41Sopenharmony_ci
10771cb0ef41Sopenharmony_citemplate <typename PropertyT>
10781cb0ef41Sopenharmony_cistruct Accessors : public ZoneObject {
10791cb0ef41Sopenharmony_ci  Accessors() : getter(nullptr), setter(nullptr) {}
10801cb0ef41Sopenharmony_ci  PropertyT* getter;
10811cb0ef41Sopenharmony_ci  PropertyT* setter;
10821cb0ef41Sopenharmony_ci};
10831cb0ef41Sopenharmony_ci
10841cb0ef41Sopenharmony_ci// A map from property names to getter/setter pairs allocated in the zone that
10851cb0ef41Sopenharmony_ci// also provides a way of accessing the pairs in the order they were first
10861cb0ef41Sopenharmony_ci// added so that the generated bytecode is always the same.
10871cb0ef41Sopenharmony_citemplate <typename PropertyT>
10881cb0ef41Sopenharmony_ciclass AccessorTable
10891cb0ef41Sopenharmony_ci    : public base::TemplateHashMap<Literal, Accessors<PropertyT>,
10901cb0ef41Sopenharmony_ci                                   bool (*)(void*, void*),
10911cb0ef41Sopenharmony_ci                                   ZoneAllocationPolicy> {
10921cb0ef41Sopenharmony_ci public:
10931cb0ef41Sopenharmony_ci  explicit AccessorTable(Zone* zone)
10941cb0ef41Sopenharmony_ci      : base::TemplateHashMap<Literal, Accessors<PropertyT>,
10951cb0ef41Sopenharmony_ci                              bool (*)(void*, void*), ZoneAllocationPolicy>(
10961cb0ef41Sopenharmony_ci            Literal::Match, ZoneAllocationPolicy(zone)),
10971cb0ef41Sopenharmony_ci        zone_(zone) {}
10981cb0ef41Sopenharmony_ci
10991cb0ef41Sopenharmony_ci  Accessors<PropertyT>* LookupOrInsert(Literal* key) {
11001cb0ef41Sopenharmony_ci    auto it = this->find(key, true);
11011cb0ef41Sopenharmony_ci    if (it->second == nullptr) {
11021cb0ef41Sopenharmony_ci      it->second = zone_->New<Accessors<PropertyT>>();
11031cb0ef41Sopenharmony_ci      ordered_accessors_.push_back({key, it->second});
11041cb0ef41Sopenharmony_ci    }
11051cb0ef41Sopenharmony_ci    return it->second;
11061cb0ef41Sopenharmony_ci  }
11071cb0ef41Sopenharmony_ci
11081cb0ef41Sopenharmony_ci  const std::vector<std::pair<Literal*, Accessors<PropertyT>*>>&
11091cb0ef41Sopenharmony_ci  ordered_accessors() {
11101cb0ef41Sopenharmony_ci    return ordered_accessors_;
11111cb0ef41Sopenharmony_ci  }
11121cb0ef41Sopenharmony_ci
11131cb0ef41Sopenharmony_ci private:
11141cb0ef41Sopenharmony_ci  std::vector<std::pair<Literal*, Accessors<PropertyT>*>> ordered_accessors_;
11151cb0ef41Sopenharmony_ci
11161cb0ef41Sopenharmony_ci  Zone* zone_;
11171cb0ef41Sopenharmony_ci};
11181cb0ef41Sopenharmony_ci
11191cb0ef41Sopenharmony_ci}  // namespace
11201cb0ef41Sopenharmony_ci
11211cb0ef41Sopenharmony_ci#ifdef DEBUG
11221cb0ef41Sopenharmony_ci
11231cb0ef41Sopenharmony_cistatic bool IsInEagerLiterals(
11241cb0ef41Sopenharmony_ci    FunctionLiteral* literal,
11251cb0ef41Sopenharmony_ci    const std::vector<FunctionLiteral*>& eager_literals) {
11261cb0ef41Sopenharmony_ci  for (FunctionLiteral* eager_literal : eager_literals) {
11271cb0ef41Sopenharmony_ci    if (literal == eager_literal) return true;
11281cb0ef41Sopenharmony_ci  }
11291cb0ef41Sopenharmony_ci  return false;
11301cb0ef41Sopenharmony_ci}
11311cb0ef41Sopenharmony_ci
11321cb0ef41Sopenharmony_ci#endif  // DEBUG
11331cb0ef41Sopenharmony_ci
11341cb0ef41Sopenharmony_ciBytecodeGenerator::BytecodeGenerator(
11351cb0ef41Sopenharmony_ci    LocalIsolate* local_isolate, Zone* compile_zone,
11361cb0ef41Sopenharmony_ci    UnoptimizedCompilationInfo* info,
11371cb0ef41Sopenharmony_ci    const AstStringConstants* ast_string_constants,
11381cb0ef41Sopenharmony_ci    std::vector<FunctionLiteral*>* eager_inner_literals, Handle<Script> script)
11391cb0ef41Sopenharmony_ci    : local_isolate_(local_isolate),
11401cb0ef41Sopenharmony_ci      zone_(compile_zone),
11411cb0ef41Sopenharmony_ci      builder_(zone(), info->num_parameters_including_this(),
11421cb0ef41Sopenharmony_ci               info->scope()->num_stack_slots(), info->feedback_vector_spec(),
11431cb0ef41Sopenharmony_ci               info->SourcePositionRecordingMode()),
11441cb0ef41Sopenharmony_ci      info_(info),
11451cb0ef41Sopenharmony_ci      ast_string_constants_(ast_string_constants),
11461cb0ef41Sopenharmony_ci      closure_scope_(info->scope()),
11471cb0ef41Sopenharmony_ci      current_scope_(info->scope()),
11481cb0ef41Sopenharmony_ci      eager_inner_literals_(eager_inner_literals),
11491cb0ef41Sopenharmony_ci      script_(script),
11501cb0ef41Sopenharmony_ci      feedback_slot_cache_(zone()->New<FeedbackSlotCache>(zone())),
11511cb0ef41Sopenharmony_ci      top_level_builder_(zone()->New<TopLevelDeclarationsBuilder>()),
11521cb0ef41Sopenharmony_ci      block_coverage_builder_(nullptr),
11531cb0ef41Sopenharmony_ci      function_literals_(0, zone()),
11541cb0ef41Sopenharmony_ci      native_function_literals_(0, zone()),
11551cb0ef41Sopenharmony_ci      object_literals_(0, zone()),
11561cb0ef41Sopenharmony_ci      array_literals_(0, zone()),
11571cb0ef41Sopenharmony_ci      class_literals_(0, zone()),
11581cb0ef41Sopenharmony_ci      template_objects_(0, zone()),
11591cb0ef41Sopenharmony_ci      execution_control_(nullptr),
11601cb0ef41Sopenharmony_ci      execution_context_(nullptr),
11611cb0ef41Sopenharmony_ci      execution_result_(nullptr),
11621cb0ef41Sopenharmony_ci      incoming_new_target_or_generator_(),
11631cb0ef41Sopenharmony_ci      optional_chaining_null_labels_(nullptr),
11641cb0ef41Sopenharmony_ci      dummy_feedback_slot_(feedback_spec(), FeedbackSlotKind::kCompareOp),
11651cb0ef41Sopenharmony_ci      generator_jump_table_(nullptr),
11661cb0ef41Sopenharmony_ci      suspend_count_(0),
11671cb0ef41Sopenharmony_ci      loop_depth_(0),
11681cb0ef41Sopenharmony_ci      current_loop_scope_(nullptr),
11691cb0ef41Sopenharmony_ci      catch_prediction_(HandlerTable::UNCAUGHT) {
11701cb0ef41Sopenharmony_ci  DCHECK_EQ(closure_scope(), closure_scope()->GetClosureScope());
11711cb0ef41Sopenharmony_ci  if (info->has_source_range_map()) {
11721cb0ef41Sopenharmony_ci    block_coverage_builder_ = zone()->New<BlockCoverageBuilder>(
11731cb0ef41Sopenharmony_ci        zone(), builder(), info->source_range_map());
11741cb0ef41Sopenharmony_ci  }
11751cb0ef41Sopenharmony_ci}
11761cb0ef41Sopenharmony_ci
11771cb0ef41Sopenharmony_cinamespace {
11781cb0ef41Sopenharmony_ci
11791cb0ef41Sopenharmony_citemplate <typename Isolate>
11801cb0ef41Sopenharmony_cistruct NullContextScopeHelper;
11811cb0ef41Sopenharmony_ci
11821cb0ef41Sopenharmony_citemplate <>
11831cb0ef41Sopenharmony_cistruct NullContextScopeHelper<Isolate> {
11841cb0ef41Sopenharmony_ci  using Type = NullContextScope;
11851cb0ef41Sopenharmony_ci};
11861cb0ef41Sopenharmony_ci
11871cb0ef41Sopenharmony_citemplate <>
11881cb0ef41Sopenharmony_cistruct NullContextScopeHelper<LocalIsolate> {
11891cb0ef41Sopenharmony_ci  class V8_NODISCARD DummyNullContextScope {
11901cb0ef41Sopenharmony_ci   public:
11911cb0ef41Sopenharmony_ci    explicit DummyNullContextScope(LocalIsolate*) {}
11921cb0ef41Sopenharmony_ci  };
11931cb0ef41Sopenharmony_ci  using Type = DummyNullContextScope;
11941cb0ef41Sopenharmony_ci};
11951cb0ef41Sopenharmony_ci
11961cb0ef41Sopenharmony_citemplate <typename Isolate>
11971cb0ef41Sopenharmony_ciusing NullContextScopeFor = typename NullContextScopeHelper<Isolate>::Type;
11981cb0ef41Sopenharmony_ci
11991cb0ef41Sopenharmony_ci}  // namespace
12001cb0ef41Sopenharmony_ci
12011cb0ef41Sopenharmony_citemplate <typename IsolateT>
12021cb0ef41Sopenharmony_ciHandle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
12031cb0ef41Sopenharmony_ci    IsolateT* isolate, Handle<Script> script) {
12041cb0ef41Sopenharmony_ci  DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
12051cb0ef41Sopenharmony_ci#ifdef DEBUG
12061cb0ef41Sopenharmony_ci  // Unoptimized compilation should be context-independent. Verify that we don't
12071cb0ef41Sopenharmony_ci  // access the native context by nulling it out during finalization.
12081cb0ef41Sopenharmony_ci  NullContextScopeFor<IsolateT> null_context_scope(isolate);
12091cb0ef41Sopenharmony_ci#endif
12101cb0ef41Sopenharmony_ci
12111cb0ef41Sopenharmony_ci  AllocateDeferredConstants(isolate, script);
12121cb0ef41Sopenharmony_ci
12131cb0ef41Sopenharmony_ci  if (block_coverage_builder_) {
12141cb0ef41Sopenharmony_ci    Handle<CoverageInfo> coverage_info =
12151cb0ef41Sopenharmony_ci        isolate->factory()->NewCoverageInfo(block_coverage_builder_->slots());
12161cb0ef41Sopenharmony_ci    info()->set_coverage_info(coverage_info);
12171cb0ef41Sopenharmony_ci    if (FLAG_trace_block_coverage) {
12181cb0ef41Sopenharmony_ci      StdoutStream os;
12191cb0ef41Sopenharmony_ci      coverage_info->CoverageInfoPrint(os, info()->literal()->GetDebugName());
12201cb0ef41Sopenharmony_ci    }
12211cb0ef41Sopenharmony_ci  }
12221cb0ef41Sopenharmony_ci
12231cb0ef41Sopenharmony_ci  if (HasStackOverflow()) return Handle<BytecodeArray>();
12241cb0ef41Sopenharmony_ci  Handle<BytecodeArray> bytecode_array = builder()->ToBytecodeArray(isolate);
12251cb0ef41Sopenharmony_ci
12261cb0ef41Sopenharmony_ci  if (incoming_new_target_or_generator_.is_valid()) {
12271cb0ef41Sopenharmony_ci    bytecode_array->set_incoming_new_target_or_generator_register(
12281cb0ef41Sopenharmony_ci        incoming_new_target_or_generator_);
12291cb0ef41Sopenharmony_ci  }
12301cb0ef41Sopenharmony_ci
12311cb0ef41Sopenharmony_ci  return bytecode_array;
12321cb0ef41Sopenharmony_ci}
12331cb0ef41Sopenharmony_ci
12341cb0ef41Sopenharmony_citemplate Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
12351cb0ef41Sopenharmony_ci    Isolate* isolate, Handle<Script> script);
12361cb0ef41Sopenharmony_citemplate Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
12371cb0ef41Sopenharmony_ci    LocalIsolate* isolate, Handle<Script> script);
12381cb0ef41Sopenharmony_ci
12391cb0ef41Sopenharmony_citemplate <typename IsolateT>
12401cb0ef41Sopenharmony_ciHandle<ByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
12411cb0ef41Sopenharmony_ci    IsolateT* isolate) {
12421cb0ef41Sopenharmony_ci  DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
12431cb0ef41Sopenharmony_ci#ifdef DEBUG
12441cb0ef41Sopenharmony_ci  // Unoptimized compilation should be context-independent. Verify that we don't
12451cb0ef41Sopenharmony_ci  // access the native context by nulling it out during finalization.
12461cb0ef41Sopenharmony_ci  NullContextScopeFor<IsolateT> null_context_scope(isolate);
12471cb0ef41Sopenharmony_ci#endif
12481cb0ef41Sopenharmony_ci
12491cb0ef41Sopenharmony_ci  Handle<ByteArray> source_position_table =
12501cb0ef41Sopenharmony_ci      builder()->ToSourcePositionTable(isolate);
12511cb0ef41Sopenharmony_ci
12521cb0ef41Sopenharmony_ci  LOG_CODE_EVENT(isolate,
12531cb0ef41Sopenharmony_ci                 CodeLinePosInfoRecordEvent(
12541cb0ef41Sopenharmony_ci                     info_->bytecode_array()->GetFirstBytecodeAddress(),
12551cb0ef41Sopenharmony_ci                     *source_position_table, JitCodeEvent::BYTE_CODE));
12561cb0ef41Sopenharmony_ci
12571cb0ef41Sopenharmony_ci  return source_position_table;
12581cb0ef41Sopenharmony_ci}
12591cb0ef41Sopenharmony_ci
12601cb0ef41Sopenharmony_citemplate Handle<ByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
12611cb0ef41Sopenharmony_ci    Isolate* isolate);
12621cb0ef41Sopenharmony_citemplate Handle<ByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
12631cb0ef41Sopenharmony_ci    LocalIsolate* isolate);
12641cb0ef41Sopenharmony_ci
12651cb0ef41Sopenharmony_ci#ifdef DEBUG
12661cb0ef41Sopenharmony_ciint BytecodeGenerator::CheckBytecodeMatches(BytecodeArray bytecode) {
12671cb0ef41Sopenharmony_ci  return builder()->CheckBytecodeMatches(bytecode);
12681cb0ef41Sopenharmony_ci}
12691cb0ef41Sopenharmony_ci#endif
12701cb0ef41Sopenharmony_ci
12711cb0ef41Sopenharmony_citemplate <typename IsolateT>
12721cb0ef41Sopenharmony_civoid BytecodeGenerator::AllocateDeferredConstants(IsolateT* isolate,
12731cb0ef41Sopenharmony_ci                                                  Handle<Script> script) {
12741cb0ef41Sopenharmony_ci  if (top_level_builder()->has_top_level_declaration()) {
12751cb0ef41Sopenharmony_ci    // Build global declaration pair array.
12761cb0ef41Sopenharmony_ci    Handle<FixedArray> declarations = top_level_builder()->AllocateDeclarations(
12771cb0ef41Sopenharmony_ci        info(), this, script, isolate);
12781cb0ef41Sopenharmony_ci    if (declarations.is_null()) return SetStackOverflow();
12791cb0ef41Sopenharmony_ci    builder()->SetDeferredConstantPoolEntry(
12801cb0ef41Sopenharmony_ci        top_level_builder()->constant_pool_entry(), declarations);
12811cb0ef41Sopenharmony_ci  }
12821cb0ef41Sopenharmony_ci
12831cb0ef41Sopenharmony_ci  // Find or build shared function infos.
12841cb0ef41Sopenharmony_ci  for (std::pair<FunctionLiteral*, size_t> literal : function_literals_) {
12851cb0ef41Sopenharmony_ci    FunctionLiteral* expr = literal.first;
12861cb0ef41Sopenharmony_ci    Handle<SharedFunctionInfo> shared_info =
12871cb0ef41Sopenharmony_ci        Compiler::GetSharedFunctionInfo(expr, script, isolate);
12881cb0ef41Sopenharmony_ci    if (shared_info.is_null()) return SetStackOverflow();
12891cb0ef41Sopenharmony_ci    builder()->SetDeferredConstantPoolEntry(literal.second, shared_info);
12901cb0ef41Sopenharmony_ci  }
12911cb0ef41Sopenharmony_ci
12921cb0ef41Sopenharmony_ci  // Find or build shared function infos for the native function templates.
12931cb0ef41Sopenharmony_ci  for (std::pair<NativeFunctionLiteral*, size_t> literal :
12941cb0ef41Sopenharmony_ci       native_function_literals_) {
12951cb0ef41Sopenharmony_ci    // This should only happen for main-thread compilations.
12961cb0ef41Sopenharmony_ci    DCHECK((std::is_same<Isolate, v8::internal::Isolate>::value));
12971cb0ef41Sopenharmony_ci
12981cb0ef41Sopenharmony_ci    NativeFunctionLiteral* expr = literal.first;
12991cb0ef41Sopenharmony_ci    v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
13001cb0ef41Sopenharmony_ci
13011cb0ef41Sopenharmony_ci    // Compute the function template for the native function.
13021cb0ef41Sopenharmony_ci    v8::Local<v8::FunctionTemplate> info =
13031cb0ef41Sopenharmony_ci        expr->extension()->GetNativeFunctionTemplate(
13041cb0ef41Sopenharmony_ci            v8_isolate, Utils::ToLocal(expr->name()));
13051cb0ef41Sopenharmony_ci    DCHECK(!info.IsEmpty());
13061cb0ef41Sopenharmony_ci
13071cb0ef41Sopenharmony_ci    Handle<SharedFunctionInfo> shared_info =
13081cb0ef41Sopenharmony_ci        FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
13091cb0ef41Sopenharmony_ci            isolate, Utils::OpenHandle(*info), expr->name());
13101cb0ef41Sopenharmony_ci    DCHECK(!shared_info.is_null());
13111cb0ef41Sopenharmony_ci    builder()->SetDeferredConstantPoolEntry(literal.second, shared_info);
13121cb0ef41Sopenharmony_ci  }
13131cb0ef41Sopenharmony_ci
13141cb0ef41Sopenharmony_ci  // Build object literal constant properties
13151cb0ef41Sopenharmony_ci  for (std::pair<ObjectLiteralBoilerplateBuilder*, size_t> literal :
13161cb0ef41Sopenharmony_ci       object_literals_) {
13171cb0ef41Sopenharmony_ci    ObjectLiteralBoilerplateBuilder* object_literal_builder = literal.first;
13181cb0ef41Sopenharmony_ci    if (object_literal_builder->properties_count() > 0) {
13191cb0ef41Sopenharmony_ci      // If constant properties is an empty fixed array, we've already added it
13201cb0ef41Sopenharmony_ci      // to the constant pool when visiting the object literal.
13211cb0ef41Sopenharmony_ci      Handle<ObjectBoilerplateDescription> constant_properties =
13221cb0ef41Sopenharmony_ci          object_literal_builder->GetOrBuildBoilerplateDescription(isolate);
13231cb0ef41Sopenharmony_ci
13241cb0ef41Sopenharmony_ci      builder()->SetDeferredConstantPoolEntry(literal.second,
13251cb0ef41Sopenharmony_ci                                              constant_properties);
13261cb0ef41Sopenharmony_ci    }
13271cb0ef41Sopenharmony_ci  }
13281cb0ef41Sopenharmony_ci
13291cb0ef41Sopenharmony_ci  // Build array literal constant elements
13301cb0ef41Sopenharmony_ci  for (std::pair<ArrayLiteralBoilerplateBuilder*, size_t> literal :
13311cb0ef41Sopenharmony_ci       array_literals_) {
13321cb0ef41Sopenharmony_ci    ArrayLiteralBoilerplateBuilder* array_literal_builder = literal.first;
13331cb0ef41Sopenharmony_ci    Handle<ArrayBoilerplateDescription> constant_elements =
13341cb0ef41Sopenharmony_ci        array_literal_builder->GetOrBuildBoilerplateDescription(isolate);
13351cb0ef41Sopenharmony_ci    builder()->SetDeferredConstantPoolEntry(literal.second, constant_elements);
13361cb0ef41Sopenharmony_ci  }
13371cb0ef41Sopenharmony_ci
13381cb0ef41Sopenharmony_ci  // Build class literal boilerplates.
13391cb0ef41Sopenharmony_ci  for (std::pair<ClassLiteral*, size_t> literal : class_literals_) {
13401cb0ef41Sopenharmony_ci    ClassLiteral* class_literal = literal.first;
13411cb0ef41Sopenharmony_ci    Handle<ClassBoilerplate> class_boilerplate =
13421cb0ef41Sopenharmony_ci        ClassBoilerplate::BuildClassBoilerplate(isolate, class_literal);
13431cb0ef41Sopenharmony_ci    builder()->SetDeferredConstantPoolEntry(literal.second, class_boilerplate);
13441cb0ef41Sopenharmony_ci  }
13451cb0ef41Sopenharmony_ci
13461cb0ef41Sopenharmony_ci  // Build template literals.
13471cb0ef41Sopenharmony_ci  for (std::pair<GetTemplateObject*, size_t> literal : template_objects_) {
13481cb0ef41Sopenharmony_ci    GetTemplateObject* get_template_object = literal.first;
13491cb0ef41Sopenharmony_ci    Handle<TemplateObjectDescription> description =
13501cb0ef41Sopenharmony_ci        get_template_object->GetOrBuildDescription(isolate);
13511cb0ef41Sopenharmony_ci    builder()->SetDeferredConstantPoolEntry(literal.second, description);
13521cb0ef41Sopenharmony_ci  }
13531cb0ef41Sopenharmony_ci}
13541cb0ef41Sopenharmony_ci
13551cb0ef41Sopenharmony_citemplate void BytecodeGenerator::AllocateDeferredConstants(
13561cb0ef41Sopenharmony_ci    Isolate* isolate, Handle<Script> script);
13571cb0ef41Sopenharmony_citemplate void BytecodeGenerator::AllocateDeferredConstants(
13581cb0ef41Sopenharmony_ci    LocalIsolate* isolate, Handle<Script> script);
13591cb0ef41Sopenharmony_ci
13601cb0ef41Sopenharmony_cinamespace {
13611cb0ef41Sopenharmony_cibool NeedsContextInitialization(DeclarationScope* scope) {
13621cb0ef41Sopenharmony_ci  return scope->NeedsContext() && !scope->is_script_scope() &&
13631cb0ef41Sopenharmony_ci         !scope->is_module_scope();
13641cb0ef41Sopenharmony_ci}
13651cb0ef41Sopenharmony_ci}  // namespace
13661cb0ef41Sopenharmony_ci
13671cb0ef41Sopenharmony_civoid BytecodeGenerator::GenerateBytecode(uintptr_t stack_limit) {
13681cb0ef41Sopenharmony_ci  InitializeAstVisitor(stack_limit);
13691cb0ef41Sopenharmony_ci
13701cb0ef41Sopenharmony_ci  // Initialize the incoming context.
13711cb0ef41Sopenharmony_ci  ContextScope incoming_context(this, closure_scope());
13721cb0ef41Sopenharmony_ci
13731cb0ef41Sopenharmony_ci  // Initialize control scope.
13741cb0ef41Sopenharmony_ci  ControlScopeForTopLevel control(this);
13751cb0ef41Sopenharmony_ci
13761cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
13771cb0ef41Sopenharmony_ci
13781cb0ef41Sopenharmony_ci  AllocateTopLevelRegisters();
13791cb0ef41Sopenharmony_ci
13801cb0ef41Sopenharmony_ci  builder()->EmitFunctionStartSourcePosition(
13811cb0ef41Sopenharmony_ci      info()->literal()->start_position());
13821cb0ef41Sopenharmony_ci
13831cb0ef41Sopenharmony_ci  if (info()->literal()->CanSuspend()) {
13841cb0ef41Sopenharmony_ci    BuildGeneratorPrologue();
13851cb0ef41Sopenharmony_ci  }
13861cb0ef41Sopenharmony_ci
13871cb0ef41Sopenharmony_ci  if (NeedsContextInitialization(closure_scope())) {
13881cb0ef41Sopenharmony_ci    // Push a new inner context scope for the function.
13891cb0ef41Sopenharmony_ci    BuildNewLocalActivationContext();
13901cb0ef41Sopenharmony_ci    ContextScope local_function_context(this, closure_scope());
13911cb0ef41Sopenharmony_ci    BuildLocalActivationContextInitialization();
13921cb0ef41Sopenharmony_ci    GenerateBytecodeBody();
13931cb0ef41Sopenharmony_ci  } else {
13941cb0ef41Sopenharmony_ci    GenerateBytecodeBody();
13951cb0ef41Sopenharmony_ci  }
13961cb0ef41Sopenharmony_ci
13971cb0ef41Sopenharmony_ci  // Check that we are not falling off the end.
13981cb0ef41Sopenharmony_ci  DCHECK(builder()->RemainderOfBlockIsDead());
13991cb0ef41Sopenharmony_ci}
14001cb0ef41Sopenharmony_ci
14011cb0ef41Sopenharmony_civoid BytecodeGenerator::GenerateBytecodeBody() {
14021cb0ef41Sopenharmony_ci  // Build the arguments object if it is used.
14031cb0ef41Sopenharmony_ci  VisitArgumentsObject(closure_scope()->arguments());
14041cb0ef41Sopenharmony_ci
14051cb0ef41Sopenharmony_ci  // Build rest arguments array if it is used.
14061cb0ef41Sopenharmony_ci  Variable* rest_parameter = closure_scope()->rest_parameter();
14071cb0ef41Sopenharmony_ci  VisitRestArgumentsArray(rest_parameter);
14081cb0ef41Sopenharmony_ci
14091cb0ef41Sopenharmony_ci  // Build assignment to the function name or {.this_function}
14101cb0ef41Sopenharmony_ci  // variables if used.
14111cb0ef41Sopenharmony_ci  VisitThisFunctionVariable(closure_scope()->function_var());
14121cb0ef41Sopenharmony_ci  VisitThisFunctionVariable(closure_scope()->this_function_var());
14131cb0ef41Sopenharmony_ci
14141cb0ef41Sopenharmony_ci  // Build assignment to {new.target} variable if it is used.
14151cb0ef41Sopenharmony_ci  VisitNewTargetVariable(closure_scope()->new_target_var());
14161cb0ef41Sopenharmony_ci
14171cb0ef41Sopenharmony_ci  // Create a generator object if necessary and initialize the
14181cb0ef41Sopenharmony_ci  // {.generator_object} variable.
14191cb0ef41Sopenharmony_ci  FunctionLiteral* literal = info()->literal();
14201cb0ef41Sopenharmony_ci  if (IsResumableFunction(literal->kind())) {
14211cb0ef41Sopenharmony_ci    BuildGeneratorObjectVariableInitialization();
14221cb0ef41Sopenharmony_ci  }
14231cb0ef41Sopenharmony_ci
14241cb0ef41Sopenharmony_ci  // Emit tracing call if requested to do so.
14251cb0ef41Sopenharmony_ci  if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter);
14261cb0ef41Sopenharmony_ci
14271cb0ef41Sopenharmony_ci  // Emit type profile call.
14281cb0ef41Sopenharmony_ci  if (info()->flags().collect_type_profile()) {
14291cb0ef41Sopenharmony_ci    feedback_spec()->AddTypeProfileSlot();
14301cb0ef41Sopenharmony_ci    int num_parameters = closure_scope()->num_parameters();
14311cb0ef41Sopenharmony_ci    for (int i = 0; i < num_parameters; i++) {
14321cb0ef41Sopenharmony_ci      Register parameter(builder()->Parameter(i));
14331cb0ef41Sopenharmony_ci      builder()->LoadAccumulatorWithRegister(parameter).CollectTypeProfile(
14341cb0ef41Sopenharmony_ci          closure_scope()->parameter(i)->initializer_position());
14351cb0ef41Sopenharmony_ci    }
14361cb0ef41Sopenharmony_ci  }
14371cb0ef41Sopenharmony_ci
14381cb0ef41Sopenharmony_ci  // Increment the function-scope block coverage counter.
14391cb0ef41Sopenharmony_ci  BuildIncrementBlockCoverageCounterIfEnabled(literal, SourceRangeKind::kBody);
14401cb0ef41Sopenharmony_ci
14411cb0ef41Sopenharmony_ci  // Visit declarations within the function scope.
14421cb0ef41Sopenharmony_ci  if (closure_scope()->is_script_scope()) {
14431cb0ef41Sopenharmony_ci    VisitGlobalDeclarations(closure_scope()->declarations());
14441cb0ef41Sopenharmony_ci  } else if (closure_scope()->is_module_scope()) {
14451cb0ef41Sopenharmony_ci    VisitModuleDeclarations(closure_scope()->declarations());
14461cb0ef41Sopenharmony_ci  } else {
14471cb0ef41Sopenharmony_ci    VisitDeclarations(closure_scope()->declarations());
14481cb0ef41Sopenharmony_ci  }
14491cb0ef41Sopenharmony_ci
14501cb0ef41Sopenharmony_ci  // Emit initializing assignments for module namespace imports (if any).
14511cb0ef41Sopenharmony_ci  VisitModuleNamespaceImports();
14521cb0ef41Sopenharmony_ci
14531cb0ef41Sopenharmony_ci  // The derived constructor case is handled in VisitCallSuper.
14541cb0ef41Sopenharmony_ci  if (IsBaseConstructor(function_kind())) {
14551cb0ef41Sopenharmony_ci    if (literal->class_scope_has_private_brand()) {
14561cb0ef41Sopenharmony_ci      ClassScope* scope = info()->scope()->outer_scope()->AsClassScope();
14571cb0ef41Sopenharmony_ci      DCHECK_NOT_NULL(scope->brand());
14581cb0ef41Sopenharmony_ci      BuildPrivateBrandInitialization(builder()->Receiver(), scope->brand());
14591cb0ef41Sopenharmony_ci    }
14601cb0ef41Sopenharmony_ci
14611cb0ef41Sopenharmony_ci    if (literal->requires_instance_members_initializer()) {
14621cb0ef41Sopenharmony_ci      BuildInstanceMemberInitialization(Register::function_closure(),
14631cb0ef41Sopenharmony_ci                                        builder()->Receiver());
14641cb0ef41Sopenharmony_ci    }
14651cb0ef41Sopenharmony_ci  }
14661cb0ef41Sopenharmony_ci
14671cb0ef41Sopenharmony_ci  // Visit statements in the function body.
14681cb0ef41Sopenharmony_ci  VisitStatements(literal->body());
14691cb0ef41Sopenharmony_ci
14701cb0ef41Sopenharmony_ci  // Emit an implicit return instruction in case control flow can fall off the
14711cb0ef41Sopenharmony_ci  // end of the function without an explicit return being present on all paths.
14721cb0ef41Sopenharmony_ci  if (!builder()->RemainderOfBlockIsDead()) {
14731cb0ef41Sopenharmony_ci    builder()->LoadUndefined();
14741cb0ef41Sopenharmony_ci    BuildReturn(literal->return_position());
14751cb0ef41Sopenharmony_ci  }
14761cb0ef41Sopenharmony_ci}
14771cb0ef41Sopenharmony_ci
14781cb0ef41Sopenharmony_civoid BytecodeGenerator::AllocateTopLevelRegisters() {
14791cb0ef41Sopenharmony_ci  if (IsResumableFunction(info()->literal()->kind())) {
14801cb0ef41Sopenharmony_ci    // Either directly use generator_object_var or allocate a new register for
14811cb0ef41Sopenharmony_ci    // the incoming generator object.
14821cb0ef41Sopenharmony_ci    Variable* generator_object_var = closure_scope()->generator_object_var();
14831cb0ef41Sopenharmony_ci    if (generator_object_var->location() == VariableLocation::LOCAL) {
14841cb0ef41Sopenharmony_ci      incoming_new_target_or_generator_ =
14851cb0ef41Sopenharmony_ci          GetRegisterForLocalVariable(generator_object_var);
14861cb0ef41Sopenharmony_ci    } else {
14871cb0ef41Sopenharmony_ci      incoming_new_target_or_generator_ = register_allocator()->NewRegister();
14881cb0ef41Sopenharmony_ci    }
14891cb0ef41Sopenharmony_ci  } else if (closure_scope()->new_target_var()) {
14901cb0ef41Sopenharmony_ci    // Either directly use new_target_var or allocate a new register for
14911cb0ef41Sopenharmony_ci    // the incoming new target object.
14921cb0ef41Sopenharmony_ci    Variable* new_target_var = closure_scope()->new_target_var();
14931cb0ef41Sopenharmony_ci    if (new_target_var->location() == VariableLocation::LOCAL) {
14941cb0ef41Sopenharmony_ci      incoming_new_target_or_generator_ =
14951cb0ef41Sopenharmony_ci          GetRegisterForLocalVariable(new_target_var);
14961cb0ef41Sopenharmony_ci    } else {
14971cb0ef41Sopenharmony_ci      incoming_new_target_or_generator_ = register_allocator()->NewRegister();
14981cb0ef41Sopenharmony_ci    }
14991cb0ef41Sopenharmony_ci  }
15001cb0ef41Sopenharmony_ci}
15011cb0ef41Sopenharmony_ci
15021cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildGeneratorPrologue() {
15031cb0ef41Sopenharmony_ci  DCHECK_GT(info()->literal()->suspend_count(), 0);
15041cb0ef41Sopenharmony_ci  DCHECK(generator_object().is_valid());
15051cb0ef41Sopenharmony_ci  generator_jump_table_ =
15061cb0ef41Sopenharmony_ci      builder()->AllocateJumpTable(info()->literal()->suspend_count(), 0);
15071cb0ef41Sopenharmony_ci
15081cb0ef41Sopenharmony_ci  // If the generator is not undefined, this is a resume, so perform state
15091cb0ef41Sopenharmony_ci  // dispatch.
15101cb0ef41Sopenharmony_ci  builder()->SwitchOnGeneratorState(generator_object(), generator_jump_table_);
15111cb0ef41Sopenharmony_ci
15121cb0ef41Sopenharmony_ci  // Otherwise, fall-through to the ordinary function prologue, after which we
15131cb0ef41Sopenharmony_ci  // will run into the generator object creation and other extra code inserted
15141cb0ef41Sopenharmony_ci  // by the parser.
15151cb0ef41Sopenharmony_ci}
15161cb0ef41Sopenharmony_ci
15171cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitBlock(Block* stmt) {
15181cb0ef41Sopenharmony_ci  // Visit declarations and statements.
15191cb0ef41Sopenharmony_ci  CurrentScope current_scope(this, stmt->scope());
15201cb0ef41Sopenharmony_ci  if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) {
15211cb0ef41Sopenharmony_ci    BuildNewLocalBlockContext(stmt->scope());
15221cb0ef41Sopenharmony_ci    ContextScope scope(this, stmt->scope());
15231cb0ef41Sopenharmony_ci    VisitBlockDeclarationsAndStatements(stmt);
15241cb0ef41Sopenharmony_ci  } else {
15251cb0ef41Sopenharmony_ci    VisitBlockDeclarationsAndStatements(stmt);
15261cb0ef41Sopenharmony_ci  }
15271cb0ef41Sopenharmony_ci}
15281cb0ef41Sopenharmony_ci
15291cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) {
15301cb0ef41Sopenharmony_ci  BlockBuilder block_builder(builder(), block_coverage_builder_, stmt);
15311cb0ef41Sopenharmony_ci  ControlScopeForBreakable execution_control(this, stmt, &block_builder);
15321cb0ef41Sopenharmony_ci  if (stmt->scope() != nullptr) {
15331cb0ef41Sopenharmony_ci    VisitDeclarations(stmt->scope()->declarations());
15341cb0ef41Sopenharmony_ci  }
15351cb0ef41Sopenharmony_ci  VisitStatements(stmt->statements());
15361cb0ef41Sopenharmony_ci}
15371cb0ef41Sopenharmony_ci
15381cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
15391cb0ef41Sopenharmony_ci  Variable* variable = decl->var();
15401cb0ef41Sopenharmony_ci  // Unused variables don't need to be visited.
15411cb0ef41Sopenharmony_ci  if (!variable->is_used()) return;
15421cb0ef41Sopenharmony_ci
15431cb0ef41Sopenharmony_ci  switch (variable->location()) {
15441cb0ef41Sopenharmony_ci    case VariableLocation::UNALLOCATED:
15451cb0ef41Sopenharmony_ci    case VariableLocation::MODULE:
15461cb0ef41Sopenharmony_ci      UNREACHABLE();
15471cb0ef41Sopenharmony_ci    case VariableLocation::LOCAL:
15481cb0ef41Sopenharmony_ci      if (variable->binding_needs_init()) {
15491cb0ef41Sopenharmony_ci        Register destination(builder()->Local(variable->index()));
15501cb0ef41Sopenharmony_ci        builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
15511cb0ef41Sopenharmony_ci      }
15521cb0ef41Sopenharmony_ci      break;
15531cb0ef41Sopenharmony_ci    case VariableLocation::PARAMETER:
15541cb0ef41Sopenharmony_ci      if (variable->binding_needs_init()) {
15551cb0ef41Sopenharmony_ci        Register destination(builder()->Parameter(variable->index()));
15561cb0ef41Sopenharmony_ci        builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
15571cb0ef41Sopenharmony_ci      }
15581cb0ef41Sopenharmony_ci      break;
15591cb0ef41Sopenharmony_ci    case VariableLocation::REPL_GLOBAL:
15601cb0ef41Sopenharmony_ci      // REPL let's are stored in script contexts. They get initialized
15611cb0ef41Sopenharmony_ci      // with the hole the same way as normal context allocated variables.
15621cb0ef41Sopenharmony_ci    case VariableLocation::CONTEXT:
15631cb0ef41Sopenharmony_ci      if (variable->binding_needs_init()) {
15641cb0ef41Sopenharmony_ci        DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
15651cb0ef41Sopenharmony_ci        builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(),
15661cb0ef41Sopenharmony_ci                                                  variable->index(), 0);
15671cb0ef41Sopenharmony_ci      }
15681cb0ef41Sopenharmony_ci      break;
15691cb0ef41Sopenharmony_ci    case VariableLocation::LOOKUP: {
15701cb0ef41Sopenharmony_ci      DCHECK_EQ(VariableMode::kDynamic, variable->mode());
15711cb0ef41Sopenharmony_ci      DCHECK(!variable->binding_needs_init());
15721cb0ef41Sopenharmony_ci
15731cb0ef41Sopenharmony_ci      Register name = register_allocator()->NewRegister();
15741cb0ef41Sopenharmony_ci
15751cb0ef41Sopenharmony_ci      builder()
15761cb0ef41Sopenharmony_ci          ->LoadLiteral(variable->raw_name())
15771cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(name)
15781cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kDeclareEvalVar, name);
15791cb0ef41Sopenharmony_ci      break;
15801cb0ef41Sopenharmony_ci    }
15811cb0ef41Sopenharmony_ci  }
15821cb0ef41Sopenharmony_ci}
15831cb0ef41Sopenharmony_ci
15841cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
15851cb0ef41Sopenharmony_ci  Variable* variable = decl->var();
15861cb0ef41Sopenharmony_ci  DCHECK(variable->mode() == VariableMode::kLet ||
15871cb0ef41Sopenharmony_ci         variable->mode() == VariableMode::kVar ||
15881cb0ef41Sopenharmony_ci         variable->mode() == VariableMode::kDynamic);
15891cb0ef41Sopenharmony_ci  // Unused variables don't need to be visited.
15901cb0ef41Sopenharmony_ci  if (!variable->is_used()) return;
15911cb0ef41Sopenharmony_ci
15921cb0ef41Sopenharmony_ci  switch (variable->location()) {
15931cb0ef41Sopenharmony_ci    case VariableLocation::UNALLOCATED:
15941cb0ef41Sopenharmony_ci    case VariableLocation::MODULE:
15951cb0ef41Sopenharmony_ci      UNREACHABLE();
15961cb0ef41Sopenharmony_ci    case VariableLocation::PARAMETER:
15971cb0ef41Sopenharmony_ci    case VariableLocation::LOCAL: {
15981cb0ef41Sopenharmony_ci      VisitFunctionLiteral(decl->fun());
15991cb0ef41Sopenharmony_ci      BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
16001cb0ef41Sopenharmony_ci      break;
16011cb0ef41Sopenharmony_ci    }
16021cb0ef41Sopenharmony_ci    case VariableLocation::REPL_GLOBAL:
16031cb0ef41Sopenharmony_ci    case VariableLocation::CONTEXT: {
16041cb0ef41Sopenharmony_ci      DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
16051cb0ef41Sopenharmony_ci      VisitFunctionLiteral(decl->fun());
16061cb0ef41Sopenharmony_ci      builder()->StoreContextSlot(execution_context()->reg(), variable->index(),
16071cb0ef41Sopenharmony_ci                                  0);
16081cb0ef41Sopenharmony_ci      break;
16091cb0ef41Sopenharmony_ci    }
16101cb0ef41Sopenharmony_ci    case VariableLocation::LOOKUP: {
16111cb0ef41Sopenharmony_ci      RegisterList args = register_allocator()->NewRegisterList(2);
16121cb0ef41Sopenharmony_ci      builder()
16131cb0ef41Sopenharmony_ci          ->LoadLiteral(variable->raw_name())
16141cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[0]);
16151cb0ef41Sopenharmony_ci      VisitFunctionLiteral(decl->fun());
16161cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(args[1]).CallRuntime(
16171cb0ef41Sopenharmony_ci          Runtime::kDeclareEvalFunction, args);
16181cb0ef41Sopenharmony_ci      break;
16191cb0ef41Sopenharmony_ci    }
16201cb0ef41Sopenharmony_ci  }
16211cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(
16221cb0ef41Sopenharmony_ci      eager_inner_literals_ != nullptr && decl->fun()->ShouldEagerCompile(),
16231cb0ef41Sopenharmony_ci      IsInEagerLiterals(decl->fun(), *eager_inner_literals_));
16241cb0ef41Sopenharmony_ci}
16251cb0ef41Sopenharmony_ci
16261cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitModuleNamespaceImports() {
16271cb0ef41Sopenharmony_ci  if (!closure_scope()->is_module_scope()) return;
16281cb0ef41Sopenharmony_ci
16291cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
16301cb0ef41Sopenharmony_ci  Register module_request = register_allocator()->NewRegister();
16311cb0ef41Sopenharmony_ci
16321cb0ef41Sopenharmony_ci  SourceTextModuleDescriptor* descriptor =
16331cb0ef41Sopenharmony_ci      closure_scope()->AsModuleScope()->module();
16341cb0ef41Sopenharmony_ci  for (auto entry : descriptor->namespace_imports()) {
16351cb0ef41Sopenharmony_ci    builder()
16361cb0ef41Sopenharmony_ci        ->LoadLiteral(Smi::FromInt(entry->module_request))
16371cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(module_request)
16381cb0ef41Sopenharmony_ci        .CallRuntime(Runtime::kGetModuleNamespace, module_request);
16391cb0ef41Sopenharmony_ci    Variable* var = closure_scope()->LookupInModule(entry->local_name);
16401cb0ef41Sopenharmony_ci    BuildVariableAssignment(var, Token::INIT, HoleCheckMode::kElided);
16411cb0ef41Sopenharmony_ci  }
16421cb0ef41Sopenharmony_ci}
16431cb0ef41Sopenharmony_ci
16441cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildDeclareCall(Runtime::FunctionId id) {
16451cb0ef41Sopenharmony_ci  if (!top_level_builder()->has_top_level_declaration()) return;
16461cb0ef41Sopenharmony_ci  DCHECK(!top_level_builder()->processed());
16471cb0ef41Sopenharmony_ci
16481cb0ef41Sopenharmony_ci  top_level_builder()->set_constant_pool_entry(
16491cb0ef41Sopenharmony_ci      builder()->AllocateDeferredConstantPoolEntry());
16501cb0ef41Sopenharmony_ci
16511cb0ef41Sopenharmony_ci  // Emit code to declare globals.
16521cb0ef41Sopenharmony_ci  RegisterList args = register_allocator()->NewRegisterList(2);
16531cb0ef41Sopenharmony_ci  builder()
16541cb0ef41Sopenharmony_ci      ->LoadConstantPoolEntry(top_level_builder()->constant_pool_entry())
16551cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(args[0])
16561cb0ef41Sopenharmony_ci      .MoveRegister(Register::function_closure(), args[1])
16571cb0ef41Sopenharmony_ci      .CallRuntime(id, args);
16581cb0ef41Sopenharmony_ci
16591cb0ef41Sopenharmony_ci  top_level_builder()->mark_processed();
16601cb0ef41Sopenharmony_ci}
16611cb0ef41Sopenharmony_ci
16621cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitModuleDeclarations(Declaration::List* decls) {
16631cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
16641cb0ef41Sopenharmony_ci  for (Declaration* decl : *decls) {
16651cb0ef41Sopenharmony_ci    Variable* var = decl->var();
16661cb0ef41Sopenharmony_ci    if (!var->is_used()) continue;
16671cb0ef41Sopenharmony_ci    if (var->location() == VariableLocation::MODULE) {
16681cb0ef41Sopenharmony_ci      if (decl->IsFunctionDeclaration()) {
16691cb0ef41Sopenharmony_ci        DCHECK(var->IsExport());
16701cb0ef41Sopenharmony_ci        FunctionDeclaration* f = static_cast<FunctionDeclaration*>(decl);
16711cb0ef41Sopenharmony_ci        AddToEagerLiteralsIfEager(f->fun());
16721cb0ef41Sopenharmony_ci        top_level_builder()->record_module_function_declaration();
16731cb0ef41Sopenharmony_ci      } else if (var->IsExport() && var->binding_needs_init()) {
16741cb0ef41Sopenharmony_ci        DCHECK(decl->IsVariableDeclaration());
16751cb0ef41Sopenharmony_ci        top_level_builder()->record_module_variable_declaration();
16761cb0ef41Sopenharmony_ci      }
16771cb0ef41Sopenharmony_ci    } else {
16781cb0ef41Sopenharmony_ci      RegisterAllocationScope inner_register_scope(this);
16791cb0ef41Sopenharmony_ci      Visit(decl);
16801cb0ef41Sopenharmony_ci    }
16811cb0ef41Sopenharmony_ci  }
16821cb0ef41Sopenharmony_ci  BuildDeclareCall(Runtime::kDeclareModuleExports);
16831cb0ef41Sopenharmony_ci}
16841cb0ef41Sopenharmony_ci
16851cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitGlobalDeclarations(Declaration::List* decls) {
16861cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
16871cb0ef41Sopenharmony_ci  for (Declaration* decl : *decls) {
16881cb0ef41Sopenharmony_ci    Variable* var = decl->var();
16891cb0ef41Sopenharmony_ci    DCHECK(var->is_used());
16901cb0ef41Sopenharmony_ci    if (var->location() == VariableLocation::UNALLOCATED) {
16911cb0ef41Sopenharmony_ci      // var or function.
16921cb0ef41Sopenharmony_ci      if (decl->IsFunctionDeclaration()) {
16931cb0ef41Sopenharmony_ci        top_level_builder()->record_global_function_declaration();
16941cb0ef41Sopenharmony_ci        FunctionDeclaration* f = static_cast<FunctionDeclaration*>(decl);
16951cb0ef41Sopenharmony_ci        AddToEagerLiteralsIfEager(f->fun());
16961cb0ef41Sopenharmony_ci      } else {
16971cb0ef41Sopenharmony_ci        top_level_builder()->record_global_variable_declaration();
16981cb0ef41Sopenharmony_ci      }
16991cb0ef41Sopenharmony_ci    } else {
17001cb0ef41Sopenharmony_ci      // let or const. Handled in NewScriptContext.
17011cb0ef41Sopenharmony_ci      DCHECK(decl->IsVariableDeclaration());
17021cb0ef41Sopenharmony_ci      DCHECK(IsLexicalVariableMode(var->mode()));
17031cb0ef41Sopenharmony_ci    }
17041cb0ef41Sopenharmony_ci  }
17051cb0ef41Sopenharmony_ci
17061cb0ef41Sopenharmony_ci  BuildDeclareCall(Runtime::kDeclareGlobals);
17071cb0ef41Sopenharmony_ci}
17081cb0ef41Sopenharmony_ci
17091cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitDeclarations(Declaration::List* declarations) {
17101cb0ef41Sopenharmony_ci  for (Declaration* decl : *declarations) {
17111cb0ef41Sopenharmony_ci    RegisterAllocationScope register_scope(this);
17121cb0ef41Sopenharmony_ci    Visit(decl);
17131cb0ef41Sopenharmony_ci  }
17141cb0ef41Sopenharmony_ci}
17151cb0ef41Sopenharmony_ci
17161cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitStatements(
17171cb0ef41Sopenharmony_ci    const ZonePtrList<Statement>* statements) {
17181cb0ef41Sopenharmony_ci  for (int i = 0; i < statements->length(); i++) {
17191cb0ef41Sopenharmony_ci    // Allocate an outer register allocations scope for the statement.
17201cb0ef41Sopenharmony_ci    RegisterAllocationScope allocation_scope(this);
17211cb0ef41Sopenharmony_ci    Statement* stmt = statements->at(i);
17221cb0ef41Sopenharmony_ci    Visit(stmt);
17231cb0ef41Sopenharmony_ci    if (builder()->RemainderOfBlockIsDead()) break;
17241cb0ef41Sopenharmony_ci  }
17251cb0ef41Sopenharmony_ci}
17261cb0ef41Sopenharmony_ci
17271cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
17281cb0ef41Sopenharmony_ci  builder()->SetStatementPosition(stmt);
17291cb0ef41Sopenharmony_ci  VisitForEffect(stmt->expression());
17301cb0ef41Sopenharmony_ci}
17311cb0ef41Sopenharmony_ci
17321cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {}
17331cb0ef41Sopenharmony_ci
17341cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
17351cb0ef41Sopenharmony_ci  ConditionalControlFlowBuilder conditional_builder(
17361cb0ef41Sopenharmony_ci      builder(), block_coverage_builder_, stmt);
17371cb0ef41Sopenharmony_ci  builder()->SetStatementPosition(stmt);
17381cb0ef41Sopenharmony_ci
17391cb0ef41Sopenharmony_ci  if (stmt->condition()->ToBooleanIsTrue()) {
17401cb0ef41Sopenharmony_ci    // Generate then block unconditionally as always true.
17411cb0ef41Sopenharmony_ci    conditional_builder.Then();
17421cb0ef41Sopenharmony_ci    Visit(stmt->then_statement());
17431cb0ef41Sopenharmony_ci  } else if (stmt->condition()->ToBooleanIsFalse()) {
17441cb0ef41Sopenharmony_ci    // Generate else block unconditionally if it exists.
17451cb0ef41Sopenharmony_ci    if (stmt->HasElseStatement()) {
17461cb0ef41Sopenharmony_ci      conditional_builder.Else();
17471cb0ef41Sopenharmony_ci      Visit(stmt->else_statement());
17481cb0ef41Sopenharmony_ci    }
17491cb0ef41Sopenharmony_ci  } else {
17501cb0ef41Sopenharmony_ci    // TODO(oth): If then statement is BreakStatement or
17511cb0ef41Sopenharmony_ci    // ContinueStatement we can reduce number of generated
17521cb0ef41Sopenharmony_ci    // jump/jump_ifs here. See BasicLoops test.
17531cb0ef41Sopenharmony_ci    VisitForTest(stmt->condition(), conditional_builder.then_labels(),
17541cb0ef41Sopenharmony_ci                 conditional_builder.else_labels(), TestFallthrough::kThen);
17551cb0ef41Sopenharmony_ci
17561cb0ef41Sopenharmony_ci    conditional_builder.Then();
17571cb0ef41Sopenharmony_ci    Visit(stmt->then_statement());
17581cb0ef41Sopenharmony_ci
17591cb0ef41Sopenharmony_ci    if (stmt->HasElseStatement()) {
17601cb0ef41Sopenharmony_ci      conditional_builder.JumpToEnd();
17611cb0ef41Sopenharmony_ci      conditional_builder.Else();
17621cb0ef41Sopenharmony_ci      Visit(stmt->else_statement());
17631cb0ef41Sopenharmony_ci    }
17641cb0ef41Sopenharmony_ci  }
17651cb0ef41Sopenharmony_ci}
17661cb0ef41Sopenharmony_ci
17671cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitSloppyBlockFunctionStatement(
17681cb0ef41Sopenharmony_ci    SloppyBlockFunctionStatement* stmt) {
17691cb0ef41Sopenharmony_ci  Visit(stmt->statement());
17701cb0ef41Sopenharmony_ci}
17711cb0ef41Sopenharmony_ci
17721cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
17731cb0ef41Sopenharmony_ci  AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
17741cb0ef41Sopenharmony_ci  builder()->SetStatementPosition(stmt);
17751cb0ef41Sopenharmony_ci  execution_control()->Continue(stmt->target());
17761cb0ef41Sopenharmony_ci}
17771cb0ef41Sopenharmony_ci
17781cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
17791cb0ef41Sopenharmony_ci  AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
17801cb0ef41Sopenharmony_ci  builder()->SetStatementPosition(stmt);
17811cb0ef41Sopenharmony_ci  execution_control()->Break(stmt->target());
17821cb0ef41Sopenharmony_ci}
17831cb0ef41Sopenharmony_ci
17841cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
17851cb0ef41Sopenharmony_ci  AllocateBlockCoverageSlotIfEnabled(stmt, SourceRangeKind::kContinuation);
17861cb0ef41Sopenharmony_ci  builder()->SetStatementPosition(stmt);
17871cb0ef41Sopenharmony_ci  VisitForAccumulatorValue(stmt->expression());
17881cb0ef41Sopenharmony_ci  int return_position = stmt->end_position();
17891cb0ef41Sopenharmony_ci  if (return_position == ReturnStatement::kFunctionLiteralReturnPosition) {
17901cb0ef41Sopenharmony_ci    return_position = info()->literal()->return_position();
17911cb0ef41Sopenharmony_ci  }
17921cb0ef41Sopenharmony_ci  if (stmt->is_async_return()) {
17931cb0ef41Sopenharmony_ci    execution_control()->AsyncReturnAccumulator(return_position);
17941cb0ef41Sopenharmony_ci  } else {
17951cb0ef41Sopenharmony_ci    execution_control()->ReturnAccumulator(return_position);
17961cb0ef41Sopenharmony_ci  }
17971cb0ef41Sopenharmony_ci}
17981cb0ef41Sopenharmony_ci
17991cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
18001cb0ef41Sopenharmony_ci  builder()->SetStatementPosition(stmt);
18011cb0ef41Sopenharmony_ci  VisitForAccumulatorValue(stmt->expression());
18021cb0ef41Sopenharmony_ci  BuildNewLocalWithContext(stmt->scope());
18031cb0ef41Sopenharmony_ci  VisitInScope(stmt->statement(), stmt->scope());
18041cb0ef41Sopenharmony_ci}
18051cb0ef41Sopenharmony_ci
18061cb0ef41Sopenharmony_cinamespace {
18071cb0ef41Sopenharmony_ci
18081cb0ef41Sopenharmony_cibool IsSmiLiteralSwitchCaseValue(Expression* expr) {
18091cb0ef41Sopenharmony_ci  if (expr->IsSmiLiteral() ||
18101cb0ef41Sopenharmony_ci      (expr->IsLiteral() && expr->AsLiteral()->IsNumber() &&
18111cb0ef41Sopenharmony_ci       expr->AsLiteral()->AsNumber() == 0.0)) {
18121cb0ef41Sopenharmony_ci    return true;
18131cb0ef41Sopenharmony_ci#ifdef DEBUG
18141cb0ef41Sopenharmony_ci  } else if (expr->IsLiteral() && expr->AsLiteral()->IsNumber()) {
18151cb0ef41Sopenharmony_ci    DCHECK(!IsSmiDouble(expr->AsLiteral()->AsNumber()));
18161cb0ef41Sopenharmony_ci#endif
18171cb0ef41Sopenharmony_ci  }
18181cb0ef41Sopenharmony_ci  return false;
18191cb0ef41Sopenharmony_ci}
18201cb0ef41Sopenharmony_ci
18211cb0ef41Sopenharmony_ci// Precondition: we called IsSmiLiteral to check this.
18221cb0ef41Sopenharmony_ciinline int ReduceToSmiSwitchCaseValue(Expression* expr) {
18231cb0ef41Sopenharmony_ci  if (V8_LIKELY(expr->IsSmiLiteral())) {
18241cb0ef41Sopenharmony_ci    return expr->AsLiteral()->AsSmiLiteral().value();
18251cb0ef41Sopenharmony_ci  } else {
18261cb0ef41Sopenharmony_ci    // Only the zero case is possible otherwise.
18271cb0ef41Sopenharmony_ci    DCHECK(expr->IsLiteral() && expr->AsLiteral()->IsNumber() &&
18281cb0ef41Sopenharmony_ci           expr->AsLiteral()->AsNumber() == -0.0);
18291cb0ef41Sopenharmony_ci    return 0;
18301cb0ef41Sopenharmony_ci  }
18311cb0ef41Sopenharmony_ci}
18321cb0ef41Sopenharmony_ci
18331cb0ef41Sopenharmony_ci// Is the range of Smi's small enough relative to number of cases?
18341cb0ef41Sopenharmony_ciinline bool IsSpreadAcceptable(int spread, int ncases) {
18351cb0ef41Sopenharmony_ci  return spread < FLAG_switch_table_spread_threshold * ncases;
18361cb0ef41Sopenharmony_ci}
18371cb0ef41Sopenharmony_ci
18381cb0ef41Sopenharmony_cistruct SwitchInfo {
18391cb0ef41Sopenharmony_ci  static const int kDefaultNotFound = -1;
18401cb0ef41Sopenharmony_ci
18411cb0ef41Sopenharmony_ci  std::map<int, CaseClause*> covered_cases;
18421cb0ef41Sopenharmony_ci  int default_case;
18431cb0ef41Sopenharmony_ci
18441cb0ef41Sopenharmony_ci  SwitchInfo() { default_case = kDefaultNotFound; }
18451cb0ef41Sopenharmony_ci
18461cb0ef41Sopenharmony_ci  bool DefaultExists() { return default_case != kDefaultNotFound; }
18471cb0ef41Sopenharmony_ci  bool CaseExists(int j) {
18481cb0ef41Sopenharmony_ci    return covered_cases.find(j) != covered_cases.end();
18491cb0ef41Sopenharmony_ci  }
18501cb0ef41Sopenharmony_ci  bool CaseExists(Expression* expr) {
18511cb0ef41Sopenharmony_ci    return IsSmiLiteralSwitchCaseValue(expr)
18521cb0ef41Sopenharmony_ci               ? CaseExists(ReduceToSmiSwitchCaseValue(expr))
18531cb0ef41Sopenharmony_ci               : false;
18541cb0ef41Sopenharmony_ci  }
18551cb0ef41Sopenharmony_ci  CaseClause* GetClause(int j) { return covered_cases[j]; }
18561cb0ef41Sopenharmony_ci
18571cb0ef41Sopenharmony_ci  bool IsDuplicate(CaseClause* clause) {
18581cb0ef41Sopenharmony_ci    return IsSmiLiteralSwitchCaseValue(clause->label()) &&
18591cb0ef41Sopenharmony_ci           CaseExists(clause->label()) &&
18601cb0ef41Sopenharmony_ci           clause != GetClause(ReduceToSmiSwitchCaseValue(clause->label()));
18611cb0ef41Sopenharmony_ci  }
18621cb0ef41Sopenharmony_ci  int MinCase() {
18631cb0ef41Sopenharmony_ci    return covered_cases.size() == 0 ? INT_MAX : covered_cases.begin()->first;
18641cb0ef41Sopenharmony_ci  }
18651cb0ef41Sopenharmony_ci  int MaxCase() {
18661cb0ef41Sopenharmony_ci    return covered_cases.size() == 0 ? INT_MIN : covered_cases.rbegin()->first;
18671cb0ef41Sopenharmony_ci  }
18681cb0ef41Sopenharmony_ci  void Print() {
18691cb0ef41Sopenharmony_ci    std::cout << "Covered_cases: " << '\n';
18701cb0ef41Sopenharmony_ci    for (auto iter = covered_cases.begin(); iter != covered_cases.end();
18711cb0ef41Sopenharmony_ci         ++iter) {
18721cb0ef41Sopenharmony_ci      std::cout << iter->first << "->" << iter->second << '\n';
18731cb0ef41Sopenharmony_ci    }
18741cb0ef41Sopenharmony_ci    std::cout << "Default_case: " << default_case << '\n';
18751cb0ef41Sopenharmony_ci  }
18761cb0ef41Sopenharmony_ci};
18771cb0ef41Sopenharmony_ci
18781cb0ef41Sopenharmony_ci// Checks whether we should use a jump table to implement a switch operation.
18791cb0ef41Sopenharmony_cibool IsSwitchOptimizable(SwitchStatement* stmt, SwitchInfo* info) {
18801cb0ef41Sopenharmony_ci  ZonePtrList<CaseClause>* cases = stmt->cases();
18811cb0ef41Sopenharmony_ci
18821cb0ef41Sopenharmony_ci  for (int i = 0; i < cases->length(); ++i) {
18831cb0ef41Sopenharmony_ci    CaseClause* clause = cases->at(i);
18841cb0ef41Sopenharmony_ci    if (clause->is_default()) {
18851cb0ef41Sopenharmony_ci      continue;
18861cb0ef41Sopenharmony_ci    } else if (!(clause->label()->IsLiteral())) {
18871cb0ef41Sopenharmony_ci      // Don't consider Smi cases after a non-literal, because we
18881cb0ef41Sopenharmony_ci      // need to evaluate the non-literal.
18891cb0ef41Sopenharmony_ci      break;
18901cb0ef41Sopenharmony_ci    } else if (IsSmiLiteralSwitchCaseValue(clause->label())) {
18911cb0ef41Sopenharmony_ci      int value = ReduceToSmiSwitchCaseValue(clause->label());
18921cb0ef41Sopenharmony_ci      info->covered_cases.insert({value, clause});
18931cb0ef41Sopenharmony_ci    }
18941cb0ef41Sopenharmony_ci  }
18951cb0ef41Sopenharmony_ci
18961cb0ef41Sopenharmony_ci  // GCC also jump-table optimizes switch statements with 6 cases or more.
18971cb0ef41Sopenharmony_ci  if (static_cast<int>(info->covered_cases.size()) >=
18981cb0ef41Sopenharmony_ci      FLAG_switch_table_min_cases) {
18991cb0ef41Sopenharmony_ci    // Due to case spread will be used as the size of jump-table,
19001cb0ef41Sopenharmony_ci    // we need to check if it doesn't overflow by casting its
19011cb0ef41Sopenharmony_ci    // min and max bounds to int64_t, and calculate if the difference is less
19021cb0ef41Sopenharmony_ci    // than or equal to INT_MAX.
19031cb0ef41Sopenharmony_ci    int64_t min = static_cast<int64_t>(info->MinCase());
19041cb0ef41Sopenharmony_ci    int64_t max = static_cast<int64_t>(info->MaxCase());
19051cb0ef41Sopenharmony_ci    int64_t spread = max - min + 1;
19061cb0ef41Sopenharmony_ci
19071cb0ef41Sopenharmony_ci    DCHECK_GT(spread, 0);
19081cb0ef41Sopenharmony_ci
19091cb0ef41Sopenharmony_ci    // Check if casted spread is acceptable and doesn't overflow.
19101cb0ef41Sopenharmony_ci    if (spread <= INT_MAX &&
19111cb0ef41Sopenharmony_ci        IsSpreadAcceptable(static_cast<int>(spread), cases->length())) {
19121cb0ef41Sopenharmony_ci      return true;
19131cb0ef41Sopenharmony_ci    }
19141cb0ef41Sopenharmony_ci  }
19151cb0ef41Sopenharmony_ci  // Invariant- covered_cases has all cases and only cases that will go in the
19161cb0ef41Sopenharmony_ci  // jump table.
19171cb0ef41Sopenharmony_ci  info->covered_cases.clear();
19181cb0ef41Sopenharmony_ci  return false;
19191cb0ef41Sopenharmony_ci}
19201cb0ef41Sopenharmony_ci
19211cb0ef41Sopenharmony_ci}  // namespace
19221cb0ef41Sopenharmony_ci
19231cb0ef41Sopenharmony_ci// This adds a jump table optimization for switch statements with Smi cases.
19241cb0ef41Sopenharmony_ci// If there are 5+ non-duplicate Smi clauses, and they are sufficiently compact,
19251cb0ef41Sopenharmony_ci// we generate a jump table. In the fall-through path, we put the compare-jumps
19261cb0ef41Sopenharmony_ci// for the non-Smi cases.
19271cb0ef41Sopenharmony_ci
19281cb0ef41Sopenharmony_ci// e.g.
19291cb0ef41Sopenharmony_ci//
19301cb0ef41Sopenharmony_ci// switch(x){
19311cb0ef41Sopenharmony_ci//   case -0: out = 10;
19321cb0ef41Sopenharmony_ci//   case 1: out = 11; break;
19331cb0ef41Sopenharmony_ci//   case 0: out = 12; break;
19341cb0ef41Sopenharmony_ci//   case 2: out = 13;
19351cb0ef41Sopenharmony_ci//   case 3: out = 14; break;
19361cb0ef41Sopenharmony_ci//   case 0.5: out = 15; break;
19371cb0ef41Sopenharmony_ci//   case 4: out = 16;
19381cb0ef41Sopenharmony_ci//   case y: out = 17;
19391cb0ef41Sopenharmony_ci//   case 5: out = 18;
19401cb0ef41Sopenharmony_ci//   default: out = 19; break;
19411cb0ef41Sopenharmony_ci// }
19421cb0ef41Sopenharmony_ci
19431cb0ef41Sopenharmony_ci// becomes this pseudo-bytecode:
19441cb0ef41Sopenharmony_ci
19451cb0ef41Sopenharmony_ci//   lda x
19461cb0ef41Sopenharmony_ci//   star r1
19471cb0ef41Sopenharmony_ci//   test_type number
19481cb0ef41Sopenharmony_ci//   jump_if_false @fallthrough
19491cb0ef41Sopenharmony_ci//   ldar r1
19501cb0ef41Sopenharmony_ci//   test_greater_than_or_equal_to smi_min
19511cb0ef41Sopenharmony_ci//   jump_if_false @fallthrough
19521cb0ef41Sopenharmony_ci//   ldar r1
19531cb0ef41Sopenharmony_ci//   test_less_than_or_equal_to smi_max
19541cb0ef41Sopenharmony_ci//   jump_if_false @fallthrough
19551cb0ef41Sopenharmony_ci//   ldar r1
19561cb0ef41Sopenharmony_ci//   bitwise_or 0
19571cb0ef41Sopenharmony_ci//   star r2
19581cb0ef41Sopenharmony_ci//   test_strict_equal r1
19591cb0ef41Sopenharmony_ci//   jump_if_false @fallthrough
19601cb0ef41Sopenharmony_ci//   ldar r2
19611cb0ef41Sopenharmony_ci//   switch_on_smi {1: @case_1, 2: @case_2, 3: @case_3, 4: @case_4}
19621cb0ef41Sopenharmony_ci// @fallthrough:
19631cb0ef41Sopenharmony_ci//   jump_if_strict_equal -0.0 @case_minus_0.0
19641cb0ef41Sopenharmony_ci//   jump_if_strict_equal 0.5  @case_0.5
19651cb0ef41Sopenharmony_ci//   jump_if_strict_equal y    @case_y
19661cb0ef41Sopenharmony_ci//   jump_if_strict_equal 5    @case_5
19671cb0ef41Sopenharmony_ci//   jump @default
19681cb0ef41Sopenharmony_ci// @case_minus_0.0:
19691cb0ef41Sopenharmony_ci//   <out = 10>
19701cb0ef41Sopenharmony_ci// @case_1
19711cb0ef41Sopenharmony_ci//   <out = 11, break>
19721cb0ef41Sopenharmony_ci// @case_0:
19731cb0ef41Sopenharmony_ci//   <out = 12, break>
19741cb0ef41Sopenharmony_ci// @case_2:
19751cb0ef41Sopenharmony_ci//   <out = 13>
19761cb0ef41Sopenharmony_ci// @case_3:
19771cb0ef41Sopenharmony_ci//   <out = 14, break>
19781cb0ef41Sopenharmony_ci// @case_0.5:
19791cb0ef41Sopenharmony_ci//   <out = 15, break>
19801cb0ef41Sopenharmony_ci// @case_4:
19811cb0ef41Sopenharmony_ci//   <out = 16>
19821cb0ef41Sopenharmony_ci// @case_y:
19831cb0ef41Sopenharmony_ci//   <out = 17>
19841cb0ef41Sopenharmony_ci// @case_5:
19851cb0ef41Sopenharmony_ci//   <out = 18>
19861cb0ef41Sopenharmony_ci// @default:
19871cb0ef41Sopenharmony_ci//   <out = 19, break>
19881cb0ef41Sopenharmony_ci
19891cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
19901cb0ef41Sopenharmony_ci  // We need this scope because we visit for register values. We have to
19911cb0ef41Sopenharmony_ci  // maintain a execution result scope where registers can be allocated.
19921cb0ef41Sopenharmony_ci  ZonePtrList<CaseClause>* clauses = stmt->cases();
19931cb0ef41Sopenharmony_ci
19941cb0ef41Sopenharmony_ci  SwitchInfo info;
19951cb0ef41Sopenharmony_ci  BytecodeJumpTable* jump_table = nullptr;
19961cb0ef41Sopenharmony_ci  bool use_jump_table = IsSwitchOptimizable(stmt, &info);
19971cb0ef41Sopenharmony_ci
19981cb0ef41Sopenharmony_ci  // N_comp_cases is number of cases we will generate comparison jumps for.
19991cb0ef41Sopenharmony_ci  // Note we ignore duplicate cases, since they are very unlikely.
20001cb0ef41Sopenharmony_ci
20011cb0ef41Sopenharmony_ci  int n_comp_cases = clauses->length();
20021cb0ef41Sopenharmony_ci  if (use_jump_table) {
20031cb0ef41Sopenharmony_ci    n_comp_cases -= static_cast<int>(info.covered_cases.size());
20041cb0ef41Sopenharmony_ci    jump_table = builder()->AllocateJumpTable(
20051cb0ef41Sopenharmony_ci        info.MaxCase() - info.MinCase() + 1, info.MinCase());
20061cb0ef41Sopenharmony_ci  }
20071cb0ef41Sopenharmony_ci
20081cb0ef41Sopenharmony_ci  // Are we still using any if-else bytecodes to evaluate the switch?
20091cb0ef41Sopenharmony_ci  bool use_jumps = n_comp_cases != 0;
20101cb0ef41Sopenharmony_ci
20111cb0ef41Sopenharmony_ci  SwitchBuilder switch_builder(builder(), block_coverage_builder_, stmt,
20121cb0ef41Sopenharmony_ci                               n_comp_cases, jump_table);
20131cb0ef41Sopenharmony_ci  ControlScopeForBreakable scope(this, stmt, &switch_builder);
20141cb0ef41Sopenharmony_ci  builder()->SetStatementPosition(stmt);
20151cb0ef41Sopenharmony_ci
20161cb0ef41Sopenharmony_ci  VisitForAccumulatorValue(stmt->tag());
20171cb0ef41Sopenharmony_ci
20181cb0ef41Sopenharmony_ci  if (use_jump_table) {
20191cb0ef41Sopenharmony_ci    // This also fills empty slots in jump table.
20201cb0ef41Sopenharmony_ci    Register r2 = register_allocator()->NewRegister();
20211cb0ef41Sopenharmony_ci
20221cb0ef41Sopenharmony_ci    Register r1 = register_allocator()->NewRegister();
20231cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(r1);
20241cb0ef41Sopenharmony_ci
20251cb0ef41Sopenharmony_ci    builder()->CompareTypeOf(TestTypeOfFlags::LiteralFlag::kNumber);
20261cb0ef41Sopenharmony_ci    switch_builder.JumpToFallThroughIfFalse();
20271cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(r1);
20281cb0ef41Sopenharmony_ci
20291cb0ef41Sopenharmony_ci    // TODO(leszeks): Note these are duplicated range checks with the
20301cb0ef41Sopenharmony_ci    // SwitchOnSmi handler for the most part.
20311cb0ef41Sopenharmony_ci
20321cb0ef41Sopenharmony_ci    builder()->LoadLiteral(Smi::kMinValue);
20331cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(r2);
20341cb0ef41Sopenharmony_ci    builder()->CompareOperation(
20351cb0ef41Sopenharmony_ci        Token::Value::GTE, r1,
20361cb0ef41Sopenharmony_ci        feedback_index(feedback_spec()->AddCompareICSlot()));
20371cb0ef41Sopenharmony_ci
20381cb0ef41Sopenharmony_ci    switch_builder.JumpToFallThroughIfFalse();
20391cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(r1);
20401cb0ef41Sopenharmony_ci
20411cb0ef41Sopenharmony_ci    builder()->LoadLiteral(Smi::kMaxValue);
20421cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(r2);
20431cb0ef41Sopenharmony_ci    builder()->CompareOperation(
20441cb0ef41Sopenharmony_ci        Token::Value::LTE, r1,
20451cb0ef41Sopenharmony_ci        feedback_index(feedback_spec()->AddCompareICSlot()));
20461cb0ef41Sopenharmony_ci
20471cb0ef41Sopenharmony_ci    switch_builder.JumpToFallThroughIfFalse();
20481cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(r1);
20491cb0ef41Sopenharmony_ci
20501cb0ef41Sopenharmony_ci    builder()->BinaryOperationSmiLiteral(
20511cb0ef41Sopenharmony_ci        Token::Value::BIT_OR, Smi::FromInt(0),
20521cb0ef41Sopenharmony_ci        feedback_index(feedback_spec()->AddBinaryOpICSlot()));
20531cb0ef41Sopenharmony_ci
20541cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(r2);
20551cb0ef41Sopenharmony_ci    builder()->CompareOperation(
20561cb0ef41Sopenharmony_ci        Token::Value::EQ_STRICT, r1,
20571cb0ef41Sopenharmony_ci        feedback_index(feedback_spec()->AddCompareICSlot()));
20581cb0ef41Sopenharmony_ci
20591cb0ef41Sopenharmony_ci    switch_builder.JumpToFallThroughIfFalse();
20601cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(r2);
20611cb0ef41Sopenharmony_ci
20621cb0ef41Sopenharmony_ci    switch_builder.EmitJumpTableIfExists(info.MinCase(), info.MaxCase(),
20631cb0ef41Sopenharmony_ci                                         info.covered_cases);
20641cb0ef41Sopenharmony_ci
20651cb0ef41Sopenharmony_ci    if (use_jumps) {
20661cb0ef41Sopenharmony_ci      builder()->LoadAccumulatorWithRegister(r1);
20671cb0ef41Sopenharmony_ci    }
20681cb0ef41Sopenharmony_ci  }
20691cb0ef41Sopenharmony_ci
20701cb0ef41Sopenharmony_ci  int case_compare_ctr = 0;
20711cb0ef41Sopenharmony_ci#ifdef DEBUG
20721cb0ef41Sopenharmony_ci  std::unordered_map<int, int> case_ctr_checker;
20731cb0ef41Sopenharmony_ci#endif
20741cb0ef41Sopenharmony_ci
20751cb0ef41Sopenharmony_ci  if (use_jumps) {
20761cb0ef41Sopenharmony_ci    Register tag_holder = register_allocator()->NewRegister();
20771cb0ef41Sopenharmony_ci    FeedbackSlot slot = clauses->length() > 0
20781cb0ef41Sopenharmony_ci                            ? feedback_spec()->AddCompareICSlot()
20791cb0ef41Sopenharmony_ci                            : FeedbackSlot::Invalid();
20801cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(tag_holder);
20811cb0ef41Sopenharmony_ci
20821cb0ef41Sopenharmony_ci    for (int i = 0; i < clauses->length(); ++i) {
20831cb0ef41Sopenharmony_ci      CaseClause* clause = clauses->at(i);
20841cb0ef41Sopenharmony_ci      if (clause->is_default()) {
20851cb0ef41Sopenharmony_ci        info.default_case = i;
20861cb0ef41Sopenharmony_ci      } else if (!info.CaseExists(clause->label())) {
20871cb0ef41Sopenharmony_ci        // Perform label comparison as if via '===' with tag.
20881cb0ef41Sopenharmony_ci        VisitForAccumulatorValue(clause->label());
20891cb0ef41Sopenharmony_ci        builder()->CompareOperation(Token::Value::EQ_STRICT, tag_holder,
20901cb0ef41Sopenharmony_ci                                    feedback_index(slot));
20911cb0ef41Sopenharmony_ci#ifdef DEBUG
20921cb0ef41Sopenharmony_ci        case_ctr_checker[i] = case_compare_ctr;
20931cb0ef41Sopenharmony_ci#endif
20941cb0ef41Sopenharmony_ci        switch_builder.JumpToCaseIfTrue(ToBooleanMode::kAlreadyBoolean,
20951cb0ef41Sopenharmony_ci                                        case_compare_ctr++);
20961cb0ef41Sopenharmony_ci      }
20971cb0ef41Sopenharmony_ci    }
20981cb0ef41Sopenharmony_ci  }
20991cb0ef41Sopenharmony_ci
21001cb0ef41Sopenharmony_ci  // For fall-throughs after comparisons (or out-of-range/non-Smi's for jump
21011cb0ef41Sopenharmony_ci  // tables).
21021cb0ef41Sopenharmony_ci  if (info.DefaultExists()) {
21031cb0ef41Sopenharmony_ci    switch_builder.JumpToDefault();
21041cb0ef41Sopenharmony_ci  } else {
21051cb0ef41Sopenharmony_ci    switch_builder.Break();
21061cb0ef41Sopenharmony_ci  }
21071cb0ef41Sopenharmony_ci
21081cb0ef41Sopenharmony_ci  case_compare_ctr = 0;
21091cb0ef41Sopenharmony_ci  for (int i = 0; i < clauses->length(); ++i) {
21101cb0ef41Sopenharmony_ci    CaseClause* clause = clauses->at(i);
21111cb0ef41Sopenharmony_ci    if (i != info.default_case) {
21121cb0ef41Sopenharmony_ci      if (!info.IsDuplicate(clause)) {
21131cb0ef41Sopenharmony_ci        bool use_table = use_jump_table && info.CaseExists(clause->label());
21141cb0ef41Sopenharmony_ci        if (!use_table) {
21151cb0ef41Sopenharmony_ci// Guarantee that we should generate compare/jump if no table.
21161cb0ef41Sopenharmony_ci#ifdef DEBUG
21171cb0ef41Sopenharmony_ci          DCHECK(case_ctr_checker[i] == case_compare_ctr);
21181cb0ef41Sopenharmony_ci#endif
21191cb0ef41Sopenharmony_ci          switch_builder.BindCaseTargetForCompareJump(case_compare_ctr++,
21201cb0ef41Sopenharmony_ci                                                      clause);
21211cb0ef41Sopenharmony_ci        } else {
21221cb0ef41Sopenharmony_ci          // Use jump table if this is not a duplicate label.
21231cb0ef41Sopenharmony_ci          switch_builder.BindCaseTargetForJumpTable(
21241cb0ef41Sopenharmony_ci              ReduceToSmiSwitchCaseValue(clause->label()), clause);
21251cb0ef41Sopenharmony_ci        }
21261cb0ef41Sopenharmony_ci      }
21271cb0ef41Sopenharmony_ci    } else {
21281cb0ef41Sopenharmony_ci      switch_builder.BindDefault(clause);
21291cb0ef41Sopenharmony_ci    }
21301cb0ef41Sopenharmony_ci    // Regardless, generate code (in case of fall throughs).
21311cb0ef41Sopenharmony_ci    VisitStatements(clause->statements());
21321cb0ef41Sopenharmony_ci  }
21331cb0ef41Sopenharmony_ci}
21341cb0ef41Sopenharmony_ci
21351cb0ef41Sopenharmony_citemplate <typename TryBodyFunc, typename CatchBodyFunc>
21361cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildTryCatch(
21371cb0ef41Sopenharmony_ci    TryBodyFunc try_body_func, CatchBodyFunc catch_body_func,
21381cb0ef41Sopenharmony_ci    HandlerTable::CatchPrediction catch_prediction,
21391cb0ef41Sopenharmony_ci    TryCatchStatement* stmt_for_coverage) {
21401cb0ef41Sopenharmony_ci  if (builder()->RemainderOfBlockIsDead()) return;
21411cb0ef41Sopenharmony_ci
21421cb0ef41Sopenharmony_ci  TryCatchBuilder try_control_builder(
21431cb0ef41Sopenharmony_ci      builder(),
21441cb0ef41Sopenharmony_ci      stmt_for_coverage == nullptr ? nullptr : block_coverage_builder_,
21451cb0ef41Sopenharmony_ci      stmt_for_coverage, catch_prediction);
21461cb0ef41Sopenharmony_ci
21471cb0ef41Sopenharmony_ci  // Preserve the context in a dedicated register, so that it can be restored
21481cb0ef41Sopenharmony_ci  // when the handler is entered by the stack-unwinding machinery.
21491cb0ef41Sopenharmony_ci  // TODO(ignition): Be smarter about register allocation.
21501cb0ef41Sopenharmony_ci  Register context = register_allocator()->NewRegister();
21511cb0ef41Sopenharmony_ci  builder()->MoveRegister(Register::current_context(), context);
21521cb0ef41Sopenharmony_ci
21531cb0ef41Sopenharmony_ci  // Evaluate the try-block inside a control scope. This simulates a handler
21541cb0ef41Sopenharmony_ci  // that is intercepting 'throw' control commands.
21551cb0ef41Sopenharmony_ci  try_control_builder.BeginTry(context);
21561cb0ef41Sopenharmony_ci  {
21571cb0ef41Sopenharmony_ci    ControlScopeForTryCatch scope(this, &try_control_builder);
21581cb0ef41Sopenharmony_ci    try_body_func();
21591cb0ef41Sopenharmony_ci  }
21601cb0ef41Sopenharmony_ci  try_control_builder.EndTry();
21611cb0ef41Sopenharmony_ci
21621cb0ef41Sopenharmony_ci  catch_body_func(context);
21631cb0ef41Sopenharmony_ci
21641cb0ef41Sopenharmony_ci  try_control_builder.EndCatch();
21651cb0ef41Sopenharmony_ci}
21661cb0ef41Sopenharmony_ci
21671cb0ef41Sopenharmony_citemplate <typename TryBodyFunc, typename FinallyBodyFunc>
21681cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildTryFinally(
21691cb0ef41Sopenharmony_ci    TryBodyFunc try_body_func, FinallyBodyFunc finally_body_func,
21701cb0ef41Sopenharmony_ci    HandlerTable::CatchPrediction catch_prediction,
21711cb0ef41Sopenharmony_ci    TryFinallyStatement* stmt_for_coverage) {
21721cb0ef41Sopenharmony_ci  if (builder()->RemainderOfBlockIsDead()) return;
21731cb0ef41Sopenharmony_ci
21741cb0ef41Sopenharmony_ci  // We can't know whether the finally block will override ("catch") an
21751cb0ef41Sopenharmony_ci  // exception thrown in the try block, so we just adopt the outer prediction.
21761cb0ef41Sopenharmony_ci  TryFinallyBuilder try_control_builder(
21771cb0ef41Sopenharmony_ci      builder(),
21781cb0ef41Sopenharmony_ci      stmt_for_coverage == nullptr ? nullptr : block_coverage_builder_,
21791cb0ef41Sopenharmony_ci      stmt_for_coverage, catch_prediction);
21801cb0ef41Sopenharmony_ci
21811cb0ef41Sopenharmony_ci  // We keep a record of all paths that enter the finally-block to be able to
21821cb0ef41Sopenharmony_ci  // dispatch to the correct continuation point after the statements in the
21831cb0ef41Sopenharmony_ci  // finally-block have been evaluated.
21841cb0ef41Sopenharmony_ci  //
21851cb0ef41Sopenharmony_ci  // The try-finally construct can enter the finally-block in three ways:
21861cb0ef41Sopenharmony_ci  // 1. By exiting the try-block normally, falling through at the end.
21871cb0ef41Sopenharmony_ci  // 2. By exiting the try-block with a function-local control flow transfer
21881cb0ef41Sopenharmony_ci  //    (i.e. through break/continue/return statements).
21891cb0ef41Sopenharmony_ci  // 3. By exiting the try-block with a thrown exception.
21901cb0ef41Sopenharmony_ci  //
21911cb0ef41Sopenharmony_ci  // The result register semantics depend on how the block was entered:
21921cb0ef41Sopenharmony_ci  //  - ReturnStatement: It represents the return value being returned.
21931cb0ef41Sopenharmony_ci  //  - ThrowStatement: It represents the exception being thrown.
21941cb0ef41Sopenharmony_ci  //  - BreakStatement/ContinueStatement: Undefined and not used.
21951cb0ef41Sopenharmony_ci  //  - Falling through into finally-block: Undefined and not used.
21961cb0ef41Sopenharmony_ci  Register token = register_allocator()->NewRegister();
21971cb0ef41Sopenharmony_ci  Register result = register_allocator()->NewRegister();
21981cb0ef41Sopenharmony_ci  ControlScope::DeferredCommands commands(this, token, result);
21991cb0ef41Sopenharmony_ci
22001cb0ef41Sopenharmony_ci  // Preserve the context in a dedicated register, so that it can be restored
22011cb0ef41Sopenharmony_ci  // when the handler is entered by the stack-unwinding machinery.
22021cb0ef41Sopenharmony_ci  // TODO(ignition): Be smarter about register allocation.
22031cb0ef41Sopenharmony_ci  Register context = register_allocator()->NewRegister();
22041cb0ef41Sopenharmony_ci  builder()->MoveRegister(Register::current_context(), context);
22051cb0ef41Sopenharmony_ci
22061cb0ef41Sopenharmony_ci  // Evaluate the try-block inside a control scope. This simulates a handler
22071cb0ef41Sopenharmony_ci  // that is intercepting all control commands.
22081cb0ef41Sopenharmony_ci  try_control_builder.BeginTry(context);
22091cb0ef41Sopenharmony_ci  {
22101cb0ef41Sopenharmony_ci    ControlScopeForTryFinally scope(this, &try_control_builder, &commands);
22111cb0ef41Sopenharmony_ci    try_body_func();
22121cb0ef41Sopenharmony_ci  }
22131cb0ef41Sopenharmony_ci  try_control_builder.EndTry();
22141cb0ef41Sopenharmony_ci
22151cb0ef41Sopenharmony_ci  // Record fall-through and exception cases.
22161cb0ef41Sopenharmony_ci  commands.RecordFallThroughPath();
22171cb0ef41Sopenharmony_ci  try_control_builder.LeaveTry();
22181cb0ef41Sopenharmony_ci  try_control_builder.BeginHandler();
22191cb0ef41Sopenharmony_ci  commands.RecordHandlerReThrowPath();
22201cb0ef41Sopenharmony_ci
22211cb0ef41Sopenharmony_ci  // Pending message object is saved on entry.
22221cb0ef41Sopenharmony_ci  try_control_builder.BeginFinally();
22231cb0ef41Sopenharmony_ci  Register message = context;  // Reuse register.
22241cb0ef41Sopenharmony_ci
22251cb0ef41Sopenharmony_ci  // Clear message object as we enter the finally block.
22261cb0ef41Sopenharmony_ci  builder()->LoadTheHole().SetPendingMessage().StoreAccumulatorInRegister(
22271cb0ef41Sopenharmony_ci      message);
22281cb0ef41Sopenharmony_ci
22291cb0ef41Sopenharmony_ci  // Evaluate the finally-block.
22301cb0ef41Sopenharmony_ci  finally_body_func(token);
22311cb0ef41Sopenharmony_ci  try_control_builder.EndFinally();
22321cb0ef41Sopenharmony_ci
22331cb0ef41Sopenharmony_ci  // Pending message object is restored on exit.
22341cb0ef41Sopenharmony_ci  builder()->LoadAccumulatorWithRegister(message).SetPendingMessage();
22351cb0ef41Sopenharmony_ci
22361cb0ef41Sopenharmony_ci  // Dynamic dispatch after the finally-block.
22371cb0ef41Sopenharmony_ci  commands.ApplyDeferredCommands();
22381cb0ef41Sopenharmony_ci}
22391cb0ef41Sopenharmony_ci
22401cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
22411cb0ef41Sopenharmony_ci                                           LoopBuilder* loop_builder) {
22421cb0ef41Sopenharmony_ci  loop_builder->LoopBody();
22431cb0ef41Sopenharmony_ci  ControlScopeForIteration execution_control(this, stmt, loop_builder);
22441cb0ef41Sopenharmony_ci  Visit(stmt->body());
22451cb0ef41Sopenharmony_ci  loop_builder->BindContinueTarget();
22461cb0ef41Sopenharmony_ci}
22471cb0ef41Sopenharmony_ci
22481cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
22491cb0ef41Sopenharmony_ci  LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
22501cb0ef41Sopenharmony_ci  if (stmt->cond()->ToBooleanIsFalse()) {
22511cb0ef41Sopenharmony_ci    // Since we know that the condition is false, we don't create a loop.
22521cb0ef41Sopenharmony_ci    // Therefore, we don't create a LoopScope (and thus we don't create a header
22531cb0ef41Sopenharmony_ci    // and a JumpToHeader). However, we still need to iterate once through the
22541cb0ef41Sopenharmony_ci    // body.
22551cb0ef41Sopenharmony_ci    VisitIterationBody(stmt, &loop_builder);
22561cb0ef41Sopenharmony_ci  } else if (stmt->cond()->ToBooleanIsTrue()) {
22571cb0ef41Sopenharmony_ci    LoopScope loop_scope(this, &loop_builder);
22581cb0ef41Sopenharmony_ci    VisitIterationBody(stmt, &loop_builder);
22591cb0ef41Sopenharmony_ci  } else {
22601cb0ef41Sopenharmony_ci    LoopScope loop_scope(this, &loop_builder);
22611cb0ef41Sopenharmony_ci    VisitIterationBody(stmt, &loop_builder);
22621cb0ef41Sopenharmony_ci    builder()->SetExpressionAsStatementPosition(stmt->cond());
22631cb0ef41Sopenharmony_ci    BytecodeLabels loop_backbranch(zone());
22641cb0ef41Sopenharmony_ci    VisitForTest(stmt->cond(), &loop_backbranch, loop_builder.break_labels(),
22651cb0ef41Sopenharmony_ci                 TestFallthrough::kThen);
22661cb0ef41Sopenharmony_ci    loop_backbranch.Bind(builder());
22671cb0ef41Sopenharmony_ci  }
22681cb0ef41Sopenharmony_ci}
22691cb0ef41Sopenharmony_ci
22701cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
22711cb0ef41Sopenharmony_ci  LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
22721cb0ef41Sopenharmony_ci
22731cb0ef41Sopenharmony_ci  if (stmt->cond()->ToBooleanIsFalse()) {
22741cb0ef41Sopenharmony_ci    // If the condition is false there is no need to generate the loop.
22751cb0ef41Sopenharmony_ci    return;
22761cb0ef41Sopenharmony_ci  }
22771cb0ef41Sopenharmony_ci
22781cb0ef41Sopenharmony_ci  LoopScope loop_scope(this, &loop_builder);
22791cb0ef41Sopenharmony_ci  if (!stmt->cond()->ToBooleanIsTrue()) {
22801cb0ef41Sopenharmony_ci    builder()->SetExpressionAsStatementPosition(stmt->cond());
22811cb0ef41Sopenharmony_ci    BytecodeLabels loop_body(zone());
22821cb0ef41Sopenharmony_ci    VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(),
22831cb0ef41Sopenharmony_ci                 TestFallthrough::kThen);
22841cb0ef41Sopenharmony_ci    loop_body.Bind(builder());
22851cb0ef41Sopenharmony_ci  }
22861cb0ef41Sopenharmony_ci  VisitIterationBody(stmt, &loop_builder);
22871cb0ef41Sopenharmony_ci}
22881cb0ef41Sopenharmony_ci
22891cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
22901cb0ef41Sopenharmony_ci  if (stmt->init() != nullptr) {
22911cb0ef41Sopenharmony_ci    Visit(stmt->init());
22921cb0ef41Sopenharmony_ci  }
22931cb0ef41Sopenharmony_ci
22941cb0ef41Sopenharmony_ci  LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
22951cb0ef41Sopenharmony_ci  if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
22961cb0ef41Sopenharmony_ci    // If the condition is known to be false there is no need to generate
22971cb0ef41Sopenharmony_ci    // body, next or condition blocks. Init block should be generated.
22981cb0ef41Sopenharmony_ci    return;
22991cb0ef41Sopenharmony_ci  }
23001cb0ef41Sopenharmony_ci
23011cb0ef41Sopenharmony_ci  LoopScope loop_scope(this, &loop_builder);
23021cb0ef41Sopenharmony_ci  if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
23031cb0ef41Sopenharmony_ci    builder()->SetExpressionAsStatementPosition(stmt->cond());
23041cb0ef41Sopenharmony_ci    BytecodeLabels loop_body(zone());
23051cb0ef41Sopenharmony_ci    VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(),
23061cb0ef41Sopenharmony_ci                 TestFallthrough::kThen);
23071cb0ef41Sopenharmony_ci    loop_body.Bind(builder());
23081cb0ef41Sopenharmony_ci  }
23091cb0ef41Sopenharmony_ci  VisitIterationBody(stmt, &loop_builder);
23101cb0ef41Sopenharmony_ci  if (stmt->next() != nullptr) {
23111cb0ef41Sopenharmony_ci    builder()->SetStatementPosition(stmt->next());
23121cb0ef41Sopenharmony_ci    Visit(stmt->next());
23131cb0ef41Sopenharmony_ci  }
23141cb0ef41Sopenharmony_ci}
23151cb0ef41Sopenharmony_ci
23161cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
23171cb0ef41Sopenharmony_ci  if (stmt->subject()->IsNullLiteral() ||
23181cb0ef41Sopenharmony_ci      stmt->subject()->IsUndefinedLiteral()) {
23191cb0ef41Sopenharmony_ci    // ForIn generates lots of code, skip if it wouldn't produce any effects.
23201cb0ef41Sopenharmony_ci    return;
23211cb0ef41Sopenharmony_ci  }
23221cb0ef41Sopenharmony_ci
23231cb0ef41Sopenharmony_ci  BytecodeLabel subject_undefined_label;
23241cb0ef41Sopenharmony_ci  FeedbackSlot slot = feedback_spec()->AddForInSlot();
23251cb0ef41Sopenharmony_ci
23261cb0ef41Sopenharmony_ci  // Prepare the state for executing ForIn.
23271cb0ef41Sopenharmony_ci  builder()->SetExpressionAsStatementPosition(stmt->subject());
23281cb0ef41Sopenharmony_ci  VisitForAccumulatorValue(stmt->subject());
23291cb0ef41Sopenharmony_ci  builder()->JumpIfUndefinedOrNull(&subject_undefined_label);
23301cb0ef41Sopenharmony_ci  Register receiver = register_allocator()->NewRegister();
23311cb0ef41Sopenharmony_ci  builder()->ToObject(receiver);
23321cb0ef41Sopenharmony_ci
23331cb0ef41Sopenharmony_ci  // Used as kRegTriple and kRegPair in ForInPrepare and ForInNext.
23341cb0ef41Sopenharmony_ci  RegisterList triple = register_allocator()->NewRegisterList(3);
23351cb0ef41Sopenharmony_ci  Register cache_length = triple[2];
23361cb0ef41Sopenharmony_ci  builder()->ForInEnumerate(receiver);
23371cb0ef41Sopenharmony_ci  builder()->ForInPrepare(triple, feedback_index(slot));
23381cb0ef41Sopenharmony_ci
23391cb0ef41Sopenharmony_ci  // Set up loop counter
23401cb0ef41Sopenharmony_ci  Register index = register_allocator()->NewRegister();
23411cb0ef41Sopenharmony_ci  builder()->LoadLiteral(Smi::zero());
23421cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(index);
23431cb0ef41Sopenharmony_ci
23441cb0ef41Sopenharmony_ci  // The loop
23451cb0ef41Sopenharmony_ci  {
23461cb0ef41Sopenharmony_ci    LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
23471cb0ef41Sopenharmony_ci    LoopScope loop_scope(this, &loop_builder);
23481cb0ef41Sopenharmony_ci    builder()->SetExpressionAsStatementPosition(stmt->each());
23491cb0ef41Sopenharmony_ci    builder()->ForInContinue(index, cache_length);
23501cb0ef41Sopenharmony_ci    loop_builder.BreakIfFalse(ToBooleanMode::kAlreadyBoolean);
23511cb0ef41Sopenharmony_ci    builder()->ForInNext(receiver, index, triple.Truncate(2),
23521cb0ef41Sopenharmony_ci                         feedback_index(slot));
23531cb0ef41Sopenharmony_ci    loop_builder.ContinueIfUndefined();
23541cb0ef41Sopenharmony_ci
23551cb0ef41Sopenharmony_ci    // Assign accumulator value to the 'each' target.
23561cb0ef41Sopenharmony_ci    {
23571cb0ef41Sopenharmony_ci      EffectResultScope scope(this);
23581cb0ef41Sopenharmony_ci      // Make sure to preserve the accumulator across the PrepareAssignmentLhs
23591cb0ef41Sopenharmony_ci      // call.
23601cb0ef41Sopenharmony_ci      AssignmentLhsData lhs_data = PrepareAssignmentLhs(
23611cb0ef41Sopenharmony_ci          stmt->each(), AccumulatorPreservingMode::kPreserve);
23621cb0ef41Sopenharmony_ci      builder()->SetExpressionPosition(stmt->each());
23631cb0ef41Sopenharmony_ci      BuildAssignment(lhs_data, Token::ASSIGN, LookupHoistingMode::kNormal);
23641cb0ef41Sopenharmony_ci    }
23651cb0ef41Sopenharmony_ci
23661cb0ef41Sopenharmony_ci    VisitIterationBody(stmt, &loop_builder);
23671cb0ef41Sopenharmony_ci    builder()->ForInStep(index);
23681cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(index);
23691cb0ef41Sopenharmony_ci  }
23701cb0ef41Sopenharmony_ci  builder()->Bind(&subject_undefined_label);
23711cb0ef41Sopenharmony_ci}
23721cb0ef41Sopenharmony_ci
23731cb0ef41Sopenharmony_ci// Desugar a for-of statement into an application of the iteration protocol.
23741cb0ef41Sopenharmony_ci//
23751cb0ef41Sopenharmony_ci// for (EACH of SUBJECT) BODY
23761cb0ef41Sopenharmony_ci//
23771cb0ef41Sopenharmony_ci//   becomes
23781cb0ef41Sopenharmony_ci//
23791cb0ef41Sopenharmony_ci// iterator = %GetIterator(SUBJECT)
23801cb0ef41Sopenharmony_ci// try {
23811cb0ef41Sopenharmony_ci//
23821cb0ef41Sopenharmony_ci//   loop {
23831cb0ef41Sopenharmony_ci//     // Make sure we are considered 'done' if .next(), .done or .value fail.
23841cb0ef41Sopenharmony_ci//     done = true
23851cb0ef41Sopenharmony_ci//     value = iterator.next()
23861cb0ef41Sopenharmony_ci//     if (value.done) break;
23871cb0ef41Sopenharmony_ci//     value = value.value
23881cb0ef41Sopenharmony_ci//     done = false
23891cb0ef41Sopenharmony_ci//
23901cb0ef41Sopenharmony_ci//     EACH = value
23911cb0ef41Sopenharmony_ci//     BODY
23921cb0ef41Sopenharmony_ci//   }
23931cb0ef41Sopenharmony_ci//   done = true
23941cb0ef41Sopenharmony_ci//
23951cb0ef41Sopenharmony_ci// } catch(e) {
23961cb0ef41Sopenharmony_ci//   iteration_continuation = RETHROW
23971cb0ef41Sopenharmony_ci// } finally {
23981cb0ef41Sopenharmony_ci//   %FinalizeIteration(iterator, done, iteration_continuation)
23991cb0ef41Sopenharmony_ci// }
24001cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
24011cb0ef41Sopenharmony_ci  EffectResultScope effect_scope(this);
24021cb0ef41Sopenharmony_ci
24031cb0ef41Sopenharmony_ci  builder()->SetExpressionAsStatementPosition(stmt->subject());
24041cb0ef41Sopenharmony_ci  VisitForAccumulatorValue(stmt->subject());
24051cb0ef41Sopenharmony_ci
24061cb0ef41Sopenharmony_ci  // Store the iterator in a dedicated register so that it can be closed on
24071cb0ef41Sopenharmony_ci  // exit, and the 'done' value in a dedicated register so that it can be
24081cb0ef41Sopenharmony_ci  // changed and accessed independently of the iteration result.
24091cb0ef41Sopenharmony_ci  IteratorRecord iterator = BuildGetIteratorRecord(stmt->type());
24101cb0ef41Sopenharmony_ci  Register done = register_allocator()->NewRegister();
24111cb0ef41Sopenharmony_ci  builder()->LoadFalse();
24121cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(done);
24131cb0ef41Sopenharmony_ci
24141cb0ef41Sopenharmony_ci  BuildTryFinally(
24151cb0ef41Sopenharmony_ci      // Try block.
24161cb0ef41Sopenharmony_ci      [&]() {
24171cb0ef41Sopenharmony_ci        Register next_result = register_allocator()->NewRegister();
24181cb0ef41Sopenharmony_ci
24191cb0ef41Sopenharmony_ci        LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
24201cb0ef41Sopenharmony_ci        LoopScope loop_scope(this, &loop_builder);
24211cb0ef41Sopenharmony_ci
24221cb0ef41Sopenharmony_ci        builder()->LoadTrue().StoreAccumulatorInRegister(done);
24231cb0ef41Sopenharmony_ci
24241cb0ef41Sopenharmony_ci        // Call the iterator's .next() method. Break from the loop if the `done`
24251cb0ef41Sopenharmony_ci        // property is truthy, otherwise load the value from the iterator result
24261cb0ef41Sopenharmony_ci        // and append the argument.
24271cb0ef41Sopenharmony_ci        builder()->SetExpressionAsStatementPosition(stmt->each());
24281cb0ef41Sopenharmony_ci        BuildIteratorNext(iterator, next_result);
24291cb0ef41Sopenharmony_ci        builder()->LoadNamedProperty(
24301cb0ef41Sopenharmony_ci            next_result, ast_string_constants()->done_string(),
24311cb0ef41Sopenharmony_ci            feedback_index(feedback_spec()->AddLoadICSlot()));
24321cb0ef41Sopenharmony_ci        loop_builder.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
24331cb0ef41Sopenharmony_ci
24341cb0ef41Sopenharmony_ci        builder()
24351cb0ef41Sopenharmony_ci            // value = value.value
24361cb0ef41Sopenharmony_ci            ->LoadNamedProperty(
24371cb0ef41Sopenharmony_ci                next_result, ast_string_constants()->value_string(),
24381cb0ef41Sopenharmony_ci                feedback_index(feedback_spec()->AddLoadICSlot()));
24391cb0ef41Sopenharmony_ci        // done = false, before the assignment to each happens, so that done is
24401cb0ef41Sopenharmony_ci        // false if the assignment throws.
24411cb0ef41Sopenharmony_ci        builder()
24421cb0ef41Sopenharmony_ci            ->StoreAccumulatorInRegister(next_result)
24431cb0ef41Sopenharmony_ci            .LoadFalse()
24441cb0ef41Sopenharmony_ci            .StoreAccumulatorInRegister(done);
24451cb0ef41Sopenharmony_ci
24461cb0ef41Sopenharmony_ci        // Assign to the 'each' target.
24471cb0ef41Sopenharmony_ci        AssignmentLhsData lhs_data = PrepareAssignmentLhs(stmt->each());
24481cb0ef41Sopenharmony_ci        builder()->LoadAccumulatorWithRegister(next_result);
24491cb0ef41Sopenharmony_ci        BuildAssignment(lhs_data, Token::ASSIGN, LookupHoistingMode::kNormal);
24501cb0ef41Sopenharmony_ci
24511cb0ef41Sopenharmony_ci        VisitIterationBody(stmt, &loop_builder);
24521cb0ef41Sopenharmony_ci      },
24531cb0ef41Sopenharmony_ci      // Finally block.
24541cb0ef41Sopenharmony_ci      [&](Register iteration_continuation_token) {
24551cb0ef41Sopenharmony_ci        // Finish the iteration in the finally block.
24561cb0ef41Sopenharmony_ci        BuildFinalizeIteration(iterator, done, iteration_continuation_token);
24571cb0ef41Sopenharmony_ci      },
24581cb0ef41Sopenharmony_ci      HandlerTable::UNCAUGHT);
24591cb0ef41Sopenharmony_ci}
24601cb0ef41Sopenharmony_ci
24611cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
24621cb0ef41Sopenharmony_ci  // Update catch prediction tracking. The updated catch_prediction value lasts
24631cb0ef41Sopenharmony_ci  // until the end of the try_block in the AST node, and does not apply to the
24641cb0ef41Sopenharmony_ci  // catch_block.
24651cb0ef41Sopenharmony_ci  HandlerTable::CatchPrediction outer_catch_prediction = catch_prediction();
24661cb0ef41Sopenharmony_ci  set_catch_prediction(stmt->GetCatchPrediction(outer_catch_prediction));
24671cb0ef41Sopenharmony_ci
24681cb0ef41Sopenharmony_ci  BuildTryCatch(
24691cb0ef41Sopenharmony_ci      // Try body.
24701cb0ef41Sopenharmony_ci      [&]() {
24711cb0ef41Sopenharmony_ci        Visit(stmt->try_block());
24721cb0ef41Sopenharmony_ci        set_catch_prediction(outer_catch_prediction);
24731cb0ef41Sopenharmony_ci      },
24741cb0ef41Sopenharmony_ci      // Catch body.
24751cb0ef41Sopenharmony_ci      [&](Register context) {
24761cb0ef41Sopenharmony_ci        if (stmt->scope()) {
24771cb0ef41Sopenharmony_ci          // Create a catch scope that binds the exception.
24781cb0ef41Sopenharmony_ci          BuildNewLocalCatchContext(stmt->scope());
24791cb0ef41Sopenharmony_ci          builder()->StoreAccumulatorInRegister(context);
24801cb0ef41Sopenharmony_ci        }
24811cb0ef41Sopenharmony_ci
24821cb0ef41Sopenharmony_ci        // If requested, clear message object as we enter the catch block.
24831cb0ef41Sopenharmony_ci        if (stmt->ShouldClearPendingException(outer_catch_prediction)) {
24841cb0ef41Sopenharmony_ci          builder()->LoadTheHole().SetPendingMessage();
24851cb0ef41Sopenharmony_ci        }
24861cb0ef41Sopenharmony_ci
24871cb0ef41Sopenharmony_ci        // Load the catch context into the accumulator.
24881cb0ef41Sopenharmony_ci        builder()->LoadAccumulatorWithRegister(context);
24891cb0ef41Sopenharmony_ci
24901cb0ef41Sopenharmony_ci        // Evaluate the catch-block.
24911cb0ef41Sopenharmony_ci        if (stmt->scope()) {
24921cb0ef41Sopenharmony_ci          VisitInScope(stmt->catch_block(), stmt->scope());
24931cb0ef41Sopenharmony_ci        } else {
24941cb0ef41Sopenharmony_ci          VisitBlock(stmt->catch_block());
24951cb0ef41Sopenharmony_ci        }
24961cb0ef41Sopenharmony_ci      },
24971cb0ef41Sopenharmony_ci      catch_prediction(), stmt);
24981cb0ef41Sopenharmony_ci}
24991cb0ef41Sopenharmony_ci
25001cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
25011cb0ef41Sopenharmony_ci  BuildTryFinally(
25021cb0ef41Sopenharmony_ci      // Try block.
25031cb0ef41Sopenharmony_ci      [&]() { Visit(stmt->try_block()); },
25041cb0ef41Sopenharmony_ci      // Finally block.
25051cb0ef41Sopenharmony_ci      [&](Register body_continuation_token) { Visit(stmt->finally_block()); },
25061cb0ef41Sopenharmony_ci      catch_prediction(), stmt);
25071cb0ef41Sopenharmony_ci}
25081cb0ef41Sopenharmony_ci
25091cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
25101cb0ef41Sopenharmony_ci  builder()->SetStatementPosition(stmt);
25111cb0ef41Sopenharmony_ci  builder()->Debugger();
25121cb0ef41Sopenharmony_ci}
25131cb0ef41Sopenharmony_ci
25141cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
25151cb0ef41Sopenharmony_ci  DCHECK_EQ(expr->scope()->outer_scope(), current_scope());
25161cb0ef41Sopenharmony_ci  uint8_t flags = CreateClosureFlags::Encode(
25171cb0ef41Sopenharmony_ci      expr->pretenure(), closure_scope()->is_function_scope(),
25181cb0ef41Sopenharmony_ci      info()->flags().might_always_opt());
25191cb0ef41Sopenharmony_ci  size_t entry = builder()->AllocateDeferredConstantPoolEntry();
25201cb0ef41Sopenharmony_ci  builder()->CreateClosure(entry, GetCachedCreateClosureSlot(expr), flags);
25211cb0ef41Sopenharmony_ci  function_literals_.push_back(std::make_pair(expr, entry));
25221cb0ef41Sopenharmony_ci  AddToEagerLiteralsIfEager(expr);
25231cb0ef41Sopenharmony_ci}
25241cb0ef41Sopenharmony_ci
25251cb0ef41Sopenharmony_civoid BytecodeGenerator::AddToEagerLiteralsIfEager(FunctionLiteral* literal) {
25261cb0ef41Sopenharmony_ci  // Only parallel compile when there's a script (not the case for source
25271cb0ef41Sopenharmony_ci  // position collection).
25281cb0ef41Sopenharmony_ci  if (!script_.is_null() && literal->should_parallel_compile()) {
25291cb0ef41Sopenharmony_ci    // If we should normally be eagerly compiling this function, we must be here
25301cb0ef41Sopenharmony_ci    // because of post_parallel_compile_tasks_for_eager_toplevel.
25311cb0ef41Sopenharmony_ci    DCHECK_IMPLIES(
25321cb0ef41Sopenharmony_ci        literal->ShouldEagerCompile(),
25331cb0ef41Sopenharmony_ci        info()->flags().post_parallel_compile_tasks_for_eager_toplevel());
25341cb0ef41Sopenharmony_ci    // There exists a lazy compile dispatcher.
25351cb0ef41Sopenharmony_ci    DCHECK(info()->dispatcher());
25361cb0ef41Sopenharmony_ci    // There exists a cloneable character stream.
25371cb0ef41Sopenharmony_ci    DCHECK(info()->character_stream()->can_be_cloned_for_parallel_access());
25381cb0ef41Sopenharmony_ci
25391cb0ef41Sopenharmony_ci    UnparkedScope scope(local_isolate_);
25401cb0ef41Sopenharmony_ci    // If there doesn't already exist a SharedFunctionInfo for this function,
25411cb0ef41Sopenharmony_ci    // then create one and enqueue it. Otherwise, we're reparsing (e.g. for the
25421cb0ef41Sopenharmony_ci    // debugger, source position collection, call printing, recompile after
25431cb0ef41Sopenharmony_ci    // flushing, etc.) and don't want to over-compile.
25441cb0ef41Sopenharmony_ci    Handle<SharedFunctionInfo> shared_info;
25451cb0ef41Sopenharmony_ci    if (!Script::FindSharedFunctionInfo(script_, local_isolate_, literal)
25461cb0ef41Sopenharmony_ci             .ToHandle(&shared_info)) {
25471cb0ef41Sopenharmony_ci      shared_info =
25481cb0ef41Sopenharmony_ci          Compiler::GetSharedFunctionInfo(literal, script_, local_isolate_);
25491cb0ef41Sopenharmony_ci      info()->dispatcher()->Enqueue(local_isolate_, shared_info,
25501cb0ef41Sopenharmony_ci                                    info()->character_stream()->Clone());
25511cb0ef41Sopenharmony_ci    }
25521cb0ef41Sopenharmony_ci  } else if (eager_inner_literals_ && literal->ShouldEagerCompile()) {
25531cb0ef41Sopenharmony_ci    DCHECK(!IsInEagerLiterals(literal, *eager_inner_literals_));
25541cb0ef41Sopenharmony_ci    DCHECK(!literal->should_parallel_compile());
25551cb0ef41Sopenharmony_ci    eager_inner_literals_->push_back(literal);
25561cb0ef41Sopenharmony_ci  }
25571cb0ef41Sopenharmony_ci}
25581cb0ef41Sopenharmony_ci
25591cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
25601cb0ef41Sopenharmony_ci  size_t class_boilerplate_entry =
25611cb0ef41Sopenharmony_ci      builder()->AllocateDeferredConstantPoolEntry();
25621cb0ef41Sopenharmony_ci  class_literals_.push_back(std::make_pair(expr, class_boilerplate_entry));
25631cb0ef41Sopenharmony_ci
25641cb0ef41Sopenharmony_ci  VisitDeclarations(expr->scope()->declarations());
25651cb0ef41Sopenharmony_ci  Register class_constructor = register_allocator()->NewRegister();
25661cb0ef41Sopenharmony_ci
25671cb0ef41Sopenharmony_ci  // Create the class brand symbol and store it on the context during class
25681cb0ef41Sopenharmony_ci  // evaluation. This will be stored in the instance later in the constructor.
25691cb0ef41Sopenharmony_ci  // We do this early so that invalid access to private methods or accessors
25701cb0ef41Sopenharmony_ci  // in computed property keys throw.
25711cb0ef41Sopenharmony_ci  if (expr->scope()->brand() != nullptr) {
25721cb0ef41Sopenharmony_ci    Register brand = register_allocator()->NewRegister();
25731cb0ef41Sopenharmony_ci    const AstRawString* class_name =
25741cb0ef41Sopenharmony_ci        expr->scope()->class_variable() != nullptr
25751cb0ef41Sopenharmony_ci            ? expr->scope()->class_variable()->raw_name()
25761cb0ef41Sopenharmony_ci            : ast_string_constants()->anonymous_string();
25771cb0ef41Sopenharmony_ci    builder()
25781cb0ef41Sopenharmony_ci        ->LoadLiteral(class_name)
25791cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(brand)
25801cb0ef41Sopenharmony_ci        .CallRuntime(Runtime::kCreatePrivateBrandSymbol, brand);
25811cb0ef41Sopenharmony_ci    BuildVariableAssignment(expr->scope()->brand(), Token::INIT,
25821cb0ef41Sopenharmony_ci                            HoleCheckMode::kElided);
25831cb0ef41Sopenharmony_ci  }
25841cb0ef41Sopenharmony_ci
25851cb0ef41Sopenharmony_ci  AccessorTable<ClassLiteral::Property> private_accessors(zone());
25861cb0ef41Sopenharmony_ci  for (int i = 0; i < expr->private_members()->length(); i++) {
25871cb0ef41Sopenharmony_ci    ClassLiteral::Property* property = expr->private_members()->at(i);
25881cb0ef41Sopenharmony_ci    DCHECK(property->is_private());
25891cb0ef41Sopenharmony_ci    switch (property->kind()) {
25901cb0ef41Sopenharmony_ci      case ClassLiteral::Property::FIELD: {
25911cb0ef41Sopenharmony_ci        // Initialize the private field variables early.
25921cb0ef41Sopenharmony_ci        // Create the private name symbols for fields during class
25931cb0ef41Sopenharmony_ci        // evaluation and store them on the context. These will be
25941cb0ef41Sopenharmony_ci        // used as keys later during instance or static initialization.
25951cb0ef41Sopenharmony_ci        RegisterAllocationScope private_name_register_scope(this);
25961cb0ef41Sopenharmony_ci        Register private_name = register_allocator()->NewRegister();
25971cb0ef41Sopenharmony_ci        VisitForRegisterValue(property->key(), private_name);
25981cb0ef41Sopenharmony_ci        builder()
25991cb0ef41Sopenharmony_ci            ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
26001cb0ef41Sopenharmony_ci            .StoreAccumulatorInRegister(private_name)
26011cb0ef41Sopenharmony_ci            .CallRuntime(Runtime::kCreatePrivateNameSymbol, private_name);
26021cb0ef41Sopenharmony_ci        DCHECK_NOT_NULL(property->private_name_var());
26031cb0ef41Sopenharmony_ci        BuildVariableAssignment(property->private_name_var(), Token::INIT,
26041cb0ef41Sopenharmony_ci                                HoleCheckMode::kElided);
26051cb0ef41Sopenharmony_ci        break;
26061cb0ef41Sopenharmony_ci      }
26071cb0ef41Sopenharmony_ci      case ClassLiteral::Property::METHOD: {
26081cb0ef41Sopenharmony_ci        RegisterAllocationScope register_scope(this);
26091cb0ef41Sopenharmony_ci        VisitForAccumulatorValue(property->value());
26101cb0ef41Sopenharmony_ci        BuildVariableAssignment(property->private_name_var(), Token::INIT,
26111cb0ef41Sopenharmony_ci                                HoleCheckMode::kElided);
26121cb0ef41Sopenharmony_ci        break;
26131cb0ef41Sopenharmony_ci      }
26141cb0ef41Sopenharmony_ci      // Collect private accessors into a table to merge the creation of
26151cb0ef41Sopenharmony_ci      // those closures later.
26161cb0ef41Sopenharmony_ci      case ClassLiteral::Property::GETTER: {
26171cb0ef41Sopenharmony_ci        Literal* key = property->key()->AsLiteral();
26181cb0ef41Sopenharmony_ci        DCHECK_NULL(private_accessors.LookupOrInsert(key)->getter);
26191cb0ef41Sopenharmony_ci        private_accessors.LookupOrInsert(key)->getter = property;
26201cb0ef41Sopenharmony_ci        break;
26211cb0ef41Sopenharmony_ci      }
26221cb0ef41Sopenharmony_ci      case ClassLiteral::Property::SETTER: {
26231cb0ef41Sopenharmony_ci        Literal* key = property->key()->AsLiteral();
26241cb0ef41Sopenharmony_ci        DCHECK_NULL(private_accessors.LookupOrInsert(key)->setter);
26251cb0ef41Sopenharmony_ci        private_accessors.LookupOrInsert(key)->setter = property;
26261cb0ef41Sopenharmony_ci        break;
26271cb0ef41Sopenharmony_ci      }
26281cb0ef41Sopenharmony_ci      default:
26291cb0ef41Sopenharmony_ci        UNREACHABLE();
26301cb0ef41Sopenharmony_ci    }
26311cb0ef41Sopenharmony_ci  }
26321cb0ef41Sopenharmony_ci
26331cb0ef41Sopenharmony_ci  {
26341cb0ef41Sopenharmony_ci    RegisterAllocationScope register_scope(this);
26351cb0ef41Sopenharmony_ci    RegisterList args = register_allocator()->NewGrowableRegisterList();
26361cb0ef41Sopenharmony_ci
26371cb0ef41Sopenharmony_ci    Register class_boilerplate = register_allocator()->GrowRegisterList(&args);
26381cb0ef41Sopenharmony_ci    Register class_constructor_in_args =
26391cb0ef41Sopenharmony_ci        register_allocator()->GrowRegisterList(&args);
26401cb0ef41Sopenharmony_ci    Register super_class = register_allocator()->GrowRegisterList(&args);
26411cb0ef41Sopenharmony_ci    DCHECK_EQ(ClassBoilerplate::kFirstDynamicArgumentIndex,
26421cb0ef41Sopenharmony_ci              args.register_count());
26431cb0ef41Sopenharmony_ci
26441cb0ef41Sopenharmony_ci    VisitForAccumulatorValueOrTheHole(expr->extends());
26451cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(super_class);
26461cb0ef41Sopenharmony_ci
26471cb0ef41Sopenharmony_ci    VisitFunctionLiteral(expr->constructor());
26481cb0ef41Sopenharmony_ci    builder()
26491cb0ef41Sopenharmony_ci        ->StoreAccumulatorInRegister(class_constructor)
26501cb0ef41Sopenharmony_ci        .MoveRegister(class_constructor, class_constructor_in_args)
26511cb0ef41Sopenharmony_ci        .LoadConstantPoolEntry(class_boilerplate_entry)
26521cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(class_boilerplate);
26531cb0ef41Sopenharmony_ci
26541cb0ef41Sopenharmony_ci    // Create computed names and method values nodes to store into the literal.
26551cb0ef41Sopenharmony_ci    for (int i = 0; i < expr->public_members()->length(); i++) {
26561cb0ef41Sopenharmony_ci      ClassLiteral::Property* property = expr->public_members()->at(i);
26571cb0ef41Sopenharmony_ci      if (property->is_computed_name()) {
26581cb0ef41Sopenharmony_ci        Register key = register_allocator()->GrowRegisterList(&args);
26591cb0ef41Sopenharmony_ci
26601cb0ef41Sopenharmony_ci        builder()->SetExpressionAsStatementPosition(property->key());
26611cb0ef41Sopenharmony_ci        BuildLoadPropertyKey(property, key);
26621cb0ef41Sopenharmony_ci        if (property->is_static()) {
26631cb0ef41Sopenharmony_ci          // The static prototype property is read only. We handle the non
26641cb0ef41Sopenharmony_ci          // computed property name case in the parser. Since this is the only
26651cb0ef41Sopenharmony_ci          // case where we need to check for an own read only property we
26661cb0ef41Sopenharmony_ci          // special case this so we do not need to do this for every property.
26671cb0ef41Sopenharmony_ci
26681cb0ef41Sopenharmony_ci          FeedbackSlot slot = GetDummyCompareICSlot();
26691cb0ef41Sopenharmony_ci          BytecodeLabel done;
26701cb0ef41Sopenharmony_ci          builder()
26711cb0ef41Sopenharmony_ci              ->LoadLiteral(ast_string_constants()->prototype_string())
26721cb0ef41Sopenharmony_ci              .CompareOperation(Token::Value::EQ_STRICT, key,
26731cb0ef41Sopenharmony_ci                                feedback_index(slot))
26741cb0ef41Sopenharmony_ci              .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &done)
26751cb0ef41Sopenharmony_ci              .CallRuntime(Runtime::kThrowStaticPrototypeError)
26761cb0ef41Sopenharmony_ci              .Bind(&done);
26771cb0ef41Sopenharmony_ci        }
26781cb0ef41Sopenharmony_ci
26791cb0ef41Sopenharmony_ci        if (property->kind() == ClassLiteral::Property::FIELD) {
26801cb0ef41Sopenharmony_ci          DCHECK(!property->is_private());
26811cb0ef41Sopenharmony_ci          // Initialize field's name variable with the computed name.
26821cb0ef41Sopenharmony_ci          DCHECK_NOT_NULL(property->computed_name_var());
26831cb0ef41Sopenharmony_ci          builder()->LoadAccumulatorWithRegister(key);
26841cb0ef41Sopenharmony_ci          BuildVariableAssignment(property->computed_name_var(), Token::INIT,
26851cb0ef41Sopenharmony_ci                                  HoleCheckMode::kElided);
26861cb0ef41Sopenharmony_ci        }
26871cb0ef41Sopenharmony_ci      }
26881cb0ef41Sopenharmony_ci
26891cb0ef41Sopenharmony_ci      DCHECK(!property->is_private());
26901cb0ef41Sopenharmony_ci
26911cb0ef41Sopenharmony_ci      if (property->kind() == ClassLiteral::Property::FIELD) {
26921cb0ef41Sopenharmony_ci        // We don't compute field's value here, but instead do it in the
26931cb0ef41Sopenharmony_ci        // initializer function.
26941cb0ef41Sopenharmony_ci        continue;
26951cb0ef41Sopenharmony_ci      }
26961cb0ef41Sopenharmony_ci
26971cb0ef41Sopenharmony_ci      Register value = register_allocator()->GrowRegisterList(&args);
26981cb0ef41Sopenharmony_ci      VisitForRegisterValue(property->value(), value);
26991cb0ef41Sopenharmony_ci    }
27001cb0ef41Sopenharmony_ci
27011cb0ef41Sopenharmony_ci    builder()->CallRuntime(Runtime::kDefineClass, args);
27021cb0ef41Sopenharmony_ci  }
27031cb0ef41Sopenharmony_ci  Register prototype = register_allocator()->NewRegister();
27041cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(prototype);
27051cb0ef41Sopenharmony_ci
27061cb0ef41Sopenharmony_ci  // Assign to the home object variable. Accumulator already contains the
27071cb0ef41Sopenharmony_ci  // prototype.
27081cb0ef41Sopenharmony_ci  Variable* home_object_variable = expr->home_object();
27091cb0ef41Sopenharmony_ci  if (home_object_variable != nullptr) {
27101cb0ef41Sopenharmony_ci    DCHECK(home_object_variable->is_used());
27111cb0ef41Sopenharmony_ci    DCHECK(home_object_variable->IsContextSlot());
27121cb0ef41Sopenharmony_ci    BuildVariableAssignment(home_object_variable, Token::INIT,
27131cb0ef41Sopenharmony_ci                            HoleCheckMode::kElided);
27141cb0ef41Sopenharmony_ci  }
27151cb0ef41Sopenharmony_ci  Variable* static_home_object_variable = expr->static_home_object();
27161cb0ef41Sopenharmony_ci  if (static_home_object_variable != nullptr) {
27171cb0ef41Sopenharmony_ci    DCHECK(static_home_object_variable->is_used());
27181cb0ef41Sopenharmony_ci    DCHECK(static_home_object_variable->IsContextSlot());
27191cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(class_constructor);
27201cb0ef41Sopenharmony_ci    BuildVariableAssignment(static_home_object_variable, Token::INIT,
27211cb0ef41Sopenharmony_ci                            HoleCheckMode::kElided);
27221cb0ef41Sopenharmony_ci  }
27231cb0ef41Sopenharmony_ci
27241cb0ef41Sopenharmony_ci  // Assign to class variable.
27251cb0ef41Sopenharmony_ci  Variable* class_variable = expr->scope()->class_variable();
27261cb0ef41Sopenharmony_ci  if (class_variable != nullptr && class_variable->is_used()) {
27271cb0ef41Sopenharmony_ci    DCHECK(class_variable->IsStackLocal() || class_variable->IsContextSlot());
27281cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(class_constructor);
27291cb0ef41Sopenharmony_ci    BuildVariableAssignment(class_variable, Token::INIT,
27301cb0ef41Sopenharmony_ci                            HoleCheckMode::kElided);
27311cb0ef41Sopenharmony_ci  }
27321cb0ef41Sopenharmony_ci
27331cb0ef41Sopenharmony_ci  // Define private accessors, using only a single call to the runtime for
27341cb0ef41Sopenharmony_ci  // each pair of corresponding getters and setters, in the order the first
27351cb0ef41Sopenharmony_ci  // component is declared.
27361cb0ef41Sopenharmony_ci  for (auto accessors : private_accessors.ordered_accessors()) {
27371cb0ef41Sopenharmony_ci    RegisterAllocationScope inner_register_scope(this);
27381cb0ef41Sopenharmony_ci    RegisterList accessors_reg = register_allocator()->NewRegisterList(2);
27391cb0ef41Sopenharmony_ci    ClassLiteral::Property* getter = accessors.second->getter;
27401cb0ef41Sopenharmony_ci    ClassLiteral::Property* setter = accessors.second->setter;
27411cb0ef41Sopenharmony_ci    VisitLiteralAccessor(getter, accessors_reg[0]);
27421cb0ef41Sopenharmony_ci    VisitLiteralAccessor(setter, accessors_reg[1]);
27431cb0ef41Sopenharmony_ci    builder()->CallRuntime(Runtime::kCreatePrivateAccessors, accessors_reg);
27441cb0ef41Sopenharmony_ci    Variable* var = getter != nullptr ? getter->private_name_var()
27451cb0ef41Sopenharmony_ci                                      : setter->private_name_var();
27461cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(var);
27471cb0ef41Sopenharmony_ci    BuildVariableAssignment(var, Token::INIT, HoleCheckMode::kElided);
27481cb0ef41Sopenharmony_ci  }
27491cb0ef41Sopenharmony_ci
27501cb0ef41Sopenharmony_ci  if (expr->instance_members_initializer_function() != nullptr) {
27511cb0ef41Sopenharmony_ci    Register initializer =
27521cb0ef41Sopenharmony_ci        VisitForRegisterValue(expr->instance_members_initializer_function());
27531cb0ef41Sopenharmony_ci
27541cb0ef41Sopenharmony_ci    FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
27551cb0ef41Sopenharmony_ci    builder()
27561cb0ef41Sopenharmony_ci        ->LoadAccumulatorWithRegister(initializer)
27571cb0ef41Sopenharmony_ci        .StoreClassFieldsInitializer(class_constructor, feedback_index(slot))
27581cb0ef41Sopenharmony_ci        .LoadAccumulatorWithRegister(class_constructor);
27591cb0ef41Sopenharmony_ci  }
27601cb0ef41Sopenharmony_ci
27611cb0ef41Sopenharmony_ci  if (expr->static_initializer() != nullptr) {
27621cb0ef41Sopenharmony_ci    // TODO(gsathya): This can be optimized away to be a part of the
27631cb0ef41Sopenharmony_ci    // class boilerplate in the future. The name argument can be
27641cb0ef41Sopenharmony_ci    // passed to the DefineClass runtime function and have it set
27651cb0ef41Sopenharmony_ci    // there.
27661cb0ef41Sopenharmony_ci    if (name.is_valid()) {
27671cb0ef41Sopenharmony_ci      Register key = register_allocator()->NewRegister();
27681cb0ef41Sopenharmony_ci      builder()
27691cb0ef41Sopenharmony_ci          ->LoadLiteral(ast_string_constants()->name_string())
27701cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(key);
27711cb0ef41Sopenharmony_ci
27721cb0ef41Sopenharmony_ci      DefineKeyedOwnPropertyInLiteralFlags data_property_flags =
27731cb0ef41Sopenharmony_ci          DefineKeyedOwnPropertyInLiteralFlag::kNoFlags;
27741cb0ef41Sopenharmony_ci      FeedbackSlot slot =
27751cb0ef41Sopenharmony_ci          feedback_spec()->AddDefineKeyedOwnPropertyInLiteralICSlot();
27761cb0ef41Sopenharmony_ci      builder()
27771cb0ef41Sopenharmony_ci          ->LoadAccumulatorWithRegister(name)
27781cb0ef41Sopenharmony_ci          .DefineKeyedOwnPropertyInLiteral(class_constructor, key,
27791cb0ef41Sopenharmony_ci                                           data_property_flags,
27801cb0ef41Sopenharmony_ci                                           feedback_index(slot));
27811cb0ef41Sopenharmony_ci    }
27821cb0ef41Sopenharmony_ci
27831cb0ef41Sopenharmony_ci    RegisterList args = register_allocator()->NewRegisterList(1);
27841cb0ef41Sopenharmony_ci    Register initializer = VisitForRegisterValue(expr->static_initializer());
27851cb0ef41Sopenharmony_ci
27861cb0ef41Sopenharmony_ci    builder()
27871cb0ef41Sopenharmony_ci        ->MoveRegister(class_constructor, args[0])
27881cb0ef41Sopenharmony_ci        .CallProperty(initializer, args,
27891cb0ef41Sopenharmony_ci                      feedback_index(feedback_spec()->AddCallICSlot()));
27901cb0ef41Sopenharmony_ci  }
27911cb0ef41Sopenharmony_ci  builder()->LoadAccumulatorWithRegister(class_constructor);
27921cb0ef41Sopenharmony_ci}
27931cb0ef41Sopenharmony_ci
27941cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
27951cb0ef41Sopenharmony_ci  VisitClassLiteral(expr, Register::invalid_value());
27961cb0ef41Sopenharmony_ci}
27971cb0ef41Sopenharmony_ci
27981cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr, Register name) {
27991cb0ef41Sopenharmony_ci  CurrentScope current_scope(this, expr->scope());
28001cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(expr->scope());
28011cb0ef41Sopenharmony_ci  if (expr->scope()->NeedsContext()) {
28021cb0ef41Sopenharmony_ci    // Make sure to associate the source position for the class
28031cb0ef41Sopenharmony_ci    // after the block context is created. Otherwise we have a mismatch
28041cb0ef41Sopenharmony_ci    // between the scope and the context, where we already are in a
28051cb0ef41Sopenharmony_ci    // block context for the class, but not yet in the class scope.
28061cb0ef41Sopenharmony_ci    BytecodeSourceInfo source_info = builder()->PopSourcePosition();
28071cb0ef41Sopenharmony_ci    BuildNewLocalBlockContext(expr->scope());
28081cb0ef41Sopenharmony_ci    ContextScope scope(this, expr->scope());
28091cb0ef41Sopenharmony_ci    builder()->PushSourcePosition(source_info);
28101cb0ef41Sopenharmony_ci    BuildClassLiteral(expr, name);
28111cb0ef41Sopenharmony_ci  } else {
28121cb0ef41Sopenharmony_ci    BuildClassLiteral(expr, name);
28131cb0ef41Sopenharmony_ci  }
28141cb0ef41Sopenharmony_ci}
28151cb0ef41Sopenharmony_ci
28161cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildClassProperty(ClassLiteral::Property* property) {
28171cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
28181cb0ef41Sopenharmony_ci  Register key;
28191cb0ef41Sopenharmony_ci
28201cb0ef41Sopenharmony_ci  // Private methods are not initialized in BuildClassProperty.
28211cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(property->is_private(),
28221cb0ef41Sopenharmony_ci                 property->kind() == ClassLiteral::Property::FIELD);
28231cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(property->key());
28241cb0ef41Sopenharmony_ci
28251cb0ef41Sopenharmony_ci  bool is_literal_store = property->key()->IsPropertyName() &&
28261cb0ef41Sopenharmony_ci                          !property->is_computed_name() &&
28271cb0ef41Sopenharmony_ci                          !property->is_private();
28281cb0ef41Sopenharmony_ci
28291cb0ef41Sopenharmony_ci  if (!is_literal_store) {
28301cb0ef41Sopenharmony_ci    key = register_allocator()->NewRegister();
28311cb0ef41Sopenharmony_ci    if (property->is_computed_name()) {
28321cb0ef41Sopenharmony_ci      DCHECK_EQ(property->kind(), ClassLiteral::Property::FIELD);
28331cb0ef41Sopenharmony_ci      DCHECK(!property->is_private());
28341cb0ef41Sopenharmony_ci      Variable* var = property->computed_name_var();
28351cb0ef41Sopenharmony_ci      DCHECK_NOT_NULL(var);
28361cb0ef41Sopenharmony_ci      // The computed name is already evaluated and stored in a variable at
28371cb0ef41Sopenharmony_ci      // class definition time.
28381cb0ef41Sopenharmony_ci      BuildVariableLoad(var, HoleCheckMode::kElided);
28391cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(key);
28401cb0ef41Sopenharmony_ci    } else if (property->is_private()) {
28411cb0ef41Sopenharmony_ci      Variable* private_name_var = property->private_name_var();
28421cb0ef41Sopenharmony_ci      DCHECK_NOT_NULL(private_name_var);
28431cb0ef41Sopenharmony_ci      BuildVariableLoad(private_name_var, HoleCheckMode::kElided);
28441cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(key);
28451cb0ef41Sopenharmony_ci    } else {
28461cb0ef41Sopenharmony_ci      VisitForRegisterValue(property->key(), key);
28471cb0ef41Sopenharmony_ci    }
28481cb0ef41Sopenharmony_ci  }
28491cb0ef41Sopenharmony_ci
28501cb0ef41Sopenharmony_ci  builder()->SetExpressionAsStatementPosition(property->value());
28511cb0ef41Sopenharmony_ci  VisitForAccumulatorValue(property->value());
28521cb0ef41Sopenharmony_ci
28531cb0ef41Sopenharmony_ci  if (is_literal_store) {
28541cb0ef41Sopenharmony_ci    FeedbackSlot slot = feedback_spec()->AddDefineNamedOwnICSlot();
28551cb0ef41Sopenharmony_ci    builder()->DefineNamedOwnProperty(
28561cb0ef41Sopenharmony_ci        builder()->Receiver(),
28571cb0ef41Sopenharmony_ci        property->key()->AsLiteral()->AsRawPropertyName(),
28581cb0ef41Sopenharmony_ci        feedback_index(slot));
28591cb0ef41Sopenharmony_ci  } else {
28601cb0ef41Sopenharmony_ci    FeedbackSlot slot = feedback_spec()->AddDefineKeyedOwnICSlot();
28611cb0ef41Sopenharmony_ci    builder()->DefineKeyedOwnProperty(builder()->Receiver(), key,
28621cb0ef41Sopenharmony_ci                                      feedback_index(slot));
28631cb0ef41Sopenharmony_ci  }
28641cb0ef41Sopenharmony_ci}
28651cb0ef41Sopenharmony_ci
28661cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitInitializeClassMembersStatement(
28671cb0ef41Sopenharmony_ci    InitializeClassMembersStatement* stmt) {
28681cb0ef41Sopenharmony_ci  for (int i = 0; i < stmt->fields()->length(); i++) {
28691cb0ef41Sopenharmony_ci    BuildClassProperty(stmt->fields()->at(i));
28701cb0ef41Sopenharmony_ci  }
28711cb0ef41Sopenharmony_ci}
28721cb0ef41Sopenharmony_ci
28731cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitInitializeClassStaticElementsStatement(
28741cb0ef41Sopenharmony_ci    InitializeClassStaticElementsStatement* stmt) {
28751cb0ef41Sopenharmony_ci  for (int i = 0; i < stmt->elements()->length(); i++) {
28761cb0ef41Sopenharmony_ci    ClassLiteral::StaticElement* element = stmt->elements()->at(i);
28771cb0ef41Sopenharmony_ci    switch (element->kind()) {
28781cb0ef41Sopenharmony_ci      case ClassLiteral::StaticElement::PROPERTY:
28791cb0ef41Sopenharmony_ci        BuildClassProperty(element->property());
28801cb0ef41Sopenharmony_ci        break;
28811cb0ef41Sopenharmony_ci      case ClassLiteral::StaticElement::STATIC_BLOCK:
28821cb0ef41Sopenharmony_ci        VisitBlock(element->static_block());
28831cb0ef41Sopenharmony_ci        break;
28841cb0ef41Sopenharmony_ci    }
28851cb0ef41Sopenharmony_ci  }
28861cb0ef41Sopenharmony_ci}
28871cb0ef41Sopenharmony_ci
28881cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildInvalidPropertyAccess(MessageTemplate tmpl,
28891cb0ef41Sopenharmony_ci                                                   Property* property) {
28901cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
28911cb0ef41Sopenharmony_ci  const AstRawString* name = property->key()->AsVariableProxy()->raw_name();
28921cb0ef41Sopenharmony_ci  RegisterList args = register_allocator()->NewRegisterList(2);
28931cb0ef41Sopenharmony_ci  builder()
28941cb0ef41Sopenharmony_ci      ->LoadLiteral(Smi::FromEnum(tmpl))
28951cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(args[0])
28961cb0ef41Sopenharmony_ci      .LoadLiteral(name)
28971cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(args[1])
28981cb0ef41Sopenharmony_ci      .CallRuntime(Runtime::kNewTypeError, args)
28991cb0ef41Sopenharmony_ci      .Throw();
29001cb0ef41Sopenharmony_ci}
29011cb0ef41Sopenharmony_ci
29021cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildPrivateBrandInitialization(Register receiver,
29031cb0ef41Sopenharmony_ci                                                        Variable* brand) {
29041cb0ef41Sopenharmony_ci  BuildVariableLoad(brand, HoleCheckMode::kElided);
29051cb0ef41Sopenharmony_ci  int depth = execution_context()->ContextChainDepth(brand->scope());
29061cb0ef41Sopenharmony_ci  ContextScope* class_context = execution_context()->Previous(depth);
29071cb0ef41Sopenharmony_ci  if (class_context) {
29081cb0ef41Sopenharmony_ci    Register brand_reg = register_allocator()->NewRegister();
29091cb0ef41Sopenharmony_ci    FeedbackSlot slot = feedback_spec()->AddDefineKeyedOwnICSlot();
29101cb0ef41Sopenharmony_ci    builder()
29111cb0ef41Sopenharmony_ci        ->StoreAccumulatorInRegister(brand_reg)
29121cb0ef41Sopenharmony_ci        .LoadAccumulatorWithRegister(class_context->reg())
29131cb0ef41Sopenharmony_ci        .DefineKeyedOwnProperty(receiver, brand_reg, feedback_index(slot));
29141cb0ef41Sopenharmony_ci  } else {
29151cb0ef41Sopenharmony_ci    // We are in the slow case where super() is called from a nested
29161cb0ef41Sopenharmony_ci    // arrow function or a eval(), so the class scope context isn't
29171cb0ef41Sopenharmony_ci    // tracked in a context register in the stack, and we have to
29181cb0ef41Sopenharmony_ci    // walk the context chain from the runtime to find it.
29191cb0ef41Sopenharmony_ci    DCHECK_NE(info()->literal()->scope()->outer_scope(), brand->scope());
29201cb0ef41Sopenharmony_ci    RegisterList brand_args = register_allocator()->NewRegisterList(4);
29211cb0ef41Sopenharmony_ci    builder()
29221cb0ef41Sopenharmony_ci        ->StoreAccumulatorInRegister(brand_args[1])
29231cb0ef41Sopenharmony_ci        .MoveRegister(receiver, brand_args[0])
29241cb0ef41Sopenharmony_ci        .MoveRegister(execution_context()->reg(), brand_args[2])
29251cb0ef41Sopenharmony_ci        .LoadLiteral(Smi::FromInt(depth))
29261cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(brand_args[3])
29271cb0ef41Sopenharmony_ci        .CallRuntime(Runtime::kAddPrivateBrand, brand_args);
29281cb0ef41Sopenharmony_ci  }
29291cb0ef41Sopenharmony_ci}
29301cb0ef41Sopenharmony_ci
29311cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildInstanceMemberInitialization(Register constructor,
29321cb0ef41Sopenharmony_ci                                                          Register instance) {
29331cb0ef41Sopenharmony_ci  RegisterList args = register_allocator()->NewRegisterList(1);
29341cb0ef41Sopenharmony_ci  Register initializer = register_allocator()->NewRegister();
29351cb0ef41Sopenharmony_ci
29361cb0ef41Sopenharmony_ci  FeedbackSlot slot = feedback_spec()->AddLoadICSlot();
29371cb0ef41Sopenharmony_ci  BytecodeLabel done;
29381cb0ef41Sopenharmony_ci
29391cb0ef41Sopenharmony_ci  builder()
29401cb0ef41Sopenharmony_ci      ->LoadClassFieldsInitializer(constructor, feedback_index(slot))
29411cb0ef41Sopenharmony_ci      // TODO(gsathya): This jump can be elided for the base
29421cb0ef41Sopenharmony_ci      // constructor and derived constructor. This is only required
29431cb0ef41Sopenharmony_ci      // when called from an arrow function.
29441cb0ef41Sopenharmony_ci      .JumpIfUndefined(&done)
29451cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(initializer)
29461cb0ef41Sopenharmony_ci      .MoveRegister(instance, args[0])
29471cb0ef41Sopenharmony_ci      .CallProperty(initializer, args,
29481cb0ef41Sopenharmony_ci                    feedback_index(feedback_spec()->AddCallICSlot()))
29491cb0ef41Sopenharmony_ci      .Bind(&done);
29501cb0ef41Sopenharmony_ci}
29511cb0ef41Sopenharmony_ci
29521cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitNativeFunctionLiteral(
29531cb0ef41Sopenharmony_ci    NativeFunctionLiteral* expr) {
29541cb0ef41Sopenharmony_ci  size_t entry = builder()->AllocateDeferredConstantPoolEntry();
29551cb0ef41Sopenharmony_ci  int index = feedback_spec()->AddCreateClosureSlot();
29561cb0ef41Sopenharmony_ci  uint8_t flags = CreateClosureFlags::Encode(false, false, false);
29571cb0ef41Sopenharmony_ci  builder()->CreateClosure(entry, index, flags);
29581cb0ef41Sopenharmony_ci  native_function_literals_.push_back(std::make_pair(expr, entry));
29591cb0ef41Sopenharmony_ci}
29601cb0ef41Sopenharmony_ci
29611cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitConditional(Conditional* expr) {
29621cb0ef41Sopenharmony_ci  ConditionalControlFlowBuilder conditional_builder(
29631cb0ef41Sopenharmony_ci      builder(), block_coverage_builder_, expr);
29641cb0ef41Sopenharmony_ci
29651cb0ef41Sopenharmony_ci  if (expr->condition()->ToBooleanIsTrue()) {
29661cb0ef41Sopenharmony_ci    // Generate then block unconditionally as always true.
29671cb0ef41Sopenharmony_ci    conditional_builder.Then();
29681cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->then_expression());
29691cb0ef41Sopenharmony_ci  } else if (expr->condition()->ToBooleanIsFalse()) {
29701cb0ef41Sopenharmony_ci    // Generate else block unconditionally if it exists.
29711cb0ef41Sopenharmony_ci    conditional_builder.Else();
29721cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->else_expression());
29731cb0ef41Sopenharmony_ci  } else {
29741cb0ef41Sopenharmony_ci    VisitForTest(expr->condition(), conditional_builder.then_labels(),
29751cb0ef41Sopenharmony_ci                 conditional_builder.else_labels(), TestFallthrough::kThen);
29761cb0ef41Sopenharmony_ci
29771cb0ef41Sopenharmony_ci    conditional_builder.Then();
29781cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->then_expression());
29791cb0ef41Sopenharmony_ci    conditional_builder.JumpToEnd();
29801cb0ef41Sopenharmony_ci
29811cb0ef41Sopenharmony_ci    conditional_builder.Else();
29821cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->else_expression());
29831cb0ef41Sopenharmony_ci  }
29841cb0ef41Sopenharmony_ci}
29851cb0ef41Sopenharmony_ci
29861cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitLiteral(Literal* expr) {
29871cb0ef41Sopenharmony_ci  if (execution_result()->IsEffect()) return;
29881cb0ef41Sopenharmony_ci  switch (expr->type()) {
29891cb0ef41Sopenharmony_ci    case Literal::kSmi:
29901cb0ef41Sopenharmony_ci      builder()->LoadLiteral(expr->AsSmiLiteral());
29911cb0ef41Sopenharmony_ci      break;
29921cb0ef41Sopenharmony_ci    case Literal::kHeapNumber:
29931cb0ef41Sopenharmony_ci      builder()->LoadLiteral(expr->AsNumber());
29941cb0ef41Sopenharmony_ci      break;
29951cb0ef41Sopenharmony_ci    case Literal::kUndefined:
29961cb0ef41Sopenharmony_ci      builder()->LoadUndefined();
29971cb0ef41Sopenharmony_ci      break;
29981cb0ef41Sopenharmony_ci    case Literal::kBoolean:
29991cb0ef41Sopenharmony_ci      builder()->LoadBoolean(expr->ToBooleanIsTrue());
30001cb0ef41Sopenharmony_ci      execution_result()->SetResultIsBoolean();
30011cb0ef41Sopenharmony_ci      break;
30021cb0ef41Sopenharmony_ci    case Literal::kNull:
30031cb0ef41Sopenharmony_ci      builder()->LoadNull();
30041cb0ef41Sopenharmony_ci      break;
30051cb0ef41Sopenharmony_ci    case Literal::kTheHole:
30061cb0ef41Sopenharmony_ci      builder()->LoadTheHole();
30071cb0ef41Sopenharmony_ci      break;
30081cb0ef41Sopenharmony_ci    case Literal::kString:
30091cb0ef41Sopenharmony_ci      builder()->LoadLiteral(expr->AsRawString());
30101cb0ef41Sopenharmony_ci      execution_result()->SetResultIsString();
30111cb0ef41Sopenharmony_ci      break;
30121cb0ef41Sopenharmony_ci    case Literal::kBigInt:
30131cb0ef41Sopenharmony_ci      builder()->LoadLiteral(expr->AsBigInt());
30141cb0ef41Sopenharmony_ci      break;
30151cb0ef41Sopenharmony_ci  }
30161cb0ef41Sopenharmony_ci}
30171cb0ef41Sopenharmony_ci
30181cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
30191cb0ef41Sopenharmony_ci  // Materialize a regular expression literal.
30201cb0ef41Sopenharmony_ci  builder()->CreateRegExpLiteral(
30211cb0ef41Sopenharmony_ci      expr->raw_pattern(), feedback_index(feedback_spec()->AddLiteralSlot()),
30221cb0ef41Sopenharmony_ci      expr->flags());
30231cb0ef41Sopenharmony_ci}
30241cb0ef41Sopenharmony_ci
30251cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildCreateObjectLiteral(Register literal,
30261cb0ef41Sopenharmony_ci                                                 uint8_t flags, size_t entry) {
30271cb0ef41Sopenharmony_ci  // TODO(cbruni): Directly generate runtime call for literals we cannot
30281cb0ef41Sopenharmony_ci  // optimize once the CreateShallowObjectLiteral stub is in sync with the TF
30291cb0ef41Sopenharmony_ci  // optimizations.
30301cb0ef41Sopenharmony_ci  int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
30311cb0ef41Sopenharmony_ci  builder()
30321cb0ef41Sopenharmony_ci      ->CreateObjectLiteral(entry, literal_index, flags)
30331cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(literal);
30341cb0ef41Sopenharmony_ci}
30351cb0ef41Sopenharmony_ci
30361cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
30371cb0ef41Sopenharmony_ci  expr->builder()->InitDepthAndFlags();
30381cb0ef41Sopenharmony_ci
30391cb0ef41Sopenharmony_ci  // Fast path for the empty object literal which doesn't need an
30401cb0ef41Sopenharmony_ci  // AllocationSite.
30411cb0ef41Sopenharmony_ci  if (expr->builder()->IsEmptyObjectLiteral()) {
30421cb0ef41Sopenharmony_ci    DCHECK(expr->builder()->IsFastCloningSupported());
30431cb0ef41Sopenharmony_ci    builder()->CreateEmptyObjectLiteral();
30441cb0ef41Sopenharmony_ci    return;
30451cb0ef41Sopenharmony_ci  }
30461cb0ef41Sopenharmony_ci
30471cb0ef41Sopenharmony_ci  Variable* home_object = expr->home_object();
30481cb0ef41Sopenharmony_ci  if (home_object != nullptr) {
30491cb0ef41Sopenharmony_ci    DCHECK(home_object->is_used());
30501cb0ef41Sopenharmony_ci    DCHECK(home_object->IsContextSlot());
30511cb0ef41Sopenharmony_ci  }
30521cb0ef41Sopenharmony_ci  MultipleEntryBlockContextScope object_literal_context_scope(
30531cb0ef41Sopenharmony_ci      this, home_object ? home_object->scope() : nullptr);
30541cb0ef41Sopenharmony_ci
30551cb0ef41Sopenharmony_ci  // Deep-copy the literal boilerplate.
30561cb0ef41Sopenharmony_ci  uint8_t flags = CreateObjectLiteralFlags::Encode(
30571cb0ef41Sopenharmony_ci      expr->builder()->ComputeFlags(),
30581cb0ef41Sopenharmony_ci      expr->builder()->IsFastCloningSupported());
30591cb0ef41Sopenharmony_ci
30601cb0ef41Sopenharmony_ci  Register literal = register_allocator()->NewRegister();
30611cb0ef41Sopenharmony_ci
30621cb0ef41Sopenharmony_ci  // Create literal object.
30631cb0ef41Sopenharmony_ci  int property_index = 0;
30641cb0ef41Sopenharmony_ci  bool clone_object_spread =
30651cb0ef41Sopenharmony_ci      expr->properties()->first()->kind() == ObjectLiteral::Property::SPREAD;
30661cb0ef41Sopenharmony_ci  if (clone_object_spread) {
30671cb0ef41Sopenharmony_ci    // Avoid the slow path for spreads in the following common cases:
30681cb0ef41Sopenharmony_ci    //   1) `let obj = { ...source }`
30691cb0ef41Sopenharmony_ci    //   2) `let obj = { ...source, override: 1 }`
30701cb0ef41Sopenharmony_ci    //   3) `let obj = { ...source, ...overrides }`
30711cb0ef41Sopenharmony_ci    RegisterAllocationScope register_scope(this);
30721cb0ef41Sopenharmony_ci    Expression* property = expr->properties()->first()->value();
30731cb0ef41Sopenharmony_ci    Register from_value = VisitForRegisterValue(property);
30741cb0ef41Sopenharmony_ci    int clone_index = feedback_index(feedback_spec()->AddCloneObjectSlot());
30751cb0ef41Sopenharmony_ci    builder()->CloneObject(from_value, flags, clone_index);
30761cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(literal);
30771cb0ef41Sopenharmony_ci    property_index++;
30781cb0ef41Sopenharmony_ci  } else {
30791cb0ef41Sopenharmony_ci    size_t entry;
30801cb0ef41Sopenharmony_ci    // If constant properties is an empty fixed array, use a cached empty fixed
30811cb0ef41Sopenharmony_ci    // array to ensure it's only added to the constant pool once.
30821cb0ef41Sopenharmony_ci    if (expr->builder()->properties_count() == 0) {
30831cb0ef41Sopenharmony_ci      entry = builder()->EmptyObjectBoilerplateDescriptionConstantPoolEntry();
30841cb0ef41Sopenharmony_ci    } else {
30851cb0ef41Sopenharmony_ci      entry = builder()->AllocateDeferredConstantPoolEntry();
30861cb0ef41Sopenharmony_ci      object_literals_.push_back(std::make_pair(expr->builder(), entry));
30871cb0ef41Sopenharmony_ci    }
30881cb0ef41Sopenharmony_ci    BuildCreateObjectLiteral(literal, flags, entry);
30891cb0ef41Sopenharmony_ci  }
30901cb0ef41Sopenharmony_ci
30911cb0ef41Sopenharmony_ci  // Store computed values into the literal.
30921cb0ef41Sopenharmony_ci  AccessorTable<ObjectLiteral::Property> accessor_table(zone());
30931cb0ef41Sopenharmony_ci  for (; property_index < expr->properties()->length(); property_index++) {
30941cb0ef41Sopenharmony_ci    ObjectLiteral::Property* property = expr->properties()->at(property_index);
30951cb0ef41Sopenharmony_ci    if (property->is_computed_name()) break;
30961cb0ef41Sopenharmony_ci    if (!clone_object_spread && property->IsCompileTimeValue()) continue;
30971cb0ef41Sopenharmony_ci
30981cb0ef41Sopenharmony_ci    RegisterAllocationScope inner_register_scope(this);
30991cb0ef41Sopenharmony_ci    Literal* key = property->key()->AsLiteral();
31001cb0ef41Sopenharmony_ci    switch (property->kind()) {
31011cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::SPREAD:
31021cb0ef41Sopenharmony_ci        UNREACHABLE();
31031cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::CONSTANT:
31041cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
31051cb0ef41Sopenharmony_ci        DCHECK(clone_object_spread || !property->value()->IsCompileTimeValue());
31061cb0ef41Sopenharmony_ci        V8_FALLTHROUGH;
31071cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::COMPUTED: {
31081cb0ef41Sopenharmony_ci        // It is safe to use [[Put]] here because the boilerplate already
31091cb0ef41Sopenharmony_ci        // contains computed properties with an uninitialized value.
31101cb0ef41Sopenharmony_ci        Register key_reg;
31111cb0ef41Sopenharmony_ci        if (key->IsStringLiteral()) {
31121cb0ef41Sopenharmony_ci          DCHECK(key->IsPropertyName());
31131cb0ef41Sopenharmony_ci        } else {
31141cb0ef41Sopenharmony_ci          key_reg = register_allocator()->NewRegister();
31151cb0ef41Sopenharmony_ci          builder()->SetExpressionPosition(property->key());
31161cb0ef41Sopenharmony_ci          VisitForRegisterValue(property->key(), key_reg);
31171cb0ef41Sopenharmony_ci        }
31181cb0ef41Sopenharmony_ci
31191cb0ef41Sopenharmony_ci        object_literal_context_scope.SetEnteredIf(
31201cb0ef41Sopenharmony_ci            property->value()->IsConciseMethodDefinition());
31211cb0ef41Sopenharmony_ci        builder()->SetExpressionPosition(property->value());
31221cb0ef41Sopenharmony_ci
31231cb0ef41Sopenharmony_ci        if (property->emit_store()) {
31241cb0ef41Sopenharmony_ci          VisitForAccumulatorValue(property->value());
31251cb0ef41Sopenharmony_ci          if (key->IsStringLiteral()) {
31261cb0ef41Sopenharmony_ci            FeedbackSlot slot = feedback_spec()->AddDefineNamedOwnICSlot();
31271cb0ef41Sopenharmony_ci            builder()->DefineNamedOwnProperty(literal, key->AsRawPropertyName(),
31281cb0ef41Sopenharmony_ci                                              feedback_index(slot));
31291cb0ef41Sopenharmony_ci          } else {
31301cb0ef41Sopenharmony_ci            FeedbackSlot slot = feedback_spec()->AddDefineKeyedOwnICSlot();
31311cb0ef41Sopenharmony_ci            builder()->DefineKeyedOwnProperty(literal, key_reg,
31321cb0ef41Sopenharmony_ci                                              feedback_index(slot));
31331cb0ef41Sopenharmony_ci          }
31341cb0ef41Sopenharmony_ci        } else {
31351cb0ef41Sopenharmony_ci          VisitForEffect(property->value());
31361cb0ef41Sopenharmony_ci        }
31371cb0ef41Sopenharmony_ci        break;
31381cb0ef41Sopenharmony_ci      }
31391cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::PROTOTYPE: {
31401cb0ef41Sopenharmony_ci        // __proto__:null is handled by CreateObjectLiteral.
31411cb0ef41Sopenharmony_ci        if (property->IsNullPrototype()) break;
31421cb0ef41Sopenharmony_ci        DCHECK(property->emit_store());
31431cb0ef41Sopenharmony_ci        DCHECK(!property->NeedsSetFunctionName());
31441cb0ef41Sopenharmony_ci        RegisterList args = register_allocator()->NewRegisterList(2);
31451cb0ef41Sopenharmony_ci        builder()->MoveRegister(literal, args[0]);
31461cb0ef41Sopenharmony_ci        object_literal_context_scope.SetEnteredIf(false);
31471cb0ef41Sopenharmony_ci        builder()->SetExpressionPosition(property->value());
31481cb0ef41Sopenharmony_ci        VisitForRegisterValue(property->value(), args[1]);
31491cb0ef41Sopenharmony_ci        builder()->CallRuntime(Runtime::kInternalSetPrototype, args);
31501cb0ef41Sopenharmony_ci        break;
31511cb0ef41Sopenharmony_ci      }
31521cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::GETTER:
31531cb0ef41Sopenharmony_ci        if (property->emit_store()) {
31541cb0ef41Sopenharmony_ci          accessor_table.LookupOrInsert(key)->getter = property;
31551cb0ef41Sopenharmony_ci        }
31561cb0ef41Sopenharmony_ci        break;
31571cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::SETTER:
31581cb0ef41Sopenharmony_ci        if (property->emit_store()) {
31591cb0ef41Sopenharmony_ci          accessor_table.LookupOrInsert(key)->setter = property;
31601cb0ef41Sopenharmony_ci        }
31611cb0ef41Sopenharmony_ci        break;
31621cb0ef41Sopenharmony_ci    }
31631cb0ef41Sopenharmony_ci  }
31641cb0ef41Sopenharmony_ci
31651cb0ef41Sopenharmony_ci    // Define accessors, using only a single call to the runtime for each pair
31661cb0ef41Sopenharmony_ci    // of corresponding getters and setters.
31671cb0ef41Sopenharmony_ci    object_literal_context_scope.SetEnteredIf(true);
31681cb0ef41Sopenharmony_ci    for (auto accessors : accessor_table.ordered_accessors()) {
31691cb0ef41Sopenharmony_ci      RegisterAllocationScope inner_register_scope(this);
31701cb0ef41Sopenharmony_ci      RegisterList args = register_allocator()->NewRegisterList(5);
31711cb0ef41Sopenharmony_ci      builder()->MoveRegister(literal, args[0]);
31721cb0ef41Sopenharmony_ci      VisitForRegisterValue(accessors.first, args[1]);
31731cb0ef41Sopenharmony_ci      VisitLiteralAccessor(accessors.second->getter, args[2]);
31741cb0ef41Sopenharmony_ci      VisitLiteralAccessor(accessors.second->setter, args[3]);
31751cb0ef41Sopenharmony_ci      builder()
31761cb0ef41Sopenharmony_ci          ->LoadLiteral(Smi::FromInt(NONE))
31771cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[4])
31781cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, args);
31791cb0ef41Sopenharmony_ci    }
31801cb0ef41Sopenharmony_ci
31811cb0ef41Sopenharmony_ci  // Object literals have two parts. The "static" part on the left contains no
31821cb0ef41Sopenharmony_ci  // computed property names, and so we can compute its map ahead of time; see
31831cb0ef41Sopenharmony_ci  // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
31841cb0ef41Sopenharmony_ci  // with the first computed property name and continues with all properties to
31851cb0ef41Sopenharmony_ci  // its right. All the code from above initializes the static component of the
31861cb0ef41Sopenharmony_ci  // object literal, and arranges for the map of the result to reflect the
31871cb0ef41Sopenharmony_ci  // static order in which the keys appear. For the dynamic properties, we
31881cb0ef41Sopenharmony_ci  // compile them into a series of "SetOwnProperty" runtime calls. This will
31891cb0ef41Sopenharmony_ci  // preserve insertion order.
31901cb0ef41Sopenharmony_ci  for (; property_index < expr->properties()->length(); property_index++) {
31911cb0ef41Sopenharmony_ci    ObjectLiteral::Property* property = expr->properties()->at(property_index);
31921cb0ef41Sopenharmony_ci    RegisterAllocationScope inner_register_scope(this);
31931cb0ef41Sopenharmony_ci
31941cb0ef41Sopenharmony_ci    bool should_be_in_object_literal_scope =
31951cb0ef41Sopenharmony_ci        (property->value()->IsConciseMethodDefinition() ||
31961cb0ef41Sopenharmony_ci         property->value()->IsAccessorFunctionDefinition());
31971cb0ef41Sopenharmony_ci
31981cb0ef41Sopenharmony_ci    if (property->IsPrototype()) {
31991cb0ef41Sopenharmony_ci      // __proto__:null is handled by CreateObjectLiteral.
32001cb0ef41Sopenharmony_ci      if (property->IsNullPrototype()) continue;
32011cb0ef41Sopenharmony_ci      DCHECK(property->emit_store());
32021cb0ef41Sopenharmony_ci      DCHECK(!property->NeedsSetFunctionName());
32031cb0ef41Sopenharmony_ci      RegisterList args = register_allocator()->NewRegisterList(2);
32041cb0ef41Sopenharmony_ci      builder()->MoveRegister(literal, args[0]);
32051cb0ef41Sopenharmony_ci
32061cb0ef41Sopenharmony_ci      DCHECK(!should_be_in_object_literal_scope);
32071cb0ef41Sopenharmony_ci      object_literal_context_scope.SetEnteredIf(false);
32081cb0ef41Sopenharmony_ci      builder()->SetExpressionPosition(property->value());
32091cb0ef41Sopenharmony_ci      VisitForRegisterValue(property->value(), args[1]);
32101cb0ef41Sopenharmony_ci      builder()->CallRuntime(Runtime::kInternalSetPrototype, args);
32111cb0ef41Sopenharmony_ci      continue;
32121cb0ef41Sopenharmony_ci    }
32131cb0ef41Sopenharmony_ci
32141cb0ef41Sopenharmony_ci    switch (property->kind()) {
32151cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::CONSTANT:
32161cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::COMPUTED:
32171cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
32181cb0ef41Sopenharmony_ci        // Computed property keys don't belong to the object literal scope (even
32191cb0ef41Sopenharmony_ci        // if they're syntactically inside it).
32201cb0ef41Sopenharmony_ci        if (property->is_computed_name()) {
32211cb0ef41Sopenharmony_ci          object_literal_context_scope.SetEnteredIf(false);
32221cb0ef41Sopenharmony_ci        }
32231cb0ef41Sopenharmony_ci        Register key = register_allocator()->NewRegister();
32241cb0ef41Sopenharmony_ci        BuildLoadPropertyKey(property, key);
32251cb0ef41Sopenharmony_ci
32261cb0ef41Sopenharmony_ci        object_literal_context_scope.SetEnteredIf(
32271cb0ef41Sopenharmony_ci            should_be_in_object_literal_scope);
32281cb0ef41Sopenharmony_ci        builder()->SetExpressionPosition(property->value());
32291cb0ef41Sopenharmony_ci        Register value;
32301cb0ef41Sopenharmony_ci
32311cb0ef41Sopenharmony_ci        // Static class fields require the name property to be set on
32321cb0ef41Sopenharmony_ci        // the class, meaning we can't wait until the
32331cb0ef41Sopenharmony_ci        // DefineKeyedOwnPropertyInLiteral call later to set the name.
32341cb0ef41Sopenharmony_ci        if (property->value()->IsClassLiteral() &&
32351cb0ef41Sopenharmony_ci            property->value()->AsClassLiteral()->static_initializer() !=
32361cb0ef41Sopenharmony_ci                nullptr) {
32371cb0ef41Sopenharmony_ci          value = register_allocator()->NewRegister();
32381cb0ef41Sopenharmony_ci          VisitClassLiteral(property->value()->AsClassLiteral(), key);
32391cb0ef41Sopenharmony_ci          builder()->StoreAccumulatorInRegister(value);
32401cb0ef41Sopenharmony_ci        } else {
32411cb0ef41Sopenharmony_ci          value = VisitForRegisterValue(property->value());
32421cb0ef41Sopenharmony_ci        }
32431cb0ef41Sopenharmony_ci
32441cb0ef41Sopenharmony_ci        DefineKeyedOwnPropertyInLiteralFlags data_property_flags =
32451cb0ef41Sopenharmony_ci            DefineKeyedOwnPropertyInLiteralFlag::kNoFlags;
32461cb0ef41Sopenharmony_ci        if (property->NeedsSetFunctionName()) {
32471cb0ef41Sopenharmony_ci          data_property_flags |=
32481cb0ef41Sopenharmony_ci              DefineKeyedOwnPropertyInLiteralFlag::kSetFunctionName;
32491cb0ef41Sopenharmony_ci        }
32501cb0ef41Sopenharmony_ci
32511cb0ef41Sopenharmony_ci        FeedbackSlot slot =
32521cb0ef41Sopenharmony_ci            feedback_spec()->AddDefineKeyedOwnPropertyInLiteralICSlot();
32531cb0ef41Sopenharmony_ci        builder()
32541cb0ef41Sopenharmony_ci            ->LoadAccumulatorWithRegister(value)
32551cb0ef41Sopenharmony_ci            .DefineKeyedOwnPropertyInLiteral(literal, key, data_property_flags,
32561cb0ef41Sopenharmony_ci                                             feedback_index(slot));
32571cb0ef41Sopenharmony_ci        break;
32581cb0ef41Sopenharmony_ci      }
32591cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::GETTER:
32601cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::SETTER: {
32611cb0ef41Sopenharmony_ci        // Computed property keys don't belong to the object literal scope (even
32621cb0ef41Sopenharmony_ci        // if they're syntactically inside it).
32631cb0ef41Sopenharmony_ci        if (property->is_computed_name()) {
32641cb0ef41Sopenharmony_ci          object_literal_context_scope.SetEnteredIf(false);
32651cb0ef41Sopenharmony_ci        }
32661cb0ef41Sopenharmony_ci        RegisterList args = register_allocator()->NewRegisterList(4);
32671cb0ef41Sopenharmony_ci        builder()->MoveRegister(literal, args[0]);
32681cb0ef41Sopenharmony_ci        BuildLoadPropertyKey(property, args[1]);
32691cb0ef41Sopenharmony_ci
32701cb0ef41Sopenharmony_ci        DCHECK(should_be_in_object_literal_scope);
32711cb0ef41Sopenharmony_ci        object_literal_context_scope.SetEnteredIf(true);
32721cb0ef41Sopenharmony_ci        builder()->SetExpressionPosition(property->value());
32731cb0ef41Sopenharmony_ci        VisitForRegisterValue(property->value(), args[2]);
32741cb0ef41Sopenharmony_ci        builder()
32751cb0ef41Sopenharmony_ci            ->LoadLiteral(Smi::FromInt(NONE))
32761cb0ef41Sopenharmony_ci            .StoreAccumulatorInRegister(args[3]);
32771cb0ef41Sopenharmony_ci        Runtime::FunctionId function_id =
32781cb0ef41Sopenharmony_ci            property->kind() == ObjectLiteral::Property::GETTER
32791cb0ef41Sopenharmony_ci                ? Runtime::kDefineGetterPropertyUnchecked
32801cb0ef41Sopenharmony_ci                : Runtime::kDefineSetterPropertyUnchecked;
32811cb0ef41Sopenharmony_ci        builder()->CallRuntime(function_id, args);
32821cb0ef41Sopenharmony_ci        break;
32831cb0ef41Sopenharmony_ci      }
32841cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::SPREAD: {
32851cb0ef41Sopenharmony_ci        RegisterList args = register_allocator()->NewRegisterList(2);
32861cb0ef41Sopenharmony_ci        builder()->MoveRegister(literal, args[0]);
32871cb0ef41Sopenharmony_ci        builder()->SetExpressionPosition(property->value());
32881cb0ef41Sopenharmony_ci        object_literal_context_scope.SetEnteredIf(false);
32891cb0ef41Sopenharmony_ci        VisitForRegisterValue(property->value(), args[1]);
32901cb0ef41Sopenharmony_ci        builder()->CallRuntime(Runtime::kInlineCopyDataProperties, args);
32911cb0ef41Sopenharmony_ci        break;
32921cb0ef41Sopenharmony_ci      }
32931cb0ef41Sopenharmony_ci      case ObjectLiteral::Property::PROTOTYPE:
32941cb0ef41Sopenharmony_ci        UNREACHABLE();  // Handled specially above.
32951cb0ef41Sopenharmony_ci    }
32961cb0ef41Sopenharmony_ci  }
32971cb0ef41Sopenharmony_ci
32981cb0ef41Sopenharmony_ci  builder()->LoadAccumulatorWithRegister(literal);
32991cb0ef41Sopenharmony_ci  if (home_object != nullptr) {
33001cb0ef41Sopenharmony_ci    object_literal_context_scope.SetEnteredIf(true);
33011cb0ef41Sopenharmony_ci    BuildVariableAssignment(home_object, Token::INIT, HoleCheckMode::kElided);
33021cb0ef41Sopenharmony_ci  }
33031cb0ef41Sopenharmony_ci}
33041cb0ef41Sopenharmony_ci
33051cb0ef41Sopenharmony_ci// Fill an array with values from an iterator, starting at a given index. It is
33061cb0ef41Sopenharmony_ci// guaranteed that the loop will only terminate if the iterator is exhausted, or
33071cb0ef41Sopenharmony_ci// if one of iterator.next(), value.done, or value.value fail.
33081cb0ef41Sopenharmony_ci//
33091cb0ef41Sopenharmony_ci// In pseudocode:
33101cb0ef41Sopenharmony_ci//
33111cb0ef41Sopenharmony_ci// loop {
33121cb0ef41Sopenharmony_ci//   value = iterator.next()
33131cb0ef41Sopenharmony_ci//   if (value.done) break;
33141cb0ef41Sopenharmony_ci//   value = value.value
33151cb0ef41Sopenharmony_ci//   array[index++] = value
33161cb0ef41Sopenharmony_ci// }
33171cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildFillArrayWithIterator(
33181cb0ef41Sopenharmony_ci    IteratorRecord iterator, Register array, Register index, Register value,
33191cb0ef41Sopenharmony_ci    FeedbackSlot next_value_slot, FeedbackSlot next_done_slot,
33201cb0ef41Sopenharmony_ci    FeedbackSlot index_slot, FeedbackSlot element_slot) {
33211cb0ef41Sopenharmony_ci  DCHECK(array.is_valid());
33221cb0ef41Sopenharmony_ci  DCHECK(index.is_valid());
33231cb0ef41Sopenharmony_ci  DCHECK(value.is_valid());
33241cb0ef41Sopenharmony_ci
33251cb0ef41Sopenharmony_ci  LoopBuilder loop_builder(builder(), nullptr, nullptr);
33261cb0ef41Sopenharmony_ci  LoopScope loop_scope(this, &loop_builder);
33271cb0ef41Sopenharmony_ci
33281cb0ef41Sopenharmony_ci  // Call the iterator's .next() method. Break from the loop if the `done`
33291cb0ef41Sopenharmony_ci  // property is truthy, otherwise load the value from the iterator result and
33301cb0ef41Sopenharmony_ci  // append the argument.
33311cb0ef41Sopenharmony_ci  BuildIteratorNext(iterator, value);
33321cb0ef41Sopenharmony_ci  builder()->LoadNamedProperty(
33331cb0ef41Sopenharmony_ci      value, ast_string_constants()->done_string(),
33341cb0ef41Sopenharmony_ci      feedback_index(feedback_spec()->AddLoadICSlot()));
33351cb0ef41Sopenharmony_ci  loop_builder.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
33361cb0ef41Sopenharmony_ci
33371cb0ef41Sopenharmony_ci  loop_builder.LoopBody();
33381cb0ef41Sopenharmony_ci  builder()
33391cb0ef41Sopenharmony_ci      // value = value.value
33401cb0ef41Sopenharmony_ci      ->LoadNamedProperty(value, ast_string_constants()->value_string(),
33411cb0ef41Sopenharmony_ci                          feedback_index(next_value_slot))
33421cb0ef41Sopenharmony_ci      // array[index] = value
33431cb0ef41Sopenharmony_ci      .StoreInArrayLiteral(array, index, feedback_index(element_slot))
33441cb0ef41Sopenharmony_ci      // index++
33451cb0ef41Sopenharmony_ci      .LoadAccumulatorWithRegister(index)
33461cb0ef41Sopenharmony_ci      .UnaryOperation(Token::INC, feedback_index(index_slot))
33471cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(index);
33481cb0ef41Sopenharmony_ci  loop_builder.BindContinueTarget();
33491cb0ef41Sopenharmony_ci}
33501cb0ef41Sopenharmony_ci
33511cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildCreateArrayLiteral(
33521cb0ef41Sopenharmony_ci    const ZonePtrList<Expression>* elements, ArrayLiteral* expr) {
33531cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
33541cb0ef41Sopenharmony_ci  Register index = register_allocator()->NewRegister();
33551cb0ef41Sopenharmony_ci  Register array = register_allocator()->NewRegister();
33561cb0ef41Sopenharmony_ci  SharedFeedbackSlot element_slot(feedback_spec(),
33571cb0ef41Sopenharmony_ci                                  FeedbackSlotKind::kStoreInArrayLiteral);
33581cb0ef41Sopenharmony_ci  ZonePtrList<Expression>::const_iterator current = elements->begin();
33591cb0ef41Sopenharmony_ci  ZonePtrList<Expression>::const_iterator end = elements->end();
33601cb0ef41Sopenharmony_ci  bool is_empty = elements->is_empty();
33611cb0ef41Sopenharmony_ci
33621cb0ef41Sopenharmony_ci  if (!is_empty && (*current)->IsSpread()) {
33631cb0ef41Sopenharmony_ci    // If we have a leading spread, use CreateArrayFromIterable to create
33641cb0ef41Sopenharmony_ci    // an array from it and then add the remaining components to that array.
33651cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(*current);
33661cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition((*current)->AsSpread()->expression());
33671cb0ef41Sopenharmony_ci    builder()->CreateArrayFromIterable().StoreAccumulatorInRegister(array);
33681cb0ef41Sopenharmony_ci
33691cb0ef41Sopenharmony_ci    if (++current != end) {
33701cb0ef41Sopenharmony_ci      // If there are remaning elements, prepare the index register that is
33711cb0ef41Sopenharmony_ci      // used for adding those elements. The next index is the length of the
33721cb0ef41Sopenharmony_ci      // newly created array.
33731cb0ef41Sopenharmony_ci      auto length = ast_string_constants()->length_string();
33741cb0ef41Sopenharmony_ci      int length_load_slot = feedback_index(feedback_spec()->AddLoadICSlot());
33751cb0ef41Sopenharmony_ci      builder()
33761cb0ef41Sopenharmony_ci          ->LoadNamedProperty(array, length, length_load_slot)
33771cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(index);
33781cb0ef41Sopenharmony_ci    }
33791cb0ef41Sopenharmony_ci  } else {
33801cb0ef41Sopenharmony_ci    // There are some elements before the first (if any) spread, and we can
33811cb0ef41Sopenharmony_ci    // use a boilerplate when creating the initial array from those elements.
33821cb0ef41Sopenharmony_ci
33831cb0ef41Sopenharmony_ci    // First, allocate a constant pool entry for the boilerplate that will
33841cb0ef41Sopenharmony_ci    // be created during finalization, and will contain all the constant
33851cb0ef41Sopenharmony_ci    // elements before the first spread. This also handle the empty array case
33861cb0ef41Sopenharmony_ci    // and one-shot optimization.
33871cb0ef41Sopenharmony_ci
33881cb0ef41Sopenharmony_ci    ArrayLiteralBoilerplateBuilder* array_literal_builder = nullptr;
33891cb0ef41Sopenharmony_ci    if (expr != nullptr) {
33901cb0ef41Sopenharmony_ci      array_literal_builder = expr->builder();
33911cb0ef41Sopenharmony_ci    } else {
33921cb0ef41Sopenharmony_ci      DCHECK(!elements->is_empty());
33931cb0ef41Sopenharmony_ci
33941cb0ef41Sopenharmony_ci      // get first_spread_index
33951cb0ef41Sopenharmony_ci      int first_spread_index = -1;
33961cb0ef41Sopenharmony_ci      for (auto iter = elements->begin(); iter != elements->end(); iter++) {
33971cb0ef41Sopenharmony_ci        if ((*iter)->IsSpread()) {
33981cb0ef41Sopenharmony_ci          first_spread_index = static_cast<int>(iter - elements->begin());
33991cb0ef41Sopenharmony_ci          break;
34001cb0ef41Sopenharmony_ci        }
34011cb0ef41Sopenharmony_ci      }
34021cb0ef41Sopenharmony_ci
34031cb0ef41Sopenharmony_ci      array_literal_builder = zone()->New<ArrayLiteralBoilerplateBuilder>(
34041cb0ef41Sopenharmony_ci          elements, first_spread_index);
34051cb0ef41Sopenharmony_ci      array_literal_builder->InitDepthAndFlags();
34061cb0ef41Sopenharmony_ci    }
34071cb0ef41Sopenharmony_ci
34081cb0ef41Sopenharmony_ci    DCHECK(array_literal_builder != nullptr);
34091cb0ef41Sopenharmony_ci    uint8_t flags = CreateArrayLiteralFlags::Encode(
34101cb0ef41Sopenharmony_ci        array_literal_builder->IsFastCloningSupported(),
34111cb0ef41Sopenharmony_ci        array_literal_builder->ComputeFlags());
34121cb0ef41Sopenharmony_ci    if (is_empty) {
34131cb0ef41Sopenharmony_ci      // Empty array literal fast-path.
34141cb0ef41Sopenharmony_ci      int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
34151cb0ef41Sopenharmony_ci      DCHECK(array_literal_builder->IsFastCloningSupported());
34161cb0ef41Sopenharmony_ci      builder()->CreateEmptyArrayLiteral(literal_index);
34171cb0ef41Sopenharmony_ci    } else {
34181cb0ef41Sopenharmony_ci      // Create array literal from boilerplate.
34191cb0ef41Sopenharmony_ci      size_t entry = builder()->AllocateDeferredConstantPoolEntry();
34201cb0ef41Sopenharmony_ci      array_literals_.push_back(std::make_pair(array_literal_builder, entry));
34211cb0ef41Sopenharmony_ci      int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
34221cb0ef41Sopenharmony_ci      builder()->CreateArrayLiteral(entry, literal_index, flags);
34231cb0ef41Sopenharmony_ci    }
34241cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(array);
34251cb0ef41Sopenharmony_ci
34261cb0ef41Sopenharmony_ci    ZonePtrList<Expression>::const_iterator first_spread_or_end =
34271cb0ef41Sopenharmony_ci        array_literal_builder->first_spread_index() >= 0
34281cb0ef41Sopenharmony_ci            ? current + array_literal_builder->first_spread_index()
34291cb0ef41Sopenharmony_ci            : end;
34301cb0ef41Sopenharmony_ci
34311cb0ef41Sopenharmony_ci    // Insert the missing non-constant elements, up until the first spread
34321cb0ef41Sopenharmony_ci    // index, into the initial array (the remaining elements will be inserted
34331cb0ef41Sopenharmony_ci    // below).
34341cb0ef41Sopenharmony_ci    DCHECK_EQ(current, elements->begin());
34351cb0ef41Sopenharmony_ci    int array_index = 0;
34361cb0ef41Sopenharmony_ci    for (; current != first_spread_or_end; ++current, array_index++) {
34371cb0ef41Sopenharmony_ci      Expression* subexpr = *current;
34381cb0ef41Sopenharmony_ci      DCHECK(!subexpr->IsSpread());
34391cb0ef41Sopenharmony_ci      // Skip the constants.
34401cb0ef41Sopenharmony_ci      if (subexpr->IsCompileTimeValue()) continue;
34411cb0ef41Sopenharmony_ci
34421cb0ef41Sopenharmony_ci      builder()
34431cb0ef41Sopenharmony_ci          ->LoadLiteral(Smi::FromInt(array_index))
34441cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(index);
34451cb0ef41Sopenharmony_ci      VisitForAccumulatorValue(subexpr);
34461cb0ef41Sopenharmony_ci      builder()->StoreInArrayLiteral(array, index,
34471cb0ef41Sopenharmony_ci                                     feedback_index(element_slot.Get()));
34481cb0ef41Sopenharmony_ci    }
34491cb0ef41Sopenharmony_ci
34501cb0ef41Sopenharmony_ci    if (current != end) {
34511cb0ef41Sopenharmony_ci      // If there are remaining elements, prepare the index register
34521cb0ef41Sopenharmony_ci      // to store the next element, which comes from the first spread.
34531cb0ef41Sopenharmony_ci      builder()
34541cb0ef41Sopenharmony_ci          ->LoadLiteral(Smi::FromInt(array_index))
34551cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(index);
34561cb0ef41Sopenharmony_ci    }
34571cb0ef41Sopenharmony_ci  }
34581cb0ef41Sopenharmony_ci
34591cb0ef41Sopenharmony_ci  // Now build insertions for the remaining elements from current to end.
34601cb0ef41Sopenharmony_ci  SharedFeedbackSlot index_slot(feedback_spec(), FeedbackSlotKind::kBinaryOp);
34611cb0ef41Sopenharmony_ci  SharedFeedbackSlot length_slot(
34621cb0ef41Sopenharmony_ci      feedback_spec(), feedback_spec()->GetStoreICSlot(LanguageMode::kStrict));
34631cb0ef41Sopenharmony_ci  for (; current != end; ++current) {
34641cb0ef41Sopenharmony_ci    Expression* subexpr = *current;
34651cb0ef41Sopenharmony_ci    if (subexpr->IsSpread()) {
34661cb0ef41Sopenharmony_ci      RegisterAllocationScope scope(this);
34671cb0ef41Sopenharmony_ci      builder()->SetExpressionAsStatementPosition(
34681cb0ef41Sopenharmony_ci          subexpr->AsSpread()->expression());
34691cb0ef41Sopenharmony_ci      VisitForAccumulatorValue(subexpr->AsSpread()->expression());
34701cb0ef41Sopenharmony_ci      builder()->SetExpressionPosition(subexpr->AsSpread()->expression());
34711cb0ef41Sopenharmony_ci      IteratorRecord iterator = BuildGetIteratorRecord(IteratorType::kNormal);
34721cb0ef41Sopenharmony_ci
34731cb0ef41Sopenharmony_ci      Register value = register_allocator()->NewRegister();
34741cb0ef41Sopenharmony_ci      FeedbackSlot next_value_load_slot = feedback_spec()->AddLoadICSlot();
34751cb0ef41Sopenharmony_ci      FeedbackSlot next_done_load_slot = feedback_spec()->AddLoadICSlot();
34761cb0ef41Sopenharmony_ci      FeedbackSlot real_index_slot = index_slot.Get();
34771cb0ef41Sopenharmony_ci      FeedbackSlot real_element_slot = element_slot.Get();
34781cb0ef41Sopenharmony_ci      BuildFillArrayWithIterator(iterator, array, index, value,
34791cb0ef41Sopenharmony_ci                                 next_value_load_slot, next_done_load_slot,
34801cb0ef41Sopenharmony_ci                                 real_index_slot, real_element_slot);
34811cb0ef41Sopenharmony_ci    } else if (!subexpr->IsTheHoleLiteral()) {
34821cb0ef41Sopenharmony_ci      // literal[index++] = subexpr
34831cb0ef41Sopenharmony_ci      VisitForAccumulatorValue(subexpr);
34841cb0ef41Sopenharmony_ci      builder()
34851cb0ef41Sopenharmony_ci          ->StoreInArrayLiteral(array, index,
34861cb0ef41Sopenharmony_ci                                feedback_index(element_slot.Get()))
34871cb0ef41Sopenharmony_ci          .LoadAccumulatorWithRegister(index);
34881cb0ef41Sopenharmony_ci      // Only increase the index if we are not the last element.
34891cb0ef41Sopenharmony_ci      if (current + 1 != end) {
34901cb0ef41Sopenharmony_ci        builder()
34911cb0ef41Sopenharmony_ci            ->UnaryOperation(Token::INC, feedback_index(index_slot.Get()))
34921cb0ef41Sopenharmony_ci            .StoreAccumulatorInRegister(index);
34931cb0ef41Sopenharmony_ci      }
34941cb0ef41Sopenharmony_ci    } else {
34951cb0ef41Sopenharmony_ci      // literal.length = ++index
34961cb0ef41Sopenharmony_ci      // length_slot is only used when there are holes.
34971cb0ef41Sopenharmony_ci      auto length = ast_string_constants()->length_string();
34981cb0ef41Sopenharmony_ci      builder()
34991cb0ef41Sopenharmony_ci          ->LoadAccumulatorWithRegister(index)
35001cb0ef41Sopenharmony_ci          .UnaryOperation(Token::INC, feedback_index(index_slot.Get()))
35011cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(index)
35021cb0ef41Sopenharmony_ci          .SetNamedProperty(array, length, feedback_index(length_slot.Get()),
35031cb0ef41Sopenharmony_ci                            LanguageMode::kStrict);
35041cb0ef41Sopenharmony_ci    }
35051cb0ef41Sopenharmony_ci  }
35061cb0ef41Sopenharmony_ci
35071cb0ef41Sopenharmony_ci  builder()->LoadAccumulatorWithRegister(array);
35081cb0ef41Sopenharmony_ci}
35091cb0ef41Sopenharmony_ci
35101cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
35111cb0ef41Sopenharmony_ci  expr->builder()->InitDepthAndFlags();
35121cb0ef41Sopenharmony_ci  BuildCreateArrayLiteral(expr->values(), expr);
35131cb0ef41Sopenharmony_ci}
35141cb0ef41Sopenharmony_ci
35151cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
35161cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(proxy);
35171cb0ef41Sopenharmony_ci  BuildVariableLoad(proxy->var(), proxy->hole_check_mode());
35181cb0ef41Sopenharmony_ci}
35191cb0ef41Sopenharmony_ci
35201cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildVariableLoad(Variable* variable,
35211cb0ef41Sopenharmony_ci                                          HoleCheckMode hole_check_mode,
35221cb0ef41Sopenharmony_ci                                          TypeofMode typeof_mode) {
35231cb0ef41Sopenharmony_ci  switch (variable->location()) {
35241cb0ef41Sopenharmony_ci    case VariableLocation::LOCAL: {
35251cb0ef41Sopenharmony_ci      Register source(builder()->Local(variable->index()));
35261cb0ef41Sopenharmony_ci      // We need to load the variable into the accumulator, even when in a
35271cb0ef41Sopenharmony_ci      // VisitForRegisterScope, in order to avoid register aliasing if
35281cb0ef41Sopenharmony_ci      // subsequent expressions assign to the same variable.
35291cb0ef41Sopenharmony_ci      builder()->LoadAccumulatorWithRegister(source);
35301cb0ef41Sopenharmony_ci      if (hole_check_mode == HoleCheckMode::kRequired) {
35311cb0ef41Sopenharmony_ci        BuildThrowIfHole(variable);
35321cb0ef41Sopenharmony_ci      }
35331cb0ef41Sopenharmony_ci      break;
35341cb0ef41Sopenharmony_ci    }
35351cb0ef41Sopenharmony_ci    case VariableLocation::PARAMETER: {
35361cb0ef41Sopenharmony_ci      Register source;
35371cb0ef41Sopenharmony_ci      if (variable->IsReceiver()) {
35381cb0ef41Sopenharmony_ci        source = builder()->Receiver();
35391cb0ef41Sopenharmony_ci      } else {
35401cb0ef41Sopenharmony_ci        source = builder()->Parameter(variable->index());
35411cb0ef41Sopenharmony_ci      }
35421cb0ef41Sopenharmony_ci      // We need to load the variable into the accumulator, even when in a
35431cb0ef41Sopenharmony_ci      // VisitForRegisterScope, in order to avoid register aliasing if
35441cb0ef41Sopenharmony_ci      // subsequent expressions assign to the same variable.
35451cb0ef41Sopenharmony_ci      builder()->LoadAccumulatorWithRegister(source);
35461cb0ef41Sopenharmony_ci      if (hole_check_mode == HoleCheckMode::kRequired) {
35471cb0ef41Sopenharmony_ci        BuildThrowIfHole(variable);
35481cb0ef41Sopenharmony_ci      }
35491cb0ef41Sopenharmony_ci      break;
35501cb0ef41Sopenharmony_ci    }
35511cb0ef41Sopenharmony_ci    case VariableLocation::UNALLOCATED: {
35521cb0ef41Sopenharmony_ci      // The global identifier "undefined" is immutable. Everything
35531cb0ef41Sopenharmony_ci      // else could be reassigned. For performance, we do a pointer comparison
35541cb0ef41Sopenharmony_ci      // rather than checking if the raw_name is really "undefined".
35551cb0ef41Sopenharmony_ci      if (variable->raw_name() == ast_string_constants()->undefined_string()) {
35561cb0ef41Sopenharmony_ci        builder()->LoadUndefined();
35571cb0ef41Sopenharmony_ci      } else {
35581cb0ef41Sopenharmony_ci        FeedbackSlot slot = GetCachedLoadGlobalICSlot(typeof_mode, variable);
35591cb0ef41Sopenharmony_ci        builder()->LoadGlobal(variable->raw_name(), feedback_index(slot),
35601cb0ef41Sopenharmony_ci                              typeof_mode);
35611cb0ef41Sopenharmony_ci      }
35621cb0ef41Sopenharmony_ci      break;
35631cb0ef41Sopenharmony_ci    }
35641cb0ef41Sopenharmony_ci    case VariableLocation::CONTEXT: {
35651cb0ef41Sopenharmony_ci      int depth = execution_context()->ContextChainDepth(variable->scope());
35661cb0ef41Sopenharmony_ci      ContextScope* context = execution_context()->Previous(depth);
35671cb0ef41Sopenharmony_ci      Register context_reg;
35681cb0ef41Sopenharmony_ci      if (context) {
35691cb0ef41Sopenharmony_ci        context_reg = context->reg();
35701cb0ef41Sopenharmony_ci        depth = 0;
35711cb0ef41Sopenharmony_ci      } else {
35721cb0ef41Sopenharmony_ci        context_reg = execution_context()->reg();
35731cb0ef41Sopenharmony_ci      }
35741cb0ef41Sopenharmony_ci
35751cb0ef41Sopenharmony_ci      BytecodeArrayBuilder::ContextSlotMutability immutable =
35761cb0ef41Sopenharmony_ci          (variable->maybe_assigned() == kNotAssigned)
35771cb0ef41Sopenharmony_ci              ? BytecodeArrayBuilder::kImmutableSlot
35781cb0ef41Sopenharmony_ci              : BytecodeArrayBuilder::kMutableSlot;
35791cb0ef41Sopenharmony_ci
35801cb0ef41Sopenharmony_ci      builder()->LoadContextSlot(context_reg, variable->index(), depth,
35811cb0ef41Sopenharmony_ci                                 immutable);
35821cb0ef41Sopenharmony_ci      if (hole_check_mode == HoleCheckMode::kRequired) {
35831cb0ef41Sopenharmony_ci        BuildThrowIfHole(variable);
35841cb0ef41Sopenharmony_ci      }
35851cb0ef41Sopenharmony_ci      break;
35861cb0ef41Sopenharmony_ci    }
35871cb0ef41Sopenharmony_ci    case VariableLocation::LOOKUP: {
35881cb0ef41Sopenharmony_ci      switch (variable->mode()) {
35891cb0ef41Sopenharmony_ci        case VariableMode::kDynamicLocal: {
35901cb0ef41Sopenharmony_ci          Variable* local_variable = variable->local_if_not_shadowed();
35911cb0ef41Sopenharmony_ci          int depth =
35921cb0ef41Sopenharmony_ci              execution_context()->ContextChainDepth(local_variable->scope());
35931cb0ef41Sopenharmony_ci          builder()->LoadLookupContextSlot(variable->raw_name(), typeof_mode,
35941cb0ef41Sopenharmony_ci                                           local_variable->index(), depth);
35951cb0ef41Sopenharmony_ci          if (hole_check_mode == HoleCheckMode::kRequired) {
35961cb0ef41Sopenharmony_ci            BuildThrowIfHole(variable);
35971cb0ef41Sopenharmony_ci          }
35981cb0ef41Sopenharmony_ci          break;
35991cb0ef41Sopenharmony_ci        }
36001cb0ef41Sopenharmony_ci        case VariableMode::kDynamicGlobal: {
36011cb0ef41Sopenharmony_ci          int depth =
36021cb0ef41Sopenharmony_ci              current_scope()->ContextChainLengthUntilOutermostSloppyEval();
36031cb0ef41Sopenharmony_ci          // TODO(1008414): Add back caching here when bug is fixed properly.
36041cb0ef41Sopenharmony_ci          FeedbackSlot slot = feedback_spec()->AddLoadGlobalICSlot(typeof_mode);
36051cb0ef41Sopenharmony_ci
36061cb0ef41Sopenharmony_ci          builder()->LoadLookupGlobalSlot(variable->raw_name(), typeof_mode,
36071cb0ef41Sopenharmony_ci                                          feedback_index(slot), depth);
36081cb0ef41Sopenharmony_ci          break;
36091cb0ef41Sopenharmony_ci        }
36101cb0ef41Sopenharmony_ci        default:
36111cb0ef41Sopenharmony_ci          builder()->LoadLookupSlot(variable->raw_name(), typeof_mode);
36121cb0ef41Sopenharmony_ci      }
36131cb0ef41Sopenharmony_ci      break;
36141cb0ef41Sopenharmony_ci    }
36151cb0ef41Sopenharmony_ci    case VariableLocation::MODULE: {
36161cb0ef41Sopenharmony_ci      int depth = execution_context()->ContextChainDepth(variable->scope());
36171cb0ef41Sopenharmony_ci      builder()->LoadModuleVariable(variable->index(), depth);
36181cb0ef41Sopenharmony_ci      if (hole_check_mode == HoleCheckMode::kRequired) {
36191cb0ef41Sopenharmony_ci        BuildThrowIfHole(variable);
36201cb0ef41Sopenharmony_ci      }
36211cb0ef41Sopenharmony_ci      break;
36221cb0ef41Sopenharmony_ci    }
36231cb0ef41Sopenharmony_ci    case VariableLocation::REPL_GLOBAL: {
36241cb0ef41Sopenharmony_ci      DCHECK(variable->IsReplGlobal());
36251cb0ef41Sopenharmony_ci      FeedbackSlot slot = GetCachedLoadGlobalICSlot(typeof_mode, variable);
36261cb0ef41Sopenharmony_ci      builder()->LoadGlobal(variable->raw_name(), feedback_index(slot),
36271cb0ef41Sopenharmony_ci                            typeof_mode);
36281cb0ef41Sopenharmony_ci      break;
36291cb0ef41Sopenharmony_ci    }
36301cb0ef41Sopenharmony_ci  }
36311cb0ef41Sopenharmony_ci}
36321cb0ef41Sopenharmony_ci
36331cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildVariableLoadForAccumulatorValue(
36341cb0ef41Sopenharmony_ci    Variable* variable, HoleCheckMode hole_check_mode, TypeofMode typeof_mode) {
36351cb0ef41Sopenharmony_ci  ValueResultScope accumulator_result(this);
36361cb0ef41Sopenharmony_ci  BuildVariableLoad(variable, hole_check_mode, typeof_mode);
36371cb0ef41Sopenharmony_ci}
36381cb0ef41Sopenharmony_ci
36391cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildReturn(int source_position) {
36401cb0ef41Sopenharmony_ci  if (FLAG_trace) {
36411cb0ef41Sopenharmony_ci    RegisterAllocationScope register_scope(this);
36421cb0ef41Sopenharmony_ci    Register result = register_allocator()->NewRegister();
36431cb0ef41Sopenharmony_ci    // Runtime returns {result} value, preserving accumulator.
36441cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(result).CallRuntime(
36451cb0ef41Sopenharmony_ci        Runtime::kTraceExit, result);
36461cb0ef41Sopenharmony_ci  }
36471cb0ef41Sopenharmony_ci  if (info()->flags().collect_type_profile()) {
36481cb0ef41Sopenharmony_ci    builder()->CollectTypeProfile(info()->literal()->return_position());
36491cb0ef41Sopenharmony_ci  }
36501cb0ef41Sopenharmony_ci  builder()->SetStatementPosition(source_position);
36511cb0ef41Sopenharmony_ci  builder()->Return();
36521cb0ef41Sopenharmony_ci}
36531cb0ef41Sopenharmony_ci
36541cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildAsyncReturn(int source_position) {
36551cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
36561cb0ef41Sopenharmony_ci
36571cb0ef41Sopenharmony_ci  if (IsAsyncGeneratorFunction(info()->literal()->kind())) {
36581cb0ef41Sopenharmony_ci    RegisterList args = register_allocator()->NewRegisterList(3);
36591cb0ef41Sopenharmony_ci    builder()
36601cb0ef41Sopenharmony_ci        ->MoveRegister(generator_object(), args[0])  // generator
36611cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(args[1])         // value
36621cb0ef41Sopenharmony_ci        .LoadTrue()
36631cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(args[2])  // done
36641cb0ef41Sopenharmony_ci        .CallRuntime(Runtime::kInlineAsyncGeneratorResolve, args);
36651cb0ef41Sopenharmony_ci  } else {
36661cb0ef41Sopenharmony_ci    DCHECK(IsAsyncFunction(info()->literal()->kind()) ||
36671cb0ef41Sopenharmony_ci           IsAsyncModule(info()->literal()->kind()));
36681cb0ef41Sopenharmony_ci    RegisterList args = register_allocator()->NewRegisterList(2);
36691cb0ef41Sopenharmony_ci    builder()
36701cb0ef41Sopenharmony_ci        ->MoveRegister(generator_object(), args[0])  // generator
36711cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(args[1])         // value
36721cb0ef41Sopenharmony_ci        .CallRuntime(Runtime::kInlineAsyncFunctionResolve, args);
36731cb0ef41Sopenharmony_ci  }
36741cb0ef41Sopenharmony_ci
36751cb0ef41Sopenharmony_ci  BuildReturn(source_position);
36761cb0ef41Sopenharmony_ci}
36771cb0ef41Sopenharmony_ci
36781cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildReThrow() { builder()->ReThrow(); }
36791cb0ef41Sopenharmony_ci
36801cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildThrowIfHole(Variable* variable) {
36811cb0ef41Sopenharmony_ci  if (variable->is_this()) {
36821cb0ef41Sopenharmony_ci    DCHECK(variable->mode() == VariableMode::kConst);
36831cb0ef41Sopenharmony_ci    builder()->ThrowSuperNotCalledIfHole();
36841cb0ef41Sopenharmony_ci  } else {
36851cb0ef41Sopenharmony_ci    builder()->ThrowReferenceErrorIfHole(variable->raw_name());
36861cb0ef41Sopenharmony_ci  }
36871cb0ef41Sopenharmony_ci}
36881cb0ef41Sopenharmony_ci
36891cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
36901cb0ef41Sopenharmony_ci                                                            Token::Value op) {
36911cb0ef41Sopenharmony_ci  DCHECK(!IsPrivateMethodOrAccessorVariableMode(variable->mode()));
36921cb0ef41Sopenharmony_ci  if (variable->is_this() && variable->mode() == VariableMode::kConst &&
36931cb0ef41Sopenharmony_ci      op == Token::INIT) {
36941cb0ef41Sopenharmony_ci    // Perform an initialization check for 'this'. 'this' variable is the
36951cb0ef41Sopenharmony_ci    // only variable able to trigger bind operations outside the TDZ
36961cb0ef41Sopenharmony_ci    // via 'super' calls.
36971cb0ef41Sopenharmony_ci    builder()->ThrowSuperAlreadyCalledIfNotHole();
36981cb0ef41Sopenharmony_ci  } else {
36991cb0ef41Sopenharmony_ci    // Perform an initialization check for let/const declared variables.
37001cb0ef41Sopenharmony_ci    // E.g. let x = (x = 20); is not allowed.
37011cb0ef41Sopenharmony_ci    DCHECK(IsLexicalVariableMode(variable->mode()));
37021cb0ef41Sopenharmony_ci    BuildThrowIfHole(variable);
37031cb0ef41Sopenharmony_ci  }
37041cb0ef41Sopenharmony_ci}
37051cb0ef41Sopenharmony_ci
37061cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildVariableAssignment(
37071cb0ef41Sopenharmony_ci    Variable* variable, Token::Value op, HoleCheckMode hole_check_mode,
37081cb0ef41Sopenharmony_ci    LookupHoistingMode lookup_hoisting_mode) {
37091cb0ef41Sopenharmony_ci  VariableMode mode = variable->mode();
37101cb0ef41Sopenharmony_ci  RegisterAllocationScope assignment_register_scope(this);
37111cb0ef41Sopenharmony_ci  BytecodeLabel end_label;
37121cb0ef41Sopenharmony_ci  switch (variable->location()) {
37131cb0ef41Sopenharmony_ci    case VariableLocation::PARAMETER:
37141cb0ef41Sopenharmony_ci    case VariableLocation::LOCAL: {
37151cb0ef41Sopenharmony_ci      Register destination;
37161cb0ef41Sopenharmony_ci      if (VariableLocation::PARAMETER == variable->location()) {
37171cb0ef41Sopenharmony_ci        if (variable->IsReceiver()) {
37181cb0ef41Sopenharmony_ci          destination = builder()->Receiver();
37191cb0ef41Sopenharmony_ci        } else {
37201cb0ef41Sopenharmony_ci          destination = builder()->Parameter(variable->index());
37211cb0ef41Sopenharmony_ci        }
37221cb0ef41Sopenharmony_ci      } else {
37231cb0ef41Sopenharmony_ci        destination = builder()->Local(variable->index());
37241cb0ef41Sopenharmony_ci      }
37251cb0ef41Sopenharmony_ci
37261cb0ef41Sopenharmony_ci      if (hole_check_mode == HoleCheckMode::kRequired) {
37271cb0ef41Sopenharmony_ci        // Load destination to check for hole.
37281cb0ef41Sopenharmony_ci        Register value_temp = register_allocator()->NewRegister();
37291cb0ef41Sopenharmony_ci        builder()
37301cb0ef41Sopenharmony_ci            ->StoreAccumulatorInRegister(value_temp)
37311cb0ef41Sopenharmony_ci            .LoadAccumulatorWithRegister(destination);
37321cb0ef41Sopenharmony_ci
37331cb0ef41Sopenharmony_ci        BuildHoleCheckForVariableAssignment(variable, op);
37341cb0ef41Sopenharmony_ci        builder()->LoadAccumulatorWithRegister(value_temp);
37351cb0ef41Sopenharmony_ci      }
37361cb0ef41Sopenharmony_ci
37371cb0ef41Sopenharmony_ci      if (mode != VariableMode::kConst || op == Token::INIT) {
37381cb0ef41Sopenharmony_ci        builder()->StoreAccumulatorInRegister(destination);
37391cb0ef41Sopenharmony_ci      } else if (variable->throw_on_const_assignment(language_mode())) {
37401cb0ef41Sopenharmony_ci        builder()->CallRuntime(Runtime::kThrowConstAssignError);
37411cb0ef41Sopenharmony_ci      }
37421cb0ef41Sopenharmony_ci      break;
37431cb0ef41Sopenharmony_ci    }
37441cb0ef41Sopenharmony_ci    case VariableLocation::UNALLOCATED: {
37451cb0ef41Sopenharmony_ci      BuildStoreGlobal(variable);
37461cb0ef41Sopenharmony_ci      break;
37471cb0ef41Sopenharmony_ci    }
37481cb0ef41Sopenharmony_ci    case VariableLocation::CONTEXT: {
37491cb0ef41Sopenharmony_ci      int depth = execution_context()->ContextChainDepth(variable->scope());
37501cb0ef41Sopenharmony_ci      ContextScope* context = execution_context()->Previous(depth);
37511cb0ef41Sopenharmony_ci      Register context_reg;
37521cb0ef41Sopenharmony_ci
37531cb0ef41Sopenharmony_ci      if (context) {
37541cb0ef41Sopenharmony_ci        context_reg = context->reg();
37551cb0ef41Sopenharmony_ci        depth = 0;
37561cb0ef41Sopenharmony_ci      } else {
37571cb0ef41Sopenharmony_ci        context_reg = execution_context()->reg();
37581cb0ef41Sopenharmony_ci      }
37591cb0ef41Sopenharmony_ci
37601cb0ef41Sopenharmony_ci      if (hole_check_mode == HoleCheckMode::kRequired) {
37611cb0ef41Sopenharmony_ci        // Load destination to check for hole.
37621cb0ef41Sopenharmony_ci        Register value_temp = register_allocator()->NewRegister();
37631cb0ef41Sopenharmony_ci        builder()
37641cb0ef41Sopenharmony_ci            ->StoreAccumulatorInRegister(value_temp)
37651cb0ef41Sopenharmony_ci            .LoadContextSlot(context_reg, variable->index(), depth,
37661cb0ef41Sopenharmony_ci                             BytecodeArrayBuilder::kMutableSlot);
37671cb0ef41Sopenharmony_ci
37681cb0ef41Sopenharmony_ci        BuildHoleCheckForVariableAssignment(variable, op);
37691cb0ef41Sopenharmony_ci        builder()->LoadAccumulatorWithRegister(value_temp);
37701cb0ef41Sopenharmony_ci      }
37711cb0ef41Sopenharmony_ci
37721cb0ef41Sopenharmony_ci      if (mode != VariableMode::kConst || op == Token::INIT) {
37731cb0ef41Sopenharmony_ci        builder()->StoreContextSlot(context_reg, variable->index(), depth);
37741cb0ef41Sopenharmony_ci      } else if (variable->throw_on_const_assignment(language_mode())) {
37751cb0ef41Sopenharmony_ci        builder()->CallRuntime(Runtime::kThrowConstAssignError);
37761cb0ef41Sopenharmony_ci      }
37771cb0ef41Sopenharmony_ci      break;
37781cb0ef41Sopenharmony_ci    }
37791cb0ef41Sopenharmony_ci    case VariableLocation::LOOKUP: {
37801cb0ef41Sopenharmony_ci      builder()->StoreLookupSlot(variable->raw_name(), language_mode(),
37811cb0ef41Sopenharmony_ci                                 lookup_hoisting_mode);
37821cb0ef41Sopenharmony_ci      break;
37831cb0ef41Sopenharmony_ci    }
37841cb0ef41Sopenharmony_ci    case VariableLocation::MODULE: {
37851cb0ef41Sopenharmony_ci      DCHECK(IsDeclaredVariableMode(mode));
37861cb0ef41Sopenharmony_ci
37871cb0ef41Sopenharmony_ci      if (mode == VariableMode::kConst && op != Token::INIT) {
37881cb0ef41Sopenharmony_ci        builder()->CallRuntime(Runtime::kThrowConstAssignError);
37891cb0ef41Sopenharmony_ci        break;
37901cb0ef41Sopenharmony_ci      }
37911cb0ef41Sopenharmony_ci
37921cb0ef41Sopenharmony_ci      // If we don't throw above, we know that we're dealing with an
37931cb0ef41Sopenharmony_ci      // export because imports are const and we do not generate initializing
37941cb0ef41Sopenharmony_ci      // assignments for them.
37951cb0ef41Sopenharmony_ci      DCHECK(variable->IsExport());
37961cb0ef41Sopenharmony_ci
37971cb0ef41Sopenharmony_ci      int depth = execution_context()->ContextChainDepth(variable->scope());
37981cb0ef41Sopenharmony_ci      if (hole_check_mode == HoleCheckMode::kRequired) {
37991cb0ef41Sopenharmony_ci        Register value_temp = register_allocator()->NewRegister();
38001cb0ef41Sopenharmony_ci        builder()
38011cb0ef41Sopenharmony_ci            ->StoreAccumulatorInRegister(value_temp)
38021cb0ef41Sopenharmony_ci            .LoadModuleVariable(variable->index(), depth);
38031cb0ef41Sopenharmony_ci        BuildHoleCheckForVariableAssignment(variable, op);
38041cb0ef41Sopenharmony_ci        builder()->LoadAccumulatorWithRegister(value_temp);
38051cb0ef41Sopenharmony_ci      }
38061cb0ef41Sopenharmony_ci      builder()->StoreModuleVariable(variable->index(), depth);
38071cb0ef41Sopenharmony_ci      break;
38081cb0ef41Sopenharmony_ci    }
38091cb0ef41Sopenharmony_ci    case VariableLocation::REPL_GLOBAL: {
38101cb0ef41Sopenharmony_ci      // A let or const declaration like 'let x = 7' is effectively translated
38111cb0ef41Sopenharmony_ci      // to:
38121cb0ef41Sopenharmony_ci      //   <top of the script>:
38131cb0ef41Sopenharmony_ci      //     ScriptContext.x = TheHole;
38141cb0ef41Sopenharmony_ci      //   ...
38151cb0ef41Sopenharmony_ci      //   <where the actual 'let' is>:
38161cb0ef41Sopenharmony_ci      //     ScriptContextTable.x = 7; // no hole check
38171cb0ef41Sopenharmony_ci      //
38181cb0ef41Sopenharmony_ci      // The ScriptContext slot for 'x' that we store to here is not
38191cb0ef41Sopenharmony_ci      // necessarily the ScriptContext of this script, but rather the
38201cb0ef41Sopenharmony_ci      // first ScriptContext that has a slot for name 'x'.
38211cb0ef41Sopenharmony_ci      DCHECK(variable->IsReplGlobal());
38221cb0ef41Sopenharmony_ci      if (op == Token::INIT) {
38231cb0ef41Sopenharmony_ci        RegisterList store_args = register_allocator()->NewRegisterList(2);
38241cb0ef41Sopenharmony_ci        builder()
38251cb0ef41Sopenharmony_ci            ->StoreAccumulatorInRegister(store_args[1])
38261cb0ef41Sopenharmony_ci            .LoadLiteral(variable->raw_name())
38271cb0ef41Sopenharmony_ci            .StoreAccumulatorInRegister(store_args[0]);
38281cb0ef41Sopenharmony_ci        builder()->CallRuntime(
38291cb0ef41Sopenharmony_ci            Runtime::kStoreGlobalNoHoleCheckForReplLetOrConst, store_args);
38301cb0ef41Sopenharmony_ci      } else {
38311cb0ef41Sopenharmony_ci        if (mode == VariableMode::kConst) {
38321cb0ef41Sopenharmony_ci          builder()->CallRuntime(Runtime::kThrowConstAssignError);
38331cb0ef41Sopenharmony_ci        } else {
38341cb0ef41Sopenharmony_ci          BuildStoreGlobal(variable);
38351cb0ef41Sopenharmony_ci        }
38361cb0ef41Sopenharmony_ci      }
38371cb0ef41Sopenharmony_ci      break;
38381cb0ef41Sopenharmony_ci    }
38391cb0ef41Sopenharmony_ci  }
38401cb0ef41Sopenharmony_ci}
38411cb0ef41Sopenharmony_ci
38421cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildLoadNamedProperty(const Expression* object_expr,
38431cb0ef41Sopenharmony_ci                                               Register object,
38441cb0ef41Sopenharmony_ci                                               const AstRawString* name) {
38451cb0ef41Sopenharmony_ci  FeedbackSlot slot = GetCachedLoadICSlot(object_expr, name);
38461cb0ef41Sopenharmony_ci  builder()->LoadNamedProperty(object, name, feedback_index(slot));
38471cb0ef41Sopenharmony_ci}
38481cb0ef41Sopenharmony_ci
38491cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildSetNamedProperty(const Expression* object_expr,
38501cb0ef41Sopenharmony_ci                                              Register object,
38511cb0ef41Sopenharmony_ci                                              const AstRawString* name) {
38521cb0ef41Sopenharmony_ci  Register value;
38531cb0ef41Sopenharmony_ci  if (!execution_result()->IsEffect()) {
38541cb0ef41Sopenharmony_ci    value = register_allocator()->NewRegister();
38551cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(value);
38561cb0ef41Sopenharmony_ci  }
38571cb0ef41Sopenharmony_ci
38581cb0ef41Sopenharmony_ci  FeedbackSlot slot = GetCachedStoreICSlot(object_expr, name);
38591cb0ef41Sopenharmony_ci  builder()->SetNamedProperty(object, name, feedback_index(slot),
38601cb0ef41Sopenharmony_ci                              language_mode());
38611cb0ef41Sopenharmony_ci
38621cb0ef41Sopenharmony_ci  if (!execution_result()->IsEffect()) {
38631cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(value);
38641cb0ef41Sopenharmony_ci  }
38651cb0ef41Sopenharmony_ci}
38661cb0ef41Sopenharmony_ci
38671cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildStoreGlobal(Variable* variable) {
38681cb0ef41Sopenharmony_ci  Register value;
38691cb0ef41Sopenharmony_ci  if (!execution_result()->IsEffect()) {
38701cb0ef41Sopenharmony_ci    value = register_allocator()->NewRegister();
38711cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(value);
38721cb0ef41Sopenharmony_ci  }
38731cb0ef41Sopenharmony_ci
38741cb0ef41Sopenharmony_ci  FeedbackSlot slot = GetCachedStoreGlobalICSlot(language_mode(), variable);
38751cb0ef41Sopenharmony_ci  builder()->StoreGlobal(variable->raw_name(), feedback_index(slot));
38761cb0ef41Sopenharmony_ci
38771cb0ef41Sopenharmony_ci  if (!execution_result()->IsEffect()) {
38781cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(value);
38791cb0ef41Sopenharmony_ci  }
38801cb0ef41Sopenharmony_ci}
38811cb0ef41Sopenharmony_ci
38821cb0ef41Sopenharmony_ci// static
38831cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData
38841cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData::NonProperty(Expression* expr) {
38851cb0ef41Sopenharmony_ci  return AssignmentLhsData(NON_PROPERTY, expr, RegisterList(), Register(),
38861cb0ef41Sopenharmony_ci                           Register(), nullptr, nullptr);
38871cb0ef41Sopenharmony_ci}
38881cb0ef41Sopenharmony_ci// static
38891cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData
38901cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData::NamedProperty(Expression* object_expr,
38911cb0ef41Sopenharmony_ci                                                    Register object,
38921cb0ef41Sopenharmony_ci                                                    const AstRawString* name) {
38931cb0ef41Sopenharmony_ci  return AssignmentLhsData(NAMED_PROPERTY, nullptr, RegisterList(), object,
38941cb0ef41Sopenharmony_ci                           Register(), object_expr, name);
38951cb0ef41Sopenharmony_ci}
38961cb0ef41Sopenharmony_ci// static
38971cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData
38981cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData::KeyedProperty(Register object,
38991cb0ef41Sopenharmony_ci                                                    Register key) {
39001cb0ef41Sopenharmony_ci  return AssignmentLhsData(KEYED_PROPERTY, nullptr, RegisterList(), object, key,
39011cb0ef41Sopenharmony_ci                           nullptr, nullptr);
39021cb0ef41Sopenharmony_ci}
39031cb0ef41Sopenharmony_ci// static
39041cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData
39051cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData::NamedSuperProperty(
39061cb0ef41Sopenharmony_ci    RegisterList super_property_args) {
39071cb0ef41Sopenharmony_ci  return AssignmentLhsData(NAMED_SUPER_PROPERTY, nullptr, super_property_args,
39081cb0ef41Sopenharmony_ci                           Register(), Register(), nullptr, nullptr);
39091cb0ef41Sopenharmony_ci}
39101cb0ef41Sopenharmony_ci// static
39111cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData
39121cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData::PrivateMethodOrAccessor(
39131cb0ef41Sopenharmony_ci    AssignType type, Property* property, Register object, Register key) {
39141cb0ef41Sopenharmony_ci  return AssignmentLhsData(type, property, RegisterList(), object, key, nullptr,
39151cb0ef41Sopenharmony_ci                           nullptr);
39161cb0ef41Sopenharmony_ci}
39171cb0ef41Sopenharmony_ci// static
39181cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData
39191cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData::KeyedSuperProperty(
39201cb0ef41Sopenharmony_ci    RegisterList super_property_args) {
39211cb0ef41Sopenharmony_ci  return AssignmentLhsData(KEYED_SUPER_PROPERTY, nullptr, super_property_args,
39221cb0ef41Sopenharmony_ci                           Register(), Register(), nullptr, nullptr);
39231cb0ef41Sopenharmony_ci}
39241cb0ef41Sopenharmony_ci
39251cb0ef41Sopenharmony_ciBytecodeGenerator::AssignmentLhsData BytecodeGenerator::PrepareAssignmentLhs(
39261cb0ef41Sopenharmony_ci    Expression* lhs, AccumulatorPreservingMode accumulator_preserving_mode) {
39271cb0ef41Sopenharmony_ci  // Left-hand side can only be a property, a global or a variable slot.
39281cb0ef41Sopenharmony_ci  Property* property = lhs->AsProperty();
39291cb0ef41Sopenharmony_ci  AssignType assign_type = Property::GetAssignType(property);
39301cb0ef41Sopenharmony_ci
39311cb0ef41Sopenharmony_ci  // Evaluate LHS expression.
39321cb0ef41Sopenharmony_ci  switch (assign_type) {
39331cb0ef41Sopenharmony_ci    case NON_PROPERTY:
39341cb0ef41Sopenharmony_ci      return AssignmentLhsData::NonProperty(lhs);
39351cb0ef41Sopenharmony_ci    case NAMED_PROPERTY: {
39361cb0ef41Sopenharmony_ci      AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
39371cb0ef41Sopenharmony_ci      Register object = VisitForRegisterValue(property->obj());
39381cb0ef41Sopenharmony_ci      const AstRawString* name =
39391cb0ef41Sopenharmony_ci          property->key()->AsLiteral()->AsRawPropertyName();
39401cb0ef41Sopenharmony_ci      return AssignmentLhsData::NamedProperty(property->obj(), object, name);
39411cb0ef41Sopenharmony_ci    }
39421cb0ef41Sopenharmony_ci    case KEYED_PROPERTY: {
39431cb0ef41Sopenharmony_ci      AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
39441cb0ef41Sopenharmony_ci      Register object = VisitForRegisterValue(property->obj());
39451cb0ef41Sopenharmony_ci      Register key = VisitForRegisterValue(property->key());
39461cb0ef41Sopenharmony_ci      return AssignmentLhsData::KeyedProperty(object, key);
39471cb0ef41Sopenharmony_ci    }
39481cb0ef41Sopenharmony_ci    case PRIVATE_METHOD:
39491cb0ef41Sopenharmony_ci    case PRIVATE_GETTER_ONLY:
39501cb0ef41Sopenharmony_ci    case PRIVATE_SETTER_ONLY:
39511cb0ef41Sopenharmony_ci    case PRIVATE_GETTER_AND_SETTER: {
39521cb0ef41Sopenharmony_ci      DCHECK(!property->IsSuperAccess());
39531cb0ef41Sopenharmony_ci      AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
39541cb0ef41Sopenharmony_ci      Register object = VisitForRegisterValue(property->obj());
39551cb0ef41Sopenharmony_ci      Register key = VisitForRegisterValue(property->key());
39561cb0ef41Sopenharmony_ci      return AssignmentLhsData::PrivateMethodOrAccessor(assign_type, property,
39571cb0ef41Sopenharmony_ci                                                        object, key);
39581cb0ef41Sopenharmony_ci    }
39591cb0ef41Sopenharmony_ci    case NAMED_SUPER_PROPERTY: {
39601cb0ef41Sopenharmony_ci      AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
39611cb0ef41Sopenharmony_ci      RegisterList super_property_args =
39621cb0ef41Sopenharmony_ci          register_allocator()->NewRegisterList(4);
39631cb0ef41Sopenharmony_ci      BuildThisVariableLoad();
39641cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(super_property_args[0]);
39651cb0ef41Sopenharmony_ci      BuildVariableLoad(
39661cb0ef41Sopenharmony_ci          property->obj()->AsSuperPropertyReference()->home_object()->var(),
39671cb0ef41Sopenharmony_ci          HoleCheckMode::kElided);
39681cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(super_property_args[1]);
39691cb0ef41Sopenharmony_ci      builder()
39701cb0ef41Sopenharmony_ci          ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
39711cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(super_property_args[2]);
39721cb0ef41Sopenharmony_ci      return AssignmentLhsData::NamedSuperProperty(super_property_args);
39731cb0ef41Sopenharmony_ci    }
39741cb0ef41Sopenharmony_ci    case KEYED_SUPER_PROPERTY: {
39751cb0ef41Sopenharmony_ci      AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
39761cb0ef41Sopenharmony_ci      RegisterList super_property_args =
39771cb0ef41Sopenharmony_ci          register_allocator()->NewRegisterList(4);
39781cb0ef41Sopenharmony_ci      BuildThisVariableLoad();
39791cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(super_property_args[0]);
39801cb0ef41Sopenharmony_ci      BuildVariableLoad(
39811cb0ef41Sopenharmony_ci          property->obj()->AsSuperPropertyReference()->home_object()->var(),
39821cb0ef41Sopenharmony_ci          HoleCheckMode::kElided);
39831cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(super_property_args[1]);
39841cb0ef41Sopenharmony_ci      VisitForRegisterValue(property->key(), super_property_args[2]);
39851cb0ef41Sopenharmony_ci      return AssignmentLhsData::KeyedSuperProperty(super_property_args);
39861cb0ef41Sopenharmony_ci    }
39871cb0ef41Sopenharmony_ci  }
39881cb0ef41Sopenharmony_ci  UNREACHABLE();
39891cb0ef41Sopenharmony_ci}
39901cb0ef41Sopenharmony_ci
39911cb0ef41Sopenharmony_ci// Build the iteration finalizer called in the finally block of an iteration
39921cb0ef41Sopenharmony_ci// protocol execution. This closes the iterator if needed, and suppresses any
39931cb0ef41Sopenharmony_ci// exception it throws if necessary, including the exception when the return
39941cb0ef41Sopenharmony_ci// method is not callable.
39951cb0ef41Sopenharmony_ci//
39961cb0ef41Sopenharmony_ci// In pseudo-code, this builds:
39971cb0ef41Sopenharmony_ci//
39981cb0ef41Sopenharmony_ci// if (!done) {
39991cb0ef41Sopenharmony_ci//   try {
40001cb0ef41Sopenharmony_ci//     let method = iterator.return
40011cb0ef41Sopenharmony_ci//     if (method !== null && method !== undefined) {
40021cb0ef41Sopenharmony_ci//       let return_val = method.call(iterator)
40031cb0ef41Sopenharmony_ci//       if (!%IsObject(return_val)) throw TypeError
40041cb0ef41Sopenharmony_ci//     }
40051cb0ef41Sopenharmony_ci//   } catch (e) {
40061cb0ef41Sopenharmony_ci//     if (iteration_continuation != RETHROW)
40071cb0ef41Sopenharmony_ci//       rethrow e
40081cb0ef41Sopenharmony_ci//   }
40091cb0ef41Sopenharmony_ci// }
40101cb0ef41Sopenharmony_ci//
40111cb0ef41Sopenharmony_ci// For async iterators, iterator.close() becomes await iterator.close().
40121cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildFinalizeIteration(
40131cb0ef41Sopenharmony_ci    IteratorRecord iterator, Register done,
40141cb0ef41Sopenharmony_ci    Register iteration_continuation_token) {
40151cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
40161cb0ef41Sopenharmony_ci  BytecodeLabels iterator_is_done(zone());
40171cb0ef41Sopenharmony_ci
40181cb0ef41Sopenharmony_ci  // if (!done) {
40191cb0ef41Sopenharmony_ci  builder()->LoadAccumulatorWithRegister(done).JumpIfTrue(
40201cb0ef41Sopenharmony_ci      ToBooleanMode::kConvertToBoolean, iterator_is_done.New());
40211cb0ef41Sopenharmony_ci
40221cb0ef41Sopenharmony_ci  {
40231cb0ef41Sopenharmony_ci    RegisterAllocationScope inner_register_scope(this);
40241cb0ef41Sopenharmony_ci    BuildTryCatch(
40251cb0ef41Sopenharmony_ci        // try {
40261cb0ef41Sopenharmony_ci        //   let method = iterator.return
40271cb0ef41Sopenharmony_ci        //   if (method !== null && method !== undefined) {
40281cb0ef41Sopenharmony_ci        //     let return_val = method.call(iterator)
40291cb0ef41Sopenharmony_ci        //     if (!%IsObject(return_val)) throw TypeError
40301cb0ef41Sopenharmony_ci        //   }
40311cb0ef41Sopenharmony_ci        // }
40321cb0ef41Sopenharmony_ci        [&]() {
40331cb0ef41Sopenharmony_ci          Register method = register_allocator()->NewRegister();
40341cb0ef41Sopenharmony_ci          builder()
40351cb0ef41Sopenharmony_ci              ->LoadNamedProperty(
40361cb0ef41Sopenharmony_ci                  iterator.object(), ast_string_constants()->return_string(),
40371cb0ef41Sopenharmony_ci                  feedback_index(feedback_spec()->AddLoadICSlot()))
40381cb0ef41Sopenharmony_ci              .JumpIfUndefinedOrNull(iterator_is_done.New())
40391cb0ef41Sopenharmony_ci              .StoreAccumulatorInRegister(method);
40401cb0ef41Sopenharmony_ci
40411cb0ef41Sopenharmony_ci          RegisterList args(iterator.object());
40421cb0ef41Sopenharmony_ci          builder()->CallProperty(
40431cb0ef41Sopenharmony_ci              method, args, feedback_index(feedback_spec()->AddCallICSlot()));
40441cb0ef41Sopenharmony_ci          if (iterator.type() == IteratorType::kAsync) {
40451cb0ef41Sopenharmony_ci            BuildAwait();
40461cb0ef41Sopenharmony_ci          }
40471cb0ef41Sopenharmony_ci          builder()->JumpIfJSReceiver(iterator_is_done.New());
40481cb0ef41Sopenharmony_ci          {
40491cb0ef41Sopenharmony_ci            // Throw this exception inside the try block so that it is
40501cb0ef41Sopenharmony_ci            // suppressed by the iteration continuation if necessary.
40511cb0ef41Sopenharmony_ci            RegisterAllocationScope register_scope(this);
40521cb0ef41Sopenharmony_ci            Register return_result = register_allocator()->NewRegister();
40531cb0ef41Sopenharmony_ci            builder()
40541cb0ef41Sopenharmony_ci                ->StoreAccumulatorInRegister(return_result)
40551cb0ef41Sopenharmony_ci                .CallRuntime(Runtime::kThrowIteratorResultNotAnObject,
40561cb0ef41Sopenharmony_ci                             return_result);
40571cb0ef41Sopenharmony_ci          }
40581cb0ef41Sopenharmony_ci        },
40591cb0ef41Sopenharmony_ci
40601cb0ef41Sopenharmony_ci        // catch (e) {
40611cb0ef41Sopenharmony_ci        //   if (iteration_continuation != RETHROW)
40621cb0ef41Sopenharmony_ci        //     rethrow e
40631cb0ef41Sopenharmony_ci        // }
40641cb0ef41Sopenharmony_ci        [&](Register context) {
40651cb0ef41Sopenharmony_ci          // Reuse context register to store the exception.
40661cb0ef41Sopenharmony_ci          Register close_exception = context;
40671cb0ef41Sopenharmony_ci          builder()->StoreAccumulatorInRegister(close_exception);
40681cb0ef41Sopenharmony_ci
40691cb0ef41Sopenharmony_ci          BytecodeLabel suppress_close_exception;
40701cb0ef41Sopenharmony_ci          builder()
40711cb0ef41Sopenharmony_ci              ->LoadLiteral(
40721cb0ef41Sopenharmony_ci                  Smi::FromInt(ControlScope::DeferredCommands::kRethrowToken))
40731cb0ef41Sopenharmony_ci              .CompareReference(iteration_continuation_token)
40741cb0ef41Sopenharmony_ci              .JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
40751cb0ef41Sopenharmony_ci                          &suppress_close_exception)
40761cb0ef41Sopenharmony_ci              .LoadAccumulatorWithRegister(close_exception)
40771cb0ef41Sopenharmony_ci              .ReThrow()
40781cb0ef41Sopenharmony_ci              .Bind(&suppress_close_exception);
40791cb0ef41Sopenharmony_ci        },
40801cb0ef41Sopenharmony_ci        HandlerTable::UNCAUGHT);
40811cb0ef41Sopenharmony_ci  }
40821cb0ef41Sopenharmony_ci
40831cb0ef41Sopenharmony_ci  iterator_is_done.Bind(builder());
40841cb0ef41Sopenharmony_ci}
40851cb0ef41Sopenharmony_ci
40861cb0ef41Sopenharmony_ci// Get the default value of a destructuring target. Will mutate the
40871cb0ef41Sopenharmony_ci// destructuring target expression if there is a default value.
40881cb0ef41Sopenharmony_ci//
40891cb0ef41Sopenharmony_ci// For
40901cb0ef41Sopenharmony_ci//   a = b
40911cb0ef41Sopenharmony_ci// in
40921cb0ef41Sopenharmony_ci//   let {a = b} = c
40931cb0ef41Sopenharmony_ci// returns b and mutates the input into a.
40941cb0ef41Sopenharmony_ciExpression* BytecodeGenerator::GetDestructuringDefaultValue(
40951cb0ef41Sopenharmony_ci    Expression** target) {
40961cb0ef41Sopenharmony_ci  Expression* default_value = nullptr;
40971cb0ef41Sopenharmony_ci  if ((*target)->IsAssignment()) {
40981cb0ef41Sopenharmony_ci    Assignment* default_init = (*target)->AsAssignment();
40991cb0ef41Sopenharmony_ci    DCHECK_EQ(default_init->op(), Token::ASSIGN);
41001cb0ef41Sopenharmony_ci    default_value = default_init->value();
41011cb0ef41Sopenharmony_ci    *target = default_init->target();
41021cb0ef41Sopenharmony_ci    DCHECK((*target)->IsValidReferenceExpression() || (*target)->IsPattern());
41031cb0ef41Sopenharmony_ci  }
41041cb0ef41Sopenharmony_ci  return default_value;
41051cb0ef41Sopenharmony_ci}
41061cb0ef41Sopenharmony_ci
41071cb0ef41Sopenharmony_ci// Convert a destructuring assignment to an array literal into a sequence of
41081cb0ef41Sopenharmony_ci// iterator accesses into the value being assigned (in the accumulator).
41091cb0ef41Sopenharmony_ci//
41101cb0ef41Sopenharmony_ci// [a().x, ...b] = accumulator
41111cb0ef41Sopenharmony_ci//
41121cb0ef41Sopenharmony_ci//   becomes
41131cb0ef41Sopenharmony_ci//
41141cb0ef41Sopenharmony_ci// iterator = %GetIterator(accumulator)
41151cb0ef41Sopenharmony_ci// try {
41161cb0ef41Sopenharmony_ci//
41171cb0ef41Sopenharmony_ci//   // Individual assignments read off the value from iterator.next() This gets
41181cb0ef41Sopenharmony_ci//   // repeated per destructuring element.
41191cb0ef41Sopenharmony_ci//   if (!done) {
41201cb0ef41Sopenharmony_ci//     // Make sure we are considered 'done' if .next(), .done or .value fail.
41211cb0ef41Sopenharmony_ci//     done = true
41221cb0ef41Sopenharmony_ci//     var next_result = iterator.next()
41231cb0ef41Sopenharmony_ci//     var tmp_done = next_result.done
41241cb0ef41Sopenharmony_ci//     if (!tmp_done) {
41251cb0ef41Sopenharmony_ci//       value = next_result.value
41261cb0ef41Sopenharmony_ci//       done = false
41271cb0ef41Sopenharmony_ci//     }
41281cb0ef41Sopenharmony_ci//   }
41291cb0ef41Sopenharmony_ci//   if (done)
41301cb0ef41Sopenharmony_ci//     value = undefined
41311cb0ef41Sopenharmony_ci//   a().x = value
41321cb0ef41Sopenharmony_ci//
41331cb0ef41Sopenharmony_ci//   // A spread receives the remaining items in the iterator.
41341cb0ef41Sopenharmony_ci//   var array = []
41351cb0ef41Sopenharmony_ci//   var index = 0
41361cb0ef41Sopenharmony_ci//   %FillArrayWithIterator(iterator, array, index, done)
41371cb0ef41Sopenharmony_ci//   done = true
41381cb0ef41Sopenharmony_ci//   b = array
41391cb0ef41Sopenharmony_ci//
41401cb0ef41Sopenharmony_ci// } catch(e) {
41411cb0ef41Sopenharmony_ci//   iteration_continuation = RETHROW
41421cb0ef41Sopenharmony_ci// } finally {
41431cb0ef41Sopenharmony_ci//   %FinalizeIteration(iterator, done, iteration_continuation)
41441cb0ef41Sopenharmony_ci// }
41451cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildDestructuringArrayAssignment(
41461cb0ef41Sopenharmony_ci    ArrayLiteral* pattern, Token::Value op,
41471cb0ef41Sopenharmony_ci    LookupHoistingMode lookup_hoisting_mode) {
41481cb0ef41Sopenharmony_ci  RegisterAllocationScope scope(this);
41491cb0ef41Sopenharmony_ci
41501cb0ef41Sopenharmony_ci  Register value = register_allocator()->NewRegister();
41511cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(value);
41521cb0ef41Sopenharmony_ci
41531cb0ef41Sopenharmony_ci  // Store the iterator in a dedicated register so that it can be closed on
41541cb0ef41Sopenharmony_ci  // exit, and the 'done' value in a dedicated register so that it can be
41551cb0ef41Sopenharmony_ci  // changed and accessed independently of the iteration result.
41561cb0ef41Sopenharmony_ci  IteratorRecord iterator = BuildGetIteratorRecord(IteratorType::kNormal);
41571cb0ef41Sopenharmony_ci  Register done = register_allocator()->NewRegister();
41581cb0ef41Sopenharmony_ci  builder()->LoadFalse();
41591cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(done);
41601cb0ef41Sopenharmony_ci
41611cb0ef41Sopenharmony_ci  BuildTryFinally(
41621cb0ef41Sopenharmony_ci      // Try block.
41631cb0ef41Sopenharmony_ci      [&]() {
41641cb0ef41Sopenharmony_ci        Register next_result = register_allocator()->NewRegister();
41651cb0ef41Sopenharmony_ci        FeedbackSlot next_value_load_slot = feedback_spec()->AddLoadICSlot();
41661cb0ef41Sopenharmony_ci        FeedbackSlot next_done_load_slot = feedback_spec()->AddLoadICSlot();
41671cb0ef41Sopenharmony_ci
41681cb0ef41Sopenharmony_ci        Spread* spread = nullptr;
41691cb0ef41Sopenharmony_ci        for (Expression* target : *pattern->values()) {
41701cb0ef41Sopenharmony_ci          if (target->IsSpread()) {
41711cb0ef41Sopenharmony_ci            spread = target->AsSpread();
41721cb0ef41Sopenharmony_ci            break;
41731cb0ef41Sopenharmony_ci          }
41741cb0ef41Sopenharmony_ci
41751cb0ef41Sopenharmony_ci          Expression* default_value = GetDestructuringDefaultValue(&target);
41761cb0ef41Sopenharmony_ci          if (!target->IsPattern()) {
41771cb0ef41Sopenharmony_ci            builder()->SetExpressionAsStatementPosition(target);
41781cb0ef41Sopenharmony_ci          }
41791cb0ef41Sopenharmony_ci
41801cb0ef41Sopenharmony_ci          AssignmentLhsData lhs_data = PrepareAssignmentLhs(target);
41811cb0ef41Sopenharmony_ci
41821cb0ef41Sopenharmony_ci          // if (!done) {
41831cb0ef41Sopenharmony_ci          //   // Make sure we are considered done if .next(), .done or .value
41841cb0ef41Sopenharmony_ci          //   // fail.
41851cb0ef41Sopenharmony_ci          //   done = true
41861cb0ef41Sopenharmony_ci          //   var next_result = iterator.next()
41871cb0ef41Sopenharmony_ci          //   var tmp_done = next_result.done
41881cb0ef41Sopenharmony_ci          //   if (!tmp_done) {
41891cb0ef41Sopenharmony_ci          //     value = next_result.value
41901cb0ef41Sopenharmony_ci          //     done = false
41911cb0ef41Sopenharmony_ci          //   }
41921cb0ef41Sopenharmony_ci          // }
41931cb0ef41Sopenharmony_ci          // if (done)
41941cb0ef41Sopenharmony_ci          //   value = undefined
41951cb0ef41Sopenharmony_ci          BytecodeLabels is_done(zone());
41961cb0ef41Sopenharmony_ci
41971cb0ef41Sopenharmony_ci          builder()->LoadAccumulatorWithRegister(done);
41981cb0ef41Sopenharmony_ci          builder()->JumpIfTrue(ToBooleanMode::kConvertToBoolean,
41991cb0ef41Sopenharmony_ci                                is_done.New());
42001cb0ef41Sopenharmony_ci
42011cb0ef41Sopenharmony_ci          builder()->LoadTrue().StoreAccumulatorInRegister(done);
42021cb0ef41Sopenharmony_ci          BuildIteratorNext(iterator, next_result);
42031cb0ef41Sopenharmony_ci          builder()
42041cb0ef41Sopenharmony_ci              ->LoadNamedProperty(next_result,
42051cb0ef41Sopenharmony_ci                                  ast_string_constants()->done_string(),
42061cb0ef41Sopenharmony_ci                                  feedback_index(next_done_load_slot))
42071cb0ef41Sopenharmony_ci              .JumpIfTrue(ToBooleanMode::kConvertToBoolean, is_done.New());
42081cb0ef41Sopenharmony_ci
42091cb0ef41Sopenharmony_ci          // Only do the assignment if this is not a hole (i.e. 'elided').
42101cb0ef41Sopenharmony_ci          if (!target->IsTheHoleLiteral()) {
42111cb0ef41Sopenharmony_ci            builder()
42121cb0ef41Sopenharmony_ci                ->LoadNamedProperty(next_result,
42131cb0ef41Sopenharmony_ci                                    ast_string_constants()->value_string(),
42141cb0ef41Sopenharmony_ci                                    feedback_index(next_value_load_slot))
42151cb0ef41Sopenharmony_ci                .StoreAccumulatorInRegister(next_result)
42161cb0ef41Sopenharmony_ci                .LoadFalse()
42171cb0ef41Sopenharmony_ci                .StoreAccumulatorInRegister(done)
42181cb0ef41Sopenharmony_ci                .LoadAccumulatorWithRegister(next_result);
42191cb0ef41Sopenharmony_ci
42201cb0ef41Sopenharmony_ci            // [<pattern> = <init>] = <value>
42211cb0ef41Sopenharmony_ci            //   becomes (roughly)
42221cb0ef41Sopenharmony_ci            // temp = <value>.next();
42231cb0ef41Sopenharmony_ci            // <pattern> = temp === undefined ? <init> : temp;
42241cb0ef41Sopenharmony_ci            BytecodeLabel do_assignment;
42251cb0ef41Sopenharmony_ci            if (default_value) {
42261cb0ef41Sopenharmony_ci              builder()->JumpIfNotUndefined(&do_assignment);
42271cb0ef41Sopenharmony_ci              // Since done == true => temp == undefined, jump directly to using
42281cb0ef41Sopenharmony_ci              // the default value for that case.
42291cb0ef41Sopenharmony_ci              is_done.Bind(builder());
42301cb0ef41Sopenharmony_ci              VisitForAccumulatorValue(default_value);
42311cb0ef41Sopenharmony_ci            } else {
42321cb0ef41Sopenharmony_ci              builder()->Jump(&do_assignment);
42331cb0ef41Sopenharmony_ci              is_done.Bind(builder());
42341cb0ef41Sopenharmony_ci              builder()->LoadUndefined();
42351cb0ef41Sopenharmony_ci            }
42361cb0ef41Sopenharmony_ci            builder()->Bind(&do_assignment);
42371cb0ef41Sopenharmony_ci
42381cb0ef41Sopenharmony_ci            BuildAssignment(lhs_data, op, lookup_hoisting_mode);
42391cb0ef41Sopenharmony_ci          } else {
42401cb0ef41Sopenharmony_ci            builder()->LoadFalse().StoreAccumulatorInRegister(done);
42411cb0ef41Sopenharmony_ci            DCHECK_EQ(lhs_data.assign_type(), NON_PROPERTY);
42421cb0ef41Sopenharmony_ci            is_done.Bind(builder());
42431cb0ef41Sopenharmony_ci          }
42441cb0ef41Sopenharmony_ci        }
42451cb0ef41Sopenharmony_ci
42461cb0ef41Sopenharmony_ci        if (spread) {
42471cb0ef41Sopenharmony_ci          RegisterAllocationScope scope(this);
42481cb0ef41Sopenharmony_ci          BytecodeLabel is_done;
42491cb0ef41Sopenharmony_ci
42501cb0ef41Sopenharmony_ci          // A spread is turned into a loop over the remainer of the iterator.
42511cb0ef41Sopenharmony_ci          Expression* target = spread->expression();
42521cb0ef41Sopenharmony_ci
42531cb0ef41Sopenharmony_ci          if (!target->IsPattern()) {
42541cb0ef41Sopenharmony_ci            builder()->SetExpressionAsStatementPosition(spread);
42551cb0ef41Sopenharmony_ci          }
42561cb0ef41Sopenharmony_ci
42571cb0ef41Sopenharmony_ci          AssignmentLhsData lhs_data = PrepareAssignmentLhs(target);
42581cb0ef41Sopenharmony_ci
42591cb0ef41Sopenharmony_ci          // var array = [];
42601cb0ef41Sopenharmony_ci          Register array = register_allocator()->NewRegister();
42611cb0ef41Sopenharmony_ci          builder()->CreateEmptyArrayLiteral(
42621cb0ef41Sopenharmony_ci              feedback_index(feedback_spec()->AddLiteralSlot()));
42631cb0ef41Sopenharmony_ci          builder()->StoreAccumulatorInRegister(array);
42641cb0ef41Sopenharmony_ci
42651cb0ef41Sopenharmony_ci          // If done, jump to assigning empty array
42661cb0ef41Sopenharmony_ci          builder()->LoadAccumulatorWithRegister(done);
42671cb0ef41Sopenharmony_ci          builder()->JumpIfTrue(ToBooleanMode::kConvertToBoolean, &is_done);
42681cb0ef41Sopenharmony_ci
42691cb0ef41Sopenharmony_ci          // var index = 0;
42701cb0ef41Sopenharmony_ci          Register index = register_allocator()->NewRegister();
42711cb0ef41Sopenharmony_ci          builder()->LoadLiteral(Smi::zero());
42721cb0ef41Sopenharmony_ci          builder()->StoreAccumulatorInRegister(index);
42731cb0ef41Sopenharmony_ci
42741cb0ef41Sopenharmony_ci          // Set done to true, since it's guaranteed to be true by the time the
42751cb0ef41Sopenharmony_ci          // array fill completes.
42761cb0ef41Sopenharmony_ci          builder()->LoadTrue().StoreAccumulatorInRegister(done);
42771cb0ef41Sopenharmony_ci
42781cb0ef41Sopenharmony_ci          // Fill the array with the iterator.
42791cb0ef41Sopenharmony_ci          FeedbackSlot element_slot =
42801cb0ef41Sopenharmony_ci              feedback_spec()->AddStoreInArrayLiteralICSlot();
42811cb0ef41Sopenharmony_ci          FeedbackSlot index_slot = feedback_spec()->AddBinaryOpICSlot();
42821cb0ef41Sopenharmony_ci          BuildFillArrayWithIterator(iterator, array, index, next_result,
42831cb0ef41Sopenharmony_ci                                     next_value_load_slot, next_done_load_slot,
42841cb0ef41Sopenharmony_ci                                     index_slot, element_slot);
42851cb0ef41Sopenharmony_ci
42861cb0ef41Sopenharmony_ci          builder()->Bind(&is_done);
42871cb0ef41Sopenharmony_ci          // Assign the array to the LHS.
42881cb0ef41Sopenharmony_ci          builder()->LoadAccumulatorWithRegister(array);
42891cb0ef41Sopenharmony_ci          BuildAssignment(lhs_data, op, lookup_hoisting_mode);
42901cb0ef41Sopenharmony_ci        }
42911cb0ef41Sopenharmony_ci      },
42921cb0ef41Sopenharmony_ci      // Finally block.
42931cb0ef41Sopenharmony_ci      [&](Register iteration_continuation_token) {
42941cb0ef41Sopenharmony_ci        // Finish the iteration in the finally block.
42951cb0ef41Sopenharmony_ci        BuildFinalizeIteration(iterator, done, iteration_continuation_token);
42961cb0ef41Sopenharmony_ci      },
42971cb0ef41Sopenharmony_ci      HandlerTable::UNCAUGHT);
42981cb0ef41Sopenharmony_ci
42991cb0ef41Sopenharmony_ci  if (!execution_result()->IsEffect()) {
43001cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(value);
43011cb0ef41Sopenharmony_ci  }
43021cb0ef41Sopenharmony_ci}
43031cb0ef41Sopenharmony_ci
43041cb0ef41Sopenharmony_ci// Convert a destructuring assignment to an object literal into a sequence of
43051cb0ef41Sopenharmony_ci// property accesses into the value being assigned (in the accumulator).
43061cb0ef41Sopenharmony_ci//
43071cb0ef41Sopenharmony_ci// { y, [x++]: a(), ...b.c } = value
43081cb0ef41Sopenharmony_ci//
43091cb0ef41Sopenharmony_ci//   becomes
43101cb0ef41Sopenharmony_ci//
43111cb0ef41Sopenharmony_ci// var rest_runtime_callargs = new Array(3);
43121cb0ef41Sopenharmony_ci// rest_runtime_callargs[0] = value;
43131cb0ef41Sopenharmony_ci//
43141cb0ef41Sopenharmony_ci// rest_runtime_callargs[1] = "y";
43151cb0ef41Sopenharmony_ci// y = value.y;
43161cb0ef41Sopenharmony_ci//
43171cb0ef41Sopenharmony_ci// var temp1 = %ToName(x++);
43181cb0ef41Sopenharmony_ci// rest_runtime_callargs[2] = temp1;
43191cb0ef41Sopenharmony_ci// a() = value[temp1];
43201cb0ef41Sopenharmony_ci//
43211cb0ef41Sopenharmony_ci// b.c =
43221cb0ef41Sopenharmony_ci// %CopyDataPropertiesWithExcludedPropertiesOnStack.call(rest_runtime_callargs);
43231cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildDestructuringObjectAssignment(
43241cb0ef41Sopenharmony_ci    ObjectLiteral* pattern, Token::Value op,
43251cb0ef41Sopenharmony_ci    LookupHoistingMode lookup_hoisting_mode) {
43261cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
43271cb0ef41Sopenharmony_ci
43281cb0ef41Sopenharmony_ci  // Store the assignment value in a register.
43291cb0ef41Sopenharmony_ci  Register value;
43301cb0ef41Sopenharmony_ci  RegisterList rest_runtime_callargs;
43311cb0ef41Sopenharmony_ci  if (pattern->builder()->has_rest_property()) {
43321cb0ef41Sopenharmony_ci    rest_runtime_callargs =
43331cb0ef41Sopenharmony_ci        register_allocator()->NewRegisterList(pattern->properties()->length());
43341cb0ef41Sopenharmony_ci    value = rest_runtime_callargs[0];
43351cb0ef41Sopenharmony_ci  } else {
43361cb0ef41Sopenharmony_ci    value = register_allocator()->NewRegister();
43371cb0ef41Sopenharmony_ci  }
43381cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(value);
43391cb0ef41Sopenharmony_ci
43401cb0ef41Sopenharmony_ci  // if (value === null || value === undefined)
43411cb0ef41Sopenharmony_ci  //   throw new TypeError(kNonCoercible);
43421cb0ef41Sopenharmony_ci  //
43431cb0ef41Sopenharmony_ci  // Since the first property access on null/undefined will also trigger a
43441cb0ef41Sopenharmony_ci  // TypeError, we can elide this check. The exception is when there are no
43451cb0ef41Sopenharmony_ci  // properties and no rest property (this is an empty literal), or when the
43461cb0ef41Sopenharmony_ci  // first property is a computed name and accessing it can have side effects.
43471cb0ef41Sopenharmony_ci  //
43481cb0ef41Sopenharmony_ci  // TODO(leszeks): Also eliminate this check if the value is known to be
43491cb0ef41Sopenharmony_ci  // non-null (e.g. an object literal).
43501cb0ef41Sopenharmony_ci  if (pattern->properties()->is_empty() ||
43511cb0ef41Sopenharmony_ci      (pattern->properties()->at(0)->is_computed_name() &&
43521cb0ef41Sopenharmony_ci       pattern->properties()->at(0)->kind() != ObjectLiteralProperty::SPREAD)) {
43531cb0ef41Sopenharmony_ci    BytecodeLabel is_null_or_undefined, not_null_or_undefined;
43541cb0ef41Sopenharmony_ci    builder()
43551cb0ef41Sopenharmony_ci        ->JumpIfUndefinedOrNull(&is_null_or_undefined)
43561cb0ef41Sopenharmony_ci        .Jump(&not_null_or_undefined);
43571cb0ef41Sopenharmony_ci
43581cb0ef41Sopenharmony_ci    {
43591cb0ef41Sopenharmony_ci      builder()->Bind(&is_null_or_undefined);
43601cb0ef41Sopenharmony_ci      builder()->SetExpressionPosition(pattern);
43611cb0ef41Sopenharmony_ci      builder()->CallRuntime(Runtime::kThrowPatternAssignmentNonCoercible,
43621cb0ef41Sopenharmony_ci                             value);
43631cb0ef41Sopenharmony_ci    }
43641cb0ef41Sopenharmony_ci    builder()->Bind(&not_null_or_undefined);
43651cb0ef41Sopenharmony_ci  }
43661cb0ef41Sopenharmony_ci
43671cb0ef41Sopenharmony_ci  int i = 0;
43681cb0ef41Sopenharmony_ci  for (ObjectLiteralProperty* pattern_property : *pattern->properties()) {
43691cb0ef41Sopenharmony_ci    RegisterAllocationScope inner_register_scope(this);
43701cb0ef41Sopenharmony_ci
43711cb0ef41Sopenharmony_ci    // The key of the pattern becomes the key into the RHS value, and the value
43721cb0ef41Sopenharmony_ci    // of the pattern becomes the target of the assignment.
43731cb0ef41Sopenharmony_ci    //
43741cb0ef41Sopenharmony_ci    // e.g. { a: b } = o becomes b = o.a
43751cb0ef41Sopenharmony_ci    Expression* pattern_key = pattern_property->key();
43761cb0ef41Sopenharmony_ci    Expression* target = pattern_property->value();
43771cb0ef41Sopenharmony_ci    Expression* default_value = GetDestructuringDefaultValue(&target);
43781cb0ef41Sopenharmony_ci
43791cb0ef41Sopenharmony_ci    if (!target->IsPattern()) {
43801cb0ef41Sopenharmony_ci      builder()->SetExpressionAsStatementPosition(target);
43811cb0ef41Sopenharmony_ci    }
43821cb0ef41Sopenharmony_ci
43831cb0ef41Sopenharmony_ci    // Calculate this property's key into the assignment RHS value, additionally
43841cb0ef41Sopenharmony_ci    // storing the key for rest_runtime_callargs if needed.
43851cb0ef41Sopenharmony_ci    //
43861cb0ef41Sopenharmony_ci    // The RHS is accessed using the key either by LoadNamedProperty (if
43871cb0ef41Sopenharmony_ci    // value_name is valid) or by LoadKeyedProperty (otherwise).
43881cb0ef41Sopenharmony_ci    const AstRawString* value_name = nullptr;
43891cb0ef41Sopenharmony_ci    Register value_key;
43901cb0ef41Sopenharmony_ci
43911cb0ef41Sopenharmony_ci    if (pattern_property->kind() != ObjectLiteralProperty::Kind::SPREAD) {
43921cb0ef41Sopenharmony_ci      if (pattern_key->IsPropertyName()) {
43931cb0ef41Sopenharmony_ci        value_name = pattern_key->AsLiteral()->AsRawPropertyName();
43941cb0ef41Sopenharmony_ci      }
43951cb0ef41Sopenharmony_ci      if (pattern->builder()->has_rest_property() || !value_name) {
43961cb0ef41Sopenharmony_ci        if (pattern->builder()->has_rest_property()) {
43971cb0ef41Sopenharmony_ci          value_key = rest_runtime_callargs[i + 1];
43981cb0ef41Sopenharmony_ci        } else {
43991cb0ef41Sopenharmony_ci          value_key = register_allocator()->NewRegister();
44001cb0ef41Sopenharmony_ci        }
44011cb0ef41Sopenharmony_ci        if (pattern_property->is_computed_name()) {
44021cb0ef41Sopenharmony_ci          // { [a()]: b().x } = c
44031cb0ef41Sopenharmony_ci          // becomes
44041cb0ef41Sopenharmony_ci          // var tmp = a()
44051cb0ef41Sopenharmony_ci          // b().x = c[tmp]
44061cb0ef41Sopenharmony_ci          DCHECK(!pattern_key->IsPropertyName() ||
44071cb0ef41Sopenharmony_ci                 !pattern_key->IsNumberLiteral());
44081cb0ef41Sopenharmony_ci          VisitForAccumulatorValue(pattern_key);
44091cb0ef41Sopenharmony_ci          builder()->ToName(value_key);
44101cb0ef41Sopenharmony_ci        } else {
44111cb0ef41Sopenharmony_ci          // We only need the key for non-computed properties when it is numeric
44121cb0ef41Sopenharmony_ci          // or is being saved for the rest_runtime_callargs.
44131cb0ef41Sopenharmony_ci          DCHECK(pattern_key->IsNumberLiteral() ||
44141cb0ef41Sopenharmony_ci                 (pattern->builder()->has_rest_property() &&
44151cb0ef41Sopenharmony_ci                  pattern_key->IsPropertyName()));
44161cb0ef41Sopenharmony_ci          VisitForRegisterValue(pattern_key, value_key);
44171cb0ef41Sopenharmony_ci        }
44181cb0ef41Sopenharmony_ci      }
44191cb0ef41Sopenharmony_ci    }
44201cb0ef41Sopenharmony_ci
44211cb0ef41Sopenharmony_ci    AssignmentLhsData lhs_data = PrepareAssignmentLhs(target);
44221cb0ef41Sopenharmony_ci
44231cb0ef41Sopenharmony_ci    // Get the value from the RHS.
44241cb0ef41Sopenharmony_ci    if (pattern_property->kind() == ObjectLiteralProperty::Kind::SPREAD) {
44251cb0ef41Sopenharmony_ci      DCHECK_EQ(i, pattern->properties()->length() - 1);
44261cb0ef41Sopenharmony_ci      DCHECK(!value_key.is_valid());
44271cb0ef41Sopenharmony_ci      DCHECK_NULL(value_name);
44281cb0ef41Sopenharmony_ci      builder()->CallRuntime(
44291cb0ef41Sopenharmony_ci          Runtime::kInlineCopyDataPropertiesWithExcludedPropertiesOnStack,
44301cb0ef41Sopenharmony_ci          rest_runtime_callargs);
44311cb0ef41Sopenharmony_ci    } else if (value_name) {
44321cb0ef41Sopenharmony_ci      builder()->LoadNamedProperty(
44331cb0ef41Sopenharmony_ci          value, value_name, feedback_index(feedback_spec()->AddLoadICSlot()));
44341cb0ef41Sopenharmony_ci    } else {
44351cb0ef41Sopenharmony_ci      DCHECK(value_key.is_valid());
44361cb0ef41Sopenharmony_ci      builder()->LoadAccumulatorWithRegister(value_key).LoadKeyedProperty(
44371cb0ef41Sopenharmony_ci          value, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
44381cb0ef41Sopenharmony_ci    }
44391cb0ef41Sopenharmony_ci
44401cb0ef41Sopenharmony_ci    // {<pattern> = <init>} = <value>
44411cb0ef41Sopenharmony_ci    //   becomes
44421cb0ef41Sopenharmony_ci    // temp = <value>;
44431cb0ef41Sopenharmony_ci    // <pattern> = temp === undefined ? <init> : temp;
44441cb0ef41Sopenharmony_ci    if (default_value) {
44451cb0ef41Sopenharmony_ci      BytecodeLabel value_not_undefined;
44461cb0ef41Sopenharmony_ci      builder()->JumpIfNotUndefined(&value_not_undefined);
44471cb0ef41Sopenharmony_ci      VisitForAccumulatorValue(default_value);
44481cb0ef41Sopenharmony_ci      builder()->Bind(&value_not_undefined);
44491cb0ef41Sopenharmony_ci    }
44501cb0ef41Sopenharmony_ci
44511cb0ef41Sopenharmony_ci    BuildAssignment(lhs_data, op, lookup_hoisting_mode);
44521cb0ef41Sopenharmony_ci
44531cb0ef41Sopenharmony_ci    i++;
44541cb0ef41Sopenharmony_ci  }
44551cb0ef41Sopenharmony_ci
44561cb0ef41Sopenharmony_ci  if (!execution_result()->IsEffect()) {
44571cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(value);
44581cb0ef41Sopenharmony_ci  }
44591cb0ef41Sopenharmony_ci}
44601cb0ef41Sopenharmony_ci
44611cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildAssignment(
44621cb0ef41Sopenharmony_ci    const AssignmentLhsData& lhs_data, Token::Value op,
44631cb0ef41Sopenharmony_ci    LookupHoistingMode lookup_hoisting_mode) {
44641cb0ef41Sopenharmony_ci  // Assign the value to the LHS.
44651cb0ef41Sopenharmony_ci  switch (lhs_data.assign_type()) {
44661cb0ef41Sopenharmony_ci    case NON_PROPERTY: {
44671cb0ef41Sopenharmony_ci      if (ObjectLiteral* pattern_as_object =
44681cb0ef41Sopenharmony_ci              lhs_data.expr()->AsObjectLiteral()) {
44691cb0ef41Sopenharmony_ci        // Split object literals into destructuring.
44701cb0ef41Sopenharmony_ci        BuildDestructuringObjectAssignment(pattern_as_object, op,
44711cb0ef41Sopenharmony_ci                                           lookup_hoisting_mode);
44721cb0ef41Sopenharmony_ci      } else if (ArrayLiteral* pattern_as_array =
44731cb0ef41Sopenharmony_ci                     lhs_data.expr()->AsArrayLiteral()) {
44741cb0ef41Sopenharmony_ci        // Split object literals into destructuring.
44751cb0ef41Sopenharmony_ci        BuildDestructuringArrayAssignment(pattern_as_array, op,
44761cb0ef41Sopenharmony_ci                                          lookup_hoisting_mode);
44771cb0ef41Sopenharmony_ci      } else {
44781cb0ef41Sopenharmony_ci        DCHECK(lhs_data.expr()->IsVariableProxy());
44791cb0ef41Sopenharmony_ci        VariableProxy* proxy = lhs_data.expr()->AsVariableProxy();
44801cb0ef41Sopenharmony_ci        BuildVariableAssignment(proxy->var(), op, proxy->hole_check_mode(),
44811cb0ef41Sopenharmony_ci                                lookup_hoisting_mode);
44821cb0ef41Sopenharmony_ci      }
44831cb0ef41Sopenharmony_ci      break;
44841cb0ef41Sopenharmony_ci    }
44851cb0ef41Sopenharmony_ci    case NAMED_PROPERTY: {
44861cb0ef41Sopenharmony_ci      BuildSetNamedProperty(lhs_data.object_expr(), lhs_data.object(),
44871cb0ef41Sopenharmony_ci                            lhs_data.name());
44881cb0ef41Sopenharmony_ci      break;
44891cb0ef41Sopenharmony_ci    }
44901cb0ef41Sopenharmony_ci    case KEYED_PROPERTY: {
44911cb0ef41Sopenharmony_ci      FeedbackSlot slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
44921cb0ef41Sopenharmony_ci      Register value;
44931cb0ef41Sopenharmony_ci      if (!execution_result()->IsEffect()) {
44941cb0ef41Sopenharmony_ci        value = register_allocator()->NewRegister();
44951cb0ef41Sopenharmony_ci        builder()->StoreAccumulatorInRegister(value);
44961cb0ef41Sopenharmony_ci      }
44971cb0ef41Sopenharmony_ci      builder()->SetKeyedProperty(lhs_data.object(), lhs_data.key(),
44981cb0ef41Sopenharmony_ci                                  feedback_index(slot), language_mode());
44991cb0ef41Sopenharmony_ci      if (!execution_result()->IsEffect()) {
45001cb0ef41Sopenharmony_ci        builder()->LoadAccumulatorWithRegister(value);
45011cb0ef41Sopenharmony_ci      }
45021cb0ef41Sopenharmony_ci      break;
45031cb0ef41Sopenharmony_ci    }
45041cb0ef41Sopenharmony_ci    case NAMED_SUPER_PROPERTY: {
45051cb0ef41Sopenharmony_ci      builder()
45061cb0ef41Sopenharmony_ci          ->StoreAccumulatorInRegister(lhs_data.super_property_args()[3])
45071cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kStoreToSuper, lhs_data.super_property_args());
45081cb0ef41Sopenharmony_ci      break;
45091cb0ef41Sopenharmony_ci    }
45101cb0ef41Sopenharmony_ci    case KEYED_SUPER_PROPERTY: {
45111cb0ef41Sopenharmony_ci      builder()
45121cb0ef41Sopenharmony_ci          ->StoreAccumulatorInRegister(lhs_data.super_property_args()[3])
45131cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kStoreKeyedToSuper,
45141cb0ef41Sopenharmony_ci                       lhs_data.super_property_args());
45151cb0ef41Sopenharmony_ci      break;
45161cb0ef41Sopenharmony_ci    }
45171cb0ef41Sopenharmony_ci    case PRIVATE_METHOD: {
45181cb0ef41Sopenharmony_ci      Property* property = lhs_data.expr()->AsProperty();
45191cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, lhs_data.object());
45201cb0ef41Sopenharmony_ci      BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateMethodWrite,
45211cb0ef41Sopenharmony_ci                                 lhs_data.expr()->AsProperty());
45221cb0ef41Sopenharmony_ci      break;
45231cb0ef41Sopenharmony_ci    }
45241cb0ef41Sopenharmony_ci    case PRIVATE_GETTER_ONLY: {
45251cb0ef41Sopenharmony_ci      Property* property = lhs_data.expr()->AsProperty();
45261cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, lhs_data.object());
45271cb0ef41Sopenharmony_ci      BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateSetterAccess,
45281cb0ef41Sopenharmony_ci                                 lhs_data.expr()->AsProperty());
45291cb0ef41Sopenharmony_ci      break;
45301cb0ef41Sopenharmony_ci    }
45311cb0ef41Sopenharmony_ci    case PRIVATE_SETTER_ONLY:
45321cb0ef41Sopenharmony_ci    case PRIVATE_GETTER_AND_SETTER: {
45331cb0ef41Sopenharmony_ci      Register value = register_allocator()->NewRegister();
45341cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(value);
45351cb0ef41Sopenharmony_ci      Property* property = lhs_data.expr()->AsProperty();
45361cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, lhs_data.object());
45371cb0ef41Sopenharmony_ci      BuildPrivateSetterAccess(lhs_data.object(), lhs_data.key(), value);
45381cb0ef41Sopenharmony_ci      if (!execution_result()->IsEffect()) {
45391cb0ef41Sopenharmony_ci        builder()->LoadAccumulatorWithRegister(value);
45401cb0ef41Sopenharmony_ci      }
45411cb0ef41Sopenharmony_ci      break;
45421cb0ef41Sopenharmony_ci    }
45431cb0ef41Sopenharmony_ci  }
45441cb0ef41Sopenharmony_ci}
45451cb0ef41Sopenharmony_ci
45461cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitAssignment(Assignment* expr) {
45471cb0ef41Sopenharmony_ci  AssignmentLhsData lhs_data = PrepareAssignmentLhs(expr->target());
45481cb0ef41Sopenharmony_ci
45491cb0ef41Sopenharmony_ci  VisitForAccumulatorValue(expr->value());
45501cb0ef41Sopenharmony_ci
45511cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(expr);
45521cb0ef41Sopenharmony_ci  BuildAssignment(lhs_data, expr->op(), expr->lookup_hoisting_mode());
45531cb0ef41Sopenharmony_ci}
45541cb0ef41Sopenharmony_ci
45551cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitCompoundAssignment(CompoundAssignment* expr) {
45561cb0ef41Sopenharmony_ci  AssignmentLhsData lhs_data = PrepareAssignmentLhs(expr->target());
45571cb0ef41Sopenharmony_ci
45581cb0ef41Sopenharmony_ci  // Evaluate the value and potentially handle compound assignments by loading
45591cb0ef41Sopenharmony_ci  // the left-hand side value and performing a binary operation.
45601cb0ef41Sopenharmony_ci  switch (lhs_data.assign_type()) {
45611cb0ef41Sopenharmony_ci    case NON_PROPERTY: {
45621cb0ef41Sopenharmony_ci      VariableProxy* proxy = expr->target()->AsVariableProxy();
45631cb0ef41Sopenharmony_ci      BuildVariableLoad(proxy->var(), proxy->hole_check_mode());
45641cb0ef41Sopenharmony_ci      break;
45651cb0ef41Sopenharmony_ci    }
45661cb0ef41Sopenharmony_ci    case NAMED_PROPERTY: {
45671cb0ef41Sopenharmony_ci      BuildLoadNamedProperty(lhs_data.object_expr(), lhs_data.object(),
45681cb0ef41Sopenharmony_ci                             lhs_data.name());
45691cb0ef41Sopenharmony_ci      break;
45701cb0ef41Sopenharmony_ci    }
45711cb0ef41Sopenharmony_ci    case KEYED_PROPERTY: {
45721cb0ef41Sopenharmony_ci      FeedbackSlot slot = feedback_spec()->AddKeyedLoadICSlot();
45731cb0ef41Sopenharmony_ci      builder()
45741cb0ef41Sopenharmony_ci          ->LoadAccumulatorWithRegister(lhs_data.key())
45751cb0ef41Sopenharmony_ci          .LoadKeyedProperty(lhs_data.object(), feedback_index(slot));
45761cb0ef41Sopenharmony_ci      break;
45771cb0ef41Sopenharmony_ci    }
45781cb0ef41Sopenharmony_ci    case NAMED_SUPER_PROPERTY: {
45791cb0ef41Sopenharmony_ci      builder()->CallRuntime(Runtime::kLoadFromSuper,
45801cb0ef41Sopenharmony_ci                             lhs_data.super_property_args().Truncate(3));
45811cb0ef41Sopenharmony_ci      break;
45821cb0ef41Sopenharmony_ci    }
45831cb0ef41Sopenharmony_ci    case KEYED_SUPER_PROPERTY: {
45841cb0ef41Sopenharmony_ci      builder()->CallRuntime(Runtime::kLoadKeyedFromSuper,
45851cb0ef41Sopenharmony_ci                             lhs_data.super_property_args().Truncate(3));
45861cb0ef41Sopenharmony_ci      break;
45871cb0ef41Sopenharmony_ci    }
45881cb0ef41Sopenharmony_ci    // BuildAssignment() will throw an error about the private method being
45891cb0ef41Sopenharmony_ci    // read-only.
45901cb0ef41Sopenharmony_ci    case PRIVATE_METHOD: {
45911cb0ef41Sopenharmony_ci      Property* property = lhs_data.expr()->AsProperty();
45921cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, lhs_data.object());
45931cb0ef41Sopenharmony_ci      builder()->LoadAccumulatorWithRegister(lhs_data.key());
45941cb0ef41Sopenharmony_ci      break;
45951cb0ef41Sopenharmony_ci    }
45961cb0ef41Sopenharmony_ci    // For read-only properties, BuildAssignment() will throw an error about
45971cb0ef41Sopenharmony_ci    // the missing setter.
45981cb0ef41Sopenharmony_ci    case PRIVATE_GETTER_ONLY:
45991cb0ef41Sopenharmony_ci    case PRIVATE_GETTER_AND_SETTER: {
46001cb0ef41Sopenharmony_ci      Property* property = lhs_data.expr()->AsProperty();
46011cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, lhs_data.object());
46021cb0ef41Sopenharmony_ci      BuildPrivateGetterAccess(lhs_data.object(), lhs_data.key());
46031cb0ef41Sopenharmony_ci      break;
46041cb0ef41Sopenharmony_ci    }
46051cb0ef41Sopenharmony_ci    case PRIVATE_SETTER_ONLY: {
46061cb0ef41Sopenharmony_ci      // The property access is invalid, but if the brand check fails too, we
46071cb0ef41Sopenharmony_ci      // need to return the error from the brand check.
46081cb0ef41Sopenharmony_ci      Property* property = lhs_data.expr()->AsProperty();
46091cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, lhs_data.object());
46101cb0ef41Sopenharmony_ci      BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateGetterAccess,
46111cb0ef41Sopenharmony_ci                                 lhs_data.expr()->AsProperty());
46121cb0ef41Sopenharmony_ci      break;
46131cb0ef41Sopenharmony_ci    }
46141cb0ef41Sopenharmony_ci  }
46151cb0ef41Sopenharmony_ci
46161cb0ef41Sopenharmony_ci  BinaryOperation* binop = expr->binary_operation();
46171cb0ef41Sopenharmony_ci  FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
46181cb0ef41Sopenharmony_ci  BytecodeLabel short_circuit;
46191cb0ef41Sopenharmony_ci  if (binop->op() == Token::NULLISH) {
46201cb0ef41Sopenharmony_ci    BytecodeLabel nullish;
46211cb0ef41Sopenharmony_ci    builder()
46221cb0ef41Sopenharmony_ci        ->JumpIfUndefinedOrNull(&nullish)
46231cb0ef41Sopenharmony_ci        .Jump(&short_circuit)
46241cb0ef41Sopenharmony_ci        .Bind(&nullish);
46251cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->value());
46261cb0ef41Sopenharmony_ci  } else if (binop->op() == Token::OR) {
46271cb0ef41Sopenharmony_ci    builder()->JumpIfTrue(ToBooleanMode::kConvertToBoolean, &short_circuit);
46281cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->value());
46291cb0ef41Sopenharmony_ci  } else if (binop->op() == Token::AND) {
46301cb0ef41Sopenharmony_ci    builder()->JumpIfFalse(ToBooleanMode::kConvertToBoolean, &short_circuit);
46311cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->value());
46321cb0ef41Sopenharmony_ci  } else if (expr->value()->IsSmiLiteral()) {
46331cb0ef41Sopenharmony_ci    builder()->BinaryOperationSmiLiteral(
46341cb0ef41Sopenharmony_ci        binop->op(), expr->value()->AsLiteral()->AsSmiLiteral(),
46351cb0ef41Sopenharmony_ci        feedback_index(slot));
46361cb0ef41Sopenharmony_ci  } else {
46371cb0ef41Sopenharmony_ci    Register old_value = register_allocator()->NewRegister();
46381cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(old_value);
46391cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->value());
46401cb0ef41Sopenharmony_ci    builder()->BinaryOperation(binop->op(), old_value, feedback_index(slot));
46411cb0ef41Sopenharmony_ci  }
46421cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(expr);
46431cb0ef41Sopenharmony_ci
46441cb0ef41Sopenharmony_ci  BuildAssignment(lhs_data, expr->op(), expr->lookup_hoisting_mode());
46451cb0ef41Sopenharmony_ci  builder()->Bind(&short_circuit);
46461cb0ef41Sopenharmony_ci}
46471cb0ef41Sopenharmony_ci
46481cb0ef41Sopenharmony_ci// Suspends the generator to resume at the next suspend_id, with output stored
46491cb0ef41Sopenharmony_ci// in the accumulator. When the generator is resumed, the sent value is loaded
46501cb0ef41Sopenharmony_ci// in the accumulator.
46511cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildSuspendPoint(int position) {
46521cb0ef41Sopenharmony_ci  // Because we eliminate jump targets in dead code, we also eliminate resumes
46531cb0ef41Sopenharmony_ci  // when the suspend is not emitted because otherwise the below call to Bind
46541cb0ef41Sopenharmony_ci  // would start a new basic block and the code would be considered alive.
46551cb0ef41Sopenharmony_ci  if (builder()->RemainderOfBlockIsDead()) {
46561cb0ef41Sopenharmony_ci    return;
46571cb0ef41Sopenharmony_ci  }
46581cb0ef41Sopenharmony_ci  const int suspend_id = suspend_count_++;
46591cb0ef41Sopenharmony_ci
46601cb0ef41Sopenharmony_ci  RegisterList registers = register_allocator()->AllLiveRegisters();
46611cb0ef41Sopenharmony_ci
46621cb0ef41Sopenharmony_ci  // Save context, registers, and state. This bytecode then returns the value
46631cb0ef41Sopenharmony_ci  // in the accumulator.
46641cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(position);
46651cb0ef41Sopenharmony_ci  builder()->SuspendGenerator(generator_object(), registers, suspend_id);
46661cb0ef41Sopenharmony_ci
46671cb0ef41Sopenharmony_ci  // Upon resume, we continue here.
46681cb0ef41Sopenharmony_ci  builder()->Bind(generator_jump_table_, suspend_id);
46691cb0ef41Sopenharmony_ci
46701cb0ef41Sopenharmony_ci  // Clobbers all registers and sets the accumulator to the
46711cb0ef41Sopenharmony_ci  // [[input_or_debug_pos]] slot of the generator object.
46721cb0ef41Sopenharmony_ci  builder()->ResumeGenerator(generator_object(), registers);
46731cb0ef41Sopenharmony_ci}
46741cb0ef41Sopenharmony_ci
46751cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitYield(Yield* expr) {
46761cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(expr);
46771cb0ef41Sopenharmony_ci  VisitForAccumulatorValue(expr->expression());
46781cb0ef41Sopenharmony_ci
46791cb0ef41Sopenharmony_ci  // If this is not the first yield
46801cb0ef41Sopenharmony_ci  if (suspend_count_ > 0) {
46811cb0ef41Sopenharmony_ci    if (IsAsyncGeneratorFunction(function_kind())) {
46821cb0ef41Sopenharmony_ci      // AsyncGenerator yields (with the exception of the initial yield)
46831cb0ef41Sopenharmony_ci      // delegate work to the AsyncGeneratorYield stub, which Awaits the operand
46841cb0ef41Sopenharmony_ci      // and on success, wraps the value in an IteratorResult.
46851cb0ef41Sopenharmony_ci      RegisterAllocationScope register_scope(this);
46861cb0ef41Sopenharmony_ci      RegisterList args = register_allocator()->NewRegisterList(3);
46871cb0ef41Sopenharmony_ci      builder()
46881cb0ef41Sopenharmony_ci          ->MoveRegister(generator_object(), args[0])  // generator
46891cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[1])         // value
46901cb0ef41Sopenharmony_ci          .LoadBoolean(catch_prediction() != HandlerTable::ASYNC_AWAIT)
46911cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[2])  // is_caught
46921cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kInlineAsyncGeneratorYield, args);
46931cb0ef41Sopenharmony_ci    } else {
46941cb0ef41Sopenharmony_ci      // Generator yields (with the exception of the initial yield) wrap the
46951cb0ef41Sopenharmony_ci      // value into IteratorResult.
46961cb0ef41Sopenharmony_ci      RegisterAllocationScope register_scope(this);
46971cb0ef41Sopenharmony_ci      RegisterList args = register_allocator()->NewRegisterList(2);
46981cb0ef41Sopenharmony_ci      builder()
46991cb0ef41Sopenharmony_ci          ->StoreAccumulatorInRegister(args[0])  // value
47001cb0ef41Sopenharmony_ci          .LoadFalse()
47011cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[1])  // done
47021cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kInlineCreateIterResultObject, args);
47031cb0ef41Sopenharmony_ci    }
47041cb0ef41Sopenharmony_ci  }
47051cb0ef41Sopenharmony_ci
47061cb0ef41Sopenharmony_ci  BuildSuspendPoint(expr->position());
47071cb0ef41Sopenharmony_ci  // At this point, the generator has been resumed, with the received value in
47081cb0ef41Sopenharmony_ci  // the accumulator.
47091cb0ef41Sopenharmony_ci
47101cb0ef41Sopenharmony_ci  // TODO(caitp): remove once yield* desugaring for async generators is handled
47111cb0ef41Sopenharmony_ci  // in BytecodeGenerator.
47121cb0ef41Sopenharmony_ci  if (expr->on_abrupt_resume() == Yield::kNoControl) {
47131cb0ef41Sopenharmony_ci    DCHECK(IsAsyncGeneratorFunction(function_kind()));
47141cb0ef41Sopenharmony_ci    return;
47151cb0ef41Sopenharmony_ci  }
47161cb0ef41Sopenharmony_ci
47171cb0ef41Sopenharmony_ci  Register input = register_allocator()->NewRegister();
47181cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(input).CallRuntime(
47191cb0ef41Sopenharmony_ci      Runtime::kInlineGeneratorGetResumeMode, generator_object());
47201cb0ef41Sopenharmony_ci
47211cb0ef41Sopenharmony_ci  // Now dispatch on resume mode.
47221cb0ef41Sopenharmony_ci  STATIC_ASSERT(JSGeneratorObject::kNext + 1 == JSGeneratorObject::kReturn);
47231cb0ef41Sopenharmony_ci  BytecodeJumpTable* jump_table =
47241cb0ef41Sopenharmony_ci      builder()->AllocateJumpTable(2, JSGeneratorObject::kNext);
47251cb0ef41Sopenharmony_ci
47261cb0ef41Sopenharmony_ci  builder()->SwitchOnSmiNoFeedback(jump_table);
47271cb0ef41Sopenharmony_ci
47281cb0ef41Sopenharmony_ci  {
47291cb0ef41Sopenharmony_ci    // Resume with throw (switch fallthrough).
47301cb0ef41Sopenharmony_ci    // TODO(leszeks): Add a debug-only check that the accumulator is
47311cb0ef41Sopenharmony_ci    // JSGeneratorObject::kThrow.
47321cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition(expr);
47331cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(input);
47341cb0ef41Sopenharmony_ci    builder()->Throw();
47351cb0ef41Sopenharmony_ci  }
47361cb0ef41Sopenharmony_ci
47371cb0ef41Sopenharmony_ci  {
47381cb0ef41Sopenharmony_ci    // Resume with return.
47391cb0ef41Sopenharmony_ci    builder()->Bind(jump_table, JSGeneratorObject::kReturn);
47401cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(input);
47411cb0ef41Sopenharmony_ci    if (IsAsyncGeneratorFunction(function_kind())) {
47421cb0ef41Sopenharmony_ci      execution_control()->AsyncReturnAccumulator(kNoSourcePosition);
47431cb0ef41Sopenharmony_ci    } else {
47441cb0ef41Sopenharmony_ci      execution_control()->ReturnAccumulator(kNoSourcePosition);
47451cb0ef41Sopenharmony_ci    }
47461cb0ef41Sopenharmony_ci  }
47471cb0ef41Sopenharmony_ci
47481cb0ef41Sopenharmony_ci  {
47491cb0ef41Sopenharmony_ci    // Resume with next.
47501cb0ef41Sopenharmony_ci    builder()->Bind(jump_table, JSGeneratorObject::kNext);
47511cb0ef41Sopenharmony_ci    BuildIncrementBlockCoverageCounterIfEnabled(expr,
47521cb0ef41Sopenharmony_ci                                                SourceRangeKind::kContinuation);
47531cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(input);
47541cb0ef41Sopenharmony_ci  }
47551cb0ef41Sopenharmony_ci}
47561cb0ef41Sopenharmony_ci
47571cb0ef41Sopenharmony_ci// Desugaring of (yield* iterable)
47581cb0ef41Sopenharmony_ci//
47591cb0ef41Sopenharmony_ci//   do {
47601cb0ef41Sopenharmony_ci//     const kNext = 0;
47611cb0ef41Sopenharmony_ci//     const kReturn = 1;
47621cb0ef41Sopenharmony_ci//     const kThrow = 2;
47631cb0ef41Sopenharmony_ci//
47641cb0ef41Sopenharmony_ci//     let output; // uninitialized
47651cb0ef41Sopenharmony_ci//
47661cb0ef41Sopenharmony_ci//     let iteratorRecord = GetIterator(iterable);
47671cb0ef41Sopenharmony_ci//     let iterator = iteratorRecord.[[Iterator]];
47681cb0ef41Sopenharmony_ci//     let next = iteratorRecord.[[NextMethod]];
47691cb0ef41Sopenharmony_ci//     let input = undefined;
47701cb0ef41Sopenharmony_ci//     let resumeMode = kNext;
47711cb0ef41Sopenharmony_ci//
47721cb0ef41Sopenharmony_ci//     while (true) {
47731cb0ef41Sopenharmony_ci//       // From the generator to the iterator:
47741cb0ef41Sopenharmony_ci//       // Forward input according to resumeMode and obtain output.
47751cb0ef41Sopenharmony_ci//       switch (resumeMode) {
47761cb0ef41Sopenharmony_ci//         case kNext:
47771cb0ef41Sopenharmony_ci//           output = next.[[Call]](iterator, « »);;
47781cb0ef41Sopenharmony_ci//           break;
47791cb0ef41Sopenharmony_ci//         case kReturn:
47801cb0ef41Sopenharmony_ci//           let iteratorReturn = iterator.return;
47811cb0ef41Sopenharmony_ci//           if (IS_NULL_OR_UNDEFINED(iteratorReturn)) {
47821cb0ef41Sopenharmony_ci//             if (IS_ASYNC_GENERATOR) input = await input;
47831cb0ef41Sopenharmony_ci//             return input;
47841cb0ef41Sopenharmony_ci//           }
47851cb0ef41Sopenharmony_ci//           output = iteratorReturn.[[Call]](iterator, «input»);
47861cb0ef41Sopenharmony_ci//           break;
47871cb0ef41Sopenharmony_ci//         case kThrow:
47881cb0ef41Sopenharmony_ci//           let iteratorThrow = iterator.throw;
47891cb0ef41Sopenharmony_ci//           if (IS_NULL_OR_UNDEFINED(iteratorThrow)) {
47901cb0ef41Sopenharmony_ci//             let iteratorReturn = iterator.return;
47911cb0ef41Sopenharmony_ci//             if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
47921cb0ef41Sopenharmony_ci//               output = iteratorReturn.[[Call]](iterator, « »);
47931cb0ef41Sopenharmony_ci//               if (IS_ASYNC_GENERATOR) output = await output;
47941cb0ef41Sopenharmony_ci//               if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
47951cb0ef41Sopenharmony_ci//             }
47961cb0ef41Sopenharmony_ci//             throw MakeTypeError(kThrowMethodMissing);
47971cb0ef41Sopenharmony_ci//           }
47981cb0ef41Sopenharmony_ci//           output = iteratorThrow.[[Call]](iterator, «input»);
47991cb0ef41Sopenharmony_ci//           break;
48001cb0ef41Sopenharmony_ci//       }
48011cb0ef41Sopenharmony_ci//
48021cb0ef41Sopenharmony_ci//       if (IS_ASYNC_GENERATOR) output = await output;
48031cb0ef41Sopenharmony_ci//       if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
48041cb0ef41Sopenharmony_ci//       if (output.done) break;
48051cb0ef41Sopenharmony_ci//
48061cb0ef41Sopenharmony_ci//       // From the generator to its user:
48071cb0ef41Sopenharmony_ci//       // Forward output, receive new input, and determine resume mode.
48081cb0ef41Sopenharmony_ci//       if (IS_ASYNC_GENERATOR) {
48091cb0ef41Sopenharmony_ci//         // AsyncGeneratorYield abstract operation awaits the operand before
48101cb0ef41Sopenharmony_ci//         // resolving the promise for the current AsyncGeneratorRequest.
48111cb0ef41Sopenharmony_ci//         %_AsyncGeneratorYield(output.value)
48121cb0ef41Sopenharmony_ci//       }
48131cb0ef41Sopenharmony_ci//       input = Suspend(output);
48141cb0ef41Sopenharmony_ci//       resumeMode = %GeneratorGetResumeMode();
48151cb0ef41Sopenharmony_ci//     }
48161cb0ef41Sopenharmony_ci//
48171cb0ef41Sopenharmony_ci//     if (resumeMode === kReturn) {
48181cb0ef41Sopenharmony_ci//       return output.value;
48191cb0ef41Sopenharmony_ci//     }
48201cb0ef41Sopenharmony_ci//     output.value
48211cb0ef41Sopenharmony_ci//   }
48221cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
48231cb0ef41Sopenharmony_ci  Register output = register_allocator()->NewRegister();
48241cb0ef41Sopenharmony_ci  Register resume_mode = register_allocator()->NewRegister();
48251cb0ef41Sopenharmony_ci  IteratorType iterator_type = IsAsyncGeneratorFunction(function_kind())
48261cb0ef41Sopenharmony_ci                                   ? IteratorType::kAsync
48271cb0ef41Sopenharmony_ci                                   : IteratorType::kNormal;
48281cb0ef41Sopenharmony_ci
48291cb0ef41Sopenharmony_ci  {
48301cb0ef41Sopenharmony_ci    RegisterAllocationScope register_scope(this);
48311cb0ef41Sopenharmony_ci    RegisterList iterator_and_input = register_allocator()->NewRegisterList(2);
48321cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->expression());
48331cb0ef41Sopenharmony_ci    IteratorRecord iterator = BuildGetIteratorRecord(
48341cb0ef41Sopenharmony_ci        register_allocator()->NewRegister() /* next method */,
48351cb0ef41Sopenharmony_ci        iterator_and_input[0], iterator_type);
48361cb0ef41Sopenharmony_ci
48371cb0ef41Sopenharmony_ci    Register input = iterator_and_input[1];
48381cb0ef41Sopenharmony_ci    builder()->LoadUndefined().StoreAccumulatorInRegister(input);
48391cb0ef41Sopenharmony_ci    builder()
48401cb0ef41Sopenharmony_ci        ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
48411cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(resume_mode);
48421cb0ef41Sopenharmony_ci
48431cb0ef41Sopenharmony_ci    {
48441cb0ef41Sopenharmony_ci      // This loop builder does not construct counters as the loop is not
48451cb0ef41Sopenharmony_ci      // visible to the user, and we therefore neither pass the block coverage
48461cb0ef41Sopenharmony_ci      // builder nor the expression.
48471cb0ef41Sopenharmony_ci      //
48481cb0ef41Sopenharmony_ci      // In addition to the normal suspend for yield*, a yield* in an async
48491cb0ef41Sopenharmony_ci      // generator has 2 additional suspends:
48501cb0ef41Sopenharmony_ci      //   - One for awaiting the iterator result of closing the generator when
48511cb0ef41Sopenharmony_ci      //     resumed with a "throw" completion, and a throw method is not
48521cb0ef41Sopenharmony_ci      //     present on the delegated iterator
48531cb0ef41Sopenharmony_ci      //   - One for awaiting the iterator result yielded by the delegated
48541cb0ef41Sopenharmony_ci      //     iterator
48551cb0ef41Sopenharmony_ci
48561cb0ef41Sopenharmony_ci      LoopBuilder loop_builder(builder(), nullptr, nullptr);
48571cb0ef41Sopenharmony_ci      LoopScope loop_scope(this, &loop_builder);
48581cb0ef41Sopenharmony_ci
48591cb0ef41Sopenharmony_ci      {
48601cb0ef41Sopenharmony_ci        BytecodeLabels after_switch(zone());
48611cb0ef41Sopenharmony_ci        BytecodeJumpTable* switch_jump_table =
48621cb0ef41Sopenharmony_ci            builder()->AllocateJumpTable(2, 1);
48631cb0ef41Sopenharmony_ci
48641cb0ef41Sopenharmony_ci        builder()
48651cb0ef41Sopenharmony_ci            ->LoadAccumulatorWithRegister(resume_mode)
48661cb0ef41Sopenharmony_ci            .SwitchOnSmiNoFeedback(switch_jump_table);
48671cb0ef41Sopenharmony_ci
48681cb0ef41Sopenharmony_ci        // Fallthrough to default case.
48691cb0ef41Sopenharmony_ci        // TODO(ignition): Add debug code to check that {resume_mode} really is
48701cb0ef41Sopenharmony_ci        // {JSGeneratorObject::kNext} in this case.
48711cb0ef41Sopenharmony_ci        STATIC_ASSERT(JSGeneratorObject::kNext == 0);
48721cb0ef41Sopenharmony_ci        {
48731cb0ef41Sopenharmony_ci          FeedbackSlot slot = feedback_spec()->AddCallICSlot();
48741cb0ef41Sopenharmony_ci          builder()->CallProperty(iterator.next(), iterator_and_input,
48751cb0ef41Sopenharmony_ci                                  feedback_index(slot));
48761cb0ef41Sopenharmony_ci          builder()->Jump(after_switch.New());
48771cb0ef41Sopenharmony_ci        }
48781cb0ef41Sopenharmony_ci
48791cb0ef41Sopenharmony_ci        STATIC_ASSERT(JSGeneratorObject::kReturn == 1);
48801cb0ef41Sopenharmony_ci        builder()->Bind(switch_jump_table, JSGeneratorObject::kReturn);
48811cb0ef41Sopenharmony_ci        {
48821cb0ef41Sopenharmony_ci          const AstRawString* return_string =
48831cb0ef41Sopenharmony_ci              ast_string_constants()->return_string();
48841cb0ef41Sopenharmony_ci          BytecodeLabels no_return_method(zone());
48851cb0ef41Sopenharmony_ci
48861cb0ef41Sopenharmony_ci          BuildCallIteratorMethod(iterator.object(), return_string,
48871cb0ef41Sopenharmony_ci                                  iterator_and_input, after_switch.New(),
48881cb0ef41Sopenharmony_ci                                  &no_return_method);
48891cb0ef41Sopenharmony_ci          no_return_method.Bind(builder());
48901cb0ef41Sopenharmony_ci          builder()->LoadAccumulatorWithRegister(input);
48911cb0ef41Sopenharmony_ci          if (iterator_type == IteratorType::kAsync) {
48921cb0ef41Sopenharmony_ci            // Await input.
48931cb0ef41Sopenharmony_ci            BuildAwait(expr->position());
48941cb0ef41Sopenharmony_ci            execution_control()->AsyncReturnAccumulator(kNoSourcePosition);
48951cb0ef41Sopenharmony_ci          } else {
48961cb0ef41Sopenharmony_ci            execution_control()->ReturnAccumulator(kNoSourcePosition);
48971cb0ef41Sopenharmony_ci          }
48981cb0ef41Sopenharmony_ci        }
48991cb0ef41Sopenharmony_ci
49001cb0ef41Sopenharmony_ci        STATIC_ASSERT(JSGeneratorObject::kThrow == 2);
49011cb0ef41Sopenharmony_ci        builder()->Bind(switch_jump_table, JSGeneratorObject::kThrow);
49021cb0ef41Sopenharmony_ci        {
49031cb0ef41Sopenharmony_ci          const AstRawString* throw_string =
49041cb0ef41Sopenharmony_ci              ast_string_constants()->throw_string();
49051cb0ef41Sopenharmony_ci          BytecodeLabels no_throw_method(zone());
49061cb0ef41Sopenharmony_ci          BuildCallIteratorMethod(iterator.object(), throw_string,
49071cb0ef41Sopenharmony_ci                                  iterator_and_input, after_switch.New(),
49081cb0ef41Sopenharmony_ci                                  &no_throw_method);
49091cb0ef41Sopenharmony_ci
49101cb0ef41Sopenharmony_ci          // If there is no "throw" method, perform IteratorClose, and finally
49111cb0ef41Sopenharmony_ci          // throw a TypeError.
49121cb0ef41Sopenharmony_ci          no_throw_method.Bind(builder());
49131cb0ef41Sopenharmony_ci          BuildIteratorClose(iterator, expr);
49141cb0ef41Sopenharmony_ci          builder()->CallRuntime(Runtime::kThrowThrowMethodMissing);
49151cb0ef41Sopenharmony_ci        }
49161cb0ef41Sopenharmony_ci
49171cb0ef41Sopenharmony_ci        after_switch.Bind(builder());
49181cb0ef41Sopenharmony_ci      }
49191cb0ef41Sopenharmony_ci
49201cb0ef41Sopenharmony_ci      if (iterator_type == IteratorType::kAsync) {
49211cb0ef41Sopenharmony_ci        // Await the result of the method invocation.
49221cb0ef41Sopenharmony_ci        BuildAwait(expr->position());
49231cb0ef41Sopenharmony_ci      }
49241cb0ef41Sopenharmony_ci
49251cb0ef41Sopenharmony_ci      // Check that output is an object.
49261cb0ef41Sopenharmony_ci      BytecodeLabel check_if_done;
49271cb0ef41Sopenharmony_ci      builder()
49281cb0ef41Sopenharmony_ci          ->StoreAccumulatorInRegister(output)
49291cb0ef41Sopenharmony_ci          .JumpIfJSReceiver(&check_if_done)
49301cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, output);
49311cb0ef41Sopenharmony_ci
49321cb0ef41Sopenharmony_ci      builder()->Bind(&check_if_done);
49331cb0ef41Sopenharmony_ci      // Break once output.done is true.
49341cb0ef41Sopenharmony_ci      builder()->LoadNamedProperty(
49351cb0ef41Sopenharmony_ci          output, ast_string_constants()->done_string(),
49361cb0ef41Sopenharmony_ci          feedback_index(feedback_spec()->AddLoadICSlot()));
49371cb0ef41Sopenharmony_ci
49381cb0ef41Sopenharmony_ci      loop_builder.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
49391cb0ef41Sopenharmony_ci
49401cb0ef41Sopenharmony_ci      // Suspend the current generator.
49411cb0ef41Sopenharmony_ci      if (iterator_type == IteratorType::kNormal) {
49421cb0ef41Sopenharmony_ci        builder()->LoadAccumulatorWithRegister(output);
49431cb0ef41Sopenharmony_ci      } else {
49441cb0ef41Sopenharmony_ci        RegisterAllocationScope inner_register_scope(this);
49451cb0ef41Sopenharmony_ci        DCHECK_EQ(iterator_type, IteratorType::kAsync);
49461cb0ef41Sopenharmony_ci        // If generatorKind is async, perform AsyncGeneratorYield(output.value),
49471cb0ef41Sopenharmony_ci        // which will await `output.value` before resolving the current
49481cb0ef41Sopenharmony_ci        // AsyncGeneratorRequest's promise.
49491cb0ef41Sopenharmony_ci        builder()->LoadNamedProperty(
49501cb0ef41Sopenharmony_ci            output, ast_string_constants()->value_string(),
49511cb0ef41Sopenharmony_ci            feedback_index(feedback_spec()->AddLoadICSlot()));
49521cb0ef41Sopenharmony_ci
49531cb0ef41Sopenharmony_ci        RegisterList args = register_allocator()->NewRegisterList(3);
49541cb0ef41Sopenharmony_ci        builder()
49551cb0ef41Sopenharmony_ci            ->MoveRegister(generator_object(), args[0])  // generator
49561cb0ef41Sopenharmony_ci            .StoreAccumulatorInRegister(args[1])         // value
49571cb0ef41Sopenharmony_ci            .LoadBoolean(catch_prediction() != HandlerTable::ASYNC_AWAIT)
49581cb0ef41Sopenharmony_ci            .StoreAccumulatorInRegister(args[2])  // is_caught
49591cb0ef41Sopenharmony_ci            .CallRuntime(Runtime::kInlineAsyncGeneratorYield, args);
49601cb0ef41Sopenharmony_ci      }
49611cb0ef41Sopenharmony_ci
49621cb0ef41Sopenharmony_ci      BuildSuspendPoint(expr->position());
49631cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(input);
49641cb0ef41Sopenharmony_ci      builder()
49651cb0ef41Sopenharmony_ci          ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode,
49661cb0ef41Sopenharmony_ci                        generator_object())
49671cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(resume_mode);
49681cb0ef41Sopenharmony_ci
49691cb0ef41Sopenharmony_ci      loop_builder.BindContinueTarget();
49701cb0ef41Sopenharmony_ci    }
49711cb0ef41Sopenharmony_ci  }
49721cb0ef41Sopenharmony_ci
49731cb0ef41Sopenharmony_ci  // Decide if we trigger a return or if the yield* expression should just
49741cb0ef41Sopenharmony_ci  // produce a value.
49751cb0ef41Sopenharmony_ci  BytecodeLabel completion_is_output_value;
49761cb0ef41Sopenharmony_ci  Register output_value = register_allocator()->NewRegister();
49771cb0ef41Sopenharmony_ci  builder()
49781cb0ef41Sopenharmony_ci      ->LoadNamedProperty(output, ast_string_constants()->value_string(),
49791cb0ef41Sopenharmony_ci                          feedback_index(feedback_spec()->AddLoadICSlot()))
49801cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(output_value)
49811cb0ef41Sopenharmony_ci      .LoadLiteral(Smi::FromInt(JSGeneratorObject::kReturn))
49821cb0ef41Sopenharmony_ci      .CompareReference(resume_mode)
49831cb0ef41Sopenharmony_ci      .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &completion_is_output_value)
49841cb0ef41Sopenharmony_ci      .LoadAccumulatorWithRegister(output_value);
49851cb0ef41Sopenharmony_ci  if (iterator_type == IteratorType::kAsync) {
49861cb0ef41Sopenharmony_ci    execution_control()->AsyncReturnAccumulator(kNoSourcePosition);
49871cb0ef41Sopenharmony_ci  } else {
49881cb0ef41Sopenharmony_ci    execution_control()->ReturnAccumulator(kNoSourcePosition);
49891cb0ef41Sopenharmony_ci  }
49901cb0ef41Sopenharmony_ci
49911cb0ef41Sopenharmony_ci  builder()->Bind(&completion_is_output_value);
49921cb0ef41Sopenharmony_ci  BuildIncrementBlockCoverageCounterIfEnabled(expr,
49931cb0ef41Sopenharmony_ci                                              SourceRangeKind::kContinuation);
49941cb0ef41Sopenharmony_ci  builder()->LoadAccumulatorWithRegister(output_value);
49951cb0ef41Sopenharmony_ci}
49961cb0ef41Sopenharmony_ci
49971cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildAwait(int position) {
49981cb0ef41Sopenharmony_ci  // Rather than HandlerTable::UNCAUGHT, async functions use
49991cb0ef41Sopenharmony_ci  // HandlerTable::ASYNC_AWAIT to communicate that top-level exceptions are
50001cb0ef41Sopenharmony_ci  // transformed into promise rejections. This is necessary to prevent emitting
50011cb0ef41Sopenharmony_ci  // multiple debug events for the same uncaught exception. There is no point
50021cb0ef41Sopenharmony_ci  // in the body of an async function where catch prediction is
50031cb0ef41Sopenharmony_ci  // HandlerTable::UNCAUGHT.
50041cb0ef41Sopenharmony_ci  DCHECK(catch_prediction() != HandlerTable::UNCAUGHT ||
50051cb0ef41Sopenharmony_ci         info()->scope()->is_repl_mode_scope());
50061cb0ef41Sopenharmony_ci
50071cb0ef41Sopenharmony_ci  {
50081cb0ef41Sopenharmony_ci    // Await(operand) and suspend.
50091cb0ef41Sopenharmony_ci    RegisterAllocationScope register_scope(this);
50101cb0ef41Sopenharmony_ci
50111cb0ef41Sopenharmony_ci    Runtime::FunctionId await_intrinsic_id;
50121cb0ef41Sopenharmony_ci    if (IsAsyncGeneratorFunction(function_kind())) {
50131cb0ef41Sopenharmony_ci      await_intrinsic_id = catch_prediction() == HandlerTable::ASYNC_AWAIT
50141cb0ef41Sopenharmony_ci                               ? Runtime::kInlineAsyncGeneratorAwaitUncaught
50151cb0ef41Sopenharmony_ci                               : Runtime::kInlineAsyncGeneratorAwaitCaught;
50161cb0ef41Sopenharmony_ci    } else {
50171cb0ef41Sopenharmony_ci      await_intrinsic_id = catch_prediction() == HandlerTable::ASYNC_AWAIT
50181cb0ef41Sopenharmony_ci                               ? Runtime::kInlineAsyncFunctionAwaitUncaught
50191cb0ef41Sopenharmony_ci                               : Runtime::kInlineAsyncFunctionAwaitCaught;
50201cb0ef41Sopenharmony_ci    }
50211cb0ef41Sopenharmony_ci    RegisterList args = register_allocator()->NewRegisterList(2);
50221cb0ef41Sopenharmony_ci    builder()
50231cb0ef41Sopenharmony_ci        ->MoveRegister(generator_object(), args[0])
50241cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(args[1])
50251cb0ef41Sopenharmony_ci        .CallRuntime(await_intrinsic_id, args);
50261cb0ef41Sopenharmony_ci  }
50271cb0ef41Sopenharmony_ci
50281cb0ef41Sopenharmony_ci  BuildSuspendPoint(position);
50291cb0ef41Sopenharmony_ci
50301cb0ef41Sopenharmony_ci  Register input = register_allocator()->NewRegister();
50311cb0ef41Sopenharmony_ci  Register resume_mode = register_allocator()->NewRegister();
50321cb0ef41Sopenharmony_ci
50331cb0ef41Sopenharmony_ci  // Now dispatch on resume mode.
50341cb0ef41Sopenharmony_ci  BytecodeLabel resume_next;
50351cb0ef41Sopenharmony_ci  builder()
50361cb0ef41Sopenharmony_ci      ->StoreAccumulatorInRegister(input)
50371cb0ef41Sopenharmony_ci      .CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator_object())
50381cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(resume_mode)
50391cb0ef41Sopenharmony_ci      .LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
50401cb0ef41Sopenharmony_ci      .CompareReference(resume_mode)
50411cb0ef41Sopenharmony_ci      .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &resume_next);
50421cb0ef41Sopenharmony_ci
50431cb0ef41Sopenharmony_ci  // Resume with "throw" completion (rethrow the received value).
50441cb0ef41Sopenharmony_ci  // TODO(leszeks): Add a debug-only check that the accumulator is
50451cb0ef41Sopenharmony_ci  // JSGeneratorObject::kThrow.
50461cb0ef41Sopenharmony_ci  builder()->LoadAccumulatorWithRegister(input).ReThrow();
50471cb0ef41Sopenharmony_ci
50481cb0ef41Sopenharmony_ci  // Resume with next.
50491cb0ef41Sopenharmony_ci  builder()->Bind(&resume_next);
50501cb0ef41Sopenharmony_ci  builder()->LoadAccumulatorWithRegister(input);
50511cb0ef41Sopenharmony_ci}
50521cb0ef41Sopenharmony_ci
50531cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitAwait(Await* expr) {
50541cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(expr);
50551cb0ef41Sopenharmony_ci  VisitForAccumulatorValue(expr->expression());
50561cb0ef41Sopenharmony_ci  BuildAwait(expr->position());
50571cb0ef41Sopenharmony_ci  BuildIncrementBlockCoverageCounterIfEnabled(expr,
50581cb0ef41Sopenharmony_ci                                              SourceRangeKind::kContinuation);
50591cb0ef41Sopenharmony_ci}
50601cb0ef41Sopenharmony_ci
50611cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitThrow(Throw* expr) {
50621cb0ef41Sopenharmony_ci  AllocateBlockCoverageSlotIfEnabled(expr, SourceRangeKind::kContinuation);
50631cb0ef41Sopenharmony_ci  VisitForAccumulatorValue(expr->exception());
50641cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(expr);
50651cb0ef41Sopenharmony_ci  builder()->Throw();
50661cb0ef41Sopenharmony_ci}
50671cb0ef41Sopenharmony_ci
50681cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) {
50691cb0ef41Sopenharmony_ci  if (property->is_optional_chain_link()) {
50701cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(optional_chaining_null_labels_);
50711cb0ef41Sopenharmony_ci    int right_range =
50721cb0ef41Sopenharmony_ci        AllocateBlockCoverageSlotIfEnabled(property, SourceRangeKind::kRight);
50731cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(obj).JumpIfUndefinedOrNull(
50741cb0ef41Sopenharmony_ci        optional_chaining_null_labels_->New());
50751cb0ef41Sopenharmony_ci    BuildIncrementBlockCoverageCounterIfEnabled(right_range);
50761cb0ef41Sopenharmony_ci  }
50771cb0ef41Sopenharmony_ci
50781cb0ef41Sopenharmony_ci  AssignType property_kind = Property::GetAssignType(property);
50791cb0ef41Sopenharmony_ci
50801cb0ef41Sopenharmony_ci  switch (property_kind) {
50811cb0ef41Sopenharmony_ci    case NON_PROPERTY:
50821cb0ef41Sopenharmony_ci      UNREACHABLE();
50831cb0ef41Sopenharmony_ci    case NAMED_PROPERTY: {
50841cb0ef41Sopenharmony_ci      builder()->SetExpressionPosition(property);
50851cb0ef41Sopenharmony_ci      const AstRawString* name =
50861cb0ef41Sopenharmony_ci          property->key()->AsLiteral()->AsRawPropertyName();
50871cb0ef41Sopenharmony_ci      BuildLoadNamedProperty(property->obj(), obj, name);
50881cb0ef41Sopenharmony_ci      break;
50891cb0ef41Sopenharmony_ci    }
50901cb0ef41Sopenharmony_ci    case KEYED_PROPERTY: {
50911cb0ef41Sopenharmony_ci      VisitForAccumulatorValue(property->key());
50921cb0ef41Sopenharmony_ci      builder()->SetExpressionPosition(property);
50931cb0ef41Sopenharmony_ci      builder()->LoadKeyedProperty(
50941cb0ef41Sopenharmony_ci          obj, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
50951cb0ef41Sopenharmony_ci      break;
50961cb0ef41Sopenharmony_ci    }
50971cb0ef41Sopenharmony_ci    case NAMED_SUPER_PROPERTY:
50981cb0ef41Sopenharmony_ci      VisitNamedSuperPropertyLoad(property, Register::invalid_value());
50991cb0ef41Sopenharmony_ci      break;
51001cb0ef41Sopenharmony_ci    case KEYED_SUPER_PROPERTY:
51011cb0ef41Sopenharmony_ci      VisitKeyedSuperPropertyLoad(property, Register::invalid_value());
51021cb0ef41Sopenharmony_ci      break;
51031cb0ef41Sopenharmony_ci    case PRIVATE_SETTER_ONLY: {
51041cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, obj);
51051cb0ef41Sopenharmony_ci      BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateGetterAccess,
51061cb0ef41Sopenharmony_ci                                 property);
51071cb0ef41Sopenharmony_ci      break;
51081cb0ef41Sopenharmony_ci    }
51091cb0ef41Sopenharmony_ci    case PRIVATE_GETTER_ONLY:
51101cb0ef41Sopenharmony_ci    case PRIVATE_GETTER_AND_SETTER: {
51111cb0ef41Sopenharmony_ci      Register key = VisitForRegisterValue(property->key());
51121cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, obj);
51131cb0ef41Sopenharmony_ci      BuildPrivateGetterAccess(obj, key);
51141cb0ef41Sopenharmony_ci      break;
51151cb0ef41Sopenharmony_ci    }
51161cb0ef41Sopenharmony_ci    case PRIVATE_METHOD: {
51171cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, obj);
51181cb0ef41Sopenharmony_ci      // In the case of private methods, property->key() is the function to be
51191cb0ef41Sopenharmony_ci      // loaded (stored in a context slot), so load this directly.
51201cb0ef41Sopenharmony_ci      VisitForAccumulatorValue(property->key());
51211cb0ef41Sopenharmony_ci      break;
51221cb0ef41Sopenharmony_ci    }
51231cb0ef41Sopenharmony_ci  }
51241cb0ef41Sopenharmony_ci}
51251cb0ef41Sopenharmony_ci
51261cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildPrivateGetterAccess(Register object,
51271cb0ef41Sopenharmony_ci                                                 Register accessor_pair) {
51281cb0ef41Sopenharmony_ci  RegisterAllocationScope scope(this);
51291cb0ef41Sopenharmony_ci  Register accessor = register_allocator()->NewRegister();
51301cb0ef41Sopenharmony_ci  RegisterList args = register_allocator()->NewRegisterList(1);
51311cb0ef41Sopenharmony_ci
51321cb0ef41Sopenharmony_ci  builder()
51331cb0ef41Sopenharmony_ci      ->CallRuntime(Runtime::kLoadPrivateGetter, accessor_pair)
51341cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(accessor)
51351cb0ef41Sopenharmony_ci      .MoveRegister(object, args[0])
51361cb0ef41Sopenharmony_ci      .CallProperty(accessor, args,
51371cb0ef41Sopenharmony_ci                    feedback_index(feedback_spec()->AddCallICSlot()));
51381cb0ef41Sopenharmony_ci}
51391cb0ef41Sopenharmony_ci
51401cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildPrivateSetterAccess(Register object,
51411cb0ef41Sopenharmony_ci                                                 Register accessor_pair,
51421cb0ef41Sopenharmony_ci                                                 Register value) {
51431cb0ef41Sopenharmony_ci  RegisterAllocationScope scope(this);
51441cb0ef41Sopenharmony_ci  Register accessor = register_allocator()->NewRegister();
51451cb0ef41Sopenharmony_ci  RegisterList args = register_allocator()->NewRegisterList(2);
51461cb0ef41Sopenharmony_ci
51471cb0ef41Sopenharmony_ci  builder()
51481cb0ef41Sopenharmony_ci      ->CallRuntime(Runtime::kLoadPrivateSetter, accessor_pair)
51491cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(accessor)
51501cb0ef41Sopenharmony_ci      .MoveRegister(object, args[0])
51511cb0ef41Sopenharmony_ci      .MoveRegister(value, args[1])
51521cb0ef41Sopenharmony_ci      .CallProperty(accessor, args,
51531cb0ef41Sopenharmony_ci                    feedback_index(feedback_spec()->AddCallICSlot()));
51541cb0ef41Sopenharmony_ci}
51551cb0ef41Sopenharmony_ci
51561cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildPrivateMethodIn(Variable* private_name,
51571cb0ef41Sopenharmony_ci                                             Expression* object_expression) {
51581cb0ef41Sopenharmony_ci  DCHECK(IsPrivateMethodOrAccessorVariableMode(private_name->mode()));
51591cb0ef41Sopenharmony_ci  ClassScope* scope = private_name->scope()->AsClassScope();
51601cb0ef41Sopenharmony_ci  if (private_name->is_static()) {
51611cb0ef41Sopenharmony_ci    // For static private methods, "#privatemethod in ..." only returns true for
51621cb0ef41Sopenharmony_ci    // the class constructor.
51631cb0ef41Sopenharmony_ci    if (scope->class_variable() == nullptr) {
51641cb0ef41Sopenharmony_ci      // Can only happen via the debugger. See comment in
51651cb0ef41Sopenharmony_ci      // BuildPrivateBrandCheck.
51661cb0ef41Sopenharmony_ci      RegisterAllocationScope register_scope(this);
51671cb0ef41Sopenharmony_ci      RegisterList args = register_allocator()->NewRegisterList(2);
51681cb0ef41Sopenharmony_ci      builder()
51691cb0ef41Sopenharmony_ci          ->LoadLiteral(Smi::FromEnum(
51701cb0ef41Sopenharmony_ci              MessageTemplate::
51711cb0ef41Sopenharmony_ci                  kInvalidUnusedPrivateStaticMethodAccessedByDebugger))
51721cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[0])
51731cb0ef41Sopenharmony_ci          .LoadLiteral(private_name->raw_name())
51741cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[1])
51751cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kNewError, args)
51761cb0ef41Sopenharmony_ci          .Throw();
51771cb0ef41Sopenharmony_ci    } else {
51781cb0ef41Sopenharmony_ci      VisitForAccumulatorValue(object_expression);
51791cb0ef41Sopenharmony_ci      Register object = register_allocator()->NewRegister();
51801cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(object);
51811cb0ef41Sopenharmony_ci
51821cb0ef41Sopenharmony_ci      BytecodeLabel is_object;
51831cb0ef41Sopenharmony_ci      builder()->JumpIfJSReceiver(&is_object);
51841cb0ef41Sopenharmony_ci
51851cb0ef41Sopenharmony_ci      RegisterList args = register_allocator()->NewRegisterList(3);
51861cb0ef41Sopenharmony_ci      builder()
51871cb0ef41Sopenharmony_ci          ->StoreAccumulatorInRegister(args[2])
51881cb0ef41Sopenharmony_ci          .LoadLiteral(Smi::FromEnum(MessageTemplate::kInvalidInOperatorUse))
51891cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[0])
51901cb0ef41Sopenharmony_ci          .LoadLiteral(private_name->raw_name())
51911cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[1])
51921cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kNewTypeError, args)
51931cb0ef41Sopenharmony_ci          .Throw();
51941cb0ef41Sopenharmony_ci
51951cb0ef41Sopenharmony_ci      builder()->Bind(&is_object);
51961cb0ef41Sopenharmony_ci      BuildVariableLoadForAccumulatorValue(scope->class_variable(),
51971cb0ef41Sopenharmony_ci                                           HoleCheckMode::kElided);
51981cb0ef41Sopenharmony_ci      builder()->CompareReference(object);
51991cb0ef41Sopenharmony_ci    }
52001cb0ef41Sopenharmony_ci  } else {
52011cb0ef41Sopenharmony_ci    BuildVariableLoadForAccumulatorValue(scope->brand(),
52021cb0ef41Sopenharmony_ci                                         HoleCheckMode::kElided);
52031cb0ef41Sopenharmony_ci    Register brand = register_allocator()->NewRegister();
52041cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(brand);
52051cb0ef41Sopenharmony_ci
52061cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(object_expression);
52071cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition(object_expression);
52081cb0ef41Sopenharmony_ci
52091cb0ef41Sopenharmony_ci    FeedbackSlot slot = feedback_spec()->AddKeyedHasICSlot();
52101cb0ef41Sopenharmony_ci    builder()->CompareOperation(Token::IN, brand, feedback_index(slot));
52111cb0ef41Sopenharmony_ci    execution_result()->SetResultIsBoolean();
52121cb0ef41Sopenharmony_ci  }
52131cb0ef41Sopenharmony_ci}
52141cb0ef41Sopenharmony_ci
52151cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildPrivateBrandCheck(Property* property,
52161cb0ef41Sopenharmony_ci                                               Register object) {
52171cb0ef41Sopenharmony_ci  Variable* private_name = property->key()->AsVariableProxy()->var();
52181cb0ef41Sopenharmony_ci  DCHECK(IsPrivateMethodOrAccessorVariableMode(private_name->mode()));
52191cb0ef41Sopenharmony_ci  ClassScope* scope = private_name->scope()->AsClassScope();
52201cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(property);
52211cb0ef41Sopenharmony_ci  if (private_name->is_static()) {
52221cb0ef41Sopenharmony_ci    // For static private methods, the only valid receiver is the class.
52231cb0ef41Sopenharmony_ci    // Load the class constructor.
52241cb0ef41Sopenharmony_ci    if (scope->class_variable() == nullptr) {
52251cb0ef41Sopenharmony_ci      // If the static private method has not been used used in source
52261cb0ef41Sopenharmony_ci      // code (either explicitly or through the presence of eval), but is
52271cb0ef41Sopenharmony_ci      // accessed by the debugger at runtime, reference to the class variable
52281cb0ef41Sopenharmony_ci      // is not available since it was not be context-allocated. Therefore we
52291cb0ef41Sopenharmony_ci      // can't build a branch check, and throw an ReferenceError as if the
52301cb0ef41Sopenharmony_ci      // method was optimized away.
52311cb0ef41Sopenharmony_ci      // TODO(joyee): get a reference to the class constructor through
52321cb0ef41Sopenharmony_ci      // something other than scope->class_variable() in this scenario.
52331cb0ef41Sopenharmony_ci      RegisterAllocationScope register_scope(this);
52341cb0ef41Sopenharmony_ci      RegisterList args = register_allocator()->NewRegisterList(2);
52351cb0ef41Sopenharmony_ci      builder()
52361cb0ef41Sopenharmony_ci          ->LoadLiteral(Smi::FromEnum(
52371cb0ef41Sopenharmony_ci              MessageTemplate::
52381cb0ef41Sopenharmony_ci                  kInvalidUnusedPrivateStaticMethodAccessedByDebugger))
52391cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[0])
52401cb0ef41Sopenharmony_ci          .LoadLiteral(private_name->raw_name())
52411cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[1])
52421cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kNewError, args)
52431cb0ef41Sopenharmony_ci          .Throw();
52441cb0ef41Sopenharmony_ci    } else {
52451cb0ef41Sopenharmony_ci      BuildVariableLoadForAccumulatorValue(scope->class_variable(),
52461cb0ef41Sopenharmony_ci                                           HoleCheckMode::kElided);
52471cb0ef41Sopenharmony_ci      BytecodeLabel return_check;
52481cb0ef41Sopenharmony_ci      builder()->CompareReference(object).JumpIfTrue(
52491cb0ef41Sopenharmony_ci          ToBooleanMode::kAlreadyBoolean, &return_check);
52501cb0ef41Sopenharmony_ci      const AstRawString* name = scope->class_variable()->raw_name();
52511cb0ef41Sopenharmony_ci      RegisterAllocationScope register_scope(this);
52521cb0ef41Sopenharmony_ci      RegisterList args = register_allocator()->NewRegisterList(2);
52531cb0ef41Sopenharmony_ci      builder()
52541cb0ef41Sopenharmony_ci          ->LoadLiteral(
52551cb0ef41Sopenharmony_ci              Smi::FromEnum(MessageTemplate::kInvalidPrivateBrandStatic))
52561cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[0])
52571cb0ef41Sopenharmony_ci          .LoadLiteral(name)
52581cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(args[1])
52591cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kNewTypeError, args)
52601cb0ef41Sopenharmony_ci          .Throw();
52611cb0ef41Sopenharmony_ci      builder()->Bind(&return_check);
52621cb0ef41Sopenharmony_ci    }
52631cb0ef41Sopenharmony_ci  } else {
52641cb0ef41Sopenharmony_ci    BuildVariableLoadForAccumulatorValue(scope->brand(),
52651cb0ef41Sopenharmony_ci                                         HoleCheckMode::kElided);
52661cb0ef41Sopenharmony_ci    builder()->LoadKeyedProperty(
52671cb0ef41Sopenharmony_ci        object, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
52681cb0ef41Sopenharmony_ci  }
52691cb0ef41Sopenharmony_ci}
52701cb0ef41Sopenharmony_ci
52711cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitPropertyLoadForRegister(Register obj,
52721cb0ef41Sopenharmony_ci                                                     Property* expr,
52731cb0ef41Sopenharmony_ci                                                     Register destination) {
52741cb0ef41Sopenharmony_ci  ValueResultScope result_scope(this);
52751cb0ef41Sopenharmony_ci  VisitPropertyLoad(obj, expr);
52761cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(destination);
52771cb0ef41Sopenharmony_ci}
52781cb0ef41Sopenharmony_ci
52791cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
52801cb0ef41Sopenharmony_ci                                                    Register opt_receiver_out) {
52811cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
52821cb0ef41Sopenharmony_ci  if (FLAG_super_ic) {
52831cb0ef41Sopenharmony_ci    Register receiver = register_allocator()->NewRegister();
52841cb0ef41Sopenharmony_ci    BuildThisVariableLoad();
52851cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(receiver);
52861cb0ef41Sopenharmony_ci    BuildVariableLoad(
52871cb0ef41Sopenharmony_ci        property->obj()->AsSuperPropertyReference()->home_object()->var(),
52881cb0ef41Sopenharmony_ci        HoleCheckMode::kElided);
52891cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition(property);
52901cb0ef41Sopenharmony_ci    auto name = property->key()->AsLiteral()->AsRawPropertyName();
52911cb0ef41Sopenharmony_ci    FeedbackSlot slot = GetCachedLoadSuperICSlot(name);
52921cb0ef41Sopenharmony_ci    builder()->LoadNamedPropertyFromSuper(receiver, name, feedback_index(slot));
52931cb0ef41Sopenharmony_ci    if (opt_receiver_out.is_valid()) {
52941cb0ef41Sopenharmony_ci      builder()->MoveRegister(receiver, opt_receiver_out);
52951cb0ef41Sopenharmony_ci    }
52961cb0ef41Sopenharmony_ci  } else {
52971cb0ef41Sopenharmony_ci    RegisterList args = register_allocator()->NewRegisterList(3);
52981cb0ef41Sopenharmony_ci    BuildThisVariableLoad();
52991cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(args[0]);
53001cb0ef41Sopenharmony_ci    BuildVariableLoad(
53011cb0ef41Sopenharmony_ci        property->obj()->AsSuperPropertyReference()->home_object()->var(),
53021cb0ef41Sopenharmony_ci        HoleCheckMode::kElided);
53031cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(args[1]);
53041cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition(property);
53051cb0ef41Sopenharmony_ci    builder()
53061cb0ef41Sopenharmony_ci        ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
53071cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(args[2])
53081cb0ef41Sopenharmony_ci        .CallRuntime(Runtime::kLoadFromSuper, args);
53091cb0ef41Sopenharmony_ci
53101cb0ef41Sopenharmony_ci    if (opt_receiver_out.is_valid()) {
53111cb0ef41Sopenharmony_ci      builder()->MoveRegister(args[0], opt_receiver_out);
53121cb0ef41Sopenharmony_ci    }
53131cb0ef41Sopenharmony_ci  }
53141cb0ef41Sopenharmony_ci}
53151cb0ef41Sopenharmony_ci
53161cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property,
53171cb0ef41Sopenharmony_ci                                                    Register opt_receiver_out) {
53181cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
53191cb0ef41Sopenharmony_ci  RegisterList args = register_allocator()->NewRegisterList(3);
53201cb0ef41Sopenharmony_ci  BuildThisVariableLoad();
53211cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(args[0]);
53221cb0ef41Sopenharmony_ci  BuildVariableLoad(
53231cb0ef41Sopenharmony_ci      property->obj()->AsSuperPropertyReference()->home_object()->var(),
53241cb0ef41Sopenharmony_ci      HoleCheckMode::kElided);
53251cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(args[1]);
53261cb0ef41Sopenharmony_ci  VisitForRegisterValue(property->key(), args[2]);
53271cb0ef41Sopenharmony_ci
53281cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(property);
53291cb0ef41Sopenharmony_ci  builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, args);
53301cb0ef41Sopenharmony_ci
53311cb0ef41Sopenharmony_ci  if (opt_receiver_out.is_valid()) {
53321cb0ef41Sopenharmony_ci    builder()->MoveRegister(args[0], opt_receiver_out);
53331cb0ef41Sopenharmony_ci  }
53341cb0ef41Sopenharmony_ci}
53351cb0ef41Sopenharmony_ci
53361cb0ef41Sopenharmony_citemplate <typename ExpressionFunc>
53371cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildOptionalChain(ExpressionFunc expression_func) {
53381cb0ef41Sopenharmony_ci  BytecodeLabel done;
53391cb0ef41Sopenharmony_ci  OptionalChainNullLabelScope label_scope(this);
53401cb0ef41Sopenharmony_ci  expression_func();
53411cb0ef41Sopenharmony_ci  builder()->Jump(&done);
53421cb0ef41Sopenharmony_ci  label_scope.labels()->Bind(builder());
53431cb0ef41Sopenharmony_ci  builder()->LoadUndefined();
53441cb0ef41Sopenharmony_ci  builder()->Bind(&done);
53451cb0ef41Sopenharmony_ci}
53461cb0ef41Sopenharmony_ci
53471cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitOptionalChain(OptionalChain* expr) {
53481cb0ef41Sopenharmony_ci  BuildOptionalChain([&]() { VisitForAccumulatorValue(expr->expression()); });
53491cb0ef41Sopenharmony_ci}
53501cb0ef41Sopenharmony_ci
53511cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitProperty(Property* expr) {
53521cb0ef41Sopenharmony_ci  AssignType property_kind = Property::GetAssignType(expr);
53531cb0ef41Sopenharmony_ci  if (property_kind != NAMED_SUPER_PROPERTY &&
53541cb0ef41Sopenharmony_ci      property_kind != KEYED_SUPER_PROPERTY) {
53551cb0ef41Sopenharmony_ci    Register obj = VisitForRegisterValue(expr->obj());
53561cb0ef41Sopenharmony_ci    VisitPropertyLoad(obj, expr);
53571cb0ef41Sopenharmony_ci  } else {
53581cb0ef41Sopenharmony_ci    VisitPropertyLoad(Register::invalid_value(), expr);
53591cb0ef41Sopenharmony_ci  }
53601cb0ef41Sopenharmony_ci}
53611cb0ef41Sopenharmony_ci
53621cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitArguments(const ZonePtrList<Expression>* args,
53631cb0ef41Sopenharmony_ci                                       RegisterList* arg_regs) {
53641cb0ef41Sopenharmony_ci  // Visit arguments.
53651cb0ef41Sopenharmony_ci  for (int i = 0; i < static_cast<int>(args->length()); i++) {
53661cb0ef41Sopenharmony_ci    VisitAndPushIntoRegisterList(args->at(i), arg_regs);
53671cb0ef41Sopenharmony_ci  }
53681cb0ef41Sopenharmony_ci}
53691cb0ef41Sopenharmony_ci
53701cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitCall(Call* expr) {
53711cb0ef41Sopenharmony_ci  Expression* callee_expr = expr->expression();
53721cb0ef41Sopenharmony_ci  Call::CallType call_type = expr->GetCallType();
53731cb0ef41Sopenharmony_ci
53741cb0ef41Sopenharmony_ci  if (call_type == Call::SUPER_CALL) {
53751cb0ef41Sopenharmony_ci    return VisitCallSuper(expr);
53761cb0ef41Sopenharmony_ci  }
53771cb0ef41Sopenharmony_ci
53781cb0ef41Sopenharmony_ci  // We compile the call differently depending on the presence of spreads and
53791cb0ef41Sopenharmony_ci  // their positions.
53801cb0ef41Sopenharmony_ci  //
53811cb0ef41Sopenharmony_ci  // If there is only one spread and it is the final argument, there is a
53821cb0ef41Sopenharmony_ci  // special CallWithSpread bytecode.
53831cb0ef41Sopenharmony_ci  //
53841cb0ef41Sopenharmony_ci  // If there is a non-final spread, we rewrite calls like
53851cb0ef41Sopenharmony_ci  //     callee(1, ...x, 2)
53861cb0ef41Sopenharmony_ci  // to
53871cb0ef41Sopenharmony_ci  //     %reflect_apply(callee, receiver, [1, ...x, 2])
53881cb0ef41Sopenharmony_ci  const Call::SpreadPosition spread_position = expr->spread_position();
53891cb0ef41Sopenharmony_ci
53901cb0ef41Sopenharmony_ci  // Grow the args list as we visit receiver / arguments to avoid allocating all
53911cb0ef41Sopenharmony_ci  // the registers up-front. Otherwise these registers are unavailable during
53921cb0ef41Sopenharmony_ci  // receiver / argument visiting and we can end up with memory leaks due to
53931cb0ef41Sopenharmony_ci  // registers keeping objects alive.
53941cb0ef41Sopenharmony_ci  RegisterList args = register_allocator()->NewGrowableRegisterList();
53951cb0ef41Sopenharmony_ci
53961cb0ef41Sopenharmony_ci  // The callee is the first register in args for ease of calling %reflect_apply
53971cb0ef41Sopenharmony_ci  // if we have a non-final spread. For all other cases it is popped from args
53981cb0ef41Sopenharmony_ci  // before emitting the call below.
53991cb0ef41Sopenharmony_ci  Register callee = register_allocator()->GrowRegisterList(&args);
54001cb0ef41Sopenharmony_ci
54011cb0ef41Sopenharmony_ci  bool implicit_undefined_receiver = false;
54021cb0ef41Sopenharmony_ci
54031cb0ef41Sopenharmony_ci  // TODO(petermarshall): We have a lot of call bytecodes that are very similar,
54041cb0ef41Sopenharmony_ci  // see if we can reduce the number by adding a separate argument which
54051cb0ef41Sopenharmony_ci  // specifies the call type (e.g., property, spread, tailcall, etc.).
54061cb0ef41Sopenharmony_ci
54071cb0ef41Sopenharmony_ci  // Prepare the callee and the receiver to the function call. This depends on
54081cb0ef41Sopenharmony_ci  // the semantics of the underlying call type.
54091cb0ef41Sopenharmony_ci  switch (call_type) {
54101cb0ef41Sopenharmony_ci    case Call::NAMED_PROPERTY_CALL:
54111cb0ef41Sopenharmony_ci    case Call::KEYED_PROPERTY_CALL:
54121cb0ef41Sopenharmony_ci    case Call::PRIVATE_CALL: {
54131cb0ef41Sopenharmony_ci      Property* property = callee_expr->AsProperty();
54141cb0ef41Sopenharmony_ci      VisitAndPushIntoRegisterList(property->obj(), &args);
54151cb0ef41Sopenharmony_ci      VisitPropertyLoadForRegister(args.last_register(), property, callee);
54161cb0ef41Sopenharmony_ci      break;
54171cb0ef41Sopenharmony_ci    }
54181cb0ef41Sopenharmony_ci    case Call::GLOBAL_CALL: {
54191cb0ef41Sopenharmony_ci      // Receiver is undefined for global calls.
54201cb0ef41Sopenharmony_ci      if (spread_position == Call::kNoSpread) {
54211cb0ef41Sopenharmony_ci        implicit_undefined_receiver = true;
54221cb0ef41Sopenharmony_ci      } else {
54231cb0ef41Sopenharmony_ci        // TODO(leszeks): There's no special bytecode for tail calls or spread
54241cb0ef41Sopenharmony_ci        // calls with an undefined receiver, so just push undefined ourselves.
54251cb0ef41Sopenharmony_ci        BuildPushUndefinedIntoRegisterList(&args);
54261cb0ef41Sopenharmony_ci      }
54271cb0ef41Sopenharmony_ci      // Load callee as a global variable.
54281cb0ef41Sopenharmony_ci      VariableProxy* proxy = callee_expr->AsVariableProxy();
54291cb0ef41Sopenharmony_ci      BuildVariableLoadForAccumulatorValue(proxy->var(),
54301cb0ef41Sopenharmony_ci                                           proxy->hole_check_mode());
54311cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(callee);
54321cb0ef41Sopenharmony_ci      break;
54331cb0ef41Sopenharmony_ci    }
54341cb0ef41Sopenharmony_ci    case Call::WITH_CALL: {
54351cb0ef41Sopenharmony_ci      Register receiver = register_allocator()->GrowRegisterList(&args);
54361cb0ef41Sopenharmony_ci      DCHECK(callee_expr->AsVariableProxy()->var()->IsLookupSlot());
54371cb0ef41Sopenharmony_ci      {
54381cb0ef41Sopenharmony_ci        RegisterAllocationScope inner_register_scope(this);
54391cb0ef41Sopenharmony_ci        Register name = register_allocator()->NewRegister();
54401cb0ef41Sopenharmony_ci
54411cb0ef41Sopenharmony_ci        // Call %LoadLookupSlotForCall to get the callee and receiver.
54421cb0ef41Sopenharmony_ci        RegisterList result_pair = register_allocator()->NewRegisterList(2);
54431cb0ef41Sopenharmony_ci        Variable* variable = callee_expr->AsVariableProxy()->var();
54441cb0ef41Sopenharmony_ci        builder()
54451cb0ef41Sopenharmony_ci            ->LoadLiteral(variable->raw_name())
54461cb0ef41Sopenharmony_ci            .StoreAccumulatorInRegister(name)
54471cb0ef41Sopenharmony_ci            .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name,
54481cb0ef41Sopenharmony_ci                                result_pair)
54491cb0ef41Sopenharmony_ci            .MoveRegister(result_pair[0], callee)
54501cb0ef41Sopenharmony_ci            .MoveRegister(result_pair[1], receiver);
54511cb0ef41Sopenharmony_ci      }
54521cb0ef41Sopenharmony_ci      break;
54531cb0ef41Sopenharmony_ci    }
54541cb0ef41Sopenharmony_ci    case Call::OTHER_CALL: {
54551cb0ef41Sopenharmony_ci      // Receiver is undefined for other calls.
54561cb0ef41Sopenharmony_ci      if (spread_position == Call::kNoSpread) {
54571cb0ef41Sopenharmony_ci        implicit_undefined_receiver = true;
54581cb0ef41Sopenharmony_ci      } else {
54591cb0ef41Sopenharmony_ci        // TODO(leszeks): There's no special bytecode for tail calls or spread
54601cb0ef41Sopenharmony_ci        // calls with an undefined receiver, so just push undefined ourselves.
54611cb0ef41Sopenharmony_ci        BuildPushUndefinedIntoRegisterList(&args);
54621cb0ef41Sopenharmony_ci      }
54631cb0ef41Sopenharmony_ci      VisitForRegisterValue(callee_expr, callee);
54641cb0ef41Sopenharmony_ci      break;
54651cb0ef41Sopenharmony_ci    }
54661cb0ef41Sopenharmony_ci    case Call::NAMED_SUPER_PROPERTY_CALL: {
54671cb0ef41Sopenharmony_ci      Register receiver = register_allocator()->GrowRegisterList(&args);
54681cb0ef41Sopenharmony_ci      Property* property = callee_expr->AsProperty();
54691cb0ef41Sopenharmony_ci      VisitNamedSuperPropertyLoad(property, receiver);
54701cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(callee);
54711cb0ef41Sopenharmony_ci      break;
54721cb0ef41Sopenharmony_ci    }
54731cb0ef41Sopenharmony_ci    case Call::KEYED_SUPER_PROPERTY_CALL: {
54741cb0ef41Sopenharmony_ci      Register receiver = register_allocator()->GrowRegisterList(&args);
54751cb0ef41Sopenharmony_ci      Property* property = callee_expr->AsProperty();
54761cb0ef41Sopenharmony_ci      VisitKeyedSuperPropertyLoad(property, receiver);
54771cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(callee);
54781cb0ef41Sopenharmony_ci      break;
54791cb0ef41Sopenharmony_ci    }
54801cb0ef41Sopenharmony_ci    case Call::NAMED_OPTIONAL_CHAIN_PROPERTY_CALL:
54811cb0ef41Sopenharmony_ci    case Call::KEYED_OPTIONAL_CHAIN_PROPERTY_CALL:
54821cb0ef41Sopenharmony_ci    case Call::PRIVATE_OPTIONAL_CHAIN_CALL: {
54831cb0ef41Sopenharmony_ci      OptionalChain* chain = callee_expr->AsOptionalChain();
54841cb0ef41Sopenharmony_ci      Property* property = chain->expression()->AsProperty();
54851cb0ef41Sopenharmony_ci      BuildOptionalChain([&]() {
54861cb0ef41Sopenharmony_ci        VisitAndPushIntoRegisterList(property->obj(), &args);
54871cb0ef41Sopenharmony_ci        VisitPropertyLoad(args.last_register(), property);
54881cb0ef41Sopenharmony_ci      });
54891cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(callee);
54901cb0ef41Sopenharmony_ci      break;
54911cb0ef41Sopenharmony_ci    }
54921cb0ef41Sopenharmony_ci    case Call::SUPER_CALL:
54931cb0ef41Sopenharmony_ci      UNREACHABLE();
54941cb0ef41Sopenharmony_ci  }
54951cb0ef41Sopenharmony_ci
54961cb0ef41Sopenharmony_ci  if (expr->is_optional_chain_link()) {
54971cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(optional_chaining_null_labels_);
54981cb0ef41Sopenharmony_ci    int right_range =
54991cb0ef41Sopenharmony_ci        AllocateBlockCoverageSlotIfEnabled(expr, SourceRangeKind::kRight);
55001cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(callee).JumpIfUndefinedOrNull(
55011cb0ef41Sopenharmony_ci        optional_chaining_null_labels_->New());
55021cb0ef41Sopenharmony_ci    BuildIncrementBlockCoverageCounterIfEnabled(right_range);
55031cb0ef41Sopenharmony_ci  }
55041cb0ef41Sopenharmony_ci
55051cb0ef41Sopenharmony_ci  int receiver_arg_count = -1;
55061cb0ef41Sopenharmony_ci  if (spread_position == Call::kHasNonFinalSpread) {
55071cb0ef41Sopenharmony_ci    // If we're building %reflect_apply, build the array literal and put it in
55081cb0ef41Sopenharmony_ci    // the 3rd argument.
55091cb0ef41Sopenharmony_ci    DCHECK(!implicit_undefined_receiver);
55101cb0ef41Sopenharmony_ci    DCHECK_EQ(args.register_count(), 2);
55111cb0ef41Sopenharmony_ci    BuildCreateArrayLiteral(expr->arguments(), nullptr);
55121cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(
55131cb0ef41Sopenharmony_ci        register_allocator()->GrowRegisterList(&args));
55141cb0ef41Sopenharmony_ci  } else {
55151cb0ef41Sopenharmony_ci    // If we're not building %reflect_apply and don't need to build an array
55161cb0ef41Sopenharmony_ci    // literal, pop the callee and evaluate all arguments to the function call
55171cb0ef41Sopenharmony_ci    // and store in sequential args registers.
55181cb0ef41Sopenharmony_ci    args = args.PopLeft();
55191cb0ef41Sopenharmony_ci    VisitArguments(expr->arguments(), &args);
55201cb0ef41Sopenharmony_ci    receiver_arg_count = implicit_undefined_receiver ? 0 : 1;
55211cb0ef41Sopenharmony_ci    CHECK_EQ(receiver_arg_count + expr->arguments()->length(),
55221cb0ef41Sopenharmony_ci             args.register_count());
55231cb0ef41Sopenharmony_ci  }
55241cb0ef41Sopenharmony_ci
55251cb0ef41Sopenharmony_ci  // Resolve callee for a potential direct eval call. This block will mutate the
55261cb0ef41Sopenharmony_ci  // callee value.
55271cb0ef41Sopenharmony_ci  if (expr->is_possibly_eval() && expr->arguments()->length() > 0) {
55281cb0ef41Sopenharmony_ci    RegisterAllocationScope inner_register_scope(this);
55291cb0ef41Sopenharmony_ci    RegisterList runtime_call_args = register_allocator()->NewRegisterList(6);
55301cb0ef41Sopenharmony_ci    // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
55311cb0ef41Sopenharmony_ci    // strings and function closure, and loading language and
55321cb0ef41Sopenharmony_ci    // position.
55331cb0ef41Sopenharmony_ci
55341cb0ef41Sopenharmony_ci    // Move the first arg.
55351cb0ef41Sopenharmony_ci    if (spread_position == Call::kHasNonFinalSpread) {
55361cb0ef41Sopenharmony_ci      int feedback_slot_index =
55371cb0ef41Sopenharmony_ci          feedback_index(feedback_spec()->AddKeyedLoadICSlot());
55381cb0ef41Sopenharmony_ci      Register args_array = args[2];
55391cb0ef41Sopenharmony_ci      builder()
55401cb0ef41Sopenharmony_ci          ->LoadLiteral(Smi::FromInt(0))
55411cb0ef41Sopenharmony_ci          .LoadKeyedProperty(args_array, feedback_slot_index)
55421cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(runtime_call_args[1]);
55431cb0ef41Sopenharmony_ci    } else {
55441cb0ef41Sopenharmony_ci      // FIXME(v8:5690): Support final spreads for eval.
55451cb0ef41Sopenharmony_ci      DCHECK_GE(receiver_arg_count, 0);
55461cb0ef41Sopenharmony_ci      builder()->MoveRegister(args[receiver_arg_count], runtime_call_args[1]);
55471cb0ef41Sopenharmony_ci    }
55481cb0ef41Sopenharmony_ci    builder()
55491cb0ef41Sopenharmony_ci        ->MoveRegister(callee, runtime_call_args[0])
55501cb0ef41Sopenharmony_ci        .MoveRegister(Register::function_closure(), runtime_call_args[2])
55511cb0ef41Sopenharmony_ci        .LoadLiteral(Smi::FromEnum(language_mode()))
55521cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(runtime_call_args[3])
55531cb0ef41Sopenharmony_ci        .LoadLiteral(Smi::FromInt(current_scope()->start_position()))
55541cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(runtime_call_args[4])
55551cb0ef41Sopenharmony_ci        .LoadLiteral(Smi::FromInt(expr->position()))
55561cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(runtime_call_args[5]);
55571cb0ef41Sopenharmony_ci
55581cb0ef41Sopenharmony_ci    // Call ResolvePossiblyDirectEval and modify the callee.
55591cb0ef41Sopenharmony_ci    builder()
55601cb0ef41Sopenharmony_ci        ->CallRuntime(Runtime::kResolvePossiblyDirectEval, runtime_call_args)
55611cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(callee);
55621cb0ef41Sopenharmony_ci  }
55631cb0ef41Sopenharmony_ci
55641cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(expr);
55651cb0ef41Sopenharmony_ci
55661cb0ef41Sopenharmony_ci  if (spread_position == Call::kHasFinalSpread) {
55671cb0ef41Sopenharmony_ci    DCHECK(!implicit_undefined_receiver);
55681cb0ef41Sopenharmony_ci    builder()->CallWithSpread(callee, args,
55691cb0ef41Sopenharmony_ci                              feedback_index(feedback_spec()->AddCallICSlot()));
55701cb0ef41Sopenharmony_ci  } else if (spread_position == Call::kHasNonFinalSpread) {
55711cb0ef41Sopenharmony_ci    builder()->CallJSRuntime(Context::REFLECT_APPLY_INDEX, args);
55721cb0ef41Sopenharmony_ci  } else if (call_type == Call::NAMED_PROPERTY_CALL ||
55731cb0ef41Sopenharmony_ci             call_type == Call::KEYED_PROPERTY_CALL) {
55741cb0ef41Sopenharmony_ci    DCHECK(!implicit_undefined_receiver);
55751cb0ef41Sopenharmony_ci    builder()->CallProperty(callee, args,
55761cb0ef41Sopenharmony_ci                            feedback_index(feedback_spec()->AddCallICSlot()));
55771cb0ef41Sopenharmony_ci  } else if (implicit_undefined_receiver) {
55781cb0ef41Sopenharmony_ci    builder()->CallUndefinedReceiver(
55791cb0ef41Sopenharmony_ci        callee, args, feedback_index(feedback_spec()->AddCallICSlot()));
55801cb0ef41Sopenharmony_ci  } else {
55811cb0ef41Sopenharmony_ci    builder()->CallAnyReceiver(
55821cb0ef41Sopenharmony_ci        callee, args, feedback_index(feedback_spec()->AddCallICSlot()));
55831cb0ef41Sopenharmony_ci  }
55841cb0ef41Sopenharmony_ci}
55851cb0ef41Sopenharmony_ci
55861cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitCallSuper(Call* expr) {
55871cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
55881cb0ef41Sopenharmony_ci  SuperCallReference* super = expr->expression()->AsSuperCallReference();
55891cb0ef41Sopenharmony_ci  const ZonePtrList<Expression>* args = expr->arguments();
55901cb0ef41Sopenharmony_ci
55911cb0ef41Sopenharmony_ci  // We compile the super call differently depending on the presence of spreads
55921cb0ef41Sopenharmony_ci  // and their positions.
55931cb0ef41Sopenharmony_ci  //
55941cb0ef41Sopenharmony_ci  // If there is only one spread and it is the final argument, there is a
55951cb0ef41Sopenharmony_ci  // special ConstructWithSpread bytecode.
55961cb0ef41Sopenharmony_ci  //
55971cb0ef41Sopenharmony_ci  // It there is a non-final spread, we rewrite something like
55981cb0ef41Sopenharmony_ci  //    super(1, ...x, 2)
55991cb0ef41Sopenharmony_ci  // to
56001cb0ef41Sopenharmony_ci  //    %reflect_construct(constructor, [1, ...x, 2], new_target)
56011cb0ef41Sopenharmony_ci  //
56021cb0ef41Sopenharmony_ci  // That is, we implement (non-last-arg) spreads in super calls via our
56031cb0ef41Sopenharmony_ci  // mechanism for spreads in array literals.
56041cb0ef41Sopenharmony_ci  const Call::SpreadPosition spread_position = expr->spread_position();
56051cb0ef41Sopenharmony_ci
56061cb0ef41Sopenharmony_ci  // Prepare the constructor to the super call.
56071cb0ef41Sopenharmony_ci  Register this_function = VisitForRegisterValue(super->this_function_var());
56081cb0ef41Sopenharmony_ci  Register constructor = register_allocator()->NewRegister();
56091cb0ef41Sopenharmony_ci  builder()
56101cb0ef41Sopenharmony_ci      ->LoadAccumulatorWithRegister(this_function)
56111cb0ef41Sopenharmony_ci      .GetSuperConstructor(constructor);
56121cb0ef41Sopenharmony_ci
56131cb0ef41Sopenharmony_ci  if (spread_position == Call::kHasNonFinalSpread) {
56141cb0ef41Sopenharmony_ci    // First generate the array containing all arguments.
56151cb0ef41Sopenharmony_ci    BuildCreateArrayLiteral(args, nullptr);
56161cb0ef41Sopenharmony_ci
56171cb0ef41Sopenharmony_ci    // Check if the constructor is in fact a constructor.
56181cb0ef41Sopenharmony_ci    builder()->ThrowIfNotSuperConstructor(constructor);
56191cb0ef41Sopenharmony_ci
56201cb0ef41Sopenharmony_ci    // Now pass that array to %reflect_construct.
56211cb0ef41Sopenharmony_ci    RegisterList construct_args = register_allocator()->NewRegisterList(3);
56221cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(construct_args[1]);
56231cb0ef41Sopenharmony_ci    builder()->MoveRegister(constructor, construct_args[0]);
56241cb0ef41Sopenharmony_ci    VisitForRegisterValue(super->new_target_var(), construct_args[2]);
56251cb0ef41Sopenharmony_ci    builder()->CallJSRuntime(Context::REFLECT_CONSTRUCT_INDEX, construct_args);
56261cb0ef41Sopenharmony_ci  } else {
56271cb0ef41Sopenharmony_ci    RegisterList args_regs = register_allocator()->NewGrowableRegisterList();
56281cb0ef41Sopenharmony_ci    VisitArguments(args, &args_regs);
56291cb0ef41Sopenharmony_ci
56301cb0ef41Sopenharmony_ci    // Check if the constructor is in fact a constructor.
56311cb0ef41Sopenharmony_ci    builder()->ThrowIfNotSuperConstructor(constructor);
56321cb0ef41Sopenharmony_ci
56331cb0ef41Sopenharmony_ci    // The new target is loaded into the accumulator from the
56341cb0ef41Sopenharmony_ci    // {new.target} variable.
56351cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(super->new_target_var());
56361cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition(expr);
56371cb0ef41Sopenharmony_ci
56381cb0ef41Sopenharmony_ci    int feedback_slot_index = feedback_index(feedback_spec()->AddCallICSlot());
56391cb0ef41Sopenharmony_ci
56401cb0ef41Sopenharmony_ci    if (spread_position == Call::kHasFinalSpread) {
56411cb0ef41Sopenharmony_ci      builder()->ConstructWithSpread(constructor, args_regs,
56421cb0ef41Sopenharmony_ci                                     feedback_slot_index);
56431cb0ef41Sopenharmony_ci    } else {
56441cb0ef41Sopenharmony_ci      DCHECK_EQ(spread_position, Call::kNoSpread);
56451cb0ef41Sopenharmony_ci      // Call construct.
56461cb0ef41Sopenharmony_ci      // TODO(turbofan): For now we do gather feedback on super constructor
56471cb0ef41Sopenharmony_ci      // calls, utilizing the existing machinery to inline the actual call
56481cb0ef41Sopenharmony_ci      // target and the JSCreate for the implicit receiver allocation. This
56491cb0ef41Sopenharmony_ci      // is not an ideal solution for super constructor calls, but it gets
56501cb0ef41Sopenharmony_ci      // the job done for now. In the long run we might want to revisit this
56511cb0ef41Sopenharmony_ci      // and come up with a better way.
56521cb0ef41Sopenharmony_ci      builder()->Construct(constructor, args_regs, feedback_slot_index);
56531cb0ef41Sopenharmony_ci    }
56541cb0ef41Sopenharmony_ci  }
56551cb0ef41Sopenharmony_ci
56561cb0ef41Sopenharmony_ci  // Explicit calls to the super constructor using super() perform an
56571cb0ef41Sopenharmony_ci  // implicit binding assignment to the 'this' variable.
56581cb0ef41Sopenharmony_ci  //
56591cb0ef41Sopenharmony_ci  // Default constructors don't need have to do the assignment because
56601cb0ef41Sopenharmony_ci  // 'this' isn't accessed in default constructors.
56611cb0ef41Sopenharmony_ci  if (!IsDefaultConstructor(info()->literal()->kind())) {
56621cb0ef41Sopenharmony_ci    Variable* var = closure_scope()->GetReceiverScope()->receiver();
56631cb0ef41Sopenharmony_ci    BuildVariableAssignment(var, Token::INIT, HoleCheckMode::kRequired);
56641cb0ef41Sopenharmony_ci  }
56651cb0ef41Sopenharmony_ci
56661cb0ef41Sopenharmony_ci  Register instance = register_allocator()->NewRegister();
56671cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(instance);
56681cb0ef41Sopenharmony_ci
56691cb0ef41Sopenharmony_ci  // The constructor scope always needs ScopeInfo, so we are certain that
56701cb0ef41Sopenharmony_ci  // the first constructor scope found in the outer scope chain is the
56711cb0ef41Sopenharmony_ci  // scope that we are looking for for this super() call.
56721cb0ef41Sopenharmony_ci  // Note that this doesn't necessarily mean that the constructor needs
56731cb0ef41Sopenharmony_ci  // a context, if it doesn't this would get handled specially in
56741cb0ef41Sopenharmony_ci  // BuildPrivateBrandInitialization().
56751cb0ef41Sopenharmony_ci  DeclarationScope* constructor_scope = info()->scope()->GetConstructorScope();
56761cb0ef41Sopenharmony_ci
56771cb0ef41Sopenharmony_ci  // We can rely on the class_scope_has_private_brand bit to tell if the
56781cb0ef41Sopenharmony_ci  // constructor needs private brand initialization, and if that's
56791cb0ef41Sopenharmony_ci  // the case we are certain that its outer class scope requires a context to
56801cb0ef41Sopenharmony_ci  // keep the brand variable, so we can just get the brand variable
56811cb0ef41Sopenharmony_ci  // from the outer scope.
56821cb0ef41Sopenharmony_ci  if (constructor_scope->class_scope_has_private_brand()) {
56831cb0ef41Sopenharmony_ci    DCHECK(constructor_scope->outer_scope()->is_class_scope());
56841cb0ef41Sopenharmony_ci    ClassScope* class_scope = constructor_scope->outer_scope()->AsClassScope();
56851cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(class_scope->brand());
56861cb0ef41Sopenharmony_ci    Variable* brand = class_scope->brand();
56871cb0ef41Sopenharmony_ci    BuildPrivateBrandInitialization(instance, brand);
56881cb0ef41Sopenharmony_ci  }
56891cb0ef41Sopenharmony_ci
56901cb0ef41Sopenharmony_ci  // The derived constructor has the correct bit set always, so we
56911cb0ef41Sopenharmony_ci  // don't emit code to load and call the initializer if not
56921cb0ef41Sopenharmony_ci  // required.
56931cb0ef41Sopenharmony_ci  //
56941cb0ef41Sopenharmony_ci  // For the arrow function or eval case, we always emit code to load
56951cb0ef41Sopenharmony_ci  // and call the initializer.
56961cb0ef41Sopenharmony_ci  //
56971cb0ef41Sopenharmony_ci  // TODO(gsathya): In the future, we could tag nested arrow functions
56981cb0ef41Sopenharmony_ci  // or eval with the correct bit so that we do the load conditionally
56991cb0ef41Sopenharmony_ci  // if required.
57001cb0ef41Sopenharmony_ci  if (info()->literal()->requires_instance_members_initializer() ||
57011cb0ef41Sopenharmony_ci      !IsDerivedConstructor(info()->literal()->kind())) {
57021cb0ef41Sopenharmony_ci    BuildInstanceMemberInitialization(this_function, instance);
57031cb0ef41Sopenharmony_ci  }
57041cb0ef41Sopenharmony_ci
57051cb0ef41Sopenharmony_ci  builder()->LoadAccumulatorWithRegister(instance);
57061cb0ef41Sopenharmony_ci}
57071cb0ef41Sopenharmony_ci
57081cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitCallNew(CallNew* expr) {
57091cb0ef41Sopenharmony_ci  RegisterList args = register_allocator()->NewGrowableRegisterList();
57101cb0ef41Sopenharmony_ci
57111cb0ef41Sopenharmony_ci  // Load the constructor. It's in the first register in args for ease of
57121cb0ef41Sopenharmony_ci  // calling %reflect_construct if we have a non-final spread. For all other
57131cb0ef41Sopenharmony_ci  // cases it is popped before emitting the construct below.
57141cb0ef41Sopenharmony_ci  VisitAndPushIntoRegisterList(expr->expression(), &args);
57151cb0ef41Sopenharmony_ci
57161cb0ef41Sopenharmony_ci  // We compile the new differently depending on the presence of spreads and
57171cb0ef41Sopenharmony_ci  // their positions.
57181cb0ef41Sopenharmony_ci  //
57191cb0ef41Sopenharmony_ci  // If there is only one spread and it is the final argument, there is a
57201cb0ef41Sopenharmony_ci  // special ConstructWithSpread bytecode.
57211cb0ef41Sopenharmony_ci  //
57221cb0ef41Sopenharmony_ci  // If there is a non-final spread, we rewrite calls like
57231cb0ef41Sopenharmony_ci  //     new ctor(1, ...x, 2)
57241cb0ef41Sopenharmony_ci  // to
57251cb0ef41Sopenharmony_ci  //     %reflect_construct(ctor, [1, ...x, 2])
57261cb0ef41Sopenharmony_ci  const CallNew::SpreadPosition spread_position = expr->spread_position();
57271cb0ef41Sopenharmony_ci
57281cb0ef41Sopenharmony_ci  if (spread_position == CallNew::kHasNonFinalSpread) {
57291cb0ef41Sopenharmony_ci    BuildCreateArrayLiteral(expr->arguments(), nullptr);
57301cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition(expr);
57311cb0ef41Sopenharmony_ci    builder()
57321cb0ef41Sopenharmony_ci        ->StoreAccumulatorInRegister(
57331cb0ef41Sopenharmony_ci            register_allocator()->GrowRegisterList(&args))
57341cb0ef41Sopenharmony_ci        .CallJSRuntime(Context::REFLECT_CONSTRUCT_INDEX, args);
57351cb0ef41Sopenharmony_ci    return;
57361cb0ef41Sopenharmony_ci  }
57371cb0ef41Sopenharmony_ci
57381cb0ef41Sopenharmony_ci  Register constructor = args.first_register();
57391cb0ef41Sopenharmony_ci  args = args.PopLeft();
57401cb0ef41Sopenharmony_ci  VisitArguments(expr->arguments(), &args);
57411cb0ef41Sopenharmony_ci
57421cb0ef41Sopenharmony_ci  // The accumulator holds new target which is the same as the
57431cb0ef41Sopenharmony_ci  // constructor for CallNew.
57441cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(expr);
57451cb0ef41Sopenharmony_ci  builder()->LoadAccumulatorWithRegister(constructor);
57461cb0ef41Sopenharmony_ci
57471cb0ef41Sopenharmony_ci  int feedback_slot_index = feedback_index(feedback_spec()->AddCallICSlot());
57481cb0ef41Sopenharmony_ci  if (spread_position == CallNew::kHasFinalSpread) {
57491cb0ef41Sopenharmony_ci    builder()->ConstructWithSpread(constructor, args, feedback_slot_index);
57501cb0ef41Sopenharmony_ci  } else {
57511cb0ef41Sopenharmony_ci    DCHECK_EQ(spread_position, CallNew::kNoSpread);
57521cb0ef41Sopenharmony_ci    builder()->Construct(constructor, args, feedback_slot_index);
57531cb0ef41Sopenharmony_ci  }
57541cb0ef41Sopenharmony_ci}
57551cb0ef41Sopenharmony_ci
57561cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
57571cb0ef41Sopenharmony_ci  if (expr->is_jsruntime()) {
57581cb0ef41Sopenharmony_ci    RegisterList args = register_allocator()->NewGrowableRegisterList();
57591cb0ef41Sopenharmony_ci    VisitArguments(expr->arguments(), &args);
57601cb0ef41Sopenharmony_ci    builder()->CallJSRuntime(expr->context_index(), args);
57611cb0ef41Sopenharmony_ci  } else {
57621cb0ef41Sopenharmony_ci    // Evaluate all arguments to the runtime call.
57631cb0ef41Sopenharmony_ci    RegisterList args = register_allocator()->NewGrowableRegisterList();
57641cb0ef41Sopenharmony_ci    VisitArguments(expr->arguments(), &args);
57651cb0ef41Sopenharmony_ci    Runtime::FunctionId function_id = expr->function()->function_id;
57661cb0ef41Sopenharmony_ci    builder()->CallRuntime(function_id, args);
57671cb0ef41Sopenharmony_ci  }
57681cb0ef41Sopenharmony_ci}
57691cb0ef41Sopenharmony_ci
57701cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
57711cb0ef41Sopenharmony_ci  VisitForEffect(expr->expression());
57721cb0ef41Sopenharmony_ci  builder()->LoadUndefined();
57731cb0ef41Sopenharmony_ci}
57741cb0ef41Sopenharmony_ci
57751cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitForTypeOfValue(Expression* expr) {
57761cb0ef41Sopenharmony_ci  if (expr->IsVariableProxy()) {
57771cb0ef41Sopenharmony_ci    // Typeof does not throw a reference error on global variables, hence we
57781cb0ef41Sopenharmony_ci    // perform a non-contextual load in case the operand is a variable proxy.
57791cb0ef41Sopenharmony_ci    VariableProxy* proxy = expr->AsVariableProxy();
57801cb0ef41Sopenharmony_ci    BuildVariableLoadForAccumulatorValue(proxy->var(), proxy->hole_check_mode(),
57811cb0ef41Sopenharmony_ci                                         TypeofMode::kInside);
57821cb0ef41Sopenharmony_ci  } else {
57831cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr);
57841cb0ef41Sopenharmony_ci  }
57851cb0ef41Sopenharmony_ci}
57861cb0ef41Sopenharmony_ci
57871cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
57881cb0ef41Sopenharmony_ci  VisitForTypeOfValue(expr->expression());
57891cb0ef41Sopenharmony_ci  builder()->TypeOf();
57901cb0ef41Sopenharmony_ci}
57911cb0ef41Sopenharmony_ci
57921cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitNot(UnaryOperation* expr) {
57931cb0ef41Sopenharmony_ci  if (execution_result()->IsEffect()) {
57941cb0ef41Sopenharmony_ci    VisitForEffect(expr->expression());
57951cb0ef41Sopenharmony_ci  } else if (execution_result()->IsTest()) {
57961cb0ef41Sopenharmony_ci    // No actual logical negation happening, we just swap the control flow, by
57971cb0ef41Sopenharmony_ci    // swapping the target labels and the fallthrough branch, and visit in the
57981cb0ef41Sopenharmony_ci    // same test result context.
57991cb0ef41Sopenharmony_ci    TestResultScope* test_result = execution_result()->AsTest();
58001cb0ef41Sopenharmony_ci    test_result->InvertControlFlow();
58011cb0ef41Sopenharmony_ci    VisitInSameTestExecutionScope(expr->expression());
58021cb0ef41Sopenharmony_ci  } else {
58031cb0ef41Sopenharmony_ci    TypeHint type_hint = VisitForAccumulatorValue(expr->expression());
58041cb0ef41Sopenharmony_ci    builder()->LogicalNot(ToBooleanModeFromTypeHint(type_hint));
58051cb0ef41Sopenharmony_ci    // Always returns a boolean value.
58061cb0ef41Sopenharmony_ci    execution_result()->SetResultIsBoolean();
58071cb0ef41Sopenharmony_ci  }
58081cb0ef41Sopenharmony_ci}
58091cb0ef41Sopenharmony_ci
58101cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
58111cb0ef41Sopenharmony_ci  switch (expr->op()) {
58121cb0ef41Sopenharmony_ci    case Token::Value::NOT:
58131cb0ef41Sopenharmony_ci      VisitNot(expr);
58141cb0ef41Sopenharmony_ci      break;
58151cb0ef41Sopenharmony_ci    case Token::Value::TYPEOF:
58161cb0ef41Sopenharmony_ci      VisitTypeOf(expr);
58171cb0ef41Sopenharmony_ci      break;
58181cb0ef41Sopenharmony_ci    case Token::Value::VOID:
58191cb0ef41Sopenharmony_ci      VisitVoid(expr);
58201cb0ef41Sopenharmony_ci      break;
58211cb0ef41Sopenharmony_ci    case Token::Value::DELETE:
58221cb0ef41Sopenharmony_ci      VisitDelete(expr);
58231cb0ef41Sopenharmony_ci      break;
58241cb0ef41Sopenharmony_ci    case Token::Value::ADD:
58251cb0ef41Sopenharmony_ci    case Token::Value::SUB:
58261cb0ef41Sopenharmony_ci    case Token::Value::BIT_NOT:
58271cb0ef41Sopenharmony_ci      VisitForAccumulatorValue(expr->expression());
58281cb0ef41Sopenharmony_ci      builder()->SetExpressionPosition(expr);
58291cb0ef41Sopenharmony_ci      builder()->UnaryOperation(
58301cb0ef41Sopenharmony_ci          expr->op(), feedback_index(feedback_spec()->AddBinaryOpICSlot()));
58311cb0ef41Sopenharmony_ci      break;
58321cb0ef41Sopenharmony_ci    default:
58331cb0ef41Sopenharmony_ci      UNREACHABLE();
58341cb0ef41Sopenharmony_ci  }
58351cb0ef41Sopenharmony_ci}
58361cb0ef41Sopenharmony_ci
58371cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitDelete(UnaryOperation* unary) {
58381cb0ef41Sopenharmony_ci  Expression* expr = unary->expression();
58391cb0ef41Sopenharmony_ci  if (expr->IsProperty()) {
58401cb0ef41Sopenharmony_ci    // Delete of an object property is allowed both in sloppy
58411cb0ef41Sopenharmony_ci    // and strict modes.
58421cb0ef41Sopenharmony_ci    Property* property = expr->AsProperty();
58431cb0ef41Sopenharmony_ci    DCHECK(!property->IsPrivateReference());
58441cb0ef41Sopenharmony_ci    Register object = VisitForRegisterValue(property->obj());
58451cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(property->key());
58461cb0ef41Sopenharmony_ci    builder()->Delete(object, language_mode());
58471cb0ef41Sopenharmony_ci  } else if (expr->IsOptionalChain()) {
58481cb0ef41Sopenharmony_ci    Expression* expr_inner = expr->AsOptionalChain()->expression();
58491cb0ef41Sopenharmony_ci    if (expr_inner->IsProperty()) {
58501cb0ef41Sopenharmony_ci      Property* property = expr_inner->AsProperty();
58511cb0ef41Sopenharmony_ci      DCHECK(!property->IsPrivateReference());
58521cb0ef41Sopenharmony_ci      BytecodeLabel done;
58531cb0ef41Sopenharmony_ci      OptionalChainNullLabelScope label_scope(this);
58541cb0ef41Sopenharmony_ci      VisitForAccumulatorValue(property->obj());
58551cb0ef41Sopenharmony_ci      if (property->is_optional_chain_link()) {
58561cb0ef41Sopenharmony_ci        int right_range = AllocateBlockCoverageSlotIfEnabled(
58571cb0ef41Sopenharmony_ci            property, SourceRangeKind::kRight);
58581cb0ef41Sopenharmony_ci        builder()->JumpIfUndefinedOrNull(label_scope.labels()->New());
58591cb0ef41Sopenharmony_ci        BuildIncrementBlockCoverageCounterIfEnabled(right_range);
58601cb0ef41Sopenharmony_ci      }
58611cb0ef41Sopenharmony_ci      Register object = register_allocator()->NewRegister();
58621cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(object);
58631cb0ef41Sopenharmony_ci      VisitForAccumulatorValue(property->key());
58641cb0ef41Sopenharmony_ci      builder()->Delete(object, language_mode());
58651cb0ef41Sopenharmony_ci      builder()->Jump(&done);
58661cb0ef41Sopenharmony_ci      label_scope.labels()->Bind(builder());
58671cb0ef41Sopenharmony_ci      builder()->LoadTrue();
58681cb0ef41Sopenharmony_ci      builder()->Bind(&done);
58691cb0ef41Sopenharmony_ci    } else {
58701cb0ef41Sopenharmony_ci      VisitForEffect(expr);
58711cb0ef41Sopenharmony_ci      builder()->LoadTrue();
58721cb0ef41Sopenharmony_ci    }
58731cb0ef41Sopenharmony_ci  } else if (expr->IsVariableProxy() &&
58741cb0ef41Sopenharmony_ci             !expr->AsVariableProxy()->is_new_target()) {
58751cb0ef41Sopenharmony_ci    // Delete of an unqualified identifier is allowed in sloppy mode but is
58761cb0ef41Sopenharmony_ci    // not allowed in strict mode.
58771cb0ef41Sopenharmony_ci    DCHECK(is_sloppy(language_mode()));
58781cb0ef41Sopenharmony_ci    Variable* variable = expr->AsVariableProxy()->var();
58791cb0ef41Sopenharmony_ci    switch (variable->location()) {
58801cb0ef41Sopenharmony_ci      case VariableLocation::PARAMETER:
58811cb0ef41Sopenharmony_ci      case VariableLocation::LOCAL:
58821cb0ef41Sopenharmony_ci      case VariableLocation::CONTEXT:
58831cb0ef41Sopenharmony_ci      case VariableLocation::REPL_GLOBAL: {
58841cb0ef41Sopenharmony_ci        // Deleting local var/let/const, context variables, and arguments
58851cb0ef41Sopenharmony_ci        // does not have any effect.
58861cb0ef41Sopenharmony_ci        builder()->LoadFalse();
58871cb0ef41Sopenharmony_ci        break;
58881cb0ef41Sopenharmony_ci      }
58891cb0ef41Sopenharmony_ci      case VariableLocation::UNALLOCATED:
58901cb0ef41Sopenharmony_ci      // TODO(adamk): Falling through to the runtime results in correct
58911cb0ef41Sopenharmony_ci      // behavior, but does unnecessary context-walking (since scope
58921cb0ef41Sopenharmony_ci      // analysis has already proven that the variable doesn't exist in
58931cb0ef41Sopenharmony_ci      // any non-global scope). Consider adding a DeleteGlobal bytecode
58941cb0ef41Sopenharmony_ci      // that knows how to deal with ScriptContexts as well as global
58951cb0ef41Sopenharmony_ci      // object properties.
58961cb0ef41Sopenharmony_ci      case VariableLocation::LOOKUP: {
58971cb0ef41Sopenharmony_ci        Register name_reg = register_allocator()->NewRegister();
58981cb0ef41Sopenharmony_ci        builder()
58991cb0ef41Sopenharmony_ci            ->LoadLiteral(variable->raw_name())
59001cb0ef41Sopenharmony_ci            .StoreAccumulatorInRegister(name_reg)
59011cb0ef41Sopenharmony_ci            .CallRuntime(Runtime::kDeleteLookupSlot, name_reg);
59021cb0ef41Sopenharmony_ci        break;
59031cb0ef41Sopenharmony_ci      }
59041cb0ef41Sopenharmony_ci      case VariableLocation::MODULE:
59051cb0ef41Sopenharmony_ci        // Modules are always in strict mode and unqualified identifers are not
59061cb0ef41Sopenharmony_ci        // allowed in strict mode.
59071cb0ef41Sopenharmony_ci        UNREACHABLE();
59081cb0ef41Sopenharmony_ci    }
59091cb0ef41Sopenharmony_ci  } else {
59101cb0ef41Sopenharmony_ci    // Delete of an unresolvable reference, new.target, and this returns true.
59111cb0ef41Sopenharmony_ci    VisitForEffect(expr);
59121cb0ef41Sopenharmony_ci    builder()->LoadTrue();
59131cb0ef41Sopenharmony_ci  }
59141cb0ef41Sopenharmony_ci}
59151cb0ef41Sopenharmony_ci
59161cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
59171cb0ef41Sopenharmony_ci  DCHECK(expr->expression()->IsValidReferenceExpression());
59181cb0ef41Sopenharmony_ci
59191cb0ef41Sopenharmony_ci  // Left-hand side can only be a property, a global or a variable slot.
59201cb0ef41Sopenharmony_ci  Property* property = expr->expression()->AsProperty();
59211cb0ef41Sopenharmony_ci  AssignType assign_type = Property::GetAssignType(property);
59221cb0ef41Sopenharmony_ci
59231cb0ef41Sopenharmony_ci  bool is_postfix = expr->is_postfix() && !execution_result()->IsEffect();
59241cb0ef41Sopenharmony_ci
59251cb0ef41Sopenharmony_ci  // Evaluate LHS expression and get old value.
59261cb0ef41Sopenharmony_ci  Register object, key, old_value;
59271cb0ef41Sopenharmony_ci  RegisterList super_property_args;
59281cb0ef41Sopenharmony_ci  const AstRawString* name;
59291cb0ef41Sopenharmony_ci  switch (assign_type) {
59301cb0ef41Sopenharmony_ci    case NON_PROPERTY: {
59311cb0ef41Sopenharmony_ci      VariableProxy* proxy = expr->expression()->AsVariableProxy();
59321cb0ef41Sopenharmony_ci      BuildVariableLoadForAccumulatorValue(proxy->var(),
59331cb0ef41Sopenharmony_ci                                           proxy->hole_check_mode());
59341cb0ef41Sopenharmony_ci      break;
59351cb0ef41Sopenharmony_ci    }
59361cb0ef41Sopenharmony_ci    case NAMED_PROPERTY: {
59371cb0ef41Sopenharmony_ci      object = VisitForRegisterValue(property->obj());
59381cb0ef41Sopenharmony_ci      name = property->key()->AsLiteral()->AsRawPropertyName();
59391cb0ef41Sopenharmony_ci      builder()->LoadNamedProperty(
59401cb0ef41Sopenharmony_ci          object, name,
59411cb0ef41Sopenharmony_ci          feedback_index(GetCachedLoadICSlot(property->obj(), name)));
59421cb0ef41Sopenharmony_ci      break;
59431cb0ef41Sopenharmony_ci    }
59441cb0ef41Sopenharmony_ci    case KEYED_PROPERTY: {
59451cb0ef41Sopenharmony_ci      object = VisitForRegisterValue(property->obj());
59461cb0ef41Sopenharmony_ci      // Use visit for accumulator here since we need the key in the accumulator
59471cb0ef41Sopenharmony_ci      // for the LoadKeyedProperty.
59481cb0ef41Sopenharmony_ci      key = register_allocator()->NewRegister();
59491cb0ef41Sopenharmony_ci      VisitForAccumulatorValue(property->key());
59501cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty(
59511cb0ef41Sopenharmony_ci          object, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
59521cb0ef41Sopenharmony_ci      break;
59531cb0ef41Sopenharmony_ci    }
59541cb0ef41Sopenharmony_ci    case NAMED_SUPER_PROPERTY: {
59551cb0ef41Sopenharmony_ci      super_property_args = register_allocator()->NewRegisterList(4);
59561cb0ef41Sopenharmony_ci      RegisterList load_super_args = super_property_args.Truncate(3);
59571cb0ef41Sopenharmony_ci      BuildThisVariableLoad();
59581cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(load_super_args[0]);
59591cb0ef41Sopenharmony_ci      BuildVariableLoad(
59601cb0ef41Sopenharmony_ci          property->obj()->AsSuperPropertyReference()->home_object()->var(),
59611cb0ef41Sopenharmony_ci          HoleCheckMode::kElided);
59621cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(load_super_args[1]);
59631cb0ef41Sopenharmony_ci      builder()
59641cb0ef41Sopenharmony_ci          ->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
59651cb0ef41Sopenharmony_ci          .StoreAccumulatorInRegister(load_super_args[2])
59661cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kLoadFromSuper, load_super_args);
59671cb0ef41Sopenharmony_ci      break;
59681cb0ef41Sopenharmony_ci    }
59691cb0ef41Sopenharmony_ci    case KEYED_SUPER_PROPERTY: {
59701cb0ef41Sopenharmony_ci      super_property_args = register_allocator()->NewRegisterList(4);
59711cb0ef41Sopenharmony_ci      RegisterList load_super_args = super_property_args.Truncate(3);
59721cb0ef41Sopenharmony_ci      BuildThisVariableLoad();
59731cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(load_super_args[0]);
59741cb0ef41Sopenharmony_ci      BuildVariableLoad(
59751cb0ef41Sopenharmony_ci          property->obj()->AsSuperPropertyReference()->home_object()->var(),
59761cb0ef41Sopenharmony_ci          HoleCheckMode::kElided);
59771cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(load_super_args[1]);
59781cb0ef41Sopenharmony_ci      VisitForRegisterValue(property->key(), load_super_args[2]);
59791cb0ef41Sopenharmony_ci      builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, load_super_args);
59801cb0ef41Sopenharmony_ci      break;
59811cb0ef41Sopenharmony_ci    }
59821cb0ef41Sopenharmony_ci    case PRIVATE_METHOD: {
59831cb0ef41Sopenharmony_ci      object = VisitForRegisterValue(property->obj());
59841cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, object);
59851cb0ef41Sopenharmony_ci      BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateMethodWrite,
59861cb0ef41Sopenharmony_ci                                 property);
59871cb0ef41Sopenharmony_ci      return;
59881cb0ef41Sopenharmony_ci    }
59891cb0ef41Sopenharmony_ci    case PRIVATE_GETTER_ONLY: {
59901cb0ef41Sopenharmony_ci      object = VisitForRegisterValue(property->obj());
59911cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, object);
59921cb0ef41Sopenharmony_ci      BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateSetterAccess,
59931cb0ef41Sopenharmony_ci                                 property);
59941cb0ef41Sopenharmony_ci      return;
59951cb0ef41Sopenharmony_ci    }
59961cb0ef41Sopenharmony_ci    case PRIVATE_SETTER_ONLY: {
59971cb0ef41Sopenharmony_ci      object = VisitForRegisterValue(property->obj());
59981cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, object);
59991cb0ef41Sopenharmony_ci      BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateGetterAccess,
60001cb0ef41Sopenharmony_ci                                 property);
60011cb0ef41Sopenharmony_ci      return;
60021cb0ef41Sopenharmony_ci    }
60031cb0ef41Sopenharmony_ci    case PRIVATE_GETTER_AND_SETTER: {
60041cb0ef41Sopenharmony_ci      object = VisitForRegisterValue(property->obj());
60051cb0ef41Sopenharmony_ci      key = VisitForRegisterValue(property->key());
60061cb0ef41Sopenharmony_ci      BuildPrivateBrandCheck(property, object);
60071cb0ef41Sopenharmony_ci      BuildPrivateGetterAccess(object, key);
60081cb0ef41Sopenharmony_ci      break;
60091cb0ef41Sopenharmony_ci    }
60101cb0ef41Sopenharmony_ci  }
60111cb0ef41Sopenharmony_ci
60121cb0ef41Sopenharmony_ci  // Save result for postfix expressions.
60131cb0ef41Sopenharmony_ci  FeedbackSlot count_slot = feedback_spec()->AddBinaryOpICSlot();
60141cb0ef41Sopenharmony_ci  if (is_postfix) {
60151cb0ef41Sopenharmony_ci    old_value = register_allocator()->NewRegister();
60161cb0ef41Sopenharmony_ci    // Convert old value into a number before saving it.
60171cb0ef41Sopenharmony_ci    // TODO(ignition): Think about adding proper PostInc/PostDec bytecodes
60181cb0ef41Sopenharmony_ci    // instead of this ToNumeric + Inc/Dec dance.
60191cb0ef41Sopenharmony_ci    builder()
60201cb0ef41Sopenharmony_ci        ->ToNumeric(feedback_index(count_slot))
60211cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(old_value);
60221cb0ef41Sopenharmony_ci  }
60231cb0ef41Sopenharmony_ci
60241cb0ef41Sopenharmony_ci  // Perform +1/-1 operation.
60251cb0ef41Sopenharmony_ci  builder()->UnaryOperation(expr->op(), feedback_index(count_slot));
60261cb0ef41Sopenharmony_ci
60271cb0ef41Sopenharmony_ci  // Store the value.
60281cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(expr);
60291cb0ef41Sopenharmony_ci  switch (assign_type) {
60301cb0ef41Sopenharmony_ci    case NON_PROPERTY: {
60311cb0ef41Sopenharmony_ci      VariableProxy* proxy = expr->expression()->AsVariableProxy();
60321cb0ef41Sopenharmony_ci      BuildVariableAssignment(proxy->var(), expr->op(),
60331cb0ef41Sopenharmony_ci                              proxy->hole_check_mode());
60341cb0ef41Sopenharmony_ci      break;
60351cb0ef41Sopenharmony_ci    }
60361cb0ef41Sopenharmony_ci    case NAMED_PROPERTY: {
60371cb0ef41Sopenharmony_ci      FeedbackSlot slot = GetCachedStoreICSlot(property->obj(), name);
60381cb0ef41Sopenharmony_ci      Register value;
60391cb0ef41Sopenharmony_ci      if (!execution_result()->IsEffect()) {
60401cb0ef41Sopenharmony_ci        value = register_allocator()->NewRegister();
60411cb0ef41Sopenharmony_ci        builder()->StoreAccumulatorInRegister(value);
60421cb0ef41Sopenharmony_ci      }
60431cb0ef41Sopenharmony_ci      builder()->SetNamedProperty(object, name, feedback_index(slot),
60441cb0ef41Sopenharmony_ci                                  language_mode());
60451cb0ef41Sopenharmony_ci      if (!execution_result()->IsEffect()) {
60461cb0ef41Sopenharmony_ci        builder()->LoadAccumulatorWithRegister(value);
60471cb0ef41Sopenharmony_ci      }
60481cb0ef41Sopenharmony_ci      break;
60491cb0ef41Sopenharmony_ci    }
60501cb0ef41Sopenharmony_ci    case KEYED_PROPERTY: {
60511cb0ef41Sopenharmony_ci      FeedbackSlot slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
60521cb0ef41Sopenharmony_ci      Register value;
60531cb0ef41Sopenharmony_ci      if (!execution_result()->IsEffect()) {
60541cb0ef41Sopenharmony_ci        value = register_allocator()->NewRegister();
60551cb0ef41Sopenharmony_ci        builder()->StoreAccumulatorInRegister(value);
60561cb0ef41Sopenharmony_ci      }
60571cb0ef41Sopenharmony_ci      builder()->SetKeyedProperty(object, key, feedback_index(slot),
60581cb0ef41Sopenharmony_ci                                  language_mode());
60591cb0ef41Sopenharmony_ci      if (!execution_result()->IsEffect()) {
60601cb0ef41Sopenharmony_ci        builder()->LoadAccumulatorWithRegister(value);
60611cb0ef41Sopenharmony_ci      }
60621cb0ef41Sopenharmony_ci      break;
60631cb0ef41Sopenharmony_ci    }
60641cb0ef41Sopenharmony_ci    case NAMED_SUPER_PROPERTY: {
60651cb0ef41Sopenharmony_ci      builder()
60661cb0ef41Sopenharmony_ci          ->StoreAccumulatorInRegister(super_property_args[3])
60671cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kStoreToSuper, super_property_args);
60681cb0ef41Sopenharmony_ci      break;
60691cb0ef41Sopenharmony_ci    }
60701cb0ef41Sopenharmony_ci    case KEYED_SUPER_PROPERTY: {
60711cb0ef41Sopenharmony_ci      builder()
60721cb0ef41Sopenharmony_ci          ->StoreAccumulatorInRegister(super_property_args[3])
60731cb0ef41Sopenharmony_ci          .CallRuntime(Runtime::kStoreKeyedToSuper, super_property_args);
60741cb0ef41Sopenharmony_ci      break;
60751cb0ef41Sopenharmony_ci    }
60761cb0ef41Sopenharmony_ci    case PRIVATE_SETTER_ONLY:
60771cb0ef41Sopenharmony_ci    case PRIVATE_GETTER_ONLY:
60781cb0ef41Sopenharmony_ci    case PRIVATE_METHOD: {
60791cb0ef41Sopenharmony_ci      UNREACHABLE();
60801cb0ef41Sopenharmony_ci    }
60811cb0ef41Sopenharmony_ci    case PRIVATE_GETTER_AND_SETTER: {
60821cb0ef41Sopenharmony_ci      Register value = register_allocator()->NewRegister();
60831cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(value);
60841cb0ef41Sopenharmony_ci      BuildPrivateSetterAccess(object, key, value);
60851cb0ef41Sopenharmony_ci      if (!execution_result()->IsEffect()) {
60861cb0ef41Sopenharmony_ci        builder()->LoadAccumulatorWithRegister(value);
60871cb0ef41Sopenharmony_ci      }
60881cb0ef41Sopenharmony_ci      break;
60891cb0ef41Sopenharmony_ci    }
60901cb0ef41Sopenharmony_ci  }
60911cb0ef41Sopenharmony_ci
60921cb0ef41Sopenharmony_ci  // Restore old value for postfix expressions.
60931cb0ef41Sopenharmony_ci  if (is_postfix) {
60941cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(old_value);
60951cb0ef41Sopenharmony_ci  }
60961cb0ef41Sopenharmony_ci}
60971cb0ef41Sopenharmony_ci
60981cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
60991cb0ef41Sopenharmony_ci  switch (binop->op()) {
61001cb0ef41Sopenharmony_ci    case Token::COMMA:
61011cb0ef41Sopenharmony_ci      VisitCommaExpression(binop);
61021cb0ef41Sopenharmony_ci      break;
61031cb0ef41Sopenharmony_ci    case Token::OR:
61041cb0ef41Sopenharmony_ci      VisitLogicalOrExpression(binop);
61051cb0ef41Sopenharmony_ci      break;
61061cb0ef41Sopenharmony_ci    case Token::AND:
61071cb0ef41Sopenharmony_ci      VisitLogicalAndExpression(binop);
61081cb0ef41Sopenharmony_ci      break;
61091cb0ef41Sopenharmony_ci    case Token::NULLISH:
61101cb0ef41Sopenharmony_ci      VisitNullishExpression(binop);
61111cb0ef41Sopenharmony_ci      break;
61121cb0ef41Sopenharmony_ci    default:
61131cb0ef41Sopenharmony_ci      VisitArithmeticExpression(binop);
61141cb0ef41Sopenharmony_ci      break;
61151cb0ef41Sopenharmony_ci  }
61161cb0ef41Sopenharmony_ci}
61171cb0ef41Sopenharmony_ci
61181cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitNaryOperation(NaryOperation* expr) {
61191cb0ef41Sopenharmony_ci  switch (expr->op()) {
61201cb0ef41Sopenharmony_ci    case Token::COMMA:
61211cb0ef41Sopenharmony_ci      VisitNaryCommaExpression(expr);
61221cb0ef41Sopenharmony_ci      break;
61231cb0ef41Sopenharmony_ci    case Token::OR:
61241cb0ef41Sopenharmony_ci      VisitNaryLogicalOrExpression(expr);
61251cb0ef41Sopenharmony_ci      break;
61261cb0ef41Sopenharmony_ci    case Token::AND:
61271cb0ef41Sopenharmony_ci      VisitNaryLogicalAndExpression(expr);
61281cb0ef41Sopenharmony_ci      break;
61291cb0ef41Sopenharmony_ci    case Token::NULLISH:
61301cb0ef41Sopenharmony_ci      VisitNaryNullishExpression(expr);
61311cb0ef41Sopenharmony_ci      break;
61321cb0ef41Sopenharmony_ci    default:
61331cb0ef41Sopenharmony_ci      VisitNaryArithmeticExpression(expr);
61341cb0ef41Sopenharmony_ci      break;
61351cb0ef41Sopenharmony_ci  }
61361cb0ef41Sopenharmony_ci}
61371cb0ef41Sopenharmony_ci
61381cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildLiteralCompareNil(
61391cb0ef41Sopenharmony_ci    Token::Value op, BytecodeArrayBuilder::NilValue nil) {
61401cb0ef41Sopenharmony_ci  if (execution_result()->IsTest()) {
61411cb0ef41Sopenharmony_ci    TestResultScope* test_result = execution_result()->AsTest();
61421cb0ef41Sopenharmony_ci    switch (test_result->fallthrough()) {
61431cb0ef41Sopenharmony_ci      case TestFallthrough::kThen:
61441cb0ef41Sopenharmony_ci        builder()->JumpIfNotNil(test_result->NewElseLabel(), op, nil);
61451cb0ef41Sopenharmony_ci        break;
61461cb0ef41Sopenharmony_ci      case TestFallthrough::kElse:
61471cb0ef41Sopenharmony_ci        builder()->JumpIfNil(test_result->NewThenLabel(), op, nil);
61481cb0ef41Sopenharmony_ci        break;
61491cb0ef41Sopenharmony_ci      case TestFallthrough::kNone:
61501cb0ef41Sopenharmony_ci        builder()
61511cb0ef41Sopenharmony_ci            ->JumpIfNil(test_result->NewThenLabel(), op, nil)
61521cb0ef41Sopenharmony_ci            .Jump(test_result->NewElseLabel());
61531cb0ef41Sopenharmony_ci    }
61541cb0ef41Sopenharmony_ci    test_result->SetResultConsumedByTest();
61551cb0ef41Sopenharmony_ci  } else {
61561cb0ef41Sopenharmony_ci    builder()->CompareNil(op, nil);
61571cb0ef41Sopenharmony_ci  }
61581cb0ef41Sopenharmony_ci}
61591cb0ef41Sopenharmony_ci
61601cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
61611cb0ef41Sopenharmony_ci  Expression* sub_expr;
61621cb0ef41Sopenharmony_ci  Literal* literal;
61631cb0ef41Sopenharmony_ci  if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
61641cb0ef41Sopenharmony_ci    // Emit a fast literal comparion for expressions of the form:
61651cb0ef41Sopenharmony_ci    // typeof(x) === 'string'.
61661cb0ef41Sopenharmony_ci    VisitForTypeOfValue(sub_expr);
61671cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition(expr);
61681cb0ef41Sopenharmony_ci    TestTypeOfFlags::LiteralFlag literal_flag =
61691cb0ef41Sopenharmony_ci        TestTypeOfFlags::GetFlagForLiteral(ast_string_constants(), literal);
61701cb0ef41Sopenharmony_ci    if (literal_flag == TestTypeOfFlags::LiteralFlag::kOther) {
61711cb0ef41Sopenharmony_ci      builder()->LoadFalse();
61721cb0ef41Sopenharmony_ci    } else {
61731cb0ef41Sopenharmony_ci      builder()->CompareTypeOf(literal_flag);
61741cb0ef41Sopenharmony_ci    }
61751cb0ef41Sopenharmony_ci  } else if (expr->IsLiteralCompareUndefined(&sub_expr)) {
61761cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(sub_expr);
61771cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition(expr);
61781cb0ef41Sopenharmony_ci    BuildLiteralCompareNil(expr->op(), BytecodeArrayBuilder::kUndefinedValue);
61791cb0ef41Sopenharmony_ci  } else if (expr->IsLiteralCompareNull(&sub_expr)) {
61801cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(sub_expr);
61811cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition(expr);
61821cb0ef41Sopenharmony_ci    BuildLiteralCompareNil(expr->op(), BytecodeArrayBuilder::kNullValue);
61831cb0ef41Sopenharmony_ci  } else {
61841cb0ef41Sopenharmony_ci    if (expr->op() == Token::IN && expr->left()->IsPrivateName()) {
61851cb0ef41Sopenharmony_ci      DCHECK(FLAG_harmony_private_brand_checks);
61861cb0ef41Sopenharmony_ci      Variable* var = expr->left()->AsVariableProxy()->var();
61871cb0ef41Sopenharmony_ci      if (IsPrivateMethodOrAccessorVariableMode(var->mode())) {
61881cb0ef41Sopenharmony_ci        BuildPrivateMethodIn(var, expr->right());
61891cb0ef41Sopenharmony_ci        return;
61901cb0ef41Sopenharmony_ci      }
61911cb0ef41Sopenharmony_ci      // For private fields, the code below does the right thing.
61921cb0ef41Sopenharmony_ci    }
61931cb0ef41Sopenharmony_ci
61941cb0ef41Sopenharmony_ci    Register lhs = VisitForRegisterValue(expr->left());
61951cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->right());
61961cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition(expr);
61971cb0ef41Sopenharmony_ci    FeedbackSlot slot;
61981cb0ef41Sopenharmony_ci    if (expr->op() == Token::IN) {
61991cb0ef41Sopenharmony_ci      slot = feedback_spec()->AddKeyedHasICSlot();
62001cb0ef41Sopenharmony_ci    } else if (expr->op() == Token::INSTANCEOF) {
62011cb0ef41Sopenharmony_ci      slot = feedback_spec()->AddInstanceOfSlot();
62021cb0ef41Sopenharmony_ci    } else {
62031cb0ef41Sopenharmony_ci      slot = feedback_spec()->AddCompareICSlot();
62041cb0ef41Sopenharmony_ci    }
62051cb0ef41Sopenharmony_ci    builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
62061cb0ef41Sopenharmony_ci  }
62071cb0ef41Sopenharmony_ci  // Always returns a boolean value.
62081cb0ef41Sopenharmony_ci  execution_result()->SetResultIsBoolean();
62091cb0ef41Sopenharmony_ci}
62101cb0ef41Sopenharmony_ci
62111cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
62121cb0ef41Sopenharmony_ci  FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
62131cb0ef41Sopenharmony_ci  Expression* subexpr;
62141cb0ef41Sopenharmony_ci  Smi literal;
62151cb0ef41Sopenharmony_ci  if (expr->IsSmiLiteralOperation(&subexpr, &literal)) {
62161cb0ef41Sopenharmony_ci    TypeHint type_hint = VisitForAccumulatorValue(subexpr);
62171cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition(expr);
62181cb0ef41Sopenharmony_ci    builder()->BinaryOperationSmiLiteral(expr->op(), literal,
62191cb0ef41Sopenharmony_ci                                         feedback_index(slot));
62201cb0ef41Sopenharmony_ci    if (expr->op() == Token::ADD && type_hint == TypeHint::kString) {
62211cb0ef41Sopenharmony_ci      execution_result()->SetResultIsString();
62221cb0ef41Sopenharmony_ci    }
62231cb0ef41Sopenharmony_ci  } else {
62241cb0ef41Sopenharmony_ci    TypeHint lhs_type = VisitForAccumulatorValue(expr->left());
62251cb0ef41Sopenharmony_ci    Register lhs = register_allocator()->NewRegister();
62261cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(lhs);
62271cb0ef41Sopenharmony_ci    TypeHint rhs_type = VisitForAccumulatorValue(expr->right());
62281cb0ef41Sopenharmony_ci    if (expr->op() == Token::ADD &&
62291cb0ef41Sopenharmony_ci        (lhs_type == TypeHint::kString || rhs_type == TypeHint::kString)) {
62301cb0ef41Sopenharmony_ci      execution_result()->SetResultIsString();
62311cb0ef41Sopenharmony_ci    }
62321cb0ef41Sopenharmony_ci
62331cb0ef41Sopenharmony_ci    builder()->SetExpressionPosition(expr);
62341cb0ef41Sopenharmony_ci    builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot));
62351cb0ef41Sopenharmony_ci  }
62361cb0ef41Sopenharmony_ci}
62371cb0ef41Sopenharmony_ci
62381cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitNaryArithmeticExpression(NaryOperation* expr) {
62391cb0ef41Sopenharmony_ci  // TODO(leszeks): Add support for lhs smi in commutative ops.
62401cb0ef41Sopenharmony_ci  TypeHint type_hint = VisitForAccumulatorValue(expr->first());
62411cb0ef41Sopenharmony_ci
62421cb0ef41Sopenharmony_ci  for (size_t i = 0; i < expr->subsequent_length(); ++i) {
62431cb0ef41Sopenharmony_ci    RegisterAllocationScope register_scope(this);
62441cb0ef41Sopenharmony_ci    if (expr->subsequent(i)->IsSmiLiteral()) {
62451cb0ef41Sopenharmony_ci      builder()->SetExpressionPosition(expr->subsequent_op_position(i));
62461cb0ef41Sopenharmony_ci      builder()->BinaryOperationSmiLiteral(
62471cb0ef41Sopenharmony_ci          expr->op(), expr->subsequent(i)->AsLiteral()->AsSmiLiteral(),
62481cb0ef41Sopenharmony_ci          feedback_index(feedback_spec()->AddBinaryOpICSlot()));
62491cb0ef41Sopenharmony_ci    } else {
62501cb0ef41Sopenharmony_ci      Register lhs = register_allocator()->NewRegister();
62511cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(lhs);
62521cb0ef41Sopenharmony_ci      TypeHint rhs_hint = VisitForAccumulatorValue(expr->subsequent(i));
62531cb0ef41Sopenharmony_ci      if (rhs_hint == TypeHint::kString) type_hint = TypeHint::kString;
62541cb0ef41Sopenharmony_ci      builder()->SetExpressionPosition(expr->subsequent_op_position(i));
62551cb0ef41Sopenharmony_ci      builder()->BinaryOperation(
62561cb0ef41Sopenharmony_ci          expr->op(), lhs,
62571cb0ef41Sopenharmony_ci          feedback_index(feedback_spec()->AddBinaryOpICSlot()));
62581cb0ef41Sopenharmony_ci    }
62591cb0ef41Sopenharmony_ci  }
62601cb0ef41Sopenharmony_ci
62611cb0ef41Sopenharmony_ci  if (type_hint == TypeHint::kString && expr->op() == Token::ADD) {
62621cb0ef41Sopenharmony_ci    // If any operand of an ADD is a String, a String is produced.
62631cb0ef41Sopenharmony_ci    execution_result()->SetResultIsString();
62641cb0ef41Sopenharmony_ci  }
62651cb0ef41Sopenharmony_ci}
62661cb0ef41Sopenharmony_ci
62671cb0ef41Sopenharmony_ci// Note: the actual spreading is performed by the surrounding expression's
62681cb0ef41Sopenharmony_ci// visitor.
62691cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitSpread(Spread* expr) { Visit(expr->expression()); }
62701cb0ef41Sopenharmony_ci
62711cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
62721cb0ef41Sopenharmony_ci  UNREACHABLE();
62731cb0ef41Sopenharmony_ci}
62741cb0ef41Sopenharmony_ci
62751cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitImportCallExpression(ImportCallExpression* expr) {
62761cb0ef41Sopenharmony_ci  const int register_count = expr->import_assertions() ? 3 : 2;
62771cb0ef41Sopenharmony_ci  RegisterList args = register_allocator()->NewRegisterList(register_count);
62781cb0ef41Sopenharmony_ci  VisitForRegisterValue(expr->specifier(), args[1]);
62791cb0ef41Sopenharmony_ci  if (expr->import_assertions()) {
62801cb0ef41Sopenharmony_ci    VisitForRegisterValue(expr->import_assertions(), args[2]);
62811cb0ef41Sopenharmony_ci  }
62821cb0ef41Sopenharmony_ci  builder()
62831cb0ef41Sopenharmony_ci      ->MoveRegister(Register::function_closure(), args[0])
62841cb0ef41Sopenharmony_ci      .CallRuntime(Runtime::kDynamicImportCall, args);
62851cb0ef41Sopenharmony_ci}
62861cb0ef41Sopenharmony_ci
62871cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildGetIterator(IteratorType hint) {
62881cb0ef41Sopenharmony_ci  if (hint == IteratorType::kAsync) {
62891cb0ef41Sopenharmony_ci    RegisterAllocationScope scope(this);
62901cb0ef41Sopenharmony_ci
62911cb0ef41Sopenharmony_ci    Register obj = register_allocator()->NewRegister();
62921cb0ef41Sopenharmony_ci    Register method = register_allocator()->NewRegister();
62931cb0ef41Sopenharmony_ci
62941cb0ef41Sopenharmony_ci    // Set method to GetMethod(obj, @@asyncIterator)
62951cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(obj).LoadAsyncIteratorProperty(
62961cb0ef41Sopenharmony_ci        obj, feedback_index(feedback_spec()->AddLoadICSlot()));
62971cb0ef41Sopenharmony_ci
62981cb0ef41Sopenharmony_ci    BytecodeLabel async_iterator_undefined, done;
62991cb0ef41Sopenharmony_ci    builder()->JumpIfUndefinedOrNull(&async_iterator_undefined);
63001cb0ef41Sopenharmony_ci
63011cb0ef41Sopenharmony_ci    // Let iterator be Call(method, obj)
63021cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(method).CallProperty(
63031cb0ef41Sopenharmony_ci        method, RegisterList(obj),
63041cb0ef41Sopenharmony_ci        feedback_index(feedback_spec()->AddCallICSlot()));
63051cb0ef41Sopenharmony_ci
63061cb0ef41Sopenharmony_ci    // If Type(iterator) is not Object, throw a TypeError exception.
63071cb0ef41Sopenharmony_ci    builder()->JumpIfJSReceiver(&done);
63081cb0ef41Sopenharmony_ci    builder()->CallRuntime(Runtime::kThrowSymbolAsyncIteratorInvalid);
63091cb0ef41Sopenharmony_ci
63101cb0ef41Sopenharmony_ci    builder()->Bind(&async_iterator_undefined);
63111cb0ef41Sopenharmony_ci    // If method is undefined,
63121cb0ef41Sopenharmony_ci    //     Let syncMethod be GetMethod(obj, @@iterator)
63131cb0ef41Sopenharmony_ci    builder()
63141cb0ef41Sopenharmony_ci        ->LoadIteratorProperty(obj,
63151cb0ef41Sopenharmony_ci                               feedback_index(feedback_spec()->AddLoadICSlot()))
63161cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(method);
63171cb0ef41Sopenharmony_ci
63181cb0ef41Sopenharmony_ci    //     Let syncIterator be Call(syncMethod, obj)
63191cb0ef41Sopenharmony_ci    builder()->CallProperty(method, RegisterList(obj),
63201cb0ef41Sopenharmony_ci                            feedback_index(feedback_spec()->AddCallICSlot()));
63211cb0ef41Sopenharmony_ci
63221cb0ef41Sopenharmony_ci    // Return CreateAsyncFromSyncIterator(syncIterator)
63231cb0ef41Sopenharmony_ci    // alias `method` register as it's no longer used
63241cb0ef41Sopenharmony_ci    Register sync_iter = method;
63251cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(sync_iter).CallRuntime(
63261cb0ef41Sopenharmony_ci        Runtime::kInlineCreateAsyncFromSyncIterator, sync_iter);
63271cb0ef41Sopenharmony_ci
63281cb0ef41Sopenharmony_ci    builder()->Bind(&done);
63291cb0ef41Sopenharmony_ci  } else {
63301cb0ef41Sopenharmony_ci    {
63311cb0ef41Sopenharmony_ci      RegisterAllocationScope scope(this);
63321cb0ef41Sopenharmony_ci
63331cb0ef41Sopenharmony_ci      Register obj = register_allocator()->NewRegister();
63341cb0ef41Sopenharmony_ci      int load_feedback_index =
63351cb0ef41Sopenharmony_ci          feedback_index(feedback_spec()->AddLoadICSlot());
63361cb0ef41Sopenharmony_ci      int call_feedback_index =
63371cb0ef41Sopenharmony_ci          feedback_index(feedback_spec()->AddCallICSlot());
63381cb0ef41Sopenharmony_ci
63391cb0ef41Sopenharmony_ci      // Let method be GetMethod(obj, @@iterator) and
63401cb0ef41Sopenharmony_ci      // iterator be Call(method, obj).
63411cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(obj).GetIterator(
63421cb0ef41Sopenharmony_ci          obj, load_feedback_index, call_feedback_index);
63431cb0ef41Sopenharmony_ci    }
63441cb0ef41Sopenharmony_ci
63451cb0ef41Sopenharmony_ci    // If Type(iterator) is not Object, throw a TypeError exception.
63461cb0ef41Sopenharmony_ci    BytecodeLabel no_type_error;
63471cb0ef41Sopenharmony_ci    builder()->JumpIfJSReceiver(&no_type_error);
63481cb0ef41Sopenharmony_ci    builder()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid);
63491cb0ef41Sopenharmony_ci    builder()->Bind(&no_type_error);
63501cb0ef41Sopenharmony_ci  }
63511cb0ef41Sopenharmony_ci}
63521cb0ef41Sopenharmony_ci
63531cb0ef41Sopenharmony_ci// Returns an IteratorRecord which is valid for the lifetime of the current
63541cb0ef41Sopenharmony_ci// register_allocation_scope.
63551cb0ef41Sopenharmony_ciBytecodeGenerator::IteratorRecord BytecodeGenerator::BuildGetIteratorRecord(
63561cb0ef41Sopenharmony_ci    Register next, Register object, IteratorType hint) {
63571cb0ef41Sopenharmony_ci  DCHECK(next.is_valid() && object.is_valid());
63581cb0ef41Sopenharmony_ci  BuildGetIterator(hint);
63591cb0ef41Sopenharmony_ci
63601cb0ef41Sopenharmony_ci  builder()
63611cb0ef41Sopenharmony_ci      ->StoreAccumulatorInRegister(object)
63621cb0ef41Sopenharmony_ci      .LoadNamedProperty(object, ast_string_constants()->next_string(),
63631cb0ef41Sopenharmony_ci                         feedback_index(feedback_spec()->AddLoadICSlot()))
63641cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(next);
63651cb0ef41Sopenharmony_ci  return IteratorRecord(object, next, hint);
63661cb0ef41Sopenharmony_ci}
63671cb0ef41Sopenharmony_ci
63681cb0ef41Sopenharmony_ciBytecodeGenerator::IteratorRecord BytecodeGenerator::BuildGetIteratorRecord(
63691cb0ef41Sopenharmony_ci    IteratorType hint) {
63701cb0ef41Sopenharmony_ci  Register next = register_allocator()->NewRegister();
63711cb0ef41Sopenharmony_ci  Register object = register_allocator()->NewRegister();
63721cb0ef41Sopenharmony_ci  return BuildGetIteratorRecord(next, object, hint);
63731cb0ef41Sopenharmony_ci}
63741cb0ef41Sopenharmony_ci
63751cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildIteratorNext(const IteratorRecord& iterator,
63761cb0ef41Sopenharmony_ci                                          Register next_result) {
63771cb0ef41Sopenharmony_ci  DCHECK(next_result.is_valid());
63781cb0ef41Sopenharmony_ci  builder()->CallProperty(iterator.next(), RegisterList(iterator.object()),
63791cb0ef41Sopenharmony_ci                          feedback_index(feedback_spec()->AddCallICSlot()));
63801cb0ef41Sopenharmony_ci
63811cb0ef41Sopenharmony_ci  if (iterator.type() == IteratorType::kAsync) {
63821cb0ef41Sopenharmony_ci    BuildAwait();
63831cb0ef41Sopenharmony_ci  }
63841cb0ef41Sopenharmony_ci
63851cb0ef41Sopenharmony_ci  BytecodeLabel is_object;
63861cb0ef41Sopenharmony_ci  builder()
63871cb0ef41Sopenharmony_ci      ->StoreAccumulatorInRegister(next_result)
63881cb0ef41Sopenharmony_ci      .JumpIfJSReceiver(&is_object)
63891cb0ef41Sopenharmony_ci      .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, next_result)
63901cb0ef41Sopenharmony_ci      .Bind(&is_object);
63911cb0ef41Sopenharmony_ci}
63921cb0ef41Sopenharmony_ci
63931cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildCallIteratorMethod(Register iterator,
63941cb0ef41Sopenharmony_ci                                                const AstRawString* method_name,
63951cb0ef41Sopenharmony_ci                                                RegisterList receiver_and_args,
63961cb0ef41Sopenharmony_ci                                                BytecodeLabel* if_called,
63971cb0ef41Sopenharmony_ci                                                BytecodeLabels* if_notcalled) {
63981cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
63991cb0ef41Sopenharmony_ci
64001cb0ef41Sopenharmony_ci  Register method = register_allocator()->NewRegister();
64011cb0ef41Sopenharmony_ci  FeedbackSlot slot = feedback_spec()->AddLoadICSlot();
64021cb0ef41Sopenharmony_ci  builder()
64031cb0ef41Sopenharmony_ci      ->LoadNamedProperty(iterator, method_name, feedback_index(slot))
64041cb0ef41Sopenharmony_ci      .JumpIfUndefinedOrNull(if_notcalled->New())
64051cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(method)
64061cb0ef41Sopenharmony_ci      .CallProperty(method, receiver_and_args,
64071cb0ef41Sopenharmony_ci                    feedback_index(feedback_spec()->AddCallICSlot()))
64081cb0ef41Sopenharmony_ci      .Jump(if_called);
64091cb0ef41Sopenharmony_ci}
64101cb0ef41Sopenharmony_ci
64111cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildIteratorClose(const IteratorRecord& iterator,
64121cb0ef41Sopenharmony_ci                                           Expression* expr) {
64131cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
64141cb0ef41Sopenharmony_ci  BytecodeLabels done(zone());
64151cb0ef41Sopenharmony_ci  BytecodeLabel if_called;
64161cb0ef41Sopenharmony_ci  RegisterList args = RegisterList(iterator.object());
64171cb0ef41Sopenharmony_ci  BuildCallIteratorMethod(iterator.object(),
64181cb0ef41Sopenharmony_ci                          ast_string_constants()->return_string(), args,
64191cb0ef41Sopenharmony_ci                          &if_called, &done);
64201cb0ef41Sopenharmony_ci  builder()->Bind(&if_called);
64211cb0ef41Sopenharmony_ci
64221cb0ef41Sopenharmony_ci  if (iterator.type() == IteratorType::kAsync) {
64231cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(expr);
64241cb0ef41Sopenharmony_ci    BuildAwait(expr->position());
64251cb0ef41Sopenharmony_ci  }
64261cb0ef41Sopenharmony_ci
64271cb0ef41Sopenharmony_ci  builder()->JumpIfJSReceiver(done.New());
64281cb0ef41Sopenharmony_ci  {
64291cb0ef41Sopenharmony_ci    RegisterAllocationScope inner_register_scope(this);
64301cb0ef41Sopenharmony_ci    Register return_result = register_allocator()->NewRegister();
64311cb0ef41Sopenharmony_ci    builder()
64321cb0ef41Sopenharmony_ci        ->StoreAccumulatorInRegister(return_result)
64331cb0ef41Sopenharmony_ci        .CallRuntime(Runtime::kThrowIteratorResultNotAnObject, return_result);
64341cb0ef41Sopenharmony_ci  }
64351cb0ef41Sopenharmony_ci
64361cb0ef41Sopenharmony_ci  done.Bind(builder());
64371cb0ef41Sopenharmony_ci}
64381cb0ef41Sopenharmony_ci
64391cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitGetTemplateObject(GetTemplateObject* expr) {
64401cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(expr);
64411cb0ef41Sopenharmony_ci  size_t entry = builder()->AllocateDeferredConstantPoolEntry();
64421cb0ef41Sopenharmony_ci  template_objects_.push_back(std::make_pair(expr, entry));
64431cb0ef41Sopenharmony_ci  FeedbackSlot literal_slot = feedback_spec()->AddLiteralSlot();
64441cb0ef41Sopenharmony_ci  builder()->GetTemplateObject(entry, feedback_index(literal_slot));
64451cb0ef41Sopenharmony_ci}
64461cb0ef41Sopenharmony_ci
64471cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitTemplateLiteral(TemplateLiteral* expr) {
64481cb0ef41Sopenharmony_ci  const ZonePtrList<const AstRawString>& parts = *expr->string_parts();
64491cb0ef41Sopenharmony_ci  const ZonePtrList<Expression>& substitutions = *expr->substitutions();
64501cb0ef41Sopenharmony_ci  // Template strings with no substitutions are turned into StringLiterals.
64511cb0ef41Sopenharmony_ci  DCHECK_GT(substitutions.length(), 0);
64521cb0ef41Sopenharmony_ci  DCHECK_EQ(parts.length(), substitutions.length() + 1);
64531cb0ef41Sopenharmony_ci
64541cb0ef41Sopenharmony_ci  // Generate string concatenation
64551cb0ef41Sopenharmony_ci  // TODO(caitp): Don't generate feedback slot if it's not used --- introduce
64561cb0ef41Sopenharmony_ci  // a simple, concise, reusable mechanism to lazily create reusable slots.
64571cb0ef41Sopenharmony_ci  FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
64581cb0ef41Sopenharmony_ci  Register last_part = register_allocator()->NewRegister();
64591cb0ef41Sopenharmony_ci  bool last_part_valid = false;
64601cb0ef41Sopenharmony_ci
64611cb0ef41Sopenharmony_ci  builder()->SetExpressionPosition(expr);
64621cb0ef41Sopenharmony_ci  for (int i = 0; i < substitutions.length(); ++i) {
64631cb0ef41Sopenharmony_ci    if (i != 0) {
64641cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(last_part);
64651cb0ef41Sopenharmony_ci      last_part_valid = true;
64661cb0ef41Sopenharmony_ci    }
64671cb0ef41Sopenharmony_ci
64681cb0ef41Sopenharmony_ci    if (!parts[i]->IsEmpty()) {
64691cb0ef41Sopenharmony_ci      builder()->LoadLiteral(parts[i]);
64701cb0ef41Sopenharmony_ci      if (last_part_valid) {
64711cb0ef41Sopenharmony_ci        builder()->BinaryOperation(Token::ADD, last_part, feedback_index(slot));
64721cb0ef41Sopenharmony_ci      }
64731cb0ef41Sopenharmony_ci      builder()->StoreAccumulatorInRegister(last_part);
64741cb0ef41Sopenharmony_ci      last_part_valid = true;
64751cb0ef41Sopenharmony_ci    }
64761cb0ef41Sopenharmony_ci
64771cb0ef41Sopenharmony_ci    TypeHint type_hint = VisitForAccumulatorValue(substitutions[i]);
64781cb0ef41Sopenharmony_ci    if (type_hint != TypeHint::kString) {
64791cb0ef41Sopenharmony_ci      builder()->ToString();
64801cb0ef41Sopenharmony_ci    }
64811cb0ef41Sopenharmony_ci    if (last_part_valid) {
64821cb0ef41Sopenharmony_ci      builder()->BinaryOperation(Token::ADD, last_part, feedback_index(slot));
64831cb0ef41Sopenharmony_ci    }
64841cb0ef41Sopenharmony_ci    last_part_valid = false;
64851cb0ef41Sopenharmony_ci  }
64861cb0ef41Sopenharmony_ci
64871cb0ef41Sopenharmony_ci  if (!parts.last()->IsEmpty()) {
64881cb0ef41Sopenharmony_ci    builder()->StoreAccumulatorInRegister(last_part);
64891cb0ef41Sopenharmony_ci    builder()->LoadLiteral(parts.last());
64901cb0ef41Sopenharmony_ci    builder()->BinaryOperation(Token::ADD, last_part, feedback_index(slot));
64911cb0ef41Sopenharmony_ci  }
64921cb0ef41Sopenharmony_ci}
64931cb0ef41Sopenharmony_ci
64941cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildThisVariableLoad() {
64951cb0ef41Sopenharmony_ci  DeclarationScope* receiver_scope = closure_scope()->GetReceiverScope();
64961cb0ef41Sopenharmony_ci  Variable* var = receiver_scope->receiver();
64971cb0ef41Sopenharmony_ci  // TODO(littledan): implement 'this' hole check elimination.
64981cb0ef41Sopenharmony_ci  HoleCheckMode hole_check_mode =
64991cb0ef41Sopenharmony_ci      IsDerivedConstructor(receiver_scope->function_kind())
65001cb0ef41Sopenharmony_ci          ? HoleCheckMode::kRequired
65011cb0ef41Sopenharmony_ci          : HoleCheckMode::kElided;
65021cb0ef41Sopenharmony_ci  BuildVariableLoad(var, hole_check_mode);
65031cb0ef41Sopenharmony_ci}
65041cb0ef41Sopenharmony_ci
65051cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitThisExpression(ThisExpression* expr) {
65061cb0ef41Sopenharmony_ci  BuildThisVariableLoad();
65071cb0ef41Sopenharmony_ci}
65081cb0ef41Sopenharmony_ci
65091cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
65101cb0ef41Sopenharmony_ci  // Handled by VisitCall().
65111cb0ef41Sopenharmony_ci  UNREACHABLE();
65121cb0ef41Sopenharmony_ci}
65131cb0ef41Sopenharmony_ci
65141cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitSuperPropertyReference(
65151cb0ef41Sopenharmony_ci    SuperPropertyReference* expr) {
65161cb0ef41Sopenharmony_ci  builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError);
65171cb0ef41Sopenharmony_ci}
65181cb0ef41Sopenharmony_ci
65191cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
65201cb0ef41Sopenharmony_ci  VisitForEffect(binop->left());
65211cb0ef41Sopenharmony_ci  Visit(binop->right());
65221cb0ef41Sopenharmony_ci}
65231cb0ef41Sopenharmony_ci
65241cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitNaryCommaExpression(NaryOperation* expr) {
65251cb0ef41Sopenharmony_ci  DCHECK_GT(expr->subsequent_length(), 0);
65261cb0ef41Sopenharmony_ci
65271cb0ef41Sopenharmony_ci  VisitForEffect(expr->first());
65281cb0ef41Sopenharmony_ci  for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
65291cb0ef41Sopenharmony_ci    VisitForEffect(expr->subsequent(i));
65301cb0ef41Sopenharmony_ci  }
65311cb0ef41Sopenharmony_ci  Visit(expr->subsequent(expr->subsequent_length() - 1));
65321cb0ef41Sopenharmony_ci}
65331cb0ef41Sopenharmony_ci
65341cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitLogicalTestSubExpression(
65351cb0ef41Sopenharmony_ci    Token::Value token, Expression* expr, BytecodeLabels* then_labels,
65361cb0ef41Sopenharmony_ci    BytecodeLabels* else_labels, int coverage_slot) {
65371cb0ef41Sopenharmony_ci  DCHECK(token == Token::OR || token == Token::AND || token == Token::NULLISH);
65381cb0ef41Sopenharmony_ci
65391cb0ef41Sopenharmony_ci  BytecodeLabels test_next(zone());
65401cb0ef41Sopenharmony_ci  if (token == Token::OR) {
65411cb0ef41Sopenharmony_ci    VisitForTest(expr, then_labels, &test_next, TestFallthrough::kElse);
65421cb0ef41Sopenharmony_ci  } else if (token == Token::AND) {
65431cb0ef41Sopenharmony_ci    VisitForTest(expr, &test_next, else_labels, TestFallthrough::kThen);
65441cb0ef41Sopenharmony_ci  } else {
65451cb0ef41Sopenharmony_ci    DCHECK_EQ(Token::NULLISH, token);
65461cb0ef41Sopenharmony_ci    VisitForNullishTest(expr, then_labels, &test_next, else_labels);
65471cb0ef41Sopenharmony_ci  }
65481cb0ef41Sopenharmony_ci  test_next.Bind(builder());
65491cb0ef41Sopenharmony_ci
65501cb0ef41Sopenharmony_ci  BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
65511cb0ef41Sopenharmony_ci}
65521cb0ef41Sopenharmony_ci
65531cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitLogicalTest(Token::Value token, Expression* left,
65541cb0ef41Sopenharmony_ci                                         Expression* right,
65551cb0ef41Sopenharmony_ci                                         int right_coverage_slot) {
65561cb0ef41Sopenharmony_ci  DCHECK(token == Token::OR || token == Token::AND || token == Token::NULLISH);
65571cb0ef41Sopenharmony_ci  TestResultScope* test_result = execution_result()->AsTest();
65581cb0ef41Sopenharmony_ci  BytecodeLabels* then_labels = test_result->then_labels();
65591cb0ef41Sopenharmony_ci  BytecodeLabels* else_labels = test_result->else_labels();
65601cb0ef41Sopenharmony_ci  TestFallthrough fallthrough = test_result->fallthrough();
65611cb0ef41Sopenharmony_ci
65621cb0ef41Sopenharmony_ci  VisitLogicalTestSubExpression(token, left, then_labels, else_labels,
65631cb0ef41Sopenharmony_ci                                right_coverage_slot);
65641cb0ef41Sopenharmony_ci  // The last test has the same then, else and fallthrough as the parent test.
65651cb0ef41Sopenharmony_ci  VisitForTest(right, then_labels, else_labels, fallthrough);
65661cb0ef41Sopenharmony_ci}
65671cb0ef41Sopenharmony_ci
65681cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitNaryLogicalTest(
65691cb0ef41Sopenharmony_ci    Token::Value token, NaryOperation* expr,
65701cb0ef41Sopenharmony_ci    const NaryCodeCoverageSlots* coverage_slots) {
65711cb0ef41Sopenharmony_ci  DCHECK(token == Token::OR || token == Token::AND || token == Token::NULLISH);
65721cb0ef41Sopenharmony_ci  DCHECK_GT(expr->subsequent_length(), 0);
65731cb0ef41Sopenharmony_ci
65741cb0ef41Sopenharmony_ci  TestResultScope* test_result = execution_result()->AsTest();
65751cb0ef41Sopenharmony_ci  BytecodeLabels* then_labels = test_result->then_labels();
65761cb0ef41Sopenharmony_ci  BytecodeLabels* else_labels = test_result->else_labels();
65771cb0ef41Sopenharmony_ci  TestFallthrough fallthrough = test_result->fallthrough();
65781cb0ef41Sopenharmony_ci
65791cb0ef41Sopenharmony_ci  VisitLogicalTestSubExpression(token, expr->first(), then_labels, else_labels,
65801cb0ef41Sopenharmony_ci                                coverage_slots->GetSlotFor(0));
65811cb0ef41Sopenharmony_ci  for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
65821cb0ef41Sopenharmony_ci    VisitLogicalTestSubExpression(token, expr->subsequent(i), then_labels,
65831cb0ef41Sopenharmony_ci                                  else_labels,
65841cb0ef41Sopenharmony_ci                                  coverage_slots->GetSlotFor(i + 1));
65851cb0ef41Sopenharmony_ci  }
65861cb0ef41Sopenharmony_ci  // The last test has the same then, else and fallthrough as the parent test.
65871cb0ef41Sopenharmony_ci  VisitForTest(expr->subsequent(expr->subsequent_length() - 1), then_labels,
65881cb0ef41Sopenharmony_ci               else_labels, fallthrough);
65891cb0ef41Sopenharmony_ci}
65901cb0ef41Sopenharmony_ci
65911cb0ef41Sopenharmony_cibool BytecodeGenerator::VisitLogicalOrSubExpression(Expression* expr,
65921cb0ef41Sopenharmony_ci                                                    BytecodeLabels* end_labels,
65931cb0ef41Sopenharmony_ci                                                    int coverage_slot) {
65941cb0ef41Sopenharmony_ci  if (expr->ToBooleanIsTrue()) {
65951cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr);
65961cb0ef41Sopenharmony_ci    end_labels->Bind(builder());
65971cb0ef41Sopenharmony_ci    return true;
65981cb0ef41Sopenharmony_ci  } else if (!expr->ToBooleanIsFalse()) {
65991cb0ef41Sopenharmony_ci    TypeHint type_hint = VisitForAccumulatorValue(expr);
66001cb0ef41Sopenharmony_ci    builder()->JumpIfTrue(ToBooleanModeFromTypeHint(type_hint),
66011cb0ef41Sopenharmony_ci                          end_labels->New());
66021cb0ef41Sopenharmony_ci  }
66031cb0ef41Sopenharmony_ci
66041cb0ef41Sopenharmony_ci  BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
66051cb0ef41Sopenharmony_ci
66061cb0ef41Sopenharmony_ci  return false;
66071cb0ef41Sopenharmony_ci}
66081cb0ef41Sopenharmony_ci
66091cb0ef41Sopenharmony_cibool BytecodeGenerator::VisitLogicalAndSubExpression(Expression* expr,
66101cb0ef41Sopenharmony_ci                                                     BytecodeLabels* end_labels,
66111cb0ef41Sopenharmony_ci                                                     int coverage_slot) {
66121cb0ef41Sopenharmony_ci  if (expr->ToBooleanIsFalse()) {
66131cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr);
66141cb0ef41Sopenharmony_ci    end_labels->Bind(builder());
66151cb0ef41Sopenharmony_ci    return true;
66161cb0ef41Sopenharmony_ci  } else if (!expr->ToBooleanIsTrue()) {
66171cb0ef41Sopenharmony_ci    TypeHint type_hint = VisitForAccumulatorValue(expr);
66181cb0ef41Sopenharmony_ci    builder()->JumpIfFalse(ToBooleanModeFromTypeHint(type_hint),
66191cb0ef41Sopenharmony_ci                           end_labels->New());
66201cb0ef41Sopenharmony_ci  }
66211cb0ef41Sopenharmony_ci
66221cb0ef41Sopenharmony_ci  BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
66231cb0ef41Sopenharmony_ci
66241cb0ef41Sopenharmony_ci  return false;
66251cb0ef41Sopenharmony_ci}
66261cb0ef41Sopenharmony_ci
66271cb0ef41Sopenharmony_cibool BytecodeGenerator::VisitNullishSubExpression(Expression* expr,
66281cb0ef41Sopenharmony_ci                                                  BytecodeLabels* end_labels,
66291cb0ef41Sopenharmony_ci                                                  int coverage_slot) {
66301cb0ef41Sopenharmony_ci  if (expr->IsLiteralButNotNullOrUndefined()) {
66311cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr);
66321cb0ef41Sopenharmony_ci    end_labels->Bind(builder());
66331cb0ef41Sopenharmony_ci    return true;
66341cb0ef41Sopenharmony_ci  } else if (!expr->IsNullOrUndefinedLiteral()) {
66351cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr);
66361cb0ef41Sopenharmony_ci    BytecodeLabel is_null_or_undefined;
66371cb0ef41Sopenharmony_ci    builder()
66381cb0ef41Sopenharmony_ci        ->JumpIfUndefinedOrNull(&is_null_or_undefined)
66391cb0ef41Sopenharmony_ci        .Jump(end_labels->New());
66401cb0ef41Sopenharmony_ci    builder()->Bind(&is_null_or_undefined);
66411cb0ef41Sopenharmony_ci  }
66421cb0ef41Sopenharmony_ci
66431cb0ef41Sopenharmony_ci  BuildIncrementBlockCoverageCounterIfEnabled(coverage_slot);
66441cb0ef41Sopenharmony_ci
66451cb0ef41Sopenharmony_ci  return false;
66461cb0ef41Sopenharmony_ci}
66471cb0ef41Sopenharmony_ci
66481cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
66491cb0ef41Sopenharmony_ci  Expression* left = binop->left();
66501cb0ef41Sopenharmony_ci  Expression* right = binop->right();
66511cb0ef41Sopenharmony_ci
66521cb0ef41Sopenharmony_ci  int right_coverage_slot =
66531cb0ef41Sopenharmony_ci      AllocateBlockCoverageSlotIfEnabled(binop, SourceRangeKind::kRight);
66541cb0ef41Sopenharmony_ci
66551cb0ef41Sopenharmony_ci  if (execution_result()->IsTest()) {
66561cb0ef41Sopenharmony_ci    TestResultScope* test_result = execution_result()->AsTest();
66571cb0ef41Sopenharmony_ci    if (left->ToBooleanIsTrue()) {
66581cb0ef41Sopenharmony_ci      builder()->Jump(test_result->NewThenLabel());
66591cb0ef41Sopenharmony_ci    } else if (left->ToBooleanIsFalse() && right->ToBooleanIsFalse()) {
66601cb0ef41Sopenharmony_ci      BuildIncrementBlockCoverageCounterIfEnabled(right_coverage_slot);
66611cb0ef41Sopenharmony_ci      builder()->Jump(test_result->NewElseLabel());
66621cb0ef41Sopenharmony_ci    } else {
66631cb0ef41Sopenharmony_ci      VisitLogicalTest(Token::OR, left, right, right_coverage_slot);
66641cb0ef41Sopenharmony_ci    }
66651cb0ef41Sopenharmony_ci    test_result->SetResultConsumedByTest();
66661cb0ef41Sopenharmony_ci  } else {
66671cb0ef41Sopenharmony_ci    BytecodeLabels end_labels(zone());
66681cb0ef41Sopenharmony_ci    if (VisitLogicalOrSubExpression(left, &end_labels, right_coverage_slot)) {
66691cb0ef41Sopenharmony_ci      return;
66701cb0ef41Sopenharmony_ci    }
66711cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(right);
66721cb0ef41Sopenharmony_ci    end_labels.Bind(builder());
66731cb0ef41Sopenharmony_ci  }
66741cb0ef41Sopenharmony_ci}
66751cb0ef41Sopenharmony_ci
66761cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitNaryLogicalOrExpression(NaryOperation* expr) {
66771cb0ef41Sopenharmony_ci  Expression* first = expr->first();
66781cb0ef41Sopenharmony_ci  DCHECK_GT(expr->subsequent_length(), 0);
66791cb0ef41Sopenharmony_ci
66801cb0ef41Sopenharmony_ci  NaryCodeCoverageSlots coverage_slots(this, expr);
66811cb0ef41Sopenharmony_ci
66821cb0ef41Sopenharmony_ci  if (execution_result()->IsTest()) {
66831cb0ef41Sopenharmony_ci    TestResultScope* test_result = execution_result()->AsTest();
66841cb0ef41Sopenharmony_ci    if (first->ToBooleanIsTrue()) {
66851cb0ef41Sopenharmony_ci      builder()->Jump(test_result->NewThenLabel());
66861cb0ef41Sopenharmony_ci    } else {
66871cb0ef41Sopenharmony_ci      VisitNaryLogicalTest(Token::OR, expr, &coverage_slots);
66881cb0ef41Sopenharmony_ci    }
66891cb0ef41Sopenharmony_ci    test_result->SetResultConsumedByTest();
66901cb0ef41Sopenharmony_ci  } else {
66911cb0ef41Sopenharmony_ci    BytecodeLabels end_labels(zone());
66921cb0ef41Sopenharmony_ci    if (VisitLogicalOrSubExpression(first, &end_labels,
66931cb0ef41Sopenharmony_ci                                    coverage_slots.GetSlotFor(0))) {
66941cb0ef41Sopenharmony_ci      return;
66951cb0ef41Sopenharmony_ci    }
66961cb0ef41Sopenharmony_ci    for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
66971cb0ef41Sopenharmony_ci      if (VisitLogicalOrSubExpression(expr->subsequent(i), &end_labels,
66981cb0ef41Sopenharmony_ci                                      coverage_slots.GetSlotFor(i + 1))) {
66991cb0ef41Sopenharmony_ci        return;
67001cb0ef41Sopenharmony_ci      }
67011cb0ef41Sopenharmony_ci    }
67021cb0ef41Sopenharmony_ci    // We have to visit the last value even if it's true, because we need its
67031cb0ef41Sopenharmony_ci    // actual value.
67041cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->subsequent(expr->subsequent_length() - 1));
67051cb0ef41Sopenharmony_ci    end_labels.Bind(builder());
67061cb0ef41Sopenharmony_ci  }
67071cb0ef41Sopenharmony_ci}
67081cb0ef41Sopenharmony_ci
67091cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
67101cb0ef41Sopenharmony_ci  Expression* left = binop->left();
67111cb0ef41Sopenharmony_ci  Expression* right = binop->right();
67121cb0ef41Sopenharmony_ci
67131cb0ef41Sopenharmony_ci  int right_coverage_slot =
67141cb0ef41Sopenharmony_ci      AllocateBlockCoverageSlotIfEnabled(binop, SourceRangeKind::kRight);
67151cb0ef41Sopenharmony_ci
67161cb0ef41Sopenharmony_ci  if (execution_result()->IsTest()) {
67171cb0ef41Sopenharmony_ci    TestResultScope* test_result = execution_result()->AsTest();
67181cb0ef41Sopenharmony_ci    if (left->ToBooleanIsFalse()) {
67191cb0ef41Sopenharmony_ci      builder()->Jump(test_result->NewElseLabel());
67201cb0ef41Sopenharmony_ci    } else if (left->ToBooleanIsTrue() && right->ToBooleanIsTrue()) {
67211cb0ef41Sopenharmony_ci      BuildIncrementBlockCoverageCounterIfEnabled(right_coverage_slot);
67221cb0ef41Sopenharmony_ci      builder()->Jump(test_result->NewThenLabel());
67231cb0ef41Sopenharmony_ci    } else {
67241cb0ef41Sopenharmony_ci      VisitLogicalTest(Token::AND, left, right, right_coverage_slot);
67251cb0ef41Sopenharmony_ci    }
67261cb0ef41Sopenharmony_ci    test_result->SetResultConsumedByTest();
67271cb0ef41Sopenharmony_ci  } else {
67281cb0ef41Sopenharmony_ci    BytecodeLabels end_labels(zone());
67291cb0ef41Sopenharmony_ci    if (VisitLogicalAndSubExpression(left, &end_labels, right_coverage_slot)) {
67301cb0ef41Sopenharmony_ci      return;
67311cb0ef41Sopenharmony_ci    }
67321cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(right);
67331cb0ef41Sopenharmony_ci    end_labels.Bind(builder());
67341cb0ef41Sopenharmony_ci  }
67351cb0ef41Sopenharmony_ci}
67361cb0ef41Sopenharmony_ci
67371cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitNaryLogicalAndExpression(NaryOperation* expr) {
67381cb0ef41Sopenharmony_ci  Expression* first = expr->first();
67391cb0ef41Sopenharmony_ci  DCHECK_GT(expr->subsequent_length(), 0);
67401cb0ef41Sopenharmony_ci
67411cb0ef41Sopenharmony_ci  NaryCodeCoverageSlots coverage_slots(this, expr);
67421cb0ef41Sopenharmony_ci
67431cb0ef41Sopenharmony_ci  if (execution_result()->IsTest()) {
67441cb0ef41Sopenharmony_ci    TestResultScope* test_result = execution_result()->AsTest();
67451cb0ef41Sopenharmony_ci    if (first->ToBooleanIsFalse()) {
67461cb0ef41Sopenharmony_ci      builder()->Jump(test_result->NewElseLabel());
67471cb0ef41Sopenharmony_ci    } else {
67481cb0ef41Sopenharmony_ci      VisitNaryLogicalTest(Token::AND, expr, &coverage_slots);
67491cb0ef41Sopenharmony_ci    }
67501cb0ef41Sopenharmony_ci    test_result->SetResultConsumedByTest();
67511cb0ef41Sopenharmony_ci  } else {
67521cb0ef41Sopenharmony_ci    BytecodeLabels end_labels(zone());
67531cb0ef41Sopenharmony_ci    if (VisitLogicalAndSubExpression(first, &end_labels,
67541cb0ef41Sopenharmony_ci                                     coverage_slots.GetSlotFor(0))) {
67551cb0ef41Sopenharmony_ci      return;
67561cb0ef41Sopenharmony_ci    }
67571cb0ef41Sopenharmony_ci    for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
67581cb0ef41Sopenharmony_ci      if (VisitLogicalAndSubExpression(expr->subsequent(i), &end_labels,
67591cb0ef41Sopenharmony_ci                                       coverage_slots.GetSlotFor(i + 1))) {
67601cb0ef41Sopenharmony_ci        return;
67611cb0ef41Sopenharmony_ci      }
67621cb0ef41Sopenharmony_ci    }
67631cb0ef41Sopenharmony_ci    // We have to visit the last value even if it's false, because we need its
67641cb0ef41Sopenharmony_ci    // actual value.
67651cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->subsequent(expr->subsequent_length() - 1));
67661cb0ef41Sopenharmony_ci    end_labels.Bind(builder());
67671cb0ef41Sopenharmony_ci  }
67681cb0ef41Sopenharmony_ci}
67691cb0ef41Sopenharmony_ci
67701cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitNullishExpression(BinaryOperation* binop) {
67711cb0ef41Sopenharmony_ci  Expression* left = binop->left();
67721cb0ef41Sopenharmony_ci  Expression* right = binop->right();
67731cb0ef41Sopenharmony_ci
67741cb0ef41Sopenharmony_ci  int right_coverage_slot =
67751cb0ef41Sopenharmony_ci      AllocateBlockCoverageSlotIfEnabled(binop, SourceRangeKind::kRight);
67761cb0ef41Sopenharmony_ci
67771cb0ef41Sopenharmony_ci  if (execution_result()->IsTest()) {
67781cb0ef41Sopenharmony_ci    TestResultScope* test_result = execution_result()->AsTest();
67791cb0ef41Sopenharmony_ci    if (left->IsLiteralButNotNullOrUndefined() && left->ToBooleanIsTrue()) {
67801cb0ef41Sopenharmony_ci      builder()->Jump(test_result->NewThenLabel());
67811cb0ef41Sopenharmony_ci    } else if (left->IsNullOrUndefinedLiteral() &&
67821cb0ef41Sopenharmony_ci               right->IsNullOrUndefinedLiteral()) {
67831cb0ef41Sopenharmony_ci      BuildIncrementBlockCoverageCounterIfEnabled(right_coverage_slot);
67841cb0ef41Sopenharmony_ci      builder()->Jump(test_result->NewElseLabel());
67851cb0ef41Sopenharmony_ci    } else {
67861cb0ef41Sopenharmony_ci      VisitLogicalTest(Token::NULLISH, left, right, right_coverage_slot);
67871cb0ef41Sopenharmony_ci    }
67881cb0ef41Sopenharmony_ci    test_result->SetResultConsumedByTest();
67891cb0ef41Sopenharmony_ci  } else {
67901cb0ef41Sopenharmony_ci    BytecodeLabels end_labels(zone());
67911cb0ef41Sopenharmony_ci    if (VisitNullishSubExpression(left, &end_labels, right_coverage_slot)) {
67921cb0ef41Sopenharmony_ci      return;
67931cb0ef41Sopenharmony_ci    }
67941cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(right);
67951cb0ef41Sopenharmony_ci    end_labels.Bind(builder());
67961cb0ef41Sopenharmony_ci  }
67971cb0ef41Sopenharmony_ci}
67981cb0ef41Sopenharmony_ci
67991cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitNaryNullishExpression(NaryOperation* expr) {
68001cb0ef41Sopenharmony_ci  Expression* first = expr->first();
68011cb0ef41Sopenharmony_ci  DCHECK_GT(expr->subsequent_length(), 0);
68021cb0ef41Sopenharmony_ci
68031cb0ef41Sopenharmony_ci  NaryCodeCoverageSlots coverage_slots(this, expr);
68041cb0ef41Sopenharmony_ci
68051cb0ef41Sopenharmony_ci  if (execution_result()->IsTest()) {
68061cb0ef41Sopenharmony_ci    TestResultScope* test_result = execution_result()->AsTest();
68071cb0ef41Sopenharmony_ci    if (first->IsLiteralButNotNullOrUndefined() && first->ToBooleanIsTrue()) {
68081cb0ef41Sopenharmony_ci      builder()->Jump(test_result->NewThenLabel());
68091cb0ef41Sopenharmony_ci    } else {
68101cb0ef41Sopenharmony_ci      VisitNaryLogicalTest(Token::NULLISH, expr, &coverage_slots);
68111cb0ef41Sopenharmony_ci    }
68121cb0ef41Sopenharmony_ci    test_result->SetResultConsumedByTest();
68131cb0ef41Sopenharmony_ci  } else {
68141cb0ef41Sopenharmony_ci    BytecodeLabels end_labels(zone());
68151cb0ef41Sopenharmony_ci    if (VisitNullishSubExpression(first, &end_labels,
68161cb0ef41Sopenharmony_ci                                  coverage_slots.GetSlotFor(0))) {
68171cb0ef41Sopenharmony_ci      return;
68181cb0ef41Sopenharmony_ci    }
68191cb0ef41Sopenharmony_ci    for (size_t i = 0; i < expr->subsequent_length() - 1; ++i) {
68201cb0ef41Sopenharmony_ci      if (VisitNullishSubExpression(expr->subsequent(i), &end_labels,
68211cb0ef41Sopenharmony_ci                                    coverage_slots.GetSlotFor(i + 1))) {
68221cb0ef41Sopenharmony_ci        return;
68231cb0ef41Sopenharmony_ci      }
68241cb0ef41Sopenharmony_ci    }
68251cb0ef41Sopenharmony_ci    // We have to visit the last value even if it's nullish, because we need its
68261cb0ef41Sopenharmony_ci    // actual value.
68271cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr->subsequent(expr->subsequent_length() - 1));
68281cb0ef41Sopenharmony_ci    end_labels.Bind(builder());
68291cb0ef41Sopenharmony_ci  }
68301cb0ef41Sopenharmony_ci}
68311cb0ef41Sopenharmony_ci
68321cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildNewLocalActivationContext() {
68331cb0ef41Sopenharmony_ci  ValueResultScope value_execution_result(this);
68341cb0ef41Sopenharmony_ci  Scope* scope = closure_scope();
68351cb0ef41Sopenharmony_ci  DCHECK_EQ(current_scope(), closure_scope());
68361cb0ef41Sopenharmony_ci
68371cb0ef41Sopenharmony_ci  // Create the appropriate context.
68381cb0ef41Sopenharmony_ci  DCHECK(scope->is_function_scope() || scope->is_eval_scope());
68391cb0ef41Sopenharmony_ci  int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
68401cb0ef41Sopenharmony_ci  if (slot_count <= ConstructorBuiltins::MaximumFunctionContextSlots()) {
68411cb0ef41Sopenharmony_ci    switch (scope->scope_type()) {
68421cb0ef41Sopenharmony_ci      case EVAL_SCOPE:
68431cb0ef41Sopenharmony_ci        builder()->CreateEvalContext(scope, slot_count);
68441cb0ef41Sopenharmony_ci        break;
68451cb0ef41Sopenharmony_ci      case FUNCTION_SCOPE:
68461cb0ef41Sopenharmony_ci        builder()->CreateFunctionContext(scope, slot_count);
68471cb0ef41Sopenharmony_ci        break;
68481cb0ef41Sopenharmony_ci      default:
68491cb0ef41Sopenharmony_ci        UNREACHABLE();
68501cb0ef41Sopenharmony_ci    }
68511cb0ef41Sopenharmony_ci  } else {
68521cb0ef41Sopenharmony_ci    Register arg = register_allocator()->NewRegister();
68531cb0ef41Sopenharmony_ci    builder()->LoadLiteral(scope).StoreAccumulatorInRegister(arg).CallRuntime(
68541cb0ef41Sopenharmony_ci        Runtime::kNewFunctionContext, arg);
68551cb0ef41Sopenharmony_ci  }
68561cb0ef41Sopenharmony_ci}
68571cb0ef41Sopenharmony_ci
68581cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildLocalActivationContextInitialization() {
68591cb0ef41Sopenharmony_ci  DeclarationScope* scope = closure_scope();
68601cb0ef41Sopenharmony_ci
68611cb0ef41Sopenharmony_ci  if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
68621cb0ef41Sopenharmony_ci    Variable* variable = scope->receiver();
68631cb0ef41Sopenharmony_ci    Register receiver(builder()->Receiver());
68641cb0ef41Sopenharmony_ci    // Context variable (at bottom of the context chain).
68651cb0ef41Sopenharmony_ci    DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
68661cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot(
68671cb0ef41Sopenharmony_ci        execution_context()->reg(), variable->index(), 0);
68681cb0ef41Sopenharmony_ci  }
68691cb0ef41Sopenharmony_ci
68701cb0ef41Sopenharmony_ci  // Copy parameters into context if necessary.
68711cb0ef41Sopenharmony_ci  int num_parameters = scope->num_parameters();
68721cb0ef41Sopenharmony_ci  for (int i = 0; i < num_parameters; i++) {
68731cb0ef41Sopenharmony_ci    Variable* variable = scope->parameter(i);
68741cb0ef41Sopenharmony_ci    if (!variable->IsContextSlot()) continue;
68751cb0ef41Sopenharmony_ci
68761cb0ef41Sopenharmony_ci    Register parameter(builder()->Parameter(i));
68771cb0ef41Sopenharmony_ci    // Context variable (at bottom of the context chain).
68781cb0ef41Sopenharmony_ci    DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
68791cb0ef41Sopenharmony_ci    builder()->LoadAccumulatorWithRegister(parameter).StoreContextSlot(
68801cb0ef41Sopenharmony_ci        execution_context()->reg(), variable->index(), 0);
68811cb0ef41Sopenharmony_ci  }
68821cb0ef41Sopenharmony_ci}
68831cb0ef41Sopenharmony_ci
68841cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) {
68851cb0ef41Sopenharmony_ci  ValueResultScope value_execution_result(this);
68861cb0ef41Sopenharmony_ci  DCHECK(scope->is_block_scope());
68871cb0ef41Sopenharmony_ci
68881cb0ef41Sopenharmony_ci  builder()->CreateBlockContext(scope);
68891cb0ef41Sopenharmony_ci}
68901cb0ef41Sopenharmony_ci
68911cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildNewLocalWithContext(Scope* scope) {
68921cb0ef41Sopenharmony_ci  ValueResultScope value_execution_result(this);
68931cb0ef41Sopenharmony_ci
68941cb0ef41Sopenharmony_ci  Register extension_object = register_allocator()->NewRegister();
68951cb0ef41Sopenharmony_ci
68961cb0ef41Sopenharmony_ci  builder()->ToObject(extension_object);
68971cb0ef41Sopenharmony_ci  builder()->CreateWithContext(extension_object, scope);
68981cb0ef41Sopenharmony_ci}
68991cb0ef41Sopenharmony_ci
69001cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildNewLocalCatchContext(Scope* scope) {
69011cb0ef41Sopenharmony_ci  ValueResultScope value_execution_result(this);
69021cb0ef41Sopenharmony_ci  DCHECK(scope->catch_variable()->IsContextSlot());
69031cb0ef41Sopenharmony_ci
69041cb0ef41Sopenharmony_ci  Register exception = register_allocator()->NewRegister();
69051cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(exception);
69061cb0ef41Sopenharmony_ci  builder()->CreateCatchContext(exception, scope);
69071cb0ef41Sopenharmony_ci}
69081cb0ef41Sopenharmony_ci
69091cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitLiteralAccessor(LiteralProperty* property,
69101cb0ef41Sopenharmony_ci                                             Register value_out) {
69111cb0ef41Sopenharmony_ci  if (property == nullptr) {
69121cb0ef41Sopenharmony_ci    builder()->LoadNull().StoreAccumulatorInRegister(value_out);
69131cb0ef41Sopenharmony_ci  } else {
69141cb0ef41Sopenharmony_ci    VisitForRegisterValue(property->value(), value_out);
69151cb0ef41Sopenharmony_ci  }
69161cb0ef41Sopenharmony_ci}
69171cb0ef41Sopenharmony_ci
69181cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitArgumentsObject(Variable* variable) {
69191cb0ef41Sopenharmony_ci  if (variable == nullptr) return;
69201cb0ef41Sopenharmony_ci
69211cb0ef41Sopenharmony_ci  DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
69221cb0ef41Sopenharmony_ci
69231cb0ef41Sopenharmony_ci  // Allocate and initialize a new arguments object and assign to the
69241cb0ef41Sopenharmony_ci  // {arguments} variable.
69251cb0ef41Sopenharmony_ci  builder()->CreateArguments(closure_scope()->GetArgumentsType());
69261cb0ef41Sopenharmony_ci  BuildVariableAssignment(variable, Token::ASSIGN, HoleCheckMode::kElided);
69271cb0ef41Sopenharmony_ci}
69281cb0ef41Sopenharmony_ci
69291cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) {
69301cb0ef41Sopenharmony_ci  if (rest == nullptr) return;
69311cb0ef41Sopenharmony_ci
69321cb0ef41Sopenharmony_ci  // Allocate and initialize a new rest parameter and assign to the {rest}
69331cb0ef41Sopenharmony_ci  // variable.
69341cb0ef41Sopenharmony_ci  builder()->CreateArguments(CreateArgumentsType::kRestParameter);
69351cb0ef41Sopenharmony_ci  DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
69361cb0ef41Sopenharmony_ci  BuildVariableAssignment(rest, Token::ASSIGN, HoleCheckMode::kElided);
69371cb0ef41Sopenharmony_ci}
69381cb0ef41Sopenharmony_ci
69391cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
69401cb0ef41Sopenharmony_ci  if (variable == nullptr) return;
69411cb0ef41Sopenharmony_ci
69421cb0ef41Sopenharmony_ci  // Store the closure we were called with in the given variable.
69431cb0ef41Sopenharmony_ci  builder()->LoadAccumulatorWithRegister(Register::function_closure());
69441cb0ef41Sopenharmony_ci  BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
69451cb0ef41Sopenharmony_ci}
69461cb0ef41Sopenharmony_ci
69471cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
69481cb0ef41Sopenharmony_ci  if (variable == nullptr) return;
69491cb0ef41Sopenharmony_ci
69501cb0ef41Sopenharmony_ci  // The generator resume trampoline abuses the new.target register
69511cb0ef41Sopenharmony_ci  // to pass in the generator object.  In ordinary calls, new.target is always
69521cb0ef41Sopenharmony_ci  // undefined because generator functions are non-constructible, so don't
69531cb0ef41Sopenharmony_ci  // assign anything to the new.target variable.
69541cb0ef41Sopenharmony_ci  if (IsResumableFunction(info()->literal()->kind())) return;
69551cb0ef41Sopenharmony_ci
69561cb0ef41Sopenharmony_ci  if (variable->location() == VariableLocation::LOCAL) {
69571cb0ef41Sopenharmony_ci    // The new.target register was already assigned by entry trampoline.
69581cb0ef41Sopenharmony_ci    DCHECK_EQ(incoming_new_target_or_generator_.index(),
69591cb0ef41Sopenharmony_ci              GetRegisterForLocalVariable(variable).index());
69601cb0ef41Sopenharmony_ci    return;
69611cb0ef41Sopenharmony_ci  }
69621cb0ef41Sopenharmony_ci
69631cb0ef41Sopenharmony_ci  // Store the new target we were called with in the given variable.
69641cb0ef41Sopenharmony_ci  builder()->LoadAccumulatorWithRegister(incoming_new_target_or_generator_);
69651cb0ef41Sopenharmony_ci  BuildVariableAssignment(variable, Token::INIT, HoleCheckMode::kElided);
69661cb0ef41Sopenharmony_ci}
69671cb0ef41Sopenharmony_ci
69681cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildGeneratorObjectVariableInitialization() {
69691cb0ef41Sopenharmony_ci  DCHECK(IsResumableFunction(info()->literal()->kind()));
69701cb0ef41Sopenharmony_ci
69711cb0ef41Sopenharmony_ci  Variable* generator_object_var = closure_scope()->generator_object_var();
69721cb0ef41Sopenharmony_ci  RegisterAllocationScope register_scope(this);
69731cb0ef41Sopenharmony_ci  RegisterList args = register_allocator()->NewRegisterList(2);
69741cb0ef41Sopenharmony_ci  Runtime::FunctionId function_id =
69751cb0ef41Sopenharmony_ci      ((IsAsyncFunction(info()->literal()->kind()) &&
69761cb0ef41Sopenharmony_ci        !IsAsyncGeneratorFunction(info()->literal()->kind())) ||
69771cb0ef41Sopenharmony_ci       IsAsyncModule(info()->literal()->kind()))
69781cb0ef41Sopenharmony_ci          ? Runtime::kInlineAsyncFunctionEnter
69791cb0ef41Sopenharmony_ci          : Runtime::kInlineCreateJSGeneratorObject;
69801cb0ef41Sopenharmony_ci  builder()
69811cb0ef41Sopenharmony_ci      ->MoveRegister(Register::function_closure(), args[0])
69821cb0ef41Sopenharmony_ci      .MoveRegister(builder()->Receiver(), args[1])
69831cb0ef41Sopenharmony_ci      .CallRuntime(function_id, args)
69841cb0ef41Sopenharmony_ci      .StoreAccumulatorInRegister(generator_object());
69851cb0ef41Sopenharmony_ci
69861cb0ef41Sopenharmony_ci  if (generator_object_var->location() == VariableLocation::LOCAL) {
69871cb0ef41Sopenharmony_ci    // The generator object register is already set to the variable's local
69881cb0ef41Sopenharmony_ci    // register.
69891cb0ef41Sopenharmony_ci    DCHECK_EQ(generator_object().index(),
69901cb0ef41Sopenharmony_ci              GetRegisterForLocalVariable(generator_object_var).index());
69911cb0ef41Sopenharmony_ci  } else {
69921cb0ef41Sopenharmony_ci    BuildVariableAssignment(generator_object_var, Token::INIT,
69931cb0ef41Sopenharmony_ci                            HoleCheckMode::kElided);
69941cb0ef41Sopenharmony_ci  }
69951cb0ef41Sopenharmony_ci}
69961cb0ef41Sopenharmony_ci
69971cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildPushUndefinedIntoRegisterList(
69981cb0ef41Sopenharmony_ci    RegisterList* reg_list) {
69991cb0ef41Sopenharmony_ci  Register reg = register_allocator()->GrowRegisterList(reg_list);
70001cb0ef41Sopenharmony_ci  builder()->LoadUndefined().StoreAccumulatorInRegister(reg);
70011cb0ef41Sopenharmony_ci}
70021cb0ef41Sopenharmony_ci
70031cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildLoadPropertyKey(LiteralProperty* property,
70041cb0ef41Sopenharmony_ci                                             Register out_reg) {
70051cb0ef41Sopenharmony_ci  if (property->key()->IsStringLiteral()) {
70061cb0ef41Sopenharmony_ci    builder()
70071cb0ef41Sopenharmony_ci        ->LoadLiteral(property->key()->AsLiteral()->AsRawString())
70081cb0ef41Sopenharmony_ci        .StoreAccumulatorInRegister(out_reg);
70091cb0ef41Sopenharmony_ci  } else {
70101cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(property->key());
70111cb0ef41Sopenharmony_ci    builder()->ToName(out_reg);
70121cb0ef41Sopenharmony_ci  }
70131cb0ef41Sopenharmony_ci}
70141cb0ef41Sopenharmony_ci
70151cb0ef41Sopenharmony_ciint BytecodeGenerator::AllocateBlockCoverageSlotIfEnabled(
70161cb0ef41Sopenharmony_ci    AstNode* node, SourceRangeKind kind) {
70171cb0ef41Sopenharmony_ci  return (block_coverage_builder_ == nullptr)
70181cb0ef41Sopenharmony_ci             ? BlockCoverageBuilder::kNoCoverageArraySlot
70191cb0ef41Sopenharmony_ci             : block_coverage_builder_->AllocateBlockCoverageSlot(node, kind);
70201cb0ef41Sopenharmony_ci}
70211cb0ef41Sopenharmony_ci
70221cb0ef41Sopenharmony_ciint BytecodeGenerator::AllocateNaryBlockCoverageSlotIfEnabled(
70231cb0ef41Sopenharmony_ci    NaryOperation* node, size_t index) {
70241cb0ef41Sopenharmony_ci  return (block_coverage_builder_ == nullptr)
70251cb0ef41Sopenharmony_ci             ? BlockCoverageBuilder::kNoCoverageArraySlot
70261cb0ef41Sopenharmony_ci             : block_coverage_builder_->AllocateNaryBlockCoverageSlot(node,
70271cb0ef41Sopenharmony_ci                                                                      index);
70281cb0ef41Sopenharmony_ci}
70291cb0ef41Sopenharmony_ci
70301cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
70311cb0ef41Sopenharmony_ci    AstNode* node, SourceRangeKind kind) {
70321cb0ef41Sopenharmony_ci  if (block_coverage_builder_ == nullptr) return;
70331cb0ef41Sopenharmony_ci  block_coverage_builder_->IncrementBlockCounter(node, kind);
70341cb0ef41Sopenharmony_ci}
70351cb0ef41Sopenharmony_ci
70361cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
70371cb0ef41Sopenharmony_ci    int coverage_array_slot) {
70381cb0ef41Sopenharmony_ci  if (block_coverage_builder_ != nullptr) {
70391cb0ef41Sopenharmony_ci    block_coverage_builder_->IncrementBlockCounter(coverage_array_slot);
70401cb0ef41Sopenharmony_ci  }
70411cb0ef41Sopenharmony_ci}
70421cb0ef41Sopenharmony_ci
70431cb0ef41Sopenharmony_ci// Visits the expression |expr| and places the result in the accumulator.
70441cb0ef41Sopenharmony_ciBytecodeGenerator::TypeHint BytecodeGenerator::VisitForAccumulatorValue(
70451cb0ef41Sopenharmony_ci    Expression* expr) {
70461cb0ef41Sopenharmony_ci  ValueResultScope accumulator_scope(this);
70471cb0ef41Sopenharmony_ci  Visit(expr);
70481cb0ef41Sopenharmony_ci  return accumulator_scope.type_hint();
70491cb0ef41Sopenharmony_ci}
70501cb0ef41Sopenharmony_ci
70511cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) {
70521cb0ef41Sopenharmony_ci  if (expr == nullptr) {
70531cb0ef41Sopenharmony_ci    builder()->LoadTheHole();
70541cb0ef41Sopenharmony_ci  } else {
70551cb0ef41Sopenharmony_ci    VisitForAccumulatorValue(expr);
70561cb0ef41Sopenharmony_ci  }
70571cb0ef41Sopenharmony_ci}
70581cb0ef41Sopenharmony_ci
70591cb0ef41Sopenharmony_ci// Visits the expression |expr| and discards the result.
70601cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitForEffect(Expression* expr) {
70611cb0ef41Sopenharmony_ci  EffectResultScope effect_scope(this);
70621cb0ef41Sopenharmony_ci  Visit(expr);
70631cb0ef41Sopenharmony_ci}
70641cb0ef41Sopenharmony_ci
70651cb0ef41Sopenharmony_ci// Visits the expression |expr| and returns the register containing
70661cb0ef41Sopenharmony_ci// the expression result.
70671cb0ef41Sopenharmony_ciRegister BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
70681cb0ef41Sopenharmony_ci  VisitForAccumulatorValue(expr);
70691cb0ef41Sopenharmony_ci  Register result = register_allocator()->NewRegister();
70701cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(result);
70711cb0ef41Sopenharmony_ci  return result;
70721cb0ef41Sopenharmony_ci}
70731cb0ef41Sopenharmony_ci
70741cb0ef41Sopenharmony_ci// Visits the expression |expr| and stores the expression result in
70751cb0ef41Sopenharmony_ci// |destination|.
70761cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitForRegisterValue(Expression* expr,
70771cb0ef41Sopenharmony_ci                                              Register destination) {
70781cb0ef41Sopenharmony_ci  ValueResultScope register_scope(this);
70791cb0ef41Sopenharmony_ci  Visit(expr);
70801cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(destination);
70811cb0ef41Sopenharmony_ci}
70821cb0ef41Sopenharmony_ci
70831cb0ef41Sopenharmony_ci// Visits the expression |expr| and pushes the result into a new register
70841cb0ef41Sopenharmony_ci// added to the end of |reg_list|.
70851cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitAndPushIntoRegisterList(Expression* expr,
70861cb0ef41Sopenharmony_ci                                                     RegisterList* reg_list) {
70871cb0ef41Sopenharmony_ci  {
70881cb0ef41Sopenharmony_ci    ValueResultScope register_scope(this);
70891cb0ef41Sopenharmony_ci    Visit(expr);
70901cb0ef41Sopenharmony_ci  }
70911cb0ef41Sopenharmony_ci  // Grow the register list after visiting the expression to avoid reserving
70921cb0ef41Sopenharmony_ci  // the register across the expression evaluation, which could cause memory
70931cb0ef41Sopenharmony_ci  // leaks for deep expressions due to dead objects being kept alive by pointers
70941cb0ef41Sopenharmony_ci  // in registers.
70951cb0ef41Sopenharmony_ci  Register destination = register_allocator()->GrowRegisterList(reg_list);
70961cb0ef41Sopenharmony_ci  builder()->StoreAccumulatorInRegister(destination);
70971cb0ef41Sopenharmony_ci}
70981cb0ef41Sopenharmony_ci
70991cb0ef41Sopenharmony_civoid BytecodeGenerator::BuildTest(ToBooleanMode mode,
71001cb0ef41Sopenharmony_ci                                  BytecodeLabels* then_labels,
71011cb0ef41Sopenharmony_ci                                  BytecodeLabels* else_labels,
71021cb0ef41Sopenharmony_ci                                  TestFallthrough fallthrough) {
71031cb0ef41Sopenharmony_ci  switch (fallthrough) {
71041cb0ef41Sopenharmony_ci    case TestFallthrough::kThen:
71051cb0ef41Sopenharmony_ci      builder()->JumpIfFalse(mode, else_labels->New());
71061cb0ef41Sopenharmony_ci      break;
71071cb0ef41Sopenharmony_ci    case TestFallthrough::kElse:
71081cb0ef41Sopenharmony_ci      builder()->JumpIfTrue(mode, then_labels->New());
71091cb0ef41Sopenharmony_ci      break;
71101cb0ef41Sopenharmony_ci    case TestFallthrough::kNone:
71111cb0ef41Sopenharmony_ci      builder()->JumpIfTrue(mode, then_labels->New());
71121cb0ef41Sopenharmony_ci      builder()->Jump(else_labels->New());
71131cb0ef41Sopenharmony_ci      break;
71141cb0ef41Sopenharmony_ci  }
71151cb0ef41Sopenharmony_ci}
71161cb0ef41Sopenharmony_ci
71171cb0ef41Sopenharmony_ci// Visits the expression |expr| for testing its boolean value and jumping to the
71181cb0ef41Sopenharmony_ci// |then| or |other| label depending on value and short-circuit semantics
71191cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitForTest(Expression* expr,
71201cb0ef41Sopenharmony_ci                                     BytecodeLabels* then_labels,
71211cb0ef41Sopenharmony_ci                                     BytecodeLabels* else_labels,
71221cb0ef41Sopenharmony_ci                                     TestFallthrough fallthrough) {
71231cb0ef41Sopenharmony_ci  bool result_consumed;
71241cb0ef41Sopenharmony_ci  TypeHint type_hint;
71251cb0ef41Sopenharmony_ci  {
71261cb0ef41Sopenharmony_ci    // To make sure that all temporary registers are returned before generating
71271cb0ef41Sopenharmony_ci    // jumps below, we ensure that the result scope is deleted before doing so.
71281cb0ef41Sopenharmony_ci    // Dead registers might be materialized otherwise.
71291cb0ef41Sopenharmony_ci    TestResultScope test_result(this, then_labels, else_labels, fallthrough);
71301cb0ef41Sopenharmony_ci    Visit(expr);
71311cb0ef41Sopenharmony_ci    result_consumed = test_result.result_consumed_by_test();
71321cb0ef41Sopenharmony_ci    type_hint = test_result.type_hint();
71331cb0ef41Sopenharmony_ci    // Labels and fallthrough might have been mutated, so update based on
71341cb0ef41Sopenharmony_ci    // TestResultScope.
71351cb0ef41Sopenharmony_ci    then_labels = test_result.then_labels();
71361cb0ef41Sopenharmony_ci    else_labels = test_result.else_labels();
71371cb0ef41Sopenharmony_ci    fallthrough = test_result.fallthrough();
71381cb0ef41Sopenharmony_ci  }
71391cb0ef41Sopenharmony_ci  if (!result_consumed) {
71401cb0ef41Sopenharmony_ci    BuildTest(ToBooleanModeFromTypeHint(type_hint), then_labels, else_labels,
71411cb0ef41Sopenharmony_ci              fallthrough);
71421cb0ef41Sopenharmony_ci  }
71431cb0ef41Sopenharmony_ci}
71441cb0ef41Sopenharmony_ci
71451cb0ef41Sopenharmony_ci// Visits the expression |expr| for testing its nullish value and jumping to the
71461cb0ef41Sopenharmony_ci// |then| or |other| label depending on value and short-circuit semantics
71471cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitForNullishTest(Expression* expr,
71481cb0ef41Sopenharmony_ci                                            BytecodeLabels* then_labels,
71491cb0ef41Sopenharmony_ci                                            BytecodeLabels* test_next_labels,
71501cb0ef41Sopenharmony_ci                                            BytecodeLabels* else_labels) {
71511cb0ef41Sopenharmony_ci  // Nullish short circuits on undefined or null, otherwise we fall back to
71521cb0ef41Sopenharmony_ci  // BuildTest with no fallthrough.
71531cb0ef41Sopenharmony_ci  // TODO(joshualitt): We should do this in a TestResultScope.
71541cb0ef41Sopenharmony_ci  TypeHint type_hint = VisitForAccumulatorValue(expr);
71551cb0ef41Sopenharmony_ci  ToBooleanMode mode = ToBooleanModeFromTypeHint(type_hint);
71561cb0ef41Sopenharmony_ci
71571cb0ef41Sopenharmony_ci  // Skip the nullish shortcircuit if we already have a boolean.
71581cb0ef41Sopenharmony_ci  if (mode != ToBooleanMode::kAlreadyBoolean) {
71591cb0ef41Sopenharmony_ci    builder()->JumpIfUndefinedOrNull(test_next_labels->New());
71601cb0ef41Sopenharmony_ci  }
71611cb0ef41Sopenharmony_ci  BuildTest(mode, then_labels, else_labels, TestFallthrough::kNone);
71621cb0ef41Sopenharmony_ci}
71631cb0ef41Sopenharmony_ci
71641cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitInSameTestExecutionScope(Expression* expr) {
71651cb0ef41Sopenharmony_ci  DCHECK(execution_result()->IsTest());
71661cb0ef41Sopenharmony_ci  {
71671cb0ef41Sopenharmony_ci    RegisterAllocationScope reg_scope(this);
71681cb0ef41Sopenharmony_ci    Visit(expr);
71691cb0ef41Sopenharmony_ci  }
71701cb0ef41Sopenharmony_ci  if (!execution_result()->AsTest()->result_consumed_by_test()) {
71711cb0ef41Sopenharmony_ci    TestResultScope* result_scope = execution_result()->AsTest();
71721cb0ef41Sopenharmony_ci    BuildTest(ToBooleanModeFromTypeHint(result_scope->type_hint()),
71731cb0ef41Sopenharmony_ci              result_scope->then_labels(), result_scope->else_labels(),
71741cb0ef41Sopenharmony_ci              result_scope->fallthrough());
71751cb0ef41Sopenharmony_ci    result_scope->SetResultConsumedByTest();
71761cb0ef41Sopenharmony_ci  }
71771cb0ef41Sopenharmony_ci}
71781cb0ef41Sopenharmony_ci
71791cb0ef41Sopenharmony_civoid BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) {
71801cb0ef41Sopenharmony_ci  DCHECK(scope->declarations()->is_empty());
71811cb0ef41Sopenharmony_ci  CurrentScope current_scope(this, scope);
71821cb0ef41Sopenharmony_ci  ContextScope context_scope(this, scope);
71831cb0ef41Sopenharmony_ci  Visit(stmt);
71841cb0ef41Sopenharmony_ci}
71851cb0ef41Sopenharmony_ci
71861cb0ef41Sopenharmony_ciRegister BytecodeGenerator::GetRegisterForLocalVariable(Variable* variable) {
71871cb0ef41Sopenharmony_ci  DCHECK_EQ(VariableLocation::LOCAL, variable->location());
71881cb0ef41Sopenharmony_ci  return builder()->Local(variable->index());
71891cb0ef41Sopenharmony_ci}
71901cb0ef41Sopenharmony_ci
71911cb0ef41Sopenharmony_ciFunctionKind BytecodeGenerator::function_kind() const {
71921cb0ef41Sopenharmony_ci  return info()->literal()->kind();
71931cb0ef41Sopenharmony_ci}
71941cb0ef41Sopenharmony_ci
71951cb0ef41Sopenharmony_ciLanguageMode BytecodeGenerator::language_mode() const {
71961cb0ef41Sopenharmony_ci  return current_scope()->language_mode();
71971cb0ef41Sopenharmony_ci}
71981cb0ef41Sopenharmony_ci
71991cb0ef41Sopenharmony_ciRegister BytecodeGenerator::generator_object() const {
72001cb0ef41Sopenharmony_ci  DCHECK(IsResumableFunction(info()->literal()->kind()));
72011cb0ef41Sopenharmony_ci  return incoming_new_target_or_generator_;
72021cb0ef41Sopenharmony_ci}
72031cb0ef41Sopenharmony_ci
72041cb0ef41Sopenharmony_ciFeedbackVectorSpec* BytecodeGenerator::feedback_spec() {
72051cb0ef41Sopenharmony_ci  return info()->feedback_vector_spec();
72061cb0ef41Sopenharmony_ci}
72071cb0ef41Sopenharmony_ci
72081cb0ef41Sopenharmony_ciint BytecodeGenerator::feedback_index(FeedbackSlot slot) const {
72091cb0ef41Sopenharmony_ci  DCHECK(!slot.IsInvalid());
72101cb0ef41Sopenharmony_ci  return FeedbackVector::GetIndex(slot);
72111cb0ef41Sopenharmony_ci}
72121cb0ef41Sopenharmony_ci
72131cb0ef41Sopenharmony_ciFeedbackSlot BytecodeGenerator::GetCachedLoadGlobalICSlot(
72141cb0ef41Sopenharmony_ci    TypeofMode typeof_mode, Variable* variable) {
72151cb0ef41Sopenharmony_ci  FeedbackSlotCache::SlotKind slot_kind =
72161cb0ef41Sopenharmony_ci      typeof_mode == TypeofMode::kInside
72171cb0ef41Sopenharmony_ci          ? FeedbackSlotCache::SlotKind::kLoadGlobalInsideTypeof
72181cb0ef41Sopenharmony_ci          : FeedbackSlotCache::SlotKind::kLoadGlobalNotInsideTypeof;
72191cb0ef41Sopenharmony_ci  FeedbackSlot slot(feedback_slot_cache()->Get(slot_kind, variable));
72201cb0ef41Sopenharmony_ci  if (!slot.IsInvalid()) {
72211cb0ef41Sopenharmony_ci    return slot;
72221cb0ef41Sopenharmony_ci  }
72231cb0ef41Sopenharmony_ci  slot = feedback_spec()->AddLoadGlobalICSlot(typeof_mode);
72241cb0ef41Sopenharmony_ci  feedback_slot_cache()->Put(slot_kind, variable, feedback_index(slot));
72251cb0ef41Sopenharmony_ci  return slot;
72261cb0ef41Sopenharmony_ci}
72271cb0ef41Sopenharmony_ci
72281cb0ef41Sopenharmony_ciFeedbackSlot BytecodeGenerator::GetCachedStoreGlobalICSlot(
72291cb0ef41Sopenharmony_ci    LanguageMode language_mode, Variable* variable) {
72301cb0ef41Sopenharmony_ci  FeedbackSlotCache::SlotKind slot_kind =
72311cb0ef41Sopenharmony_ci      is_strict(language_mode)
72321cb0ef41Sopenharmony_ci          ? FeedbackSlotCache::SlotKind::kStoreGlobalStrict
72331cb0ef41Sopenharmony_ci          : FeedbackSlotCache::SlotKind::kStoreGlobalSloppy;
72341cb0ef41Sopenharmony_ci  FeedbackSlot slot(feedback_slot_cache()->Get(slot_kind, variable));
72351cb0ef41Sopenharmony_ci  if (!slot.IsInvalid()) {
72361cb0ef41Sopenharmony_ci    return slot;
72371cb0ef41Sopenharmony_ci  }
72381cb0ef41Sopenharmony_ci  slot = feedback_spec()->AddStoreGlobalICSlot(language_mode);
72391cb0ef41Sopenharmony_ci  feedback_slot_cache()->Put(slot_kind, variable, feedback_index(slot));
72401cb0ef41Sopenharmony_ci  return slot;
72411cb0ef41Sopenharmony_ci}
72421cb0ef41Sopenharmony_ci
72431cb0ef41Sopenharmony_ciFeedbackSlot BytecodeGenerator::GetCachedLoadICSlot(const Expression* expr,
72441cb0ef41Sopenharmony_ci                                                    const AstRawString* name) {
72451cb0ef41Sopenharmony_ci  DCHECK(!expr->IsSuperPropertyReference());
72461cb0ef41Sopenharmony_ci  if (!FLAG_ignition_share_named_property_feedback) {
72471cb0ef41Sopenharmony_ci    return feedback_spec()->AddLoadICSlot();
72481cb0ef41Sopenharmony_ci  }
72491cb0ef41Sopenharmony_ci  FeedbackSlotCache::SlotKind slot_kind =
72501cb0ef41Sopenharmony_ci      FeedbackSlotCache::SlotKind::kLoadProperty;
72511cb0ef41Sopenharmony_ci  if (!expr->IsVariableProxy()) {
72521cb0ef41Sopenharmony_ci    return feedback_spec()->AddLoadICSlot();
72531cb0ef41Sopenharmony_ci  }
72541cb0ef41Sopenharmony_ci  const VariableProxy* proxy = expr->AsVariableProxy();
72551cb0ef41Sopenharmony_ci  FeedbackSlot slot(
72561cb0ef41Sopenharmony_ci      feedback_slot_cache()->Get(slot_kind, proxy->var()->index(), name));
72571cb0ef41Sopenharmony_ci  if (!slot.IsInvalid()) {
72581cb0ef41Sopenharmony_ci    return slot;
72591cb0ef41Sopenharmony_ci  }
72601cb0ef41Sopenharmony_ci  slot = feedback_spec()->AddLoadICSlot();
72611cb0ef41Sopenharmony_ci  feedback_slot_cache()->Put(slot_kind, proxy->var()->index(), name,
72621cb0ef41Sopenharmony_ci                             feedback_index(slot));
72631cb0ef41Sopenharmony_ci  return slot;
72641cb0ef41Sopenharmony_ci}
72651cb0ef41Sopenharmony_ci
72661cb0ef41Sopenharmony_ciFeedbackSlot BytecodeGenerator::GetCachedLoadSuperICSlot(
72671cb0ef41Sopenharmony_ci    const AstRawString* name) {
72681cb0ef41Sopenharmony_ci  if (!FLAG_ignition_share_named_property_feedback) {
72691cb0ef41Sopenharmony_ci    return feedback_spec()->AddLoadICSlot();
72701cb0ef41Sopenharmony_ci  }
72711cb0ef41Sopenharmony_ci  FeedbackSlotCache::SlotKind slot_kind =
72721cb0ef41Sopenharmony_ci      FeedbackSlotCache::SlotKind::kLoadSuperProperty;
72731cb0ef41Sopenharmony_ci
72741cb0ef41Sopenharmony_ci  FeedbackSlot slot(feedback_slot_cache()->Get(slot_kind, name));
72751cb0ef41Sopenharmony_ci  if (!slot.IsInvalid()) {
72761cb0ef41Sopenharmony_ci    return slot;
72771cb0ef41Sopenharmony_ci  }
72781cb0ef41Sopenharmony_ci  slot = feedback_spec()->AddLoadICSlot();
72791cb0ef41Sopenharmony_ci  feedback_slot_cache()->Put(slot_kind, name, feedback_index(slot));
72801cb0ef41Sopenharmony_ci  return slot;
72811cb0ef41Sopenharmony_ci}
72821cb0ef41Sopenharmony_ci
72831cb0ef41Sopenharmony_ciFeedbackSlot BytecodeGenerator::GetCachedStoreICSlot(const Expression* expr,
72841cb0ef41Sopenharmony_ci                                                     const AstRawString* name) {
72851cb0ef41Sopenharmony_ci  if (!FLAG_ignition_share_named_property_feedback) {
72861cb0ef41Sopenharmony_ci    return feedback_spec()->AddStoreICSlot(language_mode());
72871cb0ef41Sopenharmony_ci  }
72881cb0ef41Sopenharmony_ci  FeedbackSlotCache::SlotKind slot_kind =
72891cb0ef41Sopenharmony_ci      is_strict(language_mode()) ? FeedbackSlotCache::SlotKind::kSetNamedStrict
72901cb0ef41Sopenharmony_ci                                 : FeedbackSlotCache::SlotKind::kSetNamedSloppy;
72911cb0ef41Sopenharmony_ci  if (!expr->IsVariableProxy()) {
72921cb0ef41Sopenharmony_ci    return feedback_spec()->AddStoreICSlot(language_mode());
72931cb0ef41Sopenharmony_ci  }
72941cb0ef41Sopenharmony_ci  const VariableProxy* proxy = expr->AsVariableProxy();
72951cb0ef41Sopenharmony_ci  FeedbackSlot slot(
72961cb0ef41Sopenharmony_ci      feedback_slot_cache()->Get(slot_kind, proxy->var()->index(), name));
72971cb0ef41Sopenharmony_ci  if (!slot.IsInvalid()) {
72981cb0ef41Sopenharmony_ci    return slot;
72991cb0ef41Sopenharmony_ci  }
73001cb0ef41Sopenharmony_ci  slot = feedback_spec()->AddStoreICSlot(language_mode());
73011cb0ef41Sopenharmony_ci  feedback_slot_cache()->Put(slot_kind, proxy->var()->index(), name,
73021cb0ef41Sopenharmony_ci                             feedback_index(slot));
73031cb0ef41Sopenharmony_ci  return slot;
73041cb0ef41Sopenharmony_ci}
73051cb0ef41Sopenharmony_ci
73061cb0ef41Sopenharmony_ciint BytecodeGenerator::GetCachedCreateClosureSlot(FunctionLiteral* literal) {
73071cb0ef41Sopenharmony_ci  FeedbackSlotCache::SlotKind slot_kind =
73081cb0ef41Sopenharmony_ci      FeedbackSlotCache::SlotKind::kClosureFeedbackCell;
73091cb0ef41Sopenharmony_ci  int index = feedback_slot_cache()->Get(slot_kind, literal);
73101cb0ef41Sopenharmony_ci  if (index != -1) {
73111cb0ef41Sopenharmony_ci    return index;
73121cb0ef41Sopenharmony_ci  }
73131cb0ef41Sopenharmony_ci  index = feedback_spec()->AddCreateClosureSlot();
73141cb0ef41Sopenharmony_ci  feedback_slot_cache()->Put(slot_kind, literal, index);
73151cb0ef41Sopenharmony_ci  return index;
73161cb0ef41Sopenharmony_ci}
73171cb0ef41Sopenharmony_ci
73181cb0ef41Sopenharmony_ciFeedbackSlot BytecodeGenerator::GetDummyCompareICSlot() {
73191cb0ef41Sopenharmony_ci  return dummy_feedback_slot_.Get();
73201cb0ef41Sopenharmony_ci}
73211cb0ef41Sopenharmony_ci
73221cb0ef41Sopenharmony_ci}  // namespace interpreter
73231cb0ef41Sopenharmony_ci}  // namespace internal
73241cb0ef41Sopenharmony_ci}  // namespace v8
7325