ConstantPool: Implement a constant pool

Constants are copied into this pool so that they live at a memory
location that is close to the code that references it. The pool allocates
memory from a provided X64CodeBlock to use.

The purpose of the pool is to overcome the 32-bit offset limitation that
RIP-relative addressing has.`
This commit is contained in:
MerryMage 2017-03-19 12:33:22 +00:00
parent b0d6c29073
commit 9951961338
5 changed files with 128 additions and 0 deletions

View File

@ -244,6 +244,7 @@ if(_M_X86)
PowerPC/Jit64/JitRegCache.cpp
PowerPC/Jit64/Jit_SystemRegisters.cpp
PowerPC/Jit64Common/BlockCache.cpp
PowerPC/Jit64Common/ConstantPool.cpp
PowerPC/Jit64Common/EmuCodeBlock.cpp
PowerPC/Jit64Common/FarCodeCache.cpp
PowerPC/Jit64Common/Jit64AsmCommon.cpp

View File

@ -243,6 +243,7 @@
<ClCompile Include="PowerPC\Interpreter\Interpreter_Paired.cpp" />
<ClCompile Include="PowerPC\Interpreter\Interpreter_SystemRegisters.cpp" />
<ClCompile Include="PowerPC\Interpreter\Interpreter_Tables.cpp" />
<ClCompile Include="PowerPC\Jit64Common\ConstantPool.cpp" />
<ClCompile Include="PowerPC\JitILCommon\IR.cpp" />
<ClCompile Include="PowerPC\JitILCommon\JitILBase_Branch.cpp" />
<ClCompile Include="PowerPC\JitILCommon\JitILBase_FloatingPoint.cpp" />
@ -484,6 +485,7 @@
<ClInclude Include="PowerPC\CachedInterpreter\InterpreterBlockCache.h" />
<ClInclude Include="PowerPC\Interpreter\Interpreter.h" />
<ClInclude Include="PowerPC\Interpreter\Interpreter_FPUtils.h" />
<ClInclude Include="PowerPC\Jit64Common\ConstantPool.h" />
<ClInclude Include="PowerPC\Jit64IL\JitIL.h" />
<ClInclude Include="PowerPC\Jit64\FPURegCache.h" />
<ClInclude Include="PowerPC\Jit64\GPRRegCache.h" />

View File

@ -867,6 +867,9 @@
<ClCompile Include="IOS\USB\Bluetooth\WiimoteHIDAttr.cpp">
<Filter>IOS\USB\Bluetooth</Filter>
</ClCompile>
<ClCompile Include="PowerPC\Jit64Common\ConstantPool.cpp">
<Filter>PowerPC\Jit64Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="BootManager.h" />
@ -1487,6 +1490,9 @@
<ClInclude Include="IOS\MIOS.h">
<Filter>IOS</Filter>
</ClInclude>
<ClInclude Include="PowerPC\Jit64Common\ConstantPool.h">
<Filter>PowerPC\Jit64Common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />

View File

@ -0,0 +1,67 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <cstring>
#include <memory>
#include <utility>
#include "Common/Assert.h"
#include "Common/x64Emitter.h"
#include "Core/PowerPC/Jit64Common/ConstantPool.h"
ConstantPool::ConstantPool(Gen::X64CodeBlock* parent) : m_parent(parent)
{
}
ConstantPool::~ConstantPool() = default;
void ConstantPool::AllocCodeSpace()
{
_assert_(!m_current_ptr);
Init();
}
void ConstantPool::ClearCodeSpace()
{
Init();
}
Gen::OpArg ConstantPool::GetConstantOpArg(const void* value, size_t element_size,
size_t num_elements, size_t index)
{
const size_t value_size = element_size * num_elements;
auto iter = m_const_info.find(value);
if (iter == m_const_info.end())
{
void* ptr = std::align(ALIGNMENT, value_size, m_current_ptr, m_remaining_size);
_assert_msg_(DYNA_REC, ptr, "Constant pool has run out of space.");
m_current_ptr = static_cast<u8*>(m_current_ptr) + value_size;
m_remaining_size -= value_size;
std::memcpy(ptr, value, value_size);
iter = m_const_info.emplace(std::make_pair(value, ConstantInfo{ptr, value_size})).first;
}
const ConstantInfo& info = iter->second;
_assert_msg_(DYNA_REC, info.m_size == value_size,
"Constant has incorrect size in constant pool.");
u8* location = static_cast<u8*>(info.m_location);
return Gen::M(location + element_size * index);
}
void ConstantPool::Init()
{
// If execution happens to run to the start of the constant pool, halt.
m_parent->INT3();
m_parent->AlignCode16();
// Reserve a block of memory CONST_POOL_SIZE in size.
m_current_ptr = m_parent->GetWritableCodePtr();
m_parent->ReserveCodeSpace(CONST_POOL_SIZE);
m_remaining_size = CONST_POOL_SIZE;
m_const_info.clear();
}

View File

@ -0,0 +1,52 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <cstddef>
#include <map>
namespace Gen
{
struct OpArg;
class X64CodeBlock;
}
// Constants are copied into this pool so that they live at a memory location
// that is close to the code that references it. This ensures that the 32-bit
// limitation on RIP addressing is not an issue.
class ConstantPool
{
public:
static constexpr size_t CONST_POOL_SIZE = 1024 * 32;
static constexpr size_t ALIGNMENT = 16;
explicit ConstantPool(Gen::X64CodeBlock* parent);
~ConstantPool();
// ConstantPool reserves CONST_POOL_SIZE bytes from parent, and uses
// that space to store its constants.
void AllocCodeSpace();
void ClearCodeSpace();
// Copies the value into the pool if it doesn't exist. Returns a pointer
// to existing values if they were already copied. Pointer equality is
// used to determine if two constants are the same.
Gen::OpArg GetConstantOpArg(const void* value, size_t element_size, size_t num_elements,
size_t index);
private:
void Init();
struct ConstantInfo
{
void* m_location;
size_t m_size;
};
Gen::X64CodeBlock* m_parent;
void* m_current_ptr = nullptr;
size_t m_remaining_size = CONST_POOL_SIZE;
std::map<const void*, ConstantInfo> m_const_info;
};