Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: Source/wtf/PartitionAllocTest.cpp

Issue 136333002: PartitionAlloc: simplify PartitionPage structure some more. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fix bug. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/wtf/PartitionAlloc.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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)
OLDNEW
« no previous file with comments | « Source/wtf/PartitionAlloc.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698