Bug 1391103 - Align Maybe::mStorage like when the type is in a struct. r?froydnj
MozReview-Commit-ID: 6ArNhZA4Wdf
--- a/mfbt/Alignment.h
+++ b/mfbt/Alignment.h
@@ -29,16 +29,36 @@ class AlignmentFinder
};
public:
static const size_t alignment = sizeof(Aligner) - sizeof(T);
};
#define MOZ_ALIGNOF(T) mozilla::AlignmentFinder<T>::alignment
+namespace detail {
+template<typename T>
+struct AlignasHelper
+{
+ T mT;
+};
+} // namespace detail
+
+/*
+ * Use this instead of alignof to align struct field as if it is inside
+ * a struct. On some platforms, there exist types which have different
+ * alignment between when it is used on its own and when it is used on
+ * a struct field.
+ *
+ * Known examples are 64bit types (uint64_t, double) on 32bit Linux,
+ * where they have 8byte alignment on their own, and 4byte alignment
+ * when in struct.
+ */
+#define MOZ_ALIGNAS_IN_STRUCT(T) alignas(mozilla::detail::AlignasHelper<T>)
+
/*
* Declare the MOZ_ALIGNED_DECL macro for declaring aligned types.
*
* For instance,
*
* MOZ_ALIGNED_DECL(char arr[2], 8);
*
* will declare a two-character array |arr| aligned to 8 bytes.
--- a/mfbt/Maybe.h
+++ b/mfbt/Maybe.h
@@ -80,17 +80,17 @@ struct Nothing { };
*
* N.B. GCC has missed optimizations with Maybe in the past and may generate
* extra branches/loads/stores. Use with caution on hot paths; it's not known
* whether or not this is still a problem.
*/
template<class T>
class MOZ_NON_PARAM MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Maybe
{
- alignas(T) unsigned char mStorage[sizeof(T)];
+ MOZ_ALIGNAS_IN_STRUCT(T) unsigned char mStorage[sizeof(T)];
char mIsSome; // not bool -- guarantees minimal space consumption
// GCC fails due to -Werror=strict-aliasing if |mStorage| is directly cast to
// T*. Indirecting through these functions addresses the problem.
void* data() { return mStorage; }
const void* data() const { return mStorage; }
public: