Home | History | Annotate | Download | only in src
      1 //===- subzero/src/IceMemory.h - Memory management declarations -*- C++ -*-===//
      2 //
      3 //                        The Subzero Code Generator
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief Declares some useful data structures and routines dealing with
     12 /// memory management in Subzero (mostly, allocator types.)
     13 ///
     14 //===----------------------------------------------------------------------===//
     15 
     16 #ifndef SUBZERO_SRC_ICEMEMORY_H
     17 #define SUBZERO_SRC_ICEMEMORY_H
     18 
     19 #include "IceTLS.h"
     20 
     21 #include "llvm/Support/Allocator.h"
     22 
     23 #include <cstddef>
     24 #include <mutex>
     25 
     26 namespace Ice {
     27 
     28 class Cfg;
     29 class GlobalContext;
     30 class Liveness;
     31 
     32 using ArenaAllocator =
     33     llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, /*SlabSize=*/1024 * 1024>;
     34 
     35 class LockedArenaAllocator {
     36   LockedArenaAllocator() = delete;
     37   LockedArenaAllocator(const LockedArenaAllocator &) = delete;
     38   LockedArenaAllocator &operator=(const LockedArenaAllocator &) = delete;
     39 
     40 public:
     41   LockedArenaAllocator(ArenaAllocator *Alloc, std::mutex *Mutex)
     42       : Alloc(Alloc), AutoLock(*Mutex) {}
     43   LockedArenaAllocator(LockedArenaAllocator &&) = default;
     44   LockedArenaAllocator &operator=(LockedArenaAllocator &&) = default;
     45   ~LockedArenaAllocator() = default;
     46 
     47   ArenaAllocator *operator->() { return Alloc; }
     48 
     49 private:
     50   ArenaAllocator *Alloc;
     51   std::unique_lock<std::mutex> AutoLock;
     52 };
     53 
     54 template <typename T, typename Traits> struct sz_allocator {
     55   /// std::allocator interface implementation.
     56   /// @{
     57   using value_type = T;
     58   using pointer = T *;
     59   using const_pointer = const T *;
     60   using reference = T &;
     61   using const_reference = const T &;
     62   using size_type = std::size_t;
     63   using difference_type = std::ptrdiff_t;
     64 
     65   sz_allocator() : Current() {}
     66   template <class U>
     67   sz_allocator(const sz_allocator<U, Traits> &)
     68       : Current() {}
     69 
     70   pointer address(reference x) const {
     71     return reinterpret_cast<pointer>(&reinterpret_cast<char &>(x));
     72   }
     73   const_pointer address(const_reference x) const {
     74     return reinterpret_cast<const_pointer>(&reinterpret_cast<const char &>(x));
     75   }
     76 
     77   pointer allocate(size_type num) {
     78     assert(current() != nullptr);
     79     return current()->template Allocate<T>(num);
     80   }
     81 
     82   template <typename... A> void construct(pointer P, A &&... Args) {
     83     new (static_cast<void *>(P)) T(std::forward<A>(Args)...);
     84   }
     85 
     86   void deallocate(pointer, size_type) {}
     87 
     88   template <class U> struct rebind { typedef sz_allocator<U, Traits> other; };
     89 
     90   void destroy(pointer P) { P->~T(); }
     91   /// @}
     92 
     93   /// Manages the current underlying allocator.
     94   /// @{
     95   typename Traits::allocator_type current() {
     96     if (!Traits::cache_allocator) {
     97       // TODO(jpp): allocators should always be cacheable... maybe. Investigate.
     98       return Traits::current();
     99     }
    100     if (Current == nullptr) {
    101       Current = Traits::current();
    102     }
    103     assert(Current == Traits::current());
    104     return Current;
    105   }
    106   static void init() { Traits::init(); }
    107   /// @}
    108   typename Traits::allocator_type Current;
    109 };
    110 
    111 template <class Traits> struct sz_allocator_scope {
    112   explicit sz_allocator_scope(typename Traits::manager_type *Manager) {
    113     Traits::set_current(Manager);
    114   }
    115 
    116   ~sz_allocator_scope() { Traits::set_current(nullptr); }
    117 };
    118 
    119 template <typename T, typename U, typename Traits>
    120 inline bool operator==(const sz_allocator<T, Traits> &,
    121                        const sz_allocator<U, Traits> &) {
    122   return true;
    123 }
    124 
    125 template <typename T, typename U, typename Traits>
    126 inline bool operator!=(const sz_allocator<T, Traits> &,
    127                        const sz_allocator<U, Traits> &) {
    128   return false;
    129 }
    130 
    131 class CfgAllocatorTraits {
    132   CfgAllocatorTraits() = delete;
    133   CfgAllocatorTraits(const CfgAllocatorTraits &) = delete;
    134   CfgAllocatorTraits &operator=(const CfgAllocatorTraits &) = delete;
    135   ~CfgAllocatorTraits() = delete;
    136 
    137 public:
    138   using allocator_type = ArenaAllocator *;
    139   using manager_type = Cfg;
    140   static constexpr bool cache_allocator = false;
    141 
    142   static void init() { ICE_TLS_INIT_FIELD(CfgAllocator); };
    143 
    144   static allocator_type current();
    145   static void set_current(const manager_type *Manager);
    146   static void set_current(ArenaAllocator *Allocator);
    147   static void set_current(std::nullptr_t);
    148 
    149 private:
    150   ICE_TLS_DECLARE_FIELD(ArenaAllocator *, CfgAllocator);
    151 };
    152 
    153 template <typename T>
    154 using CfgLocalAllocator = sz_allocator<T, CfgAllocatorTraits>;
    155 
    156 using CfgLocalAllocatorScope = sz_allocator_scope<CfgAllocatorTraits>;
    157 
    158 class LivenessAllocatorTraits {
    159   LivenessAllocatorTraits() = delete;
    160   LivenessAllocatorTraits(const LivenessAllocatorTraits &) = delete;
    161   LivenessAllocatorTraits &operator=(const LivenessAllocatorTraits &) = delete;
    162   ~LivenessAllocatorTraits() = delete;
    163 
    164 public:
    165   using allocator_type = ArenaAllocator *;
    166   using manager_type = Liveness;
    167   static constexpr bool cache_allocator = true;
    168 
    169   static void init() { ICE_TLS_INIT_FIELD(LivenessAllocator); };
    170 
    171   static allocator_type current();
    172   static void set_current(const manager_type *Manager);
    173 
    174 private:
    175   ICE_TLS_DECLARE_FIELD(ArenaAllocator *, LivenessAllocator);
    176 };
    177 
    178 template <typename T>
    179 using LivenessAllocator = sz_allocator<T, LivenessAllocatorTraits>;
    180 
    181 using LivenessAllocatorScope = sz_allocator_scope<LivenessAllocatorTraits>;
    182 
    183 } // end of namespace Ice
    184 
    185 #endif // SUBZERO_SRC_ICEMEMORY_H
    186