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 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 569 PartitionBucket* bucket = reinterpret_cast<PartitionBucket*>(reinterpret_cas t<char*>(page) + kPageMetadataSize); | 569 PartitionBucket* bucket = reinterpret_cast<PartitionBucket*>(reinterpret_cas t<char*>(page) + kPageMetadataSize); |
| 570 page->freelistHead = 0; | 570 page->freelistHead = 0; |
| 571 page->nextPage = 0; | 571 page->nextPage = 0; |
| 572 page->bucket = bucket; | 572 page->bucket = bucket; |
| 573 page->numAllocatedSlots = 1; | 573 page->numAllocatedSlots = 1; |
| 574 page->numUnprovisionedSlots = 0; | 574 page->numUnprovisionedSlots = 0; |
| 575 page->pageOffset = 0; | 575 page->pageOffset = 0; |
| 576 page->freeCacheIndex = 0; | 576 page->freeCacheIndex = 0; |
| 577 | 577 |
| 578 bucket->activePagesHead = 0; | 578 bucket->activePagesHead = 0; |
| 579 bucket->freePagesHead = 0; | 579 bucket->freePagesHead = reinterpret_cast<PartitionPage*>(ret + size); |
| 580 bucket->slotSize = size; | 580 bucket->slotSize = size; |
| 581 bucket->numSystemPagesPerSlotSpan = 0; | 581 bucket->numSystemPagesPerSlotSpan = 0; |
| 582 bucket->numFullPages = 0; | 582 bucket->numFullPages = 0; |
| 583 | 583 |
| 584 return ret; | 584 return ret; |
| 585 } | 585 } |
| 586 | 586 |
| 587 static ALWAYS_INLINE void partitionDirectUnmap(PartitionPage* page) | 587 static ALWAYS_INLINE void partitionDirectUnmap(PartitionPage* page) |
| 588 { | 588 { |
| 589 size_t unmapSize = page->bucket->slotSize; | 589 size_t unmapSize = page->bucket->slotSize; |
|
Jens Widell
2014/02/27 17:02:56
This would need adjusting to use page->bucket->fre
| |
| 590 // Add on the size of the trailing guard page and preceeding partition | 590 // Add on the size of the trailing guard page and preceeding partition |
| 591 // page, then round up to allocation granularity. | 591 // page, then round up to allocation granularity. |
| 592 unmapSize += kPartitionPageSize + kSystemPageSize; | 592 unmapSize += kPartitionPageSize + kSystemPageSize; |
| 593 unmapSize += kPageAllocationGranularityOffsetMask; | 593 unmapSize += kPageAllocationGranularityOffsetMask; |
| 594 unmapSize &= kPageAllocationGranularityBaseMask; | 594 unmapSize &= kPageAllocationGranularityBaseMask; |
| 595 | 595 |
| 596 char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page)); | 596 char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page)); |
| 597 // Account for the mapping starting a partition page before the actual | 597 // Account for the mapping starting a partition page before the actual |
| 598 // allocation address. | 598 // allocation address. |
| 599 ptr -= kPartitionPageSize; | 599 ptr -= kPartitionPageSize; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 756 page->nextPage = bucket->activePagesHead; | 756 page->nextPage = bucket->activePagesHead; |
| 757 bucket->activePagesHead = page; | 757 bucket->activePagesHead = page; |
| 758 --bucket->numFullPages; | 758 --bucket->numFullPages; |
| 759 // Special case: for a partition page with just a single slot, it may | 759 // Special case: for a partition page with just a single slot, it may |
| 760 // now be empty and we want to run it through the empty logic. | 760 // now be empty and we want to run it through the empty logic. |
| 761 if (UNLIKELY(page->numAllocatedSlots == 0)) | 761 if (UNLIKELY(page->numAllocatedSlots == 0)) |
| 762 partitionFreeSlowPath(page); | 762 partitionFreeSlowPath(page); |
| 763 } | 763 } |
| 764 } | 764 } |
| 765 | 765 |
| 766 bool partitionReallocDirectMappedInPlace(PartitionRootGeneric* root, void* ptr, size_t newSize) | |
| 767 { | |
| 768 newSize = partitionCookieSizeAdjustAdd(newSize); | |
| 769 ASSERT(partitionDirectMapSize(newSize) == newSize); | |
| 770 | |
| 771 char* realPtr = static_cast<char*>(partitionCookieFreePointerAdjust(ptr)); | |
| 772 PartitionBucket* bucket = partitionPointerToPage(realPtr)->bucket; | |
| 773 | |
| 774 // bucket->slotSize is the current size of the allocation. | |
| 775 // bucket->freePagesHead points to the first system page beyond what we | |
| 776 // first allocated; we can grow the allocation up to that point. | |
| 777 | |
| 778 ASSERT(partitionBucketIsDirectMapped(bucket)); | |
| 779 | |
| 780 if (newSize < bucket->slotSize) { | |
| 781 // Shrink by decommitting unneeded pages and making them inaccessible. | |
| 782 // TODO: maybe refuse if the new size is too much smaller? | |
| 783 decommitSystemPages(realPtr + newSize, bucket->slotSize - newSize); | |
| 784 setSystemPagesInaccessible(realPtr + newSize, kSystemPageSize); | |
|
Jens Widell
2014/02/27 17:10:53
Ought to make all decommitted pages inaccessible (
| |
| 785 } else if (realPtr + newSize <= reinterpret_cast<char*>(bucket->freePagesHea d)) { | |
| 786 // Grow within the actually allocated memory. Just need to make the | |
| 787 // pages accessible again. | |
| 788 setSystemPagesAccessible(realPtr + bucket->slotSize, newSize - bucket->s lotSize); | |
| 789 | |
| 790 #ifndef NDEBUG | |
| 791 memset(realPtr + bucket->slotSize, kUninitializedByte, newSize - bucket- >slotSize); | |
| 792 #endif | |
| 793 } else { | |
| 794 // We can't perform the realloc in-place. | |
| 795 return false; | |
| 796 } | |
| 797 | |
| 798 #ifndef NDEBUG | |
| 799 // Write a new trailing cookie. | |
| 800 partitionCookieWriteValue(realPtr + newSize - kCookieSize); | |
| 801 #endif | |
| 802 | |
| 803 bucket->slotSize = newSize; | |
| 804 return true; | |
| 805 } | |
| 806 | |
| 766 void* partitionReallocGeneric(PartitionRootGeneric* root, void* ptr, size_t newS ize) | 807 void* partitionReallocGeneric(PartitionRootGeneric* root, void* ptr, size_t newS ize) |
| 767 { | 808 { |
| 768 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) | 809 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) |
| 769 return realloc(ptr, newSize); | 810 return realloc(ptr, newSize); |
| 770 #else | 811 #else |
| 771 if (UNLIKELY(!ptr)) | 812 if (UNLIKELY(!ptr)) |
| 772 return partitionAllocGeneric(root, newSize); | 813 return partitionAllocGeneric(root, newSize); |
| 773 if (UNLIKELY(!newSize)) { | 814 if (UNLIKELY(!newSize)) { |
| 774 partitionFreeGeneric(root, ptr); | 815 partitionFreeGeneric(root, ptr); |
| 775 return 0; | 816 return 0; |
| 776 } | 817 } |
| 777 | 818 |
| 778 ASSERT(partitionPointerIsValid(partitionCookieFreePointerAdjust(ptr))); | 819 ASSERT(partitionPointerIsValid(partitionCookieFreePointerAdjust(ptr))); |
| 779 | 820 |
| 780 size_t actualNewSize = partitionAllocActualSize(root, newSize); | 821 size_t actualNewSize = partitionAllocActualSize(root, newSize); |
| 781 size_t actualOldSize = partitionAllocGetSize(ptr); | 822 size_t actualOldSize = partitionAllocGetSize(ptr); |
| 782 | 823 |
| 783 // TODO: note that tcmalloc will "ignore" a downsizing realloc() unless the | 824 // TODO: note that tcmalloc will "ignore" a downsizing realloc() unless the |
| 784 // new size is a significant percentage smaller. We could do the same if we | 825 // new size is a significant percentage smaller. We could do the same if we |
| 785 // determine it is a win. | 826 // determine it is a win. |
| 786 if (actualNewSize == actualOldSize) { | 827 if (actualNewSize == actualOldSize) { |
| 787 // Trying to allocate a block of size newSize would give us a block of | 828 // Trying to allocate a block of size newSize would give us a block of |
| 788 // the same size as the one we've already got, so no point in doing | 829 // the same size as the one we've already got, so no point in doing |
| 789 // anything here. | 830 // anything here. |
| 790 // TODO: for an upsize or downsize on a direct mapped allocation, we | |
| 791 // should really try and resize it in-place. | |
| 792 return ptr; | 831 return ptr; |
| 793 } | 832 } |
| 794 | 833 |
| 834 if (partitionSizeIsDirectMapped(actualOldSize) && partitionSizeIsDirectMappe d(actualNewSize)) { | |
| 835 // We may be able to perform the realloc in place by changing the | |
| 836 // accessibility of memory pages and, if reducing the size, decommitting | |
| 837 // them. | |
| 838 if (partitionReallocDirectMappedInPlace(root, ptr, actualNewSize)) | |
| 839 return ptr; | |
| 840 } | |
| 841 | |
| 795 // This realloc cannot be resized in-place. Sadness. | 842 // This realloc cannot be resized in-place. Sadness. |
| 796 void* ret = partitionAllocGeneric(root, newSize); | 843 void* ret = partitionAllocGeneric(root, newSize); |
| 797 size_t copySize = actualOldSize; | 844 size_t copySize = actualOldSize; |
| 798 if (newSize < copySize) | 845 if (newSize < copySize) |
| 799 copySize = newSize; | 846 copySize = newSize; |
| 800 | 847 |
| 801 memcpy(ret, ptr, copySize); | 848 memcpy(ret, ptr, copySize); |
| 802 partitionFreeGeneric(root, ptr); | 849 partitionFreeGeneric(root, ptr); |
| 803 return ret; | 850 return ret; |
| 804 #endif | 851 #endif |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 855 printf("total live: %zu bytes\n", totalLive); | 902 printf("total live: %zu bytes\n", totalLive); |
| 856 printf("total resident: %zu bytes\n", totalResident); | 903 printf("total resident: %zu bytes\n", totalResident); |
| 857 printf("total freeable: %zu bytes\n", totalFreeable); | 904 printf("total freeable: %zu bytes\n", totalFreeable); |
| 858 fflush(stdout); | 905 fflush(stdout); |
| 859 } | 906 } |
| 860 | 907 |
| 861 #endif // !NDEBUG | 908 #endif // !NDEBUG |
| 862 | 909 |
| 863 } // namespace WTF | 910 } // namespace WTF |
| 864 | 911 |
| OLD | NEW |