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...) 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...) 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...) 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...) 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 |