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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
70 ~LockedPtr() { Lock->unlock(); } | 70 ~LockedPtr() { Lock->unlock(); } |
71 T *operator->() const { return Value; } | 71 T *operator->() const { return Value; } |
72 T &operator*() const { return *Value; } | 72 T &operator*() const { return *Value; } |
73 T *get() { return Value; } | 73 T *get() { return Value; } |
74 | 74 |
75 private: | 75 private: |
76 T *Value; | 76 T *Value; |
77 GlobalLockType *Lock; | 77 GlobalLockType *Lock; |
78 }; | 78 }; |
79 | 79 |
80 /// OptWorkItem is a simple wrapper used to pass parse information on a function | |
81 /// block, to a translator thread. | |
82 class OptWorkItem { | |
83 OptWorkItem(const OptWorkItem &) = delete; | |
84 OptWorkItem &operator=(const OptWorkItem &) = delete; | |
85 | |
86 public: | |
87 // Get the Cfg for the funtion to translate. | |
88 virtual std::unique_ptr<Cfg> getParsedCfg() = 0; | |
89 virtual ~OptWorkItem() {} | |
90 | |
91 protected: | |
92 OptWorkItem() {} | |
Jim Stichnoth
2016/03/25 04:31:04
OptWorkItem() = default;
?
Same for ~OptWorkItem(
Karl
2016/03/29 17:35:02
Done.
| |
93 }; | |
94 | |
80 class GlobalContext { | 95 class GlobalContext { |
81 GlobalContext() = delete; | 96 GlobalContext() = delete; |
82 GlobalContext(const GlobalContext &) = delete; | 97 GlobalContext(const GlobalContext &) = delete; |
83 GlobalContext &operator=(const GlobalContext &) = delete; | 98 GlobalContext &operator=(const GlobalContext &) = delete; |
84 | 99 |
85 /// CodeStats collects rudimentary statistics during translation. | 100 /// CodeStats collects rudimentary statistics during translation. |
86 class CodeStats { | 101 class CodeStats { |
87 CodeStats(const CodeStats &) = delete; | 102 CodeStats(const CodeStats &) = delete; |
88 CodeStats &operator=(const CodeStats &) = default; | 103 CodeStats &operator=(const CodeStats &) = default; |
89 #define CODESTATS_TABLE \ | 104 #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 | 386 /// This is the first work item sequence number that the parser produces, and |
372 /// correspondingly the first sequence number that the emitter thread will | 387 /// 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. | 388 /// 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 | 389 /// we wish to inject items with a special sequence number that may be |
375 /// executed out of order. | 390 /// executed out of order. |
376 static uint32_t getFirstSequenceNumber() { return 1; } | 391 static uint32_t getFirstSequenceNumber() { return 1; } |
377 /// Adds a newly parsed and constructed function to the Cfg work queue. | 392 /// Adds a newly parsed and constructed function to the Cfg work queue. |
378 /// Notifies any idle workers that a new function is available for | 393 /// 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 | 394 /// translating. May block if the work queue is too large, in order to control |
380 /// memory footprint. | 395 /// memory footprint. |
381 void optQueueBlockingPush(std::unique_ptr<Cfg> Func); | 396 void optQueueBlockingPush(std::unique_ptr<OptWorkItem> Item); |
382 /// Takes a Cfg from the work queue for translating. May block if the work | 397 /// 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 | 398 /// 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 | 399 /// queue is empty and either end() has been called or the Sequential flag was |
385 /// set. | 400 /// set. |
386 std::unique_ptr<Cfg> optQueueBlockingPop(); | 401 std::unique_ptr<OptWorkItem> optQueueBlockingPop(); |
387 /// Notifies that no more work will be added to the work queue. | 402 /// Notifies that no more work will be added to the work queue. |
388 void optQueueNotifyEnd() { OptQ.notifyEnd(); } | 403 void optQueueNotifyEnd() { OptQ.notifyEnd(); } |
389 | 404 |
390 /// Emit file header for output file. | 405 /// Emit file header for output file. |
391 void emitFileHeader(); | 406 void emitFileHeader(); |
392 | 407 |
393 void lowerConstants(); | 408 void lowerConstants(); |
394 | 409 |
395 void lowerJumpTables(); | 410 void lowerJumpTables(); |
396 | 411 |
(...skipping 21 matching lines...) Expand all Loading... | |
418 } | 433 } |
419 if (NumWorkers) { | 434 if (NumWorkers) { |
420 ThreadContext *WorkerTLS = new ThreadContext(); | 435 ThreadContext *WorkerTLS = new ThreadContext(); |
421 Timers->initInto(WorkerTLS->Timers); | 436 Timers->initInto(WorkerTLS->Timers); |
422 AllThreadContexts.push_back(WorkerTLS); | 437 AllThreadContexts.push_back(WorkerTLS); |
423 EmitterThreads.push_back( | 438 EmitterThreads.push_back( |
424 std::thread(&GlobalContext::emitterWrapper, this, WorkerTLS)); | 439 std::thread(&GlobalContext::emitterWrapper, this, WorkerTLS)); |
425 } | 440 } |
426 } | 441 } |
427 | 442 |
428 void waitForWorkerThreads() { | 443 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 | 444 |
457 /// Translation thread startup routine. | 445 /// Translation thread startup routine. |
458 void translateFunctionsWrapper(ThreadContext *MyTLS) { | 446 void translateFunctionsWrapper(ThreadContext *MyTLS) { |
459 ICE_TLS_SET_FIELD(TLS, MyTLS); | 447 ICE_TLS_SET_FIELD(TLS, MyTLS); |
460 translateFunctions(); | 448 translateFunctions(); |
461 } | 449 } |
462 /// Translate functions from the Cfg queue until the queue is empty. | 450 /// Translate functions from the Cfg queue until the queue is empty. |
463 void translateFunctions(); | 451 void translateFunctions(); |
464 | 452 |
465 /// Emitter thread startup routine. | 453 /// Emitter thread startup routine. |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
552 | 540 |
553 ICE_CACHELINE_BOUNDARY; | 541 ICE_CACHELINE_BOUNDARY; |
554 /// StrLock is a global lock on the dump and emit output streams. | 542 /// StrLock is a global lock on the dump and emit output streams. |
555 using StrLockType = std::mutex; | 543 using StrLockType = std::mutex; |
556 StrLockType StrLock; | 544 StrLockType StrLock; |
557 Ostream *StrDump; /// Stream for dumping / diagnostics | 545 Ostream *StrDump; /// Stream for dumping / diagnostics |
558 Ostream *StrEmit; /// Stream for code emission | 546 Ostream *StrEmit; /// Stream for code emission |
559 Ostream *StrError; /// Stream for logging errors. | 547 Ostream *StrError; /// Stream for logging errors. |
560 | 548 |
561 ICE_CACHELINE_BOUNDARY; | 549 ICE_CACHELINE_BOUNDARY; |
550 // WaitForWorkersLock is a global lock used to update | |
551 // WaitForWorkerThreadsCalled. | |
552 GlobalLockType WaitForWorkersLock; | |
553 // True if WaitForWorkerThreads have been called. | |
Jim Stichnoth
2016/03/25 04:31:04
True if waitForWorkerThreads() has been called.
Karl
2016/03/29 17:35:02
Done.
| |
554 bool WaitForWorkerThreadsCalled = false; | |
555 | |
556 ICE_CACHELINE_BOUNDARY; | |
562 | 557 |
563 Intrinsics IntrinsicsInfo; | 558 Intrinsics IntrinsicsInfo; |
564 // TODO(jpp): move to EmitterContext. | 559 // TODO(jpp): move to EmitterContext. |
565 std::unique_ptr<ELFObjectWriter> ObjectWriter; | 560 std::unique_ptr<ELFObjectWriter> ObjectWriter; |
566 BoundedProducerConsumerQueue<Cfg> OptQ; | 561 static constexpr size_t MaxOptQSize = 1 << 16; |
562 BoundedProducerConsumerQueue<OptWorkItem, MaxOptQSize> OptQ; | |
567 BoundedProducerConsumerQueue<EmitterWorkItem> EmitQ; | 563 BoundedProducerConsumerQueue<EmitterWorkItem> EmitQ; |
568 // DataLowering is only ever used by a single thread at a time (either in | 564 // 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.) | 565 // emitItems(), or in IceCompiler::run before the compilation is over.) |
570 // TODO(jpp): move to EmitterContext. | 566 // TODO(jpp): move to EmitterContext. |
571 std::unique_ptr<TargetDataLowering> DataLowering; | 567 std::unique_ptr<TargetDataLowering> DataLowering; |
572 /// If !HasEmittedCode, SubZero will accumulate all Globals (which are "true" | 568 /// If !HasEmittedCode, SubZero will accumulate all Globals (which are "true" |
573 /// program global variables) until the first code WorkItem is seen. | 569 /// program global variables) until the first code WorkItem is seen. |
574 // TODO(jpp): move to EmitterContext. | 570 // TODO(jpp): move to EmitterContext. |
575 bool HasSeenCode = false; | 571 bool HasSeenCode = false; |
576 // TODO(jpp): move to EmitterContext. | 572 // 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(); } | 693 explicit OstreamLocker(GlobalContext *Ctx) : Ctx(Ctx) { Ctx->lockStr(); } |
698 ~OstreamLocker() { Ctx->unlockStr(); } | 694 ~OstreamLocker() { Ctx->unlockStr(); } |
699 | 695 |
700 private: | 696 private: |
701 GlobalContext *const Ctx; | 697 GlobalContext *const Ctx; |
702 }; | 698 }; |
703 | 699 |
704 } // end of namespace Ice | 700 } // end of namespace Ice |
705 | 701 |
706 #endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H | 702 #endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H |
OLD | NEW |