tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 36aa80e5a65150d11dfb757f8597e192c1d5e096
parent 841cd855f097aed7ea64aa27a43b46840fca96d4
Author: Ryan Hunt <rhunt@eqrion.net>
Date:   Tue, 18 Nov 2025 16:57:29 +0000

Bug 1990931 - wasm: Add interrupt check to function prologues and use instead of stack limit trick. r=yury

1. StackMaps::finalize is split into two operations. 'finalize' deduplicates the stack map and
   gives the final stack map address to use. 'add' associates a code offset with the map. This
   is needed for resumable OOL traps where the stack map generation happens before we know the
   code offset.
2. Baseline and Ion generate an explicit interrupt check in their prologues.
3. StackOverflow traps are no longer resumable and don't check the flag.
4. The stackLimit_ field is no longer atomic.
5. JIT import exits no longer need stack maps because their stack overflow check cannot
   resume.

Differential Revision: https://phabricator.services.mozilla.com/D271456

Diffstat:
Mjs/src/jit-test/tests/wasm/simd/const-arm64-vixl-codegen.js | 2+-
Mjs/src/jit/CodeGenerator.cpp | 59++++++++++++++++++++++++++++++++++++++---------------------
Mjs/src/jit/shared/CodeGenerator-shared.cpp | 6+++++-
Mjs/src/jit/shared/CodeGenerator-shared.h | 3++-
Mjs/src/wasm/WasmBCClass.h | 9+++------
Mjs/src/wasm/WasmBCFrame.cpp | 38++++++++++++++++++++------------------
Mjs/src/wasm/WasmBCFrame.h | 7+++----
Mjs/src/wasm/WasmBaselineCompile.cpp | 66+++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mjs/src/wasm/WasmBuiltins.cpp | 8--------
Mjs/src/wasm/WasmGC.cpp | 2+-
Mjs/src/wasm/WasmGC.h | 35++++++++++++++++++++++++-----------
Mjs/src/wasm/WasmInstance.cpp | 31+++++++------------------------
Mjs/src/wasm/WasmInstance.h | 8+++-----
Mjs/src/wasm/WasmRealm.cpp | 2+-
Mjs/src/wasm/WasmStubs.cpp | 39+--------------------------------------
15 files changed, 158 insertions(+), 157 deletions(-)

diff --git a/js/src/jit-test/tests/wasm/simd/const-arm64-vixl-codegen.js b/js/src/jit-test/tests/wasm/simd/const-arm64-vixl-codegen.js @@ -9,7 +9,7 @@ var prefix = `${lead}sub sp, sp, #0x.. \\(..\\) ${lead}str x23, \\[sp, #..\\]`; var suffix = -`${lead}b #\\+0x8 \\(addr 0x.*\\) +`${lead}b #\\+0x14 \\(addr 0x.*\\) ${lead}brk #0xf000`; for ( let [bits, expected, values] of [ diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp @@ -7957,7 +7957,7 @@ void CodeGenerator::visitUnreachableResultT(LUnreachableResultT* lir) { void CodeGenerator::visitCheckOverRecursed(LCheckOverRecursed* lir) { // If we don't push anything on the stack, skip the check. - if (omitOverRecursedCheck()) { + if (omitOverRecursedStackCheck()) { return; } @@ -17139,29 +17139,46 @@ bool CodeGenerator::generateWasm(wasm::CallIndirectId callIndirectId, return decoder->fail(decoder->beginOffset(), "stack frame is too large"); } - if (omitOverRecursedCheck()) { + if (omitOverRecursedStackCheck()) { masm.reserveStack(frameSize()); - } else { - std::pair<CodeOffset, uint32_t> pair = - masm.wasmReserveStackChecked(frameSize(), entryTrapSiteDesc); - CodeOffset trapInsnOffset = pair.first; - size_t nBytesReservedBeforeTrap = pair.second; - - wasm::StackMap* functionEntryStackMap = nullptr; - if (!CreateStackMapForFunctionEntryTrap( - argTypes, trapExitLayout, trapExitLayoutNumWords, - nBytesReservedBeforeTrap, nInboundStackArgBytes, *stackMaps, - &functionEntryStackMap)) { - return false; - } - // In debug builds, we'll always have a stack map, even if there are no - // refs to track. - MOZ_ASSERT(functionEntryStackMap); + // If we don't need to check the stack for recursion, we definitely don't + // need to check for interrupts. + MOZ_ASSERT(omitOverRecursedInterruptCheck()); + } else { + masm.wasmReserveStackChecked(frameSize(), entryTrapSiteDesc); + + if (!omitOverRecursedInterruptCheck()) { + wasm::StackMap* functionEntryStackMap = nullptr; + if (!CreateStackMapForFunctionEntryTrap( + argTypes, trapExitLayout, trapExitLayoutNumWords, frameSize(), + nInboundStackArgBytes, *stackMaps, &functionEntryStackMap)) { + return false; + } - if (functionEntryStackMap && - !stackMaps->finalize(trapInsnOffset.offset(), functionEntryStackMap)) { - return false; + // In debug builds, we'll always have a stack map, even if there are no + // refs to track. + MOZ_ASSERT(functionEntryStackMap); + + auto* ool = new (alloc()) LambdaOutOfLineCode( + [this, stackMaps, functionEntryStackMap](OutOfLineCode& ool) { + masm.wasmTrap(wasm::Trap::CheckInterrupt, wasm::TrapSiteDesc()); + CodeOffset trapInsnOffset = CodeOffset(masm.currentOffset()); + + if (functionEntryStackMap && + !stackMaps->add(trapInsnOffset.offset(), + functionEntryStackMap)) { + return false; + } + masm.jump(ool.rejoin()); + return true; + }); + + addOutOfLineCode(ool, (const BytecodeSite*)nullptr); + masm.branch32(Assembler::NotEqual, + Address(InstanceReg, wasm::Instance::offsetOfInterrupt()), + Imm32(0), ool->entry()); + masm.bind(ool->rejoin()); } } diff --git a/js/src/jit/shared/CodeGenerator-shared.cpp b/js/src/jit/shared/CodeGenerator-shared.cpp @@ -1030,7 +1030,7 @@ void CodeGeneratorShared::visitOutOfLineTruncateSlow( masm.jump(ool->rejoin()); } -bool CodeGeneratorShared::omitOverRecursedCheck() const { +bool CodeGeneratorShared::omitOverRecursedStackCheck() const { // If the current function makes no calls (which means it isn't recursive) // and it uses only a small amount of stack space, it doesn't need a // stack overflow check. Note that the actual number here is somewhat @@ -1040,6 +1040,10 @@ bool CodeGeneratorShared::omitOverRecursedCheck() const { !gen->needsOverrecursedCheck(); } +bool CodeGeneratorShared::omitOverRecursedInterruptCheck() const { + return !gen->needsOverrecursedCheck(); +} + void CodeGeneratorShared::emitPreBarrier(Address address) { masm.guardedCallPreBarrier(address, MIRType::Value); } diff --git a/js/src/jit/shared/CodeGenerator-shared.h b/js/src/jit/shared/CodeGenerator-shared.h @@ -418,7 +418,8 @@ class CodeGeneratorShared : public LElementVisitor { public: void visitOutOfLineTruncateSlow(OutOfLineTruncateSlow* ool); - bool omitOverRecursedCheck() const; + bool omitOverRecursedStackCheck() const; + bool omitOverRecursedInterruptCheck() const; public: bool isGlobalObject(JSObject* object); diff --git a/js/src/wasm/WasmBCClass.h b/js/src/wasm/WasmBCClass.h @@ -310,6 +310,9 @@ struct BaseCompiler final { // emitted at the end of compilation. Vector<OutOfLineCode*, 8, SystemAllocPolicy> outOfLine_; + // The stack maps for this compilation. + StackMaps* stackMaps_; + // Stack map state. This keeps track of live pointer slots and allows precise // stack maps to be generated at safe points. StackMapGenerator stackMapGenerator_; @@ -954,12 +957,6 @@ struct BaseCompiler final { [[nodiscard]] bool createStackMap( const char* who, HasDebugFrameWithLiveRefs debugFrameWithLiveRefs); - // The most general stackmap construction. - [[nodiscard]] bool createStackMap( - const char* who, const ExitStubMapVector& extras, - uint32_t assemblerOffset, - HasDebugFrameWithLiveRefs debugFrameWithLiveRefs); - //////////////////////////////////////////////////////////// // // Control stack diff --git a/js/src/wasm/WasmBCFrame.cpp b/js/src/wasm/WasmBCFrame.cpp @@ -141,29 +141,27 @@ void BaseLocalIter::operator++(int) { bool BaseCompiler::createStackMap(const char* who) { const ExitStubMapVector noExtras; - return stackMapGenerator_.createStackMap(who, noExtras, masm.currentOffset(), - HasDebugFrameWithLiveRefs::No, stk_); + StackMap* stackMap; + return stackMapGenerator_.createStackMap( + who, noExtras, HasDebugFrameWithLiveRefs::No, stk_, &stackMap) && + (!stackMap || stackMaps_->add(masm.currentOffset(), stackMap)); } bool BaseCompiler::createStackMap(const char* who, CodeOffset assemblerOffset) { const ExitStubMapVector noExtras; - return stackMapGenerator_.createStackMap(who, noExtras, - assemblerOffset.offset(), - HasDebugFrameWithLiveRefs::No, stk_); + StackMap* stackMap; + return stackMapGenerator_.createStackMap( + who, noExtras, HasDebugFrameWithLiveRefs::No, stk_, &stackMap) && + (!stackMap || stackMaps_->add(assemblerOffset.offset(), stackMap)); } bool BaseCompiler::createStackMap( const char* who, HasDebugFrameWithLiveRefs debugFrameWithLiveRefs) { const ExitStubMapVector noExtras; - return stackMapGenerator_.createStackMap(who, noExtras, masm.currentOffset(), - debugFrameWithLiveRefs, stk_); -} - -bool BaseCompiler::createStackMap( - const char* who, const ExitStubMapVector& extras, uint32_t assemblerOffset, - HasDebugFrameWithLiveRefs debugFrameWithLiveRefs) { - return stackMapGenerator_.createStackMap(who, extras, assemblerOffset, - debugFrameWithLiveRefs, stk_); + StackMap* stackMap; + return stackMapGenerator_.createStackMap( + who, noExtras, debugFrameWithLiveRefs, stk_, &stackMap) && + (!stackMap || stackMaps_->add(masm.currentOffset(), stackMap)); } bool MachineStackTracker::cloneTo(MachineStackTracker* dst) { @@ -182,8 +180,12 @@ bool StackMapGenerator::generateStackmapEntriesForTrapExit( } bool StackMapGenerator::createStackMap( - const char* who, const ExitStubMapVector& extras, uint32_t assemblerOffset, - HasDebugFrameWithLiveRefs debugFrameWithLiveRefs, const StkVector& stk) { + const char* who, const ExitStubMapVector& extras, + HasDebugFrameWithLiveRefs debugFrameWithLiveRefs, const StkVector& stk, + wasm::StackMap** result) { + // Always initialize the result value + *result = nullptr; + size_t countedPointers = machineStackTracker.numPtrs() + memRefsOnStk; #ifndef DEBUG // An important optimization. If there are obviously no pointers, as @@ -436,8 +438,8 @@ bool StackMapGenerator::createStackMap( } #endif - // Add the completed map to the running collection thereof. - return stackMaps_->finalize(assemblerOffset, stackMap); + *result = stackMaps_->finalize(stackMap); + return true; } ////////////////////////////////////////////////////////////////////////////// diff --git a/js/src/wasm/WasmBCFrame.h b/js/src/wasm/WasmBCFrame.h @@ -1383,15 +1383,14 @@ struct StackMapGenerator { [[nodiscard]] bool generateStackmapEntriesForTrapExit( const ArgTypeVector& args, ExitStubMapVector* extras); - // Creates a stackmap associated with the instruction denoted by - // |assemblerOffset|, incorporating pointers from the current operand + // Creates a stackmap incorporating pointers from the current operand // stack |stk|, incorporating possible extra pointers in |extra| at the // lower addressed end, and possibly with the associated frame having a // DebugFrame that must be traced, as indicated by |debugFrameWithLiveRefs|. [[nodiscard]] bool createStackMap( const char* who, const ExitStubMapVector& extras, - uint32_t assemblerOffset, - HasDebugFrameWithLiveRefs debugFrameWithLiveRefs, const StkVector& stk); + HasDebugFrameWithLiveRefs debugFrameWithLiveRefs, const StkVector& stk, + wasm::StackMap** result); }; } // namespace wasm diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp @@ -216,6 +216,41 @@ class OutOfLineCode : public TempObject { virtual void generate(MacroAssembler* masm) = 0; }; +class OutOfLineAbortingTrap : public OutOfLineCode { + Trap trap_; + TrapSiteDesc desc_; + + public: + OutOfLineAbortingTrap(Trap trap, const TrapSiteDesc& desc) + : trap_(trap), desc_(desc) {} + + virtual void generate(MacroAssembler* masm) override { + masm->wasmTrap(trap_, desc_); + MOZ_ASSERT(!rejoin()->bound()); + } +}; + +class OutOfLineResumableTrap : public OutOfLineCode { + Trap trap_; + TrapSiteDesc desc_; + wasm::StackMap* stackMap_; + wasm::StackMaps* stackMaps_; + + public: + OutOfLineResumableTrap(Trap trap, const TrapSiteDesc& desc, + wasm::StackMap* stackMap, wasm::StackMaps* stackMaps) + : trap_(trap), desc_(desc), stackMap_(stackMap), stackMaps_(stackMaps) {} + + virtual void generate(MacroAssembler* masm) override { + masm->wasmTrap(trap_, desc_); + if (stackMap_ && !stackMaps_->add(masm->currentOffset(), stackMap_)) { + masm->setOOM(); + return; + } + masm->jump(rejoin()); + } +}; + OutOfLineCode* BaseCompiler::addOutOfLineCode(OutOfLineCode* ool) { if (!ool || !outOfLine_.append(ool)) { return nullptr; @@ -543,13 +578,23 @@ bool BaseCompiler::beginFunction() { TrapSiteDesc(BytecodeOffset(func_.lineOrBytecode))); ExitStubMapVector extras; - if (!stackMapGenerator_.generateStackmapEntriesForTrapExit(args, &extras)) { + StackMap* functionEntryStackMap; + if (!stackMapGenerator_.generateStackmapEntriesForTrapExit(args, &extras) || + !stackMapGenerator_.createStackMap("stack check", extras, + HasDebugFrameWithLiveRefs::No, stk_, + &functionEntryStackMap)) { return false; } - if (!createStackMap("stack check", extras, masm.currentOffset(), - HasDebugFrameWithLiveRefs::No)) { + + OutOfLineCode* ool = addOutOfLineCode(new (alloc_) OutOfLineResumableTrap( + Trap::CheckInterrupt, trapSiteDesc(), functionEntryStackMap, stackMaps_)); + if (!ool) { return false; } + masm.branch32(Assembler::NotEqual, + Address(InstanceReg, wasm::Instance::offsetOfInterrupt()), + Imm32(0), ool->entry()); + masm.bind(ool->rejoin()); size_t reservedBytes = fr.fixedAllocSize() - masm.framePushed(); MOZ_ASSERT(0 == (reservedBytes % sizeof(void*))); @@ -2014,20 +2059,6 @@ CodeOffset BaseCompiler::callSymbolic(SymbolicAddress callee, // Precondition: sync() -class OutOfLineAbortingTrap : public OutOfLineCode { - Trap trap_; - TrapSiteDesc desc_; - - public: - OutOfLineAbortingTrap(Trap trap, const TrapSiteDesc& desc) - : trap_(trap), desc_(desc) {} - - virtual void generate(MacroAssembler* masm) override { - masm->wasmTrap(trap_, desc_); - MOZ_ASSERT(!rejoin()->bound()); - } -}; - static ReturnCallAdjustmentInfo BuildReturnCallAdjustmentInfo( const FuncType& callerType, const FuncType& calleeType) { return ReturnCallAdjustmentInfo( @@ -12305,6 +12336,7 @@ BaseCompiler::BaseCompiler(const CodeMetadata& codeMeta, decoder_(decoder), iter_(codeMeta, decoder, locals), fr(*masm), + stackMaps_(stackMaps), stackMapGenerator_(stackMaps, trapExitLayout, trapExitLayoutNumWords, *masm), deadCode_(false), diff --git a/js/src/wasm/WasmBuiltins.cpp b/js/src/wasm/WasmBuiltins.cpp @@ -993,18 +993,10 @@ static void* WasmHandleTrap() { case Trap::CheckInterrupt: return CheckInterrupt(cx, activation); case Trap::StackOverflow: { - // Instance::setInterrupt() causes a fake stack overflow. Since - // Instance::setInterrupt() is called racily, it's possible for a real - // stack overflow to trap, followed by a racy call to setInterrupt(). - // Thus, we must check for a real stack overflow first before we - // CheckInterrupt() and possibly resume execution. AutoCheckRecursionLimit recursion(cx); if (!recursion.check(cx)) { return nullptr; } - if (activation->wasmExitInstance()->isInterrupted()) { - return CheckInterrupt(cx, activation); - } ReportTrapError(cx, JSMSG_OVER_RECURSED); return nullptr; } diff --git a/js/src/wasm/WasmGC.cpp b/js/src/wasm/WasmGC.cpp @@ -129,7 +129,7 @@ bool wasm::CreateStackMapForFunctionEntryTrap( } #endif - *result = stackMap; + *result = stackMaps.finalize(stackMap); return true; } diff --git a/js/src/wasm/WasmGC.h b/js/src/wasm/WasmGC.h @@ -287,9 +287,9 @@ class StackMaps { public: StackMaps() : stackMaps_(4096, js::BackgroundMallocArena) {} - // Allocates a new empty StackMap. After configuring the StackMap to your + // Allocates a new empty stack map. After configuring the stack map to your // liking, you must call finalize(). - StackMap* create(uint32_t numMappedWords) { + [[nodiscard]] StackMap* create(uint32_t numMappedWords) { MOZ_ASSERT(!createdButNotFinalized_, "a previous StackMap has been created but not finalized"); @@ -306,10 +306,10 @@ class StackMaps { return newMap; } - // Allocates a new StackMap with a given header, e.g. one that had been - // previously serialized. After configuring the StackMap to your liking, you + // Allocates a new stack map with a given header, e.g. one that had been + // previously serialized. After configuring the stack map to your liking, you // must call finalize(). - StackMap* create(const StackMapHeader& header) { + [[nodiscard]] StackMap* create(const StackMapHeader& header) { StackMap* map = create(header.numMappedWords); if (!map) { return nullptr; @@ -318,11 +318,10 @@ class StackMaps { return map; } - // Finalizes a StackMap allocated by create(), adding it to the hash map - // with a particular code offset. Upon calling finalize(), `map` is "moved" - // into the StackMaps class and must no longer be accessed. (This is because - // it may be deduplicated.) - [[nodiscard]] bool finalize(uint32_t codeOffset, StackMap* map) { + // Finalizes a stack map allocated by create(). The `map` is no longer valid + // to access as it may have been deduplicated. The returned stack map must be + // used instead. This operation is infallible. + [[nodiscard]] StackMap* finalize(StackMap* map) { #ifdef DEBUG MOZ_ASSERT( map == createdButNotFinalized_, @@ -335,15 +334,29 @@ class StackMaps { // allocation that created the new map and add the existing one to the // hash map. stackMaps_.release(beforeLastCreated_); - return codeOffsetToStackMap_.put(codeOffset, lastAdded_); + return lastAdded_; } // This stack map is new. lastAdded_ = map; stackMaps_.cancelMark(beforeLastCreated_); + return map; + } + + // Add a finalized stack map with a given code offset. + [[nodiscard]] bool add(uint32_t codeOffset, StackMap* map) { + MOZ_ASSERT(!createdButNotFinalized_); + MOZ_ASSERT(stackMaps_.contains(map)); return codeOffsetToStackMap_.put(codeOffset, map); } + // Finalizes a stack map created by create() and adds it to the given code + // offset. The `map` is no longer valid to use as it may be deduplicated and + // freed. + [[nodiscard]] bool finalize(uint32_t codeOffset, StackMap* map) { + return add(codeOffset, finalize(map)); + } + void clear() { MOZ_ASSERT(!createdButNotFinalized_); codeOffsetToStackMap_.clear(); diff --git a/js/src/wasm/WasmInstance.cpp b/js/src/wasm/WasmInstance.cpp @@ -2433,7 +2433,8 @@ bool Instance::init(JSContext* cx, const JSObjectVector& funcImports, cx_ = cx; valueBoxClass_ = AnyRef::valueBoxClass(); - resetInterrupt(cx); + interrupt_ = false; + stackLimit_ = cx->stackLimitForJitCode(JS::StackForUntrustedScript); jumpTable_ = code_->tieringJumpTable(); debugFilter_ = nullptr; callRefMetrics_ = nullptr; @@ -2826,37 +2827,19 @@ Instance::~Instance() { MOZ_ASSERT(pendingException_.isNull()); } -void Instance::setInterrupt() { - interrupt_ = true; - stackLimit_ = JS::NativeStackLimitMin; -} +void Instance::setInterrupt() { interrupt_ = true; } -bool Instance::isInterrupted() const { - return interrupt_ || stackLimit_ == JS::NativeStackLimitMin; -} +bool Instance::isInterrupted() const { return interrupt_; } -void Instance::resetInterrupt(JSContext* cx) { - interrupt_ = false; -#ifdef ENABLE_WASM_JSPI - if (cx->wasm().suspendableStackLimit != JS::NativeStackLimitMin) { - stackLimit_ = cx->wasm().suspendableStackLimit; - return; - } -#endif - stackLimit_ = cx->stackLimitForJitCode(JS::StackForUntrustedScript); -} +void Instance::resetInterrupt() { interrupt_ = false; } void Instance::setTemporaryStackLimit(JS::NativeStackLimit limit) { - if (!isInterrupted()) { - stackLimit_ = limit; - } + stackLimit_ = limit; onSuspendableStack_ = true; } void Instance::resetTemporaryStackLimit(JSContext* cx) { - if (!isInterrupted()) { - stackLimit_ = cx->stackLimitForJitCode(JS::StackForUntrustedScript); - } + stackLimit_ = cx->stackLimitForJitCode(JS::StackForUntrustedScript); onSuspendableStack_ = false; } diff --git a/js/src/wasm/WasmInstance.h b/js/src/wasm/WasmInstance.h @@ -119,10 +119,8 @@ class alignas(16) Instance { // The tag object of the pending exception. GCPtr<AnyRef> pendingExceptionTag_; - // Usually equal to cx->stackLimitForJitCode(JS::StackForUntrustedScript), - // but can be racily set to trigger immediate trap as an opportunity to - // CheckForInterrupt without an additional branch. - mozilla::Atomic<JS::NativeStackLimit, mozilla::Relaxed> stackLimit_; + // Equal to cx->stackLimitForJitCode(JS::StackForUntrustedScript). + JS::NativeStackLimit stackLimit_; // Set to 1 when wasm should call CheckForInterrupt. mozilla::Atomic<uint32_t, mozilla::Relaxed> interrupt_; @@ -395,7 +393,7 @@ class alignas(16) Instance { void setInterrupt(); bool isInterrupted() const; - void resetInterrupt(JSContext* cx); + void resetInterrupt(); void setTemporaryStackLimit(JS::NativeStackLimit limit); void resetTemporaryStackLimit(JSContext* cx); diff --git a/js/src/wasm/WasmRealm.cpp b/js/src/wasm/WasmRealm.cpp @@ -132,7 +132,7 @@ void wasm::InterruptRunningCode(JSContext* cx) { void wasm::ResetInterruptState(JSContext* cx) { auto runtimeInstances = cx->runtime()->wasmInstances.lock(); for (Instance* instance : runtimeInstances.get()) { - instance->resetInterrupt(cx); + instance->resetInterrupt(); } } diff --git a/js/src/wasm/WasmStubs.cpp b/js/src/wasm/WasmStubs.cpp @@ -1869,40 +1869,6 @@ static void FillArgumentArrayForJitExit(MacroAssembler& masm, Register instance, GenPrintf(DebugChannel::Import, masm, "\n"); } -static bool AddStackCheckForImportFunctionEntry(jit::MacroAssembler& masm, - unsigned reserve, - const FuncType& funcType, - StackMaps* stackMaps) { - std::pair<CodeOffset, uint32_t> pair = - masm.wasmReserveStackChecked(reserve, TrapSiteDesc()); - - // Attempt to create stack maps for masm.wasmReserveStackChecked. - ArgTypeVector argTypes(funcType); - RegisterOffsets trapExitLayout; - size_t trapExitLayoutNumWords; - GenerateTrapExitRegisterOffsets(&trapExitLayout, &trapExitLayoutNumWords); - CodeOffset trapInsnOffset = pair.first; - size_t nBytesReservedBeforeTrap = pair.second; - size_t nInboundStackArgBytes = - StackArgAreaSizeUnaligned(argTypes, ABIKind::Wasm); - wasm::StackMap* stackMap = nullptr; - if (!CreateStackMapForFunctionEntryTrap( - argTypes, trapExitLayout, trapExitLayoutNumWords, - nBytesReservedBeforeTrap, nInboundStackArgBytes, *stackMaps, - &stackMap)) { - return false; - } - - // In debug builds, we'll always have a stack map, even if there are no - // refs to track. - MOZ_ASSERT(stackMap); - if (stackMap) { - return stackMaps->finalize(trapInsnOffset.offset(), stackMap); - } - - return true; -} - // Generate a wrapper function with the standard intra-wasm call ABI which // simply calls an import. This wrapper function allows any import to be treated // like a normal wasm function for the purposes of exports and table calls. In @@ -1928,10 +1894,7 @@ static bool GenerateImportFunction(jit::MacroAssembler& masm, sizeof(Frame), // pushed by prologue StackArgBytesForWasmABI(funcType) + sizeOfInstanceSlot); - if (!AddStackCheckForImportFunctionEntry(masm, framePushed, funcType, - stackMaps)) { - return false; - } + masm.wasmReserveStackChecked(framePushed, TrapSiteDesc()); MOZ_ASSERT(masm.framePushed() == framePushed);