Bug 1391103 - Align Maybe::mStorage like when the type is in a struct. r?froydnj draft
authorXidorn Quan <me@upsuper.org>
Thu, 17 Aug 2017 09:49:19 +1000
changeset 650183 bdf5a6838e66fb1a632808db188cf3f94815592b
parent 650182 7c5c74c7ebdf0765014b43dbdd892d882e556777
child 727320 bead5a5fe4da3c50246804683d0923517cf1bbbd
push id75293
push userxquan@mozilla.com
push dateTue, 22 Aug 2017 00:14:55 +0000
reviewersfroydnj
bugs1391103
milestone57.0a1
Bug 1391103 - Align Maybe::mStorage like when the type is in a struct. r?froydnj MozReview-Commit-ID: 6ArNhZA4Wdf
mfbt/Alignment.h
mfbt/Maybe.h
--- 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: