blob: 38520cc221daca9e21d785a0146afc48123f3ac5 [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 Wilsonc4824e62011-11-01 14:39:04 -040025
26namespace art {
27
28namespace hprof {
29
30#define HPROF_ID_SIZE (sizeof (uint32_t))
31
32#define UNIQUE_ERROR() \
33 -((((uintptr_t)__func__) << 16 | __LINE__) & (0x7fffffff))
34
35#define HPROF_TIME 0
36#define HPROF_NULL_STACK_TRACE 0
37#define HPROF_NULL_THREAD 0
38
Jesse Wilson3aa66fd2011-11-08 20:53:40 -050039typedef uint32_t HprofId;
40typedef HprofId HprofStringId;
41typedef HprofId HprofObjectId;
42typedef HprofId HprofClassObjectId;
43typedef std::tr1::unordered_set<Class*, ObjectIdentityHash> ClassSet;
44typedef std::tr1::unordered_set<Class*, ObjectIdentityHash>::iterator ClassSetIterator;
45typedef std::tr1::unordered_map<std::string, size_t> StringMap;
46typedef std::tr1::unordered_map<std::string, size_t>::iterator StringMapIterator;
Jesse Wilsonc4824e62011-11-01 14:39:04 -040047
Jesse Wilson3aa66fd2011-11-08 20:53:40 -050048enum HprofBasicType {
Jesse Wilson0b075f12011-11-09 10:57:41 -050049 hprof_basic_object = 2,
50 hprof_basic_boolean = 4,
51 hprof_basic_char = 5,
52 hprof_basic_float = 6,
53 hprof_basic_double = 7,
54 hprof_basic_byte = 8,
55 hprof_basic_short = 9,
56 hprof_basic_int = 10,
57 hprof_basic_long = 11,
Jesse Wilsonc4824e62011-11-01 14:39:04 -040058};
59
Jesse Wilson3aa66fd2011-11-08 20:53:40 -050060enum HprofTag {
Jesse Wilson0b075f12011-11-09 10:57:41 -050061 HPROF_TAG_STRING = 0x01,
62 HPROF_TAG_LOAD_CLASS = 0x02,
63 HPROF_TAG_UNLOAD_CLASS = 0x03,
64 HPROF_TAG_STACK_FRAME = 0x04,
65 HPROF_TAG_STACK_TRACE = 0x05,
66 HPROF_TAG_ALLOC_SITES = 0x06,
67 HPROF_TAG_HEAP_SUMMARY = 0x07,
68 HPROF_TAG_START_THREAD = 0x0A,
69 HPROF_TAG_END_THREAD = 0x0B,
70 HPROF_TAG_HEAP_DUMP = 0x0C,
71 HPROF_TAG_HEAP_DUMP_SEGMENT = 0x1C,
72 HPROF_TAG_HEAP_DUMP_END = 0x2C,
73 HPROF_TAG_CPU_SAMPLES = 0x0D,
74 HPROF_TAG_CONTROL_SETTINGS = 0x0E,
Jesse Wilsonc4824e62011-11-01 14:39:04 -040075};
76
Jesse Wilson0b075f12011-11-09 10:57:41 -050077// Values for the first byte of HEAP_DUMP and HEAP_DUMP_SEGMENT records:
Jesse Wilson3aa66fd2011-11-08 20:53:40 -050078enum HprofHeapTag {
Jesse Wilson0b075f12011-11-09 10:57:41 -050079 /* standard */
80 HPROF_ROOT_UNKNOWN = 0xFF,
81 HPROF_ROOT_JNI_GLOBAL = 0x01,
82 HPROF_ROOT_JNI_LOCAL = 0x02,
83 HPROF_ROOT_JAVA_FRAME = 0x03,
84 HPROF_ROOT_NATIVE_STACK = 0x04,
85 HPROF_ROOT_STICKY_CLASS = 0x05,
86 HPROF_ROOT_THREAD_BLOCK = 0x06,
87 HPROF_ROOT_MONITOR_USED = 0x07,
88 HPROF_ROOT_THREAD_OBJECT = 0x08,
89 HPROF_CLASS_DUMP = 0x20,
90 HPROF_INSTANCE_DUMP = 0x21,
91 HPROF_OBJECT_ARRAY_DUMP = 0x22,
92 HPROF_PRIMITIVE_ARRAY_DUMP = 0x23,
Jesse Wilsonc4824e62011-11-01 14:39:04 -040093
Jesse Wilson0b075f12011-11-09 10:57:41 -050094 /* Android */
95 HPROF_HEAP_DUMP_INFO = 0xfe,
96 HPROF_ROOT_INTERNED_STRING = 0x89,
97 HPROF_ROOT_FINALIZING = 0x8a, /* obsolete */
98 HPROF_ROOT_DEBUGGER = 0x8b,
99 HPROF_ROOT_REFERENCE_CLEANUP = 0x8c, /* obsolete */
100 HPROF_ROOT_VM_INTERNAL = 0x8d,
101 HPROF_ROOT_JNI_MONITOR = 0x8e,
102 HPROF_UNREACHABLE = 0x90, /* obsolete */
103 HPROF_PRIMITIVE_ARRAY_NODATA_DUMP = 0xc3,
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400104};
105
Jesse Wilson0b075f12011-11-09 10:57:41 -0500106// Represents a top-level hprof record, whose serialized format is:
107// U1 TAG: denoting the type of the record
108// U4 TIME: number of microseconds since the time stamp in the header
109// U4 LENGTH: number of bytes that follow this uint32_t field and belong to this record
110// U1* BODY: as many bytes as specified in the above uint32_t field
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500111class HprofRecord {
Jesse Wilson0b075f12011-11-09 10:57:41 -0500112 public:
113 int Flush(FILE *fp);
114 int AddU1(uint8_t value);
115 int AddU2(uint16_t value);
116 int AddU4(uint32_t value);
117 int AddU8(uint64_t value);
118 int AddId(HprofObjectId value);
119 int AddU1List(const uint8_t *values, size_t numValues);
120 int AddU2List(const uint16_t *values, size_t numValues);
121 int AddU4List(const uint32_t *values, size_t numValues);
122 int AddU8List(const uint64_t *values, size_t numValues);
123 int AddIdList(const HprofObjectId *values, size_t numValues);
124 int AddUtf8String(const char *str);
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500125
Jesse Wilson0b075f12011-11-09 10:57:41 -0500126 unsigned char *body_;
127 uint32_t time_;
128 uint32_t length_;
129 size_t alloc_length_;
130 uint8_t tag_;
131 bool dirty_;
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400132};
133
134enum HprofHeapId {
Jesse Wilson0b075f12011-11-09 10:57:41 -0500135 HPROF_HEAP_DEFAULT = 0,
136 HPROF_HEAP_ZYGOTE = 'Z',
137 HPROF_HEAP_APP = 'A'
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400138};
139
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500140class Hprof {
Jesse Wilson0b075f12011-11-09 10:57:41 -0500141 public:
142 Hprof(const char *outputFileName, int fd, bool writeHeader, bool directToDdms);
143 ~Hprof();
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500144
Jesse Wilson0b075f12011-11-09 10:57:41 -0500145 void VisitRoot(const Object* obj);
146 int DumpHeapObject(const Object *obj);
147 bool Finish();
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500148
Jesse Wilson0b075f12011-11-09 10:57:41 -0500149 private:
150 int DumpClasses();
151 int DumpStrings();
152 int StartNewRecord(uint8_t tag, uint32_t time);
153 int FlushCurrentRecord();
154 int MarkRootObject(const Object *obj, jobject jniObj);
155 HprofClassObjectId LookupClassId(Class* clazz);
156 HprofStringId LookupStringId(String* string);
157 HprofStringId LookupStringId(const char* string);
158 HprofStringId LookupStringId(std::string string);
159 HprofStringId LookupClassNameId(Class* clazz);
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500160
Jesse Wilson0b075f12011-11-09 10:57:41 -0500161 // current_record_ *must* be first so that we can cast from a context to a record.
162 HprofRecord current_record_;
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400163
Jesse Wilson0b075f12011-11-09 10:57:41 -0500164 uint32_t gc_thread_serial_number_;
165 uint8_t gc_scan_state_;
166 HprofHeapId current_heap_; // which heap we're currently emitting
167 size_t objects_in_segment_;
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400168
Jesse Wilson0b075f12011-11-09 10:57:41 -0500169 // If direct_to_ddms_ is set, "file_name_" and "fd" will be ignored.
170 // Otherwise, "file_name_" must be valid, though if "fd" >= 0 it will
171 // only be used for debug messages.
172 bool direct_to_ddms_;
173 char *file_name_;
174 char *file_data_ptr_; // for open_memstream
175 size_t file_data_size_; // for open_memstream
176 FILE *mem_fp_;
177 int fd_;
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500178
Jesse Wilson0b075f12011-11-09 10:57:41 -0500179 mutable Mutex classes_lock_;
180 ClassSet classes_;
Jesse Wilson3aa66fd2011-11-08 20:53:40 -0500181
Jesse Wilson0b075f12011-11-09 10:57:41 -0500182 size_t next_string_id_;
183 mutable Mutex strings_lock_;
184 StringMap strings_;
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400185};
186
Elliott Hughesfbd84562011-11-07 18:56:13 -0800187int DumpHeap(const char* fileName, int fd, bool directToDdms);
Jesse Wilsonc4824e62011-11-01 14:39:04 -0400188
189} // namespace hprof
190
191} // namespace art
192
193#endif // HPROF_HPROF_H_