comparison src/share/vm/services/memSnapshot.hpp @ 6741:33143ee07800

7181995: NMT ON: NMT assertion failure assert(cur_vm->is_uncommit_record() || cur_vm->is_deallocation_record Summary: Fixed virtual memory records merge and promotion logic, should be based on sequence number vs. base address order Reviewed-by: coleenp, acorn
author zgu
date Tue, 11 Sep 2012 20:53:17 -0400
parents 4acebbe310e1
children 716c64bda5ba
comparison
equal deleted inserted replaced
6730:5d2156bcb78b 6741:33143ee07800
109 public: 109 public:
110 VMMemPointerIterator(MemPointerArray* arr): 110 VMMemPointerIterator(MemPointerArray* arr):
111 MemPointerIterator(arr) { 111 MemPointerIterator(arr) {
112 } 112 }
113 113
114 // locate an exiting record that contains specified address, or 114 // locate an existing record that contains specified address, or
115 // the record, where the record with specified address, should 115 // the record, where the record with specified address, should
116 // be inserted 116 // be inserted.
117 // virtual memory record array is sorted in address order, so
118 // binary search is performed
117 virtual MemPointer* locate(address addr) { 119 virtual MemPointer* locate(address addr) {
118 VMMemRegion* cur = (VMMemRegion*)current(); 120 int index_low = 0;
119 VMMemRegion* next_p; 121 int index_high = _array->length();
120 122 int index_mid = (index_high + index_low) / 2;
121 while (cur != NULL) { 123 int r = 1;
122 if (cur->base() > addr) { 124 while (index_low < index_high && (r = compare(index_mid, addr)) != 0) {
123 return cur; 125 if (r > 0) {
126 index_high = index_mid;
124 } else { 127 } else {
125 // find nearest existing range that has base address <= addr 128 index_low = index_mid;
126 next_p = (VMMemRegion*)peek_next();
127 if (next_p != NULL && next_p->base() <= addr) {
128 cur = (VMMemRegion*)next();
129 continue;
130 }
131 } 129 }
132 130 index_mid = (index_high + index_low) / 2;
133 if (cur->is_reserve_record() && 131 }
134 cur->base() <= addr && 132 if (r == 0) {
135 (cur->base() + cur->size() > addr)) { 133 // update current location
136 return cur; 134 _pos = index_mid;
137 } else if (cur->is_commit_record() && 135 return _array->at(index_mid);
138 cur->base() <= addr && 136 } else {
139 (cur->base() + cur->committed_size() > addr)) { 137 return NULL;
140 return cur; 138 }
141 }
142 cur = (VMMemRegion*)next();
143 }
144 return NULL;
145 } 139 }
146 140
147 #ifdef ASSERT 141 #ifdef ASSERT
148 virtual bool is_dup_pointer(const MemPointer* ptr1, 142 virtual bool is_dup_pointer(const MemPointer* ptr1,
149 const MemPointer* ptr2) const { 143 const MemPointer* ptr2) const {
158 // we do see multiple commit/uncommit on the same memory, it is ok 152 // we do see multiple commit/uncommit on the same memory, it is ok
159 return (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_alloc || 153 return (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_alloc ||
160 (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release; 154 (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release;
161 } 155 }
162 #endif 156 #endif
163 }; 157 // compare if an address falls into a memory region,
164 158 // return 0, if the address falls into a memory region at specified index
165 class StagingWalker : public MemPointerArrayIterator { 159 // return 1, if memory region pointed by specified index is higher than the address
160 // return -1, if memory region pointed by specified index is lower than the address
161 int compare(int index, address addr) const {
162 VMMemRegion* r = (VMMemRegion*)_array->at(index);
163 assert(r->is_reserve_record(), "Sanity check");
164 if (r->addr() > addr) {
165 return 1;
166 } else if (r->addr() + r->reserved_size() <= addr) {
167 return -1;
168 } else {
169 return 0;
170 }
171 }
172 };
173
174 class MallocRecordIterator : public MemPointerArrayIterator {
166 private: 175 private:
167 MemPointerArrayIteratorImpl _itr; 176 MemPointerArrayIteratorImpl _itr;
168 bool _is_vm_record; 177
169 bool _end_of_array; 178 public:
170 VMMemRegionEx _vm_record; 179 MallocRecordIterator(MemPointerArray* arr) : _itr(arr) {
171 MemPointerRecordEx _malloc_record; 180 }
172 181
173 public:
174 StagingWalker(MemPointerArray* arr): _itr(arr) {
175 _end_of_array = false;
176 next();
177 }
178
179 // return the pointer at current position
180 MemPointer* current() const { 182 MemPointer* current() const {
181 if (_end_of_array) { 183 MemPointerRecord* cur = (MemPointerRecord*)_itr.current();
184 assert(cur == NULL || !cur->is_vm_pointer(), "seek error");
185 MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next();
186 if (next == NULL || next->addr() != cur->addr()) {
187 return cur;
188 } else {
189 assert(!cur->is_vm_pointer(), "Sanity check");
190 assert(cur->is_allocation_record() && next->is_deallocation_record(),
191 "sorting order");
192 assert(cur->seq() != next->seq(), "Sanity check");
193 return cur->seq() > next->seq() ? cur : next;
194 }
195 }
196
197 MemPointer* next() {
198 MemPointerRecord* cur = (MemPointerRecord*)_itr.current();
199 assert(cur == NULL || !cur->is_vm_pointer(), "Sanity check");
200 MemPointerRecord* next = (MemPointerRecord*)_itr.next();
201 if (next == NULL) {
182 return NULL; 202 return NULL;
183 } 203 }
184 if (is_vm_record()) { 204 if (cur->addr() == next->addr()) {
185 return (MemPointer*)&_vm_record; 205 next = (MemPointerRecord*)_itr.next();
186 } else { 206 }
187 return (MemPointer*)&_malloc_record; 207 return current();
188 } 208 }
189 } 209
190 210 MemPointer* peek_next() const { ShouldNotReachHere(); return NULL; }
191 // return the next pointer and advance current position 211 MemPointer* peek_prev() const { ShouldNotReachHere(); return NULL; }
192 MemPointer* next(); 212 void remove() { ShouldNotReachHere(); }
193 213 bool insert(MemPointer* ptr) { ShouldNotReachHere(); return false; }
194 // type of 'current' record 214 bool insert_after(MemPointer* ptr) { ShouldNotReachHere(); return false; }
195 bool is_vm_record() const { 215 };
196 return _is_vm_record; 216
197 } 217 class StagingArea : public _ValueObj {
198
199 // return the next poinger without advancing current position
200 MemPointer* peek_next() const {
201 assert(false, "not supported");
202 return NULL;
203 }
204
205 MemPointer* peek_prev() const {
206 assert(false, "not supported");
207 return NULL;
208 }
209 // remove the pointer at current position
210 void remove() {
211 assert(false, "not supported");
212 }
213
214 // insert the pointer at current position
215 bool insert(MemPointer* ptr) {
216 assert(false, "not supported");
217 return false;
218 }
219
220 bool insert_after(MemPointer* ptr) {
221 assert(false, "not supported");
222 return false;
223 }
224
225 private: 218 private:
226 // consolidate all records referring to this vm region 219 MemPointerArray* _malloc_data;
227 bool consolidate_vm_records(VMMemRegionEx* vm_rec); 220 MemPointerArray* _vm_data;
221
222 public:
223 StagingArea() : _malloc_data(NULL), _vm_data(NULL) {
224 init();
225 }
226
227 ~StagingArea() {
228 if (_malloc_data != NULL) delete _malloc_data;
229 if (_vm_data != NULL) delete _vm_data;
230 }
231
232 MallocRecordIterator malloc_record_walker() {
233 return MallocRecordIterator(malloc_data());
234 }
235
236 MemPointerArrayIteratorImpl virtual_memory_record_walker();
237 bool init();
238 void clear() {
239 assert(_malloc_data != NULL && _vm_data != NULL, "Just check");
240 _malloc_data->shrink();
241 _malloc_data->clear();
242 _vm_data->clear();
243 }
244
245 inline MemPointerArray* malloc_data() { return _malloc_data; }
246 inline MemPointerArray* vm_data() { return _vm_data; }
228 }; 247 };
229 248
230 class MemBaseline; 249 class MemBaseline;
231
232 class MemSnapshot : public CHeapObj<mtNMT> { 250 class MemSnapshot : public CHeapObj<mtNMT> {
233 private: 251 private:
234 // the following two arrays contain records of all known lived memory blocks 252 // the following two arrays contain records of all known lived memory blocks
235 // live malloc-ed memory pointers 253 // live malloc-ed memory pointers
236 MemPointerArray* _alloc_ptrs; 254 MemPointerArray* _alloc_ptrs;
237 // live virtual memory pointers 255 // live virtual memory pointers
238 MemPointerArray* _vm_ptrs; 256 MemPointerArray* _vm_ptrs;
239 257
240 // stagging a generation's data, before 258 StagingArea _staging_area;
241 // it can be prompted to snapshot
242 MemPointerArray* _staging_area;
243 259
244 // the lock to protect this snapshot 260 // the lock to protect this snapshot
245 Monitor* _lock; 261 Monitor* _lock;
246 262
247 NOT_PRODUCT(size_t _untracked_count;) 263 NOT_PRODUCT(size_t _untracked_count;)
250 public: 266 public:
251 MemSnapshot(); 267 MemSnapshot();
252 virtual ~MemSnapshot(); 268 virtual ~MemSnapshot();
253 269
254 // if we are running out of native memory 270 // if we are running out of native memory
255 bool out_of_memory() const { 271 bool out_of_memory() {
256 return (_alloc_ptrs == NULL || _staging_area == NULL || 272 return (_alloc_ptrs == NULL ||
273 _staging_area.malloc_data() == NULL ||
274 _staging_area.vm_data() == NULL ||
257 _vm_ptrs == NULL || _lock == NULL || 275 _vm_ptrs == NULL || _lock == NULL ||
258 _alloc_ptrs->out_of_memory() || 276 _alloc_ptrs->out_of_memory() ||
259 _staging_area->out_of_memory() ||
260 _vm_ptrs->out_of_memory()); 277 _vm_ptrs->out_of_memory());
261 } 278 }
262 279
263 // merge a per-thread memory recorder into staging area 280 // merge a per-thread memory recorder into staging area
264 bool merge(MemRecorder* rec); 281 bool merge(MemRecorder* rec);
265 // promote staged data to snapshot 282 // promote staged data to snapshot
266 void promote(); 283 bool promote();
267 284
268 285
269 void wait(long timeout) { 286 void wait(long timeout) {
270 assert(_lock != NULL, "Just check"); 287 assert(_lock != NULL, "Just check");
271 MonitorLockerEx locker(_lock); 288 MonitorLockerEx locker(_lock);
278 NOT_PRODUCT(bool has_allocation_record(address addr);) 295 NOT_PRODUCT(bool has_allocation_record(address addr);)
279 296
280 private: 297 private:
281 // copy pointer data from src to dest 298 // copy pointer data from src to dest
282 void copy_pointer(MemPointerRecord* dest, const MemPointerRecord* src); 299 void copy_pointer(MemPointerRecord* dest, const MemPointerRecord* src);
300
301 bool promote_malloc_records(MemPointerArrayIterator* itr);
302 bool promote_virtual_memory_records(MemPointerArrayIterator* itr);
283 }; 303 };
284 304
285 305
286 #endif // SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP 306 #endif // SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP