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 |