| OLD | NEW |
| 1 //===- subzero/src/IceGlobalContext.h - Global context defs -----*- C++ -*-===// | 1 //===- subzero/src/IceGlobalContext.h - Global context defs -----*- C++ -*-===// |
| 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 10 matching lines...) Expand all Loading... |
| 21 #include "IceIntrinsics.h" | 21 #include "IceIntrinsics.h" |
| 22 #include "IceRNG.h" | 22 #include "IceRNG.h" |
| 23 #include "IceSwitchLowering.h" | 23 #include "IceSwitchLowering.h" |
| 24 #include "IceTargetLowering.def" | 24 #include "IceTargetLowering.def" |
| 25 #include "IceThreading.h" | 25 #include "IceThreading.h" |
| 26 #include "IceTimerTree.h" | 26 #include "IceTimerTree.h" |
| 27 #include "IceTypes.h" | 27 #include "IceTypes.h" |
| 28 #include "IceUtils.h" | 28 #include "IceUtils.h" |
| 29 | 29 |
| 30 #include <array> | 30 #include <array> |
| 31 #include <atomic> |
| 31 #include <cassert> | 32 #include <cassert> |
| 32 #include <functional> | 33 #include <functional> |
| 33 #include <memory> | 34 #include <memory> |
| 34 #include <mutex> | 35 #include <mutex> |
| 35 #include <thread> | 36 #include <thread> |
| 36 #include <type_traits> | 37 #include <type_traits> |
| 37 #include <utility> | 38 #include <utility> |
| 38 #include <vector> | 39 #include <vector> |
| 39 | 40 |
| 40 namespace Ice { | 41 namespace Ice { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 70 ~LockedPtr() { Lock->unlock(); } | 71 ~LockedPtr() { Lock->unlock(); } |
| 71 T *operator->() const { return Value; } | 72 T *operator->() const { return Value; } |
| 72 T &operator*() const { return *Value; } | 73 T &operator*() const { return *Value; } |
| 73 T *get() { return Value; } | 74 T *get() { return Value; } |
| 74 | 75 |
| 75 private: | 76 private: |
| 76 T *Value; | 77 T *Value; |
| 77 GlobalLockType *Lock; | 78 GlobalLockType *Lock; |
| 78 }; | 79 }; |
| 79 | 80 |
| 81 /// OptWorkItem is a simple wrapper used to pass parse information on a function |
| 82 /// block, to a translator thread. |
| 83 class OptWorkItem { |
| 84 OptWorkItem(const OptWorkItem &) = delete; |
| 85 OptWorkItem &operator=(const OptWorkItem &) = delete; |
| 86 |
| 87 public: |
| 88 // Get the Cfg for the funtion to translate. |
| 89 virtual std::unique_ptr<Cfg> getParsedCfg() = 0; |
| 90 virtual ~OptWorkItem() = default; |
| 91 |
| 92 protected: |
| 93 OptWorkItem() = default; |
| 94 }; |
| 95 |
| 80 class GlobalContext { | 96 class GlobalContext { |
| 81 GlobalContext() = delete; | 97 GlobalContext() = delete; |
| 82 GlobalContext(const GlobalContext &) = delete; | 98 GlobalContext(const GlobalContext &) = delete; |
| 83 GlobalContext &operator=(const GlobalContext &) = delete; | 99 GlobalContext &operator=(const GlobalContext &) = delete; |
| 84 | 100 |
| 85 /// CodeStats collects rudimentary statistics during translation. | 101 /// CodeStats collects rudimentary statistics during translation. |
| 86 class CodeStats { | 102 class CodeStats { |
| 87 CodeStats(const CodeStats &) = delete; | 103 CodeStats(const CodeStats &) = delete; |
| 88 CodeStats &operator=(const CodeStats &) = default; | 104 CodeStats &operator=(const CodeStats &) = default; |
| 89 #define CODESTATS_TABLE \ | 105 #define CODESTATS_TABLE \ |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 /// This is the first work item sequence number that the parser produces, and | 387 /// This is the first work item sequence number that the parser produces, and |
| 372 /// correspondingly the first sequence number that the emitter thread will | 388 /// correspondingly the first sequence number that the emitter thread will |
| 373 /// wait for. Start numbering at 1 to leave room for a sentinel, in case e.g. | 389 /// wait for. Start numbering at 1 to leave room for a sentinel, in case e.g. |
| 374 /// we wish to inject items with a special sequence number that may be | 390 /// we wish to inject items with a special sequence number that may be |
| 375 /// executed out of order. | 391 /// executed out of order. |
| 376 static uint32_t getFirstSequenceNumber() { return 1; } | 392 static uint32_t getFirstSequenceNumber() { return 1; } |
| 377 /// Adds a newly parsed and constructed function to the Cfg work queue. | 393 /// Adds a newly parsed and constructed function to the Cfg work queue. |
| 378 /// Notifies any idle workers that a new function is available for | 394 /// Notifies any idle workers that a new function is available for |
| 379 /// translating. May block if the work queue is too large, in order to control | 395 /// translating. May block if the work queue is too large, in order to control |
| 380 /// memory footprint. | 396 /// memory footprint. |
| 381 void optQueueBlockingPush(std::unique_ptr<Cfg> Func); | 397 void optQueueBlockingPush(std::unique_ptr<OptWorkItem> Item); |
| 382 /// Takes a Cfg from the work queue for translating. May block if the work | 398 /// Takes a Cfg from the work queue for translating. May block if the work |
| 383 /// queue is currently empty. Returns nullptr if there is no more work - the | 399 /// queue is currently empty. Returns nullptr if there is no more work - the |
| 384 /// queue is empty and either end() has been called or the Sequential flag was | 400 /// queue is empty and either end() has been called or the Sequential flag was |
| 385 /// set. | 401 /// set. |
| 386 std::unique_ptr<Cfg> optQueueBlockingPop(); | 402 std::unique_ptr<OptWorkItem> optQueueBlockingPop(); |
| 387 /// Notifies that no more work will be added to the work queue. | 403 /// Notifies that no more work will be added to the work queue. |
| 388 void optQueueNotifyEnd() { OptQ.notifyEnd(); } | 404 void optQueueNotifyEnd() { OptQ.notifyEnd(); } |
| 389 | 405 |
| 390 /// Emit file header for output file. | 406 /// Emit file header for output file. |
| 391 void emitFileHeader(); | 407 void emitFileHeader(); |
| 392 | 408 |
| 393 void lowerConstants(); | 409 void lowerConstants(); |
| 394 | 410 |
| 395 void lowerJumpTables(); | 411 void lowerJumpTables(); |
| 396 | 412 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 418 } | 434 } |
| 419 if (NumWorkers) { | 435 if (NumWorkers) { |
| 420 ThreadContext *WorkerTLS = new ThreadContext(); | 436 ThreadContext *WorkerTLS = new ThreadContext(); |
| 421 Timers->initInto(WorkerTLS->Timers); | 437 Timers->initInto(WorkerTLS->Timers); |
| 422 AllThreadContexts.push_back(WorkerTLS); | 438 AllThreadContexts.push_back(WorkerTLS); |
| 423 EmitterThreads.push_back( | 439 EmitterThreads.push_back( |
| 424 std::thread(&GlobalContext::emitterWrapper, this, WorkerTLS)); | 440 std::thread(&GlobalContext::emitterWrapper, this, WorkerTLS)); |
| 425 } | 441 } |
| 426 } | 442 } |
| 427 | 443 |
| 428 void waitForWorkerThreads() { | 444 void waitForWorkerThreads(); |
| 429 optQueueNotifyEnd(); | |
| 430 for (std::thread &Worker : TranslationThreads) { | |
| 431 Worker.join(); | |
| 432 } | |
| 433 TranslationThreads.clear(); | |
| 434 | |
| 435 // Only notify the emit queue to end after all the translation threads have | |
| 436 // ended. | |
| 437 emitQueueNotifyEnd(); | |
| 438 for (std::thread &Worker : EmitterThreads) { | |
| 439 Worker.join(); | |
| 440 } | |
| 441 EmitterThreads.clear(); | |
| 442 | |
| 443 if (BuildDefs::timers()) { | |
| 444 auto Timers = getTimers(); | |
| 445 for (ThreadContext *TLS : AllThreadContexts) | |
| 446 Timers->mergeFrom(TLS->Timers); | |
| 447 } | |
| 448 if (BuildDefs::dump()) { | |
| 449 // Do a separate loop over AllThreadContexts to avoid holding two locks | |
| 450 // at once. | |
| 451 auto Stats = getStatsCumulative(); | |
| 452 for (ThreadContext *TLS : AllThreadContexts) | |
| 453 Stats->add(TLS->StatsCumulative); | |
| 454 } | |
| 455 } | |
| 456 | 445 |
| 457 /// Translation thread startup routine. | 446 /// Translation thread startup routine. |
| 458 void translateFunctionsWrapper(ThreadContext *MyTLS) { | 447 void translateFunctionsWrapper(ThreadContext *MyTLS) { |
| 459 ICE_TLS_SET_FIELD(TLS, MyTLS); | 448 ICE_TLS_SET_FIELD(TLS, MyTLS); |
| 460 translateFunctions(); | 449 translateFunctions(); |
| 461 } | 450 } |
| 462 /// Translate functions from the Cfg queue until the queue is empty. | 451 /// Translate functions from the Cfg queue until the queue is empty. |
| 463 void translateFunctions(); | 452 void translateFunctions(); |
| 464 | 453 |
| 465 /// Emitter thread startup routine. | 454 /// Emitter thread startup routine. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 TimerList Timers; | 540 TimerList Timers; |
| 552 | 541 |
| 553 ICE_CACHELINE_BOUNDARY; | 542 ICE_CACHELINE_BOUNDARY; |
| 554 /// StrLock is a global lock on the dump and emit output streams. | 543 /// StrLock is a global lock on the dump and emit output streams. |
| 555 using StrLockType = std::mutex; | 544 using StrLockType = std::mutex; |
| 556 StrLockType StrLock; | 545 StrLockType StrLock; |
| 557 Ostream *StrDump; /// Stream for dumping / diagnostics | 546 Ostream *StrDump; /// Stream for dumping / diagnostics |
| 558 Ostream *StrEmit; /// Stream for code emission | 547 Ostream *StrEmit; /// Stream for code emission |
| 559 Ostream *StrError; /// Stream for logging errors. | 548 Ostream *StrError; /// Stream for logging errors. |
| 560 | 549 |
| 550 // True if waitForWorkerThreads() has been called. |
| 551 std::atomic_bool WaitForWorkerThreadsCalled; |
| 552 |
| 561 ICE_CACHELINE_BOUNDARY; | 553 ICE_CACHELINE_BOUNDARY; |
| 562 | 554 |
| 563 Intrinsics IntrinsicsInfo; | 555 Intrinsics IntrinsicsInfo; |
| 564 // TODO(jpp): move to EmitterContext. | 556 // TODO(jpp): move to EmitterContext. |
| 565 std::unique_ptr<ELFObjectWriter> ObjectWriter; | 557 std::unique_ptr<ELFObjectWriter> ObjectWriter; |
| 566 BoundedProducerConsumerQueue<Cfg> OptQ; | 558 static constexpr size_t MaxOptQSize = 1 << 16; |
| 559 BoundedProducerConsumerQueue<OptWorkItem, MaxOptQSize> OptQ; |
| 567 BoundedProducerConsumerQueue<EmitterWorkItem> EmitQ; | 560 BoundedProducerConsumerQueue<EmitterWorkItem> EmitQ; |
| 568 // DataLowering is only ever used by a single thread at a time (either in | 561 // DataLowering is only ever used by a single thread at a time (either in |
| 569 // emitItems(), or in IceCompiler::run before the compilation is over.) | 562 // emitItems(), or in IceCompiler::run before the compilation is over.) |
| 570 // TODO(jpp): move to EmitterContext. | 563 // TODO(jpp): move to EmitterContext. |
| 571 std::unique_ptr<TargetDataLowering> DataLowering; | 564 std::unique_ptr<TargetDataLowering> DataLowering; |
| 572 /// If !HasEmittedCode, SubZero will accumulate all Globals (which are "true" | 565 /// If !HasEmittedCode, SubZero will accumulate all Globals (which are "true" |
| 573 /// program global variables) until the first code WorkItem is seen. | 566 /// program global variables) until the first code WorkItem is seen. |
| 574 // TODO(jpp): move to EmitterContext. | 567 // TODO(jpp): move to EmitterContext. |
| 575 bool HasSeenCode = false; | 568 bool HasSeenCode = false; |
| 576 // TODO(jpp): move to EmitterContext. | 569 // TODO(jpp): move to EmitterContext. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 explicit OstreamLocker(GlobalContext *Ctx) : Ctx(Ctx) { Ctx->lockStr(); } | 690 explicit OstreamLocker(GlobalContext *Ctx) : Ctx(Ctx) { Ctx->lockStr(); } |
| 698 ~OstreamLocker() { Ctx->unlockStr(); } | 691 ~OstreamLocker() { Ctx->unlockStr(); } |
| 699 | 692 |
| 700 private: | 693 private: |
| 701 GlobalContext *const Ctx; | 694 GlobalContext *const Ctx; |
| 702 }; | 695 }; |
| 703 | 696 |
| 704 } // end of namespace Ice | 697 } // end of namespace Ice |
| 705 | 698 |
| 706 #endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H | 699 #endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H |
| OLD | NEW |