OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 EXPECT_TRUE(ptr); | 93 EXPECT_TRUE(ptr); |
94 if (!i) | 94 if (!i) |
95 first = WTF::partitionCookieFreePointerAdjust(ptr); | 95 first = WTF::partitionCookieFreePointerAdjust(ptr); |
96 else if (i == numSlots - 1) | 96 else if (i == numSlots - 1) |
97 last = WTF::partitionCookieFreePointerAdjust(ptr); | 97 last = WTF::partitionCookieFreePointerAdjust(ptr); |
98 } | 98 } |
99 EXPECT_EQ(WTF::partitionPointerToPage(first), WTF::partitionPointerToPage(la
st)); | 99 EXPECT_EQ(WTF::partitionPointerToPage(first), WTF::partitionPointerToPage(la
st)); |
100 if (bucket->numSystemPagesPerSlotSpan == WTF::kNumSystemPagesPerPartitionPag
e) | 100 if (bucket->numSystemPagesPerSlotSpan == WTF::kNumSystemPagesPerPartitionPag
e) |
101 EXPECT_EQ(reinterpret_cast<size_t>(first) & WTF::kPartitionPageBaseMask,
reinterpret_cast<size_t>(last) & WTF::kPartitionPageBaseMask); | 101 EXPECT_EQ(reinterpret_cast<size_t>(first) & WTF::kPartitionPageBaseMask,
reinterpret_cast<size_t>(last) & WTF::kPartitionPageBaseMask); |
102 EXPECT_EQ(numSlots, static_cast<size_t>(bucket->activePagesHead->numAllocate
dSlots)); | 102 EXPECT_EQ(numSlots, static_cast<size_t>(bucket->activePagesHead->numAllocate
dSlots)); |
103 EXPECT_EQ(0, partitionPageFreelistHead(bucket->activePagesHead)); | 103 EXPECT_EQ(0, bucket->activePagesHead->freelistHead); |
104 EXPECT_TRUE(bucket->activePagesHead); | 104 EXPECT_TRUE(bucket->activePagesHead); |
105 EXPECT_TRUE(bucket->activePagesHead != &WTF::PartitionRootGeneric::gSeedPage
); | 105 EXPECT_TRUE(bucket->activePagesHead != &WTF::PartitionRootGeneric::gSeedPage
); |
106 return bucket->activePagesHead; | 106 return bucket->activePagesHead; |
107 } | 107 } |
108 | 108 |
109 static void FreeFullPage(WTF::PartitionPage* page) | 109 static void FreeFullPage(WTF::PartitionPage* page) |
110 { | 110 { |
111 size_t size = page->bucket->slotSize; | 111 size_t size = page->bucket->slotSize; |
112 size_t numSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPag
eSize) / size; | 112 size_t numSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPag
eSize) / size; |
113 EXPECT_EQ(numSlots, static_cast<size_t>(abs(page->numAllocatedSlots))); | 113 EXPECT_EQ(numSlots, static_cast<size_t>(abs(page->numAllocatedSlots))); |
114 char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page)); | 114 char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page)); |
115 size_t i; | 115 size_t i; |
116 for (i = 0; i < numSlots; ++i) { | 116 for (i = 0; i < numSlots; ++i) { |
117 partitionFree(ptr + kPointerOffset); | 117 partitionFree(ptr + kPointerOffset); |
118 ptr += size; | 118 ptr += size; |
119 } | 119 } |
120 } | 120 } |
121 | 121 |
122 // Check that the most basic of allocate / free pairs work. | 122 // Check that the most basic of allocate / free pairs work. |
123 TEST(WTF_PartitionAlloc, Basic) | 123 TEST(WTF_PartitionAlloc, Basic) |
124 { | 124 { |
125 TestSetup(); | 125 TestSetup(); |
126 WTF::PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex
]; | 126 WTF::PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex
]; |
127 WTF::PartitionPage* seedPage = &WTF::PartitionRootGeneric::gSeedPage; | 127 WTF::PartitionPage* seedPage = &WTF::PartitionRootGeneric::gSeedPage; |
128 | 128 |
129 EXPECT_FALSE(bucket->freePagesHead); | 129 EXPECT_FALSE(bucket->freePagesHead); |
130 EXPECT_EQ(seedPage, bucket->activePagesHead); | 130 EXPECT_EQ(seedPage, bucket->activePagesHead); |
131 EXPECT_EQ(0, bucket->activePagesHead->activePageNext); | 131 EXPECT_EQ(0, bucket->activePagesHead->nextPage); |
132 | 132 |
133 void* ptr = partitionAlloc(allocator.root(), kTestAllocSize); | 133 void* ptr = partitionAlloc(allocator.root(), kTestAllocSize); |
134 EXPECT_TRUE(ptr); | 134 EXPECT_TRUE(ptr); |
135 EXPECT_EQ(kPointerOffset, reinterpret_cast<size_t>(ptr) & WTF::kPartitionPag
eOffsetMask); | 135 EXPECT_EQ(kPointerOffset, reinterpret_cast<size_t>(ptr) & WTF::kPartitionPag
eOffsetMask); |
136 // Check that the offset appears to include a guard page. | 136 // Check that the offset appears to include a guard page. |
137 EXPECT_EQ(WTF::kPartitionPageSize + kPointerOffset, reinterpret_cast<size_t>
(ptr) & WTF::kSuperPageOffsetMask); | 137 EXPECT_EQ(WTF::kPartitionPageSize + kPointerOffset, reinterpret_cast<size_t>
(ptr) & WTF::kSuperPageOffsetMask); |
138 | 138 |
139 partitionFree(ptr); | 139 partitionFree(ptr); |
140 // Expect that the last active page does not get tossed to the freelist. | 140 // Expect that the last active page does not get tossed to the freelist. |
141 EXPECT_FALSE(bucket->freePagesHead); | 141 EXPECT_FALSE(bucket->freePagesHead); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 // Test a bucket with multiple pages. | 194 // Test a bucket with multiple pages. |
195 TEST(WTF_PartitionAlloc, MultiPages) | 195 TEST(WTF_PartitionAlloc, MultiPages) |
196 { | 196 { |
197 TestSetup(); | 197 TestSetup(); |
198 WTF::PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex
]; | 198 WTF::PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex
]; |
199 | 199 |
200 WTF::PartitionPage* page = GetFullPage(kTestAllocSize); | 200 WTF::PartitionPage* page = GetFullPage(kTestAllocSize); |
201 FreeFullPage(page); | 201 FreeFullPage(page); |
202 EXPECT_FALSE(bucket->freePagesHead); | 202 EXPECT_FALSE(bucket->freePagesHead); |
203 EXPECT_EQ(page, bucket->activePagesHead); | 203 EXPECT_EQ(page, bucket->activePagesHead); |
204 EXPECT_EQ(0, page->activePageNext); | 204 EXPECT_EQ(0, page->nextPage); |
205 EXPECT_EQ(0, page->numAllocatedSlots); | 205 EXPECT_EQ(0, page->numAllocatedSlots); |
206 | 206 |
207 page = GetFullPage(kTestAllocSize); | 207 page = GetFullPage(kTestAllocSize); |
208 WTF::PartitionPage* page2 = GetFullPage(kTestAllocSize); | 208 WTF::PartitionPage* page2 = GetFullPage(kTestAllocSize); |
209 | 209 |
210 EXPECT_EQ(page2, bucket->activePagesHead); | 210 EXPECT_EQ(page2, bucket->activePagesHead); |
211 EXPECT_EQ(0, page2->activePageNext); | 211 EXPECT_EQ(0, page2->nextPage); |
212 EXPECT_EQ(reinterpret_cast<uintptr_t>(partitionPageToPointer(page)) & WTF::k
SuperPageBaseMask, reinterpret_cast<uintptr_t>(partitionPageToPointer(page2)) &
WTF::kSuperPageBaseMask); | 212 EXPECT_EQ(reinterpret_cast<uintptr_t>(partitionPageToPointer(page)) & WTF::k
SuperPageBaseMask, reinterpret_cast<uintptr_t>(partitionPageToPointer(page2)) &
WTF::kSuperPageBaseMask); |
213 | 213 |
214 // Fully free the non-current page. It should not be freelisted because | 214 // Fully free the non-current page. It should not be freelisted because |
215 // there is no other immediately useable page. The other page is full. | 215 // there is no other immediately useable page. The other page is full. |
216 FreeFullPage(page); | 216 FreeFullPage(page); |
217 EXPECT_EQ(0, page->numAllocatedSlots); | 217 EXPECT_EQ(0, page->numAllocatedSlots); |
218 EXPECT_FALSE(bucket->freePagesHead); | 218 EXPECT_FALSE(bucket->freePagesHead); |
219 EXPECT_EQ(page, bucket->activePagesHead); | 219 EXPECT_EQ(page, bucket->activePagesHead); |
220 | 220 |
221 // Allocate a new page, it should pull from the freelist. | 221 // Allocate a new page, it should pull from the freelist. |
222 page = GetFullPage(kTestAllocSize); | 222 page = GetFullPage(kTestAllocSize); |
223 EXPECT_FALSE(bucket->freePagesHead); | 223 EXPECT_FALSE(bucket->freePagesHead); |
224 EXPECT_EQ(page, bucket->activePagesHead); | 224 EXPECT_EQ(page, bucket->activePagesHead); |
225 | 225 |
226 FreeFullPage(page); | 226 FreeFullPage(page); |
227 FreeFullPage(page2); | 227 FreeFullPage(page2); |
228 EXPECT_EQ(0, page->numAllocatedSlots); | 228 EXPECT_EQ(0, page->numAllocatedSlots); |
229 EXPECT_EQ(0, page2->numAllocatedSlots); | 229 EXPECT_EQ(0, page2->numAllocatedSlots); |
230 EXPECT_TRUE(partitionPageIsFree(page2)); | 230 EXPECT_EQ(0, page2->numUnprovisionedSlots); |
| 231 EXPECT_EQ(0, page2->freelistHead); |
231 | 232 |
232 TestShutdown(); | 233 TestShutdown(); |
233 } | 234 } |
234 | 235 |
235 // Test some finer aspects of internal page transitions. | 236 // Test some finer aspects of internal page transitions. |
236 TEST(WTF_PartitionAlloc, PageTransitions) | 237 TEST(WTF_PartitionAlloc, PageTransitions) |
237 { | 238 { |
238 TestSetup(); | 239 TestSetup(); |
239 WTF::PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex
]; | 240 WTF::PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex
]; |
240 | 241 |
241 WTF::PartitionPage* page1 = GetFullPage(kTestAllocSize); | 242 WTF::PartitionPage* page1 = GetFullPage(kTestAllocSize); |
242 EXPECT_EQ(page1, bucket->activePagesHead); | 243 EXPECT_EQ(page1, bucket->activePagesHead); |
243 EXPECT_EQ(0, page1->activePageNext); | 244 EXPECT_EQ(0, page1->nextPage); |
244 WTF::PartitionPage* page2 = GetFullPage(kTestAllocSize); | 245 WTF::PartitionPage* page2 = GetFullPage(kTestAllocSize); |
245 EXPECT_EQ(page2, bucket->activePagesHead); | 246 EXPECT_EQ(page2, bucket->activePagesHead); |
246 EXPECT_EQ(0, page2->activePageNext); | 247 EXPECT_EQ(0, page2->nextPage); |
247 | 248 |
248 // Bounce page1 back into the non-full list then fill it up again. | 249 // Bounce page1 back into the non-full list then fill it up again. |
249 char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPointe
rOffset; | 250 char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPointe
rOffset; |
250 partitionFree(ptr); | 251 partitionFree(ptr); |
251 EXPECT_EQ(page1, bucket->activePagesHead); | 252 EXPECT_EQ(page1, bucket->activePagesHead); |
252 (void) partitionAlloc(allocator.root(), kTestAllocSize); | 253 (void) partitionAlloc(allocator.root(), kTestAllocSize); |
253 EXPECT_EQ(page1, bucket->activePagesHead); | 254 EXPECT_EQ(page1, bucket->activePagesHead); |
254 EXPECT_EQ(page2, bucket->activePagesHead->activePageNext); | 255 EXPECT_EQ(page2, bucket->activePagesHead->nextPage); |
255 | 256 |
256 // Allocating another page at this point should cause us to scan over page1 | 257 // Allocating another page at this point should cause us to scan over page1 |
257 // (which is both full and NOT our current page), and evict it from the | 258 // (which is both full and NOT our current page), and evict it from the |
258 // freelist. Older code had a O(n^2) condition due to failure to do this. | 259 // freelist. Older code had a O(n^2) condition due to failure to do this. |
259 WTF::PartitionPage* page3 = GetFullPage(kTestAllocSize); | 260 WTF::PartitionPage* page3 = GetFullPage(kTestAllocSize); |
260 EXPECT_EQ(page3, bucket->activePagesHead); | 261 EXPECT_EQ(page3, bucket->activePagesHead); |
261 EXPECT_EQ(0, page3->activePageNext); | 262 EXPECT_EQ(0, page3->nextPage); |
262 | 263 |
263 // Work out a pointer into page2 and free it. | 264 // Work out a pointer into page2 and free it. |
264 ptr = reinterpret_cast<char*>(partitionPageToPointer(page2)) + kPointerOffse
t; | 265 ptr = reinterpret_cast<char*>(partitionPageToPointer(page2)) + kPointerOffse
t; |
265 partitionFree(ptr); | 266 partitionFree(ptr); |
266 // Trying to allocate at this time should cause us to cycle around to page2 | 267 // Trying to allocate at this time should cause us to cycle around to page2 |
267 // and find the recently freed slot. | 268 // and find the recently freed slot. |
268 char* newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTes
tAllocSize)); | 269 char* newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTes
tAllocSize)); |
269 EXPECT_EQ(ptr, newPtr); | 270 EXPECT_EQ(ptr, newPtr); |
270 EXPECT_EQ(page2, bucket->activePagesHead); | 271 EXPECT_EQ(page2, bucket->activePagesHead); |
271 EXPECT_EQ(page3, page2->activePageNext); | 272 EXPECT_EQ(page3, page2->nextPage); |
272 | 273 |
273 // Work out a pointer into page1 and free it. This should pull the page | 274 // Work out a pointer into page1 and free it. This should pull the page |
274 // back into the list of available pages. | 275 // back into the list of available pages. |
275 ptr = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPointerOffse
t; | 276 ptr = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPointerOffse
t; |
276 partitionFree(ptr); | 277 partitionFree(ptr); |
277 // This allocation should be satisfied by page1. | 278 // This allocation should be satisfied by page1. |
278 newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAlloc
Size)); | 279 newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAlloc
Size)); |
279 EXPECT_EQ(ptr, newPtr); | 280 EXPECT_EQ(ptr, newPtr); |
280 EXPECT_EQ(page1, bucket->activePagesHead); | 281 EXPECT_EQ(page1, bucket->activePagesHead); |
281 EXPECT_EQ(page2, page1->activePageNext); | 282 EXPECT_EQ(page2, page1->nextPage); |
282 | 283 |
283 FreeFullPage(page3); | 284 FreeFullPage(page3); |
284 FreeFullPage(page2); | 285 FreeFullPage(page2); |
285 FreeFullPage(page1); | 286 FreeFullPage(page1); |
286 | 287 |
287 // Allocating whilst in this state exposed a bug, so keep the test. | 288 // Allocating whilst in this state exposed a bug, so keep the test. |
288 ptr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSiz
e)); | 289 ptr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSiz
e)); |
289 partitionFree(ptr); | 290 partitionFree(ptr); |
290 | 291 |
291 TestShutdown(); | 292 TestShutdown(); |
(...skipping 13 matching lines...) Expand all Loading... |
305 OwnPtr<WTF::PartitionPage*[]> pages = adoptArrayPtr(new WTF::PartitionPage*[
numToFillFreeListPage]); | 306 OwnPtr<WTF::PartitionPage*[]> pages = adoptArrayPtr(new WTF::PartitionPage*[
numToFillFreeListPage]); |
306 | 307 |
307 size_t i; | 308 size_t i; |
308 for (i = 0; i < numToFillFreeListPage; ++i) { | 309 for (i = 0; i < numToFillFreeListPage; ++i) { |
309 pages[i] = GetFullPage(kTestAllocSize); | 310 pages[i] = GetFullPage(kTestAllocSize); |
310 } | 311 } |
311 EXPECT_EQ(pages[numToFillFreeListPage - 1], bucket->activePagesHead); | 312 EXPECT_EQ(pages[numToFillFreeListPage - 1], bucket->activePagesHead); |
312 for (i = 0; i < numToFillFreeListPage; ++i) | 313 for (i = 0; i < numToFillFreeListPage; ++i) |
313 FreeFullPage(pages[i]); | 314 FreeFullPage(pages[i]); |
314 EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots); | 315 EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots); |
315 EXPECT_EQ(0, bucket->activePagesHead->activePageNext); | 316 EXPECT_EQ(0, bucket->activePagesHead->nextPage->freelistHead); |
| 317 EXPECT_EQ(0, bucket->activePagesHead->nextPage->numAllocatedSlots); |
| 318 EXPECT_EQ(0, bucket->activePagesHead->nextPage->numUnprovisionedSlots); |
316 | 319 |
317 // Allocate / free in a different bucket size so we get control of a | 320 // Allocate / free in a different bucket size so we get control of a |
318 // different free page list. We need two pages because one will be the last | 321 // different free page list. We need two pages because one will be the last |
319 // active page and not get freed. | 322 // active page and not get freed. |
320 WTF::PartitionPage* page1 = GetFullPage(kTestAllocSize * 2); | 323 WTF::PartitionPage* page1 = GetFullPage(kTestAllocSize * 2); |
321 WTF::PartitionPage* page2 = GetFullPage(kTestAllocSize * 2); | 324 WTF::PartitionPage* page2 = GetFullPage(kTestAllocSize * 2); |
322 FreeFullPage(page1); | 325 FreeFullPage(page1); |
323 FreeFullPage(page2); | 326 FreeFullPage(page2); |
324 | 327 |
325 // If we re-allocate all kTestAllocSize allocations, we'll pull all the | 328 // If we re-allocate all kTestAllocSize allocations, we'll pull all the |
326 // free pages and end up freeing the first page for free page objects. | 329 // free pages and end up freeing the first page for free page objects. |
327 // It's getting a bit tricky but a nice re-entrancy is going on: | 330 // It's getting a bit tricky but a nice re-entrancy is going on: |
328 // alloc(kTestAllocSize) -> pulls page from free page list -> | 331 // alloc(kTestAllocSize) -> pulls page from free page list -> |
329 // free(PartitionFreepagelistEntry) -> last entry in page freed -> | 332 // free(PartitionFreepagelistEntry) -> last entry in page freed -> |
330 // alloc(PartitionFreepagelistEntry). | 333 // alloc(PartitionFreepagelistEntry). |
331 for (i = 0; i < numToFillFreeListPage; ++i) { | 334 for (i = 0; i < numToFillFreeListPage; ++i) { |
332 pages[i] = GetFullPage(kTestAllocSize); | 335 pages[i] = GetFullPage(kTestAllocSize); |
333 } | 336 } |
334 EXPECT_EQ(pages[numToFillFreeListPage - 1], bucket->activePagesHead); | 337 EXPECT_EQ(pages[numToFillFreeListPage - 1], bucket->activePagesHead); |
335 | 338 |
336 // As part of the final free-up, we'll test another re-entrancy: | 339 // As part of the final free-up, we'll test another re-entrancy: |
337 // free(kTestAllocSize) -> last entry in page freed -> | 340 // free(kTestAllocSize) -> last entry in page freed -> |
338 // alloc(PartitionFreepagelistEntry) -> pulls page from free page list -> | 341 // alloc(PartitionFreepagelistEntry) -> pulls page from free page list -> |
339 // free(PartitionFreepagelistEntry) | 342 // free(PartitionFreepagelistEntry) |
340 for (i = 0; i < numToFillFreeListPage; ++i) | 343 for (i = 0; i < numToFillFreeListPage; ++i) |
341 FreeFullPage(pages[i]); | 344 FreeFullPage(pages[i]); |
342 EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots); | 345 EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots); |
343 EXPECT_EQ(0, bucket->activePagesHead->activePageNext); | 346 EXPECT_EQ(0, bucket->activePagesHead->nextPage->freelistHead); |
| 347 EXPECT_EQ(0, bucket->activePagesHead->nextPage->numAllocatedSlots); |
| 348 EXPECT_EQ(0, bucket->activePagesHead->nextPage->numUnprovisionedSlots); |
344 | 349 |
345 TestShutdown(); | 350 TestShutdown(); |
346 } | 351 } |
347 | 352 |
348 // Test a large series of allocations that cross more than one underlying | 353 // Test a large series of allocations that cross more than one underlying |
349 // 64KB super page allocation. | 354 // 64KB super page allocation. |
350 TEST(WTF_PartitionAlloc, MultiPageAllocs) | 355 TEST(WTF_PartitionAlloc, MultiPageAllocs) |
351 { | 356 { |
352 TestSetup(); | 357 TestSetup(); |
353 // This is guaranteed to cross a super page boundary because the first | 358 // This is guaranteed to cross a super page boundary because the first |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 EXPECT_TRUE(ptr); | 503 EXPECT_TRUE(ptr); |
499 memset(ptr, 'A', size); | 504 memset(ptr, 'A', size); |
500 ptr2 = partitionAllocGeneric(genericAllocator.root(), size); | 505 ptr2 = partitionAllocGeneric(genericAllocator.root(), size); |
501 EXPECT_TRUE(ptr2); | 506 EXPECT_TRUE(ptr2); |
502 void* ptr3 = partitionAllocGeneric(genericAllocator.root(), size); | 507 void* ptr3 = partitionAllocGeneric(genericAllocator.root(), size); |
503 EXPECT_TRUE(ptr3); | 508 EXPECT_TRUE(ptr3); |
504 void* ptr4 = partitionAllocGeneric(genericAllocator.root(), size); | 509 void* ptr4 = partitionAllocGeneric(genericAllocator.root(), size); |
505 EXPECT_TRUE(ptr4); | 510 EXPECT_TRUE(ptr4); |
506 | 511 |
507 page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr
)); | 512 page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr
)); |
508 EXPECT_NE(page, WTF::partitionPointerToPage(WTF::partitionCookieFreePointerA
djust(ptr3))); | 513 WTF::PartitionPage* page2 = WTF::partitionPointerToPage(WTF::partitionCookie
FreePointerAdjust(ptr3)); |
| 514 EXPECT_NE(page, page2); |
509 | 515 |
510 partitionFreeGeneric(genericAllocator.root(), ptr); | 516 partitionFreeGeneric(genericAllocator.root(), ptr); |
511 partitionFreeGeneric(genericAllocator.root(), ptr3); | 517 partitionFreeGeneric(genericAllocator.root(), ptr3); |
512 partitionFreeGeneric(genericAllocator.root(), ptr2); | 518 partitionFreeGeneric(genericAllocator.root(), ptr2); |
513 // Should have freelisted at this point. | 519 // Should have been freed at this point. |
514 EXPECT_TRUE(page->bucket->freePagesHead); | 520 EXPECT_FALSE(page->freelistHead); |
515 ptr3 = partitionAllocGeneric(genericAllocator.root(), size); | 521 EXPECT_EQ(0, page->numAllocatedSlots); |
516 EXPECT_TRUE(ptr3); | 522 EXPECT_EQ(0, page->numUnprovisionedSlots); |
517 void* newPtr = partitionAllocGeneric(genericAllocator.root(), size); | 523 void* newPtr = partitionAllocGeneric(genericAllocator.root(), size); |
| 524 EXPECT_EQ(ptr3, newPtr); |
| 525 newPtr = partitionAllocGeneric(genericAllocator.root(), size); |
518 EXPECT_EQ(ptr, newPtr); | 526 EXPECT_EQ(ptr, newPtr); |
519 #if OS(LINUX) && defined(NDEBUG) | 527 #if OS(LINUX) && defined(NDEBUG) |
520 // On Linux, we have a guarantee that freelisting a page should cause its | 528 // On Linux, we have a guarantee that freelisting a page should cause its |
521 // contents to be nulled out. We check for null here to detect an bug we | 529 // contents to be nulled out. We check for null here to detect an bug we |
522 // had where a large slot size was causing us to not properly free all | 530 // had where a large slot size was causing us to not properly free all |
523 // resources back to the system. | 531 // resources back to the system. |
524 // We only run the check in optimized builds because the debug build | 532 // We only run the check in optimized builds because the debug build |
525 // writes over the allocated area with an "uninitialized" byte pattern. | 533 // writes over the allocated area with an "uninitialized" byte pattern. |
526 EXPECT_EQ(0, *(reinterpret_cast<char*>(newPtr) + (size - 1))); | 534 EXPECT_EQ(0, *(reinterpret_cast<char*>(newPtr) + (size - 1))); |
527 #endif | 535 #endif |
(...skipping 17 matching lines...) Expand all Loading... |
545 | 553 |
546 void* ptr = partitionAlloc(allocator.root(), bigSize); | 554 void* ptr = partitionAlloc(allocator.root(), bigSize); |
547 EXPECT_TRUE(ptr); | 555 EXPECT_TRUE(ptr); |
548 | 556 |
549 WTF::PartitionPage* page = WTF::partitionPointerToPage(WTF::partitionCookieF
reePointerAdjust(ptr)); | 557 WTF::PartitionPage* page = WTF::partitionPointerToPage(WTF::partitionCookieF
reePointerAdjust(ptr)); |
550 size_t totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemP
ageSize) / (bigSize + kExtraAllocSize); | 558 size_t totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemP
ageSize) / (bigSize + kExtraAllocSize); |
551 EXPECT_EQ(4u, totalSlots); | 559 EXPECT_EQ(4u, totalSlots); |
552 // The freelist should have one entry, because we were able to exactly fit | 560 // The freelist should have one entry, because we were able to exactly fit |
553 // one object slot and one freelist pointer (the null that the head points | 561 // one object slot and one freelist pointer (the null that the head points |
554 // to) into a system page. | 562 // to) into a system page. |
555 EXPECT_TRUE(partitionPageFreelistHead(page)); | 563 EXPECT_TRUE(page->freelistHead); |
556 EXPECT_EQ(1, page->numAllocatedSlots); | 564 EXPECT_EQ(1, page->numAllocatedSlots); |
557 EXPECT_EQ(2, page->numUnprovisionedSlots); | 565 EXPECT_EQ(2, page->numUnprovisionedSlots); |
558 | 566 |
559 void* ptr2 = partitionAlloc(allocator.root(), bigSize); | 567 void* ptr2 = partitionAlloc(allocator.root(), bigSize); |
560 EXPECT_TRUE(ptr2); | 568 EXPECT_TRUE(ptr2); |
561 EXPECT_FALSE(partitionPageFreelistHead(page)); | 569 EXPECT_FALSE(page->freelistHead); |
562 EXPECT_EQ(2, page->numAllocatedSlots); | 570 EXPECT_EQ(2, page->numAllocatedSlots); |
563 EXPECT_EQ(2, page->numUnprovisionedSlots); | 571 EXPECT_EQ(2, page->numUnprovisionedSlots); |
564 | 572 |
565 void* ptr3 = partitionAlloc(allocator.root(), bigSize); | 573 void* ptr3 = partitionAlloc(allocator.root(), bigSize); |
566 EXPECT_TRUE(ptr3); | 574 EXPECT_TRUE(ptr3); |
567 EXPECT_TRUE(partitionPageFreelistHead(page)); | 575 EXPECT_TRUE(page->freelistHead); |
568 EXPECT_EQ(3, page->numAllocatedSlots); | 576 EXPECT_EQ(3, page->numAllocatedSlots); |
569 EXPECT_EQ(0, page->numUnprovisionedSlots); | 577 EXPECT_EQ(0, page->numUnprovisionedSlots); |
570 | 578 |
571 void* ptr4 = partitionAlloc(allocator.root(), bigSize); | 579 void* ptr4 = partitionAlloc(allocator.root(), bigSize); |
572 EXPECT_TRUE(ptr4); | 580 EXPECT_TRUE(ptr4); |
573 EXPECT_FALSE(partitionPageFreelistHead(page)); | 581 EXPECT_FALSE(page->freelistHead); |
574 EXPECT_EQ(4, page->numAllocatedSlots); | 582 EXPECT_EQ(4, page->numAllocatedSlots); |
575 EXPECT_EQ(0, page->numUnprovisionedSlots); | 583 EXPECT_EQ(0, page->numUnprovisionedSlots); |
576 | 584 |
577 void* ptr5 = partitionAlloc(allocator.root(), bigSize); | 585 void* ptr5 = partitionAlloc(allocator.root(), bigSize); |
578 EXPECT_TRUE(ptr5); | 586 EXPECT_TRUE(ptr5); |
579 | 587 |
580 WTF::PartitionPage* page2 = WTF::partitionPointerToPage(WTF::partitionCookie
FreePointerAdjust(ptr5)); | 588 WTF::PartitionPage* page2 = WTF::partitionPointerToPage(WTF::partitionCookie
FreePointerAdjust(ptr5)); |
581 EXPECT_EQ(1, page2->numAllocatedSlots); | 589 EXPECT_EQ(1, page2->numAllocatedSlots); |
582 | 590 |
583 // Churn things a little whilst there's a partial page freelist. | 591 // Churn things a little whilst there's a partial page freelist. |
584 partitionFree(ptr); | 592 partitionFree(ptr); |
585 ptr = partitionAlloc(allocator.root(), bigSize); | 593 ptr = partitionAlloc(allocator.root(), bigSize); |
586 void* ptr6 = partitionAlloc(allocator.root(), bigSize); | 594 void* ptr6 = partitionAlloc(allocator.root(), bigSize); |
587 | 595 |
588 partitionFree(ptr); | 596 partitionFree(ptr); |
589 partitionFree(ptr2); | 597 partitionFree(ptr2); |
590 partitionFree(ptr3); | 598 partitionFree(ptr3); |
591 partitionFree(ptr4); | 599 partitionFree(ptr4); |
592 partitionFree(ptr5); | 600 partitionFree(ptr5); |
593 partitionFree(ptr6); | 601 partitionFree(ptr6); |
594 EXPECT_TRUE(bucket->freePagesHead); | 602 EXPECT_TRUE(bucket->freePagesHead); |
595 EXPECT_EQ(page, bucket->freePagesHead); | 603 EXPECT_EQ(page, bucket->freePagesHead); |
596 EXPECT_TRUE(partitionPageFreelistHead(page2)); | 604 EXPECT_TRUE(page2->freelistHead); |
597 EXPECT_EQ(0, page2->numAllocatedSlots); | 605 EXPECT_EQ(0, page2->numAllocatedSlots); |
598 | 606 |
599 // And test a couple of sizes that do not cross kSystemPageSize with a singl
e allocation. | 607 // And test a couple of sizes that do not cross kSystemPageSize with a singl
e allocation. |
600 size_t mediumSize = (WTF::kSystemPageSize / 2) - kExtraAllocSize; | 608 size_t mediumSize = (WTF::kSystemPageSize / 2) - kExtraAllocSize; |
601 bucketIdx = (mediumSize + kExtraAllocSize) >> WTF::kBucketShift; | 609 bucketIdx = (mediumSize + kExtraAllocSize) >> WTF::kBucketShift; |
602 bucket = &allocator.root()->buckets()[bucketIdx]; | 610 bucket = &allocator.root()->buckets()[bucketIdx]; |
603 EXPECT_EQ(0, bucket->freePagesHead); | 611 EXPECT_EQ(0, bucket->freePagesHead); |
604 | 612 |
605 ptr = partitionAlloc(allocator.root(), mediumSize); | 613 ptr = partitionAlloc(allocator.root(), mediumSize); |
606 EXPECT_TRUE(ptr); | 614 EXPECT_TRUE(ptr); |
(...skipping 13 matching lines...) Expand all Loading... |
620 | 628 |
621 ptr = partitionAlloc(allocator.root(), smallSize); | 629 ptr = partitionAlloc(allocator.root(), smallSize); |
622 EXPECT_TRUE(ptr); | 630 EXPECT_TRUE(ptr); |
623 page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr
)); | 631 page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr
)); |
624 EXPECT_EQ(1, page->numAllocatedSlots); | 632 EXPECT_EQ(1, page->numAllocatedSlots); |
625 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize
) / (smallSize + kExtraAllocSize); | 633 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize
) / (smallSize + kExtraAllocSize); |
626 firstPageSlots = WTF::kSystemPageSize / (smallSize + kExtraAllocSize); | 634 firstPageSlots = WTF::kSystemPageSize / (smallSize + kExtraAllocSize); |
627 EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); | 635 EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); |
628 | 636 |
629 partitionFree(ptr); | 637 partitionFree(ptr); |
630 EXPECT_TRUE(partitionPageFreelistHead(page)); | 638 EXPECT_TRUE(page->freelistHead); |
631 EXPECT_EQ(0, page->numAllocatedSlots); | 639 EXPECT_EQ(0, page->numAllocatedSlots); |
632 | 640 |
633 size_t verySmallSize = (WTF::kAllocationGranularity * 2) - kExtraAllocSize; | 641 size_t verySmallSize = (WTF::kAllocationGranularity * 2) - kExtraAllocSize; |
634 bucketIdx = (verySmallSize + kExtraAllocSize) >> WTF::kBucketShift; | 642 bucketIdx = (verySmallSize + kExtraAllocSize) >> WTF::kBucketShift; |
635 bucket = &allocator.root()->buckets()[bucketIdx]; | 643 bucket = &allocator.root()->buckets()[bucketIdx]; |
636 EXPECT_EQ(0, bucket->freePagesHead); | 644 EXPECT_EQ(0, bucket->freePagesHead); |
637 | 645 |
638 ptr = partitionAlloc(allocator.root(), verySmallSize); | 646 ptr = partitionAlloc(allocator.root(), verySmallSize); |
639 EXPECT_TRUE(ptr); | 647 EXPECT_TRUE(ptr); |
640 page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr
)); | 648 page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr
)); |
641 EXPECT_EQ(1, page->numAllocatedSlots); | 649 EXPECT_EQ(1, page->numAllocatedSlots); |
642 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize
) / (verySmallSize + kExtraAllocSize); | 650 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize
) / (verySmallSize + kExtraAllocSize); |
643 firstPageSlots = WTF::kSystemPageSize / (verySmallSize + kExtraAllocSize); | 651 firstPageSlots = WTF::kSystemPageSize / (verySmallSize + kExtraAllocSize); |
644 EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); | 652 EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); |
645 | 653 |
646 partitionFree(ptr); | 654 partitionFree(ptr); |
647 EXPECT_TRUE(partitionPageFreelistHead(page)); | 655 EXPECT_TRUE(page->freelistHead); |
648 EXPECT_EQ(0, page->numAllocatedSlots); | 656 EXPECT_EQ(0, page->numAllocatedSlots); |
649 | 657 |
650 // And try an allocation size (against the generic allocator) that is | 658 // And try an allocation size (against the generic allocator) that is |
651 // larger than a system page. | 659 // larger than a system page. |
652 size_t pageAndAHalfSize = (WTF::kSystemPageSize + (WTF::kSystemPageSize / 2)
) - kExtraAllocSize; | 660 size_t pageAndAHalfSize = (WTF::kSystemPageSize + (WTF::kSystemPageSize / 2)
) - kExtraAllocSize; |
653 ptr = partitionAllocGeneric(genericAllocator.root(), pageAndAHalfSize); | 661 ptr = partitionAllocGeneric(genericAllocator.root(), pageAndAHalfSize); |
654 EXPECT_TRUE(ptr); | 662 EXPECT_TRUE(ptr); |
655 page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr
)); | 663 page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr
)); |
656 EXPECT_EQ(1, page->numAllocatedSlots); | 664 EXPECT_EQ(1, page->numAllocatedSlots); |
657 EXPECT_TRUE(partitionPageFreelistHead(page)); | 665 EXPECT_TRUE(page->freelistHead); |
658 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize
) / (pageAndAHalfSize + kExtraAllocSize); | 666 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize
) / (pageAndAHalfSize + kExtraAllocSize); |
659 EXPECT_EQ(totalSlots - 2, page->numUnprovisionedSlots); | 667 EXPECT_EQ(totalSlots - 2, page->numUnprovisionedSlots); |
660 partitionFreeGeneric(genericAllocator.root(), ptr); | 668 partitionFreeGeneric(genericAllocator.root(), ptr); |
661 | 669 |
662 // And then make sure than exactly the page size only faults one page. | 670 // And then make sure than exactly the page size only faults one page. |
663 size_t pageSize = WTF::kSystemPageSize - kExtraAllocSize; | 671 size_t pageSize = WTF::kSystemPageSize - kExtraAllocSize; |
664 ptr = partitionAllocGeneric(genericAllocator.root(), pageSize); | 672 ptr = partitionAllocGeneric(genericAllocator.root(), pageSize); |
665 EXPECT_TRUE(ptr); | 673 EXPECT_TRUE(ptr); |
666 page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr
)); | 674 page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr
)); |
667 EXPECT_EQ(1, page->numAllocatedSlots); | 675 EXPECT_EQ(1, page->numAllocatedSlots); |
668 EXPECT_FALSE(partitionPageFreelistHead(page)); | 676 EXPECT_FALSE(page->freelistHead); |
669 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize
) / (pageSize + kExtraAllocSize); | 677 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize
) / (pageSize + kExtraAllocSize); |
670 EXPECT_EQ(totalSlots - 1, page->numUnprovisionedSlots); | 678 EXPECT_EQ(totalSlots - 1, page->numUnprovisionedSlots); |
671 partitionFreeGeneric(genericAllocator.root(), ptr); | 679 partitionFreeGeneric(genericAllocator.root(), ptr); |
672 | 680 |
673 TestShutdown(); | 681 TestShutdown(); |
674 } | 682 } |
675 | 683 |
676 // Test some of the fragmentation-resistant properties of the allocator. | 684 // Test some of the fragmentation-resistant properties of the allocator. |
677 TEST(WTF_PartitionAlloc, PageRefilling) | 685 TEST(WTF_PartitionAlloc, PageRefilling) |
678 { | 686 { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
844 EXPECT_EQ(32u, WTF::countLeadingZerosSizet(0)); | 852 EXPECT_EQ(32u, WTF::countLeadingZerosSizet(0)); |
845 EXPECT_EQ(31u, WTF::countLeadingZerosSizet(1)); | 853 EXPECT_EQ(31u, WTF::countLeadingZerosSizet(1)); |
846 EXPECT_EQ(1u, WTF::countLeadingZerosSizet(1 << 30)); | 854 EXPECT_EQ(1u, WTF::countLeadingZerosSizet(1 << 30)); |
847 EXPECT_EQ(0u, WTF::countLeadingZerosSizet(1 << 31)); | 855 EXPECT_EQ(0u, WTF::countLeadingZerosSizet(1 << 31)); |
848 #endif | 856 #endif |
849 } | 857 } |
850 | 858 |
851 } // namespace | 859 } // namespace |
852 | 860 |
853 #endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) | 861 #endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) |
OLD | NEW |