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 |
11 /// \brief Declares aspects of the compilation that persist across multiple | 11 /// \brief Declares aspects of the compilation that persist across multiple |
12 /// functions. | 12 /// functions. |
13 /// | 13 /// |
14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
15 | 15 |
16 #ifndef SUBZERO_SRC_ICEGLOBALCONTEXT_H | 16 #ifndef SUBZERO_SRC_ICEGLOBALCONTEXT_H |
17 #define SUBZERO_SRC_ICEGLOBALCONTEXT_H | 17 #define SUBZERO_SRC_ICEGLOBALCONTEXT_H |
18 | 18 |
19 #include "IceDefs.h" | 19 #include "IceDefs.h" |
20 #include "IceClFlags.h" | 20 #include "IceClFlags.h" |
21 #include "IceIntrinsics.h" | 21 #include "IceIntrinsics.h" |
22 #include "IceRNG.h" | 22 #include "IceRNG.h" |
| 23 #include "IceStringPool.h" |
23 #include "IceSwitchLowering.h" | 24 #include "IceSwitchLowering.h" |
24 #include "IceTargetLowering.def" | 25 #include "IceTargetLowering.def" |
25 #include "IceThreading.h" | 26 #include "IceThreading.h" |
26 #include "IceTimerTree.h" | 27 #include "IceTimerTree.h" |
27 #include "IceTypes.h" | 28 #include "IceTypes.h" |
28 #include "IceUtils.h" | 29 #include "IceUtils.h" |
29 | 30 |
30 #include <array> | 31 #include <array> |
31 #include <cassert> | 32 #include <cassert> |
32 #include <functional> | 33 #include <functional> |
(...skipping 13 matching lines...) Expand all Loading... |
46 | 47 |
47 // Runtime helper function IDs | 48 // Runtime helper function IDs |
48 | 49 |
49 enum class RuntimeHelper { | 50 enum class RuntimeHelper { |
50 #define X(Tag, Name) H_##Tag, | 51 #define X(Tag, Name) H_##Tag, |
51 RUNTIME_HELPER_FUNCTIONS_TABLE | 52 RUNTIME_HELPER_FUNCTIONS_TABLE |
52 #undef X | 53 #undef X |
53 H_Num | 54 H_Num |
54 }; | 55 }; |
55 | 56 |
56 /// LockedPtr is a way to provide automatically locked access to some object. | |
57 template <typename T> class LockedPtr { | |
58 LockedPtr() = delete; | |
59 LockedPtr(const LockedPtr &) = delete; | |
60 LockedPtr &operator=(const LockedPtr &) = delete; | |
61 | |
62 public: | |
63 LockedPtr(T *Value, GlobalLockType *Lock) : Value(Value), Lock(Lock) { | |
64 Lock->lock(); | |
65 } | |
66 LockedPtr(LockedPtr &&Other) : Value(Other.Value), Lock(Other.Lock) { | |
67 Other.Value = nullptr; | |
68 Other.Lock = nullptr; | |
69 } | |
70 ~LockedPtr() { Lock->unlock(); } | |
71 T *operator->() const { return Value; } | |
72 T &operator*() const { return *Value; } | |
73 T *get() { return Value; } | |
74 | |
75 private: | |
76 T *Value; | |
77 GlobalLockType *Lock; | |
78 }; | |
79 | |
80 class GlobalContext { | 57 class GlobalContext { |
81 GlobalContext() = delete; | 58 GlobalContext() = delete; |
82 GlobalContext(const GlobalContext &) = delete; | 59 GlobalContext(const GlobalContext &) = delete; |
83 GlobalContext &operator=(const GlobalContext &) = delete; | 60 GlobalContext &operator=(const GlobalContext &) = delete; |
84 | 61 |
85 /// CodeStats collects rudimentary statistics during translation. | 62 /// CodeStats collects rudimentary statistics during translation. |
86 class CodeStats { | 63 class CodeStats { |
87 CodeStats(const CodeStats &) = delete; | 64 CodeStats(const CodeStats &) = delete; |
88 CodeStats &operator=(const CodeStats &) = default; | 65 CodeStats &operator=(const CodeStats &) = default; |
89 #define CODESTATS_TABLE \ | 66 #define CODESTATS_TABLE \ |
(...skipping 16 matching lines...) Expand all Loading... |
106 CodeStats() { reset(); } | 83 CodeStats() { reset(); } |
107 void reset() { Stats.fill(0); } | 84 void reset() { Stats.fill(0); } |
108 void update(CSTag Tag, uint32_t Count = 1) { | 85 void update(CSTag Tag, uint32_t Count = 1) { |
109 assert(Tag < Stats.size()); | 86 assert(Tag < Stats.size()); |
110 Stats[Tag] += Count; | 87 Stats[Tag] += Count; |
111 } | 88 } |
112 void add(const CodeStats &Other) { | 89 void add(const CodeStats &Other) { |
113 for (uint32_t i = 0; i < Stats.size(); ++i) | 90 for (uint32_t i = 0; i < Stats.size(); ++i) |
114 Stats[i] += Other.Stats[i]; | 91 Stats[i] += Other.Stats[i]; |
115 } | 92 } |
116 void dump(const IceString &Name, GlobalContext *Ctx); | 93 void dump(const std::string &Name, GlobalContext *Ctx); |
117 | 94 |
118 private: | 95 private: |
119 std::array<uint32_t, CS_NUM> Stats; | 96 std::array<uint32_t, CS_NUM> Stats; |
120 }; | 97 }; |
121 | 98 |
122 /// TimerList is a vector of TimerStack objects, with extra methods | 99 /// TimerList is a vector of TimerStack objects, with extra methods |
123 /// to initialize and merge these vectors. | 100 /// to initialize and merge these vectors. |
124 class TimerList : public std::vector<TimerStack> { | 101 class TimerList : public std::vector<TimerStack> { |
125 TimerList(const TimerList &) = delete; | 102 TimerList(const TimerList &) = delete; |
126 TimerList &operator=(const TimerList &) = delete; | 103 TimerList &operator=(const TimerList &) = delete; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 TimerList Timers; | 142 TimerList Timers; |
166 }; | 143 }; |
167 | 144 |
168 public: | 145 public: |
169 /// The dump stream is a log stream while emit is the stream code | 146 /// The dump stream is a log stream while emit is the stream code |
170 /// is emitted to. The error stream is strictly for logging errors. | 147 /// is emitted to. The error stream is strictly for logging errors. |
171 GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError, | 148 GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError, |
172 ELFStreamer *ELFStreamer); | 149 ELFStreamer *ELFStreamer); |
173 ~GlobalContext(); | 150 ~GlobalContext(); |
174 | 151 |
| 152 void dumpStrings(); |
175 /// | 153 /// |
176 /// The dump, error, and emit streams need to be used by only one | 154 /// The dump, error, and emit streams need to be used by only one |
177 /// thread at a time. This is done by exclusively reserving the | 155 /// thread at a time. This is done by exclusively reserving the |
178 /// streams via lockStr() and unlockStr(). The OstreamLocker class | 156 /// streams via lockStr() and unlockStr(). The OstreamLocker class |
179 /// can be used to conveniently manage this. | 157 /// can be used to conveniently manage this. |
180 /// | 158 /// |
181 /// The model is that a thread grabs the stream lock, then does an | 159 /// The model is that a thread grabs the stream lock, then does an |
182 /// arbitrary amount of work during which far-away callees may grab | 160 /// arbitrary amount of work during which far-away callees may grab |
183 /// the stream and do something with it, and finally the thread | 161 /// the stream and do something with it, and finally the thread |
184 /// releases the stream lock. This allows large chunks of output to | 162 /// releases the stream lock. This allows large chunks of output to |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 switch (ConstantInt64) { | 218 switch (ConstantInt64) { |
241 case 0: | 219 case 0: |
242 return getConstantZero(IceType_i64); | 220 return getConstantZero(IceType_i64); |
243 default: | 221 default: |
244 return getConstantInt64Internal(ConstantInt64); | 222 return getConstantInt64Internal(ConstantInt64); |
245 } | 223 } |
246 } | 224 } |
247 Constant *getConstantFloat(float Value); | 225 Constant *getConstantFloat(float Value); |
248 Constant *getConstantDouble(double Value); | 226 Constant *getConstantDouble(double Value); |
249 /// Returns a symbolic constant. | 227 /// Returns a symbolic constant. |
250 Constant *getConstantSym(const RelocOffsetT Offset, | 228 Constant *getConstantSymWithEmitString(const RelocOffsetT Offset, |
251 const RelocOffsetArray &OffsetExpr, | 229 const RelocOffsetArray &OffsetExpr, |
252 const IceString &Name, const IceString &EmitString); | 230 GlobalString Name, |
253 Constant *getConstantSym(RelocOffsetT Offset, const IceString &Name); | 231 const std::string &EmitString); |
254 Constant *getConstantExternSym(const IceString &Name); | 232 Constant *getConstantSym(RelocOffsetT Offset, GlobalString Name); |
| 233 Constant *getConstantExternSym(GlobalString Name); |
255 /// Returns an undef. | 234 /// Returns an undef. |
256 Constant *getConstantUndef(Type Ty); | 235 Constant *getConstantUndef(Type Ty); |
257 /// Returns a zero value. | 236 /// Returns a zero value. |
258 Constant *getConstantZero(Type Ty); | 237 Constant *getConstantZero(Type Ty); |
259 /// getConstantPool() returns a copy of the constant pool for constants of a | 238 /// getConstantPool() returns a copy of the constant pool for constants of a |
260 /// given type. | 239 /// given type. |
261 ConstantList getConstantPool(Type Ty); | 240 ConstantList getConstantPool(Type Ty); |
262 /// Returns a copy of the list of external symbols. | 241 /// Returns a copy of the list of external symbols. |
263 ConstantList getConstantExternSyms(); | 242 ConstantList getConstantExternSyms(); |
264 /// @} | 243 /// @} |
265 Constant *getRuntimeHelperFunc(RuntimeHelper FuncID) const { | 244 Constant *getRuntimeHelperFunc(RuntimeHelper FuncID) const { |
266 assert(FuncID < RuntimeHelper::H_Num); | 245 assert(FuncID < RuntimeHelper::H_Num); |
267 Constant *Result = RuntimeHelperFunc[static_cast<size_t>(FuncID)]; | 246 Constant *Result = RuntimeHelperFunc[static_cast<size_t>(FuncID)]; |
268 assert(Result != nullptr && "No such runtime helper function"); | 247 assert(Result != nullptr && "No such runtime helper function"); |
269 return Result; | 248 return Result; |
270 } | 249 } |
| 250 GlobalString getGlobalString(const std::string &Name); |
271 | 251 |
272 /// Return a locked pointer to the registered jump tables. | 252 /// Return a locked pointer to the registered jump tables. |
273 JumpTableDataList getJumpTables(); | 253 JumpTableDataList getJumpTables(); |
274 /// Create a new jump table entry and return a reference to it. | 254 /// Create a new jump table entry and return a reference to it. |
275 JumpTableData &addJumpTable(const IceString &FuncName, SizeT Id, | 255 JumpTableData &addJumpTable(GlobalString FuncName, SizeT Id, |
276 const JumpTableData::TargetList &TargetList); | 256 const JumpTableData::TargetList &TargetList); |
277 | 257 |
278 static const ClFlags &getFlags() { return Flags; } | 258 static const ClFlags &getFlags() { return Flags; } |
279 | 259 |
280 /// Allocate data of type T using the global allocator. We allow entities | 260 /// Allocate data of type T using the global allocator. We allow entities |
281 /// allocated from this global allocator to be either trivially or | 261 /// allocated from this global allocator to be either trivially or |
282 /// non-trivially destructible. We optimize the case when T is trivially | 262 /// non-trivially destructible. We optimize the case when T is trivially |
283 /// destructible by not registering a destructor. Destructors will be invoked | 263 /// destructible by not registering a destructor. Destructors will be invoked |
284 /// during GlobalContext destruction in the reverse object creation order. | 264 /// during GlobalContext destruction in the reverse object creation order. |
285 template <typename T> | 265 template <typename T> |
(...skipping 12 matching lines...) Expand all Loading... |
298 | 278 |
299 const Intrinsics &getIntrinsicsInfo() const { return IntrinsicsInfo; } | 279 const Intrinsics &getIntrinsicsInfo() const { return IntrinsicsInfo; } |
300 | 280 |
301 ELFObjectWriter *getObjectWriter() const { return ObjectWriter.get(); } | 281 ELFObjectWriter *getObjectWriter() const { return ObjectWriter.get(); } |
302 | 282 |
303 /// Reset stats at the beginning of a function. | 283 /// Reset stats at the beginning of a function. |
304 void resetStats() { | 284 void resetStats() { |
305 if (BuildDefs::dump()) | 285 if (BuildDefs::dump()) |
306 ICE_TLS_GET_FIELD(TLS)->StatsFunction.reset(); | 286 ICE_TLS_GET_FIELD(TLS)->StatsFunction.reset(); |
307 } | 287 } |
308 void dumpStats(const IceString &Name, bool Final = false); | 288 void dumpStats(const std::string &Name, bool Final = false); |
309 void statsUpdateEmitted(uint32_t InstCount) { | 289 void statsUpdateEmitted(uint32_t InstCount) { |
310 if (!getFlags().getDumpStats()) | 290 if (!getFlags().getDumpStats()) |
311 return; | 291 return; |
312 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS); | 292 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS); |
313 Tls->StatsFunction.update(CodeStats::CS_InstCount, InstCount); | 293 Tls->StatsFunction.update(CodeStats::CS_InstCount, InstCount); |
314 Tls->StatsCumulative.update(CodeStats::CS_InstCount, InstCount); | 294 Tls->StatsCumulative.update(CodeStats::CS_InstCount, InstCount); |
315 } | 295 } |
316 void statsUpdateRegistersSaved(uint32_t Num) { | 296 void statsUpdateRegistersSaved(uint32_t Num) { |
317 if (!getFlags().getDumpStats()) | 297 if (!getFlags().getDumpStats()) |
318 return; | 298 return; |
(...skipping 30 matching lines...) Expand all Loading... |
349 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS); | 329 ThreadContext *Tls = ICE_TLS_GET_FIELD(TLS); |
350 Tls->StatsFunction.update(CodeStats::CS_NumRPImms); | 330 Tls->StatsFunction.update(CodeStats::CS_NumRPImms); |
351 Tls->StatsCumulative.update(CodeStats::CS_NumRPImms); | 331 Tls->StatsCumulative.update(CodeStats::CS_NumRPImms); |
352 } | 332 } |
353 | 333 |
354 /// These are predefined TimerStackIdT values. | 334 /// These are predefined TimerStackIdT values. |
355 enum TimerStackKind { TSK_Default = 0, TSK_Funcs, TSK_Num }; | 335 enum TimerStackKind { TSK_Default = 0, TSK_Funcs, TSK_Num }; |
356 | 336 |
357 /// newTimerStackID() creates a new TimerStack in the global space. It does | 337 /// newTimerStackID() creates a new TimerStack in the global space. It does |
358 /// not affect any TimerStack objects in TLS. | 338 /// not affect any TimerStack objects in TLS. |
359 TimerStackIdT newTimerStackID(const IceString &Name); | 339 TimerStackIdT newTimerStackID(const std::string &Name); |
360 /// dumpTimers() dumps the global timer data. As such, one probably wants to | 340 /// dumpTimers() dumps the global timer data. As such, one probably wants to |
361 /// call mergeTimerStacks() as a prerequisite. | 341 /// call mergeTimerStacks() as a prerequisite. |
362 void dumpTimers(TimerStackIdT StackID = TSK_Default, | 342 void dumpTimers(TimerStackIdT StackID = TSK_Default, |
363 bool DumpCumulative = true); | 343 bool DumpCumulative = true); |
364 /// The following methods affect only the calling thread's TLS timer data. | 344 /// The following methods affect only the calling thread's TLS timer data. |
365 TimerIdT getTimerID(TimerStackIdT StackID, const IceString &Name); | 345 TimerIdT getTimerID(TimerStackIdT StackID, const std::string &Name); |
366 void pushTimer(TimerIdT ID, TimerStackIdT StackID); | 346 void pushTimer(TimerIdT ID, TimerStackIdT StackID); |
367 void popTimer(TimerIdT ID, TimerStackIdT StackID); | 347 void popTimer(TimerIdT ID, TimerStackIdT StackID); |
368 void resetTimer(TimerStackIdT StackID); | 348 void resetTimer(TimerStackIdT StackID); |
369 void setTimerName(TimerStackIdT StackID, const IceString &NewName); | 349 void setTimerName(TimerStackIdT StackID, const std::string &NewName); |
370 | 350 |
371 /// This is the first work item sequence number that the parser produces, and | 351 /// This is the first work item sequence number that the parser produces, and |
372 /// correspondingly the first sequence number that the emitter thread will | 352 /// 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. | 353 /// 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 | 354 /// we wish to inject items with a special sequence number that may be |
375 /// executed out of order. | 355 /// executed out of order. |
376 static uint32_t getFirstSequenceNumber() { return 1; } | 356 static constexpr uint32_t getFirstSequenceNumber() { return 1; } |
377 /// Adds a newly parsed and constructed function to the Cfg work queue. | 357 /// Adds a newly parsed and constructed function to the Cfg work queue. |
378 /// Notifies any idle workers that a new function is available for | 358 /// 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 | 359 /// translating. May block if the work queue is too large, in order to control |
380 /// memory footprint. | 360 /// memory footprint. |
381 void optQueueBlockingPush(std::unique_ptr<Cfg> Func); | 361 void optQueueBlockingPush(std::unique_ptr<Cfg> Func); |
382 /// Takes a Cfg from the work queue for translating. May block if the work | 362 /// 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 | 363 /// 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 | 364 /// queue is empty and either end() has been called or the Sequential flag was |
385 /// set. | 365 /// set. |
386 std::unique_ptr<Cfg> optQueueBlockingPop(); | 366 std::unique_ptr<Cfg> optQueueBlockingPop(); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 ICE_TLS_SET_FIELD(TLS, MyTLS); | 447 ICE_TLS_SET_FIELD(TLS, MyTLS); |
468 emitItems(); | 448 emitItems(); |
469 } | 449 } |
470 /// Emit functions and global initializers from the emitter queue until the | 450 /// Emit functions and global initializers from the emitter queue until the |
471 /// queue is empty. | 451 /// queue is empty. |
472 void emitItems(); | 452 void emitItems(); |
473 | 453 |
474 /// Uses DataLowering to lower Globals. Side effects: | 454 /// Uses DataLowering to lower Globals. Side effects: |
475 /// - discards the initializer list for the global variable in Globals. | 455 /// - discards the initializer list for the global variable in Globals. |
476 /// - clears the Globals array. | 456 /// - clears the Globals array. |
477 void lowerGlobals(const IceString &SectionSuffix); | 457 void lowerGlobals(const std::string &SectionSuffix); |
478 | 458 |
479 /// Lowers the profile information. | 459 /// Lowers the profile information. |
480 void lowerProfileData(); | 460 void lowerProfileData(); |
481 | 461 |
482 void dumpConstantLookupCounts(); | 462 void dumpConstantLookupCounts(); |
483 | 463 |
484 /// Utility function to match a symbol name against a match string. This is | 464 /// Utility function to match a symbol name against a match string. This is |
485 /// used in a few cases where we want to take some action on a particular | 465 /// used in a few cases where we want to take some action on a particular |
486 /// function or symbol based on a command-line argument, such as changing the | 466 /// function or symbol based on a command-line argument, such as changing the |
487 /// verbose level for a particular function. An empty Match argument means | 467 /// verbose level for a particular function. An empty Match argument means |
488 /// match everything. Returns true if there is a match. | 468 /// match everything. Returns true if there is a match. |
489 static bool matchSymbolName(const IceString &SymbolName, | 469 static bool matchSymbolName(const GlobalString &SymbolName, |
490 const IceString &Match) { | 470 const std::string &Match); |
491 return Match.empty() || Match == SymbolName; | |
492 } | |
493 | 471 |
494 static ClFlags Flags; | 472 static ClFlags Flags; |
495 | 473 |
496 /// DisposeGlobalVariablesAfterLowering controls whether the memory used by | 474 /// DisposeGlobalVariablesAfterLowering controls whether the memory used by |
497 /// GlobaleVariables can be reclaimed right after they have been lowered. | 475 /// GlobaleVariables can be reclaimed right after they have been lowered. |
498 /// @{ | 476 /// @{ |
499 bool getDisposeGlobalVariablesAfterLowering() const { | 477 bool getDisposeGlobalVariablesAfterLowering() const { |
500 return DisposeGlobalVariablesAfterLowering; | 478 return DisposeGlobalVariablesAfterLowering; |
501 } | 479 } |
502 | 480 |
503 void setDisposeGlobalVariablesAfterLowering(bool Value) { | 481 void setDisposeGlobalVariablesAfterLowering(bool Value) { |
504 DisposeGlobalVariablesAfterLowering = Value; | 482 DisposeGlobalVariablesAfterLowering = Value; |
505 } | 483 } |
506 /// @} | 484 /// @} |
507 | 485 |
| 486 LockedPtr<StringPool> getStrings() const { |
| 487 return LockedPtr<StringPool>(Strings.get(), &StringsLock); |
| 488 } |
| 489 |
508 private: | 490 private: |
509 // Try to ensure mutexes are allocated on separate cache lines. | 491 // Try to ensure mutexes are allocated on separate cache lines. |
510 | 492 |
511 // Destructors collaborate with Allocator | 493 // Destructors collaborate with Allocator |
512 ICE_CACHELINE_BOUNDARY; | 494 ICE_CACHELINE_BOUNDARY; |
513 // Managed by getAllocator() | 495 // Managed by getAllocator() |
514 GlobalLockType AllocLock; | 496 mutable GlobalLockType AllocLock; |
515 ArenaAllocator Allocator; | 497 ArenaAllocator Allocator; |
516 | 498 |
517 ICE_CACHELINE_BOUNDARY; | 499 ICE_CACHELINE_BOUNDARY; |
518 // Managed by getInitializerAllocator() | 500 // Managed by getInitializerAllocator() |
519 GlobalLockType InitAllocLock; | 501 mutable GlobalLockType InitAllocLock; |
520 VariableDeclarationList Globals; | 502 VariableDeclarationList Globals; |
521 | 503 |
522 ICE_CACHELINE_BOUNDARY; | 504 ICE_CACHELINE_BOUNDARY; |
523 // Managed by getDestructors() | 505 // Managed by getDestructors() |
524 using DestructorArray = std::vector<std::function<void()>>; | 506 using DestructorArray = std::vector<std::function<void()>>; |
525 GlobalLockType DestructorsLock; | 507 mutable GlobalLockType DestructorsLock; |
526 DestructorArray Destructors; | 508 DestructorArray Destructors; |
527 | 509 |
528 ICE_CACHELINE_BOUNDARY; | 510 ICE_CACHELINE_BOUNDARY; |
529 // Managed by getConstantPool() | 511 // Managed by getStrings() |
530 GlobalLockType ConstPoolLock; | 512 mutable GlobalLockType StringsLock; |
| 513 std::unique_ptr<StringPool> Strings; |
| 514 |
| 515 ICE_CACHELINE_BOUNDARY; |
| 516 // Managed by getConstPool() |
| 517 mutable GlobalLockType ConstPoolLock; |
531 std::unique_ptr<ConstantPool> ConstPool; | 518 std::unique_ptr<ConstantPool> ConstPool; |
532 | 519 |
533 ICE_CACHELINE_BOUNDARY; | 520 ICE_CACHELINE_BOUNDARY; |
534 // Managed by getJumpTableList() | 521 // Managed by getJumpTableList() |
535 GlobalLockType JumpTablesLock; | 522 mutable GlobalLockType JumpTablesLock; |
536 JumpTableDataList JumpTableList; | 523 JumpTableDataList JumpTableList; |
537 | 524 |
538 ICE_CACHELINE_BOUNDARY; | 525 ICE_CACHELINE_BOUNDARY; |
539 // Managed by getErrorStatus() | 526 // Managed by getErrorStatus() |
540 GlobalLockType ErrorStatusLock; | 527 mutable GlobalLockType ErrorStatusLock; |
541 ErrorCode ErrorStatus; | 528 ErrorCode ErrorStatus; |
542 | 529 |
543 ICE_CACHELINE_BOUNDARY; | 530 ICE_CACHELINE_BOUNDARY; |
544 // Managed by getStatsCumulative() | 531 // Managed by getStatsCumulative() |
545 GlobalLockType StatsLock; | 532 mutable GlobalLockType StatsLock; |
546 CodeStats StatsCumulative; | 533 CodeStats StatsCumulative; |
547 | 534 |
548 ICE_CACHELINE_BOUNDARY; | 535 ICE_CACHELINE_BOUNDARY; |
549 // Managed by getTimers() | 536 // Managed by getTimers() |
550 GlobalLockType TimerLock; | 537 mutable GlobalLockType TimerLock; |
551 TimerList Timers; | 538 TimerList Timers; |
552 | 539 |
553 ICE_CACHELINE_BOUNDARY; | 540 ICE_CACHELINE_BOUNDARY; |
554 /// StrLock is a global lock on the dump and emit output streams. | 541 /// StrLock is a global lock on the dump and emit output streams. |
555 using StrLockType = std::mutex; | 542 using StrLockType = std::mutex; |
556 StrLockType StrLock; | 543 StrLockType StrLock; |
557 Ostream *StrDump; /// Stream for dumping / diagnostics | 544 Ostream *StrDump; /// Stream for dumping / diagnostics |
558 Ostream *StrEmit; /// Stream for code emission | 545 Ostream *StrEmit; /// Stream for code emission |
559 Ostream *StrError; /// Stream for logging errors. | 546 Ostream *StrError; /// Stream for logging errors. |
560 | 547 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 if (BuildDefs::timers()) | 643 if (BuildDefs::timers()) |
657 push(); | 644 push(); |
658 } | 645 } |
659 TimerMarker(TimerIdT ID, const Cfg *Func, | 646 TimerMarker(TimerIdT ID, const Cfg *Func, |
660 TimerStackIdT StackID = GlobalContext::TSK_Default) | 647 TimerStackIdT StackID = GlobalContext::TSK_Default) |
661 : ID(ID), Ctx(nullptr), StackID(StackID) { | 648 : ID(ID), Ctx(nullptr), StackID(StackID) { |
662 // Ctx gets set at the beginning of pushCfg(). | 649 // Ctx gets set at the beginning of pushCfg(). |
663 if (BuildDefs::timers()) | 650 if (BuildDefs::timers()) |
664 pushCfg(Func); | 651 pushCfg(Func); |
665 } | 652 } |
666 TimerMarker(GlobalContext *Ctx, const IceString &FuncName) | 653 TimerMarker(GlobalContext *Ctx, const std::string &FuncName) |
667 : ID(getTimerIdFromFuncName(Ctx, FuncName)), Ctx(Ctx), | 654 : ID(getTimerIdFromFuncName(Ctx, FuncName)), Ctx(Ctx), |
668 StackID(GlobalContext::TSK_Funcs) { | 655 StackID(GlobalContext::TSK_Funcs) { |
669 if (BuildDefs::timers()) | 656 if (BuildDefs::timers()) |
670 push(); | 657 push(); |
671 } | 658 } |
672 | 659 |
673 ~TimerMarker() { | 660 ~TimerMarker() { |
674 if (BuildDefs::timers() && Active) | 661 if (BuildDefs::timers() && Active) |
675 Ctx->popTimer(ID, StackID); | 662 Ctx->popTimer(ID, StackID); |
676 } | 663 } |
677 | 664 |
678 private: | 665 private: |
679 void push(); | 666 void push(); |
680 void pushCfg(const Cfg *Func); | 667 void pushCfg(const Cfg *Func); |
681 static TimerIdT getTimerIdFromFuncName(GlobalContext *Ctx, | 668 static TimerIdT getTimerIdFromFuncName(GlobalContext *Ctx, |
682 const IceString &FuncName); | 669 const std::string &FuncName); |
683 const TimerIdT ID; | 670 const TimerIdT ID; |
684 GlobalContext *Ctx; | 671 GlobalContext *Ctx; |
685 const TimerStackIdT StackID; | 672 const TimerStackIdT StackID; |
686 bool Active = false; | 673 bool Active = false; |
687 }; | 674 }; |
688 | 675 |
689 /// Helper class for locking the streams and then automatically unlocking them. | 676 /// Helper class for locking the streams and then automatically unlocking them. |
690 class OstreamLocker { | 677 class OstreamLocker { |
691 private: | 678 private: |
692 OstreamLocker() = delete; | 679 OstreamLocker() = delete; |
693 OstreamLocker(const OstreamLocker &) = delete; | 680 OstreamLocker(const OstreamLocker &) = delete; |
694 OstreamLocker &operator=(const OstreamLocker &) = delete; | 681 OstreamLocker &operator=(const OstreamLocker &) = delete; |
695 | 682 |
696 public: | 683 public: |
697 explicit OstreamLocker(GlobalContext *Ctx) : Ctx(Ctx) { Ctx->lockStr(); } | 684 explicit OstreamLocker(GlobalContext *Ctx) : Ctx(Ctx) { Ctx->lockStr(); } |
698 ~OstreamLocker() { Ctx->unlockStr(); } | 685 ~OstreamLocker() { Ctx->unlockStr(); } |
699 | 686 |
700 private: | 687 private: |
701 GlobalContext *const Ctx; | 688 GlobalContext *const Ctx; |
702 }; | 689 }; |
703 | 690 |
704 } // end of namespace Ice | 691 } // end of namespace Ice |
705 | 692 |
706 #endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H | 693 #endif // SUBZERO_SRC_ICEGLOBALCONTEXT_H |
OLD | NEW |