From b48b6c0caafc0ff2f5960e20fcc200e57543ccb9 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 7 Aug 2019 11:53:21 +0200 Subject: [PATCH] Vector: Use memmove() for moving trivial types around more This can definitely be improved with better trivial type detection and by using the TypedTransfer template in more places. It's a bit annoying that we can't get in Vector.h since it's included in the toolchain compilation before we have libstdc++. --- AK/Traits.h | 12 ++++++++++++ AK/Vector.h | 31 ++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/AK/Traits.h b/AK/Traits.h index b651a3f6350..0eaf5d3e869 100644 --- a/AK/Traits.h +++ b/AK/Traits.h @@ -12,32 +12,44 @@ struct GenericTraits { template struct Traits : public GenericTraits { + static constexpr bool is_trivial() { return false; } }; template<> struct Traits : public GenericTraits { + static constexpr bool is_trivial() { return true; } static unsigned hash(int i) { return int_hash(i); } static void dump(int i) { kprintf("%d", i); } }; template<> struct Traits : public GenericTraits { + static constexpr bool is_trivial() { return true; } static unsigned hash(unsigned u) { return int_hash(u); } static void dump(unsigned u) { kprintf("%u", u); } }; template<> struct Traits : public GenericTraits { + static constexpr bool is_trivial() { return true; } static unsigned hash(u16 u) { return int_hash(u); } static void dump(u16 u) { kprintf("%u", u); } }; +template<> +struct Traits : public GenericTraits { + static constexpr bool is_trivial() { return true; } + static unsigned hash(char c) { return int_hash(c); } + static void dump(char c) { kprintf("%c", c); } +}; + template struct Traits { static unsigned hash(const T* p) { return int_hash((unsigned)(__PTRDIFF_TYPE__)p); } + static constexpr bool is_trivial() { return true; } static void dump(const T* p) { kprintf("%p", p); } static bool equals(const T* a, const T* b) { return a == b; } }; diff --git a/AK/Vector.h b/AK/Vector.h index 7daf6c54d8d..21e3aa1b916 100644 --- a/AK/Vector.h +++ b/AK/Vector.h @@ -63,6 +63,30 @@ private: int m_index { 0 }; }; +template +class TypedTransfer { +public: + static void move(T* destination, T* source, size_t count) + { + if constexpr (Traits::is_trivial()) { + memmove(destination, source, count * sizeof(T)); + return; + } + for (size_t i = 0; i < count; ++i) + new (&destination[i]) T(AK::move(source[i])); + } + + static void copy(T* destination, const T* source, size_t count) + { + if constexpr (Traits::is_trivial()) { + memmove(destination, source, count * sizeof(T)); + return; + } + for (size_t i = 0; i < count; ++i) + new (&destination[i]) T(source[i]); + } +}; + template class Vector { public: @@ -379,9 +403,7 @@ public: } Vector tmp = move(other); - for (int i = 0; i < tmp.size(); ++i) - new (slot(i)) T(move(tmp.at(i))); - + TypedTransfer::move(slot(0), tmp.data(), tmp.size()); m_size += other_size; } @@ -390,8 +412,7 @@ public: if (!count) return; grow_capacity(size() + count); - for (int i = 0; i < count; ++i) - new (slot(m_size + i)) T(values[i]); + TypedTransfer::copy(slot(m_size), values, count); m_size += count; }