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;
// folly::coro requires C++17 support
#if __cpp_coroutines >= 201703L && __has_include(<experimental/coroutine>)
#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
// NOTE: MSVC 2017 does not currently support the full Coroutines TS since it
// does not yet support symmetric-transfer.
......
......@@ -37,7 +37,8 @@ class co_schedule_t {
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 {
RequestContextScopeGuard contextScope{std::move(ctx)};
coro.resume();
......
......@@ -218,7 +218,7 @@ class SharedMutexFair {
return mutex_->try_lock();
}
bool await_suspend(
FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES bool await_suspend(
std::experimental::coroutine_handle<> continuation) noexcept {
auto lock = mutex_->state_.contextualLock();
......@@ -247,7 +247,7 @@ class SharedMutexFair {
return mutex_->try_lock_shared();
}
bool await_suspend(
FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES bool await_suspend(
std::experimental::coroutine_handle<> continuation) noexcept {
auto lock = mutex_->state_.contextualLock();
......
......@@ -237,7 +237,7 @@ class FOLLY_NODISCARD TaskWithExecutor {
return false;
}
void await_suspend(
FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES void await_suspend(
std::experimental::coroutine_handle<> continuation) noexcept {
auto& promise = coro_.promise();
DCHECK(!promise.continuation_);
......
......@@ -74,7 +74,8 @@ class TimedWaitAwaitable {
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_);
waitAndNotify(std::move(awaitable_), sharedState).detach();
futures::sleepUnsafe(duration_).thenValue(
......
......@@ -56,7 +56,7 @@ class ViaCoroutine {
bool await_ready() noexcept {
return false;
}
void await_suspend(
FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES void await_suspend(
std::experimental::coroutine_handle<promise_type> coro) noexcept {
// Schedule resumption of the coroutine on the executor.
auto& promise = coro.promise();
......
......@@ -1960,7 +1960,8 @@ class FutureAwaitable {
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.
// Make sure the future object doesn't get destroyed until setCallback_
// 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