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

Side by Side Diff: src/IceGlobalContext.cpp

Issue 1804133002: Subzero. Uses unique_ptrs in the emit queue. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments. Created 4 years, 9 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
« no previous file with comments | « src/IceGlobalContext.h ('k') | src/IceThreading.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 /// \file 10 /// \file
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 // translation is disabled, just dump the high-level IR and 312 // translation is disabled, just dump the high-level IR and
313 // continue. 313 // continue.
314 if (getFlags().getDisableTranslation() || 314 if (getFlags().getDisableTranslation() ||
315 !matchSymbolName(Func->getFunctionName(), 315 !matchSymbolName(Func->getFunctionName(),
316 getFlags().getTranslateOnly())) { 316 getFlags().getTranslateOnly())) {
317 Func->dump(); 317 Func->dump();
318 continue; // Func goes out of scope and gets deleted 318 continue; // Func goes out of scope and gets deleted
319 } 319 }
320 320
321 Func->translate(); 321 Func->translate();
322 EmitterWorkItem *Item = nullptr; 322 std::unique_ptr<EmitterWorkItem> Item;
323 if (Func->hasError()) { 323 if (Func->hasError()) {
324 getErrorStatus()->assign(EC_Translation); 324 getErrorStatus()->assign(EC_Translation);
325 OstreamLocker L(this); 325 OstreamLocker L(this);
326 getStrError() << "ICE translation error: " << Func->getFunctionName() 326 getStrError() << "ICE translation error: " << Func->getFunctionName()
327 << ": " << Func->getError() << ": " 327 << ": " << Func->getError() << ": "
328 << Func->getFunctionNameAndSize() << "\n"; 328 << Func->getFunctionNameAndSize() << "\n";
329 Item = new EmitterWorkItem(Func->getSequenceNumber()); 329 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber());
330 } else { 330 } else {
331 Func->getAssembler<>()->setInternal(Func->getInternal()); 331 Func->getAssembler<>()->setInternal(Func->getInternal());
332 switch (getFlags().getOutFileType()) { 332 switch (getFlags().getOutFileType()) {
333 case FT_Elf: 333 case FT_Elf:
334 case FT_Iasm: { 334 case FT_Iasm: {
335 Func->emitIAS(); 335 Func->emitIAS();
336 // The Cfg has already emitted into the assembly buffer, so 336 // The Cfg has already emitted into the assembly buffer, so
337 // stats have been fully collected into this thread's TLS. 337 // stats have been fully collected into this thread's TLS.
338 // Dump them before TLS is reset for the next Cfg. 338 // Dump them before TLS is reset for the next Cfg.
339 dumpStats(Func->getFunctionNameAndSize()); 339 dumpStats(Func->getFunctionNameAndSize());
340 Assembler *Asm = Func->releaseAssembler(); 340 auto Asm = Func->releaseAssembler();
341 // Copy relevant fields into Asm before Func is deleted. 341 // Copy relevant fields into Asm before Func is deleted.
342 Asm->setFunctionName(Func->getFunctionName()); 342 Asm->setFunctionName(Func->getFunctionName());
343 Item = new EmitterWorkItem(Func->getSequenceNumber(), Asm); 343 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber(),
344 std::move(Asm));
344 Item->setGlobalInits(Func->getGlobalInits()); 345 Item->setGlobalInits(Func->getGlobalInits());
345 } break; 346 } break;
346 case FT_Asm: 347 case FT_Asm:
347 // The Cfg has not been emitted yet, so stats are not ready 348 // The Cfg has not been emitted yet, so stats are not ready
348 // to be dumped. 349 // to be dumped.
349 std::unique_ptr<VariableDeclarationList> GlobalInits = 350 std::unique_ptr<VariableDeclarationList> GlobalInits =
350 Func->getGlobalInits(); 351 Func->getGlobalInits();
351 Item = new EmitterWorkItem(Func->getSequenceNumber(), Func.release()); 352 Item = makeUnique<EmitterWorkItem>(Func->getSequenceNumber(),
353 std::move(Func));
352 Item->setGlobalInits(std::move(GlobalInits)); 354 Item->setGlobalInits(std::move(GlobalInits));
353 break; 355 break;
354 } 356 }
355 } 357 }
356 assert(Item); 358 assert(Item != nullptr);
357 emitQueueBlockingPush(Item); 359 emitQueueBlockingPush(std::move(Item));
358 // The Cfg now gets deleted as Func goes out of scope. 360 // The Cfg now gets deleted as Func goes out of scope.
359 } 361 }
360 } 362 }
361 363
362 namespace { 364 namespace {
363 365
364 // Ensure Pending is large enough that Pending[Index] is valid. 366 // Ensure Pending is large enough that Pending[Index] is valid.
365 void resizePending(std::vector<EmitterWorkItem *> &Pending, uint32_t Index) { 367 void resizePending(std::vector<std::unique_ptr<EmitterWorkItem>> *Pending,
366 if (Index >= Pending.size()) 368 uint32_t Index) {
367 Utils::reserveAndResize(Pending, Index + 1); 369 if (Index >= Pending->size())
370 Utils::reserveAndResize(*Pending, Index + 1);
368 } 371 }
369 372
370 } // end of anonymous namespace 373 } // end of anonymous namespace
371 374
372 void GlobalContext::emitFileHeader() { 375 void GlobalContext::emitFileHeader() {
373 TimerMarker T1(Ice::TimerStack::TT_emitAsm, this); 376 TimerMarker T1(Ice::TimerStack::TT_emitAsm, this);
374 if (getFlags().getOutFileType() == FT_Elf) { 377 if (getFlags().getOutFileType() == FT_Elf) {
375 getObjectWriter()->writeInitialELFHeader(); 378 getObjectWriter()->writeInitialELFHeader();
376 } else { 379 } else {
377 if (!BuildDefs::dump()) { 380 if (!BuildDefs::dump()) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 } 467 }
465 468
466 void GlobalContext::emitItems() { 469 void GlobalContext::emitItems() {
467 const bool Threaded = !getFlags().isSequential(); 470 const bool Threaded = !getFlags().isSequential();
468 // Pending is a vector containing the reassembled, ordered list of 471 // Pending is a vector containing the reassembled, ordered list of
469 // work items. When we're ready for the next item, we first check 472 // work items. When we're ready for the next item, we first check
470 // whether it's in the Pending list. If not, we take an item from 473 // whether it's in the Pending list. If not, we take an item from
471 // the work queue, and if it's not the item we're waiting for, we 474 // the work queue, and if it's not the item we're waiting for, we
472 // insert it into Pending and repeat. The work item is deleted 475 // insert it into Pending and repeat. The work item is deleted
473 // after it is processed. 476 // after it is processed.
474 std::vector<EmitterWorkItem *> Pending; 477 std::vector<std::unique_ptr<EmitterWorkItem>> Pending;
475 uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); 478 uint32_t DesiredSequenceNumber = getFirstSequenceNumber();
476 uint32_t ShuffleStartIndex = DesiredSequenceNumber; 479 uint32_t ShuffleStartIndex = DesiredSequenceNumber;
477 uint32_t ShuffleEndIndex = DesiredSequenceNumber; 480 uint32_t ShuffleEndIndex = DesiredSequenceNumber;
478 bool EmitQueueEmpty = false; 481 bool EmitQueueEmpty = false;
479 const uint32_t ShuffleWindowSize = 482 const uint32_t ShuffleWindowSize =
480 std::max(1u, getFlags().getReorderFunctionsWindowSize()); 483 std::max(1u, getFlags().getReorderFunctionsWindowSize());
481 bool Shuffle = Threaded && getFlags().shouldReorderFunctions(); 484 bool Shuffle = Threaded && getFlags().shouldReorderFunctions();
482 // Create a random number generator for function reordering. 485 // Create a random number generator for function reordering.
483 RandomNumberGenerator RNG(getFlags().getRandomSeed(), RPE_FunctionReordering); 486 RandomNumberGenerator RNG(getFlags().getRandomSeed(), RPE_FunctionReordering);
484 487
485 while (!EmitQueueEmpty) { 488 while (!EmitQueueEmpty) {
486 resizePending(Pending, DesiredSequenceNumber); 489 resizePending(&Pending, DesiredSequenceNumber);
487 // See if Pending contains DesiredSequenceNumber. 490 // See if Pending contains DesiredSequenceNumber.
488 EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber]; 491 if (Pending[DesiredSequenceNumber] == nullptr) {
489 if (RawItem == nullptr) {
490 // We need to fetch an EmitterWorkItem from the queue. 492 // We need to fetch an EmitterWorkItem from the queue.
491 RawItem = emitQueueBlockingPop(); 493 auto RawItem = emitQueueBlockingPop();
492 if (RawItem == nullptr) { 494 if (RawItem == nullptr) {
493 // This is the notifier for an empty queue. 495 // This is the notifier for an empty queue.
494 EmitQueueEmpty = true; 496 EmitQueueEmpty = true;
495 } else { 497 } else {
496 // We get an EmitterWorkItem, we need to add it to Pending. 498 // We get an EmitterWorkItem, we need to add it to Pending.
497 uint32_t ItemSeq = RawItem->getSequenceNumber(); 499 uint32_t ItemSeq = RawItem->getSequenceNumber();
498 if (Threaded && ItemSeq != DesiredSequenceNumber) { 500 if (Threaded && ItemSeq != DesiredSequenceNumber) {
499 // Not the desired one, add it to Pending but do not increase 501 // Not the desired one, add it to Pending but do not increase
500 // DesiredSequenceNumber. Continue the loop, do not emit the item. 502 // DesiredSequenceNumber. Continue the loop, do not emit the item.
501 resizePending(Pending, ItemSeq); 503 resizePending(&Pending, ItemSeq);
502 Pending[ItemSeq] = RawItem; 504 Pending[ItemSeq] = std::move(RawItem);
503 continue; 505 continue;
504 } 506 }
505 // ItemSeq == DesiredSequenceNumber, we need to check if we should 507 // ItemSeq == DesiredSequenceNumber, we need to check if we should
506 // emit it or not. If !Threaded, we're OK with ItemSeq != 508 // emit it or not. If !Threaded, we're OK with ItemSeq !=
507 // DesiredSequenceNumber. 509 // DesiredSequenceNumber.
508 Pending[DesiredSequenceNumber] = RawItem; 510 Pending[DesiredSequenceNumber] = std::move(RawItem);
509 } 511 }
510 } 512 }
513 const auto *CurrentWorkItem = Pending[DesiredSequenceNumber].get();
514
511 // We have the desired EmitterWorkItem or nullptr as the end notifier. 515 // We have the desired EmitterWorkItem or nullptr as the end notifier.
512 // If the emitter queue is not empty, increase DesiredSequenceNumber and 516 // If the emitter queue is not empty, increase DesiredSequenceNumber and
513 // ShuffleEndIndex. 517 // ShuffleEndIndex.
514 if (!EmitQueueEmpty) { 518 if (!EmitQueueEmpty) {
515 DesiredSequenceNumber++; 519 DesiredSequenceNumber++;
516 ShuffleEndIndex++; 520 ShuffleEndIndex++;
517 } 521 }
518 522
519 if (Shuffle) { 523 if (Shuffle) {
520 // Continue fetching EmitterWorkItem if function reordering is turned on, 524 // Continue fetching EmitterWorkItem if function reordering is turned on,
521 // and emit queue is not empty, and the number of consecutive pending 525 // and emit queue is not empty, and the number of consecutive pending
522 // items is smaller than the window size, and RawItem is not a 526 // items is smaller than the window size, and RawItem is not a
523 // WI_GlobalInits kind. Emit WI_GlobalInits kind block first to avoid 527 // WI_GlobalInits kind. Emit WI_GlobalInits kind block first to avoid
524 // holding an arbitrarily large GlobalDeclarationList. 528 // holding an arbitrarily large GlobalDeclarationList.
525 if (!EmitQueueEmpty && 529 if (!EmitQueueEmpty &&
526 ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize && 530 ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize &&
527 RawItem->getKind() != EmitterWorkItem::WI_GlobalInits) 531 CurrentWorkItem->getKind() != EmitterWorkItem::WI_GlobalInits)
528 continue; 532 continue;
529 533
530 // Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to 534 // Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to
531 // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the 535 // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the
532 // pending items from Pending[ShuffleStartIndex] to 536 // pending items from Pending[ShuffleStartIndex] to
533 // Pending[ShuffleEndIndex]. 537 // Pending[ShuffleEndIndex].
534 RandomShuffle(Pending.begin() + ShuffleStartIndex, 538 RandomShuffle(Pending.begin() + ShuffleStartIndex,
535 Pending.begin() + ShuffleEndIndex, 539 Pending.begin() + ShuffleEndIndex,
536 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); 540 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
537 } 541 }
538 542
539 // Emit the item from ShuffleStartIndex to ShuffleEndIndex. 543 // Emit the item from ShuffleStartIndex to ShuffleEndIndex.
540 for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) { 544 for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) {
541 std::unique_ptr<EmitterWorkItem> Item(Pending[I]); 545 std::unique_ptr<EmitterWorkItem> Item = std::move(Pending[I]);
542 546
543 switch (Item->getKind()) { 547 switch (Item->getKind()) {
544 case EmitterWorkItem::WI_Nop: 548 case EmitterWorkItem::WI_Nop:
545 break; 549 break;
546 case EmitterWorkItem::WI_GlobalInits: { 550 case EmitterWorkItem::WI_GlobalInits: {
547 accumulateGlobals(Item->getGlobalInits()); 551 accumulateGlobals(Item->getGlobalInits());
548 } break; 552 } break;
549 case EmitterWorkItem::WI_Asm: { 553 case EmitterWorkItem::WI_Asm: {
550 lowerGlobalsIfNoCodeHasBeenSeen(); 554 lowerGlobalsIfNoCodeHasBeenSeen();
551 accumulateGlobals(Item->getGlobalInits()); 555 accumulateGlobals(Item->getGlobalInits());
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 } 859 }
856 860
857 // Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr at the 861 // Note: optQueueBlockingPush and optQueueBlockingPop use unique_ptr at the
858 // interface to take and transfer ownership, but they internally store the raw 862 // interface to take and transfer ownership, but they internally store the raw
859 // Cfg pointer in the work queue. This allows e.g. future queue optimizations 863 // Cfg pointer in the work queue. This allows e.g. future queue optimizations
860 // such as the use of atomics to modify queue elements. 864 // such as the use of atomics to modify queue elements.
861 void GlobalContext::optQueueBlockingPush(std::unique_ptr<Cfg> Func) { 865 void GlobalContext::optQueueBlockingPush(std::unique_ptr<Cfg> Func) {
862 assert(Func); 866 assert(Func);
863 { 867 {
864 TimerMarker _(TimerStack::TT_qTransPush, this); 868 TimerMarker _(TimerStack::TT_qTransPush, this);
865 OptQ.blockingPush(Func.release()); 869 OptQ.blockingPush(std::move(Func));
866 } 870 }
867 if (getFlags().isSequential()) 871 if (getFlags().isSequential())
868 translateFunctions(); 872 translateFunctions();
869 } 873 }
870 874
871 std::unique_ptr<Cfg> GlobalContext::optQueueBlockingPop() { 875 std::unique_ptr<Cfg> GlobalContext::optQueueBlockingPop() {
872 TimerMarker _(TimerStack::TT_qTransPop, this); 876 TimerMarker _(TimerStack::TT_qTransPop, this);
873 return std::unique_ptr<Cfg>(OptQ.blockingPop()); 877 return std::unique_ptr<Cfg>(OptQ.blockingPop());
874 } 878 }
875 879
876 void GlobalContext::emitQueueBlockingPush(EmitterWorkItem *Item) { 880 void GlobalContext::emitQueueBlockingPush(
881 std::unique_ptr<EmitterWorkItem> Item) {
877 assert(Item); 882 assert(Item);
878 { 883 {
879 TimerMarker _(TimerStack::TT_qEmitPush, this); 884 TimerMarker _(TimerStack::TT_qEmitPush, this);
880 EmitQ.blockingPush(Item); 885 EmitQ.blockingPush(std::move(Item));
881 } 886 }
882 if (getFlags().isSequential()) 887 if (getFlags().isSequential())
883 emitItems(); 888 emitItems();
884 } 889 }
885 890
886 EmitterWorkItem *GlobalContext::emitQueueBlockingPop() { 891 std::unique_ptr<EmitterWorkItem> GlobalContext::emitQueueBlockingPop() {
887 TimerMarker _(TimerStack::TT_qEmitPop, this); 892 TimerMarker _(TimerStack::TT_qEmitPop, this);
888 return EmitQ.blockingPop(); 893 return EmitQ.blockingPop();
889 } 894 }
890 895
891 void GlobalContext::dumpStats(const IceString &Name, bool Final) { 896 void GlobalContext::dumpStats(const IceString &Name, bool Final) {
892 if (!getFlags().getDumpStats()) 897 if (!getFlags().getDumpStats())
893 return; 898 return;
894 if (Final) { 899 if (Final) {
895 getStatsCumulative()->dump(Name, this); 900 getStatsCumulative()->dump(Name, this);
896 } else { 901 } else {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 Ctx = Func->getContext(); 943 Ctx = Func->getContext();
939 Active = 944 Active =
940 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled(); 945 Func->getFocusedTiming() || Ctx->getFlags().getSubzeroTimingEnabled();
941 if (Active) 946 if (Active)
942 Ctx->pushTimer(ID, StackID); 947 Ctx->pushTimer(ID, StackID);
943 } 948 }
944 949
945 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS); 950 ICE_TLS_DEFINE_FIELD(GlobalContext::ThreadContext *, GlobalContext, TLS);
946 951
947 } // end of namespace Ice 952 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceGlobalContext.h ('k') | src/IceThreading.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698