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) { ...@@ -46,6 +46,11 @@ inline FiberManager::Options preprocessOptions(FiberManager::Options opts) {
return opts; return opts;
} }
template <class F>
FOLLY_NOINLINE invoke_result_t<F> runNoInline(F&& func) {
return func();
}
} // namespace } // namespace
inline void FiberManager::ensureLoopScheduled() { inline void FiberManager::ensureLoopScheduled() {
...@@ -512,7 +517,7 @@ void FiberManager::addTaskFinallyEager(F&& func, G&& finally) { ...@@ -512,7 +517,7 @@ void FiberManager::addTaskFinallyEager(F&& func, G&& finally) {
template <typename F> template <typename F>
invoke_result_t<F> FiberManager::runInMainContext(F&& func) { invoke_result_t<F> FiberManager::runInMainContext(F&& func) {
if (UNLIKELY(activeFiber_ == nullptr)) { if (UNLIKELY(activeFiber_ == nullptr)) {
return func(); return runNoInline(std::forward<F>(func));
} }
typedef invoke_result_t<F> Result; typedef invoke_result_t<F> Result;
...@@ -607,5 +612,15 @@ typename FirstArgOf<F>::type::value_type inline await(F&& func) { ...@@ -607,5 +612,15 @@ typename FirstArgOf<F>::type::value_type inline await(F&& func) {
return Promise<Result, BatonT>::await(std::forward<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 fibers
} // namespace folly } // namespace folly
...@@ -675,13 +675,7 @@ typename FirstArgOf<F>::type::value_type inline await(F&& func); ...@@ -675,13 +675,7 @@ typename FirstArgOf<F>::type::value_type inline await(F&& func);
* @return value returned by func(). * @return value returned by func().
*/ */
template <typename F> template <typename F>
invoke_result_t<F> inline runInMainContext(F&& func) { 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));
}
/** /**
* Returns a refference to a fiber-local context for given Fiber. Should be * Returns a refference to a fiber-local context for given Fiber. Should be
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
#include <array>
#include <atomic> #include <atomic>
#include <thread> #include <thread>
#include <vector> #include <vector>
...@@ -982,6 +983,39 @@ TEST(FiberManager, runInMainContext) { ...@@ -982,6 +983,39 @@ TEST(FiberManager, runInMainContext) {
EXPECT_TRUE(checkRan); 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) { TEST(FiberManager, addTaskFinally) {
FiberManager manager(std::make_unique<SimpleLoopController>()); FiberManager manager(std::make_unique<SimpleLoopController>());
auto& loopController = 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