Skip to content

Commit

Permalink
Add optional allocation tracking
Browse files Browse the repository at this point in the history
Adds optional tracking to most memory allocations. It can be compiled in using the scons argument "use_allocation_tracking".
  • Loading branch information
lawnjelly committed Sep 1, 2022
1 parent 8d22a5f commit 09d5e3e
Show file tree
Hide file tree
Showing 7 changed files with 527 additions and 0 deletions.
5 changes: 5 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ opts.Add(BoolVariable("disable_advanced_gui", "Disable advanced GUI nodes and be
opts.Add(BoolVariable("no_editor_splash", "Don't use the custom splash screen for the editor", True))
opts.Add("system_certs_path", "Use this path as SSL certificates default for editor (for package maintainers)", "")
opts.Add(BoolVariable("use_precise_math_checks", "Math checks use very precise epsilon (debug option)", False))
opts.Add(BoolVariable("use_allocation_tracking", "Build with allocation tracking (debug option)", False))
opts.Add(
EnumVariable(
"rids",
Expand Down Expand Up @@ -363,6 +364,10 @@ if env_base["rids"] == "tracked_handles":
env_base.Append(CPPDEFINES=["RID_HANDLE_ALLOCATION_TRACKING_ENABLED"])
print("WARNING: Building with RIDs as tracked handles.")

if env_base["use_allocation_tracking"]:
env_base.Append(CPPDEFINES=["ALLOCATION_TRACKING_ENABLED"])
print("WARNING: Building with allocation tracking.")

if selected_platform in platform_list:
tmppath = "./platform/" + selected_platform
sys.path.insert(0, tmppath)
Expand Down
25 changes: 25 additions & 0 deletions core/os/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,23 @@ SafeNumeric<uint64_t> Memory::max_usage;

SafeNumeric<uint64_t> Memory::alloc_count;

#ifdef ALLOCATION_TRACKING_ENABLED
void *Memory::alloc_static_tracked(size_t p_bytes, const char *p_filename, int p_line, bool p_pad_align) {
void *addr = alloc_static(p_bytes, p_pad_align);
AllocationTracking::add_alloc(addr, p_bytes, p_filename, p_line);
return addr;
}

void *Memory::realloc_static_tracked(void *p_memory, size_t p_bytes, const char *p_filename, int p_line, bool p_pad_align) {
if (p_memory == nullptr) {
return alloc_static_tracked(p_bytes, p_filename, p_line, p_pad_align);
}

return realloc_static(p_memory, p_bytes, p_pad_align);
}

#endif

void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
#ifdef DEBUG_ENABLED
bool prepad = true;
Expand Down Expand Up @@ -99,6 +116,10 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
return alloc_static(p_bytes, p_pad_align);
}

#ifdef ALLOCATION_TRACKING_ENABLED
AllocationTracking::realloc(p_memory, p_bytes);
#endif

uint8_t *mem = (uint8_t *)p_memory;

#ifdef DEBUG_ENABLED
Expand Down Expand Up @@ -147,6 +168,10 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
void Memory::free_static(void *p_ptr, bool p_pad_align) {
ERR_FAIL_COND(p_ptr == nullptr);

#ifdef ALLOCATION_TRACKING_ENABLED
AllocationTracking::remove_alloc(p_ptr);
#endif

uint8_t *mem = (uint8_t *)p_ptr;

#ifdef DEBUG_ENABLED
Expand Down
41 changes: 41 additions & 0 deletions core/os/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#define MEMORY_H

#include "core/error_macros.h"
#include "core/os/memory_tracker.h"
#include "core/safe_refcount.h"

#include <stddef.h>
Expand All @@ -50,6 +51,10 @@ class Memory {
static SafeNumeric<uint64_t> alloc_count;

public:
#ifdef ALLOCATION_TRACKING_ENABLED
static void *alloc_static_tracked(size_t p_bytes, const char *p_filename, int p_line, bool p_pad_align = false);
static void *realloc_static_tracked(void *p_memory, size_t p_bytes, const char *p_filename, int p_line, bool p_pad_align = false);
#endif
static void *alloc_static(size_t p_bytes, bool p_pad_align = false);
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);
Expand All @@ -61,7 +66,12 @@ class Memory {

class DefaultAllocator {
public:
#ifdef ALLOCATION_TRACKING_ENABLED
// This kind of sucks because the tracking will only tell us the DefaultAllocator file, but is better than nothing...
_FORCE_INLINE_ static void *alloc(size_t p_memory) { return Memory::alloc_static_tracked(p_memory, __FILE__, __LINE__, false); }
#else
_FORCE_INLINE_ static void *alloc(size_t p_memory) { return Memory::alloc_static(p_memory, false); }
#endif
_FORCE_INLINE_ static void free(void *p_ptr) { Memory::free_static(p_ptr, false); }
};

Expand All @@ -78,8 +88,13 @@ void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size));
void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description);
#endif

#ifdef ALLOCATION_TRACKING_ENABLED
#define memalloc(m_size) Memory::alloc_static_tracked(m_size, __FILE__, __LINE__)
#define memrealloc(m_mem, m_size) Memory::realloc_static_tracked(m_mem, m_size, __FILE__, __LINE__)
#else
#define memalloc(m_size) Memory::alloc_static(m_size)
#define memrealloc(m_mem, m_size) Memory::realloc_static(m_mem, m_size)
#endif
#define memfree(m_mem) Memory::free_static(m_mem)

_ALWAYS_INLINE_ void postinitialize_handler(void *) {}
Expand All @@ -90,7 +105,18 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
return p_obj;
}

#ifdef ALLOCATION_TRACKING_ENABLED

template <class T>
_ALWAYS_INLINE_ T *_post_initialize_tracked(T *p_obj, const char *p_filename, int p_line) {
postinitialize_handler(p_obj);
AllocationTracking::add_alloc(p_obj, sizeof(T), p_filename, p_line);
return p_obj;
}
#define memnew(m_class) _post_initialize_tracked(new ("") m_class, __FILE__, __LINE__)
#else
#define memnew(m_class) _post_initialize(new ("") m_class)
#endif

_ALWAYS_INLINE_ void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description) {
//void *failptr=0;
Expand All @@ -108,6 +134,9 @@ _ALWAYS_INLINE_ bool predelete_handler(void *) {

template <class T>
void memdelete(T *p_class) {
#ifdef ALLOCATION_TRACKING_ENABLED
AllocationTracking::remove_alloc(p_class);
#endif
if (!predelete_handler(p_class)) {
return; // doesn't want to be deleted
}
Expand Down Expand Up @@ -136,18 +165,30 @@ void memdelete_allocator(T *p_class) {
memdelete(m_v); \
}

#ifdef ALLOCATION_TRACKING_ENABLED
#define memnew_arr(m_class, m_count) memnew_arr_template<m_class>(m_count, __FILE__, __LINE__)
#else
#define memnew_arr(m_class, m_count) memnew_arr_template<m_class>(m_count)
#endif

template <typename T>
#ifdef ALLOCATION_TRACKING_ENABLED
T *memnew_arr_template(size_t p_elements, const char *p_filename, int p_line, const char *p_descr = "") {
#else
T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
#endif
if (p_elements == 0) {
return nullptr;
}
/** overloading operator new[] cannot be done , because it may not return the real allocated address (it may pad the 'element count' before the actual array). Because of that, it must be done by hand. This is the
same strategy used by std::vector, and the PoolVector class, so it should be safe.*/

size_t len = sizeof(T) * p_elements;
#ifdef ALLOCATION_TRACKING_ENABLED
uint64_t *mem = (uint64_t *)Memory::alloc_static_tracked(len, p_filename, p_line, true);
#else
uint64_t *mem = (uint64_t *)Memory::alloc_static(len, true);
#endif
T *failptr = nullptr; //get rid of a warning
ERR_FAIL_COND_V(!mem, failptr);
*(mem - 1) = p_elements;
Expand Down
Loading

0 comments on commit 09d5e3e

Please sign in to comment.