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 13 matching lines...) Expand all Loading... | |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 #include "wtf/PartitionAlloc.h" | 32 #include "wtf/PartitionAlloc.h" |
| 33 | 33 |
| 34 #include "wtf/Atomics.h" | |
| 35 | |
| 34 #include <string.h> | 36 #include <string.h> |
| 35 | 37 |
| 36 #ifndef NDEBUG | 38 #ifndef NDEBUG |
| 37 #include <stdio.h> | 39 #include <stdio.h> |
| 38 #endif | 40 #endif |
| 39 | 41 |
| 40 // Two partition pages are used as guard / metadata page so make sure the super | 42 // Two partition pages are used as guard / metadata page so make sure the super |
| 41 // page size is bigger. | 43 // page size is bigger. |
| 42 COMPILE_ASSERT(WTF::kPartitionPageSize * 4 <= WTF::kSuperPageSize, ok_super_page _size); | 44 COMPILE_ASSERT(WTF::kPartitionPageSize * 4 <= WTF::kSuperPageSize, ok_super_page _size); |
| 43 COMPILE_ASSERT(!(WTF::kSuperPageSize % WTF::kPartitionPageSize), ok_super_page_m ultiple); | 45 COMPILE_ASSERT(!(WTF::kSuperPageSize % WTF::kPartitionPageSize), ok_super_page_m ultiple); |
| 44 // Four system pages gives us room to hack out a still-guard-paged piece | 46 // Four system pages gives us room to hack out a still-guard-paged piece |
| 45 // of metadata in the middle of a guard partition page. | 47 // of metadata in the middle of a guard partition page. |
| 46 COMPILE_ASSERT(WTF::kSystemPageSize * 4 <= WTF::kPartitionPageSize, ok_partition _page_size); | 48 COMPILE_ASSERT(WTF::kSystemPageSize * 4 <= WTF::kPartitionPageSize, ok_partition _page_size); |
| 47 COMPILE_ASSERT(!(WTF::kPartitionPageSize % WTF::kSystemPageSize), ok_partition_p age_multiple); | 49 COMPILE_ASSERT(!(WTF::kPartitionPageSize % WTF::kSystemPageSize), ok_partition_p age_multiple); |
| 48 COMPILE_ASSERT(sizeof(WTF::PartitionPage) <= WTF::kPageMetadataSize, PartitionPa ge_not_too_big); | 50 COMPILE_ASSERT(sizeof(WTF::PartitionPage) <= WTF::kPageMetadataSize, PartitionPa ge_not_too_big); |
| 49 COMPILE_ASSERT(sizeof(WTF::PartitionBucket) <= WTF::kPageMetadataSize, Partition Bucket_not_too_big); | 51 COMPILE_ASSERT(sizeof(WTF::PartitionBucket) <= WTF::kPageMetadataSize, Partition Bucket_not_too_big); |
| 50 COMPILE_ASSERT(sizeof(WTF::PartitionSuperPageExtentEntry) <= WTF::kPageMetadataS ize, PartitionSuperPageExtentEntry_not_too_big); | 52 COMPILE_ASSERT(sizeof(WTF::PartitionSuperPageExtentEntry) <= WTF::kPageMetadataS ize, PartitionSuperPageExtentEntry_not_too_big); |
| 51 COMPILE_ASSERT(WTF::kPageMetadataSize * WTF::kNumPartitionPagesPerSuperPage <= W TF::kSystemPageSize, page_metadata_fits_in_hole); | 53 COMPILE_ASSERT(WTF::kPageMetadataSize * WTF::kNumPartitionPagesPerSuperPage <= W TF::kSystemPageSize, page_metadata_fits_in_hole); |
| 52 // Check that some of our zanier calculations worked out as expected. | 54 // Check that some of our zanier calculations worked out as expected. |
| 53 COMPILE_ASSERT(WTF::kGenericSmallestBucket == 8, generic_smallest_bucket); | 55 COMPILE_ASSERT(WTF::kGenericSmallestBucket == 8, generic_smallest_bucket); |
| 54 COMPILE_ASSERT(WTF::kGenericMaxBucketed == 983040, generic_max_bucketed); | 56 COMPILE_ASSERT(WTF::kGenericMaxBucketed == 983040, generic_max_bucketed); |
| 55 | 57 |
| 56 namespace WTF { | 58 namespace WTF { |
| 57 | 59 |
| 60 enum PartitionAllocFlagsInternal { | |
| 61 // Flags after to start after all flags in PartitionAllocFlags. | |
| 62 PartitionAllocRetry = 1 << 1, | |
| 63 }; | |
| 64 | |
| 58 int PartitionRootBase::gInitializedLock = 0; | 65 int PartitionRootBase::gInitializedLock = 0; |
| 59 bool PartitionRootBase::gInitialized = false; | 66 bool PartitionRootBase::gInitialized = false; |
| 60 PartitionPage PartitionRootBase::gSeedPage; | 67 PartitionPage PartitionRootBase::gSeedPage; |
| 61 PartitionBucket PartitionRootBase::gPagedBucket; | 68 PartitionBucket PartitionRootBase::gPagedBucket; |
| 62 | 69 |
| 63 static uint16_t partitionBucketNumSystemPages(size_t size) | 70 static uint16_t partitionBucketNumSystemPages(size_t size) |
| 64 { | 71 { |
| 65 // This works out reasonably for the current bucket sizes of the generic | 72 // This works out reasonably for the current bucket sizes of the generic |
| 66 // allocator, and the current values of partition page size and constants. | 73 // allocator, and the current values of partition page size and constants. |
| 67 // Specifically, we have enough room to always pack the slots perfectly into | 74 // Specifically, we have enough room to always pack the slots perfectly into |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 294 } | 301 } |
| 295 partitionAllocBaseShutdown(root); | 302 partitionAllocBaseShutdown(root); |
| 296 return noLeaks; | 303 return noLeaks; |
| 297 } | 304 } |
| 298 | 305 |
| 299 static NEVER_INLINE void partitionOutOfMemory() | 306 static NEVER_INLINE void partitionOutOfMemory() |
| 300 { | 307 { |
| 301 IMMEDIATE_CRASH(); | 308 IMMEDIATE_CRASH(); |
| 302 } | 309 } |
| 303 | 310 |
| 311 static PartitionFreeUpMemoryCallback s_partitionFreeUpMemoryCallback = nullptr; | |
| 312 static volatile int s_partitionFreeUpMemoryRecusionCount = 0; | |
| 313 | |
| 314 void partitionSetFreeUpMemoryCallback(PartitionFreeUpMemoryCallback callback) | |
| 315 { | |
| 316 s_partitionFreeUpMemoryCallback = callback; | |
| 317 } | |
| 318 | |
| 319 static void partitionFreeUpMemory() | |
| 320 { | |
|
Chris Evans
2014/11/06 21:45:34
One more thing. Can we add here a // TODO comment
| |
| 321 if (atomicTestAndSetToOne(&s_partitionFreeUpMemoryRecusionCount)) | |
| 322 return; | |
| 323 if (s_partitionFreeUpMemoryCallback) | |
| 324 s_partitionFreeUpMemoryCallback(); | |
|
Chris Evans
2014/11/06 21:43:51
Ah, so s_partitionFreeUpMemoryCallback() is going
| |
| 325 atomicSetOneToZero(&s_partitionFreeUpMemoryRecusionCount); | |
| 326 } | |
| 327 | |
| 304 static ALWAYS_INLINE void partitionDecommitSystemPages(PartitionRootBase* root, void* addr, size_t len) | 328 static ALWAYS_INLINE void partitionDecommitSystemPages(PartitionRootBase* root, void* addr, size_t len) |
| 305 { | 329 { |
| 306 decommitSystemPages(addr, len); | 330 decommitSystemPages(addr, len); |
| 307 ASSERT(root->totalSizeOfCommittedPages > len); | 331 ASSERT(root->totalSizeOfCommittedPages > len); |
| 308 root->totalSizeOfCommittedPages -= len; | 332 root->totalSizeOfCommittedPages -= len; |
| 309 } | 333 } |
| 310 | 334 |
| 311 static ALWAYS_INLINE void partitionRecommitSystemPages(PartitionRootBase* root, void* addr, size_t len) | 335 static ALWAYS_INLINE void partitionRecommitSystemPages(PartitionRootBase* root, void* addr, size_t len) |
| 312 { | 336 { |
| 313 recommitSystemPages(addr, len); | 337 recommitSystemPages(addr, len); |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 687 goto partitionAllocSlowPathFailed; | 711 goto partitionAllocSlowPathFailed; |
| 688 // Skip the alignment check because it depends on page->bucket, which is not yet set. | 712 // Skip the alignment check because it depends on page->bucket, which is not yet set. |
| 689 newPage = partitionPointerToPageNoAlignmentCheck(rawNewPage); | 713 newPage = partitionPointerToPageNoAlignmentCheck(rawNewPage); |
| 690 } | 714 } |
| 691 | 715 |
| 692 partitionPageReset(newPage, bucket); | 716 partitionPageReset(newPage, bucket); |
| 693 bucket->activePagesHead = newPage; | 717 bucket->activePagesHead = newPage; |
| 694 return partitionPageAllocAndFillFreelist(newPage); | 718 return partitionPageAllocAndFillFreelist(newPage); |
| 695 | 719 |
| 696 partitionAllocSlowPathFailed: | 720 partitionAllocSlowPathFailed: |
| 721 if (!(flags & PartitionAllocRetry)) { | |
| 722 partitionFreeUpMemory(); | |
|
Chris Evans
2014/11/06 21:43:51
Nit: I wonder if we want a comment here to say tha
| |
| 723 void* ptr = partitionAllocSlowPath(root, flags | PartitionAllocRetry, si ze, bucket); | |
|
Jens Widell
2014/10/22 11:24:05
Wouldn't it be better to retry partitionBucketAllo
Chris Evans
2014/11/06 21:43:51
I agree that partitionBucketAlloc() is the correct
| |
| 724 if (ptr) | |
| 725 return ptr; | |
| 726 } | |
| 727 | |
| 697 if (returnNull) | 728 if (returnNull) |
| 698 return nullptr; | 729 return nullptr; |
| 699 partitionOutOfMemory(); | 730 partitionOutOfMemory(); |
| 700 return nullptr; | 731 return nullptr; |
| 701 } | 732 } |
| 702 | 733 |
| 703 static ALWAYS_INLINE void partitionFreePage(PartitionRootBase* root, PartitionPa ge* page) | 734 static ALWAYS_INLINE void partitionFreePage(PartitionRootBase* root, PartitionPa ge* page) |
| 704 { | 735 { |
| 705 ASSERT(page->freelistHead); | 736 ASSERT(page->freelistHead); |
| 706 ASSERT(!page->numAllocatedSlots); | 737 ASSERT(!page->numAllocatedSlots); |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 968 printf("total live: %zu bytes\n", totalLive); | 999 printf("total live: %zu bytes\n", totalLive); |
| 969 printf("total resident: %zu bytes\n", totalResident); | 1000 printf("total resident: %zu bytes\n", totalResident); |
| 970 printf("total freeable: %zu bytes\n", totalFreeable); | 1001 printf("total freeable: %zu bytes\n", totalFreeable); |
| 971 fflush(stdout); | 1002 fflush(stdout); |
| 972 } | 1003 } |
| 973 | 1004 |
| 974 #endif // !NDEBUG | 1005 #endif // !NDEBUG |
| 975 | 1006 |
| 976 } // namespace WTF | 1007 } // namespace WTF |
| 977 | 1008 |
| OLD | NEW |