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(
// based on the original page content, or a page of zeroes.
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;
}
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;
}
// 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
// |kPageAllocationGranularity|. This can be called early on to make it more
// likely that large allocations will succeed. Returns true if the reservation
......
......@@ -11,31 +11,31 @@
namespace base {
#if defined(OS_WIN)
static const size_t kPageAllocationGranularityShift = 16; // 64KB
static constexpr size_t kPageAllocationGranularityShift = 16; // 64KB
#elif defined(_MIPS_ARCH_LOONGSON)
static const size_t kPageAllocationGranularityShift = 14; // 16KB
static constexpr size_t kPageAllocationGranularityShift = 14; // 16KB
#else
static const size_t kPageAllocationGranularityShift = 12; // 4KB
static constexpr size_t kPageAllocationGranularityShift = 12; // 4KB
#endif
static const size_t kPageAllocationGranularity =
static constexpr size_t kPageAllocationGranularity =
1 << kPageAllocationGranularityShift;
static const size_t kPageAllocationGranularityOffsetMask =
static constexpr size_t kPageAllocationGranularityOffsetMask =
kPageAllocationGranularity - 1;
static const size_t kPageAllocationGranularityBaseMask =
static constexpr size_t kPageAllocationGranularityBaseMask =
~kPageAllocationGranularityOffsetMask;
#if defined(_MIPS_ARCH_LOONGSON)
static const size_t kSystemPageSize = 16384;
static constexpr size_t kSystemPageSize = 16384;
#else
static const size_t kSystemPageSize = 4096;
static constexpr size_t kSystemPageSize = 4096;
#endif
static const size_t kSystemPageOffsetMask = kSystemPageSize - 1;
static constexpr size_t kSystemPageOffsetMask = kSystemPageSize - 1;
static_assert((kSystemPageSize & (kSystemPageSize - 1)) == 0,
"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 const size_t kPageMetadataSize = 1 << kPageMetadataShift;
static constexpr size_t kPageMetadataShift = 5; // 32 bytes per partition page.
static constexpr size_t kPageMetadataSize = 1 << kPageMetadataShift;
} // namespace base
......
......@@ -34,6 +34,37 @@ constexpr size_t kHugeMemoryAmount =
} // 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().
// We detect this by making a reservation and ensuring that after failure, we
// can make a new reservation.
......
......@@ -10,11 +10,6 @@ namespace blink {
namespace {
inline uintptr_t RoundUpToPageAllocationGranularity(uintptr_t address) {
return (address + base::kPageAllocationGranularityOffsetMask) &
base::kPageAllocationGranularityBaseMask;
}
constexpr inline bool IsPowerOfTwo(size_t value) {
return value > 0 && (value & (value - 1)) == 0;
}
......@@ -29,7 +24,7 @@ static_assert(
0 == base::kPageAllocationGranularity % base::kSystemPageSize,
"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
// while handling content on popular web properties.
constexpr size_t kInitialWantedLimit = 512;
......@@ -37,12 +32,12 @@ size_t ComputeInitialTableLimit() {
// Different OSes have different page sizes, so we have to choose the minimum
// of memory wanted and OS page size.
constexpr size_t memory_wanted = kInitialWantedLimit * kEntrySize;
return RoundUpToPageAllocationGranularity(memory_wanted) / kEntrySize;
return base::RoundUpToPageAllocationGranularity(memory_wanted) / kEntrySize;
}
size_t MaxTableSize() {
static const size_t kMaxTableSize =
RoundUpToPageAllocationGranularity(GCInfoTable::kMaxIndex * kEntrySize);
constexpr size_t MaxTableSize() {
constexpr size_t kMaxTableSize = base::RoundUpToPageAllocationGranularity(
GCInfoTable::kMaxIndex * kEntrySize);
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