diff --git a/Source/Core/Common/CodeBlock.h b/Source/Core/Common/CodeBlock.h index 28a4919e66..9eb1732ec7 100644 --- a/Source/Core/Common/CodeBlock.h +++ b/Source/Core/Common/CodeBlock.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include "Common/Assert.h" #include "Common/CommonTypes.h" @@ -27,12 +28,13 @@ private: protected: u8* region = nullptr; + // Size of region we can use. size_t region_size = 0; - size_t parent_region_size = 0; + // Original size of the region we allocated. + size_t total_region_size = 0; - bool m_has_child = false; bool m_is_child = false; - CodeBlock* m_child = nullptr; + std::vector m_children; public: virtual ~CodeBlock() @@ -45,7 +47,8 @@ public: virtual void AllocCodeSpace(size_t size, bool need_low = true) { region_size = size; - region = static_cast(Common::AllocateExecutableMemory(region_size, need_low)); + total_region_size = size; + region = static_cast(Common::AllocateExecutableMemory(total_region_size, need_low)); T::SetCodePtr(region); } @@ -60,14 +63,16 @@ public: // Call this when shutting down. Don't rely on the destructor, even though it'll do the job. void FreeCodeSpace() { - Common::FreeMemoryPages(region, region_size); + _assert_(!m_is_child); + Common::FreeMemoryPages(region, total_region_size); region = nullptr; region_size = 0; - parent_region_size = 0; - if (m_has_child) + total_region_size = 0; + for (CodeBlock* child : m_children) { - m_child->region = nullptr; - m_child->region_size = 0; + child->region = nullptr; + child->region_size = 0; + child->total_region_size = 0; } } @@ -78,7 +83,8 @@ public: void ResetCodePtr() { T::SetCodePtr(region); } size_t GetSpaceLeft() const { - return (m_has_child ? parent_region_size : region_size) - (T::GetCodePtr() - region); + _assert_(static_cast(T::GetCodePtr() - region) < region_size); + return region_size - (T::GetCodePtr() - region); } bool IsAlmostFull() const @@ -86,16 +92,23 @@ public: // This should be bigger than the biggest block ever. return GetSpaceLeft() < 0x10000; } - void AddChildCodeSpace(CodeBlock* child, size_t size) + + bool HasChildren() const { return region_size != total_region_size; } + u8* AllocChildCodeSpace(size_t child_size) { - _assert_msg_(DYNA_REC, !m_has_child, "Already have a child! Can't have another!"); - m_child = child; - m_has_child = true; - m_child->m_is_child = true; - u8* child_region = region + region_size - size; - m_child->region = child_region; - m_child->region_size = size; - m_child->ResetCodePtr(); - parent_region_size = region_size - size; + _assert_msg_(DYNA_REG, child_size < GetSpaceLeft(), "Insufficient space for child allocation."); + u8* child_region = region + region_size - child_size; + region_size -= child_size; + return child_region; + } + void AddChildCodeSpace(CodeBlock* child, size_t child_size) + { + u8* child_region = AllocChildCodeSpace(child_size); + child->m_is_child = true; + child->region = child_region; + child->region_size = child_size; + child->total_region_size = child_size; + child->ResetCodePtr(); + m_children.emplace_back(child); } };