Index: src/IceGlobalContext.cpp |
diff --git a/src/IceGlobalContext.cpp b/src/IceGlobalContext.cpp |
index aaa3275d67c600c7364ad3d63f6f60fe661c319a..ad6d90def6f33a99b46279bed64c716ae71def9a 100644 |
--- a/src/IceGlobalContext.cpp |
+++ b/src/IceGlobalContext.cpp |
@@ -108,7 +108,7 @@ public: |
UndefPool Undefs; |
}; |
-void CodeStats::dump(const IceString &Name, Ostream &Str) { |
+void GlobalContext::CodeStats::dump(const IceString &Name, Ostream &Str) { |
if (!ALLOW_DUMP) |
return; |
Str << "|" << Name << "|Inst Count |" << InstructionsEmitted << "\n"; |
@@ -129,11 +129,18 @@ GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, |
ELFStreamer *ELFStr, VerboseMask Mask, |
TargetArch Arch, OptLevel Opt, |
IceString TestPrefix, const ClFlags &Flags) |
- : StrDump(OsDump), StrEmit(OsEmit), VMask(Mask), |
+ : IsStrLocked(false), StrDump(OsDump), StrEmit(OsEmit), VMask(Mask), |
ConstPool(new ConstantPool()), Arch(Arch), Opt(Opt), |
TestPrefix(TestPrefix), Flags(Flags), RNG(""), ObjectWriter() { |
+ // Create a new ThreadContext for the current thread. No need to |
+ // lock AllThreadContexts at this point since no other threads have |
+ // access yet to this GlobalContext object. |
+ AllThreadContexts.push_back(new ThreadContext()); |
+ TLS = AllThreadContexts.back(); |
// Pre-register built-in stack names. |
if (ALLOW_DUMP) { |
+ // TODO(stichnot): There needs to be a strong relationship between |
+ // the newTimerStackID() return values and TSK_Default/TSK_Funcs. |
newTimerStackID("Total across all functions"); |
newTimerStackID("Per-function summary"); |
} |
@@ -308,8 +315,13 @@ IceString GlobalContext::mangleName(const IceString &Name) const { |
GlobalContext::~GlobalContext() { |
llvm::DeleteContainerPointers(GlobalDeclarations); |
+ llvm::DeleteContainerPointers(AllThreadContexts); |
} |
+// TODO(stichnot): Consider adding thread-local caches of constant |
+// pool entries to reduce contention. |
+ |
+// All locking is done by the getConstantInt[0-9]+() target function. |
Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) { |
switch (Ty) { |
case IceType_i1: |
@@ -329,45 +341,55 @@ Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) { |
} |
Constant *GlobalContext::getConstantInt1(int8_t ConstantInt1) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
ConstantInt1 &= INT8_C(1); |
return ConstPool->Integers1.getOrAdd(this, ConstantInt1); |
} |
Constant *GlobalContext::getConstantInt8(int8_t ConstantInt8) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
return ConstPool->Integers8.getOrAdd(this, ConstantInt8); |
} |
Constant *GlobalContext::getConstantInt16(int16_t ConstantInt16) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
return ConstPool->Integers16.getOrAdd(this, ConstantInt16); |
} |
Constant *GlobalContext::getConstantInt32(int32_t ConstantInt32) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
return ConstPool->Integers32.getOrAdd(this, ConstantInt32); |
} |
Constant *GlobalContext::getConstantInt64(int64_t ConstantInt64) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
return ConstPool->Integers64.getOrAdd(this, ConstantInt64); |
} |
Constant *GlobalContext::getConstantFloat(float ConstantFloat) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
return ConstPool->Floats.getOrAdd(this, ConstantFloat); |
} |
Constant *GlobalContext::getConstantDouble(double ConstantDouble) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
return ConstPool->Doubles.getOrAdd(this, ConstantDouble); |
} |
Constant *GlobalContext::getConstantSym(RelocOffsetT Offset, |
const IceString &Name, |
bool SuppressMangling) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
return ConstPool->Relocatables.getOrAdd( |
this, RelocatableTuple(Offset, Name, SuppressMangling)); |
} |
Constant *GlobalContext::getConstantUndef(Type Ty) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
return ConstPool->Undefs.getOrAdd(this, Ty); |
} |
+// All locking is done by the getConstant*() target function. |
Constant *GlobalContext::getConstantZero(Type Ty) { |
switch (Ty) { |
case IceType_i1: |
@@ -403,7 +425,8 @@ Constant *GlobalContext::getConstantZero(Type Ty) { |
llvm_unreachable("Unknown type"); |
} |
-ConstantList GlobalContext::getConstantPool(Type Ty) const { |
+ConstantList GlobalContext::getConstantPool(Type Ty) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
switch (Ty) { |
case IceType_i1: |
case IceType_i8: |
@@ -435,6 +458,7 @@ ConstantList GlobalContext::getConstantPool(Type Ty) const { |
llvm_unreachable("Unknown type"); |
} |
+// No locking because only the bitcode parser thread calls it. |
jvoung (off chromium)
2015/01/15 18:20:40
fwiw, chrome has a "base/threading/thread_checker.
Jim Stichnoth
2015/01/17 18:44:17
Acknowledged.
Also, on further inspection, this m
|
FunctionDeclaration * |
GlobalContext::newFunctionDeclaration(const FuncSigType *Signature, |
unsigned CallingConv, unsigned Linkage, |
@@ -446,57 +470,64 @@ GlobalContext::newFunctionDeclaration(const FuncSigType *Signature, |
return Func; |
} |
+// No locking because only the bitcode parser thread calls it. |
VariableDeclaration *GlobalContext::newVariableDeclaration() { |
VariableDeclaration *Var = new VariableDeclaration(); |
GlobalDeclarations.push_back(Var); |
return Var; |
} |
-TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID, |
- const IceString &Name) { |
- assert(StackID < Timers.size()); |
- return Timers[StackID].getTimerID(Name); |
-} |
- |
TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) { |
if (!ALLOW_DUMP) |
return 0; |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
TimerStackIdT NewID = Timers.size(); |
Timers.push_back(TimerStack(Name)); |
return NewID; |
} |
+TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID, |
+ const IceString &Name) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
+ assert(StackID < Timers.size()); |
+ return Timers[StackID].getTimerID(Name); |
+} |
+ |
void GlobalContext::pushTimer(TimerIdT ID, TimerStackIdT StackID) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
assert(StackID < Timers.size()); |
Timers[StackID].push(ID); |
} |
void GlobalContext::popTimer(TimerIdT ID, TimerStackIdT StackID) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
assert(StackID < Timers.size()); |
Timers[StackID].pop(ID); |
} |
void GlobalContext::resetTimer(TimerStackIdT StackID) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
assert(StackID < Timers.size()); |
Timers[StackID].reset(); |
} |
void GlobalContext::setTimerName(TimerStackIdT StackID, |
const IceString &NewName) { |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
assert(StackID < Timers.size()); |
Timers[StackID].setName(NewName); |
} |
void GlobalContext::dumpStats(const IceString &Name, bool Final) { |
- if (!ALLOW_DUMP) |
+ if (!ALLOW_DUMP || !getFlags().DumpStats) |
return; |
- if (Flags.DumpStats) { |
- if (Final) { |
- StatsCumulative.dump(Name, getStrDump()); |
- } else { |
- StatsFunction.dump(Name, getStrDump()); |
- StatsCumulative.dump("_TOTAL_", getStrDump()); |
- } |
+ std::lock_guard<GlobalLockType> L(GlobalLock); |
+ OstreamLocker OL(this); |
+ if (Final) { |
+ StatsCumulative.dump(Name, getStrDump()); |
+ } else { |
+ TLS->StatsFunction.dump(Name, getStrDump()); |
+ StatsCumulative.dump("_TOTAL_", getStrDump()); |
} |
} |
@@ -504,6 +535,7 @@ void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) { |
if (!ALLOW_DUMP) |
return; |
assert(Timers.size() > StackID); |
+ OstreamLocker L(this); |
Timers[StackID].dump(getStrDump(), DumpCumulative); |
} |
@@ -516,4 +548,6 @@ TimerMarker::TimerMarker(TimerIdT ID, const Cfg *Func) |
} |
} |
+thread_local GlobalContext::ThreadContext *GlobalContext::TLS; |
+ |
} // end of namespace Ice |