blob: 7378ec9f5b6dbe25d2fdac03a6ab579f691664be [file] [log] [blame]
Jesse Wilsonc4824e62011-11-01 14:39:04 -04001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef HPROF_HPROF_H_
17#define HPROF_HPROF_H_
18
19#include <stdio.h>
20#include "globals.h"
21#include "file.h"
22#include "object.h"
Jesse Wilson3aa66fd2011-11-08 20:53:40 -050023#include "unordered_map.h"
24#include "unordered_set.h"
Jesse Wilson0c54ac12011-11-09 15:14:05 -050025#include "thread_list.h"
Jesse Wilsonc4824e62011-11-01 14:39:04 -040026
27namespace art {
28
29namespace hprof {
30
31#define HPROF_ID_SIZE (sizeof (uint32_t))
32
33#define UNIQUE_ERROR() \
34 -((((uintptr_t)__func__) << 16 | __LINE__) & (0x7fffffff))
35
36#define HPROF_TIME 0
37#define HPROF_NULL_STACK_TRACE 0
38#define HPROF_NULL_THREAD 0
39
Jesse Wilson0c54ac12011-11-09 15:14:05 -050040#define U2_TO_BUF_BE(buf, offset, value) \
41 do { \
42 unsigned char *buf_ = (unsigned char *)(buf); \
43 int offset_ = (int)(offset); \
44 uint16_t value_ = (uint16_t)(value); \
45 buf_[offset_ + 0] = (unsigned char)(value_ >> 8); \
46 buf_[offset_ + 1] = (unsigned char)(value_ ); \
47 } while (0)
48
49#define U4_TO_BUF_BE(buf, offset, value) \
50 do { \
51 unsigned char *buf_ = (unsigned char *)(buf); \
52 int offset_ = (int)(offset); \
53 uint32_t value_ = (uint32_t)(value); \
54 buf_[offset_ + 0] = (unsigned char)(value_ >> 24); \
55 buf_[offset_ + 1] = (unsigned char)(value_ >> 16); \
56 buf_[offset_ + 2] = (unsigned char)(value_ >> 8); \
57 buf_[offset_ + 3] = (unsigned char)(value_ ); \
58 } while (0)
59
60#define U8_TO_BUF_BE(buf, offset, value) \
61 do { \
62 unsigned char *buf_ = (unsigned char *)(buf); \
63 int offset_ = (int)(offset); \
64 uint64_t value_ = (uint64_t)(value); \
65 buf_[offset_ + 0] = (unsigned char)(value_ >> 56); \
66 buf_[offset_ + 1] = (unsigned char)(value_ >> 48); \
67 buf_[offset_ + 2] = (unsigned char)(value_ >> 40); \
68 buf_[offset_ + 3] = (unsigned char)(value_ >> 32); \
69 buf_[offset_ + 4] = (unsigned char)(value_ >> 24); \
70 buf_[offset_ + 5] = (unsigned char)(value_ >> 16); \
71 buf_[offset_ + 6] = (unsigned char)(value_ >> 8); \
72 buf_[offset_ + 7] = (unsigned char)(value_ ); \
73 } while (0)
74
Jesse Wilson3aa66fd2011-11-08 20:53:40 -050075typedef uint32_t HprofId;
76typedef HprofId HprofStringId;
77typedef HprofId HprofObjectId;
78typedef HprofId HprofClassObjectId;
79typedef std::tr1::unordered_set<Class*, ObjectIdentityHash> ClassSet;
80typedef std::tr1::unordered_set<Class*, ObjectIdentityHash>::iterator ClassSetIterator;
81typedef std::tr1::unordered_map<std::string, size_t> StringMap;
82typedef std::tr1::unordered_map<std::string, size_t>::iterator StringMapIterator;
Jesse Wilsonc4824e62011-11-01 14:39:04 -040083
Jesse Wilson3aa66fd2011-11-08 20:53:40 -050084enum HprofBasicType {
Jesse Wilson0b075f12011-11-09 10:57:41 -050085 hprof_basic_object = 2,
86 hprof_basic_boolean = 4,
87 hprof_basic_char = 5,
88 hprof_basic_float = 6,
89 hprof_basic_double = 7,
90 hprof_basic_byte = 8,
91 hprof_basic_short = 9,
92 hprof_basic_int = 10,
93 hprof_basic_long = 11,
Jesse Wilsonc4824e62011-11-01 14:39:04 -040094};
95
Jesse Wilson3aa66fd2011-11-08 20:53:40 -050096enum HprofTag {
Jesse Wilson0b075f12011-11-09 10:57:41 -050097 HPROF_TAG_STRING = 0x01,
98 HPROF_TAG_LOAD_CLASS = 0x02,
99 HPROF_TAG_UNLOAD_CLASS = 0x03,
100 HPROF_TAG_STACK_FRAME = 0x04,
101 HPROF_TAG_STACK_TRACE = 0x05,
102 HPROF_TAG_ALLOC_SITES = 0x06,
103 HPROF_TAG_HEAP_SUMMARY = 0x07,
104 HPROF_TAG_START_THREAD = 0x0A,
105 HPROF_TAG_END_THREAD = 0x0B,
106 HPROF_TAG_HEAP_DUMP = 0x0C,
107 HPROF_TAG_HEAP_DUMP_SEGMENT = 0x1C,
108 HPROF_TAG_HEAP_DUMP_END = 0x2C,
109 HPROF_TAG_CPU_SAMPLES = 0x0D,
110 HPROF_TAG_CONTROL_SETTINGS = 0x0E,
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400111};
112
Jesse Wilson0b075f12011-11-09 10:57:41 -0500113// Values for the first byte of HEAP_DUMP and HEAP_DUMP_SEGMENT records:
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500114enum HprofHeapTag {
Jesse Wilson0b075f12011-11-09 10:57:41 -0500115 /* standard */
116 HPROF_ROOT_UNKNOWN = 0xFF,
117 HPROF_ROOT_JNI_GLOBAL = 0x01,
118 HPROF_ROOT_JNI_LOCAL = 0x02,
119 HPROF_ROOT_JAVA_FRAME = 0x03,
120 HPROF_ROOT_NATIVE_STACK = 0x04,
121 HPROF_ROOT_STICKY_CLASS = 0x05,
122 HPROF_ROOT_THREAD_BLOCK = 0x06,
123 HPROF_ROOT_MONITOR_USED = 0x07,
124 HPROF_ROOT_THREAD_OBJECT = 0x08,
125 HPROF_CLASS_DUMP = 0x20,
126 HPROF_INSTANCE_DUMP = 0x21,
127 HPROF_OBJECT_ARRAY_DUMP = 0x22,
128 HPROF_PRIMITIVE_ARRAY_DUMP = 0x23,
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400129
Jesse Wilson0b075f12011-11-09 10:57:41 -0500130 /* Android */
131 HPROF_HEAP_DUMP_INFO = 0xfe,
132 HPROF_ROOT_INTERNED_STRING = 0x89,
133 HPROF_ROOT_FINALIZING = 0x8a, /* obsolete */
134 HPROF_ROOT_DEBUGGER = 0x8b,
135 HPROF_ROOT_REFERENCE_CLEANUP = 0x8c, /* obsolete */
136 HPROF_ROOT_VM_INTERNAL = 0x8d,
137 HPROF_ROOT_JNI_MONITOR = 0x8e,
138 HPROF_UNREACHABLE = 0x90, /* obsolete */
139 HPROF_PRIMITIVE_ARRAY_NODATA_DUMP = 0xc3,
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400140};
141
Jesse Wilson0b075f12011-11-09 10:57:41 -0500142// Represents a top-level hprof record, whose serialized format is:
143// U1 TAG: denoting the type of the record
144// U4 TIME: number of microseconds since the time stamp in the header
145// U4 LENGTH: number of bytes that follow this uint32_t field and belong to this record
146// U1* BODY: as many bytes as specified in the above uint32_t field
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500147class HprofRecord {
Jesse Wilson0b075f12011-11-09 10:57:41 -0500148 public:
149 int Flush(FILE *fp);
150 int AddU1(uint8_t value);
151 int AddU2(uint16_t value);
152 int AddU4(uint32_t value);
153 int AddU8(uint64_t value);
154 int AddId(HprofObjectId value);
155 int AddU1List(const uint8_t *values, size_t numValues);
156 int AddU2List(const uint16_t *values, size_t numValues);
157 int AddU4List(const uint32_t *values, size_t numValues);
158 int AddU8List(const uint64_t *values, size_t numValues);
159 int AddIdList(const HprofObjectId *values, size_t numValues);
160 int AddUtf8String(const char *str);
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500161
Jesse Wilson0b075f12011-11-09 10:57:41 -0500162 unsigned char *body_;
163 uint32_t time_;
164 uint32_t length_;
165 size_t alloc_length_;
166 uint8_t tag_;
167 bool dirty_;
Jesse Wilson0c54ac12011-11-09 15:14:05 -0500168
169 private:
170 int GuaranteeRecordAppend(size_t nmore);
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400171};
172
173enum HprofHeapId {
Jesse Wilson0b075f12011-11-09 10:57:41 -0500174 HPROF_HEAP_DEFAULT = 0,
175 HPROF_HEAP_ZYGOTE = 'Z',
176 HPROF_HEAP_APP = 'A'
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400177};
178
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500179class Hprof {
Jesse Wilson0b075f12011-11-09 10:57:41 -0500180 public:
181 Hprof(const char *outputFileName, int fd, bool writeHeader, bool directToDdms);
182 ~Hprof();
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500183
Jesse Wilson0b075f12011-11-09 10:57:41 -0500184 void VisitRoot(const Object* obj);
185 int DumpHeapObject(const Object *obj);
186 bool Finish();
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500187
Jesse Wilson0b075f12011-11-09 10:57:41 -0500188 private:
189 int DumpClasses();
190 int DumpStrings();
191 int StartNewRecord(uint8_t tag, uint32_t time);
192 int FlushCurrentRecord();
193 int MarkRootObject(const Object *obj, jobject jniObj);
194 HprofClassObjectId LookupClassId(Class* clazz);
195 HprofStringId LookupStringId(String* string);
196 HprofStringId LookupStringId(const char* string);
197 HprofStringId LookupStringId(std::string string);
198 HprofStringId LookupClassNameId(Class* clazz);
Jesse Wilson0c54ac12011-11-09 15:14:05 -0500199 static HprofBasicType SignatureToBasicTypeAndSize(const char *sig, size_t *sizeOut);
200 static HprofBasicType PrimitiveToBasicTypeAndSize(Primitive::Type prim, size_t *sizeOut);
201 static int StackTraceSerialNumber(const void *obj);
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500202
Jesse Wilson0b075f12011-11-09 10:57:41 -0500203 // current_record_ *must* be first so that we can cast from a context to a record.
204 HprofRecord current_record_;
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400205
Jesse Wilson0b075f12011-11-09 10:57:41 -0500206 uint32_t gc_thread_serial_number_;
207 uint8_t gc_scan_state_;
208 HprofHeapId current_heap_; // which heap we're currently emitting
209 size_t objects_in_segment_;
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400210
Jesse Wilson0b075f12011-11-09 10:57:41 -0500211 // If direct_to_ddms_ is set, "file_name_" and "fd" will be ignored.
212 // Otherwise, "file_name_" must be valid, though if "fd" >= 0 it will
213 // only be used for debug messages.
214 bool direct_to_ddms_;
215 char *file_name_;
216 char *file_data_ptr_; // for open_memstream
217 size_t file_data_size_; // for open_memstream
218 FILE *mem_fp_;
219 int fd_;
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500220
Jesse Wilson0b075f12011-11-09 10:57:41 -0500221 ClassSet classes_;
Jesse Wilson0b075f12011-11-09 10:57:41 -0500222 size_t next_string_id_;
Jesse Wilson0b075f12011-11-09 10:57:41 -0500223 StringMap strings_;
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400224};
225
Elliott Hughesfbd84562011-11-07 18:56:13 -0800226int DumpHeap(const char* fileName, int fd, bool directToDdms);
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400227
228} // namespace hprof
229
230} // namespace art
231
232#endif // HPROF_HPROF_H_