zgu@3900: /* zgu@5272: * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. zgu@3900: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. zgu@3900: * zgu@3900: * This code is free software; you can redistribute it and/or modify it zgu@3900: * under the terms of the GNU General Public License version 2 only, as zgu@3900: * published by the Free Software Foundation. zgu@3900: * zgu@3900: * This code is distributed in the hope that it will be useful, but WITHOUT zgu@3900: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or zgu@3900: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License zgu@3900: * version 2 for more details (a copy is included in the LICENSE file that zgu@3900: * accompanied this code). zgu@3900: * zgu@3900: * You should have received a copy of the GNU General Public License version zgu@3900: * 2 along with this work; if not, write to the Free Software Foundation, zgu@3900: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. zgu@3900: * zgu@3900: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA zgu@3900: * or visit www.oracle.com if you need additional information or have any zgu@3900: * questions. zgu@3900: * zgu@3900: */ zgu@3900: zgu@3900: #include "precompiled.hpp" zgu@3900: zgu@3900: #include "runtime/atomic.hpp" zgu@3900: #include "services/memBaseline.hpp" zgu@3900: #include "services/memRecorder.hpp" zgu@3900: #include "services/memPtr.hpp" zgu@3900: #include "services/memTracker.hpp" zgu@3900: zgu@3900: MemPointer* SequencedRecordIterator::next_record() { zgu@4193: MemPointerRecord* itr_cur = (MemPointerRecord*)_itr.current(); zgu@4193: if (itr_cur == NULL) { zgu@4193: return itr_cur; zgu@4193: } zgu@3900: zgu@4193: MemPointerRecord* itr_next = (MemPointerRecord*)_itr.next(); zgu@4193: zgu@4193: // don't collapse virtual memory records zgu@4193: while (itr_next != NULL && !itr_cur->is_vm_pointer() && zgu@4193: !itr_next->is_vm_pointer() && zgu@4193: same_kind(itr_cur, itr_next)) { zgu@3900: itr_cur = itr_next; zgu@4193: itr_next = (MemPointerRecord*)_itr.next(); zgu@3900: } zgu@3900: zgu@3900: return itr_cur; zgu@3900: } zgu@3900: zgu@3900: zgu@3935: volatile jint MemRecorder::_instance_count = 0; zgu@3900: zgu@3900: MemRecorder::MemRecorder() { zgu@3900: assert(MemTracker::is_on(), "Native memory tracking is off"); zgu@3935: Atomic::inc(&_instance_count); ctornqvi@4512: set_generation(); zgu@3900: zgu@3900: if (MemTracker::track_callsite()) { zgu@3900: _pointer_records = new (std::nothrow)FixedSizeMemPointerArray(); zgu@3900: } else { zgu@3900: _pointer_records = new (std::nothrow)FixedSizeMemPointerArray(); zgu@3900: } zgu@3900: _next = NULL; zgu@3900: zgu@3900: zgu@3900: if (_pointer_records != NULL) { zgu@3900: // recode itself zgu@5272: address pc = CURRENT_PC; zgu@3900: record((address)this, (MemPointerRecord::malloc_tag()|mtNMT|otNMTRecorder), zgu@5272: sizeof(MemRecorder), SequenceGenerator::next(), pc); zgu@3900: record((address)_pointer_records, (MemPointerRecord::malloc_tag()|mtNMT|otNMTRecorder), zgu@5272: _pointer_records->instance_size(), SequenceGenerator::next(), pc); zgu@3900: } zgu@3900: } zgu@3900: zgu@3900: MemRecorder::~MemRecorder() { zgu@3900: if (_pointer_records != NULL) { zgu@3900: if (MemTracker::is_on()) { zgu@3900: MemTracker::record_free((address)_pointer_records, mtNMT); zgu@3900: MemTracker::record_free((address)this, mtNMT); zgu@3900: } zgu@3900: delete _pointer_records; zgu@3900: } zgu@4400: // delete all linked recorders zgu@4400: while (_next != NULL) { zgu@4400: MemRecorder* tmp = _next; zgu@4400: _next = _next->next(); zgu@4400: tmp->set_next(NULL); zgu@4400: delete tmp; zgu@3900: } zgu@3900: Atomic::dec(&_instance_count); zgu@3900: } zgu@3900: zgu@3900: // Sorting order: zgu@3900: // 1. memory block address zgu@3900: // 2. mem pointer record tags zgu@3900: // 3. sequence number zgu@3900: int MemRecorder::sort_record_fn(const void* e1, const void* e2) { zgu@3900: const MemPointerRecord* p1 = (const MemPointerRecord*)e1; zgu@3900: const MemPointerRecord* p2 = (const MemPointerRecord*)e2; zgu@3900: int delta = UNSIGNED_COMPARE(p1->addr(), p2->addr()); zgu@3900: if (delta == 0) { zgu@3900: int df = UNSIGNED_COMPARE((p1->flags() & MemPointerRecord::tag_masks), zgu@3900: (p2->flags() & MemPointerRecord::tag_masks)); zgu@3900: if (df == 0) { zgu@3900: assert(p1->seq() != p2->seq(), "dup seq"); zgu@3900: return p1->seq() - p2->seq(); zgu@3900: } else { zgu@3900: return df; zgu@3900: } zgu@3900: } else { zgu@3900: return delta; zgu@3900: } zgu@3900: } zgu@3900: zgu@5272: bool MemRecorder::record(address p, MEMFLAGS flags, size_t size, jint seq, address pc) { zgu@5272: assert(seq > 0, "No sequence number"); zgu@3900: #ifdef ASSERT zgu@3900: if (MemPointerRecord::is_virtual_memory_record(flags)) { zgu@3900: assert((flags & MemPointerRecord::tag_masks) != 0, "bad virtual memory record"); zgu@3900: } else { zgu@3900: assert((flags & MemPointerRecord::tag_masks) == MemPointerRecord::malloc_tag() || zgu@3900: (flags & MemPointerRecord::tag_masks) == MemPointerRecord::free_tag() || zgu@3900: IS_ARENA_OBJ(flags), zgu@3900: "bad malloc record"); zgu@3900: } zgu@3900: // a recorder should only hold records within the same generation zgu@3900: unsigned long cur_generation = SequenceGenerator::current_generation(); zgu@3900: assert(cur_generation == _generation, zgu@3900: "this thread did not enter sync point"); zgu@3900: #endif zgu@3900: zgu@3900: if (MemTracker::track_callsite()) { zgu@5272: SeqMemPointerRecordEx ap(p, flags, size, seq, pc); zgu@3900: debug_only(check_dup_seq(ap.seq());) zgu@3900: return _pointer_records->append(&ap); zgu@3900: } else { zgu@5272: SeqMemPointerRecord ap(p, flags, size, seq); zgu@3900: debug_only(check_dup_seq(ap.seq());) zgu@3900: return _pointer_records->append(&ap); zgu@3900: } zgu@3900: } zgu@3900: zgu@3900: // iterator for alloc pointers zgu@3900: SequencedRecordIterator MemRecorder::pointer_itr() { zgu@3900: assert(_pointer_records != NULL, "just check"); zgu@3900: _pointer_records->sort((FN_SORT)sort_record_fn); zgu@3900: return SequencedRecordIterator(_pointer_records); zgu@3900: } zgu@3900: zgu@3900: zgu@3900: void MemRecorder::set_generation() { zgu@3900: _generation = SequenceGenerator::current_generation(); zgu@3900: } zgu@3900: ctornqvi@4512: #ifdef ASSERT ctornqvi@4512: zgu@3900: void MemRecorder::check_dup_seq(jint seq) const { zgu@3900: MemPointerArrayIteratorImpl itr(_pointer_records); zgu@3900: MemPointerRecord* rc = (MemPointerRecord*)itr.current(); zgu@3900: while (rc != NULL) { zgu@3900: assert(rc->seq() != seq, "dup seq"); zgu@3900: rc = (MemPointerRecord*)itr.next(); zgu@3900: } zgu@3900: } zgu@3900: zgu@3900: #endif