tor-browser

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

commit 7f9fbe6c0367e048f5321abd796d150283766846
parent 768bf4dd8e7ddc79928660f461ebda1d8ad0d52d
Author: André Bargull <andre.bargull@gmail.com>
Date:   Wed,  5 Nov 2025 20:55:57 +0000

Bug 1997975 - Part 9: Split (U)DivOrModI64 for arm64. r=spidermonkey-reviewers,iain

Using different instructions for division and modulus instructions makes it
easier to follow the code.

And use at-start allocations for division.

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

Diffstat:
Mjs/src/jit/LIROps.yaml | 30++++++++++++++++++++++++++----
Mjs/src/jit/arm64/CodeGenerator-arm64.cpp | 118+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mjs/src/jit/arm64/LIR-arm64.h | 69---------------------------------------------------------------------
Mjs/src/jit/arm64/Lowering-arm64.cpp | 24++++++++++++------------
4 files changed, 99 insertions(+), 142 deletions(-)

diff --git a/js/src/jit/LIROps.yaml b/js/src/jit/LIROps.yaml @@ -4403,11 +4403,33 @@ #endif #ifdef JS_CODEGEN_ARM64 -- name: DivOrModI64 - gen_boilerplate: false +- name: DivI64 + result_type: Int64 + operands: + lhs: WordSized + rhs: WordSized + mir_op: Div -- name: UDivOrModI64 - gen_boilerplate: false +- name: ModI64 + result_type: Int64 + operands: + lhs: WordSized + rhs: WordSized + mir_op: Mod + +- name: UDivI64 + result_type: Int64 + operands: + lhs: WordSized + rhs: WordSized + mir_op: Div + +- name: UModI64 + result_type: Int64 + operands: + lhs: WordSized + rhs: WordSized + mir_op: Mod - name: DivConstantI result_type: WordSized diff --git a/js/src/jit/arm64/CodeGenerator-arm64.cpp b/js/src/jit/arm64/CodeGenerator-arm64.cpp @@ -337,6 +337,20 @@ void CodeGenerator::visitMulI(LMulI* ins) { } } +template <class LIR> +static void TrapIfDivideByZero(MacroAssembler& masm, LIR* lir, + ARMRegister rhs) { + auto* mir = lir->mir(); + MOZ_ASSERT(mir->trapOnError()); + + if (mir->canBeDivideByZero()) { + Label nonZero; + masm.Cbnz(rhs, &nonZero); + masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc()); + masm.bind(&nonZero); + } +} + void CodeGenerator::visitDivI(LDivI* ins) { Register lhs = ToRegister(ins->lhs()); Register rhs = ToRegister(ins->rhs()); @@ -350,10 +364,7 @@ void CodeGenerator::visitDivI(LDivI* ins) { // Handle division by zero. if (mir->canBeDivideByZero()) { if (mir->trapOnError()) { - Label nonZero; - masm.Cbnz(rhs32, &nonZero); - masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc()); - masm.bind(&nonZero); + TrapIfDivideByZero(masm, ins, rhs32); } else if (mir->canTruncateInfinities()) { // SDIV returns zero for division by zero, exactly what we want for // truncated division. Remainder computation expects a non-zero divisor, @@ -703,10 +714,7 @@ void CodeGenerator::visitModI(LModI* ins) { // Prevent divide by zero. if (mir->canBeDivideByZero()) { if (mir->trapOnError()) { - Label nonZero; - masm.Cbnz(rhs32, &nonZero); - masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc()); - masm.bind(&nonZero); + TrapIfDivideByZero(masm, ins, rhs32); } else if (mir->isTruncated()) { // Truncated division by zero yields integer zero. masm.Mov(output32, wzr); @@ -1706,10 +1714,7 @@ void CodeGenerator::visitUDiv(LUDiv* ins) { // Prevent divide by zero. if (mir->canBeDivideByZero()) { if (mir->trapOnError()) { - Label nonZero; - masm.Cbnz(rhs32, &nonZero); - masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc()); - masm.bind(&nonZero); + TrapIfDivideByZero(masm, ins, rhs32); } else if (mir->canTruncateInfinities()) { // Udiv returns zero for division by zero, exactly what we want for // truncated division. Remainder computation expects a non-zero divisor, @@ -1757,10 +1762,7 @@ void CodeGenerator::visitUMod(LUMod* ins) { if (mir->canBeDivideByZero()) { if (mir->trapOnError()) { - Label nonZero; - masm.Cbnz(rhs32, &nonZero); - masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc()); - masm.bind(&nonZero); + TrapIfDivideByZero(masm, ins, rhs32); } else if (mir->isTruncated()) { // Truncated division by zero yields integer zero. masm.Mov(output32, wzr); @@ -2651,66 +2653,68 @@ void CodeGenerator::visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir) { } } -void CodeGenerator::visitDivOrModI64(LDivOrModI64* lir) { +void CodeGenerator::visitDivI64(LDivI64* lir) { Register lhs = ToRegister(lir->lhs()); Register rhs = ToRegister(lir->rhs()); - Register output = ToRegister(lir->output()); - Label done; + ARMRegister lhs64 = toXRegister(lir->lhs()); + ARMRegister rhs64 = toXRegister(lir->rhs()); + ARMRegister output64 = toXRegister(lir->output()); + + MDiv* mir = lir->mir(); // Handle divide by zero. - if (lir->canBeDivideByZero()) { - Label isNotDivByZero; - masm.Cbnz(ARMRegister(rhs, 64), &isNotDivByZero); - masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->trapSiteDesc()); - masm.bind(&isNotDivByZero); - } + TrapIfDivideByZero(masm, lir, rhs64); // Handle an integer overflow exception from INT64_MIN / -1. - if (lir->canBeNegativeOverflow()) { + if (mir->canBeNegativeOverflow()) { Label noOverflow; masm.branchPtr(Assembler::NotEqual, lhs, ImmWord(INT64_MIN), &noOverflow); masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(-1), &noOverflow); - if (lir->mir()->isMod()) { - masm.movePtr(ImmWord(0), output); - } else { - masm.wasmTrap(wasm::Trap::IntegerOverflow, lir->trapSiteDesc()); - } - masm.jump(&done); + masm.wasmTrap(wasm::Trap::IntegerOverflow, mir->trapSiteDesc()); masm.bind(&noOverflow); } - masm.Sdiv(ARMRegister(output, 64), ARMRegister(lhs, 64), - ARMRegister(rhs, 64)); - if (lir->mir()->isMod()) { - masm.Msub(ARMRegister(output, 64), ARMRegister(output, 64), - ARMRegister(rhs, 64), ARMRegister(lhs, 64)); - } - masm.bind(&done); + masm.Sdiv(output64, lhs64, rhs64); } -void CodeGenerator::visitUDivOrModI64(LUDivOrModI64* lir) { - Register lhs = ToRegister(lir->lhs()); - Register rhs = ToRegister(lir->rhs()); - Register output = ToRegister(lir->output()); +void CodeGenerator::visitModI64(LModI64* lir) { + ARMRegister lhs64 = toXRegister(lir->lhs()); + ARMRegister rhs64 = toXRegister(lir->rhs()); + ARMRegister output64 = toXRegister(lir->output()); - Label done; + // Handle divide by zero. + TrapIfDivideByZero(masm, lir, rhs64); + + masm.Sdiv(output64, lhs64, rhs64); + + // Compute the remainder: output = lhs - (output * rhs). + masm.Msub(output64, output64, rhs64, lhs64); +} + +void CodeGenerator::visitUDivI64(LUDivI64* lir) { + ARMRegister lhs64 = toXRegister(lir->lhs()); + ARMRegister rhs64 = toXRegister(lir->rhs()); + ARMRegister output64 = toXRegister(lir->output()); // Handle divide by zero. - if (lir->canBeDivideByZero()) { - Label isNotDivByZero; - masm.Cbnz(ARMRegister(rhs, 64), &isNotDivByZero); - masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->trapSiteDesc()); - masm.bind(&isNotDivByZero); - } + TrapIfDivideByZero(masm, lir, rhs64); - masm.Udiv(ARMRegister(output, 64), ARMRegister(lhs, 64), - ARMRegister(rhs, 64)); - if (lir->mir()->isMod()) { - masm.Msub(ARMRegister(output, 64), ARMRegister(output, 64), - ARMRegister(rhs, 64), ARMRegister(lhs, 64)); - } - masm.bind(&done); + masm.Udiv(output64, lhs64, rhs64); +} + +void CodeGenerator::visitUModI64(LUModI64* lir) { + ARMRegister lhs64 = toXRegister(lir->lhs()); + ARMRegister rhs64 = toXRegister(lir->rhs()); + ARMRegister output64 = toXRegister(lir->output()); + + // Handle divide by zero. + TrapIfDivideByZero(masm, lir, rhs64); + + masm.Udiv(output64, lhs64, rhs64); + + // Compute the remainder: output = lhs - (output * rhs). + masm.Msub(output64, output64, rhs64, lhs64); } void CodeGenerator::visitSimd128(LSimd128* ins) { diff --git a/js/src/jit/arm64/LIR-arm64.h b/js/src/jit/arm64/LIR-arm64.h @@ -26,75 +26,6 @@ class LUnbox : public LInstructionHelper<1, BOX_PIECES, 0> { const char* extraName() const { return StringFromMIRType(mir()->type()); } }; -class LDivOrModI64 : public LBinaryMath<0> { - public: - LIR_HEADER(DivOrModI64) - - LDivOrModI64(const LAllocation& lhs, const LAllocation& rhs) - : LBinaryMath(classOpcode) { - setOperand(0, lhs); - setOperand(1, rhs); - } - - MBinaryArithInstruction* mir() const { - MOZ_ASSERT(mir_->isDiv() || mir_->isMod()); - return static_cast<MBinaryArithInstruction*>(mir_); - } - - bool canBeDivideByZero() const { - if (mir_->isMod()) { - return mir_->toMod()->canBeDivideByZero(); - } - return mir_->toDiv()->canBeDivideByZero(); - } - bool canBeNegativeOverflow() const { - if (mir_->isMod()) { - return mir_->toMod()->canBeNegativeDividend(); - } - return mir_->toDiv()->canBeNegativeOverflow(); - } - wasm::TrapSiteDesc trapSiteDesc() const { - MOZ_ASSERT(mir_->isDiv() || mir_->isMod()); - if (mir_->isMod()) { - return mir_->toMod()->trapSiteDesc(); - } - return mir_->toDiv()->trapSiteDesc(); - } -}; - -class LUDivOrModI64 : public LBinaryMath<0> { - public: - LIR_HEADER(UDivOrModI64); - - LUDivOrModI64(const LAllocation& lhs, const LAllocation& rhs) - : LBinaryMath(classOpcode) { - setOperand(0, lhs); - setOperand(1, rhs); - } - - const char* extraName() const { - return mir()->isTruncated() ? "Truncated" : nullptr; - } - - MBinaryArithInstruction* mir() const { - MOZ_ASSERT(mir_->isDiv() || mir_->isMod()); - return static_cast<MBinaryArithInstruction*>(mir_); - } - bool canBeDivideByZero() const { - if (mir_->isMod()) { - return mir_->toMod()->canBeDivideByZero(); - } - return mir_->toDiv()->canBeDivideByZero(); - } - wasm::TrapSiteDesc trapSiteDesc() const { - MOZ_ASSERT(mir_->isDiv() || mir_->isMod()); - if (mir_->isMod()) { - return mir_->toMod()->trapSiteDesc(); - } - return mir_->toDiv()->trapSiteDesc(); - } -}; - } // namespace jit } // namespace js diff --git a/js/src/jit/arm64/Lowering-arm64.cpp b/js/src/jit/arm64/Lowering-arm64.cpp @@ -294,20 +294,26 @@ void LIRGeneratorARM64::lowerModI(MMod* mod) { } void LIRGeneratorARM64::lowerDivI64(MDiv* div) { - LDivOrModI64* lir = new (alloc()) - LDivOrModI64(useRegister(div->lhs()), useRegister(div->rhs())); + auto* lir = new (alloc()) + LDivI64(useRegisterAtStart(div->lhs()), useRegisterAtStart(div->rhs())); defineInt64(lir, div); } +void LIRGeneratorARM64::lowerModI64(MMod* mod) { + auto* lir = + new (alloc()) LModI64(useRegister(mod->lhs()), useRegister(mod->rhs())); + defineInt64(lir, mod); +} + void LIRGeneratorARM64::lowerUDivI64(MDiv* div) { - LUDivOrModI64* lir = new (alloc()) - LUDivOrModI64(useRegister(div->lhs()), useRegister(div->rhs())); + auto* lir = new (alloc()) + LUDivI64(useRegisterAtStart(div->lhs()), useRegisterAtStart(div->rhs())); defineInt64(lir, div); } void LIRGeneratorARM64::lowerUModI64(MMod* mod) { - LUDivOrModI64* lir = new (alloc()) - LUDivOrModI64(useRegister(mod->lhs()), useRegister(mod->rhs())); + auto* lir = + new (alloc()) LUModI64(useRegister(mod->lhs()), useRegister(mod->rhs())); defineInt64(lir, mod); } @@ -315,12 +321,6 @@ void LIRGeneratorARM64::lowerWasmBuiltinDivI64(MWasmBuiltinDivI64* div) { MOZ_CRASH("We don't use runtime div for this architecture"); } -void LIRGeneratorARM64::lowerModI64(MMod* mod) { - LDivOrModI64* lir = new (alloc()) - LDivOrModI64(useRegister(mod->lhs()), useRegister(mod->rhs())); - defineInt64(lir, mod); -} - void LIRGeneratorARM64::lowerWasmBuiltinModI64(MWasmBuiltinModI64* mod) { MOZ_CRASH("We don't use runtime mod for this architecture"); }