llvm-project/llvm/lib/ExecutionEngine/Orc/IRTransformLayer.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

34 lines
1.2 KiB
C++
Raw Normal View History

//===-------------- IRTransformLayer.cpp - IR Transform Layer -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
#include "llvm/Support/MemoryBuffer.h"
namespace llvm {
namespace orc {
IRTransformLayer::IRTransformLayer(ExecutionSession &ES, IRLayer &BaseLayer,
TransformFunction Transform)
: IRLayer(ES, BaseLayer.getManglingOptions()), BaseLayer(BaseLayer),
Transform(std::move(Transform)) {}
void IRTransformLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
ThreadSafeModule TSM) {
[ORC] Change the locking scheme for ThreadSafeModule. ThreadSafeModule/ThreadSafeContext are used to manage lifetimes and locking for LLVMContexts in ORCv2. Prior to this patch contexts were locked as soon as an associated Module was emitted (to be compiled and linked), and were not unlocked until the emit call returned. This could lead to deadlocks if interdependent modules that shared contexts were compiled on different threads: when, during emission of the first module, the dependence was discovered the second module (which would provide the required symbol) could not be emitted as the thread emitting the first module still held the lock. This patch eliminates this possibility by moving to a finer-grained locking scheme. Each client holds the module lock only while they are actively operating on it. To make this finer grained locking simpler/safer to implement this patch removes the explicit lock method, 'getContextLock', from ThreadSafeModule and replaces it with a new method, 'withModuleDo', that implicitly locks the context, calls a user-supplied function object to operate on the Module, then implicitly unlocks the context before returning the result. ThreadSafeModule TSM = getModule(...); size_t NumFunctions = TSM.withModuleDo( [](Module &M) { // <- context locked before entry to lambda. return M.size(); }); Existing ORCv2 layers that operate on ThreadSafeModules are updated to use the new method. This method is used to introduce Module locking into each of the existing layers. llvm-svn: 367686
2019-08-02 23:21:37 +08:00
assert(TSM && "Module must not be null");
if (auto TransformedTSM = Transform(std::move(TSM), *R))
BaseLayer.emit(std::move(R), std::move(*TransformedTSM));
else {
R->failMaterialization();
[ORC] Add ThreadSafeModule and ThreadSafeContext wrappers to support concurrent compilation of IR in the JIT. ThreadSafeContext is a pair of an LLVMContext and a mutex that can be used to lock that context when it needs to be accessed from multiple threads. ThreadSafeModule is a pair of a unique_ptr<Module> and a shared_ptr<ThreadSafeContext>. This allows the lifetime of a ThreadSafeContext to be managed automatically in terms of the ThreadSafeModules that refer to it: Once all modules using a ThreadSafeContext are destructed, and providing the client has not held on to a copy of shared context pointer, the context will be automatically destructed. This scheme is necessary due to the following constraits: (1) We need multiple contexts for multithreaded compilation (at least one per compile thread plus one to store any IR not currently being compiled, though one context per module is simpler). (2) We need to free contexts that are no longer being used so that the JIT does not leak memory over time. (3) Module lifetimes are not predictable (modules are compiled as needed depending on the flow of JIT'd code) so there is no single point where contexts could be reclaimed. JIT clients not using concurrency can safely use one ThreadSafeContext for all ThreadSafeModules. JIT clients who want to be able to compile concurrently should use a different ThreadSafeContext for each module, or call setCloneToNewContextOnEmit on their top-level IRLayer. The former reduces compile latency (since no clone step is needed) at the cost of additional memory overhead for uncompiled modules (as every uncompiled module will duplicate the LLVM types, constants and metadata that have been shared). llvm-svn: 343055
2018-09-26 09:24:12 +08:00
getExecutionSession().reportError(TransformedTSM.takeError());
}
}
} // End namespace orc.
} // End namespace llvm.