< prev index next >

src/hotspot/share/services/virtualMemoryTracker.cpp

Print this page

        

*** 21,30 **** --- 21,31 ---- * questions. * */ #include "precompiled.hpp" + #include "logging/log.hpp" #include "memory/metaspace.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "runtime/threadCritical.hpp" #include "services/memTracker.hpp"
*** 36,45 **** --- 37,52 ---- assert(sizeof(_snapshot) >= sizeof(VirtualMemorySnapshot), "Sanity Check"); // Use placement operator new to initialize static data area. ::new ((void*)_snapshot) VirtualMemorySnapshot(); } + void VirtualMemorySummary::snapshot(VirtualMemorySnapshot* s) { + // Snapshot current thread stacks + VirtualMemoryTracker::snapshot_thread_stacks(); + as_snapshot()->copy_to(s); + } + SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>* VirtualMemoryTracker::_reserved_regions; int compare_committed_region(const CommittedMemoryRegion& r1, const CommittedMemoryRegion& r2) { return r1.compare(r2); }
*** 284,293 **** --- 291,320 ---- VirtualMemorySummary::move_committed_memory(flag(), f, committed_size()); _flag = f; } } + address ReservedMemoryRegion::thread_stack_uncommitted_bottom() const { + assert(flag() == mtThreadStack, "Only for thread stack"); + LinkedListNode<CommittedMemoryRegion>* head = _committed_regions.head(); + address bottom = base(); + address top = base() + size(); + while (head != NULL) { + address committed_top = head->data()->base() + head->data()->size(); + if (committed_top < top) { + // committed stack guard pages, skip them + bottom = head->data()->base() + head->data()->size(); + head = head->next(); + } else { + assert(top == committed_top, "Sanity"); + break; + } + } + + return bottom; + } + bool VirtualMemoryTracker::initialize(NMT_TrackingLevel level) { if (level >= NMT_summary) { VirtualMemorySummary::initialize(); } return true;
*** 458,467 **** --- 485,568 ---- } } } } + // Iterate the range, find committed region within its bound. + class RegionIterator : public StackObj { + private: + const address _start; + const size_t _size; + + address _current_start; + size_t _current_size; + public: + RegionIterator(address start, size_t size) : + _start(start), _size(size), _current_start(start), _current_size(size) { + } + + // return true if committed region is found + bool next_committed(address& start, size_t& size); + private: + address end() const { return _start + _size; } + }; + + bool RegionIterator::next_committed(address& committed_start, size_t& committed_size) { + if (end() <= _current_start) return false; + + const size_t page_sz = os::vm_page_size(); + assert(_current_start + _current_size == end(), "Must be"); + if (os::committed_in_range(_current_start, _current_size, committed_start, committed_size)) { + assert(committed_start != NULL, "Must be"); + assert(committed_size > 0 && is_aligned(committed_size, os::vm_page_size()), "Must be"); + + size_t remaining_size = (_current_start + _current_size) - (committed_start + committed_size); + _current_start = committed_start + committed_size; + _current_size = remaining_size; + return true; + } else { + return false; + } + } + + // Walk all known thread stacks, snapshot their committed ranges. + class SnapshotThreadStackWalker : public VirtualMemoryWalker { + public: + SnapshotThreadStackWalker() {} + + bool do_allocation_site(const ReservedMemoryRegion* rgn) { + if (rgn->flag() == mtThreadStack) { + address stack_bottom = rgn->thread_stack_uncommitted_bottom(); + address committed_start; + size_t committed_size; + size_t stack_size = rgn->base() + rgn->size() - stack_bottom; + + ReservedMemoryRegion* region = const_cast<ReservedMemoryRegion*>(rgn); + NativeCallStack ncs; // empty stack + + RegionIterator itr(stack_bottom, stack_size); + DEBUG_ONLY(bool found_stack = false;) + while (itr.next_committed(committed_start, committed_size)) { + assert(committed_start != NULL, "Should not be null"); + assert(committed_size > 0, "Should not be 0"); + region->add_committed_region(committed_start, committed_size, ncs); + DEBUG_ONLY(found_stack = true;) + } + #ifdef ASSERT + if (!found_stack) { + log_debug(thread)("Thread exited without proper cleanup, may leak thread object"); + } + #endif + } + return true; + } + }; + + void VirtualMemoryTracker::snapshot_thread_stacks() { + SnapshotThreadStackWalker walker; + walk_virtual_memory(&walker); + } bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) { assert(_reserved_regions != NULL, "Sanity check"); ThreadCritical tc; // Check that the _reserved_regions haven't been deleted.
< prev index next >