Commit 435d9292 authored by Pavlo Kushnir's avatar Pavlo Kushnir Committed by Facebook Github Bot

Make sure to not inline in runInMainContext

Summary: Currently if compiler decides to inline fiber function, we'll end up allocating variables on fiber stack even though we use `runInMainContext`.

Reviewed By: andriigrynenko

Differential Revision: D18842065

fbshipit-source-id: 847c4f95c44ef49f5c7537af878ca8340f2b7b16
parent c8fbe636
......@@ -46,6 +46,11 @@ inline FiberManager::Options preprocessOptions(FiberManager::Options opts) {
return opts;
}
template <class F>
FOLLY_NOINLINE invoke_result_t<F> runNoInline(F&& func) {
return func();
}
} // namespace
inline void FiberManager::ensureLoopScheduled() {
......@@ -512,7 +517,7 @@ void FiberManager::addTaskFinallyEager(F&& func, G&& finally) {
template <typename F>
invoke_result_t<F> FiberManager::runInMainContext(F&& func) {
if (UNLIKELY(activeFiber_ == nullptr)) {
return func();
return runNoInline(std::forward<F>(func));
}
typedef invoke_result_t<F> Result;
......@@ -607,5 +612,15 @@ typename FirstArgOf<F>::type::value_type inline await(F&& func) {
return Promise<Result, BatonT>::await(std::forward<F>(func));
}
template <typename F>
invoke_result_t<F> inline runInMainContext(F&& func) {
auto fm = FiberManager::getFiberManagerUnsafe();
if (UNLIKELY(fm == nullptr)) {
return runNoInline(std::forward<F>(func));
}
return fm->runInMainContext(std::forward<F>(func));
}
} // namespace fibers
} // namespace folly
......@@ -675,13 +675,7 @@ typename FirstArgOf<F>::type::value_type inline await(F&& func);
* @return value returned by func().
*/
template <typename F>
invoke_result_t<F> inline runInMainContext(F&& func) {
auto fm = FiberManager::getFiberManagerUnsafe();
if (UNLIKELY(fm == nullptr)) {
return func();
}
return fm->runInMainContext(std::forward<F>(func));
}
invoke_result_t<F> inline runInMainContext(F&& func);
/**
* Returns a refference to a fiber-local context for given Fiber. Should be
......
......@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <array>
#include <atomic>
#include <thread>
#include <vector>
......@@ -982,6 +983,39 @@ TEST(FiberManager, runInMainContext) {
EXPECT_TRUE(checkRan);
}
namespace {
FOLLY_NOINLINE int runHugeStackInMainContext(bool& checkRan) {
auto ret = runInMainContext([&checkRan]() {
std::array<unsigned char, 1 << 20> buf;
buf.fill(42);
checkRan = true;
return buf[time(nullptr) % buf.size()];
});
EXPECT_TRUE(checkRan);
EXPECT_EQ(42, ret);
return ret;
}
} // namespace
TEST(FiberManager, runInMainContextNoInline) {
FiberManager::Options opts;
opts.recordStackEvery = 1;
FiberManager manager(std::make_unique<SimpleLoopController>(), opts);
auto& loopController =
dynamic_cast<SimpleLoopController&>(manager.loopController());
bool checkRan = false;
manager.addTask([&] { return runHugeStackInMainContext(checkRan); });
EXPECT_TRUE(manager.stackHighWatermark() < 100000);
loopController.loop([&]() { loopController.stop(); });
EXPECT_TRUE(checkRan);
}
TEST(FiberManager, addTaskFinally) {
FiberManager manager(std::make_unique<SimpleLoopController>());
auto& loopController =
......
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