| Index: src/IceGlobalContext.h
|
| diff --git a/src/IceGlobalContext.h b/src/IceGlobalContext.h
|
| index ff8ff25ed256b1793a01632c4e32c5e7f95fd207..e8c1ba2723a6228494a2824be673992dca2fb84c 100644
|
| --- a/src/IceGlobalContext.h
|
| +++ b/src/IceGlobalContext.h
|
| @@ -16,8 +16,11 @@
|
| #define SUBZERO_SRC_ICEGLOBALCONTEXT_H
|
|
|
| #include <array>
|
| +#include <functional>
|
| #include <mutex>
|
| #include <thread>
|
| +#include <type_traits>
|
| +#include <vector>
|
|
|
| #include "IceDefs.h"
|
| #include "IceClFlags.h"
|
| @@ -210,8 +213,24 @@ public:
|
| return getFlags().getDisableIRGeneration();
|
| }
|
|
|
| - // Allocate data of type T using the global allocator.
|
| - template <typename T> T *allocate() { return getAllocator()->Allocate<T>(); }
|
| + // Allocate data of type T using the global allocator. We allow entities
|
| + // allocated from this global allocator to be either trivially or
|
| + // non-trivially destructible. We optimize the case when T is trivially
|
| + // destructible by not registering a destructor. Destructors will be invoked
|
| + // during GlobalContext destruction in the reverse object creation order.
|
| + template <typename T>
|
| + typename std::enable_if<std::is_trivially_destructible<T>::value, T>::type *
|
| + allocate() {
|
| + return getAllocator()->Allocate<T>();
|
| + }
|
| +
|
| + template <typename T>
|
| + typename std::enable_if<!std::is_trivially_destructible<T>::value, T>::type *
|
| + allocate() {
|
| + T *Ret = getAllocator()->Allocate<T>();
|
| + getDestructors()->emplace_back([Ret]() { Ret->~T(); });
|
| + return Ret;
|
| + }
|
|
|
| const Intrinsics &getIntrinsicsInfo() const { return IntrinsicsInfo; }
|
|
|
| @@ -382,8 +401,9 @@ public:
|
| // until the queue is empty.
|
| void emitItems();
|
|
|
| - // Uses DataLowering to lower Globals. As a side effect, clears the Globals
|
| - // array.
|
| + // Uses DataLowering to lower Globals. Side effects:
|
| + // - discards the initializer list for the global variable in Globals.
|
| + // - clears the Globals array.
|
| void lowerGlobals(const IceString &SectionSuffix);
|
|
|
| // Lowers the profile information.
|
| @@ -403,12 +423,19 @@ public:
|
| private:
|
| // Try to ensure mutexes are allocated on separate cache lines.
|
|
|
| + // Destructors collaborate with Allocator
|
| ICE_CACHELINE_BOUNDARY;
|
| // Managed by getAllocator()
|
| GlobalLockType AllocLock;
|
| ArenaAllocator<> Allocator;
|
|
|
| ICE_CACHELINE_BOUNDARY;
|
| + // Managed by getDestructors()
|
| + typedef std::vector<std::function<void()>> DestructorArray;
|
| + GlobalLockType DestructorsLock;
|
| + DestructorArray Destructors;
|
| +
|
| + ICE_CACHELINE_BOUNDARY;
|
| // Managed by getConstantPool()
|
| GlobalLockType ConstPoolLock;
|
| std::unique_ptr<ConstantPool> ConstPool;
|
| @@ -456,7 +483,7 @@ private:
|
| // TODO(jpp): move to EmitterContext.
|
| VariableDeclarationList Globals;
|
| // TODO(jpp): move to EmitterContext.
|
| - std::unique_ptr<VariableDeclaration> ProfileBlockInfoVarDecl;
|
| + VariableDeclaration *ProfileBlockInfoVarDecl;
|
|
|
| LockedPtr<ArenaAllocator<>> getAllocator() {
|
| return LockedPtr<ArenaAllocator<>>(&Allocator, &AllocLock);
|
| @@ -470,6 +497,9 @@ private:
|
| LockedPtr<TimerList> getTimers() {
|
| return LockedPtr<TimerList>(&Timers, &TimerLock);
|
| }
|
| + LockedPtr<DestructorArray> getDestructors() {
|
| + return LockedPtr<DestructorArray>(&Destructors, &DestructorsLock);
|
| + }
|
|
|
| void accumulateGlobals(std::unique_ptr<VariableDeclarationList> Globls) {
|
| if (Globls != nullptr)
|
|
|