diff options
author | Jonathan Wakely <redi@gcc.gnu.org> | 2016-10-14 13:03:47 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2016-10-14 13:03:47 +0100 |
commit | ace4c2f060160bd3ef9032cc151e36b84e4ba3e8 (patch) | |
tree | b1ea7c7f07360d2914b518d2a602e9c3b524547e | |
parent | cb3ac86754e416f716e478f309f13108f9e9ac7f (diff) | |
download | gcc-ace4c2f060160bd3ef9032cc151e36b84e4ba3e8.zip gcc-ace4c2f060160bd3ef9032cc151e36b84e4ba3e8.tar.gz gcc-ace4c2f060160bd3ef9032cc151e36b84e4ba3e8.tar.bz2 |
PR65122 extended alignment support in allocators
PR libstdc++/65122
* include/ext/malloc_allocator.h (malloc_allocator::allocate): Use
aligned_alloc for types with extended alignment if available,
otherwise throw bad_alloc if malloc doesn't return a suitable value.
* include/ext/bitmap_allocator.h (bitmap_allocator::allocate)
(bitmap_allocator::deallocate): Use aligned new/delete for types with
extended alignment.
* include/ext/mt_allocator.h (__mt_alloc::allocate)
(__mt_alloc::deallocate): Likewise.
* include/ext/new_allocator.h (new_allocator::allocate)
(new_allocator::deallocate): Likewise.
* include/ext/pool_allocator.h (__pool_alloc::allocate)
(__pool_alloc::deallocate): Likewise.
* testsuite/20_util/allocator/overaligned.cc: New test.
* testsuite/ext/bitmap_allocator/overaligned.cc: New test.
* testsuite/ext/malloc_allocator/overaligned.cc: New test.
* testsuite/ext/mt_allocator/overaligned.cc: New test.
* testsuite/ext/new_allocator/overaligned.cc: New test.
* testsuite/ext/pool_allocator/overaligned.cc: New test.
From-SVN: r241158
-rw-r--r-- | libstdc++-v3/ChangeLog | 25 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/bitmap_allocator.h | 18 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/malloc_allocator.h | 25 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/mt_allocator.h | 18 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/new_allocator.h | 18 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/pool_allocator.h | 18 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/allocator/overaligned.cc | 48 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/ext/bitmap_allocator/overaligned.cc | 48 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/ext/malloc_allocator/overaligned.cc | 68 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/ext/mt_allocator/overaligned.cc | 48 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/ext/new_allocator/overaligned.cc | 48 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/ext/pool_allocator/overaligned.cc | 48 |
12 files changed, 426 insertions, 4 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4a052f4..a401ee0 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,7 +1,30 @@ +2016-10-14 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/65122 + * include/ext/malloc_allocator.h (malloc_allocator::allocate): Use + aligned_alloc for types with extended alignment if available, + otherwise throw bad_alloc if malloc doesn't return a suitable value. + * include/ext/bitmap_allocator.h (bitmap_allocator::allocate) + (bitmap_allocator::deallocate): Use aligned new/delete for types with + extended alignment. + * include/ext/mt_allocator.h (__mt_alloc::allocate) + (__mt_alloc::deallocate): Likewise. + * include/ext/new_allocator.h (new_allocator::allocate) + (new_allocator::deallocate): Likewise. + * include/ext/pool_allocator.h (__pool_alloc::allocate) + (__pool_alloc::deallocate): Likewise. + * testsuite/20_util/allocator/overaligned.cc: New test. + * testsuite/ext/bitmap_allocator/overaligned.cc: New test. + * testsuite/ext/malloc_allocator/overaligned.cc: New test. + * testsuite/ext/mt_allocator/overaligned.cc: New test. + * testsuite/ext/new_allocator/overaligned.cc: New test. + * testsuite/ext/pool_allocator/overaligned.cc: New test. + 2016-10-14 Tim Shen <timshen@google.com> PR libstdc++/77944 - * include/std/variant: include <bits/funcexcept.h> for __try and __catch. + * include/std/variant: Include <bits/funcexcept.h> for __try and + __catch. 2016-10-14 Jonathan Wakely <jwakely@redhat.com> diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h index c7fbd3e..836abc8 100644 --- a/libstdc++-v3/include/ext/bitmap_allocator.h +++ b/libstdc++-v3/include/ext/bitmap_allocator.h @@ -1018,6 +1018,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__n > this->max_size()) std::__throw_bad_alloc(); +#if __cpp_aligned_new + if (alignof(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + const size_type __b = __n * sizeof(value_type); + std::align_val_t __al = std::align_val_t(alignof(value_type)); + return static_cast<pointer>(::operator new(__b, __al)); + } +#endif + if (__builtin_expect(__n == 1, true)) return this->_M_allocate_single_object(); else @@ -1036,6 +1045,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__builtin_expect(__p != 0, true)) { +#if __cpp_aligned_new + // Types with extended alignment are handled by operator delete. + if (alignof(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + ::operator delete(__p, std::align_val_t(alignof(value_type))); + return; + } +#endif + if (__builtin_expect(__n == 1, true)) this->_M_deallocate_single_object(__p); else diff --git a/libstdc++-v3/include/ext/malloc_allocator.h b/libstdc++-v3/include/ext/malloc_allocator.h index 5c32eab..acb60a2 100644 --- a/libstdc++-v3/include/ext/malloc_allocator.h +++ b/libstdc++-v3/include/ext/malloc_allocator.h @@ -30,6 +30,7 @@ #define _MALLOC_ALLOCATOR_H 1 #include <cstdlib> +#include <cstddef> #include <new> #include <bits/functexcept.h> #include <bits/move.h> @@ -100,9 +101,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__n > this->max_size()) std::__throw_bad_alloc(); - pointer __ret = static_cast<_Tp*>(std::malloc(__n * sizeof(_Tp))); + pointer __ret; +#if __cpp_aligned_new +#if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC + if (alignof(_Tp) > alignof(std::max_align_t)) + { + __ret = static_cast<_Tp*>(::aligned_alloc(alignof(_Tp), + __n * sizeof(_Tp))); + } +#else +# define _GLIBCXX_CHECK_MALLOC_RESULT +#endif +#endif + if (!__ret) + __ret = static_cast<_Tp*>(std::malloc(__n * sizeof(_Tp))); if (!__ret) std::__throw_bad_alloc(); +#ifdef _GLIBCXX_CHECK_MALLOC_RESULT +#undef _GLIBCXX_CHECK_MALLOC_RESULT + if (reinterpret_cast<std::size_t>(__ret) % alignof(_Tp)) + { + // Memory returned by malloc is not suitably aligned for _Tp. + deallocate(__ret, __n); + std::__throw_bad_alloc(); + } +#endif return __ret; } diff --git a/libstdc++-v3/include/ext/mt_allocator.h b/libstdc++-v3/include/ext/mt_allocator.h index 7016e48..d7ea7c1 100644 --- a/libstdc++-v3/include/ext/mt_allocator.h +++ b/libstdc++-v3/include/ext/mt_allocator.h @@ -691,6 +691,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__n > this->max_size()) std::__throw_bad_alloc(); +#if __cpp_aligned_new + // Types with extended alignment are handled by operator new/delete. + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + std::align_val_t __al = std::align_val_t(alignof(_Tp)); + return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al)); + } +#endif + __policy_type::_S_initialize_once(); // Requests larger than _M_max_bytes are handled by operator @@ -737,6 +746,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__builtin_expect(__p != 0, true)) { +#if __cpp_aligned_new + // Types with extended alignment are handled by operator new/delete. + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + ::operator delete(__p, std::align_val_t(alignof(_Tp))); + return; + } +#endif + // Requests larger than _M_max_bytes are handled by // operators new/delete directly. __pool_type& __pool = __policy_type::_S_get_pool(); diff --git a/libstdc++-v3/include/ext/new_allocator.h b/libstdc++-v3/include/ext/new_allocator.h index dd00b73..2ff4780 100644 --- a/libstdc++-v3/include/ext/new_allocator.h +++ b/libstdc++-v3/include/ext/new_allocator.h @@ -101,13 +101,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__n > this->max_size()) std::__throw_bad_alloc(); +#if __cpp_aligned_new + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + std::align_val_t __al = std::align_val_t(alignof(_Tp)); + return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al)); + } +#endif return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); } // __p is not permitted to be a null pointer. void deallocate(pointer __p, size_type) - { ::operator delete(__p); } + { +#if __cpp_aligned_new + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + ::operator delete(__p, std::align_val_t(alignof(_Tp))); + return; + } +#endif + ::operator delete(__p); + } size_type max_size() const _GLIBCXX_USE_NOEXCEPT diff --git a/libstdc++-v3/include/ext/pool_allocator.h b/libstdc++-v3/include/ext/pool_allocator.h index ee60e90..9e0511d 100644 --- a/libstdc++-v3/include/ext/pool_allocator.h +++ b/libstdc++-v3/include/ext/pool_allocator.h @@ -219,6 +219,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__n > this->max_size()) std::__throw_bad_alloc(); + const size_t __bytes = __n * sizeof(_Tp); + +#if __cpp_aligned_new + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + std::align_val_t __al = std::align_val_t(alignof(_Tp)); + return static_cast<_Tp*>(::operator new(__bytes, __al)); + } +#endif + // If there is a race through here, assume answer from getenv // will resolve in same direction. Inspired by techniques // to efficiently support threading found in basic_string.h. @@ -230,7 +240,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __atomic_add_dispatch(&_S_force_new, -1); } - const size_t __bytes = __n * sizeof(_Tp); if (__bytes > size_t(_S_max_bytes) || _S_force_new > 0) __ret = static_cast<_Tp*>(::operator new(__bytes)); else @@ -259,6 +268,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__builtin_expect(__n != 0 && __p != 0, true)) { +#if __cpp_aligned_new + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + ::operator delete(__p, std::align_val_t(alignof(_Tp))); + return; + } +#endif const size_t __bytes = __n * sizeof(_Tp); if (__bytes > static_cast<size_t>(_S_max_bytes) || _S_force_new > 0) ::operator delete(__p); diff --git a/libstdc++-v3/testsuite/20_util/allocator/overaligned.cc b/libstdc++-v3/testsuite/20_util/allocator/overaligned.cc new file mode 100644 index 0000000..384d1d2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/allocator/overaligned.cc @@ -0,0 +1,48 @@ +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-faligned-new" } +// { dg-do run { target c++11 } } + +#include <memory> +#include <cstddef> +#include <cstdint> +#include <testsuite_hooks.h> + +constexpr std::size_t align = alignof(std::max_align_t) * 4; + +struct X { + alignas(align) char c; +}; + +void +test01() +{ + std::allocator<X> a; + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 ); + a.deallocate(p1, 1); + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 ); + a.deallocate(p2, 20); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/ext/bitmap_allocator/overaligned.cc b/libstdc++-v3/testsuite/ext/bitmap_allocator/overaligned.cc new file mode 100644 index 0000000..7d365de --- /dev/null +++ b/libstdc++-v3/testsuite/ext/bitmap_allocator/overaligned.cc @@ -0,0 +1,48 @@ +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-faligned-new" } +// { dg-do run { target c++11 } } + +#include <ext/bitmap_allocator.h> +#include <cstddef> +#include <cstdint> +#include <testsuite_hooks.h> + +constexpr std::size_t align = alignof(std::max_align_t) * 4; + +struct X { + alignas(align) char c; +}; + +void +test01() +{ + __gnu_cxx::bitmap_allocator<X> a; + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 ); + a.deallocate(p1, 1); + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 ); + a.deallocate(p2, 20); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/ext/malloc_allocator/overaligned.cc b/libstdc++-v3/testsuite/ext/malloc_allocator/overaligned.cc new file mode 100644 index 0000000..87182f1 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/malloc_allocator/overaligned.cc @@ -0,0 +1,68 @@ +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-faligned-new" } +// { dg-do run { target c++11 } } + +#include <ext/malloc_allocator.h> +#include <cstddef> +#include <cstdint> +#include <testsuite_hooks.h> + +constexpr std::size_t align = alignof(std::max_align_t) * 2; + +struct X { + alignas(align) char c; +}; + +void +test01() +{ + __gnu_cxx::malloc_allocator<X> a; +#if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 ); + a.deallocate(p1, 1); + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 ); + a.deallocate(p2, 20); +#else + // Allocating for extended alignment is unreliable without aligned_alloc() + try + { + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 ); + a.deallocate(p1, 1); + } + catch (const std::bad_alloc&) + { } + try + { + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 ); + a.deallocate(p2, 20); + } + catch (const std::bad_alloc&) + { } +#endif +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/overaligned.cc b/libstdc++-v3/testsuite/ext/mt_allocator/overaligned.cc new file mode 100644 index 0000000..41b8b46 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/mt_allocator/overaligned.cc @@ -0,0 +1,48 @@ +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-faligned-new" } +// { dg-do run { target c++11 } } + +#include <ext/mt_allocator.h> +#include <cstddef> +#include <cstdint> +#include <testsuite_hooks.h> + +constexpr std::size_t align = alignof(std::max_align_t) * 4; + +struct X { + alignas(align) char c; +}; + +void +test01() +{ + __gnu_cxx::__mt_alloc<X> a; + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 ); + a.deallocate(p1, 1); + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 ); + a.deallocate(p2, 20); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/ext/new_allocator/overaligned.cc b/libstdc++-v3/testsuite/ext/new_allocator/overaligned.cc new file mode 100644 index 0000000..27413cf --- /dev/null +++ b/libstdc++-v3/testsuite/ext/new_allocator/overaligned.cc @@ -0,0 +1,48 @@ +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-faligned-new" } +// { dg-do run { target c++11 } } + +#include <ext/new_allocator.h> +#include <cstddef> +#include <cstdint> +#include <testsuite_hooks.h> + +constexpr std::size_t align = alignof(std::max_align_t) * 4; + +struct X { + alignas(align) char c; +}; + +void +test01() +{ + __gnu_cxx::new_allocator<X> a; + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 ); + a.deallocate(p1, 1); + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 ); + a.deallocate(p2, 20); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/ext/pool_allocator/overaligned.cc b/libstdc++-v3/testsuite/ext/pool_allocator/overaligned.cc new file mode 100644 index 0000000..b509b79 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/pool_allocator/overaligned.cc @@ -0,0 +1,48 @@ +// Copyright (C) 2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-faligned-new" } +// { dg-do run { target c++11 } } + +#include <ext/pool_allocator.h> +#include <cstddef> +#include <cstdint> +#include <testsuite_hooks.h> + +constexpr std::size_t align = alignof(std::max_align_t) * 4; + +struct X { + alignas(align) char c; +}; + +void +test01() +{ + __gnu_cxx::__pool_alloc<X> a; + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 ); + a.deallocate(p1, 1); + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 ); + a.deallocate(p2, 20); +} + +int +main() +{ + test01(); +} |