src/share/vm/services/memRecorder.hpp

Thu, 19 Jul 2012 09:05:42 -0400

author
zgu
date
Thu, 19 Jul 2012 09:05:42 -0400
changeset 3935
7e5976e66c62
parent 3900
d2a62e0f25eb
child 3994
e5bf1c79ed5b
permissions
-rw-r--r--

7182543: NMT ON: Aggregate a few NMT related bugs
Summary: 1) Fixed MemTrackWorker::generations_in_used() calculation 2) Ensured NMT not to leak memory recorders after shutdown 3) Used ThreadCritical to block safepoint safe threads
Reviewed-by: acorn, coleenp, dholmes, kvn

zgu@3900 1 /*
zgu@3900 2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
zgu@3900 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
zgu@3900 4 *
zgu@3900 5 * This code is free software; you can redistribute it and/or modify it
zgu@3900 6 * under the terms of the GNU General Public License version 2 only, as
zgu@3900 7 * published by the Free Software Foundation.
zgu@3900 8 *
zgu@3900 9 * This code is distributed in the hope that it will be useful, but WITHOUT
zgu@3900 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
zgu@3900 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
zgu@3900 12 * version 2 for more details (a copy is included in the LICENSE file that
zgu@3900 13 * accompanied this code).
zgu@3900 14 *
zgu@3900 15 * You should have received a copy of the GNU General Public License version
zgu@3900 16 * 2 along with this work; if not, write to the Free Software Foundation,
zgu@3900 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
zgu@3900 18 *
zgu@3900 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
zgu@3900 20 * or visit www.oracle.com if you need additional information or have any
zgu@3900 21 * questions.
zgu@3900 22 *
zgu@3900 23 */
zgu@3900 24
zgu@3900 25 #ifndef SHARE_VM_SERVICES_MEM_RECORDER_HPP
zgu@3900 26 #define SHARE_VM_SERVICES_MEM_RECORDER_HPP
zgu@3900 27
zgu@3900 28 #include "memory/allocation.hpp"
zgu@3900 29 #include "runtime/os.hpp"
zgu@3900 30 #include "services/memPtrArray.hpp"
zgu@3900 31
zgu@3900 32 class MemSnapshot;
zgu@3900 33 class MemTracker;
zgu@3900 34 class MemTrackWorker;
zgu@3900 35
zgu@3900 36 // Fixed size memory pointer array implementation
zgu@3900 37 template <class E, int SIZE> class FixedSizeMemPointerArray :
zgu@3900 38 public MemPointerArray {
zgu@3900 39 // This implementation is for memory recorder only
zgu@3900 40 friend class MemRecorder;
zgu@3900 41
zgu@3900 42 private:
zgu@3900 43 E _data[SIZE];
zgu@3900 44 int _size;
zgu@3900 45
zgu@3900 46 protected:
zgu@3900 47 FixedSizeMemPointerArray(bool init_elements = false):
zgu@3900 48 _size(0){
zgu@3900 49 if (init_elements) {
zgu@3900 50 for (int index = 0; index < SIZE; index ++) {
zgu@3900 51 ::new ((void*)&_data[index]) E();
zgu@3900 52 }
zgu@3900 53 }
zgu@3900 54 }
zgu@3900 55
zgu@3900 56 void* operator new(size_t size, const std::nothrow_t& nothrow_constant) {
zgu@3900 57 // the instance is part of memRecorder, needs to be tagged with 'otNMTRecorder'
zgu@3900 58 // to avoid recursion
zgu@3900 59 return os::malloc(size, (mtNMT | otNMTRecorder));
zgu@3900 60 }
zgu@3900 61
zgu@3900 62 void* operator new(size_t size) {
zgu@3900 63 assert(false, "use nothrow version");
zgu@3900 64 return NULL;
zgu@3900 65 }
zgu@3900 66
zgu@3900 67 void operator delete(void* p) {
zgu@3900 68 os::free(p, (mtNMT | otNMTRecorder));
zgu@3900 69 }
zgu@3900 70
zgu@3900 71 // instance size
zgu@3900 72 inline size_t instance_size() const {
zgu@3900 73 return sizeof(FixedSizeMemPointerArray<E, SIZE>);
zgu@3900 74 }
zgu@3900 75
zgu@3900 76 debug_only(int capacity() const { return SIZE; })
zgu@3900 77
zgu@3900 78 public:
zgu@3900 79 // implementation of public interface
zgu@3900 80 bool out_of_memory() const { return false; }
zgu@3900 81 bool is_empty() const { return _size == 0; }
zgu@3900 82 bool is_full() { return length() >= SIZE; }
zgu@3900 83 int length() const { return _size; }
zgu@3900 84
zgu@3900 85 void clear() {
zgu@3900 86 _size = 0;
zgu@3900 87 }
zgu@3900 88
zgu@3900 89 bool append(MemPointer* ptr) {
zgu@3900 90 if (is_full()) return false;
zgu@3900 91 _data[_size ++] = *(E*)ptr;
zgu@3900 92 return true;
zgu@3900 93 }
zgu@3900 94
zgu@3900 95 virtual bool insert_at(MemPointer* p, int pos) {
zgu@3900 96 assert(false, "append only");
zgu@3900 97 return false;
zgu@3900 98 }
zgu@3900 99
zgu@3900 100 virtual bool remove_at(int pos) {
zgu@3900 101 assert(false, "not supported");
zgu@3900 102 return false;
zgu@3900 103 }
zgu@3900 104
zgu@3900 105 MemPointer* at(int index) const {
zgu@3900 106 assert(index >= 0 && index < length(),
zgu@3900 107 "parameter check");
zgu@3900 108 return ((E*)&_data[index]);
zgu@3900 109 }
zgu@3900 110
zgu@3900 111 void sort(FN_SORT fn) {
zgu@3900 112 qsort((void*)_data, _size, sizeof(E), fn);
zgu@3900 113 }
zgu@3900 114
zgu@3900 115 bool shrink() {
zgu@3900 116 return false;
zgu@3900 117 }
zgu@3900 118 };
zgu@3900 119
zgu@3900 120
zgu@3900 121 // This iterator requires pre-sorted MemPointerArray, which is sorted by:
zgu@3900 122 // 1. address
zgu@3900 123 // 2. allocation type
zgu@3900 124 // 3. sequence number
zgu@3900 125 // During the array walking, iterator collapses pointers with the same
zgu@3900 126 // address and allocation type, and only returns the one with highest
zgu@3900 127 // sequence number.
zgu@3900 128 //
zgu@3900 129 // This is read-only iterator, update methods are asserted.
zgu@3900 130 class SequencedRecordIterator : public MemPointerArrayIterator {
zgu@3900 131 private:
zgu@3900 132 MemPointerArrayIteratorImpl _itr;
zgu@3900 133 MemPointer* _cur;
zgu@3900 134
zgu@3900 135 public:
zgu@3900 136 SequencedRecordIterator(const MemPointerArray* arr):
zgu@3900 137 _itr(const_cast<MemPointerArray*>(arr)) {
zgu@3900 138 _cur = next_record();
zgu@3900 139 }
zgu@3900 140
zgu@3900 141 SequencedRecordIterator(const SequencedRecordIterator& itr):
zgu@3900 142 _itr(itr._itr) {
zgu@3900 143 _cur = next_record();
zgu@3900 144 }
zgu@3900 145
zgu@3900 146 // return the pointer at current position
zgu@3900 147 virtual MemPointer* current() const {
zgu@3900 148 return _cur;
zgu@3900 149 };
zgu@3900 150
zgu@3900 151 // return the next pointer and advance current position
zgu@3900 152 virtual MemPointer* next() {
zgu@3900 153 _cur = next_record();
zgu@3900 154 return _cur;
zgu@3900 155 }
zgu@3900 156
zgu@3900 157 // return the next pointer without advancing current position
zgu@3900 158 virtual MemPointer* peek_next() const {
zgu@3900 159 assert(false, "not implemented");
zgu@3900 160 return NULL;
zgu@3900 161
zgu@3900 162 }
zgu@3900 163 // return the previous pointer without changing current position
zgu@3900 164 virtual MemPointer* peek_prev() const {
zgu@3900 165 assert(false, "not implemented");
zgu@3900 166 return NULL;
zgu@3900 167 }
zgu@3900 168
zgu@3900 169 // remove the pointer at current position
zgu@3900 170 virtual void remove() {
zgu@3900 171 assert(false, "read-only iterator");
zgu@3900 172 };
zgu@3900 173 // insert the pointer at current position
zgu@3900 174 virtual bool insert(MemPointer* ptr) {
zgu@3900 175 assert(false, "read-only iterator");
zgu@3900 176 return false;
zgu@3900 177 }
zgu@3900 178
zgu@3900 179 virtual bool insert_after(MemPointer* ptr) {
zgu@3900 180 assert(false, "read-only iterator");
zgu@3900 181 return false;
zgu@3900 182 }
zgu@3900 183 private:
zgu@3900 184 // collapse the 'same kind' of records, and return this 'kind' of
zgu@3900 185 // record with highest sequence number
zgu@3900 186 MemPointer* next_record();
zgu@3900 187
zgu@3900 188 // Test if the two records are the same kind: the same memory block and allocation
zgu@3900 189 // type.
zgu@3900 190 inline bool same_kind(const MemPointerRecord* p1, const MemPointerRecord* p2) const {
zgu@3900 191 return (p1->addr() == p2->addr() &&
zgu@3900 192 (p1->flags() &MemPointerRecord::tag_masks) ==
zgu@3900 193 (p2->flags() & MemPointerRecord::tag_masks));
zgu@3900 194 }
zgu@3900 195 };
zgu@3900 196
zgu@3900 197
zgu@3900 198
zgu@3900 199 #define DEFAULT_RECORDER_PTR_ARRAY_SIZE 512
zgu@3900 200
zgu@3900 201 class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> {
zgu@3900 202 friend class MemSnapshot;
zgu@3900 203 friend class MemTracker;
zgu@3900 204 friend class MemTrackWorker;
zgu@3900 205
zgu@3900 206 protected:
zgu@3900 207 // the array that holds memory records
zgu@3900 208 MemPointerArray* _pointer_records;
zgu@3900 209
zgu@3900 210 private:
zgu@3900 211 // used for linked list
zgu@3900 212 MemRecorder* _next;
zgu@3900 213 // active recorder can only record a certain generation data
zgu@3900 214 debug_only(unsigned long _generation;)
zgu@3900 215
zgu@3900 216 protected:
zgu@3900 217 _NOINLINE_ MemRecorder();
zgu@3900 218 ~MemRecorder();
zgu@3900 219
zgu@3900 220 // record a memory operation
zgu@3900 221 bool record(address addr, MEMFLAGS flags, size_t size, address caller_pc = 0);
zgu@3900 222
zgu@3900 223 // linked list support
zgu@3900 224 inline void set_next(MemRecorder* rec) {
zgu@3900 225 _next = rec;
zgu@3900 226 }
zgu@3900 227
zgu@3900 228 inline MemRecorder* next() const {
zgu@3900 229 return _next;
zgu@3900 230 }
zgu@3900 231
zgu@3900 232 // if the recorder is full
zgu@3900 233 inline bool is_full() const {
zgu@3900 234 assert(_pointer_records != NULL, "just check");
zgu@3900 235 return _pointer_records->is_full();
zgu@3900 236 }
zgu@3900 237
zgu@3900 238 // if running out of memory when initializing recorder's internal
zgu@3900 239 // data
zgu@3900 240 inline bool out_of_memory() const {
zgu@3900 241 return (_pointer_records == NULL ||
zgu@3900 242 _pointer_records->out_of_memory());
zgu@3900 243 }
zgu@3900 244
zgu@3900 245 inline void clear() {
zgu@3900 246 assert(_pointer_records != NULL, "Just check");
zgu@3900 247 _pointer_records->clear();
zgu@3900 248 }
zgu@3900 249
zgu@3900 250 SequencedRecordIterator pointer_itr();
zgu@3900 251
zgu@3935 252 protected:
zgu@3900 253 // number of MemRecorder instance
zgu@3935 254 static volatile jint _instance_count;
zgu@3900 255
zgu@3900 256 private:
zgu@3900 257 // sorting function, sort records into following order
zgu@3900 258 // 1. memory address
zgu@3900 259 // 2. allocation type
zgu@3900 260 // 3. sequence number
zgu@3900 261 static int sort_record_fn(const void* e1, const void* e2);
zgu@3900 262
zgu@3900 263 debug_only(void check_dup_seq(jint seq) const;)
zgu@3900 264 debug_only(void set_generation();)
zgu@3900 265 };
zgu@3900 266
zgu@3900 267 #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP

mercurial