diff options
author | 2024-01-07 15:48:41 +0000 | |
---|---|---|
committer | 2024-01-24 05:15:45 +0000 | |
commit | dd98d26e9bb6add7b79efb5abe01a437b33a3b96 (patch) | |
tree | 54182f7af0e17a530f4cf218a1d6fae4f092807f /runtime/gc/allocator/rosalloc.h | |
parent | 3027926d518f624b0287fcab705d7e5cd93b9b40 (diff) |
Optimize division by / modulo of gPageSize
When running under the page-agnostic configuration, while the global
constant gPageSize is always set to a power-of-two value at static
initialization time, it may not be recognised as a guaranteed
power-of-two by the compiler for the purpose of optimizations. This
means that divisions by gPageSize may not be replaced by an efficient
right-shift, and applications of modulo gPageSize may not be optimized
via a bitwise-AND.
This patch introduces two functions: one to perform a gPageSize division
as a logical right-shift, and the other to compute modulo gPageSize via
bitwise-AND.
Inlining these optimized implementations is then done everywhere that
requires division or modulo of gPageSize. As they are inlined, the
compiler is able to optimize the reuse of registers when multiple
divisions or modulos are required (for example, the result of
WhichPowerOf2 on the page size is stored when subsequent divisions are
necessary, which then each become just a single right-shift).
The tests were run for legacy 4K, page size agnostic 4K and 16K.
Test: art/tools/run-gtests.sh
Test: art/test/testrunner/testrunner.py --target --64
Test: art/tools/run-libcore-tests.sh --mode=device --variant=X64
Test: art/tools/run-libjdwp-tests.sh --mode=device --variant=X64
Change-Id: I01bd5fa89b88806c84660d4a2d62ddcba061678c
Diffstat (limited to 'runtime/gc/allocator/rosalloc.h')
-rw-r--r-- | runtime/gc/allocator/rosalloc.h | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/runtime/gc/allocator/rosalloc.h b/runtime/gc/allocator/rosalloc.h index 531f509fd8..333f80ff92 100644 --- a/runtime/gc/allocator/rosalloc.h +++ b/runtime/gc/allocator/rosalloc.h @@ -62,7 +62,7 @@ class RosAlloc { } void SetByteSize(RosAlloc* rosalloc, size_t byte_size) REQUIRES(rosalloc->lock_) { - DCHECK_EQ(byte_size % gPageSize, static_cast<size_t>(0)); + DCHECK_EQ(ModuloPageSize(byte_size), static_cast<size_t>(0)); uint8_t* fpr_base = reinterpret_cast<uint8_t*>(this); size_t pm_idx = rosalloc->ToPageMapIndex(fpr_base); rosalloc->free_page_run_size_map_[pm_idx] = byte_size; @@ -103,7 +103,7 @@ class RosAlloc { void ReleasePages(RosAlloc* rosalloc) REQUIRES(rosalloc->lock_) { uint8_t* start = reinterpret_cast<uint8_t*>(this); size_t byte_size = ByteSize(rosalloc); - DCHECK_EQ(byte_size % gPageSize, static_cast<size_t>(0)); + DCHECK_EQ(ModuloPageSize(byte_size), static_cast<size_t>(0)); if (ShouldReleasePages(rosalloc)) { rosalloc->ReleasePageRange(start, start + byte_size); } @@ -611,13 +611,13 @@ class RosAlloc { DCHECK_LE(base_, addr); DCHECK_LT(addr, base_ + capacity_); size_t byte_offset = reinterpret_cast<const uint8_t*>(addr) - base_; - DCHECK_EQ(byte_offset % static_cast<size_t>(gPageSize), static_cast<size_t>(0)); - return byte_offset / gPageSize; + DCHECK_EQ(ModuloPageSize(byte_offset), static_cast<size_t>(0)); + return DivideByPageSize(byte_offset); } // Returns the page map index from an address with rounding. size_t RoundDownToPageMapIndex(const void* addr) const { DCHECK(base_ <= addr && addr < reinterpret_cast<uint8_t*>(base_) + capacity_); - return (reinterpret_cast<uintptr_t>(addr) - reinterpret_cast<uintptr_t>(base_)) / gPageSize; + return DivideByPageSize(reinterpret_cast<uintptr_t>(addr) - reinterpret_cast<uintptr_t>(base_)); } // A memory allocation request larger than this size is treated as a large object and allocated @@ -916,7 +916,7 @@ class RosAlloc { return dedicated_full_run_; } bool IsFreePage(size_t idx) const { - DCHECK_LT(idx, capacity_ / gPageSize); + DCHECK_LT(idx, DivideByPageSize(capacity_)); uint8_t pm_type = page_map_[idx]; return pm_type == kPageMapReleased || pm_type == kPageMapEmpty; } |