Commit cf04f3b0 authored by Takashi SAKAMOTO's avatar Takashi SAKAMOTO Committed by Commit Bot

The last freelist entry should not be discarded when using OS_WIN.

DiscardVirtualMemory makes the contents of discarded memory undefined.
c.f. https://msdn.microsoft.com/ja-jp/library/windows/desktop/dn781432(v=vs.85).aspx

BUG=

Change-Id: Ifd06e6f75271dc6a38cf0a34027cb20f1a887cfe
Reviewed-on: https://chromium-review.googlesource.com/571621
Commit-Queue: Takashi Sakamoto <tasak@google.com>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#486700}
parent 51dee544
...@@ -1100,7 +1100,11 @@ static size_t PartitionPurgePage(PartitionPage* page, bool discard) { ...@@ -1100,7 +1100,11 @@ static size_t PartitionPurgePage(PartitionPage* page, bool discard) {
DCHECK(page->num_unprovisioned_slots < bucket_num_slots); DCHECK(page->num_unprovisioned_slots < bucket_num_slots);
size_t num_slots = bucket_num_slots - page->num_unprovisioned_slots; size_t num_slots = bucket_num_slots - page->num_unprovisioned_slots;
char slot_usage[max_slot_count]; char slot_usage[max_slot_count];
#if !defined(OS_WIN)
// The last freelist entry should not be discarded when using OS_WIN.
// DiscardVirtualMemory makes the contents of discarded memory undefined.
size_t last_slot = static_cast<size_t>(-1); size_t last_slot = static_cast<size_t>(-1);
#endif
memset(slot_usage, 1, num_slots); memset(slot_usage, 1, num_slots);
char* ptr = reinterpret_cast<char*>(PartitionPageToPointer(page)); char* ptr = reinterpret_cast<char*>(PartitionPageToPointer(page));
PartitionFreelistEntry* entry = page->freelist_head; PartitionFreelistEntry* entry = page->freelist_head;
...@@ -1111,6 +1115,7 @@ static size_t PartitionPurgePage(PartitionPage* page, bool discard) { ...@@ -1111,6 +1115,7 @@ static size_t PartitionPurgePage(PartitionPage* page, bool discard) {
DCHECK(slotIndex < num_slots); DCHECK(slotIndex < num_slots);
slot_usage[slotIndex] = 0; slot_usage[slotIndex] = 0;
entry = PartitionFreelistMask(entry->next); entry = PartitionFreelistMask(entry->next);
#if !defined(OS_WIN)
// If we have a slot where the masked freelist entry is 0, we can // If we have a slot where the masked freelist entry is 0, we can
// actually discard that freelist entry because touching a discarded // actually discard that freelist entry because touching a discarded
// page is guaranteed to return original content or 0. // page is guaranteed to return original content or 0.
...@@ -1118,6 +1123,7 @@ static size_t PartitionPurgePage(PartitionPage* page, bool discard) { ...@@ -1118,6 +1123,7 @@ static size_t PartitionPurgePage(PartitionPage* page, bool discard) {
// because the masking function is negation.) // because the masking function is negation.)
if (!PartitionFreelistMask(entry)) if (!PartitionFreelistMask(entry))
last_slot = slotIndex; last_slot = slotIndex;
#endif
} }
// If the slot(s) at the end of the slot span are not in used, we can // If the slot(s) at the end of the slot span are not in used, we can
...@@ -1162,7 +1168,9 @@ static size_t PartitionPurgePage(PartitionPage* page, bool discard) { ...@@ -1162,7 +1168,9 @@ static size_t PartitionPurgePage(PartitionPage* page, bool discard) {
*entry_ptr = PartitionFreelistMask(entry); *entry_ptr = PartitionFreelistMask(entry);
entry_ptr = reinterpret_cast<PartitionFreelistEntry**>(entry); entry_ptr = reinterpret_cast<PartitionFreelistEntry**>(entry);
num_new_entries++; num_new_entries++;
#if !defined(OS_WIN)
last_slot = slotIndex; last_slot = slotIndex;
#endif
} }
// Terminate the freelist chain. // Terminate the freelist chain.
*entry_ptr = nullptr; *entry_ptr = nullptr;
...@@ -1185,8 +1193,12 @@ static size_t PartitionPurgePage(PartitionPage* page, bool discard) { ...@@ -1185,8 +1193,12 @@ static size_t PartitionPurgePage(PartitionPage* page, bool discard) {
// null, we can discard that pointer value too. // null, we can discard that pointer value too.
char* begin_ptr = ptr + (i * slot_size); char* begin_ptr = ptr + (i * slot_size);
char* end_ptr = begin_ptr + slot_size; char* end_ptr = begin_ptr + slot_size;
#if !defined(OS_WIN)
if (i != last_slot) if (i != last_slot)
begin_ptr += sizeof(PartitionFreelistEntry); begin_ptr += sizeof(PartitionFreelistEntry);
#else
begin_ptr += sizeof(PartitionFreelistEntry);
#endif
begin_ptr = reinterpret_cast<char*>( begin_ptr = reinterpret_cast<char*>(
RoundUpToSystemPage(reinterpret_cast<size_t>(begin_ptr))); RoundUpToSystemPage(reinterpret_cast<size_t>(begin_ptr)));
end_ptr = reinterpret_cast<char*>( end_ptr = reinterpret_cast<char*>(
......
...@@ -1839,14 +1839,22 @@ TEST_F(PartitionAllocTest, PurgeDiscardable) { ...@@ -1839,14 +1839,22 @@ TEST_F(PartitionAllocTest, PurgeDiscardable) {
EXPECT_TRUE(stats); EXPECT_TRUE(stats);
EXPECT_TRUE(stats->is_valid); EXPECT_TRUE(stats->is_valid);
EXPECT_EQ(0u, stats->decommittable_bytes); EXPECT_EQ(0u, stats->decommittable_bytes);
#if defined(OS_WIN)
EXPECT_EQ(0u, stats->discardable_bytes);
#else
EXPECT_EQ(kSystemPageSize, stats->discardable_bytes); EXPECT_EQ(kSystemPageSize, stats->discardable_bytes);
#endif
EXPECT_EQ(kSystemPageSize, stats->active_bytes); EXPECT_EQ(kSystemPageSize, stats->active_bytes);
EXPECT_EQ(2 * kSystemPageSize, stats->resident_bytes); EXPECT_EQ(2 * kSystemPageSize, stats->resident_bytes);
} }
CheckPageInCore(ptr1 - kPointerOffset, true); CheckPageInCore(ptr1 - kPointerOffset, true);
PartitionPurgeMemoryGeneric(generic_allocator.root(), PartitionPurgeMemoryGeneric(generic_allocator.root(),
PartitionPurgeDiscardUnusedSystemPages); PartitionPurgeDiscardUnusedSystemPages);
#if defined(OS_WIN)
CheckPageInCore(ptr1 - kPointerOffset, true);
#else
CheckPageInCore(ptr1 - kPointerOffset, false); CheckPageInCore(ptr1 - kPointerOffset, false);
#endif
PartitionFreeGeneric(generic_allocator.root(), ptr2); PartitionFreeGeneric(generic_allocator.root(), ptr2);
} }
...@@ -1969,7 +1977,11 @@ TEST_F(PartitionAllocTest, PurgeDiscardable) { ...@@ -1969,7 +1977,11 @@ TEST_F(PartitionAllocTest, PurgeDiscardable) {
EXPECT_TRUE(stats); EXPECT_TRUE(stats);
EXPECT_TRUE(stats->is_valid); EXPECT_TRUE(stats->is_valid);
EXPECT_EQ(0u, stats->decommittable_bytes); EXPECT_EQ(0u, stats->decommittable_bytes);
#if defined(OS_WIN)
EXPECT_EQ(kSystemPageSize, stats->discardable_bytes);
#else
EXPECT_EQ(2 * kSystemPageSize, stats->discardable_bytes); EXPECT_EQ(2 * kSystemPageSize, stats->discardable_bytes);
#endif
EXPECT_EQ(kSystemPageSize, stats->active_bytes); EXPECT_EQ(kSystemPageSize, stats->active_bytes);
EXPECT_EQ(4 * kSystemPageSize, stats->resident_bytes); EXPECT_EQ(4 * kSystemPageSize, stats->resident_bytes);
} }
...@@ -1981,7 +1993,11 @@ TEST_F(PartitionAllocTest, PurgeDiscardable) { ...@@ -1981,7 +1993,11 @@ TEST_F(PartitionAllocTest, PurgeDiscardable) {
PartitionPurgeDiscardUnusedSystemPages); PartitionPurgeDiscardUnusedSystemPages);
EXPECT_EQ(1u, page->num_unprovisioned_slots); EXPECT_EQ(1u, page->num_unprovisioned_slots);
CheckPageInCore(ptr1 - kPointerOffset, true); CheckPageInCore(ptr1 - kPointerOffset, true);
#if defined(OS_WIN)
CheckPageInCore(ptr1 - kPointerOffset + kSystemPageSize, true);
#else
CheckPageInCore(ptr1 - kPointerOffset + kSystemPageSize, false); CheckPageInCore(ptr1 - kPointerOffset + kSystemPageSize, false);
#endif
CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 2), true); CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 2), true);
CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 3), false); CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 3), false);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment