summaryrefslogtreecommitdiffstats
path: root/include/godot_cpp/core/memory.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/godot_cpp/core/memory.hpp')
-rw-r--r--include/godot_cpp/core/memory.hpp46
1 files changed, 34 insertions, 12 deletions
diff --git a/include/godot_cpp/core/memory.hpp b/include/godot_cpp/core/memory.hpp
index 97a2b13..6775cf7 100644
--- a/include/godot_cpp/core/memory.hpp
+++ b/include/godot_cpp/core/memory.hpp
@@ -40,10 +40,6 @@
#include <type_traits>
-#ifndef PAD_ALIGN
-#define PAD_ALIGN 16 //must always be greater than this at much
-#endif
-
// p_dummy argument is added to avoid conflicts with the engine functions when both engine and GDExtension are built as a static library on iOS.
void *operator new(size_t p_size, const char *p_dummy, const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool
void *operator new(size_t p_size, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)); ///< operator new that takes a description and uses MemoryStaticPool
@@ -69,6 +65,18 @@ class Memory {
Memory();
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
+ // Note: "alloc size" is used and set by the engine and is never accessed or changed for the extension.
+
+ static constexpr size_t SIZE_OFFSET = 0;
+ static constexpr size_t ELEMENT_OFFSET = ((SIZE_OFFSET + sizeof(uint64_t)) % alignof(uint64_t) == 0) ? (SIZE_OFFSET + sizeof(uint64_t)) : ((SIZE_OFFSET + sizeof(uint64_t)) + alignof(uint64_t) - ((SIZE_OFFSET + sizeof(uint64_t)) % alignof(uint64_t)));
+ static constexpr size_t DATA_OFFSET = ((ELEMENT_OFFSET + sizeof(uint64_t)) % alignof(max_align_t) == 0) ? (ELEMENT_OFFSET + sizeof(uint64_t)) : ((ELEMENT_OFFSET + sizeof(uint64_t)) + alignof(max_align_t) - ((ELEMENT_OFFSET + sizeof(uint64_t)) % alignof(max_align_t)));
+
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);
@@ -99,7 +107,7 @@ struct Comparator {
template <class T>
void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wrapped, T>>::type * = nullptr) {
- if (!std::is_trivially_destructible<T>::value) {
+ if constexpr (!std::is_trivially_destructible_v<T>) {
p_class->~T();
}
@@ -113,7 +121,7 @@ void memdelete(T *p_class) {
template <class T, class A>
void memdelete_allocator(T *p_class) {
- if (!std::is_trivially_destructible<T>::value) {
+ if constexpr (!std::is_trivially_destructible_v<T>) {
p_class->~T();
}
@@ -136,6 +144,10 @@ public:
#define memnew_arr(m_class, m_count) memnew_arr_template<m_class>(m_count)
+_FORCE_INLINE_ uint64_t *_get_element_count_ptr(uint8_t *p_ptr) {
+ return (uint64_t *)(p_ptr - Memory::DATA_OFFSET + Memory::ELEMENT_OFFSET);
+}
+
template <typename T>
T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
if (p_elements == 0) {
@@ -145,12 +157,14 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
same strategy used by std::vector, and the Vector class, so it should be safe.*/
size_t len = sizeof(T) * p_elements;
- uint64_t *mem = (uint64_t *)Memory::alloc_static(len, true);
+ uint8_t *mem = (uint8_t *)Memory::alloc_static(len, true);
T *failptr = nullptr; // Get rid of a warning.
ERR_FAIL_NULL_V(mem, failptr);
- *(mem - 1) = p_elements;
- if (!std::is_trivially_destructible<T>::value) {
+ uint64_t *_elem_count_ptr = _get_element_count_ptr(mem);
+ *(_elem_count_ptr) = p_elements;
+
+ if constexpr (!std::is_trivially_destructible_v<T>) {
T *elems = (T *)mem;
/* call operator new */
@@ -163,11 +177,19 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
}
template <typename T>
+size_t memarr_len(const T *p_class) {
+ uint8_t *ptr = (uint8_t *)p_class;
+ uint64_t *_elem_count_ptr = _get_element_count_ptr(ptr);
+ return *(_elem_count_ptr);
+}
+
+template <typename T>
void memdelete_arr(T *p_class) {
- uint64_t *ptr = (uint64_t *)p_class;
+ uint8_t *ptr = (uint8_t *)p_class;
- if (!std::is_trivially_destructible<T>::value) {
- uint64_t elem_count = *(ptr - 1);
+ if constexpr (!std::is_trivially_destructible_v<T>) {
+ uint64_t *_elem_count_ptr = _get_element_count_ptr(ptr);
+ uint64_t elem_count = *(_elem_count_ptr);
for (uint64_t i = 0; i < elem_count; i++) {
p_class[i].~T();