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:
parent
b0d6c29073
commit
9951961338
|
@ -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
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
};
|
Loading…
Reference in New Issue