From e3c76f793724cd7e0ade4dc610b104fb9996901c Mon Sep 17 00:00:00 2001 From: Sebastian Parborg Date: Mon, 19 Oct 2020 13:03:06 +0200 Subject: Fix libmv eigen alignment issues when compiling with AVX support There would be eigen alignment issues with the custom libmv vector class when compiling with AVX optimizations. This would lead to segfaults. Simply use the std::vector base class as suggested by the old TODO in the class header. Reviewed By: Sergey Differential Revision: http://developer.blender.org/D8968 --- intern/libmv/libmv/base/vector.h | 145 ++------------------------------- intern/libmv/libmv/base/vector_test.cc | 17 ++-- 2 files changed, 11 insertions(+), 151 deletions(-) diff --git a/intern/libmv/libmv/base/vector.h b/intern/libmv/libmv/base/vector.h index bdc4392155c..300291c5679 100644 --- a/intern/libmv/libmv/base/vector.h +++ b/intern/libmv/libmv/base/vector.h @@ -25,151 +25,18 @@ #ifndef LIBMV_BASE_VECTOR_H #define LIBMV_BASE_VECTOR_H -#include -#include +#include #include namespace libmv { -// A simple container class, which guarantees 16 byte alignment needed for most -// vectorization. Don't use this container for classes that cannot be copied -// via memcpy. -// FIXME: this class has some issues: -// - doesn't support iterators. -// - impede compatibility with code using STL. -// - the STL already provide support for custom allocators -// it could be replaced with a simple -// template class vector : std::vector {} declaration -// provided it doesn't break code relying on libmv::vector specific behavior -template > -class vector { - public: - ~vector() { clear(); } +// A simple container class, which guarantees the correct memory alignment +// needed for most eigen vectorization. Don't use this container for classes +// that cannot be copied via memcpy. - vector() { init(); } - vector(int size) { init(); resize(size); } - vector(int size, const T & val) { - init(); - resize(size); - std::fill(data_, data_+size_, val); } - - // Copy constructor and assignment. - vector(const vector &rhs) { - init(); - copy(rhs); - } - vector &operator=(const vector &rhs) { - if (&rhs != this) { - copy(rhs); - } - return *this; - } - - /// Swaps the contents of two vectors in constant time. - void swap(vector &other) { - std::swap(allocator_, other.allocator_); - std::swap(size_, other.size_); - std::swap(capacity_, other.capacity_); - std::swap(data_, other.data_); - } - - T *data() const { return data_; } - int size() const { return size_; } - int capacity() const { return capacity_; } - const T& back() const { return data_[size_ - 1]; } - T& back() { return data_[size_ - 1]; } - const T& front() const { return data_[0]; } - T& front() { return data_[0]; } - const T& operator[](int n) const { return data_[n]; } - T& operator[](int n) { return data_[n]; } - const T& at(int n) const { return data_[n]; } - T& at(int n) { return data_[n]; } - const T * begin() const { return data_; } - const T * end() const { return data_+size_; } - T * begin() { return data_; } - T * end() { return data_+size_; } - - void resize(size_t size) { - reserve(size); - if (size > size_) { - construct(size_, size); - } else if (size < size_) { - destruct(size, size_); - } - size_ = size; - } - - void push_back(const T &value) { - if (size_ == capacity_) { - reserve(size_ ? 2 * size_ : 1); - } - new (&data_[size_++]) T(value); - } - - void pop_back() { - resize(size_ - 1); - } - - void clear() { - destruct(0, size_); - deallocate(); - init(); - } - - void reserve(unsigned int size) { - if (size > size_) { - T *data = static_cast(allocate(size)); - memcpy(static_cast(data), data_, sizeof(*data)*size_); - allocator_.deallocate(data_, capacity_); - data_ = data; - capacity_ = size; - } - } - - bool empty() { - return size_ == 0; - } - - private: - void construct(int start, int end) { - for (int i = start; i < end; ++i) { - new (&data_[i]) T; - } - } - void destruct(int start, int end) { - for (int i = start; i < end; ++i) { - data_[i].~T(); - } - } - void init() { - size_ = 0; - data_ = 0; - capacity_ = 0; - } - - void *allocate(int size) { - return size ? allocator_.allocate(size) : 0; - } - - void deallocate() { - allocator_.deallocate(data_, size_); - data_ = 0; - } - - void copy(const vector &rhs) { - resize(rhs.size()); - for (int i = 0; i < rhs.size(); ++i) { - (*this)[i] = rhs[i]; - } - } - - Allocator allocator_; - size_t size_; - size_t capacity_; - T *data_; -}; +template +using vector = std::vector>; } // namespace libmv diff --git a/intern/libmv/libmv/base/vector_test.cc b/intern/libmv/libmv/base/vector_test.cc index f17718c3926..44b9a152148 100644 --- a/intern/libmv/libmv/base/vector_test.cc +++ b/intern/libmv/libmv/base/vector_test.cc @@ -115,31 +115,24 @@ TEST_F(VectorTest, ResizeConstructsAndDestructsAsExpected) { // Create one object. v.resize(1); EXPECT_EQ(1, v.size()); - EXPECT_EQ(1, v.capacity()); EXPECT_EQ(1, foo_construct_calls); - EXPECT_EQ(0, foo_destruct_calls); EXPECT_EQ(5, v[0].value); // Create two more. v.resize(3); EXPECT_EQ(3, v.size()); - EXPECT_EQ(3, v.capacity()); EXPECT_EQ(3, foo_construct_calls); - EXPECT_EQ(0, foo_destruct_calls); // Delete the last one. v.resize(2); EXPECT_EQ(2, v.size()); EXPECT_EQ(3, v.capacity()); EXPECT_EQ(3, foo_construct_calls); - EXPECT_EQ(1, foo_destruct_calls); // Delete the remaining two. v.resize(0); EXPECT_EQ(0, v.size()); - EXPECT_EQ(3, v.capacity()); EXPECT_EQ(3, foo_construct_calls); - EXPECT_EQ(3, foo_destruct_calls); } TEST_F(VectorTest, PushPopBack) { @@ -192,15 +185,15 @@ TEST_F(VectorTest, STLFind) { a.push_back(5); a.push_back(3); - // Find return an int * + // Find returns an int * EXPECT_EQ(std::find(&a[0], &a[2], 1) == &a[0], true); EXPECT_EQ(std::find(&a[0], &a[2], 5) == &a[1], true); EXPECT_EQ(std::find(&a[0], &a[2], 3) == &a[2], true); - // Find return a const int * - EXPECT_EQ(std::find(a.begin(), a.end(), 1) == &a[0], true); - EXPECT_EQ(std::find(a.begin(), a.end(), 5) == &a[1], true); - EXPECT_EQ(std::find(a.begin(), a.end(), 3) == &a[2], true); + // Find returns an interator + EXPECT_EQ(std::find(a.begin(), a.end(), 1) == std::next(a.begin(), 0), true); + EXPECT_EQ(std::find(a.begin(), a.end(), 5) == std::next(a.begin(), 1), true); + EXPECT_EQ(std::find(a.begin(), a.end(), 3) == std::next(a.begin(), 2), true); // Search value that are not in the vector EXPECT_EQ(std::find(a.begin(), a.end(), 0) == a.end(), true); -- cgit v1.2.3