comparison src/share/vm/services/memSnapshot.cpp @ 6979:fb3190e77d3c

8001592: NMT: assertion failed: assert(_amount >= amt) failed: Just check: memBaseline.hpp:180 Summary: Fixed NMT that miscounted arena memory when it is used as value or stack object. Reviewed-by: acorn, coleenp
author zgu
date Fri, 09 Nov 2012 19:24:31 -0500
parents 69ad7823b1ca
children 8c413497f434
comparison
equal deleted inserted replaced
6938:8940ddc1036f 6979:fb3190e77d3c
48 tty->print_cr(" (release)"); 48 tty->print_cr(" (release)");
49 } else { 49 } else {
50 tty->print_cr(" (tag)"); 50 tty->print_cr(" (tag)");
51 } 51 }
52 } else { 52 } else {
53 if (rec->is_arena_size_record()) { 53 if (rec->is_arena_memory_record()) {
54 tty->print_cr(" (arena size)"); 54 tty->print_cr(" (arena size)");
55 } else if (rec->is_allocation_record()) { 55 } else if (rec->is_allocation_record()) {
56 tty->print_cr(" (malloc)"); 56 tty->print_cr(" (malloc)");
57 } else { 57 } else {
58 tty->print_cr(" (free)"); 58 tty->print_cr(" (free)");
388 delete _lock; 388 delete _lock;
389 _lock = NULL; 389 _lock = NULL;
390 } 390 }
391 } 391 }
392 392
393 void MemSnapshot::copy_pointer(MemPointerRecord* dest, const MemPointerRecord* src) { 393
394 void MemSnapshot::copy_seq_pointer(MemPointerRecord* dest, const MemPointerRecord* src) {
394 assert(dest != NULL && src != NULL, "Just check"); 395 assert(dest != NULL && src != NULL, "Just check");
395 assert(dest->addr() == src->addr(), "Just check"); 396 assert(dest->addr() == src->addr(), "Just check");
396 397 assert(dest->seq() > 0 && src->seq() > 0, "not sequenced");
397 MEMFLAGS flags = dest->flags(); 398
399 if (MemTracker::track_callsite()) {
400 *(SeqMemPointerRecordEx*)dest = *(SeqMemPointerRecordEx*)src;
401 } else {
402 *(SeqMemPointerRecord*)dest = *(SeqMemPointerRecord*)src;
403 }
404 }
405
406 void MemSnapshot::assign_pointer(MemPointerRecord*dest, const MemPointerRecord* src) {
407 assert(src != NULL && dest != NULL, "Just check");
408 assert(dest->seq() == 0 && src->seq() >0, "cast away sequence");
398 409
399 if (MemTracker::track_callsite()) { 410 if (MemTracker::track_callsite()) {
400 *(MemPointerRecordEx*)dest = *(MemPointerRecordEx*)src; 411 *(MemPointerRecordEx*)dest = *(MemPointerRecordEx*)src;
401 } else { 412 } else {
402 *dest = *src; 413 *(MemPointerRecord*)dest = *(MemPointerRecord*)src;
403 } 414 }
404 } 415 }
405 416
406 417 // merge a recorder to the staging area
407 // merge a per-thread memory recorder to the staging area
408 bool MemSnapshot::merge(MemRecorder* rec) { 418 bool MemSnapshot::merge(MemRecorder* rec) {
409 assert(rec != NULL && !rec->out_of_memory(), "Just check"); 419 assert(rec != NULL && !rec->out_of_memory(), "Just check");
410 420
411 SequencedRecordIterator itr(rec->pointer_itr()); 421 SequencedRecordIterator itr(rec->pointer_itr());
412 422
413 MutexLockerEx lock(_lock, true); 423 MutexLockerEx lock(_lock, true);
414 MemPointerIterator malloc_staging_itr(_staging_area.malloc_data()); 424 MemPointerIterator malloc_staging_itr(_staging_area.malloc_data());
415 MemPointerRecord *p1, *p2; 425 MemPointerRecord* incoming_rec = (MemPointerRecord*) itr.current();
416 p1 = (MemPointerRecord*) itr.current(); 426 MemPointerRecord* matched_rec;
417 while (p1 != NULL) { 427
418 if (p1->is_vm_pointer()) { 428 while (incoming_rec != NULL) {
429 if (incoming_rec->is_vm_pointer()) {
419 // we don't do anything with virtual memory records during merge 430 // we don't do anything with virtual memory records during merge
420 if (!_staging_area.vm_data()->append(p1)) { 431 if (!_staging_area.vm_data()->append(incoming_rec)) {
421 return false; 432 return false;
422 } 433 }
423 } else { 434 } else {
424 // locate matched record and/or also position the iterator to proper 435 // locate matched record and/or also position the iterator to proper
425 // location for this incoming record. 436 // location for this incoming record.
426 p2 = (MemPointerRecord*)malloc_staging_itr.locate(p1->addr()); 437 matched_rec = (MemPointerRecord*)malloc_staging_itr.locate(incoming_rec->addr());
427 // we have not seen this memory block, so just add to staging area 438 // we have not seen this memory block in this generation,
428 if (p2 == NULL) { 439 // so just add to staging area
429 if (!malloc_staging_itr.insert(p1)) { 440 if (matched_rec == NULL) {
441 if (!malloc_staging_itr.insert(incoming_rec)) {
430 return false; 442 return false;
431 } 443 }
432 } else if (p1->addr() == p2->addr()) { 444 } else if (incoming_rec->addr() == matched_rec->addr()) {
433 MemPointerRecord* staging_next = (MemPointerRecord*)malloc_staging_itr.peek_next(); 445 // whoever has higher sequence number wins
434 // a memory block can have many tagging records, find right one to replace or 446 if (incoming_rec->seq() > matched_rec->seq()) {
435 // right position to insert 447 copy_seq_pointer(matched_rec, incoming_rec);
436 while (staging_next != NULL && staging_next->addr() == p1->addr()) { 448 }
437 if ((staging_next->flags() & MemPointerRecord::tag_masks) <= 449 } else if (incoming_rec->addr() < matched_rec->addr()) {
438 (p1->flags() & MemPointerRecord::tag_masks)) { 450 if (!malloc_staging_itr.insert(incoming_rec)) {
439 p2 = (MemPointerRecord*)malloc_staging_itr.next();
440 staging_next = (MemPointerRecord*)malloc_staging_itr.peek_next();
441 } else {
442 break;
443 }
444 }
445 int df = (p1->flags() & MemPointerRecord::tag_masks) -
446 (p2->flags() & MemPointerRecord::tag_masks);
447 if (df == 0) {
448 assert(p1->seq() > 0, "not sequenced");
449 assert(p2->seq() > 0, "not sequenced");
450 if (p1->seq() > p2->seq()) {
451 copy_pointer(p2, p1);
452 }
453 } else if (df < 0) {
454 if (!malloc_staging_itr.insert(p1)) {
455 return false;
456 }
457 } else {
458 if (!malloc_staging_itr.insert_after(p1)) {
459 return false;
460 }
461 }
462 } else if (p1->addr() < p2->addr()) {
463 if (!malloc_staging_itr.insert(p1)) {
464 return false; 451 return false;
465 } 452 }
466 } else { 453 } else {
467 if (!malloc_staging_itr.insert_after(p1)) { 454 ShouldNotReachHere();
468 return false; 455 }
469 } 456 }
470 } 457 incoming_rec = (MemPointerRecord*)itr.next();
471 }
472 p1 = (MemPointerRecord*)itr.next();
473 } 458 }
474 NOT_PRODUCT(void check_staging_data();) 459 NOT_PRODUCT(void check_staging_data();)
475 return true; 460 return true;
476 } 461 }
477
478 462
479 463
480 // promote data to next generation 464 // promote data to next generation
481 bool MemSnapshot::promote() { 465 bool MemSnapshot::promote() {
482 assert(_alloc_ptrs != NULL && _vm_ptrs != NULL, "Just check"); 466 assert(_alloc_ptrs != NULL && _vm_ptrs != NULL, "Just check");
505 while (new_rec != NULL) { 489 while (new_rec != NULL) {
506 matched_rec = (MemPointerRecord*)malloc_snapshot_itr.locate(new_rec->addr()); 490 matched_rec = (MemPointerRecord*)malloc_snapshot_itr.locate(new_rec->addr());
507 // found matched memory block 491 // found matched memory block
508 if (matched_rec != NULL && new_rec->addr() == matched_rec->addr()) { 492 if (matched_rec != NULL && new_rec->addr() == matched_rec->addr()) {
509 // snapshot already contains 'live' records 493 // snapshot already contains 'live' records
510 assert(matched_rec->is_allocation_record() || matched_rec->is_arena_size_record(), 494 assert(matched_rec->is_allocation_record() || matched_rec->is_arena_memory_record(),
511 "Sanity check"); 495 "Sanity check");
512 // update block states 496 // update block states
513 if (new_rec->is_allocation_record() || new_rec->is_arena_size_record()) { 497 if (new_rec->is_allocation_record()) {
514 copy_pointer(matched_rec, new_rec); 498 assign_pointer(matched_rec, new_rec);
499 } else if (new_rec->is_arena_memory_record()) {
500 if (new_rec->size() == 0) {
501 // remove size record once size drops to 0
502 malloc_snapshot_itr.remove();
503 } else {
504 assign_pointer(matched_rec, new_rec);
505 }
515 } else { 506 } else {
516 // a deallocation record 507 // a deallocation record
517 assert(new_rec->is_deallocation_record(), "Sanity check"); 508 assert(new_rec->is_deallocation_record(), "Sanity check");
518 // an arena record can be followed by a size record, we need to remove both 509 // an arena record can be followed by a size record, we need to remove both
519 if (matched_rec->is_arena_record()) { 510 if (matched_rec->is_arena_record()) {
520 MemPointerRecord* next = (MemPointerRecord*)malloc_snapshot_itr.peek_next(); 511 MemPointerRecord* next = (MemPointerRecord*)malloc_snapshot_itr.peek_next();
521 if (next->is_arena_size_record()) { 512 if (next->is_arena_memory_record() && next->is_memory_record_of_arena(matched_rec)) {
522 // it has to match the arena record
523 assert(next->is_size_record_of_arena(matched_rec), "Sanity check");
524 malloc_snapshot_itr.remove(); 513 malloc_snapshot_itr.remove();
525 } 514 }
526 } 515 }
527 // the memory is deallocated, remove related record(s) 516 // the memory is deallocated, remove related record(s)
528 malloc_snapshot_itr.remove(); 517 malloc_snapshot_itr.remove();
529 } 518 }
530 } else { 519 } else {
531 // it is a new record, insert into snapshot 520 // don't insert size 0 record
532 if (new_rec->is_arena_size_record()) { 521 if (new_rec->is_arena_memory_record() && new_rec->size() == 0) {
533 MemPointerRecord* prev = (MemPointerRecord*)malloc_snapshot_itr.peek_prev(); 522 new_rec = NULL;
534 if (prev == NULL || !prev->is_arena_record() || !new_rec->is_size_record_of_arena(prev)) { 523 }
535 // no matched arena record, ignore the size record 524
536 new_rec = NULL;
537 }
538 }
539 // only 'live' record can go into snapshot
540 if (new_rec != NULL) { 525 if (new_rec != NULL) {
541 if (new_rec->is_allocation_record() || new_rec->is_arena_size_record()) { 526 if (new_rec->is_allocation_record() || new_rec->is_arena_memory_record()) {
542 if (matched_rec != NULL && new_rec->addr() > matched_rec->addr()) { 527 if (matched_rec != NULL && new_rec->addr() > matched_rec->addr()) {
543 if (!malloc_snapshot_itr.insert_after(new_rec)) { 528 if (!malloc_snapshot_itr.insert_after(new_rec)) {
544 return false; 529 return false;
545 } 530 }
546 } else { 531 } else {