Skip to content

Commit 1ba8ed0

Browse files
philnik777ldionne
andauthored
[libc++] Mark more types as trivially relocatable (llvm#89724)
Co-authored-by: Louis Dionne <[email protected]>
1 parent f84056c commit 1ba8ed0

File tree

21 files changed

+202
-0
lines changed

21 files changed

+202
-0
lines changed

libcxx/docs/ReleaseNotes/19.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ Improvements and New Features
5858
-----------------------------
5959

6060
- The performance of growing ``std::vector`` has been improved for trivially relocatable types.
61+
- A lot of types are considered trivially relocatable now, including ``vector`` and ``string``.
6162
- The performance of ``ranges::fill`` and ``ranges::fill_n`` has been improved for ``vector<bool>::iterator``\s,
6263
resulting in a performance increase of up to 1400x.
6364
- The ``std::mismatch`` algorithm has been optimized for integral types, which can lead up to 40x performance

libcxx/include/__exception/exception_ptr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
6666
friend _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT;
6767

6868
public:
69+
// exception_ptr is basically a COW string.
70+
using __trivially_relocatable = exception_ptr;
71+
6972
_LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {}
7073
_LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}
7174

libcxx/include/__expected/expected.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <__type_traits/is_swappable.h>
3232
#include <__type_traits/is_trivially_constructible.h>
3333
#include <__type_traits/is_trivially_destructible.h>
34+
#include <__type_traits/is_trivially_relocatable.h>
3435
#include <__type_traits/is_void.h>
3536
#include <__type_traits/lazy.h>
3637
#include <__type_traits/negation.h>
@@ -463,6 +464,11 @@ class expected : private __expected_base<_Tp, _Err> {
463464
using error_type = _Err;
464465
using unexpected_type = unexpected<_Err>;
465466

467+
using __trivially_relocatable =
468+
__conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value && __libcpp_is_trivially_relocatable<_Err>::value,
469+
expected,
470+
void>;
471+
466472
template <class _Up>
467473
using rebind = expected<_Up, error_type>;
468474

libcxx/include/__locale

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ _LIBCPP_HIDE_FROM_ABI const _Facet& use_facet(const locale&);
4949

5050
class _LIBCPP_EXPORTED_FROM_ABI locale {
5151
public:
52+
// locale is essentially a shared_ptr that doesn't support weak_ptrs and never got a move constructor.
53+
using __trivially_relocatable = locale;
54+
5255
// types:
5356
class _LIBCPP_EXPORTED_FROM_ABI facet;
5457
class _LIBCPP_EXPORTED_FROM_ABI id;

libcxx/include/__memory/shared_ptr.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,10 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr {
419419
typedef _Tp element_type;
420420
#endif
421421

422+
// A shared_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require
423+
// any bookkeeping, so it's always trivially relocatable.
424+
using __trivially_relocatable = shared_ptr;
425+
422426
private:
423427
element_type* __ptr_;
424428
__shared_weak_count* __cntrl_;
@@ -1301,6 +1305,10 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr {
13011305
typedef _Tp element_type;
13021306
#endif
13031307

1308+
// A weak_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require
1309+
// any bookkeeping, so it's always trivially relocatable.
1310+
using __trivially_relocatable = weak_ptr;
1311+
13041312
private:
13051313
element_type* __ptr_;
13061314
__shared_weak_count* __cntrl_;

libcxx/include/__split_buffer

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
#include <__memory/pointer_traits.h>
2525
#include <__memory/swap_allocator.h>
2626
#include <__type_traits/add_lvalue_reference.h>
27+
#include <__type_traits/conditional.h>
2728
#include <__type_traits/enable_if.h>
2829
#include <__type_traits/integral_constant.h>
2930
#include <__type_traits/is_nothrow_assignable.h>
3031
#include <__type_traits/is_nothrow_constructible.h>
3132
#include <__type_traits/is_swappable.h>
3233
#include <__type_traits/is_trivially_destructible.h>
34+
#include <__type_traits/is_trivially_relocatable.h>
3335
#include <__type_traits/remove_reference.h>
3436
#include <__utility/forward.h>
3537
#include <__utility/move.h>
@@ -64,6 +66,15 @@ public:
6466
using iterator = pointer;
6567
using const_iterator = const_pointer;
6668

69+
// A __split_buffer contains the following members which may be trivially relocatable:
70+
// - pointer: may be trivially relocatable, so it's checked
71+
// - allocator_type: may be trivially relocatable, so it's checked
72+
// __split_buffer doesn't have any self-references, so it's trivially relocatable if its members are.
73+
using __trivially_relocatable = __conditional_t<
74+
__libcpp_is_trivially_relocatable<pointer>::value && __libcpp_is_trivially_relocatable<allocator_type>::value,
75+
__split_buffer,
76+
void>;
77+
6778
pointer __first_;
6879
pointer __begin_;
6980
pointer __end_;

libcxx/include/__utility/pair.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <__type_traits/is_nothrow_constructible.h>
3535
#include <__type_traits/is_same.h>
3636
#include <__type_traits/is_swappable.h>
37+
#include <__type_traits/is_trivially_relocatable.h>
3738
#include <__type_traits/nat.h>
3839
#include <__type_traits/remove_cvref.h>
3940
#include <__type_traits/unwrap_ref.h>
@@ -71,6 +72,11 @@ struct _LIBCPP_TEMPLATE_VIS pair
7172
_T1 first;
7273
_T2 second;
7374

75+
using __trivially_relocatable =
76+
__conditional_t<__libcpp_is_trivially_relocatable<_T1>::value && __libcpp_is_trivially_relocatable<_T2>::value,
77+
pair,
78+
void>;
79+
7480
_LIBCPP_HIDE_FROM_ABI pair(pair const&) = default;
7581
_LIBCPP_HIDE_FROM_ABI pair(pair&&) = default;
7682

libcxx/include/array

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce
130130
#include <__type_traits/is_nothrow_constructible.h>
131131
#include <__type_traits/is_same.h>
132132
#include <__type_traits/is_swappable.h>
133+
#include <__type_traits/is_trivially_relocatable.h>
133134
#include <__type_traits/remove_cv.h>
134135
#include <__utility/empty.h>
135136
#include <__utility/integer_sequence.h>
@@ -166,6 +167,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
166167

167168
template <class _Tp, size_t _Size>
168169
struct _LIBCPP_TEMPLATE_VIS array {
170+
using __trivially_relocatable = __conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, array, void>;
171+
169172
// types:
170173
using __self = array;
171174
using value_type = _Tp;

libcxx/include/deque

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,16 @@ public:
477477
using reverse_iterator = std::reverse_iterator<iterator>;
478478
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
479479

480+
// A deque contains the following members which may be trivially relocatable:
481+
// - __map: is a `__split_buffer`, see `__split_buffer` for more information on when it is trivially relocatable
482+
// - size_type: is always trivially relocatable, since it is required to be an integral type
483+
// - allocator_type: may not be trivially relocatable, so it's checked
484+
// None of these are referencing the `deque` itself, so if all of them are trivially relocatable, `deque` is too.
485+
using __trivially_relocatable = __conditional_t<
486+
__libcpp_is_trivially_relocatable<__map>::value && __libcpp_is_trivially_relocatable<allocator_type>::value,
487+
deque,
488+
void>;
489+
480490
static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
481491
"[allocator.requirements] states that rebinding an allocator to the same type should result in the "
482492
"original allocator");

libcxx/include/optional

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ namespace std {
209209
#include <__type_traits/is_trivially_assignable.h>
210210
#include <__type_traits/is_trivially_constructible.h>
211211
#include <__type_traits/is_trivially_destructible.h>
212+
#include <__type_traits/is_trivially_relocatable.h>
212213
#include <__type_traits/negation.h>
213214
#include <__type_traits/remove_const.h>
214215
#include <__type_traits/remove_cvref.h>
@@ -580,6 +581,8 @@ class _LIBCPP_DECLSPEC_EMPTY_BASES optional
580581
public:
581582
using value_type = _Tp;
582583

584+
using __trivially_relocatable = conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, optional, void>;
585+
583586
private:
584587
// Disable the reference extension using this static assert.
585588
static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>,

0 commit comments

Comments
 (0)