hprof.cc revision e7158116f345df6df73f0df7ebdc2be8e0e4f3e8
1c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson/*
2c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * Copyright (C) 2008 The Android Open Source Project
3c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson *
4c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * you may not use this file except in compliance with the License.
6c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * You may obtain a copy of the License at
7c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson *
8c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson *
10c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * Unless required by applicable law or agreed to in writing, software
11c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * See the License for the specific language governing permissions and
14c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * limitations under the License.
15c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson */
16c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson
17c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson/*
18c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * Preparation and completion of hprof data generation.  The output is
19c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * written into two files and then combined.  This is necessary because
20c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * we generate some of the data (strings and classes) while we dump the
21c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * heap, and some analysis tools require that the class and string data
22c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson * appear first.
23c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson */
24c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson
25c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson#include "hprof.h"
266d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers
27622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include <cutils/open_memstream.h>
28622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include <errno.h>
29622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include <fcntl.h>
30622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include <stdio.h>
31622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include <string.h>
32622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include <sys/time.h>
33622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include <sys/uio.h>
34622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include <time.h>
35622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include <time.h>
36622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include <unistd.h>
37622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
38622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include <set>
39622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
40c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier#include "art_field-inl.h"
4107ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
42e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h"
4380afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/time_utils.h"
44761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h"
456d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "class_linker.h"
4662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h"
47c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson#include "debugger.h"
484f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
49e34fa1df67fbe0173b4ea9abddcc3ae3d0537037Mathieu Chartier#include "gc_root.h"
501d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/heap_bitmap.h"
511d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/heap.h"
521d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space.h"
53622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include "globals.h"
54ad466adf38db74a9840659626858196091151a64Mathieu Chartier#include "jdwp/jdwp.h"
55ad466adf38db74a9840659626858196091151a64Mathieu Chartier#include "jdwp/jdwp_priv.h"
562dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h"
572dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h"
582dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
59dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes#include "os.h"
60622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include "safe_map.h"
6100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
62622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include "thread_list.h"
63c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson
64c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilsonnamespace art {
65c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson
66c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilsonnamespace hprof {
67c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson
68ad466adf38db74a9840659626858196091151a64Mathieu Chartierstatic constexpr bool kDirectStream = true;
69622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampestatic constexpr uint32_t kHprofTime = 0;
713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampestatic constexpr uint32_t kHprofNullStackTrace = 0;
723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampestatic constexpr uint32_t kHprofNullThread = 0;
733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampestatic constexpr size_t kMaxObjectsPerSegment = 128;
753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampestatic constexpr size_t kMaxBytesPerSegment = 4096;
763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe// The static field-name for the synthetic object generated to account for class static overhead.
783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampestatic constexpr const char* kStaticOverheadName = "$staticOverhead";
79622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
80622a6988351d77da0008142f4ce1ea447d838556Elliott Hughesenum HprofTag {
81622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_STRING = 0x01,
82622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_LOAD_CLASS = 0x02,
83622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_UNLOAD_CLASS = 0x03,
84622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_STACK_FRAME = 0x04,
85622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_STACK_TRACE = 0x05,
86622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_ALLOC_SITES = 0x06,
87622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_HEAP_SUMMARY = 0x07,
88622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_START_THREAD = 0x0A,
89622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_END_THREAD = 0x0B,
90622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_HEAP_DUMP = 0x0C,
91622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_HEAP_DUMP_SEGMENT = 0x1C,
92622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_HEAP_DUMP_END = 0x2C,
93622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_CPU_SAMPLES = 0x0D,
94622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_TAG_CONTROL_SETTINGS = 0x0E,
95622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes};
96622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
97622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes// Values for the first byte of HEAP_DUMP and HEAP_DUMP_SEGMENT records:
98622a6988351d77da0008142f4ce1ea447d838556Elliott Hughesenum HprofHeapTag {
99622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  // Traditional.
100622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_UNKNOWN = 0xFF,
101622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_JNI_GLOBAL = 0x01,
102622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_JNI_LOCAL = 0x02,
103622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_JAVA_FRAME = 0x03,
104622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_NATIVE_STACK = 0x04,
105622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_STICKY_CLASS = 0x05,
106622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_THREAD_BLOCK = 0x06,
107622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_MONITOR_USED = 0x07,
108622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_THREAD_OBJECT = 0x08,
109622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_CLASS_DUMP = 0x20,
110622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_INSTANCE_DUMP = 0x21,
111622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_OBJECT_ARRAY_DUMP = 0x22,
112622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_PRIMITIVE_ARRAY_DUMP = 0x23,
113622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
114622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  // Android.
115622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_HEAP_DUMP_INFO = 0xfe,
116622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_INTERNED_STRING = 0x89,
117622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_FINALIZING = 0x8a,  // Obsolete.
118622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_DEBUGGER = 0x8b,
119622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_REFERENCE_CLEANUP = 0x8c,  // Obsolete.
120622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_VM_INTERNAL = 0x8d,
121622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_ROOT_JNI_MONITOR = 0x8e,
122622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_UNREACHABLE = 0x90,  // Obsolete.
123dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  HPROF_PRIMITIVE_ARRAY_NODATA_DUMP = 0xc3,  // Obsolete.
124622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes};
125622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
126622a6988351d77da0008142f4ce1ea447d838556Elliott Hughesenum HprofHeapId {
127622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_HEAP_DEFAULT = 0,
128622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  HPROF_HEAP_ZYGOTE = 'Z',
129ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier  HPROF_HEAP_APP = 'A',
130ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier  HPROF_HEAP_IMAGE = 'I',
131622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes};
132622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
133622a6988351d77da0008142f4ce1ea447d838556Elliott Hughesenum HprofBasicType {
134622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof_basic_object = 2,
135622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof_basic_boolean = 4,
136622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof_basic_char = 5,
137622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof_basic_float = 6,
138622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof_basic_double = 7,
139622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof_basic_byte = 8,
140622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof_basic_short = 9,
141622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof_basic_int = 10,
142622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  hprof_basic_long = 11,
143622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes};
144622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
145ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogerstypedef uint32_t HprofStringId;
146ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogerstypedef uint32_t HprofClassObjectId;
147622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
1483a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampeclass EndianOutput {
149622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes public:
1503a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  EndianOutput() : length_(0), sum_length_(0), max_length_(0), started_(false) {}
1513a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual ~EndianOutput() {}
152dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
1533a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void StartNewRecord(uint8_t tag, uint32_t time) {
1543a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (length_ > 0) {
1553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      EndRecord();
1563a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
1573a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_EQ(length_, 0U);
1583a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    AddU1(tag);
1593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    AddU4(time);
1603a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    AddU4(0xdeaddead);  // Length, replaced on flush.
1613a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    started_ = true;
162dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
163dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
1643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void EndRecord() {
1653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Replace length in header.
1663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (started_) {
1673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      UpdateU4(sizeof(uint8_t) + sizeof(uint32_t),
1683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe               length_ - sizeof(uint8_t) - 2 * sizeof(uint32_t));
1693a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
170dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
1713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HandleEndRecord();
172622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
1733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    sum_length_ += length_;
1743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    max_length_ = std::max(max_length_, length_);
1753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    length_ = 0;
1763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    started_ = false;
1773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
178622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
1793a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void AddU1(uint8_t value) {
1803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    AddU1List(&value, 1);
1813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
182ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddU2(uint16_t value) {
183ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU2List(&value, 1);
184622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
185ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddU4(uint32_t value) {
186ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU4List(&value, 1);
187622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
188622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
189ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddU8(uint64_t value) {
190ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU8List(&value, 1);
191622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
192622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
193ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddObjectId(const mirror::Object* value) {
194ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU4(PointerToLowMemUInt32(value));
195ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  }
196ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
197ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  // The ID for the synthetic object generated to account for class static overhead.
198ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddClassStaticsId(const mirror::Class* value) {
199ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU4(1 | PointerToLowMemUInt32(value));
200622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
201622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
202ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddJniGlobalRefId(jobject value) {
203ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU4(PointerToLowMemUInt32(value));
204622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
205622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
206ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddClassId(HprofClassObjectId value) {
207ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU4(value);
208622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
209622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
210ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddStringId(HprofStringId value) {
211ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU4(value);
212dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
213dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
2143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void AddU1List(const uint8_t* values, size_t count) {
2153a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HandleU1List(values, count);
2163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    length_ += count;
2173a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2183a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void AddU2List(const uint16_t* values, size_t count) {
2193a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HandleU2List(values, count);
2203a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    length_ += count * sizeof(uint16_t);
2213a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2223a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void AddU4List(const uint32_t* values, size_t count) {
2233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HandleU4List(values, count);
2243a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    length_ += count * sizeof(uint32_t);
2253a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
226ca71458862be8505330b7fd5649a062f31d143dcAndreas Gampe  virtual void UpdateU4(size_t offset, uint32_t new_value ATTRIBUTE_UNUSED) {
2273a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_LE(offset, length_ - 4);
2283a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2293a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void AddU8List(const uint64_t* values, size_t count) {
2303a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HandleU8List(values, count);
2313a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    length_ += count * sizeof(uint64_t);
2323a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
233622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
234ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddIdList(mirror::ObjectArray<mirror::Object>* values)
2353a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
236ad466adf38db74a9840659626858196091151a64Mathieu Chartier    const int32_t length = values->GetLength();
237ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    for (int32_t i = 0; i < length; ++i) {
238ad466adf38db74a9840659626858196091151a64Mathieu Chartier      AddObjectId(values->GetWithoutChecks(i));
239ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    }
240622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
241622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
242ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddUtf8String(const char* str) {
243622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes    // The terminating NUL character is NOT written.
244ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU1List((const uint8_t*)str, strlen(str));
245622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
246622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
2473a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t Length() const {
248dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    return length_;
249dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
250622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
2513a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t SumLength() const {
2523a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return sum_length_;
253622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
254dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
2553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t MaxLength() const {
2563a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return max_length_;
2573a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
258dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
2593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe protected:
2603a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual void HandleU1List(const uint8_t* values ATTRIBUTE_UNUSED,
2613a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe                            size_t count ATTRIBUTE_UNUSED) {
2623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2633a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual void HandleU2List(const uint16_t* values ATTRIBUTE_UNUSED,
2643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe                            size_t count ATTRIBUTE_UNUSED) {
2653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual void HandleU4List(const uint32_t* values ATTRIBUTE_UNUSED,
2673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe                            size_t count ATTRIBUTE_UNUSED) {
2683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2693a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual void HandleU8List(const uint64_t* values ATTRIBUTE_UNUSED,
2703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe                            size_t count ATTRIBUTE_UNUSED) {
2713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual void HandleEndRecord() {
2733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
274dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
2753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t length_;      // Current record size.
2763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t sum_length_;  // Size of all data.
2773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t max_length_;  // Maximum seen length.
2783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  bool started_;       // Was StartRecord called?
279622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes};
280622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
2813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe// This keeps things buffered until flushed.
2823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampeclass EndianOutputBuffered : public EndianOutput {
283622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes public:
2843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  explicit EndianOutputBuffered(size_t reserve_size) {
2853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_.reserve(reserve_size);
2863a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2873a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual ~EndianOutputBuffered() {}
2883a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
2893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void UpdateU4(size_t offset, uint32_t new_value) OVERRIDE {
2903a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_LE(offset, length_ - 4);
2913a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_[offset + 0] = static_cast<uint8_t>((new_value >> 24) & 0xFF);
2923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_[offset + 1] = static_cast<uint8_t>((new_value >> 16) & 0xFF);
2933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_[offset + 2] = static_cast<uint8_t>((new_value >> 8)  & 0xFF);
2943a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_[offset + 3] = static_cast<uint8_t>((new_value >> 0)  & 0xFF);
295dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
296dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
2973a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe protected:
2983a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleU1List(const uint8_t* values, size_t count) OVERRIDE {
2993a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_EQ(length_, buffer_.size());
3003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_.insert(buffer_.end(), values, values + count);
3013a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3023a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3033a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleU2List(const uint16_t* values, size_t count) OVERRIDE {
3043a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_EQ(length_, buffer_.size());
3053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    for (size_t i = 0; i < count; ++i) {
3063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      uint16_t value = *values;
3073a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 8) & 0xFF));
3083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 0) & 0xFF));
3093a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      values++;
310dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
3113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3123a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleU4List(const uint32_t* values, size_t count) OVERRIDE {
3143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_EQ(length_, buffer_.size());
3153a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    for (size_t i = 0; i < count; ++i) {
3163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      uint32_t value = *values;
3173a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 24) & 0xFF));
3183a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 16) & 0xFF));
3193a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 8)  & 0xFF));
3203a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 0)  & 0xFF));
3213a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      values++;
322dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
323dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
324dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
3253a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleU8List(const uint64_t* values, size_t count) OVERRIDE {
3263a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_EQ(length_, buffer_.size());
3273a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    for (size_t i = 0; i < count; ++i) {
3283a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      uint64_t value = *values;
3293a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 56) & 0xFF));
3303a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 48) & 0xFF));
3313a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 40) & 0xFF));
3323a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 32) & 0xFF));
3333a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 24) & 0xFF));
3343a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 16) & 0xFF));
3353a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 8)  & 0xFF));
3363a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 0)  & 0xFF));
3373a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      values++;
33800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
339ad466adf38db74a9840659626858196091151a64Mathieu Chartier  }
340dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
3413a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleEndRecord() OVERRIDE {
3423a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_EQ(buffer_.size(), length_);
3433a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (kIsDebugBuild && started_) {
3443a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      uint32_t stored_length =
3453a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          static_cast<uint32_t>(buffer_[5]) << 24 |
3463a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          static_cast<uint32_t>(buffer_[6]) << 16 |
3473a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          static_cast<uint32_t>(buffer_[7]) << 8 |
3483a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          static_cast<uint32_t>(buffer_[8]);
3493a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      DCHECK_EQ(stored_length, length_ - sizeof(uint8_t) - 2 * sizeof(uint32_t));
350ad466adf38db74a9840659626858196091151a64Mathieu Chartier    }
3513a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HandleFlush(buffer_.data(), length_);
3523a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_.clear();
353ad466adf38db74a9840659626858196091151a64Mathieu Chartier  }
354dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
3553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual void HandleFlush(const uint8_t* buffer ATTRIBUTE_UNUSED, size_t length ATTRIBUTE_UNUSED) {
3563a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3573a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3583a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  std::vector<uint8_t> buffer_;
3593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe};
3603a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3613a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampeclass FileEndianOutput FINAL : public EndianOutputBuffered {
3623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe public:
3633a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  FileEndianOutput(File* fp, size_t reserved_size)
3643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      : EndianOutputBuffered(reserved_size), fp_(fp), errors_(false) {
3653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK(fp != nullptr);
3663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  ~FileEndianOutput() {
3683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3693a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  bool Errors() {
3713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return errors_;
3723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe protected:
3753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleFlush(const uint8_t* buffer, size_t length) OVERRIDE {
3763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (!errors_) {
3773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      errors_ = !fp_->WriteFully(buffer, length);
378ad466adf38db74a9840659626858196091151a64Mathieu Chartier    }
379ad466adf38db74a9840659626858196091151a64Mathieu Chartier  }
380ad466adf38db74a9840659626858196091151a64Mathieu Chartier
3813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe private:
3823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  File* fp_;
3833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  bool errors_;
3843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe};
3853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3863a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampeclass NetStateEndianOutput FINAL : public EndianOutputBuffered {
3873a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe public:
3883a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  NetStateEndianOutput(JDWP::JdwpNetStateBase* net_state, size_t reserved_size)
3893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      : EndianOutputBuffered(reserved_size), net_state_(net_state) {
3903a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK(net_state != nullptr);
3913a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  ~NetStateEndianOutput() {}
3933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3943a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe protected:
3953a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleFlush(const uint8_t* buffer, size_t length) OVERRIDE {
3963a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    std::vector<iovec> iov;
3973a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    iov.push_back(iovec());
3983a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    iov[0].iov_base = const_cast<void*>(reinterpret_cast<const void*>(buffer));
3993a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    iov[0].iov_len = length;
4003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    net_state_->WriteBufferedPacketLocked(iov);
4013a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
4023a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
4033a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe private:
4043a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  JDWP::JdwpNetStateBase* net_state_;
4053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe};
4063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
407bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier#define __ output_->
4083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
409bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartierclass Hprof : public SingleRootVisitor {
4103a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe public:
4113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  Hprof(const char* output_filename, int fd, bool direct_to_ddms)
4123a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      : filename_(output_filename),
4133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        fd_(fd),
4143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        direct_to_ddms_(direct_to_ddms),
4153a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        start_ns_(NanoTime()),
4163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        current_heap_(HPROF_HEAP_DEFAULT),
4173a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        objects_in_segment_(0),
4183a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        next_string_id_(0x400000) {
4193a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    LOG(INFO) << "hprof: heap dump \"" << filename_ << "\" starting...";
4203a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
4213a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
4223a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void Dump()
4233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
424ad466adf38db74a9840659626858196091151a64Mathieu Chartier      LOCKS_EXCLUDED(Locks::heap_bitmap_lock_) {
4253a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // First pass to measure the size of the dump.
4263a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    size_t overall_size;
4273a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    size_t max_length;
428ad466adf38db74a9840659626858196091151a64Mathieu Chartier    {
4293a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      EndianOutput count_output;
430bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      output_ = &count_output;
431bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      ProcessHeap(false);
4323a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      overall_size = count_output.SumLength();
4333a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      max_length = count_output.MaxLength();
434bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      output_ = nullptr;
435ad466adf38db74a9840659626858196091151a64Mathieu Chartier    }
436dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
4373a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    bool okay;
4383a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (direct_to_ddms_) {
4393a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      if (kDirectStream) {
4403a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        okay = DumpToDdmsDirect(overall_size, max_length, CHUNK_TYPE("HPDS"));
4414303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe      } else {
4423a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        okay = DumpToDdmsBuffered(overall_size, max_length);
443dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      }
4443a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else {
4453a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      okay = DumpToFile(overall_size, max_length);
446dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
447dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
448dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    if (okay) {
449dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      uint64_t duration = NanoTime() - start_ns_;
45050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers      LOG(INFO) << "hprof: heap dump completed ("
4513a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          << PrettySize(RoundUp(overall_size, 1024))
45250b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers          << ") in " << PrettyDuration(duration);
453dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
454dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
455622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
456622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes private:
45783c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartier  static void VisitObjectCallback(mirror::Object* obj, void* arg)
458b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
459ad466adf38db74a9840659626858196091151a64Mathieu Chartier    DCHECK(obj != nullptr);
460ad466adf38db74a9840659626858196091151a64Mathieu Chartier    DCHECK(arg != nullptr);
461bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    reinterpret_cast<Hprof*>(arg)->DumpHeapObject(obj);
462dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
463622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
464bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void DumpHeapObject(mirror::Object* obj)
4653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
4663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
467bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void DumpHeapClass(mirror::Class* klass)
46883c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartier      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
469622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
470bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void DumpHeapArray(mirror::Array* obj, mirror::Class* klass)
4713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
4723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
473bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void DumpHeapInstanceObject(mirror::Object* obj, mirror::Class* klass)
4743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
4753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
476bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void ProcessHeap(bool header_first)
4770c8c303c20cdaaf54d26e45cc17dc5afb820d8efHiroshi Yamauchi      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) {
4783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Reset current heap and object count.
4793a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    current_heap_ = HPROF_HEAP_DEFAULT;
4803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    objects_in_segment_ = 0;
4813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
4823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (header_first) {
483bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      ProcessHeader();
484bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      ProcessBody();
4853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else {
486bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      ProcessBody();
487bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      ProcessHeader();
4883a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
4893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
490622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
491bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void ProcessBody() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) {
492bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    Runtime* const runtime = Runtime::Current();
4933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Walk the roots and the heap.
494bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_->StartNewRecord(HPROF_TAG_HEAP_DUMP_SEGMENT, kHprofTime);
4953a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
496bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    runtime->VisitRoots(this);
497bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    runtime->VisitImageRoots(this);
498bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    runtime->GetHeap()->VisitObjectsPaused(VisitObjectCallback, this);
4993a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
500bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_->StartNewRecord(HPROF_TAG_HEAP_DUMP_END, kHprofTime);
501bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_->EndRecord();
5023a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
5033a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
504bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void ProcessHeader() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) {
5053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Write the header.
506bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    WriteFixedHeader();
5073a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Write the string and class tables, and any stack traces, to the header.
5083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // (jhat requires that these appear before any of the data in the body that refers to them.)
509bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    WriteStringTable();
510bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    WriteClassTable();
511bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    WriteStackTraces();
512bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_->EndRecord();
5133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
5143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
515bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void WriteClassTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
516dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    uint32_t nextSerialNumber = 1;
517dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
518ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    for (mirror::Class* c : classes_) {
519ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      CHECK(c != nullptr);
520bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      output_->StartNewRecord(HPROF_TAG_LOAD_CLASS, kHprofTime);
521dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // LOAD CLASS format:
522dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // U4: class serial number (always > 0)
523dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // ID: class object ID. We use the address of the class object structure as its ID.
524dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // U4: stack trace serial number
525dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // ID: class name string ID
5263a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4(nextSerialNumber++);
5273a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddObjectId(c);
5283a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4(kHprofNullStackTrace);
5293a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddStringId(LookupClassNameId(c));
530dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
5310c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
5320c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
533bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void WriteStringTable() {
534ad466adf38db74a9840659626858196091151a64Mathieu Chartier    for (const std::pair<std::string, HprofStringId>& p : strings_) {
535ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const std::string& string = p.first;
536ad466adf38db74a9840659626858196091151a64Mathieu Chartier      const size_t id = p.second;
537dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
538bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      output_->StartNewRecord(HPROF_TAG_STRING, kHprofTime);
5390c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
540dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // STRING format:
541dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // ID:  ID for this string
5422cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      // U1*: UTF8 characters for string (NOT null terminated)
543dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      //      (the record format encodes the length)
5443a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4(id);
5453a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddUtf8String(string.c_str());
546dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
547dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
5480c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
549bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void StartNewHeapDumpSegment() {
550dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    // This flushes the old segment and starts a new one.
551bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_->StartNewRecord(HPROF_TAG_HEAP_DUMP_SEGMENT, kHprofTime);
552dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    objects_in_segment_ = 0;
553dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    // Starting a new HEAP_DUMP resets the heap to default.
554dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    current_heap_ = HPROF_HEAP_DEFAULT;
555dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
556dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
557bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void CheckHeapSegmentConstraints() {
558bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    if (objects_in_segment_ >= kMaxObjectsPerSegment || output_->Length() >= kMaxBytesPerSegment) {
559bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      StartNewHeapDumpSegment();
5603a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
5613a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
5623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
563bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void VisitRoot(mirror::Object* obj, const RootInfo& root_info)
564bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
5653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void MarkRootObject(const mirror::Object* obj, jobject jni_obj, HprofHeapTag heap_tag,
566bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier                      uint32_t thread_serial);
567dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
568ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  HprofClassObjectId LookupClassId(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
569ad466adf38db74a9840659626858196091151a64Mathieu Chartier    if (c != nullptr) {
570ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      auto result = classes_.insert(c);
571ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const mirror::Class* present = *result.first;
572ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      CHECK_EQ(present, c);
573ad466adf38db74a9840659626858196091151a64Mathieu Chartier      // Make sure that we've assigned a string ID for this class' name
574ad466adf38db74a9840659626858196091151a64Mathieu Chartier      LookupClassNameId(c);
575ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    }
576ad466adf38db74a9840659626858196091151a64Mathieu Chartier    return PointerToLowMemUInt32(c);
577dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
578dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
579ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  HprofStringId LookupStringId(mirror::String* string) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
580dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    return LookupStringId(string->ToModifiedUtf8());
581dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
582dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
583dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  HprofStringId LookupStringId(const char* string) {
584dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    return LookupStringId(std::string(string));
585dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
586dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
587dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  HprofStringId LookupStringId(const std::string& string) {
588ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    auto it = strings_.find(string);
589dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    if (it != strings_.end()) {
590dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      return it->second;
591dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
592dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    HprofStringId id = next_string_id_++;
593dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    strings_.Put(string, id);
594dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    return id;
595dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
596dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
597ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  HprofStringId LookupClassNameId(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
598dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    return LookupStringId(PrettyDescriptor(c));
599dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
600dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
601bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void WriteFixedHeader() {
6020c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // Write the file header.
6030c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // U1: NUL-terminated magic string.
6043a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    const char magic[] = "JAVA PROFILE 1.0.3";
6053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1List(reinterpret_cast<const uint8_t*>(magic), sizeof(magic));
6063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
6073280517651195602253ed92a2749964e96cad27eCalin Juravle    // U4: size of identifiers.  We're using addresses as IDs and our heap references are stored
6083280517651195602253ed92a2749964e96cad27eCalin Juravle    // as uint32_t.
6093280517651195602253ed92a2749964e96cad27eCalin Juravle    // Note of warning: hprof-conv hard-codes the size of identifiers to 4.
610575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe    static_assert(sizeof(mirror::HeapReference<mirror::Object>) == sizeof(uint32_t),
611575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe                  "Unexpected HeapReference size");
6123a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(sizeof(uint32_t));
6133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
6140c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // The current time, in milliseconds since 0:00 GMT, 1/1/70.
6157b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes    timeval now;
6163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    const uint64_t nowMs = (gettimeofday(&now, nullptr) < 0) ? 0 :
617ad466adf38db74a9840659626858196091151a64Mathieu Chartier        (uint64_t)now.tv_sec * 1000 + now.tv_usec / 1000;
6183a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // TODO: It seems it would be correct to use U8.
6190c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // U4: high word of the 64-bit time.
6203a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(static_cast<uint32_t>(nowMs >> 32));
6210c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // U4: low word of the 64-bit time.
6223a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(static_cast<uint32_t>(nowMs & 0xFFFFFFFF));
6230c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
6240c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
625bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void WriteStackTraces() {
626dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    // Write a dummy stack trace record so the analysis tools don't freak out.
627bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_->StartNewRecord(HPROF_TAG_STACK_TRACE, kHprofTime);
6283a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(kHprofNullStackTrace);
6293a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(kHprofNullThread);
6303a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(0);    // no frames
6313a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
6323a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
6333a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  bool DumpToDdmsBuffered(size_t overall_size ATTRIBUTE_UNUSED, size_t max_length ATTRIBUTE_UNUSED)
6340c8c303c20cdaaf54d26e45cc17dc5afb820d8efHiroshi Yamauchi      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) {
6353a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    LOG(FATAL) << "Unimplemented";
6363a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    UNREACHABLE();
6373a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        // Send the data off to DDMS.
6383a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        iovec iov[2];
6393a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        iov[0].iov_base = header_data_ptr_;
6403a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        iov[0].iov_len = header_data_size_;
6413a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        iov[1].iov_base = body_data_ptr_;
6423a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        iov[1].iov_len = body_data_size_;
6433a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        Dbg::DdmSendChunkV(CHUNK_TYPE("HPDS"), iov, 2);
6443a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
6453a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
6463a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  bool DumpToFile(size_t overall_size, size_t max_length)
6470c8c303c20cdaaf54d26e45cc17dc5afb820d8efHiroshi Yamauchi      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) {
6483a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Where exactly are we writing to?
6493a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    int out_fd;
6503a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (fd_ >= 0) {
6513a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      out_fd = dup(fd_);
6523a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      if (out_fd < 0) {
6533a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        ThrowRuntimeException("Couldn't dump heap; dup(%d) failed: %s", fd_, strerror(errno));
6543a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        return false;
6553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      }
6563a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else {
6573a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      out_fd = open(filename_.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
6583a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      if (out_fd < 0) {
6593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        ThrowRuntimeException("Couldn't dump heap; open(\"%s\") failed: %s", filename_.c_str(),
6603a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe                              strerror(errno));
6613a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        return false;
6623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      }
6633a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
6643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
6653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    std::unique_ptr<File> file(new File(out_fd, filename_, true));
6663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    bool okay;
6673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    {
6683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      FileEndianOutput file_output(file.get(), max_length);
669bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      output_ = &file_output;
670bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      ProcessHeap(true);
6713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      okay = !file_output.Errors();
6723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
6733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      if (okay) {
6743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        // Check for expected size.
6753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        CHECK_EQ(file_output.SumLength(), overall_size);
6763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      }
677bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      output_ = nullptr;
6783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
6793a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
6803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (okay) {
6813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      okay = file->FlushCloseOrErase() == 0;
6823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else {
6833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      file->Erase();
6843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
6853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (!okay) {
6863a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      std::string msg(StringPrintf("Couldn't dump heap; writing \"%s\" failed: %s",
6873a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe                                   filename_.c_str(), strerror(errno)));
6883a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ThrowRuntimeException("%s", msg.c_str());
6893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      LOG(ERROR) << msg;
6903a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
6913a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
6923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return okay;
6933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
6943a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
6953a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  bool DumpToDdmsDirect(size_t overall_size, size_t max_length, uint32_t chunk_type)
6960c8c303c20cdaaf54d26e45cc17dc5afb820d8efHiroshi Yamauchi      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) {
6973a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    CHECK(direct_to_ddms_);
6983a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    JDWP::JdwpState* state = Dbg::GetJdwpState();
6993a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    CHECK(state != nullptr);
7003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    JDWP::JdwpNetStateBase* net_state = state->netState;
7013a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    CHECK(net_state != nullptr);
7023a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7033a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Hold the socket lock for the whole time since we want this to be atomic.
7043a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    MutexLock mu(Thread::Current(), *net_state->GetSocketLock());
7053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Prepare the Ddms chunk.
7073a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    constexpr size_t kChunkHeaderSize = kJDWPHeaderLen + 8;
7083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    uint8_t chunk_header[kChunkHeaderSize] = { 0 };
7093a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    state->SetupChunkHeader(chunk_type, overall_size, kChunkHeaderSize, chunk_header);
7103a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Prepare the output and send the chunk header.
7123a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    NetStateEndianOutput net_output(net_state, max_length);
713bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_ = &net_output;
7143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    net_output.AddU1List(chunk_header, kChunkHeaderSize);
7153a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Write the dump.
717bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    ProcessHeap(true);
7183a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7193a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Check for expected size.
7203a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    CHECK_EQ(net_output.SumLength(), overall_size + kChunkHeaderSize);
721bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_ = nullptr;
7223a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return true;
7240c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
7250c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
726dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  // If direct_to_ddms_ is set, "filename_" and "fd" will be ignored.
727dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  // Otherwise, "filename_" must be valid, though if "fd" >= 0 it will
728dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  // only be used for debug messages.
729dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  std::string filename_;
730dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  int fd_;
731dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  bool direct_to_ddms_;
7320c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
733dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  uint64_t start_ns_;
734dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
735bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  EndianOutput* output_;
736bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier
7377934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  HprofHeapId current_heap_;  // Which heap we're currently dumping.
738dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  size_t objects_in_segment_;
739dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
740ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  std::set<mirror::Class*> classes_;
741ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  HprofStringId next_string_id_;
742ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  SafeMap<std::string, HprofStringId> strings_;
743dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
744dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(Hprof);
745dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes};
7460c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
7473a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampestatic HprofBasicType SignatureToBasicTypeAndSize(const char* sig, size_t* size_out) {
7480c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  char c = sig[0];
7490c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  HprofBasicType ret;
7500c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  size_t size;
7510c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
7520c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  switch (c) {
7533a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case '[':
7543a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'L':
7553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_object;
7563a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 4;
7573a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
7583a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'Z':
7593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_boolean;
7603a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 1;
7613a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
7623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'C':
7633a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_char;
7643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 2;
7653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
7663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'F':
7673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_float;
7683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 4;
7693a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
7703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'D':
7713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_double;
7723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 8;
7733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
7743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'B':
7753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_byte;
7763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 1;
7773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
7783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'S':
7793a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_short;
7803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 2;
7813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
7823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'I':
7833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_int;
7843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 4;
7853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
7863a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'J':
7873a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_long;
7883a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 8;
7893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
7903a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    default:
7913a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      LOG(FATAL) << "UNREACHABLE";
7923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      UNREACHABLE();
7930c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
7940c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
7953a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (size_out != nullptr) {
7963a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    *size_out = size;
7970c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
7980c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
7990c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  return ret;
8000c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson}
8010c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
8020c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson// Always called when marking objects, but only does
8030c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson// something when ctx->gc_scan_state_ is non-zero, which is usually
8040c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson// only true when marking the root set or unreachable
8050c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson// objects.  Used to add rootset references to obj.
8063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampevoid Hprof::MarkRootObject(const mirror::Object* obj, jobject jni_obj, HprofHeapTag heap_tag,
807bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier                           uint32_t thread_serial) {
8083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (heap_tag == 0) {
8093a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return;
8103a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
8113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
812bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  CheckHeapSegmentConstraints();
8133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
8143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  switch (heap_tag) {
8153a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // ID: object ID
8163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_UNKNOWN:
8173a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_STICKY_CLASS:
8183a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_MONITOR_USED:
8193a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_INTERNED_STRING:
8203a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_DEBUGGER:
8213a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_VM_INTERNAL:
8223a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(heap_tag);
8233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddObjectId(obj);
8243a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
8253a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
8263a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // ID: object ID
8273a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // ID: JNI global ref ID
8283a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_JNI_GLOBAL:
8293a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(heap_tag);
8303a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddObjectId(obj);
8313a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddJniGlobalRefId(jni_obj);
8323a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
8333a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
8343a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // ID: object ID
8353a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // U4: thread serial number
8363a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // U4: frame number in stack trace (-1 for empty)
8373a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_JNI_LOCAL:
8383a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_JNI_MONITOR:
8393a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_JAVA_FRAME:
8403a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(heap_tag);
8413a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddObjectId(obj);
8423a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4(thread_serial);
8433a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4((uint32_t)-1);
8443a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
8453a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
8463a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // ID: object ID
8473a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // U4: thread serial number
8483a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_NATIVE_STACK:
8493a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_THREAD_BLOCK:
8503a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(heap_tag);
8513a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddObjectId(obj);
8523a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4(thread_serial);
8533a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
8543a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
8553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // ID: thread object ID
8563a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // U4: thread serial number
8573a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // U4: stack trace serial number
8583a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_THREAD_OBJECT:
8593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(heap_tag);
8603a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddObjectId(obj);
8613a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4(thread_serial);
8623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4((uint32_t)-1);    // xxx
8633a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
8643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
8653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_CLASS_DUMP:
8663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_INSTANCE_DUMP:
8673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_OBJECT_ARRAY_DUMP:
8683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_PRIMITIVE_ARRAY_DUMP:
8693a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_HEAP_DUMP_INFO:
8703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_PRIMITIVE_ARRAY_NODATA_DUMP:
8713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // Ignored.
8723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
8733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
8743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_FINALIZING:
8753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_REFERENCE_CLEANUP:
8763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_UNREACHABLE:
8773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      LOG(FATAL) << "obsolete tag " << static_cast<int>(heap_tag);
8783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
8790c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
8800c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
881dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  ++objects_in_segment_;
8820c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson}
8830c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
8842dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersstatic int StackTraceSerialNumber(const mirror::Object* /*obj*/) {
8853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  return kHprofNullStackTrace;
8860c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson}
8870c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
888bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid Hprof::DumpHeapObject(mirror::Object* obj) {
8893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // Ignore classes that are retired.
8903a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (obj->IsClass() && obj->AsClass()->IsRetired()) {
8913a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return;
8923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
8933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
894e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier  gc::Heap* const heap = Runtime::Current()->GetHeap();
895e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier  const gc::space::ContinuousSpace* const space = heap->FindContinuousSpaceFromObject(obj, true);
896ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier  HprofHeapId heap_type = HPROF_HEAP_APP;
897ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier  if (space != nullptr) {
898ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier    if (space->IsZygoteSpace()) {
899ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier      heap_type = HPROF_HEAP_ZYGOTE;
900ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier    } else if (space->IsImageSpace()) {
901ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier      heap_type = HPROF_HEAP_IMAGE;
902ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier    }
903e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier  } else {
904e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier    const auto* los = heap->GetLargeObjectsSpace();
905e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier    if (los->Contains(obj) && los->IsZygoteLargeObject(Thread::Current(), obj)) {
906e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier      heap_type = HPROF_HEAP_ZYGOTE;
907e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier    }
908ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier  }
909bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  CheckHeapSegmentConstraints();
9100c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
911ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier  if (heap_type != current_heap_) {
9120c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    HprofStringId nameId;
9130c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
9140c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // This object is in a different heap than the current one.
9150c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // Emit a HEAP_DUMP_INFO tag to change heaps.
9163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(HPROF_HEAP_DUMP_INFO);
9173a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(static_cast<uint32_t>(heap_type));   // uint32_t: heap type
918ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier    switch (heap_type) {
9190c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    case HPROF_HEAP_APP:
9200c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      nameId = LookupStringId("app");
9210c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      break;
9220c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    case HPROF_HEAP_ZYGOTE:
9230c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      nameId = LookupStringId("zygote");
9240c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      break;
925ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier    case HPROF_HEAP_IMAGE:
926ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier      nameId = LookupStringId("image");
927ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier      break;
9280c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    default:
9290c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      // Internal error
9300c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      LOG(ERROR) << "Unexpected desiredHeap";
9310c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      nameId = LookupStringId("<ILLEGAL>");
9320c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      break;
9330c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    }
9343a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddStringId(nameId);
935ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier    current_heap_ = heap_type;
9360c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
9370c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
9382dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Class* c = obj->GetClass();
9393a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (c == nullptr) {
9402cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    // This object will bother HprofReader, because it has a null
9410c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // class, so just don't dump it. It could be
9420c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // gDvm.unlinkedJavaLangClass or it could be an object just
9430c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // allocated which hasn't been initialized yet.
9440c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  } else {
9450c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    if (obj->IsClass()) {
946bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      DumpHeapClass(obj->AsClass());
9473a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else if (c->IsArrayClass()) {
948bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      DumpHeapArray(obj->AsArray(), c);
9493a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else {
950bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      DumpHeapInstanceObject(obj, c);
9513a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
9523a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
9530c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
9543a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  ++objects_in_segment_;
9553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe}
9560c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
957bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid Hprof::DumpHeapClass(mirror::Class* klass) {
958ca068b2385ba160367d1e7fd123317b851b99390Sebastien Hertz  if (!klass->IsLoaded() && !klass->IsErroneous()) {
959ca068b2385ba160367d1e7fd123317b851b99390Sebastien Hertz    // Class is allocated but not yet loaded: we cannot access its fields or super class.
960ca068b2385ba160367d1e7fd123317b851b99390Sebastien Hertz    return;
961ca068b2385ba160367d1e7fd123317b851b99390Sebastien Hertz  }
9623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t sFieldCount = klass->NumStaticFields();
9633a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (sFieldCount != 0) {
9643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    int byteLength = sFieldCount * sizeof(JValue);  // TODO bogus; fields are packed
9653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Create a byte array to reflect the allocation of the
9663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // StaticField array at the end of this class.
9673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
9683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddClassStaticsId(klass);
9693a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(StackTraceSerialNumber(klass));
9703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(byteLength);
9713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(hprof_basic_byte);
9723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    for (int i = 0; i < byteLength; ++i) {
9733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(0);
9743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
9753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
9760c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
9773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddU1(HPROF_CLASS_DUMP);
9783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddClassId(LookupClassId(klass));
9793a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddU4(StackTraceSerialNumber(klass));
9803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddClassId(LookupClassId(klass->GetSuperClass()));
9813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddObjectId(klass->GetClassLoader());
9823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddObjectId(nullptr);    // no signer
9833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddObjectId(nullptr);    // no prot domain
9843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddObjectId(nullptr);    // reserved
9853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddObjectId(nullptr);    // reserved
9863a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (klass->IsClassClass()) {
9873a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // ClassObjects have their static fields appended, so aren't all the same size.
9883a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // But they're at least this size.
9893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(sizeof(mirror::Class));  // instance size
9900ce43539b3bbade7d95482c4da0126a54d5bcba9Jeff Hao  } else if (klass->IsStringClass()) {
9910ce43539b3bbade7d95482c4da0126a54d5bcba9Jeff Hao    // Strings are variable length with character data at the end like arrays.
9920ce43539b3bbade7d95482c4da0126a54d5bcba9Jeff Hao    // This outputs the size of an empty string.
9930ce43539b3bbade7d95482c4da0126a54d5bcba9Jeff Hao    __ AddU4(sizeof(mirror::String));
9940ce43539b3bbade7d95482c4da0126a54d5bcba9Jeff Hao  } else if (klass->IsArrayClass() || klass->IsPrimitive()) {
9953a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(0);
9963a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  } else {
9973a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(klass->GetObjectSize());  // instance size
9983a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
9993a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
10003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddU2(0);  // empty const pool
10010c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
10023a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // Static fields
10033a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (sFieldCount == 0) {
10043a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU2((uint16_t)0);
10053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  } else {
10063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU2((uint16_t)(sFieldCount+1));
10073a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddStringId(LookupStringId(kStaticOverheadName));
10083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(hprof_basic_object);
10093a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddClassStaticsId(klass);
10103a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
10113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    for (size_t i = 0; i < sFieldCount; ++i) {
1012c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      ArtField* f = klass->GetStaticField(i);
10133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
10143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size_t size;
10153a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
10163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddStringId(LookupStringId(f->GetName()));
10173a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(t);
101815f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      switch (t) {
101915f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_byte:
1020ff38c04b88e86bffdd520bc1863d05334ada6c94Mathieu Chartier          __ AddU1(f->GetByte(klass));
10213a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          break;
102215f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_boolean:
102315f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier          __ AddU1(f->GetBoolean(klass));
102415f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier          break;
102515f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_char:
1026ff38c04b88e86bffdd520bc1863d05334ada6c94Mathieu Chartier          __ AddU2(f->GetChar(klass));
10273a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          break;
102815f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_short:
102915f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier          __ AddU2(f->GetShort(klass));
103015f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier          break;
103115f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_float:
103215f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_int:
103315f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_object:
10343a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          __ AddU4(f->Get32(klass));
10353a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          break;
103615f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_double:
103715f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_long:
10383a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          __ AddU8(f->Get64(klass));
10393a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          break;
10403a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        default:
10413a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          LOG(FATAL) << "Unexpected size " << size;
10423a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          UNREACHABLE();
10430c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      }
10443a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
10453a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
10463a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
10473a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // Instance fields for this class (no superclass fields)
10487c1f53e4253e6acff5e76f00e6bf666518068c4dMathieu Chartier  int iFieldCount = klass->NumInstanceFields();
1049848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  if (klass->IsStringClass()) {
1050848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU2((uint16_t)iFieldCount + 1);
1051848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  } else {
1052848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU2((uint16_t)iFieldCount);
1053848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  }
10543a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  for (int i = 0; i < iFieldCount; ++i) {
1055c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    ArtField* f = klass->GetInstanceField(i);
10563a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddStringId(LookupStringId(f->GetName()));
10573a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), nullptr);
10583a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(t);
10593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
1060848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  // Add native value character array for strings.
1061848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  if (klass->IsStringClass()) {
1062848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddStringId(LookupStringId("value"));
1063848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU1(hprof_basic_object);
1064848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  }
10653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe}
10663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
1067bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid Hprof::DumpHeapArray(mirror::Array* obj, mirror::Class* klass) {
10683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  uint32_t length = obj->GetLength();
10690c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
10703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (obj->IsObjectArray()) {
10713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // obj is an object array.
10723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(HPROF_OBJECT_ARRAY_DUMP);
10730c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
10743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddObjectId(obj);
10753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(StackTraceSerialNumber(obj));
10763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(length);
10773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddClassId(LookupClassId(klass));
10780c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
10792cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    // Dump the elements, which are always objects or null.
10803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddIdList(obj->AsObjectArray<mirror::Object>());
10813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  } else {
10823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    size_t size;
10833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HprofBasicType t = SignatureToBasicTypeAndSize(
10843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        Primitive::Descriptor(klass->GetComponentType()->GetPrimitiveType()), &size);
10853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
10863a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // obj is a primitive array.
10873a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
10883a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
10893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddObjectId(obj);
10903a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(StackTraceSerialNumber(obj));
10913a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(length);
10923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(t);
10933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
10943a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Dump the raw, packed element values.
10953a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (size == 1) {
10963a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1List(reinterpret_cast<const uint8_t*>(obj->GetRawData(sizeof(uint8_t), 0)), length);
10973a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else if (size == 2) {
10983a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU2List(reinterpret_cast<const uint16_t*>(obj->GetRawData(sizeof(uint16_t), 0)), length);
10993a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else if (size == 4) {
11003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4List(reinterpret_cast<const uint32_t*>(obj->GetRawData(sizeof(uint32_t), 0)), length);
11013a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else if (size == 8) {
11023a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU8List(reinterpret_cast<const uint64_t*>(obj->GetRawData(sizeof(uint64_t), 0)), length);
11033a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
11043a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
11053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe}
11063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
1107bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid Hprof::DumpHeapInstanceObject(mirror::Object* obj, mirror::Class* klass) {
11083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // obj is an instance object.
11093a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddU1(HPROF_INSTANCE_DUMP);
11103a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddObjectId(obj);
11113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddU4(StackTraceSerialNumber(obj));
11123a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddClassId(LookupClassId(klass));
11133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
11143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // Reserve some space for the length of the instance data, which we won't
11153a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // know until we're done writing it.
1116bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  size_t size_patch_offset = output_->Length();
11173a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddU4(0x77777777);
11183a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
11193a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // Write the instance data;  fields for this class, followed by super class fields,
11203a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // and so on. Don't write the klass or monitor fields of Object.class.
1121848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  mirror::Class* orig_klass = klass;
11227c1f53e4253e6acff5e76f00e6bf666518068c4dMathieu Chartier  do {
11233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    int ifieldCount = klass->NumInstanceFields();
11243a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    for (int i = 0; i < ifieldCount; ++i) {
1125c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      ArtField* f = klass->GetInstanceField(i);
11263a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size_t size;
112715f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      auto t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
112815f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      switch (t) {
112915f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_byte:
1130ff38c04b88e86bffdd520bc1863d05334ada6c94Mathieu Chartier        __ AddU1(f->GetByte(obj));
113115f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        break;
113215f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_boolean:
113315f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        __ AddU1(f->GetBoolean(obj));
113415f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        break;
113515f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_char:
1136ff38c04b88e86bffdd520bc1863d05334ada6c94Mathieu Chartier        __ AddU2(f->GetChar(obj));
113715f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        break;
113815f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_short:
113915f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        __ AddU2(f->GetShort(obj));
114015f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        break;
114115f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_float:
114215f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_int:
114315f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_object:
11443a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        __ AddU4(f->Get32(obj));
114515f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        break;
114615f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_double:
114715f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_long:
11483a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        __ AddU8(f->Get64(obj));
114915f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        break;
11500c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      }
11510c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    }
11523a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
11533a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    klass = klass->GetSuperClass();
11547c1f53e4253e6acff5e76f00e6bf666518068c4dMathieu Chartier  } while (klass != nullptr);
11550c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
1156848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  // Output native value character array for strings.
1157848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  if (orig_klass->IsStringClass()) {
1158848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    mirror::String* s = obj->AsString();
115990bcbd50aca23331869f64a2ecb8e6c292c127ffJeff Hao    mirror::Object* value;
116090bcbd50aca23331869f64a2ecb8e6c292c127ffJeff Hao    if (s->GetLength() == 0) {
116190bcbd50aca23331869f64a2ecb8e6c292c127ffJeff Hao      // If string is empty, use an object-aligned address within the string for the value.
116290bcbd50aca23331869f64a2ecb8e6c292c127ffJeff Hao      value = reinterpret_cast<mirror::Object*>(reinterpret_cast<uintptr_t>(s) + kObjectAlignment);
116390bcbd50aca23331869f64a2ecb8e6c292c127ffJeff Hao    } else {
116490bcbd50aca23331869f64a2ecb8e6c292c127ffJeff Hao      value = reinterpret_cast<mirror::Object*>(s->GetValue());
116590bcbd50aca23331869f64a2ecb8e6c292c127ffJeff Hao    }
116690bcbd50aca23331869f64a2ecb8e6c292c127ffJeff Hao    __ AddObjectId(value);
1167848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao
1168848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    // Patch the instance field length.
1169848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ UpdateU4(size_patch_offset, output_->Length() - (size_patch_offset + 4));
1170848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao
1171848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
117290bcbd50aca23331869f64a2ecb8e6c292c127ffJeff Hao    __ AddObjectId(value);
1173848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU4(StackTraceSerialNumber(obj));
1174848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU4(s->GetLength());
1175848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU1(hprof_basic_char);
1176848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU2List(s->GetValue(), s->GetLength());
1177848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  } else {
1178848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    // Patch the instance field length.
1179848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ UpdateU4(size_patch_offset, output_->Length() - (size_patch_offset + 4));
1180848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  }
11810c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson}
11820c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
1183bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid Hprof::VisitRoot(mirror::Object* obj, const RootInfo& info) {
11840b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson  static const HprofHeapTag xlate[] = {
11850b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_UNKNOWN,
11860b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_JNI_GLOBAL,
11870b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_JNI_LOCAL,
11880b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_JAVA_FRAME,
11890b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_NATIVE_STACK,
11900b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_STICKY_CLASS,
11910b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_THREAD_BLOCK,
11920b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_MONITOR_USED,
11930b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_THREAD_OBJECT,
11940b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_INTERNED_STRING,
11950b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_FINALIZING,
11960b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_DEBUGGER,
11970b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_REFERENCE_CLEANUP,
11980b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_VM_INTERNAL,
11990b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_JNI_MONITOR,
12000b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson  };
1201e34fa1df67fbe0173b4ea9abddcc3ae3d0537037Mathieu Chartier  CHECK_LT(info.GetType(), sizeof(xlate) / sizeof(HprofHeapTag));
12023a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (obj == nullptr) {
12030b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    return;
12040b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson  }
1205bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  MarkRootObject(obj, 0, xlate[info.GetType()], info.GetThreadId());
1206c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson}
1207c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson
1208dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes// If "direct_to_ddms" is true, the other arguments are ignored, and data is
1209dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes// sent directly to DDMS.
1210dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes// If "fd" is >= 0, the output will be written to that file descriptor.
1211dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes// Otherwise, "filename" is used to create an output file.
1212dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughesvoid DumpHeap(const char* filename, int fd, bool direct_to_ddms) {
12133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  CHECK(filename != nullptr);
12140b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson
12152cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi  Thread* self = Thread::Current();
12162cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi  gc::Heap* heap = Runtime::Current()->GetHeap();
12172cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi  if (heap->IsGcConcurrentAndMoving()) {
12182cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi    // Need to take a heap dump while GC isn't running. See the
12192cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi    // comment in Heap::VisitObjects().
12202cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi    heap->IncrementDisableMovingGC(self);
12212cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi  }
1222bf44d42d978861f33fd5978f49392db3321ae414Mathieu Chartier  Runtime::Current()->GetThreadList()->SuspendAll(__FUNCTION__, true /* long suspend */);
1223dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  Hprof hprof(filename, fd, direct_to_ddms);
1224dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  hprof.Dump();
122500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Runtime::Current()->GetThreadList()->ResumeAll();
12262cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi  if (heap->IsGcConcurrentAndMoving()) {
12272cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi    heap->DecrementDisableMovingGC(self);
12282cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi  }
1229c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson}
1230c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson
1231ad466adf38db74a9840659626858196091151a64Mathieu Chartier}  // namespace hprof
1232c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson}  // namespace art
1233