Skip to content

Commit cb730ad

Browse files
committed
Reformulate the API around number of objects instead of number of bytes
1 parent 0196f5b commit cb730ad

File tree

11 files changed

+74
-40
lines changed

11 files changed

+74
-40
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,7 @@ set(files
879879
__utility/cmp.h
880880
__utility/convert_to_integral.h
881881
__utility/declval.h
882+
__utility/element_count.h
882883
__utility/empty.h
883884
__utility/exception_guard.h
884885
__utility/exchange.h

libcxx/include/__functional/function.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,13 @@ class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> {
192192
}
193193
};
194194

195+
template <class _Tp>
196+
struct __deallocating_deleter {
197+
_LIBCPP_HIDE_FROM_ABI void operator()(void* __p) const {
198+
std::__libcpp_deallocate<_Tp>(static_cast<_Tp*>(__p), __element_count(1));
199+
}
200+
};
201+
195202
template <class _Fp, class _Rp, class... _ArgTypes>
196203
class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> {
197204
_Fp __f_;
@@ -212,8 +219,7 @@ class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> {
212219

213220
_LIBCPP_HIDE_FROM_ABI __default_alloc_func* __clone() const {
214221
using _Self = __default_alloc_func;
215-
unique_ptr<_Self, __deallocating_deleter<_Self>> __hold(
216-
static_cast<_Self*>(std::__libcpp_allocate<_Self>(sizeof(_Self), _LIBCPP_ALIGNOF(_Self))));
222+
unique_ptr<_Self, __deallocating_deleter<_Self>> __hold(std::__libcpp_allocate<_Self>(__element_count(1)));
217223
_Self* __res = ::new ((void*)__hold.get()) _Self(__f_);
218224
(void)__hold.release();
219225
return __res;
@@ -223,7 +229,7 @@ class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> {
223229

224230
_LIBCPP_HIDE_FROM_ABI static void __destroy_and_delete(__default_alloc_func* __f) {
225231
__f->destroy();
226-
__deallocating_deleter<__default_alloc_func>()(__f);
232+
std::__libcpp_deallocate<__default_alloc_func>(__f, __element_count(1));
227233
}
228234
};
229235

@@ -669,8 +675,7 @@ class __policy_func<_Rp(_ArgTypes...)> {
669675
if (__use_small_storage<_Fun>()) {
670676
::new ((void*)&__buf_.__small) _Fun(std::move(__f));
671677
} else {
672-
unique_ptr<_Fun, __deallocating_deleter<_Fun>> __hold(
673-
static_cast<_Fun*>(std::__libcpp_allocate<_Fun>(sizeof(_Fun), _LIBCPP_ALIGNOF(_Fun))));
678+
unique_ptr<_Fun, __deallocating_deleter<_Fun>> __hold(std::__libcpp_allocate<_Fun>(__element_count(1)));
674679
__buf_.__large = ::new ((void*)__hold.get()) _Fun(std::move(__f));
675680
(void)__hold.release();
676681
}

libcxx/include/__memory/allocator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if<!is_void<_Tp>::v
102102
if (__libcpp_is_constant_evaluated()) {
103103
return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
104104
} else {
105-
return static_cast<_Tp*>(std::__libcpp_allocate<_Tp>(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)));
105+
return std::__libcpp_allocate<_Tp>(__element_count(__n));
106106
}
107107
}
108108

@@ -117,7 +117,7 @@ class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if<!is_void<_Tp>::v
117117
if (__libcpp_is_constant_evaluated()) {
118118
::operator delete(__p);
119119
} else {
120-
std::__libcpp_deallocate<_Tp>((void*)__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));
120+
std::__libcpp_deallocate<_Tp>(__p, __element_count(__n));
121121
}
122122
}
123123

libcxx/include/__memory/unique_temporary_buffer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct __temporary_buffer_deleter {
4040
return;
4141
}
4242

43-
std::__libcpp_deallocate_unsized<_Tp>((void*)__ptr, _LIBCPP_ALIGNOF(_Tp));
43+
std::__libcpp_deallocate_unsized<_Tp>(__ptr);
4444
}
4545
};
4646

libcxx/include/__new/allocate.h

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <__cstddef/size_t.h>
1515
#include <__new/align_val_t.h>
1616
#include <__new/global_new_delete.h> // for _LIBCPP_HAS_SIZED_DEALLOCATION
17+
#include <__type_traits/type_identity.h>
18+
#include <__utility/element_count.h>
1719

1820
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1921
# pragma GCC system_header
@@ -48,16 +50,17 @@ _LIBCPP_HIDE_FROM_ABI void __libcpp_operator_delete(_Args... __args) _NOEXCEPT {
4850
}
4951

5052
template <class _Tp>
51-
inline _LIBCPP_HIDE_FROM_ABI void* __libcpp_allocate(size_t __size, size_t __align) {
53+
inline _LIBCPP_HIDE_FROM_ABI _Tp* __libcpp_allocate(__element_count __n, size_t __align = _LIBCPP_ALIGNOF(_Tp)) {
54+
size_t __size = static_cast<size_t>(__n) * sizeof(_Tp);
5255
#if _LIBCPP_HAS_ALIGNED_ALLOCATION
5356
if (__is_overaligned_for_new(__align)) {
5457
const align_val_t __align_val = static_cast<align_val_t>(__align);
55-
return std::__libcpp_operator_new(__size, __align_val);
58+
return static_cast<_Tp*>(std::__libcpp_operator_new(__size, __align_val));
5659
}
5760
#endif
5861

5962
(void)__align;
60-
return std::__libcpp_operator_new(__size);
63+
return static_cast<_Tp*>(std::__libcpp_operator_new(__size));
6164
}
6265

6366
#if _LIBCPP_HAS_SIZED_DEALLOCATION
@@ -67,7 +70,9 @@ inline _LIBCPP_HIDE_FROM_ABI void* __libcpp_allocate(size_t __size, size_t __ali
6770
#endif
6871

6972
template <class _Tp>
70-
inline _LIBCPP_HIDE_FROM_ABI void __libcpp_deallocate(void* __ptr, size_t __size, size_t __align) _NOEXCEPT {
73+
inline _LIBCPP_HIDE_FROM_ABI void __libcpp_deallocate(
74+
__type_identity_t<_Tp>* __ptr, __element_count __n, size_t __align = _LIBCPP_ALIGNOF(_Tp)) _NOEXCEPT {
75+
size_t __size = static_cast<size_t>(__n) * sizeof(_Tp);
7176
(void)__size;
7277
#if !_LIBCPP_HAS_ALIGNED_ALLOCATION
7378
(void)__align;
@@ -82,17 +87,11 @@ inline _LIBCPP_HIDE_FROM_ABI void __libcpp_deallocate(void* __ptr, size_t __size
8287
#endif
8388
}
8489

85-
template <class _Tp>
86-
struct __deallocating_deleter {
87-
_LIBCPP_HIDE_FROM_ABI void operator()(void* __p) const {
88-
std::__libcpp_deallocate<_Tp>(__p, sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));
89-
}
90-
};
91-
9290
#undef _LIBCPP_ONLY_IF_SIZED_DEALLOCATION
9391

9492
template <class _Tp>
95-
inline _LIBCPP_HIDE_FROM_ABI void __libcpp_deallocate_unsized(void* __ptr, size_t __align) _NOEXCEPT {
93+
inline _LIBCPP_HIDE_FROM_ABI void
94+
__libcpp_deallocate_unsized(__type_identity_t<_Tp>* __ptr, size_t __align = _LIBCPP_ALIGNOF(_Tp)) _NOEXCEPT {
9695
#if !_LIBCPP_HAS_ALIGNED_ALLOCATION
9796
(void)__align;
9897
return std::__libcpp_operator_delete(__ptr);

libcxx/include/__string/constexpr_c_functions.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <__type_traits/is_trivially_copyable.h>
2626
#include <__type_traits/is_trivially_lexicographically_comparable.h>
2727
#include <__type_traits/remove_cv.h>
28+
#include <__utility/element_count.h>
2829
#include <__utility/is_pointer_in_range.h>
2930

3031
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -33,10 +34,6 @@
3334

3435
_LIBCPP_BEGIN_NAMESPACE_STD
3536

36-
// Type used to encode that a function takes an integer that represents a number
37-
// of elements as opposed to a number of bytes.
38-
enum class __element_count : size_t {};
39-
4037
template <class _Tp>
4138
inline const bool __is_char_type = false;
4239

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___UTILITY_ELEMENT_COUNT_H
10+
#define _LIBCPP___UTILITY_ELEMENT_COUNT_H
11+
12+
#include <__config>
13+
#include <cstddef>
14+
15+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
16+
# pragma GCC system_header
17+
#endif
18+
19+
_LIBCPP_BEGIN_NAMESPACE_STD
20+
21+
// Type used to encode that a function takes an integer that represents a number
22+
// of elements as opposed to a number of bytes.
23+
enum class __element_count : size_t {};
24+
25+
_LIBCPP_END_NAMESPACE_STD
26+
27+
#endif // _LIBCPP___UTILITY_ELEMENT_COUNT_H

libcxx/include/__utility/small_buffer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class __small_buffer {
6868
if constexpr (__fits_in_buffer<_Stored>) {
6969
return std::launder(reinterpret_cast<_Stored*>(__buffer_));
7070
} else {
71-
byte* __allocation = static_cast<byte*>(std::__libcpp_allocate<_Stored>(sizeof(_Stored), alignof(_Stored)));
71+
byte* __allocation = static_cast<byte*>(std::__libcpp_allocate<_Stored>(__element_count(1)));
7272
std::construct_at(reinterpret_cast<byte**>(__buffer_), __allocation);
7373
return std::launder(reinterpret_cast<_Stored*>(__allocation));
7474
}
@@ -77,7 +77,7 @@ class __small_buffer {
7777
template <class _Stored>
7878
_LIBCPP_HIDE_FROM_ABI void __dealloc() noexcept {
7979
if constexpr (!__fits_in_buffer<_Stored>)
80-
std::__libcpp_deallocate<_Stored>(*reinterpret_cast<void**>(__buffer_), sizeof(_Stored), alignof(_Stored));
80+
std::__libcpp_deallocate<_Stored>(__get<_Stored>(), __element_count(1));
8181
}
8282

8383
template <class _Stored, class... _Args>

libcxx/include/module.modulemap

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,7 @@ module std [system] {
15271527
module allocation_guard { header "__memory/allocation_guard.h" }
15281528
module allocator {
15291529
header "__memory/allocator.h"
1530-
export std.new.allocate // TODO: Workaround for https://github.com/llvm/llvm-project/issues/120108
1530+
export * // TODO: Workaround for https://github.com/llvm/llvm-project/issues/120108
15311531
}
15321532
module allocator_arg_t { header "__memory/allocator_arg_t.h" }
15331533
module allocator_destructor { header "__memory/allocator_destructor.h" }
@@ -1569,7 +1569,7 @@ module std [system] {
15691569
header "__memory/unique_temporary_buffer.h"
15701570
export std.memory.unique_ptr
15711571
export std_core.type_traits.is_constant_evaluated
1572-
export std.new.allocate // TODO: Workaround for https://github.com/llvm/llvm-project/issues/120108
1572+
export * // TODO: Workaround for https://github.com/llvm/llvm-project/issues/120108
15731573
}
15741574
module uses_allocator { header "__memory/uses_allocator.h" }
15751575
module uses_allocator_construction { header "__memory/uses_allocator_construction.h" }
@@ -1607,6 +1607,7 @@ module std [system] {
16071607
module align_val_t { header "__new/align_val_t.h" }
16081608
module allocate {
16091609
header "__new/allocate.h"
1610+
export std.utility.element_count // used as part of the API
16101611
export * // TODO: Workaround for https://github.com/llvm/llvm-project/issues/120108
16111612
}
16121613
module destroying_delete_t { header "__new/destroying_delete_t.h" }
@@ -1915,7 +1916,10 @@ module std [system] {
19151916

19161917
module string {
19171918
module char_traits { header "__string/char_traits.h" }
1918-
module constexpr_c_functions { header "__string/constexpr_c_functions.h" }
1919+
module constexpr_c_functions {
1920+
header "__string/constexpr_c_functions.h"
1921+
export std.utility.element_count // used as part of the constexpr C function's API
1922+
}
19191923
module extern_template_lists { header "__string/extern_template_lists.h" }
19201924
module fwd { header "__fwd/string.h" }
19211925

@@ -2025,6 +2029,7 @@ module std [system] {
20252029
}
20262030
module cmp { header "__utility/cmp.h" }
20272031
module convert_to_integral { header "__utility/convert_to_integral.h" }
2032+
module element_count { header "__utility/element_count.h" }
20282033
module exception_guard { header "__utility/exception_guard.h" }
20292034
module exchange { header "__utility/exchange.h" }
20302035
module forward_like { header "__utility/forward_like.h" }

libcxx/src/memory_resource.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,21 @@ static bool is_aligned_to(void* ptr, size_t align) {
4141
class _LIBCPP_EXPORTED_FROM_ABI __new_delete_memory_resource_imp : public memory_resource {
4242
void* do_allocate(size_t bytes, size_t align) override {
4343
#if _LIBCPP_HAS_ALIGNED_ALLOCATION
44-
return std::__libcpp_allocate<std::byte>(bytes, align);
44+
return std::__libcpp_allocate<std::byte>(__element_count(bytes), align);
4545
#else
4646
if (bytes == 0)
4747
bytes = 1;
48-
void* result = std::__libcpp_allocate<std::byte>(bytes, align);
48+
std::byte* result = std::__libcpp_allocate<std::byte>(__element_count(bytes), align);
4949
if (!is_aligned_to(result, align)) {
50-
std::__libcpp_deallocate<std::byte>(result, bytes, align);
50+
std::__libcpp_deallocate<std::byte>(result, __element_count(bytes), align);
5151
__throw_bad_alloc();
5252
}
5353
return result;
5454
#endif
5555
}
5656

5757
void do_deallocate(void* p, size_t bytes, size_t align) override {
58-
std::__libcpp_deallocate<std::byte>(p, bytes, align);
58+
std::__libcpp_deallocate<std::byte>(static_cast<std::byte*>(p), __element_count(bytes), align);
5959
}
6060

6161
bool do_is_equal(const memory_resource& other) const noexcept override { return &other == this; }

libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,42 +138,42 @@ void test_libcpp_dealloc() {
138138
std::size_t with_size_val = 2;
139139

140140
{
141-
std::__libcpp_deallocate_unsized<char>(p, under_align_val);
141+
std::__libcpp_deallocate_unsized<char>(static_cast<char*>(p), under_align_val);
142142
assert(stats.expect_plain());
143143
}
144144
stats.reset();
145145

146146
#if defined(NO_SIZE) && defined(NO_ALIGN)
147147
{
148-
std::__libcpp_deallocate<char>(p, with_size_val, over_align_val);
148+
std::__libcpp_deallocate<char>(static_cast<char*>(p), std::__element_count(with_size_val), over_align_val);
149149
assert(stats.expect_plain());
150150
}
151151
stats.reset();
152152
#elif defined(NO_SIZE)
153153
{
154-
std::__libcpp_deallocate<char>(p, with_size_val, over_align_val);
154+
std::__libcpp_deallocate<char>(static_cast<char*>(p), std::__element_count(with_size_val), over_align_val);
155155
assert(stats.expect_align(over_align_val));
156156
}
157157
stats.reset();
158158
#elif defined(NO_ALIGN)
159159
{
160-
std::__libcpp_deallocate<char>(p, with_size_val, over_align_val);
160+
std::__libcpp_deallocate<char>(static_cast<char*>(p), std::__element_count(with_size_val), over_align_val);
161161
assert(stats.expect_size(with_size_val));
162162
}
163163
stats.reset();
164164
#else
165165
{
166-
std::__libcpp_deallocate<char>(p, with_size_val, over_align_val);
166+
std::__libcpp_deallocate<char>(static_cast<char*>(p), std::__element_count(with_size_val), over_align_val);
167167
assert(stats.expect_size_align(with_size_val, over_align_val));
168168
}
169169
stats.reset();
170170
{
171-
std::__libcpp_deallocate_unsized<char>(p, over_align_val);
171+
std::__libcpp_deallocate_unsized<char>(static_cast<char*>(p), over_align_val);
172172
assert(stats.expect_align(over_align_val));
173173
}
174174
stats.reset();
175175
{
176-
std::__libcpp_deallocate<char>(p, with_size_val, under_align_val);
176+
std::__libcpp_deallocate<char>(static_cast<char*>(p), std::__element_count(with_size_val), under_align_val);
177177
assert(stats.expect_size(with_size_val));
178178
}
179179
stats.reset();

0 commit comments

Comments
 (0)