Bug 1366511: Part 1 - Allow packing Result<T, nsresult> values into a single word. r=ehsan,nbp
authorKris Maglione <maglione.k@gmail.com>
Thu, 31 Aug 2017 16:01:43 -0700
changeset 378147 88629182740457e16a97c55bc2d99a2c94960566
parent 378146 23668b78e645d68f3240d4554516572ab57c6319
child 378148 0ae47966e150a75c69cc6b691529aa8c7126565c
push id32422
push userarchaeopteryx@coole-files.de
push dateFri, 01 Sep 2017 08:39:53 +0000
treeherdermozilla-central@a3585c77e2b1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan, nbp
bugs1366511
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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
@@ -91,16 +91,42 @@ public:
 
   bool isOk() const { return mErrorValue == nullptr; }
 
   V unwrap() const { return V(); }
   E& unwrapErr() const { return *mErrorValue; }
 };
 
 /**
+ * Specialization for when the success type is Ok (or another empty class) and
+ * the error type is a value type which can never have the value 0 (as
+ * determined by UnusedZero<>).
+ */
+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))