Issue #3049 - Stabilize loongarch64 Ion patching and wasm loads

This commit is contained in:
Basilisk-Dev 2026-04-24 17:45:29 -04:00 committed by wuggy
commit 85c6fcc68e
3 changed files with 164 additions and 65 deletions

View file

@ -22,20 +22,13 @@ void js::jit::PatchJump(CodeLocationJump& jump_, CodeLocationLabel label,
ReprotectCode reprotect) {
Instruction* inst = reinterpret_cast<Instruction*>(jump_.raw());
// jumpWithPatch() reserves four instructions:
// beq zero, zero, 0
// INVALID_OFFSET
// nop
// nop
// Patch that block into the long-jump form used elsewhere in the backend:
// load64 scratch, target
// jirl zero, scratch, 0
MaybeAutoWritableJitCode awjc(inst, 4 * sizeof(uint32_t), reprotect);
Assembler::WriteLoad64Instructions(inst, ScratchRegister,
uintptr_t(label.raw()));
inst[3] = InstImm(op_jirl, BOffImm16(0), ScratchRegister, zero);
// jumpWithPatch() emits a long-jump template up front so patching only
// updates the embedded target pointer and never mutates live control-flow
// opcodes in place.
MaybeAutoWritableJitCode awjc(inst, 3 * sizeof(uint32_t), reprotect);
Assembler::UpdateLoad64Value(inst, uintptr_t(label.raw()));
AutoFlushICache::flush(uintptr_t(inst), 4 * sizeof(uint32_t));
AutoFlushICache::flush(uintptr_t(inst), 3 * sizeof(uint32_t));
}
// Note this is used for inter-wasm calls and may pass arguments and results
@ -2337,7 +2330,12 @@ void Assembler::bind(RepatchLabel* label) {
if (label->used() && !oom()) {
BufferOffset branch(label->offset());
InstImm* inst = reinterpret_cast<InstImm*>(editSrc(branch));
bind(inst, branch.getOffset(), dest.getOffset());
if ((inst[0].extractBitField(31, 25)) ==
((uint32_t)op_lu12i_w >> 25)) {
addLongJump(branch, dest);
} else {
bind(inst, branch.getOffset(), dest.getOffset());
}
}
label->bind(dest.getOffset());
}

View file

@ -1547,6 +1547,145 @@ void MacroAssemblerLOONGARCH64::ma_store(Imm32 imm, const BaseIndex& dest,
asMasm().ma_store(scratch, Address(scratch2, 0), size, extension);
}
void MacroAssemblerLOONGARCH64::ma_load_unaligned(
const wasm::MemoryAccessDesc& access, Register dest, const BaseIndex& src,
Register temp, LoadStoreSize size, LoadStoreExtension extension) {
MOZ_ASSERT(dest != temp);
asMasm().computeEffectiveAddress(src, temp);
BufferOffset load = as_ld_bu(dest, temp, 0);
if (size != SizeByte) {
ScratchRegisterScope scratch(asMasm());
const size_t byteSize = size / 8;
for (size_t i = 1; i < byteSize; i++) {
as_ld_bu(scratch, temp, i);
as_slli_d(scratch, scratch, 8 * i);
as_or(dest, dest, scratch);
}
}
switch (size) {
case SizeByte:
if (extension == SignExtend) {
as_ext_w_b(dest, dest);
}
break;
case SizeHalfWord:
if (extension == SignExtend) {
as_ext_w_h(dest, dest);
}
break;
case SizeWord:
if (extension == SignExtend) {
as_addi_w(dest, dest, 0);
}
break;
case SizeDouble:
break;
default:
MOZ_CRASH("Invalid argument for ma_load_unaligned");
}
append(access, load.getOffset(), asMasm().framePushed());
}
void MacroAssemblerLOONGARCH64::ma_store_unaligned(
const wasm::MemoryAccessDesc& access, Register data, const BaseIndex& dest,
Register temp, LoadStoreSize size, LoadStoreExtension extension) {
(void)extension;
MOZ_ASSERT(data != temp);
asMasm().computeEffectiveAddress(dest, temp);
BufferOffset store = as_st_b(data, temp, 0);
if (size != SizeByte) {
ScratchRegisterScope scratch(asMasm());
const size_t byteSize = size / 8;
for (size_t i = 1; i < byteSize; i++) {
as_srli_d(scratch, data, 8 * i);
as_st_b(scratch, temp, i);
}
}
append(access, store.getOffset(), asMasm().framePushed());
}
void MacroAssemblerLOONGARCH64::loadUnalignedDouble(
const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp,
FloatRegister dest) {
asMasm().computeEffectiveAddress(src, temp);
ScratchRegisterScope scratch(asMasm());
SecondScratchRegisterScope scratch2(asMasm());
BufferOffset load = as_ld_bu(scratch, temp, 0);
for (size_t i = 1; i < sizeof(double); i++) {
as_ld_bu(scratch2, temp, i);
as_slli_d(scratch2, scratch2, 8 * i);
as_or(scratch, scratch, scratch2);
}
append(access, load.getOffset(), asMasm().framePushed());
moveToDouble(scratch, dest);
}
void MacroAssemblerLOONGARCH64::loadUnalignedFloat32(
const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp,
FloatRegister dest) {
asMasm().computeEffectiveAddress(src, temp);
ScratchRegisterScope scratch(asMasm());
SecondScratchRegisterScope scratch2(asMasm());
BufferOffset load = as_ld_bu(scratch, temp, 0);
for (size_t i = 1; i < sizeof(float); i++) {
as_ld_bu(scratch2, temp, i);
as_slli_d(scratch2, scratch2, 8 * i);
as_or(scratch, scratch, scratch2);
}
append(access, load.getOffset(), asMasm().framePushed());
moveToFloat32(scratch, dest);
}
void MacroAssemblerLOONGARCH64::storeUnalignedDouble(
const wasm::MemoryAccessDesc& access, FloatRegister src, Register temp,
const BaseIndex& dest) {
asMasm().computeEffectiveAddress(dest, temp);
ScratchRegisterScope scratch(asMasm());
SecondScratchRegisterScope scratch2(asMasm());
moveFromDouble(src, scratch);
BufferOffset store = as_st_b(scratch, temp, 0);
for (size_t i = 1; i < sizeof(double); i++) {
as_srli_d(scratch2, scratch, 8 * i);
as_st_b(scratch2, temp, i);
}
append(access, store.getOffset(), asMasm().framePushed());
}
void MacroAssemblerLOONGARCH64::storeUnalignedFloat32(
const wasm::MemoryAccessDesc& access, FloatRegister src, Register temp,
const BaseIndex& dest) {
asMasm().computeEffectiveAddress(dest, temp);
ScratchRegisterScope scratch(asMasm());
SecondScratchRegisterScope scratch2(asMasm());
moveFromFloat32(src, scratch);
BufferOffset store = as_st_b(scratch, temp, 0);
for (size_t i = 1; i < sizeof(float); i++) {
as_srli_d(scratch2, scratch, 8 * i);
as_st_b(scratch2, temp, i);
}
append(access, store.getOffset(), asMasm().framePushed());
}
// Branches when done from within loongarch-specific code.
// TODO(loongarch64) Optimize ma_b
void MacroAssemblerLOONGARCH64::ma_b(Register lhs, Register rhs, Label* label,
@ -2512,16 +2651,18 @@ CodeOffsetJump MacroAssemblerLOONGARCH64Compat::backedgeJump(
CodeOffsetJump MacroAssemblerLOONGARCH64Compat::jumpWithPatch(
RepatchLabel* label, Label* documentation) {
(void)documentation;
MOZ_ASSERT(!label->used());
BufferOffset bo = nextOffset();
label->use(bo.getOffset());
m_buffer.ensureSpace(4 * sizeof(uint32_t));
writeInst(InstImm(op_beq, BOffImm16(0), zero, zero).encode());
writeInst(LabelBase::INVALID_OFFSET);
as_nop();
as_nop();
if (label->bound()) {
addLongJump(bo, BufferOffset(label->offset()));
}
ma_liPatchable(ScratchRegister, ImmWord(LabelBase::INVALID_OFFSET));
as_jirl(zero, ScratchRegister, BOffImm16(0));
return CodeOffsetJump(bo.getOffset());
}

View file

@ -559,62 +559,22 @@ class MacroAssemblerLOONGARCH64 : public Assembler {
}
void ma_load_unaligned(const wasm::MemoryAccessDesc& access, Register dest,
const BaseIndex& src, Register temp,
LoadStoreSize size, LoadStoreExtension extension) {
(void)access;
(void)dest;
(void)src;
(void)temp;
(void)size;
(void)extension;
MOZ_CRASH("wasm unaligned integer loads are not supported on loongarch64 yet");
}
LoadStoreSize size, LoadStoreExtension extension);
void ma_store_unaligned(const wasm::MemoryAccessDesc& access, Register data,
const BaseIndex& dest, Register temp,
LoadStoreSize size, LoadStoreExtension extension) {
(void)access;
(void)data;
(void)dest;
(void)temp;
(void)size;
(void)extension;
MOZ_CRASH("wasm unaligned integer stores are not supported on loongarch64 yet");
}
LoadStoreSize size, LoadStoreExtension extension);
void loadUnalignedDouble(const wasm::MemoryAccessDesc& access,
const BaseIndex& src, Register temp,
FloatRegister dest) {
(void)access;
(void)src;
(void)temp;
(void)dest;
MOZ_CRASH("wasm unaligned double loads are not supported on loongarch64 yet");
}
FloatRegister dest);
void loadUnalignedFloat32(const wasm::MemoryAccessDesc& access,
const BaseIndex& src, Register temp,
FloatRegister dest) {
(void)access;
(void)src;
(void)temp;
(void)dest;
MOZ_CRASH("wasm unaligned float loads are not supported on loongarch64 yet");
}
FloatRegister dest);
void storeUnalignedDouble(const wasm::MemoryAccessDesc& access,
FloatRegister src, Register temp,
const BaseIndex& dest) {
(void)access;
(void)src;
(void)temp;
(void)dest;
MOZ_CRASH("wasm unaligned double stores are not supported on loongarch64 yet");
}
const BaseIndex& dest);
void storeUnalignedFloat32(const wasm::MemoryAccessDesc& access,
FloatRegister src, Register temp,
const BaseIndex& dest) {
(void)access;
(void)src;
(void)temp;
(void)dest;
MOZ_CRASH("wasm unaligned float stores are not supported on loongarch64 yet");
}
const BaseIndex& dest);
void ma_cmp_set(Register dst, Register lhs, Register rhs, Condition c);
void ma_cmp_set(Register dst, Register lhs, Imm32 imm, Condition c);