Chromium Code Reviews| 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 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 314 static NEVER_INLINE void partitionExcessiveAllocationSize() | 314 static NEVER_INLINE void partitionExcessiveAllocationSize() |
| 315 { | 315 { |
| 316 IMMEDIATE_CRASH(); | 316 IMMEDIATE_CRASH(); |
| 317 } | 317 } |
| 318 | 318 |
| 319 static NEVER_INLINE void partitionBucketFull() | 319 static NEVER_INLINE void partitionBucketFull() |
| 320 { | 320 { |
| 321 IMMEDIATE_CRASH(); | 321 IMMEDIATE_CRASH(); |
| 322 } | 322 } |
| 323 | 323 |
| 324 static bool partitionPageStateIsEmpty(const PartitionPage* page) | 324 static bool ALWAYS_INLINE partitionPageStateIsActive(const PartitionPage* page) |
| 325 { | 325 { |
| 326 ASSERT(page != &PartitionRootGeneric::gSeedPage); | 326 ASSERT(page != &PartitionRootGeneric::gSeedPage); |
| 327 return !page->numAllocatedSlots; | 327 ASSERT(!page->pageOffset); |
| 328 return (page->numAllocatedSlots && (page->freelistHead || page->numUnprovisi onedSlots)); | |
|
haraken
2015/06/24 00:51:52
page->numAllocatedSlots => page->numAllocatedSlots
| |
| 328 } | 329 } |
| 329 | 330 |
| 330 static bool partitionPageStateIsDecommitted(const PartitionPage* page) | 331 static bool ALWAYS_INLINE partitionPageStateIsFull(const PartitionPage* page) |
|
haraken
2015/06/24 00:51:51
This method is a bit confusing, since it returns f
| |
| 331 { | 332 { |
| 332 ASSERT(page != &PartitionRootGeneric::gSeedPage); | 333 ASSERT(page != &PartitionRootGeneric::gSeedPage); |
| 333 bool ret = !page->numAllocatedSlots && !page->freelistHead; | 334 ASSERT(!page->pageOffset); |
| 335 bool ret = (page->numAllocatedSlots == partitionBucketSlots(page->bucket)); | |
| 336 if (ret) { | |
| 337 ASSERT(!page->freelistHead); | |
| 338 ASSERT(!page->numUnprovisionedSlots); | |
| 339 } | |
| 340 return ret; | |
| 341 } | |
| 342 | |
| 343 static bool ALWAYS_INLINE partitionPageStateIsEmpty(const PartitionPage* page) | |
| 344 { | |
| 345 ASSERT(page != &PartitionRootGeneric::gSeedPage); | |
| 346 ASSERT(!page->pageOffset); | |
| 347 return (!page->numAllocatedSlots && page->freelistHead); | |
| 348 } | |
| 349 | |
| 350 static bool ALWAYS_INLINE partitionPageStateIsDecommitted(const PartitionPage* p age) | |
| 351 { | |
| 352 ASSERT(page != &PartitionRootGeneric::gSeedPage); | |
| 353 ASSERT(!page->pageOffset); | |
| 354 bool ret = (!page->numAllocatedSlots && !page->freelistHead); | |
| 334 if (ret) { | 355 if (ret) { |
| 335 ASSERT(!page->numUnprovisionedSlots); | 356 ASSERT(!page->numUnprovisionedSlots); |
| 336 ASSERT(page->emptyCacheIndex == -1); | 357 ASSERT(page->emptyCacheIndex == -1); |
| 337 ASSERT(!page->pageOffset); | |
| 338 } | 358 } |
| 339 return ret; | 359 return ret; |
| 340 } | 360 } |
| 341 | 361 |
| 342 static void partitionIncreaseCommittedPages(PartitionRootBase* root, size_t len) | 362 static void partitionIncreaseCommittedPages(PartitionRootBase* root, size_t len) |
| 343 { | 363 { |
| 344 root->totalSizeOfCommittedPages += len; | 364 root->totalSizeOfCommittedPages += len; |
| 345 ASSERT(root->totalSizeOfCommittedPages <= root->totalSizeOfSuperPages + root ->totalSizeOfDirectMappedPages); | 365 ASSERT(root->totalSizeOfCommittedPages <= root->totalSizeOfSuperPages + root ->totalSizeOfDirectMappedPages); |
| 346 } | 366 } |
| 347 | 367 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 445 ASSERT(ret >= currentExtent->superPageBase && ret < currentExtent->super PagesEnd); | 465 ASSERT(ret >= currentExtent->superPageBase && ret < currentExtent->super PagesEnd); |
| 446 } | 466 } |
| 447 return ret; | 467 return ret; |
| 448 } | 468 } |
| 449 | 469 |
| 450 static ALWAYS_INLINE uint16_t partitionBucketPartitionPages(const PartitionBucke t* bucket) | 470 static ALWAYS_INLINE uint16_t partitionBucketPartitionPages(const PartitionBucke t* bucket) |
| 451 { | 471 { |
| 452 return (bucket->numSystemPagesPerSlotSpan + (kNumSystemPagesPerPartitionPage - 1)) / kNumSystemPagesPerPartitionPage; | 472 return (bucket->numSystemPagesPerSlotSpan + (kNumSystemPagesPerPartitionPage - 1)) / kNumSystemPagesPerPartitionPage; |
| 453 } | 473 } |
| 454 | 474 |
| 455 static ALWAYS_INLINE void partitionPageReset(PartitionPage* page, PartitionBucke t* bucket) | 475 static ALWAYS_INLINE void partitionPageReset(PartitionPage* page) |
| 456 { | 476 { |
| 457 ASSERT(page->bucket == bucket); | |
| 458 ASSERT(partitionPageStateIsDecommitted(page)); | 477 ASSERT(partitionPageStateIsDecommitted(page)); |
| 459 | 478 |
| 460 page->numUnprovisionedSlots = partitionBucketSlots(bucket); | 479 page->numUnprovisionedSlots = partitionBucketSlots(page->bucket); |
| 461 ASSERT(page->numUnprovisionedSlots); | 480 ASSERT(page->numUnprovisionedSlots); |
| 462 | 481 |
| 463 page->nextPage = nullptr; | 482 page->nextPage = nullptr; |
| 464 } | 483 } |
| 465 | 484 |
| 466 static ALWAYS_INLINE void partitionPageSetup(PartitionPage* page, PartitionBucke t* bucket) | 485 static ALWAYS_INLINE void partitionPageSetup(PartitionPage* page, PartitionBucke t* bucket) |
| 467 { | 486 { |
| 468 // The bucket never changes. We set it up once. | 487 // The bucket never changes. We set it up once. |
| 469 page->bucket = bucket; | 488 page->bucket = bucket; |
| 470 page->emptyCacheIndex = -1; | 489 page->emptyCacheIndex = -1; |
| 471 | 490 |
| 472 partitionPageReset(page, bucket); | 491 partitionPageReset(page); |
| 473 | 492 |
| 474 // If this page has just a single slot, do not set up page offsets for any | 493 // If this page has just a single slot, do not set up page offsets for any |
| 475 // page metadata other than the first one. This ensures that attempts to | 494 // page metadata other than the first one. This ensures that attempts to |
| 476 // touch invalid page metadata fail. | 495 // touch invalid page metadata fail. |
| 477 if (page->numUnprovisionedSlots == 1) | 496 if (page->numUnprovisionedSlots == 1) |
| 478 return; | 497 return; |
| 479 | 498 |
| 480 uint16_t numPartitionPages = partitionBucketPartitionPages(bucket); | 499 uint16_t numPartitionPages = partitionBucketPartitionPages(bucket); |
| 481 char* pageCharPtr = reinterpret_cast<char*>(page); | 500 char* pageCharPtr = reinterpret_cast<char*>(page); |
| 482 for (uint16_t i = 1; i < numPartitionPages; ++i) { | 501 for (uint16_t i = 1; i < numPartitionPages; ++i) { |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 574 | 593 |
| 575 PartitionPage* nextPage; | 594 PartitionPage* nextPage; |
| 576 | 595 |
| 577 for (; page; page = nextPage) { | 596 for (; page; page = nextPage) { |
| 578 nextPage = page->nextPage; | 597 nextPage = page->nextPage; |
| 579 ASSERT(page->bucket == bucket); | 598 ASSERT(page->bucket == bucket); |
| 580 ASSERT(page != bucket->emptyPagesHead); | 599 ASSERT(page != bucket->emptyPagesHead); |
| 581 ASSERT(page != bucket->decommittedPagesHead); | 600 ASSERT(page != bucket->decommittedPagesHead); |
| 582 | 601 |
| 583 // Deal with empty and decommitted pages. | 602 // Deal with empty and decommitted pages. |
| 584 if (UNLIKELY(!page->numAllocatedSlots)) { | 603 if (LIKELY(partitionPageStateIsActive(page))) { |
| 585 ASSERT(partitionPageStateIsEmpty(page)); | |
| 586 if (UNLIKELY(!page->freelistHead)) { | |
| 587 ASSERT(partitionPageStateIsDecommitted(page)); | |
| 588 page->nextPage = bucket->decommittedPagesHead; | |
| 589 bucket->decommittedPagesHead = page; | |
| 590 } else { | |
| 591 page->nextPage = bucket->emptyPagesHead; | |
| 592 bucket->emptyPagesHead = page; | |
| 593 } | |
| 594 } else if (LIKELY(page->freelistHead != 0) || LIKELY(page->numUnprovisio nedSlots)) { | |
| 595 // This page is usable because it has freelist entries, or has | 604 // This page is usable because it has freelist entries, or has |
| 596 // unprovisioned slots we can create freelist entries from. | 605 // unprovisioned slots we can create freelist entries from. |
| 597 bucket->activePagesHead = page; | 606 bucket->activePagesHead = page; |
| 598 return true; | 607 return true; |
| 608 } | |
| 609 if (LIKELY(partitionPageStateIsEmpty(page))) { | |
| 610 page->nextPage = bucket->emptyPagesHead; | |
| 611 bucket->emptyPagesHead = page; | |
| 612 } else if (LIKELY(partitionPageStateIsDecommitted(page))) { | |
| 613 page->nextPage = bucket->decommittedPagesHead; | |
| 614 bucket->decommittedPagesHead = page; | |
| 599 } else { | 615 } else { |
| 616 ASSERT(partitionPageStateIsFull(page)); | |
| 600 // If we get here, we found a full page. Skip over it too, and also | 617 // If we get here, we found a full page. Skip over it too, and also |
| 601 // tag it as full (via a negative value). We need it tagged so that | 618 // tag it as full (via a negative value). We need it tagged so that |
| 602 // free'ing can tell, and move it back into the active page list. | 619 // free'ing can tell, and move it back into the active page list. |
| 603 ASSERT(page->numAllocatedSlots == partitionBucketSlots(bucket)); | |
| 604 page->numAllocatedSlots = -page->numAllocatedSlots; | 620 page->numAllocatedSlots = -page->numAllocatedSlots; |
| 605 ++bucket->numFullPages; | 621 ++bucket->numFullPages; |
| 606 // numFullPages is a uint16_t for efficient packing so guard against | 622 // numFullPages is a uint16_t for efficient packing so guard against |
| 607 // overflow to be safe. | 623 // overflow to be safe. |
| 608 if (UNLIKELY(!bucket->numFullPages)) | 624 if (UNLIKELY(!bucket->numFullPages)) |
| 609 partitionBucketFull(); | 625 partitionBucketFull(); |
| 610 // Not necessary but might help stop accidents. | 626 // Not necessary but might help stop accidents. |
| 611 page->nextPage = 0; | 627 page->nextPage = 0; |
| 612 } | 628 } |
| 613 } | 629 } |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 760 ASSERT(bucket->activePagesHead == &PartitionRootGeneric::gSeedPage); | 776 ASSERT(bucket->activePagesHead == &PartitionRootGeneric::gSeedPage); |
| 761 if (size > kGenericMaxDirectMapped) { | 777 if (size > kGenericMaxDirectMapped) { |
| 762 if (returnNull) | 778 if (returnNull) |
| 763 return nullptr; | 779 return nullptr; |
| 764 partitionExcessiveAllocationSize(); | 780 partitionExcessiveAllocationSize(); |
| 765 } | 781 } |
| 766 newPage = partitionDirectMap(root, flags, size); | 782 newPage = partitionDirectMap(root, flags, size); |
| 767 } else if (LIKELY(partitionSetNewActivePage(bucket))) { | 783 } else if (LIKELY(partitionSetNewActivePage(bucket))) { |
| 768 // First, did we find an active page in the active pages list? | 784 // First, did we find an active page in the active pages list? |
| 769 newPage = bucket->activePagesHead; | 785 newPage = bucket->activePagesHead; |
| 770 ASSERT(newPage != &PartitionRootGeneric::gSeedPage); | 786 ASSERT(partitionPageStateIsActive(newPage)); |
| 771 } else if (LIKELY(bucket->emptyPagesHead != nullptr) || LIKELY(bucket->decom mittedPagesHead != nullptr)) { | 787 } else if (LIKELY(bucket->emptyPagesHead != nullptr) || LIKELY(bucket->decom mittedPagesHead != nullptr)) { |
| 772 // Second, look in our lists of empty and decommitted pages. | 788 // Second, look in our lists of empty and decommitted pages. |
| 773 // Check empty pages first, which are preferred, but beware that an | 789 // Check empty pages first, which are preferred, but beware that an |
| 774 // empty page might have been decommitted. | 790 // empty page might have been decommitted. |
| 775 while (LIKELY((newPage = bucket->emptyPagesHead) != nullptr)) { | 791 while (LIKELY((newPage = bucket->emptyPagesHead) != nullptr)) { |
| 776 ASSERT(partitionPageStateIsEmpty(newPage)); | 792 ASSERT(newPage->bucket == bucket); |
| 793 ASSERT(partitionPageStateIsEmpty(newPage) || partitionPageStateIsDec ommitted(newPage)); | |
| 777 bucket->emptyPagesHead = newPage->nextPage; | 794 bucket->emptyPagesHead = newPage->nextPage; |
| 778 // Accept the empty page unless it got decommitted. | 795 // Accept the empty page unless it got decommitted. |
| 779 if (newPage->freelistHead) { | 796 if (newPage->freelistHead) { |
| 780 newPage->nextPage = nullptr; | 797 newPage->nextPage = nullptr; |
| 781 break; | 798 break; |
| 782 } | 799 } |
| 783 ASSERT(partitionPageStateIsDecommitted(newPage)); | 800 ASSERT(partitionPageStateIsDecommitted(newPage)); |
| 784 newPage->nextPage = bucket->decommittedPagesHead; | 801 newPage->nextPage = bucket->decommittedPagesHead; |
| 785 bucket->decommittedPagesHead = newPage; | 802 bucket->decommittedPagesHead = newPage; |
| 786 } | 803 } |
| 787 if (UNLIKELY(!newPage) && LIKELY(bucket->decommittedPagesHead != nullptr )) { | 804 if (UNLIKELY(!newPage) && LIKELY(bucket->decommittedPagesHead != nullptr )) { |
| 788 newPage = bucket->decommittedPagesHead; | 805 newPage = bucket->decommittedPagesHead; |
| 806 ASSERT(newPage->bucket == bucket); | |
| 807 ASSERT(partitionPageStateIsDecommitted(newPage)); | |
| 789 bucket->decommittedPagesHead = newPage->nextPage; | 808 bucket->decommittedPagesHead = newPage->nextPage; |
| 790 ASSERT(partitionPageStateIsDecommitted(newPage)); | |
| 791 void* addr = partitionPageToPointer(newPage); | 809 void* addr = partitionPageToPointer(newPage); |
| 792 partitionRecommitSystemPages(root, addr, partitionBucketBytes(newPag e->bucket)); | 810 partitionRecommitSystemPages(root, addr, partitionBucketBytes(newPag e->bucket)); |
| 793 partitionPageReset(newPage, bucket); | 811 partitionPageReset(newPage); |
| 794 } | 812 } |
| 795 ASSERT(newPage); | 813 ASSERT(newPage); |
| 796 } else { | 814 } else { |
| 797 // Third. If we get here, we need a brand new page. | 815 // Third. If we get here, we need a brand new page. |
| 798 uint16_t numPartitionPages = partitionBucketPartitionPages(bucket); | 816 uint16_t numPartitionPages = partitionBucketPartitionPages(bucket); |
| 799 void* rawPages = partitionAllocPartitionPages(root, flags, numPartitionP ages); | 817 void* rawPages = partitionAllocPartitionPages(root, flags, numPartitionP ages); |
| 800 if (LIKELY(rawPages != nullptr)) { | 818 if (LIKELY(rawPages != nullptr)) { |
| 801 newPage = partitionPointerToPageNoAlignmentCheck(rawPages); | 819 newPage = partitionPointerToPageNoAlignmentCheck(rawPages); |
| 802 partitionPageSetup(newPage, bucket); | 820 partitionPageSetup(newPage, bucket); |
| 803 } | 821 } |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 826 return entry; | 844 return entry; |
| 827 } | 845 } |
| 828 // Otherwise, we need to build the freelist. | 846 // Otherwise, we need to build the freelist. |
| 829 ASSERT(newPage->numUnprovisionedSlots); | 847 ASSERT(newPage->numUnprovisionedSlots); |
| 830 return partitionPageAllocAndFillFreelist(newPage); | 848 return partitionPageAllocAndFillFreelist(newPage); |
| 831 } | 849 } |
| 832 | 850 |
| 833 static ALWAYS_INLINE void partitionDecommitPage(PartitionRootBase* root, Partiti onPage* page) | 851 static ALWAYS_INLINE void partitionDecommitPage(PartitionRootBase* root, Partiti onPage* page) |
| 834 { | 852 { |
| 835 ASSERT(partitionPageStateIsEmpty(page)); | 853 ASSERT(partitionPageStateIsEmpty(page)); |
| 836 ASSERT(page->freelistHead); | |
| 837 ASSERT(!partitionBucketIsDirectMapped(page->bucket)); | 854 ASSERT(!partitionBucketIsDirectMapped(page->bucket)); |
| 838 void* addr = partitionPageToPointer(page); | 855 void* addr = partitionPageToPointer(page); |
| 839 partitionDecommitSystemPages(root, addr, partitionBucketBytes(page->bucket)) ; | 856 partitionDecommitSystemPages(root, addr, partitionBucketBytes(page->bucket)) ; |
| 840 | 857 |
| 841 // We actually leave the decommitted page in the active list. We'll sweep | 858 // We actually leave the decommitted page in the active list. We'll sweep |
| 842 // it on to the decommitted page list when we next walk the active page | 859 // it on to the decommitted page list when we next walk the active page |
| 843 // list. | 860 // list. |
| 844 // Pulling this trick enables us to use a singly-linked page list for all | 861 // Pulling this trick enables us to use a singly-linked page list for all |
| 845 // cases, which is critical in keeping the page metadata structure down to | 862 // cases, which is critical in keeping the page metadata structure down to |
| 846 // 32 bytes in size. | 863 // 32 bytes in size. |
| 847 page->freelistHead = 0; | 864 page->freelistHead = 0; |
| 848 page->numUnprovisionedSlots = 0; | 865 page->numUnprovisionedSlots = 0; |
|
haraken
2015/06/24 00:51:52
Shall we add ASSERT(partitionPageStateIsDecommitte
| |
| 849 } | 866 } |
| 850 | 867 |
| 851 static void partitionDecommitPageIfPossible(PartitionRootBase* root, PartitionPa ge* page) | 868 static void partitionDecommitPageIfPossible(PartitionRootBase* root, PartitionPa ge* page) |
| 852 { | 869 { |
| 853 ASSERT(page->emptyCacheIndex >= 0); | 870 ASSERT(page->emptyCacheIndex >= 0); |
| 854 ASSERT(static_cast<unsigned>(page->emptyCacheIndex) < kMaxFreeableSpans); | 871 ASSERT(static_cast<unsigned>(page->emptyCacheIndex) < kMaxFreeableSpans); |
| 855 ASSERT(page == root->globalEmptyPageRing[page->emptyCacheIndex]); | 872 ASSERT(page == root->globalEmptyPageRing[page->emptyCacheIndex]); |
| 856 if (!page->numAllocatedSlots && page->freelistHead) { | 873 if (partitionPageStateIsEmpty(page)) |
| 857 // The page is still empty, and not decommitted, so _really_ decommit | |
| 858 // it. | |
| 859 partitionDecommitPage(root, page); | 874 partitionDecommitPage(root, page); |
| 860 } | 875 |
| 861 page->emptyCacheIndex = -1; | 876 page->emptyCacheIndex = -1; |
| 862 } | 877 } |
| 863 | 878 |
| 864 static ALWAYS_INLINE void partitionRegisterEmptyPage(PartitionPage* page) | 879 static ALWAYS_INLINE void partitionRegisterEmptyPage(PartitionPage* page) |
| 865 { | 880 { |
| 866 ASSERT(partitionPageStateIsEmpty(page)); | 881 ASSERT(partitionPageStateIsEmpty(page)); |
| 867 PartitionRootBase* root = partitionPageToRoot(page); | 882 PartitionRootBase* root = partitionPageToRoot(page); |
| 868 | 883 |
| 869 // If the page is already registered as empty, give it another life. | 884 // If the page is already registered as empty, give it another life. |
| 870 if (page->emptyCacheIndex != -1) { | 885 if (page->emptyCacheIndex != -1) { |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1183 if (rawSize) | 1198 if (rawSize) |
| 1184 statsOut->activeBytes += static_cast<uint32_t>(rawSize); | 1199 statsOut->activeBytes += static_cast<uint32_t>(rawSize); |
| 1185 else | 1200 else |
| 1186 statsOut->activeBytes += (page->numAllocatedSlots * statsOut->bucketSlot Size); | 1201 statsOut->activeBytes += (page->numAllocatedSlots * statsOut->bucketSlot Size); |
| 1187 | 1202 |
| 1188 size_t pageBytesResident = partitionRoundUpToSystemPage((bucketNumSlots - pa ge->numUnprovisionedSlots) * statsOut->bucketSlotSize); | 1203 size_t pageBytesResident = partitionRoundUpToSystemPage((bucketNumSlots - pa ge->numUnprovisionedSlots) * statsOut->bucketSlotSize); |
| 1189 statsOut->residentBytes += pageBytesResident; | 1204 statsOut->residentBytes += pageBytesResident; |
| 1190 if (partitionPageStateIsEmpty(page)) { | 1205 if (partitionPageStateIsEmpty(page)) { |
| 1191 statsOut->decommittableBytes += pageBytesResident; | 1206 statsOut->decommittableBytes += pageBytesResident; |
| 1192 ++statsOut->numEmptyPages; | 1207 ++statsOut->numEmptyPages; |
| 1193 } else if (page->numAllocatedSlots == bucketNumSlots) { | 1208 } else if (partitionPageStateIsFull(page)) { |
| 1194 ++statsOut->numFullPages; | 1209 ++statsOut->numFullPages; |
| 1195 } else { | 1210 } else { |
| 1196 ASSERT(page->numAllocatedSlots > 0); | 1211 ASSERT(partitionPageStateIsActive(page)); |
| 1197 ++statsOut->numActivePages; | 1212 ++statsOut->numActivePages; |
| 1198 } | 1213 } |
| 1199 } | 1214 } |
| 1200 | 1215 |
| 1201 static void partitionDumpBucketStats(PartitionBucketMemoryStats* statsOut, const PartitionBucket* bucket) | 1216 static void partitionDumpBucketStats(PartitionBucketMemoryStats* statsOut, const PartitionBucket* bucket) |
| 1202 { | 1217 { |
| 1203 ASSERT(!partitionBucketIsDirectMapped(bucket)); | 1218 ASSERT(!partitionBucketIsDirectMapped(bucket)); |
| 1204 statsOut->isValid = false; | 1219 statsOut->isValid = false; |
| 1205 // If the active page list is empty (== &PartitionRootGeneric::gSeedPage), | 1220 // If the active page list is empty (== &PartitionRootGeneric::gSeedPage), |
| 1206 // the bucket might still need to be reported if it has a list of empty, | 1221 // the bucket might still need to be reported if it has a list of empty, |
| 1207 // decommitted or full pages. | 1222 // decommitted or full pages. |
| 1208 if (bucket->activePagesHead == &PartitionRootGeneric::gSeedPage && !bucket-> emptyPagesHead && !bucket->decommittedPagesHead && !bucket->numFullPages) | 1223 if (bucket->activePagesHead == &PartitionRootGeneric::gSeedPage && !bucket-> emptyPagesHead && !bucket->decommittedPagesHead && !bucket->numFullPages) |
| 1209 return; | 1224 return; |
| 1210 | 1225 |
| 1211 memset(statsOut, '\0', sizeof(*statsOut)); | 1226 memset(statsOut, '\0', sizeof(*statsOut)); |
| 1212 statsOut->isValid = true; | 1227 statsOut->isValid = true; |
| 1213 statsOut->isDirectMap = false; | 1228 statsOut->isDirectMap = false; |
| 1214 statsOut->numFullPages = static_cast<size_t>(bucket->numFullPages); | 1229 statsOut->numFullPages = static_cast<size_t>(bucket->numFullPages); |
| 1215 statsOut->bucketSlotSize = bucket->slotSize; | 1230 statsOut->bucketSlotSize = bucket->slotSize; |
| 1216 uint16_t bucketNumSlots = partitionBucketSlots(bucket); | 1231 uint16_t bucketNumSlots = partitionBucketSlots(bucket); |
| 1217 size_t bucketUsefulStorage = statsOut->bucketSlotSize * bucketNumSlots; | 1232 size_t bucketUsefulStorage = statsOut->bucketSlotSize * bucketNumSlots; |
| 1218 statsOut->allocatedPageSize = partitionBucketBytes(bucket); | 1233 statsOut->allocatedPageSize = partitionBucketBytes(bucket); |
| 1219 statsOut->activeBytes = bucket->numFullPages * bucketUsefulStorage; | 1234 statsOut->activeBytes = bucket->numFullPages * bucketUsefulStorage; |
| 1220 statsOut->residentBytes = bucket->numFullPages * statsOut->allocatedPageSize ; | 1235 statsOut->residentBytes = bucket->numFullPages * statsOut->allocatedPageSize ; |
| 1221 | 1236 |
| 1222 for (const PartitionPage* page = bucket->emptyPagesHead; page; page = page-> nextPage) { | 1237 for (const PartitionPage* page = bucket->emptyPagesHead; page; page = page-> nextPage) { |
| 1223 ASSERT(partitionPageStateIsEmpty(page)); | 1238 ASSERT(partitionPageStateIsEmpty(page) || partitionPageStateIsDecommitte d(page)); |
| 1224 partitionDumpPageStats(statsOut, page); | 1239 partitionDumpPageStats(statsOut, page); |
| 1225 } | 1240 } |
| 1226 for (const PartitionPage* page = bucket->decommittedPagesHead; page; page = page->nextPage) { | 1241 for (const PartitionPage* page = bucket->decommittedPagesHead; page; page = page->nextPage) { |
| 1227 ASSERT(partitionPageStateIsDecommitted(page)); | 1242 ASSERT(partitionPageStateIsDecommitted(page)); |
| 1228 partitionDumpPageStats(statsOut, page); | 1243 partitionDumpPageStats(statsOut, page); |
| 1229 } | 1244 } |
| 1230 | 1245 |
| 1231 if (bucket->activePagesHead != &PartitionRootGeneric::gSeedPage) { | 1246 if (bucket->activePagesHead != &PartitionRootGeneric::gSeedPage) { |
| 1232 for (const PartitionPage* page = bucket->activePagesHead; page; page = p age->nextPage) { | 1247 for (const PartitionPage* page = bucket->activePagesHead; page; page = p age->nextPage) { |
| 1233 ASSERT(page != &PartitionRootGeneric::gSeedPage); | 1248 ASSERT(page != &PartitionRootGeneric::gSeedPage); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1301 // partitionsDumpBucketStats is called after collecting stats because it | 1316 // partitionsDumpBucketStats is called after collecting stats because it |
| 1302 // can use PartitionAlloc to allocate and this can affect the statistics. | 1317 // can use PartitionAlloc to allocate and this can affect the statistics. |
| 1303 for (size_t i = 0; i < partitionNumBuckets; ++i) { | 1318 for (size_t i = 0; i < partitionNumBuckets; ++i) { |
| 1304 if (memoryStats[i].isValid) | 1319 if (memoryStats[i].isValid) |
| 1305 partitionStatsDumper->partitionsDumpBucketStats(partitionName, &memo ryStats[i]); | 1320 partitionStatsDumper->partitionsDumpBucketStats(partitionName, &memo ryStats[i]); |
| 1306 } | 1321 } |
| 1307 } | 1322 } |
| 1308 | 1323 |
| 1309 } // namespace WTF | 1324 } // namespace WTF |
| 1310 | 1325 |
| OLD | NEW |