|  | //===- 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 <cstddef> | 
|  | #include <mutex> | 
|  |  | 
|  | namespace Ice { | 
|  |  | 
|  | class Cfg; | 
|  | class GlobalContext; | 
|  | class Liveness; | 
|  |  | 
|  | using ArenaAllocator = | 
|  | llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, /*SlabSize=*/1024 * 1024>; | 
|  |  | 
|  | 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<std::mutex> AutoLock; | 
|  | }; | 
|  |  | 
|  | template <typename T, typename Traits> 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 <class U> | 
|  | sz_allocator(const sz_allocator<U, Traits> &) | 
|  | : Current() {} | 
|  |  | 
|  | pointer address(reference x) const { | 
|  | return reinterpret_cast<pointer>(&reinterpret_cast<char &>(x)); | 
|  | } | 
|  | const_pointer address(const_reference x) const { | 
|  | return reinterpret_cast<const_pointer>(&reinterpret_cast<const char &>(x)); | 
|  | } | 
|  |  | 
|  | pointer allocate(size_type num) { | 
|  | assert(current() != nullptr); | 
|  | return current()->template Allocate<T>(num); | 
|  | } | 
|  |  | 
|  | template <typename... A> void construct(pointer P, A &&... Args) { | 
|  | new (static_cast<void *>(P)) T(std::forward<A>(Args)...); | 
|  | } | 
|  |  | 
|  | void deallocate(pointer, size_type) {} | 
|  |  | 
|  | template <class U> struct rebind { typedef sz_allocator<U, Traits> 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 <class Traits> 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 <typename T, typename U, typename Traits> | 
|  | inline bool operator==(const sz_allocator<T, Traits> &, | 
|  | const sz_allocator<U, Traits> &) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | template <typename T, typename U, typename Traits> | 
|  | inline bool operator!=(const sz_allocator<T, Traits> &, | 
|  | const sz_allocator<U, Traits> &) { | 
|  | 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 <typename T> | 
|  | using CfgLocalAllocator = sz_allocator<T, CfgAllocatorTraits>; | 
|  |  | 
|  | using CfgLocalAllocatorScope = sz_allocator_scope<CfgAllocatorTraits>; | 
|  |  | 
|  | 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 <typename T> | 
|  | using LivenessAllocator = sz_allocator<T, LivenessAllocatorTraits>; | 
|  |  | 
|  | using LivenessAllocatorScope = sz_allocator_scope<LivenessAllocatorTraits>; | 
|  |  | 
|  | } // end of namespace Ice | 
|  |  | 
|  | #endif // SUBZERO_SRC_ICEMEMORY_H |