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"
518c2ff641294715864013737fdec57cdfd410270cMan Cao#include "gc/allocation_record.h"
521d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/heap.h"
531d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space.h"
54622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include "globals.h"
55ad466adf38db74a9840659626858196091151a64Mathieu Chartier#include "jdwp/jdwp.h"
56ad466adf38db74a9840659626858196091151a64Mathieu Chartier#include "jdwp/jdwp_priv.h"
572dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h"
582dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h"
592dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
60dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes#include "os.h"
61622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include "safe_map.h"
6200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
63622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes#include "thread_list.h"
64c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson
65c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilsonnamespace art {
66c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson
67c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilsonnamespace hprof {
68c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson
69ad466adf38db74a9840659626858196091151a64Mathieu Chartierstatic constexpr bool kDirectStream = true;
70622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampestatic constexpr uint32_t kHprofTime = 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.
78a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartierstatic constexpr const char* kClassOverheadName = "$classOverhead";
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;
1478c2ff641294715864013737fdec57cdfd410270cMan Caotypedef uint32_t HprofClassSerialNumber;
1488c2ff641294715864013737fdec57cdfd410270cMan Caotypedef uint32_t HprofStackTraceSerialNumber;
1498c2ff641294715864013737fdec57cdfd410270cMan Caotypedef uint32_t HprofStackFrameId;
1508c2ff641294715864013737fdec57cdfd410270cMan Caostatic constexpr HprofStackTraceSerialNumber kHprofNullStackTrace = 0;
151622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
1523a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampeclass EndianOutput {
153622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes public:
1543a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  EndianOutput() : length_(0), sum_length_(0), max_length_(0), started_(false) {}
1553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual ~EndianOutput() {}
156dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
1573a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void StartNewRecord(uint8_t tag, uint32_t time) {
1583a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (length_ > 0) {
1593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      EndRecord();
1603a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
1613a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_EQ(length_, 0U);
1623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    AddU1(tag);
1633a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    AddU4(time);
1643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    AddU4(0xdeaddead);  // Length, replaced on flush.
1653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    started_ = true;
166dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
167dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
1683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void EndRecord() {
1693a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Replace length in header.
1703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (started_) {
1713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      UpdateU4(sizeof(uint8_t) + sizeof(uint32_t),
1723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe               length_ - sizeof(uint8_t) - 2 * sizeof(uint32_t));
1733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
174dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
1753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HandleEndRecord();
176622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
1773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    sum_length_ += length_;
1783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    max_length_ = std::max(max_length_, length_);
1793a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    length_ = 0;
1803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    started_ = false;
1813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
182622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
1833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void AddU1(uint8_t value) {
1843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    AddU1List(&value, 1);
1853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
186ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddU2(uint16_t value) {
187ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU2List(&value, 1);
188622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
189ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddU4(uint32_t value) {
190ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU4List(&value, 1);
191622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
192622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
193ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddU8(uint64_t value) {
194ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU8List(&value, 1);
195622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
196622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
197ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddObjectId(const mirror::Object* value) {
198ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU4(PointerToLowMemUInt32(value));
199ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  }
200ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
2018c2ff641294715864013737fdec57cdfd410270cMan Cao  void AddStackTraceSerialNumber(HprofStackTraceSerialNumber value) {
2028c2ff641294715864013737fdec57cdfd410270cMan Cao    AddU4(value);
2038c2ff641294715864013737fdec57cdfd410270cMan Cao  }
2048c2ff641294715864013737fdec57cdfd410270cMan Cao
205ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  // The ID for the synthetic object generated to account for class static overhead.
206ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddClassStaticsId(const mirror::Class* value) {
207ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU4(1 | PointerToLowMemUInt32(value));
208622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
209622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
210ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddJniGlobalRefId(jobject value) {
211ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU4(PointerToLowMemUInt32(value));
212622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
213622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
214ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddClassId(HprofClassObjectId value) {
215ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU4(value);
216622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
217622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
218ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddStringId(HprofStringId value) {
219ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU4(value);
220dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
221dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
2223a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void AddU1List(const uint8_t* values, size_t count) {
2233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HandleU1List(values, count);
2243a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    length_ += count;
2253a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2263a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void AddU2List(const uint16_t* values, size_t count) {
2273a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HandleU2List(values, count);
2283a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    length_ += count * sizeof(uint16_t);
2293a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2303a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void AddU4List(const uint32_t* values, size_t count) {
2313a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HandleU4List(values, count);
2323a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    length_ += count * sizeof(uint32_t);
2333a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
234ca71458862be8505330b7fd5649a062f31d143dcAndreas Gampe  virtual void UpdateU4(size_t offset, uint32_t new_value ATTRIBUTE_UNUSED) {
2353a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_LE(offset, length_ - 4);
2363a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2373a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void AddU8List(const uint64_t* values, size_t count) {
2383a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HandleU8List(values, count);
2393a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    length_ += count * sizeof(uint64_t);
2403a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
241622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
242ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddIdList(mirror::ObjectArray<mirror::Object>* values)
24390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
244ad466adf38db74a9840659626858196091151a64Mathieu Chartier    const int32_t length = values->GetLength();
245ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    for (int32_t i = 0; i < length; ++i) {
246ad466adf38db74a9840659626858196091151a64Mathieu Chartier      AddObjectId(values->GetWithoutChecks(i));
247ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    }
248622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
249622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
250ad466adf38db74a9840659626858196091151a64Mathieu Chartier  void AddUtf8String(const char* str) {
251622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes    // The terminating NUL character is NOT written.
252ad466adf38db74a9840659626858196091151a64Mathieu Chartier    AddU1List((const uint8_t*)str, strlen(str));
253622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
254622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
2553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t Length() const {
256dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    return length_;
257dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
258622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
2593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t SumLength() const {
2603a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return sum_length_;
261622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes  }
262dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
2633a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t MaxLength() const {
2643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return max_length_;
2653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
266dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
2673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe protected:
2683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual void HandleU1List(const uint8_t* values ATTRIBUTE_UNUSED,
2693a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe                            size_t count ATTRIBUTE_UNUSED) {
2703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual void HandleU2List(const uint16_t* values ATTRIBUTE_UNUSED,
2723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe                            size_t count ATTRIBUTE_UNUSED) {
2733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual void HandleU4List(const uint32_t* values ATTRIBUTE_UNUSED,
2753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe                            size_t count ATTRIBUTE_UNUSED) {
2763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual void HandleU8List(const uint64_t* values ATTRIBUTE_UNUSED,
2783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe                            size_t count ATTRIBUTE_UNUSED) {
2793a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual void HandleEndRecord() {
2813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
282dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
2833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t length_;      // Current record size.
2843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t sum_length_;  // Size of all data.
2853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  size_t max_length_;  // Maximum seen length.
2863a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  bool started_;       // Was StartRecord called?
287622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes};
288622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
2893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe// This keeps things buffered until flushed.
2903a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampeclass EndianOutputBuffered : public EndianOutput {
291622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes public:
2923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  explicit EndianOutputBuffered(size_t reserve_size) {
2933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_.reserve(reserve_size);
2943a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
2953a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual ~EndianOutputBuffered() {}
2963a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
2973a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void UpdateU4(size_t offset, uint32_t new_value) OVERRIDE {
2983a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_LE(offset, length_ - 4);
2993a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_[offset + 0] = static_cast<uint8_t>((new_value >> 24) & 0xFF);
3003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_[offset + 1] = static_cast<uint8_t>((new_value >> 16) & 0xFF);
3013a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_[offset + 2] = static_cast<uint8_t>((new_value >> 8)  & 0xFF);
3023a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_[offset + 3] = static_cast<uint8_t>((new_value >> 0)  & 0xFF);
303dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
304dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
3053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe protected:
3063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleU1List(const uint8_t* values, size_t count) OVERRIDE {
3073a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_EQ(length_, buffer_.size());
3083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_.insert(buffer_.end(), values, values + count);
3093a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3103a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleU2List(const uint16_t* values, size_t count) OVERRIDE {
3123a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_EQ(length_, buffer_.size());
3133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    for (size_t i = 0; i < count; ++i) {
3143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      uint16_t value = *values;
3153a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 8) & 0xFF));
3163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 0) & 0xFF));
3173a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      values++;
318dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
3193a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3203a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3213a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleU4List(const uint32_t* values, size_t count) OVERRIDE {
3223a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_EQ(length_, buffer_.size());
3233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    for (size_t i = 0; i < count; ++i) {
3243a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      uint32_t value = *values;
3253a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 24) & 0xFF));
3263a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 16) & 0xFF));
3273a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 8)  & 0xFF));
3283a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 0)  & 0xFF));
3293a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      values++;
330dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
331dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
332dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
3333a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleU8List(const uint64_t* values, size_t count) OVERRIDE {
3343a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_EQ(length_, buffer_.size());
3353a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    for (size_t i = 0; i < count; ++i) {
3363a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      uint64_t value = *values;
3373a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 56) & 0xFF));
3383a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 48) & 0xFF));
3393a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 40) & 0xFF));
3403a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 32) & 0xFF));
3413a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 24) & 0xFF));
3423a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 16) & 0xFF));
3433a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 8)  & 0xFF));
3443a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      buffer_.push_back(static_cast<uint8_t>((value >> 0)  & 0xFF));
3453a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      values++;
34600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
347ad466adf38db74a9840659626858196091151a64Mathieu Chartier  }
348dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
3493a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleEndRecord() OVERRIDE {
3503a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK_EQ(buffer_.size(), length_);
3513a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (kIsDebugBuild && started_) {
3523a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      uint32_t stored_length =
3533a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          static_cast<uint32_t>(buffer_[5]) << 24 |
3543a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          static_cast<uint32_t>(buffer_[6]) << 16 |
3553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          static_cast<uint32_t>(buffer_[7]) << 8 |
3563a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          static_cast<uint32_t>(buffer_[8]);
3573a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      DCHECK_EQ(stored_length, length_ - sizeof(uint8_t) - 2 * sizeof(uint32_t));
358ad466adf38db74a9840659626858196091151a64Mathieu Chartier    }
3593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HandleFlush(buffer_.data(), length_);
3603a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    buffer_.clear();
361ad466adf38db74a9840659626858196091151a64Mathieu Chartier  }
362dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
3633a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  virtual void HandleFlush(const uint8_t* buffer ATTRIBUTE_UNUSED, size_t length ATTRIBUTE_UNUSED) {
3643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  std::vector<uint8_t> buffer_;
3673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe};
3683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3693a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampeclass FileEndianOutput FINAL : public EndianOutputBuffered {
3703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe public:
3713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  FileEndianOutput(File* fp, size_t reserved_size)
3723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      : EndianOutputBuffered(reserved_size), fp_(fp), errors_(false) {
3733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK(fp != nullptr);
3743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  ~FileEndianOutput() {
3763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  bool Errors() {
3793a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return errors_;
3803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
3813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe protected:
3833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleFlush(const uint8_t* buffer, size_t length) OVERRIDE {
3843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (!errors_) {
3853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      errors_ = !fp_->WriteFully(buffer, length);
386ad466adf38db74a9840659626858196091151a64Mathieu Chartier    }
387ad466adf38db74a9840659626858196091151a64Mathieu Chartier  }
388ad466adf38db74a9840659626858196091151a64Mathieu Chartier
3893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe private:
3903a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  File* fp_;
3913a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  bool errors_;
3923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe};
3933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
3943a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampeclass NetStateEndianOutput FINAL : public EndianOutputBuffered {
3953a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe public:
3963a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  NetStateEndianOutput(JDWP::JdwpNetStateBase* net_state, size_t reserved_size)
3973a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      : EndianOutputBuffered(reserved_size), net_state_(net_state) {
3983a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    DCHECK(net_state != nullptr);
3993a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
4003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  ~NetStateEndianOutput() {}
4013a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
4023a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe protected:
4033a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void HandleFlush(const uint8_t* buffer, size_t length) OVERRIDE {
4043a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    std::vector<iovec> iov;
4053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    iov.push_back(iovec());
4063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    iov[0].iov_base = const_cast<void*>(reinterpret_cast<const void*>(buffer));
4073a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    iov[0].iov_len = length;
4083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    net_state_->WriteBufferedPacketLocked(iov);
4093a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
4103a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
4113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe private:
4123a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  JDWP::JdwpNetStateBase* net_state_;
4133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe};
4143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
415bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier#define __ output_->
4163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
417bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartierclass Hprof : public SingleRootVisitor {
4183a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe public:
4193a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  Hprof(const char* output_filename, int fd, bool direct_to_ddms)
4203a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      : filename_(output_filename),
4213a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        fd_(fd),
422c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier        direct_to_ddms_(direct_to_ddms) {
4233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    LOG(INFO) << "hprof: heap dump \"" << filename_ << "\" starting...";
4243a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
4253a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
4263a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void Dump()
427c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier    REQUIRES(Locks::mutator_lock_)
428c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier    REQUIRES(!Locks::heap_bitmap_lock_, !Locks::alloc_tracker_lock_) {
4298c2ff641294715864013737fdec57cdfd410270cMan Cao    {
4308c2ff641294715864013737fdec57cdfd410270cMan Cao      MutexLock mu(Thread::Current(), *Locks::alloc_tracker_lock_);
4318c2ff641294715864013737fdec57cdfd410270cMan Cao      if (Runtime::Current()->GetHeap()->IsAllocTrackingEnabled()) {
4328c2ff641294715864013737fdec57cdfd410270cMan Cao        PopulateAllocationTrackingTraces();
4338c2ff641294715864013737fdec57cdfd410270cMan Cao      }
4348c2ff641294715864013737fdec57cdfd410270cMan Cao    }
4358c2ff641294715864013737fdec57cdfd410270cMan Cao
4363a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // First pass to measure the size of the dump.
4373a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    size_t overall_size;
4383a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    size_t max_length;
439ad466adf38db74a9840659626858196091151a64Mathieu Chartier    {
4403a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      EndianOutput count_output;
441bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      output_ = &count_output;
442bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      ProcessHeap(false);
4433a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      overall_size = count_output.SumLength();
4443a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      max_length = count_output.MaxLength();
445bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      output_ = nullptr;
446ad466adf38db74a9840659626858196091151a64Mathieu Chartier    }
447dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
4483a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    bool okay;
4493a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (direct_to_ddms_) {
4503a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      if (kDirectStream) {
4513a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        okay = DumpToDdmsDirect(overall_size, max_length, CHUNK_TYPE("HPDS"));
4524303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe      } else {
4533a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        okay = DumpToDdmsBuffered(overall_size, max_length);
454dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      }
4553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else {
4563a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      okay = DumpToFile(overall_size, max_length);
457dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
458dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
459dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    if (okay) {
460c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier      const uint64_t duration = NanoTime() - start_ns_;
461c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier      LOG(INFO) << "hprof: heap dump completed (" << PrettySize(RoundUp(overall_size, KB))
462c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier                << ") in " << PrettyDuration(duration)
463c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier                << " objects " << total_objects_
464c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier                << " objects with stack traces " << total_objects_with_stack_trace_;
465dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
466dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
467622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
468622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes private:
46983c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartier  static void VisitObjectCallback(mirror::Object* obj, void* arg)
47090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
471ad466adf38db74a9840659626858196091151a64Mathieu Chartier    DCHECK(obj != nullptr);
472ad466adf38db74a9840659626858196091151a64Mathieu Chartier    DCHECK(arg != nullptr);
473bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    reinterpret_cast<Hprof*>(arg)->DumpHeapObject(obj);
474dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
475622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
476bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void DumpHeapObject(mirror::Object* obj)
47790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
4783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
479bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void DumpHeapClass(mirror::Class* klass)
48090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
481622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
482bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void DumpHeapArray(mirror::Array* obj, mirror::Class* klass)
48390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
4843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
485bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void DumpHeapInstanceObject(mirror::Object* obj, mirror::Class* klass)
48690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
4873a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
488bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void ProcessHeap(bool header_first)
48990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      REQUIRES(Locks::mutator_lock_) {
4903a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Reset current heap and object count.
4913a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    current_heap_ = HPROF_HEAP_DEFAULT;
4923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    objects_in_segment_ = 0;
4933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
4943a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (header_first) {
4958c2ff641294715864013737fdec57cdfd410270cMan Cao      ProcessHeader(true);
496bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      ProcessBody();
4973a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else {
498bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      ProcessBody();
4998c2ff641294715864013737fdec57cdfd410270cMan Cao      ProcessHeader(false);
5003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
5013a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
502622a6988351d77da0008142f4ce1ea447d838556Elliott Hughes
50390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  void ProcessBody() REQUIRES(Locks::mutator_lock_) {
504bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    Runtime* const runtime = Runtime::Current();
5053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Walk the roots and the heap.
506bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_->StartNewRecord(HPROF_TAG_HEAP_DUMP_SEGMENT, kHprofTime);
5073a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
508e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler    simple_roots_.clear();
509bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    runtime->VisitRoots(this);
510bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    runtime->VisitImageRoots(this);
511bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    runtime->GetHeap()->VisitObjectsPaused(VisitObjectCallback, this);
5123a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
513bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_->StartNewRecord(HPROF_TAG_HEAP_DUMP_END, kHprofTime);
514bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_->EndRecord();
5153a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
5163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
51790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  void ProcessHeader(bool string_first) REQUIRES(Locks::mutator_lock_) {
5183a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Write the header.
519bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    WriteFixedHeader();
5203a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Write the string and class tables, and any stack traces, to the header.
5213a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // (jhat requires that these appear before any of the data in the body that refers to them.)
5228c2ff641294715864013737fdec57cdfd410270cMan Cao    // jhat also requires the string table appear before class table and stack traces.
5238c2ff641294715864013737fdec57cdfd410270cMan Cao    // However, WriteStackTraces() can modify the string table, so it's necessary to call
5248c2ff641294715864013737fdec57cdfd410270cMan Cao    // WriteStringTable() last in the first pass, to compute the correct length of the output.
5258c2ff641294715864013737fdec57cdfd410270cMan Cao    if (string_first) {
5268c2ff641294715864013737fdec57cdfd410270cMan Cao      WriteStringTable();
5278c2ff641294715864013737fdec57cdfd410270cMan Cao    }
528bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    WriteClassTable();
529bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    WriteStackTraces();
5308c2ff641294715864013737fdec57cdfd410270cMan Cao    if (!string_first) {
5318c2ff641294715864013737fdec57cdfd410270cMan Cao      WriteStringTable();
5328c2ff641294715864013737fdec57cdfd410270cMan Cao    }
533bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_->EndRecord();
5343a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
5353a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
53690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  void WriteClassTable() SHARED_REQUIRES(Locks::mutator_lock_) {
5378c2ff641294715864013737fdec57cdfd410270cMan Cao    for (const auto& p : classes_) {
5388c2ff641294715864013737fdec57cdfd410270cMan Cao      mirror::Class* c = p.first;
5398c2ff641294715864013737fdec57cdfd410270cMan Cao      HprofClassSerialNumber sn = p.second;
540ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      CHECK(c != nullptr);
541bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      output_->StartNewRecord(HPROF_TAG_LOAD_CLASS, kHprofTime);
542dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // LOAD CLASS format:
543dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // U4: class serial number (always > 0)
544dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // ID: class object ID. We use the address of the class object structure as its ID.
545dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // U4: stack trace serial number
546dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // ID: class name string ID
5478c2ff641294715864013737fdec57cdfd410270cMan Cao      __ AddU4(sn);
5483a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddObjectId(c);
5498c2ff641294715864013737fdec57cdfd410270cMan Cao      __ AddStackTraceSerialNumber(LookupStackTraceSerialNumber(c));
5503a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddStringId(LookupClassNameId(c));
551dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
5520c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
5530c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
554bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void WriteStringTable() {
555ad466adf38db74a9840659626858196091151a64Mathieu Chartier    for (const std::pair<std::string, HprofStringId>& p : strings_) {
556ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const std::string& string = p.first;
557ad466adf38db74a9840659626858196091151a64Mathieu Chartier      const size_t id = p.second;
558dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
559bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      output_->StartNewRecord(HPROF_TAG_STRING, kHprofTime);
5600c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
561dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // STRING format:
562dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      // ID:  ID for this string
5632cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      // U1*: UTF8 characters for string (NOT null terminated)
564dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      //      (the record format encodes the length)
5653a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4(id);
5663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddUtf8String(string.c_str());
567dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
568dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
5690c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
570bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void StartNewHeapDumpSegment() {
571dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    // This flushes the old segment and starts a new one.
572bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_->StartNewRecord(HPROF_TAG_HEAP_DUMP_SEGMENT, kHprofTime);
573dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    objects_in_segment_ = 0;
574dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    // Starting a new HEAP_DUMP resets the heap to default.
575dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    current_heap_ = HPROF_HEAP_DEFAULT;
576dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
577dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
578bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void CheckHeapSegmentConstraints() {
579bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    if (objects_in_segment_ >= kMaxObjectsPerSegment || output_->Length() >= kMaxBytesPerSegment) {
580bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      StartNewHeapDumpSegment();
5813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
5823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
5833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
584bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void VisitRoot(mirror::Object* obj, const RootInfo& root_info)
58590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_);
5863a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  void MarkRootObject(const mirror::Object* obj, jobject jni_obj, HprofHeapTag heap_tag,
587bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier                      uint32_t thread_serial);
588dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
58990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  HprofClassObjectId LookupClassId(mirror::Class* c) SHARED_REQUIRES(Locks::mutator_lock_) {
590ad466adf38db74a9840659626858196091151a64Mathieu Chartier    if (c != nullptr) {
5918c2ff641294715864013737fdec57cdfd410270cMan Cao      auto it = classes_.find(c);
5928c2ff641294715864013737fdec57cdfd410270cMan Cao      if (it == classes_.end()) {
5938c2ff641294715864013737fdec57cdfd410270cMan Cao        // first time to see this class
5948c2ff641294715864013737fdec57cdfd410270cMan Cao        HprofClassSerialNumber sn = next_class_serial_number_++;
5958c2ff641294715864013737fdec57cdfd410270cMan Cao        classes_.Put(c, sn);
5968c2ff641294715864013737fdec57cdfd410270cMan Cao        // Make sure that we've assigned a string ID for this class' name
5978c2ff641294715864013737fdec57cdfd410270cMan Cao        LookupClassNameId(c);
5988c2ff641294715864013737fdec57cdfd410270cMan Cao      }
599ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    }
600ad466adf38db74a9840659626858196091151a64Mathieu Chartier    return PointerToLowMemUInt32(c);
601dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
602dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
6038c2ff641294715864013737fdec57cdfd410270cMan Cao  HprofStackTraceSerialNumber LookupStackTraceSerialNumber(const mirror::Object* obj)
60490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
6058c2ff641294715864013737fdec57cdfd410270cMan Cao    auto r = allocation_records_.find(obj);
6068c2ff641294715864013737fdec57cdfd410270cMan Cao    if (r == allocation_records_.end()) {
6078c2ff641294715864013737fdec57cdfd410270cMan Cao      return kHprofNullStackTrace;
6088c2ff641294715864013737fdec57cdfd410270cMan Cao    } else {
6098c2ff641294715864013737fdec57cdfd410270cMan Cao      const gc::AllocRecordStackTrace* trace = r->second;
6108c2ff641294715864013737fdec57cdfd410270cMan Cao      auto result = traces_.find(trace);
6118c2ff641294715864013737fdec57cdfd410270cMan Cao      CHECK(result != traces_.end());
6128c2ff641294715864013737fdec57cdfd410270cMan Cao      return result->second;
6138c2ff641294715864013737fdec57cdfd410270cMan Cao    }
6148c2ff641294715864013737fdec57cdfd410270cMan Cao  }
6158c2ff641294715864013737fdec57cdfd410270cMan Cao
61690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  HprofStringId LookupStringId(mirror::String* string) SHARED_REQUIRES(Locks::mutator_lock_) {
617dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    return LookupStringId(string->ToModifiedUtf8());
618dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
619dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
620dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  HprofStringId LookupStringId(const char* string) {
621dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    return LookupStringId(std::string(string));
622dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
623dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
624dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  HprofStringId LookupStringId(const std::string& string) {
625ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    auto it = strings_.find(string);
626dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    if (it != strings_.end()) {
627dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes      return it->second;
628dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    }
629dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    HprofStringId id = next_string_id_++;
630dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    strings_.Put(string, id);
631dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    return id;
632dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
633dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
63490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  HprofStringId LookupClassNameId(mirror::Class* c) SHARED_REQUIRES(Locks::mutator_lock_) {
635dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    return LookupStringId(PrettyDescriptor(c));
636dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  }
637dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
638bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  void WriteFixedHeader() {
6390c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // Write the file header.
6400c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // U1: NUL-terminated magic string.
6413a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    const char magic[] = "JAVA PROFILE 1.0.3";
6423a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1List(reinterpret_cast<const uint8_t*>(magic), sizeof(magic));
6433a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
6443280517651195602253ed92a2749964e96cad27eCalin Juravle    // U4: size of identifiers.  We're using addresses as IDs and our heap references are stored
6453280517651195602253ed92a2749964e96cad27eCalin Juravle    // as uint32_t.
6463280517651195602253ed92a2749964e96cad27eCalin Juravle    // Note of warning: hprof-conv hard-codes the size of identifiers to 4.
647575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe    static_assert(sizeof(mirror::HeapReference<mirror::Object>) == sizeof(uint32_t),
648575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe                  "Unexpected HeapReference size");
6493a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(sizeof(uint32_t));
6503a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
6510c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // The current time, in milliseconds since 0:00 GMT, 1/1/70.
6527b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes    timeval now;
6533a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    const uint64_t nowMs = (gettimeofday(&now, nullptr) < 0) ? 0 :
654ad466adf38db74a9840659626858196091151a64Mathieu Chartier        (uint64_t)now.tv_sec * 1000 + now.tv_usec / 1000;
6553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // TODO: It seems it would be correct to use U8.
6560c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // U4: high word of the 64-bit time.
6573a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(static_cast<uint32_t>(nowMs >> 32));
6580c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // U4: low word of the 64-bit time.
6593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(static_cast<uint32_t>(nowMs & 0xFFFFFFFF));
6600c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
6610c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
66290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier  void WriteStackTraces() SHARED_REQUIRES(Locks::mutator_lock_) {
663dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes    // Write a dummy stack trace record so the analysis tools don't freak out.
664bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_->StartNewRecord(HPROF_TAG_STACK_TRACE, kHprofTime);
6658c2ff641294715864013737fdec57cdfd410270cMan Cao    __ AddStackTraceSerialNumber(kHprofNullStackTrace);
6663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(kHprofNullThread);
6673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(0);    // no frames
6688c2ff641294715864013737fdec57cdfd410270cMan Cao
6698c2ff641294715864013737fdec57cdfd410270cMan Cao    // TODO: jhat complains "WARNING: Stack trace not found for serial # -1", but no trace should
6708c2ff641294715864013737fdec57cdfd410270cMan Cao    // have -1 as its serial number (as long as HprofStackTraceSerialNumber doesn't overflow).
6718c2ff641294715864013737fdec57cdfd410270cMan Cao    for (const auto& it : traces_) {
6728c2ff641294715864013737fdec57cdfd410270cMan Cao      const gc::AllocRecordStackTrace* trace = it.first;
6738c2ff641294715864013737fdec57cdfd410270cMan Cao      HprofStackTraceSerialNumber trace_sn = it.second;
6748c2ff641294715864013737fdec57cdfd410270cMan Cao      size_t depth = trace->GetDepth();
6758c2ff641294715864013737fdec57cdfd410270cMan Cao
6768c2ff641294715864013737fdec57cdfd410270cMan Cao      // First write stack frames of the trace
6778c2ff641294715864013737fdec57cdfd410270cMan Cao      for (size_t i = 0; i < depth; ++i) {
6788c2ff641294715864013737fdec57cdfd410270cMan Cao        const gc::AllocRecordStackTraceElement* frame = &trace->GetStackElement(i);
6798c2ff641294715864013737fdec57cdfd410270cMan Cao        ArtMethod* method = frame->GetMethod();
6808c2ff641294715864013737fdec57cdfd410270cMan Cao        CHECK(method != nullptr);
6818c2ff641294715864013737fdec57cdfd410270cMan Cao        output_->StartNewRecord(HPROF_TAG_STACK_FRAME, kHprofTime);
6828c2ff641294715864013737fdec57cdfd410270cMan Cao        // STACK FRAME format:
6838c2ff641294715864013737fdec57cdfd410270cMan Cao        // ID: stack frame ID. We use the address of the AllocRecordStackTraceElement object as its ID.
6848c2ff641294715864013737fdec57cdfd410270cMan Cao        // ID: method name string ID
6858c2ff641294715864013737fdec57cdfd410270cMan Cao        // ID: method signature string ID
6868c2ff641294715864013737fdec57cdfd410270cMan Cao        // ID: source file name string ID
6878c2ff641294715864013737fdec57cdfd410270cMan Cao        // U4: class serial number
6888c2ff641294715864013737fdec57cdfd410270cMan Cao        // U4: >0, line number; 0, no line information available; -1, unknown location
6898c2ff641294715864013737fdec57cdfd410270cMan Cao        auto frame_result = frames_.find(frame);
6908c2ff641294715864013737fdec57cdfd410270cMan Cao        CHECK(frame_result != frames_.end());
6918c2ff641294715864013737fdec57cdfd410270cMan Cao        __ AddU4(frame_result->second);
6928c2ff641294715864013737fdec57cdfd410270cMan Cao        __ AddStringId(LookupStringId(method->GetName()));
6938c2ff641294715864013737fdec57cdfd410270cMan Cao        __ AddStringId(LookupStringId(method->GetSignature().ToString()));
6948c2ff641294715864013737fdec57cdfd410270cMan Cao        const char* source_file = method->GetDeclaringClassSourceFile();
6958c2ff641294715864013737fdec57cdfd410270cMan Cao        if (source_file == nullptr) {
6968c2ff641294715864013737fdec57cdfd410270cMan Cao          source_file = "";
6978c2ff641294715864013737fdec57cdfd410270cMan Cao        }
6988c2ff641294715864013737fdec57cdfd410270cMan Cao        __ AddStringId(LookupStringId(source_file));
6998c2ff641294715864013737fdec57cdfd410270cMan Cao        auto class_result = classes_.find(method->GetDeclaringClass());
7008c2ff641294715864013737fdec57cdfd410270cMan Cao        CHECK(class_result != classes_.end());
7018c2ff641294715864013737fdec57cdfd410270cMan Cao        __ AddU4(class_result->second);
7028c2ff641294715864013737fdec57cdfd410270cMan Cao        __ AddU4(frame->ComputeLineNumber());
7038c2ff641294715864013737fdec57cdfd410270cMan Cao      }
7048c2ff641294715864013737fdec57cdfd410270cMan Cao
7058c2ff641294715864013737fdec57cdfd410270cMan Cao      // Then write the trace itself
7068c2ff641294715864013737fdec57cdfd410270cMan Cao      output_->StartNewRecord(HPROF_TAG_STACK_TRACE, kHprofTime);
7078c2ff641294715864013737fdec57cdfd410270cMan Cao      // STACK TRACE format:
7088c2ff641294715864013737fdec57cdfd410270cMan Cao      // U4: stack trace serial number. We use the address of the AllocRecordStackTrace object as its serial number.
7098c2ff641294715864013737fdec57cdfd410270cMan Cao      // U4: thread serial number. We use Thread::GetTid().
7108c2ff641294715864013737fdec57cdfd410270cMan Cao      // U4: number of frames
7118c2ff641294715864013737fdec57cdfd410270cMan Cao      // [ID]*: series of stack frame ID's
7128c2ff641294715864013737fdec57cdfd410270cMan Cao      __ AddStackTraceSerialNumber(trace_sn);
7138c2ff641294715864013737fdec57cdfd410270cMan Cao      __ AddU4(trace->GetTid());
7148c2ff641294715864013737fdec57cdfd410270cMan Cao      __ AddU4(depth);
7158c2ff641294715864013737fdec57cdfd410270cMan Cao      for (size_t i = 0; i < depth; ++i) {
7168c2ff641294715864013737fdec57cdfd410270cMan Cao        const gc::AllocRecordStackTraceElement* frame = &trace->GetStackElement(i);
7178c2ff641294715864013737fdec57cdfd410270cMan Cao        auto frame_result = frames_.find(frame);
7188c2ff641294715864013737fdec57cdfd410270cMan Cao        CHECK(frame_result != frames_.end());
7198c2ff641294715864013737fdec57cdfd410270cMan Cao        __ AddU4(frame_result->second);
7208c2ff641294715864013737fdec57cdfd410270cMan Cao      }
7218c2ff641294715864013737fdec57cdfd410270cMan Cao    }
7223a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
7233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7243a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  bool DumpToDdmsBuffered(size_t overall_size ATTRIBUTE_UNUSED, size_t max_length ATTRIBUTE_UNUSED)
72590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      REQUIRES(Locks::mutator_lock_) {
7263a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    LOG(FATAL) << "Unimplemented";
7273a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    UNREACHABLE();
7283a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        // Send the data off to DDMS.
7293a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        iovec iov[2];
7303a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        iov[0].iov_base = header_data_ptr_;
7313a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        iov[0].iov_len = header_data_size_;
7323a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        iov[1].iov_base = body_data_ptr_;
7333a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        iov[1].iov_len = body_data_size_;
7343a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    //        Dbg::DdmSendChunkV(CHUNK_TYPE("HPDS"), iov, 2);
7353a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
7363a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7373a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  bool DumpToFile(size_t overall_size, size_t max_length)
73890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      REQUIRES(Locks::mutator_lock_) {
7393a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Where exactly are we writing to?
7403a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    int out_fd;
7413a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (fd_ >= 0) {
7423a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      out_fd = dup(fd_);
7433a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      if (out_fd < 0) {
7443a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        ThrowRuntimeException("Couldn't dump heap; dup(%d) failed: %s", fd_, strerror(errno));
7453a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        return false;
7463a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      }
7473a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else {
7483a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      out_fd = open(filename_.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
7493a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      if (out_fd < 0) {
7503a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        ThrowRuntimeException("Couldn't dump heap; open(\"%s\") failed: %s", filename_.c_str(),
7513a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe                              strerror(errno));
7523a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        return false;
7533a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      }
7543a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
7553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7563a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    std::unique_ptr<File> file(new File(out_fd, filename_, true));
7573a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    bool okay;
7583a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    {
7593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      FileEndianOutput file_output(file.get(), max_length);
760bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      output_ = &file_output;
761bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      ProcessHeap(true);
7623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      okay = !file_output.Errors();
7633a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      if (okay) {
765c515f21dabd53e1b68bd2780fe86039d0dab49f8Andreas Gampe        // Check for expected size. Output is expected to be less-or-equal than first phase, see
766c515f21dabd53e1b68bd2780fe86039d0dab49f8Andreas Gampe        // b/23521263.
767c515f21dabd53e1b68bd2780fe86039d0dab49f8Andreas Gampe        DCHECK_LE(file_output.SumLength(), overall_size);
7683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      }
769bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      output_ = nullptr;
7703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
7713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (okay) {
7733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      okay = file->FlushCloseOrErase() == 0;
7743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else {
7753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      file->Erase();
7763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
7773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (!okay) {
7783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      std::string msg(StringPrintf("Couldn't dump heap; writing \"%s\" failed: %s",
7793a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe                                   filename_.c_str(), strerror(errno)));
7803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ThrowRuntimeException("%s", msg.c_str());
7813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      LOG(ERROR) << msg;
7823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
7833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return okay;
7853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
7863a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7873a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  bool DumpToDdmsDirect(size_t overall_size, size_t max_length, uint32_t chunk_type)
78890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      REQUIRES(Locks::mutator_lock_) {
7893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    CHECK(direct_to_ddms_);
7903a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    JDWP::JdwpState* state = Dbg::GetJdwpState();
7913a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    CHECK(state != nullptr);
7923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    JDWP::JdwpNetStateBase* net_state = state->netState;
7933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    CHECK(net_state != nullptr);
7943a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7953a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Hold the socket lock for the whole time since we want this to be atomic.
7963a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    MutexLock mu(Thread::Current(), *net_state->GetSocketLock());
7973a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
7983a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Prepare the Ddms chunk.
7993a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    constexpr size_t kChunkHeaderSize = kJDWPHeaderLen + 8;
8003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    uint8_t chunk_header[kChunkHeaderSize] = { 0 };
8013a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    state->SetupChunkHeader(chunk_type, overall_size, kChunkHeaderSize, chunk_header);
8023a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
8033a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Prepare the output and send the chunk header.
8043a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    NetStateEndianOutput net_output(net_state, max_length);
805bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_ = &net_output;
8063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    net_output.AddU1List(chunk_header, kChunkHeaderSize);
8073a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
8083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Write the dump.
809bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    ProcessHeap(true);
8103a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
811c515f21dabd53e1b68bd2780fe86039d0dab49f8Andreas Gampe    // Check for expected size. See DumpToFile for comment.
812c515f21dabd53e1b68bd2780fe86039d0dab49f8Andreas Gampe    DCHECK_LE(net_output.SumLength(), overall_size + kChunkHeaderSize);
813bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    output_ = nullptr;
8143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
8153a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return true;
8160c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
8170c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
8188c2ff641294715864013737fdec57cdfd410270cMan Cao  void PopulateAllocationTrackingTraces()
81990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      REQUIRES(Locks::mutator_lock_, Locks::alloc_tracker_lock_) {
8208c2ff641294715864013737fdec57cdfd410270cMan Cao    gc::AllocRecordObjectMap* records = Runtime::Current()->GetHeap()->GetAllocationRecords();
8218c2ff641294715864013737fdec57cdfd410270cMan Cao    CHECK(records != nullptr);
8228c2ff641294715864013737fdec57cdfd410270cMan Cao    HprofStackTraceSerialNumber next_trace_sn = kHprofNullStackTrace + 1;
8238c2ff641294715864013737fdec57cdfd410270cMan Cao    HprofStackFrameId next_frame_id = 0;
82442c3c33df8b6eefc4ba532f1981282510f109928Man Cao    size_t count = 0;
8258c2ff641294715864013737fdec57cdfd410270cMan Cao
8268c2ff641294715864013737fdec57cdfd410270cMan Cao    for (auto it = records->Begin(), end = records->End(); it != end; ++it) {
8278c2ff641294715864013737fdec57cdfd410270cMan Cao      const mirror::Object* obj = it->first.Read();
82842c3c33df8b6eefc4ba532f1981282510f109928Man Cao      if (obj == nullptr) {
82942c3c33df8b6eefc4ba532f1981282510f109928Man Cao        continue;
83042c3c33df8b6eefc4ba532f1981282510f109928Man Cao      }
83142c3c33df8b6eefc4ba532f1981282510f109928Man Cao      ++count;
83223428587d32361736d4c5e0ba7270c7602695a43Mathieu Chartier      const gc::AllocRecordStackTrace* trace = it->second.GetStackTrace();
8338c2ff641294715864013737fdec57cdfd410270cMan Cao
8348c2ff641294715864013737fdec57cdfd410270cMan Cao      // Copy the pair into a real hash map to speed up look up.
8358c2ff641294715864013737fdec57cdfd410270cMan Cao      auto records_result = allocation_records_.emplace(obj, trace);
8368c2ff641294715864013737fdec57cdfd410270cMan Cao      // The insertion should always succeed, i.e. no duplicate object pointers in "records"
8378c2ff641294715864013737fdec57cdfd410270cMan Cao      CHECK(records_result.second);
8388c2ff641294715864013737fdec57cdfd410270cMan Cao
8398c2ff641294715864013737fdec57cdfd410270cMan Cao      // Generate serial numbers for traces, and IDs for frames.
8408c2ff641294715864013737fdec57cdfd410270cMan Cao      auto traces_result = traces_.find(trace);
8418c2ff641294715864013737fdec57cdfd410270cMan Cao      if (traces_result == traces_.end()) {
8428c2ff641294715864013737fdec57cdfd410270cMan Cao        traces_.emplace(trace, next_trace_sn++);
8438c2ff641294715864013737fdec57cdfd410270cMan Cao        // only check frames if the trace is newly discovered
8448c2ff641294715864013737fdec57cdfd410270cMan Cao        for (size_t i = 0, depth = trace->GetDepth(); i < depth; ++i) {
8458c2ff641294715864013737fdec57cdfd410270cMan Cao          const gc::AllocRecordStackTraceElement* frame = &trace->GetStackElement(i);
8468c2ff641294715864013737fdec57cdfd410270cMan Cao          auto frames_result = frames_.find(frame);
8478c2ff641294715864013737fdec57cdfd410270cMan Cao          if (frames_result == frames_.end()) {
8488c2ff641294715864013737fdec57cdfd410270cMan Cao            frames_.emplace(frame, next_frame_id++);
8498c2ff641294715864013737fdec57cdfd410270cMan Cao          }
8508c2ff641294715864013737fdec57cdfd410270cMan Cao        }
8518c2ff641294715864013737fdec57cdfd410270cMan Cao      }
8528c2ff641294715864013737fdec57cdfd410270cMan Cao    }
8538c2ff641294715864013737fdec57cdfd410270cMan Cao    CHECK_EQ(traces_.size(), next_trace_sn - kHprofNullStackTrace - 1);
8548c2ff641294715864013737fdec57cdfd410270cMan Cao    CHECK_EQ(frames_.size(), next_frame_id);
855c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier    total_objects_with_stack_trace_ = count;
8568c2ff641294715864013737fdec57cdfd410270cMan Cao  }
8578c2ff641294715864013737fdec57cdfd410270cMan Cao
858dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  // If direct_to_ddms_ is set, "filename_" and "fd" will be ignored.
859dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  // Otherwise, "filename_" must be valid, though if "fd" >= 0 it will
860dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  // only be used for debug messages.
861dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  std::string filename_;
862dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  int fd_;
863dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  bool direct_to_ddms_;
8640c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
865c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier  uint64_t start_ns_ = NanoTime();
866dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
867c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier  EndianOutput* output_ = nullptr;
868bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier
869c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier  HprofHeapId current_heap_ = HPROF_HEAP_DEFAULT;  // Which heap we're currently dumping.
870c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier  size_t objects_in_segment_ = 0;
871dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
872c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier  size_t total_objects_ = 0u;
873c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier  size_t total_objects_with_stack_trace_ = 0u;
874c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier
875c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier  HprofStringId next_string_id_ = 0x400000;
876ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  SafeMap<std::string, HprofStringId> strings_;
877c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier  HprofClassSerialNumber next_class_serial_number_ = 1;
8788c2ff641294715864013737fdec57cdfd410270cMan Cao  SafeMap<mirror::Class*, HprofClassSerialNumber> classes_;
8798c2ff641294715864013737fdec57cdfd410270cMan Cao
8808c2ff641294715864013737fdec57cdfd410270cMan Cao  std::unordered_map<const gc::AllocRecordStackTrace*, HprofStackTraceSerialNumber,
8818c2ff641294715864013737fdec57cdfd410270cMan Cao                     gc::HashAllocRecordTypesPtr<gc::AllocRecordStackTrace>,
8828c2ff641294715864013737fdec57cdfd410270cMan Cao                     gc::EqAllocRecordTypesPtr<gc::AllocRecordStackTrace>> traces_;
8838c2ff641294715864013737fdec57cdfd410270cMan Cao  std::unordered_map<const gc::AllocRecordStackTraceElement*, HprofStackFrameId,
8848c2ff641294715864013737fdec57cdfd410270cMan Cao                     gc::HashAllocRecordTypesPtr<gc::AllocRecordStackTraceElement>,
8858c2ff641294715864013737fdec57cdfd410270cMan Cao                     gc::EqAllocRecordTypesPtr<gc::AllocRecordStackTraceElement>> frames_;
8868c2ff641294715864013737fdec57cdfd410270cMan Cao  std::unordered_map<const mirror::Object*, const gc::AllocRecordStackTrace*> allocation_records_;
887dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes
888e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler  // Set used to keep track of what simple root records we have already
889e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler  // emitted, to avoid emitting duplicate entries. The simple root records are
890e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler  // those that contain no other information than the root type and the object
891e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler  // id. A pair of root type and object id is packed into a uint64_t, with
892e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler  // the root type in the upper 32 bits and the object id in the lower 32
893e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler  // bits.
894e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler  std::unordered_set<uint64_t> simple_roots_;
895e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler
896e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  friend class GcRootVisitor;
897dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(Hprof);
898dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes};
8990c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
9003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampestatic HprofBasicType SignatureToBasicTypeAndSize(const char* sig, size_t* size_out) {
9010c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  char c = sig[0];
9020c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  HprofBasicType ret;
9030c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  size_t size;
9040c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
9050c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  switch (c) {
9063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case '[':
9073a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'L':
9083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_object;
9093a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 4;
9103a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
9113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'Z':
9123a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_boolean;
9133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 1;
9143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
9153a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'C':
9163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_char;
9173a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 2;
9183a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
9193a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'F':
9203a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_float;
9213a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 4;
9223a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
9233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'D':
9243a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_double;
9253a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 8;
9263a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
9273a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'B':
9283a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_byte;
9293a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 1;
9303a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
9313a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'S':
9323a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_short;
9333a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 2;
9343a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
9353a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'I':
9363a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_int;
9373a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 4;
9383a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
9393a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case 'J':
9403a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      ret = hprof_basic_long;
9413a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size = 8;
9423a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
9433a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    default:
9443a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      LOG(FATAL) << "UNREACHABLE";
9453a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      UNREACHABLE();
9460c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
9470c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
9483a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (size_out != nullptr) {
9493a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    *size_out = size;
9500c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
9510c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
9520c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  return ret;
9530c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson}
9540c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
9550c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson// Always called when marking objects, but only does
9560c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson// something when ctx->gc_scan_state_ is non-zero, which is usually
9570c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson// only true when marking the root set or unreachable
9580c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson// objects.  Used to add rootset references to obj.
9593a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampevoid Hprof::MarkRootObject(const mirror::Object* obj, jobject jni_obj, HprofHeapTag heap_tag,
960bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier                           uint32_t thread_serial) {
9613a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (heap_tag == 0) {
9623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return;
9633a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
9643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
965bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  CheckHeapSegmentConstraints();
9663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
9673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  switch (heap_tag) {
9683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // ID: object ID
9693a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_UNKNOWN:
9703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_STICKY_CLASS:
9713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_MONITOR_USED:
9723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_INTERNED_STRING:
9733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_DEBUGGER:
974e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler    case HPROF_ROOT_VM_INTERNAL: {
975e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler      uint64_t key = (static_cast<uint64_t>(heap_tag) << 32) | PointerToLowMemUInt32(obj);
976e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler      if (simple_roots_.insert(key).second) {
977e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler        __ AddU1(heap_tag);
978e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler        __ AddObjectId(obj);
979e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler      }
9803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
981e792305f5238df71a1928faf142cd35713aa3e47Richard Uhler    }
9823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
9833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // ID: object ID
9843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // ID: JNI global ref ID
9853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_JNI_GLOBAL:
9863a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(heap_tag);
9873a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddObjectId(obj);
9883a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddJniGlobalRefId(jni_obj);
9893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
9903a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
9913a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // ID: object ID
9923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // U4: thread serial number
9933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // U4: frame number in stack trace (-1 for empty)
9943a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_JNI_LOCAL:
9953a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_JNI_MONITOR:
9963a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_JAVA_FRAME:
9973a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(heap_tag);
9983a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddObjectId(obj);
9993a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4(thread_serial);
10003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4((uint32_t)-1);
10013a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
10023a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
10033a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // ID: object ID
10043a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // U4: thread serial number
10053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_NATIVE_STACK:
10063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_THREAD_BLOCK:
10073a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(heap_tag);
10083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddObjectId(obj);
10093a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4(thread_serial);
10103a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
10113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
10123a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // ID: thread object ID
10133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // U4: thread serial number
10143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // U4: stack trace serial number
10153a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_THREAD_OBJECT:
10163a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(heap_tag);
10173a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddObjectId(obj);
10183a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4(thread_serial);
10193a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4((uint32_t)-1);    // xxx
10203a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
10213a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
10223a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_CLASS_DUMP:
10233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_INSTANCE_DUMP:
10243a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_OBJECT_ARRAY_DUMP:
10253a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_PRIMITIVE_ARRAY_DUMP:
10263a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_HEAP_DUMP_INFO:
10273a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_PRIMITIVE_ARRAY_NODATA_DUMP:
10283a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      // Ignored.
10293a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
10303a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
10313a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_FINALIZING:
10323a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_ROOT_REFERENCE_CLEANUP:
10333a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    case HPROF_UNREACHABLE:
10343a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      LOG(FATAL) << "obsolete tag " << static_cast<int>(heap_tag);
10353a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      break;
10360c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
10370c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
1038dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes  ++objects_in_segment_;
10390c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson}
10400c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
1041e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier// Use for visiting the GcRoots held live by ArtFields, ArtMethods, and ClassLoaders.
1042e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartierclass GcRootVisitor {
1043e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier public:
1044e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  explicit GcRootVisitor(Hprof* hprof) : hprof_(hprof) {}
1045e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
1046e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  void operator()(mirror::Object* obj ATTRIBUTE_UNUSED,
1047e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier                  MemberOffset offset ATTRIBUTE_UNUSED,
1048e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier                  bool is_static ATTRIBUTE_UNUSED) const {}
1049e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
1050e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  // Note that these don't have read barriers. Its OK however since the GC is guaranteed to not be
1051e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  // running during the hprof dumping process.
1052e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const
1053e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
1054e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier    if (!root->IsNull()) {
1055e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier      VisitRoot(root);
1056e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier    }
1057e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  }
1058e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
1059e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
1060e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_) {
1061e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier    mirror::Object* obj = root->AsMirrorPtr();
1062e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier    // The two cases are either classes or dex cache arrays. If it is a dex cache array, then use
1063e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier    // VM internal. Otherwise the object is a declaring class of an ArtField or ArtMethod or a
1064e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier    // class from a ClassLoader.
1065e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier    hprof_->VisitRoot(obj, RootInfo(obj->IsClass() ? kRootStickyClass : kRootVMInternal));
1066e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  }
1067e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
1068e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
1069e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier private:
1070e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  Hprof* const hprof_;
1071e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier};
1072e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
1073bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid Hprof::DumpHeapObject(mirror::Object* obj) {
10743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // Ignore classes that are retired.
10753a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (obj->IsClass() && obj->AsClass()->IsRetired()) {
10763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    return;
10773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
10783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
1079c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier  ++total_objects_;
1080c9cd7ac27479c2fbc4c8451536ec628307f260cdMathieu Chartier
1081e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  GcRootVisitor visitor(this);
1082059ef3ddb2088f926ac452889e0953fdcd646a5eMathieu Chartier  obj->VisitReferences(visitor, VoidFunctor());
1083e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
1084e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier  gc::Heap* const heap = Runtime::Current()->GetHeap();
1085e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier  const gc::space::ContinuousSpace* const space = heap->FindContinuousSpaceFromObject(obj, true);
1086ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier  HprofHeapId heap_type = HPROF_HEAP_APP;
1087ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier  if (space != nullptr) {
1088ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier    if (space->IsZygoteSpace()) {
1089ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier      heap_type = HPROF_HEAP_ZYGOTE;
1090ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier    } else if (space->IsImageSpace()) {
1091ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier      heap_type = HPROF_HEAP_IMAGE;
1092ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier    }
1093e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier  } else {
1094e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier    const auto* los = heap->GetLargeObjectsSpace();
1095e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier    if (los->Contains(obj) && los->IsZygoteLargeObject(Thread::Current(), obj)) {
1096e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier      heap_type = HPROF_HEAP_ZYGOTE;
1097e7158116f345df6df73f0df7ebdc2be8e0e4f3e8Mathieu Chartier    }
1098ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier  }
1099bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  CheckHeapSegmentConstraints();
11000c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
1101ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier  if (heap_type != current_heap_) {
11020c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    HprofStringId nameId;
11030c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
11040c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // This object is in a different heap than the current one.
11050c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // Emit a HEAP_DUMP_INFO tag to change heaps.
11063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(HPROF_HEAP_DUMP_INFO);
11073a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(static_cast<uint32_t>(heap_type));   // uint32_t: heap type
1108ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier    switch (heap_type) {
11090c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    case HPROF_HEAP_APP:
11100c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      nameId = LookupStringId("app");
11110c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      break;
11120c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    case HPROF_HEAP_ZYGOTE:
11130c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      nameId = LookupStringId("zygote");
11140c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      break;
1115ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier    case HPROF_HEAP_IMAGE:
1116ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier      nameId = LookupStringId("image");
1117ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier      break;
11180c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    default:
11190c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      // Internal error
11200c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      LOG(ERROR) << "Unexpected desiredHeap";
11210c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      nameId = LookupStringId("<ILLEGAL>");
11220c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      break;
11230c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    }
11243a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddStringId(nameId);
1125ae1ad009f7e531aaf95ffbc080a4ad8769c1d4d0Mathieu Chartier    current_heap_ = heap_type;
11260c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  }
11270c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
11282dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Class* c = obj->GetClass();
11293a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (c == nullptr) {
11302cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    // This object will bother HprofReader, because it has a null
11310c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // class, so just don't dump it. It could be
11320c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // gDvm.unlinkedJavaLangClass or it could be an object just
11330c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    // allocated which hasn't been initialized yet.
11340c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson  } else {
11350c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    if (obj->IsClass()) {
1136bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      DumpHeapClass(obj->AsClass());
11373a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else if (c->IsArrayClass()) {
1138bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      DumpHeapArray(obj->AsArray(), c);
11393a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else {
1140bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      DumpHeapInstanceObject(obj, c);
11413a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
11423a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
11430c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
11443a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  ++objects_in_segment_;
11453a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe}
11460c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
1147bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid Hprof::DumpHeapClass(mirror::Class* klass) {
1148ca068b2385ba160367d1e7fd123317b851b99390Sebastien Hertz  if (!klass->IsLoaded() && !klass->IsErroneous()) {
1149ca068b2385ba160367d1e7fd123317b851b99390Sebastien Hertz    // Class is allocated but not yet loaded: we cannot access its fields or super class.
1150ca068b2385ba160367d1e7fd123317b851b99390Sebastien Hertz    return;
1151ca068b2385ba160367d1e7fd123317b851b99390Sebastien Hertz  }
1152a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier  const size_t num_static_fields = klass->NumStaticFields();
1153a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier  // Total class size including embedded IMT, embedded vtable, and static fields.
1154a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier  const size_t class_size = klass->GetClassSize();
1155a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier  // Class size excluding static fields (relies on reference fields being the first static fields).
1156a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier  const size_t class_size_without_overhead = sizeof(mirror::Class);
1157a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier  CHECK_LE(class_size_without_overhead, class_size);
1158a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier  const size_t overhead_size = class_size - class_size_without_overhead;
1159a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier
1160a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier  if (overhead_size != 0) {
11613a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Create a byte array to reflect the allocation of the
11623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // StaticField array at the end of this class.
11633a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
11643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddClassStaticsId(klass);
11658c2ff641294715864013737fdec57cdfd410270cMan Cao    __ AddStackTraceSerialNumber(LookupStackTraceSerialNumber(klass));
1166a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier    __ AddU4(overhead_size);
11673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(hprof_basic_byte);
1168a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier    for (size_t i = 0; i < overhead_size; ++i) {
11693a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(0);
11703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
11713a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
11720c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
11733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddU1(HPROF_CLASS_DUMP);
11743a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddClassId(LookupClassId(klass));
11758c2ff641294715864013737fdec57cdfd410270cMan Cao  __ AddStackTraceSerialNumber(LookupStackTraceSerialNumber(klass));
11763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddClassId(LookupClassId(klass->GetSuperClass()));
11773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddObjectId(klass->GetClassLoader());
11783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddObjectId(nullptr);    // no signer
11793a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddObjectId(nullptr);    // no prot domain
11803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddObjectId(nullptr);    // reserved
11813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddObjectId(nullptr);    // reserved
11823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (klass->IsClassClass()) {
11833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // ClassObjects have their static fields appended, so aren't all the same size.
11843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // But they're at least this size.
1185a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier    __ AddU4(class_size_without_overhead);  // instance size
11860ce43539b3bbade7d95482c4da0126a54d5bcba9Jeff Hao  } else if (klass->IsStringClass()) {
11870ce43539b3bbade7d95482c4da0126a54d5bcba9Jeff Hao    // Strings are variable length with character data at the end like arrays.
11880ce43539b3bbade7d95482c4da0126a54d5bcba9Jeff Hao    // This outputs the size of an empty string.
11890ce43539b3bbade7d95482c4da0126a54d5bcba9Jeff Hao    __ AddU4(sizeof(mirror::String));
11900ce43539b3bbade7d95482c4da0126a54d5bcba9Jeff Hao  } else if (klass->IsArrayClass() || klass->IsPrimitive()) {
11913a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(0);
11923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  } else {
11933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(klass->GetObjectSize());  // instance size
11943a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
11953a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
11963a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddU2(0);  // empty const pool
11970c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
11983a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // Static fields
1199a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier  if (overhead_size == 0) {
1200a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier    __ AddU2(static_cast<uint16_t>(0));
12013a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  } else {
1202a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier    __ AddU2(static_cast<uint16_t>(num_static_fields + 1));
1203a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier    __ AddStringId(LookupStringId(kClassOverheadName));
12043a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(hprof_basic_object);
12053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddClassStaticsId(klass);
12063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
1207a6d3a7ef8e648e8a65b38ea0bc475fad1d1fc105Mathieu Chartier    for (size_t i = 0; i < num_static_fields; ++i) {
1208c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      ArtField* f = klass->GetStaticField(i);
12093a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
12103a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size_t size;
12113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
12123a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddStringId(LookupStringId(f->GetName()));
12133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1(t);
121415f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      switch (t) {
121515f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_byte:
1216ff38c04b88e86bffdd520bc1863d05334ada6c94Mathieu Chartier          __ AddU1(f->GetByte(klass));
12173a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          break;
121815f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_boolean:
121915f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier          __ AddU1(f->GetBoolean(klass));
122015f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier          break;
122115f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_char:
1222ff38c04b88e86bffdd520bc1863d05334ada6c94Mathieu Chartier          __ AddU2(f->GetChar(klass));
12233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          break;
122415f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_short:
122515f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier          __ AddU2(f->GetShort(klass));
122615f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier          break;
122715f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_float:
122815f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_int:
122915f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_object:
12303a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          __ AddU4(f->Get32(klass));
12313a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          break;
123215f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_double:
123315f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        case hprof_basic_long:
12343a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          __ AddU8(f->Get64(klass));
12353a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          break;
12363a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        default:
12373a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          LOG(FATAL) << "Unexpected size " << size;
12383a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe          UNREACHABLE();
12390c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      }
12403a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
12413a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
12423a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
12433a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // Instance fields for this class (no superclass fields)
12447c1f53e4253e6acff5e76f00e6bf666518068c4dMathieu Chartier  int iFieldCount = klass->NumInstanceFields();
1245848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  if (klass->IsStringClass()) {
1246848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU2((uint16_t)iFieldCount + 1);
1247848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  } else {
1248848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU2((uint16_t)iFieldCount);
1249848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  }
12503a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  for (int i = 0; i < iFieldCount; ++i) {
1251c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    ArtField* f = klass->GetInstanceField(i);
12523a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddStringId(LookupStringId(f->GetName()));
12533a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), nullptr);
12543a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(t);
12553a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
1256848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  // Add native value character array for strings.
1257848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  if (klass->IsStringClass()) {
1258848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddStringId(LookupStringId("value"));
1259848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU1(hprof_basic_object);
1260848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  }
12613a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe}
12623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
1263bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid Hprof::DumpHeapArray(mirror::Array* obj, mirror::Class* klass) {
12643a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  uint32_t length = obj->GetLength();
12650c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
12663a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (obj->IsObjectArray()) {
12673a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // obj is an object array.
12683a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(HPROF_OBJECT_ARRAY_DUMP);
12690c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
12703a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddObjectId(obj);
12718c2ff641294715864013737fdec57cdfd410270cMan Cao    __ AddStackTraceSerialNumber(LookupStackTraceSerialNumber(obj));
12723a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(length);
12733a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddClassId(LookupClassId(klass));
12740c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
12752cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    // Dump the elements, which are always objects or null.
12763a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddIdList(obj->AsObjectArray<mirror::Object>());
12773a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  } else {
12783a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    size_t size;
12793a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    HprofBasicType t = SignatureToBasicTypeAndSize(
12803a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        Primitive::Descriptor(klass->GetComponentType()->GetPrimitiveType()), &size);
12813a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
12823a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // obj is a primitive array.
12833a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
12843a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
12853a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddObjectId(obj);
12868c2ff641294715864013737fdec57cdfd410270cMan Cao    __ AddStackTraceSerialNumber(LookupStackTraceSerialNumber(obj));
12873a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU4(length);
12883a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    __ AddU1(t);
12893a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
12903a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    // Dump the raw, packed element values.
12913a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    if (size == 1) {
12923a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU1List(reinterpret_cast<const uint8_t*>(obj->GetRawData(sizeof(uint8_t), 0)), length);
12933a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else if (size == 2) {
12943a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU2List(reinterpret_cast<const uint16_t*>(obj->GetRawData(sizeof(uint16_t), 0)), length);
12953a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else if (size == 4) {
12963a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU4List(reinterpret_cast<const uint32_t*>(obj->GetRawData(sizeof(uint32_t), 0)), length);
12973a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    } else if (size == 8) {
12983a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      __ AddU8List(reinterpret_cast<const uint64_t*>(obj->GetRawData(sizeof(uint64_t), 0)), length);
12993a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    }
13003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  }
13013a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe}
13023a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
1303bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid Hprof::DumpHeapInstanceObject(mirror::Object* obj, mirror::Class* klass) {
13043a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // obj is an instance object.
13053a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddU1(HPROF_INSTANCE_DUMP);
13063a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddObjectId(obj);
13078c2ff641294715864013737fdec57cdfd410270cMan Cao  __ AddStackTraceSerialNumber(LookupStackTraceSerialNumber(obj));
13083a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddClassId(LookupClassId(klass));
13093a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
13103a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // Reserve some space for the length of the instance data, which we won't
13113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  // know until we're done writing it.
1312bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  size_t size_patch_offset = output_->Length();
13133a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  __ AddU4(0x77777777);
13143a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
131507d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier  // What we will use for the string value if the object is a string.
131607d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier  mirror::Object* string_value = nullptr;
131707d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier
131807d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier  // Write the instance data;  fields for this class, followed by super class fields, and so on.
13197c1f53e4253e6acff5e76f00e6bf666518068c4dMathieu Chartier  do {
132007d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier    const size_t instance_fields = klass->NumInstanceFields();
132107d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier    for (size_t i = 0; i < instance_fields; ++i) {
1322c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      ArtField* f = klass->GetInstanceField(i);
13233a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe      size_t size;
132407d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier      HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
132515f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      switch (t) {
132615f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_byte:
1327ff38c04b88e86bffdd520bc1863d05334ada6c94Mathieu Chartier        __ AddU1(f->GetByte(obj));
132815f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        break;
132915f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_boolean:
133015f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        __ AddU1(f->GetBoolean(obj));
133115f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        break;
133215f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_char:
1333ff38c04b88e86bffdd520bc1863d05334ada6c94Mathieu Chartier        __ AddU2(f->GetChar(obj));
133415f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        break;
133515f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_short:
133615f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        __ AddU2(f->GetShort(obj));
133715f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        break;
133815f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_float:
133915f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_int:
134015f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_object:
13413a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        __ AddU4(f->Get32(obj));
134215f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        break;
134315f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_double:
134415f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier      case hprof_basic_long:
13453a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe        __ AddU8(f->Get64(obj));
134615f345cdfaebe480de6387b67d4be4eb5f106870Mathieu Chartier        break;
13470c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson      }
13480c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson    }
134907d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier    // Add value field for String if necessary.
135007d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier    if (klass->IsStringClass()) {
135107d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier      mirror::String* s = obj->AsString();
135207d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier      if (s->GetLength() == 0) {
135307d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier        // If string is empty, use an object-aligned address within the string for the value.
135407d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier        string_value = reinterpret_cast<mirror::Object*>(
135507d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier            reinterpret_cast<uintptr_t>(s) + kObjectAlignment);
135607d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier      } else {
135707d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier        string_value = reinterpret_cast<mirror::Object*>(s->GetValue());
135807d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier      }
135907d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier      __ AddObjectId(string_value);
136007d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier    }
13613a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe
13623a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe    klass = klass->GetSuperClass();
13637c1f53e4253e6acff5e76f00e6bf666518068c4dMathieu Chartier  } while (klass != nullptr);
13640c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
136507d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier  // Patch the instance field length.
136607d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier  __ UpdateU4(size_patch_offset, output_->Length() - (size_patch_offset + 4));
136707d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier
1368848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  // Output native value character array for strings.
136907d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier  CHECK_EQ(obj->IsString(), string_value != nullptr);
137007d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier  if (string_value != nullptr) {
1371848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    mirror::String* s = obj->AsString();
1372848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
137307d7eab545916ef0602afddae162f5b6b1a68b7dMathieu Chartier    __ AddObjectId(string_value);
13748c2ff641294715864013737fdec57cdfd410270cMan Cao    __ AddStackTraceSerialNumber(LookupStackTraceSerialNumber(obj));
1375848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU4(s->GetLength());
1376848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU1(hprof_basic_char);
1377848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    __ AddU2List(s->GetValue(), s->GetLength());
1378848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  }
13790c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson}
13800c54ac102a3c489d284a8db5d91189da5b455c40Jesse Wilson
1381bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid Hprof::VisitRoot(mirror::Object* obj, const RootInfo& info) {
13820b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson  static const HprofHeapTag xlate[] = {
13830b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_UNKNOWN,
13840b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_JNI_GLOBAL,
13850b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_JNI_LOCAL,
13860b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_JAVA_FRAME,
13870b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_NATIVE_STACK,
13880b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_STICKY_CLASS,
13890b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_THREAD_BLOCK,
13900b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_MONITOR_USED,
13910b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_THREAD_OBJECT,
13920b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_INTERNED_STRING,
13930b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_FINALIZING,
13940b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_DEBUGGER,
13950b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_REFERENCE_CLEANUP,
13960b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_VM_INTERNAL,
13970b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    HPROF_ROOT_JNI_MONITOR,
13980b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson  };
1399e34fa1df67fbe0173b4ea9abddcc3ae3d0537037Mathieu Chartier  CHECK_LT(info.GetType(), sizeof(xlate) / sizeof(HprofHeapTag));
14003a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  if (obj == nullptr) {
14010b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson    return;
14020b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson  }
1403bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier  MarkRootObject(obj, 0, xlate[info.GetType()], info.GetThreadId());
1404c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson}
1405c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson
1406dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes// If "direct_to_ddms" is true, the other arguments are ignored, and data is
1407dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes// sent directly to DDMS.
1408dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes// If "fd" is >= 0, the output will be written to that file descriptor.
1409dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughes// Otherwise, "filename" is used to create an output file.
1410dcfdd2b03af29dcaf234d062a79acb919f130435Elliott Hughesvoid DumpHeap(const char* filename, int fd, bool direct_to_ddms) {
14113a91309c30a7575776526ffe6e9a46dc648a59feAndreas Gampe  CHECK(filename != nullptr);
14120b075f18e69959f5afbe6d815a766df082ec99dfJesse Wilson
14132cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi  Thread* self = Thread::Current();
14142cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi  gc::Heap* heap = Runtime::Current()->GetHeap();
14152cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi  if (heap->IsGcConcurrentAndMoving()) {
14162cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi    // Need to take a heap dump while GC isn't running. See the
14172cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi    // comment in Heap::VisitObjects().
14182cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi    heap->IncrementDisableMovingGC(self);
14192cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi  }
14204f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier  {
14214f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    ScopedSuspendAll ssa(__FUNCTION__, true /* long suspend */);
14224f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    Hprof hprof(filename, fd, direct_to_ddms);
14234f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier    hprof.Dump();
14244f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier  }
14252cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi  if (heap->IsGcConcurrentAndMoving()) {
14262cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi    heap->DecrementDisableMovingGC(self);
14272cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi  }
1428c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson}
1429c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson
1430ad466adf38db74a9840659626858196091151a64Mathieu Chartier}  // namespace hprof
1431c4824e60fef6cb9fdf0f8442408338f4141e09deJesse Wilson}  // namespace art
1432