From: Yedidya Feldblum Date: Tue, 31 Oct 2017 05:00:27 +0000 (-0700) Subject: Outline most throw expressions in Expected X-Git-Tag: v2017.11.06.00~28 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=e3d0887cb670dd2eb70b805925b2d4b128ea0f70 Outline most throw expressions in Expected Summary: [Folly] Outline most `throw` expressions in `Expected`. They are definitionally cold, but in-line `throw` statements can expand code size more than is desirable. * Inline `throw` statement: https://godbolt.org/g/LPaf7V. * Outline `throw` statement: https://godbolt.org/g/HZBXn6. Reviewed By: Orvid Differential Revision: D6183613 fbshipit-source-id: 28240bb4aa40790d99da783a3c368db81fded124 --- diff --git a/folly/Expected.cpp b/folly/Expected.cpp new file mode 100644 index 00000000..7cb07e87 --- /dev/null +++ b/folly/Expected.cpp @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace folly { + +namespace expected_detail { + +// clang-format off +[[noreturn]] void throwBadExpectedAccess() { + throw BadExpectedAccess(); +} +// clang-format on + +} // namespace expected_detail + +} // namespace folly diff --git a/folly/Expected.h b/folly/Expected.h index c9874eba..945797bc 100644 --- a/folly/Expected.h +++ b/folly/Expected.h @@ -663,6 +663,12 @@ class BadExpectedAccess : public std::logic_error { BadExpectedAccess() : std::logic_error("bad Expected access") {} }; +namespace expected_detail { + +[[noreturn]] void throwBadExpectedAccess(); + +} // namespace expected_detail + /** * Unexpected - a helper type used to disambiguate the construction of * Expected objects in the error state. @@ -1059,7 +1065,7 @@ class Expected final : expected_detail::ExpectedStorage { void swap(Expected& that) noexcept( expected_detail::StrictAllOf::value) { if (this->uninitializedByException() || that.uninitializedByException()) { - throw BadExpectedAccess(); + expected_detail::throwBadExpectedAccess(); } using std::swap; if (*this) { @@ -1199,7 +1205,7 @@ class Expected final : expected_detail::ExpectedStorage { std::declval(), std::declval()...)) { if (this->uninitializedByException()) { - throw BadExpectedAccess(); + expected_detail::throwBadExpectedAccess(); } return expected_detail::ExpectedHelper::then_( base(), static_cast(fns)...); @@ -1210,7 +1216,7 @@ class Expected final : expected_detail::ExpectedStorage { std::declval(), std::declval()...)) { if (this->uninitializedByException()) { - throw BadExpectedAccess(); + expected_detail::throwBadExpectedAccess(); } return expected_detail::ExpectedHelper::then_( base(), static_cast(fns)...); @@ -1221,7 +1227,7 @@ class Expected final : expected_detail::ExpectedStorage { std::declval(), std::declval()...)) { if (this->uninitializedByException()) { - throw BadExpectedAccess(); + expected_detail::throwBadExpectedAccess(); } return expected_detail::ExpectedHelper::then_( std::move(base()), static_cast(fns)...); @@ -1235,7 +1241,7 @@ class Expected final : expected_detail::ExpectedStorage { std::declval()(std::declval())) { using Ret = decltype(std::declval()(std::declval())); if (this->uninitializedByException()) { - throw BadExpectedAccess(); + expected_detail::throwBadExpectedAccess(); } return Ret(expected_detail::ExpectedHelper::thenOrThrow_( base(), static_cast(yes), static_cast(no))); @@ -1246,7 +1252,7 @@ class Expected final : expected_detail::ExpectedStorage { std::declval()(std::declval())) { using Ret = decltype(std::declval()(std::declval())); if (this->uninitializedByException()) { - throw BadExpectedAccess(); + expected_detail::throwBadExpectedAccess(); } return Ret(expected_detail::ExpectedHelper::thenOrThrow_( base(), static_cast(yes), static_cast(no))); @@ -1257,7 +1263,7 @@ class Expected final : expected_detail::ExpectedStorage { std::declval()(std::declval())) { using Ret = decltype(std::declval()(std::declval())); if (this->uninitializedByException()) { - throw BadExpectedAccess(); + expected_detail::throwBadExpectedAccess(); } return Ret(expected_detail::ExpectedHelper::thenOrThrow_( std::move(base()), static_cast(yes), static_cast(no))); @@ -1269,13 +1275,13 @@ class Expected final : expected_detail::ExpectedStorage { if (LIKELY(hasError())) { throw typename Unexpected::BadExpectedAccess(this->error_); } - throw BadExpectedAccess(); + expected_detail::throwBadExpectedAccess(); } } void requireError() const { if (UNLIKELY(!hasError())) { - throw BadExpectedAccess(); + expected_detail::throwBadExpectedAccess(); } } @@ -1289,12 +1295,11 @@ inline typename std::enable_if::value, bool>::type operator==( const Expected& lhs, const Expected& rhs) { - if (UNLIKELY(lhs.which_ != rhs.which_)) { - return UNLIKELY(lhs.uninitializedByException()) ? false - : throw BadExpectedAccess(); - } if (UNLIKELY(lhs.uninitializedByException())) { - throw BadExpectedAccess(); + expected_detail::throwBadExpectedAccess(); + } + if (UNLIKELY(lhs.which_ != rhs.which_)) { + return false; } if (UNLIKELY(lhs.hasError())) { return true; // All error states are considered equal @@ -1318,7 +1323,7 @@ operator<( const Expected& rhs) { if (UNLIKELY( lhs.uninitializedByException() || rhs.uninitializedByException())) { - throw BadExpectedAccess(); + expected_detail::throwBadExpectedAccess(); } if (UNLIKELY(lhs.hasError())) { return !rhs.hasError(); diff --git a/folly/Makefile.am b/folly/Makefile.am index 4873c4ce..c24cd2c0 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -503,6 +503,7 @@ libfolly_la_SOURCES = \ dynamic.cpp \ ExceptionWrapper.cpp \ Executor.cpp \ + Expected.cpp \ File.cpp \ FileUtil.cpp \ FingerprintTables.cpp \