summaryrefslogtreecommitdiff
path: root/mfbt
diff options
context:
space:
mode:
authorFranklinDM <mrmineshafter17@gmail.com>2023-03-17 18:51:04 +0800
committerFranklinDM <mrmineshafter17@gmail.com>2023-03-17 20:29:19 +0800
commit5e6a0efb65eb9176db9ec37470c5730fd4ef5d88 (patch)
treedf0085e0863c6f8926a57a56907994ef4c58a2aa /mfbt
parent0c35e43441ec35bbd0e35105c1609fd8eeba624d (diff)
downloaduxp-5e6a0efb65eb9176db9ec37470c5730fd4ef5d88.tar.gz
Issue #2166 - Part 2: Use alignas/alignof in MaybeOneOf
Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1338374
Diffstat (limited to 'mfbt')
-rw-r--r--mfbt/MaybeOneOf.h35
1 files changed, 27 insertions, 8 deletions
diff --git a/mfbt/MaybeOneOf.h b/mfbt/MaybeOneOf.h
index ea8124772d..e4f298ec51 100644
--- a/mfbt/MaybeOneOf.h
+++ b/mfbt/MaybeOneOf.h
@@ -3,15 +3,20 @@
* 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/. */
+/*
+ * A class storing one of two optional value types that supports
+ * in-place lazy construction.
+ */
+
#ifndef mozilla_MaybeOneOf_h
#define mozilla_MaybeOneOf_h
-#include "mozilla/Alignment.h"
#include "mozilla/Assertions.h"
#include "mozilla/Move.h"
#include "mozilla/TemplateLib.h"
-#include <new> // For placement new
+#include <new> // for placement new
+#include <stddef.h> // for size_t
namespace mozilla {
@@ -23,11 +28,25 @@ namespace mozilla {
* |construct<T2>()|, a T1 or T2 object will be constructed with the given
* arguments and that object will be destroyed when the owning MaybeOneOf is
* destroyed.
+ *
+ * Because MaybeOneOf must be aligned suitable to hold any value stored within
+ * it, and because |alignas| requirements don't affect platform ABI with respect
+ * to how parameters are laid out in memory, MaybeOneOf can't be used as the
+ * type of a function parameter. Pass MaybeOneOf to functions by pointer or
+ * reference instead.
*/
template<class T1, class T2>
-class MaybeOneOf
+class MOZ_NON_PARAM MaybeOneOf
{
- AlignedStorage<tl::Max<sizeof(T1), sizeof(T2)>::value> storage;
+ static constexpr size_t StorageAlignment =
+ tl::Max<alignof(T1), alignof(T2)>::value;
+ static constexpr size_t StorageSize =
+ tl::Max<sizeof(T1), sizeof(T2)>::value;
+
+ alignas(StorageAlignment) unsigned char storage_[StorageSize];
+
+ void* storage() { return storage_; }
+ const void* storage() const { return storage_; }
enum State { None, SomeT1, SomeT2 } state;
template <class T, class Ignored = void> struct Type2State {};
@@ -36,14 +55,14 @@ class MaybeOneOf
T& as()
{
MOZ_ASSERT(state == Type2State<T>::result);
- return *(T*)storage.addr();
+ return *static_cast<T*>(storage());
}
template <class T>
const T& as() const
{
MOZ_ASSERT(state == Type2State<T>::result);
- return *(T*)storage.addr();
+ return *static_cast<const T*>(storage());
}
public:
@@ -65,7 +84,7 @@ public:
}
}
- MaybeOneOf &operator=(MaybeOneOf&& rhs)
+ MaybeOneOf& operator=(MaybeOneOf&& rhs)
{
MOZ_ASSERT(this != &rhs, "Self-move is prohibited");
this->~MaybeOneOf();
@@ -83,7 +102,7 @@ public:
{
MOZ_ASSERT(state == None);
state = Type2State<T>::result;
- ::new (storage.addr()) T(Forward<Args>(aArgs)...);
+ ::new (storage()) T(Forward<Args>(aArgs)...);
}
template <class T>