blob: 2d0d77af78a2139ba62c52bbade549adf7f22f7c [file] [log] [blame]
Andreas Gampee21dc3d2014-12-08 16:59:43 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_UTILS_SWAP_SPACE_H_
18#define ART_COMPILER_UTILS_SWAP_SPACE_H_
19
20#include <cstdlib>
21#include <list>
22#include <set>
23#include <stdint.h>
24#include <stddef.h>
25
26#include "base/logging.h"
27#include "base/macros.h"
28#include "base/mutex.h"
29#include "mem_map.h"
30#include "utils.h"
31#include "utils/debug_stack.h"
32
33namespace art {
34
35// Chunk of space.
36struct SpaceChunk {
37 uint8_t* ptr;
38 size_t size;
39
40 uintptr_t Start() const {
41 return reinterpret_cast<uintptr_t>(ptr);
42 }
43 uintptr_t End() const {
44 return reinterpret_cast<uintptr_t>(ptr) + size;
45 }
46};
47
48inline bool operator==(const SpaceChunk& lhs, const SpaceChunk& rhs) {
49 return (lhs.size == rhs.size) && (lhs.ptr == rhs.ptr);
50}
51
52class SortChunkByPtr {
53 public:
54 bool operator()(const SpaceChunk& a, const SpaceChunk& b) const {
55 return reinterpret_cast<uintptr_t>(a.ptr) < reinterpret_cast<uintptr_t>(b.ptr);
56 }
57};
58
59// An arena pool that creates arenas backed by an mmaped file.
60class SwapSpace {
61 public:
62 SwapSpace(int fd, size_t initial_size);
63 ~SwapSpace();
64 void* Alloc(size_t size) LOCKS_EXCLUDED(lock_);
65 void Free(void* ptr, size_t size) LOCKS_EXCLUDED(lock_);
66
67 size_t GetSize() {
68 return size_;
69 }
70
71 private:
72 SpaceChunk NewFileChunk(size_t min_size);
73
74 int fd_;
75 size_t size_;
76 std::list<SpaceChunk> maps_;
77
78 // NOTE: Boost.Bimap would be useful for the two following members.
79
80 // Map start of a free chunk to its size.
81 typedef std::set<SpaceChunk, SortChunkByPtr> FreeByStartSet;
82 FreeByStartSet free_by_start_ GUARDED_BY(lock_);
83
84 // Map size to an iterator to free_by_start_'s entry.
85 typedef std::pair<size_t, FreeByStartSet::const_iterator> FreeBySizeEntry;
86 struct FreeBySizeComparator {
87 bool operator()(const FreeBySizeEntry& lhs, const FreeBySizeEntry& rhs) {
88 if (lhs.first != rhs.first) {
89 return lhs.first < rhs.first;
90 } else {
91 return lhs.second->Start() < rhs.second->Start();
92 }
93 }
94 };
95 typedef std::set<FreeBySizeEntry, FreeBySizeComparator> FreeBySizeSet;
96 FreeBySizeSet free_by_size_ GUARDED_BY(lock_);
97
98 mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
99 DISALLOW_COPY_AND_ASSIGN(SwapSpace);
100};
101
102template <typename T> class SwapAllocator;
103
104template <>
105class SwapAllocator<void> {
106 public:
107 typedef void value_type;
108 typedef void* pointer;
109 typedef const void* const_pointer;
110
111 template <typename U>
112 struct rebind {
113 typedef SwapAllocator<U> other;
114 };
115
116 explicit SwapAllocator(SwapSpace* swap_space) : swap_space_(swap_space) {}
117
118 template <typename U>
119 SwapAllocator(const SwapAllocator<U>& other) : swap_space_(other.swap_space_) {}
120
121 SwapAllocator(const SwapAllocator& other) = default;
122 SwapAllocator& operator=(const SwapAllocator& other) = default;
123 ~SwapAllocator() = default;
124
125 private:
126 SwapSpace* swap_space_;
127
128 template <typename U>
129 friend class SwapAllocator;
130};
131
132template <typename T>
133class SwapAllocator {
134 public:
135 typedef T value_type;
136 typedef T* pointer;
137 typedef T& reference;
138 typedef const T* const_pointer;
139 typedef const T& const_reference;
140 typedef size_t size_type;
141 typedef ptrdiff_t difference_type;
142
143 template <typename U>
144 struct rebind {
145 typedef SwapAllocator<U> other;
146 };
147
148 explicit SwapAllocator(SwapSpace* swap_space) : swap_space_(swap_space) {}
149
150 template <typename U>
151 SwapAllocator(const SwapAllocator<U>& other) : swap_space_(other.swap_space_) {}
152
153 SwapAllocator(const SwapAllocator& other) = default;
154 SwapAllocator& operator=(const SwapAllocator& other) = default;
155 ~SwapAllocator() = default;
156
157 size_type max_size() const {
158 return static_cast<size_type>(-1) / sizeof(T);
159 }
160
161 pointer address(reference x) const { return &x; }
162 const_pointer address(const_reference x) const { return &x; }
163
164 pointer allocate(size_type n, SwapAllocator<void>::pointer hint ATTRIBUTE_UNUSED = nullptr) {
165 DCHECK_LE(n, max_size());
166 if (swap_space_ == nullptr) {
167 return reinterpret_cast<T*>(malloc(n * sizeof(T)));
168 } else {
169 return reinterpret_cast<T*>(swap_space_->Alloc(n * sizeof(T)));
170 }
171 }
172 void deallocate(pointer p, size_type n) {
173 if (swap_space_ == nullptr) {
174 free(p);
175 } else {
176 swap_space_->Free(p, n * sizeof(T));
177 }
178 }
179
180 void construct(pointer p, const_reference val) {
181 new (static_cast<void*>(p)) value_type(val);
182 }
183 template <class U, class... Args>
184 void construct(U* p, Args&&... args) {
185 ::new (static_cast<void*>(p)) U(std::forward<Args>(args)...);
186 }
187 void destroy(pointer p) {
188 p->~value_type();
189 }
190
191 inline bool operator==(SwapAllocator const& other) {
192 return swap_space_ == other.swap_space_;
193 }
194 inline bool operator!=(SwapAllocator const& other) {
195 return !operator==(other);
196 }
197
198 private:
199 SwapSpace* swap_space_;
200
201 template <typename U>
202 friend class SwapAllocator;
203};
204
205template <typename T>
206using SwapVector = std::vector<T, SwapAllocator<T>>;
207template <typename T, typename Comparator>
208using SwapSet = std::set<T, Comparator, SwapAllocator<T>>;
209
210} // namespace art
211
212#endif // ART_COMPILER_UTILS_SWAP_SPACE_H_