tor-browser

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

commit 61531ae59512cb9cce8e15f811456c0d986d001e
parent 1abede9c2655529600e24ca666bd03f3ec788a26
Author: Cristina Horotan <chorotan@mozilla.com>
Date:   Sat, 13 Dec 2025 00:23:27 +0200

Revert "Bug 1992240 - wasm: Fix JIT entry when negative denormal is used without denormal support. r=jandem" for causing SM failures on RegisterSets.h

This reverts commit dddc9fc62a56f7286db6d09c89078bbf0c5dea90.

Revert "Bug 1992240 - Rename masm.canonicalizeDouble/Float. r=jandem"

This reverts commit af7592e9e83b84cf5af6555c246d62c562817088.

Revert "Bug 1992240 - wasm: Revert Bug 1977692. r=bvisness"

This reverts commit 6eea065a3b9c8dd1a7fbc716f9ff67db393f4413.

Diffstat:
Mjs/src/jit-test/lib/wasm.js | 1-
Mjs/src/jit-test/tests/auto-regress/bug1940716.js | 6++----
Mjs/src/jit-test/tests/wasm/gc/i31ref.js | 17++++++++++++-----
Mjs/src/jit/CacheIRCompiler.cpp | 10+++++-----
Mjs/src/jit/CodeGenerator.cpp | 10+++++-----
Mjs/src/jit/MacroAssembler-inl.h | 18++----------------
Mjs/src/jit/MacroAssembler.cpp | 14++++++++------
Mjs/src/jit/MacroAssembler.h | 12++----------
Mjs/src/wasm/WasmAnyRef.cpp | 2+-
Mjs/src/wasm/WasmStubs.cpp | 45+++++++--------------------------------------
10 files changed, 44 insertions(+), 91 deletions(-)

diff --git a/js/src/jit-test/lib/wasm.js b/js/src/jit-test/lib/wasm.js @@ -488,7 +488,6 @@ let WasmNonAnyrefValues = [ {x:1337}, ["abracadabra"], 13.37, - -0, 0x7fffffff + 0.1, -0x7fffffff - 0.1, 0x80000000 + 0.1, diff --git a/js/src/jit-test/tests/auto-regress/bug1940716.js b/js/src/jit-test/tests/auto-regress/bug1940716.js @@ -1,4 +1,4 @@ -// |jit-test| --disable-main-thread-denormals; skip-if: !getBuildConfiguration("can-disable-main-thread-denormals") || !wasmIsSupported(); +// |jit-test| --disable-main-thread-denormals; skip-if: !getBuildConfiguration("can-disable-main-thread-denormals") || !wasmIsSupported() || (getBuildConfiguration("osx") && getBuildConfiguration("arm64")); function a(b) { c = new WebAssembly.Module(b); @@ -7,9 +7,7 @@ function a(b) { function d(e) { return a(wasmTextToBinary(e)); } +f = [ , Number.MIN_VALUE ] let { refTest } = d(`(func (export "refTest") (param externref))`).exports; - -// Ensure there are enough values to trigger a wasm JIT entry -f = Array(16).fill([Number.MIN_VALUE, -Number.MIN_VALUE]).flat(); for (h of f) refTest(h); diff --git a/js/src/jit-test/tests/wasm/gc/i31ref.js b/js/src/jit-test/tests/wasm/gc/i31ref.js @@ -1,3 +1,9 @@ +// -0 is a valid value with which to create an i31ref, but because it +// roundtrips to +0, it wrecks a lot of our WASM tests (which use Object.is for +// comparison). Therefore we don't include -0 in the main list, and deal with +// that complexity in this file specifically. +WasmI31refValues.push(-0); + let InvalidI31Values = [ null, Number.EPSILON, @@ -5,8 +11,9 @@ let InvalidI31Values = [ Number.MIN_SAFE_INTEGER, Number.MIN_VALUE, Number.MAX_VALUE, + Infinity, + -Infinity, Number.NaN, - -0, // Number objects are not coerced ...WasmI31refValues.map(n => new Number(n)), // Non-integers are not valid @@ -95,16 +102,16 @@ for (let i of InvalidI31Values) { // Test that we can roundtrip 31-bit integers through the i31ref type // faithfully. for (let i of WasmI31refValues) { - assertEq(refI31(i), i); - assertEq(refI31Identity(i), i); + assertEq(refI31(i), Object.is(i, -0) ? 0 : i); + assertEq(refI31Identity(i), Object.is(i, -0) ? 0 : i); assertEq(i31GetU(i), valueAsI31GetU(i)); - assertEq(i31GetS(i), i); + assertEq(i31GetS(i), Object.is(i, -0) ? 0 : i); } // Test that i31ref values are truncated when given a 32-bit value for (let i of WasmI31refValues) { let adjusted = i | 0x80000000; - assertEq(refI31(adjusted), i); + assertEq(refI31(adjusted), Object.is(i, -0) ? 0 : i); } // Test that comparing identical i31 values works diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp @@ -7614,7 +7614,7 @@ bool CacheIRCompiler::emitStoreTypedArrayElement(ObjOperandId objId, // Canonicalize floating point values for differential testing. if (js::SupportDifferentialTesting()) { - masm.canonicalizeDoubleNaN(floatScratch0); + masm.canonicalizeDouble(floatScratch0); } masm.storeToTypedFloatArray(elementType, floatScratch0, dest, temp, @@ -7940,7 +7940,7 @@ bool CacheIRCompiler::emitLoadDataViewValueResult( FloatRegister scratchFloat32 = floatScratch0.get().asSingle(); masm.moveGPRToFloat16(outputScratch, scratchFloat32, scratch2, liveVolatileRegs()); - masm.canonicalizeFloatNaN(scratchFloat32); + masm.canonicalizeFloat(scratchFloat32); masm.convertFloat32ToDouble(scratchFloat32, floatScratch0); masm.boxDouble(floatScratch0, output.valueReg(), floatScratch0); break; @@ -7948,14 +7948,14 @@ bool CacheIRCompiler::emitLoadDataViewValueResult( case Scalar::Float32: { FloatRegister scratchFloat32 = floatScratch0.get().asSingle(); masm.moveGPRToFloat32(outputScratch, scratchFloat32); - masm.canonicalizeFloatNaN(scratchFloat32); + masm.canonicalizeFloat(scratchFloat32); masm.convertFloat32ToDouble(scratchFloat32, floatScratch0); masm.boxDouble(floatScratch0, output.valueReg(), floatScratch0); break; } case Scalar::Float64: masm.moveGPR64ToDouble(outputReg64, floatScratch0); - masm.canonicalizeDoubleNaN(floatScratch0); + masm.canonicalizeDouble(floatScratch0); masm.boxDouble(floatScratch0, output.valueReg(), floatScratch0); break; case Scalar::BigInt64: @@ -8134,7 +8134,7 @@ bool CacheIRCompiler::emitStoreDataViewValueResult( // Canonicalize floating point values for differential testing. if (Scalar::isFloatingType(elementType) && js::SupportDifferentialTesting()) { - masm.canonicalizeDoubleNaN(floatScratch0); + masm.canonicalizeDouble(floatScratch0); } // Load the value into a gpr register. diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp @@ -19431,15 +19431,15 @@ void CodeGenerator::visitLoadDataViewElement(LLoadDataViewElement* lir) { break; case Scalar::Float16: masm.moveGPRToFloat16(temp1, out.fpu(), temp2, volatileRegs); - masm.canonicalizeFloatNaN(out.fpu()); + masm.canonicalizeFloat(out.fpu()); break; case Scalar::Float32: masm.moveGPRToFloat32(temp1, out.fpu()); - masm.canonicalizeFloatNaN(out.fpu()); + masm.canonicalizeFloat(out.fpu()); break; case Scalar::Float64: masm.moveGPR64ToDouble(temp64, out.fpu()); - masm.canonicalizeDoubleNaN(out.fpu()); + masm.canonicalizeDouble(out.fpu()); break; case Scalar::Int8: case Scalar::Uint8: @@ -22880,14 +22880,14 @@ void CodeGenerator::visitCanonicalizeNaND(LCanonicalizeNaND* ins) { auto output = ToFloatRegister(ins->output()); MOZ_ASSERT(output == ToFloatRegister(ins->input())); - masm.canonicalizeDoubleNaN(output); + masm.canonicalizeDouble(output); } void CodeGenerator::visitCanonicalizeNaNF(LCanonicalizeNaNF* ins) { auto output = ToFloatRegister(ins->output()); MOZ_ASSERT(output == ToFloatRegister(ins->input())); - masm.canonicalizeFloatNaN(output); + masm.canonicalizeFloat(output); } template <size_t NumDefs> diff --git a/js/src/jit/MacroAssembler-inl.h b/js/src/jit/MacroAssembler-inl.h @@ -869,34 +869,20 @@ void MacroAssembler::branchFloat32NotInUInt64Range(Address src, Register temp, // ======================================================================== // Canonicalization primitives. -void MacroAssembler::canonicalizeFloatNaN(FloatRegister reg) { +void MacroAssembler::canonicalizeFloat(FloatRegister reg) { Label notNaN; branchFloat(DoubleOrdered, reg, reg, &notNaN); loadConstantFloat32(float(JS::GenericNaN()), reg); bind(&notNaN); } -void MacroAssembler::canonicalizeDoubleNaN(FloatRegister reg) { +void MacroAssembler::canonicalizeDouble(FloatRegister reg) { Label notNaN; branchDouble(DoubleOrdered, reg, reg, &notNaN); loadConstantDouble(JS::GenericNaN(), reg); bind(&notNaN); } -void MacroAssembler::canonicalizeDoubleZero(FloatRegister reg, - FloatRegister scratch) { - // If denormals are disabled, then operations on them will flush denormal - // values to zero (FTZ flag). We need the cheapest operation that is the - // identity function. - // - // Unfortunately, just moving the float register doesn't trigger FTZ. Adding - // '+-0' isn't an identity function, because it can toggle the sign bit. - // - // Therefore we choose to multiply by 1.0, which won't change the result. - loadConstantDouble(1.0, scratch); - mulDouble(scratch, reg); -} - // ======================================================================== // Memory access primitives. diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp @@ -166,15 +166,15 @@ void MacroAssembler::loadFromTypedArray(Scalar::Type arrayType, const T& src, break; case Scalar::Float16: loadFloat16(src, dest.fpu(), temp1, temp2, volatileLiveRegs); - canonicalizeFloatNaN(dest.fpu()); + canonicalizeFloat(dest.fpu()); break; case Scalar::Float32: loadFloat32(src, dest.fpu()); - canonicalizeFloatNaN(dest.fpu()); + canonicalizeFloat(dest.fpu()); break; case Scalar::Float64: loadDouble(src, dest.fpu()); - canonicalizeDoubleNaN(dest.fpu()); + canonicalizeDouble(dest.fpu()); break; case Scalar::BigInt64: case Scalar::BigUint64: @@ -7467,7 +7467,8 @@ void MacroAssembler::branchValueConvertsToWasmAnyRefInline( bind(&checkDouble); { unboxDouble(src, scratchFloat); - convertDoubleToInt32(scratchFloat, scratchInt, &fallthrough); + convertDoubleToInt32(scratchFloat, scratchInt, &fallthrough, + /*negativeZeroCheck=*/false); branch32(Assembler::GreaterThan, scratchInt, Imm32(wasm::AnyRef::MaxI31Value), &fallthrough); branch32(Assembler::LessThan, scratchInt, Imm32(wasm::AnyRef::MinI31Value), @@ -7496,7 +7497,8 @@ void MacroAssembler::convertValueToWasmAnyRef(ValueOperand src, Register dest, bind(&doubleValue); { unboxDouble(src, scratchFloat); - convertDoubleToInt32(scratchFloat, dest, oolConvert); + convertDoubleToInt32(scratchFloat, dest, oolConvert, + /*negativeZeroCheck=*/false); branch32(Assembler::GreaterThan, dest, Imm32(wasm::AnyRef::MaxI31Value), oolConvert); branch32(Assembler::LessThan, dest, Imm32(wasm::AnyRef::MinI31Value), @@ -10753,7 +10755,7 @@ void MacroAssembler::touchFrameValues(Register numStackValues, #ifdef FUZZING_JS_FUZZILLI void MacroAssembler::fuzzilliHashDouble(FloatRegister src, Register result, Register temp) { - canonicalizeDoubleNaN(src); + canonicalizeDouble(src); # ifdef JS_PUNBOX64 Register64 r64(temp); diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h @@ -2229,17 +2229,9 @@ class MacroAssembler : public MacroAssemblerSpecific { // ======================================================================== // Canonicalization primitives. - inline void canonicalizeDoubleNaN(FloatRegister reg); + inline void canonicalizeDouble(FloatRegister reg); - inline void canonicalizeFloatNaN(FloatRegister reg); - - // If denormal support is disabled, there are 2^53 ways to represent zero. - // This function canonicalizes the representation to either -0.0 or +0.0, - // maintaining the sign bit of the input. - // - // This function will not change the value of the double if denormals are - // enabled. - inline void canonicalizeDoubleZero(FloatRegister reg, FloatRegister scratch); + inline void canonicalizeFloat(FloatRegister reg); public: // ======================================================================== diff --git a/js/src/wasm/WasmAnyRef.cpp b/js/src/wasm/WasmAnyRef.cpp @@ -86,7 +86,7 @@ bool AnyRef::fromJSValue(JSContext* cx, HandleValue value, if (value.isDouble()) { double doubleValue = value.toDouble(); int32_t intValue; - if (mozilla::NumberIsInt32(doubleValue, &intValue) && + if (mozilla::NumberEqualsInt32(doubleValue, &intValue) && !int32NeedsBoxing(intValue)) { result.set(AnyRef::fromInt32(intValue)); return true; diff --git a/js/src/wasm/WasmStubs.cpp b/js/src/wasm/WasmStubs.cpp @@ -1111,37 +1111,6 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, case ValType::Ref: { // Guarded against by temporarilyUnsupportedReftypeForEntry() MOZ_RELEASE_ASSERT(funcType.args()[i].refType().isExtern()); - - // If the value is a double that is a negative denormal and denormals - // are disabled, then `branchValueConvertsToWasmAnyRefInline` will view - // it as '-0' (which must be boxed in the OOL path). However, the - // AnyRef boxing code uses `mozilla::NumberIsInt32` which does not - // properly handle the CPU DAZ/FTZ flags and returns true and therefore - // doesn't box the double. This leads to an assertion below where we - // expected the value to be boxed. - // - // Making `mozilla::NumberIsInt32` handle the CPU DAZ/FTZ flags would - // add a significant cost to many hot-paths. We instead just - // eagerly canonicalize denormals to +-0.0 here to avoid inconsistent - // results (see Bug 1971519). - { - ScratchDoubleScope tmpD(masm); - - Label notDouble; - masm.branchTestDouble(Assembler::NotEqual, scratchV, &notDouble); - - // Unbox the double and canonicalize any denormal values - masm.unboxDouble(scratchV, scratchF); - masm.canonicalizeDoubleZero(scratchF, tmpD); - - // Box the value back into scratchV and also store it back to the - // stack. - masm.boxDouble(scratchF, scratchV, tmpD); - masm.storeValue(scratchV, jitArgAddr); - - masm.bind(&notDouble); - } - masm.branchValueConvertsToWasmAnyRefInline(scratchV, scratchG, scratchF, &next); masm.jump(&oolCall); @@ -1285,7 +1254,7 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, masm.boxNonDouble(JSVAL_TYPE_INT32, ReturnReg, JSReturnOperand); break; case ValType::F32: { - masm.canonicalizeFloatNaN(ReturnFloat32Reg); + masm.canonicalizeFloat(ReturnFloat32Reg); masm.convertFloat32ToDouble(ReturnFloat32Reg, ReturnDoubleReg); GenPrintF64(DebugChannel::Function, masm, ReturnDoubleReg); ScratchDoubleScope fpscratch(masm); @@ -1293,7 +1262,7 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, break; } case ValType::F64: { - masm.canonicalizeDoubleNaN(ReturnDoubleReg); + masm.canonicalizeDouble(ReturnDoubleReg); GenPrintF64(DebugChannel::Function, masm, ReturnDoubleReg); ScratchDoubleScope fpscratch(masm); masm.boxDouble(ReturnDoubleReg, JSReturnOperand, fpscratch); @@ -1587,11 +1556,11 @@ void wasm::GenerateDirectCallFromJit(MacroAssembler& masm, const FuncExport& fe, GenPrintI64(DebugChannel::Function, masm, ReturnReg64); break; case wasm::ValType::F32: - masm.canonicalizeFloatNaN(ReturnFloat32Reg); + masm.canonicalizeFloat(ReturnFloat32Reg); GenPrintF32(DebugChannel::Function, masm, ReturnFloat32Reg); break; case wasm::ValType::F64: - masm.canonicalizeDoubleNaN(ReturnDoubleReg); + masm.canonicalizeDouble(ReturnDoubleReg); GenPrintF64(DebugChannel::Function, masm, ReturnDoubleReg); break; case wasm::ValType::Ref: @@ -1825,14 +1794,14 @@ static void FillArgumentArrayForJitExit(MacroAssembler& masm, Register instance, // Preserve the NaN pattern in the input. ScratchDoubleScope fpscratch(masm); masm.moveDouble(srcReg, fpscratch); - masm.canonicalizeDoubleNaN(fpscratch); + masm.canonicalizeDouble(fpscratch); GenPrintF64(DebugChannel::Import, masm, fpscratch); masm.boxDouble(fpscratch, dst); } else if (type == MIRType::Float32) { // JS::Values can't store Float32, so convert to a Double. ScratchDoubleScope fpscratch(masm); masm.convertFloat32ToDouble(srcReg, fpscratch); - masm.canonicalizeDoubleNaN(fpscratch); + masm.canonicalizeDouble(fpscratch); GenPrintF64(DebugChannel::Import, masm, fpscratch); masm.boxDouble(fpscratch, dst); } else if (type == MIRType::Simd128) { @@ -1875,7 +1844,7 @@ static void FillArgumentArrayForJitExit(MacroAssembler& masm, Register instance, } else { masm.loadDouble(src, dscratch); } - masm.canonicalizeDoubleNaN(dscratch); + masm.canonicalizeDouble(dscratch); GenPrintF64(DebugChannel::Import, masm, dscratch); masm.boxDouble(dscratch, dst); } else if (type == MIRType::Simd128) {