diff --git a/External/FEXCore/Source/Interface/Core/Frontend.cpp b/External/FEXCore/Source/Interface/Core/Frontend.cpp index cbe38b6dd..18ed89953 100644 --- a/External/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/External/FEXCore/Source/Interface/Core/Frontend.cpp @@ -16,6 +16,7 @@ $end_info$ #include #include #include +#include namespace FEXCore::Frontend { using namespace FEXCore::X86Tables; @@ -122,7 +123,16 @@ static uint32_t MapModRMToReg(uint8_t REX, uint8_t bits, bool HighBits, bool Has Decoder::Decoder(FEXCore::Context::Context *ctx) : CTX {ctx} { - DecodedBuffer.resize(DefaultDecodedBufferSize); + // Using mmap is a start-up time optimization + // Take advantage of page faulting to reduce startup time for minimal runtime cost + DecodedBuffer = + reinterpret_cast( + ::mmap(0, sizeof(FEXCore::X86Tables::DecodedInst) * DefaultDecodedBufferSize, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); +} + +Decoder::~Decoder() { + ::munmap(DecodedBuffer, sizeof(FEXCore::X86Tables::DecodedInst) * DefaultDecodedBufferSize); } uint8_t Decoder::ReadByte() { @@ -214,28 +224,28 @@ void Decoder::DecodeModRM_16(X86Tables::DecodedOperand *Operand, X86Tables::ModR {FEXCore::X86State::REG_RBX, FEXCore::X86State::REG_RDI}, {FEXCore::X86State::REG_RBP, FEXCore::X86State::REG_RSI}, {FEXCore::X86State::REG_RBP, FEXCore::X86State::REG_RDI}, - {FEXCore::X86State::REG_RSI, 255}, - {FEXCore::X86State::REG_RDI, 255}, - {255, 255}, - {FEXCore::X86State::REG_RBX, 255}, + {FEXCore::X86State::REG_RSI, FEXCore::X86State::REG_INVALID}, + {FEXCore::X86State::REG_RDI, FEXCore::X86State::REG_INVALID}, + {FEXCore::X86State::REG_INVALID, FEXCore::X86State::REG_INVALID}, + {FEXCore::X86State::REG_RBX, FEXCore::X86State::REG_INVALID}, // Mod = 0b01 {FEXCore::X86State::REG_RBX, FEXCore::X86State::REG_RSI}, {FEXCore::X86State::REG_RBX, FEXCore::X86State::REG_RDI}, {FEXCore::X86State::REG_RBP, FEXCore::X86State::REG_RSI}, {FEXCore::X86State::REG_RBP, FEXCore::X86State::REG_RDI}, - {FEXCore::X86State::REG_RSI, 255}, - {FEXCore::X86State::REG_RDI, 255}, - {FEXCore::X86State::REG_RBP, 255}, - {FEXCore::X86State::REG_RBX, 255}, + {FEXCore::X86State::REG_RSI, FEXCore::X86State::REG_INVALID}, + {FEXCore::X86State::REG_RDI, FEXCore::X86State::REG_INVALID}, + {FEXCore::X86State::REG_RBP, FEXCore::X86State::REG_INVALID}, + {FEXCore::X86State::REG_RBX, FEXCore::X86State::REG_INVALID}, // Mod = 0b10 {FEXCore::X86State::REG_RBX, FEXCore::X86State::REG_RSI}, {FEXCore::X86State::REG_RBX, FEXCore::X86State::REG_RDI}, {FEXCore::X86State::REG_RBP, FEXCore::X86State::REG_RSI}, {FEXCore::X86State::REG_RBP, FEXCore::X86State::REG_RDI}, - {FEXCore::X86State::REG_RSI, 255}, - {FEXCore::X86State::REG_RDI, 255}, - {FEXCore::X86State::REG_RBP, 255}, - {FEXCore::X86State::REG_RBX, 255}, + {FEXCore::X86State::REG_RSI, FEXCore::X86State::REG_INVALID}, + {FEXCore::X86State::REG_RDI, FEXCore::X86State::REG_INVALID}, + {FEXCore::X86State::REG_RBP, FEXCore::X86State::REG_INVALID}, + {FEXCore::X86State::REG_RBX, FEXCore::X86State::REG_INVALID}, }}; uint8_t LookupIndex = ModRM.mod << 3 | ModRM.rm; @@ -929,7 +939,7 @@ bool Decoder::DecodeInstruction(uint64_t PC) { } if (DecodeInst->Dest.IsGPR()) { - assert(DecodeInst->Dest.Data.GPR.GPR != 255); + assert(DecodeInst->Dest.Data.GPR.GPR != FEXCore::X86State::REG_INVALID); } return true; @@ -1091,7 +1101,7 @@ bool Decoder::DecodeInstructionsAtEntry(uint8_t const* _InstStream, uint64_t PC) } if (DecodedSize >= CTX->Config.MaxInstPerBlock || - DecodedSize >= DecodedBuffer.size()) { + DecodedSize >= DefaultDecodedBufferSize) { break; } @@ -1108,7 +1118,7 @@ bool Decoder::DecodeInstructionsAtEntry(uint8_t const* _InstStream, uint64_t PC) // Copy over only the number of instructions we decoded CurrentBlockDecoding.NumInstructions = BlockNumberOfInstructions; - CurrentBlockDecoding.DecodedInstructions = &DecodedBuffer.at(BlockStartOffset); + CurrentBlockDecoding.DecodedInstructions = &DecodedBuffer[BlockStartOffset]; } diff --git a/External/FEXCore/Source/Interface/Core/Frontend.h b/External/FEXCore/Source/Interface/Core/Frontend.h index 395109bcc..34f32e67c 100644 --- a/External/FEXCore/Source/Interface/Core/Frontend.h +++ b/External/FEXCore/Source/Interface/Core/Frontend.h @@ -24,6 +24,7 @@ public: }; Decoder(FEXCore::Context::Context *ctx); + ~Decoder(); bool DecodeInstructionsAtEntry(uint8_t const* InstStream, uint64_t PC); std::vector const *GetDecodedBlocks() const { @@ -50,7 +51,7 @@ private: bool NormalOpHeader(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op); static constexpr size_t DefaultDecodedBufferSize = 0x10000; - std::vector DecodedBuffer; + FEXCore::X86Tables::DecodedInst *DecodedBuffer{}; size_t DecodedSize {}; uint8_t const *InstStream; diff --git a/External/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp b/External/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp index 954b25a21..693a8106c 100644 --- a/External/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp +++ b/External/FEXCore/Source/Interface/IR/Passes/RegisterAllocationPass.cpp @@ -12,6 +12,7 @@ $end_info$ #include #include +#include #define SRA_DEBUG(...) // printf(__VA_ARGS__) @@ -177,6 +178,7 @@ namespace { }; static_assert(sizeof(RegisterNode) == 128 * 4); + constexpr size_t REGISTER_NODES_PER_PAGE = FEXCore::Core::PAGE_SIZE / sizeof(RegisterNode); struct RegisterSet { std::vector Classes; @@ -204,8 +206,8 @@ namespace { struct RegisterGraph { std::unique_ptr AllocData; RegisterSet Set; - std::vector Nodes; - uint32_t NodeCount; + RegisterNode *Nodes{}; + uint32_t NodeCount{}; std::vector SpillStack; std::unordered_map> BlockPredecessors; std::unordered_map> VisitedNodePredecessors; @@ -254,15 +256,30 @@ namespace { } void FreeRegisterGraph(RegisterGraph *Graph) { + if (Graph->Nodes) { + ::munmap(Graph->Nodes, Graph->NodeCount * sizeof(RegisterNode)); + } delete Graph; } void ResetRegisterGraph(RegisterGraph *Graph, uint64_t NodeCount) { - NodeCount = AlignUp(NodeCount, sizeof(uint64_t)); - Graph->Nodes.clear(); - Graph->Nodes.resize(NodeCount); + NodeCount = AlignUp(NodeCount, REGISTER_NODES_PER_PAGE); + if (Graph->NodeCount < NodeCount) { + if (Graph->Nodes) { + // If the needed node count is smaller than what we currently have allocated + // then unmap it so we can remap a larger memory space + ::munmap(Graph->Nodes, Graph->NodeCount * sizeof(RegisterNode)); + } + + // We don't have a mapping, allocate a space that gives us a default zero mapping + Graph->Nodes = reinterpret_cast(::mmap(0, NodeCount * sizeof(RegisterNode), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); + } + else { + // If we already have an allocation then zero out how many nodes we need + memset(Graph->Nodes, 0, NodeCount * sizeof(RegisterNode)); + } + Graph->VisitedNodePredecessors.clear(); - Graph->AllocData.reset(); Graph->AllocData.reset((FEXCore::IR::RegisterAllocationData*)FEXCore::Allocator::malloc(FEXCore::IR::RegisterAllocationData::Size(NodeCount))); memset(&Graph->AllocData->Map[0], INVALID_REGCLASS.Raw, NodeCount); Graph->AllocData->MapCount = NodeCount; diff --git a/unittests/gvisor-tests/Disabled_Tests b/unittests/gvisor-tests/Disabled_Tests index 0fd1e4b8c..37338b766 100644 --- a/unittests/gvisor-tests/Disabled_Tests +++ b/unittests/gvisor-tests/Disabled_Tests @@ -84,3 +84,6 @@ time_test # The behaviour of this changes depending on if you have asserts enabled or not # siginfo_t with unsynchronized context pause_test + +# ARMv8.4 periodically flakes on this one +rtsignal_test diff --git a/unittests/gvisor-tests/Known_Failures b/unittests/gvisor-tests/Known_Failures index f63d16362..5748d567c 100644 --- a/unittests/gvisor-tests/Known_Failures +++ b/unittests/gvisor-tests/Known_Failures @@ -170,3 +170,6 @@ stat_times_test # The behaviour of this changes depending on if you have asserts enabled or not # siginfo_t with unsynchronized context pause_test + +# ARMv8.4 periodically flakes on this one +rtsignal_test