Commit be64717b authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

[base] Page allocator: Add rounding helpers

- Add Round{Up,Down}ToPageAllocationGranularity.
- Add unittests for rounding.

Change-Id: I131a0b493867fbe54ca2a6d1382fa6176e984162
Reviewed-on: https://chromium-review.googlesource.com/1067524Reviewed-by: default avatarAlbert J. Wong <ajwong@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#560873}
parent 91ef3f9d
...@@ -133,14 +133,33 @@ BASE_EXPORT WARN_UNUSED_RESULT bool RecommitSystemPages( ...@@ -133,14 +133,33 @@ BASE_EXPORT WARN_UNUSED_RESULT bool RecommitSystemPages(
// based on the original page content, or a page of zeroes. // based on the original page content, or a page of zeroes.
BASE_EXPORT void DiscardSystemPages(void* address, size_t length); BASE_EXPORT void DiscardSystemPages(void* address, size_t length);
ALWAYS_INLINE uintptr_t RoundUpToSystemPage(uintptr_t address) { // Rounds up |address| to the next multiple of |kSystemPageSize|. Returns
// 0 for an |address| of 0.
constexpr ALWAYS_INLINE uintptr_t RoundUpToSystemPage(uintptr_t address) {
return (address + kSystemPageOffsetMask) & kSystemPageBaseMask; return (address + kSystemPageOffsetMask) & kSystemPageBaseMask;
} }
ALWAYS_INLINE uintptr_t RoundDownToSystemPage(uintptr_t address) { // Rounds down |address| to the previous multiple of |kSystemPageSize|. Returns
// 0 for an |address| of 0.
constexpr ALWAYS_INLINE uintptr_t RoundDownToSystemPage(uintptr_t address) {
return address & kSystemPageBaseMask; return address & kSystemPageBaseMask;
} }
// Rounds up |address| to the next multiple of |kPageAllocationGranularity|.
// Returns 0 for an |address| of 0.
constexpr ALWAYS_INLINE uintptr_t
RoundUpToPageAllocationGranularity(uintptr_t address) {
return (address + kPageAllocationGranularityOffsetMask) &
kPageAllocationGranularityBaseMask;
}
// Rounds down |address| to the previous multiple of
// |kPageAllocationGranularity|. Returns 0 for an |address| of 0.
constexpr ALWAYS_INLINE uintptr_t
RoundDownToPageAllocationGranularity(uintptr_t address) {
return address & kPageAllocationGranularityBaseMask;
}
// Reserves (at least) |size| bytes of address space, aligned to // Reserves (at least) |size| bytes of address space, aligned to
// |kPageAllocationGranularity|. This can be called early on to make it more // |kPageAllocationGranularity|. This can be called early on to make it more
// likely that large allocations will succeed. Returns true if the reservation // likely that large allocations will succeed. Returns true if the reservation
......
...@@ -11,31 +11,31 @@ ...@@ -11,31 +11,31 @@
namespace base { namespace base {
#if defined(OS_WIN) #if defined(OS_WIN)
static const size_t kPageAllocationGranularityShift = 16; // 64KB static constexpr size_t kPageAllocationGranularityShift = 16; // 64KB
#elif defined(_MIPS_ARCH_LOONGSON) #elif defined(_MIPS_ARCH_LOONGSON)
static const size_t kPageAllocationGranularityShift = 14; // 16KB static constexpr size_t kPageAllocationGranularityShift = 14; // 16KB
#else #else
static const size_t kPageAllocationGranularityShift = 12; // 4KB static constexpr size_t kPageAllocationGranularityShift = 12; // 4KB
#endif #endif
static const size_t kPageAllocationGranularity = static constexpr size_t kPageAllocationGranularity =
1 << kPageAllocationGranularityShift; 1 << kPageAllocationGranularityShift;
static const size_t kPageAllocationGranularityOffsetMask = static constexpr size_t kPageAllocationGranularityOffsetMask =
kPageAllocationGranularity - 1; kPageAllocationGranularity - 1;
static const size_t kPageAllocationGranularityBaseMask = static constexpr size_t kPageAllocationGranularityBaseMask =
~kPageAllocationGranularityOffsetMask; ~kPageAllocationGranularityOffsetMask;
#if defined(_MIPS_ARCH_LOONGSON) #if defined(_MIPS_ARCH_LOONGSON)
static const size_t kSystemPageSize = 16384; static constexpr size_t kSystemPageSize = 16384;
#else #else
static const size_t kSystemPageSize = 4096; static constexpr size_t kSystemPageSize = 4096;
#endif #endif
static const size_t kSystemPageOffsetMask = kSystemPageSize - 1; static constexpr size_t kSystemPageOffsetMask = kSystemPageSize - 1;
static_assert((kSystemPageSize & (kSystemPageSize - 1)) == 0, static_assert((kSystemPageSize & (kSystemPageSize - 1)) == 0,
"kSystemPageSize must be power of 2"); "kSystemPageSize must be power of 2");
static const size_t kSystemPageBaseMask = ~kSystemPageOffsetMask; static constexpr size_t kSystemPageBaseMask = ~kSystemPageOffsetMask;
static const size_t kPageMetadataShift = 5; // 32 bytes per partition page. static constexpr size_t kPageMetadataShift = 5; // 32 bytes per partition page.
static const size_t kPageMetadataSize = 1 << kPageMetadataShift; static constexpr size_t kPageMetadataSize = 1 << kPageMetadataShift;
} // namespace base } // namespace base
......
...@@ -34,6 +34,37 @@ constexpr size_t kHugeMemoryAmount = ...@@ -34,6 +34,37 @@ constexpr size_t kHugeMemoryAmount =
} // namespace } // namespace
TEST(PageAllocatorTest, Rounding) {
EXPECT_EQ(0u, RoundUpToSystemPage(0u));
EXPECT_EQ(kSystemPageSize, RoundUpToSystemPage(1));
EXPECT_EQ(kSystemPageSize, RoundUpToSystemPage(kSystemPageSize - 1));
EXPECT_EQ(kSystemPageSize, RoundUpToSystemPage(kSystemPageSize));
EXPECT_EQ(2 * kSystemPageSize, RoundUpToSystemPage(kSystemPageSize + 1));
EXPECT_EQ(0u, RoundDownToSystemPage(0u));
EXPECT_EQ(0u, RoundDownToSystemPage(kSystemPageSize - 1));
EXPECT_EQ(kSystemPageSize, RoundDownToSystemPage(kSystemPageSize));
EXPECT_EQ(kSystemPageSize, RoundDownToSystemPage(kSystemPageSize + 1));
EXPECT_EQ(kSystemPageSize, RoundDownToSystemPage(2 * kSystemPageSize - 1));
EXPECT_EQ(0u, RoundUpToPageAllocationGranularity(0u));
EXPECT_EQ(kPageAllocationGranularity, RoundUpToPageAllocationGranularity(1));
EXPECT_EQ(kPageAllocationGranularity,
RoundUpToPageAllocationGranularity(kPageAllocationGranularity - 1));
EXPECT_EQ(kPageAllocationGranularity,
RoundUpToPageAllocationGranularity(kPageAllocationGranularity));
EXPECT_EQ(2 * kPageAllocationGranularity,
RoundUpToPageAllocationGranularity(kPageAllocationGranularity + 1));
EXPECT_EQ(0u, RoundDownToPageAllocationGranularity(0u));
EXPECT_EQ(
0u, RoundDownToPageAllocationGranularity(kPageAllocationGranularity - 1));
EXPECT_EQ(kPageAllocationGranularity,
RoundDownToPageAllocationGranularity(kPageAllocationGranularity));
EXPECT_EQ(kPageAllocationGranularity, RoundDownToPageAllocationGranularity(
kPageAllocationGranularity + 1));
EXPECT_EQ(
kPageAllocationGranularity,
RoundDownToPageAllocationGranularity(2 * kPageAllocationGranularity - 1));
}
// Test that failed page allocations invoke base::ReleaseReservation(). // Test that failed page allocations invoke base::ReleaseReservation().
// We detect this by making a reservation and ensuring that after failure, we // We detect this by making a reservation and ensuring that after failure, we
// can make a new reservation. // can make a new reservation.
......
...@@ -10,11 +10,6 @@ namespace blink { ...@@ -10,11 +10,6 @@ namespace blink {
namespace { namespace {
inline uintptr_t RoundUpToPageAllocationGranularity(uintptr_t address) {
return (address + base::kPageAllocationGranularityOffsetMask) &
base::kPageAllocationGranularityBaseMask;
}
constexpr inline bool IsPowerOfTwo(size_t value) { constexpr inline bool IsPowerOfTwo(size_t value) {
return value > 0 && (value & (value - 1)) == 0; return value > 0 && (value & (value - 1)) == 0;
} }
...@@ -29,7 +24,7 @@ static_assert( ...@@ -29,7 +24,7 @@ static_assert(
0 == base::kPageAllocationGranularity % base::kSystemPageSize, 0 == base::kPageAllocationGranularity % base::kSystemPageSize,
"System page size must be a multiple of page page allocation granularity"); "System page size must be a multiple of page page allocation granularity");
size_t ComputeInitialTableLimit() { constexpr size_t ComputeInitialTableLimit() {
// (Light) experimentation suggests that Blink doesn't need more than this // (Light) experimentation suggests that Blink doesn't need more than this
// while handling content on popular web properties. // while handling content on popular web properties.
constexpr size_t kInitialWantedLimit = 512; constexpr size_t kInitialWantedLimit = 512;
...@@ -37,12 +32,12 @@ size_t ComputeInitialTableLimit() { ...@@ -37,12 +32,12 @@ size_t ComputeInitialTableLimit() {
// Different OSes have different page sizes, so we have to choose the minimum // Different OSes have different page sizes, so we have to choose the minimum
// of memory wanted and OS page size. // of memory wanted and OS page size.
constexpr size_t memory_wanted = kInitialWantedLimit * kEntrySize; constexpr size_t memory_wanted = kInitialWantedLimit * kEntrySize;
return RoundUpToPageAllocationGranularity(memory_wanted) / kEntrySize; return base::RoundUpToPageAllocationGranularity(memory_wanted) / kEntrySize;
} }
size_t MaxTableSize() { constexpr size_t MaxTableSize() {
static const size_t kMaxTableSize = constexpr size_t kMaxTableSize = base::RoundUpToPageAllocationGranularity(
RoundUpToPageAllocationGranularity(GCInfoTable::kMaxIndex * kEntrySize); GCInfoTable::kMaxIndex * kEntrySize);
return kMaxTableSize; return kMaxTableSize;
} }
......
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