diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp index a0adcb0ef..336184d52 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp @@ -61,7 +61,7 @@ void JITCore::Op_NoOp(FEXCore::IR::IROp_Header *IROp, uint32_t Node) { } JITCore::JITCore(FEXCore::Context::Context *ctx, FEXCore::Core::InternalThreadState *Thread) - : vixl::aarch64::MacroAssembler(1024 * 1024 * 128, vixl::aarch64::PositionDependentCode) + : vixl::aarch64::MacroAssembler(MAX_CODE_SIZE, vixl::aarch64::PositionDependentCode) , CTX {ctx} , State {Thread} #if _M_X86_64 @@ -97,6 +97,9 @@ JITCore::JITCore(FEXCore::Context::Context *ctx, FEXCore::Core::InternalThreadSt CPU.SetUp(); SetAllowAssembler(true); CreateCustomDispatch(Thread); + GenerateDispatchHelpers(); + + ConstantCodeCacheOffset = GetCursorOffset(); uint32_t NumUsedGPRs = NumGPRs; uint32_t NumUsedGPRPairs = NumGPRPairs; @@ -138,6 +141,17 @@ JITCore::JITCore(FEXCore::Context::Context *ctx, FEXCore::Core::InternalThreadSt RegisterVectorHandlers(); } +void JITCore::ClearCache() { + // Get the backing code buffer + auto Buffer = GetBuffer(); + + // Rewind the code buffer's cursor back to just after the helpers + Buffer->Rewind(ConstantCodeCacheOffset); + + // Make sure to set internal state as clean + Buffer->SetClean(); +} + JITCore::~JITCore() { } @@ -203,7 +217,7 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const using namespace aarch64; JumpTargets.clear(); CurrentIR = IR; - + uint32_t SSACount = CurrentIR->GetSSACount(); uintptr_t ListBegin = CurrentIR->GetListData(); uintptr_t DataBegin = CurrentIR->GetData(); @@ -217,6 +231,12 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const return State->IntBackend->CompileCode(IR, DebugData); } + // Fairly excessive buffer range to make sure we don't overflow + uint32_t BufferRange = SSACount * 16; + if ((GetCursorOffset() + BufferRange) > MAX_CODE_SIZE) { + State->CTX->ClearCodeCache(State, HeaderOp->Entry); + } + LogMan::Throw::A(RAPass->HasFullRA(), "Arm64 JIT only works with RA"); SpillSlots = RAPass->SpillSlots(); @@ -298,7 +318,6 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const FinalizeCode(); - auto CodeEnd = Buffer->GetOffsetAddress(GetCursorOffset()); CPU.EnsureIAndDCacheCoherency(reinterpret_cast(Entry), Buffer->GetOffsetAddress(GetCursorOffset()) - reinterpret_cast(Entry)); #if _M_X86_64 @@ -480,6 +499,11 @@ void JITCore::CreateCustomDispatch(FEXCore::Core::InternalThreadState *Thread) { //CustomDispatchGenerated = true; } + +void JITCore::GenerateDispatchHelpers() { + // Nothing here yet +} + FEXCore::CPU::CPUBackend *CreateJITCore(FEXCore::Context::Context *ctx, FEXCore::Core::InternalThreadState *Thread) { return new JITCore(ctx, Thread); } diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h index 3e6e14f42..2dc244a2d 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h @@ -100,6 +100,8 @@ public: } #endif + void ClearCache() override; + private: FEXCore::Context::Context *CTX; FEXCore::Core::InternalThreadState *State; @@ -128,6 +130,8 @@ private: constexpr static uint8_t RA_64 = 1; constexpr static uint8_t RA_FPR = 2; + static constexpr uint32_t MAX_CODE_SIZE = 1024 * 1024 * 128; + template aarch64::Register GetReg(uint32_t Node); @@ -169,6 +173,13 @@ private: void LoadConstant(vixl::aarch64::Register Reg, uint64_t Constant); void CreateCustomDispatch(FEXCore::Core::InternalThreadState *Thread); + void GenerateDispatchHelpers(); + ptrdiff_t ConstantCodeCacheOffset{}; + /** + * @name Dispatch Helper functions + * @{ */ + /** @} */ + bool CustomDispatchGenerated {false}; using CustomDispatch = void(*)(FEXCore::Core::InternalThreadState *Thread); CustomDispatch DispatchPtr{};