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 |