Răsfoiți Sursa

Merge pull request #24732 from hpvb/vector-pod-optimization

Optimizations for trivial types
Rémi Verschelde 6 ani în urmă
părinte
comite
578c6316c8
2 a modificat fișierele cu 44 adăugiri și 25 ștergeri
  1. 26 15
      core/cowdata.h
  2. 18 10
      core/os/memory.h

+ 26 - 15
core/cowdata.h

@@ -31,6 +31,8 @@
 #ifndef COWDATA_H_
 #define COWDATA_H_
 
+#include <string.h>
+
 #include "core/os/memory.h"
 #include "core/safe_refcount.h"
 
@@ -194,12 +196,14 @@ void CowData<T>::_unref(void *p_data) {
 		return; // still in use
 	// clean up
 
-	uint32_t *count = _get_size();
-	T *data = (T *)(count + 1);
+	if (!__has_trivial_destructor(T)) {
+		uint32_t *count = _get_size();
+		T *data = (T *)(count + 1);
 
-	for (uint32_t i = 0; i < *count; ++i) {
-		// call destructors
-		data[i].~T();
+		for (uint32_t i = 0; i < *count; ++i) {
+			// call destructors
+			data[i].~T();
+		}
 	}
 
 	// free mem
@@ -226,9 +230,13 @@ void CowData<T>::_copy_on_write() {
 		T *_data = (T *)(mem_new);
 
 		// initialize new elements
-		for (uint32_t i = 0; i < current_size; i++) {
+		if (__has_trivial_copy(T)) {
+			memcpy(mem_new, _ptr, current_size * sizeof(T));
 
-			memnew_placement(&_data[i], T(_get_data()[i]));
+		} else {
+			for (uint32_t i = 0; i < current_size; i++) {
+				memnew_placement(&_data[i], T(_get_data()[i]));
+			}
 		}
 
 		_unref(_ptr);
@@ -275,22 +283,25 @@ Error CowData<T>::resize(int p_size) {
 		}
 
 		// construct the newly created elements
-		T *elems = _get_data();
 
-		for (int i = *_get_size(); i < p_size; i++) {
+		if (!__has_trivial_constructor(T)) {
+			T *elems = _get_data();
 
-			memnew_placement(&elems[i], T);
+			for (int i = *_get_size(); i < p_size; i++) {
+				memnew_placement(&elems[i], T);
+			}
 		}
 
 		*_get_size() = p_size;
 
 	} else if (p_size < size()) {
 
-		// deinitialize no longer needed elements
-		for (uint32_t i = p_size; i < *_get_size(); i++) {
-
-			T *t = &_get_data()[i];
-			t->~T();
+		if (!__has_trivial_destructor(T)) {
+			// deinitialize no longer needed elements
+			for (uint32_t i = p_size; i < *_get_size(); i++) {
+				T *t = &_get_data()[i];
+				t->~T();
+			}
 		}
 
 		void *_ptrnew = (T *)Memory::realloc_static(_ptr, alloc_size, true);

+ 18 - 10
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);
 }