Index: src/IceGlobalContext.cpp |
diff --git a/src/IceGlobalContext.cpp b/src/IceGlobalContext.cpp |
index d353bfe3874352d9ee789a218c84c5ab5a115634..189cca52120f306ab0039016f5f4ccc215aa7d65 100644 |
--- a/src/IceGlobalContext.cpp |
+++ b/src/IceGlobalContext.cpp |
@@ -218,6 +218,37 @@ public: |
UndefPool Undefs; |
}; |
+void GlobalContext::waitForWorkerThreads() { |
+ if (WaitForWorkerThreadsCalled.exchange(true)) |
+ return; |
+ optQueueNotifyEnd(); |
+ for (std::thread &Worker : TranslationThreads) { |
+ Worker.join(); |
+ } |
+ TranslationThreads.clear(); |
+ |
+ // Only notify the emit queue to end after all the translation threads have |
+ // ended. |
+ emitQueueNotifyEnd(); |
+ for (std::thread &Worker : EmitterThreads) { |
+ Worker.join(); |
+ } |
+ EmitterThreads.clear(); |
+ |
+ if (BuildDefs::timers()) { |
+ auto Timers = getTimers(); |
+ for (ThreadContext *TLS : AllThreadContexts) |
+ Timers->mergeFrom(TLS->Timers); |
+ } |
+ if (BuildDefs::dump()) { |
+ // Do a separate loop over AllThreadContexts to avoid holding two locks |
Jim Stichnoth
2016/03/31 16:08:08
reflow...
Karl
2016/03/31 16:33:49
Done.
|
+ // at once. |
+ auto Stats = getStatsCumulative(); |
+ for (ThreadContext *TLS : AllThreadContexts) |
+ Stats->add(TLS->StatsCumulative); |
+ } |
+} |
+ |
void GlobalContext::CodeStats::dump(const IceString &Name, GlobalContext *Ctx) { |
if (!BuildDefs::dump()) |
return; |
@@ -254,9 +285,12 @@ void GlobalContext::CodeStats::dump(const IceString &Name, GlobalContext *Ctx) { |
GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError, |
ELFStreamer *ELFStr) |
: ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump), |
- StrEmit(OsEmit), StrError(OsError), ObjectWriter(), |
- OptQ(/*Sequential=*/Flags.isSequential(), |
- /*MaxSize=*/Flags.getNumTranslationThreads()), |
+ StrEmit(OsEmit), StrError(OsError), WaitForWorkerThreadsCalled(false), |
+ ObjectWriter(), OptQ(/*Sequential=*/Flags.isSequential(), |
+ /*MaxSize=*/ |
+ (Flags.getParseParallel() && Flags.getBuildOnRead()) |
+ ? MaxOptQSize |
+ : Flags.getNumTranslationThreads()), |
// EmitQ is allowed unlimited size. |
EmitQ(/*Sequential=*/Flags.isSequential()), |
DataLowering(TargetDataLowering::createLowering(this)) { |
@@ -309,7 +343,8 @@ GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError, |
void GlobalContext::translateFunctions() { |
TimerMarker Timer(TimerStack::TT_translateFunctions, this); |
- while (std::unique_ptr<Cfg> Func = optQueueBlockingPop()) { |
+ while (std::unique_ptr<OptWorkItem> OptItem = optQueueBlockingPop()) { |
+ std::unique_ptr<Cfg> Func = OptItem->getParsedCfg(); |
John
2016/03/31 15:51:36
optional: auto
Karl
2016/03/31 16:33:49
Done.
|
// Install Func in TLS for Cfg-specific container allocators. |
CfgLocalAllocatorScope _(Func.get()); |
// Reset per-function stats being accumulated in TLS. |
@@ -867,19 +902,19 @@ void GlobalContext::setTimerName(TimerStackIdT StackID, |
// interface to take and transfer ownership, but they internally store the raw |
// Cfg pointer in the work queue. This allows e.g. future queue optimizations |
// such as the use of atomics to modify queue elements. |
-void GlobalContext::optQueueBlockingPush(std::unique_ptr<Cfg> Func) { |
- assert(Func); |
+void GlobalContext::optQueueBlockingPush(std::unique_ptr<OptWorkItem> Item) { |
+ assert(Item); |
{ |
TimerMarker _(TimerStack::TT_qTransPush, this); |
- OptQ.blockingPush(std::move(Func)); |
+ OptQ.blockingPush(std::move(Item)); |
} |
if (getFlags().isSequential()) |
translateFunctions(); |
} |
-std::unique_ptr<Cfg> GlobalContext::optQueueBlockingPop() { |
+std::unique_ptr<OptWorkItem> GlobalContext::optQueueBlockingPop() { |
TimerMarker _(TimerStack::TT_qTransPop, this); |
- return std::unique_ptr<Cfg>(OptQ.blockingPop()); |
+ return std::unique_ptr<OptWorkItem>(OptQ.blockingPop()); |
} |
void GlobalContext::emitQueueBlockingPush( |