| 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 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 | 517 |
| 518 uint16_t numPartitionPages = partitionBucketPartitionPages(bucket); | 518 uint16_t numPartitionPages = partitionBucketPartitionPages(bucket); |
| 519 char* pageCharPtr = reinterpret_cast<char*>(page); | 519 char* pageCharPtr = reinterpret_cast<char*>(page); |
| 520 for (uint16_t i = 1; i < numPartitionPages; ++i) { | 520 for (uint16_t i = 1; i < numPartitionPages; ++i) { |
| 521 pageCharPtr += kPageMetadataSize; | 521 pageCharPtr += kPageMetadataSize; |
| 522 PartitionPage* secondaryPage = reinterpret_cast<PartitionPage*>(pageChar
Ptr); | 522 PartitionPage* secondaryPage = reinterpret_cast<PartitionPage*>(pageChar
Ptr); |
| 523 secondaryPage->pageOffset = i; | 523 secondaryPage->pageOffset = i; |
| 524 } | 524 } |
| 525 } | 525 } |
| 526 | 526 |
| 527 static ALWAYS_INLINE size_t partitionRoundUpToSystemPage(size_t size) | |
| 528 { | |
| 529 return (size + kSystemPageOffsetMask) & kSystemPageBaseMask; | |
| 530 } | |
| 531 | |
| 532 static ALWAYS_INLINE size_t partitionRoundDownToSystemPage(size_t size) | |
| 533 { | |
| 534 return size & kSystemPageBaseMask; | |
| 535 } | |
| 536 | |
| 537 static ALWAYS_INLINE char* partitionPageAllocAndFillFreelist(PartitionPage* page
) | 527 static ALWAYS_INLINE char* partitionPageAllocAndFillFreelist(PartitionPage* page
) |
| 538 { | 528 { |
| 539 ASSERT(page != &PartitionRootGeneric::gSeedPage); | 529 ASSERT(page != &PartitionRootGeneric::gSeedPage); |
| 540 uint16_t numSlots = page->numUnprovisionedSlots; | 530 uint16_t numSlots = page->numUnprovisionedSlots; |
| 541 ASSERT(numSlots); | 531 ASSERT(numSlots); |
| 542 PartitionBucket* bucket = page->bucket; | 532 PartitionBucket* bucket = page->bucket; |
| 543 // We should only get here when _every_ slot is either used or unprovisioned
. | 533 // We should only get here when _every_ slot is either used or unprovisioned
. |
| 544 // (The third state is "on the freelist". If we have a non-empty freelist, w
e should not get here.) | 534 // (The third state is "on the freelist". If we have a non-empty freelist, w
e should not get here.) |
| 545 ASSERT(numSlots + page->numAllocatedSlots == partitionBucketSlots(bucket)); | 535 ASSERT(numSlots + page->numAllocatedSlots == partitionBucketSlots(bucket)); |
| 546 // Similarly, make explicitly sure that the freelist is empty. | 536 // Similarly, make explicitly sure that the freelist is empty. |
| 547 ASSERT(!page->freelistHead); | 537 ASSERT(!page->freelistHead); |
| 548 ASSERT(page->numAllocatedSlots >= 0); | 538 ASSERT(page->numAllocatedSlots >= 0); |
| 549 | 539 |
| 550 size_t size = bucket->slotSize; | 540 size_t size = bucket->slotSize; |
| 551 char* base = reinterpret_cast<char*>(partitionPageToPointer(page)); | 541 char* base = reinterpret_cast<char*>(partitionPageToPointer(page)); |
| 552 char* returnObject = base + (size * page->numAllocatedSlots); | 542 char* returnObject = base + (size * page->numAllocatedSlots); |
| 553 char* firstFreelistPointer = returnObject + size; | 543 char* firstFreelistPointer = returnObject + size; |
| 554 char* firstFreelistPointerExtent = firstFreelistPointer + sizeof(PartitionFr
eelistEntry*); | 544 char* firstFreelistPointerExtent = firstFreelistPointer + sizeof(PartitionFr
eelistEntry*); |
| 555 // Our goal is to fault as few system pages as possible. We calculate the | 545 // Our goal is to fault as few system pages as possible. We calculate the |
| 556 // page containing the "end" of the returned slot, and then allow freelist | 546 // page containing the "end" of the returned slot, and then allow freelist |
| 557 // pointers to be written up to the end of that page. | 547 // pointers to be written up to the end of that page. |
| 558 char* subPageLimit = reinterpret_cast<char*>(partitionRoundUpToSystemPage(re
interpret_cast<size_t>(firstFreelistPointer))); | 548 char* subPageLimit = reinterpret_cast<char*>(WTF::roundUpToSystemPage(reinte
rpret_cast<size_t>(firstFreelistPointer))); |
| 559 char* slotsLimit = returnObject + (size * numSlots); | 549 char* slotsLimit = returnObject + (size * numSlots); |
| 560 char* freelistLimit = subPageLimit; | 550 char* freelistLimit = subPageLimit; |
| 561 if (UNLIKELY(slotsLimit < freelistLimit)) | 551 if (UNLIKELY(slotsLimit < freelistLimit)) |
| 562 freelistLimit = slotsLimit; | 552 freelistLimit = slotsLimit; |
| 563 | 553 |
| 564 uint16_t numNewFreelistEntries = 0; | 554 uint16_t numNewFreelistEntries = 0; |
| 565 if (LIKELY(firstFreelistPointerExtent <= freelistLimit)) { | 555 if (LIKELY(firstFreelistPointerExtent <= freelistLimit)) { |
| 566 // Only consider used space in the slot span. If we consider wasted | 556 // Only consider used space in the slot span. If we consider wasted |
| 567 // space, we may get an off-by-one when a freelist pointer fits in the | 557 // space, we may get an off-by-one when a freelist pointer fits in the |
| 568 // wasted space, but a slot does not. | 558 // wasted space, but a slot does not. |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1102 const PartitionBucket* bucket = page->bucket; | 1092 const PartitionBucket* bucket = page->bucket; |
| 1103 size_t slotSize = bucket->slotSize; | 1093 size_t slotSize = bucket->slotSize; |
| 1104 if (slotSize < kSystemPageSize || !page->numAllocatedSlots) | 1094 if (slotSize < kSystemPageSize || !page->numAllocatedSlots) |
| 1105 return 0; | 1095 return 0; |
| 1106 | 1096 |
| 1107 size_t bucketNumSlots = partitionBucketSlots(bucket); | 1097 size_t bucketNumSlots = partitionBucketSlots(bucket); |
| 1108 size_t discardableBytes = 0; | 1098 size_t discardableBytes = 0; |
| 1109 | 1099 |
| 1110 size_t rawSize = partitionPageGetRawSize(const_cast<PartitionPage*>(page)); | 1100 size_t rawSize = partitionPageGetRawSize(const_cast<PartitionPage*>(page)); |
| 1111 if (rawSize) { | 1101 if (rawSize) { |
| 1112 uint32_t usedBytes = static_cast<uint32_t>(partitionRoundUpToSystemPage(
rawSize)); | 1102 uint32_t usedBytes = static_cast<uint32_t>(WTF::roundUpToSystemPage(rawS
ize)); |
| 1113 discardableBytes = bucket->slotSize - usedBytes; | 1103 discardableBytes = bucket->slotSize - usedBytes; |
| 1114 if (discardableBytes && discard) { | 1104 if (discardableBytes && discard) { |
| 1115 char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page)); | 1105 char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page)); |
| 1116 ptr += usedBytes; | 1106 ptr += usedBytes; |
| 1117 discardSystemPages(ptr, discardableBytes); | 1107 discardSystemPages(ptr, discardableBytes); |
| 1118 } | 1108 } |
| 1119 return discardableBytes; | 1109 return discardableBytes; |
| 1120 } | 1110 } |
| 1121 | 1111 |
| 1122 const size_t maxSlotCount = (kPartitionPageSize * kMaxPartitionPagesPerSlotS
pan) / kSystemPageSize; | 1112 const size_t maxSlotCount = (kPartitionPageSize * kMaxPartitionPagesPerSlotS
pan) / kSystemPageSize; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1153 ASSERT(numSlots); | 1143 ASSERT(numSlots); |
| 1154 } | 1144 } |
| 1155 // First, do the work of calculating the discardable bytes. Don't actually | 1145 // First, do the work of calculating the discardable bytes. Don't actually |
| 1156 // discard anything unless the discard flag was passed in. | 1146 // discard anything unless the discard flag was passed in. |
| 1157 char* beginPtr = nullptr; | 1147 char* beginPtr = nullptr; |
| 1158 char* endPtr = nullptr; | 1148 char* endPtr = nullptr; |
| 1159 size_t unprovisionedBytes = 0; | 1149 size_t unprovisionedBytes = 0; |
| 1160 if (truncatedSlots) { | 1150 if (truncatedSlots) { |
| 1161 beginPtr = ptr + (numSlots * slotSize); | 1151 beginPtr = ptr + (numSlots * slotSize); |
| 1162 endPtr = beginPtr + (slotSize * truncatedSlots); | 1152 endPtr = beginPtr + (slotSize * truncatedSlots); |
| 1163 beginPtr = reinterpret_cast<char*>(partitionRoundUpToSystemPage(reinterp
ret_cast<size_t>(beginPtr))); | 1153 beginPtr = reinterpret_cast<char*>(WTF::roundUpToSystemPage(reinterpret_
cast<size_t>(beginPtr))); |
| 1164 // We round the end pointer here up and not down because we're at the | 1154 // We round the end pointer here up and not down because we're at the |
| 1165 // end of a slot span, so we "own" all the way up the page boundary. | 1155 // end of a slot span, so we "own" all the way up the page boundary. |
| 1166 endPtr = reinterpret_cast<char*>(partitionRoundUpToSystemPage(reinterpre
t_cast<size_t>(endPtr))); | 1156 endPtr = reinterpret_cast<char*>(WTF::roundUpToSystemPage(reinterpret_ca
st<size_t>(endPtr))); |
| 1167 ASSERT(endPtr <= ptr + partitionBucketBytes(bucket)); | 1157 ASSERT(endPtr <= ptr + partitionBucketBytes(bucket)); |
| 1168 if (beginPtr < endPtr) { | 1158 if (beginPtr < endPtr) { |
| 1169 unprovisionedBytes = endPtr - beginPtr; | 1159 unprovisionedBytes = endPtr - beginPtr; |
| 1170 discardableBytes += unprovisionedBytes; | 1160 discardableBytes += unprovisionedBytes; |
| 1171 } | 1161 } |
| 1172 } | 1162 } |
| 1173 if (unprovisionedBytes && discard) { | 1163 if (unprovisionedBytes && discard) { |
| 1174 ASSERT(truncatedSlots > 0); | 1164 ASSERT(truncatedSlots > 0); |
| 1175 size_t numNewEntries = 0; | 1165 size_t numNewEntries = 0; |
| 1176 page->numUnprovisionedSlots += static_cast<uint16_t>(truncatedSlots); | 1166 page->numUnprovisionedSlots += static_cast<uint16_t>(truncatedSlots); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1200 for (size_t i = 0; i < numSlots; ++i) { | 1190 for (size_t i = 0; i < numSlots; ++i) { |
| 1201 if (slotUsage[i]) | 1191 if (slotUsage[i]) |
| 1202 continue; | 1192 continue; |
| 1203 // The first address we can safely discard is just after the freelist | 1193 // The first address we can safely discard is just after the freelist |
| 1204 // pointer. There's one quirk: if the freelist pointer is actually a | 1194 // pointer. There's one quirk: if the freelist pointer is actually a |
| 1205 // null, we can discard that pointer value too. | 1195 // null, we can discard that pointer value too. |
| 1206 char* beginPtr = ptr + (i * slotSize); | 1196 char* beginPtr = ptr + (i * slotSize); |
| 1207 char* endPtr = beginPtr + slotSize; | 1197 char* endPtr = beginPtr + slotSize; |
| 1208 if (i != lastSlot) | 1198 if (i != lastSlot) |
| 1209 beginPtr += sizeof(PartitionFreelistEntry); | 1199 beginPtr += sizeof(PartitionFreelistEntry); |
| 1210 beginPtr = reinterpret_cast<char*>(partitionRoundUpToSystemPage(reinterp
ret_cast<size_t>(beginPtr))); | 1200 beginPtr = reinterpret_cast<char*>(WTF::roundUpToSystemPage(reinterpret_
cast<size_t>(beginPtr))); |
| 1211 endPtr = reinterpret_cast<char*>(partitionRoundDownToSystemPage(reinterp
ret_cast<size_t>(endPtr))); | 1201 endPtr = reinterpret_cast<char*>(WTF::roundDownToSystemPage(reinterpret_
cast<size_t>(endPtr))); |
| 1212 if (beginPtr < endPtr) { | 1202 if (beginPtr < endPtr) { |
| 1213 size_t partialSlotBytes = endPtr - beginPtr; | 1203 size_t partialSlotBytes = endPtr - beginPtr; |
| 1214 discardableBytes += partialSlotBytes; | 1204 discardableBytes += partialSlotBytes; |
| 1215 if (discard) | 1205 if (discard) |
| 1216 discardSystemPages(beginPtr, partialSlotBytes); | 1206 discardSystemPages(beginPtr, partialSlotBytes); |
| 1217 } | 1207 } |
| 1218 } | 1208 } |
| 1219 return discardableBytes; | 1209 return discardableBytes; |
| 1220 } | 1210 } |
| 1221 | 1211 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1263 } | 1253 } |
| 1264 | 1254 |
| 1265 statsOut->discardableBytes += partitionPurgePage(const_cast<PartitionPage*>(
page), false); | 1255 statsOut->discardableBytes += partitionPurgePage(const_cast<PartitionPage*>(
page), false); |
| 1266 | 1256 |
| 1267 size_t rawSize = partitionPageGetRawSize(const_cast<PartitionPage*>(page)); | 1257 size_t rawSize = partitionPageGetRawSize(const_cast<PartitionPage*>(page)); |
| 1268 if (rawSize) | 1258 if (rawSize) |
| 1269 statsOut->activeBytes += static_cast<uint32_t>(rawSize); | 1259 statsOut->activeBytes += static_cast<uint32_t>(rawSize); |
| 1270 else | 1260 else |
| 1271 statsOut->activeBytes += (page->numAllocatedSlots * statsOut->bucketSlot
Size); | 1261 statsOut->activeBytes += (page->numAllocatedSlots * statsOut->bucketSlot
Size); |
| 1272 | 1262 |
| 1273 size_t pageBytesResident = partitionRoundUpToSystemPage((bucketNumSlots - pa
ge->numUnprovisionedSlots) * statsOut->bucketSlotSize); | 1263 size_t pageBytesResident = WTF::roundUpToSystemPage((bucketNumSlots - page->
numUnprovisionedSlots) * statsOut->bucketSlotSize); |
| 1274 statsOut->residentBytes += pageBytesResident; | 1264 statsOut->residentBytes += pageBytesResident; |
| 1275 if (partitionPageStateIsEmpty(page)) { | 1265 if (partitionPageStateIsEmpty(page)) { |
| 1276 statsOut->decommittableBytes += pageBytesResident; | 1266 statsOut->decommittableBytes += pageBytesResident; |
| 1277 ++statsOut->numEmptyPages; | 1267 ++statsOut->numEmptyPages; |
| 1278 } else if (partitionPageStateIsFull(page)) { | 1268 } else if (partitionPageStateIsFull(page)) { |
| 1279 ++statsOut->numFullPages; | 1269 ++statsOut->numFullPages; |
| 1280 } else { | 1270 } else { |
| 1281 ASSERT(partitionPageStateIsActive(page)); | 1271 ASSERT(partitionPageStateIsActive(page)); |
| 1282 ++statsOut->numActivePages; | 1272 ++statsOut->numActivePages; |
| 1283 } | 1273 } |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1412 partitionStats.totalDiscardableBytes += memoryStats[i].discardableBy
tes; | 1402 partitionStats.totalDiscardableBytes += memoryStats[i].discardableBy
tes; |
| 1413 if (!isLightDump) | 1403 if (!isLightDump) |
| 1414 partitionStatsDumper->partitionsDumpBucketStats(partitionName, &
memoryStats[i]); | 1404 partitionStatsDumper->partitionsDumpBucketStats(partitionName, &
memoryStats[i]); |
| 1415 } | 1405 } |
| 1416 } | 1406 } |
| 1417 partitionStatsDumper->partitionDumpTotals(partitionName, &partitionStats); | 1407 partitionStatsDumper->partitionDumpTotals(partitionName, &partitionStats); |
| 1418 } | 1408 } |
| 1419 | 1409 |
| 1420 } // namespace WTF | 1410 } // namespace WTF |
| 1421 | 1411 |
| OLD | NEW |