aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ExecutionEngine/JIT/JITEmitter.cpp
diff options
context:
space:
mode:
authorReid Spencer <rspencer@reidspencer.com>2005-07-12 15:51:55 +0000
committerReid Spencer <rspencer@reidspencer.com>2005-07-12 15:51:55 +0000
commitee448630bdf7eb6037fe2c50518d32010c433ca3 (patch)
treef8ecc527ec9e16ba1b610b08cbb35e2e05e5ebef /lib/ExecutionEngine/JIT/JITEmitter.cpp
parentb2164e5cb5086f0595e96fdbb5ffc614dea9c441 (diff)
downloadexternal_llvm-ee448630bdf7eb6037fe2c50518d32010c433ca3.tar.gz
external_llvm-ee448630bdf7eb6037fe2c50518d32010c433ca3.tar.bz2
external_llvm-ee448630bdf7eb6037fe2c50518d32010c433ca3.zip
For PR540:
This patch completes the changes for making lli thread-safe. Here's the list of changes: * The Support/ThreadSupport* files were removed and replaced with the MutexGuard.h file since all ThreadSupport* declared was a Mutex Guard. The implementation of MutexGuard.h is now based on sys::Mutex which hides its implementation and makes it unnecessary to have the -NoSupport.h and -PThreads.h versions of ThreadSupport. * All places in ExecutionEngine that previously referred to "Mutex" now refer to sys::Mutex * All places in ExecutionEngine that previously referred to "MutexLocker" now refer to MutexGuard (this is frivolous but I believe the technically correct name for such a class is "Guard" not a "Locker"). These changes passed all of llvm-test. All we need now are some test cases that actually use multiple threads. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22404 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine/JIT/JITEmitter.cpp')
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp56
1 files changed, 40 insertions, 16 deletions
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index 301f5e77ee..47adee0019 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -120,6 +120,28 @@ void JITMemoryManager::endFunctionBody(unsigned char *FunctionEnd) {
// JIT lazy compilation code.
//
namespace {
+ class JITResolverState {
+ private:
+ /// FunctionToStubMap - Keep track of the stub created for a particular
+ /// function so that we can reuse them if necessary.
+ std::map<Function*, void*> FunctionToStubMap;
+
+ /// StubToFunctionMap - Keep track of the function that each stub
+ /// corresponds to.
+ std::map<void*, Function*> StubToFunctionMap;
+
+ public:
+ std::map<Function*, void*>& getFunctionToStubMap(const MutexGuard& locked) {
+ assert(locked.holds(TheJIT->lock));
+ return FunctionToStubMap;
+ }
+
+ std::map<void*, Function*>& getStubToFunctionMap(const MutexGuard& locked) {
+ assert(locked.holds(TheJIT->lock));
+ return StubToFunctionMap;
+ }
+ };
+
/// JITResolver - Keep track of, and resolve, call sites for functions that
/// have not yet been compiled.
class JITResolver {
@@ -130,13 +152,7 @@ namespace {
/// rewrite instructions to use.
TargetJITInfo::LazyResolverFn LazyResolverFn;
- // FunctionToStubMap - Keep track of the stub created for a particular
- // function so that we can reuse them if necessary.
- std::map<Function*, void*> FunctionToStubMap;
-
- // StubToFunctionMap - Keep track of the function that each stub corresponds
- // to.
- std::map<void*, Function*> StubToFunctionMap;
+ JITResolverState state;
/// ExternalFnToStubMap - This is the equivalent of FunctionToStubMap for
/// external functions.
@@ -159,8 +175,9 @@ namespace {
/// instruction without the use of a stub, record the location of the use so
/// we know which function is being used at the location.
void *AddCallbackAtLocation(Function *F, void *Location) {
+ MutexGuard locked(TheJIT->lock);
/// Get the target-specific JIT resolver function.
- StubToFunctionMap[Location] = F;
+ state.getStubToFunctionMap(locked)[Location] = F;
return (void*)LazyResolverFn;
}
@@ -181,8 +198,10 @@ static JITResolver &getJITResolver(MachineCodeEmitter *MCE = 0) {
/// getFunctionStub - This returns a pointer to a function stub, creating
/// one on demand as needed.
void *JITResolver::getFunctionStub(Function *F) {
+ MutexGuard locked(TheJIT->lock);
+
// If we already have a stub for this function, recycle it.
- void *&Stub = FunctionToStubMap[F];
+ void *&Stub = state.getFunctionToStubMap(locked)[F];
if (Stub) return Stub;
// Call the lazy resolver function unless we already KNOW it is an external
@@ -207,7 +226,7 @@ void *JITResolver::getFunctionStub(Function *F) {
// Finally, keep track of the stub-to-Function mapping so that the
// JITCompilerFn knows which function to compile!
- StubToFunctionMap[Stub] = F;
+ state.getStubToFunctionMap(locked)[Stub] = F;
return Stub;
}
@@ -231,16 +250,21 @@ void *JITResolver::getExternalFunctionStub(void *FnAddr) {
void *JITResolver::JITCompilerFn(void *Stub) {
JITResolver &JR = getJITResolver();
+ MutexGuard locked(TheJIT->lock);
+
// The address given to us for the stub may not be exactly right, it might be
// a little bit after the stub. As such, use upper_bound to find it.
std::map<void*, Function*>::iterator I =
- JR.StubToFunctionMap.upper_bound(Stub);
- assert(I != JR.StubToFunctionMap.begin() && "This is not a known stub!");
+ JR.state.getStubToFunctionMap(locked).upper_bound(Stub);
+ assert(I != JR.state.getStubToFunctionMap(locked).begin() && "This is not a known stub!");
Function *F = (--I)->second;
- // The target function will rewrite the stub so that the compilation callback
- // function is no longer called from this stub.
- JR.StubToFunctionMap.erase(I);
+ // We might like to remove the stub from the StubToFunction map.
+ // We can't do that! Multiple threads could be stuck, waiting to acquire the
+ // lock above. As soon as the 1st function finishes compiling the function,
+ // the next one will be released, and needs to be able to find the function it needs
+ // to call.
+ //JR.state.getStubToFunctionMap(locked).erase(I);
DEBUG(std::cerr << "JIT: Lazily resolving function '" << F->getName()
<< "' In stub ptr = " << Stub << " actual ptr = "
@@ -249,7 +273,7 @@ void *JITResolver::JITCompilerFn(void *Stub) {
void *Result = TheJIT->getPointerToFunction(F);
// We don't need to reuse this stub in the future, as F is now compiled.
- JR.FunctionToStubMap.erase(F);
+ JR.state.getFunctionToStubMap(locked).erase(F);
// FIXME: We could rewrite all references to this stub if we knew them.
return Result;