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 |