diff --git a/js/src/jit/arm64/Assembler-arm64.cpp b/js/src/jit/arm64/Assembler-arm64.cpp index 1df60e081790..9d0b4c06be2c 100644 --- a/js/src/jit/arm64/Assembler-arm64.cpp +++ b/js/src/jit/arm64/Assembler-arm64.cpp @@ -356,7 +356,8 @@ size_t Assembler::addPatchableJump(BufferOffset src, RelocationKind reloc) { return extendedTableIndex; } -// PatchJump() is only used by the IonCacheIRCompiler. +// PatchJump() is only used by the IonCacheIRCompiler and patches code generated +// by jumpWithPatch. // // The CodeLocationJump is the jump to be patched. // The code for the jump is emitted by jumpWithPatch(). @@ -369,12 +370,18 @@ void PatchJump(CodeLocationJump& jump_, CodeLocationLabel label) { Instruction* branch = (Instruction*)load->NextInstruction()->skipPool(); MOZ_ASSERT(branch->IsUncondB()); - // FIXME: For the moment, just assume that the load isn't needed. - // FIXME: That assumption implies that the branch target is always in-range. if (branch->IsTargetReachable((Instruction*)label.raw())) { branch->SetImmPCOffsetTarget((Instruction*)label.raw()); } else { - MOZ_CRASH("PatchJump target not reachable"); + // Set the literal read by the load instruction to the target. + load->SetLiteral64(uint64_t(label.raw())); + // Get the scratch register set by the load instruction. + vixl::Register loadTarget = vixl::Register(load->Rt(), 64); + // Overwrite the branch instruction to branch on the same register as the + // load instruction. + Assembler::br(branch, loadTarget); + MOZ_ASSERT(branch->IsBR()); + MOZ_ASSERT(load->Rt() == branch->Rn()); } } diff --git a/js/src/jit/arm64/MacroAssembler-arm64.h b/js/src/jit/arm64/MacroAssembler-arm64.h index 0e812b0b6843..9792ff2ac29b 100644 --- a/js/src/jit/arm64/MacroAssembler-arm64.h +++ b/js/src/jit/arm64/MacroAssembler-arm64.h @@ -1255,7 +1255,9 @@ class MacroAssemblerCompat : public vixl::MacroAssembler { ARMBuffer::PoolEntry pe; BufferOffset load_bo; - // FIXME: This load is currently unused. + // This no-op load exists for PatchJump(), in the case of a target outside + // the range of +/- 128 MB. If the load is used, then the branch here is + // overwritten with a `BR` from the loaded register. load_bo = immPool64(scratch64, (uint64_t)label, &pe); BufferOffset branch_bo = b(-1, LabelDoc()); diff --git a/js/src/jit/arm64/vixl/Instructions-vixl.h b/js/src/jit/arm64/vixl/Instructions-vixl.h index 1fb6ff97307f..844eb2a0dc98 100644 --- a/js/src/jit/arm64/vixl/Instructions-vixl.h +++ b/js/src/jit/arm64/vixl/Instructions-vixl.h @@ -462,6 +462,10 @@ class Instruction { return literal; } + void SetLiteral64(uint64_t literal) const { + memcpy(LiteralAddress(), &literal, sizeof(literal)); + } + float LiteralFP32() const { return rawbits_to_float(Literal32()); }