From patchwork Wed Oct 2 10:50:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 1991969 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=MaU5E4p2; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XJWyK1y3lz1xt1 for ; Wed, 2 Oct 2024 20:58:49 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id F346D384DEE3 for ; Wed, 2 Oct 2024 10:58:46 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 8FDC83858416 for ; Wed, 2 Oct 2024 10:58:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8FDC83858416 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 8FDC83858416 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727866705; cv=none; b=U/I2NpSG0HDPtUGmVnzyNCMNfCBIR4TU3YG9v1v/wObBQZxHvhd1jEXZlKyYv7dMT05P3wB1qm90TOqK50RCRTq2HVtDizHHC1oQ4fQP3vo8KiDgH1w3MikJQQcRmEtEvGxXN7ME547HqHk8UOu47mpJNR82nurmUPVoikfYkBc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727866705; c=relaxed/simple; bh=ZiHuTpm+UqRkOJ0oktVqdgNPk4TRYNRPKgPW9KqdxCE=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=VpayifxjUi/3YQD1qpdsARx4DOyChx3sIQ+HV5lZO/KssjR7cuvX7hEf7OSaLWk6oqr2KGgbIKwvglDCwKC/i2zKZ0LzlUslDZlSTMR3PpoPJcnQbrvKKjVtCNjgKsMWjTt+Cn31ZLh9lh2MdUGGx7yrekXbku6XuBxPpz5JqzQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1727866703; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=hbsiydGVz92pEFgyxUPZySh7Fm50LIBIioz8wn37jHo=; b=MaU5E4p2brataNtgiq1rSi01TPkSZ8AT4byarTFEl3jh0mFulQKjn6bKl8W8LSHSdXYvGS sG8DBtVqQkjXQsqHuS9YpYy0Xo8iHFyXCcnGABdyVUWJcsDuSz20iBEZAsLCLJhHreKHXN 0i5E4HusIldvLKkUpTQZP9xUlnLfOw8= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-393-rKZLv0nnNDySrPtsF2hi5Q-1; Wed, 02 Oct 2024 06:58:20 -0400 X-MC-Unique: rKZLv0nnNDySrPtsF2hi5Q-1 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 16D001955DD1; Wed, 2 Oct 2024 10:58:19 +0000 (UTC) Received: from localhost (unknown [10.42.28.136]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 83F4B1956056; Wed, 2 Oct 2024 10:58:18 +0000 (UTC) From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [PATCH] libstdc++: Add __gnu_cxx::__alloc_traits::_Destroy_static_type [PR110057] Date: Wed, 2 Oct 2024 11:50:24 +0100 Message-ID: <20241002105817.3171616-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.0 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_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org We could also use this in all containers (and node handles) and in the control block created by std::allocate_shared. To use it for containers we will need to decide whether to change the non-standard std::_Destroy(FwdIter, FwdIter, Allocator&) to use this, or whether to add a new _Destroy_static function and make the containers use that instead. For this RFC patch, I've only used it in a few places in std::vector where a single object is created/destroyed directly, so not when destroying multiple elements using std::_Destroy. Tested x86_64-linux. -- >8 -- Add a version of allocator_traits::destroy that can be used when the static type is known, so that we can make an explicit destructor call that avoids virtual lookup. This is only possible when the allocator doesn't provide a destroy member, so that we know we're going to invoke the destructor directly. In containers like std::vector we know that we're never destroying elements through a pointer to base, because the dynamic type is known to be the same as the static type. libstdc++-v3/ChangeLog: PR libstdc++/110057 * include/bits/stl_vector.h: Use _Destroy_static_type instead of destroy. * include/bits/vector.tcc: Likewise. * include/ext/alloc_traits.h (__alloc_traits::_Destroy_static_type): New function template. --- libstdc++-v3/include/bits/stl_vector.h | 5 ++-- libstdc++-v3/include/bits/vector.tcc | 3 ++- libstdc++-v3/include/ext/alloc_traits.h | 32 ++++++++++++++++++++++++- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index e284536ad31..f7451fa9e18 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -1325,7 +1325,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { __glibcxx_requires_nonempty(); --this->_M_impl._M_finish; - _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); + _Alloc_traits::_Destroy_static_type(this->_M_impl, + this->_M_impl._M_finish); _GLIBCXX_ASAN_ANNOTATE_SHRINK(1); } @@ -1870,7 +1871,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX20_CONSTEXPR ~_Temporary_value() - { _Alloc_traits::destroy(_M_this->_M_impl, _M_ptr()); } + { _Alloc_traits::_Destroy_static_type(_M_this->_M_impl, _M_ptr()); } _GLIBCXX20_CONSTEXPR value_type& _M_val() noexcept { return _M_storage._M_val; } diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index a99a5b56b77..660a8b4e414 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -184,7 +184,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (__position + 1 != end()) _GLIBCXX_MOVE3(__position + 1, end(), __position); --this->_M_impl._M_finish; - _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); + _Alloc_traits::_Destroy_static_type(this->_M_impl, + this->_M_impl._M_finish); _GLIBCXX_ASAN_ANNOTATE_SHRINK(1); return __position; } diff --git a/libstdc++-v3/include/ext/alloc_traits.h b/libstdc++-v3/include/ext/alloc_traits.h index d2560531bac..17caaee2715 100644 --- a/libstdc++-v3/include/ext/alloc_traits.h +++ b/libstdc++-v3/include/ext/alloc_traits.h @@ -33,7 +33,7 @@ #pragma GCC system_header #endif -# include +#include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { @@ -95,6 +95,30 @@ template noexcept(noexcept(_Base_type::destroy(__a, std::__to_address(__p)))) { _Base_type::destroy(__a, std::__to_address(__p)); } + // Equivalent to `destroy` except that when `a.destroy(p)` is not valid, + // the destructor will be called using a qualified name, so that no + // dynamic dispatch to a virtual destructor is done. This can be used + // in e.g. std::vector where we know that the elements do not have a + // dynamic type that is different from the static type. + template + [[__gnu__::__always_inline__]] + static _GLIBCXX20_CONSTEXPR void + _Destroy_static_type(_Alloc& __a, _Ptr __p) + { +#if __cpp_concepts + auto __ptr = std::__to_address(__p); + if constexpr (requires { __a.destroy(__ptr); }) + __a.destroy(__ptr); + else + { + using _Tp = std::remove_pointer_t; + __ptr->_Tp::~_Tp(); + } +#else + destroy(__a, __p); +#endif + } + [[__gnu__::__always_inline__]] static constexpr _Alloc _S_select_on_copy(const _Alloc& __a) { return _Base_type::select_on_container_copy_construction(__a); } @@ -178,6 +202,12 @@ template template struct rebind { typedef typename _Alloc::template rebind<_Tp>::other other; }; + + template + __attribute__((__always_inline__)) + static void + _Destroy_static_type(_Alloc& __a, _Ptr __p) + { __a.destroy(__p); } #endif // C++11 };