Chromium Code Reviews| 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 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 321 reinterpret_cast<uintptr_t>(b.stack[d])); | 321 reinterpret_cast<uintptr_t>(b.stack[d])); |
| 322 if (printed < 0 || printed >= bufsize - buflen) return buflen; | 322 if (printed < 0 || printed >= bufsize - buflen) return buflen; |
| 323 buflen += printed; | 323 buflen += printed; |
| 324 } | 324 } |
| 325 printed = snprintf(buf + buflen, bufsize - buflen, "\n"); | 325 printed = snprintf(buf + buflen, bufsize - buflen, "\n"); |
| 326 if (printed < 0 || printed >= bufsize - buflen) return buflen; | 326 if (printed < 0 || printed >= bufsize - buflen) return buflen; |
| 327 buflen += printed; | 327 buflen += printed; |
| 328 return buflen; | 328 return buflen; |
| 329 } | 329 } |
| 330 | 330 |
| 331 int HeapProfileTable::UnparsePseudoStackBucket( | |
| 332 const Bucket& bucket, | |
| 333 char* buffer, int written, int buffer_size, | |
| 334 Stats* profile_stats) { | |
| 335 if (profile_stats != NULL) { | |
| 336 profile_stats->allocs += bucket.allocs; | |
| 337 profile_stats->alloc_size += bucket.alloc_size; | |
| 338 profile_stats->frees += bucket.frees; | |
| 339 profile_stats->free_size += bucket.free_size; | |
| 340 } | |
| 341 int printed = snprintf(buffer + written, | |
|
dsinclair
2013/06/18 15:30:15
Would it be possible, instead of converting to JSO
Dai Mikurube (NOT FULLTIME)
2013/06/19 04:34:03
Agreed with dsinclair. Would it be possible to ke
| |
| 342 buffer_size - written, | |
| 343 "{" | |
| 344 "\"trace\": \""); | |
| 345 written += printed; | |
| 346 RAW_DCHECK(bucket.depth <= HeapProfileBucket::kMaxStackDepth, | |
| 347 "stack depth too deep"); | |
| 348 for (int d = 0; d < bucket.depth; d++) { | |
| 349 printed = snprintf(buffer + written, buffer_size - written, "%s ", | |
| 350 reinterpret_cast<const char*>(bucket.stack[d])); | |
| 351 // Brute-force replace any " with ' to keep the JSON correct. | |
| 352 for (int i = 0; i < printed; ++i) { | |
| 353 char* c = buffer + written + i; | |
| 354 if (*c == '"') | |
| 355 *c = '\''; | |
| 356 } | |
| 357 if (printed < 0 || printed >= buffer_size - written) return written; | |
| 358 written += printed; | |
| 359 } | |
| 360 printed = snprintf(buffer + written, | |
| 361 buffer_size - written, | |
| 362 "\", " | |
| 363 "\"current_allocs\": %d, " | |
| 364 "\"current_bytes\": %" PRId64 ", " | |
| 365 "\"total_allocs\": %d, " | |
| 366 "\"total_bytes\": %" PRId64 | |
| 367 "}", | |
| 368 bucket.allocs - bucket.frees, | |
| 369 bucket.alloc_size - bucket.free_size, | |
| 370 bucket.allocs, | |
| 371 bucket.alloc_size); | |
| 372 // If it looks like the snprintf failed, ignore the fact we printed anything | |
| 373 if (printed < 0 || printed >= buffer_size - written) return written; | |
| 374 written += printed; | |
| 375 return written; | |
| 376 } | |
| 377 | |
| 331 HeapProfileTable::Bucket** | 378 HeapProfileTable::Bucket** |
| 332 HeapProfileTable::MakeSortedBucketList() const { | 379 HeapProfileTable::MakeSortedBucketList() const { |
| 333 Bucket** list = static_cast<Bucket**>(alloc_(sizeof(Bucket) * num_buckets_)); | 380 Bucket** list = static_cast<Bucket**>(alloc_(sizeof(Bucket) * num_buckets_)); |
| 334 | 381 |
| 335 int bucket_count = 0; | 382 int bucket_count = 0; |
| 336 for (int i = 0; i < kHashTableSize; i++) { | 383 for (int i = 0; i < kHashTableSize; i++) { |
| 337 for (Bucket* curr = bucket_table_[i]; curr != 0; curr = curr->next) { | 384 for (Bucket* curr = bucket_table_[i]; curr != 0; curr = curr->next) { |
| 338 list[bucket_count++] = curr; | 385 list[bucket_count++] = curr; |
| 339 } | 386 } |
| 340 } | 387 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 433 RAW_DCHECK(bucket_length < size, ""); | 480 RAW_DCHECK(bucket_length < size, ""); |
| 434 | 481 |
| 435 dealloc_(list); | 482 dealloc_(list); |
| 436 | 483 |
| 437 RAW_DCHECK(buf + bucket_length <= map_start, ""); | 484 RAW_DCHECK(buf + bucket_length <= map_start, ""); |
| 438 memmove(buf + bucket_length, map_start, map_length); // close the gap | 485 memmove(buf + bucket_length, map_start, map_length); // close the gap |
| 439 | 486 |
| 440 return bucket_length + map_length; | 487 return bucket_length + map_length; |
| 441 } | 488 } |
| 442 | 489 |
| 490 int HeapProfileTable::FillPseudoStackProfile(char buffer[], | |
| 491 int buffer_size) const { | |
| 492 Bucket** list = MakeSortedBucketList(); | |
| 493 | |
| 494 Stats stats; | |
| 495 memset(&stats, 0, sizeof(stats)); | |
| 496 int written = snprintf(buffer, buffer_size, "[\n"); | |
| 497 written = UnparsePseudoStackBucket( | |
| 498 total_, buffer, written, buffer_size, &stats); | |
| 499 | |
| 500 for (int i = 0; i < num_buckets_; i++) { | |
| 501 written += snprintf(buffer + written, buffer_size - written, ",\n"); | |
| 502 written = UnparsePseudoStackBucket( | |
| 503 *list[i], buffer, written, buffer_size, &stats); | |
| 504 } | |
| 505 RAW_DCHECK(written < buffer_size, ""); | |
| 506 | |
| 507 written += snprintf(buffer + written, buffer_size - written, "\n]\n"); | |
| 508 | |
| 509 dealloc_(list); | |
| 510 | |
| 511 return written; | |
| 512 } | |
| 513 | |
| 443 // static | 514 // static |
| 444 void HeapProfileTable::DumpBucketIterator(const Bucket* bucket, | 515 void HeapProfileTable::DumpBucketIterator(const Bucket* bucket, |
| 445 BufferArgs* args) { | 516 BufferArgs* args) { |
| 446 args->buflen = UnparseBucket(*bucket, args->buf, args->buflen, args->bufsize, | 517 args->buflen = UnparseBucket(*bucket, args->buf, args->buflen, args->bufsize, |
| 447 "", NULL); | 518 "", NULL); |
| 448 } | 519 } |
| 449 | 520 |
| 450 #if defined(TYPE_PROFILING) | 521 #if defined(TYPE_PROFILING) |
| 451 // static | 522 // static |
| 452 void HeapProfileTable::TallyTypesItererator( | 523 void HeapProfileTable::TallyTypesItererator( |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 741 char* unused) { | 812 char* unused) { |
| 742 // Perhaps also log the allocation stack trace (unsymbolized) | 813 // Perhaps also log the allocation stack trace (unsymbolized) |
| 743 // on this line in case somebody finds it useful. | 814 // on this line in case somebody finds it useful. |
| 744 RAW_LOG(ERROR, "leaked %"PRIuS" byte object %p", v->bytes, ptr); | 815 RAW_LOG(ERROR, "leaked %"PRIuS" byte object %p", v->bytes, ptr); |
| 745 } | 816 } |
| 746 | 817 |
| 747 void HeapProfileTable::Snapshot::ReportIndividualObjects() { | 818 void HeapProfileTable::Snapshot::ReportIndividualObjects() { |
| 748 char unused; | 819 char unused; |
| 749 map_.Iterate(ReportObject, &unused); | 820 map_.Iterate(ReportObject, &unused); |
| 750 } | 821 } |
| OLD | NEW |