diff --git a/js/src/jit/arm64/MacroAssembler-arm64.h b/js/src/jit/arm64/MacroAssembler-arm64.h index 4b4b9fdda8d..471a3eb72ac 100644 --- a/js/src/jit/arm64/MacroAssembler-arm64.h +++ b/js/src/jit/arm64/MacroAssembler-arm64.h @@ -1557,15 +1557,12 @@ class MacroAssemblerCompat : public vixl::MacroAssembler Ret(vixl::ip0); } - void j(Condition code, Label* dest) { - b(dest, code); - } - void j(Label* dest) { - b(dest, Always); + void j(Condition cond, Label* dest) { + B(dest, cond); } void branch(Condition cond, Label* label) { - b(label, cond); + B(label, cond); } void branch(JitCode* target) { syncStackPtr(); @@ -1576,20 +1573,20 @@ class MacroAssemblerCompat : public vixl::MacroAssembler void branch32(Condition cond, const Operand& lhs, Register rhs, Label* label) { // since rhs is an operand, do the compare backwards Cmp(ARMRegister(rhs, 32), lhs); - b(label, Assembler::InvertCmpCondition(cond)); + B(label, Assembler::InvertCmpCondition(cond)); } void branch32(Condition cond, const Operand& lhs, Imm32 rhs, Label* label) { ARMRegister l = lhs.reg(); Cmp(l, Operand(rhs.value)); - b(label, cond); + B(label, cond); } void branch32(Condition cond, Register lhs, Register rhs, Label* label) { cmp32(lhs, rhs); - b(label, cond); + B(label, cond); } void branch32(Condition cond, Register lhs, Imm32 imm, Label* label) { cmp32(lhs, imm); - b(label, cond); + B(label, cond); } void branch32(Condition cond, const Address& lhs, Register rhs, Label* label) { vixl::UseScratchRegisterScope temps(this); @@ -1676,7 +1673,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler MOZ_ASSERT(!label->bound()); if (cond != Always) { Label notTaken; - b(¬Taken, Assembler::InvertCondition(cond)); + B(¬Taken, Assembler::InvertCondition(cond)); branch_bo = b(-1); bind(¬Taken); } else { @@ -2536,7 +2533,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler Label onFalse; branch(Zero, &onFalse); branch(Overflow, &onFalse); - b(label); + B(label); bind(&onFalse); } } diff --git a/js/src/jit/arm64/vixl/Instructions-vixl.cpp b/js/src/jit/arm64/vixl/Instructions-vixl.cpp index 147da333cdc..c49ae1311ae 100644 --- a/js/src/jit/arm64/vixl/Instructions-vixl.cpp +++ b/js/src/jit/arm64/vixl/Instructions-vixl.cpp @@ -211,6 +211,29 @@ LSDataSize CalcLSPairDataSize(LoadStorePairOp op) { } +int Instruction::ImmBranchRangeBitwidth(ImmBranchType branch_type) { + switch (branch_type) { + case UncondBranchType: + return ImmUncondBranch_width; + case CondBranchType: + return ImmCondBranch_width; + case CompareBranchType: + return ImmCmpBranch_width; + case TestBranchType: + return ImmTestBranch_width; + default: + VIXL_UNREACHABLE(); + return 0; + } +} + + +bool Instruction::IsValidImmPCOffset(ImmBranchType branch_type, + int32_t offset) { + return is_intn(ImmBranchRangeBitwidth(branch_type), offset); +} + + const Instruction* Instruction::ImmPCOffsetTarget() const { const Instruction * base = this; ptrdiff_t offset; diff --git a/js/src/jit/arm64/vixl/Instructions-vixl.h b/js/src/jit/arm64/vixl/Instructions-vixl.h index d4e1f5f2f44..2fe0e9c5aaf 100644 --- a/js/src/jit/arm64/vixl/Instructions-vixl.h +++ b/js/src/jit/arm64/vixl/Instructions-vixl.h @@ -271,6 +271,9 @@ class Instruction { INSTRUCTION_FIELDS_LIST(DEFINE_SETTERS) #undef DEFINE_SETTERS + static int ImmBranchRangeBitwidth(ImmBranchType branch_type); + static bool IsValidImmPCOffset(ImmBranchType branch_type, int32_t offset); + // Indicate whether Rd can be the stack pointer or the zero register. This // does not check that the instruction actually has an Rd field. Reg31Mode RdMode() const { diff --git a/js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp b/js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp index e9537be46a1..22c03642fb4 100644 --- a/js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp +++ b/js/src/jit/arm64/vixl/MacroAssembler-vixl.cpp @@ -63,6 +63,25 @@ void MacroAssembler::B(Label* label, BranchType type, Register reg, int bit) { } +void MacroAssembler::B(Label* label, Condition cond) { + VIXL_ASSERT((cond != al) && (cond != nv)); + + if (label->bound() && LabelIsOutOfRange(label, CondBranchType)) { + // If the label is out of range, invert the condition to use an + // unconditional branch, which has 26 bits instead of 19. + Label done; + b(&done, InvertCondition(cond)); + b(label); + bind(&done); + } else { + // TODO: Need to register a slot in a literal pool, so that we can + // write a branch instruction there and use that to branch in case + // the unbound label winds up being out of range. + b(label, cond); + } +} + + void MacroAssembler::And(const Register& rd, const Register& rn, const Operand& operand) { LogicalMacro(rd, rn, operand, AND); } diff --git a/js/src/jit/arm64/vixl/MacroAssembler-vixl.h b/js/src/jit/arm64/vixl/MacroAssembler-vixl.h index ddfe9130b45..90d5c200daa 100644 --- a/js/src/jit/arm64/vixl/MacroAssembler-vixl.h +++ b/js/src/jit/arm64/vixl/MacroAssembler-vixl.h @@ -328,10 +328,7 @@ class MacroAssembler : public js::jit::Assembler { void B(Label* label) { b(label); } - void B(Label* label, Condition cond) { - VIXL_ASSERT((cond != al) && (cond != nv)); - b(label, cond); - } + void B(Label* label, Condition cond); void B(Condition cond, Label* label) { B(label, cond); } @@ -1076,6 +1073,10 @@ class MacroAssembler : public js::jit::Assembler { void PrepareForPush(int count, int size); void PrepareForPop(int count, int size); + bool LabelIsOutOfRange(Label* label, ImmBranchType branch_type) { + return !Instruction::IsValidImmPCOffset(branch_type, nextOffset().diffB(label)); + } + #if DEBUG // Tell whether any of the macro instruction can be used. When false the // MacroAssembler will assert if a method which can emit a variable number