int hprofStartup_StackFrame() { HashIter iter; /* Cache the string "<unknown>" for use when the source file is * unknown. */ hprofLookupStringId("<unknown>"); /* This will be called when a GC begins. */ for (dvmHashIterBegin(gStackFrameHashTable, &iter); !dvmHashIterDone(&iter); dvmHashIterNext(&iter)) { StackFrameEntry *stackFrameEntry; const Method *method; /* Clear the 'live' bit at the start of the GC pass. */ stackFrameEntry = (StackFrameEntry *) dvmHashIterData(&iter); stackFrameEntry->live = 0; method = stackFrameEntry->frame.method; if (method == NULL) { continue; } /* Make sure the method name, descriptor, and source file are in * the string table, and that the method class is in the class * table. This is needed because strings and classes will be dumped * before stack frames. */ if (method->name) { hprofLookupStringId(method->name); } DexStringCache cache; const char* descriptor; dexStringCacheInit(&cache); descriptor = dexProtoGetMethodDescriptor(&method->prototype, &cache); hprofLookupStringId(descriptor); dexStringCacheRelease(&cache); const char* sourceFile = dvmGetMethodSourceFile(method); if (sourceFile) { hprofLookupStringId(sourceFile); } if (method->clazz) { hprofLookupClassId(method->clazz); } } return 0; }
/* *bref:获取class的id. */ static int getPrettyClassNameId(const char *descriptor) { std::string name(dvmHumanReadableDescriptor(descriptor)); return hprofLookupStringId(name.c_str()); }
int hprofDumpStackFrames(hprof_context_t *ctx) { HashIter iter; hprof_record_t *rec = &ctx->curRec; dvmHashTableLock(gStackFrameHashTable); for (dvmHashIterBegin(gStackFrameHashTable, &iter); !dvmHashIterDone(&iter); dvmHashIterNext(&iter)) { const StackFrameEntry *stackFrameEntry; const Method *method; int pc; const char *sourceFile; ClassObject *clazz; int lineNum; hprofStartNewRecord(ctx, HPROF_TAG_STACK_FRAME, HPROF_TIME); stackFrameEntry = (const StackFrameEntry *) dvmHashIterData(&iter); assert(stackFrameEntry != NULL); method = stackFrameEntry->frame.method; pc = stackFrameEntry->frame.pc; sourceFile = dvmGetMethodSourceFile(method); if (sourceFile == NULL) { sourceFile = "<unknown>"; lineNum = 0; } else { lineNum = dvmLineNumFromPC(method, pc); } clazz = (ClassObject *) hprofLookupClassId(method->clazz); /* STACK FRAME format: * * ID: ID for this stack frame * ID: ID for the method name * ID: ID for the method descriptor * ID: ID for the source file name * u4: class serial number * u4: line number, 0 = no line information * * We use the address of the stack frame as its ID. */ DexStringCache cache; const char* descriptor; dexStringCacheInit(&cache); descriptor = dexProtoGetMethodDescriptor(&method->prototype, &cache); hprofAddIdToRecord(rec, (u4) stackFrameEntry); hprofAddIdToRecord(rec, hprofLookupStringId(method->name)); hprofAddIdToRecord(rec, hprofLookupStringId(descriptor)); hprofAddIdToRecord(rec, hprofLookupStringId(sourceFile)); hprofAddU4ToRecord(rec, (u4) clazz->serialNumber); hprofAddU4ToRecord(rec, (u4) lineNum); dexStringCacheRelease(&cache); } dvmHashTableUnlock(gStackFrameHashTable); return 0; }
static int getPrettyClassNameId(const char *descriptor) { hprof_string_id classNameId; char *dotName = dvmDescriptorToDot(descriptor); /* Hprof suggests that array class names be converted from, e.g., * "[[[I" to "int[][][]" and "[Lorg.blort.Spaz;" to * "org.blort.Spaz[]". */ if (dotName[0] == '[') { const char *c; char *newName; char *nc; size_t dim; size_t newLen; c = dotName; dim = 0; while (*c == '[') { dim++; c++; } if (*c == 'L') { c++; } else { /* It's a primitive type; we should use a pretty name. * Add semicolons to make all strings have the format * of object class names. */ switch (*c) { case 'Z': c = "boolean;"; break; case 'C': c = "char;"; break; case 'F': c = "float;"; break; case 'D': c = "double;"; break; case 'B': c = "byte;"; break; case 'S': c = "short;"; break; case 'I': c = "int;"; break; case 'J': c = "long;"; break; default: assert(false); c = "UNKNOWN;"; break; } } /* We have a string of the form "name;" and * we want to replace the semicolon with as many * "[]" pairs as is in dim. */ newLen = strlen(c)-1 + dim*2; newName = malloc(newLen + 1); if (newName == NULL) { return -1; } strcpy(newName, c); newName[newLen] = '\0'; /* Point nc to the semicolon. */ nc = newName + newLen - dim*2; assert(*nc == ';'); while (dim--) { *nc++ = '['; *nc++ = ']'; } assert(*nc == '\0'); classNameId = hprofLookupStringId(newName); free(newName); } else { classNameId = hprofLookupStringId(dotName); } free(dotName); return classNameId; }