packages/js115/power9-jit-744152.diff

286 lines
10 KiB
Diff

# HG changeset patch
# User Cameron Kaiser <spectre@floodgap.com>
# Date 1695240514 25200
# Wed Sep 20 13:08:34 2023 -0700
# Node ID bd8eea54a76bd887fd7741eb252ee8bc09bf79f2
# Parent 3ac07c6a65bceaeb75d59aafa7728388c31ea11d
Ion fixes
diff -r 3ac07c6a65bc -r bd8eea54a76b js/src/jit/JitFrames.cpp
--- a/js/src/jit/JitFrames.cpp Fri Sep 15 12:44:43 2023 -0700
+++ b/js/src/jit/JitFrames.cpp Wed Sep 20 13:08:34 2023 -0700
@@ -1701,17 +1701,25 @@
case RValueAllocation::CST_NULL:
return NullValue();
case RValueAllocation::DOUBLE_REG:
return DoubleValue(fromRegister<double>(alloc.fpuReg()));
case RValueAllocation::ANY_FLOAT_REG:
+#if defined(JS_CODEGEN_PPC64)
+ // There is no (simple) way from the ISA to determine if an arbitrary
+ // FPR contains a float or a double since the ISA treats them largely
+ // synonymously, so the MachineState will always contain a double even
+ // if it's encoding a float.
+ return Float32Value((float)fromRegister<double>(alloc.fpuReg()));
+#else
return Float32Value(fromRegister<float>(alloc.fpuReg()));
+#endif
case RValueAllocation::ANY_FLOAT_STACK:
return Float32Value(ReadFrameFloat32Slot(fp_, alloc.stackOffset()));
case RValueAllocation::TYPED_REG:
return FromTypedPayload(alloc.knownType(), fromRegister(alloc.reg2()));
case RValueAllocation::TYPED_STACK: {
@@ -2316,20 +2324,21 @@
uintptr_t* addr = state_.as<SafepointState>().addressOfRegister(reg);
return *addr;
}
MOZ_CRASH("Invalid state");
}
template <typename T>
T MachineState::read(FloatRegister reg) const {
-#if !defined(JS_CODEGEN_RISCV64)
+#if !defined(JS_CODEGEN_RISCV64) && !defined(JS_CODEGEN_PPC64)
MOZ_ASSERT(reg.size() == sizeof(T));
#else
// RISCV64 always store FloatRegister as 64bit.
+ // So does Power ISA (see SnapshotIterator::allocationValue).
MOZ_ASSERT(reg.size() == sizeof(double));
#endif
#if !defined(JS_CODEGEN_NONE) && !defined(JS_CODEGEN_WASM32)
if (state_.is<BailoutState>()) {
uint32_t offset = reg.getRegisterDumpOffsetInBytes();
MOZ_ASSERT((offset % sizeof(T)) == 0);
MOZ_ASSERT((offset + sizeof(T)) <= sizeof(RegisterDump::FPUArray));
diff -r 3ac07c6a65bc -r bd8eea54a76b js/src/jit/LIR.h
--- a/js/src/jit/LIR.h Fri Sep 15 12:44:43 2023 -0700
+++ b/js/src/jit/LIR.h Wed Sep 20 13:08:34 2023 -0700
@@ -547,17 +547,17 @@
static LDefinition BogusTemp() { return LDefinition(); }
Policy policy() const {
return (Policy)((bits_ >> POLICY_SHIFT) & POLICY_MASK);
}
Type type() const { return (Type)((bits_ >> TYPE_SHIFT) & TYPE_MASK); }
static bool isFloatRegCompatible(Type type, FloatRegister reg) {
-#ifdef JS_CODEGEN_RISCV64
+#if defined(JS_CODEGEN_RISCV64) || defined(JS_CODEGEN_PPC64)
if (type == FLOAT32 || type == DOUBLE) {
return reg.isSingle() || reg.isDouble();
}
#else
if (type == FLOAT32) {
return reg.isSingle();
}
if (type == DOUBLE) {
diff -r 3ac07c6a65bc -r bd8eea54a76b js/src/jit/ppc64/CodeGenerator-ppc64.cpp
--- a/js/src/jit/ppc64/CodeGenerator-ppc64.cpp Fri Sep 15 12:44:43 2023 -0700
+++ b/js/src/jit/ppc64/CodeGenerator-ppc64.cpp Wed Sep 20 13:08:34 2023 -0700
@@ -1364,18 +1364,17 @@
MOZ_ASSERT(shift == 1);
masm.x_srwi(tmp, lhs, 31);
masm.add32(lhs, tmp);
}
// Do the shift.
masm.as_srawi(dest, tmp, shift);
} else {
- if (lhs != dest)
- masm.move32(lhs, dest);
+ masm.move32(lhs, dest);
}
}
void
CodeGenerator::visitModI(LModI* ins)
{
ADBlock();
@@ -1627,45 +1626,35 @@
Register dest = ToRegister(ins->output());
if (rhs->isConstant()) {
int32_t shift = ToInt32(rhs) & 0x1F;
switch (ins->bitop()) {
case JSOp::Lsh:
if (shift)
masm.x_slwi(dest, lhs, shift);
- else if (dest != lhs)
+ else
masm.move32(lhs, dest);
break;
case JSOp::Rsh:
if (shift)
masm.as_srawi(dest, lhs, shift);
- else if (dest != lhs)
+ else
masm.move32(lhs, dest);
break;
case JSOp::Ursh:
if (shift) {
masm.x_srwi(dest, lhs, shift);
-#if(0)
- } else if (ins->mir()->toUrsh()->fallible()) {
+ } else {
// x >>> 0 can overflow.
- masm.as_extsw(ScratchRegister, lhs);
- bailoutCmp32(Assembler::LessThan, ScratchRegister, Imm32(0), ins->snapshot());
- } else {
+ if (ins->mir()->toUrsh()->fallible()) {
+ bailoutCmp32(Assembler::LessThan, lhs, Imm32(0), ins->snapshot());
+ }
masm.move32(lhs, dest);
}
-#else
- } else {
- // x >>> 0 can overflow.
- if (ins->mir()->toUrsh()->fallible())
- bailoutCmp32(Assembler::LessThan, lhs, Imm32(0), ins->snapshot());
- if (dest != lhs)
- masm.move32(lhs, dest);
- }
-#endif
break;
default:
MOZ_CRASH("Unexpected shift op");
}
} else {
// The shift amounts should be AND'ed into the 0-31 range.
masm.as_andi_rc(dest, ToRegister(rhs), 0x1f);
@@ -1675,22 +1664,17 @@
break;
case JSOp::Rsh:
masm.as_sraw(dest, lhs, dest);
break;
case JSOp::Ursh:
masm.as_srw(dest, lhs, dest);
if (ins->mir()->toUrsh()->fallible()) {
// x >>> 0 can overflow.
-#if(0)
- masm.as_extsw(ScratchRegister, lhs);
- bailoutCmp32(Assembler::LessThan, ScratchRegister, Imm32(0), ins->snapshot());
-#else
bailoutCmp32(Assembler::LessThan, dest, Imm32(0), ins->snapshot());
-#endif
}
break;
default:
MOZ_CRASH("Unexpected shift op");
}
}
}
diff -r 3ac07c6a65bc -r bd8eea54a76b js/src/jit/ppc64/MacroAssembler-ppc64-inl.h
--- a/js/src/jit/ppc64/MacroAssembler-ppc64-inl.h Fri Sep 15 12:44:43 2023 -0700
+++ b/js/src/jit/ppc64/MacroAssembler-ppc64-inl.h Wed Sep 20 13:08:34 2023 -0700
@@ -369,21 +369,29 @@
MacroAssembler::mulBy3(Register src, Register dest)
{
// I guess this *is* better than mulli.
MOZ_ASSERT(src != ScratchRegister);
as_add(ScratchRegister, src, src);
as_add(dest, ScratchRegister, src);
}
+// This is used in MacroAssembler::loadInt32ToStringWithBase. Instead of
+// letting us use our superior arithmetic instructions, the JIT has reduced
+// us to faffing around with magic constants because that's what x86* does.
+// This leads to sign extension hazards.
void MacroAssembler::mulHighUnsigned32(Imm32 imm, Register src, Register dest) {
MOZ_ASSERT(src != ScratchRegister);
+ // Compensate for (likely) sign extension by always clearing upper bits.
move32(imm, ScratchRegister);
- as_mulhw(dest, ScratchRegister, src);
- x_sldi(dest, dest, 32);
+ as_rldicl(ScratchRegister, ScratchRegister, 0, 32); // "clrldi"
+ // loadInt32ToStringWithBase expects what is effectively unsigned multiply.
+ as_mulhwu(dest, ScratchRegister, src);
+ // Clear upper bits again, as they are undefined by the spec.
+ as_rldicl(dest, dest, 0, 32); // "clrldi"
}
void
MacroAssembler::inc64(AbsoluteAddress dest)
{
ma_li(SecondScratchReg, ImmWord(uintptr_t(dest.addr)));
as_ld(ThirdScratchReg, SecondScratchReg, 0);
as_addi(ScratchRegister, ThirdScratchReg, 1);
diff -r 3ac07c6a65bc -r bd8eea54a76b js/src/jit/ppc64/MacroAssembler-ppc64.cpp
--- a/js/src/jit/ppc64/MacroAssembler-ppc64.cpp Fri Sep 15 12:44:43 2023 -0700
+++ b/js/src/jit/ppc64/MacroAssembler-ppc64.cpp Wed Sep 20 13:08:34 2023 -0700
@@ -4769,21 +4769,23 @@
void
MacroAssembler::branchPtrInNurseryChunk(Condition cond, Register ptr, Register temp,
Label* label)
{
ADBlock();
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
MOZ_ASSERT(ptr != temp);
MOZ_ASSERT(ptr != ScratchRegister); // Both may be used internally.
- MOZ_ASSERT(temp != ScratchRegister);
- MOZ_ASSERT(temp != InvalidReg);
-
- ma_and(temp, ptr, Imm32(int32_t(~gc::ChunkMask)));
- branchPtr(InvertCondition(cond), Address(temp, gc::ChunkStoreBufferOffset),
+ MOZ_ASSERT(ptr != SecondScratchReg);
+ MOZ_ASSERT(temp != ScratchRegister); // probably unpossible
+ MOZ_ASSERT(temp != SecondScratchReg);
+ MOZ_ASSERT(gc::ChunkStoreBufferOffset < 32767);
+
+ ma_and(SecondScratchReg, ptr, Imm32(int32_t(~gc::ChunkMask)));
+ branchPtr(InvertCondition(cond), Address(SecondScratchReg, gc::ChunkStoreBufferOffset),
ImmWord(0), label);
}
void
MacroAssembler::comment(const char* msg)
{
Assembler::comment(msg);
}
diff -r 3ac07c6a65bc -r bd8eea54a76b js/src/wasm/WasmFrameIter.cpp
--- a/js/src/wasm/WasmFrameIter.cpp Fri Sep 15 12:44:43 2023 -0700
+++ b/js/src/wasm/WasmFrameIter.cpp Wed Sep 20 13:08:34 2023 -0700
@@ -1286,17 +1286,33 @@
#elif defined(JS_CODEGEN_ARM)
if (offsetFromEntry == BeforePushRetAddr || codeRange->isThunk()) {
// The return address is still in lr and fp holds the caller's fp.
fixedPC = (uint8_t*)registers.lr;
fixedFP = fp;
AssertMatchesCallSite(fixedPC, fixedFP);
} else
#elif defined(JS_CODEGEN_PPC64)
- MOZ_ASSERT(0);
+ if (codeRange->isThunk()) {
+ // The FarJumpIsland sequence temporarily scrambles LR.
+ // Don't unwind to the caller.
+ fixedPC = pc;
+ fixedFP = fp;
+ *unwoundCaller = false;
+ AssertMatchesCallSite(
+ Frame::fromUntaggedWasmExitFP(fp)->returnAddress(),
+ Frame::fromUntaggedWasmExitFP(fp)->rawCaller());
+ } else if (offsetFromEntry < PushedFP) {
+ // On ppc64 we rely on register state instead of state saved on
+ // stack until the wasm::Frame is completely built.
+ // On entry the return address is in LR and fp holds the caller's fp.
+ fixedPC = (uint8_t*)registers.lr;
+ fixedFP = fp;
+ AssertMatchesCallSite(fixedPC, fixedFP);
+ } else
#endif
if (offsetFromEntry == PushedRetAddr || codeRange->isThunk()) {
// The return address has been pushed on the stack but fp still
// points to the caller's fp.
fixedPC = sp[0];
fixedFP = fp;
AssertMatchesCallSite(fixedPC, fixedFP);
} else if (offsetFromEntry == PushedFP) {