| 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 const uintptr_t addr = reinterpret_cast<uintptr_t>(ptr); |
| 515 const uintptr_t alignedAddr = (addr + kSystemPageOffsetMask) & kSystemPageBa
seMask; |
| 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 const uintptr_t addr = reinterpret_cast<uintptr_t>(ptr); |
| 522 const uintptr_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 582 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 |