tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit b938fe44ff7c1977d2b750e23c97c6df5c7e5099
parent e99c1970686484100badb848d49189433e76b4a2
Author: serge-sans-paille <sguelton@mozilla.com>
Date:   Thu,  2 Oct 2025 05:11:42 +0000

Bug 1991397 - Use [[no_unique_address]] to implement Compact Pair r=necko-reviewers,kershaw

It makes the implementation trivial compared to the Empty Base
Optimization one.

Differential Revision: https://phabricator.services.mozilla.com/D266656

Diffstat:
Mmfbt/CompactPair.h | 194+++++++++++--------------------------------------------------------------------
Mmfbt/UniquePtr.h | 1-
Mmfbt/tests/TestHashTable.cpp | 1+
Mnetwerk/base/nsURLHelper.cpp | 1+
Mnetwerk/protocol/http/HttpBaseChannel.cpp | 1+
Mtoolkit/components/aboutthirdparty/AboutThirdParty.h | 1+
6 files changed, 31 insertions(+), 168 deletions(-)

diff --git a/mfbt/CompactPair.h b/mfbt/CompactPair.h @@ -9,200 +9,60 @@ #ifndef mozilla_CompactPair_h #define mozilla_CompactPair_h -#include <type_traits> +#include "mozilla/Attributes.h" + +#include <cstddef> #include <tuple> +#include <type_traits> #include <utility> -#include "mozilla/Attributes.h" - namespace mozilla { -namespace detail { - -enum StorageType { AsBase, AsMember }; - -// Optimize storage using the Empty Base Optimization -- that empty base classes -// don't take up space -- to optimize size when one or the other class is -// stateless and can be used as a base class. -// -// The extra conditions on storage for B are necessary so that CompactPairHelper -// won't ambiguously inherit from either A or B, such that one or the other base -// class would be inaccessible. -template <typename A, typename B, - detail::StorageType = - std::is_empty_v<A> ? detail::AsBase : detail::AsMember, - detail::StorageType = std::is_empty_v<B> && - !std::is_base_of<A, B>::value && - !std::is_base_of<B, A>::value - ? detail::AsBase - : detail::AsMember> -struct CompactPairHelper; - -template <typename A, typename B> -struct CompactPairHelper<A, B, AsMember, AsMember> { - protected: - template <typename... AArgs, std::size_t... AIndexes, typename... BArgs, - std::size_t... BIndexes> - constexpr CompactPairHelper(std::tuple<AArgs...>& aATuple, - std::tuple<BArgs...>& aBTuple, - std::index_sequence<AIndexes...>, - std::index_sequence<BIndexes...>) - : mFirstA(std::forward<AArgs>(std::get<AIndexes>(aATuple))...), - mSecondB(std::forward<BArgs>(std::get<BIndexes>(aBTuple))...) {} - - public: - template <typename AArg, typename BArg> - constexpr CompactPairHelper(AArg&& aA, BArg&& aB) - : mFirstA(std::forward<AArg>(aA)), mSecondB(std::forward<BArg>(aB)) {} - - constexpr A& first() { return mFirstA; } - constexpr const A& first() const { return mFirstA; } - constexpr B& second() { return mSecondB; } - constexpr const B& second() const { return mSecondB; } - - void swap(CompactPairHelper& aOther) { - std::swap(mFirstA, aOther.mFirstA); - std::swap(mSecondB, aOther.mSecondB); - } - - private: - A mFirstA; - B mSecondB; -}; - -template <typename A, typename B> -struct CompactPairHelper<A, B, AsMember, AsBase> : private B { - protected: - template <typename... AArgs, std::size_t... AIndexes, typename... BArgs, - std::size_t... BIndexes> - constexpr CompactPairHelper(std::tuple<AArgs...>& aATuple, - std::tuple<BArgs...>& aBTuple, - std::index_sequence<AIndexes...>, - std::index_sequence<BIndexes...>) - : B(std::forward<BArgs>(std::get<BIndexes>(aBTuple))...), - mFirstA(std::forward<AArgs>(std::get<AIndexes>(aATuple))...) {} - - public: - template <typename AArg, typename BArg> - constexpr CompactPairHelper(AArg&& aA, BArg&& aB) - : B(std::forward<BArg>(aB)), mFirstA(std::forward<AArg>(aA)) {} - - constexpr A& first() { return mFirstA; } - constexpr const A& first() const { return mFirstA; } - constexpr B& second() { return *this; } - constexpr const B& second() const { return *this; } - - void swap(CompactPairHelper& aOther) { - std::swap(mFirstA, aOther.mFirstA); - std::swap(static_cast<B&>(*this), static_cast<B&>(aOther)); - } - - private: - A mFirstA; -}; - -template <typename A, typename B> -struct CompactPairHelper<A, B, AsBase, AsMember> : private A { - protected: - template <typename... AArgs, std::size_t... AIndexes, typename... BArgs, - std::size_t... BIndexes> - constexpr CompactPairHelper(std::tuple<AArgs...>& aATuple, - std::tuple<BArgs...>& aBTuple, - std::index_sequence<AIndexes...>, - std::index_sequence<BIndexes...>) - : A(std::forward<AArgs>(std::get<AIndexes>(aATuple))...), - mSecondB(std::forward<BArgs>(std::get<BIndexes>(aBTuple))...) {} - - public: - template <typename AArg, typename BArg> - constexpr CompactPairHelper(AArg&& aA, BArg&& aB) - : A(std::forward<AArg>(aA)), mSecondB(std::forward<BArg>(aB)) {} - - constexpr A& first() { return *this; } - constexpr const A& first() const { return *this; } - constexpr B& second() { return mSecondB; } - constexpr const B& second() const { return mSecondB; } - - void swap(CompactPairHelper& aOther) { - std::swap(static_cast<A&>(*this), static_cast<A&>(aOther)); - std::swap(mSecondB, aOther.mSecondB); - } - - private: - B mSecondB; -}; - -template <typename A, typename B> -struct CompactPairHelper<A, B, AsBase, AsBase> : private A, private B { - protected: - template <typename... AArgs, std::size_t... AIndexes, typename... BArgs, - std::size_t... BIndexes> - constexpr CompactPairHelper(std::tuple<AArgs...>& aATuple, - std::tuple<BArgs...>& aBTuple, - std::index_sequence<AIndexes...>, - std::index_sequence<BIndexes...>) - : A(std::forward<AArgs>(std::get<AIndexes>(aATuple))...), - B(std::forward<BArgs>(std::get<BIndexes>(aBTuple))...) {} - - public: - template <typename AArg, typename BArg> - constexpr CompactPairHelper(AArg&& aA, BArg&& aB) - : A(std::forward<AArg>(aA)), B(std::forward<BArg>(aB)) {} - - constexpr A& first() { return static_cast<A&>(*this); } - constexpr const A& first() const { return static_cast<A&>(*this); } - constexpr B& second() { return static_cast<B&>(*this); } - constexpr const B& second() const { return static_cast<B&>(*this); } - - void swap(CompactPairHelper& aOther) { - std::swap(static_cast<A&>(*this), static_cast<A&>(aOther)); - std::swap(static_cast<B&>(*this), static_cast<B&>(aOther)); - } -}; - -} // namespace detail - /** * CompactPair is the logical concatenation of an instance of A with an instance - * B. Space is conserved when possible. Neither A nor B may be a final class. + * B. Space is conserved when possible. * * In general if space conservation is not critical is preferred to use * std::pair. * - * It's typically clearer to have individual A and B member fields. Except if - * you want the space-conserving qualities of CompactPair, you're probably - * better off not using this! - * - * No guarantees are provided about the memory layout of A and B, the order of - * initialization or destruction of A and B, and so on. (This is approximately - * required to optimize space usage.) The first/second names are merely - * conceptual! */ template <typename A, typename B> -struct CompactPair : private detail::CompactPairHelper<A, B> { - typedef typename detail::CompactPairHelper<A, B> Base; +class CompactPair { + MOZ_NO_UNIQUE_ADDRESS A mFirst; + MOZ_NO_UNIQUE_ADDRESS B mSecond; - using Base::Base; + template <class APack, size_t... AIs, class BPack, size_t... BIs> + constexpr CompactPair(APack&& aFirst, std::index_sequence<AIs...>, + BPack&& aSecond, std::index_sequence<BIs...>) + : mFirst(std::get<AIs>(aFirst)...), mSecond(std::get<BIs>(aSecond)...) {} + public: template <typename... AArgs, typename... BArgs> constexpr CompactPair(std::piecewise_construct_t, std::tuple<AArgs...> aFirst, std::tuple<BArgs...> aSecond) - : Base(aFirst, aSecond, std::index_sequence_for<AArgs...>(), - std::index_sequence_for<BArgs...>()) {} + : CompactPair(aFirst, std::make_index_sequence<sizeof...(AArgs)>(), + aSecond, std::make_index_sequence<sizeof...(BArgs)>()) {} + template <typename U, typename V> + explicit constexpr CompactPair(U&& aFirst, V&& aSecond) + : mFirst(std::forward<U>(aFirst)), mSecond(std::forward<V>(aSecond)) {} CompactPair(CompactPair&& aOther) = default; CompactPair(const CompactPair& aOther) = default; CompactPair& operator=(CompactPair&& aOther) = default; CompactPair& operator=(const CompactPair& aOther) = default; - /** The A instance. */ - using Base::first; - /** The B instance. */ - using Base::second; + constexpr A& first() { return mFirst; } + constexpr const A& first() const { return mFirst; } + constexpr B& second() { return mSecond; } + constexpr const B& second() const { return mSecond; } /** Swap this pair with another pair. */ - void swap(CompactPair& aOther) { Base::swap(aOther); } + void swap(CompactPair& aOther) { + using std::swap; + swap(mFirst, aOther.mFirst); + swap(mSecond, aOther.mSecond); + } }; /** diff --git a/mfbt/UniquePtr.h b/mfbt/UniquePtr.h @@ -15,7 +15,6 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" -#include "mozilla/CompactPair.h" #include "mozilla/Compiler.h" namespace mozilla { diff --git a/mfbt/tests/TestHashTable.cpp b/mfbt/tests/TestHashTable.cpp @@ -4,6 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "mozilla/CompactPair.h" #include "mozilla/HashTable.h" #include "mozilla/PairHash.h" diff --git a/netwerk/base/nsURLHelper.cpp b/netwerk/base/nsURLHelper.cpp @@ -7,6 +7,7 @@ #include "nsURLHelper.h" #include "mozilla/AppShutdown.h" +#include "mozilla/CompactPair.h" #include "mozilla/Encoding.h" #include "mozilla/Mutex.h" #include "mozilla/RangedPtr.h" diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -21,6 +21,7 @@ #include "mozilla/AntiTrackingUtils.h" #include "mozilla/BasePrincipal.h" #include "mozilla/BinarySearch.h" +#include "mozilla/CompactPair.h" #include "mozilla/ConsoleReportCollector.h" #include "mozilla/DebugOnly.h" #include "mozilla/InputStreamLengthHelper.h" diff --git a/toolkit/components/aboutthirdparty/AboutThirdParty.h b/toolkit/components/aboutthirdparty/AboutThirdParty.h @@ -7,6 +7,7 @@ #ifndef __AboutThirdParty_h__ #define __AboutThirdParty_h__ +#include "mozilla/CompactPair.h" #include "mozilla/MozPromise.h" #include "nsIAboutThirdParty.h" #include "nsInterfaceHashtable.h"