//===- subzero/src/IceMemory.h - Memory management declarations -*- C++ -*-===// // // The Subzero Code Generator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// \file /// \brief Declares some useful data structures and routines dealing with /// memory management in Subzero (mostly, allocator types.) /// //===----------------------------------------------------------------------===// #ifndef SUBZERO_SRC_ICEMEMORY_H #define SUBZERO_SRC_ICEMEMORY_H #include "IceTLS.h" #include "llvm/Support/Allocator.h" #include #include namespace Ice { class Cfg; class GlobalContext; class Liveness; using ArenaAllocator = llvm::BumpPtrAllocatorImpl; class LockedArenaAllocator { LockedArenaAllocator() = delete; LockedArenaAllocator(const LockedArenaAllocator &) = delete; LockedArenaAllocator &operator=(const LockedArenaAllocator &) = delete; public: LockedArenaAllocator(ArenaAllocator *Alloc, std::mutex *Mutex) : Alloc(Alloc), AutoLock(*Mutex) {} LockedArenaAllocator(LockedArenaAllocator &&) = default; LockedArenaAllocator &operator=(LockedArenaAllocator &&) = default; ~LockedArenaAllocator() = default; ArenaAllocator *operator->() { return Alloc; } private: ArenaAllocator *Alloc; std::unique_lock AutoLock; }; template struct sz_allocator { /// std::allocator interface implementation. /// @{ using value_type = T; using pointer = T *; using const_pointer = const T *; using reference = T &; using const_reference = const T &; using size_type = std::size_t; using difference_type = std::ptrdiff_t; sz_allocator() : Current() {} template sz_allocator(const sz_allocator &) : Current() {} pointer address(reference x) const { return reinterpret_cast(&reinterpret_cast(x)); } const_pointer address(const_reference x) const { return reinterpret_cast(&reinterpret_cast(x)); } pointer allocate(size_type num) { assert(current() != nullptr); return current()->template Allocate(num); } template void construct(pointer P, A &&... Args) { new (static_cast(P)) T(std::forward(Args)...); } void deallocate(pointer, size_type) {} template struct rebind { typedef sz_allocator other; }; void destroy(pointer P) { P->~T(); } /// @} /// Manages the current underlying allocator. /// @{ typename Traits::allocator_type current() { if (!Traits::cache_allocator) { // TODO(jpp): allocators should always be cacheable... maybe. Investigate. return Traits::current(); } if (Current == nullptr) { Current = Traits::current(); } assert(Current == Traits::current()); return Current; } static void init() { Traits::init(); } /// @} typename Traits::allocator_type Current; }; template struct sz_allocator_scope { explicit sz_allocator_scope(typename Traits::manager_type *Manager) { Traits::set_current(Manager); } ~sz_allocator_scope() { Traits::set_current(nullptr); } }; template inline bool operator==(const sz_allocator &, const sz_allocator &) { return true; } template inline bool operator!=(const sz_allocator &, const sz_allocator &) { return false; } class CfgAllocatorTraits { CfgAllocatorTraits() = delete; CfgAllocatorTraits(const CfgAllocatorTraits &) = delete; CfgAllocatorTraits &operator=(const CfgAllocatorTraits &) = delete; ~CfgAllocatorTraits() = delete; public: using allocator_type = ArenaAllocator *; using manager_type = Cfg; static constexpr bool cache_allocator = false; static void init() { ICE_TLS_INIT_FIELD(CfgAllocator); }; static allocator_type current(); static void set_current(const manager_type *Manager); static void set_current(ArenaAllocator *Allocator); static void set_current(std::nullptr_t); private: ICE_TLS_DECLARE_FIELD(ArenaAllocator *, CfgAllocator); }; template using CfgLocalAllocator = sz_allocator; using CfgLocalAllocatorScope = sz_allocator_scope; class LivenessAllocatorTraits { LivenessAllocatorTraits() = delete; LivenessAllocatorTraits(const LivenessAllocatorTraits &) = delete; LivenessAllocatorTraits &operator=(const LivenessAllocatorTraits &) = delete; ~LivenessAllocatorTraits() = delete; public: using allocator_type = ArenaAllocator *; using manager_type = Liveness; static constexpr bool cache_allocator = true; static void init() { ICE_TLS_INIT_FIELD(LivenessAllocator); }; static allocator_type current(); static void set_current(const manager_type *Manager); private: ICE_TLS_DECLARE_FIELD(ArenaAllocator *, LivenessAllocator); }; template using LivenessAllocator = sz_allocator; using LivenessAllocatorScope = sz_allocator_scope; } // end of namespace Ice #endif // SUBZERO_SRC_ICEMEMORY_H