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 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 502 | 502 |
| 503 uint16_t numPartitionPages = partitionBucketPartitionPages(bucket); | 503 uint16_t numPartitionPages = partitionBucketPartitionPages(bucket); |
| 504 char* pageCharPtr = reinterpret_cast<char*>(page); | 504 char* pageCharPtr = reinterpret_cast<char*>(page); |
| 505 for (uint16_t i = 1; i < numPartitionPages; ++i) { | 505 for (uint16_t i = 1; i < numPartitionPages; ++i) { |
| 506 pageCharPtr += kPageMetadataSize; | 506 pageCharPtr += kPageMetadataSize; |
| 507 PartitionPage* secondaryPage = reinterpret_cast<PartitionPage*>(pageChar Ptr); | 507 PartitionPage* secondaryPage = reinterpret_cast<PartitionPage*>(pageChar Ptr); |
| 508 secondaryPage->pageOffset = i; | 508 secondaryPage->pageOffset = i; |
| 509 } | 509 } |
| 510 } | 510 } |
| 511 | 511 |
| 512 static ALWAYS_INLINE size_t partitionRoundUpToSystemPage(size_t size) | 512 static ALWAYS_INLINE char* partitionAlignUpToSystemPage(char* ptr) |
| 513 { | 513 { |
| 514 return (size + kSystemPageOffsetMask) & kSystemPageBaseMask; | 514 size_t addr = reinterpret_cast<size_t>(ptr); |
|
Primiano Tucci (use gerrit)
2015/09/03 11:24:53
these should be uintptr_t, also + const (i.e. cons
Ruud van Asseldonk
2015/09/03 13:44:47
Sure, but note that the current code uses size_t.
| |
| 515 size_t alignedAddr = (addr + kSystemPageOffsetMask) & kSystemPageBaseMask; | |
| 516 return reinterpret_cast<char*>(alignedAddr); | |
| 515 } | 517 } |
| 516 | 518 |
| 517 static ALWAYS_INLINE size_t partitionRoundDownToSystemPage(size_t size) | 519 static ALWAYS_INLINE char* partitionAlignDownToSystemPage(char* ptr) |
| 518 { | 520 { |
| 519 return size & kSystemPageBaseMask; | 521 size_t addr = reinterpret_cast<size_t>(ptr); |
|
Primiano Tucci (use gerrit)
2015/09/03 11:24:53
same here
| |
| 522 size_t alignedAddr = addr & kSystemPageBaseMask; | |
| 523 return reinterpret_cast<char*>(alignedAddr); | |
| 520 } | 524 } |
| 521 | 525 |
| 522 static ALWAYS_INLINE char* partitionPageAllocAndFillFreelist(PartitionPage* page ) | 526 static ALWAYS_INLINE char* partitionPageAllocAndFillFreelist(PartitionPage* page ) |
| 523 { | 527 { |
| 524 ASSERT(page != &PartitionRootGeneric::gSeedPage); | 528 ASSERT(page != &PartitionRootGeneric::gSeedPage); |
| 525 uint16_t numSlots = page->numUnprovisionedSlots; | 529 uint16_t numSlots = page->numUnprovisionedSlots; |
| 526 ASSERT(numSlots); | 530 ASSERT(numSlots); |
| 527 PartitionBucket* bucket = page->bucket; | 531 PartitionBucket* bucket = page->bucket; |
| 528 // We should only get here when _every_ slot is either used or unprovisioned . | 532 // We should only get here when _every_ slot is either used or unprovisioned . |
| 529 // (The third state is "on the freelist". If we have a non-empty freelist, w e should not get here.) | 533 // (The third state is "on the freelist". If we have a non-empty freelist, w e should not get here.) |
| 530 ASSERT(numSlots + page->numAllocatedSlots == partitionBucketSlots(bucket)); | 534 ASSERT(numSlots + page->numAllocatedSlots == partitionBucketSlots(bucket)); |
| 531 // Similarly, make explicitly sure that the freelist is empty. | 535 // Similarly, make explicitly sure that the freelist is empty. |
| 532 ASSERT(!page->freelistHead); | 536 ASSERT(!page->freelistHead); |
| 533 ASSERT(page->numAllocatedSlots >= 0); | 537 ASSERT(page->numAllocatedSlots >= 0); |
| 534 | 538 |
| 535 size_t size = bucket->slotSize; | 539 size_t size = bucket->slotSize; |
| 536 char* base = reinterpret_cast<char*>(partitionPageToPointer(page)); | 540 char* base = reinterpret_cast<char*>(partitionPageToPointer(page)); |
| 537 char* returnObject = base + (size * page->numAllocatedSlots); | 541 char* returnObject = base + (size * page->numAllocatedSlots); |
| 538 char* firstFreelistPointer = returnObject + size; | 542 char* firstFreelistPointer = returnObject + size; |
| 539 char* firstFreelistPointerExtent = firstFreelistPointer + sizeof(PartitionFr eelistEntry*); | 543 char* firstFreelistPointerExtent = firstFreelistPointer + sizeof(PartitionFr eelistEntry*); |
| 540 // Our goal is to fault as few system pages as possible. We calculate the | 544 // Our goal is to fault as few system pages as possible. We calculate the |
| 541 // page containing the "end" of the returned slot, and then allow freelist | 545 // page containing the "end" of the returned slot, and then allow freelist |
| 542 // pointers to be written up to the end of that page. | 546 // pointers to be written up to the end of that page. |
| 543 char* subPageLimit = reinterpret_cast<char*>(partitionRoundUpToSystemPage(re interpret_cast<size_t>(firstFreelistPointer))); | 547 char* subPageLimit = partitionAlignUpToSystemPage(firstFreelistPointer); |
| 544 char* slotsLimit = returnObject + (size * numSlots); | 548 char* slotsLimit = returnObject + (size * numSlots); |
| 545 char* freelistLimit = subPageLimit; | 549 char* freelistLimit = subPageLimit; |
| 546 if (UNLIKELY(slotsLimit < freelistLimit)) | 550 if (UNLIKELY(slotsLimit < freelistLimit)) |
| 547 freelistLimit = slotsLimit; | 551 freelistLimit = slotsLimit; |
| 548 | 552 |
| 549 uint16_t numNewFreelistEntries = 0; | 553 uint16_t numNewFreelistEntries = 0; |
| 550 if (LIKELY(firstFreelistPointerExtent <= freelistLimit)) { | 554 if (LIKELY(firstFreelistPointerExtent <= freelistLimit)) { |
| 551 // Only consider used space in the slot span. If we consider wasted | 555 // Only consider used space in the slot span. If we consider wasted |
| 552 // space, we may get an off-by-one when a freelist pointer fits in the | 556 // space, we may get an off-by-one when a freelist pointer fits in the |
| 553 // wasted space, but a slot does not. | 557 // wasted space, but a slot does not. |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 644 | 648 |
| 645 static ALWAYS_INLINE void partitionPageSetRawSize(PartitionPage* page, size_t si ze) | 649 static ALWAYS_INLINE void partitionPageSetRawSize(PartitionPage* page, size_t si ze) |
| 646 { | 650 { |
| 647 size_t* rawSizePtr = partitionPageGetRawSizePtr(page); | 651 size_t* rawSizePtr = partitionPageGetRawSizePtr(page); |
| 648 if (UNLIKELY(rawSizePtr != nullptr)) | 652 if (UNLIKELY(rawSizePtr != nullptr)) |
| 649 *rawSizePtr = size; | 653 *rawSizePtr = size; |
| 650 } | 654 } |
| 651 | 655 |
| 652 static ALWAYS_INLINE PartitionPage* partitionDirectMap(PartitionRootBase* root, int flags, size_t rawSize) | 656 static ALWAYS_INLINE PartitionPage* partitionDirectMap(PartitionRootBase* root, int flags, size_t rawSize) |
| 653 { | 657 { |
| 654 size_t size = partitionDirectMapSize(rawSize); | 658 size_t size = partitionRoundUpToSystemPage(rawSize); |
| 655 | 659 |
| 656 // Because we need to fake looking like a super page, we need to allocate | 660 // Because we need to fake looking like a super page, we need to allocate |
| 657 // a bunch of system pages more than "size": | 661 // a bunch of system pages more than "size": |
| 658 // - The first few system pages are the partition page in which the super | 662 // - The first few system pages are the partition page in which the super |
| 659 // page metadata is stored. We fault just one system page out of a partition | 663 // page metadata is stored. We fault just one system page out of a partition |
| 660 // page sized clump. | 664 // page sized clump. |
| 661 // - We add a trailing guard page on 32-bit (on 64-bit we rely on the | 665 // - We add a trailing guard page on 32-bit (on 64-bit we rely on the |
| 662 // massive address space plus randomization instead). | 666 // massive address space plus randomization instead). |
| 663 size_t mapSize = size + kPartitionPageSize; | 667 size_t mapSize = size + kPartitionPageSize; |
| 664 #if !CPU(64BIT) | 668 #if !CPU(64BIT) |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 969 } | 973 } |
| 970 | 974 |
| 971 bool partitionReallocDirectMappedInPlace(PartitionRootGeneric* root, PartitionPa ge* page, size_t rawSize) | 975 bool partitionReallocDirectMappedInPlace(PartitionRootGeneric* root, PartitionPa ge* page, size_t rawSize) |
| 972 { | 976 { |
| 973 ASSERT(partitionBucketIsDirectMapped(page->bucket)); | 977 ASSERT(partitionBucketIsDirectMapped(page->bucket)); |
| 974 | 978 |
| 975 rawSize = partitionCookieSizeAdjustAdd(rawSize); | 979 rawSize = partitionCookieSizeAdjustAdd(rawSize); |
| 976 | 980 |
| 977 // Note that the new size might be a bucketed size; this function is called | 981 // Note that the new size might be a bucketed size; this function is called |
| 978 // whenever we're reallocating a direct mapped allocation. | 982 // whenever we're reallocating a direct mapped allocation. |
| 979 size_t newSize = partitionDirectMapSize(rawSize); | 983 size_t newSize = partitionRoundUpToSystemPage(rawSize); |
| 980 if (newSize < kGenericMinDirectMappedDownsize) | 984 if (newSize < kGenericMinDirectMappedDownsize) |
| 981 return false; | 985 return false; |
| 982 | 986 |
| 983 // bucket->slotSize is the current size of the allocation. | 987 // bucket->slotSize is the current size of the allocation. |
| 984 size_t currentSize = page->bucket->slotSize; | 988 size_t currentSize = page->bucket->slotSize; |
| 985 if (newSize == currentSize) | 989 if (newSize == currentSize) |
| 986 return true; | 990 return true; |
| 987 | 991 |
| 988 char* charPtr = static_cast<char*>(partitionPageToPointer(page)); | 992 char* charPtr = static_cast<char*>(partitionPageToPointer(page)); |
| 989 | 993 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1136 ASSERT(numSlots); | 1140 ASSERT(numSlots); |
| 1137 } | 1141 } |
| 1138 // First, do the work of calculating the discardable bytes. Don't actually | 1142 // First, do the work of calculating the discardable bytes. Don't actually |
| 1139 // discard anything unless the discard flag was passed in. | 1143 // discard anything unless the discard flag was passed in. |
| 1140 char* beginPtr = nullptr; | 1144 char* beginPtr = nullptr; |
| 1141 char* endPtr = nullptr; | 1145 char* endPtr = nullptr; |
| 1142 size_t unprovisionedBytes = 0; | 1146 size_t unprovisionedBytes = 0; |
| 1143 if (truncatedSlots) { | 1147 if (truncatedSlots) { |
| 1144 beginPtr = ptr + (numSlots * slotSize); | 1148 beginPtr = ptr + (numSlots * slotSize); |
| 1145 endPtr = beginPtr + (slotSize * truncatedSlots); | 1149 endPtr = beginPtr + (slotSize * truncatedSlots); |
| 1146 beginPtr = reinterpret_cast<char*>(partitionRoundUpToSystemPage(reinterp ret_cast<size_t>(beginPtr))); | 1150 beginPtr = partitionAlignUpToSystemPage(beginPtr); |
| 1147 // We round the end pointer here up and not down because we're at the | 1151 // We round the end pointer here up and not down because we're at the |
| 1148 // end of a slot span, so we "own" all the way up the page boundary. | 1152 // end of a slot span, so we "own" all the way up the page boundary. |
| 1149 endPtr = reinterpret_cast<char*>(partitionRoundUpToSystemPage(reinterpre t_cast<size_t>(endPtr))); | 1153 endPtr = partitionAlignUpToSystemPage(endPtr); |
| 1150 ASSERT(endPtr <= ptr + partitionBucketBytes(bucket)); | 1154 ASSERT(endPtr <= ptr + partitionBucketBytes(bucket)); |
| 1151 if (beginPtr < endPtr) { | 1155 if (beginPtr < endPtr) { |
| 1152 unprovisionedBytes = endPtr - beginPtr; | 1156 unprovisionedBytes = endPtr - beginPtr; |
| 1153 discardableBytes += unprovisionedBytes; | 1157 discardableBytes += unprovisionedBytes; |
| 1154 } | 1158 } |
| 1155 } | 1159 } |
| 1156 if (unprovisionedBytes && discard) { | 1160 if (unprovisionedBytes && discard) { |
| 1157 ASSERT(truncatedSlots > 0); | 1161 ASSERT(truncatedSlots > 0); |
| 1158 size_t numNewEntries = 0; | 1162 size_t numNewEntries = 0; |
| 1159 page->numUnprovisionedSlots += truncatedSlots; | 1163 page->numUnprovisionedSlots += truncatedSlots; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1183 for (size_t i = 0; i < numSlots; ++i) { | 1187 for (size_t i = 0; i < numSlots; ++i) { |
| 1184 if (slotUsage[i]) | 1188 if (slotUsage[i]) |
| 1185 continue; | 1189 continue; |
| 1186 // The first address we can safely discard is just after the freelist | 1190 // The first address we can safely discard is just after the freelist |
| 1187 // pointer. There's one quirk: if the freelist pointer is actually a | 1191 // pointer. There's one quirk: if the freelist pointer is actually a |
| 1188 // null, we can discard that pointer value too. | 1192 // null, we can discard that pointer value too. |
| 1189 char* beginPtr = ptr + (i * slotSize); | 1193 char* beginPtr = ptr + (i * slotSize); |
| 1190 char* endPtr = beginPtr + slotSize; | 1194 char* endPtr = beginPtr + slotSize; |
| 1191 if (i != lastSlot) | 1195 if (i != lastSlot) |
| 1192 beginPtr += sizeof(PartitionFreelistEntry); | 1196 beginPtr += sizeof(PartitionFreelistEntry); |
| 1193 beginPtr = reinterpret_cast<char*>(partitionRoundUpToSystemPage(reinterp ret_cast<size_t>(beginPtr))); | 1197 beginPtr = partitionAlignUpToSystemPage(beginPtr); |
| 1194 endPtr = reinterpret_cast<char*>(partitionRoundDownToSystemPage(reinterp ret_cast<size_t>(endPtr))); | 1198 endPtr = partitionAlignDownToSystemPage(endPtr); |
| 1195 if (beginPtr < endPtr) { | 1199 if (beginPtr < endPtr) { |
| 1196 size_t partialSlotBytes = endPtr - beginPtr; | 1200 size_t partialSlotBytes = endPtr - beginPtr; |
| 1197 discardableBytes += partialSlotBytes; | 1201 discardableBytes += partialSlotBytes; |
| 1198 if (discard) | 1202 if (discard) |
| 1199 discardSystemPages(beginPtr, partialSlotBytes); | 1203 discardSystemPages(beginPtr, partialSlotBytes); |
| 1200 } | 1204 } |
| 1201 } | 1205 } |
| 1202 return discardableBytes; | 1206 return discardableBytes; |
| 1203 } | 1207 } |
| 1204 | 1208 |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1396 partitionStats.totalDiscardableBytes += memoryStats[i].discardableBy tes; | 1400 partitionStats.totalDiscardableBytes += memoryStats[i].discardableBy tes; |
| 1397 if (!isLightDump) | 1401 if (!isLightDump) |
| 1398 partitionStatsDumper->partitionsDumpBucketStats(partitionName, & memoryStats[i]); | 1402 partitionStatsDumper->partitionsDumpBucketStats(partitionName, & memoryStats[i]); |
| 1399 } | 1403 } |
| 1400 } | 1404 } |
| 1401 partitionStatsDumper->partitionDumpTotals(partitionName, &partitionStats); | 1405 partitionStatsDumper->partitionDumpTotals(partitionName, &partitionStats); |
| 1402 } | 1406 } |
| 1403 | 1407 |
| 1404 } // namespace WTF | 1408 } // namespace WTF |
| 1405 | 1409 |
| OLD | NEW |