From 84cecb9610ae99d4fa933cf2ec52166fcdad1974 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Sat, 29 Aug 2026 07:55:35 +0000 Subject: [PATCH] [JSC] FTL inline-cache patchpoints must declare fpTempRegister as clobbered Since "Simplify AssemblyHelpers::purifyNaN" (https://commits.webkit.org/290899@main, bug 288302), AssemblyHelpers::purifyNaN() materializes PNaN in MacroAssembler::fpTempRegister (xmm15 on x86-64, q31 on ARM64). InlineCacheCompiler calls it from the IndexedTypedArrayFloat{16,32,64}Load access cases, so a GetByVal IC stub that has picked up a Float*Array load case silently overwrites fpTempRegister. That is harmless under Baseline and DFG, which never allocate fpTempRegister, but FTL lets Air allocate it like any other FP register, and the FTL IC patchpoints only declared RegisterSet::macroClobberedGPRs(). With enough FP register pressure Air keeps a live double in fpTempRegister across a generic GetByVal, and once the IC attaches a typed-array load case that double turns into NaN. The attached test computes NaN from finite operands 100% of the time on x86-64 without this change. Every one of these patchpoint generators runs under AllowMacroScratchRegisterUsage, i.e. the code they emit (and the IC stubs and slow paths they link to) is permitted to use the macro assembler's scratch registers - that permission covers the FP scratch register as well as the GP ones, so declare RegisterSet::macroClobberedFPRs() alongside macroClobberedGPRs() on all of them rather than only on the GetByVal that happens to reach purifyNaN() today. * JSTests/stress/ftl-get-by-val-ic-typed-array-float-load-clobbers-fp-temp-register.js: Added. * Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp --- ...ay-float-load-clobbers-fp-temp-register.js | 38 +++++++++++++++++++ Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp | 38 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 JSTests/stress/ftl-get-by-val-ic-typed-array-float-load-clobbers-fp-temp-register.js diff --git a/JSTests/stress/ftl-get-by-val-ic-typed-array-float-load-clobbers-fp-temp-register.js b/JSTests/stress/ftl-get-by-val-ic-typed-array-float-load-clobbers-fp-temp-register.js new file mode 100644 index 000000000000..269bde9aa54b --- /dev/null +++ b/JSTests/stress/ftl-get-by-val-ic-typed-array-float-load-clobbers-fp-temp-register.js @@ -0,0 +1,38 @@ +//@ runDefault("--useConcurrentJIT=0") +// The IndexedTypedArrayFloat{16,32,64}Load inline cache stubs call AssemblyHelpers::purifyNaN(), +// which materializes PNaN in MacroAssembler::fpTempRegister (xmm15 on x86-64, q31 on ARM64). +// FTL lets Air allocate that register, so a double that is live across a generic GetByVal +// patchpoint could be silently replaced with NaN once the IC attached a typed-array load case. + +function f(arr, idx, d) { + // Enough doubles live across the access that Air has to use every FP register, including fpTempRegister. + const a0 = d + 0.5, a1 = d + 1.5, a2 = d + 2.5, a3 = d + 3.5, a4 = d + 4.5, a5 = d + 5.5, a6 = d + 6.5, a7 = d + 7.5; + const b0 = d * 0.5, b1 = d * 1.5, b2 = d * 2.5, b3 = d * 3.5, b4 = d * 4.5, b5 = d * 5.5, b6 = d * 6.5, b7 = d * 7.5; + const x = arr[idx]; + return x + a0 * b0 + a1 * b1 + a2 * b2 + a3 * b3 + a4 * b4 + a5 * b5 + a6 * b6 + a7 * b7 + (a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7) - (b0 + b1 + b2 + b3 + b4 + b5 + b6 + b7); +} +noInline(f); + +function expected(idx, d) { + const a0 = d + 0.5, a1 = d + 1.5, a2 = d + 2.5, a3 = d + 3.5, a4 = d + 4.5, a5 = d + 5.5, a6 = d + 6.5, a7 = d + 7.5; + const b0 = d * 0.5, b1 = d * 1.5, b2 = d * 2.5, b3 = d * 3.5, b4 = d * 4.5, b5 = d * 5.5, b6 = d * 6.5, b7 = d * 7.5; + return (idx + 0.25) + a0 * b0 + a1 * b1 + a2 * b2 + a3 * b3 + a4 * b4 + a5 * b5 + a6 * b6 + a7 * b7 + (a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7) - (b0 + b1 + b2 + b3 + b4 + b5 + b6 + b7); +} +noInline(expected); +noFTL(expected); + +for (const TypedArray of [Float64Array, Float32Array, Float16Array]) { + const ta = new TypedArray(8); + for (let i = 0; i < 8; i++) + ta[i] = i + 0.25; + const other = { 0: 0.25, 1: 1.25, 2: 2.25, 3: 3.25, 4: 4.25, 5: 5.25, 6: 6.25, 7: 7.25 }; + for (let i = 0; i < 200000; i++) { + const arr = (i & 1023) === 0 ? other : ta; // keep the GetByVal generic so it goes through an IC + const idx = i & 7; + const d = (i % 97) * 0.25; + const r = f(arr, idx, d); + const e = expected(idx, d); + if (r !== e) + throw new Error(TypedArray.name + ": i=" + i + " got " + r + " expected " + e); + } +} diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp index 199c2beeecdf..baca4cf21877 100644 --- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp +++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp @@ -2927,6 +2927,7 @@ class LowerDFGToB3 { RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); patchpoint->numGPScratchRegisters = 1; patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); State* state = &m_ftlState; CodeOrigin semanticNodeOrigin = node->origin.semantic; patchpoint->setGenerator( @@ -3034,6 +3035,7 @@ class LowerDFGToB3 { patchpoint->numGPScratchRegisters = 1; patchpoint->numFPScratchRegisters = 2; patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); State* state = &m_ftlState; CodeOrigin semanticNodeOrigin = node->origin.semantic; patchpoint->setGenerator( @@ -4531,6 +4533,7 @@ class LowerDFGToB3 { patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = 4; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -4611,6 +4614,7 @@ class LowerDFGToB3 { patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = 4; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -4710,6 +4714,7 @@ class LowerDFGToB3 { patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = 3; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -4785,6 +4790,7 @@ class LowerDFGToB3 { patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = Options::useHandlerICInFTL() ? 1 : 0; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -4877,6 +4883,7 @@ class LowerDFGToB3 { patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = 4; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -4941,6 +4948,7 @@ class LowerDFGToB3 { patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = Options::useHandlerICInFTL() ? 1 : 0; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -5085,6 +5093,7 @@ class LowerDFGToB3 { patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = Options::useHandlerICInFTL() ? 1 : 0; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -5233,6 +5242,7 @@ class LowerDFGToB3 { patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = 4; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -5330,6 +5340,7 @@ class LowerDFGToB3 { patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = Options::useHandlerICInFTL() ? 1 : 0; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -5703,6 +5714,7 @@ class LowerDFGToB3 { patchpoint->append(m_notCellMask, ValueRep::reg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::reg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = Options::useHandlerICInFTL() ? 3 : 0; // FIXME: If this is a PutByIdFlush, we might want to late-clobber volatile registers. @@ -5806,6 +5818,7 @@ class LowerDFGToB3 { patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = 3; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -5968,6 +5981,7 @@ class LowerDFGToB3 { #endif patchpoint->appendSomeRegister(base); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = 2; patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { @@ -6166,6 +6180,7 @@ IGNORE_CLANG_WARNINGS_END if (typedArrayType.has_value() && typedArrayType.value() == TypeDataView) { patchpoint->appendSomeRegister(base); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = 3; unsigned osrExitArgumentOffset = patchpoint->numChildren() + /* result */ 1; @@ -6201,6 +6216,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->appendSomeRegister(base); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = 2; patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { JIT_COMMENT(jit, "typedArrayLength"); @@ -6667,6 +6683,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = Options::useHandlerICInFTL() ? 1 : 0; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -7397,6 +7414,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = Options::useHandlerICInFTL() ? 1 : 0; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -8021,6 +8039,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = Options::useHandlerICInFTL() ? 1 : 0; RefPtr exceptionHandle = @@ -13934,6 +13953,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(m_notCellMask, ValueRep::reg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::reg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->clobberLate(RegisterSet::registersToSaveForJSCall(RegisterSet::allScalarRegisters())); patchpoint->resultConstraints = { ValueRep::reg(GPRInfo::returnValueGPR) }; @@ -14025,6 +14045,7 @@ IGNORE_CLANG_WARNINGS_END } patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); if (!isTail) { patchpoint->clobberLate(RegisterSet::registersToSaveForJSCall(RegisterSet::allScalarRegisters())); patchpoint->resultConstraints = { ValueRep::reg(GPRInfo::returnValueGPR) }; @@ -14443,6 +14464,7 @@ IGNORE_CLANG_WARNINGS_END RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->clobber(RegisterSet::registersToSaveForJSCall(RegisterSet::allScalarRegisters())); // No inputs will be in a volatile register. patchpoint->resultConstraints = { ValueRep::reg(GPRInfo::returnValueGPR) }; @@ -14704,6 +14726,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(m_numberTag, ValueRep::reg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->clobberLate(RegisterSet::registersToSaveForJSCall(RegisterSet::allScalarRegisters())); patchpoint->resultConstraints = { ValueRep::reg(GPRInfo::returnValueGPR) }; @@ -14941,6 +14964,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(m_notCellMask, ValueRep::reg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::reg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->clobberLate(RegisterSet::registersToSaveForJSCall(RegisterSet::allScalarRegisters())); patchpoint->resultConstraints = { ValueRep::reg(GPRInfo::returnValueGPR) }; @@ -15030,6 +15054,7 @@ IGNORE_CLANG_WARNINGS_END PatchpointValue* patchpoint = m_out.patchpoint(Int64); patchpoint->append(ConstrainedValue(argument, ValueRep::SomeLateRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->setGenerator( [=](CCallHelpers& jit, const StackmapGenerationParams& params) { AllowMacroScratchRegisterUsage allowScratch(jit); @@ -17702,6 +17727,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); if constexpr (type == AccessType::InById) patchpoint->numGPScratchRegisters = Options::useHandlerICInFTL() ? 2 : 0; else @@ -17862,6 +17888,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = 3; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -17937,6 +17964,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = 4; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -18301,6 +18329,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->numGPScratchRegisters = Options::useHandlerICInFTL() ? 1 : 0; patchpoint->resultConstraints = { ValueRep::SomeEarlyRegister }; patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -19206,6 +19235,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = Options::useHandlerICInFTL() ? 1 : 0; RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -20251,6 +20281,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(ConstrainedValue(argument, ValueRep::SomeLateRegister)); patchpoint->numGPScratchRegisters = inlineCodeStats8Bit.needsTemp2() ? 6 : 5; patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->setGenerator( [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { AllowMacroScratchRegisterUsage allowScratch(jit); @@ -21083,6 +21114,7 @@ IGNORE_CLANG_WARNINGS_END // https://bugs.webkit.org/show_bug.cgi?id=152848 patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); @@ -21172,6 +21204,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = Options::useHandlerICInFTL() ? 2 : 0; RefPtr exceptionHandle = @@ -21914,6 +21947,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->numGPScratchRegisters = domJIT->numGPScratchRegisters; patchpoint->numFPScratchRegisters = domJIT->numFPScratchRegisters; patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); State* state = &m_ftlState; Node* node = m_node; @@ -22115,6 +22149,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->append(m_numberTag, ValueRep::reg(GPRInfo::numberTagRegister)); RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->numGPScratchRegisters = domJIT->numGPScratchRegisters; patchpoint->numFPScratchRegisters = domJIT->numFPScratchRegisters; patchpoint->resultConstraints = { ValueRep::SomeEarlyRegister }; @@ -23555,6 +23590,7 @@ IGNORE_CLANG_WARNINGS_END preparePatchpointForExceptions(patchpoint); patchpoint->numGPScratchRegisters = BinaryBitOpGenerator::needsScratchGPR ? 1 : 0; patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->resultConstraints = { ValueRep::SomeEarlyRegister }; State* state = &m_ftlState; CodeOrigin semanticNodeOrigin = node->origin.semantic; @@ -23621,6 +23657,7 @@ IGNORE_CLANG_WARNINGS_END patchpoint->numGPScratchRegisters = 1; patchpoint->numFPScratchRegisters = 1; patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); patchpoint->resultConstraints = { ValueRep::SomeEarlyRegister }; State* state = &m_ftlState; CodeOrigin semanticNodeOrigin = node->origin.semantic; @@ -23697,6 +23734,7 @@ IGNORE_CLANG_WARNINGS_END if (isARM64()) { // emitAllocateWithNonNullAllocator uses the scratch registers on ARM. patchpoint->clobber(RegisterSet::macroClobberedGPRs()); + patchpoint->clobber(RegisterSet::macroClobberedFPRs()); } patchpoint->effects.terminal = true; if (actualAllocator.isConstant())