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;
}
Esempio n. 2
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;
}
Esempio n. 4
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;
}