--- old/src/share/vm/services/memPtr.hpp 2012-10-31 11:57:28.011797000 -0400 +++ new/src/share/vm/services/memPtr.hpp 2012-10-31 11:57:26.848933000 -0400 @@ -299,18 +299,29 @@ } // if this memory region fully contains another one - inline bool contains_region(const MemPointerRecord* other) const { - return contains_region(other->addr(), other->size()); + inline bool contain_region(const MemPointerRecord* other) const { + return contain_region(other->addr(), other->size()); } // if this memory region fully contains specified memory range - inline bool contains_region(address add, size_t sz) const { + inline bool contain_region(address add, size_t sz) const { return (addr() <= add && addr() + size() >= add + sz); } - inline bool contains_address(address add) const { + inline bool contain_address(address add) const { return (addr() <= add && addr() + size() > add); } + + // if this memory region overlaps another region + inline bool overlap_region(const MemPointerRecord* other) const { + assert(other != NULL, "Just check"); + assert(size() > 0 && other->size() > 0, "empty range"); + return contain_address(other->addr()) || + contain_address(other->addr() + other->size() - 1) || // exclude end address + other->contain_address(addr()) || + other->contain_address(addr() + size() - 1); // exclude end address + } + }; // MemPointerRecordEx also records callsite pc, from where --- old/src/share/vm/services/memSnapshot.cpp 2012-10-31 11:57:31.330990000 -0400 +++ new/src/share/vm/services/memSnapshot.cpp 2012-10-31 11:57:30.270988000 -0400 @@ -31,6 +31,69 @@ #include "services/memSnapshot.hpp" #include "services/memTracker.hpp" +#ifdef ASSERT + +void decode_pointer_record(MemPointerRecord* rec) { + tty->print("Pointer: [" PTR_FORMAT " - " PTR_FORMAT "] size = %d bytes", rec->addr(), + rec->addr() + rec->size(), (int)rec->size()); + tty->print(" type = %s", MemBaseline::type2name(FLAGS_TO_MEMORY_TYPE(rec->flags()))); + if (rec->is_vm_pointer()) { + if (rec->is_allocation_record()) { + tty->print_cr(" (reserve)"); + } else if (rec->is_commit_record()) { + tty->print_cr(" (commit)"); + } else if (rec->is_uncommit_record()) { + tty->print_cr(" (uncommit)"); + } else if (rec->is_deallocation_record()) { + tty->print_cr(" (release)"); + } else { + tty->print_cr(" (tag)"); + } + } else { + if (rec->is_arena_size_record()) { + tty->print_cr(" (arena size)"); + } else if (rec->is_allocation_record()) { + tty->print_cr(" (malloc)"); + } else { + tty->print_cr(" (free)"); + } + } + if (MemTracker::track_callsite()) { + char buf[1024]; + address pc = ((MemPointerRecordEx*)rec)->pc(); + if (pc != NULL && os::dll_address_to_function_name(pc, buf, sizeof(buf), NULL)) { + tty->print_cr("\tfrom %s", buf); + } else { + tty->print_cr("\tcould not decode pc = " PTR_FORMAT "", pc); + } + } +} + +void decode_vm_region_record(VMMemRegion* rec) { + tty->print("VM Region [" PTR_FORMAT " - " PTR_FORMAT "]", rec->addr(), + rec->addr() + rec->size()); + tty->print(" type = %s", MemBaseline::type2name(FLAGS_TO_MEMORY_TYPE(rec->flags()))); + if (rec->is_allocation_record()) { + tty->print_cr(" (reserved)"); + } else if (rec->is_commit_record()) { + tty->print_cr(" (committed)"); + } else { + ShouldNotReachHere(); + } + if (MemTracker::track_callsite()) { + char buf[1024]; + address pc = ((VMMemRegionEx*)rec)->pc(); + if (pc != NULL && os::dll_address_to_function_name(pc, buf, sizeof(buf), NULL)) { + tty->print_cr("\tfrom %s", buf); + } else { + tty->print_cr("\tcould not decode pc = " PTR_FORMAT "", pc); + } + + } +} + +#endif + bool VMMemPointerIterator::insert_record(MemPointerRecord* rec) { VMMemRegionEx new_rec; @@ -60,65 +123,74 @@ // in different types. bool VMMemPointerIterator::add_reserved_region(MemPointerRecord* rec) { assert(rec->is_allocation_record(), "Sanity check"); - VMMemRegion* cur = (VMMemRegion*)current(); + VMMemRegion* reserved_rgn = (VMMemRegion*)current(); // we don't have anything yet - if (cur == NULL) { + if (reserved_rgn == NULL) { return insert_record(rec); } - assert(cur->is_reserved_region(), "Sanity check"); + assert(reserved_rgn->is_reserved_region(), "Sanity check"); // duplicated records - if (cur->is_same_region(rec)) { + if (reserved_rgn->is_same_region(rec)) { return true; } - assert(cur->base() > rec->addr(), "Just check: locate()"); - assert(rec->addr() + rec->size() <= cur->base(), "Can not overlap"); + assert(reserved_rgn->base() > rec->addr(), "Just check: locate()"); + assert(!reserved_rgn->overlap_region(rec), "Can not overlap"); return insert_record(rec); } // we do consolidate committed regions bool VMMemPointerIterator::add_committed_region(MemPointerRecord* rec) { assert(rec->is_commit_record(), "Sanity check"); - VMMemRegion* cur; - cur = (VMMemRegion*)current(); - assert(cur->is_reserved_region() && cur->contains_region(rec), + VMMemRegion* reserved_rgn = (VMMemRegion*)current(); + assert(reserved_rgn->is_reserved_region() && reserved_rgn->contain_region(rec), "Sanity check"); // thread's native stack is always marked as "committed", ignore // the "commit" operation for creating stack guard pages - if (FLAGS_TO_MEMORY_TYPE(cur->flags()) == mtThreadStack && + if (FLAGS_TO_MEMORY_TYPE(reserved_rgn->flags()) == mtThreadStack && FLAGS_TO_MEMORY_TYPE(rec->flags()) != mtThreadStack) { return true; } - cur = (VMMemRegion*)next(); - while (cur != NULL && cur->is_committed_region()) { + // if the reserved region has any committed regions + VMMemRegion* committed_rgn = (VMMemRegion*)next(); + while (committed_rgn != NULL && committed_rgn->is_committed_region()) { // duplicated commit records - if(cur->contains_region(rec)) { + if(committed_rgn->contain_region(rec)) { return true; - } - if (cur->base() > rec->addr()) { - // committed regions can not overlap - assert(rec->addr() + rec->size() <= cur->base(), "Can not overlap"); - if (rec->addr() + rec->size() == cur->base()) { - cur->expand_region(rec->addr(), rec->size()); - return true; + } else if (committed_rgn->overlap_region(rec)) { + // overlaps front part + if (rec->addr() < committed_rgn->addr()) { + committed_rgn->expand_region(rec->addr(), + committed_rgn->addr() - rec->addr()); } else { - return insert_record(rec); + // overlaps tail part + address committed_rgn_end = committed_rgn->addr() + + committed_rgn->size(); + assert(committed_rgn_end < rec->addr() + rec->size(), + "overlap tail part"); + committed_rgn->expand_region(committed_rgn_end, + (rec->addr() + rec->size()) - committed_rgn_end); } - } else if (cur->base() + cur->size() == rec->addr()) { - cur->expand_region(rec->addr(), rec->size()); + } else if (committed_rgn->base() + committed_rgn->size() == rec->addr()) { + // adjunct each other + committed_rgn->expand_region(rec->addr(), rec->size()); VMMemRegion* next_reg = (VMMemRegion*)next(); // see if we can consolidate next committed region if (next_reg != NULL && next_reg->is_committed_region() && - next_reg->base() == cur->base() + cur->size()) { - cur->expand_region(next_reg->base(), next_reg->size()); + next_reg->base() == committed_rgn->base() + committed_rgn->size()) { + committed_rgn->expand_region(next_reg->base(), next_reg->size()); + // delete merged region remove(); } return true; + } else if (committed_rgn->base() > rec->addr()) { + // found the location, insert this committed region + return insert_record(rec); } - cur = (VMMemRegion*)next(); + committed_rgn = (VMMemRegion*)next(); } return insert_record(rec); } @@ -127,7 +199,7 @@ assert(rec->is_uncommit_record(), "sanity check"); VMMemRegion* cur; cur = (VMMemRegion*)current(); - assert(cur->is_reserved_region() && cur->contains_region(rec), + assert(cur->is_reserved_region() && cur->contain_region(rec), "Sanity check"); // thread's native stack is always marked as "committed", ignore // the "commit" operation for creating stack guard pages @@ -141,7 +213,7 @@ // region already uncommitted, must be due to duplicated record if (cur->addr() >= rec->addr() + rec->size()) { break; - } else if (cur->contains_region(rec)) { + } else if (cur->contain_region(rec)) { // uncommit whole region if (cur->is_same_region(rec)) { remove(); @@ -176,7 +248,7 @@ bool VMMemPointerIterator::remove_released_region(MemPointerRecord* rec) { assert(rec->is_deallocation_record(), "Sanity check"); VMMemRegion* cur = (VMMemRegion*)current(); - assert(cur->is_reserved_region() && cur->contains_region(rec), + assert(cur->is_reserved_region() && cur->contain_region(rec), "Sanity check"); #ifdef ASSERT VMMemRegion* next_reg = (VMMemRegion*)peek_next(); @@ -217,7 +289,7 @@ } bool VMMemPointerIterator::split_reserved_region(VMMemRegion* rgn, address new_rgn_addr, size_t new_rgn_size) { - assert(rgn->contains_region(new_rgn_addr, new_rgn_size), "Not fully contained"); + assert(rgn->contain_region(new_rgn_addr, new_rgn_size), "Not fully contained"); address pc = (MemTracker::track_callsite() ? ((VMMemRegionEx*)rgn)->pc() : NULL); if (rgn->base() == new_rgn_addr) { // new region is at the beginning of the region size_t sz = rgn->size() - new_rgn_size; @@ -501,7 +573,7 @@ // the nearest reserved region has base address just above the specified // address reserved_rec = (VMMemRegion*)vm_snapshot_itr.locate(new_rec->addr()); - if (reserved_rec != NULL && reserved_rec->contains_region(new_rec)) { + if (reserved_rec != NULL && reserved_rec->contain_region(new_rec)) { // snapshot can only have 'live' records assert(reserved_rec->is_reserved_region(), "Sanity check"); if (new_rec->is_allocation_record()) { --- old/src/share/vm/services/memSnapshot.hpp 2012-10-31 11:57:34.695593000 -0400 +++ new/src/share/vm/services/memSnapshot.hpp 2012-10-31 11:57:33.668244000 -0400 @@ -119,10 +119,10 @@ VMMemRegion* reg = (VMMemRegion*)current(); while (reg != NULL) { if (reg->is_reserved_region()) { - if (reg->contains_address(addr) || addr < reg->base()) { + if (reg->contain_address(addr) || addr < reg->base()) { return reg; + } } - } reg = (VMMemRegion*)next(); } return NULL;