1756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// Copyright 2010 the V8 project authors. All rights reserved.
2756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// Redistribution and use in source and binary forms, with or without
3756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// modification, are permitted provided that the following conditions are
4756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// met:
5756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick//
6756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick//     * Redistributions of source code must retain the above copyright
7756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick//       notice, this list of conditions and the following disclaimer.
8756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick//     * Redistributions in binary form must reproduce the above
9756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick//       copyright notice, this list of conditions and the following
10756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick//       disclaimer in the documentation and/or other materials provided
11756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick//       with the distribution.
12756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick//     * Neither the name of Google Inc. nor the names of its
13756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick//       contributors may be used to endorse or promote products derived
14756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick//       from this software without specific prior written permission.
15756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick//
16756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
28756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#include <stdio.h>
29756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#include <stdlib.h>
30756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
31756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#include <algorithm>
32756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
33756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#include <google_breakpad/processor/minidump.h>
34756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
35756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#define ENABLE_DEBUGGER_SUPPORT
36756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
37756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#include <v8.h>
38756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
39756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merricknamespace {
40756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
41756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickusing google_breakpad::Minidump;
42756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickusing google_breakpad::MinidumpContext;
43756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickusing google_breakpad::MinidumpThread;
44756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickusing google_breakpad::MinidumpThreadList;
45756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickusing google_breakpad::MinidumpException;
46756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickusing google_breakpad::MinidumpMemoryRegion;
47756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
48756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickconst char* InstanceTypeToString(int type) {
49756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static char const* names[v8::internal::LAST_TYPE] = {0};
50756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (names[v8::internal::STRING_TYPE] == NULL) {
51756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    using namespace v8::internal;
52756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#define SET(type) names[type] = #type;
53756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    INSTANCE_TYPE_LIST(SET)
54756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#undef SET
55756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
56756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  return names[type];
57756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
58756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
59756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
60756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merricku_int32_t ReadPointedValue(MinidumpMemoryRegion* region,
61756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                           u_int64_t base,
62756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                           int offset) {
63756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  u_int32_t ptr = 0;
64756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(region->GetMemoryAtAddress(base + 4 * offset, &ptr));
65756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  u_int32_t value = 0;
66756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(region->GetMemoryAtAddress(ptr, &value));
67756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  return value;
68756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
69756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
70756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
71756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid ReadArray(MinidumpMemoryRegion* region,
72756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick               u_int64_t array_ptr,
73756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick               int size,
74756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick               int* output) {
75756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  for (int i = 0; i < size; i++) {
76756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    u_int32_t value;
77756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CHECK(region->GetMemoryAtAddress(array_ptr + 4 * i, &value));
78756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    output[i] = value;
79756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
80756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
81756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
82756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
83756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merricku_int32_t ReadArrayFrom(MinidumpMemoryRegion* region,
84756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                        u_int64_t base,
85756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                        int offset,
86756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                        int size,
87756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                        int* output) {
88756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  u_int32_t ptr = 0;
89756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(region->GetMemoryAtAddress(base + 4 * offset, &ptr));
90756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ReadArray(region, ptr, size, output);
91756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
92756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
93756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
94756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickdouble toM(int size) {
95756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  return size / (1024. * 1024.);
96756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
97756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
98756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
99756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickclass IndirectSorter {
100756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick public:
101756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  explicit IndirectSorter(int* a) : a_(a) { }
102756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
103756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool operator() (int i0, int i1) {
104756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return a_[i0] > a_[i1];
105756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
106756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
107756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick private:
108756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int* a_;
109756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick};
110756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
111756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid DumpHeapStats(const char *minidump_file) {
112756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Minidump minidump(minidump_file);
113756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(minidump.Read());
114756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
115756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  MinidumpException *exception = minidump.GetException();
116756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(exception);
117756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  MinidumpContext* crash_context = exception->GetContext();
119756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(crash_context);
120756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
121756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  u_int32_t exception_thread_id = 0;
122756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(exception->GetThreadID(&exception_thread_id));
123756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
124756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  MinidumpThreadList* thread_list = minidump.GetThreadList();
125756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(thread_list);
126756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
127756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  MinidumpThread* exception_thread =
128756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      thread_list->GetThreadByID(exception_thread_id);
129756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(exception_thread);
130756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
131756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Currently only 32-bit Windows minidumps are supported.
132756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_EQ(MD_CONTEXT_X86, crash_context->GetContextCPU());
133756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
134756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const MDRawContextX86* contextX86 = crash_context->GetContextX86();
135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(contextX86);
136756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
137756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const u_int32_t esp = contextX86->esp;
138756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
139756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  MinidumpMemoryRegion* memory_region = exception_thread->GetMemory();
140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(memory_region);
141756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
142756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const u_int64_t last = memory_region->GetBase() + memory_region->GetSize();
143756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
144756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  u_int64_t heap_stats_addr = 0;
145756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  for (u_int64_t addr = esp; addr < last; addr += 4) {
146756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    u_int32_t value = 0;
147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CHECK(memory_region->GetMemoryAtAddress(addr, &value));
148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (value >= esp && value < last) {
149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      u_int32_t value2 = 0;
150756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      CHECK(memory_region->GetMemoryAtAddress(value, &value2));
151756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      if (value2 == v8::internal::HeapStats::kStartMarker) {
152756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        heap_stats_addr = addr;
153756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        break;
154756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      }
155756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
156756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
157756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(heap_stats_addr);
158756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
159756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Read heap stats.
160756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
161756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#define READ_FIELD(offset) \
162756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ReadPointedValue(memory_region, heap_stats_addr, offset)
163756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
164756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK(READ_FIELD(0) == v8::internal::HeapStats::kStartMarker);
16580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK(READ_FIELD(24) == v8::internal::HeapStats::kEndMarker);
166756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
167756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int new_space_size = READ_FIELD(1);
168756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int new_space_capacity = READ_FIELD(2);
169756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int old_pointer_space_size = READ_FIELD(3);
170756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int old_pointer_space_capacity = READ_FIELD(4);
171756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int old_data_space_size = READ_FIELD(5);
172756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int old_data_space_capacity = READ_FIELD(6);
173756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int code_space_size = READ_FIELD(7);
174756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int code_space_capacity = READ_FIELD(8);
175756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int map_space_size = READ_FIELD(9);
176756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int map_space_capacity = READ_FIELD(10);
177756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int cell_space_size = READ_FIELD(11);
178756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int cell_space_capacity = READ_FIELD(12);
179756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int lo_space_size = READ_FIELD(13);
180756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int global_handle_count = READ_FIELD(14);
181756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int weak_global_handle_count = READ_FIELD(15);
182756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int pending_global_handle_count = READ_FIELD(16);
183756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int near_death_global_handle_count = READ_FIELD(17);
184756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int destroyed_global_handle_count = READ_FIELD(18);
185756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int memory_allocator_size = READ_FIELD(19);
186756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const int memory_allocator_capacity = READ_FIELD(20);
18780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const int os_error = READ_FIELD(23);
188756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#undef READ_FIELD
189756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
190756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int objects_per_type[v8::internal::LAST_TYPE + 1] = {0};
191756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ReadArrayFrom(memory_region, heap_stats_addr, 21,
192756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                v8::internal::LAST_TYPE + 1, objects_per_type);
193756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
194756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int size_per_type[v8::internal::LAST_TYPE + 1] = {0};
195756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  ReadArrayFrom(memory_region, heap_stats_addr, 22, v8::internal::LAST_TYPE + 1,
196756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                size_per_type);
197756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
198756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int js_global_objects =
199756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      objects_per_type[v8::internal::JS_GLOBAL_OBJECT_TYPE];
200756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int js_builtins_objects =
201756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      objects_per_type[v8::internal::JS_BUILTINS_OBJECT_TYPE];
202756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int js_global_proxies =
203756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      objects_per_type[v8::internal::JS_GLOBAL_PROXY_TYPE];
204756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
205756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int indices[v8::internal::LAST_TYPE + 1];
206756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  for (int i = 0; i <= v8::internal::LAST_TYPE; i++) {
207756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    indices[i] = i;
208756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
209756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
210756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  std::stable_sort(indices, indices + sizeof(indices)/sizeof(indices[0]),
211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick                  IndirectSorter(size_per_type));
212756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
213756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int total_size = 0;
214756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  for (int i = 0; i <= v8::internal::LAST_TYPE; i++) {
215756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    total_size += size_per_type[i];
216756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
217756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
218756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Print heap stats.
219756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
220756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  printf("exception thread ID: %" PRIu32 " (%#" PRIx32 ")\n",
221756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick         exception_thread_id, exception_thread_id);
222756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  printf("heap stats address: %#" PRIx64 "\n", heap_stats_addr);
223756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#define PRINT_INT_STAT(stat) \
224756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    printf("\t%-25s\t% 10d\n", #stat ":", stat);
225756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#define PRINT_MB_STAT(stat) \
226756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    printf("\t%-25s\t% 10.3f MB\n", #stat ":", toM(stat));
227756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(new_space_size);
228756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(new_space_capacity);
229756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(old_pointer_space_size);
230756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(old_pointer_space_capacity);
231756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(old_data_space_size);
232756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(old_data_space_capacity);
233756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(code_space_size);
234756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(code_space_capacity);
235756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(map_space_size);
236756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(map_space_capacity);
237756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(cell_space_size);
238756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(cell_space_capacity);
239756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(lo_space_size);
240756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_INT_STAT(global_handle_count);
241756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_INT_STAT(weak_global_handle_count);
242756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_INT_STAT(pending_global_handle_count);
243756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_INT_STAT(near_death_global_handle_count);
244756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_INT_STAT(destroyed_global_handle_count);
245756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(memory_allocator_size);
246756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  PRINT_MB_STAT(memory_allocator_capacity);
24780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  PRINT_INT_STAT(os_error);
248756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#undef PRINT_STAT
249756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
250756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  printf("\n");
251756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
252756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  printf(
253756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      "\tJS_GLOBAL_OBJECT_TYPE/JS_BUILTINS_OBJECT_TYPE/JS_GLOBAL_PROXY_TYPE: "
254756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      "%d/%d/%d\n\n",
255756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      js_global_objects, js_builtins_objects, js_global_proxies);
256756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
257756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  int running_size = 0;
258756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  for (int i = 0; i <= v8::internal::LAST_TYPE; i++) {
259756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int type = indices[i];
260756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    const char* name = InstanceTypeToString(type);
261756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (name == NULL) {
262756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      // Unknown instance type.  Check that there is no objects of that type.
263756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      CHECK_EQ(0, objects_per_type[type]);
264756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      CHECK_EQ(0, size_per_type[type]);
265756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      continue;
266756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
267756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    int size = size_per_type[type];
268756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    running_size += size;
269756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    printf("\t%-37s% 9d% 11.3f MB% 10.3f%%% 10.3f%%\n",
270756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           name, objects_per_type[type], toM(size),
271756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           100. * size / total_size, 100. * running_size / total_size);
272756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
273756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  printf("\t%-37s% 9d% 11.3f MB% 10.3f%%% 10.3f%%\n",
274756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick         "total", 0, toM(total_size), 100., 100.);
275756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
276756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
277756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}  // namespace
278756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
279756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickint main(int argc, char **argv) {
280756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (argc != 2) {
281756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    fprintf(stderr, "usage: %s <minidump>\n", argv[0]);
282756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return 1;
283756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
284756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
285756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  DumpHeapStats(argv[1]);
286756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
287756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  return 0;
288756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
289