Allow non word aligned heap limit for space bitmap
For the mem map large object space, the bitmap covers the entire
range of memory. This is done by passing in max int as the space
capacity. Previously, the space bitmap heap limit was computed by
multiplying the number of words by the word stride. In 32 bit systems
this caused heap limit to be (1 << 32) == 0 for the mem map large
object space.
This CL allows storing max int as the heap limit and returning that
from the function.
Added regression test to large object test.
Test: verify lyft installs and launches with the profile that was causing problems
Test: test-art-host
Bug: 64413646
(cherry picked from commit 76bb14a18283859b3b6e44c2b71ac441d8c252cf)
Change-Id: I34cabe80420e5bbb880adaea5e1737ca8efd8886
diff --git a/runtime/gc/accounting/space_bitmap.cc b/runtime/gc/accounting/space_bitmap.cc
index 92b4360..280c0b1 100644
--- a/runtime/gc/accounting/space_bitmap.cc
+++ b/runtime/gc/accounting/space_bitmap.cc
@@ -48,16 +48,21 @@
CHECK(mem_map != nullptr);
uintptr_t* bitmap_begin = reinterpret_cast<uintptr_t*>(mem_map->Begin());
const size_t bitmap_size = ComputeBitmapSize(heap_capacity);
- return new SpaceBitmap(name, mem_map, bitmap_begin, bitmap_size, heap_begin);
+ return new SpaceBitmap(name, mem_map, bitmap_begin, bitmap_size, heap_begin, heap_capacity);
}
template<size_t kAlignment>
-SpaceBitmap<kAlignment>::SpaceBitmap(const std::string& name, MemMap* mem_map, uintptr_t* bitmap_begin,
- size_t bitmap_size, const void* heap_begin)
+SpaceBitmap<kAlignment>::SpaceBitmap(const std::string& name,
+ MemMap* mem_map,
+ uintptr_t* bitmap_begin,
+ size_t bitmap_size,
+ const void* heap_begin,
+ size_t heap_capacity)
: mem_map_(mem_map),
bitmap_begin_(reinterpret_cast<Atomic<uintptr_t>*>(bitmap_begin)),
bitmap_size_(bitmap_size),
heap_begin_(reinterpret_cast<uintptr_t>(heap_begin)),
+ heap_limit_(reinterpret_cast<uintptr_t>(heap_begin) + heap_capacity),
name_(name) {
CHECK(bitmap_begin_ != nullptr);
CHECK_NE(bitmap_size, 0U);
@@ -89,6 +94,7 @@
if (new_size < bitmap_size_) {
bitmap_size_ = new_size;
}
+ heap_limit_ = new_end;
// Not sure if doing this trim is necessary, since nothing past the end of the heap capacity
// should be marked.
}
diff --git a/runtime/gc/accounting/space_bitmap.h b/runtime/gc/accounting/space_bitmap.h
index 2fe6394..b49e0b7 100644
--- a/runtime/gc/accounting/space_bitmap.h
+++ b/runtime/gc/accounting/space_bitmap.h
@@ -163,6 +163,7 @@
void SetHeapSize(size_t bytes) {
// TODO: Un-map the end of the mem map.
+ heap_limit_ = heap_begin_ + bytes;
bitmap_size_ = OffsetToIndex(bytes) * sizeof(intptr_t);
CHECK_EQ(HeapSize(), bytes);
}
@@ -173,7 +174,7 @@
// The maximum address which the bitmap can span. (HeapBegin() <= object < HeapLimit()).
uint64_t HeapLimit() const {
- return static_cast<uint64_t>(HeapBegin()) + HeapSize();
+ return heap_limit_;
}
// Set the max address which can covered by the bitmap.
@@ -196,8 +197,12 @@
private:
// TODO: heap_end_ is initialized so that the heap bitmap is empty, this doesn't require the -1,
// however, we document that this is expected on heap_end_
- SpaceBitmap(const std::string& name, MemMap* mem_map, uintptr_t* bitmap_begin, size_t bitmap_size,
- const void* heap_begin);
+ SpaceBitmap(const std::string& name,
+ MemMap* mem_map,
+ uintptr_t* bitmap_begin,
+ size_t bitmap_size,
+ const void* heap_begin,
+ size_t heap_capacity);
template<bool kSetBit>
bool Modify(const mirror::Object* obj);
@@ -211,10 +216,13 @@
// Size of this bitmap.
size_t bitmap_size_;
- // The base address of the heap, which corresponds to the word containing the first bit in the
- // bitmap.
+ // The start address of the memory covered by the bitmap, which corresponds to the word
+ // containing the first bit in the bitmap.
const uintptr_t heap_begin_;
+ // The end address of the memory covered by the bitmap. This may not be on a word boundary.
+ uintptr_t heap_limit_;
+
// Name of this bitmap.
std::string name_;
};
diff --git a/runtime/gc/space/large_object_space_test.cc b/runtime/gc/space/large_object_space_test.cc
index 79b775a..9baa016 100644
--- a/runtime/gc/space/large_object_space_test.cc
+++ b/runtime/gc/space/large_object_space_test.cc
@@ -38,12 +38,19 @@
Thread* const self = Thread::Current();
for (size_t i = 0; i < 2; ++i) {
LargeObjectSpace* los = nullptr;
+ const size_t capacity = 128 * MB;
if (i == 0) {
los = space::LargeObjectMapSpace::Create("large object space");
} else {
- los = space::FreeListSpace::Create("large object space", nullptr, 128 * MB);
+ los = space::FreeListSpace::Create("large object space", nullptr, capacity);
}
+ // Make sure the bitmap is not empty and actually covers at least how much we expect.
+ CHECK_LT(static_cast<uintptr_t>(los->GetLiveBitmap()->HeapBegin()),
+ static_cast<uintptr_t>(los->GetLiveBitmap()->HeapLimit()));
+ CHECK_LE(static_cast<uintptr_t>(los->GetLiveBitmap()->HeapBegin() + capacity),
+ static_cast<uintptr_t>(los->GetLiveBitmap()->HeapLimit()));
+
static const size_t num_allocations = 64;
static const size_t max_allocation_size = 0x100000;
std::vector<std::pair<mirror::Object*, size_t>> requests;