Skip to content

Commit 87c6629

Browse files
authored
Merge pull request #2014 from Ivorforce/memory-3.0
Sync `operator new` with Godot upstream
2 parents 889fe68 + cb5257a commit 87c6629

4 files changed

Lines changed: 39 additions & 54 deletions

File tree

include/godot_cpp/classes/wrapped.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ public: \
498498
\
499499
static void *_gde_binding_create_callback(void *p_token, void *p_instance) { \
500500
/* Do not call memnew here, we don't want the post-initializer to be called */ \
501-
return new ("", "") m_class((GodotObject *)p_instance); \
501+
return new (godot::DefaultAllocator{}) m_class((GodotObject *)p_instance); \
502502
} \
503503
static void _gde_binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \
504504
/* Explicitly call the deconstructor to ensure proper lifecycle for non-trivial members */ \

include/godot_cpp/core/class_db.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class ClassDB {
119119
if constexpr (!std::is_abstract_v<T>) {
120120
Wrapped::_set_construct_info<T>();
121121
#if GODOT_VERSION_MINOR >= 4
122-
T *new_object = new ("", "") T;
122+
T *new_object = new (godot::DefaultAllocator{}) T;
123123
if (p_notify_postinitialize) {
124124
new_object->_postinitialize();
125125
}

include/godot_cpp/core/memory.hpp

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,32 +32,15 @@
3232

3333
#include <cstddef>
3434
#include <cstdint>
35+
#include <new> // IWYU pragma: keep // `new` operators.
3536

3637
#include <godot_cpp/core/defs.hpp>
3738
#include <godot_cpp/core/error_macros.hpp>
3839
#include <godot_cpp/godot.hpp>
3940

4041
#include <type_traits>
4142

42-
// 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.
43-
void *operator new(size_t p_size, const char *p_dummy, const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool
44-
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
45-
void *operator new(size_t p_size, const char *p_dummy, void *p_pointer, size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
46-
47-
_ALWAYS_INLINE_ void *operator new(size_t p_size, const char *p_dummy, void *p_pointer, size_t check, const char *p_description) {
48-
return p_pointer;
49-
}
50-
51-
#ifdef _MSC_VER
52-
// When compiling with VC++ 2017, the above declarations of placement new generate many irrelevant warnings (C4291).
53-
// The purpose of the following definitions is to muffle these warnings, not to provide a usable implementation of placement delete.
54-
void operator delete(void *p_mem, const char *p_dummy, const char *p_description);
55-
void operator delete(void *p_mem, const char *p_dummy, void *(*p_allocfunc)(size_t p_size));
56-
void operator delete(void *p_mem, const char *p_dummy, void *p_pointer, size_t check, const char *p_description);
57-
#endif
58-
5943
namespace godot {
60-
6144
class Wrapped;
6245

6346
namespace Memory {
@@ -92,6 +75,35 @@ void *realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align = false);
9275
void free_static(void *p_ptr, bool p_pad_align = false);
9376
}; //namespace Memory
9477

78+
class DefaultAllocator {
79+
public:
80+
_ALWAYS_INLINE_ static void *alloc(size_t p_memory) { return Memory::alloc_static(p_memory); }
81+
_ALWAYS_INLINE_ static void free(void *p_ptr) { Memory::free_static(p_ptr); }
82+
};
83+
84+
} // namespace godot
85+
86+
// Overload of `new` operator to use the `Memory::alloc_static()` function.
87+
// The `DefaultAllocator` parameter is just a tag to select this overload.
88+
// NOTE: do not inline `new` operators due to GCC+LTO compiler bug (see GH-119752).
89+
void *operator new(size_t p_size, godot::DefaultAllocator p_allocator);
90+
91+
// Overload of `new` operator to use a custom allocation function.
92+
// p_allocator argument is added to avoid conflicts with the engine functions when both engine and GDExtension are built as a static library on iOS.
93+
void *operator new(size_t p_size, godot::DefaultAllocator p_allocator, void *(*p_allocfunc)(size_t p_size));
94+
95+
#if defined(_MSC_VER) && !defined(__clang__)
96+
// When compiling with VC++ 2017, the above declarations of placement new generate many irrelevant warnings (C4291).
97+
// The purpose of the following definitions is to muffle these warnings, not to provide a usable implementation of placement delete.
98+
inline void operator delete(void *p_mem, godot::DefaultAllocator p_allocator) {
99+
CRASH_NOW_MSG("Call to placement delete should not happen.");
100+
}
101+
inline void operator delete(void *p_mem, godot::DefaultAllocator, void *(*p_allocfunc)(size_t p_size)) {
102+
CRASH_NOW_MSG("Call to placement delete should not happen.");
103+
}
104+
#endif // defined(_MSC_VER) && !defined(__clang__)
105+
106+
namespace godot {
95107
template <typename T, std::enable_if_t<!std::is_base_of<::godot::Wrapped, T>::value, bool> = true>
96108
_ALWAYS_INLINE_ void _pre_initialize() {}
97109

@@ -117,10 +129,10 @@ _ALWAYS_INLINE_ memnew_result_t<T> _post_initialize(T *p_obj) {
117129
#define memrealloc(m_mem, m_size) ::godot::Memory::realloc_static(m_mem, m_size)
118130
#define memfree(m_mem) ::godot::Memory::free_static(m_mem)
119131

120-
#define memnew(m_class) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", "") m_class))
132+
#define memnew(m_class) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new (godot::DefaultAllocator{}) m_class)>>(), ::godot::_post_initialize(new (godot::DefaultAllocator{}) m_class))
121133

122-
#define memnew_allocator(m_class, m_allocator) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", m_allocator::alloc) m_class))
123-
#define memnew_placement(m_placement, m_class) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", m_placement, sizeof(m_class), "") m_class))
134+
#define memnew_allocator(m_class, m_allocator) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new (godot::DefaultAllocator{}, m_allocator::alloc) m_class)>>(), ::godot::_post_initialize(new (godot::DefaultAllocator{}, m_allocator::alloc) m_class))
135+
#define memnew_placement(m_placement, m_class) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new (m_placement) m_class)>>(), ::godot::_post_initialize(new (m_placement) m_class))
124136

125137
template <typename T>
126138
void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wrapped, T>>::type * = nullptr) {
@@ -145,12 +157,6 @@ void memdelete_allocator(T *p_class) {
145157
A::free(p_class);
146158
}
147159

148-
class DefaultAllocator {
149-
public:
150-
_ALWAYS_INLINE_ static void *alloc(size_t p_memory) { return Memory::alloc_static(p_memory); }
151-
_ALWAYS_INLINE_ static void free(void *p_ptr) { Memory::free_static(p_ptr); }
152-
};
153-
154160
template <typename T>
155161
class DefaultTypedAllocator {
156162
public:
@@ -166,7 +172,7 @@ _FORCE_INLINE_ uint64_t *_get_element_count_ptr(uint8_t *p_ptr) {
166172
}
167173

168174
template <typename T>
169-
T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
175+
T *memnew_arr_template(size_t p_elements) {
170176
if (p_elements == 0) {
171177
return nullptr;
172178
}
@@ -186,7 +192,7 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
186192

187193
/* call operator new */
188194
for (size_t i = 0; i < p_elements; i++) {
189-
new ("", &elems[i], sizeof(T), p_descr) T;
195+
new (&elems[i]) T;
190196
}
191197
}
192198

src/core/memory.cpp

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -95,31 +95,10 @@ _GlobalNil _GlobalNilClass::_nil;
9595

9696
} // namespace godot
9797

98-
// 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.
99-
void *operator new(size_t p_size, const char *p_dummy, const char *p_description) {
98+
void *operator new(size_t p_size, godot::DefaultAllocator p_allocator) {
10099
return godot::Memory::alloc_static(p_size);
101100
}
102101

103-
void *operator new(size_t p_size, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)) {
102+
void *operator new(size_t p_size, godot::DefaultAllocator p_allocator, void *(*p_allocfunc)(size_t p_size)) {
104103
return p_allocfunc(p_size);
105104
}
106-
107-
using namespace godot;
108-
109-
#ifdef _MSC_VER
110-
void operator delete(void *p_mem, const char *p_dummy, const char *p_description) {
111-
ERR_PRINT("Call to placement delete should not happen.");
112-
CRASH_NOW();
113-
}
114-
115-
void operator delete(void *p_mem, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)) {
116-
ERR_PRINT("Call to placement delete should not happen.");
117-
CRASH_NOW();
118-
}
119-
120-
void operator delete(void *p_mem, const char *p_dummy, void *p_pointer, size_t check, const char *p_description) {
121-
ERR_PRINT("Call to placement delete should not happen.");
122-
CRASH_NOW();
123-
}
124-
125-
#endif

0 commit comments

Comments
 (0)