public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "andysem at mail dot ru" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug libstdc++/98978] New: Consider packing _M_Engaged in the tail padding of T in optional<>
Date: Fri, 05 Feb 2021 17:14:39 +0000	[thread overview]
Message-ID: <bug-98978-4@http.gcc.gnu.org/bugzilla/> (raw)

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98978

            Bug ID: 98978
           Summary: Consider packing _M_Engaged in the tail padding of T
                    in optional<>
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: andysem at mail dot ru
  Target Milestone: ---

Using std::optional with some types may considerably increase object sizes
since it adds alignof(T) bytes worth of overhead. Sometimes it is possible to
avoid this overhead if the flag indicating presence of the stored value
(_M_Engaged in libstdc++ sources) is placed in the tail padding of the T
object. This can be done if std::optional constructs an object of a type that
derives from T, which has an additional bool data member that is initialized to
true upon construction. The below code roughly illustrates the idea:

template< typename T >
struct _Optional_payload_base
{
  struct _PresentT : T
  {
    const bool _M_Engaged = true;

    // Forwarding ctors and other members
  };

  static constexpr size_t engaged_offset = offsetof(_PresentT, _M_Engaged);

  struct _AbsentT
  {
    unsigned char _M_Offset[engaged_offset];
    const bool _M_Engaged = false;
  };

  union _Storage
  {
    _AbsentT _M_Empty;
    _PresentT _M_Value;

    _Storage() : _M_Empty() {}

    // Forwarding ctors and other members
  };

  _Storage _M_payload

  bool is_engaged() const noexcept
  {
    return *reinterpret_cast< const bool* >(reinterpret_cast< const unsigned
char* >(&_M_payload) + engaged_offset);
  }
};

The above relies on some implementation details, such as:

- offsetof works for the type T. It does for many types in gcc, beyond what is
required by the C++ standard. Maybe there is a way to avoid offsetof, I just
didn't immediately see it.
- The location of _M_Engaged in both _PresentT and _AbsentT is the same. This
is a property of the target ABI, and AFAICS it should be true at least on x86
psABI and I think Microsoft ABI.

The above will only work for non-final class types, for other types, and where
the above requirements don't hold true, the current code with a separate
_M_Engaged flag would work.

             reply	other threads:[~2021-02-05 17:14 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-05 17:14 andysem at mail dot ru [this message]
2021-02-05 17:58 ` [Bug libstdc++/98978] " redi at gcc dot gnu.org
2021-02-05 18:00 ` redi at gcc dot gnu.org
2021-02-05 20:44 ` andysem at mail dot ru
2021-02-06 17:26 ` redi at gcc dot gnu.org
2021-08-31 16:24 ` redi at gcc dot gnu.org
2022-09-07 12:30 ` redi at gcc dot gnu.org
2022-09-18 12:27 ` andysem at mail dot ru

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-98978-4@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).