diff --git a/core/os/memory.cpp b/core/os/memory.cpp index 32c316e58e8c..4c6500b27d5f 100644 --- a/core/os/memory.cpp +++ b/core/os/memory.cpp @@ -44,6 +44,20 @@ void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)) { return p_allocfunc(p_size); } +bool g_is_logging = true; + +const size_t ARENA_SIZE = 1024 * 1024 * 512; +Arena g_memeory_arena_images(ARENA_SIZE); +Arena g_memeory_arena_code(ARENA_SIZE); + + +bool starts_with(const std::string& str, const std::string& prefix) { + if (str.length() < prefix.length()) { + return false; + } + return str.compare(0, prefix.length(), prefix) == 0; +} + #ifdef _MSC_VER void operator delete(void *p_mem, const char *p_description) { CRASH_NOW_MSG("Call to placement delete should not happen."); diff --git a/core/os/memory.h b/core/os/memory.h index 14a40f9d9d05..bec660dc0268 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -107,6 +107,55 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) { #define memnew_allocator(m_class, m_allocator) _post_initialize(new (m_allocator::alloc) m_class) #define memnew_placement(m_placement, m_class) _post_initialize(new (m_placement) m_class) +extern bool g_is_logging; + +struct Arena { + size_t m_size; + size_t m_used; + uint8_t* m_buffer; + + explicit Arena(size_t size) : + m_size(size), + m_used(0) { + m_buffer = new uint8_t[size]; + } + + ~Arena() { + delete[] m_buffer; + } + + template + T* allocate(Args&&... args) { + // Get the memory location + size_t alignment = alignof(T); + uintptr_t current = reinterpret_cast(m_buffer + m_used); + uintptr_t aligned = (current + alignment - 1) & ~(alignment - 1); + size_t padding = aligned - current; + + // Make sure there is enough space + size_t total_size = sizeof(T); + if (m_used + total_size + padding > m_size) { + std::cerr << "Out of memory" << std::endl; + std::cerr.flush(); + return nullptr; + } + m_used += total_size + padding; + + // Call the constructor and use the memory location + T* result = new (reinterpret_cast(aligned)) T(std::forward(args)...); + return result; + } + + void reset() { + m_used = 0; + } +}; + + +extern Arena g_memeory_arena_images; +extern Arena g_memeory_arena_code; + +bool starts_with(const std::string& str, const std::string& prefix); template std::string get_type_name() { @@ -121,9 +170,11 @@ std::string get_type_name() { template void print_type_info(const char* message) { - std::string type_name = get_type_name(); - std::cout << "!!!!! " << message << ": " << type_name << std::endl; - std::cout.flush(); + if (g_is_logging) { + std::string type_name = get_type_name(); + std::cout << "???? " << message << ": " << type_name << std::endl; + std::cout.flush(); + } } #define memnewOldWithArgs2(T, m_class) \ @@ -134,8 +185,10 @@ void print_type_info(const char* message) { #define memnewOldWithArgs3(name, m_class) \ ({ \ - std::cout << "!!!!! memnewOldWithArgs3: " << name << std::endl; \ - std::cout.flush(); \ + if (g_is_logging) { \ + std::cout << "???? memnewOldWithArgs3: " << name << std::endl; \ + std::cout.flush(); \ + }\ _post_initialize(new ("") m_class); \ }) @@ -149,24 +202,60 @@ void print_type_info(const char* message) { template /*_ALWAYS_INLINE_*/ T* memnewWithArgs(Args&&... args) { - T* result = new ("") T(std::forward(args)...); - print_type_info("memnewWithArgs"); + std::string type_name = get_type_name(); + T* result = nullptr; + + if (starts_with(type_name, "GDScriptParser::")) { + result = g_memeory_arena_code.allocate(std::forward(args)...); + //print_type_info("!!!!!!!!memnewWithArgs"); + } else if (type_name == "Image") { + result = g_memeory_arena_images.allocate(std::forward(args)...); + //print_type_info("!!!!!!!!memnewWithArgs"); + } else { + result = new ("") T(std::forward(args)...); + print_type_info("memnewWithArgs"); + } + postinitialize_handler(result); return result; } template /*_ALWAYS_INLINE_*/ T* memnewNoConstructor() { - T* result = new ("") T; - print_type_info("memnewNoConstructor"); + std::string type_name = get_type_name(); + T* result = nullptr; + + if (starts_with(type_name, "GDScriptParser::")) { + result = g_memeory_arena_code.allocate(); + //print_type_info("!!!!!!!!memnewNoConstructor"); + } else if (type_name == "Image") { + result = g_memeory_arena_images.allocate(); + //print_type_info("!!!!!!!!memnewNoConstructor"); + } else { + result = new ("") T; + print_type_info("memnewNoConstructor"); + } + postinitialize_handler(result); return result; } template /*_ALWAYS_INLINE_*/ T* memnewNoArgs() { - T* result = new ("") T; - print_type_info("memnewNoArgs"); + std::string type_name = get_type_name(); + T* result = nullptr; + + if (starts_with(type_name, "GDScriptParser::")) { + result = g_memeory_arena_code.allocate(); + //print_type_info("!!!!!!!!memnewNoArgs"); + } else if (type_name == "Image") { + result = g_memeory_arena_images.allocate(); + //print_type_info("!!!!!!!!memnewNoArgs"); + } else { + result = new ("") T; + print_type_info("memnewNoArgs"); + } + postinitialize_handler(result); return result; } @@ -180,14 +269,23 @@ _ALWAYS_INLINE_ bool predelete_handler(void *) { template void memdelete(T *p_class) { + std::string type_name = get_type_name(); + if (!predelete_handler(p_class)) { return; // doesn't want to be deleted } + if constexpr (!std::is_trivially_destructible_v) { p_class->~T(); } - Memory::free_static(p_class, false); + if (starts_with(type_name, "GDScriptParser::")) { + // FIXME: Have the Arena free the memory here + } else if (type_name == "Image") { + // FIXME: Have the Arena free the memory here + } else { + Memory::free_static(p_class, false); + } } template @@ -289,7 +387,7 @@ class DefaultTypedAllocator { public: template _FORCE_INLINE_ T *new_allocation(const Args &&...p_args) { return memnewWithArgs(p_args...); } - _FORCE_INLINE_ void delete_allocation(T *p_allocation) { memdelete(p_allocation); } + _FORCE_INLINE_ void delete_allocation(T *p_allocation) { memdelete(p_allocation); } }; #endif // MEMORY_H