Issue #3049 - Extend LoongArch minimal JIT frame slots

This commit is contained in:
Basilisk-Dev 2026-04-23 17:48:36 -04:00 • committed by wuggy
commit 03088e2abc

View file

@ -48,13 +48,17 @@ enum LoongArchReg : uint8_t {
t8 = 20 t8 = 20
}; };
static constexpr size_t MaxArgCount = 16; static constexpr size_t MaxArgCount = 32;
static constexpr LoongArchReg ArgsPointerReg = a0; static constexpr LoongArchReg ArgsPointerReg = a0;
static constexpr LoongArchReg ResultPointerReg = a1; static constexpr LoongArchReg ResultPointerReg = a1;
static constexpr LoongArchReg LocalRegs[] = { a2, a3, a4, a5, a6, a7 }; static constexpr LoongArchReg LocalRegs[] = { a2, a3, a4, a5, a6, a7 };
static constexpr LoongArchReg StackRegs[] = { t0, t1, t2, t3, t4, t5, t6 }; static constexpr LoongArchReg StackRegs[] = { t0, t1, t2, t3, t4, t5, t6 };
static constexpr LoongArchReg WideScratch = t7; static constexpr LoongArchReg WideScratch = t7;
static constexpr LoongArchReg NarrowScratch = t8; static constexpr LoongArchReg NarrowScratch = t8;
static constexpr size_t MaxLocalCount = 24;
static constexpr size_t LocalScratchBase = MaxArgCount;
static constexpr size_t LocalScratchSlotCount = MaxLocalCount - mozilla::ArrayLength(LocalRegs);
static constexpr size_t FrameSlotCount = LocalScratchBase + LocalScratchSlotCount;
enum class MinimalValueKind : uint32_t { enum class MinimalValueKind : uint32_t {
Int32 = 0, Int32 = 0,
@ -188,7 +192,7 @@ struct ControlFlowState
LoongArchReg stackRegs[mozilla::ArrayLength(StackRegs)]; LoongArchReg stackRegs[mozilla::ArrayLength(StackRegs)];
MinimalValueKind stackKinds[mozilla::ArrayLength(StackRegs)]; MinimalValueKind stackKinds[mozilla::ArrayLength(StackRegs)];
MinimalValueKind argKinds[MaxArgCount]; MinimalValueKind argKinds[MaxArgCount];
MinimalValueKind localKinds[mozilla::ArrayLength(LocalRegs)]; MinimalValueKind localKinds[MaxLocalCount];
ControlFlowState() ControlFlowState()
: initialized(false), : initialized(false),
@ -211,7 +215,7 @@ class MinimalLoongArchCompiler
size_t failPatchCount_; size_t failPatchCount_;
StackValue stack_[mozilla::ArrayLength(StackRegs)]; StackValue stack_[mozilla::ArrayLength(StackRegs)];
MinimalValueKind argKinds_[MaxArgCount]; MinimalValueKind argKinds_[MaxArgCount];
MinimalValueKind localKinds_[mozilla::ArrayLength(LocalRegs)]; MinimalValueKind localKinds_[MaxLocalCount];
size_t stackDepth_; size_t stackDepth_;
bool reachable_; bool reachable_;
bool sawReturn_; bool sawReturn_;
@ -338,6 +342,13 @@ class MinimalLoongArchCompiler
return emitLoadWord(dst, ArgsPointerReg, slot * sizeof(int32_t)); return emitLoadWord(dst, ArgsPointerReg, slot * sizeof(int32_t));
} }
static uint32_t localScratchOffset(uint32_t slot) {
MOZ_ASSERT(slot >= mozilla::ArrayLength(LocalRegs));
MOZ_ASSERT(slot < MaxLocalCount);
uint32_t scratchSlot = uint32_t(LocalScratchBase + slot - mozilla::ArrayLength(LocalRegs));
return scratchSlot * sizeof(int32_t);
}
bool emitSltui(LoongArchReg dst, LoongArchReg src, uint32_t imm) { bool emitSltui(LoongArchReg dst, LoongArchReg src, uint32_t imm) {
return emit(EncodeUnsignedImm12(0x02400000, dst, src, imm)); return emit(EncodeUnsignedImm12(0x02400000, dst, src, imm));
} }
@ -649,8 +660,13 @@ class MinimalLoongArchCompiler
bool emitStoreLocal(uint32_t slot) { bool emitStoreLocal(uint32_t slot) {
if (slot >= script_->nfixed() || !stackDepth_) if (slot >= script_->nfixed() || !stackDepth_)
return false; return false;
if (!emitMove(LocalRegs[slot], stack_[stackDepth_ - 1].reg)) if (slot < mozilla::ArrayLength(LocalRegs)) {
return false; if (!emitMove(LocalRegs[slot], stack_[stackDepth_ - 1].reg))
return false;
} else {
if (!emitStoreWord(stack_[stackDepth_ - 1].reg, ArgsPointerReg, localScratchOffset(slot)))
return false;
}
localKinds_[slot] = stack_[stackDepth_ - 1].kind; localKinds_[slot] = stack_[stackDepth_ - 1].kind;
return true; return true;
} }
@ -666,7 +682,7 @@ class MinimalLoongArchCompiler
bool supportedScriptShape() const { bool supportedScriptShape() const {
return script_->numArgs() <= MaxArgCount && return script_->numArgs() <= MaxArgCount &&
script_->nfixed() <= mozilla::ArrayLength(LocalRegs) && script_->nfixed() <= MaxLocalCount &&
!script_->isAsync() && !script_->isAsync() &&
!script_->isStarGenerator() && !script_->isStarGenerator() &&
!script_->isLegacyGenerator() && !script_->isLegacyGenerator() &&
@ -733,7 +749,7 @@ class MinimalLoongArchCompiler
if (!pcStates_.appendN(ControlFlowState(), script_->length() + 1)) if (!pcStates_.appendN(ControlFlowState(), script_->length() + 1))
return false; return false;
for (size_t i = 0; i < script_->nfixed(); i++) { for (size_t i = 0; i < script_->nfixed() && i < mozilla::ArrayLength(LocalRegs); i++) {
if (!emitLoadImm32(LocalRegs[i], 0)) if (!emitLoadImm32(LocalRegs[i], 0))
return false; return false;
} }
@ -771,8 +787,17 @@ class MinimalLoongArchCompiler
uint32_t local = GET_LOCALNO(pc); uint32_t local = GET_LOCALNO(pc);
if (local >= script_->nfixed()) if (local >= script_->nfixed())
return false; return false;
if (!pushTempFromReg(LocalRegs[local], localKinds_[local])) if (local < mozilla::ArrayLength(LocalRegs)) {
return false; if (!pushTempFromReg(LocalRegs[local], localKinds_[local]))
return false;
} else {
if (stackDepth_ >= mozilla::ArrayLength(StackRegs))
return false;
LoongArchReg dst = allocStackReg();
if (!emitLoadWord(dst, ArgsPointerReg, localScratchOffset(local)))
return false;
stack_[stackDepth_++] = { dst, localKinds_[local] };
}
break; break;
} }
case JSOP_SETLOCAL: case JSOP_SETLOCAL:
@ -1457,10 +1482,10 @@ TryCallLoongArchMinimalJit(JSContext* cx, HandleFunction fun, const CallArgs& ar
return true; return true;
MinimalJitResult result = { 0, MinimalValueKind::Int32 }; MinimalJitResult result = { 0, MinimalValueKind::Int32 };
int32_t argPayloads[MaxArgCount] = { 0 }; int32_t frameSlots[FrameSlotCount] = { 0 };
for (uint32_t i = 0; i < script->numArgs(); i++) for (uint32_t i = 0; i < script->numArgs(); i++)
argPayloads[i] = args[i].toInt32(); frameSlots[i] = args[i].toInt32();
if (!fn(argPayloads, &result)) if (!fn(frameSlots, &result))
return true; return true;
args.rval().set(MinimalJitResultToValue(result)); args.rval().set(MinimalJitResultToValue(result));
@ -1491,10 +1516,10 @@ TryEnterLoongArchMinimalJit(JSContext* cx, RunState& state)
return false; return false;
MinimalJitResult result = { 0, MinimalValueKind::Int32 }; MinimalJitResult result = { 0, MinimalValueKind::Int32 };
int32_t argPayloads[MaxArgCount] = { 0 }; int32_t frameSlots[FrameSlotCount] = { 0 };
for (uint32_t i = 0; i < state.script()->numArgs(); i++) for (uint32_t i = 0; i < state.script()->numArgs(); i++)
argPayloads[i] = invoke.args()[i].toInt32(); frameSlots[i] = invoke.args()[i].toInt32();
if (!fn(argPayloads, &result)) if (!fn(frameSlots, &result))
return false; return false;
state.setReturnValue(MinimalJitResultToValue(result)); state.setReturnValue(MinimalJitResultToValue(result));