blob: 755e96855169b9f2a4ee6672c9b9c4f0f91b09ef [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
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/*
17 * Class object pool
18 */
19
20#include "Hprof.h"
21
22static HashTable *gClassHashTable;
23
24int
25hprofStartup_Class()
26{
27 gClassHashTable = dvmHashTableCreate(128, NULL);
28 if (gClassHashTable == NULL) {
29 return UNIQUE_ERROR();
30 }
31 return 0;
32}
33
34int
35hprofShutdown_Class()
36{
37 dvmHashTableFree(gClassHashTable);
38
39 return 0;
40}
41
42static u4
43computeClassHash(const ClassObject *clazz)
44{
45 u4 hash;
46 const char *cp;
47 char c;
48
49 cp = clazz->descriptor;
50 hash = (u4)clazz->classLoader;
51 while ((c = *cp++) != '\0') {
52 hash = hash * 31 + c;
53 }
54
55 return hash;
56}
57
58static int
59classCmp(const void *v1, const void *v2)
60{
61 const ClassObject *c1 = (const ClassObject *)v1;
62 const ClassObject *c2 = (const ClassObject *)v2;
63 intptr_t diff;
64
65 diff = (uintptr_t)c1->classLoader - (uintptr_t)c2->classLoader;
66 if (diff == 0) {
67 return strcmp(c1->descriptor, c2->descriptor);
68 }
69 return diff;
70}
71
72static int
73getPrettyClassNameId(const char *descriptor)
74{
Elliott Hughes50169662010-11-22 13:14:23 -080075 char* name = dvmHumanReadableDescriptor(descriptor);
76 if (name == NULL) {
77 return -1;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080078 }
Elliott Hughes50169662010-11-22 13:14:23 -080079 hprof_string_id classNameId = hprofLookupStringId(name);
80 free(name);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080081 return classNameId;
82}
83
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080084hprof_class_object_id
85hprofLookupClassId(const ClassObject *clazz)
86{
87 void *val;
88
89 if (clazz == NULL) {
90 /* Someone's probably looking up the superclass
91 * of java.lang.Object or of a primitive class.
92 */
93 return (hprof_class_object_id)0;
94 }
95
96 dvmHashTableLock(gClassHashTable);
97
98 /* We're using the hash table as a list.
99 * TODO: replace the hash table with a more suitable structure
100 */
101 val = dvmHashTableLookup(gClassHashTable, computeClassHash(clazz),
102 (void *)clazz, classCmp, true);
103 assert(val != NULL);
104
105 dvmHashTableUnlock(gClassHashTable);
106
107 /* Make sure that the class's name is in the string table.
108 * This is a bunch of extra work that we only have to do
109 * because of the order of tables in the output file
110 * (strings need to be dumped before classes).
111 */
112 getPrettyClassNameId(clazz->descriptor);
113
114 return (hprof_class_object_id)clazz;
115}
116
117int
118hprofDumpClasses(hprof_context_t *ctx)
119{
120 HashIter iter;
121 hprof_record_t *rec = &ctx->curRec;
122 int err;
123
124 dvmHashTableLock(gClassHashTable);
125
126 for (err = 0, dvmHashIterBegin(gClassHashTable, &iter);
127 err == 0 && !dvmHashIterDone(&iter);
128 dvmHashIterNext(&iter))
129 {
130 err = hprofStartNewRecord(ctx, HPROF_TAG_LOAD_CLASS, HPROF_TIME);
131 if (err == 0) {
132 const ClassObject *clazz;
133
134 clazz = (const ClassObject *)dvmHashIterData(&iter);
135 assert(clazz != NULL);
136
137 /* LOAD CLASS format:
138 *
139 * u4: class serial number (always > 0)
140 * ID: class object ID
141 * u4: stack trace serial number
142 * ID: class name string ID
Carl Shapirode750892010-06-08 16:37:12 -0700143 *
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800144 * We use the address of the class object structure as its ID.
145 */
146 hprofAddU4ToRecord(rec, clazz->serialNumber);
147 hprofAddIdToRecord(rec, (hprof_class_object_id)clazz);
148 hprofAddU4ToRecord(rec, HPROF_NULL_STACK_TRACE);
149 hprofAddIdToRecord(rec, getPrettyClassNameId(clazz->descriptor));
150 }
151 }
152
153 dvmHashTableUnlock(gClassHashTable);
154
155 return err;
156}