Refactor and optimize memory region bit functions
Move optimized bit reading from FieldEncoding to MemoryRegion,
added optimized StoreBits to MemoryRegion.
Compilation of a large app on host:
Before:
Time -j1: 31.897s
2.00% art::MemoryRegion::StoreBits(unsigned long, unsigned int, unsigned long)
After:
Time -j1: 29.620s
0.39% art::MemoryRegion::StoreBits(unsigned long, unsigned int, unsigned long)
Bug: 34621054
Test: test-art-host
Change-Id: I0509613da83cc5741d5cfada3f8a8af503784e9e
diff --git a/runtime/memory_region.cc b/runtime/memory_region.cc
index a5c70c3..5bf0f40 100644
--- a/runtime/memory_region.cc
+++ b/runtime/memory_region.cc
@@ -33,4 +33,36 @@
from.pointer(), from.size());
}
+void MemoryRegion::StoreBits(uintptr_t bit_offset, uint32_t value, size_t length) {
+ DCHECK_LE(value, MaxInt<uint32_t>(length));
+ DCHECK_LE(length, BitSizeOf<uint32_t>());
+ DCHECK_LE(bit_offset + length, size_in_bits());
+ if (length == 0) {
+ return;
+ }
+ // Bits are stored in this order {7 6 5 4 3 2 1 0}.
+ // How many remaining bits in current byte is (bit_offset % kBitsPerByte) + 1.
+ uint8_t* out = ComputeInternalPointer<uint8_t>(bit_offset >> kBitsPerByteLog2);
+ auto orig_len = length;
+ auto orig_value = value;
+ uintptr_t bit_remainder = bit_offset % kBitsPerByte;
+ while (true) {
+ const uintptr_t remaining_bits = kBitsPerByte - bit_remainder;
+ if (length <= remaining_bits) {
+ // Length is smaller than all of remainder bits.
+ size_t mask = ((1 << length) - 1) << bit_remainder;
+ *out = (*out & ~mask) | (value << bit_remainder);
+ break;
+ }
+ // Copy remaining bits in current byte.
+ size_t value_mask = (1 << remaining_bits) - 1;
+ *out = (*out & ~(value_mask << bit_remainder)) | ((value & value_mask) << bit_remainder);
+ value >>= remaining_bits;
+ bit_remainder = 0;
+ length -= remaining_bits;
+ ++out;
+ }
+ DCHECK_EQ(LoadBits(bit_offset, orig_len), orig_value) << bit_offset << " " << orig_len;
+}
+
} // namespace art