// we don't consolidate reserved regions, since they may be categorized // in different types. bool VMMemPointerIterator::add_reserved_region(MemPointerRecord* rec) { assert(rec->is_allocation_record(), "Sanity check"); VMMemRegion* reserved_region = (VMMemRegion*)current(); // we don't have anything yet if (reserved_region == NULL) { return insert_record(rec); } assert(reserved_region->is_reserved_region(), "Sanity check"); // duplicated records if (reserved_region->is_same_region(rec)) { return true; } // Overlapping stack regions indicate that a JNI thread failed to // detach from the VM before exiting. This leaks the JavaThread object. if (CheckJNICalls) { guarantee(FLAGS_TO_MEMORY_TYPE(reserved_region->flags()) != mtThreadStack || !reserved_region->overlaps_region(rec), "Attached JNI thread exited without being detached"); } // otherwise, we should not have overlapping reserved regions assert(FLAGS_TO_MEMORY_TYPE(reserved_region->flags()) == mtThreadStack || reserved_region->base() > rec->addr(), "Just check: locate()"); assert(FLAGS_TO_MEMORY_TYPE(reserved_region->flags()) == mtThreadStack || !reserved_region->overlaps_region(rec), "overlapping reserved regions"); return insert_record(rec); }
// we do consolidate committed regions bool VMMemPointerIterator::add_committed_region(MemPointerRecord* rec) { assert(rec->is_commit_record(), "Sanity check"); VMMemRegion* reserved_rgn = (VMMemRegion*)current(); assert(reserved_rgn->is_reserved_region() && reserved_rgn->contains_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(reserved_rgn->flags()) == mtThreadStack && FLAGS_TO_MEMORY_TYPE(rec->flags()) != mtThreadStack) { return true; } // 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(committed_rgn->contains_region(rec)) { return true; } else if (committed_rgn->overlaps_region(rec)) { // overlaps front part if (rec->addr() < committed_rgn->addr()) { committed_rgn->expand_region(rec->addr(), committed_rgn->addr() - rec->addr()); } else { // 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 (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() == 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); } committed_rgn = (VMMemRegion*)next(); } return insert_record(rec); }
bool VMMemPointerIterator::remove_uncommitted_region(MemPointerRecord* rec) { assert(rec->is_uncommit_record(), "sanity check"); VMMemRegion* cur; cur = (VMMemRegion*)current(); assert(cur->is_reserved_region() && cur->contains_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 && FLAGS_TO_MEMORY_TYPE(rec->flags()) != mtThreadStack) { return true; } cur = (VMMemRegion*)next(); while (cur != NULL && cur->is_committed_region()) { // region already uncommitted, must be due to duplicated record if (cur->addr() >= rec->addr() + rec->size()) { break; } else if (cur->contains_region(rec)) { // uncommit whole region if (cur->is_same_region(rec)) { remove(); break; } else if (rec->addr() == cur->addr() || rec->addr() + rec->size() == cur->addr() + cur->size()) { // uncommitted from either end of current memory region. cur->exclude_region(rec->addr(), rec->size()); break; } else { // split the committed region and release the middle address high_addr = cur->addr() + cur->size(); size_t sz = high_addr - rec->addr(); cur->exclude_region(rec->addr(), sz); sz = high_addr - (rec->addr() + rec->size()); if (MemTracker::track_callsite()) { MemPointerRecordEx tmp(rec->addr() + rec->size(), cur->flags(), sz, ((VMMemRegionEx*)cur)->pc()); return insert_record_after(&tmp); } else { MemPointerRecord tmp(rec->addr() + rec->size(), cur->flags(), sz); return insert_record_after(&tmp); } } } cur = (VMMemRegion*)next(); } // we may not find committed record due to duplicated records return true; }
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_memory_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); } } }
VMMem(MEMFLAGS flags) { assert(HAS_VALID_MEMORY_TYPE(flags), "no type"); _type = FLAGS_TO_MEMORY_TYPE(flags); _count = 0; _reserved_amount = 0; _committed_amount = 0; }
void BaselineReporter::report_virtual_memory_map(const MemBaseline& baseline) { _outputer.start_virtual_memory_map(); MemBaseline* pBL = const_cast<MemBaseline*>(&baseline); MemPointerArrayIteratorImpl itr = MemPointerArrayIteratorImpl(pBL->_vm_map); VMMemRegionEx* rgn = (VMMemRegionEx*)itr.current(); while (rgn != NULL) { if (rgn->is_reserved_region()) { _outputer.reserved_memory_region(FLAGS_TO_MEMORY_TYPE(rgn->flags()), rgn->base(), rgn->base() + rgn->size(), amount_in_current_scale(rgn->size()), rgn->pc()); } else { _outputer.committed_memory_region(rgn->base(), rgn->base() + rgn->size(), amount_in_current_scale(rgn->size()), rgn->pc()); } rgn = (VMMemRegionEx*)itr.next(); } _outputer.done_virtual_memory_map(); }
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); } } }
bool is_duplicated_record(MemPointerRecord* p1, MemPointerRecord* p2) const { bool ret = (p1->addr() == p2->addr() && p1->size() == p2->size() && p1->flags() == p2->flags()); assert(!(ret && FLAGS_TO_MEMORY_TYPE(p1->flags()) == mtThreadStack), "dup on stack record"); return ret; }
inline bool is_type(MEMFLAGS flags) const { return FLAGS_TO_MEMORY_TYPE(flags) == _type; }
inline void set_type(MEMFLAGS flags) { _type = FLAGS_TO_MEMORY_TYPE(flags); }
MallocMem(MEMFLAGS flags) { assert(HAS_VALID_MEMORY_TYPE(flags), "no type"); _type = FLAGS_TO_MEMORY_TYPE(flags); _count = 0; _amount = 0; }