Exemplo n.º 1
0
int
hprofShutdown_Stack()
{
    HashIter iter;

    /* This will be called when a GC has completed. */
    for (dvmHashIterBegin(gStackTraceHashTable, &iter);
         !dvmHashIterDone(&iter);
         dvmHashIterNext(&iter)) {
        StackTraceEntry *stackTraceEntry;

        /*
         * If the 'live' bit is 0, the trace is not in use by any current
         * heap object and may be destroyed.
         */
        stackTraceEntry = (StackTraceEntry *) dvmHashIterData(&iter);
        if (!stackTraceEntry->live) {
            dvmHashTableRemove(gStackTraceHashTable,
                    computeStackTraceHash(stackTraceEntry), stackTraceEntry);
            free(stackTraceEntry);
        }
    }

    return 0;
}
Exemplo n.º 2
0
/*
 * Evaluate the amount of probing required for the specified hash table.
 *
 * We do this by running through all entries in the hash table, computing
 * the hash value and then doing a lookup.
 *
 * The caller should lock the table before calling here.
 */
void dvmHashTableProbeCount(HashTable* pHashTable, HashCalcFunc calcFunc,
    HashCompareFunc cmpFunc)
{
    int numEntries, minProbe, maxProbe, totalProbe;
    HashIter iter;

    numEntries = maxProbe = totalProbe = 0;
    minProbe = 65536*32767;

    for (dvmHashIterBegin(pHashTable, &iter); !dvmHashIterDone(&iter);
        dvmHashIterNext(&iter))
    {
        const void* data = (const void*)dvmHashIterData(&iter);
        int count;

        count = countProbes(pHashTable, (*calcFunc)(data), data, cmpFunc);

        numEntries++;

        if (count < minProbe)
            minProbe = count;
        if (count > maxProbe)
            maxProbe = count;
        totalProbe += count;
    }

    LOGI("Probe: min=%d max=%d, total=%d in %d (%d), avg=%.3f\n",
        minProbe, maxProbe, totalProbe, numEntries, pHashTable->tableSize,
        (float) totalProbe / (float) numEntries);
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
int
hprofDumpStacks(hprof_context_t *ctx)
{
    HashIter iter;
    hprof_record_t *rec = &ctx->curRec;

    dvmHashTableLock(gStackTraceHashTable);

    for (dvmHashIterBegin(gStackTraceHashTable, &iter);
         !dvmHashIterDone(&iter);
         dvmHashIterNext(&iter))
    {
        const StackTraceEntry *stackTraceEntry;
        int count;
        int i;

        hprofStartNewRecord(ctx, HPROF_TAG_STACK_TRACE, HPROF_TIME);
        
        stackTraceEntry = (const StackTraceEntry *) dvmHashIterData(&iter);
        assert(stackTraceEntry != NULL);

        /* STACK TRACE format:
         *
         * u4:     serial number for this stack
         * u4:     serial number for the running thread
         * u4:     number of frames
         * [ID]*:  ID for the stack frame
         */
        hprofAddU4ToRecord(rec, stackTraceEntry->trace.serialNumber);
        hprofAddU4ToRecord(rec, stackTraceEntry->trace.threadSerialNumber);
        
        count = 0;
        while ((count < STACK_DEPTH) &&
               (stackTraceEntry->trace.frameIds[count] != 0)) {
            count++;
        }
        hprofAddU4ToRecord(rec, count);
        for (i = 0; i < count; i++) {
            hprofAddU4ToRecord(rec, stackTraceEntry->trace.frameIds[i]);
        }
    }

    dvmHashTableUnlock(gStackTraceHashTable);

    return 0;
}
Exemplo n.º 5
0
int
hprofStartup_Stack()
{
    HashIter iter;

    /* This will be called when a GC begins. */
    for (dvmHashIterBegin(gStackTraceHashTable, &iter);
         !dvmHashIterDone(&iter);
         dvmHashIterNext(&iter)) {
        StackTraceEntry *stackTraceEntry;

        /* Clear the 'live' bit at the start of the GC pass. */
        stackTraceEntry = (StackTraceEntry *) dvmHashIterData(&iter);
        stackTraceEntry->live = 0;
    }

    return 0;
}
Exemplo n.º 6
0
/*
 * Test iterator.
 */
static void dumpIterator(HashTable* pTab)
{
    int count = 0;

    //printf("Print from iterator:\n");
    HashIter iter;
    for (dvmHashIterBegin(pTab, &iter); !dvmHashIterDone(&iter);
        dvmHashIterNext(&iter))
    {
        //const char* str = (const char*) dvmHashIterData(&iter);
        //printf("  '%s'\n", str);
        // (should verify strings)
        count++;
    }
    if (count != kNumTestEntries) {
        ALOGE("TestHash iterator test failed");
        assert(false);
    }
}
Exemplo n.º 7
0
int
hprofDumpClasses(hprof_context_t *ctx)
{
    HashIter iter;
    hprof_record_t *rec = &ctx->curRec;
    int err;

    dvmHashTableLock(gClassHashTable);

    for (err = 0, dvmHashIterBegin(gClassHashTable, &iter);
         err == 0 && !dvmHashIterDone(&iter);
         dvmHashIterNext(&iter))
    {
        err = hprofStartNewRecord(ctx, HPROF_TAG_LOAD_CLASS, HPROF_TIME);
        if (err == 0) {
            const ClassObject *clazz;

            clazz = (const ClassObject *)dvmHashIterData(&iter);
            assert(clazz != NULL);

            /* LOAD CLASS format:
             *
             * u4:     class serial number (always > 0)
             * ID:     class object ID
             * u4:     stack trace serial number
             * ID:     class name string ID
             *
             * We use the address of the class object structure as its ID.
             */
            hprofAddU4ToRecord(rec, clazz->serialNumber);
            hprofAddIdToRecord(rec, (hprof_class_object_id)clazz);
            hprofAddU4ToRecord(rec, HPROF_NULL_STACK_TRACE);
            hprofAddIdToRecord(rec, getPrettyClassNameId(clazz->descriptor));
        }
    }

    dvmHashTableUnlock(gClassHashTable);

    return err;
}
Exemplo n.º 8
0
/*
 * Some quick hash table tests.
 */
bool dvmTestHash()
{
    HashTable* pTab;
    char tmpStr[64];
    const char* str;
    u4 hash;
    int i;

    ALOGV("TestHash BEGIN");

    pTab = dvmHashTableCreate(dvmHashSize(12), free);
    if (pTab == NULL)
        return false;

    dvmHashTableLock(pTab);

    /* add some entries */
    for (i = 0; i < kNumTestEntries; i++) {
        sprintf(tmpStr, "entry %d", i);
        hash = dvmComputeUtf8Hash(tmpStr);
        dvmHashTableLookup(pTab, hash, strdup(tmpStr),
            (HashCompareFunc) strcmp, true);
    }

    dvmHashTableUnlock(pTab);

    /* make sure we can find all entries */
    for (i = 0; i < kNumTestEntries; i++) {
        sprintf(tmpStr, "entry %d", i);
        hash = dvmComputeUtf8Hash(tmpStr);
        str = (const char*) dvmHashTableLookup(pTab, hash, tmpStr,
                (HashCompareFunc) strcmp, false);
        if (str == NULL) {
            ALOGE("TestHash: failure: could not find '%s'", tmpStr);
            /* return false */
        }
    }

    /* make sure it behaves correctly when entry not found and !doAdd */
    sprintf(tmpStr, "entry %d", 17);
    hash = dvmComputeUtf8Hash(tmpStr);
    str = (const char*) dvmHashTableLookup(pTab, hash, tmpStr,
            (HashCompareFunc) strcmp, false);
    if (str == NULL) {
        /* good */
    } else {
        ALOGE("TestHash found nonexistent string (improper add?)");
    }

    dumpForeach(pTab);
    dumpIterator(pTab);

    /* make sure they all get freed */
    dvmHashTableFree(pTab);


    /*
     * Round 2: verify probing & tombstones.
     */
    pTab = dvmHashTableCreate(dvmHashSize(2), free);
    if (pTab == NULL)
        return false;

    hash = 0;

    /* two entries, same hash, different values */
    const char* str1;
    str1 = (char*) dvmHashTableLookup(pTab, hash, strdup("one"),
            (HashCompareFunc) strcmp, true);
    assert(str1 != NULL);
    str = (const char*) dvmHashTableLookup(pTab, hash, strdup("two"),
            (HashCompareFunc) strcmp, true);

    /* remove the first one */
    if (!dvmHashTableRemove(pTab, hash, (void*)str1))
        ALOGE("TestHash failed to delete item");
    else
        free((void*)str1);     // "Remove" doesn't call the free func

    /* make sure iterator doesn't included deleted entries */
    int count = 0;
    HashIter iter;
    for (dvmHashIterBegin(pTab, &iter); !dvmHashIterDone(&iter);
        dvmHashIterNext(&iter))
    {
        count++;
    }
    if (count != 1) {
        ALOGE("TestHash wrong number of entries (%d)", count);
    }

    /* see if we can find them */
    str = (const char*) dvmHashTableLookup(pTab, hash, (void*)"one",
            (HashCompareFunc) strcmp,false);
    if (str != NULL)
        ALOGE("TestHash deleted entry has returned!");
    str = (const char*) dvmHashTableLookup(pTab, hash, (void*)"two",
            (HashCompareFunc) strcmp,false);
    if (str == NULL)
        ALOGE("TestHash entry vanished");

    /* force a table realloc to exercise tombstone removal */
    for (i = 0; i < 20; i++) {
        sprintf(tmpStr, "entry %d", i);
        str = (const char*) dvmHashTableLookup(pTab, hash, strdup(tmpStr),
                (HashCompareFunc) strcmp, true);
        assert(str != NULL);
    }

    dvmHashTableFree(pTab);
    ALOGV("TestHash END");

    return true;
}
Exemplo n.º 9
0
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;
}