OLD | NEW |
1 // Copyright (c) 2006, Google Inc. | 1 // Copyright (c) 2006, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 | 85 |
86 DEFINE_int32(heap_check_max_leaks, | 86 DEFINE_int32(heap_check_max_leaks, |
87 EnvToInt("HEAP_CHECK_MAX_LEAKS", 20), | 87 EnvToInt("HEAP_CHECK_MAX_LEAKS", 20), |
88 "The maximum number of leak reports to print."); | 88 "The maximum number of leak reports to print."); |
89 | 89 |
90 //---------------------------------------------------------------------- | 90 //---------------------------------------------------------------------- |
91 | 91 |
92 // header of the dumped heap profile | 92 // header of the dumped heap profile |
93 static const char kProfileHeader[] = "heap profile: "; | 93 static const char kProfileHeader[] = "heap profile: "; |
94 static const char kProcSelfMapsHeader[] = "\nMAPPED_LIBRARIES:\n"; | 94 static const char kProcSelfMapsHeader[] = "\nMAPPED_LIBRARIES:\n"; |
| 95 #if defined(TYPE_PROFILING) |
| 96 static const char kTypeProfileStatsHeader[] = "type statistics:\n"; |
| 97 #endif // defined(TYPE_PROFILING) |
95 | 98 |
96 //---------------------------------------------------------------------- | 99 //---------------------------------------------------------------------- |
97 | 100 |
98 const char HeapProfileTable::kFileExt[] = ".heap"; | 101 const char HeapProfileTable::kFileExt[] = ".heap"; |
99 | 102 |
100 //---------------------------------------------------------------------- | 103 //---------------------------------------------------------------------- |
101 | 104 |
102 // Size for alloc_table_ and mmap_table_. | 105 // Size for alloc_table_ and mmap_table_. |
103 static const int kHashTableSize = 179999; | 106 static const int kHashTableSize = 179999; |
104 /*static*/ const int HeapProfileTable::kMaxStackDepth; | 107 /*static*/ const int HeapProfileTable::kMaxStackDepth; |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 RawFD fd = RawOpenForWriting(file_name); | 414 RawFD fd = RawOpenForWriting(file_name); |
412 if (fd == kIllegalRawFD) { | 415 if (fd == kIllegalRawFD) { |
413 RAW_LOG(ERROR, "Failed dumping live objects to %s", file_name); | 416 RAW_LOG(ERROR, "Failed dumping live objects to %s", file_name); |
414 return; | 417 return; |
415 } | 418 } |
416 const DumpMarkedArgs args(fd, mark); | 419 const DumpMarkedArgs args(fd, mark); |
417 alloc_address_map_->Iterate<const DumpMarkedArgs&>(DumpMarkedIterator, args); | 420 alloc_address_map_->Iterate<const DumpMarkedArgs&>(DumpMarkedIterator, args); |
418 RawClose(fd); | 421 RawClose(fd); |
419 } | 422 } |
420 | 423 |
| 424 #if defined(TYPE_PROFILING) |
| 425 void HeapProfileTable::DumpTypeStatistics(const char* file_name) const { |
| 426 RawFD fd = RawOpenForWriting(file_name); |
| 427 if (fd == kIllegalRawFD) { |
| 428 RAW_LOG(ERROR, "Failed dumping type statistics to %s", file_name); |
| 429 return; |
| 430 } |
| 431 |
| 432 AddressMap<TypeCount>* type_size_map; |
| 433 type_size_map = new(alloc_(sizeof(AddressMap<TypeCount>))) |
| 434 AddressMap<TypeCount>(alloc_, dealloc_); |
| 435 alloc_address_map_->Iterate(TallyTypesItererator, type_size_map); |
| 436 |
| 437 RawWrite(fd, kTypeProfileStatsHeader, strlen(kTypeProfileStatsHeader)); |
| 438 const DumpArgs args(fd, NULL); |
| 439 type_size_map->Iterate<const DumpArgs&>(DumpTypesIterator, args); |
| 440 RawClose(fd); |
| 441 |
| 442 type_size_map->~AddressMap<TypeCount>(); |
| 443 dealloc_(type_size_map); |
| 444 } |
| 445 #endif // defined(TYPE_PROFILING) |
| 446 |
421 void HeapProfileTable::IterateOrderedAllocContexts( | 447 void HeapProfileTable::IterateOrderedAllocContexts( |
422 AllocContextIterator callback) const { | 448 AllocContextIterator callback) const { |
423 Bucket** list = MakeSortedBucketList(); | 449 Bucket** list = MakeSortedBucketList(); |
424 AllocContextInfo info; | 450 AllocContextInfo info; |
425 for (int i = 0; i < num_alloc_buckets_; ++i) { | 451 for (int i = 0; i < num_alloc_buckets_; ++i) { |
426 *static_cast<Stats*>(&info) = *static_cast<Stats*>(list[i]); | 452 *static_cast<Stats*>(&info) = *static_cast<Stats*>(list[i]); |
427 info.stack_depth = list[i]->depth; | 453 info.stack_depth = list[i]->depth; |
428 info.call_stack = list[i]->stack; | 454 info.call_stack = list[i]->stack; |
429 callback(info); | 455 callback(info); |
430 } | 456 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 RAW_DCHECK(bucket_length < size, ""); | 494 RAW_DCHECK(bucket_length < size, ""); |
469 | 495 |
470 dealloc_(list); | 496 dealloc_(list); |
471 | 497 |
472 RAW_DCHECK(buf + bucket_length <= map_start, ""); | 498 RAW_DCHECK(buf + bucket_length <= map_start, ""); |
473 memmove(buf + bucket_length, map_start, map_length); // close the gap | 499 memmove(buf + bucket_length, map_start, map_length); // close the gap |
474 | 500 |
475 return bucket_length + map_length; | 501 return bucket_length + map_length; |
476 } | 502 } |
477 | 503 |
| 504 #if defined(TYPE_PROFILING) |
| 505 // static |
| 506 void HeapProfileTable::TallyTypesItererator( |
| 507 const void* ptr, |
| 508 AllocValue* value, |
| 509 AddressMap<TypeCount>* type_size_map) { |
| 510 const std::type_info* type = LookupType(ptr); |
| 511 |
| 512 const void* key = NULL; |
| 513 if (type) |
| 514 key = type->name(); |
| 515 |
| 516 TypeCount* count = type_size_map->FindMutable(key); |
| 517 if (count) { |
| 518 count->bytes += value->bytes; |
| 519 ++count->objects; |
| 520 } else { |
| 521 type_size_map->Insert(key, TypeCount(value->bytes, 1)); |
| 522 } |
| 523 } |
| 524 |
| 525 // static |
| 526 void HeapProfileTable::DumpTypesIterator(const void* ptr, |
| 527 TypeCount* count, |
| 528 const DumpArgs& args) { |
| 529 char buf[1024]; |
| 530 int len; |
| 531 const char* mangled_type_name = static_cast<const char*>(ptr); |
| 532 len = snprintf(buf, sizeof(buf), "%6d: %8"PRId64" @ %s\n", |
| 533 count->objects, count->bytes, |
| 534 mangled_type_name ? mangled_type_name : "(no_typeinfo)"); |
| 535 RawWrite(args.fd, buf, len); |
| 536 } |
| 537 #endif // defined(TYPE_PROFILING) |
| 538 |
478 inline | 539 inline |
479 void HeapProfileTable::DumpNonLiveIterator(const void* ptr, AllocValue* v, | 540 void HeapProfileTable::DumpNonLiveIterator(const void* ptr, AllocValue* v, |
480 const DumpArgs& args) { | 541 const DumpArgs& args) { |
481 if (v->live()) { | 542 if (v->live()) { |
482 v->set_live(false); | 543 v->set_live(false); |
483 return; | 544 return; |
484 } | 545 } |
485 if (v->ignore()) { | 546 if (v->ignore()) { |
486 return; | 547 return; |
487 } | 548 } |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 char* unused) { | 798 char* unused) { |
738 // Perhaps also log the allocation stack trace (unsymbolized) | 799 // Perhaps also log the allocation stack trace (unsymbolized) |
739 // on this line in case somebody finds it useful. | 800 // on this line in case somebody finds it useful. |
740 RAW_LOG(ERROR, "leaked %"PRIuS" byte object %p", v->bytes, ptr); | 801 RAW_LOG(ERROR, "leaked %"PRIuS" byte object %p", v->bytes, ptr); |
741 } | 802 } |
742 | 803 |
743 void HeapProfileTable::Snapshot::ReportIndividualObjects() { | 804 void HeapProfileTable::Snapshot::ReportIndividualObjects() { |
744 char unused; | 805 char unused; |
745 map_.Iterate(ReportObject, &unused); | 806 map_.Iterate(ReportObject, &unused); |
746 } | 807 } |
OLD | NEW |