blob: fc19d7aaa74a92114ba6cd015281a2993c03f23b [file] [log] [blame]
John Portoe82b5602016-02-24 15:58:55 -08001//===- 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
26namespace Ice {
27
28class Cfg;
29class GlobalContext;
John Porto7bb9cab2016-04-01 05:43:09 -070030class Liveness;
John Portoe82b5602016-02-24 15:58:55 -080031
32using ArenaAllocator =
33 llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, /*SlabSize=*/1024 * 1024>;
34
35class LockedArenaAllocator {
36 LockedArenaAllocator() = delete;
37 LockedArenaAllocator(const LockedArenaAllocator &) = delete;
38 LockedArenaAllocator &operator=(const LockedArenaAllocator &) = delete;
39
40public:
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
49private:
50 ArenaAllocator *Alloc;
51 std::unique_lock<std::mutex> AutoLock;
52};
53
54template <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
John Porto7bb9cab2016-04-01 05:43:09 -070065 sz_allocator() : Current() {}
66 template <class U>
67 sz_allocator(const sz_allocator<U, Traits> &)
68 : Current() {}
John Portoe82b5602016-02-24 15:58:55 -080069
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) {
John Porto7bb9cab2016-04-01 05:43:09 -070078 assert(current() != nullptr);
John Portoe82b5602016-02-24 15:58:55 -080079 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 /// @{
John Porto7bb9cab2016-04-01 05:43:09 -070095 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 }
John Portoe82b5602016-02-24 15:58:55 -0800106 static void init() { Traits::init(); }
107 /// @}
John Porto7bb9cab2016-04-01 05:43:09 -0700108 typename Traits::allocator_type Current;
John Portoe82b5602016-02-24 15:58:55 -0800109};
110
111template <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
119template <typename T, typename U, typename Traits>
120inline bool operator==(const sz_allocator<T, Traits> &,
121 const sz_allocator<U, Traits> &) {
122 return true;
123}
124
125template <typename T, typename U, typename Traits>
126inline bool operator!=(const sz_allocator<T, Traits> &,
127 const sz_allocator<U, Traits> &) {
128 return false;
129}
130
131class CfgAllocatorTraits {
132 CfgAllocatorTraits() = delete;
133 CfgAllocatorTraits(const CfgAllocatorTraits &) = delete;
134 CfgAllocatorTraits &operator=(const CfgAllocatorTraits &) = delete;
135 ~CfgAllocatorTraits() = delete;
136
137public:
138 using allocator_type = ArenaAllocator *;
139 using manager_type = Cfg;
John Porto7bb9cab2016-04-01 05:43:09 -0700140 static constexpr bool cache_allocator = false;
John Portoe82b5602016-02-24 15:58:55 -0800141
Ben Clayton2a582382019-04-24 12:11:36 +0100142 static void init() { ICE_TLS_INIT_FIELD(CfgAllocator); }
John Portoe82b5602016-02-24 15:58:55 -0800143
144 static allocator_type current();
145 static void set_current(const manager_type *Manager);
Nicolas Capensa9a92a52016-09-06 12:59:58 -0400146 static void set_current(ArenaAllocator *Allocator);
Jim Stichnoth5d5b6622016-09-09 09:29:08 -0700147 static void set_current(std::nullptr_t);
John Portoe82b5602016-02-24 15:58:55 -0800148
149private:
150 ICE_TLS_DECLARE_FIELD(ArenaAllocator *, CfgAllocator);
151};
152
153template <typename T>
154using CfgLocalAllocator = sz_allocator<T, CfgAllocatorTraits>;
155
156using CfgLocalAllocatorScope = sz_allocator_scope<CfgAllocatorTraits>;
157
John Porto7bb9cab2016-04-01 05:43:09 -0700158class LivenessAllocatorTraits {
159 LivenessAllocatorTraits() = delete;
160 LivenessAllocatorTraits(const LivenessAllocatorTraits &) = delete;
161 LivenessAllocatorTraits &operator=(const LivenessAllocatorTraits &) = delete;
162 ~LivenessAllocatorTraits() = delete;
163
164public:
165 using allocator_type = ArenaAllocator *;
166 using manager_type = Liveness;
167 static constexpr bool cache_allocator = true;
168
Ben Clayton2a582382019-04-24 12:11:36 +0100169 static void init() { ICE_TLS_INIT_FIELD(LivenessAllocator); }
John Porto7bb9cab2016-04-01 05:43:09 -0700170
171 static allocator_type current();
172 static void set_current(const manager_type *Manager);
173
174private:
175 ICE_TLS_DECLARE_FIELD(ArenaAllocator *, LivenessAllocator);
176};
177
178template <typename T>
179using LivenessAllocator = sz_allocator<T, LivenessAllocatorTraits>;
180
181using LivenessAllocatorScope = sz_allocator_scope<LivenessAllocatorTraits>;
182
John Portoe82b5602016-02-24 15:58:55 -0800183} // end of namespace Ice
184
185#endif // SUBZERO_SRC_ICEMEMORY_H