chromium/v8/src/interpreter/bytecode-generator.cc

// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/interpreter/bytecode-generator.h"

#include <map>
#include <optional>
#include <unordered_map>
#include <unordered_set>

#include "include/v8-extension.h"
#include "src/api/api-inl.h"
#include "src/ast/ast-source-ranges.h"
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/builtins/builtins-constructor.h"
#include "src/codegen/compiler.h"
#include "src/codegen/unoptimized-compilation-info.h"
#include "src/common/globals.h"
#include "src/compiler-dispatcher/lazy-compile-dispatcher.h"
#include "src/heap/parked-scope.h"
#include "src/interpreter/bytecode-array-builder.h"
#include "src/interpreter/bytecode-flags-and-tokens.h"
#include "src/interpreter/bytecode-jump-table.h"
#include "src/interpreter/bytecode-label.h"
#include "src/interpreter/bytecode-register-allocator.h"
#include "src/interpreter/bytecode-register-optimizer.h"
#include "src/interpreter/bytecode-register.h"
#include "src/interpreter/control-flow-builders.h"
#include "src/logging/local-logger.h"
#include "src/logging/log.h"
#include "src/numbers/conversions.h"
#include "src/objects/debug-objects.h"
#include "src/objects/js-disposable-stack.h"
#include "src/objects/objects.h"
#include "src/objects/smi.h"
#include "src/objects/template-objects.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/token.h"
#include "src/utils/ostreams.h"

namespace v8 {
namespace internal {
namespace interpreter {

// Scoped class tracking context objects created by the visitor. Represents
// mutations of the context chain within the function body, allowing pushing and
// popping of the current {context_register} during visitation.
class V8_NODISCARD BytecodeGenerator::ContextScope {};

// Scoped class for tracking control statements entered by the
// visitor.
class V8_NODISCARD BytecodeGenerator::ControlScope {};

// Helper class for a try-finally control scope. It can record intercepted
// control-flow commands that cause entry into a finally-block, and re-apply
// them after again leaving that block. Special tokens are used to identify
// paths going through the finally-block to dispatch after leaving the block.
class V8_NODISCARD BytecodeGenerator::ControlScope::DeferredCommands final {};

// Scoped class for dealing with control flow reaching the function level.
class BytecodeGenerator::ControlScopeForTopLevel final
    : public BytecodeGenerator::ControlScope {};

// Scoped class for enabling break inside blocks and switch blocks.
class BytecodeGenerator::ControlScopeForBreakable final
    : public BytecodeGenerator::ControlScope {};

// Scoped class for enabling 'break' and 'continue' in iteration
// constructs, e.g. do...while, while..., for...
class BytecodeGenerator::ControlScopeForIteration final
    : public BytecodeGenerator::ControlScope {};

// Scoped class for enabling 'throw' in try-catch constructs.
class BytecodeGenerator::ControlScopeForTryCatch final
    : public BytecodeGenerator::ControlScope {};

// Scoped class for enabling control flow through try-finally constructs.
class BytecodeGenerator::ControlScopeForTryFinally final
    : public BytecodeGenerator::ControlScope {};

// Scoped class for collecting 'return' statments in a derived constructor.
// Derived constructors can only return undefined or objects, and this check
// must occur right before return (e.g., after `finally` blocks execute).
class BytecodeGenerator::ControlScopeForDerivedConstructor final
    : public BytecodeGenerator::ControlScope {};

// Allocate and fetch the coverage indices tracking NaryLogical Expressions.
class BytecodeGenerator::NaryCodeCoverageSlots {};

void BytecodeGenerator::ControlScope::PerformCommand(Command command,
                                                     Statement* statement,
                                                     int source_position) {}

void BytecodeGenerator::ControlScope::PopContextToExpectedDepth() {}

class V8_NODISCARD BytecodeGenerator::RegisterAllocationScope final {};

class V8_NODISCARD BytecodeGenerator::AccumulatorPreservingScope final {};

// Scoped base class for determining how the result of an expression will be
// used.
class V8_NODISCARD BytecodeGenerator::ExpressionResultScope {};

// Scoped class used when the result of the current expression is not
// expected to produce a result.
class BytecodeGenerator::EffectResultScope final
    : public ExpressionResultScope {};

// Scoped class used when the result of the current expression to be
// evaluated should go into the interpreter's accumulator.
class V8_NODISCARD BytecodeGenerator::ValueResultScope final
    : public ExpressionResultScope {};

// Scoped class used when the result of the current expression to be
// evaluated is only tested with jumps to two branches.
class V8_NODISCARD BytecodeGenerator::TestResultScope final
    : public ExpressionResultScope {};

// Used to build a list of toplevel declaration data.
class BytecodeGenerator::TopLevelDeclarationsBuilder final : public ZoneObject {};

class V8_NODISCARD BytecodeGenerator::CurrentScope final {};

class V8_NODISCARD BytecodeGenerator::MultipleEntryBlockContextScope {};

class BytecodeGenerator::FeedbackSlotCache : public ZoneObject {};

// Scoped class to help elide hole checks within a conditionally executed basic
// block. Each conditionally executed basic block must have a scope to emit
// hole checks correctly.
//
// The duration of the scope must correspond to a basic block. Numbered
// Variables (see Variable::HoleCheckBitmap) are remembered in the bitmap when
// the first hole check is emitted. Subsequent hole checks are elided.
//
// On scope exit, the hole check state at construction time is restored.
class V8_NODISCARD BytecodeGenerator::HoleCheckElisionScope {};

// Scoped class to help elide hole checks within control flow that branch and
// merge.
//
// Each such control flow construct (e.g., if-else, ternary expressions) must
// have a scope to emit hole checks correctly. Additionally, each branch must
// have a Branch.
//
// The Merge or MergeIf method must be called to merge variables that have been
// hole-checked along every branch are marked as no longer needing a hole check.
//
// Example:
//
//   HoleCheckElisionMergeScope merge_elider(this);
//   {
//      HoleCheckElisionMergeScope::Branch branch_elider(merge_elider);
//      Visit(then_branch);
//   }
//   {
//      HoleCheckElisionMergeScope::Branch branch_elider(merge_elider);
//      Visit(else_branch);
//   }
//   merge_elider.Merge();
//
// Conversely, it is incorrect to use this class for control flow constructs
// that do not merge (e.g., if without else). HoleCheckElisionScope should be
// used for those cases.
class V8_NODISCARD BytecodeGenerator::HoleCheckElisionMergeScope final {};

class BytecodeGenerator::IteratorRecord final {};

class V8_NODISCARD BytecodeGenerator::OptionalChainNullLabelScope final {};

// LoopScope delimits the scope of {loop}, from its header to its final jump.
// It should be constructed iff a (conceptual) back edge should be produced. In
// the case of creating a LoopBuilder but never emitting the loop, it is valid
// to skip the creation of LoopScope.
class V8_NODISCARD BytecodeGenerator::LoopScope final {};

class V8_NODISCARD BytecodeGenerator::ForInScope final {};

class V8_NODISCARD BytecodeGenerator::DisposablesStackScope final {};

namespace {

template <typename PropertyT>
struct Accessors : public ZoneObject {};

// A map from property names to getter/setter pairs allocated in the zone that
// also provides a way of accessing the pairs in the order they were first
// added so that the generated bytecode is always the same.
template <typename PropertyT>
class AccessorTable
    : public base::TemplateHashMap<Literal, Accessors<PropertyT>,
                                   bool (*)(void*, void*),
                                   ZoneAllocationPolicy> {};

}  // namespace

#ifdef DEBUG

static bool IsInEagerLiterals(
    FunctionLiteral* literal,
    const std::vector<FunctionLiteral*>& eager_literals) {}

#endif  // DEBUG

BytecodeGenerator::BytecodeGenerator(
    LocalIsolate* local_isolate, Zone* compile_zone,
    UnoptimizedCompilationInfo* info,
    const AstStringConstants* ast_string_constants,
    std::vector<FunctionLiteral*>* eager_inner_literals, Handle<Script> script)
    :{}

namespace {

template <typename Isolate>
struct NullContextScopeHelper;

template <>
struct NullContextScopeHelper<Isolate> {};

template <>
struct NullContextScopeHelper<LocalIsolate> {};

NullContextScopeFor;

}  // namespace

template <typename IsolateT>
Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
    IsolateT* isolate, Handle<Script> script) {}

template Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
    Isolate* isolate, Handle<Script> script);
template Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(
    LocalIsolate* isolate, Handle<Script> script);

template <typename IsolateT>
Handle<TrustedByteArray> BytecodeGenerator::FinalizeSourcePositionTable(
    IsolateT* isolate) {}

template Handle<TrustedByteArray>
BytecodeGenerator::FinalizeSourcePositionTable(Isolate* isolate);
template Handle<TrustedByteArray>
BytecodeGenerator::FinalizeSourcePositionTable(LocalIsolate* isolate);

#ifdef DEBUG
int BytecodeGenerator::CheckBytecodeMatches(Tagged<BytecodeArray> bytecode) {}
#endif

template <typename IsolateT>
void BytecodeGenerator::AllocateDeferredConstants(IsolateT* isolate,
                                                  Handle<Script> script) {}

template void BytecodeGenerator::AllocateDeferredConstants(
    Isolate* isolate, Handle<Script> script);
template void BytecodeGenerator::AllocateDeferredConstants(
    LocalIsolate* isolate, Handle<Script> script);

namespace {
bool NeedsContextInitialization(DeclarationScope* scope) {}
}  // namespace

void BytecodeGenerator::GenerateBytecode(uintptr_t stack_limit) {}

void BytecodeGenerator::GenerateBytecodeBody() {}

void BytecodeGenerator::GenerateBodyPrologue() {}

void BytecodeGenerator::GenerateBaseConstructorBody() {}

void BytecodeGenerator::GenerateDerivedConstructorBody() {}

void BytecodeGenerator::GenerateAsyncFunctionBody() {}

void BytecodeGenerator::GenerateBodyStatements() {}

void BytecodeGenerator::GenerateBodyStatementsWithoutImplicitFinalReturn() {}

void BytecodeGenerator::AllocateTopLevelRegisters() {}

void BytecodeGenerator::BuildGeneratorPrologue() {}

void BytecodeGenerator::VisitBlock(Block* stmt) {}

void BytecodeGenerator::VisitBlockMaybeDispose(Block* stmt) {}

void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) {}

void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {}

void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {}

void BytecodeGenerator::VisitModuleNamespaceImports() {}

void BytecodeGenerator::BuildDeclareCall(Runtime::FunctionId id) {}

void BytecodeGenerator::VisitModuleDeclarations(Declaration::List* decls) {}

void BytecodeGenerator::VisitGlobalDeclarations(Declaration::List* decls) {}

void BytecodeGenerator::VisitDeclarations(Declaration::List* declarations) {}

void BytecodeGenerator::VisitStatements(
    const ZonePtrList<Statement>* statements) {}

void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {}

void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {}

void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {}

void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
    SloppyBlockFunctionStatement* stmt) {}

void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {}

void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {}

void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {}

void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {}

namespace {

bool IsSmiLiteralSwitchCaseValue(Expression* expr) {}

// Precondition: we called IsSmiLiteral to check this.
inline int ReduceToSmiSwitchCaseValue(Expression* expr) {}

// Is the range of Smi's small enough relative to number of cases?
inline bool IsSpreadAcceptable(int spread, int ncases) {}

struct SwitchInfo {};

// Checks whether we should use a jump table to implement a switch operation.
bool IsSwitchOptimizable(SwitchStatement* stmt, SwitchInfo* info) {}

}  // namespace

// This adds a jump table optimization for switch statements with Smi cases.
// If there are 5+ non-duplicate Smi clauses, and they are sufficiently compact,
// we generate a jump table. In the fall-through path, we put the compare-jumps
// for the non-Smi cases.

// e.g.
//
// switch(x){
//   case -0: out = 10;
//   case 1: out = 11; break;
//   case 0: out = 12; break;
//   case 2: out = 13;
//   case 3: out = 14; break;
//   case 0.5: out = 15; break;
//   case 4: out = 16;
//   case y: out = 17;
//   case 5: out = 18;
//   default: out = 19; break;
// }

// becomes this pseudo-bytecode:

//   lda x
//   star r1
//   test_type number
//   jump_if_false @fallthrough
//   ldar r1
//   test_greater_than_or_equal_to smi_min
//   jump_if_false @fallthrough
//   ldar r1
//   test_less_than_or_equal_to smi_max
//   jump_if_false @fallthrough
//   ldar r1
//   bitwise_or 0
//   star r2
//   test_strict_equal r1
//   jump_if_false @fallthrough
//   ldar r2
//   switch_on_smi {1: @case_1, 2: @case_2, 3: @case_3, 4: @case_4}
// @fallthrough:
//   jump_if_strict_equal -0.0 @case_minus_0.0
//   jump_if_strict_equal 0.5  @case_0.5
//   jump_if_strict_equal y    @case_y
//   jump_if_strict_equal 5    @case_5
//   jump @default
// @case_minus_0.0:
//   <out = 10>
// @case_1
//   <out = 11, break>
// @case_0:
//   <out = 12, break>
// @case_2:
//   <out = 13>
// @case_3:
//   <out = 14, break>
// @case_0.5:
//   <out = 15, break>
// @case_4:
//   <out = 16>
// @case_y:
//   <out = 17>
// @case_5:
//   <out = 18>
// @default:
//   <out = 19, break>

void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {}

template <typename TryBodyFunc, typename CatchBodyFunc>
void BytecodeGenerator::BuildTryCatch(
    TryBodyFunc try_body_func, CatchBodyFunc catch_body_func,
    HandlerTable::CatchPrediction catch_prediction,
    TryCatchStatement* stmt_for_coverage) {}

template <typename TryBodyFunc, typename FinallyBodyFunc>
void BytecodeGenerator::BuildTryFinally(
    TryBodyFunc try_body_func, FinallyBodyFunc finally_body_func,
    HandlerTable::CatchPrediction catch_prediction,
    TryFinallyStatement* stmt_for_coverage) {}

template <typename WrappedFunc>
void BytecodeGenerator::BuildDisposeScope(WrappedFunc wrapped_func,
                                          bool has_await_using) {}

void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
                                           LoopBuilder* loop_builder) {}

void BytecodeGenerator::VisitIterationBodyInHoleCheckElisionScope(
    IterationStatement* stmt, LoopBuilder* loop_builder) {}

void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {}

void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {}

void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {}

void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {}

// Desugar a for-of statement into an application of the iteration protocol.
//
// for (EACH of SUBJECT) BODY
//
//   becomes
//
// iterator = %GetIterator(SUBJECT)
// try {
//
//   loop {
//     // Make sure we are considered 'done' if .next(), .done or .value fail.
//     done = true
//     value = iterator.next()
//     if (value.done) break;
//     value = value.value
//     done = false
//
//     EACH = value
//     BODY
//   }
//   done = true
//
// } catch(e) {
//   iteration_continuation = RETHROW
// } finally {
//   %FinalizeIteration(iterator, done, iteration_continuation)
// }
void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {}

void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {}

void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {}

void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {}

void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {}

void BytecodeGenerator::AddToEagerLiteralsIfEager(FunctionLiteral* literal) {}

void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {}

void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {}

void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr, Register name) {}

void BytecodeGenerator::BuildClassProperty(ClassLiteral::Property* property) {}

void BytecodeGenerator::VisitInitializeClassMembersStatement(
    InitializeClassMembersStatement* stmt) {}

void BytecodeGenerator::VisitInitializeClassStaticElementsStatement(
    InitializeClassStaticElementsStatement* stmt) {}

void BytecodeGenerator::VisitAutoAccessorGetterBody(
    AutoAccessorGetterBody* stmt) {}

void BytecodeGenerator::VisitAutoAccessorSetterBody(
    AutoAccessorSetterBody* stmt) {}

void BytecodeGenerator::BuildInvalidPropertyAccess(MessageTemplate tmpl,
                                                   Property* property) {}

void BytecodeGenerator::BuildPrivateBrandInitialization(Register receiver,
                                                        Variable* brand) {}

void BytecodeGenerator::BuildInstanceMemberInitialization(Register constructor,
                                                          Register instance) {}

void BytecodeGenerator::VisitNativeFunctionLiteral(
    NativeFunctionLiteral* expr) {}

void BytecodeGenerator::VisitConditionalChain(ConditionalChain* expr) {}

void BytecodeGenerator::VisitConditional(Conditional* expr) {}

void BytecodeGenerator::VisitLiteral(Literal* expr) {}

void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {}

void BytecodeGenerator::BuildCreateObjectLiteral(Register literal,
                                                 uint8_t flags, size_t entry) {}

void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {}

// Fill an array with values from an iterator, starting at a given index. It is
// guaranteed that the loop will only terminate if the iterator is exhausted, or
// if one of iterator.next(), value.done, or value.value fail.
//
// In pseudocode:
//
// loop {
//   value = iterator.next()
//   if (value.done) break;
//   value = value.value
//   array[index++] = value
// }
void BytecodeGenerator::BuildFillArrayWithIterator(
    IteratorRecord iterator, Register array, Register index, Register value,
    FeedbackSlot next_value_slot, FeedbackSlot next_done_slot,
    FeedbackSlot index_slot, FeedbackSlot element_slot) {}

void BytecodeGenerator::BuildCreateArrayLiteral(
    const ZonePtrList<Expression>* elements, ArrayLiteral* expr) {}

void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {}

void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {}

bool BytecodeGenerator::IsVariableInRegister(Variable* var, Register reg) {}

void BytecodeGenerator::SetVariableInRegister(Variable* var, Register reg) {}

Variable* BytecodeGenerator::GetPotentialVariableInAccumulator() {}

void BytecodeGenerator::BuildVariableLoad(Variable* variable,
                                          HoleCheckMode hole_check_mode,
                                          TypeofMode typeof_mode) {}

void BytecodeGenerator::BuildVariableLoadForAccumulatorValue(
    Variable* variable, HoleCheckMode hole_check_mode, TypeofMode typeof_mode) {}

void BytecodeGenerator::BuildReturn(int source_position) {}

void BytecodeGenerator::BuildAsyncReturn(int source_position) {}

void BytecodeGenerator::BuildReThrow() {}

void BytecodeGenerator::RememberHoleCheckInCurrentBlock(Variable* variable) {}

void BytecodeGenerator::BuildThrowIfHole(Variable* variable) {}

bool BytecodeGenerator::VariableNeedsHoleCheckInCurrentBlock(
    Variable* variable, HoleCheckMode hole_check_mode) {}

bool BytecodeGenerator::VariableNeedsHoleCheckInCurrentBlockForAssignment(
    Variable* variable, Token::Value op, HoleCheckMode hole_check_mode) {}

void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
                                                            Token::Value op) {}

void BytecodeGenerator::BuildVariableAssignment(
    Variable* variable, Token::Value op, HoleCheckMode hole_check_mode,
    LookupHoistingMode lookup_hoisting_mode) {}

void BytecodeGenerator::BuildLoadNamedProperty(const Expression* object_expr,
                                               Register object,
                                               const AstRawString* name) {}

void BytecodeGenerator::BuildSetNamedProperty(const Expression* object_expr,
                                              Register object,
                                              const AstRawString* name) {}

void BytecodeGenerator::BuildStoreGlobal(Variable* variable) {}

void BytecodeGenerator::BuildLoadKeyedProperty(Register object,
                                               FeedbackSlot slot) {}

// static
BytecodeGenerator::AssignmentLhsData
BytecodeGenerator::AssignmentLhsData::NonProperty(Expression* expr) {}
// static
BytecodeGenerator::AssignmentLhsData
BytecodeGenerator::AssignmentLhsData::NamedProperty(Expression* object_expr,
                                                    Register object,
                                                    const AstRawString* name) {}
// static
BytecodeGenerator::AssignmentLhsData
BytecodeGenerator::AssignmentLhsData::KeyedProperty(Register object,
                                                    Register key) {}
// static
BytecodeGenerator::AssignmentLhsData
BytecodeGenerator::AssignmentLhsData::NamedSuperProperty(
    RegisterList super_property_args) {}
// static
BytecodeGenerator::AssignmentLhsData
BytecodeGenerator::AssignmentLhsData::PrivateMethodOrAccessor(
    AssignType type, Property* property, Register object, Register key) {}
// static
BytecodeGenerator::AssignmentLhsData
BytecodeGenerator::AssignmentLhsData::PrivateDebugEvaluate(AssignType type,
                                                           Property* property,
                                                           Register object) {}
// static
BytecodeGenerator::AssignmentLhsData
BytecodeGenerator::AssignmentLhsData::KeyedSuperProperty(
    RegisterList super_property_args) {}

BytecodeGenerator::AssignmentLhsData BytecodeGenerator::PrepareAssignmentLhs(
    Expression* lhs, AccumulatorPreservingMode accumulator_preserving_mode) {}

// Build the iteration finalizer called in the finally block of an iteration
// protocol execution. This closes the iterator if needed, and suppresses any
// exception it throws if necessary, including the exception when the return
// method is not callable.
//
// In pseudo-code, this builds:
//
// if (!done) {
//   try {
//     let method = iterator.return
//     if (method !== null && method !== undefined) {
//       let return_val = method.call(iterator)
//       if (!%IsObject(return_val)) throw TypeError
//     }
//   } catch (e) {
//     if (iteration_continuation != RETHROW)
//       rethrow e
//   }
// }
//
// For async iterators, iterator.close() becomes await iterator.close().
void BytecodeGenerator::BuildFinalizeIteration(
    IteratorRecord iterator, Register done,
    Register iteration_continuation_token) {}

// Get the default value of a destructuring target. Will mutate the
// destructuring target expression if there is a default value.
//
// For
//   a = b
// in
//   let {a = b} = c
// returns b and mutates the input into a.
Expression* BytecodeGenerator::GetDestructuringDefaultValue(
    Expression** target) {}

// Convert a destructuring assignment to an array literal into a sequence of
// iterator accesses into the value being assigned (in the accumulator).
//
// [a().x, ...b] = accumulator
//
//   becomes
//
// iterator = %GetIterator(accumulator)
// try {
//
//   // Individual assignments read off the value from iterator.next() This gets
//   // repeated per destructuring element.
//   if (!done) {
//     // Make sure we are considered 'done' if .next(), .done or .value fail.
//     done = true
//     var next_result = iterator.next()
//     var tmp_done = next_result.done
//     if (!tmp_done) {
//       value = next_result.value
//       done = false
//     }
//   }
//   if (done)
//     value = undefined
//   a().x = value
//
//   // A spread receives the remaining items in the iterator.
//   var array = []
//   var index = 0
//   %FillArrayWithIterator(iterator, array, index, done)
//   done = true
//   b = array
//
// } catch(e) {
//   iteration_continuation = RETHROW
// } finally {
//   %FinalizeIteration(iterator, done, iteration_continuation)
// }
void BytecodeGenerator::BuildDestructuringArrayAssignment(
    ArrayLiteral* pattern, Token::Value op,
    LookupHoistingMode lookup_hoisting_mode) {}

// Convert a destructuring assignment to an object literal into a sequence of
// property accesses into the value being assigned (in the accumulator).
//
// { y, [x++]: a(), ...b.c } = value
//
//   becomes
//
// var rest_runtime_callargs = new Array(3);
// rest_runtime_callargs[0] = value;
//
// rest_runtime_callargs[1] = "y";
// y = value.y;
//
// var temp1 = %ToName(x++);
// rest_runtime_callargs[2] = temp1;
// a() = value[temp1];
//
// b.c =
// %CopyDataPropertiesWithExcludedPropertiesOnStack.call(rest_runtime_callargs);
void BytecodeGenerator::BuildDestructuringObjectAssignment(
    ObjectLiteral* pattern, Token::Value op,
    LookupHoistingMode lookup_hoisting_mode) {}

void BytecodeGenerator::BuildAssignment(
    const AssignmentLhsData& lhs_data, Token::Value op,
    LookupHoistingMode lookup_hoisting_mode) {}

void BytecodeGenerator::VisitAssignment(Assignment* expr) {}

void BytecodeGenerator::VisitCompoundAssignment(CompoundAssignment* expr) {}

// Suspends the generator to resume at the next suspend_id, with output stored
// in the accumulator. When the generator is resumed, the sent value is loaded
// in the accumulator.
void BytecodeGenerator::BuildSuspendPoint(int position) {}

void BytecodeGenerator::VisitYield(Yield* expr) {}

// Desugaring of (yield* iterable)
//
//   do {
//     const kNext = 0;
//     const kReturn = 1;
//     const kThrow = 2;
//
//     let output; // uninitialized
//
//     let iteratorRecord = GetIterator(iterable);
//     let iterator = iteratorRecord.[[Iterator]];
//     let next = iteratorRecord.[[NextMethod]];
//     let input = undefined;
//     let resumeMode = kNext;
//
//     while (true) {
//       // From the generator to the iterator:
//       // Forward input according to resumeMode and obtain output.
//       switch (resumeMode) {
//         case kNext:
//           output = next.[[Call]](iterator, « »);;
//           break;
//         case kReturn:
//           let iteratorReturn = iterator.return;
//           if (IS_NULL_OR_UNDEFINED(iteratorReturn)) {
//             if (IS_ASYNC_GENERATOR) input = await input;
//             return input;
//           }
//           output = iteratorReturn.[[Call]](iterator, «input»);
//           break;
//         case kThrow:
//           let iteratorThrow = iterator.throw;
//           if (IS_NULL_OR_UNDEFINED(iteratorThrow)) {
//             let iteratorReturn = iterator.return;
//             if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
//               output = iteratorReturn.[[Call]](iterator, « »);
//               if (IS_ASYNC_GENERATOR) output = await output;
//               if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
//             }
//             throw MakeTypeError(kThrowMethodMissing);
//           }
//           output = iteratorThrow.[[Call]](iterator, «input»);
//           break;
//       }
//
//       if (IS_ASYNC_GENERATOR) output = await output;
//       if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
//       if (output.done) break;
//
//       // From the generator to its user:
//       // Forward output, receive new input, and determine resume mode.
//       if (IS_ASYNC_GENERATOR) {
//         // Resolve the promise for the current AsyncGeneratorRequest.
//         %_AsyncGeneratorResolve(output.value, /* done = */ false)
//       }
//       input = Suspend(output);
//       resumeMode = %GeneratorGetResumeMode();
//     }
//
//     if (resumeMode === kReturn) {
//       return output.value;
//     }
//     output.value
//   }
void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {}

void BytecodeGenerator::BuildAwait(int position) {}

void BytecodeGenerator::VisitAwait(Await* expr) {}

void BytecodeGenerator::VisitThrow(Throw* expr) {}

void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) {}

void BytecodeGenerator::BuildPrivateDebugDynamicGet(Property* property,
                                                    Register obj) {}

void BytecodeGenerator::BuildPrivateDebugDynamicSet(Property* property,
                                                    Register obj,
                                                    Register value) {}

void BytecodeGenerator::BuildPrivateGetterAccess(Register object,
                                                 Register accessor_pair) {}

void BytecodeGenerator::BuildPrivateSetterAccess(Register object,
                                                 Register accessor_pair,
                                                 Register value) {}

void BytecodeGenerator::BuildPrivateMethodIn(Variable* private_name,
                                             Expression* object_expression) {}

void BytecodeGenerator::BuildPrivateBrandCheck(Property* property,
                                               Register object) {}

void BytecodeGenerator::VisitPropertyLoadForRegister(Register obj,
                                                     Property* expr,
                                                     Register destination) {}

void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
                                                    Register opt_receiver_out) {}

void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property,
                                                    Register opt_receiver_out) {}

template <typename ExpressionFunc>
void BytecodeGenerator::BuildOptionalChain(ExpressionFunc expression_func) {}

void BytecodeGenerator::VisitOptionalChain(OptionalChain* expr) {}

void BytecodeGenerator::VisitProperty(Property* expr) {}

void BytecodeGenerator::VisitArguments(const ZonePtrList<Expression>* args,
                                       RegisterList* arg_regs) {}

void BytecodeGenerator::VisitCall(Call* expr) {}

void BytecodeGenerator::VisitCallSuper(Call* expr) {}

void BytecodeGenerator::BuildInstanceInitializationAfterSuperCall(
    Register this_function, Register instance) {}

void BytecodeGenerator::BuildGetAndCheckSuperConstructor(
    Register this_function, Register new_target, Register constructor,
    BytecodeLabel* super_ctor_call_done) {}

void BytecodeGenerator::BuildSuperCallOptimization(
    Register this_function, Register new_target,
    Register constructor_then_instance, BytecodeLabel* super_ctor_call_done) {}

void BytecodeGenerator::VisitCallNew(CallNew* expr) {}

void BytecodeGenerator::VisitSuperCallForwardArgs(SuperCallForwardArgs* expr) {}

void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {}

void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {}

void BytecodeGenerator::VisitForTypeOfValue(Expression* expr) {}

void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {}

void BytecodeGenerator::VisitNot(UnaryOperation* expr) {}

void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {}

void BytecodeGenerator::VisitDelete(UnaryOperation* unary) {}

void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {}

void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {}

void BytecodeGenerator::VisitNaryOperation(NaryOperation* expr) {}

void BytecodeGenerator::BuildLiteralCompareNil(
    Token::Value op, BytecodeArrayBuilder::NilValue nil) {}

void BytecodeGenerator::BuildLiteralStrictCompareBoolean(Literal* literal) {}

bool BytecodeGenerator::IsLocalVariableWithInternalizedStringHint(
    Expression* expr) {}

static bool IsTypeof(Expression* expr) {}

static bool IsCharU(const AstRawString* str) {}

static bool IsLiteralCompareTypeof(CompareOperation* expr,
                                   Expression** sub_expr,
                                   TestTypeOfFlags::LiteralFlag* flag,
                                   const AstStringConstants* ast_constants) {}

void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {}

void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {}

void BytecodeGenerator::VisitNaryArithmeticExpression(NaryOperation* expr) {}

// Note: the actual spreading is performed by the surrounding expression's
// visitor.
void BytecodeGenerator::VisitSpread(Spread* expr) {}

void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {}

void BytecodeGenerator::VisitImportCallExpression(ImportCallExpression* expr) {}

void BytecodeGenerator::BuildGetIterator(IteratorType hint) {}

// Returns an IteratorRecord which is valid for the lifetime of the current
// register_allocation_scope.
BytecodeGenerator::IteratorRecord BytecodeGenerator::BuildGetIteratorRecord(
    Register next, Register object, IteratorType hint) {}

BytecodeGenerator::IteratorRecord BytecodeGenerator::BuildGetIteratorRecord(
    IteratorType hint) {}

void BytecodeGenerator::BuildIteratorNext(const IteratorRecord& iterator,
                                          Register next_result) {}

void BytecodeGenerator::BuildCallIteratorMethod(Register iterator,
                                                const AstRawString* method_name,
                                                RegisterList receiver_and_args,
                                                BytecodeLabel* if_called,
                                                BytecodeLabels* if_notcalled) {}

void BytecodeGenerator::BuildIteratorClose(const IteratorRecord& iterator,
                                           Expression* expr) {}

void BytecodeGenerator::VisitGetTemplateObject(GetTemplateObject* expr) {}

void BytecodeGenerator::VisitTemplateLiteral(TemplateLiteral* expr) {}

void BytecodeGenerator::BuildThisVariableLoad() {}

void BytecodeGenerator::VisitThisExpression(ThisExpression* expr) {}

void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {}

void BytecodeGenerator::VisitSuperPropertyReference(
    SuperPropertyReference* expr) {}

void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {}

void BytecodeGenerator::VisitNaryCommaExpression(NaryOperation* expr) {}

void BytecodeGenerator::VisitLogicalTestSubExpression(
    Token::Value token, Expression* expr, BytecodeLabels* then_labels,
    BytecodeLabels* else_labels, int coverage_slot) {}

void BytecodeGenerator::VisitLogicalTest(Token::Value token, Expression* left,
                                         Expression* right,
                                         int right_coverage_slot) {}

void BytecodeGenerator::VisitNaryLogicalTest(
    Token::Value token, NaryOperation* expr,
    const NaryCodeCoverageSlots* coverage_slots) {}

bool BytecodeGenerator::VisitLogicalOrSubExpression(Expression* expr,
                                                    BytecodeLabels* end_labels,
                                                    int coverage_slot) {}

bool BytecodeGenerator::VisitLogicalAndSubExpression(Expression* expr,
                                                     BytecodeLabels* end_labels,
                                                     int coverage_slot) {}

bool BytecodeGenerator::VisitNullishSubExpression(Expression* expr,
                                                  BytecodeLabels* end_labels,
                                                  int coverage_slot) {}

void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {}

void BytecodeGenerator::VisitNaryLogicalOrExpression(NaryOperation* expr) {}

void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {}

void BytecodeGenerator::VisitNaryLogicalAndExpression(NaryOperation* expr) {}

void BytecodeGenerator::VisitNullishExpression(BinaryOperation* binop) {}

void BytecodeGenerator::VisitNaryNullishExpression(NaryOperation* expr) {}

void BytecodeGenerator::BuildNewLocalActivationContext() {}

void BytecodeGenerator::BuildLocalActivationContextInitialization() {}

void BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) {}

void BytecodeGenerator::BuildNewLocalWithContext(Scope* scope) {}

void BytecodeGenerator::BuildNewLocalCatchContext(Scope* scope) {}

void BytecodeGenerator::VisitLiteralAccessor(LiteralProperty* property,
                                             Register value_out) {}

void BytecodeGenerator::VisitArgumentsObject(Variable* variable) {}

void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) {}

void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {}

void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {}

void BytecodeGenerator::BuildGeneratorObjectVariableInitialization() {}

void BytecodeGenerator::BuildPushUndefinedIntoRegisterList(
    RegisterList* reg_list) {}

void BytecodeGenerator::BuildLoadPropertyKey(LiteralProperty* property,
                                             Register out_reg) {}

int BytecodeGenerator::AllocateBlockCoverageSlotIfEnabled(
    AstNode* node, SourceRangeKind kind) {}

int BytecodeGenerator::AllocateNaryBlockCoverageSlotIfEnabled(
    NaryOperation* node, size_t index) {}

int BytecodeGenerator::AllocateConditionalChainBlockCoverageSlotIfEnabled(
    ConditionalChain* node, SourceRangeKind kind, size_t index) {}

void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
    AstNode* node, SourceRangeKind kind) {}

void BytecodeGenerator::BuildIncrementBlockCoverageCounterIfEnabled(
    int coverage_array_slot) {}

// Visits the expression |expr| and places the result in the accumulator.
BytecodeGenerator::TypeHint BytecodeGenerator::VisitForAccumulatorValue(
    Expression* expr) {}

void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) {}

// Visits the expression |expr| and discards the result.
void BytecodeGenerator::VisitForEffect(Expression* expr) {}

// Visits the expression |expr| and returns the register containing
// the expression result.
Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {}

// Visits the expression |expr| and stores the expression result in
// |destination|.
void BytecodeGenerator::VisitForRegisterValue(Expression* expr,
                                              Register destination) {}

// Visits the expression |expr| and pushes the result into a new register
// added to the end of |reg_list|.
void BytecodeGenerator::VisitAndPushIntoRegisterList(Expression* expr,
                                                     RegisterList* reg_list) {}

void BytecodeGenerator::BuildTest(ToBooleanMode mode,
                                  BytecodeLabels* then_labels,
                                  BytecodeLabels* else_labels,
                                  TestFallthrough fallthrough) {}

// Visits the expression |expr| for testing its boolean value and jumping to the
// |then| or |other| label depending on value and short-circuit semantics
void BytecodeGenerator::VisitForTest(Expression* expr,
                                     BytecodeLabels* then_labels,
                                     BytecodeLabels* else_labels,
                                     TestFallthrough fallthrough) {}

// Visits the expression |expr| for testing its nullish value and jumping to the
// |then| or |other| label depending on value and short-circuit semantics
void BytecodeGenerator::VisitForNullishTest(Expression* expr,
                                            BytecodeLabels* then_labels,
                                            BytecodeLabels* test_next_labels,
                                            BytecodeLabels* else_labels) {}

void BytecodeGenerator::VisitInSameTestExecutionScope(Expression* expr) {}

void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) {}

template <typename T>
void BytecodeGenerator::VisitInHoleCheckElisionScope(T* node) {}

BytecodeGenerator::TypeHint
BytecodeGenerator::VisitInHoleCheckElisionScopeForAccumulatorValue(
    Expression* expr) {}

Register BytecodeGenerator::GetRegisterForLocalVariable(Variable* variable) {}

BytecodeGenerator::TypeHint BytecodeGenerator::GetTypeHintForLocalVariable(
    Variable* variable) {}

FunctionKind BytecodeGenerator::function_kind() const {}

LanguageMode BytecodeGenerator::language_mode() const {}

Register BytecodeGenerator::generator_object() const {}

FeedbackVectorSpec* BytecodeGenerator::feedback_spec() {}

int BytecodeGenerator::feedback_index(FeedbackSlot slot) const {}

FeedbackSlot BytecodeGenerator::GetCachedLoadGlobalICSlot(
    TypeofMode typeof_mode, Variable* variable) {}

FeedbackSlot BytecodeGenerator::GetCachedStoreGlobalICSlot(
    LanguageMode language_mode, Variable* variable) {}

FeedbackSlot BytecodeGenerator::GetCachedLoadICSlot(const Expression* expr,
                                                    const AstRawString* name) {}

FeedbackSlot BytecodeGenerator::GetCachedLoadSuperICSlot(
    const AstRawString* name) {}

FeedbackSlot BytecodeGenerator::GetCachedStoreICSlot(const Expression* expr,
                                                     const AstRawString* name) {}

int BytecodeGenerator::GetCachedCreateClosureSlot(FunctionLiteral* literal) {}

FeedbackSlot BytecodeGenerator::GetDummyCompareICSlot() {}

}  // namespace interpreter
}  // namespace internal
}  // namespace v8