From 973af312ebd28b1fc0f97b5f348b329d5684a6fb Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Mon, 8 Jan 2024 18:14:22 -0800 Subject: [PATCH] Simplify basic_format_args --- include/fmt/core.h | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/include/fmt/core.h b/include/fmt/core.h index 03a47557d1ee0..bfafb57bf5d78 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -1727,15 +1727,19 @@ template class basic_format_args { // argument types are passed in the descriptor. This reduces binary code size // per formatting function call. unsigned long long desc_; - union { - // If is_packed() returns true then argument values are stored in values_; - // otherwise they are stored in args_. This is done to improve cache - // locality and reduce compiled code size since storing larger objects - // may require more code (at least on x86-64) even if the same amount of - // data is actually copied to stack. It saves ~10% on the bloat test. - const detail::value* values_; - const format_arg* args_; - }; + + // If is_packed() returns true then arguments are stored as `detail::value`; + // otherwise they are stored as `format_arg` objects. This is done to improve + // cache locality and reduce compiled code size since storing larger objects + // may require more code (at least on x86-64) even if the same amount of + // data is actually copied to stack. It saves ~10% on the bloat test. + const void* args_; + + auto get_value(int index) const -> const detail::value& { + return is_packed() + ? static_cast*>(args_)[index] + : static_cast(args_)[index].value_; + } constexpr auto is_packed() const -> bool { return (desc_ & detail::is_unpacked_bit) == 0; @@ -1750,12 +1754,6 @@ template class basic_format_args { return static_cast((desc_ >> shift) & mask); } - constexpr FMT_INLINE basic_format_args(unsigned long long desc, - const detail::value* values) - : desc_(desc), values_(values) {} - constexpr basic_format_args(unsigned long long desc, const format_arg* args) - : desc_(desc), args_(args) {} - public: constexpr basic_format_args() : desc_(0), args_(nullptr) {} @@ -1767,8 +1765,8 @@ template class basic_format_args { template constexpr FMT_INLINE basic_format_args( const format_arg_store_impl& store) - : basic_format_args(format_arg_store_impl::desc, - store.args()) {} + : desc_(format_arg_store_impl::desc), + args_(store.args()) {} /** \rst @@ -1778,7 +1776,7 @@ template class basic_format_args { */ constexpr FMT_INLINE basic_format_args( const dynamic_format_arg_store& store) - : basic_format_args(store.get_types(), store.data()) {} + : desc_(store.get_types()), args_(store.data()) {} /** \rst @@ -1786,20 +1784,20 @@ template class basic_format_args { \endrst */ constexpr basic_format_args(const format_arg* args, int count) - : basic_format_args(detail::is_unpacked_bit | detail::to_unsigned(count), - args) {} + : desc_(detail::is_unpacked_bit | detail::to_unsigned(count)), + args_(args) {} /** Returns the argument with the specified id. */ FMT_CONSTEXPR auto get(int id) const -> format_arg { format_arg arg; if (!is_packed()) { - if (id < max_size()) arg = args_[id]; + if (id < max_size()) arg = static_cast(args_)[id]; return arg; } if (id >= detail::max_packed_args) return arg; arg.type_ = type(id); if (arg.type_ == detail::type::none_type) return arg; - arg.value_ = values_[id]; + arg.value_ = static_cast*>(args_)[id]; return arg; } @@ -1812,8 +1810,7 @@ template class basic_format_args { template FMT_CONSTEXPR auto get_id(basic_string_view name) const -> int { if (!has_named_args()) return -1; - const auto& named_args = - (is_packed() ? values_[-1] : args_[-1].value_).named_args; + const auto& named_args = get_value(-1).named_args; for (size_t i = 0; i < named_args.size; ++i) { if (named_args.data[i].name == name) return named_args.data[i].id; }