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 NOT_PRODUCT(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 assert(!p1->is_vm_pointer() && !p2->is_vm_pointer(), "malloc pointer only"); 192 return (p1->addr() == p2->addr() && 193 (p1->flags() &MemPointerRecord::tag_masks) == 194 (p2->flags() & MemPointerRecord::tag_masks)); 195 } 196 }; 197 198 199 200 #define DEFAULT_RECORDER_PTR_ARRAY_SIZE 512 201 202 class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> { 203 friend class MemSnapshot; 204 friend class MemTracker; 205 friend class MemTrackWorker; 206 207 protected: 208 // the array that holds memory records 209 MemPointerArray* _pointer_records; 210 211 private: 212 // used for linked list 213 MemRecorder* _next; 214 // active recorder can only record a certain generation data 215 debug_only(unsigned long _generation;) 216 217 protected: 218 _NOINLINE_ MemRecorder(); 219 ~MemRecorder(); 220 221 // record a memory operation 222 bool record(address addr, MEMFLAGS flags, size_t size, address caller_pc = 0); 223 224 // linked list support 225 inline void set_next(MemRecorder* rec) { 226 _next = rec; 227 } 228 229 inline MemRecorder* next() const { 230 return _next; 231 } 232 233 // if the recorder is full 234 inline bool is_full() const { 235 assert(_pointer_records != NULL, "just check"); 236 return _pointer_records->is_full(); 237 } 238 239 // if running out of memory when initializing recorder's internal 240 // data 241 inline bool out_of_memory() const { 242 return (_pointer_records == NULL || 243 _pointer_records->out_of_memory()); 244 } 245 246 inline void clear() { 247 assert(_pointer_records != NULL, "Just check"); 248 _pointer_records->clear(); 249 } 250 251 SequencedRecordIterator pointer_itr(); 252 253 protected: 254 // number of MemRecorder instance 255 static volatile jint _instance_count; 256 257 private: 258 // sorting function, sort records into following order 259 // 1. memory address 260 // 2. allocation type 261 // 3. sequence number 262 static int sort_record_fn(const void* e1, const void* e2); 263 264 debug_only(void check_dup_seq(jint seq) const;) 265 debug_only(void set_generation();) 266 }; 267 268 #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP