• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
22 static HashTable *gClassHashTable;
23 
hprofStartup_Class()24 int hprofStartup_Class()
25 {
26     gClassHashTable = dvmHashTableCreate(128, NULL);
27     if (gClassHashTable == NULL) {
28         return UNIQUE_ERROR();
29     }
30     return 0;
31 }
32 
hprofShutdown_Class()33 int hprofShutdown_Class()
34 {
35     dvmHashTableFree(gClassHashTable);
36 
37     return 0;
38 }
39 
computeClassHash(const ClassObject * clazz)40 static u4 computeClassHash(const ClassObject *clazz)
41 {
42     u4 hash;
43     const char *cp;
44     char c;
45 
46     cp = clazz->descriptor;
47     hash = (u4)clazz->classLoader;
48     while ((c = *cp++) != '\0') {
49         hash = hash * 31 + c;
50     }
51 
52     return hash;
53 }
54 
classCmp(const void * v1,const void * v2)55 static int classCmp(const void *v1, const void *v2)
56 {
57     const ClassObject *c1 = (const ClassObject *)v1;
58     const ClassObject *c2 = (const ClassObject *)v2;
59     intptr_t diff;
60 
61     diff = (uintptr_t)c1->classLoader - (uintptr_t)c2->classLoader;
62     if (diff == 0) {
63         return strcmp(c1->descriptor, c2->descriptor);
64     }
65     return diff;
66 }
67 
getPrettyClassNameId(const char * descriptor)68 static int getPrettyClassNameId(const char *descriptor) {
69     std::string name(dvmHumanReadableDescriptor(descriptor));
70     return hprofLookupStringId(name.c_str());
71 }
72 
hprofLookupClassId(const ClassObject * clazz)73 hprof_class_object_id hprofLookupClassId(const ClassObject *clazz)
74 {
75     void *val;
76 
77     if (clazz == NULL) {
78         /* Someone's probably looking up the superclass
79          * of java.lang.Object or of a primitive class.
80          */
81         return (hprof_class_object_id)0;
82     }
83 
84     dvmHashTableLock(gClassHashTable);
85 
86     /* We're using the hash table as a list.
87      * TODO: replace the hash table with a more suitable structure
88      */
89     val = dvmHashTableLookup(gClassHashTable, computeClassHash(clazz),
90             (void *)clazz, classCmp, true);
91     assert(val != NULL);
92 
93     dvmHashTableUnlock(gClassHashTable);
94 
95     /* Make sure that the class's name is in the string table.
96      * This is a bunch of extra work that we only have to do
97      * because of the order of tables in the output file
98      * (strings need to be dumped before classes).
99      */
100     getPrettyClassNameId(clazz->descriptor);
101 
102     return (hprof_class_object_id)clazz;
103 }
104 
hprofDumpClasses(hprof_context_t * ctx)105 int hprofDumpClasses(hprof_context_t *ctx)
106 {
107     HashIter iter;
108     hprof_record_t *rec = &ctx->curRec;
109     int err;
110 
111     dvmHashTableLock(gClassHashTable);
112 
113     for (err = 0, dvmHashIterBegin(gClassHashTable, &iter);
114          err == 0 && !dvmHashIterDone(&iter);
115          dvmHashIterNext(&iter))
116     {
117         err = hprofStartNewRecord(ctx, HPROF_TAG_LOAD_CLASS, HPROF_TIME);
118         if (err == 0) {
119             const ClassObject *clazz;
120 
121             clazz = (const ClassObject *)dvmHashIterData(&iter);
122             assert(clazz != NULL);
123 
124             /* LOAD CLASS format:
125              *
126              * u4:     class serial number (always > 0)
127              * ID:     class object ID
128              * u4:     stack trace serial number
129              * ID:     class name string ID
130              *
131              * We use the address of the class object structure as its ID.
132              */
133             hprofAddU4ToRecord(rec, clazz->serialNumber);
134             hprofAddIdToRecord(rec, (hprof_class_object_id)clazz);
135             hprofAddU4ToRecord(rec, HPROF_NULL_STACK_TRACE);
136             hprofAddIdToRecord(rec, getPrettyClassNameId(clazz->descriptor));
137         }
138     }
139 
140     dvmHashTableUnlock(gClassHashTable);
141 
142     return err;
143 }
144