Bug 1366511: Part 1 - Allow packing Result<T, nsresult> values into a single word. r?ehsan,nbp draft
authorKris Maglione <maglione.k@gmail.com>
Tue, 29 Aug 2017 21:46:54 -0700
changeset 655535 291191cde633995e98c165cc4631d097e947be16
parent 654684 5b981c6ba496caff287cb0810f6bce4c2253f5ad
child 655536 bdf69e6d9837c52fbe532cb7e0ac0b054eb94dad
push id76906
push usermaglione.k@gmail.com
push dateWed, 30 Aug 2017 04:49:23 +0000
reviewersehsan, nbp
bugs1366511
milestone57.0a1
Bug 1366511: Part 1 - Allow packing Result<T, nsresult> values into a single word. r?ehsan,nbp When used as an error value, nsresult should never be NS_OK, which means that we should be able to safely pack simple nsresult Result values into a single word. MozReview-Commit-ID: GJvnyTPjynk
mfbt/Result.h
xpcom/base/nscore.h
--- a/mfbt/Result.h
+++ b/mfbt/Result.h
@@ -90,16 +90,37 @@ public:
   explicit ResultImplementation(E& aErrorValue) : mErrorValue(&aErrorValue) {}
 
   bool isOk() const { return mErrorValue == nullptr; }
 
   V unwrap() const { return V(); }
   E& unwrapErr() const { return *mErrorValue; }
 };
 
+template <typename V, typename E>
+class ResultImplementation<V, E, PackingStrategy::NullIsOk>
+{
+  static constexpr E NullValue = E(0);
+
+  E mErrorValue;
+
+public:
+  explicit ResultImplementation(V) : mErrorValue(NullValue) {}
+  explicit ResultImplementation(E aErrorValue) : mErrorValue(aErrorValue)
+  {
+    MOZ_ASSERT(aErrorValue != NullValue);
+  }
+
+  bool isOk() const { return mErrorValue == NullValue; }
+
+  V unwrap() const { return V(); }
+  E unwrapErr() const { return mErrorValue; }
+};
+
+
 /**
  * Specialization for when alignment permits using the least significant bit as
  * a tag bit.
  */
 template <typename V, typename E>
 class ResultImplementation<V*, E&, PackingStrategy::LowBitTagIsError>
 {
   uintptr_t mBits;
--- a/xpcom/base/nscore.h
+++ b/xpcom/base/nscore.h
@@ -189,16 +189,36 @@
 
 /**
  * Generic XPCOM result data type
  */
 #include "nsError.h"
 
 typedef MozRefCountType nsrefcnt;
 
+namespace mozilla {
+// Extensions to the mozilla::Result type for handling of nsresult values.
+//
+// Note that these specializations need to be defined before Result.h is
+// included, or we run into explicit specialization after instantiation errors,
+// especially if Result.h is used in multiple sources in a unified compile.
+
+namespace detail {
+// When used as an error value, nsresult should never be NS_OK.
+// This specialization allows us to pack Result<Ok, nsresult> into a
+// nsresult-sized value.
+template<typename T> struct UnusedZero;
+template<>
+struct UnusedZero<nsresult>
+{
+  static const bool value = true;
+};
+} // namespace detail
+} // namespace mozilla
+
 /*
  * Use these macros to do 64bit safe pointer conversions.
  */
 
 #define NS_PTR_TO_INT32(x) ((int32_t)(intptr_t)(x))
 #define NS_PTR_TO_UINT32(x) ((uint32_t)(intptr_t)(x))
 #define NS_INT32_TO_PTR(x) ((void*)(intptr_t)(x))