Mercurial > hg > graal-jvmci-8
comparison src/share/vm/services/memBaseline.cpp @ 6882:716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
Summary: Enhanced virtual memory tracking to track committed regions as well as reserved regions, so NMT now can generate virtual memory map.
Reviewed-by: acorn, coleenp
author | zgu |
---|---|
date | Fri, 19 Oct 2012 21:40:07 -0400 |
parents | d2a62e0f25eb |
children | fb3190e77d3c |
comparison
equal
deleted
inserted
replaced
6879:8ebcedb7604d | 6882:716c64bda5ba |
---|---|
38 {mtInternal, "Internal"}, | 38 {mtInternal, "Internal"}, |
39 {mtOther, "Other"}, | 39 {mtOther, "Other"}, |
40 {mtSymbol, "Symbol"}, | 40 {mtSymbol, "Symbol"}, |
41 {mtNMT, "Memory Tracking"}, | 41 {mtNMT, "Memory Tracking"}, |
42 {mtChunk, "Pooled Free Chunks"}, | 42 {mtChunk, "Pooled Free Chunks"}, |
43 {mtClassShared,"Shared spaces for classes"}, | |
43 {mtNone, "Unknown"} // It can happen when type tagging records are lagging | 44 {mtNone, "Unknown"} // It can happen when type tagging records are lagging |
44 // behind | 45 // behind |
45 }; | 46 }; |
46 | 47 |
47 MemBaseline::MemBaseline() { | 48 MemBaseline::MemBaseline() { |
53 _arena_data[index].set_type(MemType2NameMap[index]._flag); | 54 _arena_data[index].set_type(MemType2NameMap[index]._flag); |
54 } | 55 } |
55 | 56 |
56 _malloc_cs = NULL; | 57 _malloc_cs = NULL; |
57 _vm_cs = NULL; | 58 _vm_cs = NULL; |
59 _vm_map = NULL; | |
58 | 60 |
59 _number_of_classes = 0; | 61 _number_of_classes = 0; |
60 _number_of_threads = 0; | 62 _number_of_threads = 0; |
61 } | 63 } |
62 | 64 |
68 } | 70 } |
69 | 71 |
70 if (_vm_cs != NULL) { | 72 if (_vm_cs != NULL) { |
71 delete _vm_cs; | 73 delete _vm_cs; |
72 _vm_cs = NULL; | 74 _vm_cs = NULL; |
75 } | |
76 | |
77 if (_vm_map != NULL) { | |
78 delete _vm_map; | |
79 _vm_map = NULL; | |
73 } | 80 } |
74 | 81 |
75 reset(); | 82 reset(); |
76 } | 83 } |
77 | 84 |
83 _total_malloced = 0; | 90 _total_malloced = 0; |
84 _number_of_classes = 0; | 91 _number_of_classes = 0; |
85 | 92 |
86 if (_malloc_cs != NULL) _malloc_cs->clear(); | 93 if (_malloc_cs != NULL) _malloc_cs->clear(); |
87 if (_vm_cs != NULL) _vm_cs->clear(); | 94 if (_vm_cs != NULL) _vm_cs->clear(); |
95 if (_vm_map != NULL) _vm_map->clear(); | |
88 | 96 |
89 for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { | 97 for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { |
90 _malloc_data[index].clear(); | 98 _malloc_data[index].clear(); |
91 _vm_data[index].clear(); | 99 _vm_data[index].clear(); |
92 _arena_data[index].clear(); | 100 _arena_data[index].clear(); |
93 } | 101 } |
94 } | 102 } |
95 | 103 |
96 MemBaseline::~MemBaseline() { | 104 MemBaseline::~MemBaseline() { |
97 if (_malloc_cs != NULL) { | 105 clear(); |
98 delete _malloc_cs; | |
99 } | |
100 | |
101 if (_vm_cs != NULL) { | |
102 delete _vm_cs; | |
103 } | |
104 } | 106 } |
105 | 107 |
106 // baseline malloc'd memory records, generate overall summary and summaries by | 108 // baseline malloc'd memory records, generate overall summary and summaries by |
107 // memory types | 109 // memory types |
108 bool MemBaseline::baseline_malloc_summary(const MemPointerArray* malloc_records) { | 110 bool MemBaseline::baseline_malloc_summary(const MemPointerArray* malloc_records) { |
109 MemPointerArrayIteratorImpl mItr((MemPointerArray*)malloc_records); | 111 MemPointerArrayIteratorImpl malloc_itr((MemPointerArray*)malloc_records); |
110 MemPointerRecord* mptr = (MemPointerRecord*)mItr.current(); | 112 MemPointerRecord* malloc_ptr = (MemPointerRecord*)malloc_itr.current(); |
111 size_t used_arena_size = 0; | 113 size_t used_arena_size = 0; |
112 int index; | 114 int index; |
113 while (mptr != NULL) { | 115 while (malloc_ptr != NULL) { |
114 index = flag2index(FLAGS_TO_MEMORY_TYPE(mptr->flags())); | 116 index = flag2index(FLAGS_TO_MEMORY_TYPE(malloc_ptr->flags())); |
115 size_t size = mptr->size(); | 117 size_t size = malloc_ptr->size(); |
116 _total_malloced += size; | 118 _total_malloced += size; |
117 _malloc_data[index].inc(size); | 119 _malloc_data[index].inc(size); |
118 if (MemPointerRecord::is_arena_record(mptr->flags())) { | 120 if (MemPointerRecord::is_arena_record(malloc_ptr->flags())) { |
119 // see if arena size record present | 121 // see if arena size record present |
120 MemPointerRecord* next_p = (MemPointerRecordEx*)mItr.peek_next(); | 122 MemPointerRecord* next_malloc_ptr = (MemPointerRecordEx*)malloc_itr.peek_next(); |
121 if (MemPointerRecord::is_arena_size_record(next_p->flags())) { | 123 if (MemPointerRecord::is_arena_size_record(next_malloc_ptr->flags())) { |
122 assert(next_p->is_size_record_of_arena(mptr), "arena records do not match"); | 124 assert(next_malloc_ptr->is_size_record_of_arena(malloc_ptr), "arena records do not match"); |
123 size = next_p->size(); | 125 size = next_malloc_ptr->size(); |
124 _arena_data[index].inc(size); | 126 _arena_data[index].inc(size); |
125 used_arena_size += size; | 127 used_arena_size += size; |
126 mItr.next(); | 128 malloc_itr.next(); |
127 } | 129 } |
128 } | 130 } |
129 mptr = (MemPointerRecordEx*)mItr.next(); | 131 malloc_ptr = (MemPointerRecordEx*)malloc_itr.next(); |
130 } | 132 } |
131 | 133 |
132 // substract used arena size to get size of arena chunk in free list | 134 // substract used arena size to get size of arena chunk in free list |
133 index = flag2index(mtChunk); | 135 index = flag2index(mtChunk); |
134 _malloc_data[index].reduce(used_arena_size); | 136 _malloc_data[index].reduce(used_arena_size); |
140 } | 142 } |
141 | 143 |
142 // baseline mmap'd memory records, generate overall summary and summaries by | 144 // baseline mmap'd memory records, generate overall summary and summaries by |
143 // memory types | 145 // memory types |
144 bool MemBaseline::baseline_vm_summary(const MemPointerArray* vm_records) { | 146 bool MemBaseline::baseline_vm_summary(const MemPointerArray* vm_records) { |
145 MemPointerArrayIteratorImpl vItr((MemPointerArray*)vm_records); | 147 MemPointerArrayIteratorImpl vm_itr((MemPointerArray*)vm_records); |
146 VMMemRegion* vptr = (VMMemRegion*)vItr.current(); | 148 VMMemRegion* vm_ptr = (VMMemRegion*)vm_itr.current(); |
147 int index; | 149 int index; |
148 while (vptr != NULL) { | 150 while (vm_ptr != NULL) { |
149 index = flag2index(FLAGS_TO_MEMORY_TYPE(vptr->flags())); | 151 if (vm_ptr->is_reserved_region()) { |
150 | 152 index = flag2index(FLAGS_TO_MEMORY_TYPE(vm_ptr->flags())); |
151 // we use the number of thread stack to count threads | 153 // we use the number of thread stack to count threads |
152 if (IS_MEMORY_TYPE(vptr->flags(), mtThreadStack)) { | 154 if (IS_MEMORY_TYPE(vm_ptr->flags(), mtThreadStack)) { |
153 _number_of_threads ++; | 155 _number_of_threads ++; |
154 } | 156 } |
155 _total_vm_reserved += vptr->reserved_size(); | 157 _total_vm_reserved += vm_ptr->size(); |
156 _total_vm_committed += vptr->committed_size(); | 158 _vm_data[index].inc(vm_ptr->size(), 0); |
157 _vm_data[index].inc(vptr->reserved_size(), vptr->committed_size()); | 159 } else { |
158 vptr = (VMMemRegion*)vItr.next(); | 160 _total_vm_committed += vm_ptr->size(); |
161 _vm_data[index].inc(0, vm_ptr->size()); | |
162 } | |
163 vm_ptr = (VMMemRegion*)vm_itr.next(); | |
159 } | 164 } |
160 return true; | 165 return true; |
161 } | 166 } |
162 | 167 |
163 // baseline malloc'd memory by callsites, but only the callsites with memory allocation | 168 // baseline malloc'd memory by callsites, but only the callsites with memory allocation |
164 // over 1KB are stored. | 169 // over 1KB are stored. |
165 bool MemBaseline::baseline_malloc_details(const MemPointerArray* malloc_records) { | 170 bool MemBaseline::baseline_malloc_details(const MemPointerArray* malloc_records) { |
166 assert(MemTracker::track_callsite(), "detail tracking is off"); | 171 assert(MemTracker::track_callsite(), "detail tracking is off"); |
167 | 172 |
168 MemPointerArrayIteratorImpl mItr((MemPointerArray*)malloc_records); | 173 MemPointerArrayIteratorImpl malloc_itr(const_cast<MemPointerArray*>(malloc_records)); |
169 MemPointerRecordEx* mptr = (MemPointerRecordEx*)mItr.current(); | 174 MemPointerRecordEx* malloc_ptr = (MemPointerRecordEx*)malloc_itr.current(); |
170 MallocCallsitePointer mp; | 175 MallocCallsitePointer malloc_callsite; |
171 | 176 |
177 // initailize malloc callsite array | |
172 if (_malloc_cs == NULL) { | 178 if (_malloc_cs == NULL) { |
173 _malloc_cs = new (std::nothrow) MemPointerArrayImpl<MallocCallsitePointer>(64); | 179 _malloc_cs = new (std::nothrow) MemPointerArrayImpl<MallocCallsitePointer>(64); |
174 // out of native memory | 180 // out of native memory |
175 if (_malloc_cs == NULL) { | 181 if (_malloc_cs == NULL || _malloc_cs->out_of_memory()) { |
176 return false; | 182 return false; |
177 } | 183 } |
178 } else { | 184 } else { |
179 _malloc_cs->clear(); | 185 _malloc_cs->clear(); |
180 } | 186 } |
181 | 187 |
188 MemPointerArray* malloc_data = const_cast<MemPointerArray*>(malloc_records); | |
189 | |
190 // sort into callsite pc order. Details are aggregated by callsites | |
191 malloc_data->sort((FN_SORT)malloc_sort_by_pc); | |
192 bool ret = true; | |
193 | |
182 // baseline memory that is totaled over 1 KB | 194 // baseline memory that is totaled over 1 KB |
183 while (mptr != NULL) { | 195 while (malloc_ptr != NULL) { |
184 if (!MemPointerRecord::is_arena_size_record(mptr->flags())) { | 196 if (!MemPointerRecord::is_arena_size_record(malloc_ptr->flags())) { |
185 // skip thread stacks | 197 // skip thread stacks |
186 if (!IS_MEMORY_TYPE(mptr->flags(), mtThreadStack)) { | 198 if (!IS_MEMORY_TYPE(malloc_ptr->flags(), mtThreadStack)) { |
187 if (mp.addr() != mptr->pc()) { | 199 if (malloc_callsite.addr() != malloc_ptr->pc()) { |
188 if ((mp.amount()/K) > 0) { | 200 if ((malloc_callsite.amount()/K) > 0) { |
189 if (!_malloc_cs->append(&mp)) { | 201 if (!_malloc_cs->append(&malloc_callsite)) { |
202 ret = false; | |
203 break; | |
204 } | |
205 } | |
206 malloc_callsite = MallocCallsitePointer(malloc_ptr->pc()); | |
207 } | |
208 malloc_callsite.inc(malloc_ptr->size()); | |
209 } | |
210 } | |
211 malloc_ptr = (MemPointerRecordEx*)malloc_itr.next(); | |
212 } | |
213 | |
214 // restore to address order. Snapshot malloc data is maintained in memory | |
215 // address order. | |
216 malloc_data->sort((FN_SORT)malloc_sort_by_addr); | |
217 | |
218 if (!ret) { | |
190 return false; | 219 return false; |
191 } | 220 } |
192 } | 221 // deal with last record |
193 mp = MallocCallsitePointer(mptr->pc()); | 222 if (malloc_callsite.addr() != 0 && (malloc_callsite.amount()/K) > 0) { |
194 } | 223 if (!_malloc_cs->append(&malloc_callsite)) { |
195 mp.inc(mptr->size()); | |
196 } | |
197 } | |
198 mptr = (MemPointerRecordEx*)mItr.next(); | |
199 } | |
200 | |
201 if (mp.addr() != 0 && (mp.amount()/K) > 0) { | |
202 if (!_malloc_cs->append(&mp)) { | |
203 return false; | 224 return false; |
204 } | 225 } |
205 } | 226 } |
206 return true; | 227 return true; |
207 } | 228 } |
208 | 229 |
209 // baseline mmap'd memory by callsites | 230 // baseline mmap'd memory by callsites |
210 bool MemBaseline::baseline_vm_details(const MemPointerArray* vm_records) { | 231 bool MemBaseline::baseline_vm_details(const MemPointerArray* vm_records) { |
211 assert(MemTracker::track_callsite(), "detail tracking is off"); | 232 assert(MemTracker::track_callsite(), "detail tracking is off"); |
212 | 233 |
213 VMCallsitePointer vp; | 234 VMCallsitePointer vm_callsite; |
214 MemPointerArrayIteratorImpl vItr((MemPointerArray*)vm_records); | 235 VMCallsitePointer* cur_callsite = NULL; |
215 VMMemRegionEx* vptr = (VMMemRegionEx*)vItr.current(); | 236 MemPointerArrayIteratorImpl vm_itr((MemPointerArray*)vm_records); |
216 | 237 VMMemRegionEx* vm_ptr = (VMMemRegionEx*)vm_itr.current(); |
238 | |
239 // initialize virtual memory map array | |
240 if (_vm_map == NULL) { | |
241 _vm_map = new (std::nothrow) MemPointerArrayImpl<VMMemRegionEx>(vm_records->length()); | |
242 if (_vm_map == NULL || _vm_map->out_of_memory()) { | |
243 return false; | |
244 } | |
245 } else { | |
246 _vm_map->clear(); | |
247 } | |
248 | |
249 // initialize virtual memory callsite array | |
217 if (_vm_cs == NULL) { | 250 if (_vm_cs == NULL) { |
218 _vm_cs = new (std::nothrow) MemPointerArrayImpl<VMCallsitePointer>(64); | 251 _vm_cs = new (std::nothrow) MemPointerArrayImpl<VMCallsitePointer>(64); |
219 if (_vm_cs == NULL) { | 252 if (_vm_cs == NULL || _vm_cs->out_of_memory()) { |
220 return false; | 253 return false; |
221 } | 254 } |
222 } else { | 255 } else { |
223 _vm_cs->clear(); | 256 _vm_cs->clear(); |
224 } | 257 } |
225 | 258 |
226 while (vptr != NULL) { | 259 // consolidate virtual memory data |
227 if (vp.addr() != vptr->pc()) { | 260 VMMemRegionEx* reserved_rec = NULL; |
228 if (!_vm_cs->append(&vp)) { | 261 VMMemRegionEx* committed_rec = NULL; |
262 | |
263 // vm_ptr is coming in increasing base address order | |
264 while (vm_ptr != NULL) { | |
265 if (vm_ptr->is_reserved_region()) { | |
266 // consolidate reserved memory regions for virtual memory map. | |
267 // The criteria for consolidation is: | |
268 // 1. two adjacent reserved memory regions | |
269 // 2. belong to the same memory type | |
270 // 3. reserved from the same callsite | |
271 if (reserved_rec == NULL || | |
272 reserved_rec->base() + reserved_rec->size() != vm_ptr->addr() || | |
273 FLAGS_TO_MEMORY_TYPE(reserved_rec->flags()) != FLAGS_TO_MEMORY_TYPE(vm_ptr->flags()) || | |
274 reserved_rec->pc() != vm_ptr->pc()) { | |
275 if (!_vm_map->append(vm_ptr)) { | |
229 return false; | 276 return false; |
230 } | 277 } |
231 vp = VMCallsitePointer(vptr->pc()); | 278 // inserted reserved region, we need the pointer to the element in virtual |
232 } | 279 // memory map array. |
233 vp.inc(vptr->size(), vptr->committed_size()); | 280 reserved_rec = (VMMemRegionEx*)_vm_map->at(_vm_map->length() - 1); |
234 vptr = (VMMemRegionEx*)vItr.next(); | 281 } else { |
235 } | 282 reserved_rec->expand_region(vm_ptr->addr(), vm_ptr->size()); |
236 if (vp.addr() != 0) { | 283 } |
237 if (!_vm_cs->append(&vp)) { | 284 |
285 if (cur_callsite != NULL && !_vm_cs->append(cur_callsite)) { | |
238 return false; | 286 return false; |
239 } | 287 } |
240 } | 288 vm_callsite = VMCallsitePointer(vm_ptr->pc()); |
289 cur_callsite = &vm_callsite; | |
290 vm_callsite.inc(vm_ptr->size(), 0); | |
291 } else { | |
292 // consolidate committed memory regions for virtual memory map | |
293 // The criterial is: | |
294 // 1. two adjacent committed memory regions | |
295 // 2. committed from the same callsite | |
296 if (committed_rec == NULL || | |
297 committed_rec->base() + committed_rec->size() != vm_ptr->addr() || | |
298 committed_rec->pc() != vm_ptr->pc()) { | |
299 if (!_vm_map->append(vm_ptr)) { | |
300 return false; | |
301 } | |
302 committed_rec = (VMMemRegionEx*)_vm_map->at(_vm_map->length() - 1); | |
303 } else { | |
304 committed_rec->expand_region(vm_ptr->addr(), vm_ptr->size()); | |
305 } | |
306 vm_callsite.inc(0, vm_ptr->size()); | |
307 } | |
308 vm_ptr = (VMMemRegionEx*)vm_itr.next(); | |
309 } | |
310 // deal with last record | |
311 if (cur_callsite != NULL && !_vm_cs->append(cur_callsite)) { | |
312 return false; | |
313 } | |
314 | |
315 // sort it into callsite pc order. Details are aggregated by callsites | |
316 _vm_cs->sort((FN_SORT)bl_vm_sort_by_pc); | |
317 | |
318 // walk the array to consolidate record by pc | |
319 MemPointerArrayIteratorImpl itr(_vm_cs); | |
320 VMCallsitePointer* callsite_rec = (VMCallsitePointer*)itr.current(); | |
321 VMCallsitePointer* next_rec = (VMCallsitePointer*)itr.next(); | |
322 while (next_rec != NULL) { | |
323 assert(callsite_rec != NULL, "Sanity check"); | |
324 if (next_rec->addr() == callsite_rec->addr()) { | |
325 callsite_rec->inc(next_rec->reserved_amount(), next_rec->committed_amount()); | |
326 itr.remove(); | |
327 next_rec = (VMCallsitePointer*)itr.current(); | |
328 } else { | |
329 callsite_rec = next_rec; | |
330 next_rec = (VMCallsitePointer*)itr.next(); | |
331 } | |
332 } | |
333 | |
241 return true; | 334 return true; |
242 } | 335 } |
243 | 336 |
244 // baseline a snapshot. If summary_only = false, memory usages aggregated by | 337 // baseline a snapshot. If summary_only = false, memory usages aggregated by |
245 // callsites are also baselined. | 338 // callsites are also baselined. |
249 _baselined = baseline_malloc_summary(snapshot._alloc_ptrs) && | 342 _baselined = baseline_malloc_summary(snapshot._alloc_ptrs) && |
250 baseline_vm_summary(snapshot._vm_ptrs); | 343 baseline_vm_summary(snapshot._vm_ptrs); |
251 _number_of_classes = SystemDictionary::number_of_classes(); | 344 _number_of_classes = SystemDictionary::number_of_classes(); |
252 | 345 |
253 if (!summary_only && MemTracker::track_callsite() && _baselined) { | 346 if (!summary_only && MemTracker::track_callsite() && _baselined) { |
254 ((MemPointerArray*)snapshot._alloc_ptrs)->sort((FN_SORT)malloc_sort_by_pc); | |
255 ((MemPointerArray*)snapshot._vm_ptrs)->sort((FN_SORT)vm_sort_by_pc); | |
256 _baselined = baseline_malloc_details(snapshot._alloc_ptrs) && | 347 _baselined = baseline_malloc_details(snapshot._alloc_ptrs) && |
257 baseline_vm_details(snapshot._vm_ptrs); | 348 baseline_vm_details(snapshot._vm_ptrs); |
258 ((MemPointerArray*)snapshot._alloc_ptrs)->sort((FN_SORT)malloc_sort_by_addr); | |
259 ((MemPointerArray*)snapshot._vm_ptrs)->sort((FN_SORT)vm_sort_by_addr); | |
260 } | 349 } |
261 return _baselined; | 350 return _baselined; |
262 } | 351 } |
263 | 352 |
264 | 353 |
276 for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { | 365 for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { |
277 if (MemType2NameMap[index]._flag == type) { | 366 if (MemType2NameMap[index]._flag == type) { |
278 return MemType2NameMap[index]._name; | 367 return MemType2NameMap[index]._name; |
279 } | 368 } |
280 } | 369 } |
281 assert(false, "no type"); | 370 assert(false, err_msg("bad type %x", type)); |
282 return NULL; | 371 return NULL; |
283 } | 372 } |
284 | 373 |
285 | 374 |
286 MemBaseline& MemBaseline::operator=(const MemBaseline& other) { | 375 MemBaseline& MemBaseline::operator=(const MemBaseline& other) { |
339 const MallocCallsitePointer* mp1 = (const MallocCallsitePointer*)p1; | 428 const MallocCallsitePointer* mp1 = (const MallocCallsitePointer*)p1; |
340 const MallocCallsitePointer* mp2 = (const MallocCallsitePointer*)p2; | 429 const MallocCallsitePointer* mp2 = (const MallocCallsitePointer*)p2; |
341 return UNSIGNED_COMPARE(mp1->addr(), mp2->addr()); | 430 return UNSIGNED_COMPARE(mp1->addr(), mp2->addr()); |
342 } | 431 } |
343 | 432 |
344 // sort snapshot mmap'd records in callsite pc order | |
345 int MemBaseline::vm_sort_by_pc(const void* p1, const void* p2) { | |
346 assert(MemTracker::track_callsite(),"Just check"); | |
347 const VMMemRegionEx* mp1 = (const VMMemRegionEx*)p1; | |
348 const VMMemRegionEx* mp2 = (const VMMemRegionEx*)p2; | |
349 return UNSIGNED_COMPARE(mp1->pc(), mp2->pc()); | |
350 } | |
351 | 433 |
352 // sort baselined mmap'd records in size (reserved size) order | 434 // sort baselined mmap'd records in size (reserved size) order |
353 int MemBaseline::bl_vm_sort_by_size(const void* p1, const void* p2) { | 435 int MemBaseline::bl_vm_sort_by_size(const void* p1, const void* p2) { |
354 assert(MemTracker::is_on(), "Just check"); | 436 assert(MemTracker::is_on(), "Just check"); |
355 const VMCallsitePointer* mp1 = (const VMCallsitePointer*)p1; | 437 const VMCallsitePointer* mp1 = (const VMCallsitePointer*)p1; |
374 int delta = UNSIGNED_COMPARE(mp1->addr(), mp2->addr()); | 456 int delta = UNSIGNED_COMPARE(mp1->addr(), mp2->addr()); |
375 assert(delta != 0, "dup pointer"); | 457 assert(delta != 0, "dup pointer"); |
376 return delta; | 458 return delta; |
377 } | 459 } |
378 | 460 |
379 // sort snapshot mmap'd records in memory block address order | |
380 int MemBaseline::vm_sort_by_addr(const void* p1, const void* p2) { | |
381 assert(MemTracker::is_on(), "Just check"); | |
382 const VMMemRegion* mp1 = (const VMMemRegion*)p1; | |
383 const VMMemRegion* mp2 = (const VMMemRegion*)p2; | |
384 int delta = UNSIGNED_COMPARE(mp1->addr(), mp2->addr()); | |
385 assert(delta != 0, "dup pointer"); | |
386 return delta; | |
387 } |