diff --git a/src/dynarmic/src/dynarmic/backend/x64/constant_pool.cpp b/src/dynarmic/src/dynarmic/backend/x64/constant_pool.cpp index 8782ab0c73..77fbedc296 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/constant_pool.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/constant_pool.cpp @@ -7,34 +7,27 @@ */ #include - -#include "common/assert.h" - +#include #include "dynarmic/backend/x64/block_of_code.h" #include "dynarmic/backend/x64/constant_pool.h" namespace Dynarmic::Backend::X64 { -ConstantPool::ConstantPool(BlockOfCode& code, size_t size) - : insertion_point(0) -{ - code.EnsureMemoryCommitted(align_size + size); - code.int3(); +ConstantPool::ConstantPool(BlockOfCode& code, size_t size) noexcept { + auto const align_size = 64; //always align to cacheline + code.EnsureMemoryCommitted(2 * align_size + size); code.align(align_size); - pool = std::span(reinterpret_cast(code.AllocateFromCodeSpace(size)), size / align_size); + pool = std::span(static_cast(code.AllocateFromCodeSpace(size)), size / sizeof(u128)); } -Xbyak::Address ConstantPool::GetConstant(BlockOfCode& code, const Xbyak::AddressFrame& frame, u64 lower, u64 upper) { - const auto constant = ConstantT(lower, upper); - auto it = constant_info.find(constant); - if (it == constant_info.end()) { - ASSERT(insertion_point < pool.size()); - ConstantT& target_constant = pool[insertion_point]; - target_constant = constant; - it = constant_info.insert({constant, &target_constant}).first; - ++insertion_point; - } - return frame[code.rip + it->second]; +Xbyak::Address ConstantPool::GetConstant(BlockOfCode& code, const Xbyak::AddressFrame& frame, u64 lo, u64 hi) noexcept { + // offset grows iff new constant is added + auto const key = std::make_pair(lo, hi); + auto const val = u32(constant_info.size()); + auto const [it, _] = constant_info.insert({key, val}); + // if it != constant_info.end(): assume(pool[it->second] == c); + pool[it->second] = u128{lo, hi}; + return frame[code.rip + std::addressof(pool[it->second])]; } } // namespace Dynarmic::Backend::X64 diff --git a/src/dynarmic/src/dynarmic/backend/x64/constant_pool.h b/src/dynarmic/src/dynarmic/backend/x64/constant_pool.h index d3bad95d70..2d557766de 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/constant_pool.h +++ b/src/dynarmic/src/dynarmic/backend/x64/constant_pool.h @@ -12,6 +12,7 @@ #include #include #include +#include #include "common/common_types.h" #include "common/container/unordered_map.h" @@ -21,31 +22,17 @@ namespace Dynarmic::Backend::X64 { class BlockOfCode; -/// ConstantPool allocates a block of memory from BlockOfCode. +/// @brief ConstantPool allocates a block of memory from BlockOfCode. /// It places constants into this block of memory, returning the address /// of the memory location where the constant is placed. If the constant /// already exists, its memory location is reused. class ConstantPool final { public: - ConstantPool(BlockOfCode& code, size_t size); - - Xbyak::Address GetConstant(BlockOfCode& code, const Xbyak::AddressFrame& frame, u64 lower, u64 upper = 0); - -private: - static constexpr size_t align_size = 16; // bytes - - using ConstantT = std::pair; - static_assert(sizeof(ConstantT) == align_size); - - struct ConstantHash { - std::size_t operator()(const ConstantT& constant) const noexcept { - return constant.first ^ std::rotl(constant.second, 1); - } - }; - - ::Common::unordered_map constant_info; - std::span pool; - std::size_t insertion_point; + ConstantPool(BlockOfCode& code, size_t size) noexcept; + Xbyak::Address GetConstant(BlockOfCode& code, const Xbyak::AddressFrame& frame, u64 lower, u64 upper = 0) noexcept; + // key = identity hash, value = offset from pool.data() + ::Common::unordered_map, u32, boost::hash>> constant_info; + std::span pool; }; } // namespace Dynarmic::Backend::X64