diff --git a/core/os/memory.cpp b/core/os/memory.cpp index 867158d52a1..a8eec8401c7 100644 --- a/core/os/memory.cpp +++ b/core/os/memory.cpp @@ -57,8 +57,8 @@ void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_d #endif #ifdef DEBUG_ENABLED -SafeNumeric Memory::mem_usage; -SafeNumeric Memory::max_usage; +static SafeNumeric _current_mem_usage; +static SafeNumeric _max_mem_usage; #endif void *Memory::alloc_aligned_static(size_t p_bytes, size_t p_alignment) { @@ -117,8 +117,8 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) { *s = p_bytes; #ifdef DEBUG_ENABLED - uint64_t new_mem_usage = mem_usage.add(p_bytes); - max_usage.exchange_if_greater(new_mem_usage); + uint64_t new_mem_usage = _current_mem_usage.add(p_bytes); + _max_mem_usage.exchange_if_greater(new_mem_usage); #endif return s8 + DATA_OFFSET; } else { @@ -148,10 +148,10 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) { #ifdef DEBUG_ENABLED if (p_bytes > *s) { - uint64_t new_mem_usage = mem_usage.add(p_bytes - *s); - max_usage.exchange_if_greater(new_mem_usage); + uint64_t new_mem_usage = _current_mem_usage.add(p_bytes - *s); + _max_mem_usage.exchange_if_greater(new_mem_usage); } else { - mem_usage.sub(*s - p_bytes); + _current_mem_usage.sub(*s - p_bytes); } #endif @@ -195,7 +195,7 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) { #ifdef DEBUG_ENABLED uint64_t *s = (uint64_t *)(mem + SIZE_OFFSET); - mem_usage.sub(*s); + _current_mem_usage.sub(*s); #endif free(mem); @@ -210,7 +210,7 @@ uint64_t Memory::get_mem_available() { uint64_t Memory::get_mem_usage() { #ifdef DEBUG_ENABLED - return mem_usage.get(); + return _current_mem_usage.get(); #else return 0; #endif @@ -218,7 +218,7 @@ uint64_t Memory::get_mem_usage() { uint64_t Memory::get_mem_max_usage() { #ifdef DEBUG_ENABLED - return max_usage.get(); + return _max_mem_usage.get(); #else return 0; #endif diff --git a/core/os/memory.h b/core/os/memory.h index 1a7dc288706..17426bb6f4d 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -31,74 +31,63 @@ #pragma once #include "core/error/error_macros.h" -#include "core/templates/safe_refcount.h" #include // IWYU pragma: keep // `new` operators. #include -class Memory { -#ifdef DEBUG_ENABLED - static SafeNumeric mem_usage; - static SafeNumeric max_usage; -#endif - -public: - // Alignment: ↓ max_align_t ↓ uint64_t ↓ max_align_t - // ┌─────────────────┬──┬────────────────┬──┬───────────... - // │ uint64_t │░░│ uint64_t │░░│ T[] - // │ alloc size │░░│ element count │░░│ data - // └─────────────────┴──┴────────────────┴──┴───────────... - // Offset: ↑ SIZE_OFFSET ↑ ELEMENT_OFFSET ↑ DATA_OFFSET - - static const size_t SIZE_OFFSET; - static const size_t ELEMENT_OFFSET; - static const size_t DATA_OFFSET; - - template - static void *alloc_static(size_t p_bytes, bool p_pad_align = false); - _FORCE_INLINE_ static void *alloc_static_zeroed(size_t p_bytes, bool p_pad_align = false) { return alloc_static(p_bytes, p_pad_align); } - static void *realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align = false); - static void free_static(void *p_ptr, bool p_pad_align = false); - - // ↓ return value of alloc_aligned_static - // ┌─────────────────┬─────────┬─────────┬──────────────────┐ - // │ padding (up to │ uint32_t│ void* │ padding (up to │ - // │ p_alignment - 1)│ offset │ p_bytes │ p_alignment - 1) │ - // └─────────────────┴─────────┴─────────┴──────────────────┘ - // - // alloc_aligned_static will allocate p_bytes + p_alignment - 1 + sizeof(uint32_t) and - // then offset the pointer until alignment is satisfied. - // - // This offset is stored before the start of the returned ptr so we can retrieve the original/real - // start of the ptr in order to free it. - // - // The rest is wasted as padding in the beginning and end of the ptr. The sum of padding at - // both start and end of the block must add exactly to p_alignment - 1. - // - // p_alignment MUST be a power of 2. - static void *alloc_aligned_static(size_t p_bytes, size_t p_alignment); - static void *realloc_aligned_static(void *p_memory, size_t p_bytes, size_t p_prev_bytes, size_t p_alignment); - // Pass the ptr returned by alloc_aligned_static to free it. - // e.g. - // void *data = realloc_aligned_static( bytes, 16 ); - // free_aligned_static( data ); - static void free_aligned_static(void *p_memory); - - static uint64_t get_mem_available(); - static uint64_t get_mem_usage(); - static uint64_t get_mem_max_usage(); - - static constexpr size_t get_aligned_address(size_t p_address, size_t p_alignment); -}; - -constexpr size_t Memory::get_aligned_address(size_t p_address, size_t p_alignment) { +namespace Memory { +constexpr size_t get_aligned_address(size_t p_address, size_t p_alignment) { const size_t n_bytes_unaligned = p_address % p_alignment; return (n_bytes_unaligned == 0) ? p_address : (p_address + p_alignment - n_bytes_unaligned); } -inline constexpr size_t Memory::SIZE_OFFSET = 0; -inline constexpr size_t Memory::ELEMENT_OFFSET = get_aligned_address(SIZE_OFFSET + sizeof(uint64_t), alignof(uint64_t)); -inline constexpr size_t Memory::DATA_OFFSET = get_aligned_address(ELEMENT_OFFSET + sizeof(uint64_t), alignof(max_align_t)); +// Alignment: ↓ max_align_t ↓ uint64_t ↓ max_align_t +// ┌─────────────────┬──┬────────────────┬──┬───────────... +// │ uint64_t │░░│ uint64_t │░░│ T[] +// │ alloc size │░░│ element count │░░│ data +// └─────────────────┴──┴────────────────┴──┴───────────... +// Offset: ↑ SIZE_OFFSET ↑ ELEMENT_OFFSET ↑ DATA_OFFSET + +inline constexpr size_t SIZE_OFFSET = 0; +inline constexpr size_t ELEMENT_OFFSET = get_aligned_address(SIZE_OFFSET + sizeof(uint64_t), alignof(uint64_t)); +inline constexpr size_t DATA_OFFSET = get_aligned_address(ELEMENT_OFFSET + sizeof(uint64_t), alignof(max_align_t)); + +template +void *alloc_static(size_t p_bytes, bool p_pad_align = false); +_FORCE_INLINE_ static void *alloc_static_zeroed(size_t p_bytes, bool p_pad_align = false) { + return alloc_static(p_bytes, p_pad_align); +} +void *realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align = false); +void free_static(void *p_ptr, bool p_pad_align = false); + +// ↓ return value of alloc_aligned_static +// ┌─────────────────┬─────────┬─────────┬──────────────────┐ +// │ padding (up to │ uint32_t│ void* │ padding (up to │ +// │ p_alignment - 1)│ offset │ p_bytes │ p_alignment - 1) │ +// └─────────────────┴─────────┴─────────┴──────────────────┘ +// +// alloc_aligned_static will allocate p_bytes + p_alignment - 1 + sizeof(uint32_t) and +// then offset the pointer until alignment is satisfied. +// +// This offset is stored before the start of the returned ptr so we can retrieve the original/real +// start of the ptr in order to free it. +// +// The rest is wasted as padding in the beginning and end of the ptr. The sum of padding at +// both start and end of the block must add exactly to p_alignment - 1. +// +// p_alignment MUST be a power of 2. +void *alloc_aligned_static(size_t p_bytes, size_t p_alignment); +void *realloc_aligned_static(void *p_memory, size_t p_bytes, size_t p_prev_bytes, size_t p_alignment); +// Pass the ptr returned by alloc_aligned_static to free it. +// e.g. +// void *data = realloc_aligned_static( bytes, 16 ); +// free_aligned_static( data ); +void free_aligned_static(void *p_memory); + +uint64_t get_mem_available(); +uint64_t get_mem_usage(); +uint64_t get_mem_max_usage(); +}; //namespace Memory class DefaultAllocator { public: