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 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 goto partitionAllocSlowPathFailed; | 692 goto partitionAllocSlowPathFailed; |
693 // Skip the alignment check because it depends on page->bucket, which is
not yet set. | 693 // Skip the alignment check because it depends on page->bucket, which is
not yet set. |
694 newPage = partitionPointerToPageNoAlignmentCheck(rawNewPage); | 694 newPage = partitionPointerToPageNoAlignmentCheck(rawNewPage); |
695 } | 695 } |
696 | 696 |
697 partitionPageReset(newPage, bucket); | 697 partitionPageReset(newPage, bucket); |
698 bucket->activePagesHead = newPage; | 698 bucket->activePagesHead = newPage; |
699 return partitionPageAllocAndFillFreelist(newPage); | 699 return partitionPageAllocAndFillFreelist(newPage); |
700 | 700 |
701 partitionAllocSlowPathFailed: | 701 partitionAllocSlowPathFailed: |
702 if (returnNull) | 702 if (returnNull) { |
| 703 // If we get here, we will set the active page to null, which is an |
| 704 // invalid state. To support continued use of this bucket, we need to |
| 705 // restore a valid state, by setting the active page to the seed page. |
| 706 bucket->activePagesHead = &PartitionRootGeneric::gSeedPage; |
703 return nullptr; | 707 return nullptr; |
| 708 } |
704 partitionOutOfMemory(); | 709 partitionOutOfMemory(); |
705 return nullptr; | 710 return nullptr; |
706 } | 711 } |
707 | 712 |
708 static ALWAYS_INLINE void partitionFreePage(PartitionRootBase* root, PartitionPa
ge* page) | 713 static ALWAYS_INLINE void partitionFreePage(PartitionRootBase* root, PartitionPa
ge* page) |
709 { | 714 { |
710 ASSERT(page->freelistHead); | 715 ASSERT(page->freelistHead); |
711 ASSERT(!page->numAllocatedSlots); | 716 ASSERT(!page->numAllocatedSlots); |
712 partitionUnusePage(root, page); | 717 partitionUnusePage(root, page); |
713 // We actually leave the freed page in the active list. We'll sweep it on | 718 // We actually leave the freed page in the active list. We'll sweep it on |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 ++currentIndex; | 761 ++currentIndex; |
757 if (currentIndex == kMaxFreeableSpans) | 762 if (currentIndex == kMaxFreeableSpans) |
758 currentIndex = 0; | 763 currentIndex = 0; |
759 root->globalEmptyPageRingIndex = currentIndex; | 764 root->globalEmptyPageRingIndex = currentIndex; |
760 } | 765 } |
761 | 766 |
762 void partitionFreeSlowPath(PartitionPage* page) | 767 void partitionFreeSlowPath(PartitionPage* page) |
763 { | 768 { |
764 PartitionBucket* bucket = page->bucket; | 769 PartitionBucket* bucket = page->bucket; |
765 ASSERT(page != &PartitionRootGeneric::gSeedPage); | 770 ASSERT(page != &PartitionRootGeneric::gSeedPage); |
766 ASSERT(bucket->activePagesHead != &PartitionRootGeneric::gSeedPage); | |
767 if (LIKELY(page->numAllocatedSlots == 0)) { | 771 if (LIKELY(page->numAllocatedSlots == 0)) { |
768 // Page became fully unused. | 772 // Page became fully unused. |
769 if (UNLIKELY(partitionBucketIsDirectMapped(bucket))) { | 773 if (UNLIKELY(partitionBucketIsDirectMapped(bucket))) { |
770 partitionDirectUnmap(page); | 774 partitionDirectUnmap(page); |
771 return; | 775 return; |
772 } | 776 } |
773 // If it's the current active page, attempt to change it. We'd prefer to
leave | 777 // If it's the current active page, attempt to change it. We'd prefer to
leave |
774 // the page empty as a gentle force towards defragmentation. | 778 // the page empty as a gentle force towards defragmentation. |
775 if (LIKELY(page == bucket->activePagesHead) && page->nextPage) { | 779 if (LIKELY(page == bucket->activePagesHead) && page->nextPage) { |
776 if (partitionSetNewActivePage(page->nextPage)) { | 780 if (partitionSetNewActivePage(page->nextPage)) { |
(...skipping 17 matching lines...) Expand all Loading... |
794 ASSERT(page->numAllocatedSlots < 0); | 798 ASSERT(page->numAllocatedSlots < 0); |
795 // A transition of numAllocatedSlots from 0 to -1 is not legal, and | 799 // A transition of numAllocatedSlots from 0 to -1 is not legal, and |
796 // likely indicates a double-free. | 800 // likely indicates a double-free. |
797 RELEASE_ASSERT(page->numAllocatedSlots != -1); | 801 RELEASE_ASSERT(page->numAllocatedSlots != -1); |
798 page->numAllocatedSlots = -page->numAllocatedSlots - 2; | 802 page->numAllocatedSlots = -page->numAllocatedSlots - 2; |
799 ASSERT(page->numAllocatedSlots == partitionBucketSlots(bucket) - 1); | 803 ASSERT(page->numAllocatedSlots == partitionBucketSlots(bucket) - 1); |
800 // Fully used page became partially used. It must be put back on the | 804 // Fully used page became partially used. It must be put back on the |
801 // non-full page list. Also make it the current page to increase the | 805 // non-full page list. Also make it the current page to increase the |
802 // chances of it being filled up again. The old current page will be | 806 // chances of it being filled up again. The old current page will be |
803 // the next page. | 807 // the next page. |
804 page->nextPage = bucket->activePagesHead; | 808 if (UNLIKELY(bucket->activePagesHead == &PartitionRootGeneric::gSeedPage
)) |
| 809 page->nextPage = 0; |
| 810 else |
| 811 page->nextPage = bucket->activePagesHead; |
805 bucket->activePagesHead = page; | 812 bucket->activePagesHead = page; |
806 --bucket->numFullPages; | 813 --bucket->numFullPages; |
807 // Special case: for a partition page with just a single slot, it may | 814 // Special case: for a partition page with just a single slot, it may |
808 // now be empty and we want to run it through the empty logic. | 815 // now be empty and we want to run it through the empty logic. |
809 if (UNLIKELY(page->numAllocatedSlots == 0)) | 816 if (UNLIKELY(page->numAllocatedSlots == 0)) |
810 partitionFreeSlowPath(page); | 817 partitionFreeSlowPath(page); |
811 } | 818 } |
812 } | 819 } |
813 | 820 |
814 bool partitionReallocDirectMappedInPlace(PartitionRootGeneric* root, PartitionPa
ge* page, size_t newSize) | 821 bool partitionReallocDirectMappedInPlace(PartitionRootGeneric* root, PartitionPa
ge* page, size_t newSize) |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
973 printf("total live: %zu bytes\n", totalLive); | 980 printf("total live: %zu bytes\n", totalLive); |
974 printf("total resident: %zu bytes\n", totalResident); | 981 printf("total resident: %zu bytes\n", totalResident); |
975 printf("total freeable: %zu bytes\n", totalFreeable); | 982 printf("total freeable: %zu bytes\n", totalFreeable); |
976 fflush(stdout); | 983 fflush(stdout); |
977 } | 984 } |
978 | 985 |
979 #endif // !NDEBUG | 986 #endif // !NDEBUG |
980 | 987 |
981 } // namespace WTF | 988 } // namespace WTF |
982 | 989 |
OLD | NEW |