Commit c5d71971 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

Add FOLLY_NOINLINE to non-trivial await_suspend implementations

Summary: This is mainly to workaround bugs triggered by LTO, when stack allocated variables in await_suspend end up on a coroutine frame.

Reviewed By: lewissbaker

Differential Revision: D15143193

fbshipit-source-id: 9553274e2d9c021902d9d19e7ecb2a91a86e787a
parent 6b97363a
...@@ -477,6 +477,9 @@ constexpr auto kCpplibVer = 0; ...@@ -477,6 +477,9 @@ constexpr auto kCpplibVer = 0;
// folly::coro requires C++17 support // folly::coro requires C++17 support
#if __cpp_coroutines >= 201703L && __has_include(<experimental/coroutine>) #if __cpp_coroutines >= 201703L && __has_include(<experimental/coroutine>)
#define FOLLY_HAS_COROUTINES 1 #define FOLLY_HAS_COROUTINES 1
// This is mainly to workaround bugs triggered by LTO, when stack allocated
// variables in await_suspend end up on a coroutine frame.
#define FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES FOLLY_NOINLINE
#elif _MSC_VER && _RESUMABLE_FUNCTIONS_SUPPORTED #elif _MSC_VER && _RESUMABLE_FUNCTIONS_SUPPORTED
// NOTE: MSVC 2017 does not currently support the full Coroutines TS since it // NOTE: MSVC 2017 does not currently support the full Coroutines TS since it
// does not yet support symmetric-transfer. // does not yet support symmetric-transfer.
......
...@@ -37,7 +37,8 @@ class co_schedule_t { ...@@ -37,7 +37,8 @@ class co_schedule_t {
return false; return false;
} }
void await_suspend(std::experimental::coroutine_handle<> coro) { FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES void await_suspend(
std::experimental::coroutine_handle<> coro) {
executor_->add([coro, ctx = RequestContext::saveContext()]() mutable { executor_->add([coro, ctx = RequestContext::saveContext()]() mutable {
RequestContextScopeGuard contextScope{std::move(ctx)}; RequestContextScopeGuard contextScope{std::move(ctx)};
coro.resume(); coro.resume();
......
...@@ -218,7 +218,7 @@ class SharedMutexFair { ...@@ -218,7 +218,7 @@ class SharedMutexFair {
return mutex_->try_lock(); return mutex_->try_lock();
} }
bool await_suspend( FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES bool await_suspend(
std::experimental::coroutine_handle<> continuation) noexcept { std::experimental::coroutine_handle<> continuation) noexcept {
auto lock = mutex_->state_.contextualLock(); auto lock = mutex_->state_.contextualLock();
...@@ -247,7 +247,7 @@ class SharedMutexFair { ...@@ -247,7 +247,7 @@ class SharedMutexFair {
return mutex_->try_lock_shared(); return mutex_->try_lock_shared();
} }
bool await_suspend( FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES bool await_suspend(
std::experimental::coroutine_handle<> continuation) noexcept { std::experimental::coroutine_handle<> continuation) noexcept {
auto lock = mutex_->state_.contextualLock(); auto lock = mutex_->state_.contextualLock();
......
...@@ -237,7 +237,7 @@ class FOLLY_NODISCARD TaskWithExecutor { ...@@ -237,7 +237,7 @@ class FOLLY_NODISCARD TaskWithExecutor {
return false; return false;
} }
void await_suspend( FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES void await_suspend(
std::experimental::coroutine_handle<> continuation) noexcept { std::experimental::coroutine_handle<> continuation) noexcept {
auto& promise = coro_.promise(); auto& promise = coro_.promise();
DCHECK(!promise.continuation_); DCHECK(!promise.continuation_);
......
...@@ -74,7 +74,8 @@ class TimedWaitAwaitable { ...@@ -74,7 +74,8 @@ class TimedWaitAwaitable {
return false; return false;
} }
bool await_suspend(std::experimental::coroutine_handle<> ch) { FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES bool await_suspend(
std::experimental::coroutine_handle<> ch) {
auto sharedState = std::make_shared<SharedState>(ch, storage_); auto sharedState = std::make_shared<SharedState>(ch, storage_);
waitAndNotify(std::move(awaitable_), sharedState).detach(); waitAndNotify(std::move(awaitable_), sharedState).detach();
futures::sleepUnsafe(duration_).thenValue( futures::sleepUnsafe(duration_).thenValue(
......
...@@ -56,7 +56,7 @@ class ViaCoroutine { ...@@ -56,7 +56,7 @@ class ViaCoroutine {
bool await_ready() noexcept { bool await_ready() noexcept {
return false; return false;
} }
void await_suspend( FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES void await_suspend(
std::experimental::coroutine_handle<promise_type> coro) noexcept { std::experimental::coroutine_handle<promise_type> coro) noexcept {
// Schedule resumption of the coroutine on the executor. // Schedule resumption of the coroutine on the executor.
auto& promise = coro.promise(); auto& promise = coro.promise();
......
...@@ -1960,7 +1960,8 @@ class FutureAwaitable { ...@@ -1960,7 +1960,8 @@ class FutureAwaitable {
return std::move(result_).value(); return std::move(result_).value();
} }
void await_suspend(std::experimental::coroutine_handle<> h) { FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES void await_suspend(
std::experimental::coroutine_handle<> h) {
// FutureAwaitable may get destroyed as soon as the callback is executed. // FutureAwaitable may get destroyed as soon as the callback is executed.
// Make sure the future object doesn't get destroyed until setCallback_ // Make sure the future object doesn't get destroyed until setCallback_
// returns. // returns.
......
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