⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 287801 in webkit


Ignore:
Timestamp:
Jan 7, 2022, 5:57:04 PM (5 years ago)
Author:
sbarati@apple.com
Message:

Add support for Wasm exceptions in the Air generator
https://bugs.webkit.org/show_bug.cgi?id=231211
<rdar://problem/84132861>

Reviewed by Filip Pizlo.

This patch adds support to Air for Wasm exceptions. The implementation
is very similar to how we implement it in the B3 Wasm tier. This patch
shares code with the B3 tier where it can.

This patch also fixes a bug where you the early clobbered registers
of a patchpoint could prevent the prior instruction from register allocating.
For example, you can have the instructions I1, I2. Where I2 clobbers the
entire register file. It doesn't mean I1 shouldn't be able to allocate
registers. Instead, the clobber should occur after I1 executes. This patch
fixes the issue.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • b3/air/AirAllocateRegistersAndStackAndGenerateCode.cpp:

(JSC::B3::Air::GenerateAndAllocateRegisters::generate):

  • wasm/WasmAirIRGenerator.cpp:

(JSC::Wasm::AirIRGenerator::ControlData::ControlData):
(JSC::Wasm::AirIRGenerator::ControlData::isTry):
(JSC::Wasm::AirIRGenerator::ControlData::isCatch):
(JSC::Wasm::AirIRGenerator::ControlData::convertTryToCatch):
(JSC::Wasm::AirIRGenerator::ControlData::convertTryToCatchAll):
(JSC::Wasm::AirIRGenerator::ControlData::tryStart const):
(JSC::Wasm::AirIRGenerator::ControlData::tryEnd const):
(JSC::Wasm::AirIRGenerator::ControlData::tryDepth const):
(JSC::Wasm::AirIRGenerator::ControlData::catchKind const):
(JSC::Wasm::AirIRGenerator::ControlData::exception const):
(JSC::Wasm::AirIRGenerator::emitCallPatchpoint):
(JSC::Wasm::AirIRGenerator::addStackMap):
(JSC::Wasm::AirIRGenerator::takeStackmaps):
(JSC::Wasm::AirIRGenerator::takeExceptionHandlers):
(JSC::Wasm::AirIRGenerator::newTmp):
(JSC::Wasm::AirIRGenerator::emitPatchpoint):
(JSC::Wasm::AirIRGenerator::emitLoad):
(JSC::Wasm::AirIRGenerator::AirIRGenerator):
(JSC::Wasm::AirIRGenerator::finalizeEntrypoints):
(JSC::Wasm::AirIRGenerator::forEachLiveValue):
(JSC::Wasm::AirIRGenerator::emitLoopTierUpCheck):
(JSC::Wasm::AirIRGenerator::addTry):
(JSC::Wasm::AirIRGenerator::addCatch):
(JSC::Wasm::AirIRGenerator::addCatchAll):
(JSC::Wasm::AirIRGenerator::addCatchToUnreachable):
(JSC::Wasm::AirIRGenerator::addCatchAllToUnreachable):
(JSC::Wasm::AirIRGenerator::emitCatchImpl):
(JSC::Wasm::AirIRGenerator::addDelegate):
(JSC::Wasm::AirIRGenerator::addDelegateToUnreachable):
(JSC::Wasm::AirIRGenerator::addThrow):
(JSC::Wasm::AirIRGenerator::addRethrow):
(JSC::Wasm::AirIRGenerator::addEndToUnreachable):
(JSC::Wasm::AirIRGenerator::addCall):
(JSC::Wasm::AirIRGenerator::emitIndirectCall):
(JSC::Wasm::parseAndCompileAir):
(JSC::Wasm::AirIRGenerator::preparePatchpointForExceptions):

  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::insertEntrySwitch):
(JSC::Wasm::B3IRGenerator::emitCatchImpl):
(JSC::Wasm::B3IRGenerator::addThrow):
(JSC::Wasm::B3IRGenerator::addRethrow):
(JSC::Wasm::PatchpointExceptionHandle::generate const): Deleted.
(JSC::Wasm::buildEntryBufferForCatch): Deleted.
(JSC::Wasm::computeExceptionHandlerLocations): Deleted.

  • wasm/WasmB3IRGenerator.h:
  • wasm/WasmBBQPlan.cpp:

(JSC::Wasm::BBQPlan::compileFunction):

  • wasm/WasmIRGeneratorHelpers.h: Added.

(JSC::Wasm::PatchpointExceptionHandle::generate const):
(JSC::Wasm::computeExceptionHandlerLocations):
(JSC::Wasm::emitRethrowImpl):
(JSC::Wasm::emitThrowImpl):
(JSC::Wasm::buildEntryBufferForCatch):
(JSC::Wasm::emitCatchPrologueShared):

  • wasm/WasmLLIntGenerator.cpp:

(JSC::Wasm::LLIntGenerator::finalize):

  • wasm/WasmModuleInformation.h:
  • wasm/WasmOMGPlan.cpp:
  • wasm/WasmOSREntryPlan.cpp:
  • wasm/WasmStreamingParser.cpp:

(JSC::Wasm::StreamingParser::parseCodeSectionSize):

Location:
trunk/Source/JavaScriptCore
Files:
1 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r287800 r287801  
     12022-01-07  Saam Barati  <sbarati@apple.com>
     2
     3        Add support for Wasm exceptions in the Air generator
     4        https://bugs.webkit.org/show_bug.cgi?id=231211
     5        <rdar://problem/84132861>
     6
     7        Reviewed by Filip Pizlo.
     8
     9        This patch adds support to Air for Wasm exceptions. The implementation
     10        is very similar to how we implement it in the B3 Wasm tier. This patch
     11        shares code with the B3 tier where it can.
     12       
     13        This patch also fixes a bug where you the early clobbered registers
     14        of a patchpoint could prevent the prior instruction from register allocating.
     15        For example, you can have the instructions I1, I2. Where I2 clobbers the
     16        entire register file. It doesn't mean I1 shouldn't be able to allocate
     17        registers. Instead, the clobber should occur after I1 executes. This patch
     18        fixes the issue.
     19
     20        * JavaScriptCore.xcodeproj/project.pbxproj:
     21        * b3/air/AirAllocateRegistersAndStackAndGenerateCode.cpp:
     22        (JSC::B3::Air::GenerateAndAllocateRegisters::generate):
     23        * wasm/WasmAirIRGenerator.cpp:
     24        (JSC::Wasm::AirIRGenerator::ControlData::ControlData):
     25        (JSC::Wasm::AirIRGenerator::ControlData::isTry):
     26        (JSC::Wasm::AirIRGenerator::ControlData::isCatch):
     27        (JSC::Wasm::AirIRGenerator::ControlData::convertTryToCatch):
     28        (JSC::Wasm::AirIRGenerator::ControlData::convertTryToCatchAll):
     29        (JSC::Wasm::AirIRGenerator::ControlData::tryStart const):
     30        (JSC::Wasm::AirIRGenerator::ControlData::tryEnd const):
     31        (JSC::Wasm::AirIRGenerator::ControlData::tryDepth const):
     32        (JSC::Wasm::AirIRGenerator::ControlData::catchKind const):
     33        (JSC::Wasm::AirIRGenerator::ControlData::exception const):
     34        (JSC::Wasm::AirIRGenerator::emitCallPatchpoint):
     35        (JSC::Wasm::AirIRGenerator::addStackMap):
     36        (JSC::Wasm::AirIRGenerator::takeStackmaps):
     37        (JSC::Wasm::AirIRGenerator::takeExceptionHandlers):
     38        (JSC::Wasm::AirIRGenerator::newTmp):
     39        (JSC::Wasm::AirIRGenerator::emitPatchpoint):
     40        (JSC::Wasm::AirIRGenerator::emitLoad):
     41        (JSC::Wasm::AirIRGenerator::AirIRGenerator):
     42        (JSC::Wasm::AirIRGenerator::finalizeEntrypoints):
     43        (JSC::Wasm::AirIRGenerator::forEachLiveValue):
     44        (JSC::Wasm::AirIRGenerator::emitLoopTierUpCheck):
     45        (JSC::Wasm::AirIRGenerator::addTry):
     46        (JSC::Wasm::AirIRGenerator::addCatch):
     47        (JSC::Wasm::AirIRGenerator::addCatchAll):
     48        (JSC::Wasm::AirIRGenerator::addCatchToUnreachable):
     49        (JSC::Wasm::AirIRGenerator::addCatchAllToUnreachable):
     50        (JSC::Wasm::AirIRGenerator::emitCatchImpl):
     51        (JSC::Wasm::AirIRGenerator::addDelegate):
     52        (JSC::Wasm::AirIRGenerator::addDelegateToUnreachable):
     53        (JSC::Wasm::AirIRGenerator::addThrow):
     54        (JSC::Wasm::AirIRGenerator::addRethrow):
     55        (JSC::Wasm::AirIRGenerator::addEndToUnreachable):
     56        (JSC::Wasm::AirIRGenerator::addCall):
     57        (JSC::Wasm::AirIRGenerator::emitIndirectCall):
     58        (JSC::Wasm::parseAndCompileAir):
     59        (JSC::Wasm::AirIRGenerator::preparePatchpointForExceptions):
     60        * wasm/WasmB3IRGenerator.cpp:
     61        (JSC::Wasm::B3IRGenerator::insertEntrySwitch):
     62        (JSC::Wasm::B3IRGenerator::emitCatchImpl):
     63        (JSC::Wasm::B3IRGenerator::addThrow):
     64        (JSC::Wasm::B3IRGenerator::addRethrow):
     65        (JSC::Wasm::PatchpointExceptionHandle::generate const): Deleted.
     66        (JSC::Wasm::buildEntryBufferForCatch): Deleted.
     67        (JSC::Wasm::computeExceptionHandlerLocations): Deleted.
     68        * wasm/WasmB3IRGenerator.h:
     69        * wasm/WasmBBQPlan.cpp:
     70        (JSC::Wasm::BBQPlan::compileFunction):
     71        * wasm/WasmIRGeneratorHelpers.h: Added.
     72        (JSC::Wasm::PatchpointExceptionHandle::generate const):
     73        (JSC::Wasm::computeExceptionHandlerLocations):
     74        (JSC::Wasm::emitRethrowImpl):
     75        (JSC::Wasm::emitThrowImpl):
     76        (JSC::Wasm::buildEntryBufferForCatch):
     77        (JSC::Wasm::emitCatchPrologueShared):
     78        * wasm/WasmLLIntGenerator.cpp:
     79        (JSC::Wasm::LLIntGenerator::finalize):
     80        * wasm/WasmModuleInformation.h:
     81        * wasm/WasmOMGPlan.cpp:
     82        * wasm/WasmOSREntryPlan.cpp:
     83        * wasm/WasmStreamingParser.cpp:
     84        (JSC::Wasm::StreamingParser::parseCodeSectionSize):
     85
    1862022-01-07  Alexey Shvayka  <ashvayka@apple.com>
    287
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r287582 r287801  
    901901                52EED7942492B870008F4C93 /* FunctionAllowlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 52EED7932492B868008F4C93 /* FunctionAllowlist.h */; };
    902902                52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */; };
     903                52FDABC32788076B00C15B59 /* WasmIRGeneratorHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 52FDABC22788076900C15B59 /* WasmIRGeneratorHelpers.h */; };
    903904                530A66B91FA3E78B0026A545 /* UnifiedSource3-mm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 530A66B11FA3E77A0026A545 /* UnifiedSource3-mm.mm */; };
    904905                530A66BA1FA3E78B0026A545 /* UnifiedSource4-mm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 530A66B81FA3E77E0026A545 /* UnifiedSource4-mm.mm */; };
     
    37613762                52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyWrapperFunction.cpp; path = js/WebAssemblyWrapperFunction.cpp; sourceTree = "<group>"; };
    37623763                52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyWrapperFunction.h; path = js/WebAssemblyWrapperFunction.h; sourceTree = "<group>"; };
     3764                52FDABC22788076900C15B59 /* WasmIRGeneratorHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WasmIRGeneratorHelpers.h; sourceTree = "<group>"; };
    37633765                5300740C22DD6F6600B9ACB3 /* JSFinalizationRegistry.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSFinalizationRegistry.cpp; sourceTree = "<group>"; };
    37643766                530A63401FA3E31C0026A545 /* SourcesCocoa.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SourcesCocoa.txt; sourceTree = "<group>"; };
     
    73067308                                148521D526EAEBDF00CC1D1A /* WasmHandlerInfo.cpp */,
    73077309                                148521D726EAEBFE00CC1D1A /* WasmHandlerInfo.h */,
     7310                                52FDABC22788076900C15B59 /* WasmIRGeneratorHelpers.h */,
    73087311                                AD8FF3961EB5BD850087FF82 /* WasmIndexOrName.cpp */,
    73097312                                AD8FF3951EB5BD850087FF82 /* WasmIndexOrName.h */,
     
    1116111164                                E393ADD81FE702D00022D681 /* WeakMapImplInlines.h in Headers */,
    1116211165                                A7CA3AE617DA41AE006538AF /* WeakMapPrototype.h in Headers */,
     11166                                52FDABC32788076B00C15B59 /* WasmIRGeneratorHelpers.h in Headers */,
    1116311167                                539930C822AD3B9A0051CDE2 /* WeakObjectRefConstructor.h in Headers */,
    1116411168                                539BFBAE22AD3C3A0023F4C0 /* WeakObjectRefPrototype.h in Headers */,
  • trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersAndStackAndGenerateCode.cpp

    r280650 r287801  
    11/*
    2  * Copyright (C) 2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    613613
    614614            RegisterSet clobberedRegisters;
     615            RegisterSet earlyNextClobberedRegisters;
    615616            {
    616617                Inst* nextInst = block->get(instIndex + 1);
     
    619620                        clobberedRegisters.merge(inst.extraClobberedRegs());
    620621                    if (nextInst && nextInst->kind.opcode == Patch)
    621                         clobberedRegisters.merge(nextInst->extraEarlyClobberedRegs());
     622                        earlyNextClobberedRegisters.merge(nextInst->extraEarlyClobberedRegs());
    622623
    623624                    clobberedRegisters.filter(m_allowedRegisters);
    624625                    clobberedRegisters.exclude(m_namedDefdRegs);
     626                    earlyNextClobberedRegisters.filter(m_allowedRegisters);
    625627
    626628                    m_namedDefdRegs.merge(clobberedRegisters);
     
    740742            }
    741743
    742             if (inst.isTerminal() && block->numSuccessors()) {
    743                 // By default, we spill everything between block boundaries. However, we have a small
    744                 // heuristic to pass along register state. We should eventually make this better.
    745                 // What we do now is if we have a successor with a single predecessor (us), and we
    746                 // haven't yet generated code for it, we give it our register state. If all our successors
    747                 // can take on our register state, we don't flush at the end of this block.
    748 
    749                 bool everySuccessorGetsOurRegisterState = true;
    750                 for (unsigned i = 0; i < block->numSuccessors(); ++i) {
    751                     BasicBlock* successor = block->successorBlock(i);
    752                     if (successor->numPredecessors() == 1 && !context.blockLabels[successor]->isSet())
    753                         currentAllocationMap[successor] = currentAllocation;
    754                     else
    755                         everySuccessorGetsOurRegisterState = false;
    756                 }
    757                 if (!everySuccessorGetsOurRegisterState) {
    758                     for (Tmp tmp : m_liveness->liveAtTail(block)) {
    759                         if (tmp.isReg() && isDisallowedRegister(tmp.reg()))
    760                             continue;
    761                         if (Reg reg = m_map[tmp].reg)
    762                             flush(tmp, reg);
    763                     }
    764                 }
    765             }
     744            auto clobber = [&] (const RegisterSet& set) {
     745                for (Reg reg : set) {
     746                    Tmp tmp(reg);
     747                    ASSERT(currentAllocation[reg] == tmp);
     748                    m_availableRegs[tmp.bank()].set(reg);
     749                    m_currentAllocation->at(reg) = Tmp();
     750                    m_map[tmp].reg = Reg();
     751                }
     752            };
    766753
    767754            if (!inst.isTerminal()) {
     
    771758                ASSERT_UNUSED(jump, !jump.isSet());
    772759
    773                 for (Reg reg : clobberedRegisters) {
    774                     Tmp tmp(reg);
    775                     ASSERT(currentAllocation[reg] == tmp);
    776                     m_availableRegs[tmp.bank()].set(reg);
    777                     m_currentAllocation->at(reg) = Tmp();
    778                     m_map[tmp].reg = Reg();
    779                 }
     760                allocNamed(earlyNextClobberedRegisters, true);
     761                clobber(clobberedRegisters);
     762                clobber(earlyNextClobberedRegisters);
    780763            } else {
    781764                ASSERT(needsToGenerate);
     765
     766                clobber(clobberedRegisters);
     767                ASSERT(earlyNextClobberedRegisters.isEmpty());
     768
     769                if (block->numSuccessors()) {
     770                    // By default, we spill everything between block boundaries. However, we have a small
     771                    // heuristic to pass along register state. We should eventually make this better.
     772                    // What we do now is if we have a successor with a single predecessor (us), and we
     773                    // haven't yet generated code for it, we give it our register state. If all our successors
     774                    // can take on our register state, we don't flush at the end of this block.
     775
     776
     777                    bool everySuccessorGetsOurRegisterState = true;
     778                    for (unsigned i = 0; i < block->numSuccessors(); ++i) {
     779                        BasicBlock* successor = block->successorBlock(i);
     780                        if (successor->numPredecessors() == 1 && !context.blockLabels[successor]->isSet())
     781                            currentAllocationMap[successor] = currentAllocation;
     782                        else
     783                            everySuccessorGetsOurRegisterState = false;
     784                    }
     785                    if (!everySuccessorGetsOurRegisterState) {
     786                        for (Tmp tmp : m_liveness->liveAtTail(block)) {
     787                            if (tmp.isReg() && isDisallowedRegister(tmp.reg()))
     788                                continue;
     789                            if (Reg reg = m_map[tmp].reg)
     790                                flush(tmp, reg);
     791                        }
     792                    }
     793                }
     794
    782795                if (inst.kind.opcode == Jump && block->successorBlock(0) == m_code.findNextBlock(block))
    783796                    needsToGenerate = false;
  • trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp

    r287160 r287801  
    11/*
    2  * Copyright (C) 2019-2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4949#include "WasmExceptionType.h"
    5050#include "WasmFunctionParser.h"
     51#include "WasmIRGeneratorHelpers.h"
    5152#include "WasmInstance.h"
    5253#include "WasmMemory.h"
     
    133134
    134135    struct ControlData {
    135         ControlData(B3::Origin origin, BlockSignature result, ResultList resultTmps, BlockType type, BasicBlock* continuation, BasicBlock* special = nullptr)
     136        ControlData(B3::Origin, BlockSignature result, ResultList resultTmps, BlockType type, BasicBlock* continuation, BasicBlock* special = nullptr)
    136137            : controlBlockType(type)
    137138            , continuation(continuation)
     
    140141            , returnType(result)
    141142        {
    142             UNUSED_PARAM(origin);
     143        }
     144
     145        ControlData(B3::Origin, BlockSignature result, ResultList resultTmps, BlockType type, BasicBlock* continuation, unsigned tryStart, unsigned tryDepth)
     146            : controlBlockType(type)
     147            , continuation(continuation)
     148            , special(nullptr)
     149            , results(resultTmps)
     150            , returnType(result)
     151            , m_tryStart(tryStart)
     152            , m_tryCatchDepth(tryDepth)
     153        {
    143154        }
    144155
     
    149160        static bool isIf(const ControlData& control) { return control.blockType() == BlockType::If; }
    150161        static bool isTry(const ControlData& control) { return control.blockType() == BlockType::Try; }
    151         static bool isCatch(const ControlData& control) { return control.blockType() == BlockType::Catch; }
    152162        static bool isAnyCatch(const ControlData& control) { return control.blockType() == BlockType::Catch; }
     163        static bool isCatch(const ControlData& control) { return isAnyCatch(control) && control.catchKind() == CatchKind::Catch; }
    153164        static bool isTopLevel(const ControlData& control) { return control.blockType() == BlockType::TopLevel; }
    154165        static bool isLoop(const ControlData& control) { return control.blockType() == BlockType::Loop; }
     
    222233        }
    223234
     235        void convertTryToCatch(unsigned tryEndCallSiteIndex, TypedTmp exception)
     236        {
     237            ASSERT(blockType() == BlockType::Try);
     238            controlBlockType = BlockType::Catch;
     239            m_catchKind = CatchKind::Catch;
     240            m_tryEnd = tryEndCallSiteIndex;
     241            m_exception = exception;
     242        }
     243
     244        void convertTryToCatchAll(unsigned tryEndCallSiteIndex, TypedTmp exception)
     245        {
     246            ASSERT(blockType() == BlockType::Try);
     247            controlBlockType = BlockType::Catch;
     248            m_catchKind = CatchKind::CatchAll;
     249            m_tryEnd = tryEndCallSiteIndex;
     250            m_exception = exception;
     251        }
     252
     253        unsigned tryStart() const
     254        {
     255            ASSERT(controlBlockType == BlockType::Try || controlBlockType == BlockType::Catch);
     256            return m_tryStart;
     257        }
     258
     259        unsigned tryEnd() const
     260        {
     261            ASSERT(controlBlockType == BlockType::Catch);
     262            return m_tryEnd;
     263        }
     264
     265        unsigned tryDepth() const
     266        {
     267            ASSERT(controlBlockType == BlockType::Try || controlBlockType == BlockType::Catch);
     268            return m_tryCatchDepth;
     269        }
     270
     271        CatchKind catchKind() const
     272        {
     273            ASSERT(controlBlockType == BlockType::Catch);
     274            return m_catchKind;
     275        }
     276
     277        TypedTmp exception() const
     278        {
     279            ASSERT(controlBlockType == BlockType::Catch);
     280            return m_exception;
     281        }
     282
    224283    private:
    225284        friend class AirIRGenerator;
     
    229288        ResultList results;
    230289        BlockSignature returnType;
     290        unsigned m_tryStart;
     291        unsigned m_tryEnd;
     292        unsigned m_tryCatchDepth;
     293        CatchKind m_catchKind;
     294        TypedTmp m_exception;
    231295    };
    232296
     
    260324
    261325    AirIRGenerator(const ModuleInformation&, B3::Procedure&, InternalFunction*, Vector<UnlinkedWasmToWasmCall>&, MemoryMode, unsigned functionIndex, TierUpCount*, const Signature&);
     326
     327    void finalizeEntrypoints();
    262328
    263329    PartialResult WARN_UNUSED_RETURN addArguments(const Signature&);
     
    350416    PartialResult WARN_UNUSED_RETURN addUnreachable();
    351417    PartialResult WARN_UNUSED_RETURN emitIndirectCall(TypedTmp calleeInstance, ExpressionType calleeCode, const Signature&, const Vector<ExpressionType>& args, ResultList&);
    352     B3::PatchpointValue* WARN_UNUSED_RETURN emitCallPatchpoint(BasicBlock*, const Signature&, const ResultList& results, const Vector<TypedTmp>& args, Vector<ConstrainedTmp>&& extraArgs = { });
     418    std::pair<B3::PatchpointValue*, PatchpointExceptionHandle> WARN_UNUSED_RETURN emitCallPatchpoint(BasicBlock*, const Signature&, const ResultList& results, const Vector<TypedTmp>& args, Vector<ConstrainedTmp> extraArgs = { });
    353419
    354420    PartialResult addShift(Type, B3::Air::Opcode, ExpressionType value, ExpressionType shift, ExpressionType& result);
     
    362428    void didPopValueFromStack() { }
    363429
     430    Tmp emitCatchImpl(CatchKind, ControlType&, unsigned exceptionIndex = 0);
     431    template <size_t inlineCapacity>
     432    PatchpointExceptionHandle preparePatchpointForExceptions(B3::PatchpointValue*, Vector<ConstrainedTmp, inlineCapacity>& args);
     433
    364434    const Bag<B3::PatchpointValue*>& patchpoints() const
    365435    {
    366436        return m_patchpoints;
     437    }
     438
     439    void addStackMap(unsigned callSiteIndex, StackMap&& stackmap)
     440    {
     441        m_stackmaps.add(CallSiteIndex(callSiteIndex), WTFMove(stackmap));
     442    }
     443
     444    StackMaps&& takeStackmaps()
     445    {
     446        return WTFMove(m_stackmaps);
     447    }
     448
     449    Vector<UnlinkedHandlerInfo>&& takeExceptionHandlers()
     450    {
     451        return WTFMove(m_exceptionHandlers);
    367452    }
    368453
     
    418503    Tmp newTmp(B3::Bank bank)
    419504    {
    420         switch (bank) {
    421         case B3::GP:
    422             if (m_freeGPs.size())
    423                 return m_freeGPs.takeLast();
    424             break;
    425         case B3::FP:
    426             if (m_freeFPs.size())
    427                 return m_freeFPs.takeLast();
    428             break;
    429         }
    430505        return m_code.newTmp(bank);
    431506    }
     
    497572    }
    498573
     574    template <size_t inlineSize>
     575    void emitPatchpoint(BasicBlock* basicBlock, B3::PatchpointValue* patch, Tmp result, Vector<ConstrainedTmp, inlineSize>&& args)
     576    {
     577        emitPatchpoint(basicBlock, patch, Vector<Tmp, 8> { result }, WTFMove(args));
     578    }
     579
    499580    template <typename ResultTmpType, size_t inlineSize>
    500     void emitPatchpoint(BasicBlock* basicBlock, B3::PatchpointValue* patch, const Vector<ResultTmpType, 8>&  results, Vector<ConstrainedTmp, inlineSize>&& args)
     581    void emitPatchpoint(BasicBlock* basicBlock, B3::PatchpointValue* patch, const Vector<ResultTmpType, 8>& results, Vector<ConstrainedTmp, inlineSize>&& args)
    501582    {
    502583        if (!m_patchpointSpecial)
     
    550631            patch->append(dummyValue, tmp.rep);
    551632            switch (tmp.rep.kind()) {
    552             case B3::ValueRep::ColdAny: // B3::Value propagates ColdAny information and later Air will allocate appropriate stack.
     633            // B3::Value propagates (Late)ColdAny information and later Air will allocate appropriate stack.
     634            case B3::ValueRep::ColdAny:
     635            case B3::ValueRep::LateColdAny:
    553636            case B3::ValueRep::SomeRegister:
    554637                inst.args.append(tmp.tmp);
     
    560643                break;
    561644            case B3::ValueRep::StackArgument: {
    562                 ASSERT(!patch->effects.terminal);
    563645                Arg arg = Arg::callArg(tmp.rep.offsetFromSP());
    564646                append(basicBlock, tmp.tmp.isGP() ? Move : MoveDouble, tmp.tmp, arg);
     
    690772    }
    691773
     774    void emitLoad(B3::Air::Opcode op, B3::Type type, Tmp base, size_t offset, Tmp result)
     775    {
     776        if (Arg::isValidAddrForm(offset, B3::widthForType(type)))
     777            append(op, Arg::addr(base, offset), result);
     778        else {
     779            auto temp2 = g64();
     780            append(Move, Arg::bigImm(offset), temp2);
     781            append(Add64, temp2, base, temp2);
     782            append(op, Arg::addr(temp2), result);
     783        }
     784    }
     785
     786    void emitLoad(Tmp base, size_t offset, TypedTmp result)
     787    {
     788        emitLoad(moveOpForValueType(result.type()), toB3Type(result.type()), base, offset, result.tmp());
     789    }
     790
    692791    void emitThrowException(CCallHelpers&, ExceptionType);
    693792
     
    738837    }
    739838
     839    template <typename Function>
     840    void forEachLiveValue(Function);
     841
    740842    FunctionParser<AirIRGenerator>* m_parser { nullptr };
    741843    const ModuleInformation& m_info;
     
    749851    BasicBlock* m_currentBlock { nullptr };
    750852    BasicBlock* m_rootBlock { nullptr };
     853    BasicBlock* m_mainEntrypointStart { nullptr };
    751854    Vector<TypedTmp> m_locals;
    752855    Vector<UnlinkedWasmToWasmCall>& m_unlinkedWasmToWasmCalls; // List each call site and the function index whose address it should be patched with.
     
    754857    GPRReg m_boundsCheckingSizeGPR { InvalidGPRReg };
    755858    GPRReg m_wasmContextInstanceGPR { InvalidGPRReg };
     859    GPRReg m_prologueWasmContextGPR { InvalidGPRReg };
    756860    bool m_makesCalls { false };
    757 
    758     Vector<Tmp, 8> m_freeGPs;
    759     Vector<Tmp, 8> m_freeFPs;
    760861
    761862    HashMap<BlockSignature, B3::Type> m_tupleMap;
     
    775876
    776877    B3::PatchpointSpecial* m_patchpointSpecial { nullptr };
     878
     879    RefPtr<B3::Air::PrologueGenerator> m_prologueGenerator;
     880
     881    Vector<BasicBlock*> m_catchEntrypoints;
     882
     883    Checked<unsigned> m_tryCatchDepth { 0 };
     884    Checked<unsigned> m_callSiteIndex { 0 };
     885    StackMaps m_stackmaps;
     886    Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
    777887};
    778888
     
    848958    }
    849959
    850     m_code.setNumEntrypoints(1);
    851 
    852     GPRReg contextInstance = Context::useFastTLS() ? wasmCallingConvention().prologueScratchGPRs[1] : m_wasmContextInstanceGPR;
    853 
    854     Ref<B3::Air::PrologueGenerator> prologueGenerator = createSharedTask<B3::Air::PrologueGeneratorFunction>([=] (CCallHelpers& jit, B3::Air::Code& code) {
     960    m_prologueWasmContextGPR = Context::useFastTLS() ? wasmCallingConvention().prologueScratchGPRs[1] : m_wasmContextInstanceGPR;
     961
     962    m_prologueGenerator = createSharedTask<B3::Air::PrologueGeneratorFunction>([=] (CCallHelpers& jit, B3::Air::Code& code) {
    855963        AllowMacroScratchRegisterUsage allowScratch(jit);
    856964        code.emitDefaultPrologue(jit);
     
    8921000
    8931001                if (Context::useFastTLS())
    894                     jit.loadWasmContextInstance(contextInstance);
     1002                    jit.loadWasmContextInstance(m_prologueWasmContextGPR);
    8951003
    8961004                jit.addPtr(CCallHelpers::TrustedImm32(-checkSize), GPRInfo::callFrameRegister, scratch);
     
    8981006                if (UNLIKELY(needUnderflowCheck))
    8991007                    overflow.append(jit.branchPtr(CCallHelpers::Above, scratch, GPRInfo::callFrameRegister));
    900                 overflow.append(jit.branchPtr(CCallHelpers::Below, scratch, CCallHelpers::Address(contextInstance, Instance::offsetOfCachedStackLimit())));
     1008                overflow.append(jit.branchPtr(CCallHelpers::Below, scratch, CCallHelpers::Address(m_prologueWasmContextGPR, Instance::offsetOfCachedStackLimit())));
    9011009                jit.addLinkTask([overflow] (LinkBuffer& linkBuffer) {
    9021010                    linkBuffer.link(overflow, CodeLocationLabel<JITThunkPtrTag>(Thunks::singleton().stub(throwStackOverflowFromWasmThunkGenerator).code()));
     
    9041012            } else if (m_usesInstanceValue && Context::useFastTLS()) {
    9051013                // No overflow check is needed, but the instance values still needs to be correct.
    906                 jit.loadWasmContextInstance(contextInstance);
     1014                jit.loadWasmContextInstance(m_prologueWasmContextGPR);
    9071015            }
    908         }
    909     });
    910 
    911     m_code.setPrologueForEntrypoint(0, WTFMove(prologueGenerator));
     1016
     1017            if (m_catchEntrypoints.size()) {
     1018                GPRReg scratch = wasmCallingConvention().prologueScratchGPRs[0];
     1019                jit.loadPtr(CCallHelpers::Address(m_prologueWasmContextGPR, Instance::offsetOfOwner()), scratch);
     1020                jit.store64(scratch, CCallHelpers::Address(GPRInfo::callFrameRegister, CallFrameSlot::thisArgument * sizeof(Register)));
     1021            }
     1022        }
     1023    });
    9121024
    9131025    if (Context::useFastTLS()) {
    9141026        m_instanceValue = g64();
    9151027        // FIXME: Would be nice to only do this if we use instance value.
    916         append(Move, Tmp(contextInstance), m_instanceValue);
     1028        append(Move, Tmp(m_prologueWasmContextGPR), m_instanceValue);
    9171029    } else
    918         m_instanceValue = { Tmp(contextInstance), Types::I64 };
     1030        m_instanceValue = { Tmp(m_prologueWasmContextGPR), Types::I64 };
     1031
     1032    append(EntrySwitch);
     1033    m_mainEntrypointStart = m_code.addBlock();
     1034    m_currentBlock = m_mainEntrypointStart;
    9191035
    9201036    ASSERT(!m_locals.size());
     
    9551071}
    9561072
     1073void AirIRGenerator::finalizeEntrypoints()
     1074{
     1075    unsigned numEntrypoints = 1 + m_catchEntrypoints.size();
     1076    m_proc.setNumEntrypoints(numEntrypoints);
     1077    m_code.setPrologueForEntrypoint(0, Ref<B3::Air::PrologueGenerator>(*m_prologueGenerator));
     1078
     1079    if (m_catchEntrypoints.size()) {
     1080        Ref<B3::Air::PrologueGenerator> catchPrologueGenerator = createSharedTask<B3::Air::PrologueGeneratorFunction>([this] (CCallHelpers& jit, B3::Air::Code& code) {
     1081            AllowMacroScratchRegisterUsage allowScratch(jit);
     1082            emitCatchPrologueShared(code, jit);
     1083
     1084            if (Context::useFastTLS()) {
     1085                // Shared prologue expects this in this register when entering the function using fast TLS.
     1086                jit.loadWasmContextInstance(m_prologueWasmContextGPR);
     1087            }
     1088        });
     1089
     1090        for (unsigned i = 0; i < m_catchEntrypoints.size(); ++i)
     1091            m_code.setPrologueForEntrypoint(1 + i, catchPrologueGenerator.copyRef());
     1092    }
     1093
     1094    BasicBlock::SuccessorList successors;
     1095    successors.append(m_mainEntrypointStart);
     1096    successors.appendVector(m_catchEntrypoints);
     1097
     1098    RELEASE_ASSERT(numEntrypoints == successors.size());
     1099    m_rootBlock->successors() = successors;
     1100}
     1101
    9571102B3::Type AirIRGenerator::toB3ResultType(BlockSignature returnType)
    9581103{
     
    10261171        linkBuffer.link(jumpToExceptionStub, CodeLocationLabel<JITThunkPtrTag>(Thunks::singleton().stub(throwExceptionFromWasmThunkGenerator).code()));
    10271172    });
     1173}
     1174
     1175template <typename Function>
     1176void AirIRGenerator::forEachLiveValue(Function function)
     1177{
     1178    for (const auto& local : m_locals)
     1179        function(local);
     1180    for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
     1181        ControlData& data = m_parser->controlStack()[controlIndex].controlData;
     1182        Stack& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
     1183        for (const auto& tmp : expressionStack)
     1184            function(tmp.value());
     1185        if (ControlType::isAnyCatch(data))
     1186            function(data.exception());
     1187    }
    10281188}
    10291189
     
    29043064    patchArgs.append(countdownPtr);
    29053065
    2906     for (auto& local : m_locals)
    2907         patchArgs.append(ConstrainedTmp(local, B3::ValueRep::ColdAny));
    2908     for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
    2909         Stack& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
    2910         for (TypedExpression value : expressionStack)
    2911             patchArgs.append(ConstrainedTmp(value.value(), B3::ValueRep::ColdAny));
    2912     }
     3066    forEachLiveValue([&] (Tmp tmp) {
     3067        patchArgs.append(ConstrainedTmp(tmp, B3::ValueRep::ColdAny));
     3068    });
    29133069    for (TypedExpression value : enclosingStack)
    29143070        patchArgs.append(ConstrainedTmp(value.value(), B3::ValueRep::ColdAny));
     
    30133169}
    30143170
    3015 // FIXME: Add support for Wasm exceptions in the Air generator
    3016 // https://bugs.webkit.org/show_bug.cgi?id=231211
    3017 auto AirIRGenerator::addTry(BlockSignature, Stack&, ControlType&, Stack&) -> PartialResult
    3018 {
    3019     return { };
    3020 }
    3021 
    3022 auto AirIRGenerator::addCatch(unsigned, const Signature&, Stack&, ControlType&, ResultList&) -> PartialResult
    3023 {
    3024     RELEASE_ASSERT_NOT_REACHED();
    3025     return { };
    3026 }
    3027 
    3028 auto AirIRGenerator::addCatchToUnreachable(unsigned, const Signature&, ControlType&, ResultList&) -> PartialResult
    3029 {
    3030     RELEASE_ASSERT_NOT_REACHED();
    3031     return { };
    3032 }
    3033 
    3034 auto AirIRGenerator::addCatchAll(Stack&, ControlType&) -> PartialResult
    3035 {
    3036     RELEASE_ASSERT_NOT_REACHED();
    3037     return { };
    3038 }
    3039 
    3040 auto AirIRGenerator::addCatchAllToUnreachable(ControlType&) -> PartialResult
    3041 {
    3042     RELEASE_ASSERT_NOT_REACHED();
    3043     return { };
    3044 }
    3045 
    3046 auto AirIRGenerator::addDelegate(ControlType&, ControlType&) -> PartialResult
    3047 {
    3048     RELEASE_ASSERT_NOT_REACHED();
    3049     return { };
    3050 }
    3051 
    3052 auto AirIRGenerator::addDelegateToUnreachable(ControlType&, ControlType&) -> PartialResult
    3053 {
    3054     RELEASE_ASSERT_NOT_REACHED();
    3055     return { };
    3056 }
    3057 
    3058 auto AirIRGenerator::addThrow(unsigned exceptionIndex, Vector<ExpressionType>&, Stack&) -> PartialResult
    3059 {
    3060     UNUSED_PARAM(exceptionIndex);
    3061     return { };
    3062 }
    3063 
    3064 auto AirIRGenerator::addRethrow(unsigned, ControlType&) -> PartialResult
    3065 {
     3171auto AirIRGenerator::addTry(BlockSignature signature, Stack& enclosingStack, ControlType& result, Stack& newStack) -> PartialResult
     3172{
     3173    ++m_tryCatchDepth;
     3174
     3175    BasicBlock* continuation = m_code.addBlock();
     3176    splitStack(signature, enclosingStack, newStack);
     3177    result = ControlData(origin(), signature, tmpsForSignature(signature), BlockType::Try, continuation, ++m_callSiteIndex, m_tryCatchDepth);
     3178    return { };
     3179}
     3180
     3181auto AirIRGenerator::addCatch(unsigned exceptionIndex, const Signature& signature, Stack& currentStack, ControlType& data, ResultList& results) -> PartialResult
     3182{
     3183    unifyValuesWithBlock(currentStack, data.results);
     3184    append(Jump);
     3185    m_currentBlock->setSuccessors(data.continuation);
     3186    return addCatchToUnreachable(exceptionIndex, signature, data, results);
     3187}
     3188
     3189auto AirIRGenerator::addCatchAll(Stack& currentStack, ControlType& data) -> PartialResult
     3190{
     3191    unifyValuesWithBlock(currentStack, data.results);
     3192    append(Jump);
     3193    m_currentBlock->setSuccessors(data.continuation);
     3194    return addCatchAllToUnreachable(data);
     3195}
     3196
     3197auto AirIRGenerator::addCatchToUnreachable(unsigned exceptionIndex, const Signature& signature, ControlType& data, ResultList& results) -> PartialResult
     3198{
     3199    Tmp buffer = emitCatchImpl(CatchKind::Catch, data, exceptionIndex);
     3200    for (unsigned i = 0; i < signature.argumentCount(); ++i) {
     3201        Type type = signature.argument(i);
     3202        TypedTmp tmp = tmpForType(type);
     3203        emitLoad(buffer, i * sizeof(uint64_t), tmp);
     3204        results.append(tmp);
     3205    }
     3206    return { };
     3207}
     3208
     3209auto AirIRGenerator::addCatchAllToUnreachable(ControlType& data) -> PartialResult
     3210{
     3211    emitCatchImpl(CatchKind::CatchAll, data);
     3212    return { };
     3213}
     3214
     3215Tmp AirIRGenerator::emitCatchImpl(CatchKind kind, ControlType& data, unsigned exceptionIndex)
     3216{
     3217    m_currentBlock = m_code.addBlock();
     3218    m_catchEntrypoints.append(m_currentBlock);
     3219
     3220    if (ControlType::isTry(data)) {
     3221        if (kind == CatchKind::Catch)
     3222            data.convertTryToCatch(++m_callSiteIndex, g64());
     3223        else
     3224            data.convertTryToCatchAll(++m_callSiteIndex, g64());
     3225    }
     3226    // We convert from "try" to "catch" ControlType above. This doesn't
     3227    // happen if ControlType is already a "catch". This can happen when
     3228    // we have multiple catches like "try {} catch(A){} catch(B){}...CatchAll(E){}".
     3229    // We just convert the first ControlType to a catch, then the others will
     3230    // use its fields.
     3231    ASSERT(ControlType::isAnyCatch(data));
     3232
     3233    HandlerType handlerType = kind == CatchKind::Catch ? HandlerType::Catch : HandlerType::CatchAll;
     3234    m_exceptionHandlers.append({ handlerType, data.tryStart(), data.tryEnd(), 0, m_tryCatchDepth, exceptionIndex });
     3235
     3236    restoreWebAssemblyGlobalState(RestoreCachedStackLimit::Yes, m_info.memory, instanceValue(), m_currentBlock);
     3237
     3238    unsigned indexInBuffer = 0;
     3239    auto loadFromScratchBuffer = [&] (TypedTmp result) {
     3240        size_t offset = sizeof(uint64_t) * indexInBuffer;
     3241        ++indexInBuffer;
     3242        Tmp bufferPtr = Tmp(GPRInfo::argumentGPR0);
     3243        emitLoad(bufferPtr, offset, result);
     3244    };
     3245    forEachLiveValue([&] (TypedTmp tmp) {
     3246        // We set our current ControlEntry's exception below after the patchpoint, it's
     3247        // not in the incoming buffer of live values.
     3248        auto toIgnore = data.exception();
     3249        if (tmp.tmp() != toIgnore.tmp())
     3250            loadFromScratchBuffer(tmp);
     3251    });
     3252
     3253    B3::PatchpointValue* patch = addPatchpoint(m_proc.addTuple({ B3::pointerType(), B3::pointerType() }));
     3254    patch->effects.exitsSideways = true;
     3255    patch->clobber(RegisterSet::macroScratchRegisters());
     3256    RegisterSet clobberLate = RegisterSet::volatileRegistersForJSCall();
     3257    clobberLate.add(GPRInfo::argumentGPR0);
     3258    patch->clobberLate(clobberLate);
     3259    patch->resultConstraints.append(B3::ValueRep::reg(GPRInfo::returnValueGPR));
     3260    patch->resultConstraints.append(B3::ValueRep::reg(GPRInfo::returnValueGPR2));
     3261    patch->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     3262        AllowMacroScratchRegisterUsage allowScratch(jit);
     3263        jit.move(params[2].gpr(), GPRInfo::argumentGPR0);
     3264        CCallHelpers::Call call = jit.call(OperationPtrTag);
     3265        jit.addLinkTask([call] (LinkBuffer& linkBuffer) {
     3266            linkBuffer.link(call, FunctionPtr<OperationPtrTag>(operationWasmRetrieveAndClearExceptionIfCatchable));
     3267        });
     3268    });
     3269
     3270    Tmp exception = Tmp(GPRInfo::returnValueGPR);
     3271    Tmp buffer = Tmp(GPRInfo::returnValueGPR2);
     3272    emitPatchpoint(m_currentBlock, patch, Vector<Tmp, 8>::from(exception, buffer), Vector<ConstrainedTmp, 1>::from(instanceValue()));
     3273    append(Move, exception, data.exception());
     3274
     3275    return buffer;
     3276}
     3277
     3278auto AirIRGenerator::addDelegate(ControlType& target, ControlType& data) -> PartialResult
     3279{
     3280    return addDelegateToUnreachable(target, data);
     3281}
     3282
     3283auto AirIRGenerator::addDelegateToUnreachable(ControlType& target, ControlType& data) -> PartialResult
     3284{
     3285    unsigned targetDepth = 0;
     3286    if (ControlType::isTry(target))
     3287        targetDepth = target.tryDepth();
     3288
     3289    m_exceptionHandlers.append({ HandlerType::Delegate, data.tryStart(), ++m_callSiteIndex, 0, m_tryCatchDepth, targetDepth });
     3290    return { };
     3291}
     3292
     3293auto AirIRGenerator::addThrow(unsigned exceptionIndex, Vector<ExpressionType>& args, Stack&) -> PartialResult
     3294{
     3295    B3::PatchpointValue* patch = addPatchpoint(B3::Void);
     3296    patch->effects.terminal = true;
     3297    patch->clobber(RegisterSet::volatileRegistersForJSCall());
     3298
     3299    Vector<ConstrainedTmp, 8> patchArgs;
     3300    patchArgs.append(ConstrainedTmp(instanceValue(), B3::ValueRep::reg(GPRInfo::argumentGPR0)));
     3301    patchArgs.append(ConstrainedTmp(Tmp(GPRInfo::callFrameRegister), B3::ValueRep::reg(GPRInfo::argumentGPR1)));
     3302    for (unsigned i = 0; i < args.size(); ++i)
     3303        patchArgs.append(ConstrainedTmp(args[i], B3::ValueRep::stackArgument(i * sizeof(EncodedJSValue))));
     3304
     3305    PatchpointExceptionHandle handle = preparePatchpointForExceptions(patch, patchArgs);
     3306
     3307    patch->setGenerator([this, exceptionIndex, handle] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     3308        AllowMacroScratchRegisterUsage allowScratch(jit);
     3309        handle.generate(jit, params, this);
     3310        emitThrowImpl(jit, exceptionIndex);
     3311    });
     3312
     3313    emitPatchpoint(m_currentBlock, patch, Tmp(), WTFMove(patchArgs));
     3314
     3315    return { };
     3316}
     3317
     3318auto AirIRGenerator::addRethrow(unsigned, ControlType& data) -> PartialResult
     3319{
     3320    B3::PatchpointValue* patch = addPatchpoint(B3::Void);
     3321    patch->clobber(RegisterSet::volatileRegistersForJSCall());
     3322    patch->effects.terminal = true;
     3323
     3324    Vector<ConstrainedTmp, 3> patchArgs;
     3325    patchArgs.append(ConstrainedTmp(instanceValue(), B3::ValueRep::reg(GPRInfo::argumentGPR0)));
     3326    patchArgs.append(ConstrainedTmp(Tmp(GPRInfo::callFrameRegister), B3::ValueRep::reg(GPRInfo::argumentGPR1)));
     3327    patchArgs.append(ConstrainedTmp(data.exception(), B3::ValueRep::reg(GPRInfo::argumentGPR2)));
     3328
     3329    PatchpointExceptionHandle handle = preparePatchpointForExceptions(patch, patchArgs);
     3330    patch->setGenerator([this, handle] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     3331        AllowMacroScratchRegisterUsage allowScratch(jit);
     3332        handle.generate(jit, params, this);
     3333        emitRethrowImpl(jit);
     3334    });
     3335
     3336    emitPatchpoint(m_currentBlock, patch, Tmp(), WTFMove(patchArgs));
     3337
    30663338    return { };
    30673339}
     
    32103482        append(data.special, Jump);
    32113483        data.special->setSuccessors(m_currentBlock);
    3212     }
     3484    } else if (data.blockType() == BlockType::Try || data.blockType() == BlockType::Catch)
     3485        --m_tryCatchDepth;
    32133486
    32143487    if (data.blockType() == BlockType::Loop) {
     
    32343507}
    32353508
    3236 B3::PatchpointValue* AirIRGenerator::emitCallPatchpoint(BasicBlock* block, const Signature& signature, const ResultList& results, const Vector<TypedTmp>& args, Vector<ConstrainedTmp>&& patchArgs)
     3509std::pair<B3::PatchpointValue*, PatchpointExceptionHandle> AirIRGenerator::emitCallPatchpoint(BasicBlock* block, const Signature& signature, const ResultList& results, const Vector<TypedTmp>& args, Vector<ConstrainedTmp> patchArgs)
    32373510{
    32383511    auto* patchpoint = addPatchpoint(toB3ResultType(&signature));
     
    32593532        patchpoint->resultConstraints = WTFMove(resultConstraints);
    32603533    }
     3534    PatchpointExceptionHandle exceptionHandle = preparePatchpointForExceptions(patchpoint, patchArgs);
    32613535    emitPatchpoint(block, patchpoint, results, WTFMove(patchArgs));
    3262     return patchpoint;
     3536    return { patchpoint, exceptionHandle };
    32633537}
    32643538
     
    32963570
    32973571        {
    3298             auto* patchpoint = emitCallPatchpoint(isWasmBlock, signature, results, args);
     3572            auto pair = emitCallPatchpoint(isWasmBlock, signature, results, args);
     3573            auto* patchpoint = pair.first;
     3574            auto exceptionHandle = pair.second;
    32993575            // We need to clobber all potential pinned registers since we might be leaving the instance.
    33003576            // We pessimistically assume we could be calling to something that is bounds checking.
     
    33023578            patchpoint->clobberLate(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
    33033579
    3304             patchpoint->setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     3580            patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    33053581                AllowMacroScratchRegisterUsage allowScratch(jit);
     3582                exceptionHandle.generate(jit, params, this);
    33063583                CCallHelpers::Call call = jit.threadSafePatchableNearCall();
    33073584                jit.addLinkTask([unlinkedWasmToWasmCalls, call, functionIndex] (LinkBuffer& linkBuffer) {
     
    33223599            Vector<ConstrainedTmp> jumpArgs;
    33233600            jumpArgs.append({ jumpDestination, B3::ValueRep::SomeRegister });
    3324             auto* patchpoint = emitCallPatchpoint(isEmbedderBlock, signature, results, args, WTFMove(jumpArgs));
     3601            auto pair = emitCallPatchpoint(isEmbedderBlock, signature, results, args, WTFMove(jumpArgs));
     3602            auto* patchpoint = pair.first;
     3603            auto exceptionHandle = pair.second;
     3604
    33253605            // We need to clobber all potential pinned registers since we might be leaving the instance.
    33263606            // We pessimistically assume we could be calling to something that is bounds checking.
    33273607            // FIXME: We shouldn't have to do this: https://bugs.webkit.org/show_bug.cgi?id=172181
    33283608            patchpoint->clobberLate(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
    3329             patchpoint->setGenerator([] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     3609            patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    33303610                AllowMacroScratchRegisterUsage allowScratch(jit);
     3611                exceptionHandle.generate(jit, params, this);
    33313612                jit.call(params[params.proc().resultCount(params.value()->type())].gpr(), WasmEntryPtrTag);
    33323613            });
     
    33403621        restoreWebAssemblyGlobalState(RestoreCachedStackLimit::Yes, m_info.memory, currentInstance, continuation);
    33413622    } else {
    3342         auto* patchpoint = emitCallPatchpoint(m_currentBlock, signature, results, args);
     3623        auto pair = emitCallPatchpoint(m_currentBlock, signature, results, args);
     3624        auto* patchpoint = pair.first;
     3625        auto exceptionHandle = pair.second;
    33433626        // We need to clobber the size register since the LLInt always bounds checks
    33443627        if (m_mode == MemoryMode::Signaling || m_info.memory.isShared())
    33453628            patchpoint->clobberLate(RegisterSet { PinnedRegisterInfo::get().boundsCheckingSizeRegister });
    3346         patchpoint->setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
     3629        patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    33473630            AllowMacroScratchRegisterUsage allowScratch(jit);
     3631            exceptionHandle.generate(jit, params, this);
    33483632            CCallHelpers::Call call = jit.threadSafePatchableNearCall();
    33493633            jit.addLinkTask([unlinkedWasmToWasmCalls, call, functionIndex] (LinkBuffer& linkBuffer) {
     
    35243808        results.append(tmpForType(signature.returnType(i)));
    35253809
    3526     auto* patchpoint = emitCallPatchpoint(m_currentBlock, signature, results, args, WTFMove(extraArgs));
     3810    auto pair = emitCallPatchpoint(m_currentBlock, signature, results, args, WTFMove(extraArgs));
     3811    auto* patchpoint = pair.first;
     3812    auto exceptionHandle = pair.second;
    35273813
    35283814    // We need to clobber all potential pinned registers since we might be leaving the instance.
     
    35363822    patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    35373823        AllowMacroScratchRegisterUsage allowScratch(jit);
     3824        exceptionHandle.generate(jit, params, this);
    35383825        jit.call(params[params.proc().resultCount(params.value()->type())].gpr(), WasmEntryPtrTag);
    35393826    });
     
    35963883    compilationContext.wasmEntrypointJIT = makeUnique<CCallHelpers>();
    35973884
    3598     B3::Procedure procedure;
     3885    compilationContext.procedure = makeUnique<B3::Procedure>();
     3886    auto& procedure = *compilationContext.procedure;
    35993887    Code& code = procedure.code();
    36003888
     
    36163904    WASM_FAIL_IF_HELPER_FAILS(parser.parse());
    36173905
     3906    irGenerator.finalizeEntrypoints();
    36183907
    36193908    for (BasicBlock* block : code) {
     
    36223911    }
    36233912
    3624     {
    3625         if (UNLIKELY(shouldDumpIRAtEachPhase(B3::AirMode))) {
    3626             dataLogLn("Generated patchpoints");
    3627             for (B3::PatchpointValue** patch : irGenerator.patchpoints())
    3628                 dataLogLn(deepDump(procedure, *patch));
    3629         }
    3630 
    3631         B3::Air::prepareForGeneration(code);
    3632         B3::Air::generate(code, *compilationContext.wasmEntrypointJIT);
    3633         compilationContext.wasmEntrypointByproducts = procedure.releaseByproducts();
    3634         result->entrypoint.calleeSaveRegisters = code.calleeSaveRegisterAtOffsetList();
    3635     }
     3913    if (UNLIKELY(shouldDumpIRAtEachPhase(B3::AirMode))) {
     3914        dataLogLn("Generated patchpoints");
     3915        for (B3::PatchpointValue** patch : irGenerator.patchpoints())
     3916            dataLogLn(deepDump(procedure, *patch));
     3917    }
     3918
     3919    B3::Air::prepareForGeneration(code);
     3920    B3::Air::generate(code, *compilationContext.wasmEntrypointJIT);
     3921
     3922    compilationContext.wasmEntrypointByproducts = procedure.releaseByproducts();
     3923    result->entrypoint.calleeSaveRegisters = code.calleeSaveRegisterAtOffsetList();
     3924    result->stackmaps = irGenerator.takeStackmaps();
     3925    result->exceptionHandlers = irGenerator.takeExceptionHandlers();
    36363926
    36373927    return result;
     
    51795469}
    51805470
     5471template <size_t inlineCapacity>
     5472PatchpointExceptionHandle AirIRGenerator::preparePatchpointForExceptions(B3::PatchpointValue* patch, Vector<ConstrainedTmp, inlineCapacity>& args)
     5473{
     5474    ++m_callSiteIndex;
     5475    if (!m_tryCatchDepth)
     5476        return { };
     5477
     5478    unsigned numLiveValues = 0;
     5479    forEachLiveValue([&] (Tmp tmp) {
     5480        ++numLiveValues;
     5481        args.append(ConstrainedTmp(tmp, B3::ValueRep::LateColdAny));
     5482    });
     5483
     5484    patch->effects.exitsSideways = true;
     5485
     5486    return PatchpointExceptionHandle { m_callSiteIndex, numLiveValues };
     5487}
     5488
    51815489} } // namespace JSC::Wasm
    51825490
  • trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp

    r287738 r287801  
    11/*
    2  * Copyright (C) 2016-2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2016-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5858#include "WasmExceptionType.h"
    5959#include "WasmFunctionParser.h"
     60#include "WasmIRGeneratorHelpers.h"
    6061#include "WasmInstance.h"
    6162#include "WasmMemory.h"
     
    8788}
    8889}
    89 
    90 class B3IRGenerator;
    91 struct PatchpointExceptionHandle {
    92     void generate(CCallHelpers&, const B3::StackmapGenerationParams&, B3IRGenerator*) const;
    93 
    94     static constexpr unsigned s_invalidCallSiteIndex =  std::numeric_limits<unsigned>::max();
    95 
    96     unsigned m_callSiteIndex { s_invalidCallSiteIndex };
    97     unsigned m_numLiveValues;
    98 };
    9990
    10091class B3IRGenerator {
     
    579570};
    580571
    581 void PatchpointExceptionHandle::generate(CCallHelpers& jit, const B3::StackmapGenerationParams& params, B3IRGenerator* generator) const
    582 {
    583     if (m_callSiteIndex == s_invalidCallSiteIndex)
    584         return;
    585 
    586     StackMap values(m_numLiveValues);
    587     unsigned paramsOffset = params.size() - m_numLiveValues;
    588     unsigned childrenOffset = params.value()->numChildren() - m_numLiveValues;
    589     for (unsigned i = 0; i < m_numLiveValues; ++i)
    590         values[i] = OSREntryValue(params[i + paramsOffset], params.value()->child(i + childrenOffset)->type());
    591 
    592     generator->addStackMap(m_callSiteIndex, WTFMove(values));
    593     jit.store32(CCallHelpers::TrustedImm32(m_callSiteIndex), CCallHelpers::tagFor(CallFrameSlot::argumentCountIncludingThis));
    594 }
    595 
    596572// Memory accesses in WebAssembly have unsigned 32-bit offsets, whereas they have signed 32-bit offsets in B3.
    597573int32_t B3IRGenerator::fixupPointerPlusOffset(Value*& ptr, uint32_t offset)
     
    858834}
    859835
    860 static void buildEntryBufferForCatch(Probe::Context& context)
    861 {
    862     CallFrame* callFrame = context.fp<CallFrame*>();
    863     CallSiteIndex callSiteIndex = callFrame->callSiteIndex();
    864     OptimizingJITCallee* callee = bitwise_cast<OptimizingJITCallee*>(callFrame->callee().asWasmCallee());
    865     const StackMap& stackmap = callee->stackmap(callSiteIndex);
    866     VM* vm = context.gpr<VM*>(GPRInfo::regT0);
    867     uint64_t* buffer = vm->wasmContext.scratchBufferForSize(stackmap.size() * 8);
    868     loadValuesIntoBuffer(context, stackmap, buffer);
    869 
    870     context.gpr(GPRInfo::argumentGPR0) = bitwise_cast<uintptr_t>(buffer);
    871 }
    872 
    873836void B3IRGenerator::insertEntrySwitch()
    874837{
     
    877840    Ref<B3::Air::PrologueGenerator> catchPrologueGenerator = createSharedTask<B3::Air::PrologueGeneratorFunction>([] (CCallHelpers& jit, B3::Air::Code& code) {
    878841        AllowMacroScratchRegisterUsage allowScratch(jit);
    879 
    880         jit.emitGetFromCallFrameHeaderPtr(CallFrameSlot::callee, GPRInfo::regT0);
    881         {
    882             // FIXME: Handling precise allocations in WasmB3IRGenerator catch entrypoints might be unnecessary
    883             // https://bugs.webkit.org/show_bug.cgi?id=231213
    884             auto preciseAllocationCase = jit.branchTestPtr(CCallHelpers::NonZero, GPRInfo::regT0, CCallHelpers::TrustedImm32(PreciseAllocation::halfAlignment));
    885             jit.andPtr(CCallHelpers::TrustedImmPtr(MarkedBlock::blockMask), GPRInfo::regT0);
    886             jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, MarkedBlock::offsetOfFooter + MarkedBlock::Footer::offsetOfVM()), GPRInfo::regT0);
    887             auto loadedCase = jit.jump();
    888 
    889             preciseAllocationCase.link(&jit);
    890             jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, PreciseAllocation::offsetOfWeakSet() + WeakSet::offsetOfVM() - PreciseAllocation::headerSize()), GPRInfo::regT0);
    891 
    892             loadedCase.link(&jit);
    893         }
    894         jit.restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(GPRInfo::regT0, GPRInfo::regT3);
    895 
    896         jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, VM::calleeForWasmCatchOffset()), GPRInfo::regT3);
    897         jit.storePtr(CCallHelpers::TrustedImmPtr(nullptr), CCallHelpers::Address(GPRInfo::regT0, VM::calleeForWasmCatchOffset()));
    898         jit.emitPutToCallFrameHeader(GPRInfo::regT3, CallFrameSlot::callee);
    899 
    900         jit.load64(CCallHelpers::Address(GPRInfo::regT0, VM::callFrameForCatchOffset()), GPRInfo::callFrameRegister);
    901         jit.storePtr(CCallHelpers::TrustedImmPtr(nullptr), CCallHelpers::Address(GPRInfo::regT0, VM::callFrameForCatchOffset()));
    902 
    903         jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, CallFrameSlot::thisArgument * sizeof(Register)), GPRInfo::regT3);
    904         jit.loadPtr(CCallHelpers::Address(GPRInfo::regT3, JSWebAssemblyInstance::offsetOfInstance()), GPRInfo::regT3);
    905         jit.storeWasmContextInstance(GPRInfo::regT3);
    906 
    907         jit.probe(tagCFunction<JITProbePtrTag>(buildEntryBufferForCatch), nullptr);
    908 
    909         jit.addPtr(CCallHelpers::TrustedImm32(-code.frameSize()), GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister);
     842        emitCatchPrologueShared(code, jit);
    910843    });
    911844
     
    26532586            data.convertTryToCatchAll(++m_callSiteIndex, m_proc.addVariable(pointerType()));
    26542587    }
     2588    // We convert from "try" to "catch" ControlType above. This doesn't
     2589    // happen if ControlType is already a "catch". This can happen when
     2590    // we have multiple catches like "try {} catch(A){} catch(B){}...CatchAll(E){}"
     2591    ASSERT(ControlType::isAnyCatch(data));
    26552592
    26562593    HandlerType handlerType = kind == CatchKind::Catch ? HandlerType::Catch : HandlerType::CatchAll;
     
    27232660    patch->setGenerator([this, exceptionIndex, handle] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    27242661        AllowMacroScratchRegisterUsage allowScratch(jit);
    2725         GPRReg scratch = GPRInfo::nonPreservedNonArgumentGPR0;
    27262662        handle.generate(jit, params, this);
    2727 
    2728         jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0, Instance::offsetOfOwner()), scratch);
    2729         {
    2730             auto preciseAllocationCase = jit.branchTestPtr(CCallHelpers::NonZero, scratch, CCallHelpers::TrustedImm32(PreciseAllocation::halfAlignment));
    2731             jit.andPtr(CCallHelpers::TrustedImmPtr(MarkedBlock::blockMask), scratch);
    2732             jit.loadPtr(CCallHelpers::Address(scratch, MarkedBlock::offsetOfFooter + MarkedBlock::Footer::offsetOfVM()), scratch);
    2733             auto loadedCase = jit.jump();
    2734 
    2735             preciseAllocationCase.link(&jit);
    2736             jit.loadPtr(CCallHelpers::Address(scratch, PreciseAllocation::offsetOfWeakSet() + WeakSet::offsetOfVM() - PreciseAllocation::headerSize()), scratch);
    2737 
    2738             loadedCase.link(&jit);
    2739         }
    2740         jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(scratch);
    2741 
    2742         jit.move(MacroAssembler::TrustedImm32(exceptionIndex), GPRInfo::argumentGPR2);
    2743         jit.move(MacroAssembler::stackPointerRegister, GPRInfo::argumentGPR3);
    2744         CCallHelpers::Call call = jit.call(OperationPtrTag);
    2745         jit.farJump(GPRInfo::returnValueGPR, ExceptionHandlerPtrTag);
    2746         jit.addLinkTask([call] (LinkBuffer& linkBuffer) {
    2747             linkBuffer.link(call, FunctionPtr<OperationPtrTag>(operationWasmThrow));
    2748         });
     2663        emitThrowImpl(jit, exceptionIndex);
    27492664    });
    27502665    m_currentBlock->append(patch);
     
    27642679    patch->setGenerator([this, handle] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    27652680        AllowMacroScratchRegisterUsage allowScratch(jit);
    2766 
    2767         GPRReg scratch = GPRInfo::nonPreservedNonArgumentGPR0;
    2768         jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0, Instance::offsetOfOwner()), scratch);
    2769         {
    2770             auto preciseAllocationCase = jit.branchTestPtr(CCallHelpers::NonZero, scratch, CCallHelpers::TrustedImm32(PreciseAllocation::halfAlignment));
    2771             jit.andPtr(CCallHelpers::TrustedImmPtr(MarkedBlock::blockMask), scratch);
    2772             jit.loadPtr(CCallHelpers::Address(scratch, MarkedBlock::offsetOfFooter + MarkedBlock::Footer::offsetOfVM()), scratch);
    2773             auto loadedCase = jit.jump();
    2774 
    2775             preciseAllocationCase.link(&jit);
    2776             jit.loadPtr(CCallHelpers::Address(scratch, PreciseAllocation::offsetOfWeakSet() + WeakSet::offsetOfVM() - PreciseAllocation::headerSize()), scratch);
    2777 
    2778             loadedCase.link(&jit);
    2779         }
    2780         jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(scratch);
    2781 
    27822681        handle.generate(jit, params, this);
    2783         CCallHelpers::Call call = jit.call(OperationPtrTag);
    2784         jit.farJump(GPRInfo::returnValueGPR, ExceptionHandlerPtrTag);
    2785         jit.addLinkTask([call] (LinkBuffer& linkBuffer) {
    2786             linkBuffer.link(call, FunctionPtr<OperationPtrTag>(operationWasmRethrow));
    2787         });
     2682        emitRethrowImpl(jit);
    27882683    });
    27892684    m_currentBlock->append(patch);
     
    33213216}
    33223217
    3323 void computeExceptionHandlerLocations(Vector<CodeLocationLabel<ExceptionHandlerPtrTag>>& handlers, const InternalFunction* function, const CompilationContext& context, LinkBuffer& linkBuffer)
    3324 {
    3325     if (!context.procedure)
    3326         return;
    3327 
    3328     unsigned entrypointIndex = 0;
    3329     unsigned numEntrypoints = context.procedure->numEntrypoints();
    3330     for (const UnlinkedHandlerInfo& handlerInfo : function->exceptionHandlers) {
    3331         RELEASE_ASSERT(entrypointIndex < numEntrypoints);
    3332         if (handlerInfo.m_type == HandlerType::Delegate) {
    3333             handlers.append({ });
    3334             continue;
    3335         }
    3336 
    3337         ++entrypointIndex;
    3338         handlers.append(linkBuffer.locationOf<ExceptionHandlerPtrTag>(context.procedure->code().entrypointLabel(entrypointIndex)));
    3339     }
    3340     RELEASE_ASSERT(entrypointIndex == numEntrypoints - 1);
    3341 }
    3342 
    33433218// Custom wasm ops. These are the ones too messy to do in wasm.json.
    33443219
  • trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h

    r286920 r287801  
    6060Expected<std::unique_ptr<InternalFunction>, String> parseAndCompile(CompilationContext&, const FunctionData&, const Signature&, Vector<UnlinkedWasmToWasmCall>&, unsigned& osrEntryScratchBufferSize, const ModuleInformation&, MemoryMode, CompilationMode, uint32_t functionIndex, uint32_t loopIndexForOSREntry, TierUpCount* = nullptr);
    6161
    62 void computeExceptionHandlerLocations(Vector<CodeLocationLabel<ExceptionHandlerPtrTag>>& handlers, const InternalFunction*, const CompilationContext&, LinkBuffer&);
    6362void computePCToCodeOriginMap(CompilationContext&, LinkBuffer&);
    6463
  • trunk/Source/JavaScriptCore/wasm/WasmBBQPlan.cpp

    r287221 r287801  
    3737#include "WasmCalleeGroup.h"
    3838#include "WasmCalleeRegistry.h"
     39#include "WasmIRGeneratorHelpers.h"
    3940#include "WasmSignatureInlines.h"
    4041#include "WasmTierUpCount.h"
     
    204205    if (Options::webAssemblyBBQAirModeThreshold() && m_moduleInformation->codeSectionSize >= Options::webAssemblyBBQAirModeThreshold())
    205206        forceUsingB3 = true;
    206     else if (!m_moduleInformation->m_functionDoesNotUseExceptions.quickGet(functionIndex))
    207         forceUsingB3 = true;
    208207    else if (!Options::wasmBBQUsesAir())
    209208        forceUsingB3 = true;
  • trunk/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp

    r287459 r287801  
    559559    RELEASE_ASSERT(usedBuffer.capacity() == oldCapacity);
    560560    *threadSpecific = WTFMove(usedBuffer);
    561 
    562     if (!m_usesExceptions)
    563         m_info.m_functionDoesNotUseExceptions.quickSet(m_functionIndex);
    564561
    565562    return WTFMove(m_codeBlock);
  • trunk/Source/JavaScriptCore/wasm/WasmModuleInformation.h

    r286992 r287801  
    120120    BitVector m_declaredFunctions;
    121121    BitVector m_declaredExceptions;
    122     BitVector m_functionDoesNotUseExceptions;
    123122    mutable BitVector m_referencedFunctions;
    124123};
  • trunk/Source/JavaScriptCore/wasm/WasmOMGPlan.cpp

    r287221 r287801  
    3434#include "WasmCallee.h"
    3535#include "WasmCalleeRegistry.h"
     36#include "WasmIRGeneratorHelpers.h"
    3637#include "WasmNameSection.h"
    3738#include "WasmSignatureInlines.h"
  • trunk/Source/JavaScriptCore/wasm/WasmOSREntryPlan.cpp

    r287379 r287801  
    3333#include "WasmB3IRGenerator.h"
    3434#include "WasmCallee.h"
     35#include "WasmIRGeneratorHelpers.h"
    3536#include "WasmMachineThreads.h"
    3637#include "WasmNameSection.h"
  • trunk/Source/JavaScriptCore/wasm/WasmStreamingParser.cpp

    r283852 r287801  
    118118    m_functionIndex = 0;
    119119    m_codeOffset = m_offset;
    120     m_info->m_functionDoesNotUseExceptions.ensureSize(functionCount);
    121120
    122121    WASM_PARSER_FAIL_IF(functionCount == std::numeric_limits<uint32_t>::max(), "Code section's count is too big ", functionCount);
Note: See TracChangeset for help on using the changeset viewer.