mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 13:00:41 +02:00
Specifically this tries to avoid changing much behaviour and keeping the code the same. So most of it is a direct transplant without any modifications. This is step one of the process so I can start logically separating the code and making sense of it. This mostly moves the AOT IR handling to its own independent file for separation. Cleaning up the Core.cpp file quite heavily. Two minor behaviour changes that got mixed up with this change. The first one is an ASAN fix. This is the FEX_PACKED on the RegisterAllocationData class. I didn't want to change too heavily how this serialization works but I wanted to resolve the ASAN error. This may change in the coming work. Problem was the padding betwene the uint32_t and the PhysicalRegister wasn't initialized but was being read. Since it is all uint8_t types afterwards there isn't a perf issue here. Second fix was a crash that occurs if you're attempting to both capture and load IR on the same run. This is a quirk where we mmap the original IR file. Then on shutdown the IR file is getting saved. At which point we open the IR file again, truncate it, and start serializing all of the IR data. The truncation makes it so our mmap of the file is no longer resident, resulting in a crash when reading our IR cache from the mmap region. Now open a temporary file and rename it after storing. Resolves the crash but still doesn't really solve the issue of multiple processes overwriting the same IR files.
163 lines
4.7 KiB
C++
163 lines
4.7 KiB
C++
#pragma once
|
|
|
|
#include <FEXCore/Config/Config.h>
|
|
|
|
#include <atomic>
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <fstream>
|
|
#include <memory>
|
|
#include <map>
|
|
#include <unordered_map>
|
|
#include <shared_mutex>
|
|
#include <queue>
|
|
|
|
namespace FEXCore::Core {
|
|
struct DebugData;
|
|
}
|
|
|
|
namespace FEXCore::IR {
|
|
class RegisterAllocationData;
|
|
class IRListView;
|
|
|
|
constexpr auto COOKIE_VERSION = [](const char CookieText[4], uint32_t Version) {
|
|
uint64_t Cookie = Version;
|
|
Cookie <<= 32;
|
|
|
|
// Make the cookie text be the lower bits
|
|
Cookie |= CookieText[3];
|
|
Cookie <<= 8;
|
|
Cookie |= CookieText[2];
|
|
Cookie <<= 8;
|
|
Cookie |= CookieText[1];
|
|
Cookie <<= 8;
|
|
Cookie |= CookieText[0];
|
|
|
|
return Cookie;
|
|
};
|
|
constexpr static uint32_t AOTIR_VERSION = 0x0000'00004;
|
|
constexpr static uint64_t AOTIR_COOKIE = COOKIE_VERSION("FEXI", AOTIR_VERSION);
|
|
|
|
struct AOTIRInlineEntry {
|
|
uint64_t GuestHash;
|
|
uint64_t GuestLength;
|
|
|
|
/* RAData followed by IRData */
|
|
uint8_t InlineData[0];
|
|
|
|
IR::RegisterAllocationData *GetRAData();
|
|
IR::IRListView *GetIRData();
|
|
};
|
|
|
|
struct AOTIRInlineIndexEntry {
|
|
uint64_t GuestStart;
|
|
uint64_t DataOffset;
|
|
};
|
|
|
|
struct AOTIRInlineIndex {
|
|
uint64_t Count;
|
|
uint64_t DataBase;
|
|
AOTIRInlineIndexEntry Entries[0];
|
|
|
|
AOTIRInlineEntry *Find(uint64_t GuestStart);
|
|
AOTIRInlineEntry *GetInlineEntry(uint64_t DataOffset);
|
|
};
|
|
|
|
struct AOTIRCaptureCacheEntry {
|
|
std::unique_ptr<std::ofstream> Stream;
|
|
std::map<uint64_t, uint64_t> Index;
|
|
|
|
void AppendAOTIRCaptureCache(uint64_t GuestRIP, uint64_t Start, uint64_t Length, uint64_t Hash, FEXCore::IR::IRListView *IRList, FEXCore::IR::RegisterAllocationData *RAData);
|
|
};
|
|
|
|
struct AOTIRCacheEntry {
|
|
AOTIRInlineIndex *Array;
|
|
void *mapping;
|
|
size_t size;
|
|
};
|
|
|
|
using AOTCacheType = std::unordered_map<std::string, FEXCore::IR::AOTIRCacheEntry>;
|
|
bool LoadAOTIRCache(AOTCacheType *AOTIRCache, int streamfd);
|
|
|
|
class AOTIRCaptureCache final {
|
|
public:
|
|
|
|
AOTIRCaptureCache(FEXCore::Context::Context *ctx) : CTX {ctx} {}
|
|
~AOTIRCaptureCache();
|
|
|
|
void FinalizeAOTIRCache();
|
|
void AOTIRCaptureCacheWriteoutQueue_Flush();
|
|
void AOTIRCaptureCacheWriteoutQueue_Append(const std::function<void()> &fn);
|
|
void WriteFilesWithCode(std::function<void(const std::string& fileid, const std::string& filename)> Writer);
|
|
|
|
struct PreGenerateIRFetchResult {
|
|
FEXCore::IR::IRListView *IRList {};
|
|
FEXCore::IR::RegisterAllocationData *RAData {};
|
|
FEXCore::Core::DebugData *DebugData {};
|
|
uint64_t StartAddr {};
|
|
uint64_t Length {};
|
|
bool GeneratedIR {};
|
|
};
|
|
[[nodiscard]] PreGenerateIRFetchResult PreGenerateIRFetch(uint64_t GuestRIP, FEXCore::IR::IRListView *IRList);
|
|
|
|
bool PostCompileCode(FEXCore::Core::InternalThreadState *Thread,
|
|
void* CodePtr,
|
|
uint64_t GuestRIP,
|
|
uint64_t StartAddr,
|
|
uint64_t Length,
|
|
FEXCore::IR::RegisterAllocationData *RAData,
|
|
FEXCore::IR::IRListView *IRList,
|
|
FEXCore::Core::DebugData *DebugData,
|
|
bool GeneratedIR,
|
|
bool DecrementRefCount);
|
|
|
|
void AddNamedRegion(uintptr_t Base, uintptr_t Size, uintptr_t Offset, const std::string &filename);
|
|
void RemoveNamedRegion(uintptr_t Base, uintptr_t Size);
|
|
|
|
// Callbacks
|
|
void SetAOTIRLoader(std::function<int(const std::string&)> CacheReader) {
|
|
AOTIRLoader = CacheReader;
|
|
}
|
|
|
|
void SetAOTIRWriter(std::function<std::unique_ptr<std::ofstream>(const std::string&)> CacheWriter) {
|
|
AOTIRWriter = CacheWriter;
|
|
}
|
|
|
|
void SetAOTIRRenamer(std::function<void(const std::string&)> CacheRenamer) {
|
|
AOTIRRenamer = CacheRenamer;
|
|
}
|
|
|
|
private:
|
|
FEXCore::Context::Context *CTX;
|
|
|
|
std::shared_mutex AOTIRCacheLock;
|
|
std::shared_mutex AOTIRCaptureCacheWriteoutLock;
|
|
std::atomic<bool> AOTIRCaptureCacheWriteoutFlusing;
|
|
|
|
std::queue<std::function<void()>> AOTIRCaptureCacheWriteoutQueue;
|
|
|
|
std::map<std::string, std::string> FilesWithCode;
|
|
|
|
struct AddrToFileEntry {
|
|
uint64_t Start;
|
|
uint64_t Len;
|
|
uint64_t Offset;
|
|
std::string fileid;
|
|
std::string filename;
|
|
void *CachedFileEntry;
|
|
bool ContainsCode;
|
|
};
|
|
|
|
using AddrToFileMapType = std::map<uint64_t, AddrToFileEntry>;
|
|
AddrToFileMapType AddrToFile;
|
|
FEXCore::IR::AOTCacheType AOTIRCache;
|
|
|
|
std::function<int(const std::string&)> AOTIRLoader;
|
|
std::function<std::unique_ptr<std::ofstream>(const std::string&)> AOTIRWriter;
|
|
std::function<void(const std::string&)> AOTIRRenamer;
|
|
std::unordered_map<std::string, FEXCore::IR::AOTIRCaptureCacheEntry> AOTIRCaptureCacheMap;
|
|
|
|
AddrToFileMapType::iterator FindAddrForFile(uint64_t Entry, uint64_t Length);
|
|
};
|
|
}
|