diff --git a/External/FEXCore/Source/Interface/Context/Context.cpp b/External/FEXCore/Source/Interface/Context/Context.cpp index 7cbb0a0fc..2f25596f7 100644 --- a/External/FEXCore/Source/Interface/Context/Context.cpp +++ b/External/FEXCore/Source/Interface/Context/Context.cpp @@ -142,7 +142,7 @@ namespace FEXCore::Context { return CTX->CPUID.RunFunction(Function, Leaf); } - void SetAOTIRLoader(FEXCore::Context::Context *CTX, std::function(const std::string&)> CacheReader) { + void SetAOTIRLoader(FEXCore::Context::Context *CTX, std::function CacheReader) { CTX->AOTIRLoader = CacheReader; } diff --git a/External/FEXCore/Source/Interface/Context/Context.h b/External/FEXCore/Source/Interface/Context/Context.h index c6d511bd2..5d0ffcb6b 100644 --- a/External/FEXCore/Source/Interface/Context/Context.h +++ b/External/FEXCore/Source/Interface/Context/Context.h @@ -52,6 +52,39 @@ namespace FEXCore::Context { MODE_SINGLESTEP = 1, }; + struct AOTIRCaptureCacheEntry { + uint64_t start; + uint64_t len; + uint64_t crc; + IR::IRListView *IR; + IR::RegisterAllocationData *RAData; + }; + + 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 Context { friend class FEXCore::HLE::SyscallHandler; #ifdef JIT_ARM64 @@ -113,15 +146,14 @@ namespace FEXCore::Context { std::function CustomExitHandler; struct AOTIRCacheEntry { - uint64_t start; - uint64_t len; - uint64_t crc; - IR::IRListView *IR; - IR::RegisterAllocationData *RAData; + AOTIRInlineIndex *Array; + void *mapping; + size_t size; }; - std::function(const std::string&)> AOTIRLoader; - std::unordered_map> AOTIRCache; + std::unordered_map AOTIRCache; + std::function AOTIRLoader; + std::unordered_map> AOTIRCaptureCache; struct AddrToFileEntry { uint64_t Start; @@ -183,7 +215,7 @@ namespace FEXCore::Context { std::tuple CompileCode(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestRIP); uintptr_t CompileBlock(FEXCore::Core::CpuStateFrame *Frame, uint64_t GuestRIP); - bool LoadAOTIRCache(std::istream &stream); + bool LoadAOTIRCache(int streamfd); bool WriteAOTIRCache(std::function(const std::string&)> CacheWriter); // Used for thread creation from syscalls void InitializeCompiler(FEXCore::Core::InternalThreadState* State, bool CompileThread); diff --git a/External/FEXCore/Source/Interface/Core/Core.cpp b/External/FEXCore/Source/Interface/Core/Core.cpp index 3a0a627bd..03343362c 100644 --- a/External/FEXCore/Source/Interface/Core/Core.cpp +++ b/External/FEXCore/Source/Interface/Core/Core.cpp @@ -30,12 +30,16 @@ $end_info$ #include #include "Interface/HLE/Thunks/Thunks.h" +#include "FEXCore/Utils/Allocator.h" #include #include #include #include #include +#include +#include +#include #include "Interface/Core/GdbServer.h" @@ -172,13 +176,17 @@ namespace FEXCore::Context { Threads.clear(); } - // AOTIRCache needs manual clear - for (auto &Mod: AOTIRCache) { + // AOTIRCaptureCache needs manual clear + for (auto &Mod: AOTIRCaptureCache) { for (auto &Entry: Mod.second) { delete Entry.second.IR; free(Entry.second.RAData); } } + + for (auto &Mod: AOTIRCache) { + FEXCore::Allocator::munmap(Mod.second.mapping, Mod.second.size); + } } bool Context::InitCore(FEXCore::CodeLoader *Loader) { @@ -776,6 +784,41 @@ namespace FEXCore::Context { return {IRList, RAData.release(), TotalInstructions, TotalInstructionsLength, Thread->FrontendDecoder->DecodedMinAddress, Thread->FrontendDecoder->DecodedMaxAddress - Thread->FrontendDecoder->DecodedMinAddress }; } + AOTIRInlineEntry *AOTIRInlineIndex::GetInlineEntry(uint64_t DataOffset) { + uintptr_t This = (uintptr_t)this; + + return (AOTIRInlineEntry*)(This + DataBase + DataOffset); + } + + AOTIRInlineEntry *AOTIRInlineIndex::Find(uint64_t GuestStart) { + ssize_t l = 0; + ssize_t r = Count - 1; + + while (l <= r) { + size_t m = l + (r - l) / 2; + + if (Entries[m].GuestStart == GuestStart) + return GetInlineEntry(Entries[m].DataOffset); + else if (Entries[m].GuestStart < GuestStart) + l = m + 1; + else + r = m - 1; + } + + return nullptr; + } + + IR::RegisterAllocationData *AOTIRInlineEntry::GetRAData() { + return (IR::RegisterAllocationData *)InlineData; + } + + IR::IRListView *AOTIRInlineEntry::GetIRData() { + auto RAData = GetRAData(); + auto Offset = RAData->Size(RAData->MapCount); + + return (IR::IRListView *)&InlineData[Offset]; + } + std::tuple Context::CompileCode(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestRIP) { FEXCore::IR::IRListView *IRList {}; FEXCore::Core::DebugData *DebugData {}; @@ -804,28 +847,36 @@ namespace FEXCore::Context { auto file = AddrToFile.lower_bound(GuestRIP); if (file != AddrToFile.begin()) { --file; - auto Mod = (decltype(AOTIRCache)::value_type::second_type*) file->second.CachedFileEntry; + auto Mod = (AOTIRInlineIndex*)file->second.CachedFileEntry; if (Mod == nullptr) { - file->second.CachedFileEntry = Mod = &AOTIRCache[file->second.fileid]; + file->second.CachedFileEntry = Mod = AOTIRCache[file->second.fileid].Array; } - auto AOTEntry = Mod->find(GuestRIP - file->second.Start + file->second.Offset); + if (Mod != nullptr) + { + auto AOTEntry = Mod->Find(GuestRIP - file->second.Start + file->second.Offset); - if (AOTEntry != Mod->end()) { - // verify hash - auto MappedStart = AOTEntry->second.start + file->second.Start - file->second.Offset; - auto hash = XXH3_64bits((void*)MappedStart, AOTEntry->second.len); - if (hash == AOTEntry->second.crc) { - IRList = AOTEntry->second.IR; - //LogMan::Msg::D("using %s + %lx -> %lx\n", file->second.fileid.c_str(), AOTEntry->first, GuestRIP); + if (AOTEntry) { + // verify hash + auto MappedStart = GuestRIP; + auto hash = XXH3_64bits((void*)MappedStart, AOTEntry->GuestLength); + if (hash == AOTEntry->GuestHash) { + IRList = AOTEntry->GetIRData(); + //LogMan::Msg::D("using %s + %lx -> %lx\n", file->second.fileid.c_str(), AOTEntry->first, GuestRIP); - RAData = AOTEntry->second.RAData; - DebugData = new FEXCore::Core::DebugData(); - StartAddr = MappedStart; - Length = AOTEntry->second.len; - GeneratedIR = true; + RAData = AOTEntry->GetRAData();; + DebugData = new FEXCore::Core::DebugData(); + StartAddr = MappedStart; + Length = AOTEntry->GuestLength; + + GeneratedIR = true; + } else { + LogMan::Msg::I("AOTIR: hash check failed %lx\n", MappedStart); + } + } else { + //LogMan::Msg::I("AOTIR: Failed to find %lx, %lx, %s\n", GuestRIP, GuestRIP - file->second.Start + file->second.Offset, file->second.fileid.c_str()); } } } @@ -857,87 +908,49 @@ namespace FEXCore::Context { return { Thread->CPUBackend->CompileCode(GuestRIP, IRList, DebugData, RAData), IRList, DebugData, RAData, GeneratedIR, StartAddr, Length}; } - bool Context::LoadAOTIRCache(std::istream &stream) { - std::lock_guard lk(AOTIRCacheLock); + static bool readAll(int fd, void *data, size_t size) { + int rv = read(fd, data, size); + + if (rv != size) + return false; + else + return true; + } + + bool Context::LoadAOTIRCache(int streamfd) { uint64_t tag; - stream.read((char*)&tag, sizeof(tag)); - if (!stream || tag != 0xDEADBEEFC0D30002) + + if (!readAll(streamfd, (char*)&tag, sizeof(tag)) || tag != 0xDEADBEEFC0D30003) + return false; + + std::string Module; + uint64_t ModSize; + + if (!readAll(streamfd, (char*)&ModSize, sizeof(ModSize))) return false; - uint64_t ModCount; - stream.read((char*)&ModCount, sizeof(ModCount)); - if (!stream) + Module.resize(ModSize); + if (!readAll(streamfd, (char*)&Module[0], Module.size())) return false; - for (int ModIndex = 0; ModIndex < ModCount; ModIndex++) { - std::string Module; - uint64_t ModSize; - stream.read((char*)&ModSize, sizeof(ModSize)); - if (!stream) - return false; + struct stat fileinfo; + if (fstat(streamfd, &fileinfo) < 0) + return false; + size_t Size = (fileinfo.st_size + 4095) & ~4095; - Module.resize(ModSize); - stream.read((char*)&Module[0], Module.size()); - if (!stream) - return false; + void *FilePtr = FEXCore::Allocator::mmap(nullptr, Size, PROT_READ, MAP_SHARED, streamfd, 0); - auto &Mod = AOTIRCache[Module]; + if (FilePtr == MAP_FAILED) + return false; - uint64_t FnCount; - stream.read((char*)&FnCount, sizeof(FnCount)); - if (!stream) - return false; + auto Array = (AOTIRInlineIndex *)((char*)FilePtr + sizeof(tag) + sizeof(ModSize) + ((ModSize+31) & ~31)); - LogMan::Msg::D("AOTIR: Module %s has %ld functions", Module.c_str(), FnCount); - for (int FnIndex = 0; FnIndex < FnCount; FnIndex++) { - uint64_t addr, start, crc, len; - stream.read((char*)&addr, sizeof(addr)); - if (!stream) - return false; + AOTIRCache.insert({Module, {Array, FilePtr, Size}}); - stream.read((char*)&start, sizeof(start)); - if (!stream) - return false; - stream.read((char*)&len, sizeof(len)); - if (!stream) - return false; - stream.read((char*)&crc, sizeof(crc)); - if (!stream) - return false; - auto IR = new IR::IRListView(stream); - if (!stream) { - delete IR; - return false; - } - uint64_t RASize; - stream.read((char*)&RASize, sizeof(RASize)); - if (!stream) { - delete IR; - return false; - } - IR::RegisterAllocationData *RAData = (IR::RegisterAllocationData *)malloc(IR::RegisterAllocationData::Size(RASize)); - RAData->MapCount = RASize; - - stream.read((char*)&RAData->Map[0], sizeof(RAData->Map[0]) * RASize); - - if (!stream) { - delete IR; - return false; - } - stream.read((char*)&RAData->SpillSlotCount, sizeof(RAData->SpillSlotCount)); - if (!stream) { - delete IR; - return false; - } - - IR->SetShared(true); - RAData->IsShared = true; - - Mod.insert({addr, {start, len, crc, IR, RAData}}); - } - } + LogMan::Msg::D("AOTIR: Module %s has %ld functions", Module.c_str(), Array->Count); return true; + } bool Context::WriteAOTIRCache(std::function(const std::string&)> CacheWriter) { @@ -945,7 +958,7 @@ namespace FEXCore::Context { bool rv = true; - for (auto AOTModule: AOTIRCache) { + for (auto AOTModule: AOTIRCaptureCache) { if (AOTModule.second.size() == 0) { continue; } @@ -954,28 +967,59 @@ namespace FEXCore::Context { if (!*stream) { rv = false; } - uint64_t tag = 0xDEADBEEFC0D30002; + uint64_t tag = 0xDEADBEEFC0D30003; stream->write((char*)&tag, sizeof(tag)); - uint64_t ModCount = 1; - stream->write((char*)&ModCount, sizeof(ModCount)); auto ModSize = AOTModule.first.size(); stream->write((char*)&ModSize, sizeof(ModSize)); stream->write((char*)&AOTModule.first[0], ModSize); + auto Skip = ((ModSize + 31) & ~31) - ModSize; + char Zero = 0; + for (int i = 0; i < Skip; i++) + stream->write(&Zero, 1); + + // AOTIRInlineIndex + + auto FnCount = AOTModule.second.size(); stream->write((char*)&FnCount, sizeof(FnCount)); + size_t DataBase = sizeof(FnCount) + sizeof(DataBase) + FnCount * sizeof(AOTIRInlineIndexEntry); + stream->write((char*)&DataBase, sizeof(DataBase)); + + size_t DataOffset = 0; for (auto entry: AOTModule.second) { + //AOTIRInlineIndexEntry + + // GuestStart stream->write((char*)&entry.first, sizeof(entry.first)); - stream->write((char*)&entry.second.start, sizeof(entry.second.start)); - stream->write((char*)&entry.second.len, sizeof(entry.second.len)); + + // DataOffset + stream->write((char*)&DataOffset, sizeof(DataOffset)); + + + DataOffset += sizeof(entry.second.crc); + DataOffset += sizeof(entry.second.len); + + DataOffset += entry.second.RAData->Size(entry.second.RAData->MapCount); + + DataOffset += entry.second.IR->GetInlineSize(); + } + + // AOTIRInlineEntry + for (auto entry: AOTModule.second) { + //GuestHash stream->write((char*)&entry.second.crc, sizeof(entry.second.crc)); + + //GuestLength + stream->write((char*)&entry.second.len, sizeof(entry.second.len)); + + // RAData (inline) + stream->write((char*)entry.second.RAData, entry.second.RAData->Size(entry.second.RAData->MapCount)); + + // IRData (inline) entry.second.IR->Serialize(*stream); - uint64_t RASize = entry.second.RAData->MapCount; - stream->write((char*)&RASize, sizeof(RASize)); - stream->write((char*)&entry.second.RAData->Map[0], sizeof(entry.second.RAData->Map[0]) * RASize); - stream->write((char*)&entry.second.RAData->SpillSlotCount, sizeof(entry.second.RAData->SpillSlotCount)); } } @@ -1068,7 +1112,7 @@ namespace FEXCore::Context { if (file != AddrToFile.begin()) { --file; if (file->second.Start <= StartAddr && (file->second.Start + file->second.Len) >= (StartAddr + Length)) { - AOTIRCache[file->second.fileid].insert({GuestRIP - file->second.Start + file->second.Offset, {StartAddr - file->second.Start + file->second.Offset, Length, hash, IRList, RAData}}); + AOTIRCaptureCache[file->second.fileid].insert({GuestRIP - file->second.Start + file->second.Offset, {StartAddr - file->second.Start + file->second.Offset, Length, hash, IRList, RAData}}); } } } @@ -1220,18 +1264,22 @@ namespace FEXCore::Context { fileid += Config.ABILocalFlags ? "L" : "l"; fileid += Config.ABINoPF ? "p" : "P"; + std::lock_guard lk(AOTIRCacheLock); + AddrToFile.insert({ Base, { Base, Size, Offset, fileid, nullptr } }); if (Config.AOTIRLoad && !AOTIRCache.contains(fileid) && AOTIRLoader) { - auto stream = AOTIRLoader(fileid); - if (*stream) { - LoadAOTIRCache(*stream); + auto streamfd = AOTIRLoader(fileid); + if (streamfd != -1) { + LoadAOTIRCache(streamfd); + close(streamfd); } } } } void Context::RemoveNamedRegion(uintptr_t Base, uintptr_t Size) { + std::lock_guard lk(AOTIRCacheLock); // TODO: Support partial removing AddrToFile.erase(Base); } diff --git a/External/FEXCore/include/FEXCore/Core/Context.h b/External/FEXCore/include/FEXCore/Core/Context.h index 20c5cc953..cf029cbc1 100644 --- a/External/FEXCore/include/FEXCore/Core/Context.h +++ b/External/FEXCore/include/FEXCore/Core/Context.h @@ -226,7 +226,7 @@ namespace FEXCore::Context { __attribute__((visibility("default"))) void AddNamedRegion(FEXCore::Context::Context *CTX, uintptr_t Base, uintptr_t Length, uintptr_t Offset, const std::string& Name); __attribute__((visibility("default"))) void RemoveNamedRegion(FEXCore::Context::Context *CTX, uintptr_t Base, uintptr_t Length); - __attribute__((visibility("default"))) void SetAOTIRLoader(FEXCore::Context::Context *CTX, std::function(const std::string&)> CacheReader); + __attribute__((visibility("default"))) void SetAOTIRLoader(FEXCore::Context::Context *CTX, std::function CacheReader); __attribute__((visibility("default"))) bool WriteAOTIR(FEXCore::Context::Context *CTX, std::function(const std::string&)> CacheWriter); __attribute__((visibility("default"))) void FlushCodeRange(FEXCore::Core::InternalThreadState *Thread, uint64_t Start, uint64_t Length); } diff --git a/External/FEXCore/include/FEXCore/IR/IntrusiveIRList.h b/External/FEXCore/include/FEXCore/IR/IntrusiveIRList.h index 999f07b01..3b7da1409 100644 --- a/External/FEXCore/include/FEXCore/IR/IntrusiveIRList.h +++ b/External/FEXCore/include/FEXCore/IR/IntrusiveIRList.h @@ -89,77 +89,90 @@ class DualIntrusiveAllocator final { class IRListView final { + enum Flags { + FLAG_IsCopy = 1, + FLAG_Shared = 2, + }; + public: IRListView() = delete; IRListView(IRListView &&) = delete; - IRListView(DualIntrusiveAllocator *Data, bool _IsCopy) : IsCopy(_IsCopy) { + IRListView(DualIntrusiveAllocator *Data, bool _IsCopy) { + SetCopy(_IsCopy); DataSize = Data->DataSize(); ListSize = Data->ListSize(); - if (IsCopy) { - IRData = malloc(DataSize + ListSize); - ListData = reinterpret_cast(reinterpret_cast(IRData) + DataSize); - memcpy(IRData, reinterpret_cast(Data->DataBegin()), DataSize); - memcpy(ListData, reinterpret_cast(Data->ListBegin()), ListSize); + if (_IsCopy) { + IRDataInternal = malloc(DataSize + ListSize); + ListDataInternal = reinterpret_cast(reinterpret_cast(IRDataInternal) + DataSize); + memcpy(IRDataInternal, reinterpret_cast(Data->DataBegin()), DataSize); + memcpy(ListDataInternal, reinterpret_cast(Data->ListBegin()), ListSize); } else { // We are just pointing to the data - IRData = reinterpret_cast(Data->DataBegin()); - ListData = reinterpret_cast(Data->ListBegin()); + IRDataInternal = reinterpret_cast(Data->DataBegin()); + ListDataInternal = reinterpret_cast(Data->ListBegin()); } } - IRListView(IRListView *Old, bool _IsCopy) : IsCopy(_IsCopy) { + IRListView(IRListView *Old, bool _IsCopy) { + SetCopy(_IsCopy); DataSize = Old->DataSize; ListSize = Old->ListSize; - if (IsCopy) { - IRData = malloc(DataSize + ListSize); - ListData = reinterpret_cast(reinterpret_cast(IRData) + DataSize); - memcpy(IRData, Old->IRData, DataSize); - memcpy(ListData, Old->ListData, ListSize); + if (_IsCopy) { + IRDataInternal = malloc(DataSize + ListSize); + ListDataInternal = reinterpret_cast(reinterpret_cast(IRDataInternal) + DataSize); + memcpy(IRDataInternal, Old->IRDataInternal, DataSize); + memcpy(ListDataInternal, Old->ListDataInternal, ListSize); } else { - IRData = Old->IRData; - ListData = Old->ListData; + IRDataInternal = Old->IRDataInternal; + ListDataInternal = Old->ListDataInternal; } } - IRListView(std::istream& stream) : IsCopy(true) { - stream.read((char*)&DataSize, sizeof(DataSize)); - stream.read((char*)&ListSize, sizeof(ListSize)); - - IRData = malloc(DataSize + ListSize); - ListData = reinterpret_cast(reinterpret_cast(IRData) + DataSize); - stream.read((char*)IRData, DataSize); - stream.read((char*)ListData, ListSize); - } - ~IRListView() { - if (IsCopy) { - free (IRData); + if (IsCopy()) { + free (IRDataInternal); // ListData is just offset from IRData } } void Serialize(std::ostream& stream) { + void *nul = nullptr; + //void *IRDataInternal; + stream.write((char*)&nul, sizeof(nul)); + //void *ListDataInternal; + stream.write((char*)&nul, sizeof(nul)); + //size_t DataSize; stream.write((char*)&DataSize, sizeof(DataSize)); + //size_t ListSize; stream.write((char*)&ListSize, sizeof(ListSize)); - stream.write((char*)IRData, DataSize); - stream.write((char*)ListData, ListSize); + //uint64_t Flags; + uint64_t WrittenFlags = Flags | FLAG_Shared; //on disk format always has the Shared flag + stream.write((char*)&WrittenFlags, sizeof(WrittenFlags)); + + // inline data + stream.write((char*)GetData(), DataSize); + stream.write((char*)GetListData(), ListSize); + } + + size_t GetInlineSize() { + static_assert(sizeof(*this) == 40); + return sizeof(*this) + DataSize + ListSize; } IRListView *CreateCopy() { return new IRListView(this, true); } - uintptr_t const GetData() const { return reinterpret_cast(IRData); } - uintptr_t const GetListData() const { return reinterpret_cast(ListData); } - size_t GetDataSize() const { return DataSize; } size_t GetListSize() const { return ListSize; } size_t GetSSACount() const { return ListSize / sizeof(OrderedNode); } - bool IsShared() const { return _IsShared; } - void SetShared(bool Set) { _IsShared = Set; } + bool IsCopy() const { return Flags & FLAG_IsCopy; } + void SetCopy(bool Set) { if (Set) Flags |= FLAG_IsCopy; else Flags &= ~FLAG_IsCopy; } + bool IsShared() const { return Flags & FLAG_Shared; } + void SetShared(bool Set) { if (Set) Flags |= FLAG_Shared; else Flags &= ~FLAG_Shared; } uint32_t GetID(OrderedNode *Node) const { return Node->Wrapped(GetListData()).ID(); @@ -268,7 +281,7 @@ public: { OrderedNodeWrapper Wrapped; Wrapped.NodeOffset = sizeof(OrderedNode); - return iterator(reinterpret_cast(ListData), reinterpret_cast(IRData), Wrapped); + return iterator(reinterpret_cast(GetListData()), reinterpret_cast(GetData()), Wrapped); } /** @@ -280,7 +293,7 @@ public: { OrderedNodeWrapper Wrapped; Wrapped.NodeOffset = 0; - return iterator(reinterpret_cast(ListData), reinterpret_cast(IRData), Wrapped); + return iterator(reinterpret_cast(GetListData()), reinterpret_cast(GetData()), Wrapped); } /** @@ -288,27 +301,35 @@ public: * @return Iterator for this op */ iterator at(OrderedNodeWrapper Wrapped) const noexcept { - return iterator(reinterpret_cast(ListData), reinterpret_cast(IRData), Wrapped); + return iterator(reinterpret_cast(GetListData()), reinterpret_cast(GetData()), Wrapped); } iterator at(uint32_t ID) const noexcept { OrderedNodeWrapper Wrapped; Wrapped.NodeOffset = ID * sizeof(OrderedNode); - return iterator(reinterpret_cast(ListData), reinterpret_cast(IRData), Wrapped); + return iterator(reinterpret_cast(GetListData()), reinterpret_cast(GetData()), Wrapped); } iterator at(OrderedNode *Node) const noexcept { - auto Wrapped = Node->Wrapped(reinterpret_cast(ListData)); - return iterator(reinterpret_cast(ListData), reinterpret_cast(IRData), Wrapped); + auto Wrapped = Node->Wrapped(reinterpret_cast(GetListData())); + return iterator(reinterpret_cast(GetListData()), reinterpret_cast(GetData()), Wrapped); + } + + uintptr_t const GetData() const { + return reinterpret_cast(IRDataInternal ? IRDataInternal : InlineData); + } + + uintptr_t const GetListData() const { + return reinterpret_cast(ListDataInternal ? ListDataInternal : &InlineData[DataSize]); } private: - void *IRData; - void *ListData; + void *IRDataInternal; + void *ListDataInternal; size_t DataSize; size_t ListSize; - bool IsCopy; - bool _IsShared {false}; + uint64_t Flags {0}; + uint8_t InlineData[0]; }; struct IRListViewDeleter { diff --git a/Source/Tests/FEXLoader.cpp b/Source/Tests/FEXLoader.cpp index c298c14cc..ee07aad22 100644 --- a/Source/Tests/FEXLoader.cpp +++ b/Source/Tests/FEXLoader.cpp @@ -320,10 +320,10 @@ int main(int argc, char **argv, char **const envp) { LogMan::Msg::I("Warning: AOTIR is experimental, and might lead to crashes. Capture doesn't work with programs that fork."); } - FEXCore::Context::SetAOTIRLoader(CTX, [](const std::string &fileid) -> std::unique_ptr { + FEXCore::Context::SetAOTIRLoader(CTX, [](const std::string &fileid) -> int { auto filepath = std::filesystem::path(FEXCore::Config::GetDataDirectory()) / "aotir" / fileid; - return std::make_unique(filepath, std::ios::in | std::ios::binary); + return open(filepath.c_str(), O_RDONLY); }); for(auto handler: Loader.AOTMappers) {