From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 4EE793857C50 for ; Tue, 12 Apr 2022 21:41:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 4EE793857C50 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-492-ovo-SJIjN_a5P5hK1TbtfA-1; Tue, 12 Apr 2022 17:41:31 -0400 X-MC-Unique: ovo-SJIjN_a5P5hK1TbtfA-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 5E078833963; Tue, 12 Apr 2022 21:41:31 +0000 (UTC) Received: from localhost (unknown [10.33.36.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id 22C62C15D4F; Tue, 12 Apr 2022 21:41:31 +0000 (UTC) From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed 3/5] libstdc++: Use allocator to construct std::stacktrace_entry objects Date: Tue, 12 Apr 2022 22:41:26 +0100 Message-Id: <20220412214128.509227-3-jwakely@redhat.com> In-Reply-To: <20220412214128.509227-1-jwakely@redhat.com> References: <20220412214128.509227-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.85 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libstdc++@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++ mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Apr 2022 21:41:34 -0000 Tested powerpc64-linux, pushed to trunk. -- >8 -- Because std::basic_stacktrace is an allocator-aware container its elements should be initialized using allocator_traits::construct and destroyed using allocator_traits::destroy. This adds new _M_clone and _M_assign helper functions to construct elements correctly and uses those functions instead of calling std::uninitialized_copy_n. The _Impl::_M_destroy function needs to be passed an allocator to destroy the elements correctly, so is replaced by _M_resize which can also be used to trim the container to a smaller size. Because destroying and creating std::stacktrace_entry objects is cheap, the copy/move assignment operators can just destroy all existing elements and use _Impl._M_clone or _Impl._M_assign to create new ones. libstdc++-v3/ChangeLog: * include/std/stacktrace (basic_stacktrace): Use _Impl::_M_clone or _Impl::_M_assign to initialize elements in allocated storage. (basic_stacktrace::_M_clear()): Use _Impl::_M_resize instead of _Impl::_M_destroy. (basic_stacktrace::_Impl::_M_destroy()): Replace with ... (basic_stacktrace::_Impl::_M_resize(size_type, allocator&)): New function. (basic_stacktrace::_Impl::_M_push_back): Use _M_xclone. Construct new element using allocator. (basic_stacktrace::_Impl::_M_clone): New function. (basic_stacktrace::_Impl::_M_xclone): New function. (basic_stacktrace::_Impl::_M_assign): New function. --- libstdc++-v3/include/std/stacktrace | 92 +++++++++++++++-------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/libstdc++-v3/include/std/stacktrace b/libstdc++-v3/include/std/stacktrace index f36c5a9abef..382d900a822 100644 --- a/libstdc++-v3/include/std/stacktrace +++ b/libstdc++-v3/include/std/stacktrace @@ -289,7 +289,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__err < 0) __ret._M_clear(); else if (__ret.size() > __max_depth) - __ret._M_impl._M_size = __max_depth; + __ret._M_impl._M_resize(__max_depth, __ret._M_alloc); } return __ret; } @@ -318,11 +318,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_alloc(__alloc) { if (const auto __s = __other._M_impl._M_size) - if (auto __f = _M_impl._M_allocate(_M_alloc, __s)) - { - std::uninitialized_copy_n(__other.begin(), __s, __f); - _M_impl._M_size = __s; - } + _M_impl = __other._M_impl._M_clone(_M_alloc); } basic_stacktrace(basic_stacktrace&& __other, @@ -334,11 +330,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else if (_M_alloc == __other._M_alloc) _M_impl = std::__exchange(__other._M_impl, {}); else if (const auto __s = __other._M_impl._M_size) - if (auto __f = _M_impl._M_allocate(_M_alloc, __s)) - { - std::uninitialized_copy_n(__other.begin(), __s, __f); - _M_impl._M_size = __s; - } + _M_impl = __other._M_impl._M_clone(_M_alloc); } basic_stacktrace& @@ -370,19 +362,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if constexpr (__pocca) _M_alloc = __other._M_alloc; - if (auto __f = _M_impl._M_allocate(_M_alloc, __s)) - { - std::uninitialized_copy_n(__other.begin(), __s, __f); - _M_impl._M_size = __s; - } + _M_impl = __other._M_impl._M_clone(_M_alloc); } else { - // Current storage is large enough and can be freed by whichever - // allocator we will have after this function returns. - auto __to = std::copy_n(__other.begin(), __s, begin()); - std::destroy(__to, end()); - _M_impl._M_size = __s; + // Current storage is large enough. + _M_impl._M_resize(0, _M_alloc); + _M_impl._M_assign(__other._M_impl, _M_alloc); if constexpr (__pocca) _M_alloc = __other._M_alloc; @@ -418,23 +404,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { // Need to allocate new storage. _M_clear(); - - if (auto __f = _M_impl._M_allocate(_M_alloc, __s)) - { - std::uninitialized_copy_n(__other.begin(), __s, __f); - _M_impl._M_size = __s; - } + _M_impl = __other._M_impl._M_clone(_M_alloc); } else { // Current storage is large enough. - auto __first = __other.begin(); - auto __mid = __first + std::min(__s, _M_impl._M_size); - auto __last = __other.end(); - auto __to = std::copy(__first, __mid, begin()); - __to = std::uninitialized_copy(__mid, __last, __to); - std::destroy(__to, end()); - _M_impl._M_size = __s; + _M_impl._M_resize(0, _M_alloc); + _M_impl._M_assign(__other._M_impl, _M_alloc); } } @@ -527,7 +503,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } private: - // Precondition: _M_capacity != 0 bool _M_push_back(const value_type& __x) noexcept { @@ -537,7 +512,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _M_clear() noexcept { - _M_impl._M_destroy(); + _M_impl._M_resize(0, _M_alloc); _M_impl._M_deallocate(_M_alloc); } @@ -647,32 +622,59 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #undef _GLIBCXX_OPERATOR_DELETE #undef _GLIBCXX_OPERATOR_NEW + // Precondition: __n <= _M_size void - _M_destroy() noexcept + _M_resize(size_type __n, allocator_type& __alloc) noexcept { - std::destroy_n(_M_frames, _M_size); - _M_size = 0; + for (size_type __i = __n; __i < _M_size; ++__i) + _AllocTraits::destroy(__alloc, &_M_frames[__i]); + _M_size = __n; } - // Precondition: _M_capacity != 0 bool _M_push_back(allocator_type& __alloc, const stacktrace_entry& __f) noexcept { if (_M_size == _M_capacity) [[unlikely]] { - _Impl __tmp; - if (auto __f = __tmp._M_allocate(__alloc, _M_capacity * 2)) - std::uninitialized_copy_n(_M_frames, _M_size, __f); - else + _Impl __tmp = _M_xclone(_M_capacity ? _M_capacity : 8, __alloc); + if (!__tmp._M_capacity) [[unlikely]] return false; + _M_resize(0, __alloc); _M_deallocate(__alloc); *this = __tmp; } stacktrace_entry* __addr = std::to_address(_M_frames + _M_size++); - std::construct_at(__addr, __f); + _AllocTraits::construct(__alloc, __addr, __f); return true; } + + // Precondition: _M_size != 0 + _Impl + _M_clone(allocator_type& __alloc) const noexcept + { + return _M_xclone(_M_size, __alloc); + } + + // Precondition: _M_size != 0 || __extra != 0 + _Impl + _M_xclone(size_type __extra, allocator_type& __alloc) const noexcept + { + _Impl __i; + if (__i._M_allocate(__alloc, _M_size + __extra)) [[likely]] + __i._M_assign(*this, __alloc); + return __i; + } + + // Precondition: _M_capacity >= __other._M_size + void + _M_assign(const _Impl& __other, allocator_type& __alloc) noexcept + { + std::__uninitialized_copy_a(__other._M_frames, + __other._M_frames + __other._M_size, + _M_frames, __alloc); + _M_size = __other._M_size; + } }; [[no_unique_address]] allocator_type _M_alloc{}; -- 2.34.1