Mark constructing an Unexpected as cold
authorPhil Willoughby <philwill@fb.com>
Mon, 6 Nov 2017 17:06:27 +0000 (09:06 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Mon, 6 Nov 2017 17:21:04 +0000 (09:21 -0800)
Summary:
By marking the main constructors of `Unexpected` cold we are telling the compiler that we don't expect to execute them often. This can improve the locality and performance of the `Expected` branch, and reduce the code-size for the `Unexpected` branch.

The constructors we have marked cold here are only the ones used to originate an `Unexpected`. We don't mark the copy- move- or conversion-constructors as `cold` because they will typically be used in error-handling branches and it is not correct to say that they are colder than their surroundings in that case. Note that the entire error-handling branch is likely to be deduced to be cold because we told the compiler that it is likely that hasValue() is true and hasError() is false.

Because `makeUnexpected` unconditionally invokes one of these cold constructors it will inherit the property of being cold.

The GCC function attribute reference, which describes what `cold` means, is here: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes

Reviewed By: yfeldblum

Differential Revision: D6234305

fbshipit-source-id: 6876073e92ce54936ba7152175d76be653f5f463

folly/CppAttributes.h
folly/Expected.h

index 7a13f61517cd1220666f6c5b4c5e551e718e03bd..466aab91a81144527e968415207f666674d52d46 100644 (file)
 #define FOLLY_NULLABLE
 #define FOLLY_NONNULL
 #endif
 #define FOLLY_NULLABLE
 #define FOLLY_NONNULL
 #endif
+
+/**
+ * "Cold" indicates to the compiler that a function is only expected to be
+ * called from unlikely code paths. It can affect decisions made by the
+ * optimizer both when processing the function body and when analyzing
+ * call-sites.
+ */
+#if __GNUC__
+#define FOLLY_COLD __attribute__((__cold__))
+#else
+#define FOLLY_COLD
+#endif
index f15010dfe821600c58c1221e6739870b743af1f5..2705f33533e7e95fc43b191b9611f74e9f9f422e 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <glog/logging.h>
 
 
 #include <glog/logging.h>
 
+#include <folly/CppAttributes.h>
 #include <folly/Likely.h>
 #include <folly/Optional.h>
 #include <folly/Portability.h>
 #include <folly/Likely.h>
 #include <folly/Optional.h>
 #include <folly/Portability.h>
@@ -711,8 +712,10 @@ class Unexpected final {
   Unexpected(Unexpected&&) = default;
   Unexpected& operator=(const Unexpected&) = default;
   Unexpected& operator=(Unexpected&&) = default;
   Unexpected(Unexpected&&) = default;
   Unexpected& operator=(const Unexpected&) = default;
   Unexpected& operator=(Unexpected&&) = default;
-  constexpr /* implicit */ Unexpected(const Error& err) : error_(err) {}
-  constexpr /* implicit */ Unexpected(Error&& err) : error_(std::move(err)) {}
+  FOLLY_COLD constexpr /* implicit */ Unexpected(const Error& err)
+      : error_(err) {}
+  FOLLY_COLD constexpr /* implicit */ Unexpected(Error&& err)
+      : error_(std::move(err)) {}
 
   template <class Other FOLLY_REQUIRES_TRAILING(
       std::is_constructible<Error, Other&&>::value)>
 
   template <class Other FOLLY_REQUIRES_TRAILING(
       std::is_constructible<Error, Other&&>::value)>