Support JIT on a separate thread
On platforms where the calling thread has a very small stack, LLVM can
overflow the stack. Work around it by creating a temporary thread for
performing LLVM optimizations and codegen.
Bug: b/149829034
Change-Id: I59edd0f7d02b4724ea30f9413ea3efbb4d200290
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/41389
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index 4879076..b0bc37e 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -632,55 +632,70 @@
std::shared_ptr<Routine> Nucleus::acquireRoutine(const char *name, const Config::Edit &cfgEdit /* = Config::Edit::None */)
{
- auto cfg = cfgEdit.apply(jit->config);
+ std::shared_ptr<Routine> routine;
- if(jit->builder->GetInsertBlock()->empty() || !jit->builder->GetInsertBlock()->back().isTerminator())
- {
- llvm::Type *type = jit->function->getReturnType();
+ auto acquire = [&]() {
+ auto cfg = cfgEdit.apply(jit->config);
- if(type->isVoidTy())
+ if(jit->builder->GetInsertBlock()->empty() || !jit->builder->GetInsertBlock()->back().isTerminator())
{
- createRetVoid();
+ llvm::Type *type = jit->function->getReturnType();
+
+ if(type->isVoidTy())
+ {
+ createRetVoid();
+ }
+ else
+ {
+ createRet(V(llvm::UndefValue::get(type)));
+ }
}
- else
- {
- createRet(V(llvm::UndefValue::get(type)));
- }
- }
#ifdef ENABLE_RR_DEBUG_INFO
- if(jit->debugInfo != nullptr)
- {
- jit->debugInfo->Finalize();
- }
+ if(jit->debugInfo != nullptr)
+ {
+ jit->debugInfo->Finalize();
+ }
#endif // ENABLE_RR_DEBUG_INFO
- if(false)
- {
- std::error_code error;
- llvm::raw_fd_ostream file(std::string(name) + "-llvm-dump-unopt.txt", error);
- jit->module->print(file, 0);
- }
+ if(false)
+ {
+ std::error_code error;
+ llvm::raw_fd_ostream file(std::string(name) + "-llvm-dump-unopt.txt", error);
+ jit->module->print(file, 0);
+ }
#if defined(ENABLE_RR_LLVM_IR_VERIFICATION) || !defined(NDEBUG)
- {
- llvm::legacy::PassManager pm;
- pm.add(llvm::createVerifierPass());
- pm.run(*jit->module);
- }
+ {
+ llvm::legacy::PassManager pm;
+ pm.add(llvm::createVerifierPass());
+ pm.run(*jit->module);
+ }
#endif // defined(ENABLE_RR_LLVM_IR_VERIFICATION) || !defined(NDEBUG)
- jit->optimize(cfg);
+ jit->optimize(cfg);
- if(false)
- {
- std::error_code error;
- llvm::raw_fd_ostream file(std::string(name) + "-llvm-dump-opt.txt", error);
- jit->module->print(file, 0);
- }
+ if(false)
+ {
+ std::error_code error;
+ llvm::raw_fd_ostream file(std::string(name) + "-llvm-dump-opt.txt", error);
+ jit->module->print(file, 0);
+ }
- auto routine = jit->acquireRoutine(&jit->function, 1, cfg);
- jit.reset();
+ routine = jit->acquireRoutine(&jit->function, 1, cfg);
+ jit.reset();
+ };
+
+#ifdef JIT_IN_SEPARATE_THREAD
+ // Perform optimizations and codegen in a separate thread to avoid stack overflow.
+ // FIXME(b/149829034): This is not a long-term solution. Reactor has no control
+ // over the threading and stack sizes of its users, so this should be addressed
+ // at a higher level instead.
+ std::thread thread(acquire);
+ thread.join();
+#else
+ acquire();
+#endif
return routine;
}