tor-browser

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

commit 0e17b2f9c4321f55c4299bc18515e2c27616d2b2
parent 9b710255f243aeb399642d6af4c713f8f1b61339
Author: Ryan Hunt <rhunt@eqrion.net>
Date:   Tue, 18 Nov 2025 16:57:30 +0000

Bug 1990931 - wasm: Improve signature check code layout. r=yury

There is a trap instruction in our signature checking that we
conditionally skip over. This doesn't play well with the static
branch prediction guidelines (assume conditional forward branches
are not taken).

Ideally the trap would be moved OOL, but that messes up frame
unwinding and so the best we can do is conditionally jump to
the trap on failure, and unconditionally jump past the trap
on success.

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

Diffstat:
Mjs/src/wasm/WasmFrameIter.cpp | 44+++++++++++++++++++++++++++++++++-----------
1 file changed, 33 insertions(+), 11 deletions(-)

diff --git a/js/src/wasm/WasmFrameIter.cpp b/js/src/wasm/WasmFrameIter.cpp @@ -820,22 +820,26 @@ void wasm::GenerateFunctionPrologue(MacroAssembler& masm, Register scratch1 = WasmTableCallScratchReg0; Register scratch2 = WasmTableCallScratchReg1; - // Check if this function's type is exactly the expected function type + // Load the STV of this callee's function type masm.loadPtr( Address(InstanceReg, Instance::offsetInData( callIndirectId.instanceDataOffset() + offsetof(wasm::TypeDefInstanceData, superTypeVector))), scratch1); - masm.branchPtr(Assembler::Condition::Equal, WasmTableCallSigReg, - scratch1, &functionBody); - // Otherwise, we need to see if this function's type is a sub type of - // the expected function type. This requires us to check if the - // expected's type is in the super type vector of this function's type. - // - // We can skip this if our function type has no super types. + // Emit a longer check when the callee function type has a super type, + // as the caller may be using one of the super type's of this callee. if (callIndirectId.hasSuperType()) { + // Check if this function's type is exactly the expected function type + masm.branchPtr(Assembler::Condition::Equal, WasmTableCallSigReg, + scratch1, &functionBody); + + // Otherwise, we need to see if this function's type is a sub type of + // the expected function type. This requires us to check if the + // expected's type is in the super type vector of this function's + // type. + // Check if the expected function type was an immediate, not a // type definition. Because we only allow the immediate form for // final types without super types, this implies that we have a @@ -854,16 +858,34 @@ void wasm::GenerateFunctionPrologue(MacroAssembler& masm, // Perform the check masm.branchWasmSTVIsSubtypeDynamicDepth(scratch1, WasmTableCallSigReg, subTypingDepth, scratch2, - &functionBody, true); + &fail, false); + } else { + // This callee function type has no super types, there is only one + // possible type we should be called with. Check for it. + masm.branchPtr(Assembler::Condition::NotEqual, WasmTableCallSigReg, + scratch1, &fail); } + masm.jump(&functionBody); + // Put the trap behind a jump so that we play nice with static code + // prediction. We can't move this out of the prologue or it will mess + // up wasm::StartUnwinding, which uses the PC to determine if the frame + // has been constructed or not. masm.bind(&fail); masm.wasmTrap(Trap::IndirectCallBadSig, TrapSiteDesc()); break; } case CallIndirectIdKind::Immediate: { - masm.branch32(Assembler::Condition::Equal, WasmTableCallSigReg, - Imm32(callIndirectId.immediate()), &functionBody); + Label fail; + masm.branch32(Assembler::Condition::NotEqual, WasmTableCallSigReg, + Imm32(callIndirectId.immediate()), &fail); + masm.jump(&functionBody); + + // Put the trap behind a jump so that we play nice with static code + // prediction. We can't move this out of the prologue or it will mess + // up wasm::StartUnwinding, which uses the PC to determine if the frame + // has been constructed or not. + masm.bind(&fail); masm.wasmTrap(Trap::IndirectCallBadSig, TrapSiteDesc()); break; }