tor-browser

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

commit 1b30618ccf0f6e1febaac598fbb6717d0d7402d3
parent 8a0ce9ee7a6a3e0479de1d299a00d0f82b9f76aa
Author: André Bargull <andre.bargull@gmail.com>
Date:   Thu, 23 Oct 2025 09:56:10 +0000

Bug 1995496 - Part 2: Inline ma_div_branch_overflow into callers. r=spidermonkey-reviewers,iain

The name `ma_div_branch_overflow` is misleading, because there's no "overflow".
Inlining the method also makes it easier to use the recommended div-mod
sequence on riscv64.

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

Diffstat:
Mjs/src/jit/loong64/CodeGenerator-loong64.cpp | 11++++-------
Mjs/src/jit/loong64/MacroAssembler-loong64.cpp | 18------------------
Mjs/src/jit/loong64/MacroAssembler-loong64.h | 6------
Mjs/src/jit/mips-shared/CodeGenerator-mips-shared.cpp | 21++++++++++++++-------
Mjs/src/jit/mips-shared/MacroAssembler-mips-shared.cpp | 33---------------------------------
Mjs/src/jit/mips-shared/MacroAssembler-mips-shared.h | 6------
Mjs/src/jit/riscv64/CodeGenerator-riscv64.cpp | 18++++++++----------
Mjs/src/jit/riscv64/MacroAssembler-riscv64.cpp | 44--------------------------------------------
Mjs/src/jit/riscv64/MacroAssembler-riscv64.h | 6------
9 files changed, 26 insertions(+), 137 deletions(-)

diff --git a/js/src/jit/loong64/CodeGenerator-loong64.cpp b/js/src/jit/loong64/CodeGenerator-loong64.cpp @@ -995,7 +995,6 @@ void CodeGenerator::visitMulI64(LMulI64* lir) { } void CodeGenerator::visitDivI(LDivI* ins) { - // Extract the registers from this instruction Register lhs = ToRegister(ins->lhs()); Register rhs = ToRegister(ins->rhs()); Register dest = ToRegister(ins->output()); @@ -1057,8 +1056,6 @@ void CodeGenerator::visitDivI(LDivI* ins) { bailoutCmp32(Assembler::LessThan, rhs, Imm32(0), ins->snapshot()); masm.bind(&nonzero); } - // Note: above safety checks could not be verified as Ion seems to be - // smarter and requires double arithmetic in such cases. // All regular. Lets call div. if (mir->canTruncateRemainder()) { @@ -1066,9 +1063,10 @@ void CodeGenerator::visitDivI(LDivI* ins) { } else { MOZ_ASSERT(mir->fallible()); - Label remainderNonZero; - masm.ma_div_branch_overflow(dest, lhs, rhs, &remainderNonZero); - bailoutFrom(&remainderNonZero, ins->snapshot()); + masm.as_mod_w(temp, lhs, rhs); + bailoutCmp32(Assembler::NonZero, temp, temp, ins->snapshot()); + + masm.as_div_w(dest, lhs, rhs); } masm.bind(&done); @@ -1116,7 +1114,6 @@ void CodeGenerator::visitDivPowTwoI(LDivPowTwoI* ins) { } void CodeGenerator::visitModI(LModI* ins) { - // Extract the registers from this instruction Register lhs = ToRegister(ins->lhs()); Register rhs = ToRegister(ins->rhs()); Register dest = ToRegister(ins->output()); diff --git a/js/src/jit/loong64/MacroAssembler-loong64.cpp b/js/src/jit/loong64/MacroAssembler-loong64.cpp @@ -1632,24 +1632,6 @@ void MacroAssemblerLOONG64::ma_mul32TestOverflow(Register rd, Register rj, ma_b(rd, scratch, overflow, Assembler::NotEqual); } -void MacroAssemblerLOONG64::ma_div_branch_overflow(Register rd, Register rj, - Register rk, - Label* overflow) { - UseScratchRegisterScope temps(asMasm()); - Register scratch = temps.Acquire(); - as_mod_w(scratch, rj, rk); - ma_b(scratch, scratch, overflow, Assembler::NonZero); - as_div_w(rd, rj, rk); -} - -void MacroAssemblerLOONG64::ma_div_branch_overflow(Register rd, Register rj, - Imm32 imm, Label* overflow) { - UseScratchRegisterScope temps(asMasm()); - Register scratch = temps.Acquire(); - ma_li(scratch, imm); - ma_div_branch_overflow(rd, rj, scratch, overflow); -} - void MacroAssemblerLOONG64::ma_mod_mask(Register src, Register dest, Register hold, Register remain, int32_t shift, Label* negZero) { diff --git a/js/src/jit/loong64/MacroAssembler-loong64.h b/js/src/jit/loong64/MacroAssembler-loong64.h @@ -312,12 +312,6 @@ class MacroAssemblerLOONG64 : public Assembler { void ma_mul32TestOverflow(Register rd, Register rj, Imm32 imm, Label* overflow); - // divisions - void ma_div_branch_overflow(Register rd, Register rj, Register rk, - Label* overflow); - void ma_div_branch_overflow(Register rd, Register rj, Imm32 imm, - Label* overflow); - // fast mod, uses scratch registers, and thus needs to be in the assembler // implicitly assumes that we can overwrite dest at the beginning of the // sequence diff --git a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp @@ -484,7 +484,6 @@ void CodeGenerator::visitMulI64(LMulI64* lir) { } void CodeGenerator::visitDivI(LDivI* ins) { - // Extract the registers from this instruction Register lhs = ToRegister(ins->lhs()); Register rhs = ToRegister(ins->rhs()); Register dest = ToRegister(ins->output()); @@ -546,8 +545,6 @@ void CodeGenerator::visitDivI(LDivI* ins) { bailoutCmp32(Assembler::LessThan, rhs, Imm32(0), ins->snapshot()); masm.bind(&nonzero); } - // Note: above safety checks could not be verified as Ion seems to be - // smarter and requires double arithmetic in such cases. // All regular. Lets call div. if (mir->canTruncateRemainder()) { @@ -560,9 +557,20 @@ void CodeGenerator::visitDivI(LDivI* ins) { } else { MOZ_ASSERT(mir->fallible()); - Label remainderNonZero; - masm.ma_div_branch_overflow(dest, lhs, rhs, &remainderNonZero); - bailoutFrom(&remainderNonZero, ins->snapshot()); +#ifdef MIPSR6 + masm.as_mod(temp, lhs, rhs); +#else + masm.as_div(lhs, rhs); + masm.as_mfhi(temp); +#endif + + bailoutCmp32(Assembler::NonZero, temp, temp, ins->snapshot()); + +#ifdef MIPSR6 + masm.as_div(dest, lhs, rhs); +#else + masm.as_mflo(dest); +#endif } masm.bind(&done); @@ -609,7 +617,6 @@ void CodeGenerator::visitDivPowTwoI(LDivPowTwoI* ins) { } void CodeGenerator::visitModI(LModI* ins) { - // Extract the registers from this instruction Register lhs = ToRegister(ins->lhs()); Register rhs = ToRegister(ins->rhs()); Register dest = ToRegister(ins->output()); diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp @@ -386,39 +386,6 @@ void MacroAssemblerMIPSShared::ma_mul32TestOverflow(Register rd, Register rs, ma_b(rd, scratch, overflow, Assembler::NotEqual); } -void MacroAssemblerMIPSShared::ma_div_branch_overflow(Register rd, Register rs, - Register rt, - Label* overflow) { - UseScratchRegisterScope temps(*this); - Register scratch = temps.Acquire(); -#ifdef MIPSR6 - if (rd == rs) { - Register scratch2 = temps.Acquire(); - ma_move(scratch2, rs); - rs = scratch2; - } - as_mod(scratch, rs, rt); -#else - as_div(rs, rt); - as_mfhi(scratch); -#endif - ma_b(scratch, scratch, overflow, Assembler::NonZero); -#ifdef MIPSR6 - as_div(rd, rs, rt); -#else - as_mflo(rd); -#endif -} - -void MacroAssemblerMIPSShared::ma_div_branch_overflow(Register rd, Register rs, - Imm32 imm, - Label* overflow) { - UseScratchRegisterScope temps(*this); - Register scratch = temps.Acquire(); - ma_li(scratch, imm); - ma_div_branch_overflow(rd, rs, scratch, overflow); -} - void MacroAssemblerMIPSShared::ma_mod_mask(Register src, Register dest, Register hold, Register remain, int32_t shift, Label* negZero) { diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h @@ -147,12 +147,6 @@ class MacroAssemblerMIPSShared : public Assembler { void ma_mul32TestOverflow(Register rd, Register rs, Imm32 imm, Label* overflow); - // divisions - void ma_div_branch_overflow(Register rd, Register rs, Register rt, - Label* overflow); - void ma_div_branch_overflow(Register rd, Register rs, Imm32 imm, - Label* overflow); - // fast mod, uses scratch registers, and thus needs to be in the assembler // implicitly assumes that we can overwrite dest at the beginning of the // sequence diff --git a/js/src/jit/riscv64/CodeGenerator-riscv64.cpp b/js/src/jit/riscv64/CodeGenerator-riscv64.cpp @@ -465,8 +465,6 @@ void CodeGenerator::visitUDivOrModI64(LUDivOrModI64* lir) { Register rhs = ToRegister(lir->rhs()); Register output = ToRegister(lir->output()); - Label done; - // Prevent divide by zero. if (lir->canBeDivideByZero()) { Label nonZero; @@ -480,8 +478,6 @@ void CodeGenerator::visitUDivOrModI64(LUDivOrModI64* lir) { } else { masm.ma_divu64(output, lhs, rhs); } - - masm.bind(&done); } void CodeGenerator::visitWasmLoadI64(LWasmLoadI64* lir) { @@ -1055,7 +1051,6 @@ void CodeGenerator::visitMulI64(LMulI64* lir) { } void CodeGenerator::visitDivI(LDivI* ins) { - // Extract the registers from this instruction Register lhs = ToRegister(ins->lhs()); Register rhs = ToRegister(ins->rhs()); Register dest = ToRegister(ins->output()); @@ -1117,18 +1112,21 @@ void CodeGenerator::visitDivI(LDivI* ins) { bailoutCmp32(Assembler::LessThan, rhs, Imm32(0), ins->snapshot()); masm.bind(&nonzero); } - // Note: above safety checks could not be verified as Ion seems to be - // smarter and requires double arithmetic in such cases. // All regular. Lets call div. if (mir->canTruncateRemainder()) { masm.ma_div32(dest, lhs, rhs); } else { MOZ_ASSERT(mir->fallible()); + MOZ_ASSERT(lhs != dest && rhs != dest); + + // The recommended code sequence to obtain both the quotient and remainder + // is div[u] followed by mod[u]. + masm.ma_div32(dest, lhs, rhs); + masm.ma_mod32(temp, lhs, rhs); - Label remainderNonZero; - masm.ma_div_branch_overflow(dest, lhs, rhs, &remainderNonZero); - bailoutFrom(&remainderNonZero, ins->snapshot()); + // If the remainder is != 0, bailout since this must be a double. + bailoutCmp32(Assembler::NonZero, temp, temp, ins->snapshot()); } masm.bind(&done); diff --git a/js/src/jit/riscv64/MacroAssembler-riscv64.cpp b/js/src/jit/riscv64/MacroAssembler-riscv64.cpp @@ -6503,50 +6503,6 @@ void MacroAssemblerRiscv64::Popcnt64(Register rd, Register rs, } #endif -void MacroAssemblerRiscv64::ma_div_branch_overflow(Register rd, Register rj, - Register rk, - Label* overflow) { - UseScratchRegisterScope temps(this); - Register scratch = temps.Acquire(); - - Register dest = rd; - if (rd == rj || rd == rk) { - dest = temps.Acquire(); - } - - // The recommended code sequence to obtain both the quotient and remainder - // is div[u] followed by mod[u]. - ma_div32(dest, rj, rk); - ma_mod32(scratch, rj, rk); - ma_b(scratch, scratch, overflow, Assembler::NonZero); - - if (dest != rd) { - mv(rd, dest); - } -} - -void MacroAssemblerRiscv64::ma_div_branch_overflow(Register rd, Register rj, - Imm32 imm, Label* overflow) { - UseScratchRegisterScope temps(this); - Register scratch = temps.Acquire(); - ma_li(scratch, imm); - - Register dest = rd; - if (rd == rj) { - dest = temps.Acquire(); - } - - // The recommended code sequence to obtain both the quotient and remainder - // is div[u] followed by mod[u]. - ma_div32(dest, rj, scratch); - ma_mod32(scratch, rj, scratch); - ma_b(scratch, scratch, overflow, Assembler::NonZero); - - if (dest != rd) { - mv(rd, dest); - } -} - void MacroAssemblerRiscv64::ma_mod_mask(Register src, Register dest, Register hold, Register remain, int32_t shift, Label* negZero) { diff --git a/js/src/jit/riscv64/MacroAssembler-riscv64.h b/js/src/jit/riscv64/MacroAssembler-riscv64.h @@ -365,12 +365,6 @@ class MacroAssemblerRiscv64 : public Assembler { void ma_mul32TestOverflow(Register rd, Register rj, Imm32 imm, Label* overflow); - // divisions - void ma_div_branch_overflow(Register rd, Register rj, Register rk, - Label* overflow); - void ma_div_branch_overflow(Register rd, Register rj, Imm32 imm, - Label* overflow); - // fast mod, uses scratch registers, and thus needs to be in the assembler // implicitly assumes that we can overwrite dest at the beginning of the // sequence