Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: src/IceGlobalContext.cpp

Issue 876083007: Subzero: Emit functions and global initializers in a separate thread. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Add comments Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===// 1 //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file defines aspects of the compilation that persist across 10 // This file defines aspects of the compilation that persist across
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 } 128 }
129 129
130 GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, 130 GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit,
131 ELFStreamer *ELFStr, VerboseMask Mask, 131 ELFStreamer *ELFStr, VerboseMask Mask,
132 TargetArch Arch, OptLevel Opt, 132 TargetArch Arch, OptLevel Opt,
133 IceString TestPrefix, const ClFlags &Flags) 133 IceString TestPrefix, const ClFlags &Flags)
134 : ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump), 134 : ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump),
135 StrEmit(OsEmit), VMask(Mask), Arch(Arch), Opt(Opt), 135 StrEmit(OsEmit), VMask(Mask), Arch(Arch), Opt(Opt),
136 TestPrefix(TestPrefix), Flags(Flags), RNG(""), ObjectWriter(), 136 TestPrefix(TestPrefix), Flags(Flags), RNG(""), ObjectWriter(),
137 CfgQ(/*MaxSize=*/Flags.NumTranslationThreads, 137 CfgQ(/*MaxSize=*/Flags.NumTranslationThreads,
138 /*Sequential=*/(Flags.NumTranslationThreads == 0)) { 138 /*Sequential=*/(Flags.NumTranslationThreads == 0)),
139 EmitQ(/*MaxSize=*/Flags.NumTranslationThreads,
JF 2015/02/08 00:29:47 Translation an emit thread numbers should be indep
Jim Stichnoth 2015/02/08 17:11:23 Oops, cargo-cult error. The Sequential logic is t
140 /*Sequential=*/(Flags.NumTranslationThreads == 0)) {
139 // Make sure thread_local fields are properly initialized before any 141 // Make sure thread_local fields are properly initialized before any
140 // accesses are made. Do this here instead of at the start of 142 // accesses are made. Do this here instead of at the start of
141 // main() so that all clients (e.g. unit tests) can benefit for 143 // main() so that all clients (e.g. unit tests) can benefit for
142 // free. 144 // free.
143 GlobalContext::TlsInit(); 145 GlobalContext::TlsInit();
144 Cfg::TlsInit(); 146 Cfg::TlsInit();
145 // Create a new ThreadContext for the current thread. No need to 147 // Create a new ThreadContext for the current thread. No need to
146 // lock AllThreadContexts at this point since no other threads have 148 // lock AllThreadContexts at this point since no other threads have
147 // access yet to this GlobalContext object. 149 // access yet to this GlobalContext object.
148 ThreadContext *MyTLS = new ThreadContext(); 150 ThreadContext *MyTLS = new ThreadContext();
(...skipping 22 matching lines...) Expand all
171 // match the -verbose-focus command-line option. 173 // match the -verbose-focus command-line option.
172 if (!matchSymbolName(Func->getFunctionName(), getFlags().VerboseFocusOn)) 174 if (!matchSymbolName(Func->getFunctionName(), getFlags().VerboseFocusOn))
173 Func->setVerbose(IceV_None); 175 Func->setVerbose(IceV_None);
174 // Disable translation if -notranslate is specified, or if the 176 // Disable translation if -notranslate is specified, or if the
175 // current function matches the -translate-only option. If 177 // current function matches the -translate-only option. If
176 // translation is disabled, just dump the high-level IR and 178 // translation is disabled, just dump the high-level IR and
177 // continue. 179 // continue.
178 if (getFlags().DisableTranslation || 180 if (getFlags().DisableTranslation ||
179 !matchSymbolName(Func->getFunctionName(), getFlags().TranslateOnly)) { 181 !matchSymbolName(Func->getFunctionName(), getFlags().TranslateOnly)) {
180 Func->dump(); 182 Func->dump();
183 Cfg::setCurrentCfg(nullptr);
181 } else { 184 } else {
182 Func->translate(); 185 Func->translate();
186 EmitterWorkItem *Item = nullptr;
183 if (Func->hasError()) { 187 if (Func->hasError()) {
184 getErrorStatus()->assign(EC_Translation); 188 getErrorStatus()->assign(EC_Translation);
185 OstreamLocker L(this); 189 OstreamLocker L(this);
186 getStrDump() << "ICE translation error: " << Func->getError() << "\n"; 190 getStrDump() << "ICE translation error: " << Func->getError() << "\n";
191 Item = new EmitterWorkItem(Func->getSequenceNumber());
187 } else { 192 } else {
188 if (getFlags().UseIntegratedAssembler) 193 if (getFlags().UseIntegratedAssembler) {
189 Func->emitIAS(); 194 Func->emitIAS();
190 else 195 // The Cfg has already emitted into the assembly buffer, so
191 Func->emit(); 196 // stats have been fully collected into this thread's TLS.
192 // TODO(stichnot): actually add to emit queue 197 // Dump them before TLS is reset for the next Cfg.
198 dumpStats(Func->getFunctionName());
199 Assembler *Asm = Func->releaseAssembler();
200 // Copy relevant fields into Asm before Func is deleted.
201 Asm->setFunctionName(Func->getFunctionName());
202 Asm->setInternal(Func->getInternal());
203 Item = new EmitterWorkItem(Func->getSequenceNumber(), Asm);
204 } else {
205 // The Cfg has not been emitted yet, so stats are not ready
206 // to be dumped.
207 Item = new EmitterWorkItem(Func->getSequenceNumber(), Func.release());
208 }
193 } 209 }
210 Cfg::setCurrentCfg(nullptr);
211 assert(Item);
212 emitQueueBlockingPush(Item);
213 }
214 // The Cfg now gets deleted as Func goes out of scope.
215 }
216 }
217
218 namespace {
219
220 void lowerGlobals(GlobalContext *Ctx,
Jim Stichnoth 2015/02/07 14:53:07 This is moved largely unchanged from Translator::l
221 VariableDeclarationList *VariableDeclarations,
222 TargetDataLowering *DataLowering) {
223 TimerMarker T(TimerStack::TT_emitGlobalInitializers, Ctx);
224 bool DisableTranslation = Ctx->getFlags().DisableTranslation;
225 const bool DumpGlobalVariables =
226 ALLOW_DUMP && Ctx->getVerbose() && Ctx->getFlags().VerboseFocusOn.empty();
227 if (Ctx->getFlags().UseELFWriter) {
228 // Dump all globals if requested, but don't interleave w/ emission.
229 if (DumpGlobalVariables) {
230 OstreamLocker L(Ctx);
231 Ostream &Stream = Ctx->getStrDump();
232 for (const Ice::VariableDeclaration *Global : *VariableDeclarations) {
233 Global->dump(Ctx, Stream);
234 }
235 }
236 DataLowering->lowerGlobalsELF(*VariableDeclarations);
237 } else {
238 const IceString &TranslateOnly = Ctx->getFlags().TranslateOnly;
239 OstreamLocker L(Ctx);
240 Ostream &Stream = Ctx->getStrDump();
241 for (const Ice::VariableDeclaration *Global : *VariableDeclarations) {
242 // Interleave dump output w/ emit output.
243 if (DumpGlobalVariables)
244 Global->dump(Ctx, Stream);
245 if (!DisableTranslation &&
246 GlobalContext::matchSymbolName(Global->getName(), TranslateOnly))
247 DataLowering->lowerGlobal(*Global);
248 }
249 }
250 }
251
252 // Ensure Pending is large enough that Pending[Index] is valid.
253 void resizePending(std::vector<EmitterWorkItem *> &Pending, uint32_t Index) {
254 if (Index >= Pending.size())
255 Pending.resize(Index + 1);
256 }
257
258 } // end of anonymous namespace
259
260 void GlobalContext::emitItems() {
261 const bool Threaded = getFlags().NumTranslationThreads;
262 // Pending is a vector containing the reassembled, ordered list of
263 // work items. When we're ready for the next item, we first check
264 // whether it's in the Pending list. If not, we take an item from
265 // the work queue, and if it's not the item we're waiting for, we
266 // insert it into Pending and repeat. The work item is deleted
267 // after it is processed.
268 std::vector<EmitterWorkItem *> Pending;
269 uint32_t DesiredSequenceNumber = getFirstSequenceNumber();
270 while (true) {
271 resizePending(Pending, DesiredSequenceNumber);
272 // See if Pending contains DesiredSequenceNumber.
273 EmitterWorkItem *Item = Pending[DesiredSequenceNumber];
274 if (Item == nullptr)
275 Item = emitQueueBlockingPop();
276 if (Item == nullptr)
277 return;
278 uint32_t ItemSeq = Item->getSequenceNumber();
279 if (Threaded && ItemSeq != DesiredSequenceNumber) {
280 resizePending(Pending, ItemSeq);
281 Pending[ItemSeq] = Item;
282 continue;
283 }
284
285 ++DesiredSequenceNumber;
286 switch (Item->getKind()) {
287 case EmitterWorkItem::WI_Nop:
288 break;
289 case EmitterWorkItem::WI_GlobalInits: {
290 lowerGlobals(this, Item->getGlobalInits(),
291 TargetDataLowering::createLowering(this).get());
292 } break;
293 case EmitterWorkItem::WI_Asm: {
294 Assembler *Asm = Item->getAsm();
295 Asm->alignFunction();
296 IceString MangledName = mangleName(Asm->getFunctionName());
297 if (getFlags().UseELFWriter) {
298 getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(),
299 Asm);
300 } else {
301 OstreamLocker L(this);
302 Cfg::emitTextHeader(MangledName, this, Asm);
303 Asm->emitIASBytes(this);
304 }
305 } break;
306 case EmitterWorkItem::WI_Cfg: {
307 assert(!getFlags().UseIntegratedAssembler);
308 Cfg *Func = Item->getCfg();
309 // Unfortunately, we have to temporarily install the Cfg in TLS
310 // because Variable::asType() uses the allocator to create the
311 // differently-typed copy.
312 Cfg::setCurrentCfg(Func);
313 Func->emit();
314 Cfg::setCurrentCfg(nullptr);
194 dumpStats(Func->getFunctionName()); 315 dumpStats(Func->getFunctionName());
316 } break;
195 } 317 }
196 Cfg::setCurrentCfg(nullptr); 318 delete Item;
197 // The Cfg now gets deleted as Func goes out of scope.
198 } 319 }
199 } 320 }
200 321
201 // Scan a string for S[0-9A-Z]*_ patterns and replace them with 322 // Scan a string for S[0-9A-Z]*_ patterns and replace them with
202 // S<num>_ where <num> is the next base-36 value. If a type name 323 // S<num>_ where <num> is the next base-36 value. If a type name
203 // legitimately contains that pattern, then the substitution will be 324 // legitimately contains that pattern, then the substitution will be
204 // made in error and most likely the link will fail. In this case, 325 // made in error and most likely the link will fail. In this case,
205 // the test classes can be rewritten not to use that pattern, which is 326 // the test classes can be rewritten not to use that pattern, which is
206 // much simpler and more reliable than implementing a full demangling 327 // much simpler and more reliable than implementing a full demangling
207 // parser. Another substitution-in-error may occur if a type 328 // parser. Another substitution-in-error may occur if a type
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 assert(StackID < Timers->size()); 668 assert(StackID < Timers->size());
548 Timers->at(StackID).setName(NewName); 669 Timers->at(StackID).setName(NewName);
549 } 670 }
550 671
551 // Note: cfgQueueBlockingPush and cfgQueueBlockingPop use unique_ptr 672 // Note: cfgQueueBlockingPush and cfgQueueBlockingPop use unique_ptr
552 // at the interface to take and transfer ownership, but they 673 // at the interface to take and transfer ownership, but they
553 // internally store the raw Cfg pointer in the work queue. This 674 // internally store the raw Cfg pointer in the work queue. This
554 // allows e.g. future queue optimizations such as the use of atomics 675 // allows e.g. future queue optimizations such as the use of atomics
555 // to modify queue elements. 676 // to modify queue elements.
556 void GlobalContext::cfgQueueBlockingPush(std::unique_ptr<Cfg> Func) { 677 void GlobalContext::cfgQueueBlockingPush(std::unique_ptr<Cfg> Func) {
678 assert(Func);
557 CfgQ.blockingPush(Func.release()); 679 CfgQ.blockingPush(Func.release());
680 if (getFlags().NumTranslationThreads == 0)
681 translateFunctions();
558 } 682 }
559 683
560 std::unique_ptr<Cfg> GlobalContext::cfgQueueBlockingPop() { 684 std::unique_ptr<Cfg> GlobalContext::cfgQueueBlockingPop() {
561 return std::unique_ptr<Cfg>(CfgQ.blockingPop()); 685 return std::unique_ptr<Cfg>(CfgQ.blockingPop());
562 } 686 }
563 687
688 void GlobalContext::emitQueueBlockingPush(EmitterWorkItem *Item) {
689 assert(Item);
690 EmitQ.blockingPush(Item);
691 if (getFlags().NumTranslationThreads == 0)
692 emitItems();
693 }
694
695 EmitterWorkItem *GlobalContext::emitQueueBlockingPop() {
696 return EmitQ.blockingPop();
697 }
698
564 void GlobalContext::dumpStats(const IceString &Name, bool Final) { 699 void GlobalContext::dumpStats(const IceString &Name, bool Final) {
565 if (!ALLOW_DUMP || !getFlags().DumpStats) 700 if (!ALLOW_DUMP || !getFlags().DumpStats)
566 return; 701 return;
567 OstreamLocker OL(this); 702 OstreamLocker OL(this);
568 if (Final) { 703 if (Final) {
569 getStatsCumulative()->dump(Name, getStrDump()); 704 getStatsCumulative()->dump(Name, getStrDump());
570 } else { 705 } else {
571 ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Name, getStrDump()); 706 ICE_TLS_GET_FIELD(TLS)->StatsFunction.dump(Name, getStrDump());
572 } 707 }
573 } 708 }
(...skipping 22 matching lines...) Expand all
596 Ctx->pushTimer(ID, StackID); 731 Ctx->pushTimer(ID, StackID);
597 } 732 }
598 733
599 void TimerMarker::pushCfg(const Cfg *Func) { 734 void TimerMarker::pushCfg(const Cfg *Func) {
600 Ctx = Func->getContext(); 735 Ctx = Func->getContext();
601 Active = Func->getFocusedTiming() || Ctx->getFlags().SubzeroTimingEnabled; 736 Active = Func->getFocusedTiming() || Ctx->getFlags().SubzeroTimingEnabled;
602 if (Active) 737 if (Active)
603 Ctx->pushTimer(ID, StackID); 738 Ctx->pushTimer(ID, StackID);
604 } 739 }
605 740
741 EmitterWorkItem::~EmitterWorkItem() {
742 // TODO(kschimpf,stichnot): Delete GlobalInits once it is managed in
743 // the parser as a unique_ptr.
744
745 // delete GlobalInits;
746 delete Function;
747 delete RawFunc;
748 }
749
606 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); 750 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS);
607 751
608 } // end of namespace Ice 752 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698