Skip to content

Commit

Permalink
Merge pull request #3327 from Sonicadvance1/remove_syscall_indirection
Browse files Browse the repository at this point in the history
Arm64: Removes a vtable indirection in syscalls
  • Loading branch information
Sonicadvance1 committed Jan 5, 2024
2 parents 4b37921 + 266f7fe commit 743df8d
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 12 deletions.
2 changes: 0 additions & 2 deletions FEXCore/Source/Interface/Context/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,4 @@ namespace FEXCore::Context {
std::atomic<bool> HasCustomIRHandlers{};
fextl::unordered_map<uint64_t, std::tuple<CustomIREntrypointHandler, void *, void *>> CustomIRHandlers;
};

uint64_t HandleSyscall(FEXCore::HLE::SyscallHandler *Handler, FEXCore::Core::CpuStateFrame *Frame, FEXCore::HLE::SyscallArguments *Args);
}
6 changes: 0 additions & 6 deletions FEXCore/Source/Interface/Core/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1281,12 +1281,6 @@ namespace FEXCore::Context {
HasCustomIRHandlers = !CustomIRHandlers.empty();
}

uint64_t HandleSyscall(FEXCore::HLE::SyscallHandler *Handler, FEXCore::Core::CpuStateFrame *Frame, FEXCore::HLE::SyscallArguments *Args) {
uint64_t Result{};
Result = Handler->HandleSyscall(Frame, Args);
return Result;
}

IR::AOTIRCacheEntry *ContextImpl::LoadAOTIRCacheEntry(const fextl::string &filename) {
auto rv = IRCaptureCache.LoadAOTIRCacheEntry(filename);
return rv;
Expand Down
8 changes: 6 additions & 2 deletions FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ desc: Main glue logic of the arm64 splatter backend
#include <FEXCore/Utils/CompilerDefs.h>
#include <FEXCore/Utils/EnumUtils.h>
#include <FEXCore/Utils/Profiler.h>
#include <FEXCore/HLE/SyscallHandler.h>

#include "Interface/Core/Interpreter/InterpreterOps.h"

Expand Down Expand Up @@ -574,8 +575,11 @@ Arm64JITCore::Arm64JITCore(FEXCore::Context::ContextImpl *ctx, FEXCore::Core::In
Common.XCRFunction = PMF.GetConvertedPointer();
}

Common.SyscallHandlerObj = reinterpret_cast<uint64_t>(CTX->SyscallHandler);
Common.SyscallHandlerFunc = reinterpret_cast<uint64_t>(FEXCore::Context::HandleSyscall);
{
FEXCore::Utils::MemberFunctionToPointerCast PMF(&FEXCore::HLE::SyscallHandler::HandleSyscall);
Common.SyscallHandlerObj = reinterpret_cast<uint64_t>(CTX->SyscallHandler);
Common.SyscallHandlerFunc = PMF.GetVTableEntry(CTX->SyscallHandler);
}
Common.ExitFunctionLink = reinterpret_cast<uintptr_t>(&Context::ContextImpl::ThreadExitFunctionLink<Arm64JITCore_ExitFunctionLink>);

// Fill in the fallback handlers
Expand Down
32 changes: 30 additions & 2 deletions FEXCore/Source/Utils/MemberFunctionToPointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,52 @@ class MemberFunctionToPointerCast final {
public:
MemberFunctionToPointerCast(PointerToMemberType Function) {
memcpy(&PMF, &Function, sizeof(PMF));
}

uintptr_t GetConvertedPointer() const {
#ifdef _M_X86_64
// Itanium C++ ABI (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#member-function-pointers)
// Low bit of ptr specifies if this Member function pointer is virtual or not
// Throw an assert if we were trying to cast a virtual member
LOGMAN_THROW_AA_FMT((PMF.ptr & 1) == 0, "C++ Pointer-To-Member representation didn't have low bit set to 0. Are you trying to cast a virtual member?");
#elif defined(_M_ARM_64 )
#elif defined(_M_ARM_64)
// C++ ABI for the Arm 64-bit Architecture (IHI 0059E)
// 4.2.1 Representation of pointer to member function
// Differs from Itanium specification
LOGMAN_THROW_AA_FMT(PMF.adj == 0, "C++ Pointer-To-Member representation didn't have adj == 0. Are you trying to cast a virtual member?");
#else
#error Don't know how to cast Member to function here. Likely just Itanium
#endif
return PMF.ptr;
}

uintptr_t GetConvertedPointer() const {
// Gets the vtable entry position of a virtual member function.
size_t GetVTableOffset() const {
#ifdef _M_X86_64
// Itanium C++ ABI (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#member-function-pointers)
// Low bit of ptr specifies if this Member function pointer is virtual or not
// Throw an assert if we are not loading a virtual member.
LOGMAN_THROW_AA_FMT((PMF.ptr & 1) == 1, "C++ Pointer-To-Member representation didn't have low bit set to 1. This cast only works for virtual members.");
return PMF.ptr & ~1ULL;
#elif defined(_M_ARM_64)
// C++ ABI for the Arm 64-bit Architecture (IHI 0059E)
// 4.2.1 Representation of pointer to member function
// Differs from Itanium specification
LOGMAN_THROW_AA_FMT((PMF.adj & 1) == 1, "C++ Pointer-To-Member representation didn't have adj == 1. This cast only works for virtual members.");
return PMF.ptr;
#else
#error Don't know how to cast Member to function here. Likely just Itanium
#endif
}

// Gets the pointer to the vtable entry for the object passed it.
template<typename Class>
uintptr_t GetVTableEntry(Class *VirtualClass) const {
// VTable is always stored at the beginning of a class object.
uintptr_t *VTable = *reinterpret_cast<uintptr_t**>(VirtualClass);

size_t Offset = GetVTableOffset() / sizeof(void*);
return VTable[Offset];
}

private:
Expand Down

0 comments on commit 743df8d

Please sign in to comment.