Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: Source/wtf/PartitionAlloc.cpp

Issue 1053793004: Add a UseCounter that measures the amount of memory used in PartitionAlloc (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 double wasteRatio = (double) waste / (double) pageSize; 91 double wasteRatio = (double) waste / (double) pageSize;
92 if (wasteRatio < bestWasteRatio) { 92 if (wasteRatio < bestWasteRatio) {
93 bestWasteRatio = wasteRatio; 93 bestWasteRatio = wasteRatio;
94 bestPages = i; 94 bestPages = i;
95 } 95 }
96 } 96 }
97 ASSERT(bestPages > 0); 97 ASSERT(bestPages > 0);
98 return bestPages; 98 return bestPages;
99 } 99 }
100 100
101 static void parititonAllocBaseInit(PartitionRootBase* root) 101 static void parititonAllocBaseInit(PartitionRootBase* root, NotifyCommittedMemor yChangedFunction notifyCommittedMemoryChangedFunction)
102 { 102 {
103 ASSERT(!root->initialized); 103 ASSERT(!root->initialized);
104 104
105 spinLockLock(&PartitionRootBase::gInitializedLock); 105 spinLockLock(&PartitionRootBase::gInitializedLock);
106 if (!PartitionRootBase::gInitialized) { 106 if (!PartitionRootBase::gInitialized) {
107 PartitionRootBase::gInitialized = true; 107 PartitionRootBase::gInitialized = true;
108 // We mark the seed page as free to make sure it is skipped by our 108 // We mark the seed page as free to make sure it is skipped by our
109 // logic to find a new active page. 109 // logic to find a new active page.
110 PartitionRootBase::gPagedBucket.activePagesHead = &PartitionRootGeneric: :gSeedPage; 110 PartitionRootBase::gPagedBucket.activePagesHead = &PartitionRootGeneric: :gSeedPage;
111 } 111 }
112 spinLockUnlock(&PartitionRootBase::gInitializedLock); 112 spinLockUnlock(&PartitionRootBase::gInitializedLock);
113 113
114 root->initialized = true; 114 root->initialized = true;
115 root->totalSizeOfCommittedPages = 0; 115 root->totalSizeOfCommittedPages = 0;
116 root->totalSizeOfSuperPages = 0; 116 root->totalSizeOfSuperPages = 0;
117 root->totalSizeOfDirectMappedPages = 0; 117 root->totalSizeOfDirectMappedPages = 0;
118 root->nextSuperPage = 0; 118 root->nextSuperPage = 0;
119 root->nextPartitionPage = 0; 119 root->nextPartitionPage = 0;
120 root->nextPartitionPageEnd = 0; 120 root->nextPartitionPageEnd = 0;
121 root->firstExtent = 0; 121 root->firstExtent = 0;
122 root->currentExtent = 0; 122 root->currentExtent = 0;
123 123
124 memset(&root->globalEmptyPageRing, '\0', sizeof(root->globalEmptyPageRing)); 124 memset(&root->globalEmptyPageRing, '\0', sizeof(root->globalEmptyPageRing));
125 root->globalEmptyPageRingIndex = 0; 125 root->globalEmptyPageRingIndex = 0;
126 126
127 // This is a "magic" value so we can test if a root pointer is valid. 127 // This is a "magic" value so we can test if a root pointer is valid.
128 root->invertedSelf = ~reinterpret_cast<uintptr_t>(root); 128 root->invertedSelf = ~reinterpret_cast<uintptr_t>(root);
129
130 root->notifyCommittedMemoryChangedFunction = notifyCommittedMemoryChangedFun ction;
129 } 131 }
130 132
131 static void partitionBucketInitBase(PartitionBucket* bucket, PartitionRootBase* root) 133 static void partitionBucketInitBase(PartitionBucket* bucket, PartitionRootBase* root)
132 { 134 {
133 bucket->activePagesHead = &PartitionRootGeneric::gSeedPage; 135 bucket->activePagesHead = &PartitionRootGeneric::gSeedPage;
134 bucket->freePagesHead = 0; 136 bucket->freePagesHead = 0;
135 bucket->numFullPages = 0; 137 bucket->numFullPages = 0;
136 bucket->numSystemPagesPerSlotSpan = partitionBucketNumSystemPages(bucket->sl otSize); 138 bucket->numSystemPagesPerSlotSpan = partitionBucketNumSystemPages(bucket->sl otSize);
137 } 139 }
138 140
139 void partitionAllocInit(PartitionRoot* root, size_t numBuckets, size_t maxAlloca tion) 141 void partitionAllocInit(PartitionRoot* root, size_t numBuckets, size_t maxAlloca tion, NotifyCommittedMemoryChangedFunction notifyCommittedMemoryChangedFunction)
140 { 142 {
141 parititonAllocBaseInit(root); 143 parititonAllocBaseInit(root, notifyCommittedMemoryChangedFunction);
142 144
143 root->numBuckets = numBuckets; 145 root->numBuckets = numBuckets;
144 root->maxAllocation = maxAllocation; 146 root->maxAllocation = maxAllocation;
145 size_t i; 147 size_t i;
146 for (i = 0; i < root->numBuckets; ++i) { 148 for (i = 0; i < root->numBuckets; ++i) {
147 PartitionBucket* bucket = &root->buckets()[i]; 149 PartitionBucket* bucket = &root->buckets()[i];
148 if (!i) 150 if (!i)
149 bucket->slotSize = kAllocationGranularity; 151 bucket->slotSize = kAllocationGranularity;
150 else 152 else
151 bucket->slotSize = i << kBucketShift; 153 bucket->slotSize = i << kBucketShift;
152 partitionBucketInitBase(bucket, root); 154 partitionBucketInitBase(bucket, root);
153 } 155 }
154 } 156 }
155 157
156 void partitionAllocGenericInit(PartitionRootGeneric* root) 158 void partitionAllocGenericInit(PartitionRootGeneric* root, NotifyCommittedMemory ChangedFunction notifyCommittedMemoryChangedFunction)
157 { 159 {
158 parititonAllocBaseInit(root); 160 parititonAllocBaseInit(root, notifyCommittedMemoryChangedFunction);
159 161
160 root->lock = 0; 162 root->lock = 0;
161 163
162 // Precalculate some shift and mask constants used in the hot path. 164 // Precalculate some shift and mask constants used in the hot path.
163 // Example: malloc(41) == 101001 binary. 165 // Example: malloc(41) == 101001 binary.
164 // Order is 6 (1 << 6-1)==32 is highest bit set. 166 // Order is 6 (1 << 6-1)==32 is highest bit set.
165 // orderIndex is the next three MSB == 010 == 2. 167 // orderIndex is the next three MSB == 010 == 2.
166 // subOrderIndexMask is a mask for the remaining bits == 11 (masking to 01 f or the subOrderIndex). 168 // subOrderIndexMask is a mask for the remaining bits == 11 (masking to 01 f or the subOrderIndex).
167 size_t order; 169 size_t order;
168 for (order = 0; order <= kBitsPerSizet; ++order) { 170 for (order = 0; order <= kBitsPerSizet; ++order) {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 #if !CPU(64BIT) 323 #if !CPU(64BIT)
322 // Check whether this OOM is due to a lot of super pages that are allocated 324 // Check whether this OOM is due to a lot of super pages that are allocated
323 // but not committed, probably due to http://crbug.com/421387. 325 // but not committed, probably due to http://crbug.com/421387.
324 if (root->totalSizeOfSuperPages + root->totalSizeOfDirectMappedPages - root- >totalSizeOfCommittedPages > kReasonableSizeOfUnusedPages) { 326 if (root->totalSizeOfSuperPages + root->totalSizeOfDirectMappedPages - root- >totalSizeOfCommittedPages > kReasonableSizeOfUnusedPages) {
325 partitionOutOfMemoryWithLotsOfUncommitedPages(); 327 partitionOutOfMemoryWithLotsOfUncommitedPages();
326 } 328 }
327 #endif 329 #endif
328 IMMEDIATE_CRASH(); 330 IMMEDIATE_CRASH();
329 } 331 }
330 332
333 static void partitionIncreaseCommittedPages(PartitionRootBase* root, size_t len)
haraken 2015/04/05 15:01:52 I added two separate functions (for increase and d
334 {
335 root->totalSizeOfCommittedPages += len;
336 ASSERT(root->totalSizeOfCommittedPages <= root->totalSizeOfSuperPages + root ->totalSizeOfDirectMappedPages);
337 if (root->notifyCommittedMemoryChangedFunction)
338 root->notifyCommittedMemoryChangedFunction();
339 }
340
341 static void partitionDecreaseCommittedPages(PartitionRootBase* root, size_t len)
342 {
343 root->totalSizeOfCommittedPages -= len;
344 ASSERT(root->totalSizeOfCommittedPages <= root->totalSizeOfSuperPages + root ->totalSizeOfDirectMappedPages);
345 if (root->notifyCommittedMemoryChangedFunction)
346 root->notifyCommittedMemoryChangedFunction();
347 }
348
331 static ALWAYS_INLINE void partitionDecommitSystemPages(PartitionRootBase* root, void* addr, size_t len) 349 static ALWAYS_INLINE void partitionDecommitSystemPages(PartitionRootBase* root, void* addr, size_t len)
332 { 350 {
333 decommitSystemPages(addr, len); 351 decommitSystemPages(addr, len);
334 ASSERT(root->totalSizeOfCommittedPages >= len); 352 partitionDecreaseCommittedPages(root, len);
335 root->totalSizeOfCommittedPages -= len;
336 } 353 }
337 354
338 static ALWAYS_INLINE void partitionRecommitSystemPages(PartitionRootBase* root, void* addr, size_t len) 355 static ALWAYS_INLINE void partitionRecommitSystemPages(PartitionRootBase* root, void* addr, size_t len)
339 { 356 {
340 recommitSystemPages(addr, len); 357 recommitSystemPages(addr, len);
341 root->totalSizeOfCommittedPages += len; 358 partitionIncreaseCommittedPages(root, len);
342 ASSERT(root->totalSizeOfCommittedPages <= root->totalSizeOfSuperPages + root ->totalSizeOfDirectMappedPages);
343 } 359 }
344 360
345 static ALWAYS_INLINE void* partitionAllocPartitionPages(PartitionRootBase* root, int flags, uint16_t numPartitionPages) 361 static ALWAYS_INLINE void* partitionAllocPartitionPages(PartitionRootBase* root, int flags, uint16_t numPartitionPages)
346 { 362 {
347 ASSERT(!(reinterpret_cast<uintptr_t>(root->nextPartitionPage) % kPartitionPa geSize)); 363 ASSERT(!(reinterpret_cast<uintptr_t>(root->nextPartitionPage) % kPartitionPa geSize));
348 ASSERT(!(reinterpret_cast<uintptr_t>(root->nextPartitionPageEnd) % kPartitio nPageSize)); 364 ASSERT(!(reinterpret_cast<uintptr_t>(root->nextPartitionPageEnd) % kPartitio nPageSize));
349 RELEASE_ASSERT(numPartitionPages <= kNumPartitionPagesPerSuperPage); 365 RELEASE_ASSERT(numPartitionPages <= kNumPartitionPagesPerSuperPage);
350 size_t totalSize = kPartitionPageSize * numPartitionPages; 366 size_t totalSize = kPartitionPageSize * numPartitionPages;
351 size_t numPartitionPagesLeft = (root->nextPartitionPageEnd - root->nextParti tionPage) >> kPartitionPageShift; 367 size_t numPartitionPagesLeft = (root->nextPartitionPageEnd - root->nextParti tionPage) >> kPartitionPageShift;
352 if (LIKELY(numPartitionPagesLeft >= numPartitionPages)) { 368 if (LIKELY(numPartitionPagesLeft >= numPartitionPages)) {
353 // In this case, we can still hand out pages from the current super page 369 // In this case, we can still hand out pages from the current super page
354 // allocation. 370 // allocation.
355 char* ret = root->nextPartitionPage; 371 char* ret = root->nextPartitionPage;
356 root->nextPartitionPage += totalSize; 372 root->nextPartitionPage += totalSize;
357 root->totalSizeOfCommittedPages += totalSize; 373 partitionIncreaseCommittedPages(root, totalSize);
358 ASSERT(root->totalSizeOfCommittedPages <= root->totalSizeOfSuperPages + root->totalSizeOfDirectMappedPages);
359 return ret; 374 return ret;
360 } 375 }
361 376
362 // Need a new super page. We want to allocate super pages in a continguous 377 // Need a new super page. We want to allocate super pages in a continguous
363 // address region as much as possible. This is important for not causing 378 // address region as much as possible. This is important for not causing
364 // page table bloat and not fragmenting address spaces in 32 bit architectur es. 379 // page table bloat and not fragmenting address spaces in 32 bit architectur es.
365 char* requestedAddress = root->nextSuperPage; 380 char* requestedAddress = root->nextSuperPage;
366 char* superPage = reinterpret_cast<char*>(allocPages(requestedAddress, kSupe rPageSize, kSuperPageSize, PageAccessible)); 381 char* superPage = reinterpret_cast<char*>(allocPages(requestedAddress, kSupe rPageSize, kSuperPageSize, PageAccessible));
367 if (UNLIKELY(!superPage)) 382 if (UNLIKELY(!superPage))
368 return 0; 383 return 0;
369 384
370 root->totalSizeOfSuperPages += kSuperPageSize; 385 root->totalSizeOfSuperPages += kSuperPageSize;
371 root->totalSizeOfCommittedPages += totalSize; 386 partitionIncreaseCommittedPages(root, totalSize);
372 ASSERT(root->totalSizeOfCommittedPages <= root->totalSizeOfSuperPages + root ->totalSizeOfDirectMappedPages);
373 387
374 root->nextSuperPage = superPage + kSuperPageSize; 388 root->nextSuperPage = superPage + kSuperPageSize;
375 char* ret = superPage + kPartitionPageSize; 389 char* ret = superPage + kPartitionPageSize;
376 root->nextPartitionPage = ret + totalSize; 390 root->nextPartitionPage = ret + totalSize;
377 root->nextPartitionPageEnd = root->nextSuperPage - kPartitionPageSize; 391 root->nextPartitionPageEnd = root->nextSuperPage - kPartitionPageSize;
378 // Make the first partition page in the super page a guard page, but leave a 392 // Make the first partition page in the super page a guard page, but leave a
379 // hole in the middle. 393 // hole in the middle.
380 // This is where we put page metadata and also a tiny amount of extent 394 // This is where we put page metadata and also a tiny amount of extent
381 // metadata. 395 // metadata.
382 setSystemPagesInaccessible(superPage, kSystemPageSize); 396 setSystemPagesInaccessible(superPage, kSystemPageSize);
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 // - The first few system pages are the partition page in which the super 619 // - The first few system pages are the partition page in which the super
606 // page metadata is stored. We fault just one system page out of a partition 620 // page metadata is stored. We fault just one system page out of a partition
607 // page sized clump. 621 // page sized clump.
608 // - We add a trailing guard page. 622 // - We add a trailing guard page.
609 size_t mapSize = size + kPartitionPageSize + kSystemPageSize; 623 size_t mapSize = size + kPartitionPageSize + kSystemPageSize;
610 // Round up to the allocation granularity. 624 // Round up to the allocation granularity.
611 mapSize += kPageAllocationGranularityOffsetMask; 625 mapSize += kPageAllocationGranularityOffsetMask;
612 mapSize &= kPageAllocationGranularityBaseMask; 626 mapSize &= kPageAllocationGranularityBaseMask;
613 627
614 size_t committedPageSize = size + kSystemPageSize; 628 size_t committedPageSize = size + kSystemPageSize;
615 root->totalSizeOfCommittedPages += committedPageSize;
616 root->totalSizeOfDirectMappedPages += committedPageSize; 629 root->totalSizeOfDirectMappedPages += committedPageSize;
617 ASSERT(root->totalSizeOfCommittedPages <= root->totalSizeOfSuperPages + root ->totalSizeOfDirectMappedPages); 630 partitionIncreaseCommittedPages(root, committedPageSize);
618 631
619 // TODO: we may want to let the operating system place these allocations 632 // TODO: we may want to let the operating system place these allocations
620 // where it pleases. On 32-bit, this might limit address space 633 // where it pleases. On 32-bit, this might limit address space
621 // fragmentation and on 64-bit, this might have useful savings for TLB 634 // fragmentation and on 64-bit, this might have useful savings for TLB
622 // and page table overhead. 635 // and page table overhead.
623 // TODO: if upsizing realloc()s are common on large sizes, we could 636 // TODO: if upsizing realloc()s are common on large sizes, we could
624 // consider over-allocating address space on 64-bit, "just in case". 637 // consider over-allocating address space on 64-bit, "just in case".
625 // TODO: consider pre-populating page tables (e.g. MAP_POPULATE on Linux, 638 // TODO: consider pre-populating page tables (e.g. MAP_POPULATE on Linux,
626 // MADV_WILLNEED on POSIX). 639 // MADV_WILLNEED on POSIX).
627 // TODO: these pages will be zero-filled. Consider internalizing an 640 // TODO: these pages will be zero-filled. Consider internalizing an
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 static ALWAYS_INLINE void partitionDirectUnmap(PartitionPage* page) 683 static ALWAYS_INLINE void partitionDirectUnmap(PartitionPage* page)
671 { 684 {
672 size_t unmapSize = partitionPageToDirectMapExtent(page)->mapSize; 685 size_t unmapSize = partitionPageToDirectMapExtent(page)->mapSize;
673 686
674 // Add on the size of the trailing guard page and preceeding partition 687 // Add on the size of the trailing guard page and preceeding partition
675 // page. 688 // page.
676 unmapSize += kPartitionPageSize + kSystemPageSize; 689 unmapSize += kPartitionPageSize + kSystemPageSize;
677 690
678 PartitionRootBase* root = partitionPageToRoot(page); 691 PartitionRootBase* root = partitionPageToRoot(page);
679 size_t uncommittedPageSize = page->bucket->slotSize + kSystemPageSize; 692 size_t uncommittedPageSize = page->bucket->slotSize + kSystemPageSize;
680 ASSERT(root->totalSizeOfCommittedPages >= uncommittedPageSize); 693 partitionDecreaseCommittedPages(root, uncommittedPageSize);
681 root->totalSizeOfCommittedPages -= uncommittedPageSize;
682 ASSERT(root->totalSizeOfDirectMappedPages >= uncommittedPageSize); 694 ASSERT(root->totalSizeOfDirectMappedPages >= uncommittedPageSize);
683 root->totalSizeOfDirectMappedPages -= uncommittedPageSize; 695 root->totalSizeOfDirectMappedPages -= uncommittedPageSize;
684 696
685 ASSERT(!(unmapSize & kPageAllocationGranularityOffsetMask)); 697 ASSERT(!(unmapSize & kPageAllocationGranularityOffsetMask));
686 698
687 char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page)); 699 char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page));
688 // Account for the mapping starting a partition page before the actual 700 // Account for the mapping starting a partition page before the actual
689 // allocation address. 701 // allocation address.
690 ptr -= kPartitionPageSize; 702 ptr -= kPartitionPageSize;
691 703
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 printf("total live: %zu bytes\n", totalLive); 1053 printf("total live: %zu bytes\n", totalLive);
1042 printf("total resident: %zu bytes\n", totalResident); 1054 printf("total resident: %zu bytes\n", totalResident);
1043 printf("total freeable: %zu bytes\n", totalFreeable); 1055 printf("total freeable: %zu bytes\n", totalFreeable);
1044 fflush(stdout); 1056 fflush(stdout);
1045 } 1057 }
1046 1058
1047 #endif // !NDEBUG 1059 #endif // !NDEBUG
1048 1060
1049 } // namespace WTF 1061 } // namespace WTF
1050 1062
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698