diff options
author | Hein-Pieter van Braam <hp@tmm.cx> | 2019-01-03 05:56:41 +0100 |
---|---|---|
committer | Hein-Pieter van Braam <hp@tmm.cx> | 2019-01-03 08:47:34 +0100 |
commit | 4240e3d668be01a8497747b542279041a64a11cd (patch) | |
tree | 1d4a527d0a9450a29b0311503da572d7511d31c7 /core/os | |
parent | d930c909f250f8584d38784cfaebb6a312696ef0 (diff) |
Optimizations for trivial types
Relying on various compiler primitives we can reduce the work done
in our memory allocators and CowData. For types with trivial ctors or
dtors we can skip looping over all elements when creating, resizing,
and destroying lists of objects.
These primitives are supported by clang, msvc, and GCC. However, once
we've moved to C++11 we can rely on several std:: primitives that do
the same thing and are standardized.
In my testing the extra conditionals introduced here get removed from
the generated program entirely as the results for these primitives is
known at compile time.
Diffstat (limited to 'core/os')
-rw-r--r-- | core/os/memory.h | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/core/os/memory.h b/core/os/memory.h index 558dc5ddf3..f3ca9fc614 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -116,7 +116,9 @@ void memdelete(T *p_class) { if (!predelete_handler(p_class)) return; // doesn't want to be deleted - p_class->~T(); + if (!__has_trivial_destructor(T)) + p_class->~T(); + Memory::free_static(p_class, false); } @@ -125,7 +127,9 @@ void memdelete_allocator(T *p_class) { if (!predelete_handler(p_class)) return; // doesn't want to be deleted - p_class->~T(); + if (!__has_trivial_destructor(T)) + p_class->~T(); + A::free(p_class); } @@ -150,11 +154,13 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") { ERR_FAIL_COND_V(!mem, failptr); *(mem - 1) = p_elements; - T *elems = (T *)mem; + if (!__has_trivial_constructor(T)) { + T *elems = (T *)mem; - /* call operator new */ - for (size_t i = 0; i < p_elements; i++) { - new (&elems[i], sizeof(T), p_descr) T; + /* call operator new */ + for (size_t i = 0; i < p_elements; i++) { + new (&elems[i], sizeof(T), p_descr) T; + } } return (T *)mem; @@ -177,12 +183,14 @@ void memdelete_arr(T *p_class) { uint64_t *ptr = (uint64_t *)p_class; - uint64_t elem_count = *(ptr - 1); + if (!__has_trivial_destructor(T)) { + uint64_t elem_count = *(ptr - 1); - for (uint64_t i = 0; i < elem_count; i++) { + for (uint64_t i = 0; i < elem_count; i++) { + p_class[i].~T(); + } + } - p_class[i].~T(); - }; Memory::free_static(ptr, true); } |