Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEXCore: Decompose some std::function usage to regular pointers #3361

Merged
merged 1 commit into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions FEXCore/Source/Interface/Context/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ namespace FEXCore::Context {
MODE_SINGLESTEP = 1,
};

struct ExitFunctionLinkData {
uint64_t HostBranch;
uint64_t GuestRIP;
};

using BlockDelinkerFunc = void(*)(FEXCore::Core::CpuStateFrame *Frame, FEXCore::Context::ExitFunctionLinkData *Record);

class ContextImpl final : public FEXCore::Context::Context {
public:
// Context base class implementation.
Expand Down Expand Up @@ -274,12 +281,7 @@ namespace FEXCore::Context {
void SignalThread(FEXCore::Core::InternalThreadState *Thread, FEXCore::Core::SignalEvent Event);

static void ThreadRemoveCodeEntry(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestRIP);
static void ThreadAddBlockLink(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestDestination, uintptr_t HostLink, const std::function<void()> &delinker);

struct ExitFunctionLinkData {
uint64_t HostBranch;
uint64_t GuestRIP;
};
static void ThreadAddBlockLink(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestDestination, FEXCore::Context::ExitFunctionLinkData *HostLink, const BlockDelinkerFunc &delinker);

template<auto Fn>
static uint64_t ThreadExitFunctionLink(FEXCore::Core::CpuStateFrame *Frame, ExitFunctionLinkData *Record) {
Expand Down
4 changes: 2 additions & 2 deletions FEXCore/Source/Interface/Core/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1237,7 +1237,7 @@ namespace FEXCore::Context {
}
}

void ContextImpl::ThreadAddBlockLink(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestDestination, uintptr_t HostLink, const std::function<void()> &delinker) {
void ContextImpl::ThreadAddBlockLink(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestDestination, FEXCore::Context::ExitFunctionLinkData *HostLink, const FEXCore::Context::BlockDelinkerFunc &delinker) {
auto lk = GuardSignalDeferringSection<std::shared_lock>(static_cast<ContextImpl*>(Thread->CTX)->CodeInvalidationMutex, Thread);

Thread->LookupCache->AddBlockLink(GuestDestination, HostLink, delinker);
Expand All @@ -1249,7 +1249,7 @@ namespace FEXCore::Context {
std::lock_guard<std::recursive_mutex> lk(Thread->LookupCache->WriteLock);

Thread->DebugStore.erase(GuestRIP);
Thread->LookupCache->Erase(GuestRIP);
Thread->LookupCache->Erase(Thread->CurrentFrame, GuestRIP);
}

CustomIRResult ContextImpl::AddCustomIREntrypoint(uintptr_t Entrypoint, CustomIREntrypointHandler Handler, void *Creator, void *Data) {
Expand Down
38 changes: 22 additions & 16 deletions FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,24 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) {
}


static uint64_t Arm64JITCore_ExitFunctionLink(FEXCore::Core::CpuStateFrame *Frame, FEXCore::Context::ContextImpl::ExitFunctionLinkData *Record) {
static void DirectBlockDelinker(FEXCore::Core::CpuStateFrame *Frame, FEXCore::Context::ExitFunctionLinkData *Record) {
auto LinkerAddress = Frame->Pointers.Common.ExitFunctionLinker;
uintptr_t branch = (uintptr_t)(Record) - 8;
FEXCore::ARMEmitter::Emitter emit((uint8_t*)(branch), 8);
FEXCore::ARMEmitter::ForwardLabel l_BranchHost;
emit.ldr(FEXCore::ARMEmitter::XReg::x0, &l_BranchHost);
emit.blr(FEXCore::ARMEmitter::Reg::r0);
emit.Bind(&l_BranchHost);
emit.dc64(LinkerAddress);
FEXCore::ARMEmitter::Emitter::ClearICache((void*)branch, 8);
}

static void IndirectBlockDelinker(FEXCore::Core::CpuStateFrame *Frame, FEXCore::Context::ExitFunctionLinkData *Record) {
auto LinkerAddress = Frame->Pointers.Common.ExitFunctionLinker;
Record->HostBranch = LinkerAddress;
}

static uint64_t Arm64JITCore_ExitFunctionLink(FEXCore::Core::CpuStateFrame *Frame, FEXCore::Context::ExitFunctionLinkData *Record) {
auto Thread = Frame->Thread;
auto GuestRip = Record->GuestRIP;

Expand All @@ -493,34 +510,23 @@ static uint64_t Arm64JITCore_ExitFunctionLink(FEXCore::Core::CpuStateFrame *Fram
}

uintptr_t branch = (uintptr_t)(Record) - 8;
auto LinkerAddress = Frame->Pointers.Common.ExitFunctionLinker;

auto offset = HostCode/4 - branch/4;
if (vixl::IsInt26(offset)) {
// optimal case - can branch directly
// patch the code
FEXCore::ARMEmitter::Emitter emit((uint8_t*)(branch), 24);
FEXCore::ARMEmitter::Emitter emit((uint8_t*)(branch), 4);
emit.b(offset);
FEXCore::ARMEmitter::Emitter::ClearICache((void*)branch, 24);
FEXCore::ARMEmitter::Emitter::ClearICache((void*)branch, 4);

// Add de-linking handler
Thread->LookupCache->AddBlockLink(GuestRip, (uintptr_t)Record, [branch, LinkerAddress]{
FEXCore::ARMEmitter::Emitter emit((uint8_t*)(branch), 24);
FEXCore::ARMEmitter::ForwardLabel l_BranchHost;
emit.ldr(FEXCore::ARMEmitter::XReg::x0, &l_BranchHost);
emit.blr(FEXCore::ARMEmitter::Reg::r0);
emit.Bind(&l_BranchHost);
emit.dc64(LinkerAddress);
FEXCore::ARMEmitter::Emitter::ClearICache((void*)branch, 24);
});
Thread->LookupCache->AddBlockLink(GuestRip, Record, DirectBlockDelinker);
} else {
// fallback case - do a soft-er link by patching the pointer
Record->HostBranch = HostCode;

// Add de-linking handler
Thread->LookupCache->AddBlockLink(GuestRip, (uintptr_t)Record, [Record, LinkerAddress]{
Record->HostBranch = LinkerAddress;
});
Thread->LookupCache->AddBlockLink(GuestRip, Record, IndirectBlockDelinker);
}

return HostCode;
Expand Down
15 changes: 7 additions & 8 deletions FEXCore/Source/Interface/Core/LookupCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,15 @@ class LookupCache {
L1Entry.HostCode = (uintptr_t)HostCode;
}

void Erase(uint64_t Address) {
void Erase(FEXCore::Core::CpuStateFrame *Frame, uint64_t Address) {

std::lock_guard<std::recursive_mutex> lk(WriteLock);

// Sever any links to this block
auto lower = BlockLinks->lower_bound({Address, 0});
auto upper = BlockLinks->upper_bound({Address, UINTPTR_MAX});
auto lower = BlockLinks->lower_bound({Address, nullptr});
auto upper = BlockLinks->upper_bound({Address, reinterpret_cast<FEXCore::Context::ExitFunctionLinkData *>(UINTPTR_MAX)});
for (auto it = lower; it != upper; it = BlockLinks->erase(it)) {
it->second();
it->second(Frame, it->first.HostLink);
}

// Remove from BlockList
Expand Down Expand Up @@ -141,8 +141,7 @@ class LookupCache {
BlockPointers[PageOffset].HostCode = 0;
}


void AddBlockLink(uint64_t GuestDestination, uintptr_t HostLink, const std::function<void()> &delinker) {
void AddBlockLink(uint64_t GuestDestination, FEXCore::Context::ExitFunctionLinkData * HostLink, const FEXCore::Context::BlockDelinkerFunc &delinker) {
std::lock_guard<std::recursive_mutex> lk(WriteLock);

BlockLinks->insert({{GuestDestination, HostLink}, delinker});
Expand Down Expand Up @@ -224,7 +223,7 @@ class LookupCache {

struct BlockLinkTag {
uint64_t GuestDestination;
uintptr_t HostLink;
FEXCore::Context::ExitFunctionLinkData *HostLink;

bool operator <(const BlockLinkTag& other) const {
if (GuestDestination < other.GuestDestination)
Expand All @@ -243,7 +242,7 @@ class LookupCache {
//
// This makes `BlockLinks` look like a raw pointer that could memory leak, but since it is backed by the MBR, it won't.
std::pmr::monotonic_buffer_resource BlockLinks_mbr;
using BlockLinksMapType = std::pmr::map<BlockLinkTag, std::function<void()>>;
using BlockLinksMapType = std::pmr::map<BlockLinkTag, FEXCore::Context::BlockDelinkerFunc>;
fextl::unique_ptr<std::pmr::polymorphic_allocator<std::byte>> BlockLinks_pma;
BlockLinksMapType *BlockLinks;

Expand Down
Loading