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

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

Issue 641643004: Reapply the non-MathExtras parts of (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 2 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.h ('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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 COMPILE_ASSERT(WTF::kGenericSmallestBucket == 8, generic_smallest_bucket); 53 COMPILE_ASSERT(WTF::kGenericSmallestBucket == 8, generic_smallest_bucket);
54 COMPILE_ASSERT(WTF::kGenericMaxBucketed == 983040, generic_max_bucketed); 54 COMPILE_ASSERT(WTF::kGenericMaxBucketed == 983040, generic_max_bucketed);
55 55
56 namespace WTF { 56 namespace WTF {
57 57
58 int PartitionRootBase::gInitializedLock = 0; 58 int PartitionRootBase::gInitializedLock = 0;
59 bool PartitionRootBase::gInitialized = false; 59 bool PartitionRootBase::gInitialized = false;
60 PartitionPage PartitionRootBase::gSeedPage; 60 PartitionPage PartitionRootBase::gSeedPage;
61 PartitionBucket PartitionRootBase::gPagedBucket; 61 PartitionBucket PartitionRootBase::gPagedBucket;
62 62
63 static size_t partitionBucketNumSystemPages(size_t size) 63 static uint16_t partitionBucketNumSystemPages(size_t size)
64 { 64 {
65 // This works out reasonably for the current bucket sizes of the generic 65 // This works out reasonably for the current bucket sizes of the generic
66 // allocator, and the current values of partition page size and constants. 66 // allocator, and the current values of partition page size and constants.
67 // Specifically, we have enough room to always pack the slots perfectly into 67 // Specifically, we have enough room to always pack the slots perfectly into
68 // some number of system pages. The only waste is the waste associated with 68 // some number of system pages. The only waste is the waste associated with
69 // unfaulted pages (i.e. wasted address space). 69 // unfaulted pages (i.e. wasted address space).
70 // TODO: we end up using a lot of system pages for very small sizes. For 70 // TODO: we end up using a lot of system pages for very small sizes. For
71 // example, we'll use 12 system pages for slot size 24. The slot size is 71 // example, we'll use 12 system pages for slot size 24. The slot size is
72 // so small that the waste would be tiny with just 4, or 1, system pages. 72 // so small that the waste would be tiny with just 4, or 1, system pages.
73 // Later, we can investigate whether there are anti-fragmentation benefits 73 // Later, we can investigate whether there are anti-fragmentation benefits
74 // to using fewer system pages. 74 // to using fewer system pages.
75 double bestWasteRatio = 1.0f; 75 double bestWasteRatio = 1.0f;
76 size_t bestPages = 0; 76 uint16_t bestPages = 0;
77 if (size > kMaxSystemPagesPerSlotSpan * kSystemPageSize) { 77 if (size > kMaxSystemPagesPerSlotSpan * kSystemPageSize) {
78 ASSERT(!(size % kSystemPageSize)); 78 ASSERT(!(size % kSystemPageSize));
79 return size / kSystemPageSize; 79 return static_cast<uint16_t>(size / kSystemPageSize);
80 } 80 }
81 ASSERT(size <= kMaxSystemPagesPerSlotSpan * kSystemPageSize); 81 ASSERT(size <= kMaxSystemPagesPerSlotSpan * kSystemPageSize);
82 for (size_t i = kNumSystemPagesPerPartitionPage - 1; i <= kMaxSystemPagesPer SlotSpan; ++i) { 82 for (uint16_t i = kNumSystemPagesPerPartitionPage - 1; i <= kMaxSystemPagesP erSlotSpan; ++i) {
83 size_t pageSize = kSystemPageSize * i; 83 size_t pageSize = kSystemPageSize * i;
84 size_t numSlots = pageSize / size; 84 size_t numSlots = pageSize / size;
85 size_t waste = pageSize - (numSlots * size); 85 size_t waste = pageSize - (numSlots * size);
86 // Leaving a page unfaulted is not free; the page will occupy an empty p age table entry. 86 // Leaving a page unfaulted is not free; the page will occupy an empty p age table entry.
87 // Make a simple attempt to account for that. 87 // Make a simple attempt to account for that.
88 size_t numRemainderPages = i & (kNumSystemPagesPerPartitionPage - 1); 88 size_t numRemainderPages = i & (kNumSystemPagesPerPartitionPage - 1);
89 size_t numUnfaultedPages = numRemainderPages ? (kNumSystemPagesPerPartit ionPage - numRemainderPages) : 0; 89 size_t numUnfaultedPages = numRemainderPages ? (kNumSystemPagesPerPartit ionPage - numRemainderPages) : 0;
90 waste += sizeof(void*) * numUnfaultedPages; 90 waste += sizeof(void*) * numUnfaultedPages;
91 double wasteRatio = (double) waste / (double) pageSize; 91 double wasteRatio = (double) waste / (double) pageSize;
92 if (wasteRatio < bestWasteRatio) { 92 if (wasteRatio < bestWasteRatio) {
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 ASSERT(root->totalSizeOfCommittedPages > len); 315 ASSERT(root->totalSizeOfCommittedPages > len);
316 root->totalSizeOfCommittedPages -= len; 316 root->totalSizeOfCommittedPages -= len;
317 } 317 }
318 318
319 static ALWAYS_INLINE void partitionRecommitSystemPages(PartitionRootBase* root, void* addr, size_t len) 319 static ALWAYS_INLINE void partitionRecommitSystemPages(PartitionRootBase* root, void* addr, size_t len)
320 { 320 {
321 recommitSystemPages(addr, len); 321 recommitSystemPages(addr, len);
322 root->totalSizeOfCommittedPages += len; 322 root->totalSizeOfCommittedPages += len;
323 } 323 }
324 324
325 static ALWAYS_INLINE void* partitionAllocPartitionPages(PartitionRootBase* root, int flags, size_t numPartitionPages) 325 static ALWAYS_INLINE void* partitionAllocPartitionPages(PartitionRootBase* root, int flags, uint16_t numPartitionPages)
326 { 326 {
327 ASSERT(!(reinterpret_cast<uintptr_t>(root->nextPartitionPage) % kPartitionPa geSize)); 327 ASSERT(!(reinterpret_cast<uintptr_t>(root->nextPartitionPage) % kPartitionPa geSize));
328 ASSERT(!(reinterpret_cast<uintptr_t>(root->nextPartitionPageEnd) % kPartitio nPageSize)); 328 ASSERT(!(reinterpret_cast<uintptr_t>(root->nextPartitionPageEnd) % kPartitio nPageSize));
329 RELEASE_ASSERT(numPartitionPages <= kNumPartitionPagesPerSuperPage); 329 RELEASE_ASSERT(numPartitionPages <= kNumPartitionPagesPerSuperPage);
330 size_t totalSize = kPartitionPageSize * numPartitionPages; 330 size_t totalSize = kPartitionPageSize * numPartitionPages;
331 root->totalSizeOfCommittedPages += totalSize; 331 root->totalSizeOfCommittedPages += totalSize;
332 size_t numPartitionPagesLeft = (root->nextPartitionPageEnd - root->nextParti tionPage) >> kPartitionPageShift; 332 size_t numPartitionPagesLeft = (root->nextPartitionPageEnd - root->nextParti tionPage) >> kPartitionPageShift;
333 if (LIKELY(numPartitionPagesLeft >= numPartitionPages)) { 333 if (LIKELY(numPartitionPagesLeft >= numPartitionPages)) {
334 // In this case, we can still hand out pages from the current super page 334 // In this case, we can still hand out pages from the current super page
335 // allocation. 335 // allocation.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 return ret; 397 return ret;
398 } 398 }
399 399
400 static ALWAYS_INLINE void partitionUnusePage(PartitionRootBase* root, PartitionP age* page) 400 static ALWAYS_INLINE void partitionUnusePage(PartitionRootBase* root, PartitionP age* page)
401 { 401 {
402 ASSERT(page->bucket->numSystemPagesPerSlotSpan); 402 ASSERT(page->bucket->numSystemPagesPerSlotSpan);
403 void* addr = partitionPageToPointer(page); 403 void* addr = partitionPageToPointer(page);
404 partitionDecommitSystemPages(root, addr, page->bucket->numSystemPagesPerSlot Span * kSystemPageSize); 404 partitionDecommitSystemPages(root, addr, page->bucket->numSystemPagesPerSlot Span * kSystemPageSize);
405 } 405 }
406 406
407 static ALWAYS_INLINE size_t partitionBucketSlots(const PartitionBucket* bucket) 407 static ALWAYS_INLINE uint16_t partitionBucketSlots(const PartitionBucket* bucket )
408 { 408 {
409 return (bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / bucket->slotS ize; 409 return static_cast<uint16_t>((bucket->numSystemPagesPerSlotSpan * kSystemPag eSize) / bucket->slotSize);
410 } 410 }
411 411
412 static ALWAYS_INLINE size_t partitionBucketPartitionPages(const PartitionBucket* bucket) 412 static ALWAYS_INLINE uint16_t partitionBucketPartitionPages(const PartitionBucke t* bucket)
413 { 413 {
414 return (bucket->numSystemPagesPerSlotSpan + (kNumSystemPagesPerPartitionPage - 1)) / kNumSystemPagesPerPartitionPage; 414 return (bucket->numSystemPagesPerSlotSpan + (kNumSystemPagesPerPartitionPage - 1)) / kNumSystemPagesPerPartitionPage;
415 } 415 }
416 416
417 static ALWAYS_INLINE void partitionPageReset(PartitionPage* page, PartitionBucke t* bucket) 417 static ALWAYS_INLINE void partitionPageReset(PartitionPage* page, PartitionBucke t* bucket)
418 { 418 {
419 ASSERT(page != &PartitionRootGeneric::gSeedPage); 419 ASSERT(page != &PartitionRootGeneric::gSeedPage);
420 page->numAllocatedSlots = 0; 420 page->numAllocatedSlots = 0;
421 page->numUnprovisionedSlots = partitionBucketSlots(bucket); 421 page->numUnprovisionedSlots = partitionBucketSlots(bucket);
422 ASSERT(page->numUnprovisionedSlots); 422 ASSERT(page->numUnprovisionedSlots);
423 page->bucket = bucket; 423 page->bucket = bucket;
424 page->nextPage = 0; 424 page->nextPage = 0;
425 // NULLing the freelist is not strictly necessary but it makes an ASSERT in partitionPageFillFreelist simpler. 425 // NULLing the freelist is not strictly necessary but it makes an ASSERT in partitionPageFillFreelist simpler.
426 page->freelistHead = 0; 426 page->freelistHead = 0;
427 page->pageOffset = 0; 427 page->pageOffset = 0;
428 page->freeCacheIndex = -1; 428 page->freeCacheIndex = -1;
429 size_t numPartitionPages = partitionBucketPartitionPages(bucket); 429 uint16_t numPartitionPages = partitionBucketPartitionPages(bucket);
430 size_t i;
431 char* pageCharPtr = reinterpret_cast<char*>(page); 430 char* pageCharPtr = reinterpret_cast<char*>(page);
432 for (i = 1; i < numPartitionPages; ++i) { 431 for (uint16_t i = 1; i < numPartitionPages; ++i) {
433 pageCharPtr += kPageMetadataSize; 432 pageCharPtr += kPageMetadataSize;
434 PartitionPage* secondaryPage = reinterpret_cast<PartitionPage*>(pageChar Ptr); 433 PartitionPage* secondaryPage = reinterpret_cast<PartitionPage*>(pageChar Ptr);
435 secondaryPage->pageOffset = i; 434 secondaryPage->pageOffset = i;
436 } 435 }
437 } 436 }
438 437
439 static ALWAYS_INLINE char* partitionPageAllocAndFillFreelist(PartitionPage* page ) 438 static ALWAYS_INLINE char* partitionPageAllocAndFillFreelist(PartitionPage* page )
440 { 439 {
441 ASSERT(page != &PartitionRootGeneric::gSeedPage); 440 ASSERT(page != &PartitionRootGeneric::gSeedPage);
442 size_t numSlots = page->numUnprovisionedSlots; 441 uint16_t numSlots = page->numUnprovisionedSlots;
443 ASSERT(numSlots); 442 ASSERT(numSlots);
444 PartitionBucket* bucket = page->bucket; 443 PartitionBucket* bucket = page->bucket;
445 // We should only get here when _every_ slot is either used or unprovisioned . 444 // We should only get here when _every_ slot is either used or unprovisioned .
446 // (The third state is "on the freelist". If we have a non-empty freelist, w e should not get here.) 445 // (The third state is "on the freelist". If we have a non-empty freelist, w e should not get here.)
447 ASSERT(numSlots + page->numAllocatedSlots == partitionBucketSlots(bucket)); 446 ASSERT(numSlots + page->numAllocatedSlots == partitionBucketSlots(bucket));
448 // Similarly, make explicitly sure that the freelist is empty. 447 // Similarly, make explicitly sure that the freelist is empty.
449 ASSERT(!page->freelistHead); 448 ASSERT(!page->freelistHead);
450 ASSERT(page->numAllocatedSlots >= 0); 449 ASSERT(page->numAllocatedSlots >= 0);
451 450
452 size_t size = bucket->slotSize; 451 size_t size = bucket->slotSize;
453 char* base = reinterpret_cast<char*>(partitionPageToPointer(page)); 452 char* base = reinterpret_cast<char*>(partitionPageToPointer(page));
454 char* returnObject = base + (size * page->numAllocatedSlots); 453 char* returnObject = base + (size * page->numAllocatedSlots);
455 char* firstFreelistPointer = returnObject + size; 454 char* firstFreelistPointer = returnObject + size;
456 char* firstFreelistPointerExtent = firstFreelistPointer + sizeof(PartitionFr eelistEntry*); 455 char* firstFreelistPointerExtent = firstFreelistPointer + sizeof(PartitionFr eelistEntry*);
457 // Our goal is to fault as few system pages as possible. We calculate the 456 // Our goal is to fault as few system pages as possible. We calculate the
458 // page containing the "end" of the returned slot, and then allow freelist 457 // page containing the "end" of the returned slot, and then allow freelist
459 // pointers to be written up to the end of that page. 458 // pointers to be written up to the end of that page.
460 char* subPageLimit = reinterpret_cast<char*>((reinterpret_cast<uintptr_t>(fi rstFreelistPointer) + kSystemPageOffsetMask) & kSystemPageBaseMask); 459 char* subPageLimit = reinterpret_cast<char*>((reinterpret_cast<uintptr_t>(fi rstFreelistPointer) + kSystemPageOffsetMask) & kSystemPageBaseMask);
461 char* slotsLimit = returnObject + (size * page->numUnprovisionedSlots); 460 char* slotsLimit = returnObject + (size * page->numUnprovisionedSlots);
462 char* freelistLimit = subPageLimit; 461 char* freelistLimit = subPageLimit;
463 if (UNLIKELY(slotsLimit < freelistLimit)) 462 if (UNLIKELY(slotsLimit < freelistLimit))
464 freelistLimit = slotsLimit; 463 freelistLimit = slotsLimit;
465 464
466 size_t numNewFreelistEntries = 0; 465 uint16_t numNewFreelistEntries = 0;
467 if (LIKELY(firstFreelistPointerExtent <= freelistLimit)) { 466 if (LIKELY(firstFreelistPointerExtent <= freelistLimit)) {
468 // Only consider used space in the slot span. If we consider wasted 467 // Only consider used space in the slot span. If we consider wasted
469 // space, we may get an off-by-one when a freelist pointer fits in the 468 // space, we may get an off-by-one when a freelist pointer fits in the
470 // wasted space, but a slot does not. 469 // wasted space, but a slot does not.
471 // We know we can fit at least one freelist pointer. 470 // We know we can fit at least one freelist pointer.
472 numNewFreelistEntries = 1; 471 numNewFreelistEntries = 1;
473 // Any further entries require space for the whole slot span. 472 // Any further entries require space for the whole slot span.
474 numNewFreelistEntries += (freelistLimit - firstFreelistPointerExtent) / size; 473 numNewFreelistEntries += static_cast<uint16_t>((freelistLimit - firstFre elistPointerExtent) / size);
475 } 474 }
476 475
477 // We always return an object slot -- that's the +1 below. 476 // We always return an object slot -- that's the +1 below.
478 // We do not neccessarily create any new freelist entries, because we cross sub page boundaries frequently for large bucket sizes. 477 // We do not neccessarily create any new freelist entries, because we cross sub page boundaries frequently for large bucket sizes.
479 ASSERT(numNewFreelistEntries + 1 <= numSlots); 478 ASSERT(numNewFreelistEntries + 1 <= numSlots);
480 numSlots -= (numNewFreelistEntries + 1); 479 numSlots -= (numNewFreelistEntries + 1);
481 page->numUnprovisionedSlots = numSlots; 480 page->numUnprovisionedSlots = numSlots;
482 page->numAllocatedSlots++; 481 page->numAllocatedSlots++;
483 482
484 if (LIKELY(numNewFreelistEntries)) { 483 if (LIKELY(numNewFreelistEntries)) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 ASSERT(page->numAllocatedSlots >= 0); 531 ASSERT(page->numAllocatedSlots >= 0);
533 if (LIKELY(page->numAllocatedSlots == 0)) { 532 if (LIKELY(page->numAllocatedSlots == 0)) {
534 ASSERT(page->freeCacheIndex == -1); 533 ASSERT(page->freeCacheIndex == -1);
535 // We hit a free page, so shepherd it on to the free page list. 534 // We hit a free page, so shepherd it on to the free page list.
536 page->nextPage = bucket->freePagesHead; 535 page->nextPage = bucket->freePagesHead;
537 bucket->freePagesHead = page; 536 bucket->freePagesHead = page;
538 } else { 537 } else {
539 // If we get here, we found a full page. Skip over it too, and also 538 // If we get here, we found a full page. Skip over it too, and also
540 // tag it as full (via a negative value). We need it tagged so that 539 // tag it as full (via a negative value). We need it tagged so that
541 // free'ing can tell, and move it back into the active page list. 540 // free'ing can tell, and move it back into the active page list.
542 ASSERT(page->numAllocatedSlots == static_cast<int>(partitionBucketSl ots(bucket))); 541 ASSERT(page->numAllocatedSlots == partitionBucketSlots(bucket));
543 page->numAllocatedSlots = -page->numAllocatedSlots; 542 page->numAllocatedSlots = -page->numAllocatedSlots;
544 ++bucket->numFullPages; 543 ++bucket->numFullPages;
545 // numFullPages is a uint16_t for efficient packing so guard against 544 // numFullPages is a uint16_t for efficient packing so guard against
546 // overflow to be safe. 545 // overflow to be safe.
547 RELEASE_ASSERT(bucket->numFullPages); 546 RELEASE_ASSERT(bucket->numFullPages);
548 // Not necessary but might help stop accidents. 547 // Not necessary but might help stop accidents.
549 page->nextPage = 0; 548 page->nextPage = 0;
550 } 549 }
551 } 550 }
552 551
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 ASSERT(newPage != &PartitionRootGeneric::gSeedPage); 685 ASSERT(newPage != &PartitionRootGeneric::gSeedPage);
687 ASSERT(!newPage->freelistHead); 686 ASSERT(!newPage->freelistHead);
688 ASSERT(!newPage->numAllocatedSlots); 687 ASSERT(!newPage->numAllocatedSlots);
689 ASSERT(!newPage->numUnprovisionedSlots); 688 ASSERT(!newPage->numUnprovisionedSlots);
690 ASSERT(newPage->freeCacheIndex == -1); 689 ASSERT(newPage->freeCacheIndex == -1);
691 bucket->freePagesHead = newPage->nextPage; 690 bucket->freePagesHead = newPage->nextPage;
692 void* addr = partitionPageToPointer(newPage); 691 void* addr = partitionPageToPointer(newPage);
693 partitionRecommitSystemPages(root, addr, newPage->bucket->numSystemPages PerSlotSpan * kSystemPageSize); 692 partitionRecommitSystemPages(root, addr, newPage->bucket->numSystemPages PerSlotSpan * kSystemPageSize);
694 } else { 693 } else {
695 // Third. If we get here, we need a brand new page. 694 // Third. If we get here, we need a brand new page.
696 size_t numPartitionPages = partitionBucketPartitionPages(bucket); 695 uint16_t numPartitionPages = partitionBucketPartitionPages(bucket);
697 void* rawNewPage = partitionAllocPartitionPages(root, flags, numPartitio nPages); 696 void* rawNewPage = partitionAllocPartitionPages(root, flags, numPartitio nPages);
698 if (UNLIKELY(!rawNewPage)) { 697 if (UNLIKELY(!rawNewPage)) {
699 ASSERT(returnNull); 698 ASSERT(returnNull);
700 return 0; 699 return 0;
701 } 700 }
702 // Skip the alignment check because it depends on page->bucket, which is not yet set. 701 // Skip the alignment check because it depends on page->bucket, which is not yet set.
703 newPage = partitionPointerToPageNoAlignmentCheck(rawNewPage); 702 newPage = partitionPointerToPageNoAlignmentCheck(rawNewPage);
704 } 703 }
705 704
706 partitionPageReset(newPage, bucket); 705 partitionPageReset(newPage, bucket);
(...skipping 20 matching lines...) Expand all
727 PartitionRootBase* root = partitionPageToRoot(page); 726 PartitionRootBase* root = partitionPageToRoot(page);
728 727
729 // If the page is already registered as empty, give it another life. 728 // If the page is already registered as empty, give it another life.
730 if (page->freeCacheIndex != -1) { 729 if (page->freeCacheIndex != -1) {
731 ASSERT(page->freeCacheIndex >= 0); 730 ASSERT(page->freeCacheIndex >= 0);
732 ASSERT(static_cast<unsigned>(page->freeCacheIndex) < kMaxFreeableSpans); 731 ASSERT(static_cast<unsigned>(page->freeCacheIndex) < kMaxFreeableSpans);
733 ASSERT(root->globalEmptyPageRing[page->freeCacheIndex] == page); 732 ASSERT(root->globalEmptyPageRing[page->freeCacheIndex] == page);
734 root->globalEmptyPageRing[page->freeCacheIndex] = 0; 733 root->globalEmptyPageRing[page->freeCacheIndex] = 0;
735 } 734 }
736 735
737 size_t currentIndex = root->globalEmptyPageRingIndex; 736 int16_t currentIndex = root->globalEmptyPageRingIndex;
738 PartitionPage* pageToFree = root->globalEmptyPageRing[currentIndex]; 737 PartitionPage* pageToFree = root->globalEmptyPageRing[currentIndex];
739 // The page might well have been re-activated, filled up, etc. before we get 738 // The page might well have been re-activated, filled up, etc. before we get
740 // around to looking at it here. 739 // around to looking at it here.
741 if (pageToFree) { 740 if (pageToFree) {
742 ASSERT(pageToFree != &PartitionRootBase::gSeedPage); 741 ASSERT(pageToFree != &PartitionRootBase::gSeedPage);
743 ASSERT(pageToFree->freeCacheIndex >= 0); 742 ASSERT(pageToFree->freeCacheIndex >= 0);
744 ASSERT(static_cast<unsigned>(pageToFree->freeCacheIndex) < kMaxFreeableS pans); 743 ASSERT(static_cast<unsigned>(pageToFree->freeCacheIndex) < kMaxFreeableS pans);
745 ASSERT(pageToFree == root->globalEmptyPageRing[pageToFree->freeCacheInde x]); 744 ASSERT(pageToFree == root->globalEmptyPageRing[pageToFree->freeCacheInde x]);
746 if (!pageToFree->numAllocatedSlots && pageToFree->freelistHead) { 745 if (!pageToFree->numAllocatedSlots && pageToFree->freelistHead) {
747 // The page is still empty, and not freed, so _really_ free it. 746 // The page is still empty, and not freed, so _really_ free it.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 } 791 }
793 partitionRegisterEmptyPage(page); 792 partitionRegisterEmptyPage(page);
794 } else { 793 } else {
795 // Ensure that the page is full. That's the only valid case if we 794 // Ensure that the page is full. That's the only valid case if we
796 // arrive here. 795 // arrive here.
797 ASSERT(page->numAllocatedSlots < 0); 796 ASSERT(page->numAllocatedSlots < 0);
798 // A transition of numAllocatedSlots from 0 to -1 is not legal, and 797 // A transition of numAllocatedSlots from 0 to -1 is not legal, and
799 // likely indicates a double-free. 798 // likely indicates a double-free.
800 RELEASE_ASSERT(page->numAllocatedSlots != -1); 799 RELEASE_ASSERT(page->numAllocatedSlots != -1);
801 page->numAllocatedSlots = -page->numAllocatedSlots - 2; 800 page->numAllocatedSlots = -page->numAllocatedSlots - 2;
802 ASSERT(page->numAllocatedSlots == static_cast<int>(partitionBucketSlots( bucket) - 1)); 801 ASSERT(page->numAllocatedSlots == partitionBucketSlots(bucket) - 1);
803 // Fully used page became partially used. It must be put back on the 802 // Fully used page became partially used. It must be put back on the
804 // non-full page list. Also make it the current page to increase the 803 // non-full page list. Also make it the current page to increase the
805 // chances of it being filled up again. The old current page will be 804 // chances of it being filled up again. The old current page will be
806 // the next page. 805 // the next page.
807 page->nextPage = bucket->activePagesHead; 806 page->nextPage = bucket->activePagesHead;
808 bucket->activePagesHead = page; 807 bucket->activePagesHead = page;
809 --bucket->numFullPages; 808 --bucket->numFullPages;
810 // Special case: for a partition page with just a single slot, it may 809 // Special case: for a partition page with just a single slot, it may
811 // now be empty and we want to run it through the empty logic. 810 // now be empty and we want to run it through the empty logic.
812 if (UNLIKELY(page->numAllocatedSlots == 0)) 811 if (UNLIKELY(page->numAllocatedSlots == 0))
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 // Empty bucket with no freelist or full pages. Skip reporting it. 934 // Empty bucket with no freelist or full pages. Skip reporting it.
936 continue; 935 continue;
937 } 936 }
938 size_t numFreePages = 0; 937 size_t numFreePages = 0;
939 PartitionPage* freePages = bucket.freePagesHead; 938 PartitionPage* freePages = bucket.freePagesHead;
940 while (freePages) { 939 while (freePages) {
941 ++numFreePages; 940 ++numFreePages;
942 freePages = freePages->nextPage; 941 freePages = freePages->nextPage;
943 } 942 }
944 size_t bucketSlotSize = bucket.slotSize; 943 size_t bucketSlotSize = bucket.slotSize;
945 size_t bucketNumSlots = partitionBucketSlots(&bucket); 944 uint16_t bucketNumSlots = partitionBucketSlots(&bucket);
946 size_t bucketUsefulStorage = bucketSlotSize * bucketNumSlots; 945 size_t bucketUsefulStorage = bucketSlotSize * bucketNumSlots;
947 size_t bucketPageSize = bucket.numSystemPagesPerSlotSpan * kSystemPageSi ze; 946 size_t bucketPageSize = bucket.numSystemPagesPerSlotSpan * kSystemPageSi ze;
948 size_t bucketWaste = bucketPageSize - bucketUsefulStorage; 947 size_t bucketWaste = bucketPageSize - bucketUsefulStorage;
949 size_t numActiveBytes = bucket.numFullPages * bucketUsefulStorage; 948 size_t numActiveBytes = bucket.numFullPages * bucketUsefulStorage;
950 size_t numResidentBytes = bucket.numFullPages * bucketPageSize; 949 size_t numResidentBytes = bucket.numFullPages * bucketPageSize;
951 size_t numFreeableBytes = 0; 950 size_t numFreeableBytes = 0;
952 size_t numActivePages = 0; 951 size_t numActivePages = 0;
953 const PartitionPage* page = bucket.activePagesHead; 952 const PartitionPage* page = bucket.activePagesHead;
954 while (page) { 953 while (page) {
955 ASSERT(page != &PartitionRootGeneric::gSeedPage); 954 ASSERT(page != &PartitionRootGeneric::gSeedPage);
(...skipping 20 matching lines...) Expand all
976 printf("total live: %zu bytes\n", totalLive); 975 printf("total live: %zu bytes\n", totalLive);
977 printf("total resident: %zu bytes\n", totalResident); 976 printf("total resident: %zu bytes\n", totalResident);
978 printf("total freeable: %zu bytes\n", totalFreeable); 977 printf("total freeable: %zu bytes\n", totalFreeable);
979 fflush(stdout); 978 fflush(stdout);
980 } 979 }
981 980
982 #endif // !NDEBUG 981 #endif // !NDEBUG
983 982
984 } // namespace WTF 983 } // namespace WTF
985 984
OLDNEW
« no previous file with comments | « Source/wtf/PartitionAlloc.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698