| 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) | |
| 98 | 95 |
| 99 //---------------------------------------------------------------------- | 96 //---------------------------------------------------------------------- |
| 100 | 97 |
| 101 const char HeapProfileTable::kFileExt[] = ".heap"; | 98 const char HeapProfileTable::kFileExt[] = ".heap"; |
| 102 | 99 |
| 103 //---------------------------------------------------------------------- | 100 //---------------------------------------------------------------------- |
| 104 | 101 |
| 105 static const int kHashTableSize = 179999; // Size for bucket_table_. | 102 static const int kHashTableSize = 179999; // Size for bucket_table_. |
| 106 // GCC requires this declaration, but MSVC does not allow it. | 103 // GCC requires this declaration, but MSVC does not allow it. |
| 107 #if !defined(COMPILER_MSVC) | 104 #if !defined(COMPILER_MSVC) |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 RawFD fd = RawOpenForWriting(file_name); | 351 RawFD fd = RawOpenForWriting(file_name); |
| 355 if (fd == kIllegalRawFD) { | 352 if (fd == kIllegalRawFD) { |
| 356 RAW_LOG(ERROR, "Failed dumping live objects to %s", file_name); | 353 RAW_LOG(ERROR, "Failed dumping live objects to %s", file_name); |
| 357 return; | 354 return; |
| 358 } | 355 } |
| 359 const DumpMarkedArgs args(fd, mark); | 356 const DumpMarkedArgs args(fd, mark); |
| 360 address_map_->Iterate<const DumpMarkedArgs&>(DumpMarkedIterator, args); | 357 address_map_->Iterate<const DumpMarkedArgs&>(DumpMarkedIterator, args); |
| 361 RawClose(fd); | 358 RawClose(fd); |
| 362 } | 359 } |
| 363 | 360 |
| 364 #if defined(TYPE_PROFILING) | |
| 365 void HeapProfileTable::DumpTypeStatistics(const char* file_name) const { | |
| 366 RawFD fd = RawOpenForWriting(file_name); | |
| 367 if (fd == kIllegalRawFD) { | |
| 368 RAW_LOG(ERROR, "Failed dumping type statistics to %s", file_name); | |
| 369 return; | |
| 370 } | |
| 371 | |
| 372 AddressMap<TypeCount>* type_size_map; | |
| 373 type_size_map = new(alloc_(sizeof(AddressMap<TypeCount>))) | |
| 374 AddressMap<TypeCount>(alloc_, dealloc_); | |
| 375 address_map_->Iterate(TallyTypesItererator, type_size_map); | |
| 376 | |
| 377 RawWrite(fd, kTypeProfileStatsHeader, strlen(kTypeProfileStatsHeader)); | |
| 378 const DumpArgs args(fd, NULL); | |
| 379 type_size_map->Iterate<const DumpArgs&>(DumpTypesIterator, args); | |
| 380 RawClose(fd); | |
| 381 | |
| 382 type_size_map->~AddressMap<TypeCount>(); | |
| 383 dealloc_(type_size_map); | |
| 384 } | |
| 385 #endif // defined(TYPE_PROFILING) | |
| 386 | |
| 387 void HeapProfileTable::IterateOrderedAllocContexts( | 361 void HeapProfileTable::IterateOrderedAllocContexts( |
| 388 AllocContextIterator callback) const { | 362 AllocContextIterator callback) const { |
| 389 Bucket** list = MakeSortedBucketList(); | 363 Bucket** list = MakeSortedBucketList(); |
| 390 AllocContextInfo info; | 364 AllocContextInfo info; |
| 391 for (int i = 0; i < num_buckets_; ++i) { | 365 for (int i = 0; i < num_buckets_; ++i) { |
| 392 *static_cast<Stats*>(&info) = *static_cast<Stats*>(list[i]); | 366 *static_cast<Stats*>(&info) = *static_cast<Stats*>(list[i]); |
| 393 info.stack_depth = list[i]->depth; | 367 info.stack_depth = list[i]->depth; |
| 394 info.call_stack = list[i]->stack; | 368 info.call_stack = list[i]->stack; |
| 395 callback(info); | 369 callback(info); |
| 396 } | 370 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 return bucket_length + map_length; | 418 return bucket_length + map_length; |
| 445 } | 419 } |
| 446 | 420 |
| 447 // static | 421 // static |
| 448 void HeapProfileTable::DumpBucketIterator(const Bucket* bucket, | 422 void HeapProfileTable::DumpBucketIterator(const Bucket* bucket, |
| 449 BufferArgs* args) { | 423 BufferArgs* args) { |
| 450 args->buflen = UnparseBucket(*bucket, args->buf, args->buflen, args->bufsize, | 424 args->buflen = UnparseBucket(*bucket, args->buf, args->buflen, args->bufsize, |
| 451 "", NULL); | 425 "", NULL); |
| 452 } | 426 } |
| 453 | 427 |
| 454 #if defined(TYPE_PROFILING) | |
| 455 // static | |
| 456 void HeapProfileTable::TallyTypesItererator( | |
| 457 const void* ptr, | |
| 458 AllocValue* value, | |
| 459 AddressMap<TypeCount>* type_size_map) { | |
| 460 const std::type_info* type = LookupType(ptr); | |
| 461 | |
| 462 const void* key = NULL; | |
| 463 if (type) | |
| 464 key = type->name(); | |
| 465 | |
| 466 TypeCount* count = type_size_map->FindMutable(key); | |
| 467 if (count) { | |
| 468 count->bytes += value->bytes; | |
| 469 ++count->objects; | |
| 470 } else { | |
| 471 type_size_map->Insert(key, TypeCount(value->bytes, 1)); | |
| 472 } | |
| 473 } | |
| 474 | |
| 475 // static | |
| 476 void HeapProfileTable::DumpTypesIterator(const void* ptr, | |
| 477 TypeCount* count, | |
| 478 const DumpArgs& args) { | |
| 479 char buf[1024]; | |
| 480 int len; | |
| 481 const char* mangled_type_name = static_cast<const char*>(ptr); | |
| 482 len = snprintf(buf, sizeof(buf), "%6d: %8" PRId64 " @ %s\n", | |
| 483 count->objects, count->bytes, | |
| 484 mangled_type_name ? mangled_type_name : "(no_typeinfo)"); | |
| 485 RawWrite(args.fd, buf, len); | |
| 486 } | |
| 487 #endif // defined(TYPE_PROFILING) | |
| 488 | |
| 489 inline | 428 inline |
| 490 void HeapProfileTable::DumpNonLiveIterator(const void* ptr, AllocValue* v, | 429 void HeapProfileTable::DumpNonLiveIterator(const void* ptr, AllocValue* v, |
| 491 const DumpArgs& args) { | 430 const DumpArgs& args) { |
| 492 if (v->live()) { | 431 if (v->live()) { |
| 493 v->set_live(false); | 432 v->set_live(false); |
| 494 return; | 433 return; |
| 495 } | 434 } |
| 496 if (v->ignore()) { | 435 if (v->ignore()) { |
| 497 return; | 436 return; |
| 498 } | 437 } |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 char* unused) { | 684 char* unused) { |
| 746 // Perhaps also log the allocation stack trace (unsymbolized) | 685 // Perhaps also log the allocation stack trace (unsymbolized) |
| 747 // on this line in case somebody finds it useful. | 686 // on this line in case somebody finds it useful. |
| 748 RAW_LOG(ERROR, "leaked %" PRIuS " byte object %p", v->bytes, ptr); | 687 RAW_LOG(ERROR, "leaked %" PRIuS " byte object %p", v->bytes, ptr); |
| 749 } | 688 } |
| 750 | 689 |
| 751 void HeapProfileTable::Snapshot::ReportIndividualObjects() { | 690 void HeapProfileTable::Snapshot::ReportIndividualObjects() { |
| 752 char unused; | 691 char unused; |
| 753 map_.Iterate(ReportObject, &unused); | 692 map_.Iterate(ReportObject, &unused); |
| 754 } | 693 } |
| OLD | NEW |