commit 768bf4dd8e7ddc79928660f461ebda1d8ad0d52d
parent f6641e56e6d0b478da576e004e0bf19cf7fb3b6f
Author: André Bargull <andre.bargull@gmail.com>
Date: Wed, 5 Nov 2025 20:55:56 +0000
Bug 1997975 - Part 8: Use compare-branch-zero instructions for bailouts on arm64. r=spidermonkey-reviewers,iain
Improve bailout code to use `cbz` resp. `cbnz` instructions.
Differential Revision: https://phabricator.services.mozilla.com/D271109
Diffstat:
2 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/js/src/jit/arm64/CodeGenerator-arm64.cpp b/js/src/jit/arm64/CodeGenerator-arm64.cpp
@@ -91,6 +91,25 @@ void CodeGeneratorARM64::bailoutIf(Assembler::Condition condition,
masm.B(ool->entry(), condition);
}
+void CodeGeneratorARM64::bailoutIfZero(Assembler::Condition condition,
+ ARMRegister rt, LSnapshot* snapshot) {
+ MOZ_ASSERT(condition == Assembler::Zero || condition == Assembler::NonZero);
+
+ encode(snapshot);
+
+ InlineScriptTree* tree = snapshot->mir()->block()->trackedTree();
+ auto* ool = new (alloc()) LambdaOutOfLineCode(
+ [=](OutOfLineCode& ool) { emitBailoutOOL(snapshot); });
+ addOutOfLineCode(ool,
+ new (alloc()) BytecodeSite(tree, tree->script()->code()));
+
+ if (condition == Assembler::Zero) {
+ masm.Cbz(rt, ool->entry());
+ } else {
+ masm.Cbnz(rt, ool->entry());
+ }
+}
+
void CodeGeneratorARM64::bailoutFrom(Label* label, LSnapshot* snapshot) {
MOZ_ASSERT_IF(!masm.oom(), label->used());
MOZ_ASSERT_IF(!masm.oom(), !label->bound());
@@ -220,8 +239,7 @@ void CodeGenerator::visitMulI(LMulI* ins) {
if (mul->canBeNegativeZero() && constant <= 0) {
Assembler::Condition bailoutCond =
(constant == 0) ? Assembler::LessThan : Assembler::Equal;
- masm.Cmp(toWRegister(lhs), Operand(0));
- bailoutIf(bailoutCond, ins->snapshot());
+ bailoutCmp32(bailoutCond, lhsreg, Imm32(0), ins->snapshot());
}
switch (constant) {
diff --git a/js/src/jit/arm64/CodeGenerator-arm64.h b/js/src/jit/arm64/CodeGenerator-arm64.h
@@ -31,24 +31,59 @@ class CodeGeneratorARM64 : public CodeGeneratorShared {
MoveOperand toMoveOperand(const LAllocation a) const;
void bailoutIf(Assembler::Condition condition, LSnapshot* snapshot);
+ void bailoutIfZero(Assembler::Condition condition, ARMRegister rt,
+ LSnapshot* snapshot);
void bailoutFrom(Label* label, LSnapshot* snapshot);
void bailout(LSnapshot* snapshot);
template <typename T1, typename T2>
void bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs,
LSnapshot* snapshot) {
+ if constexpr (std::is_same_v<T1, Register> &&
+ (std::is_same_v<T2, Imm32> || std::is_same_v<T2, Imm64> ||
+ std::is_same_v<T2, ImmWord> || std::is_same_v<T2, ImmPtr>)) {
+ if (rhs.value == 0) {
+ if (c == Assembler::Equal) {
+ bailoutIfZero(Assembler::Zero, ARMRegister(lhs, 64), snapshot);
+ return;
+ }
+ if (c == Assembler::NotEqual) {
+ bailoutIfZero(Assembler::NonZero, ARMRegister(lhs, 64), snapshot);
+ return;
+ }
+ }
+ }
masm.cmpPtr(lhs, rhs);
return bailoutIf(c, snapshot);
}
template <typename T1, typename T2>
void bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs,
LSnapshot* snapshot) {
+ if constexpr (std::is_same_v<T1, Register> && std::is_same_v<T2, Imm32>) {
+ if (rhs.value == 0) {
+ if (c == Assembler::Equal) {
+ bailoutIfZero(Assembler::Zero, ARMRegister(lhs, 32), snapshot);
+ return;
+ }
+ if (c == Assembler::NotEqual) {
+ bailoutIfZero(Assembler::NonZero, ARMRegister(lhs, 32), snapshot);
+ return;
+ }
+ }
+ }
masm.cmp32(lhs, rhs);
return bailoutIf(c, snapshot);
}
template <typename T1, typename T2>
void bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs,
LSnapshot* snapshot) {
+ if constexpr (std::is_same_v<T1, Register> &&
+ std::is_same_v<T2, Register>) {
+ if (lhs == rhs && (c == Assembler::Zero || c == Assembler::NonZero)) {
+ bailoutIfZero(c, ARMRegister(lhs, 32), snapshot);
+ return;
+ }
+ }
masm.test32(lhs, rhs);
return bailoutIf(c, snapshot);
}