/* * Copyright (C) 2008-2023, 2026 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich * 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 "AbstractModuleRecord.h" #include "BuiltinExecutables.h" #include "BuiltinNames.h" #include "BytecodeGeneratorBaseInlines.h" #include "BytecodeGeneratorification.h" #include "BytecodeUseDef.h" #include "DefinePropertyAttributes.h" #include "Interpreter.h" #include "JSAsyncGenerator.h" #include "JSBigInt.h" #include "JSCInlines.h" #include "JSCellButterfly.h" #include "JSTemplateObjectDescriptor.h" #include "Options.h" #include "PrivateFieldPutKind.h" #include "StrongInlines.h" #include "SuperSampler.h" #include "SymbolTableInlines.h" #include "TopExceptionScope.h" #include "UnlinkedCodeBlock.h" #include "UnlinkedEvalCodeBlock.h" #include "UnlinkedFunctionCodeBlock.h" #include "UnlinkedMetadataTableInlines.h" #include "UnlinkedModuleProgramCodeBlock.h" #include "UnlinkedProgramCodeBlock.h" #include "VMTrapsInlines.h" #include "VariableEnvironmentInlines.h" #include #include #include #include #include WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN namespace JSC { WTF_MAKE_TZONE_ALLOCATED_IMPL(BytecodeGenerator); WTF_MAKE_TZONE_ALLOCATED_IMPL(ForInContext); template struct VarArgsOp; template<> struct VarArgsOp { using type = OpCallVarargs; }; template<> struct VarArgsOp { using type = OpCallVarargs; }; template<> struct VarArgsOp { using type = OpCallVarargs; }; template<> struct VarArgsOp { using type = OpTailCallVarargs; }; template<> struct VarArgsOp { using type = OpConstructVarargs; }; template<> struct VarArgsOp { using type = OpSuperConstructVarargs; }; template<> void GenericLabel::setLocation(BytecodeGenerator& generator, unsigned location) { static_cast(generator).invalidateLoadedPrivateNames(); 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(OpJeqPtr) CASE(OpJneqPtr) CASE(OpJnstricteq) CASE(OpJless) CASE(OpJlesseq) CASE(OpJgreater) CASE(OpJgreatereq) CASE(OpJnless) CASE(OpJnlesseq) CASE(OpJngreater) CASE(OpJngreatereq) CASE(OpJbelow) CASE(OpJbeloweq) CASE(OpIteratorCloseCheck) 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()); } template void BytecodeGenerator::asyncFuncParametersTryCatchWrap(NOESCAPE const EmitBytecodeFunctor& emitBytecode) { TryData* tryData = nullptr; if (m_asyncFuncParametersTryCatchInfo) { AsyncFuncParametersTryCatchInfo& info = m_asyncFuncParametersTryCatchInfo.value(); ASSERT(info.catchStartLabel && info.thrownValue); Ref