Commit 9552fbcd authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

tweak catch_exception taking fun-ptrs

Summary: To reduce build size, avoid creating unnecessary functions. If the provided callable is already a function-pointer, the callee will already not be inlined.

Differential Revision: D27984345

fbshipit-source-id: a5a31330541338eb04e802bd9dafd99188af3ab9
parent f35ba916
...@@ -74,7 +74,7 @@ fbstring exceptionStr(std::exception_ptr ep) { ...@@ -74,7 +74,7 @@ fbstring exceptionStr(std::exception_ptr ep) {
[&]() -> fbstring { [&]() -> fbstring {
return catch_exception<std::exception const&>( return catch_exception<std::exception const&>(
[&]() -> fbstring { std::rethrow_exception(std::move(ep)); }, [&]() -> fbstring { std::rethrow_exception(std::move(ep)); },
[](auto&& e) { return exceptionStr(e); }); static_cast<fbstring (&)(std::exception const&)>(exceptionStr));
}, },
[&]() -> fbstring { [&]() -> fbstring {
return type ? demangle(*type) : "<unknown exception>"; return type ? demangle(*type) : "<unknown exception>";
......
...@@ -16,12 +16,14 @@ ...@@ -16,12 +16,14 @@
#include <folly/ScopeGuard.h> #include <folly/ScopeGuard.h>
#include <exception>
#include <iostream> #include <iostream>
/*static*/ void folly::detail::ScopeGuardImplBase::warnAboutToCrash() noexcept { /*static*/ void folly::detail::ScopeGuardImplBase::terminate() noexcept {
// Ensure the availability of std::cerr // Ensure the availability of std::cerr
std::ios_base::Init ioInit; std::ios_base::Init ioInit;
std::cerr std::cerr
<< "This program will now terminate because a folly::ScopeGuard callback " << "This program will now terminate because a folly::ScopeGuard callback "
"threw an \nexception.\n"; "threw an \nexception.\n";
std::rethrow_exception(std::current_exception());
} }
...@@ -43,7 +43,7 @@ class ScopeGuardImplBase { ...@@ -43,7 +43,7 @@ class ScopeGuardImplBase {
protected: protected:
ScopeGuardImplBase(bool dismissed = false) noexcept : dismissed_(dismissed) {} ScopeGuardImplBase(bool dismissed = false) noexcept : dismissed_(dismissed) {}
static void warnAboutToCrash() noexcept; [[noreturn]] static void terminate() noexcept;
static ScopeGuardImplBase makeEmptyScopeGuard() noexcept { static ScopeGuardImplBase makeEmptyScopeGuard() noexcept {
return ScopeGuardImplBase{}; return ScopeGuardImplBase{};
} }
...@@ -125,7 +125,8 @@ class ScopeGuardImpl : public ScopeGuardImplBase { ...@@ -125,7 +125,8 @@ class ScopeGuardImpl : public ScopeGuardImplBase {
void execute() noexcept(InvokeNoexcept) { void execute() noexcept(InvokeNoexcept) {
if (InvokeNoexcept) { if (InvokeNoexcept) {
using R = decltype(function_()); using R = decltype(function_());
auto catcher = []() -> R { warnAboutToCrash(), std::terminate(); }; auto catcher_word = reinterpret_cast<uintptr_t>(&terminate);
auto catcher = reinterpret_cast<R (*)()>(catcher_word);
catch_exception(function_, catcher); catch_exception(function_, catcher);
} else { } else {
function_(); function_();
......
...@@ -125,7 +125,9 @@ template <typename Ex, typename... Args> ...@@ -125,7 +125,9 @@ template <typename Ex, typename... Args>
/// ///
/// Usage note: /// Usage note:
/// Passing extra values as arguments rather than capturing them allows smaller /// Passing extra values as arguments rather than capturing them allows smaller
/// inlined native at the call-site. /// inlined native code at the call-site. Passing function-pointers or function-
/// references rather than general callables with captures allows allows smaller
/// inlined native code at the call-site as well.
/// ///
/// Example: /// Example:
/// ///
...@@ -138,11 +140,24 @@ template <typename Ex, typename... Args> ...@@ -138,11 +140,24 @@ template <typename Ex, typename... Args>
/// }, /// },
/// i); /// i);
/// } /// }
template <typename F, typename... A> template <
typename F,
typename... A,
typename FD = std::remove_pointer_t<std::decay_t<F>>,
std::enable_if_t<!std::is_function<FD>::value, int> = 0>
FOLLY_NOINLINE FOLLY_COLD auto invoke_cold(F&& f, A&&... a) FOLLY_NOINLINE FOLLY_COLD auto invoke_cold(F&& f, A&&... a)
-> decltype(static_cast<F&&>(f)(static_cast<A&&>(a)...)) { -> decltype(static_cast<F&&>(f)(static_cast<A&&>(a)...)) {
return static_cast<F&&>(f)(static_cast<A&&>(a)...); return static_cast<F&&>(f)(static_cast<A&&>(a)...);
} }
template <
typename F,
typename... A,
typename FD = std::remove_pointer_t<std::decay_t<F>>,
std::enable_if_t<std::is_function<FD>::value, int> = 0>
FOLLY_ERASE auto invoke_cold(F&& f, A&&... a)
-> decltype(f(static_cast<A&&>(a)...)) {
return f(static_cast<A&&>(a)...);
}
/// invoke_noreturn_cold /// invoke_noreturn_cold
/// ///
......
...@@ -124,8 +124,12 @@ TEST_F(ExceptionTest, catch_exception) { ...@@ -124,8 +124,12 @@ TEST_F(ExceptionTest, catch_exception) {
auto thrower = [](int i) { return [=]() -> int { throw i; }; }; auto thrower = [](int i) { return [=]() -> int { throw i; }; };
EXPECT_EQ(3, folly::catch_exception(returner(3), returner(4))); EXPECT_EQ(3, folly::catch_exception(returner(3), returner(4)));
EXPECT_EQ(3, folly::catch_exception<int>(returner(3), identity)); EXPECT_EQ(3, folly::catch_exception<int>(returner(3), identity));
EXPECT_EQ(3, folly::catch_exception<int>(returner(3), +identity));
EXPECT_EQ(3, folly::catch_exception<int>(returner(3), *+identity));
EXPECT_EQ(4, folly::catch_exception(thrower(3), returner(4))); EXPECT_EQ(4, folly::catch_exception(thrower(3), returner(4)));
EXPECT_EQ(3, folly::catch_exception<int>(thrower(3), identity)); EXPECT_EQ(3, folly::catch_exception<int>(thrower(3), identity));
EXPECT_EQ(3, folly::catch_exception<int>(thrower(3), +identity));
EXPECT_EQ(3, folly::catch_exception<int>(thrower(3), *+identity));
} }
TEST_F(ExceptionTest, rethrow_current_exception) { TEST_F(ExceptionTest, rethrow_current_exception) {
......
...@@ -92,13 +92,13 @@ template <typename Arg> ...@@ -92,13 +92,13 @@ template <typename Arg>
auto appendObjectToString(std::string& str, const Arg* arg, int) -> decltype( auto appendObjectToString(std::string& str, const Arg* arg, int) -> decltype(
toAppend(std::declval<Arg>(), std::declval<std::string*>()), toAppend(std::declval<Arg>(), std::declval<std::string*>()),
std::declval<void>()) { std::declval<void>()) {
::folly::catch_exception<const std::exception&>( ::folly::catch_exception(
[&] { toAppend(*arg, &str); }, [&] { toAppend(*arg, &str); },
[&](const std::exception&) {
// If anything goes wrong in `toAppend()` fall back to // If anything goes wrong in `toAppend()` fall back to
// appendRawObjectInfo() // appendRawObjectInfo()
::folly::logging::appendRawObjectInfo(str, arg); ::folly::logging::appendRawObjectInfo<Arg>,
}); str,
arg);
} }
template <typename Arg> template <typename Arg>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment