ART: Merge entries with same name and protect in MemMap dump.
This should make the MemMap dump less chatty and allow the
logger to keep more relevant output.
Bug: 20873174
Change-Id: I09058798faa8f79d154cee5008017b03700df8db
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 1068e90..55a8411 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -385,7 +385,7 @@
LOG(INTERNAL_FATAL) << "Attempting see if it's a bad root";
mark_sweep_->VerifyRoots();
PrintFileToLog("/proc/self/maps", LogSeverity::INTERNAL_FATAL);
- MemMap::DumpMaps(LOG(INTERNAL_FATAL));
+ MemMap::DumpMaps(LOG(INTERNAL_FATAL), true);
LOG(FATAL) << "Can't mark invalid object";
}
}
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index cbbc76c..4129d75 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -491,7 +491,7 @@
bool no_gap = MemMap::CheckNoGaps(GetImageSpace()->GetMemMap(),
non_moving_space_->GetMemMap());
if (!no_gap) {
- MemMap::DumpMaps(LOG(ERROR));
+ MemMap::DumpMaps(LOG(ERROR), true);
LOG(FATAL) << "There's a gap between the image space and the non-moving space";
}
}
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index a5f7341..cf4233c 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -617,13 +617,68 @@
return true;
}
-void MemMap::DumpMaps(std::ostream& os) {
+void MemMap::DumpMaps(std::ostream& os, bool terse) {
MutexLock mu(Thread::Current(), *Locks::mem_maps_lock_);
- DumpMapsLocked(os);
+ DumpMapsLocked(os, terse);
}
-void MemMap::DumpMapsLocked(std::ostream& os) {
- os << *maps_;
+void MemMap::DumpMapsLocked(std::ostream& os, bool terse) {
+ const auto& mem_maps = *maps_;
+ if (!terse) {
+ os << mem_maps;
+ return;
+ }
+
+ // Terse output example:
+ // [MemMap: 0x409be000+0x20P~0x11dP+0x20P~0x61cP+0x20P prot=0x3 LinearAlloc]
+ // [MemMap: 0x451d6000+0x6bP(3) prot=0x3 large object space allocation]
+ // The details:
+ // "+0x20P" means 0x20 pages taken by a single mapping,
+ // "~0x11dP" means a gap of 0x11d pages,
+ // "+0x6bP(3)" means 3 mappings one after another, together taking 0x6b pages.
+ os << "MemMap:" << std::endl;
+ for (auto it = mem_maps.begin(), maps_end = mem_maps.end(); it != maps_end;) {
+ MemMap* map = it->second;
+ void* base = it->first;
+ CHECK_EQ(base, map->BaseBegin());
+ os << "[MemMap: " << base;
+ ++it;
+ // Merge consecutive maps with the same protect flags and name.
+ constexpr size_t kMaxGaps = 9;
+ size_t num_gaps = 0;
+ size_t num = 1u;
+ size_t size = map->BaseSize();
+ CHECK(IsAligned<kPageSize>(size));
+ void* end = map->BaseEnd();
+ while (it != maps_end &&
+ it->second->GetProtect() == map->GetProtect() &&
+ it->second->GetName() == map->GetName() &&
+ (it->second->BaseBegin() == end || num_gaps < kMaxGaps)) {
+ if (it->second->BaseBegin() != end) {
+ ++num_gaps;
+ os << "+0x" << std::hex << (size / kPageSize) << "P";
+ if (num != 1u) {
+ os << "(" << std::dec << num << ")";
+ }
+ size_t gap =
+ reinterpret_cast<uintptr_t>(it->second->BaseBegin()) - reinterpret_cast<uintptr_t>(end);
+ CHECK(IsAligned<kPageSize>(gap));
+ os << "~0x" << std::hex << (gap / kPageSize) << "P";
+ num = 0u;
+ size = 0u;
+ }
+ CHECK(IsAligned<kPageSize>(it->second->BaseSize()));
+ ++num;
+ size += it->second->BaseSize();
+ end = it->second->BaseEnd();
+ ++it;
+ }
+ os << "+0x" << std::hex << (size / kPageSize) << "P";
+ if (num != 1u) {
+ os << "(" << std::dec << num << ")";
+ }
+ os << " prot=0x" << std::hex << map->GetProtect() << " " << map->GetName() << "]" << std::endl;
+ }
}
bool MemMap::HasMemMap(MemMap* map) {
diff --git a/runtime/mem_map.h b/runtime/mem_map.h
index dc6d935..6023a70 100644
--- a/runtime/mem_map.h
+++ b/runtime/mem_map.h
@@ -137,7 +137,7 @@
static bool CheckNoGaps(MemMap* begin_map, MemMap* end_map)
LOCKS_EXCLUDED(Locks::mem_maps_lock_);
- static void DumpMaps(std::ostream& os)
+ static void DumpMaps(std::ostream& os, bool terse = false)
LOCKS_EXCLUDED(Locks::mem_maps_lock_);
typedef AllocationTrackingMultiMap<void*, MemMap*, kAllocatorTagMaps> Maps;
@@ -149,7 +149,7 @@
MemMap(const std::string& name, uint8_t* begin, size_t size, void* base_begin, size_t base_size,
int prot, bool reuse) LOCKS_EXCLUDED(Locks::mem_maps_lock_);
- static void DumpMapsLocked(std::ostream& os)
+ static void DumpMapsLocked(std::ostream& os, bool terse)
EXCLUSIVE_LOCKS_REQUIRED(Locks::mem_maps_lock_);
static bool HasMemMap(MemMap* map)
EXCLUSIVE_LOCKS_REQUIRED(Locks::mem_maps_lock_);