/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/decoder.hpp"
#include "services/memBaseline.hpp"
#include "services/memPtr.hpp"
#include "services/memPtrArray.hpp"
#include "services/memSnapshot.hpp"
#include "services/memTracker.hpp"
#ifdef ASSERT
if (rec->is_vm_pointer()) {
if (rec->is_allocation_record()) {
} else if (rec->is_commit_record()) {
} else if (rec->is_uncommit_record()) {
} else if (rec->is_deallocation_record()) {
} else {
}
} else {
if (rec->is_arena_memory_record()) {
} else if (rec->is_allocation_record()) {
} else {
}
}
if (MemTracker::track_callsite()) {
} else {
}
}
}
if (rec->is_allocation_record()) {
} else if (rec->is_commit_record()) {
} else {
}
if (MemTracker::track_callsite()) {
} else {
}
}
}
#endif
"Sanity check");
if (MemTracker::track_callsite()) {
} else {
}
}
"Sanity check");
if (MemTracker::track_callsite()) {
} else {
}
return insert_after(&new_rec);
}
// we don't consolidate reserved regions, since they may be categorized
// in different types.
// we don't have anything yet
if (reserved_region == NULL) {
return insert_record(rec);
}
// duplicated records
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) {
"Attached JNI thread exited without being detached");
}
// otherwise, we should not have overlapping reserved regions
return insert_record(rec);
}
// we do consolidate committed regions
"Sanity check");
// thread's native stack is always marked as "committed", ignore
// the "commit" operation for creating stack guard pages
return true;
}
// if the reserved region has any committed regions
// duplicated commit records
return true;
// overlaps front part
} else {
// overlaps tail part
committed_rgn->size();
"overlap tail part");
}
// adjunct each other
// see if we can consolidate next committed region
// delete merged region
remove();
}
return true;
// found the location, insert this committed region
return insert_record(rec);
}
}
return insert_record(rec);
}
"Sanity check");
// thread's native stack is always marked as "committed", ignore
// the "commit" operation for creating stack guard pages
return true;
}
// region already uncommitted, must be due to duplicated record
break;
// uncommit whole region
remove();
break;
// uncommitted from either end of current memory region.
break;
} else { // split the committed region and release the middle
if (MemTracker::track_callsite()) {
return insert_record_after(&tmp);
} else {
return insert_record_after(&tmp);
}
}
}
}
// we may not find committed record due to duplicated records
return true;
}
"Sanity check");
// In snapshot, the virtual memory records are sorted in following orders:
// 1. virtual memory's base address
// 2. virtual memory reservation record, followed by commit records within this reservation.
// The commit records are also in base address order.
// When a reserved region is released, we want to remove the reservation record and all
// commit records following it.
#ifdef ASSERT
#endif
// remove virtual memory reservation record
remove();
// remove committed regions within above reservation
"Range check");
remove();
}
// released region is at either end of this region
} else { // split the reserved region and release the middle
if (MemTracker::track_callsite()) {
return ret;
} else {
return ret;
}
}
return true;
}
// skip all 'commit' records associated with previous reserved region
while (p != NULL && p->is_committed_region() &&
p = (VMMemRegion*)next();
}
return insert_record(rec);
}
bool VMMemPointerIterator::split_reserved_region(VMMemRegion* rgn, address new_rgn_addr, size_t new_rgn_size) {
// the original region becomes 'new' region
// remaining becomes next region
return insert_reserved_region(&next_rgn);
return insert_reserved_region(&next_rgn);
} else {
// the orginal region will be split into three
// first region
// the second region is the new region
if (!insert_reserved_region(&new_rgn)) return false;
// the remaining region
return insert_reserved_region(&rem_rgn);
}
}
}
if (MemTracker::track_callsite()) {
} else {
}
!_malloc_data->out_of_memory() &&
!_vm_data->out_of_memory()) {
return true;
} else {
_malloc_data = NULL;
return false;
}
}
// sort into seq number order
return VMRecordIterator(arr);
}
if (MemTracker::track_callsite()) {
} else {
}
NOT_PRODUCT(_untracked_count = 0;)
_number_of_classes = 0;
}
MemSnapshot::~MemSnapshot() {
{
if (_alloc_ptrs != NULL) {
delete _alloc_ptrs;
_alloc_ptrs = NULL;
}
delete _vm_ptrs;
}
}
delete _lock;
}
}
if (MemTracker::track_callsite()) {
} else {
}
}
if (MemTracker::track_callsite()) {
} else {
}
}
// merge a recorder to the staging area
while (incoming_rec != NULL) {
if (incoming_rec->is_vm_pointer()) {
// we don't do anything with virtual memory records during merge
return false;
}
} else {
// location for this incoming record.
// we have not seen this memory block in this generation,
// so just add to staging area
if (matched_rec == NULL) {
return false;
}
// whoever has higher sequence number wins
}
return false;
}
} else {
}
}
}
NOT_PRODUCT(void check_staging_data();)
return true;
}
// promote data to next generation
"Just check");
bool promoted = false;
if (promote_malloc_records(&malloc_itr)) {
if (promote_virtual_memory_records(&vm_itr)) {
promoted = true;
}
}
return promoted;
}
// found matched memory block
// snapshot already contains 'live' records
"Sanity check");
// update block states
if (new_rec->is_allocation_record()) {
} else if (new_rec->is_arena_memory_record()) {
// remove size record once size drops to 0
} else {
}
} else {
// a deallocation record
// an arena record can be followed by a size record, we need to remove both
if (matched_rec->is_arena_record()) {
}
}
// the memory is deallocated, remove related record(s)
}
} else {
// don't insert size 0 record
}
return false;
}
} else {
return false;
}
}
}
#ifndef PRODUCT
// NMT can not track some startup memory, which is allocated before NMT is on
_untracked_count ++;
}
#endif
}
}
}
return true;
}
// locate a reserved region that contains the specified address, or
// the nearest reserved region has base address just above the specified
// address
// snapshot can only have 'live' records
if (new_rec->is_allocation_record()) {
// only deal with split a bigger reserved region into smaller regions.
// So far, CDS is the only use case.
return false;
}
}
} else if (new_rec->is_uncommit_record()) {
return false;
}
} else if (new_rec->is_commit_record()) {
// insert or expand existing committed region to cover this
// newly committed region
return false;
}
} else if (new_rec->is_deallocation_record()) {
// release part or all memory region
return false;
}
} else if (new_rec->is_type_tagging_record()) {
// tag this reserved virtual memory range to a memory type. Can not re-tag a memory range
// to different type.
"Sanity check");
} else {
}
} else {
/*
* The assertion failure indicates mis-matched virtual memory records. The likely
* scenario is, that some virtual memory operations are not going through os::xxxx_memory()
* api, which have to be tracked manually. (perfMemory is an example).
*/
return false;
}
}
}
return true;
}
#ifndef PRODUCT
(100.0 * (float)_alloc_ptrs->length()) / (float)_alloc_ptrs->capacity(), _alloc_ptrs->instance_size()/K);
(100.0 * (float)_staging_area.malloc_data()->length()) / (float)_staging_area.malloc_data()->capacity(),
st->print_cr("\tVirtual memory staging Area: %d/%d [%5.2f%%] %dKB", _staging_area.vm_data()->length(),
}
while (p != NULL) {
}
prev = p;
}
}
return true;
}
}
return false;
}
#endif // PRODUCT
#ifdef ASSERT
"sorting order");
}
}
}
if (ptr->is_committed_region()) {
}
if (MemTracker::track_callsite()) {
} else {
}
}
}
}
}
#endif // ASSERT