1 /* 2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 27 #include "runtime/atomic.hpp" 28 #include "services/memBaseline.hpp" 29 #include "services/memRecorder.hpp" 30 #include "services/memPtr.hpp" 31 #include "services/memTracker.hpp" 32 33 MemPointer* SequencedRecordIterator::next_record() { 34 MemPointer* itr_cur = _itr.current(); 35 if (itr_cur == NULL) return NULL; 36 MemPointer* itr_next = _itr.next(); 37 38 while (itr_next != NULL && 39 same_kind((MemPointerRecord*)itr_cur, (MemPointerRecord*)itr_next)) { 40 itr_cur = itr_next; 41 itr_next = _itr.next(); 42 } 43 44 return itr_cur; 45 } 46 47 48 debug_only(volatile jint MemRecorder::_instance_count = 0;) 49 50 MemRecorder::MemRecorder() { 51 assert(MemTracker::is_on(), "Native memory tracking is off"); 52 debug_only(Atomic::inc(&_instance_count);) 53 debug_only(set_generation();) 54 55 if (MemTracker::track_callsite()) { 56 _pointer_records = new (std::nothrow)FixedSizeMemPointerArray<SeqMemPointerRecordEx, 57 DEFAULT_RECORDER_PTR_ARRAY_SIZE>(); 58 } else { 59 _pointer_records = new (std::nothrow)FixedSizeMemPointerArray<SeqMemPointerRecord, 60 DEFAULT_RECORDER_PTR_ARRAY_SIZE>(); 61 } 62 _next = NULL; 63 64 65 if (_pointer_records != NULL) { 66 // recode itself 67 record((address)this, (MemPointerRecord::malloc_tag()|mtNMT|otNMTRecorder), 68 sizeof(MemRecorder), CALLER_PC); 69 record((address)_pointer_records, (MemPointerRecord::malloc_tag()|mtNMT|otNMTRecorder), 70 _pointer_records->instance_size(),CURRENT_PC); 71 } 72 } 73 74 MemRecorder::~MemRecorder() { 75 if (_pointer_records != NULL) { 76 if (MemTracker::is_on()) { 77 MemTracker::record_free((address)_pointer_records, mtNMT); 78 MemTracker::record_free((address)this, mtNMT); 79 } 80 delete _pointer_records; 81 } 82 if (_next != NULL) { 83 delete _next; 84 } 85 86 #ifdef ASSERT 87 Atomic::dec(&_instance_count); 88 #endif 89 } 90 91 // Sorting order: 92 // 1. memory block address 93 // 2. mem pointer record tags 94 // 3. sequence number 95 int MemRecorder::sort_record_fn(const void* e1, const void* e2) { 96 const MemPointerRecord* p1 = (const MemPointerRecord*)e1; 97 const MemPointerRecord* p2 = (const MemPointerRecord*)e2; 98 int delta = UNSIGNED_COMPARE(p1->addr(), p2->addr()); 99 if (delta == 0) { 100 int df = UNSIGNED_COMPARE((p1->flags() & MemPointerRecord::tag_masks), 101 (p2->flags() & MemPointerRecord::tag_masks)); 102 if (df == 0) { 103 assert(p1->seq() != p2->seq(), "dup seq"); 104 return p1->seq() - p2->seq(); 105 } else { 106 return df; 107 } 108 } else { 109 return delta; 110 } 111 } 112 113 bool MemRecorder::record(address p, MEMFLAGS flags, size_t size, address pc) { 114 #ifdef ASSERT 115 if (MemPointerRecord::is_virtual_memory_record(flags)) { 116 assert((flags & MemPointerRecord::tag_masks) != 0, "bad virtual memory record"); 117 } else { 118 assert((flags & MemPointerRecord::tag_masks) == MemPointerRecord::malloc_tag() || 119 (flags & MemPointerRecord::tag_masks) == MemPointerRecord::free_tag() || 120 IS_ARENA_OBJ(flags), 121 "bad malloc record"); 122 } 123 // a recorder should only hold records within the same generation 124 unsigned long cur_generation = SequenceGenerator::current_generation(); 125 assert(cur_generation == _generation, 126 "this thread did not enter sync point"); 127 #endif 128 129 if (MemTracker::track_callsite()) { 130 SeqMemPointerRecordEx ap(p, flags, size, pc); 131 debug_only(check_dup_seq(ap.seq());) 132 return _pointer_records->append(&ap); 133 } else { 134 SeqMemPointerRecord ap(p, flags, size); 135 debug_only(check_dup_seq(ap.seq());) 136 return _pointer_records->append(&ap); 137 } 138 } 139 140 // iterator for alloc pointers 141 SequencedRecordIterator MemRecorder::pointer_itr() { 142 assert(_pointer_records != NULL, "just check"); 143 _pointer_records->sort((FN_SORT)sort_record_fn); 144 return SequencedRecordIterator(_pointer_records); 145 } 146 147 148 #ifdef ASSERT 149 void MemRecorder::set_generation() { 150 _generation = SequenceGenerator::current_generation(); 151 } 152 153 void MemRecorder::check_dup_seq(jint seq) const { 154 MemPointerArrayIteratorImpl itr(_pointer_records); 155 MemPointerRecord* rc = (MemPointerRecord*)itr.current(); 156 while (rc != NULL) { 157 assert(rc->seq() != seq, "dup seq"); 158 rc = (MemPointerRecord*)itr.next(); 159 } 160 } 161 162 #endif