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 #ifndef SHARE_VM_SERVICES_MEM_RECORDER_HPP 26 #define SHARE_VM_SERVICES_MEM_RECORDER_HPP 27 28 #include "memory/allocation.hpp" 29 #include "runtime/os.hpp" 30 #include "services/memPtrArray.hpp" 31 32 class MemSnapshot; 33 class MemTracker; 34 class MemTrackWorker; 35 36 // Fixed size memory pointer array implementation 37 template <class E, int SIZE> class FixedSizeMemPointerArray : 38 public MemPointerArray { 39 // This implementation is for memory recorder only 40 friend class MemRecorder; 41 42 private: 43 E _data[SIZE]; 44 int _size; 45 46 protected: 47 FixedSizeMemPointerArray(bool init_elements = false): 48 _size(0){ 49 if (init_elements) { 50 for (int index = 0; index < SIZE; index ++) { 51 ::new ((void*)&_data[index]) E(); 52 } 53 } 54 } 55 56 void* operator new(size_t size, const std::nothrow_t& nothrow_constant) { 57 // the instance is part of memRecorder, needs to be tagged with 'otNMTRecorder' 58 // to avoid recursion 59 return os::malloc(size, (mtNMT | otNMTRecorder)); 60 } 61 62 void* operator new(size_t size) { 63 assert(false, "use nothrow version"); 64 return NULL; 65 } 66 67 void operator delete(void* p) { 68 os::free(p, (mtNMT | otNMTRecorder)); 69 } 70 71 // instance size 72 inline size_t instance_size() const { 73 return sizeof(FixedSizeMemPointerArray<E, SIZE>); 74 } 75 76 debug_only(int capacity() const { return SIZE; }) 77 78 public: 79 // implementation of public interface 80 bool out_of_memory() const { return false; } 81 bool is_empty() const { return _size == 0; } 82 bool is_full() { return length() >= SIZE; } 83 int length() const { return _size; } 84 85 void clear() { 86 _size = 0; 87 } 88 89 bool append(MemPointer* ptr) { 90 if (is_full()) return false; 91 _data[_size ++] = *(E*)ptr; 92 return true; 93 } 94 95 virtual bool insert_at(MemPointer* p, int pos) { 96 assert(false, "append only"); 97 return false; 98 } 99 100 virtual bool remove_at(int pos) { 101 assert(false, "not supported"); 102 return false; 103 } 104 105 MemPointer* at(int index) const { 106 assert(index >= 0 && index < length(), 107 "parameter check"); 108 return ((E*)&_data[index]); 109 } 110 111 void sort(FN_SORT fn) { 112 qsort((void*)_data, _size, sizeof(E), fn); 113 } 114 115 bool shrink() { 116 return false; 117 } 118 }; 119 120 121 // This iterator requires pre-sorted MemPointerArray, which is sorted by: 122 // 1. address 123 // 2. allocation type 124 // 3. sequence number 125 // During the array walking, iterator collapses pointers with the same 126 // address and allocation type, and only returns the one with highest 127 // sequence number. 128 // 129 // This is read-only iterator, update methods are asserted. 130 class SequencedRecordIterator : public MemPointerArrayIterator { 131 private: 132 MemPointerArrayIteratorImpl _itr; 133 MemPointer* _cur; 134 135 public: 136 SequencedRecordIterator(const MemPointerArray* arr): 137 _itr(const_cast<MemPointerArray*>(arr)) { 138 _cur = next_record(); 139 } 140 141 SequencedRecordIterator(const SequencedRecordIterator& itr): 142 _itr(itr._itr) { 143 _cur = next_record(); 144 } 145 146 // return the pointer at current position 147 virtual MemPointer* current() const { 148 return _cur; 149 }; 150 151 // return the next pointer and advance current position 152 virtual MemPointer* next() { 153 _cur = next_record(); 154 return _cur; 155 } 156 157 // return the next pointer without advancing current position 158 virtual MemPointer* peek_next() const { 159 assert(false, "not implemented"); 160 return NULL; 161 162 } 163 // return the previous pointer without changing current position 164 virtual MemPointer* peek_prev() const { 165 assert(false, "not implemented"); 166 return NULL; 167 } 168 169 // remove the pointer at current position 170 virtual void remove() { 171 assert(false, "read-only iterator"); 172 }; 173 // insert the pointer at current position 174 virtual bool insert(MemPointer* ptr) { 175 assert(false, "read-only iterator"); 176 return false; 177 } 178 179 virtual bool insert_after(MemPointer* ptr) { 180 assert(false, "read-only iterator"); 181 return false; 182 } 183 private: 184 // collapse the 'same kind' of records, and return this 'kind' of 185 // record with highest sequence number 186 MemPointer* next_record(); 187 188 // Test if the two records are the same kind: the same memory block and allocation 189 // type. 190 inline bool same_kind(const MemPointerRecord* p1, const MemPointerRecord* p2) const { 191 return (p1->addr() == p2->addr() && 192 (p1->flags() &MemPointerRecord::tag_masks) == 193 (p2->flags() & MemPointerRecord::tag_masks)); 194 } 195 }; 196 197 198 199 #define DEFAULT_RECORDER_PTR_ARRAY_SIZE 512 200 201 class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> { 202 friend class MemSnapshot; 203 friend class MemTracker; 204 friend class MemTrackWorker; 205 206 protected: 207 // the array that holds memory records 208 MemPointerArray* _pointer_records; 209 210 private: 211 // used for linked list 212 MemRecorder* _next; 213 // active recorder can only record a certain generation data 214 debug_only(unsigned long _generation;) 215 216 protected: 217 _NOINLINE_ MemRecorder(); 218 ~MemRecorder(); 219 220 // record a memory operation 221 bool record(address addr, MEMFLAGS flags, size_t size, address caller_pc = 0); 222 223 // linked list support 224 inline void set_next(MemRecorder* rec) { 225 _next = rec; 226 } 227 228 inline MemRecorder* next() const { 229 return _next; 230 } 231 232 // if the recorder is full 233 inline bool is_full() const { 234 assert(_pointer_records != NULL, "just check"); 235 return _pointer_records->is_full(); 236 } 237 238 // if running out of memory when initializing recorder's internal 239 // data 240 inline bool out_of_memory() const { 241 return (_pointer_records == NULL || 242 _pointer_records->out_of_memory()); 243 } 244 245 inline void clear() { 246 assert(_pointer_records != NULL, "Just check"); 247 _pointer_records->clear(); 248 } 249 250 SequencedRecordIterator pointer_itr(); 251 252 protected: 253 // number of MemRecorder instance 254 static volatile jint _instance_count; 255 256 private: 257 // sorting function, sort records into following order 258 // 1. memory address 259 // 2. allocation type 260 // 3. sequence number 261 static int sort_record_fn(const void* e1, const void* e2); 262 263 debug_only(void check_dup_seq(jint seq) const;) 264 debug_only(void set_generation();) 265 }; 266 267 #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP