/*
 * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
 * Copyright (C) 2012 Igalia, S.L.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "BytecodeGenerator.h"

#include "ArithProfile.h"
#include "BuiltinExecutables.h"
#include "BuiltinNames.h"
#include "BytecodeGeneratorBaseInlines.h"
#include "BytecodeGeneratorification.h"
#include "BytecodeLivenessAnalysis.h"
#include "BytecodeUseDef.h"
#include "CatchScope.h"
#include "DefinePropertyAttributes.h"
#include "Interpreter.h"
#include "JSAsyncGenerator.h"
#include "JSBigInt.h"
#include "JSCInlines.h"
#include "JSFunction.h"
#include "JSGeneratorFunction.h"
#include "JSImmutableButterfly.h"
#include "JSLexicalEnvironment.h"
#include "JSTemplateObjectDescriptor.h"
#include "LinkTimeConstant.h"
#include "LowLevelInterpreter.h"
#include "Options.h"
#include "PreciseJumpTargetsInlines.h"
#include "StackAlignment.h"
#include "StrongInlines.h"
#include "SuperSamplerBytecodeScope.h"
#include "UnlinkedCodeBlock.h"
#include "UnlinkedEvalCodeBlock.h"
#include "UnlinkedFunctionCodeBlock.h"
#include "UnlinkedMetadataTableInlines.h"
#include "UnlinkedModuleProgramCodeBlock.h"
#include "UnlinkedProgramCodeBlock.h"
#include <wtf/BitVector.h>
#include <wtf/CommaPrinter.h>
#include <wtf/Optional.h>
#include <wtf/SmallPtrSet.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/WTFString.h>

namespace JSC {

template<typename CallOp, typename = std::true_type>
struct VarArgsOp;

template<typename CallOp>
struct VarArgsOp<CallOp, std::enable_if_t<std::is_same<CallOp, OpTailCall>::value, std::true_type>> {
    using type = OpTailCallVarargs;
};


template<typename CallOp>
struct VarArgsOp<CallOp, std::enable_if_t<!std::is_same<CallOp, OpTailCall>::value, std::true_type>> {
    using type = OpCallVarargs;
};

template<>
void GenericLabel<JSGeneratorTraits>::setLocation(BytecodeGenerator& generator, unsigned location)
{
    m_location = location;
    
    for (auto offset : m_unresolvedJumps) {
        auto instruction = generator.m_writer.ref(offset);
        int target = m_location - offset;

#define CASE(__op) \
    case __op::opcodeID:  \
        instruction->cast<__op>()->setTargetLabel(BoundLabel(target), [&]() { \
            generator.m_codeBlock->addOutOfLineJumpTarget(instruction.offset(), target); \
            return BoundLabel(); \
        }); \
        break;

        switch (instruction->opcodeID()) {
        CASE(OpJmp)
        CASE(OpJtrue)
        CASE(OpJfalse)
        CASE(OpJeqNull)
        CASE(OpJneqNull)
        CASE(OpJundefinedOrNull)
        CASE(OpJnundefinedOrNull)
        CASE(OpJeq)
        CASE(OpJstricteq)
        CASE(OpJneq)
        CASE(OpJneqPtr)
        CASE(OpJnstricteq)
        CASE(OpJless)
        CASE(OpJlesseq)
        CASE(OpJgreater)
        CASE(OpJgreatereq)
        CASE(OpJnless)
        CASE(OpJnlesseq)
        CASE(OpJngreater)
        CASE(OpJngreatereq)
        CASE(OpJbelow)
        CASE(OpJbeloweq)
        default:
            ASSERT_NOT_REACHED();
        }
#undef CASE
    }
}

void Variable::dump(PrintStream& out) const
{
    out.print(
        "{ident = ", m_ident,
        ", offset = ", m_offset,
        ", local = ", RawPointer(m_local),
        ", attributes = ", m_attributes,
        ", kind = ", m_kind,
        ", symbolTableConstantIndex = ", m_symbolTableConstantIndex,
        ", isLexicallyScoped = ", m_isLexicallyScoped, "}");
}

FinallyContext::FinallyContext(BytecodeGenerator& generator, Label& finallyLabel)
    : m_outerContext(generator.m_currentFinallyContext)
    , m_finallyLabel(&finallyLabel)
{
    ASSERT(m_jumps.isEmpty());
    m_completionRecord.typeRegister = generator.newTemporary();
    m_completionRecord.valueRegister = generator.newTemporary();
    generator.emitLoad(completionTypeRegister(), CompletionType::Normal);
    generator.moveEmptyValue(completionValueRegister());
}

ParserError BytecodeGenerator::generate()
{
    m_codeBlock->setThisRegister(m_thisRegister.virtualRegister());

    emitLogShadowChickenPrologueIfNecessary();
    
    // If we have declared a variable named "arguments" and we are using arguments then we should
    // perform that assignment now.
    if (m_needToInitializeArguments)
        initializeVariable(variable(propertyNames().arguments), m_argumentsRegister);

    if (m_restParameter)
        m_restParameter->emit(*this);

    {
        RefPtr<RegisterID> temp = newTemporary();
        RefPtr<RegisterID> tolLevelScope;
        for (auto functionPair : m_functionsToInitialize) {
            FunctionMetadataNode* metadata = functionPair.first;
            FunctionVariableType functionType = functionPair.second;
            emitNewFunction(temp.get(), metadata);
            if (functionType == NormalFunctionVariable)
                initializeVariable(variable(metadata->ident()), temp.get());
            else if (functionType == TopLevelFunctionVariable) {
                if (!tolLevelScope) {
                    // We know this will resolve to the top level scope or global object because our parser/global initialization code 
                    // doesn't allow let/const/class variables to have the same names as functions.
                    // This is a top level function, and it's an error to ever create a top level function
                    // name that would resolve to a lexical variable. E.g:
                    // ```
                    //     function f() {
                    //         {
                    //             let x;
                    //             {
                    //             //// error thrown here
                    //                  eval("function x(){}");
                    //             }
                    //         }
                    //     }
                    // ```
                    // Therefore, we're guaranteed to have this resolve to a top level variable.
                    RefPtr<RegisterID> tolLevelObjectScope = emitResolveScope(nullptr, Variable(metadata->ident()));
                    tolLevelScope = newBlockScopeVariable();
                    move(tolLevelScope.get(), tolLevelObjectScope.get());
                }
                emitPutToScope(tolLevelScope.get(), Variable(metadata->ident()), temp.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
            } else
                RELEASE_ASSERT_NOT_REACHED();
        }
    }
    
    bool callingClassConstructor = false;
    switch (constructorKind()) {
    case ConstructorKind::None:
    case ConstructorKind::Naked:
        break;
    case ConstructorKind::Base:
    case ConstructorKind::Extends:
        callingClassConstructor = !isConstructor();
        break;
    }
    if (!callingClassConstructor)
        m_scopeNode->emitBytecode(*this);
    else {
        // At this point we would have emitted an unconditional throw followed by some nonsense that's
        // just an artifact of how this generator is structured. That code never runs, but it confuses
        // bytecode analyses because it constitutes an unterminated basic block. So, we terminate the
        // basic block the strongest way possible.
        emitUnreachable();
    }

    for (auto& handler : m_exceptionHandlersToEmit) {
        Ref<Label> realCatchTarget = newLabel();
        TryData* tryData = handler.tryData;

        OpCatch::emit(this, handler.exceptionRegister, handler.thrownValueRegister);
        realCatchTarget->setLocation(*this, m_lastInstruction.offset());
        if (handler.completionTypeRegister.isValid()) {
            RegisterID completionTypeRegister { handler.completionTypeRegister };
            CompletionType completionType =
                tryData->handlerType == HandlerType::Finally || tryData->handlerType == HandlerType::SynthesizedFinally
                ? CompletionType::Throw
                : CompletionType::Normal;
            emitLoad(&completionTypeRegister, completionType);
        }
        m_codeBlock->addJumpTarget(m_lastInstruction.offset());


        emitJump(tryData->target.get());
        tryData->target = WTFMove(realCatchTarget);
    }

    m_staticPropertyAnalyzer.kill();

    for (auto& range : m_tryRanges) {
        int start = range.start->bind();
        int end = range.end->bind();
        
        // This will happen for empty try blocks and for some cases of finally blocks:
        //
        // try {
        //    try {
        //    } finally {
        //        return 42;
        //        // *HERE*
        //    }
        // } finally {
        //    print("things");
        // }
        //
        // The return will pop scopes to execute the outer finally block. But this includes
        // popping the try context for the inner try. The try context is live in the fall-through
        // part of the finally block not because we will emit a handler that overlaps the finally,
        // but because we haven't yet had a chance to plant the catch target. Then when we finish
        // emitting code for the outer finally block, we repush the try contex, this time with a
        // new start index. But that means that the start index for the try range corresponding
        // to the inner-finally-following-the-return (marked as "*HERE*" above) will be greater
        // than the end index of the try block. This is harmless since end < start handlers will
        // never get matched in our logic, but we do the runtime a favor and choose to not emit
        // such handlers at all.
        if (end <= start)
            continue;
        
        UnlinkedHandlerInfo info(static_cast<uint32_t>(start), static_cast<uint32_t>(end),
            static_cast<uint32_t>(range.tryData->target->bind()), range.tryData->handlerType);
        m_codeBlock->addExceptionHandler(info);
    }
    

    if (isGeneratorOrAsyncFunctionBodyParseMode(m_codeBlock->parseMode()))
        performGeneratorification(*this, m_codeBlock.get(), m_writer, m_generatorFrameSymbolTable.get(), m_generatorFrameSymbolTableIndex);

    RELEASE_ASSERT(static_cast<unsigned>(m_codeBlock->numCalleeLocals()) < static_cast<unsigned>(FirstConstantRegisterIndex));
    m_codeBlock->setInstructions(m_writer.finalize());

    m_codeBlock->shrinkToFit();

    if (m_expressionTooDeep)
        return ParserError(ParserError::OutOfMemory);
    return ParserError(ParserError::ErrorNone);
}

BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment* parentScopeTDZVariables)
    : BytecodeGeneratorBase(Strong<UnlinkedCodeBlock>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
    , m_codeGenerationMode(codeGenerationMode)
    , m_scopeNode(programNode)
    , m_thisRegister(CallFrame::thisArgumentOffset())
    , m_codeType(GlobalCode)
    , m_vm(vm)
    , m_needsToUpdateArrowFunctionContext(programNode->usesArrowFunction() || programNode->usesEval())
{
    ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables->size());

    m_codeBlock->setNumParameters(1); // Allocate space for "this"

    emitEnter();

    allocateAndEmitScope();

    emitCheckTraps();

    const FunctionStack& functionStack = programNode->functionStack();

    for (auto* function : functionStack)
        m_functionsToInitialize.append(std::make_pair(function, TopLevelFunctionVariable));

    if (Options::validateBytecode()) {
        for (auto& entry : programNode->varDeclarations())
            RELEASE_ASSERT(entry.value.isVar());
    }
    codeBlock->setVariableDeclarations(programNode->varDeclarations());
    codeBlock->setLexicalDeclarations(programNode->lexicalVariables());
    // Even though this program may have lexical variables that go under TDZ, when linking the get_from_scope/put_to_scope
    // operations we emit we will have ResolveTypes that implictly do TDZ checks. Therefore, we don't need
    // additional TDZ checks on top of those. This is why we can omit pushing programNode->lexicalVariables()
    // to the TDZ stack.
    
    if (needsToUpdateArrowFunctionContext()) {
        initializeArrowFunctionContextScopeIfNeeded();
        emitPutThisToArrowFunctionContextScope();
    }
}

BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment* parentScopeTDZVariables)
    : BytecodeGeneratorBase(Strong<UnlinkedCodeBlock>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
    , m_codeGenerationMode(codeGenerationMode)
    , m_scopeNode(functionNode)
    , m_codeType(FunctionCode)
    , m_vm(vm)
    , m_isBuiltinFunction(codeBlock->isBuiltinFunction())
    , m_usesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode())
    // FIXME: We should be able to have tail call elimination with the profiler
    // enabled. This is currently not possible because the profiler expects
    // op_will_call / op_did_call pairs before and after a call, which are not
    // compatible with tail calls (we have no way of emitting op_did_call).
    // https://bugs.webkit.org/show_bug.cgi?id=148819
    //
    // Note that we intentionally enable tail call for naked constructors since it does not have special code for "return".
    , m_inTailPosition(Options::useTailCalls() && !isConstructor() && constructorKind() == ConstructorKind::None && isStrictMode())
    , m_needsToUpdateArrowFunctionContext(functionNode->usesArrowFunction() || functionNode->usesEval())
    , m_derivedContextType(codeBlock->derivedContextType())
{
    SymbolTable* functionSymbolTable = SymbolTable::create(m_vm);
    functionSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval);
    int symbolTableConstantIndex = 0;

    FunctionParameters& parameters = *functionNode->parameters(); 
    // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-functiondeclarationinstantiation
    // This implements IsSimpleParameterList in the Ecma 2015 spec.
    // If IsSimpleParameterList is false, we will create a strict-mode like arguments object.
    // IsSimpleParameterList is false if the argument list contains any default parameter values,
    // a rest parameter, or any destructuring patterns.
    // If we do have default parameters, destructuring parameters, or a rest parameter, our parameters will be allocated in a different scope.
    bool isSimpleParameterList = parameters.isSimpleParameterList();

    SourceParseMode parseMode = codeBlock->parseMode();

    bool containsArrowOrEvalButNotInArrowBlock = ((functionNode->usesArrowFunction() && functionNode->doAnyInnerArrowFunctionsUseAnyFeature()) || functionNode->usesEval()) && !m_codeBlock->isArrowFunction();
    bool shouldCaptureSomeOfTheThings = shouldEmitDebugHooks() || functionNode->needsActivation() || containsArrowOrEvalButNotInArrowBlock;

    bool shouldCaptureAllOfTheThings = shouldEmitDebugHooks() || codeBlock->usesEval();
    bool needsArguments = ((functionNode->usesArguments() && !codeBlock->isArrowFunction()) || codeBlock->usesEval() || (functionNode->usesArrowFunction() && !codeBlock->isArrowFunction() && isArgumentsUsedInInnerArrowFunction()));

    if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode)) {
        // Generator and AsyncFunction never provides "arguments". "arguments" reference will be resolved in an upper generator function scope.
        needsArguments = false;
    }

    if (isGeneratorOrAsyncFunctionWrapperParseMode(parseMode) && needsArguments) {
        // Generator does not provide "arguments". Instead, wrapping GeneratorFunction provides "arguments".
        // This is because arguments of a generator should be evaluated before starting it.
        // To workaround it, we evaluate these arguments as arguments of a wrapping generator function, and reference it from a generator.
        //
        //    function *gen(a, b = hello())
        //    {
        //        return {
        //            @generatorNext: function (@generator, @generatorState, @generatorValue, @generatorResumeMode, @generatorFrame)
        //            {
        //                arguments;  // This `arguments` should reference to the gen's arguments.
        //                ...
        //            }
        //        }
        //    }
        shouldCaptureSomeOfTheThings = true;
    }

    if (shouldCaptureAllOfTheThings)
        functionNode->varDeclarations().markAllVariablesAsCaptured();
    
    auto captures = scopedLambda<bool (UniquedStringImpl*)>([&] (UniquedStringImpl* uid) -> bool {
        if (!shouldCaptureSomeOfTheThings)
            return false;
        if (needsArguments && uid == propertyNames().arguments.impl()) {
            // Actually, we only need to capture the arguments object when we "need full activation"
            // because of name scopes. But historically we did it this way, so for now we just preserve
            // the old behavior.
            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=143072
            return true;
        }
        return functionNode->captures(uid);
    });
    auto varKind = [&] (UniquedStringImpl* uid) -> VarKind {
        return captures(uid) ? VarKind::Scope : VarKind::Stack;
    };

    m_calleeRegister.setIndex(CallFrameSlot::callee);

    initializeParameters(parameters);
    ASSERT(!(isSimpleParameterList && m_restParameter));

    emitEnter();

    if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode))
        m_generatorRegister = &m_parameters[1];

    allocateAndEmitScope();

    emitCheckTraps();
    
    if (functionNameIsInScope(functionNode->ident(), functionNode->functionMode())) {
        ASSERT(parseMode != SourceParseMode::GeneratorBodyMode);
        ASSERT(!isAsyncFunctionBodyParseMode(parseMode));
        bool isDynamicScope = functionNameScopeIsDynamic(codeBlock->usesEval(), codeBlock->isStrictMode());
        bool isFunctionNameCaptured = captures(functionNode->ident().impl());
        bool markAsCaptured = isDynamicScope || isFunctionNameCaptured;
        emitPushFunctionNameScope(functionNode->ident(), &m_calleeRegister, markAsCaptured);
    }

    if (shouldCaptureSomeOfTheThings)
        m_lexicalEnvironmentRegister = addVar();

    if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode) || shouldCaptureSomeOfTheThings || shouldEmitTypeProfilerHooks())
        symbolTableConstantIndex = addConstantValue(functionSymbolTable)->index();

    // We can allocate the "var" environment if we don't have default parameter expressions. If we have
    // default parameter expressions, we have to hold off on allocating the "var" environment because
    // the parent scope of the "var" environment is the parameter environment.
    if (isSimpleParameterList)
        initializeVarLexicalEnvironment(symbolTableConstantIndex, functionSymbolTable, shouldCaptureSomeOfTheThings);

    // Figure out some interesting facts about our arguments.
    bool capturesAnyArgumentByName = false;
    if (functionNode->hasCapturedVariables()) {
        FunctionParameters& parameters = *functionNode->parameters();
        for (size_t i = 0; i < parameters.size(); ++i) {
            auto pattern = parameters.at(i).first;
            if (!pattern->isBindingNode())
                continue;
            const Identifier& ident = static_cast<const BindingNode*>(pattern)->boundProperty();
            capturesAnyArgumentByName |= captures(ident.impl());
        }
    }
    
    if (capturesAnyArgumentByName)
        ASSERT(m_lexicalEnvironmentRegister);

    // Need to know what our functions are called. Parameters have some goofy behaviors when it
    // comes to functions of the same name.
    for (FunctionMetadataNode* function : functionNode->functionStack())
        m_functions.add(function->ident().impl());
    
    if (needsArguments) {
        // Create the arguments object now. We may put the arguments object into the activation if
        // it is captured. Either way, we create two arguments object variables: one is our
        // private variable that is immutable, and another that is the user-visible variable. The
        // immutable one is only used here, or during formal parameter resolutions if we opt for
        // DirectArguments.
        
        m_argumentsRegister = addVar();
        m_argumentsRegister->ref();
    }
    
    if (needsArguments && !codeBlock->isStrictMode() && isSimpleParameterList) {
        // If we captured any formal parameter by name, then we use ScopedArguments. Otherwise we
        // use DirectArguments. With ScopedArguments, we lift all of our arguments into the
        // activation.
        
        if (capturesAnyArgumentByName) {
            functionSymbolTable->setArgumentsLength(vm, parameters.size());
            
            // For each parameter, we have two possibilities:
            // Either it's a binding node with no function overlap, in which case it gets a name
            // in the symbol table - or it just gets space reserved in the symbol table. Either
            // way we lift the value into the scope.
            for (unsigned i = 0; i < parameters.size(); ++i) {
                ScopeOffset offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary);
                functionSymbolTable->setArgumentOffset(vm, i, offset);
                if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first)) {
                    VarOffset varOffset(offset);
                    SymbolTableEntry entry(varOffset);
                    // Stores to these variables via the ScopedArguments object will not do
                    // notifyWrite(), since that would be cumbersome. Also, watching formal
                    // parameters when "arguments" is in play is unlikely to be super profitable.
                    // So, we just disable it.
                    entry.disableWatching(m_vm);
                    functionSymbolTable->set(NoLockingNecessary, name, entry);
                }
                OpPutToScope::emit(this, m_lexicalEnvironmentRegister, UINT_MAX, virtualRegisterForArgument(1 + i), GetPutInfo(ThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization), SymbolTableOrScopeDepth::symbolTable(VirtualRegister { symbolTableConstantIndex }), offset.offset());
            }
            
            // This creates a scoped arguments object and copies the overflow arguments into the
            // scope. It's the equivalent of calling ScopedArguments::createByCopying().
            OpCreateScopedArguments::emit(this, m_argumentsRegister, m_lexicalEnvironmentRegister);
        } else {
            // We're going to put all parameters into the DirectArguments object. First ensure
            // that the symbol table knows that this is happening.
            for (unsigned i = 0; i < parameters.size(); ++i) {
                if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first))
                    functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(DirectArgumentsOffset(i))));
            }
            
            OpCreateDirectArguments::emit(this, m_argumentsRegister);
        }
    } else if (isSimpleParameterList) {
        // Create the formal parameters the normal way. Any of them could be captured, or not. If
        // captured, lift them into the scope. We cannot do this if we have default parameter expressions
        // because when default parameter expressions exist, they belong in their own lexical environment
        // separate from the "var" lexical environment.
        for (unsigned i = 0; i < parameters.size(); ++i) {
            UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first);
            if (!name)
                continue;
            
            if (!captures(name)) {
                // This is the easy case - just tell the symbol table about the argument. It will
                // be accessed directly.
                functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(virtualRegisterForArgument(1 + i))));
                continue;
            }
            
            ScopeOffset offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary);
            const Identifier& ident =
                static_cast<const BindingNode*>(parameters.at(i).first)->boundProperty();
            functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(offset)));
            
            OpPutToScope::emit(this, m_lexicalEnvironmentRegister, addConstant(ident), virtualRegisterForArgument(1 + i), GetPutInfo(ThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization), SymbolTableOrScopeDepth::symbolTable(VirtualRegister { symbolTableConstantIndex }), offset.offset());
        }
    }
    
    if (needsArguments && (codeBlock->isStrictMode() || !isSimpleParameterList)) {
        // Allocate a cloned arguments object.
        OpCreateClonedArguments::emit(this, m_argumentsRegister);
    }
    
    // There are some variables that need to be preinitialized to something other than Undefined:
    //
    // - "arguments": unless it's used as a function or parameter, this should refer to the
    //   arguments object.
    //
    // - functions: these always override everything else.
    //
    // The most logical way to do all of this is to initialize none of the variables until now,
    // and then initialize them in BytecodeGenerator::generate() in such an order that the rules
    // for how these things override each other end up holding. We would initialize "arguments" first, 
    // then all arguments, then the functions.
    //
    // But some arguments are already initialized by default, since if they aren't captured and we
    // don't have "arguments" then we just point the symbol table at the stack slot of those
    // arguments. We end up initializing the rest of the arguments that have an uncomplicated
    // binding (i.e. don't involve destructuring) above when figuring out how to lay them out,
    // because that's just the simplest thing. This means that when we initialize them, we have to
    // watch out for the things that override arguments (namely, functions).
    
    // This is our final act of weirdness. "arguments" is overridden by everything except the
    // callee. We add it to the symbol table if it's not already there and it's not an argument.
    bool shouldCreateArgumentsVariableInParameterScope = false;
    if (needsArguments) {
        // If "arguments" is overridden by a function or destructuring parameter name, then it's
        // OK for us to call createVariable() because it won't change anything. It's also OK for
        // us to them tell BytecodeGenerator::generate() to write to it because it will do so
        // before it initializes functions and destructuring parameters. But if "arguments" is
        // overridden by a "simple" function parameter, then we have to bail: createVariable()
        // would assert and BytecodeGenerator::generate() would write the "arguments" after the
        // argument value had already been properly initialized.
        
        bool haveParameterNamedArguments = false;
        for (unsigned i = 0; i < parameters.size(); ++i) {
            UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first);
            if (name == propertyNames().arguments.impl()) {
                haveParameterNamedArguments = true;
                break;
            }
        }

        bool shouldCreateArgumensVariable = !haveParameterNamedArguments
            && !SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(m_codeBlock->parseMode());
        shouldCreateArgumentsVariableInParameterScope = shouldCreateArgumensVariable && !isSimpleParameterList;
        // Do not create arguments variable in case of Arrow function. Value will be loaded from parent scope
        if (shouldCreateArgumensVariable && !shouldCreateArgumentsVariableInParameterScope) {
            createVariable(
                propertyNames().arguments, varKind(propertyNames().arguments.impl()), functionSymbolTable);

            m_needToInitializeArguments = true;
        }
    }

    for (FunctionMetadataNode* function : functionNode->functionStack()) {
        const Identifier& ident = function->ident();
        createVariable(ident, varKind(ident.impl()), functionSymbolTable);
        m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable));
    }
    for (auto& entry : functionNode->varDeclarations()) {
        ASSERT(!entry.value.isLet() && !entry.value.isConst());
        if (!entry.value.isVar()) // This is either a parameter or callee.
            continue;
        if (shouldCreateArgumentsVariableInParameterScope && entry.key.get() == propertyNames().arguments.impl())
            continue;
        createVariable(Identifier::fromUid(m_vm, entry.key.get()), varKind(entry.key.get()), functionSymbolTable, IgnoreExisting);
    }


    if (functionNode->needsNewTargetRegisterForThisScope() || isNewTargetUsedInInnerArrowFunction() || codeBlock->usesEval())
        m_newTargetRegister = addVar();

    switch (parseMode) {
    case SourceParseMode::GeneratorWrapperFunctionMode:
    case SourceParseMode::GeneratorWrapperMethodMode: {
        m_generatorRegister = addVar();

        // FIXME: Emit to_this only when Generator uses it.
        // https://bugs.webkit.org/show_bug.cgi?id=151586
        emitToThis();

        emitCreateGenerator(m_generatorRegister, &m_calleeRegister);
        break;
    }

    case SourceParseMode::AsyncGeneratorWrapperMethodMode:
    case SourceParseMode::AsyncGeneratorWrapperFunctionMode: {
        m_generatorRegister = addVar();

        // FIXME: Emit to_this only when Generator uses it.
        // https://bugs.webkit.org/show_bug.cgi?id=151586
        emitToThis();

        emitCreateAsyncGenerator(m_generatorRegister, &m_calleeRegister);
        break;
    }

    case SourceParseMode::AsyncArrowFunctionMode:
    case SourceParseMode::AsyncMethodMode:
    case SourceParseMode::AsyncFunctionMode: {
        ASSERT(!isConstructor());
        ASSERT(constructorKind() == ConstructorKind::None);
        m_generatorRegister = addVar();
        m_promiseRegister = addVar();

        if (parseMode != SourceParseMode::AsyncArrowFunctionMode) {
            // FIXME: Emit to_this only when AsyncFunctionBody uses it.
            // https://bugs.webkit.org/show_bug.cgi?id=151586
            emitToThis();
        }

        emitNewGenerator(m_generatorRegister);
        emitNewPromise(promiseRegister(), m_isBuiltinFunction);
        break;
    }

    case SourceParseMode::AsyncGeneratorBodyMode:
    case SourceParseMode::AsyncFunctionBodyMode:
    case SourceParseMode::AsyncArrowFunctionBodyMode:
    case SourceParseMode::GeneratorBodyMode: {
        // |this| is already filled correctly before here.
        if (m_newTargetRegister)
            emitLoad(m_newTargetRegister, jsUndefined());
        break;
    }

    default: {
        if (SourceParseMode::ArrowFunctionMode != parseMode) {
            if (isConstructor()) {
                if (m_newTargetRegister)
                    move(m_newTargetRegister, &m_thisRegister);
                switch (constructorKind()) {
                case ConstructorKind::Naked:
                    // Naked constructor not create |this| automatically.
                    break;
                case ConstructorKind::None:
                case ConstructorKind::Base:
                    emitCreateThis(&m_thisRegister);
                    break;
                case ConstructorKind::Extends:
                    moveEmptyValue(&m_thisRegister);
                    break;
                }
            } else {
                switch (constructorKind()) {
                case ConstructorKind::None: {
                    bool shouldEmitToThis = false;
                    if (functionNode->usesThis() || codeBlock->usesEval() || m_scopeNode->doAnyInnerArrowFunctionsUseThis() || m_scopeNode->doAnyInnerArrowFunctionsUseEval())
                        shouldEmitToThis = true;
                    else if ((functionNode->usesSuperProperty() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperProperty()) && !codeBlock->isStrictMode()) {
                        // We must emit to_this when we're not in strict mode because we
                        // will convert |this| to an object, and that object may be passed
                        // to a strict function as |this|. This is observable because that
                        // strict function's to_this will just return the object.
                        //
                        // We don't need to emit this for strict-mode code because
                        // strict-mode code may call another strict function, which will
                        // to_this if it directly uses this; this is OK, because we defer
                        // to_this until |this| is used directly. Strict-mode code might
                        // also call a sloppy mode function, and that will to_this, which
                        // will defer the conversion, again, until necessary.
                        shouldEmitToThis = true;
                    }

                    if (shouldEmitToThis)
                        emitToThis();
                    break;
                }
                case ConstructorKind::Naked:
                    emitThrowTypeError("Cannot call a constructor without |new|");
                    break;
                case ConstructorKind::Base:
                case ConstructorKind::Extends:
                    emitThrowTypeError("Cannot call a class constructor without |new|");
                    break;
                }
            }
        }
        break;
    }
    }

    // We need load |super| & |this| for arrow function before initializeDefaultParameterValuesAndSetupFunctionScopeStack
    // if we have default parameter expression. Because |super| & |this| values can be used there
    if ((SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(parseMode) && !isSimpleParameterList) || parseMode == SourceParseMode::AsyncArrowFunctionBodyMode) {
        if (functionNode->usesThis() || functionNode->usesSuperProperty())
            emitLoadThisFromArrowFunctionLexicalEnvironment();

        if (m_scopeNode->needsNewTargetRegisterForThisScope())
            emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
    }

    if (needsToUpdateArrowFunctionContext() && !codeBlock->isArrowFunction()) {
        bool canReuseLexicalEnvironment = isSimpleParameterList;
        initializeArrowFunctionContextScopeIfNeeded(functionSymbolTable, canReuseLexicalEnvironment);
        emitPutThisToArrowFunctionContextScope();
        emitPutNewTargetToArrowFunctionContextScope();
        emitPutDerivedConstructorToArrowFunctionContextScope();
    }

    // All "addVar()"s needs to happen before "initializeDefaultParameterValuesAndSetupFunctionScopeStack()" is called
    // because a function's default parameter ExpressionNodes will use temporary registers.
    pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize, TDZRequirement::UnderTDZ);

    Ref<Label> catchLabel = newLabel();
    TryData* tryFormalParametersData = nullptr;
    bool needTryCatch = isAsyncFunctionWrapperParseMode(parseMode) && !isSimpleParameterList;
    if (needTryCatch) {
        Ref<Label> tryFormalParametersStart = newEmittedLabel();
        tryFormalParametersData = pushTry(tryFormalParametersStart.get(), catchLabel.get(), HandlerType::SynthesizedCatch);
    }

    initializeDefaultParameterValuesAndSetupFunctionScopeStack(parameters, isSimpleParameterList, functionNode, functionSymbolTable, symbolTableConstantIndex, captures, shouldCreateArgumentsVariableInParameterScope);

    if (needTryCatch) {
        Ref<Label> didNotThrow = newLabel();
        emitJump(didNotThrow.get());
        emitLabel(catchLabel.get());
        popTry(tryFormalParametersData, catchLabel.get());

        RefPtr<RegisterID> thrownValue = newTemporary();
        emitOutOfLineCatchHandler(thrownValue.get(), nullptr, tryFormalParametersData);

        // @rejectPromiseWithFirstResolvingFunctionCallCheck(@promise, thrownValue);
        // return @promise;
        RefPtr<RegisterID> rejectPromise = moveLinkTimeConstant(nullptr, LinkTimeConstant::rejectPromiseWithFirstResolvingFunctionCallCheck);
        CallArguments args(*this, nullptr, 2);
        emitLoad(args.thisRegister(), jsUndefined());
        move(args.argumentRegister(0), promiseRegister());
        move(args.argumentRegister(1), thrownValue.get());
        JSTextPosition divot(functionNode->firstLine(), functionNode->startOffset(), functionNode->lineStartOffset());
        emitCall(newTemporary(), rejectPromise.get(), NoExpectedFunction, args, divot, divot, divot, DebuggableCall::No);

        emitReturn(promiseRegister());
        emitLabel(didNotThrow.get());
    }

    // If we don't have  default parameter expression, then loading |this| inside an arrow function must be done
    // after initializeDefaultParameterValuesAndSetupFunctionScopeStack() because that function sets up the
    // SymbolTable stack and emitLoadThisFromArrowFunctionLexicalEnvironment() consults the SymbolTable stack
    if (SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(parseMode) && isSimpleParameterList) {
        if (functionNode->usesThis() || functionNode->usesSuperProperty())
            emitLoadThisFromArrowFunctionLexicalEnvironment();
    
        if (m_scopeNode->needsNewTargetRegisterForThisScope())
            emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
    }
    
    // Set up the lexical environment scope as the generator frame. We store the saved and resumed generator registers into this scope with the symbol keys.
    // Since they are symbol keyed, these variables cannot be reached from the usual code.
    if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode)) {
        m_generatorFrameSymbolTable.set(m_vm, functionSymbolTable);
        m_generatorFrameSymbolTableIndex = symbolTableConstantIndex;
        if (m_lexicalEnvironmentRegister)
            move(generatorFrameRegister(), m_lexicalEnvironmentRegister);
        else {
            // It would be possible that generator does not need to suspend and resume any registers.
            // In this case, we would like to avoid creating a lexical environment as much as possible.
            // op_create_generator_frame_environment is a marker, which is similar to op_yield.
            // Generatorification inserts lexical environment creation if necessary. Otherwise, we convert it to op_mov frame, `undefined`.
            OpCreateGeneratorFrameEnvironment::emit(this, generatorFrameRegister(), scopeRegister(), VirtualRegister { symbolTableConstantIndex }, addConstantValue(jsUndefined()));
        }
        static_assert(static_cast<unsigned>(JSGenerator::Field::Frame) == static_cast<unsigned>(JSAsyncGenerator::Field::Frame));
        emitPutInternalField(generatorRegister(), static_cast<unsigned>(JSGenerator::Field::Frame), generatorFrameRegister());
    }

    bool shouldInitializeBlockScopedFunctions = false; // We generate top-level function declarations in ::generate().
    pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
}

BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment* parentScopeTDZVariables)
    : BytecodeGeneratorBase(Strong<UnlinkedCodeBlock>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
    , m_codeGenerationMode(codeGenerationMode)
    , m_scopeNode(evalNode)
    , m_thisRegister(CallFrame::thisArgumentOffset())
    , m_codeType(EvalCode)
    , m_vm(vm)
    , m_usesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode())
    , m_needsToUpdateArrowFunctionContext(evalNode->usesArrowFunction() || evalNode->usesEval())
    , m_derivedContextType(codeBlock->derivedContextType())
{
    m_codeBlock->setNumParameters(1);

    pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize, TDZRequirement::UnderTDZ);

    emitEnter();

    allocateAndEmitScope();

    emitCheckTraps();
    
    for (FunctionMetadataNode* function : evalNode->functionStack()) {
        m_codeBlock->addFunctionDecl(makeFunction(function));
        m_functionsToInitialize.append(std::make_pair(function, TopLevelFunctionVariable));
    }

    const VariableEnvironment& varDeclarations = evalNode->varDeclarations();
    Vector<Identifier, 0, UnsafeVectorOverflow> variables;
    Vector<Identifier, 0, UnsafeVectorOverflow> hoistedFunctions;
    for (auto& entry : varDeclarations) {
        ASSERT(entry.value.isVar());
        ASSERT(entry.key->isAtom() || entry.key->isSymbol());
        if (entry.value.isSloppyModeHoistingCandidate())
            hoistedFunctions.append(Identifier::fromUid(m_vm, entry.key.get()));
        else
            variables.append(Identifier::fromUid(m_vm, entry.key.get()));
    }
    codeBlock->adoptVariables(variables);
    codeBlock->adoptFunctionHoistingCandidates(WTFMove(hoistedFunctions));
    
    if (evalNode->needsNewTargetRegisterForThisScope())
        m_newTargetRegister = addVar();

    if (codeBlock->isArrowFunctionContext() && (evalNode->usesThis() || evalNode->usesSuperProperty()))
        emitLoadThisFromArrowFunctionLexicalEnvironment();

    if (evalNode->needsNewTargetRegisterForThisScope())
        emitLoadNewTargetFromArrowFunctionLexicalEnvironment();

    if (needsToUpdateArrowFunctionContext() && !codeBlock->isArrowFunctionContext() && !isDerivedConstructorContext()) {
        initializeArrowFunctionContextScopeIfNeeded();
        emitPutThisToArrowFunctionContextScope();
    }
    
    bool shouldInitializeBlockScopedFunctions = false; // We generate top-level function declarations in ::generate().
    pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
}

BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment* parentScopeTDZVariables)
    : BytecodeGeneratorBase(Strong<UnlinkedCodeBlock>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
    , m_codeGenerationMode(codeGenerationMode)
    , m_scopeNode(moduleProgramNode)
    , m_thisRegister(CallFrame::thisArgumentOffset())
    , m_codeType(ModuleCode)
    , m_vm(vm)
    , m_usesNonStrictEval(false)
    , m_needsToUpdateArrowFunctionContext(moduleProgramNode->usesArrowFunction() || moduleProgramNode->usesEval())
{
    ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables->size());

    SymbolTable* moduleEnvironmentSymbolTable = SymbolTable::create(m_vm);
    moduleEnvironmentSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval);
    moduleEnvironmentSymbolTable->setScopeType(SymbolTable::ScopeType::LexicalScope);

    bool shouldCaptureAllOfTheThings = shouldEmitDebugHooks() || codeBlock->usesEval();
    if (shouldCaptureAllOfTheThings)
        moduleProgramNode->varDeclarations().markAllVariablesAsCaptured();

    auto captures = [&] (UniquedStringImpl* uid) -> bool {
        return moduleProgramNode->captures(uid);
    };
    auto lookUpVarKind = [&] (UniquedStringImpl* uid, const VariableEnvironmentEntry& entry) -> VarKind {
        // Allocate the exported variables in the module environment.
        if (entry.isExported())
            return VarKind::Scope;

        // Allocate the namespace variables in the module environment to instantiate
        // it from the outside of the module code.
        if (entry.isImportedNamespace())
            return VarKind::Scope;

        if (entry.isCaptured())
            return VarKind::Scope;
        return captures(uid) ? VarKind::Scope : VarKind::Stack;
    };

    emitEnter();

    allocateAndEmitScope();

    emitCheckTraps();
    
    m_calleeRegister.setIndex(CallFrameSlot::callee);

    m_codeBlock->setNumParameters(1); // Allocate space for "this"

    // Now declare all variables.

    createVariable(m_vm.propertyNames->builtinNames().metaPrivateName(), VarKind::Scope, moduleEnvironmentSymbolTable, VerifyExisting);

    for (auto& entry : moduleProgramNode->varDeclarations()) {
        ASSERT(!entry.value.isLet() && !entry.value.isConst());
        if (!entry.value.isVar()) // This is either a parameter or callee.
            continue;
        // Imported bindings are not allocated in the module environment as usual variables' way.
        // These references remain the "Dynamic" in the unlinked code block. Later, when linking
        // the code block, we resolve the reference to the "ModuleVar".
        if (entry.value.isImported() && !entry.value.isImportedNamespace())
            continue;
        createVariable(Identifier::fromUid(m_vm, entry.key.get()), lookUpVarKind(entry.key.get(), entry.value), moduleEnvironmentSymbolTable, IgnoreExisting);
    }

    VariableEnvironment& lexicalVariables = moduleProgramNode->lexicalVariables();
    instantiateLexicalVariables(lexicalVariables, moduleEnvironmentSymbolTable, ScopeRegisterType::Block, lookUpVarKind);

    // We keep the symbol table in the constant pool.
    RegisterID* constantSymbolTable = nullptr;
    if (shouldEmitTypeProfilerHooks())
        constantSymbolTable = addConstantValue(moduleEnvironmentSymbolTable);
    else
        constantSymbolTable = addConstantValue(moduleEnvironmentSymbolTable->cloneScopePart(m_vm));

    pushTDZVariables(lexicalVariables, TDZCheckOptimization::Optimize, TDZRequirement::UnderTDZ);
    bool isWithScope = false;
    m_lexicalScopeStack.append({ moduleEnvironmentSymbolTable, m_topMostScope, isWithScope, constantSymbolTable->index() });
    emitPrefillStackTDZVariables(lexicalVariables, moduleEnvironmentSymbolTable);

    // makeFunction assumes that there's correct TDZ stack entries.
    // So it should be called after putting our lexical environment to the TDZ stack correctly.

    for (FunctionMetadataNode* function : moduleProgramNode->functionStack()) {
        const auto& iterator = moduleProgramNode->varDeclarations().find(function->ident().impl());
        RELEASE_ASSERT(iterator != moduleProgramNode->varDeclarations().end());
        RELEASE_ASSERT(!iterator->value.isImported());

        VarKind varKind = lookUpVarKind(iterator->key.get(), iterator->value);
        if (varKind == VarKind::Scope) {
            // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
            // Section 15.2.1.16.4, step 16-a-iv-1.
            // All heap allocated function declarations should be instantiated when the module environment
            // is created. They include the exported function declarations and not-exported-but-heap-allocated
            // function declarations. This is required because exported function should be instantiated before
            // executing the any module in the dependency graph. This enables the modules to link the imported
            // bindings before executing the any module code.
            //
            // And since function declarations are instantiated before executing the module body code, the spec
            // allows the functions inside the module to be executed before its module body is executed under
            // the circular dependencies. The following is the example.
            //
            // Module A (executed first):
            //    import { b } from "B";
            //    // Here, the module "B" is not executed yet, but the function declaration is already instantiated.
            //    // So we can call the function exported from "B".
            //    b();
            //
            //    export function a() {
            //    }
            //
            // Module B (executed second):
            //    import { a } from "A";
            //
            //    export function b() {
            //        c();
            //    }
            //
            //    // c is not exported, but since it is referenced from the b, we should instantiate it before
            //    // executing the "B" module code.
            //    function c() {
            //        a();
            //    }
            //
            // Module EntryPoint (executed last):
            //    import "B";
            //    import "A";
            //
            m_codeBlock->addFunctionDecl(makeFunction(function));
        } else {
            // Stack allocated functions can be allocated when executing the module's body.
            m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable));
        }
    }

    // Remember the constant register offset to the top-most symbol table. This symbol table will be
    // cloned in the code block linking. After that, to create the module environment, we retrieve
    // the cloned symbol table from the linked code block by using this offset.
    codeBlock->setModuleEnvironmentSymbolTableConstantRegisterOffset(constantSymbolTable->index());
}

BytecodeGenerator::~BytecodeGenerator()
{
}

void BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack(
    FunctionParameters& parameters, bool isSimpleParameterList, FunctionNode* functionNode, SymbolTable* functionSymbolTable, 
    int symbolTableConstantIndex, const ScopedLambda<bool (UniquedStringImpl*)>& captures, bool shouldCreateArgumentsVariableInParameterScope)
{
    Vector<std::pair<Identifier, RefPtr<RegisterID>>> valuesToMoveIntoVars;
    ASSERT(!(isSimpleParameterList && shouldCreateArgumentsVariableInParameterScope));
    if (!isSimpleParameterList) {
        // Refer to the ES6 spec section 9.2.12: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-functiondeclarationinstantiation
        // This implements step 21.
        VariableEnvironment environment;
        Vector<Identifier> allParameterNames; 
        for (unsigned i = 0; i < parameters.size(); i++)
            parameters.at(i).first->collectBoundIdentifiers(allParameterNames);
        if (shouldCreateArgumentsVariableInParameterScope)
            allParameterNames.append(propertyNames().arguments);
        IdentifierSet parameterSet;
        for (auto& ident : allParameterNames) {
            parameterSet.add(ident.impl());
            auto addResult = environment.add(ident);
            addResult.iterator->value.setIsLet(); // When we have default parameter expressions, parameters act like "let" variables.
            if (captures(ident.impl()))
                addResult.iterator->value.setIsCaptured();
        }
        // This implements step 25 of section 9.2.12.
        pushLexicalScopeInternal(environment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);

        if (shouldCreateArgumentsVariableInParameterScope) {
            Variable argumentsVariable = variable(propertyNames().arguments); 
            initializeVariable(argumentsVariable, m_argumentsRegister);
            liftTDZCheckIfPossible(argumentsVariable);
        }

        RefPtr<RegisterID> temp = newTemporary();
        for (unsigned i = 0; i < parameters.size(); i++) {
            std::pair<DestructuringPatternNode*, ExpressionNode*> parameter = parameters.at(i);
            if (parameter.first->isRestParameter())
                continue;
            if ((i + 1) < m_parameters.size())
                move(temp.get(), &m_parameters[i + 1]);
            else
                emitGetArgument(temp.get(), i);
            if (parameter.second) {
                RefPtr<RegisterID> condition = emitIsUndefined(newTemporary(), temp.get());
                Ref<Label> skipDefaultParameterBecauseNotUndefined = newLabel();
                emitJumpIfFalse(condition.get(), skipDefaultParameterBecauseNotUndefined.get());
                emitNode(temp.get(), parameter.second);
                emitLabel(skipDefaultParameterBecauseNotUndefined.get());
            }

            parameter.first->bindValue(*this, temp.get());
        }

        // Final act of weirdness for default parameters. If a "var" also
        // has the same name as a parameter, it should start out as the
        // value of that parameter. Note, though, that they will be distinct
        // bindings.
        // This is step 28 of section 9.2.12. 
        for (auto& entry : functionNode->varDeclarations()) {
            if (!entry.value.isVar()) // This is either a parameter or callee.
                continue;

            if (parameterSet.contains(entry.key)) {
                Identifier ident = Identifier::fromUid(m_vm, entry.key.get());
                Variable var = variable(ident);
                RegisterID* scope = emitResolveScope(nullptr, var);
                RefPtr<RegisterID> value = emitGetFromScope(newTemporary(), scope, var, DoNotThrowIfNotFound);
                valuesToMoveIntoVars.append(std::make_pair(ident, value));
            }
        }

        // Functions with default parameter expressions must have a separate environment
        // record for parameters and "var"s. The "var" environment record must have the
        // parameter environment record as its parent.
        // See step 28 of section 9.2.12.
        bool hasCapturedVariables = !!m_lexicalEnvironmentRegister; 
        initializeVarLexicalEnvironment(symbolTableConstantIndex, functionSymbolTable, hasCapturedVariables);
    }

    // This completes step 28 of section 9.2.12.
    for (unsigned i = 0; i < valuesToMoveIntoVars.size(); i++) {
        ASSERT(!isSimpleParameterList);
        Variable var = variable(valuesToMoveIntoVars[i].first);
        RegisterID* scope = emitResolveScope(nullptr, var);
        emitPutToScope(scope, var, valuesToMoveIntoVars[i].second.get(), DoNotThrowIfNotFound, InitializationMode::NotInitialization);
    }
}

bool BytecodeGenerator::needsDerivedConstructorInArrowFunctionLexicalEnvironment()
{
    ASSERT(m_codeBlock->isClassContext() || !(isConstructor() && constructorKind() == ConstructorKind::Extends));
    return m_codeBlock->isClassContext() && isSuperUsedInInnerArrowFunction();
}

void BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded(SymbolTable* functionSymbolTable, bool canReuseLexicalEnvironment)
{
    ASSERT(!m_arrowFunctionContextLexicalEnvironmentRegister);

    if (canReuseLexicalEnvironment && m_lexicalEnvironmentRegister) {
        RELEASE_ASSERT(!m_codeBlock->isArrowFunction());
        RELEASE_ASSERT(functionSymbolTable);

        m_arrowFunctionContextLexicalEnvironmentRegister = m_lexicalEnvironmentRegister;
        
        ScopeOffset offset;
        
        if (isThisUsedInInnerArrowFunction()) {
            offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary);
            functionSymbolTable->set(NoLockingNecessary, propertyNames().thisIdentifier.impl(), SymbolTableEntry(VarOffset(offset)));
        }

        if (m_codeType == FunctionCode && isNewTargetUsedInInnerArrowFunction()) {
            offset = functionSymbolTable->takeNextScopeOffset();
            functionSymbolTable->set(NoLockingNecessary, propertyNames().builtinNames().newTargetLocalPrivateName().impl(), SymbolTableEntry(VarOffset(offset)));
        }
        
        if (needsDerivedConstructorInArrowFunctionLexicalEnvironment()) {
            offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary);
            functionSymbolTable->set(NoLockingNecessary, propertyNames().builtinNames().derivedConstructorPrivateName().impl(), SymbolTableEntry(VarOffset(offset)));
        }

        return;
    }

    VariableEnvironment environment;

    if (isThisUsedInInnerArrowFunction()) {
        auto addResult = environment.add(propertyNames().thisIdentifier);
        addResult.iterator->value.setIsCaptured();
        addResult.iterator->value.setIsLet();
    }
    
    if (m_codeType == FunctionCode && isNewTargetUsedInInnerArrowFunction()) {
        auto addTarget = environment.add(propertyNames().builtinNames().newTargetLocalPrivateName());
        addTarget.iterator->value.setIsCaptured();
        addTarget.iterator->value.setIsLet();
    }

    if (needsDerivedConstructorInArrowFunctionLexicalEnvironment()) {
        auto derivedConstructor = environment.add(propertyNames().builtinNames().derivedConstructorPrivateName());
        derivedConstructor.iterator->value.setIsCaptured();
        derivedConstructor.iterator->value.setIsLet();
    }

    if (environment.size() > 0) {
        size_t size = m_lexicalScopeStack.size();
        pushLexicalScopeInternal(environment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);

        ASSERT_UNUSED(size, m_lexicalScopeStack.size() == size + 1);

        m_arrowFunctionContextLexicalEnvironmentRegister = m_lexicalScopeStack.last().m_scope;
    }
}

RegisterID* BytecodeGenerator::initializeNextParameter()
{
    VirtualRegister reg = virtualRegisterForArgument(m_codeBlock->numParameters());
    m_parameters.grow(m_parameters.size() + 1);
    auto& parameter = registerFor(reg);
    parameter.setIndex(reg.offset());
    m_codeBlock->addParameter();
    return &parameter;
}

void BytecodeGenerator::initializeParameters(FunctionParameters& parameters)
{
    // Make sure the code block knows about all of our parameters, and make sure that parameters
    // needing destructuring are noted.
    m_thisRegister.setIndex(initializeNextParameter()->index()); // this

    bool nonSimpleArguments = false;
    for (unsigned i = 0; i < parameters.size(); ++i) {
        auto parameter = parameters.at(i);
        auto pattern = parameter.first;
        if (pattern->isRestParameter()) {
            RELEASE_ASSERT(!m_restParameter);
            m_restParameter = static_cast<RestParameterNode*>(pattern);
            nonSimpleArguments = true;
            continue;
        }
        if (parameter.second) {
            nonSimpleArguments = true;
            continue;
        }
        if (!nonSimpleArguments)
            initializeNextParameter();
    }
}

void BytecodeGenerator::initializeVarLexicalEnvironment(int symbolTableConstantIndex, SymbolTable* functionSymbolTable, bool hasCapturedVariables)
{
    if (hasCapturedVariables) {
        RELEASE_ASSERT(m_lexicalEnvironmentRegister);
        OpCreateLexicalEnvironment::emit(this, m_lexicalEnvironmentRegister, scopeRegister(), VirtualRegister { symbolTableConstantIndex }, addConstantValue(jsUndefined()));

        OpMov::emit(this, scopeRegister(), m_lexicalEnvironmentRegister);

        pushLocalControlFlowScope();
    }
    bool isWithScope = false;
    m_lexicalScopeStack.append({ functionSymbolTable, m_lexicalEnvironmentRegister, isWithScope, symbolTableConstantIndex });
    m_varScopeLexicalScopeStackIndex = m_lexicalScopeStack.size() - 1;
}

UniquedStringImpl* BytecodeGenerator::visibleNameForParameter(DestructuringPatternNode* pattern)
{
    if (pattern->isBindingNode()) {
        const Identifier& ident = static_cast<const BindingNode*>(pattern)->boundProperty();
        if (!m_functions.contains(ident.impl()))
            return ident.impl();
    }
    return nullptr;
}

RegisterID* BytecodeGenerator::newBlockScopeVariable()
{
    reclaimFreeRegisters();

    return newRegister();
}

Ref<LabelScope> BytecodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name)
{
    shrinkToFit(m_labelScopes);

    // Allocate new label scope.
    m_labelScopes.append(type, name, labelScopeDepth(), newLabel(), type == LabelScope::Loop ? RefPtr<Label>(newLabel()) : RefPtr<Label>()); // Only loops have continue targets.
    return m_labelScopes.last();
}

void BytecodeGenerator::emitEnter()
{
    OpEnter::emit(this);

    if (LIKELY(Options::optimizeRecursiveTailCalls())) {
        // We must add the end of op_enter as a potential jump target, because the bytecode parser may decide to split its basic block
        // to have somewhere to jump to if there is a recursive tail-call that points to this function.
        m_codeBlock->addJumpTarget(instructions().size());
        // This disables peephole optimizations when an instruction is a jump target
        m_lastOpcodeID = op_end;
    }
}

void BytecodeGenerator::emitLoopHint()
{
    OpLoopHint::emit(this);
    emitCheckTraps();
}

void BytecodeGenerator::emitJump(Label& target)
{
    OpJmp::emit(this, target.bind(this));
}

void BytecodeGenerator::emitCheckTraps()
{
    OpCheckTraps::emit(this);
}

void ALWAYS_INLINE BytecodeGenerator::rewind()
{
    ASSERT(m_lastInstruction.isValid());
    m_lastOpcodeID = op_end;
    m_writer.rewind(m_lastInstruction);
}

template<typename BinOp, typename JmpOp>
bool BytecodeGenerator::fuseCompareAndJump(RegisterID* cond, Label& target, bool swapOperands)
{
    ASSERT(canDoPeepholeOptimization());
    auto binop = m_lastInstruction->as<BinOp>();
    if (cond->index() == binop.m_dst.offset() && cond->isTemporary() && !cond->refCount()) {
        rewind();

        if (swapOperands)
            std::swap(binop.m_lhs, binop.m_rhs);

        JmpOp::emit(this, binop.m_lhs, binop.m_rhs, target.bind(this));
        return true;
    }
    return false;
}

template<typename UnaryOp, typename JmpOp>
bool BytecodeGenerator::fuseTestAndJmp(RegisterID* cond, Label& target)
{
    ASSERT(canDoPeepholeOptimization());
    auto unop = m_lastInstruction->as<UnaryOp>();
    if (cond->index() == unop.m_dst.offset() && cond->isTemporary() && !cond->refCount()) {
        rewind();

        JmpOp::emit(this, unop.m_operand, target.bind(this));
        return true;
    }
    return false;
}

void BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label& target)
{
    if (canDoPeepholeOptimization()) {
        if (m_lastOpcodeID == op_less) {
            if (fuseCompareAndJump<OpLess, OpJless>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_lesseq) {
            if (fuseCompareAndJump<OpLesseq, OpJlesseq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_greater) {
            if (fuseCompareAndJump<OpGreater, OpJgreater>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_greatereq) {
            if (fuseCompareAndJump<OpGreatereq, OpJgreatereq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_eq) {
            if (fuseCompareAndJump<OpEq, OpJeq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_stricteq) {
            if (fuseCompareAndJump<OpStricteq, OpJstricteq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_neq) {
            if (fuseCompareAndJump<OpNeq, OpJneq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_nstricteq) {
            if (fuseCompareAndJump<OpNstricteq, OpJnstricteq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_below) {
            if (fuseCompareAndJump<OpBelow, OpJbelow>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_beloweq) {
            if (fuseCompareAndJump<OpBeloweq, OpJbeloweq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_eq_null && target.isForward()) {
            if (fuseTestAndJmp<OpEqNull, OpJeqNull>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_neq_null && target.isForward()) {
            if (fuseTestAndJmp<OpNeqNull, OpJneqNull>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_is_undefined_or_null && target.isForward()) {
            if (fuseTestAndJmp<OpIsUndefinedOrNull, OpJundefinedOrNull>(cond, target))
                return;
        }
    }

    OpJtrue::emit(this, cond, target.bind(this));
}

void BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label& target)
{
    if (canDoPeepholeOptimization()) {
        if (m_lastOpcodeID == op_less && target.isForward()) {
            if (fuseCompareAndJump<OpLess, OpJnless>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_lesseq && target.isForward()) {
            if (fuseCompareAndJump<OpLesseq, OpJnlesseq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_greater && target.isForward()) {
            if (fuseCompareAndJump<OpGreater, OpJngreater>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_greatereq && target.isForward()) {
            if (fuseCompareAndJump<OpGreatereq, OpJngreatereq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_eq && target.isForward()) {
            if (fuseCompareAndJump<OpEq, OpJneq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_stricteq && target.isForward()) {
            if (fuseCompareAndJump<OpStricteq, OpJnstricteq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_neq && target.isForward()) {
            if (fuseCompareAndJump<OpNeq, OpJeq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_nstricteq && target.isForward()) {
            if (fuseCompareAndJump<OpNstricteq, OpJstricteq>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_below && target.isForward()) {
            if (fuseCompareAndJump<OpBelow, OpJbeloweq>(cond, target, true))
                return;
        } else if (m_lastOpcodeID == op_beloweq && target.isForward()) {
            if (fuseCompareAndJump<OpBeloweq, OpJbelow>(cond, target, true))
                return;
        } else if (m_lastOpcodeID == op_not) {
            if (fuseTestAndJmp<OpNot, OpJtrue>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_eq_null && target.isForward()) {
            if (fuseTestAndJmp<OpEqNull, OpJneqNull>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_neq_null && target.isForward()) {
            if (fuseTestAndJmp<OpNeqNull, OpJeqNull>(cond, target))
                return;
        } else if (m_lastOpcodeID == op_is_undefined_or_null && target.isForward()) {
            if (fuseTestAndJmp<OpIsUndefinedOrNull, OpJnundefinedOrNull>(cond, target))
                return;
        }
    }

    OpJfalse::emit(this, cond, target.bind(this));
}

void BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label& target)
{
    OpJneqPtr::emit(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::callFunction), target.bind(this));
}

void BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label& target)
{
    OpJneqPtr::emit(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::applyFunction), target.bind(this));
}

bool BytecodeGenerator::hasConstant(const Identifier& ident) const
{
    UniquedStringImpl* rep = ident.impl();
    return m_identifierMap.contains(rep);
}

unsigned BytecodeGenerator::addConstant(const Identifier& ident)
{
    UniquedStringImpl* rep = ident.impl();
    IdentifierMap::AddResult result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers());
    if (result.isNewEntry)
        m_codeBlock->addIdentifier(ident);

    return result.iterator->value;
}

// We can't hash JSValue(), so we use a dedicated data member to cache it.
RegisterID* BytecodeGenerator::addConstantEmptyValue()
{
    if (!m_emptyValueRegister) {
        int index = addConstantIndex();
        m_codeBlock->addConstant(JSValue());
        m_emptyValueRegister = &m_constantPoolRegisters[index];
    }

    return m_emptyValueRegister;
}

RegisterID* BytecodeGenerator::addConstantValue(JSValue v, SourceCodeRepresentation sourceCodeRepresentation)
{
    if (!v)
        return addConstantEmptyValue();

    int index = m_nextConstantOffset;

    if (sourceCodeRepresentation == SourceCodeRepresentation::Double && v.isInt32())
        v = jsDoubleNumber(v.asNumber());
    EncodedJSValueWithRepresentation valueMapKey { JSValue::encode(v), sourceCodeRepresentation };
    JSValueMap::AddResult result = m_jsValueMap.add(valueMapKey, m_nextConstantOffset);
    if (result.isNewEntry) {
        addConstantIndex();
        m_codeBlock->addConstant(v, sourceCodeRepresentation);
    } else
        index = result.iterator->value;
    return &m_constantPoolRegisters[index];
}

RegisterID* BytecodeGenerator::moveLinkTimeConstant(RegisterID* dst, LinkTimeConstant type)
{
    RegisterID* constant = m_linkTimeConstantRegisters.ensure(type, [&] {
        int index = addConstantIndex();
        m_codeBlock->addConstant(type);
        return &m_constantPoolRegisters[index];
    }).iterator->value;
    if (!dst)
        return constant;

    OpMov::emit(this, dst, constant);

    return dst;
}

RegisterID* BytecodeGenerator::moveEmptyValue(RegisterID* dst)
{
    RefPtr<RegisterID> emptyValue = addConstantEmptyValue();

    OpMov::emit(this, dst, emptyValue.get());

    return dst;
}

RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
{
    ASSERT(src != m_emptyValueRegister);

    m_staticPropertyAnalyzer.mov(dst, src);
    OpMov::emit(this, dst, src);

    return dst;
}

RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src, ResultType type)
{
    switch (opcodeID) {
    case op_not:
        emitUnaryOp<OpNot>(dst, src);
        break;
    case op_negate:
        OpNegate::emit(this, dst, src, type);
        break;
    case op_bitnot:
        emitUnaryOp<OpBitnot>(dst, src);
        break;
    case op_to_number:
        emitUnaryOp<OpToNumber>(dst, src);
        break;
    case op_to_numeric:
        emitUnaryOp<OpToNumeric>(dst, src);
        break;
    default:
        ASSERT_NOT_REACHED();
    }
    return dst;
}

RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types)
{
    switch (opcodeID) {
    case op_eq:
        return emitBinaryOp<OpEq>(dst, src1, src2, types);
    case op_neq:
        return emitBinaryOp<OpNeq>(dst, src1, src2, types);
    case op_stricteq:
        return emitBinaryOp<OpStricteq>(dst, src1, src2, types);
    case op_nstricteq:
        return emitBinaryOp<OpNstricteq>(dst, src1, src2, types);
    case op_less:
        return emitBinaryOp<OpLess>(dst, src1, src2, types);
    case op_lesseq:
        return emitBinaryOp<OpLesseq>(dst, src1, src2, types);
    case op_greater:
        return emitBinaryOp<OpGreater>(dst, src1, src2, types);
    case op_greatereq:
        return emitBinaryOp<OpGreatereq>(dst, src1, src2, types);
    case op_below:
        return emitBinaryOp<OpBelow>(dst, src1, src2, types);
    case op_beloweq:
        return emitBinaryOp<OpBeloweq>(dst, src1, src2, types);
    case op_mod:
        return emitBinaryOp<OpMod>(dst, src1, src2, types);
    case op_pow:
        return emitBinaryOp<OpPow>(dst, src1, src2, types);
    case op_lshift:
        return emitBinaryOp<OpLshift>(dst, src1, src2, types);
    case op_rshift:
        return emitBinaryOp<OpRshift>(dst, src1, src2, types);
    case op_urshift:
        return emitBinaryOp<OpUrshift>(dst, src1, src2, types);
    case op_add:
        return emitBinaryOp<OpAdd>(dst, src1, src2, types);
    case op_mul:
        return emitBinaryOp<OpMul>(dst, src1, src2, types);
    case op_div:
        return emitBinaryOp<OpDiv>(dst, src1, src2, types);
    case op_sub:
        return emitBinaryOp<OpSub>(dst, src1, src2, types);
    case op_bitand:
        return emitBinaryOp<OpBitand>(dst, src1, src2, types);
    case op_bitxor:
        return emitBinaryOp<OpBitxor>(dst, src1, src2, types);
    case op_bitor:
        return emitBinaryOp<OpBitor>(dst, src1, src2, types);
    default:
        ASSERT_NOT_REACHED();
        return nullptr;
    }
}

RegisterID* BytecodeGenerator::emitToObject(RegisterID* dst, RegisterID* src, const Identifier& message)
{
    OpToObject::emit(this, dst, src, addConstant(message));
    return dst;
}

RegisterID* BytecodeGenerator::emitToNumber(RegisterID* dst, RegisterID* src)
{
    return emitUnaryOp<OpToNumber>(dst, src);
}

RegisterID* BytecodeGenerator::emitToNumeric(RegisterID* dst, RegisterID* src)
{
    return emitUnaryOp<OpToNumeric>(dst, src);
}

RegisterID* BytecodeGenerator::emitToString(RegisterID* dst, RegisterID* src)
{
    return emitUnaryOp<OpToString>(dst, src);
}

RegisterID* BytecodeGenerator::emitTypeOf(RegisterID* dst, RegisterID* src)
{
    return emitUnaryOp<OpTypeof>(dst, src);
}

RegisterID* BytecodeGenerator::emitInc(RegisterID* srcDst)
{
    OpInc::emit(this, srcDst);
    return srcDst;
}

RegisterID* BytecodeGenerator::emitDec(RegisterID* srcDst)
{
    OpDec::emit(this, srcDst);
    return srcDst;
}

bool BytecodeGenerator::emitEqualityOpImpl(RegisterID* dst, RegisterID* src1, RegisterID* src2)
{
    if (!canDoPeepholeOptimization())
        return false;

    if (m_lastInstruction->is<OpTypeof>()) {
        auto op = m_lastInstruction->as<OpTypeof>();
        if (src1->index() == op.m_dst.offset()
            && src1->isTemporary()
            && m_codeBlock->isConstantRegisterIndex(src2->index())
            && m_codeBlock->constantRegister(src2->index()).get().isString()) {
            const String& value = asString(m_codeBlock->constantRegister(src2->index()).get())->tryGetValue();
            if (value == "undefined") {
                rewind();
                OpIsUndefined::emit(this, dst, op.m_value);
                return true;
            }
            if (value == "boolean") {
                rewind();
                OpIsBoolean::emit(this, dst, op.m_value);
                return true;
            }
            if (value == "number") {
                rewind();
                OpIsNumber::emit(this, dst, op.m_value);
                return true;
            }
            if (value == "string") {
                rewind();
                OpIsCellWithType::emit(this, dst, op.m_value, StringType);
                return true;
            }
            if (value == "symbol") {
                rewind();
                OpIsCellWithType::emit(this, dst, op.m_value, SymbolType);
                return true;
            }
            if (Options::useBigInt() && value == "bigint") {
                rewind();
                OpIsCellWithType::emit(this, dst, op.m_value, BigIntType);
                return true;
            }
            if (value == "object") {
                rewind();
                OpIsObjectOrNull::emit(this, dst, op.m_value);
                return true;
            }
            if (value == "function") {
                rewind();
                OpIsFunction::emit(this, dst, op.m_value);
                return true;
            }
        }
    }

    return false;
}

void BytecodeGenerator::emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot)
{
    ASSERT(shouldEmitTypeProfilerHooks());

    unsigned start = startDivot.offset; // Ranges are inclusive of their endpoints, AND 0 indexed.
    unsigned end = endDivot.offset - 1; // End Ranges already go one past the inclusive range, so subtract 1.
    unsigned instructionOffset = instructions().size() - 1;
    m_codeBlock->addTypeProfilerExpressionInfo(instructionOffset, start, end);
}

void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag)
{
    if (!shouldEmitTypeProfilerHooks())
        return;

    if (!registerToProfile)
        return;

    OpProfileType::emit(this, registerToProfile, { }, flag, { }, resolveType());

    // Don't emit expression info for this version of profile type. This generally means
    // we're profiling information for something that isn't in the actual text of a JavaScript
    // program. For example, implicit return undefined from a function call.
}

void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, const JSTextPosition& startDivot, const JSTextPosition& endDivot)
{
    emitProfileType(registerToProfile, ProfileTypeBytecodeDoesNotHaveGlobalID, startDivot, endDivot);
}

void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag, const JSTextPosition& startDivot, const JSTextPosition& endDivot)
{
    if (!shouldEmitTypeProfilerHooks())
        return;

    if (!registerToProfile)
        return;

    OpProfileType::emit(this, registerToProfile, { },  flag, { }, resolveType());
    emitTypeProfilerExpressionInfo(startDivot, endDivot);
}

void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, const Variable& var, const JSTextPosition& startDivot, const JSTextPosition& endDivot)
{
    if (!shouldEmitTypeProfilerHooks())
        return;

    if (!registerToProfile)
        return;

    ProfileTypeBytecodeFlag flag;
    SymbolTableOrScopeDepth symbolTableOrScopeDepth;
    if (var.local() || var.offset().isScope()) {
        flag = ProfileTypeBytecodeLocallyResolved;
        ASSERT(var.symbolTableConstantIndex());
        symbolTableOrScopeDepth = SymbolTableOrScopeDepth::symbolTable(VirtualRegister { var.symbolTableConstantIndex() });
    } else {
        flag = ProfileTypeBytecodeClosureVar;
        symbolTableOrScopeDepth = SymbolTableOrScopeDepth::scopeDepth(localScopeDepth());
    }

    OpProfileType::emit(this, registerToProfile, symbolTableOrScopeDepth, flag, addConstant(var.ident()), resolveType());
    emitTypeProfilerExpressionInfo(startDivot, endDivot);
}

void BytecodeGenerator::emitProfileControlFlow(int textOffset)
{
    if (shouldEmitControlFlowProfilerHooks()) {
        RELEASE_ASSERT(textOffset >= 0);

        OpProfileControlFlow::emit(this, textOffset);
        m_codeBlock->addOpProfileControlFlowBytecodeOffset(m_lastInstruction.offset());
    }
}

unsigned BytecodeGenerator::addConstantIndex()
{
    unsigned index = m_nextConstantOffset;
    m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
    ++m_nextConstantOffset;
    return index;
}

RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b)
{
    return emitLoad(dst, jsBoolean(b));
}

RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier)
{
    ASSERT(!identifier.isSymbol());
    JSString*& stringInMap = m_stringMap.add(identifier.impl(), nullptr).iterator->value;
    if (!stringInMap)
        stringInMap = jsOwnedString(vm(), identifier.string());

    return emitLoad(dst, JSValue(stringInMap));
}

RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v, SourceCodeRepresentation sourceCodeRepresentation)
{
    RegisterID* constantID = addConstantValue(v, sourceCodeRepresentation);
    if (dst)
        return move(dst, constantID);
    return constantID;
}

RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, IdentifierSet& set)
{
    if (m_codeBlock->numberOfConstantIdentifierSets()) {
        for (const auto& entry : m_codeBlock->constantIdentifierSets()) {
            if (entry.first != set)
                continue;
            
            return &m_constantPoolRegisters[entry.second];
        }
    }
    
    unsigned index = addConstantIndex();
    m_codeBlock->addSetConstant(set);
    RegisterID* m_setRegister = &m_constantPoolRegisters[index];
    
    if (dst)
        return move(dst, m_setRegister);
    
    return m_setRegister;
}

template<typename LookUpVarKindFunctor>
bool BytecodeGenerator::instantiateLexicalVariables(const VariableEnvironment& lexicalVariables, SymbolTable* symbolTable, ScopeRegisterType scopeRegisterType, LookUpVarKindFunctor lookUpVarKind)
{
    bool hasCapturedVariables = false;
    {
        for (auto& entry : lexicalVariables) {
            ASSERT(entry.value.isLet() || entry.value.isConst() || entry.value.isFunction());
            ASSERT(!entry.value.isVar());
            SymbolTableEntry symbolTableEntry = symbolTable->get(NoLockingNecessary, entry.key.get());
            ASSERT(symbolTableEntry.isNull());

            // Imported bindings which are not the namespace bindings are not allocated
            // in the module environment as usual variables' way.
            // And since these types of the variables only seen in the module environment,
            // other lexical environment need not to take care this.
            if (entry.value.isImported() && !entry.value.isImportedNamespace())
                continue;

            VarKind varKind = lookUpVarKind(entry.key.get(), entry.value);
            VarOffset varOffset;
            if (varKind == VarKind::Scope) {
                varOffset = VarOffset(symbolTable->takeNextScopeOffset(NoLockingNecessary));
                hasCapturedVariables = true;
            } else {
                ASSERT(varKind == VarKind::Stack);
                RegisterID* local;
                if (scopeRegisterType == ScopeRegisterType::Block) {
                    local = newBlockScopeVariable();
                    local->ref();
                } else
                    local = addVar();
                varOffset = VarOffset(local->virtualRegister());
            }

            SymbolTableEntry newEntry(varOffset, static_cast<unsigned>(entry.value.isConst() ? PropertyAttribute::ReadOnly : PropertyAttribute::None));
            symbolTable->add(NoLockingNecessary, entry.key.get(), newEntry);
        }
    }
    return hasCapturedVariables;
}

void BytecodeGenerator::emitPrefillStackTDZVariables(const VariableEnvironment& lexicalVariables, SymbolTable* symbolTable)
{
    // Prefill stack variables with the TDZ empty value.
    // Scope variables will be initialized to the TDZ empty value when JSLexicalEnvironment is allocated.
    for (auto& entry : lexicalVariables) {
        // Imported bindings which are not the namespace bindings are not allocated
        // in the module environment as usual variables' way.
        // And since these types of the variables only seen in the module environment,
        // other lexical environment need not to take care this.
        if (entry.value.isImported() && !entry.value.isImportedNamespace())
            continue;

        if (entry.value.isFunction())
            continue;

        SymbolTableEntry symbolTableEntry = symbolTable->get(NoLockingNecessary, entry.key.get());
        ASSERT(!symbolTableEntry.isNull());
        VarOffset offset = symbolTableEntry.varOffset();
        if (offset.isScope())
            continue;

        ASSERT(offset.isStack());
        moveEmptyValue(&registerFor(offset.stackOffset()));
    }
}

void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, TDZCheckOptimization tdzCheckOptimization, NestedScopeType nestedScopeType, RegisterID** constantSymbolTableResult, bool shouldInitializeBlockScopedFunctions)
{
    VariableEnvironment& environment = node->lexicalVariables();
    RegisterID* constantSymbolTableResultTemp = nullptr;
    pushLexicalScopeInternal(environment, tdzCheckOptimization, nestedScopeType, &constantSymbolTableResultTemp, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);

    if (shouldInitializeBlockScopedFunctions)
        initializeBlockScopedFunctions(environment, node->functionStack(), constantSymbolTableResultTemp);

    if (constantSymbolTableResult && constantSymbolTableResultTemp)
        *constantSymbolTableResult = constantSymbolTableResultTemp;
}

void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, TDZCheckOptimization tdzCheckOptimization, NestedScopeType nestedScopeType,
    RegisterID** constantSymbolTableResult, TDZRequirement tdzRequirement, ScopeType scopeType, ScopeRegisterType scopeRegisterType)
{
    if (!environment.size())
        return;

    if (shouldEmitDebugHooks())
        environment.markAllVariablesAsCaptured();

    SymbolTable* symbolTable = SymbolTable::create(m_vm);
    switch (scopeType) {
    case ScopeType::CatchScope:
        symbolTable->setScopeType(SymbolTable::ScopeType::CatchScope);
        break;
    case ScopeType::LetConstScope:
        symbolTable->setScopeType(SymbolTable::ScopeType::LexicalScope);
        break;
    case ScopeType::FunctionNameScope:
        symbolTable->setScopeType(SymbolTable::ScopeType::FunctionNameScope);
        break;
    }

    if (nestedScopeType == NestedScopeType::IsNested)
        symbolTable->markIsNestedLexicalScope();

    auto lookUpVarKind = [] (UniquedStringImpl*, const VariableEnvironmentEntry& entry) -> VarKind {
        return entry.isCaptured() ? VarKind::Scope : VarKind::Stack;
    };

    bool hasCapturedVariables = instantiateLexicalVariables(environment, symbolTable, scopeRegisterType, lookUpVarKind);

    RegisterID* newScope = nullptr;
    RegisterID* constantSymbolTable = nullptr;
    int symbolTableConstantIndex = 0;
    if (shouldEmitTypeProfilerHooks()) {
        constantSymbolTable = addConstantValue(symbolTable);
        symbolTableConstantIndex = constantSymbolTable->index();
    }
    if (hasCapturedVariables) {
        if (scopeRegisterType == ScopeRegisterType::Block) {
            newScope = newBlockScopeVariable();
            newScope->ref();
        } else
            newScope = addVar();
        if (!constantSymbolTable) {
            ASSERT(!shouldEmitTypeProfilerHooks());
            constantSymbolTable = addConstantValue(symbolTable->cloneScopePart(m_vm));
            symbolTableConstantIndex = constantSymbolTable->index();
        }
        if (constantSymbolTableResult)
            *constantSymbolTableResult = constantSymbolTable;

        OpCreateLexicalEnvironment::emit(this, newScope, scopeRegister(), VirtualRegister { symbolTableConstantIndex }, addConstantValue(tdzRequirement == TDZRequirement::UnderTDZ ? jsTDZValue() : jsUndefined()));

        move(scopeRegister(), newScope);

        pushLocalControlFlowScope();
    }

    bool isWithScope = false;
    m_lexicalScopeStack.append({ symbolTable, newScope, isWithScope, symbolTableConstantIndex });
    pushTDZVariables(environment, tdzCheckOptimization, tdzRequirement);

    if (tdzRequirement == TDZRequirement::UnderTDZ)
        emitPrefillStackTDZVariables(environment, symbolTable);
}

void BytecodeGenerator::initializeBlockScopedFunctions(VariableEnvironment& environment, FunctionStack& functionStack, RegisterID* constantSymbolTable)
{
    /*
     * We must transform block scoped function declarations in strict mode like so:
     *
     * function foo() {
     *     if (c) {
     *           function foo() { ... }
     *           if (bar) { ... }
     *           else { ... }
     *           function baz() { ... }
     *     }
     * }
     *
     * to:
     *
     * function foo() {
     *     if (c) {
     *         let foo = function foo() { ... }
     *         let baz = function baz() { ... }
     *         if (bar) { ... }
     *         else { ... }
     *     }
     * }
     * 
     * But without the TDZ checks.
    */

    if (!environment.size()) {
        RELEASE_ASSERT(!functionStack.size());
        return;
    }

    if (!functionStack.size())
        return;

    SymbolTable* symbolTable = m_lexicalScopeStack.last().m_symbolTable;
    RegisterID* scope = m_lexicalScopeStack.last().m_scope;
    RefPtr<RegisterID> temp = newTemporary();
    int symbolTableIndex = constantSymbolTable ? constantSymbolTable->index() : 0;
    for (FunctionMetadataNode* function : functionStack) {
        const Identifier& name = function->ident();
        auto iter = environment.find(name.impl());
        RELEASE_ASSERT(iter != environment.end());
        RELEASE_ASSERT(iter->value.isFunction());
        // We purposefully don't hold the symbol table lock around this loop because emitNewFunctionExpressionCommon may GC.
        SymbolTableEntry entry = symbolTable->get(NoLockingNecessary, name.impl()); 
        RELEASE_ASSERT(!entry.isNull());
        emitNewFunctionExpressionCommon(temp.get(), function);
        bool isLexicallyScoped = true;
        emitPutToScope(scope, variableForLocalEntry(name, entry, symbolTableIndex, isLexicallyScoped), temp.get(), DoNotThrowIfNotFound, InitializationMode::Initialization);
    }
}

void BytecodeGenerator::hoistSloppyModeFunctionIfNecessary(const Identifier& functionName)
{
    if (m_scopeNode->hasSloppyModeHoistedFunction(functionName.impl())) {
        if (codeType() != EvalCode) {
            Variable currentFunctionVariable = variable(functionName);
            RefPtr<RegisterID> currentValue;
            if (RegisterID* local = currentFunctionVariable.local())
                currentValue = local;
            else {
                RefPtr<RegisterID> scope = emitResolveScope(nullptr, currentFunctionVariable);
                currentValue = emitGetFromScope(newTemporary(), scope.get(), currentFunctionVariable, DoNotThrowIfNotFound);
            }

            ASSERT(m_varScopeLexicalScopeStackIndex);
            ASSERT(*m_varScopeLexicalScopeStackIndex < m_lexicalScopeStack.size());
            LexicalScopeStackEntry varScope = m_lexicalScopeStack[*m_varScopeLexicalScopeStackIndex];
            SymbolTable* varSymbolTable = varScope.m_symbolTable;
            ASSERT(varSymbolTable->scopeType() == SymbolTable::ScopeType::VarScope);
            SymbolTableEntry entry = varSymbolTable->get(NoLockingNecessary, functionName.impl());
            if (functionName == propertyNames().arguments && entry.isNull()) {
                // "arguments" might be put in the parameter scope when we have a non-simple
                // parameter list since "arguments" is visible to expressions inside the
                // parameter evaluation list.
                // e.g:
                // function foo(x = arguments) { { function arguments() { } } }
                RELEASE_ASSERT(*m_varScopeLexicalScopeStackIndex > 0);
                varScope = m_lexicalScopeStack[*m_varScopeLexicalScopeStackIndex - 1];
                SymbolTable* parameterSymbolTable = varScope.m_symbolTable;
                entry = parameterSymbolTable->get(NoLockingNecessary, functionName.impl());
            }
            RELEASE_ASSERT(!entry.isNull());
            bool isLexicallyScoped = false;
            emitPutToScope(varScope.m_scope, variableForLocalEntry(functionName, entry, varScope.m_symbolTableConstantIndex, isLexicallyScoped), currentValue.get(), DoNotThrowIfNotFound, InitializationMode::NotInitialization);
        } else {
            Variable currentFunctionVariable = variable(functionName);
            RefPtr<RegisterID> currentValue;
            if (RegisterID* local = currentFunctionVariable.local())
                currentValue = local;
            else {
                RefPtr<RegisterID> scope = emitResolveScope(nullptr, currentFunctionVariable);
                currentValue = emitGetFromScope(newTemporary(), scope.get(), currentFunctionVariable, DoNotThrowIfNotFound);
            }

            RefPtr<RegisterID> scopeId = emitResolveScopeForHoistingFuncDeclInEval(nullptr, functionName);
            RefPtr<RegisterID> checkResult = emitIsUndefined(newTemporary(), scopeId.get());
            
            Ref<Label> isNotVarScopeLabel = newLabel();
            emitJumpIfTrue(checkResult.get(), isNotVarScopeLabel.get());

            // Put to outer scope
            emitPutToScope(scopeId.get(), functionName, currentValue.get(), DoNotThrowIfNotFound, InitializationMode::NotInitialization);
            emitLabel(isNotVarScopeLabel.get());

        }
    }
}

RegisterID* BytecodeGenerator::emitResolveScopeForHoistingFuncDeclInEval(RegisterID* dst, const Identifier& property)
{
    ASSERT(m_codeType == EvalCode);

    dst = finalDestination(dst);
    OpResolveScopeForHoistingFuncDeclInEval::emit(this, kill(dst), m_topMostScope, addConstant(property));
    return dst;
}

void BytecodeGenerator::popLexicalScope(VariableEnvironmentNode* node)
{
    VariableEnvironment& environment = node->lexicalVariables();
    popLexicalScopeInternal(environment);
}

void BytecodeGenerator::popLexicalScopeInternal(VariableEnvironment& environment)
{
    // NOTE: This function only makes sense for scopes that aren't ScopeRegisterType::Var (only function name scope right now is ScopeRegisterType::Var).
    // This doesn't make sense for ScopeRegisterType::Var because we deref RegisterIDs here.
    if (!environment.size())
        return;

    if (shouldEmitDebugHooks())
        environment.markAllVariablesAsCaptured();

    auto stackEntry = m_lexicalScopeStack.takeLast();
    SymbolTable* symbolTable = stackEntry.m_symbolTable;
    bool hasCapturedVariables = false;
    for (auto& entry : environment) {
        if (entry.value.isCaptured()) {
            hasCapturedVariables = true;
            continue;
        }
        SymbolTableEntry symbolTableEntry = symbolTable->get(NoLockingNecessary, entry.key.get());
        ASSERT(!symbolTableEntry.isNull());
        VarOffset offset = symbolTableEntry.varOffset();
        ASSERT(offset.isStack());
        RegisterID* local = &registerFor(offset.stackOffset());
        local->deref();
    }

    if (hasCapturedVariables) {
        RELEASE_ASSERT(stackEntry.m_scope);
        emitGetParentScope(scopeRegister(), stackEntry.m_scope);
        popLocalControlFlowScope();
        stackEntry.m_scope->deref();
    }

    m_TDZStack.removeLast();
    m_cachedVariablesUnderTDZ = { };
}

void BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode* node, RegisterID* loopSymbolTable)
{
    VariableEnvironment& environment = node->lexicalVariables();
    if (!environment.size())
        return;
    if (shouldEmitDebugHooks())
        environment.markAllVariablesAsCaptured();
    if (!environment.hasCapturedVariables())
        return;

    RELEASE_ASSERT(loopSymbolTable);

    // This function needs to do setup for a for loop's activation if any of
    // the for loop's lexically declared variables are captured (that is, variables
    // declared in the loop header, not the loop body). This function needs to
    // make a copy of the current activation and copy the values from the previous
    // activation into the new activation because each iteration of a for loop
    // gets a new activation.

    auto stackEntry = m_lexicalScopeStack.last();
    SymbolTable* symbolTable = stackEntry.m_symbolTable;
    RegisterID* loopScope = stackEntry.m_scope;
    ASSERT(symbolTable->scopeSize());
    ASSERT(loopScope);
    Vector<std::pair<RegisterID*, Identifier>> activationValuesToCopyOver;

    {
        activationValuesToCopyOver.reserveInitialCapacity(symbolTable->scopeSize());

        for (auto end = symbolTable->end(NoLockingNecessary), ptr = symbolTable->begin(NoLockingNecessary); ptr != end; ++ptr) {
            if (!ptr->value.varOffset().isScope())
                continue;

            RefPtr<UniquedStringImpl> ident = ptr->key;
            Identifier identifier = Identifier::fromUid(m_vm, ident.get());

            RegisterID* transitionValue = newBlockScopeVariable();
            transitionValue->ref();
            emitGetFromScope(transitionValue, loopScope, variableForLocalEntry(identifier, ptr->value, loopSymbolTable->index(), true), DoNotThrowIfNotFound);
            activationValuesToCopyOver.uncheckedAppend(std::make_pair(transitionValue, identifier));
        }
    }

    // We need this dynamic behavior of the executing code to ensure
    // each loop iteration has a new activation object. (It's pretty ugly).
    // Also, this new activation needs to be assigned to the same register
    // as the previous scope because the loop body is compiled under
    // the assumption that the scope's register index is constant even
    // though the value in that register will change on each loop iteration.
    emitGetParentScope(scopeRegister(), loopScope);

    OpCreateLexicalEnvironment::emit(this, loopScope, scopeRegister(), loopSymbolTable, addConstantValue(jsTDZValue()));

    move(scopeRegister(), loopScope);

    {
        for (const auto& pair : activationValuesToCopyOver) {
            const Identifier& identifier = pair.second;
            SymbolTableEntry entry = symbolTable->get(NoLockingNecessary, identifier.impl());
            RELEASE_ASSERT(!entry.isNull());
            RegisterID* transitionValue = pair.first;
            emitPutToScope(loopScope, variableForLocalEntry(identifier, entry, loopSymbolTable->index(), true), transitionValue, DoNotThrowIfNotFound, InitializationMode::NotInitialization);
            transitionValue->deref();
        }
    }
}

Variable BytecodeGenerator::variable(const Identifier& property, ThisResolutionType thisResolutionType)
{
    if (property == propertyNames().thisIdentifier && thisResolutionType == ThisResolutionType::Local)
        return Variable(property, VarOffset(thisRegister()->virtualRegister()), thisRegister(), static_cast<unsigned>(PropertyAttribute::ReadOnly), Variable::SpecialVariable, 0, false);
    
    // We can optimize lookups if the lexical variable is found before a "with" or "catch"
    // scope because we're guaranteed static resolution. If we have to pass through
    // a "with" or "catch" scope we loose this guarantee.
    // We can't optimize cases like this:
    // {
    //     let x = ...;
    //     with (o) {
    //         doSomethingWith(x);
    //     }
    // }
    // Because we can't gaurantee static resolution on x.
    // But, in this case, we are guaranteed static resolution:
    // {
    //     let x = ...;
    //     with (o) {
    //         let x = ...;
    //         doSomethingWith(x);
    //     }
    // }
    for (unsigned i = m_lexicalScopeStack.size(); i--; ) {
        auto& stackEntry = m_lexicalScopeStack[i];
        if (stackEntry.m_isWithScope)
            return Variable(property);
        SymbolTable* symbolTable = stackEntry.m_symbolTable;
        SymbolTableEntry symbolTableEntry = symbolTable->get(NoLockingNecessary, property.impl());
        if (symbolTableEntry.isNull())
            continue;
        bool resultIsCallee = false;
        if (symbolTable->scopeType() == SymbolTable::ScopeType::FunctionNameScope) {
            if (m_usesNonStrictEval) {
                // We don't know if an eval has introduced a "var" named the same thing as the function name scope variable name.
                // We resort to dynamic lookup to answer this question.
                Variable result = Variable(property);
                return result;
            }
            resultIsCallee = true;
        }
        Variable result = variableForLocalEntry(property, symbolTableEntry, stackEntry.m_symbolTableConstantIndex, symbolTable->scopeType() == SymbolTable::ScopeType::LexicalScope);
        if (resultIsCallee)
            result.setIsReadOnly();
        return result;
    }
    
    return Variable(property);
}

Variable BytecodeGenerator::variableForLocalEntry(
    const Identifier& property, const SymbolTableEntry& entry, int symbolTableConstantIndex, bool isLexicallyScoped)
{
    VarOffset offset = entry.varOffset();
    
    RegisterID* local;
    if (offset.isStack())
        local = &registerFor(offset.stackOffset());
    else
        local = nullptr;
    
    return Variable(property, offset, local, entry.getAttributes(), Variable::NormalVariable, symbolTableConstantIndex, isLexicallyScoped);
}

void BytecodeGenerator::createVariable(
    const Identifier& property, VarKind varKind, SymbolTable* symbolTable, ExistingVariableMode existingVariableMode)
{
    ASSERT(property != propertyNames().thisIdentifier);
    SymbolTableEntry entry = symbolTable->get(NoLockingNecessary, property.impl());
    
    if (!entry.isNull()) {
        if (existingVariableMode == IgnoreExisting)
            return;
        
        // Do some checks to ensure that the variable we're being asked to create is sufficiently
        // compatible with the one we have already created.

        VarOffset offset = entry.varOffset();
        
        // We can't change our minds about whether it's captured.
        if (offset.kind() != varKind) {
            dataLog(
                "Trying to add variable called ", property, " as ", varKind,
                " but it was already added as ", offset, ".\n");
            RELEASE_ASSERT_NOT_REACHED();
        }

        return;
    }
    
    VarOffset varOffset;
    if (varKind == VarKind::Scope)
        varOffset = VarOffset(symbolTable->takeNextScopeOffset(NoLockingNecessary));
    else {
        ASSERT(varKind == VarKind::Stack);
        varOffset = VarOffset(virtualRegisterForLocal(m_calleeLocals.size()));
    }
    SymbolTableEntry newEntry(varOffset, 0);
    symbolTable->add(NoLockingNecessary, property.impl(), newEntry);
    
    if (varKind == VarKind::Stack) {
        RegisterID* local = addVar();
        RELEASE_ASSERT(local->index() == varOffset.stackOffset().offset());
    }
}

RegisterID* BytecodeGenerator::emitOverridesHasInstance(RegisterID* dst, RegisterID* constructor, RegisterID* hasInstanceValue)
{
    OpOverridesHasInstance::emit(this, dst, constructor, hasInstanceValue);
    return dst;
}

// Indicates the least upper bound of resolve type based on local scope. The bytecode linker
// will start with this ResolveType and compute the least upper bound including intercepting scopes.
ResolveType BytecodeGenerator::resolveType()
{
    for (unsigned i = m_lexicalScopeStack.size(); i--; ) {
        if (m_lexicalScopeStack[i].m_isWithScope)
            return Dynamic;
        if (m_usesNonStrictEval && m_lexicalScopeStack[i].m_symbolTable->scopeType() == SymbolTable::ScopeType::FunctionNameScope) {
            // We never want to assign to a FunctionNameScope. Returning Dynamic here achieves this goal.
            // If we aren't in non-strict eval mode, then NodesCodeGen needs to take care not to emit
            // a put_to_scope with the destination being the function name scope variable.
            return Dynamic;
        }
    }

    if (m_usesNonStrictEval)
        return GlobalPropertyWithVarInjectionChecks;
    return GlobalProperty;
}

RegisterID* BytecodeGenerator::emitResolveScope(RegisterID* dst, const Variable& variable)
{
    switch (variable.offset().kind()) {
    case VarKind::Stack:
        return nullptr;
        
    case VarKind::DirectArgument:
        return argumentsRegister();
        
    case VarKind::Scope: {
        // This always refers to the activation that *we* allocated, and not the current scope that code
        // lives in. Note that this will change once we have proper support for block scoping. Once that
        // changes, it will be correct for this code to return scopeRegister(). The only reason why we
        // don't do that already is that m_lexicalEnvironment is required by ConstDeclNode. ConstDeclNode
        // requires weird things because it is a shameful pile of nonsense, but block scoping would make
        // that code sensible and obviate the need for us to do bad things.
        for (unsigned i = m_lexicalScopeStack.size(); i--; ) {
            auto& stackEntry = m_lexicalScopeStack[i];
            // We should not resolve a variable to VarKind::Scope if a "with" scope lies in between the current
            // scope and the resolved scope.
            RELEASE_ASSERT(!stackEntry.m_isWithScope);

            if (stackEntry.m_symbolTable->get(NoLockingNecessary, variable.ident().impl()).isNull())
                continue;
            
            RegisterID* scope = stackEntry.m_scope;
            RELEASE_ASSERT(scope);
            return scope;
        }

        RELEASE_ASSERT_NOT_REACHED();
        return nullptr;
        
    }
    case VarKind::Invalid:
        // Indicates non-local resolution.
        
        dst = tempDestination(dst);
        OpResolveScope::emit(this, kill(dst), scopeRegister(), addConstant(variable.ident()), resolveType(), localScopeDepth());
        return dst;
    }
    
    RELEASE_ASSERT_NOT_REACHED();
    return nullptr;
}

RegisterID* BytecodeGenerator::emitGetFromScope(RegisterID* dst, RegisterID* scope, const Variable& variable, ResolveMode resolveMode)
{
    switch (variable.offset().kind()) {
    case VarKind::Stack:
        return move(dst, variable.local());
        
    case VarKind::DirectArgument: {
        OpGetFromArguments::emit(this, kill(dst), scope, variable.offset().capturedArgumentsOffset().offset());
        return dst;
    }
        
    case VarKind::Scope:
    case VarKind::Invalid: {
        OpGetFromScope::emit(
            this,
            kill(dst),
            scope,
            addConstant(variable.ident()),
            GetPutInfo(resolveMode, variable.offset().isScope() ? LocalClosureVar : resolveType(), InitializationMode::NotInitialization),
            localScopeDepth(),
            variable.offset().isScope() ? variable.offset().scopeOffset().offset() : 0);
        return dst;
    } }
    
    RELEASE_ASSERT_NOT_REACHED();
}

RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Variable& variable, RegisterID* value, ResolveMode resolveMode, InitializationMode initializationMode)
{
    switch (variable.offset().kind()) {
    case VarKind::Stack:
        move(variable.local(), value);
        return value;
        
    case VarKind::DirectArgument:
        OpPutToArguments::emit(this, scope, variable.offset().capturedArgumentsOffset().offset(), value);
        return value;
        
    case VarKind::Scope:
    case VarKind::Invalid: {
        GetPutInfo getPutInfo(0);
        SymbolTableOrScopeDepth symbolTableOrScopeDepth;
        ScopeOffset offset;
        if (variable.offset().isScope()) {
            offset = variable.offset().scopeOffset();
            getPutInfo = GetPutInfo(resolveMode, LocalClosureVar, initializationMode);
            symbolTableOrScopeDepth = SymbolTableOrScopeDepth::symbolTable(VirtualRegister { variable.symbolTableConstantIndex() });
        } else {
            ASSERT(resolveType() != LocalClosureVar);
            getPutInfo = GetPutInfo(resolveMode, resolveType(), initializationMode);
            symbolTableOrScopeDepth = SymbolTableOrScopeDepth::scopeDepth(localScopeDepth());
        }
        OpPutToScope::emit(this, scope, addConstant(variable.ident()), value, getPutInfo, symbolTableOrScopeDepth, !!offset ? offset.offset() : 0);
        return value;
    } }
    
    RELEASE_ASSERT_NOT_REACHED();
}

RegisterID* BytecodeGenerator::initializeVariable(const Variable& variable, RegisterID* value)
{
    RELEASE_ASSERT(variable.offset().kind() != VarKind::Invalid);
    RegisterID* scope = emitResolveScope(nullptr, variable);
    return emitPutToScope(scope, variable, value, ThrowIfNotFound, InitializationMode::NotInitialization);
}

RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype)
{
    OpInstanceof::emit(this, dst, value, basePrototype);
    return dst;
}

RegisterID* BytecodeGenerator::emitInstanceOfCustom(RegisterID* dst, RegisterID* value, RegisterID* constructor, RegisterID* hasInstanceValue)
{
    OpInstanceofCustom::emit(this, dst, value, constructor, hasInstanceValue);
    return dst;
}

RegisterID* BytecodeGenerator::emitInByVal(RegisterID* dst, RegisterID* property, RegisterID* base)
{
    OpInByVal::emit(this, dst, base, property);
    return dst;
}

RegisterID* BytecodeGenerator::emitInById(RegisterID* dst, RegisterID* base, const Identifier& property)
{
    OpInById::emit(this, dst, base, addConstant(property));
    return dst;
}

RegisterID* BytecodeGenerator::emitTryGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
{
    ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties are not supported with tryGetById.");

    OpTryGetById::emit(this, kill(dst), base, addConstant(property));
    return dst;
}

RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
{
    ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with get_by_val.");

    OpGetById::emit(this, kill(dst), base, addConstant(property));
    return dst;
}

RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, RegisterID* thisVal, const Identifier& property)
{
    ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with get_by_val.");

    OpGetByIdWithThis::emit(this, kill(dst), base, thisVal, addConstant(property));
    return dst;
}

RegisterID* BytecodeGenerator::emitDirectGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
{
    ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with get_by_val_direct.");

    OpGetByIdDirect::emit(this, kill(dst), base, addConstant(property));
    return dst;
}

RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
{
    ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with put_by_val.");

    unsigned propertyIndex = addConstant(property);

    m_staticPropertyAnalyzer.putById(base, propertyIndex);

    OpPutById::emit(this, base, propertyIndex, value, PutByIdNone); // is not direct
    return value;
}

RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, RegisterID* thisValue, const Identifier& property, RegisterID* value)
{
    ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with put_by_val.");

    unsigned propertyIndex = addConstant(property);

    OpPutByIdWithThis::emit(this, base, thisValue, propertyIndex, value);

    return value;
}

RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType putType)
{
    ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with put_by_val(direct).");

    unsigned propertyIndex = addConstant(property);

    m_staticPropertyAnalyzer.putById(base, propertyIndex);

    PutByIdFlags type = (putType == PropertyNode::KnownDirect || property != m_vm.propertyNames->underscoreProto) ? PutByIdIsDirect : PutByIdNone;
    OpPutById::emit(this, base, propertyIndex, value, type);
    return value;
}

void BytecodeGenerator::emitPutGetterById(RegisterID* base, const Identifier& property, unsigned attributes, RegisterID* getter)
{
    unsigned propertyIndex = addConstant(property);
    m_staticPropertyAnalyzer.putById(base, propertyIndex);

    OpPutGetterById::emit(this, base, propertyIndex, attributes, getter);
}

void BytecodeGenerator::emitPutSetterById(RegisterID* base, const Identifier& property, unsigned attributes, RegisterID* setter)
{
    unsigned propertyIndex = addConstant(property);
    m_staticPropertyAnalyzer.putById(base, propertyIndex);

    OpPutSetterById::emit(this, base, propertyIndex, attributes, setter);
}

void BytecodeGenerator::emitPutGetterSetter(RegisterID* base, const Identifier& property, unsigned attributes, RegisterID* getter, RegisterID* setter)
{
    unsigned propertyIndex = addConstant(property);

    m_staticPropertyAnalyzer.putById(base, propertyIndex);

    OpPutGetterSetterById::emit(this, base, propertyIndex, attributes, getter, setter);
}

void BytecodeGenerator::emitPutGetterByVal(RegisterID* base, RegisterID* property, unsigned attributes, RegisterID* getter)
{
    OpPutGetterByVal::emit(this, base, property, attributes, getter);
}

void BytecodeGenerator::emitPutSetterByVal(RegisterID* base, RegisterID* property, unsigned attributes, RegisterID* setter)
{
    OpPutSetterByVal::emit(this, base, property, attributes, setter);
}

void BytecodeGenerator::emitPutGeneratorFields(RegisterID* nextFunction)
{
    emitPutInternalField(m_generatorRegister, static_cast<unsigned>(JSGenerator::Field::Next), nextFunction);

    // We do not store 'this' in arrow function within constructor,
    // because it might be not initialized, if super is called later.
    if (!(isDerivedConstructorContext() && m_codeBlock->parseMode() == SourceParseMode::AsyncArrowFunctionMode))
        emitPutInternalField(m_generatorRegister, static_cast<unsigned>(JSGenerator::Field::This), &m_thisRegister);
}

void BytecodeGenerator::emitPutAsyncGeneratorFields(RegisterID* nextFunction)
{
    ASSERT(isAsyncGeneratorWrapperParseMode(parseMode()));

    emitPutInternalField(m_generatorRegister, static_cast<unsigned>(JSAsyncGenerator::Field::Next), nextFunction);
    emitPutInternalField(m_generatorRegister, static_cast<unsigned>(JSAsyncGenerator::Field::This), &m_thisRegister);
}

RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
{
    OpDelById::emit(this, dst, base, addConstant(property));
    return dst;
}

RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
{
    for (size_t i = m_forInContextStack.size(); i--; ) {
        ForInContext& context = m_forInContextStack[i].get();
        if (context.local() != property)
            continue;

        if (context.isIndexedForInContext()) {
            auto& indexedContext = context.asIndexedForInContext();
            kill(dst);
            if (OpGetByVal::checkWithoutMetadataID<OpcodeSize::Narrow>(this, dst, base, property))
                OpGetByVal::emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(this, dst, base, indexedContext.index());
            else if (OpGetByVal::checkWithoutMetadataID<OpcodeSize::Wide16>(this, dst, base, property))
                OpGetByVal::emitWithSmallestSizeRequirement<OpcodeSize::Wide16>(this, dst, base, indexedContext.index());
            else
                OpGetByVal::emit<OpcodeSize::Wide32>(this, dst, base, indexedContext.index());
            indexedContext.addGetInst(m_lastInstruction.offset(), property->index());
            return dst;
        }

        // We cannot do the above optimization here since OpGetDirectPname => OpGetByVal conversion involves different metadata ID allocation.
        StructureForInContext& structureContext = context.asStructureForInContext();
        OpGetDirectPname::emit<OpcodeSize::Wide32>(this, kill(dst), base, property, structureContext.index(), structureContext.enumerator());

        structureContext.addGetInst(m_lastInstruction.offset(), property->index());
        return dst;
    }

    OpGetByVal::emit(this, kill(dst), base, property);
    return dst;
}

RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* thisValue, RegisterID* property)
{
    OpGetByValWithThis::emit(this, kill(dst), base, thisValue, property);
    return dst;
}

RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
{
    OpPutByVal::emit(this, base, property, value);
    return value;
}

RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* thisValue, RegisterID* property, RegisterID* value)
{
    OpPutByValWithThis::emit(this, base, thisValue, property, value);
    return value;
}

RegisterID* BytecodeGenerator::emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
{
    OpPutByValDirect::emit(this, base, property, value);
    return value;
}

RegisterID* BytecodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
{
    OpDelByVal::emit(this, dst, base, property);
    return dst;
}

RegisterID* BytecodeGenerator::emitGetInternalField(RegisterID* dst, RegisterID* base, unsigned index)
{
    OpGetInternalField::emit(this, dst, base, index);
    return dst;
}

RegisterID* BytecodeGenerator::emitPutInternalField(RegisterID* base, unsigned index, RegisterID* value)
{
    OpPutInternalField::emit(this, base, index, value);
    return value;
}

void BytecodeGenerator::emitSuperSamplerBegin()
{
    OpSuperSamplerBegin::emit(this);
}

void BytecodeGenerator::emitSuperSamplerEnd()
{
    OpSuperSamplerEnd::emit(this);
}

RegisterID* BytecodeGenerator::emitIdWithProfile(RegisterID* src, SpeculatedType profile)
{
    OpIdentityWithProfile::emit(this, src, static_cast<uint32_t>(profile >> 32), static_cast<uint32_t>(profile));
    return src;
}

void BytecodeGenerator::emitUnreachable()
{
    OpUnreachable::emit(this);
}

RegisterID* BytecodeGenerator::emitGetArgument(RegisterID* dst, int32_t index)
{
    OpGetArgument::emit(this, dst, index + 1 /* Including |this| */);
    return dst;
}

RegisterID* BytecodeGenerator::emitCreateThis(RegisterID* dst)
{
    OpCreateThis::emit(this, dst, dst, 0);
    m_staticPropertyAnalyzer.createThis(dst, m_lastInstruction);
    return dst;
}

RegisterID* BytecodeGenerator::emitCreatePromise(RegisterID* dst, RegisterID* newTarget, bool isInternalPromise)
{
    OpCreatePromise::emit(this, dst, newTarget, isInternalPromise);
    return dst;
}

RegisterID* BytecodeGenerator::emitNewPromise(RegisterID* dst, bool isInternalPromise)
{
    OpNewPromise::emit(this, dst, isInternalPromise);
    return dst;
}

RegisterID* BytecodeGenerator::emitCreateGenerator(RegisterID* dst, RegisterID* newTarget)
{
    OpCreateGenerator::emit(this, dst, newTarget);
    return dst;
}

RegisterID* BytecodeGenerator::emitNewGenerator(RegisterID* dst)
{
    OpNewGenerator::emit(this, dst);
    return dst;
}

RegisterID* BytecodeGenerator::emitCreateAsyncGenerator(RegisterID* dst, RegisterID* newTarget)
{
    OpCreateAsyncGenerator::emit(this, dst, newTarget);
    return dst;
}

RegisterID* BytecodeGenerator::emitCreateArgumentsButterfly(RegisterID* dst)
{
    OpCreateArgumentsButterfly::emit(this, dst);
    return dst;
}

void BytecodeGenerator::emitTDZCheck(RegisterID* target)
{
    OpCheckTdz::emit(this, target);
}

bool BytecodeGenerator::needsTDZCheck(const Variable& variable)
{
    for (unsigned i = m_TDZStack.size(); i--;) {
        auto iter = m_TDZStack[i].find(variable.ident().impl());
        if (iter == m_TDZStack[i].end())
            continue;
        return iter->value != TDZNecessityLevel::NotNeeded;
    }

    return false;
}

void BytecodeGenerator::emitTDZCheckIfNecessary(const Variable& variable, RegisterID* target, RegisterID* scope)
{
    if (needsTDZCheck(variable)) {
        if (target)
            emitTDZCheck(target);
        else {
            RELEASE_ASSERT(!variable.isLocal() && scope);
            RefPtr<RegisterID> result = emitGetFromScope(newTemporary(), scope, variable, DoNotThrowIfNotFound);
            emitTDZCheck(result.get());
        }
    }
}

void BytecodeGenerator::liftTDZCheckIfPossible(const Variable& variable)
{
    RefPtr<UniquedStringImpl> identifier(variable.ident().impl());
    for (unsigned i = m_TDZStack.size(); i--;) {
        auto iter = m_TDZStack[i].find(identifier);
        if (iter != m_TDZStack[i].end()) {
            if (iter->value == TDZNecessityLevel::Optimize) {
                m_cachedVariablesUnderTDZ = { };
                iter->value = TDZNecessityLevel::NotNeeded;
            }
            break;
        }
    }
}

void BytecodeGenerator::pushTDZVariables(const VariableEnvironment& environment, TDZCheckOptimization optimization, TDZRequirement requirement)
{
    if (!environment.size())
        return;
    
    TDZNecessityLevel level;
    if (requirement == TDZRequirement::UnderTDZ) {
        if (optimization == TDZCheckOptimization::Optimize)
            level = TDZNecessityLevel::Optimize;
        else
            level = TDZNecessityLevel::DoNotOptimize;
    } else
        level = TDZNecessityLevel::NotNeeded;
    
    TDZMap map;
    for (const auto& entry : environment)
        map.add(entry.key, entry.value.isFunction() ? TDZNecessityLevel::NotNeeded : level);

    m_TDZStack.append(WTFMove(map));
    m_cachedVariablesUnderTDZ = { };
}

Optional<CompactVariableMap::Handle> BytecodeGenerator::getVariablesUnderTDZ()
{
    if (m_cachedVariablesUnderTDZ) {
        if (!m_hasCachedVariablesUnderTDZ) {
            ASSERT(m_cachedVariablesUnderTDZ.environment().toVariableEnvironment().isEmpty());
            return WTF::nullopt;
        }
        return m_cachedVariablesUnderTDZ;
    }

    // We keep track of variablesThatDontNeedTDZ in this algorithm to prevent
    // reporting that "x" is under TDZ if this function is called at "...".
    //
    //     {
    //         {
    //             let x;
    //             ...
    //         }
    //         let x;
    //     }
    SmallPtrSet<UniquedStringImpl*, 16> variablesThatDontNeedTDZ;
    VariableEnvironment environment;
    for (unsigned i = m_TDZStack.size(); i--; ) {
        auto& map = m_TDZStack[i];
        for (auto& entry : map)  {
            if (entry.value != TDZNecessityLevel::NotNeeded) {
                if (!variablesThatDontNeedTDZ.contains(entry.key.get()))
                    environment.add(entry.key.get());
            } else
                variablesThatDontNeedTDZ.add(entry.key.get());
        }
    }

    m_cachedVariablesUnderTDZ = m_vm.m_compactVariableMap->get(environment);
    m_hasCachedVariablesUnderTDZ = !environment.isEmpty();
    if (!m_hasCachedVariablesUnderTDZ)
        return WTF::nullopt;

    return m_cachedVariablesUnderTDZ;
}

void BytecodeGenerator::preserveTDZStack(BytecodeGenerator::PreservedTDZStack& preservedStack)
{
    preservedStack.m_preservedTDZStack = m_TDZStack;
}

void BytecodeGenerator::restoreTDZStack(const BytecodeGenerator::PreservedTDZStack& preservedStack)
{
    m_TDZStack = preservedStack.m_preservedTDZStack;
    m_cachedVariablesUnderTDZ = { };
}

RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst)
{
    OpNewObject::emit(this, dst, 0);
    m_staticPropertyAnalyzer.newObject(dst, m_lastInstruction);

    return dst;
}

JSValue BytecodeGenerator::addBigIntConstant(const Identifier& identifier, uint8_t radix, bool sign)
{
    return m_bigIntMap.ensure(BigIntMapEntry(identifier.impl(), radix, sign), [&] {
        auto scope = DECLARE_CATCH_SCOPE(vm());
        auto parseIntSign = sign ? JSBigInt::ParseIntSign::Signed : JSBigInt::ParseIntSign::Unsigned;
        JSBigInt* bigIntInMap = JSBigInt::parseInt(nullptr, vm(), identifier.string(), radix, JSBigInt::ErrorParseMode::ThrowExceptions, parseIntSign);
        // FIXME: [ESNext] Enables a way to throw an error on ByteCodeGenerator step
        // https://bugs.webkit.org/show_bug.cgi?id=180139
        scope.assertNoException();
        RELEASE_ASSERT(bigIntInMap);
        addConstantValue(bigIntInMap);

        return bigIntInMap;
    }).iterator->value;
}

JSString* BytecodeGenerator::addStringConstant(const Identifier& identifier)
{
    JSString*& stringInMap = m_stringMap.add(identifier.impl(), nullptr).iterator->value;
    if (!stringInMap) {
        stringInMap = jsString(vm(), identifier.string());
        addConstantValue(stringInMap);
    }
    return stringInMap;
}

RegisterID* BytecodeGenerator::addTemplateObjectConstant(Ref<TemplateObjectDescriptor>&& descriptor, int endOffset)
{
    auto result = m_templateObjectDescriptorSet.add(WTFMove(descriptor));
    JSTemplateObjectDescriptor* descriptorValue = m_templateDescriptorMap.ensure(endOffset, [&] {
        return JSTemplateObjectDescriptor::create(vm(), result.iterator->copyRef(), endOffset);
    }).iterator->value;
    int index = addConstantIndex();
    m_codeBlock->addConstant(descriptorValue);
    return &m_constantPoolRegisters[index];
}

RegisterID* BytecodeGenerator::emitNewArrayBuffer(RegisterID* dst, JSImmutableButterfly* array, IndexingType recommendedIndexingType)
{
    OpNewArrayBuffer::emit(this, dst, addConstantValue(array), recommendedIndexingType);
    return dst;
}

RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements, unsigned length, IndexingType recommendedIndexingType)
{
    Vector<RefPtr<RegisterID>, 16, UnsafeVectorOverflow> argv;
    for (ElementNode* n = elements; n; n = n->next()) {
        if (!length)
            break;
        length--;
        ASSERT(!n->value()->isSpreadExpression());
        argv.append(newTemporary());
        // op_new_array requires the initial values to be a sequential range of registers
        ASSERT(argv.size() == 1 || argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() - 1);
        emitNode(argv.last().get(), n->value());
    }
    ASSERT(!length);
    OpNewArray::emit(this, dst, argv.size() ? argv[0].get() : VirtualRegister { 0 }, argv.size(), recommendedIndexingType);
    return dst;
}

RegisterID* BytecodeGenerator::emitNewArrayWithSpread(RegisterID* dst, ElementNode* elements)
{
    BitVector bitVector;
    Vector<RefPtr<RegisterID>, 16> argv;
    for (ElementNode* node = elements; node; node = node->next()) {
        bitVector.set(argv.size(), node->value()->isSpreadExpression());

        argv.append(newTemporary());
        // op_new_array_with_spread requires the initial values to be a sequential range of registers.
        RELEASE_ASSERT(argv.size() == 1 || argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() - 1);
    }

    RELEASE_ASSERT(argv.size());

    {
        unsigned i = 0;
        for (ElementNode* node = elements; node; node = node->next()) {
            if (node->value()->isSpreadExpression()) {
                ExpressionNode* expression = static_cast<SpreadExpressionNode*>(node->value())->expression();
                RefPtr<RegisterID> tmp = newTemporary();
                emitNode(tmp.get(), expression);

                OpSpread::emit(this, argv[i].get(), tmp.get());
            } else {
                ExpressionNode* expression = node->value();
                emitNode(argv[i].get(), expression);
            }
            i++;
        }
    }

    unsigned bitVectorIndex = m_codeBlock->addBitVector(WTFMove(bitVector));
    OpNewArrayWithSpread::emit(this, dst, argv[0].get(), argv.size(), bitVectorIndex);
    return dst;
}

RegisterID* BytecodeGenerator::emitNewArrayWithSize(RegisterID* dst, RegisterID* length)
{
    OpNewArrayWithSize::emit(this, dst, length);
    return dst;
}

RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
{
    OpNewRegexp::emit(this, dst, addConstantValue(regExp));
    return dst;
}

void BytecodeGenerator::emitNewFunctionExpressionCommon(RegisterID* dst, FunctionMetadataNode* function)
{
    unsigned index = m_codeBlock->addFunctionExpr(makeFunction(function));

    switch (function->parseMode()) {
    case SourceParseMode::GeneratorWrapperFunctionMode:
    case SourceParseMode::GeneratorWrapperMethodMode:
        OpNewGeneratorFuncExp::emit(this, dst, scopeRegister(), index);
        break;
    case SourceParseMode::AsyncFunctionMode:
    case SourceParseMode::AsyncMethodMode:
    case SourceParseMode::AsyncArrowFunctionMode:
        OpNewAsyncFuncExp::emit(this, dst, scopeRegister(), index);
        break;
    case SourceParseMode::AsyncGeneratorWrapperFunctionMode:
    case SourceParseMode::AsyncGeneratorWrapperMethodMode:
        OpNewAsyncGeneratorFuncExp::emit(this, dst, scopeRegister(), index);
        break;
    default:
        OpNewFuncExp::emit(this, dst, scopeRegister(), index);
        break;
    }
}

RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func)
{
    emitNewFunctionExpressionCommon(dst, func->metadata());
    return dst;
}

RegisterID* BytecodeGenerator::emitNewArrowFunctionExpression(RegisterID* dst, ArrowFuncExprNode* func)
{
    ASSERT(SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(func->metadata()->parseMode()));
    emitNewFunctionExpressionCommon(dst, func->metadata());
    return dst;
}

RegisterID* BytecodeGenerator::emitNewMethodDefinition(RegisterID* dst, MethodDefinitionNode* func)
{
    ASSERT(isMethodParseMode(func->metadata()->parseMode()));
    emitNewFunctionExpressionCommon(dst, func->metadata());
    return dst;
}

RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, ConstructorKind constructorKind, const Identifier& name,
    const Identifier& ecmaName, const SourceCode& classSource)
{
    UnlinkedFunctionExecutable* executable = m_vm.builtinExecutables()->createDefaultConstructor(constructorKind, name);
    executable->setInvalidTypeProfilingOffsets();
    executable->setEcmaName(ecmaName);
    executable->setClassSource(classSource);

    unsigned index = m_codeBlock->addFunctionExpr(executable);

    OpNewFuncExp::emit(this, dst, scopeRegister(), index);
    return dst;
}

RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionMetadataNode* function)
{
    unsigned index = m_codeBlock->addFunctionDecl(makeFunction(function));
    if (isGeneratorWrapperParseMode(function->parseMode()))
        OpNewGeneratorFunc::emit(this, dst, scopeRegister(), index);
    else if (function->parseMode() == SourceParseMode::AsyncFunctionMode)
        OpNewAsyncFunc::emit(this, dst, scopeRegister(), index);
    else if (isAsyncGeneratorWrapperParseMode(function->parseMode()))
        OpNewAsyncGeneratorFunc::emit(this, dst, scopeRegister(), index);
    else
        OpNewFunc::emit(this, dst, scopeRegister(), index);
    return dst;
}

void BytecodeGenerator::emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, RegisterID* name)
{
    if (valueNode->isBaseFuncExprNode()) {
        FunctionMetadataNode* metadata = static_cast<BaseFuncExprNode*>(valueNode)->metadata();
        if (!metadata->ecmaName().isNull())
            return;
    } else if (valueNode->isClassExprNode()) {
        ClassExprNode* classExprNode = static_cast<ClassExprNode*>(valueNode);
        if (!classExprNode->ecmaName().isNull())
            return;
        if (classExprNode->hasStaticProperty(m_vm.propertyNames->name))
            return;
    } else
        return;

    // FIXME: We should use an op_call to an internal function here instead.
    // https://bugs.webkit.org/show_bug.cgi?id=155547
    OpSetFunctionName::emit(this, value, name);
}

RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
{
    return emitCall<OpCall>(dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd, debuggableCall);
}

RegisterID* BytecodeGenerator::emitCallInTailPosition(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
{
    if (m_inTailPosition) {
        m_codeBlock->setHasTailCalls();
        return emitCall<OpTailCall>(dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd, debuggableCall);
    }
    return emitCall<OpCall>(dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd, debuggableCall);
}

RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
{
    return emitCall<OpCallEval>(dst, func, NoExpectedFunction, callArguments, divot, divotStart, divotEnd, debuggableCall);
}

ExpectedFunction BytecodeGenerator::expectedFunctionForIdentifier(const Identifier& identifier)
{
    if (identifier == propertyNames().Object || identifier == propertyNames().builtinNames().ObjectPrivateName())
        return ExpectObjectConstructor;
    if (identifier == propertyNames().Array || identifier == propertyNames().builtinNames().ArrayPrivateName())
        return ExpectArrayConstructor;
    return NoExpectedFunction;
}

ExpectedFunction BytecodeGenerator::emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, Label& done)
{
    Ref<Label> realCall = newLabel();
    switch (expectedFunction) {
    case ExpectObjectConstructor: {
        // If the number of arguments is non-zero, then we can't do anything interesting.
        if (callArguments.argumentCountIncludingThis() >= 2)
            return NoExpectedFunction;
        
        OpJneqPtr::emit(this, func, moveLinkTimeConstant(nullptr, LinkTimeConstant::Object), realCall->bind(this));
        
        if (dst != ignoredResult())
            emitNewObject(dst);
        break;
    }
        
    case ExpectArrayConstructor: {
        // If you're doing anything other than "new Array()" or "new Array(foo)" then we
        // don't do inline it, for now. The only reason is that call arguments are in
        // the opposite order of what op_new_array expects, so we'd either need to change
        // how op_new_array works or we'd need an op_new_array_reverse. Neither of these
        // things sounds like it's worth it.
        if (callArguments.argumentCountIncludingThis() > 2)
            return NoExpectedFunction;
        
        OpJneqPtr::emit(this, func, moveLinkTimeConstant(nullptr, LinkTimeConstant::Array), realCall->bind(this));
        
        if (dst != ignoredResult()) {
            if (callArguments.argumentCountIncludingThis() == 2)
                emitNewArrayWithSize(dst, callArguments.argumentRegister(0));
            else {
                ASSERT(callArguments.argumentCountIncludingThis() == 1);
                OpNewArray::emit(this, dst, VirtualRegister { 0 }, 0, ArrayWithUndecided);
            }
        }
        break;
    }
        
    default:
        ASSERT(expectedFunction == NoExpectedFunction);
        return NoExpectedFunction;
    }
    
    OpJmp::emit(this, done.bind(this));
    emitLabel(realCall.get());
    
    return expectedFunction;
}

template<typename CallOp>
RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
{
    constexpr auto opcodeID = CallOp::opcodeID;
    ASSERT(opcodeID == op_call || opcodeID == op_call_eval || opcodeID == op_tail_call);
    ASSERT(func->refCount());
    
    // Generate code for arguments.
    unsigned argument = 0;
    if (callArguments.argumentsNode()) {
        ArgumentListNode* n = callArguments.argumentsNode()->m_listNode;
        if (n && n->m_expr->isSpreadExpression()) {
            RELEASE_ASSERT(!n->m_next);
            auto expression = static_cast<SpreadExpressionNode*>(n->m_expr)->expression();
            if (expression->isArrayLiteral()) {
                auto* elements = static_cast<ArrayNode*>(expression)->elements();
                if (elements && !elements->next() && elements->value()->isSpreadExpression()) {
                    ExpressionNode* expression = static_cast<SpreadExpressionNode*>(elements->value())->expression();
                    RefPtr<RegisterID> argumentRegister = emitNode(callArguments.argumentRegister(0), expression);
                    OpSpread::emit(this, argumentRegister.get(), argumentRegister.get());

                    return emitCallVarargs<typename VarArgsOp<CallOp>::type>(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, debuggableCall);
                }
            }
            RefPtr<RegisterID> argumentRegister;
            argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0));
            RefPtr<RegisterID> thisRegister = move(newTemporary(), callArguments.thisRegister());
            return emitCallVarargs<typename VarArgsOp<CallOp>::type>(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, debuggableCall);
        }
        for (; n; n = n->m_next)
            emitNode(callArguments.argumentRegister(argument++), n);
    }
    
    // Reserve space for call frame.
    Vector<RefPtr<RegisterID>, CallFrame::headerSizeInRegisters, UnsafeVectorOverflow> callFrame;
    for (int i = 0; i < CallFrame::headerSizeInRegisters; ++i)
        callFrame.append(newTemporary());

    if (shouldEmitDebugHooks() && debuggableCall == DebuggableCall::Yes)
        emitDebugHook(WillExecuteExpression, divotStart);

    emitExpressionInfo(divot, divotStart, divotEnd);

    Ref<Label> done = newLabel();
    expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
    
    if (opcodeID == op_tail_call)
        emitLogShadowChickenTailIfNecessary();
    
    // Emit call.
    ASSERT(dst);
    ASSERT(dst != ignoredResult());
    CallOp::emit(this, dst, func, callArguments.argumentCountIncludingThis(), callArguments.stackOffset());
    
    if (expectedFunction != NoExpectedFunction)
        emitLabel(done.get());

    return dst;
}

RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
{
    return emitCallVarargs<OpCallVarargs>(dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
}

RegisterID* BytecodeGenerator::emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
{
    if (m_inTailPosition)
        return emitCallVarargs<OpTailCallVarargs>(dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
    return emitCallVarargs<OpCallVarargs>(dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
}

RegisterID* BytecodeGenerator::emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
{
    return emitCallVarargs<OpConstructVarargs>(dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
}

RegisterID* BytecodeGenerator::emitCallForwardArgumentsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
{
    // We must emit a tail call here because we did not allocate an arguments object thus we would otherwise have no way to correctly make this call.
    ASSERT(m_inTailPosition || !Options::useTailCalls());
    return emitCallVarargs<OpTailCallForwardArguments>(dst, func, thisRegister, nullptr, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
}
    
template<typename VarargsOp>
RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
{
    if (shouldEmitDebugHooks() && debuggableCall == DebuggableCall::Yes)
        emitDebugHook(WillExecuteExpression, divotStart);

    emitExpressionInfo(divot, divotStart, divotEnd);

    if (VarargsOp::opcodeID == op_tail_call_varargs)
        emitLogShadowChickenTailIfNecessary();
    
    // Emit call.
    ASSERT(dst != ignoredResult());
    VarargsOp::emit(this, dst, func, thisRegister, arguments ? arguments : VirtualRegister(0), firstFreeRegister, firstVarArgOffset);
    return dst;
}

void BytecodeGenerator::emitLogShadowChickenPrologueIfNecessary()
{
    if (!shouldEmitDebugHooks() && !Options::alwaysUseShadowChicken())
        return;
    OpLogShadowChickenPrologue::emit(this, scopeRegister());
}

void BytecodeGenerator::emitLogShadowChickenTailIfNecessary()
{
    if (!shouldEmitDebugHooks() && !Options::alwaysUseShadowChicken())
        return;
    OpLogShadowChickenTail::emit(this, thisRegister(), scopeRegister());
}

void BytecodeGenerator::emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
    RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition& position)
{
    DefinePropertyAttributes attributes;
    if (options & PropertyConfigurable)
        attributes.setConfigurable(true);

    if (options & PropertyWritable)
        attributes.setWritable(true);
    else if (valueRegister)
        attributes.setWritable(false);

    if (options & PropertyEnumerable)
        attributes.setEnumerable(true);

    if (valueRegister)
        attributes.setValue();
    if (getterRegister)
        attributes.setGet();
    if (setterRegister)
        attributes.setSet();

    ASSERT(!valueRegister || (!getterRegister && !setterRegister));

    emitExpressionInfo(position, position, position);

    if (attributes.hasGet() || attributes.hasSet()) {
        RefPtr<RegisterID> throwTypeErrorFunction;
        if (!attributes.hasGet() || !attributes.hasSet())
            throwTypeErrorFunction = moveLinkTimeConstant(nullptr, LinkTimeConstant::throwTypeErrorFunction);

        RefPtr<RegisterID> getter;
        if (attributes.hasGet())
            getter = getterRegister;
        else
            getter = throwTypeErrorFunction;

        RefPtr<RegisterID> setter;
        if (attributes.hasSet())
            setter = setterRegister;
        else
            setter = throwTypeErrorFunction;

        OpDefineAccessorProperty::emit(this, newObj, propertyNameRegister, getter.get(), setter.get(), emitLoad(nullptr, jsNumber(attributes.rawRepresentation())));
    } else {
        OpDefineDataProperty::emit(this, newObj, propertyNameRegister, valueRegister, emitLoad(nullptr, jsNumber(attributes.rawRepresentation())));
    }
}

RegisterID* BytecodeGenerator::emitReturn(RegisterID* src, ReturnFrom from)
{
    // Normal functions and naked constructors do not handle `return` specially.
    if (isConstructor() && constructorKind() != ConstructorKind::Naked) {
        bool isDerived = constructorKind() == ConstructorKind::Extends;
        bool srcIsThis = src->index() == m_thisRegister.index();

        if (isDerived && (srcIsThis || from == ReturnFrom::Finally))
            emitTDZCheck(src);

        if (!srcIsThis || from == ReturnFrom::Finally) {
            Ref<Label> isObjectLabel = newLabel();
            emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectLabel.get());

            if (isDerived) {
                Ref<Label> isUndefinedLabel = newLabel();
                emitJumpIfTrue(emitIsUndefined(newTemporary(), src), isUndefinedLabel.get());
                emitThrowTypeError("Cannot return a non-object type in the constructor of a derived class.");
                emitLabel(isUndefinedLabel.get());
                emitTDZCheck(&m_thisRegister);
            }
            OpRet::emit(this, &m_thisRegister);
            emitLabel(isObjectLabel.get());
        }
    }

    OpRet::emit(this, src);
    return src;
}

RegisterID* BytecodeGenerator::emitEnd(RegisterID* src)
{
    OpEnd::emit(this, src);
    return src;
}


RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, RegisterID* lazyThis, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
{
    ASSERT(func->refCount());

    // Generate code for arguments.
    unsigned argument = 0;
    if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
        
        ArgumentListNode* n = callArguments.argumentsNode()->m_listNode;
        if (n && n->m_expr->isSpreadExpression()) {
            RELEASE_ASSERT(!n->m_next);
            auto expression = static_cast<SpreadExpressionNode*>(n->m_expr)->expression();
            if (expression->isArrayLiteral()) {
                auto* elements = static_cast<ArrayNode*>(expression)->elements();
                if (elements && !elements->next() && elements->value()->isSpreadExpression()) {
                    ExpressionNode* expression = static_cast<SpreadExpressionNode*>(elements->value())->expression();
                    RefPtr<RegisterID> argumentRegister = emitNode(callArguments.argumentRegister(0), expression);
                    OpSpread::emit(this, argumentRegister.get(), argumentRegister.get());

                    move(callArguments.thisRegister(), lazyThis);
                    RefPtr<RegisterID> thisRegister = move(newTemporary(), callArguments.thisRegister());
                    return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, DebuggableCall::No);
                }
            }
            RefPtr<RegisterID> argumentRegister;
            argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0));
            move(callArguments.thisRegister(), lazyThis);
            return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, DebuggableCall::No);
        }
        
        for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
            emitNode(callArguments.argumentRegister(argument++), n);
    }
    
    move(callArguments.thisRegister(), lazyThis);
    
    // Reserve space for call frame.
    Vector<RefPtr<RegisterID>, CallFrame::headerSizeInRegisters, UnsafeVectorOverflow> callFrame;
    for (int i = 0; i < CallFrame::headerSizeInRegisters; ++i)
        callFrame.append(newTemporary());

    emitExpressionInfo(divot, divotStart, divotEnd);
    
    Ref<Label> done = newLabel();
    expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());

    OpConstruct::emit(this, dst, func, callArguments.argumentCountIncludingThis(), callArguments.stackOffset());

    if (expectedFunction != NoExpectedFunction)
        emitLabel(done.get());

    return dst;
}

RegisterID* BytecodeGenerator::emitStrcat(RegisterID* dst, RegisterID* src, int count)
{
    OpStrcat::emit(this, dst, src, count);
    return dst;
}

void BytecodeGenerator::emitToPrimitive(RegisterID* dst, RegisterID* src)
{
    OpToPrimitive::emit(this, dst, src);
}

void BytecodeGenerator::emitGetScope()
{
    OpGetScope::emit(this, scopeRegister());
}

RegisterID* BytecodeGenerator::emitPushWithScope(RegisterID* objectScope)
{
    pushLocalControlFlowScope();
    RegisterID* newScope = newBlockScopeVariable();
    newScope->ref();

    OpPushWithScope::emit(this, newScope, scopeRegister(), objectScope);

    move(scopeRegister(), newScope);
    m_lexicalScopeStack.append({ nullptr, newScope, true, 0 });

    return newScope;
}

RegisterID* BytecodeGenerator::emitGetParentScope(RegisterID* dst, RegisterID* scope)
{
    OpGetParentScope::emit(this, dst, scope);
    return dst;
}

void BytecodeGenerator::emitPopWithScope()
{
    emitGetParentScope(scopeRegister(), scopeRegister());
    popLocalControlFlowScope();
    auto stackEntry = m_lexicalScopeStack.takeLast();
    stackEntry.m_scope->deref();
    RELEASE_ASSERT(stackEntry.m_isWithScope);
}

void BytecodeGenerator::emitDebugHook(DebugHookType debugHookType, const JSTextPosition& divot)
{
    if (!shouldEmitDebugHooks())
        return;

    emitExpressionInfo(divot, divot, divot);
    OpDebug::emit(this, debugHookType, false);
}

void BytecodeGenerator::emitDebugHook(DebugHookType debugHookType, unsigned line, unsigned charOffset, unsigned lineStart)
{
    emitDebugHook(debugHookType, JSTextPosition(line, charOffset, lineStart));
}

void BytecodeGenerator::emitDebugHook(StatementNode* statement)
{
    // DebuggerStatementNode will output its own special debug hook.
    if (statement->isDebuggerStatement())
        return;

    emitDebugHook(WillExecuteStatement, statement->position());
}

void BytecodeGenerator::emitDebugHook(ExpressionNode* expr)
{
    emitDebugHook(WillExecuteStatement, expr->position());
}

void BytecodeGenerator::emitWillLeaveCallFrameDebugHook()
{
    RELEASE_ASSERT(m_scopeNode->isFunctionNode());
    emitDebugHook(WillLeaveCallFrame, m_scopeNode->lastLine(), m_scopeNode->startOffset(), m_scopeNode->lineStartOffset());
}

void BytecodeGenerator::pushFinallyControlFlowScope(FinallyContext& finallyContext)
{
    ControlFlowScope scope(ControlFlowScope::Finally, currentLexicalScopeIndex(), &finallyContext);
    m_controlFlowScopeStack.append(WTFMove(scope));

    m_finallyDepth++;
    m_currentFinallyContext = &finallyContext;
}

void BytecodeGenerator::popFinallyControlFlowScope()
{
    ASSERT(m_controlFlowScopeStack.size());
    ASSERT(m_controlFlowScopeStack.last().isFinallyScope());
    ASSERT(m_finallyDepth > 0);
    ASSERT(m_currentFinallyContext);
    m_currentFinallyContext = m_currentFinallyContext->outerContext();
    m_finallyDepth--;
    m_controlFlowScopeStack.removeLast();
}

LabelScope* BytecodeGenerator::breakTarget(const Identifier& name)
{
    shrinkToFit(m_labelScopes);

    if (!m_labelScopes.size())
        return nullptr;

    // We special-case the following, which is a syntax error in Firefox:
    // label:
    //     break;
    if (name.isEmpty()) {
        for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
            LabelScope& scope = m_labelScopes[i];
            if (scope.type() != LabelScope::NamedLabel)
                return &scope;
        }
        return nullptr;
    }

    for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
        LabelScope& scope = m_labelScopes[i];
        if (scope.name() && *scope.name() == name)
            return &scope;
    }
    return nullptr;
}

LabelScope* BytecodeGenerator::continueTarget(const Identifier& name)
{
    shrinkToFit(m_labelScopes);

    if (!m_labelScopes.size())
        return nullptr;

    if (name.isEmpty()) {
        for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
            LabelScope& scope = m_labelScopes[i];
            if (scope.type() == LabelScope::Loop) {
                ASSERT(scope.continueTarget());
                return &scope;
            }
        }
        return nullptr;
    }

    // Continue to the loop nested nearest to the label scope that matches
    // 'name'.
    LabelScope* result = nullptr;
    for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
        LabelScope& scope = m_labelScopes[i];
        if (scope.type() == LabelScope::Loop) {
            ASSERT(scope.continueTarget());
            result = &scope;
        }
        if (scope.name() && *scope.name() == name)
            return result; // may be null.
    }
    return nullptr;
}

void BytecodeGenerator::allocateAndEmitScope()
{
    m_scopeRegister = addVar();
    m_scopeRegister->ref();
    m_codeBlock->setScopeRegister(scopeRegister()->virtualRegister());
    emitGetScope();
    m_topMostScope = addVar();
    move(m_topMostScope, scopeRegister());
}

TryData* BytecodeGenerator::pushTry(Label& start, Label& handlerLabel, HandlerType handlerType)
{
    m_tryData.append(TryData { handlerLabel, handlerType });
    TryData* result = &m_tryData.last();
    
    m_tryContextStack.append(TryContext {
        start,
        result
    });
    
    return result;
}

void BytecodeGenerator::popTry(TryData* tryData, Label& end)
{
    m_usesExceptions = true;
    
    ASSERT_UNUSED(tryData, m_tryContextStack.last().tryData == tryData);
    
    m_tryRanges.append(TryRange {
        m_tryContextStack.last().start.copyRef(),
        end,
        m_tryContextStack.last().tryData
    });
    m_tryContextStack.removeLast();
}

void BytecodeGenerator::emitOutOfLineCatchHandler(RegisterID* thrownValueRegister, RegisterID* completionTypeRegister, TryData* data)
{
    RegisterID* unused = newTemporary();
    emitOutOfLineExceptionHandler(unused, thrownValueRegister, completionTypeRegister, data);
}

void BytecodeGenerator::emitOutOfLineFinallyHandler(RegisterID* exceptionRegister, RegisterID* completionTypeRegister, TryData* data)
{
    RegisterID* unused = newTemporary();
    ASSERT(completionTypeRegister);
    emitOutOfLineExceptionHandler(exceptionRegister, unused, completionTypeRegister, data);
}

void BytecodeGenerator::emitOutOfLineExceptionHandler(RegisterID* exceptionRegister, RegisterID* thrownValueRegister, RegisterID* completionTypeRegister, TryData* data)
{
    VirtualRegister completionTypeVirtualRegister = completionTypeRegister ? completionTypeRegister : VirtualRegister();
    m_exceptionHandlersToEmit.append({ data, exceptionRegister, thrownValueRegister, completionTypeVirtualRegister });
}

void BytecodeGenerator::restoreScopeRegister(int lexicalScopeIndex)
{
    if (lexicalScopeIndex == CurrentLexicalScopeIndex)
        return; // No change needed.

    if (lexicalScopeIndex != OutermostLexicalScopeIndex) {
        ASSERT(lexicalScopeIndex < static_cast<int>(m_lexicalScopeStack.size()));
        int endIndex = lexicalScopeIndex + 1;
        for (size_t i = endIndex; i--; ) {
            if (m_lexicalScopeStack[i].m_scope) {
                move(scopeRegister(), m_lexicalScopeStack[i].m_scope);
                return;
            }
        }
    }
    // Note that if we don't find a local scope in the current function/program,
    // we must grab the outer-most scope of this bytecode generation.
    move(scopeRegister(), m_topMostScope);
}

void BytecodeGenerator::restoreScopeRegister()
{
    restoreScopeRegister(currentLexicalScopeIndex());
}

int BytecodeGenerator::labelScopeDepthToLexicalScopeIndex(int targetLabelScopeDepth)
{
    ASSERT(labelScopeDepth() - targetLabelScopeDepth >= 0);
    size_t scopeDelta = labelScopeDepth() - targetLabelScopeDepth;
    ASSERT(scopeDelta <= m_controlFlowScopeStack.size());
    if (!scopeDelta)
        return CurrentLexicalScopeIndex;

    ControlFlowScope& targetScope = m_controlFlowScopeStack[targetLabelScopeDepth];
    return targetScope.lexicalScopeIndex;
}

void BytecodeGenerator::emitThrow(RegisterID* exc)
{
    m_usesExceptions = true;
    OpThrow::emit(this, exc);
}

RegisterID* BytecodeGenerator::emitArgumentCount(RegisterID* dst)
{
    OpArgumentCount::emit(this, dst);
    return dst;
}

unsigned BytecodeGenerator::localScopeDepth() const
{
    return m_localScopeDepth;
}

int BytecodeGenerator::labelScopeDepth() const
{
    unsigned depth = localScopeDepth() + m_finallyDepth;
    ASSERT(depth == m_controlFlowScopeStack.size());
    return depth;
}

void BytecodeGenerator::emitThrowStaticError(ErrorType errorType, RegisterID* raw)
{
    RefPtr<RegisterID> message = newTemporary();
    emitToString(message.get(), raw);
    OpThrowStaticError::emit(this, message.get(), errorType);
}

void BytecodeGenerator::emitThrowStaticError(ErrorType errorType, const Identifier& message)
{
    OpThrowStaticError::emit(this, addConstantValue(addStringConstant(message)), errorType);
}

void BytecodeGenerator::emitThrowReferenceError(const String& message)
{
    emitThrowStaticError(ErrorType::ReferenceError, Identifier::fromString(m_vm, message));
}

void BytecodeGenerator::emitThrowTypeError(const String& message)
{
    emitThrowStaticError(ErrorType::TypeError, Identifier::fromString(m_vm, message));
}

void BytecodeGenerator::emitThrowTypeError(const Identifier& message)
{
    emitThrowStaticError(ErrorType::TypeError, message);
}

void BytecodeGenerator::emitThrowRangeError(const Identifier& message)
{
    emitThrowStaticError(ErrorType::RangeError, message);
}

void BytecodeGenerator::emitThrowOutOfMemoryError()
{
    emitThrowStaticError(ErrorType::Error, Identifier::fromString(m_vm, "Out of memory"));
}

void BytecodeGenerator::emitPushFunctionNameScope(const Identifier& property, RegisterID* callee, bool isCaptured)
{
    // There is some nuance here:
    // If we're in strict mode code, the function name scope variable acts exactly like a "const" variable.
    // If we're not in strict mode code, we want to allow bogus assignments to the name scoped variable.
    // This means any assignment to the variable won't throw, but it won't actually assign a new value to it.
    // To accomplish this, we don't report that this scope is a lexical scope. This will prevent
    // any throws when trying to assign to the variable (while still ensuring it keeps its original
    // value). There is some ugliness and exploitation of a leaky abstraction here, but it's better than 
    // having a completely new op code and a class to handle name scopes which are so close in functionality
    // to lexical environments.
    VariableEnvironment nameScopeEnvironment;
    auto addResult = nameScopeEnvironment.add(property);
    if (isCaptured)
        addResult.iterator->value.setIsCaptured();
    addResult.iterator->value.setIsConst(); // The function name scope name acts like a const variable.
    unsigned numVars = m_codeBlock->m_numVars;
    pushLexicalScopeInternal(nameScopeEnvironment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::FunctionNameScope, ScopeRegisterType::Var);
    ASSERT_UNUSED(numVars, m_codeBlock->m_numVars == static_cast<int>(numVars + 1)); // Should have only created one new "var" for the function name scope.
    bool shouldTreatAsLexicalVariable = isStrictMode();
    Variable functionVar = variableForLocalEntry(property, m_lexicalScopeStack.last().m_symbolTable->get(NoLockingNecessary, property.impl()), m_lexicalScopeStack.last().m_symbolTableConstantIndex, shouldTreatAsLexicalVariable);
    emitPutToScope(m_lexicalScopeStack.last().m_scope, functionVar, callee, ThrowIfNotFound, InitializationMode::NotInitialization);
}

void BytecodeGenerator::pushLocalControlFlowScope()
{
    ControlFlowScope scope(ControlFlowScope::Label, currentLexicalScopeIndex());
    m_controlFlowScopeStack.append(WTFMove(scope));
    m_localScopeDepth++;
}

void BytecodeGenerator::popLocalControlFlowScope()
{
    ASSERT(m_controlFlowScopeStack.size());
    ASSERT(!m_controlFlowScopeStack.last().isFinallyScope());
    m_controlFlowScopeStack.removeLast();
    m_localScopeDepth--;
}

void BytecodeGenerator::emitPushCatchScope(VariableEnvironment& environment)
{
    pushLexicalScopeInternal(environment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::UnderTDZ, ScopeType::CatchScope, ScopeRegisterType::Block);
}

void BytecodeGenerator::emitPopCatchScope(VariableEnvironment& environment) 
{
    popLexicalScopeInternal(environment);
}

void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
{
    switch (type) {
    case SwitchInfo::SwitchImmediate: {
        size_t tableIndex = m_codeBlock->numberOfSwitchJumpTables();
        m_codeBlock->addSwitchJumpTable();
        OpSwitchImm::emit(this, tableIndex, BoundLabel(), scrutineeRegister);
        break;
    }
    case SwitchInfo::SwitchCharacter: {
        size_t tableIndex = m_codeBlock->numberOfSwitchJumpTables();
        m_codeBlock->addSwitchJumpTable();
        OpSwitchChar::emit(this, tableIndex, BoundLabel(), scrutineeRegister);
        break;
    }
    case SwitchInfo::SwitchString: {
        size_t tableIndex = m_codeBlock->numberOfStringSwitchJumpTables();
        m_codeBlock->addStringSwitchJumpTable();
        OpSwitchString::emit(this, tableIndex, BoundLabel(), scrutineeRegister);
        break;
    }
    default:
        RELEASE_ASSERT_NOT_REACHED();
    }

    SwitchInfo info = { m_lastInstruction.offset(), type };
    m_switchContextStack.append(info);
}

static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max)
{
    UNUSED_PARAM(max);
    ASSERT(node->isNumber());
    double value = static_cast<NumberNode*>(node)->value();
    int32_t key = static_cast<int32_t>(value);
    ASSERT(key == value);
    ASSERT(key >= min);
    ASSERT(key <= max);
    return key - min;
}

static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max)
{
    UNUSED_PARAM(max);
    ASSERT(node->isString());
    StringImpl* clause = static_cast<StringNode*>(node)->value().impl();
    ASSERT(clause->length() == 1);
    
    int32_t key = (*clause)[0];
    ASSERT(key >= min);
    ASSERT(key <= max);
    return key - min;
}

static void prepareJumpTableForSwitch(
    UnlinkedSimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount,
    const Vector<Ref<Label>, 8>& labels, ExpressionNode** nodes, int32_t min, int32_t max,
    int32_t (*keyGetter)(ExpressionNode*, int32_t min, int32_t max))
{
    jumpTable.min = min;
    jumpTable.branchOffsets.resize(max - min + 1);
    jumpTable.branchOffsets.fill(0);
    for (uint32_t i = 0; i < clauseCount; ++i) {
        // We're emitting this after the clause labels should have been fixed, so 
        // the labels should not be "forward" references
        ASSERT(!labels[i]->isForward());
        jumpTable.add(keyGetter(nodes[i], min, max), labels[i]->bind(switchAddress)); 
    }
}

static void prepareJumpTableForStringSwitch(UnlinkedStringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, const Vector<Ref<Label>, 8>& labels, ExpressionNode** nodes)
{
    for (uint32_t i = 0; i < clauseCount; ++i) {
        // We're emitting this after the clause labels should have been fixed, so 
        // the labels should not be "forward" references
        ASSERT(!labels[i]->isForward());
        
        ASSERT(nodes[i]->isString());
        StringImpl* clause = static_cast<StringNode*>(nodes[i])->value().impl();
        jumpTable.offsetTable.add(clause, UnlinkedStringJumpTable::OffsetLocation { labels[i]->bind(switchAddress) });
    }
}

void BytecodeGenerator::endSwitch(uint32_t clauseCount, const Vector<Ref<Label>, 8>& labels, ExpressionNode** nodes, Label& defaultLabel, int32_t min, int32_t max)
{
    SwitchInfo switchInfo = m_switchContextStack.last();
    m_switchContextStack.removeLast();

    BoundLabel defaultTarget = defaultLabel.bind(switchInfo.bytecodeOffset);
    auto handleSwitch = [&](auto* op, auto bytecode) {
        op->setDefaultOffset(defaultTarget, [&]() {
            m_codeBlock->addOutOfLineJumpTarget(switchInfo.bytecodeOffset, defaultTarget);
            return BoundLabel();
        });

        UnlinkedSimpleJumpTable& jumpTable = m_codeBlock->switchJumpTable(bytecode.m_tableIndex);
        prepareJumpTableForSwitch(
            jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max,
            switchInfo.switchType == SwitchInfo::SwitchImmediate
                ? keyForImmediateSwitch
                : keyForCharacterSwitch); 
    };
    
    auto ref = m_writer.ref(switchInfo.bytecodeOffset);
    switch (switchInfo.switchType) {
    case SwitchInfo::SwitchImmediate: {
        handleSwitch(ref->cast<OpSwitchImm>(), ref->as<OpSwitchImm>());
        break;
    }
    case SwitchInfo::SwitchCharacter: {
        handleSwitch(ref->cast<OpSwitchChar>(), ref->as<OpSwitchChar>());
        break;
    }
        
    case SwitchInfo::SwitchString: {
        ref->cast<OpSwitchString>()->setDefaultOffset(defaultTarget, [&]() {
            m_codeBlock->addOutOfLineJumpTarget(switchInfo.bytecodeOffset, defaultTarget);
            return BoundLabel();
        });

        UnlinkedStringJumpTable& jumpTable = m_codeBlock->stringSwitchJumpTable(ref->as<OpSwitchString>().m_tableIndex);
        prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes);
        break;
    }
        
    default:
        RELEASE_ASSERT_NOT_REACHED();
        break;
    }
}

RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException()
{
    // It would be nice to do an even better job of identifying exactly where the expression is.
    // And we could make the caller pass the node pointer in, if there was some way of getting
    // that from an arbitrary node. However, calling emitExpressionInfo without any useful data
    // is still good enough to get us an accurate line number.
    m_expressionTooDeep = true;
    return newTemporary();
}

bool BytecodeGenerator::isArgumentNumber(const Identifier& ident, int argumentNumber)
{
    RegisterID* registerID = variable(ident).local();
    if (!registerID)
        return false;
    return registerID->index() == CallFrame::argumentOffset(argumentNumber);
}

bool BytecodeGenerator::emitReadOnlyExceptionIfNeeded(const Variable& variable)
{
    // If we're in strict mode, we always throw.
    // If we're not in strict mode, we throw for "const" variables but not the function callee.
    if (isStrictMode() || variable.isConst()) {
        emitThrowTypeError(Identifier::fromString(m_vm, ReadonlyPropertyWriteError));
        return true;
    }
    return false;
}

void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const ScopedLambda<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* forLoopNode, RegisterID* forLoopSymbolTable)
{
    bool isForAwait = forLoopNode ? forLoopNode->isForAwait() : false;
    ASSERT(!isForAwait || (isForAwait && isAsyncFunctionParseMode(parseMode())));

    RefPtr<RegisterID> subject = newTemporary();
    emitNode(subject.get(), subjectNode);
    RefPtr<RegisterID> iterator = isForAwait ? emitGetAsyncIterator(subject.get(), node) : emitGetIterator(subject.get(), node);
    RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next);

    Ref<Label> loopDone = newLabel();
    Ref<Label> tryStartLabel = newLabel();
    Ref<Label> finallyViaThrowLabel = newLabel();
    Ref<Label> finallyLabel = newLabel();
    Ref<Label> catchLabel = newLabel();
    Ref<Label> endCatchLabel = newLabel();

    // RefPtr<Register> iterator's lifetime must be longer than IteratorCloseContext.
    FinallyContext finallyContext(*this, finallyLabel.get());
    pushFinallyControlFlowScope(finallyContext);

    {
        Ref<LabelScope> scope = newLabelScope(LabelScope::Loop);
        RefPtr<RegisterID> value = newTemporary();
        emitLoad(value.get(), jsUndefined());

        emitJump(*scope->continueTarget());

        Ref<Label> loopStart = newLabel();
        emitLabel(loopStart.get());
        emitLoopHint();

        emitLabel(tryStartLabel.get());
        TryData* tryData = pushTry(tryStartLabel.get(), finallyViaThrowLabel.get(), HandlerType::SynthesizedFinally);
        callBack(*this, value.get());
        emitJump(*scope->continueTarget());

        // IteratorClose sequence for abrupt completions.
        {
            // Finally block for the enumeration.
            emitLabel(finallyViaThrowLabel.get());
            popTry(tryData, finallyViaThrowLabel.get());

            Ref<Label> finallyBodyLabel = newLabel();
            RefPtr<RegisterID> finallyExceptionRegister = newTemporary();

            emitOutOfLineFinallyHandler(finallyContext.completionValueRegister(), finallyContext.completionTypeRegister(), tryData);
            move(finallyExceptionRegister.get(), finallyContext.completionValueRegister());
            emitJump(finallyBodyLabel.get());

            emitLabel(finallyLabel.get());
            moveEmptyValue(finallyExceptionRegister.get());

            // Finally fall through case.
            emitLabel(finallyBodyLabel.get());
            restoreScopeRegister();

            Ref<Label> finallyDone = newLabel();

            RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
            emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), finallyDone.get());

            Ref<Label> returnCallTryStart = newLabel();
            emitLabel(returnCallTryStart.get());
            TryData* returnCallTryData = pushTry(returnCallTryStart.get(), catchLabel.get(), HandlerType::SynthesizedCatch);

            CallArguments returnArguments(*this, nullptr);
            move(returnArguments.thisRegister(), iterator.get());
            emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);

            if (isForAwait)
                emitAwait(value.get());

            emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), finallyDone.get());
            emitThrowTypeError("Iterator result interface is not an object."_s);

            emitLabel(finallyDone.get());
            emitFinallyCompletion(finallyContext, endCatchLabel.get());

            popTry(returnCallTryData, finallyDone.get());

            // Catch block for exceptions that may be thrown while calling the return
            // handler in the enumeration finally block. The only reason we need this
            // catch block is because if entered the above finally block due to a thrown
            // exception, then we want to re-throw the original exception on exiting
            // the finally block. Otherwise, we'll let any new exception pass through.
            {
                emitLabel(catchLabel.get());

                RefPtr<RegisterID> exceptionRegister = newTemporary();
                emitOutOfLineFinallyHandler(exceptionRegister.get(), finallyContext.completionTypeRegister(), returnCallTryData);
                // Since this is a synthesized catch block and we're guaranteed to never need
                // to resolve any symbols from the scope, we can skip restoring the scope
                // register here.

                Ref<Label> throwLabel = newLabel();
                emitJumpIfTrue(emitIsEmpty(newTemporary(), finallyExceptionRegister.get()), throwLabel.get());
                move(exceptionRegister.get(), finallyExceptionRegister.get());

                emitLabel(throwLabel.get());
                emitThrow(exceptionRegister.get());

                emitLabel(endCatchLabel.get());
            }
        }

        emitLabel(*scope->continueTarget());
        if (forLoopNode) {
            RELEASE_ASSERT(forLoopNode->isForOfNode());
            prepareLexicalScopeForNextForLoopIteration(forLoopNode, forLoopSymbolTable);
            emitDebugHook(forLoopNode->lexpr());
        }

        {
            emitIteratorNext(value.get(), nextMethod.get(), iterator.get(), node, isForAwait ? EmitAwait::Yes : EmitAwait::No);

            emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), loopDone.get());
            emitGetById(value.get(), value.get(), propertyNames().value);
            emitJump(loopStart.get());
        }

        bool breakLabelIsBound = scope->breakTargetMayBeBound();
        if (breakLabelIsBound)
            emitLabel(scope->breakTarget());
        popFinallyControlFlowScope();
        if (breakLabelIsBound) {
            // IteratorClose sequence for break-ed control flow.
            emitIteratorClose(iterator.get(), node, isForAwait ? EmitAwait::Yes : EmitAwait::No);
        }
    }
    emitLabel(loopDone.get());
}

RegisterID* BytecodeGenerator::emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode* taggedTemplate)
{
    TemplateObjectDescriptor::StringVector rawStrings;
    TemplateObjectDescriptor::OptionalStringVector cookedStrings;

    TemplateStringListNode* templateString = taggedTemplate->templateLiteral()->templateStrings();
    for (; templateString; templateString = templateString->next()) {
        auto* string = templateString->value();
        ASSERT(string->raw());
        rawStrings.append(string->raw()->impl());
        if (!string->cooked())
            cookedStrings.append(WTF::nullopt);
        else
            cookedStrings.append(string->cooked()->impl());
    }
    RefPtr<RegisterID> constant = addTemplateObjectConstant(TemplateObjectDescriptor::create(WTFMove(rawStrings), WTFMove(cookedStrings)), taggedTemplate->endOffset());
    if (!dst)
        return constant.get();
    return move(dst, constant.get());
}

RegisterID* BytecodeGenerator::emitGetGlobalPrivate(RegisterID* dst, const Identifier& property)
{
    dst = tempDestination(dst);
    Variable var = variable(property);
    if (RegisterID* local = var.local())
        return move(dst, local);

    RefPtr<RegisterID> scope = newTemporary();
    move(scope.get(), emitResolveScope(scope.get(), var));
    return emitGetFromScope(dst, scope.get(), var, ThrowIfNotFound);
}

RegisterID* BytecodeGenerator::emitGetEnumerableLength(RegisterID* dst, RegisterID* base)
{
    OpGetEnumerableLength::emit(this, dst, base);
    return dst;
}

RegisterID* BytecodeGenerator::emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
{
    OpHasGenericProperty::emit(this, dst, base, propertyName);
    return dst;
}

RegisterID* BytecodeGenerator::emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
{
    OpHasIndexedProperty::emit(this, dst, base, propertyName);
    return dst;
}

RegisterID* BytecodeGenerator::emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator)
{
    OpHasStructureProperty::emit(this, dst, base, propertyName, enumerator);
    return dst;
}

RegisterID* BytecodeGenerator::emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base)
{
    OpGetPropertyEnumerator::emit(this, dst, base);
    return dst;
}

RegisterID* BytecodeGenerator::emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
{
    OpEnumeratorStructurePname::emit(this, dst, enumerator, index);
    return dst;
}

RegisterID* BytecodeGenerator::emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
{
    OpEnumeratorGenericPname::emit(this, dst, enumerator, index);
    return dst;
}

RegisterID* BytecodeGenerator::emitToIndexString(RegisterID* dst, RegisterID* index)
{
    OpToIndexString::emit(this, dst, index);
    return dst;
}

RegisterID* BytecodeGenerator::emitIsCellWithType(RegisterID* dst, RegisterID* src, JSType type)
{
    OpIsCellWithType::emit(this, dst, src, type);
    return dst;
}

RegisterID* BytecodeGenerator::emitIsObject(RegisterID* dst, RegisterID* src)
{
    OpIsObject::emit(this, dst, src);
    return dst;
}

RegisterID* BytecodeGenerator::emitIsNumber(RegisterID* dst, RegisterID* src)
{
    OpIsNumber::emit(this, dst, src);
    return dst;
}

RegisterID* BytecodeGenerator::emitIsUndefined(RegisterID* dst, RegisterID* src)
{
    OpIsUndefined::emit(this, dst, src);
    return dst;
}

RegisterID* BytecodeGenerator::emitIsUndefinedOrNull(RegisterID* dst, RegisterID* src)
{
    OpIsUndefinedOrNull::emit(this, dst, src);
    return dst;
}

RegisterID* BytecodeGenerator::emitIsEmpty(RegisterID* dst, RegisterID* src)
{
    OpIsEmpty::emit(this, dst, src);
    return dst;
}
    
RegisterID* BytecodeGenerator::emitIteratorNext(RegisterID* dst, RegisterID* nextMethod, RegisterID* iterator, const ThrowableExpressionData* node, EmitAwait doEmitAwait)
{
    {
        CallArguments nextArguments(*this, nullptr);
        move(nextArguments.thisRegister(), iterator);
        emitCall(dst, nextMethod, NoExpectedFunction, nextArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);

        if (doEmitAwait == EmitAwait::Yes)
            emitAwait(dst);
    }
    {
        Ref<Label> typeIsObject = newLabel();
        emitJumpIfTrue(emitIsObject(newTemporary(), dst), typeIsObject.get());
        emitThrowTypeError("Iterator result interface is not an object."_s);
        emitLabel(typeIsObject.get());
    }
    return dst;
}

RegisterID* BytecodeGenerator::emitIteratorNextWithValue(RegisterID* dst, RegisterID* nextMethod, RegisterID* iterator, RegisterID* value, const ThrowableExpressionData* node)
{
    {
        CallArguments nextArguments(*this, nullptr, 1);
        move(nextArguments.thisRegister(), iterator);
        move(nextArguments.argumentRegister(0), value);
        emitCall(dst, nextMethod, NoExpectedFunction, nextArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);
    }

    return dst;
}

void BytecodeGenerator::emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node, EmitAwait doEmitAwait)
{
    Ref<Label> done = newLabel();
    RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator, propertyNames().returnKeyword);
    emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), done.get());

    RefPtr<RegisterID> value = newTemporary();
    CallArguments returnArguments(*this, nullptr);
    move(returnArguments.thisRegister(), iterator);
    emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);

    if (doEmitAwait == EmitAwait::Yes)
        emitAwait(value.get());

    emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), done.get());
    emitThrowTypeError("Iterator result interface is not an object."_s);
    emitLabel(done.get());
}

void BytecodeGenerator::pushIndexedForInScope(RegisterID* localRegister, RegisterID* indexRegister)
{
    if (!localRegister)
        return;
    unsigned bodyBytecodeStartOffset = instructions().size();
    m_forInContextStack.append(adoptRef(*new IndexedForInContext(localRegister, indexRegister, bodyBytecodeStartOffset)));
}

void BytecodeGenerator::popIndexedForInScope(RegisterID* localRegister)
{
    if (!localRegister)
        return;
    unsigned bodyBytecodeEndOffset = instructions().size();
    m_forInContextStack.last()->asIndexedForInContext().finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset);
    m_forInContextStack.removeLast();
}

RegisterID* BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment(const Identifier& identifier)
{
    ASSERT(m_codeBlock->isArrowFunction() || m_codeBlock->isArrowFunctionContext() || constructorKind() == ConstructorKind::Extends || m_codeType == EvalCode);

    return emitResolveScope(nullptr, variable(identifier, ThisResolutionType::Scoped));
}

void BytecodeGenerator::emitLoadThisFromArrowFunctionLexicalEnvironment()
{
    emitGetFromScope(thisRegister(), emitLoadArrowFunctionLexicalEnvironment(propertyNames().thisIdentifier), variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped), DoNotThrowIfNotFound);
}
    
RegisterID* BytecodeGenerator::emitLoadNewTargetFromArrowFunctionLexicalEnvironment()
{
    Variable newTargetVar = variable(propertyNames().builtinNames().newTargetLocalPrivateName());

    return emitGetFromScope(m_newTargetRegister, emitLoadArrowFunctionLexicalEnvironment(propertyNames().builtinNames().newTargetLocalPrivateName()), newTargetVar, ThrowIfNotFound);
    
}

RegisterID* BytecodeGenerator::emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment()
{
    Variable protoScopeVar = variable(propertyNames().builtinNames().derivedConstructorPrivateName());
    return emitGetFromScope(newTemporary(), emitLoadArrowFunctionLexicalEnvironment(propertyNames().builtinNames().derivedConstructorPrivateName()), protoScopeVar, ThrowIfNotFound);
}

RegisterID* BytecodeGenerator::ensureThis()
{
    if (constructorKind() == ConstructorKind::Extends || isDerivedConstructorContext()) {
        if ((needsToUpdateArrowFunctionContext() && isSuperCallUsedInInnerArrowFunction()) || m_codeBlock->parseMode() == SourceParseMode::AsyncArrowFunctionBodyMode)
            emitLoadThisFromArrowFunctionLexicalEnvironment();

        emitTDZCheck(thisRegister());
    }

    return thisRegister();
}
    
bool BytecodeGenerator::isThisUsedInInnerArrowFunction()
{
    return m_scopeNode->doAnyInnerArrowFunctionsUseThis() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperProperty() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
}
    
bool BytecodeGenerator::isArgumentsUsedInInnerArrowFunction()
{
    return m_scopeNode->doAnyInnerArrowFunctionsUseArguments() || m_scopeNode->doAnyInnerArrowFunctionsUseEval();
}

bool BytecodeGenerator::isNewTargetUsedInInnerArrowFunction()
{
    return m_scopeNode->doAnyInnerArrowFunctionsUseNewTarget() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
}

bool BytecodeGenerator::isSuperUsedInInnerArrowFunction()
{
    return m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperProperty() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
}

bool BytecodeGenerator::isSuperCallUsedInInnerArrowFunction()
{
    return m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
}
    
void BytecodeGenerator::emitPutNewTargetToArrowFunctionContextScope()
{
    if (isNewTargetUsedInInnerArrowFunction()) {
        ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister);
        
        Variable newTargetVar = variable(propertyNames().builtinNames().newTargetLocalPrivateName());
        emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, newTargetVar, newTarget(), DoNotThrowIfNotFound, InitializationMode::Initialization);
    }
}
    
void BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope()
{
    if (needsDerivedConstructorInArrowFunctionLexicalEnvironment()) {
        ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister);

        Variable protoScope = variable(propertyNames().builtinNames().derivedConstructorPrivateName());
        emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, protoScope, &m_calleeRegister, DoNotThrowIfNotFound, InitializationMode::Initialization);
    }
}

void BytecodeGenerator::emitPutThisToArrowFunctionContextScope()
{
    if (isThisUsedInInnerArrowFunction() || (m_scopeNode->usesSuperCall() && m_codeType == EvalCode)) {
        ASSERT(isDerivedConstructorContext() || m_arrowFunctionContextLexicalEnvironmentRegister != nullptr);

        Variable thisVar = variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped);
        RegisterID* scope = isDerivedConstructorContext() ? emitLoadArrowFunctionLexicalEnvironment(propertyNames().thisIdentifier) : m_arrowFunctionContextLexicalEnvironmentRegister;
    
        emitPutToScope(scope, thisVar, thisRegister(), ThrowIfNotFound, InitializationMode::NotInitialization);
    }
}

void BytecodeGenerator::pushStructureForInScope(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
{
    if (!localRegister)
        return;
    unsigned bodyBytecodeStartOffset = instructions().size();
    m_forInContextStack.append(adoptRef(*new StructureForInContext(localRegister, indexRegister, propertyRegister, enumeratorRegister, bodyBytecodeStartOffset)));
}

void BytecodeGenerator::popStructureForInScope(RegisterID* localRegister)
{
    if (!localRegister)
        return;
    unsigned bodyBytecodeEndOffset = instructions().size();
    m_forInContextStack.last()->asStructureForInContext().finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset);
    m_forInContextStack.removeLast();
}

RegisterID* BytecodeGenerator::emitRestParameter(RegisterID* result, unsigned numParametersToSkip)
{
    RefPtr<RegisterID> restArrayLength = newTemporary();
    OpGetRestLength::emit(this, restArrayLength.get(), numParametersToSkip);

    OpCreateRest::emit(this, result, restArrayLength.get(), numParametersToSkip);

    return result;
}

void BytecodeGenerator::emitRequireObjectCoercible(RegisterID* value, const String& error)
{
    Ref<Label> target = newLabel();
    OpJnundefinedOrNull::emit(this, value, target->bind(this));
    emitThrowTypeError(error);
    emitLabel(target.get());
}

void BytecodeGenerator::emitYieldPoint(RegisterID* argument, JSAsyncGenerator::AsyncGeneratorSuspendReason result)
{
    Ref<Label> mergePoint = newLabel();
    unsigned yieldPointIndex = m_yieldPoints++;
    emitGeneratorStateChange(yieldPointIndex + 1);

    if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode) {
        int suspendReason = static_cast<int32_t>(result);
        emitPutInternalField(generatorRegister(), static_cast<unsigned>(JSAsyncGenerator::Field::SuspendReason), emitLoad(nullptr, jsNumber(suspendReason)));
    }

    // Split the try range here.
    Ref<Label> savePoint = newEmittedLabel();
    for (unsigned i = m_tryContextStack.size(); i--;) {
        TryContext& context = m_tryContextStack[i];
        m_tryRanges.append(TryRange {
            context.start.copyRef(),
            savePoint.copyRef(),
            context.tryData
        });
        // Try range will be restared at the merge point.
        context.start = mergePoint.get();
    }
    Vector<TryContext> savedTryContextStack;
    m_tryContextStack.swap(savedTryContextStack);


#if CPU(NEEDS_ALIGNED_ACCESS)
    // conservatively align for the bytecode rewriter: it will delete this yield and
    // append a fragment, so we make sure that the start of the fragments is aligned
    while (m_writer.position() % OpcodeSize::Wide32)
        OpNop::emit<OpcodeSize::Narrow>(this);
#endif
    OpYield::emit(this, generatorFrameRegister(), yieldPointIndex, argument);

    // Restore the try contexts, which start offset is updated to the merge point.
    m_tryContextStack.swap(savedTryContextStack);
    emitLabel(mergePoint.get());
}

RegisterID* BytecodeGenerator::emitYield(RegisterID* argument, JSAsyncGenerator::AsyncGeneratorSuspendReason result)
{
    emitYieldPoint(argument, result);

    Ref<Label> normalLabel = newLabel();
    RefPtr<RegisterID> condition = newTemporary();
    emitEqualityOp<OpStricteq>(condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGenerator::GeneratorResumeMode::NormalMode))));
    emitJumpIfTrue(condition.get(), normalLabel.get());

    Ref<Label> throwLabel = newLabel();
    emitEqualityOp<OpStricteq>(condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGenerator::GeneratorResumeMode::ThrowMode))));
    emitJumpIfTrue(condition.get(), throwLabel.get());
    // Return.
    {
        RefPtr<RegisterID> returnRegister = generatorValueRegister();
        bool hasFinally = emitReturnViaFinallyIfNeeded(returnRegister.get());
        if (!hasFinally)
            emitReturn(returnRegister.get());
    }

    // Throw.
    emitLabel(throwLabel.get());
    emitThrow(generatorValueRegister());

    // Normal.
    emitLabel(normalLabel.get());
    return generatorValueRegister();
}

RegisterID* BytecodeGenerator::emitCallIterator(RegisterID* iterator, RegisterID* argument, ThrowableExpressionData* node)
{
    CallArguments args(*this, nullptr);
    move(args.thisRegister(), argument);
    emitCall(iterator, iterator, NoExpectedFunction, args, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);

    return iterator;
}

void BytecodeGenerator::emitAwait(RegisterID* value)
{
    emitYield(value, JSAsyncGenerator::AsyncGeneratorSuspendReason::Await);
    move(value, generatorValueRegister());
}

RegisterID* BytecodeGenerator::emitGetIterator(RegisterID* argument, ThrowableExpressionData* node)
{
    RefPtr<RegisterID> iterator = emitGetById(newTemporary(), argument, propertyNames().iteratorSymbol);
    emitCallIterator(iterator.get(), argument, node);

    return iterator.get();
}

RegisterID* BytecodeGenerator::emitGetAsyncIterator(RegisterID* argument, ThrowableExpressionData* node)
{
    RefPtr<RegisterID> iterator = emitGetById(newTemporary(), argument, propertyNames().asyncIteratorSymbol);
    Ref<Label> asyncIteratorNotFound = newLabel();
    Ref<Label> asyncIteratorFound = newLabel();
    Ref<Label> iteratorReceived = newLabel();

    emitJumpIfTrue(emitUnaryOp<OpEqNull>(newTemporary(), iterator.get()), asyncIteratorNotFound.get());

    emitJump(asyncIteratorFound.get());
    emitLabel(asyncIteratorNotFound.get());

    RefPtr<RegisterID> commonIterator = emitGetIterator(argument, node);
    move(iterator.get(), commonIterator.get());

    RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next);

    RefPtr<RegisterID> createAsyncFromSyncIterator = moveLinkTimeConstant(nullptr, LinkTimeConstant::createAsyncFromSyncIterator);

    CallArguments args(*this, nullptr, 2);
    emitLoad(args.thisRegister(), jsUndefined());

    move(args.argumentRegister(0), iterator.get());
    move(args.argumentRegister(1), nextMethod.get());

    JSTextPosition divot(m_scopeNode->firstLine(), m_scopeNode->startOffset(), m_scopeNode->lineStartOffset());
    emitCall(iterator.get(), createAsyncFromSyncIterator.get(), NoExpectedFunction, args, divot, divot, divot, DebuggableCall::No);

    emitJump(iteratorReceived.get());

    emitLabel(asyncIteratorFound.get());
    emitCallIterator(iterator.get(), argument, node);
    emitLabel(iteratorReceived.get());

    return iterator.get();
}

RegisterID* BytecodeGenerator::emitDelegateYield(RegisterID* argument, ThrowableExpressionData* node)
{
    RefPtr<RegisterID> value = newTemporary();
    {
        RefPtr<RegisterID> iterator = parseMode() == SourceParseMode::AsyncGeneratorBodyMode ? emitGetAsyncIterator(argument, node) : emitGetIterator(argument, node);
        RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next);

        Ref<Label> loopDone = newLabel();
        {
            Ref<Label> nextElement = newLabel();
            emitLoad(value.get(), jsUndefined());

            emitJump(nextElement.get());

            Ref<Label> loopStart = newLabel();
            emitLabel(loopStart.get());
            emitLoopHint();

            Ref<Label> branchOnResult = newLabel();
            {
                emitYieldPoint(value.get(), JSAsyncGenerator::AsyncGeneratorSuspendReason::Yield);

                Ref<Label> normalLabel = newLabel();
                Ref<Label> returnLabel = newLabel();
                {
                    RefPtr<RegisterID> condition = newTemporary();
                    emitEqualityOp<OpStricteq>(condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGenerator::GeneratorResumeMode::NormalMode))));
                    emitJumpIfTrue(condition.get(), normalLabel.get());

                    emitEqualityOp<OpStricteq>(condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGenerator::GeneratorResumeMode::ReturnMode))));
                    emitJumpIfTrue(condition.get(), returnLabel.get());

                    // Fallthrough to ThrowMode.
                }

                // Throw.
                {
                    Ref<Label> throwMethodFound = newLabel();
                    RefPtr<RegisterID> throwMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().throwKeyword);
                    emitJumpIfFalse(emitIsUndefined(newTemporary(), throwMethod.get()), throwMethodFound.get());

                    EmitAwait emitAwaitInIteratorClose = parseMode() == SourceParseMode::AsyncGeneratorBodyMode ? EmitAwait::Yes : EmitAwait::No;
                    emitIteratorClose(iterator.get(), node, emitAwaitInIteratorClose);

                    emitThrowTypeError("Delegated generator does not have a 'throw' method."_s);

                    emitLabel(throwMethodFound.get());
                    CallArguments throwArguments(*this, nullptr, 1);
                    move(throwArguments.thisRegister(), iterator.get());
                    move(throwArguments.argumentRegister(0), generatorValueRegister());
                    emitCall(value.get(), throwMethod.get(), NoExpectedFunction, throwArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);

                    emitJump(branchOnResult.get());
                }

                // Return.
                emitLabel(returnLabel.get());
                {
                    Ref<Label> returnMethodFound = newLabel();
                    RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
                    emitJumpIfFalse(emitIsUndefined(newTemporary(), returnMethod.get()), returnMethodFound.get());

                    move(value.get(), generatorValueRegister());

                    Ref<Label> returnSequence = newLabel();
                    emitJump(returnSequence.get());

                    emitLabel(returnMethodFound.get());
                    CallArguments returnArguments(*this, nullptr, 1);
                    move(returnArguments.thisRegister(), iterator.get());
                    move(returnArguments.argumentRegister(0), generatorValueRegister());
                    emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);

                    if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode)
                        emitAwait(value.get());

                    Ref<Label> returnIteratorResultIsObject = newLabel();
                    emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), returnIteratorResultIsObject.get());
                    emitThrowTypeError("Iterator result interface is not an object."_s);

                    emitLabel(returnIteratorResultIsObject.get());

                    Ref<Label> returnFromGenerator = newLabel();
                    emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), returnFromGenerator.get());

                    emitGetById(value.get(), value.get(), propertyNames().value);
                    emitJump(loopStart.get());

                    emitLabel(returnFromGenerator.get());
                    emitGetById(value.get(), value.get(), propertyNames().value);

                    emitLabel(returnSequence.get());
                    bool hasFinally = emitReturnViaFinallyIfNeeded(value.get());
                    if (!hasFinally)
                        emitReturn(value.get());
                }

                // Normal.
                emitLabel(normalLabel.get());
                move(value.get(), generatorValueRegister());
            }

            emitLabel(nextElement.get());
            emitIteratorNextWithValue(value.get(), nextMethod.get(), iterator.get(), value.get(), node);

            emitLabel(branchOnResult.get());

            if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode)
                emitAwait(value.get());

            Ref<Label> iteratorValueIsObject = newLabel();
            emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), iteratorValueIsObject.get());
            emitThrowTypeError("Iterator result interface is not an object."_s);
            emitLabel(iteratorValueIsObject.get());

            emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), loopDone.get());
            emitGetById(value.get(), value.get(), propertyNames().value);

            emitJump(loopStart.get());
        }
        emitLabel(loopDone.get());
    }

    emitGetById(value.get(), value.get(), propertyNames().value);
    return value.get();
}


void BytecodeGenerator::emitGeneratorStateChange(int32_t state)
{
    RegisterID* completedState = emitLoad(nullptr, jsNumber(state));
    static_assert(static_cast<unsigned>(JSGenerator::Field::State) == static_cast<unsigned>(JSAsyncGenerator::Field::State));
    emitPutInternalField(generatorRegister(), static_cast<unsigned>(JSGenerator::Field::State), completedState);
}

bool BytecodeGenerator::emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label& jumpTarget)
{
    ASSERT(labelScopeDepth() - targetLabelScopeDepth >= 0);
    size_t numberOfScopesToCheckForFinally = labelScopeDepth() - targetLabelScopeDepth;
    ASSERT(numberOfScopesToCheckForFinally <= m_controlFlowScopeStack.size());
    if (!numberOfScopesToCheckForFinally)
        return false;

    FinallyContext* innermostFinallyContext = nullptr;
    FinallyContext* outermostFinallyContext = nullptr;
    size_t scopeIndex = m_controlFlowScopeStack.size() - 1;
    while (numberOfScopesToCheckForFinally--) {
        ControlFlowScope* scope = &m_controlFlowScopeStack[scopeIndex--];
        if (scope->isFinallyScope()) {
            FinallyContext* finallyContext = scope->finallyContext;
            if (!innermostFinallyContext)
                innermostFinallyContext = finallyContext;
            outermostFinallyContext = finallyContext;
            finallyContext->incNumberOfBreaksOrContinues();
        }
    }
    if (!outermostFinallyContext)
        return false; // No finallys to thread through.

    auto jumpID = bytecodeOffsetToJumpID(instructions().size());
    int lexicalScopeIndex = labelScopeDepthToLexicalScopeIndex(targetLabelScopeDepth);
    outermostFinallyContext->registerJump(jumpID, lexicalScopeIndex, jumpTarget);

    emitLoad(innermostFinallyContext->completionTypeRegister(), jumpID);
    emitJump(*innermostFinallyContext->finallyLabel());
    return true; // We'll be jumping to a finally block.
}

bool BytecodeGenerator::emitReturnViaFinallyIfNeeded(RegisterID* returnRegister)
{
    size_t numberOfScopesToCheckForFinally = m_controlFlowScopeStack.size();
    if (!numberOfScopesToCheckForFinally)
        return false;

    FinallyContext* innermostFinallyContext = nullptr;
    while (numberOfScopesToCheckForFinally) {
        size_t scopeIndex = --numberOfScopesToCheckForFinally;
        ControlFlowScope* scope = &m_controlFlowScopeStack[scopeIndex];
        if (scope->isFinallyScope()) {
            FinallyContext* finallyContext = scope->finallyContext;
            if (!innermostFinallyContext)
                innermostFinallyContext = finallyContext;
            finallyContext->setHandlesReturns();
        }
    }
    if (!innermostFinallyContext)
        return false; // No finallys to thread through.

    emitLoad(innermostFinallyContext->completionTypeRegister(), CompletionType::Return);
    move(innermostFinallyContext->completionValueRegister(), returnRegister);
    emitJump(*innermostFinallyContext->finallyLabel());
    return true; // We'll be jumping to a finally block.
}

void BytecodeGenerator::emitFinallyCompletion(FinallyContext& context, Label& normalCompletionLabel)
{
    if (context.numberOfBreaksOrContinues() || context.handlesReturns()) {
        emitJumpIf<OpStricteq>(context.completionTypeRegister(), CompletionType::Normal, normalCompletionLabel);

        FinallyContext* outerContext = context.outerContext();

        size_t numberOfJumps = context.numberOfJumps();
        ASSERT(outerContext || numberOfJumps == context.numberOfBreaksOrContinues());

        // Handle Break or Continue completions that jumps into this FinallyContext.
        for (size_t i = 0; i < numberOfJumps; i++) {
            Ref<Label> nextLabel = newLabel();
            auto& jump = context.jumps(i);
            emitJumpIf<OpNstricteq>(context.completionTypeRegister(), jump.jumpID, nextLabel.get());

            // This case is for Break / Continue completions from an inner finally context
            // with a jump target that is not beyond the next outer finally context:
            //
            //     try {
            //         for (... stuff ...) {
            //             try {
            //                 continue; // Sets completionType to jumpID of top of the for loop.
            //             } finally {
            //             } // Jump to top of the for loop on completion.
            //         }
            //     } finally {
            //     }
            //
            // Since the jumpID is targetting a label that is inside the outer finally context,
            // we can jump to it directly on completion of this finally context: there is no intermediate
            // finally blocks to run. After the Break / Continue, we will contnue execution as normal.
            // So, we'll set the completionType to Normal (on behalf of the target) before we jump.
            // We can also set the completion value to undefined, but it will never be used for normal
            // completion anyway. So, we'll skip setting it.

            restoreScopeRegister(jump.targetLexicalScopeIndex);
            emitLoad(context.completionTypeRegister(), CompletionType::Normal);
            emitJump(jump.targetLabel.get());

            emitLabel(nextLabel.get());
        }

        // Handle completions that take us out of this FinallyContext.
        if (outerContext) {
            if (context.handlesReturns()) {
                Ref<Label> isNotReturnLabel = newLabel();
                emitJumpIf<OpNstricteq>(context.completionTypeRegister(), CompletionType::Return, isNotReturnLabel.get());

                // This case is for Return completion from an inner finally context:
                //
                //     try {
                //         try {
                //             return result; // Sets completionType to Return, and completionValue to result.
                //         } finally {
                //         } // Jump to outer finally on completion.
                //     } finally {
                //     }
                //
                // Since we know there's at least one outer finally context (beyond the current context),
                // we cannot actually return from here. Instead, we pass the completionType and completionValue
                // on to the next outer finally, and let it decide what to do next on its completion. The
                // outer finally may or may not actual return depending on whether it encounters an abrupt
                // completion in its body that overrrides this Return completion.

                move(outerContext->completionTypeRegister(), context.completionTypeRegister());
                move(outerContext->completionValueRegister(), context.completionValueRegister());
                emitJump(*outerContext->finallyLabel());

                emitLabel(isNotReturnLabel.get());
            }

            bool hasBreaksOrContinuesThatEscapeCurrentFinally = context.numberOfBreaksOrContinues() > numberOfJumps;
            if (hasBreaksOrContinuesThatEscapeCurrentFinally) {
                Ref<Label> isThrowOrNormalLabel = newLabel();
                emitJumpIf<OpBeloweq>(context.completionTypeRegister(), CompletionType::Throw, isThrowOrNormalLabel.get());

                // A completionType above Throw means we have a Break or Continue encoded as a jumpID.
                // We already ruled out Return above.
                static_assert(CompletionType::Throw < CompletionType::Return && CompletionType::Throw < CompletionType::Return, "jumpIDs are above CompletionType::Return");

                // This case is for Break / Continue completions in an inner finally context:
                //
                // 10: label:
                // 11: try {
                // 12:     try {
                // 13:         for (... stuff ...)
                // 14:             break label; // Sets completionType to jumpID of label.
                // 15:     } finally {
                // 16:     } // Jumps to outer finally on completion.
                // 17:  } finally {
                // 18:  }
                //
                // The break (line 14) says to continue execution at the label at line 10. Before we can
                // goto line 10, the inner context's finally (line 15) needs to be run, followed by the
                // outer context's finally (line 17). 'outerContext' being non-null above tells us that
                // there is at least one outer finally context that we need to run after we complete the
                // current finally. Note that unless the body of the outer finally abruptly completes in a
                // different way, that outer finally also needs to complete with a Break / Continue to
                // the same target label. Hence, we need to pass the jumpID in this finally's completionTypeRegister
                // to the outer finally. The completion value for Break and Continue according to the spec
                // is undefined, but it won't ever be used. So, we'll skip setting it.
                //
                // Note that all we're doing here is passing the Break / Continue completion to the next
                // outer finally context. We don't worry about finally contexts beyond that. It is the
                // responsibility of the next outer finally to determine what to do next at its completion,
                // and pass on to the next outer context if present and needed.

                move(outerContext->completionTypeRegister(), context.completionTypeRegister());
                emitJump(*outerContext->finallyLabel());

                emitLabel(isThrowOrNormalLabel.get());
            }

        } else {
            // We are the outermost finally.
            if (context.handlesReturns()) {
                Ref<Label> notReturnLabel = newLabel();
                emitJumpIf<OpNstricteq>(context.completionTypeRegister(), CompletionType::Return, notReturnLabel.get());

                // This case is for Return completion from the outermost finally context:
                //
                //     try {
                //         return result; // Sets completionType to Return, and completionValue to result.
                //     } finally {
                //     } // Executes the return of the completionValue.
                //
                // Since we know there's no outer finally context (beyond the current context) to run,
                // we can actually execute a return for this Return completion. The value to return
                // is whatever is in the completionValueRegister.

                emitWillLeaveCallFrameDebugHook();
                emitReturn(context.completionValueRegister(), ReturnFrom::Finally);

                emitLabel(notReturnLabel.get());
            }
        }
    }

    // By now, we've rule out all Break / Continue / Return completions above. The only remaining
    // possibilities are Normal or Throw.

    emitJumpIf<OpNstricteq>(context.completionTypeRegister(), CompletionType::Throw, normalCompletionLabel);

    // We get here because we entered this finally context with Throw completionType (i.e. we have
    // an exception that we need to rethrow), and we didn't encounter a different abrupt completion
    // that overrides that incoming completionType. All we have to do here is re-throw the exception
    // captured in the completionValue.
    //
    // Note that unlike for Break / Continue / Return, we don't need to worry about outer finally
    // contexts. This is because any outer finally context (if present) will have its own exception
    // handler, which will take care of receiving the Throw completion, and re-capturing the exception
    // in its completionValue.

    emitThrow(context.completionValueRegister());
}

template<typename CompareOp>
void BytecodeGenerator::emitJumpIf(RegisterID* completionTypeRegister, CompletionType type, Label& jumpTarget)
{
    RefPtr<RegisterID> tempRegister = newTemporary();
    RegisterID* valueConstant = addConstantValue(jsNumber(static_cast<int>(type)));
    OperandTypes operandTypes = OperandTypes(ResultType::numberTypeIsInt32(), ResultType::unknownType());

    auto equivalenceResult = emitBinaryOp<CompareOp>(tempRegister.get(), completionTypeRegister, valueConstant, operandTypes);
    emitJumpIfTrue(equivalenceResult, jumpTarget);
}

void BytecodeGenerator::pushOptionalChainTarget()
{
    m_optionalChainTargetStack.append(newLabel());
}

void BytecodeGenerator::popOptionalChainTarget()
{
    ASSERT(m_optionalChainTargetStack.size());
    emitLabel(m_optionalChainTargetStack.takeLast().get());
}

void BytecodeGenerator::popOptionalChainTarget(RegisterID* dst, bool isDelete)
{
    Ref<Label> endLabel = newLabel();
    emitJump(endLabel.get());

    popOptionalChainTarget();
    emitLoad(dst, isDelete ? jsBoolean(true) : jsUndefined());

    emitLabel(endLabel.get());
}

void BytecodeGenerator::emitOptionalCheck(RegisterID* src)
{
    ASSERT(m_optionalChainTargetStack.size());
    emitJumpIfTrue(emitIsUndefinedOrNull(newTemporary(), src), m_optionalChainTargetStack.last().get());
}

void ForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlock* codeBlock, unsigned bodyBytecodeEndOffset)
{
    // Lexically invalidating ForInContexts is kind of weak sauce, but it only occurs if
    // either of the following conditions is true:
    //
    // (1) The loop iteration variable is re-assigned within the body of the loop.
    // (2) The loop iteration variable is captured in the lexical scope of the function.
    //
    // These two situations occur sufficiently rarely that it's okay to use this style of
    // "analysis" to make iteration faster. If we didn't want to do this, we would either have
    // to perform some flow-sensitive analysis to see if/when the loop iteration variable was
    // reassigned, or we'd have to resort to runtime checks to see if the variable had been
    // reassigned from its original value.

    for (unsigned offset = bodyBytecodeStartOffset(); isValid() && offset < bodyBytecodeEndOffset;) {
        auto instruction = generator.instructions().at(offset);
        ASSERT(!instruction->is<OpEnter>());
        computeDefsForBytecodeIndex(codeBlock, instruction.ptr(), [&] (VirtualRegister operand) {
            if (local()->virtualRegister() == operand)
                invalidate();
        });
        offset += instruction->size();
    }
}

void StructureForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlock* codeBlock, unsigned bodyBytecodeEndOffset)
{
    Base::finalize(generator, codeBlock, bodyBytecodeEndOffset);
    if (isValid())
        return;

    OpcodeID lastOpcodeID = generator.m_lastOpcodeID;
    InstructionStream::MutableRef lastInstruction = generator.m_lastInstruction;
    for (const auto& instTuple : m_getInsts) {
        unsigned instIndex = std::get<0>(instTuple);
        int propertyRegIndex = std::get<1>(instTuple);
        auto instruction = generator.m_writer.ref(instIndex);
        auto end = instIndex + instruction->size();
        ASSERT(instruction->isWide32());

        generator.m_writer.seek(instIndex);

        auto bytecode = instruction->as<OpGetDirectPname>();

        // disable peephole optimizations
        generator.m_lastOpcodeID = op_end;

        // Change the opcode to get_by_val.
        // 1. dst stays the same.
        // 2. base stays the same.
        // 3. property gets switched to the original property.
        OpGetByVal::emit<OpcodeSize::Wide32>(&generator, bytecode.m_dst, bytecode.m_base, VirtualRegister(propertyRegIndex));

        // 4. nop out the remaining bytes
        while (generator.m_writer.position() < end)
            OpNop::emit<OpcodeSize::Narrow>(&generator);
    }
    generator.m_writer.seek(generator.m_writer.size());
    if (generator.m_lastInstruction.offset() + generator.m_lastInstruction->size() != generator.m_writer.size()) {
        generator.m_lastOpcodeID = lastOpcodeID;
        generator.m_lastInstruction = lastInstruction;
    }
}

void IndexedForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlock* codeBlock, unsigned bodyBytecodeEndOffset)
{
    Base::finalize(generator, codeBlock, bodyBytecodeEndOffset);
    if (isValid())
        return;

    for (const auto& instPair : m_getInsts) {
        unsigned instIndex = instPair.first;
        int propertyRegIndex = instPair.second;
        generator.m_writer.ref(instIndex)->cast<OpGetByVal>()->setProperty(VirtualRegister(propertyRegIndex), []() {
            ASSERT_NOT_REACHED();
            return VirtualRegister();
        });
    }
}

void StaticPropertyAnalysis::record()
{
    auto* instruction = m_instructionRef.ptr();
    auto size = m_propertyIndexes.size();
    switch (instruction->opcodeID()) {
    case OpNewObject::opcodeID:
        instruction->cast<OpNewObject>()->setInlineCapacity(size, []() {
            return 255;
        });
        return;
    case OpCreateThis::opcodeID:
        instruction->cast<OpCreateThis>()->setInlineCapacity(size, []() {
            return 255;
        });
        return;
    default:
        ASSERT_NOT_REACHED();
    }
}

void BytecodeGenerator::emitToThis()
{
    OpToThis::emit(this, kill(&m_thisRegister));
}

} // namespace JSC

namespace WTF {

void printInternal(PrintStream& out, JSC::Variable::VariableKind kind)
{
    switch (kind) {
    case JSC::Variable::NormalVariable:
        out.print("Normal");
        return;
    case JSC::Variable::SpecialVariable:
        out.print("Special");
        return;
    }
    RELEASE_ASSERT_NOT_REACHED();
}

} // namespace WTF

