1 //===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator tests ---===//
\r
3 // The LLVM Compiler Infrastructure
\r
5 // This file is distributed under the University of Illinois Open Source
\r
6 // License. See LICENSE.TXT for details.
\r
8 //===----------------------------------------------------------------------===//
\r
10 #include "llvm/Support/Memory.h"
\r
11 #include "llvm/Support/Process.h"
\r
13 #include "gtest/gtest.h"
\r
16 using namespace llvm;
\r
17 using namespace sys;
\r
21 class MappedMemoryTest : public ::testing::TestWithParam<unsigned> {
\r
23 MappedMemoryTest() {
\r
25 PageSize = sys::Process::GetPageSize();
\r
29 // Adds RW flags to permit testing of the resulting memory
\r
30 unsigned getTestableEquivalent(unsigned RequestedFlags) {
\r
31 switch (RequestedFlags) {
\r
32 case Memory::MF_READ:
\r
33 case Memory::MF_WRITE:
\r
34 case Memory::MF_READ|Memory::MF_WRITE:
\r
35 return Memory::MF_READ|Memory::MF_WRITE;
\r
36 case Memory::MF_READ|Memory::MF_EXEC:
\r
37 case Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC:
\r
38 case Memory::MF_EXEC:
\r
39 return Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC;
\r
41 // Default in case values are added to the enum, as required by some compilers
\r
42 return Memory::MF_READ|Memory::MF_WRITE;
\r
45 // Returns true if the memory blocks overlap
\r
46 bool doesOverlap(MemoryBlock M1, MemoryBlock M2) {
\r
47 if (M1.base() == M2.base())
\r
50 if (M1.base() > M2.base())
\r
51 return (unsigned char *)M2.base() + M2.size() > M1.base();
\r
53 return (unsigned char *)M1.base() + M1.size() > M2.base();
\r
60 TEST_P(MappedMemoryTest, AllocAndRelease) {
\r
62 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);
\r
63 EXPECT_EQ(error_code::success(), EC);
\r
65 EXPECT_NE((void*)0, M1.base());
\r
66 EXPECT_LE(sizeof(int), M1.size());
\r
68 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
\r
71 TEST_P(MappedMemoryTest, MultipleAllocAndRelease) {
\r
73 MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC);
\r
74 EXPECT_EQ(error_code::success(), EC);
\r
75 MemoryBlock M2 = Memory::allocateMappedMemory(64, 0, Flags, EC);
\r
76 EXPECT_EQ(error_code::success(), EC);
\r
77 MemoryBlock M3 = Memory::allocateMappedMemory(32, 0, Flags, EC);
\r
78 EXPECT_EQ(error_code::success(), EC);
\r
80 EXPECT_NE((void*)0, M1.base());
\r
81 EXPECT_LE(16U, M1.size());
\r
82 EXPECT_NE((void*)0, M2.base());
\r
83 EXPECT_LE(64U, M2.size());
\r
84 EXPECT_NE((void*)0, M3.base());
\r
85 EXPECT_LE(32U, M3.size());
\r
87 EXPECT_FALSE(doesOverlap(M1, M2));
\r
88 EXPECT_FALSE(doesOverlap(M2, M3));
\r
89 EXPECT_FALSE(doesOverlap(M1, M3));
\r
91 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
\r
92 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
\r
93 MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC);
\r
94 EXPECT_EQ(error_code::success(), EC);
\r
95 EXPECT_NE((void*)0, M4.base());
\r
96 EXPECT_LE(16U, M4.size());
\r
97 EXPECT_FALSE(Memory::releaseMappedMemory(M4));
\r
98 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
\r
101 TEST_P(MappedMemoryTest, BasicWrite) {
\r
102 // This test applies only to writeable combinations
\r
103 if (Flags && !(Flags & Memory::MF_WRITE))
\r
107 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);
\r
108 EXPECT_EQ(error_code::success(), EC);
\r
110 EXPECT_NE((void*)0, M1.base());
\r
111 EXPECT_LE(sizeof(int), M1.size());
\r
113 int *a = (int*)M1.base();
\r
117 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
\r
120 TEST_P(MappedMemoryTest, MultipleWrite) {
\r
121 // This test applies only to writeable combinations
\r
122 if (Flags && !(Flags & Memory::MF_WRITE))
\r
125 MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC);
\r
126 EXPECT_EQ(error_code::success(), EC);
\r
127 MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC);
\r
128 EXPECT_EQ(error_code::success(), EC);
\r
129 MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC);
\r
130 EXPECT_EQ(error_code::success(), EC);
\r
132 EXPECT_FALSE(doesOverlap(M1, M2));
\r
133 EXPECT_FALSE(doesOverlap(M2, M3));
\r
134 EXPECT_FALSE(doesOverlap(M1, M3));
\r
136 EXPECT_NE((void*)0, M1.base());
\r
137 EXPECT_LE(1U * sizeof(int), M1.size());
\r
138 EXPECT_NE((void*)0, M2.base());
\r
139 EXPECT_LE(8U * sizeof(int), M2.size());
\r
140 EXPECT_NE((void*)0, M3.base());
\r
141 EXPECT_LE(4U * sizeof(int), M3.size());
\r
143 int *x = (int*)M1.base();
\r
146 int *y = (int*)M2.base();
\r
147 for (int i = 0; i < 8; i++) {
\r
151 int *z = (int*)M3.base();
\r
155 EXPECT_EQ(7, y[7]);
\r
158 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
\r
159 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
\r
161 MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), 0, Flags, EC);
\r
162 EXPECT_EQ(error_code::success(), EC);
\r
163 EXPECT_NE((void*)0, M4.base());
\r
164 EXPECT_LE(64U * sizeof(int), M4.size());
\r
165 x = (int*)M4.base();
\r
168 EXPECT_FALSE(Memory::releaseMappedMemory(M4));
\r
170 // Verify that M2 remains unaffected by other activity
\r
171 for (int i = 0; i < 8; i++) {
\r
172 EXPECT_EQ(i, y[i]);
\r
174 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
\r
177 TEST_P(MappedMemoryTest, EnabledWrite) {
\r
179 MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), 0, Flags, EC);
\r
180 EXPECT_EQ(error_code::success(), EC);
\r
181 MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC);
\r
182 EXPECT_EQ(error_code::success(), EC);
\r
183 MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC);
\r
184 EXPECT_EQ(error_code::success(), EC);
\r
186 EXPECT_NE((void*)0, M1.base());
\r
187 EXPECT_LE(2U * sizeof(int), M1.size());
\r
188 EXPECT_NE((void*)0, M2.base());
\r
189 EXPECT_LE(8U * sizeof(int), M2.size());
\r
190 EXPECT_NE((void*)0, M3.base());
\r
191 EXPECT_LE(4U * sizeof(int), M3.size());
\r
193 EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags)));
\r
194 EXPECT_FALSE(Memory::protectMappedMemory(M2, getTestableEquivalent(Flags)));
\r
195 EXPECT_FALSE(Memory::protectMappedMemory(M3, getTestableEquivalent(Flags)));
\r
197 EXPECT_FALSE(doesOverlap(M1, M2));
\r
198 EXPECT_FALSE(doesOverlap(M2, M3));
\r
199 EXPECT_FALSE(doesOverlap(M1, M3));
\r
201 int *x = (int*)M1.base();
\r
203 int *y = (int*)M2.base();
\r
204 for (unsigned int i = 0; i < 8; i++) {
\r
207 int *z = (int*)M3.base();
\r
211 EXPECT_EQ(7, y[7]);
\r
214 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
\r
215 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
\r
216 EXPECT_EQ(6, y[6]);
\r
218 MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC);
\r
219 EXPECT_EQ(error_code::success(), EC);
\r
220 EXPECT_NE((void*)0, M4.base());
\r
221 EXPECT_LE(16U, M4.size());
\r
222 EXPECT_EQ(error_code::success(), Memory::protectMappedMemory(M4, getTestableEquivalent(Flags)));
\r
223 x = (int*)M4.base();
\r
226 EXPECT_FALSE(Memory::releaseMappedMemory(M4));
\r
227 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
\r
230 TEST_P(MappedMemoryTest, SuccessiveNear) {
\r
232 MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC);
\r
233 EXPECT_EQ(error_code::success(), EC);
\r
234 MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC);
\r
235 EXPECT_EQ(error_code::success(), EC);
\r
236 MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC);
\r
237 EXPECT_EQ(error_code::success(), EC);
\r
239 EXPECT_NE((void*)0, M1.base());
\r
240 EXPECT_LE(16U, M1.size());
\r
241 EXPECT_NE((void*)0, M2.base());
\r
242 EXPECT_LE(64U, M2.size());
\r
243 EXPECT_NE((void*)0, M3.base());
\r
244 EXPECT_LE(32U, M3.size());
\r
246 EXPECT_FALSE(doesOverlap(M1, M2));
\r
247 EXPECT_FALSE(doesOverlap(M2, M3));
\r
248 EXPECT_FALSE(doesOverlap(M1, M3));
\r
250 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
\r
251 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
\r
252 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
\r
255 TEST_P(MappedMemoryTest, DuplicateNear) {
\r
257 MemoryBlock Near((void*)(3*PageSize), 16);
\r
258 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
\r
259 EXPECT_EQ(error_code::success(), EC);
\r
260 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
\r
261 EXPECT_EQ(error_code::success(), EC);
\r
262 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
\r
263 EXPECT_EQ(error_code::success(), EC);
\r
265 EXPECT_NE((void*)0, M1.base());
\r
266 EXPECT_LE(16U, M1.size());
\r
267 EXPECT_NE((void*)0, M2.base());
\r
268 EXPECT_LE(64U, M2.size());
\r
269 EXPECT_NE((void*)0, M3.base());
\r
270 EXPECT_LE(32U, M3.size());
\r
272 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
\r
273 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
\r
274 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
\r
277 TEST_P(MappedMemoryTest, ZeroNear) {
\r
279 MemoryBlock Near(0, 0);
\r
280 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
\r
281 EXPECT_EQ(error_code::success(), EC);
\r
282 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
\r
283 EXPECT_EQ(error_code::success(), EC);
\r
284 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
\r
285 EXPECT_EQ(error_code::success(), EC);
\r
287 EXPECT_NE((void*)0, M1.base());
\r
288 EXPECT_LE(16U, M1.size());
\r
289 EXPECT_NE((void*)0, M2.base());
\r
290 EXPECT_LE(64U, M2.size());
\r
291 EXPECT_NE((void*)0, M3.base());
\r
292 EXPECT_LE(32U, M3.size());
\r
294 EXPECT_FALSE(doesOverlap(M1, M2));
\r
295 EXPECT_FALSE(doesOverlap(M2, M3));
\r
296 EXPECT_FALSE(doesOverlap(M1, M3));
\r
298 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
\r
299 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
\r
300 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
\r
303 TEST_P(MappedMemoryTest, ZeroSizeNear) {
\r
305 MemoryBlock Near((void*)(4*PageSize), 0);
\r
306 MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
\r
307 EXPECT_EQ(error_code::success(), EC);
\r
308 MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
\r
309 EXPECT_EQ(error_code::success(), EC);
\r
310 MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
\r
311 EXPECT_EQ(error_code::success(), EC);
\r
313 EXPECT_NE((void*)0, M1.base());
\r
314 EXPECT_LE(16U, M1.size());
\r
315 EXPECT_NE((void*)0, M2.base());
\r
316 EXPECT_LE(64U, M2.size());
\r
317 EXPECT_NE((void*)0, M3.base());
\r
318 EXPECT_LE(32U, M3.size());
\r
320 EXPECT_FALSE(doesOverlap(M1, M2));
\r
321 EXPECT_FALSE(doesOverlap(M2, M3));
\r
322 EXPECT_FALSE(doesOverlap(M1, M3));
\r
324 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
\r
325 EXPECT_FALSE(Memory::releaseMappedMemory(M3));
\r
326 EXPECT_FALSE(Memory::releaseMappedMemory(M2));
\r
329 TEST_P(MappedMemoryTest, UnalignedNear) {
\r
331 MemoryBlock Near((void*)(2*PageSize+5), 0);
\r
332 MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC);
\r
333 EXPECT_EQ(error_code::success(), EC);
\r
335 EXPECT_NE((void*)0, M1.base());
\r
336 EXPECT_LE(sizeof(int), M1.size());
\r
338 EXPECT_FALSE(Memory::releaseMappedMemory(M1));
\r
341 // Note that Memory::MF_WRITE is not supported exclusively across
\r
342 // operating systems and architectures and can imply MF_READ|MF_WRITE
\r
343 unsigned MemoryFlags[] = {
\r
346 Memory::MF_READ|Memory::MF_WRITE,
\r
348 Memory::MF_READ|Memory::MF_EXEC,
\r
349 Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC
\r
352 INSTANTIATE_TEST_CASE_P(AllocationTests,
\r
354 ::testing::ValuesIn(MemoryFlags));
\r
356 } // anonymous namespace
\r