diff options
Diffstat (limited to 'vm/hprof/HprofStack.c')
| -rw-r--r-- | vm/hprof/HprofStack.c | 266 |
1 files changed, 0 insertions, 266 deletions
diff --git a/vm/hprof/HprofStack.c b/vm/hprof/HprofStack.c deleted file mode 100644 index 04641ef7c..000000000 --- a/vm/hprof/HprofStack.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Hprof.h" -#include "HprofStack.h" -#include "alloc/HeapInternal.h" - -static HashTable *gStackTraceHashTable = NULL; -static int gSerialNumber = 0; - -/* Number of stack frames to cache */ -#define STACK_DEPTH 8 - -typedef struct { - int serialNumber; - int threadSerialNumber; - int frameIds[STACK_DEPTH]; -} StackTrace; - -typedef struct { - StackTrace trace; - u1 live; -} StackTraceEntry; - -static u4 computeStackTraceHash(const StackTraceEntry *stackTraceEntry); - -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; -} - -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; -} - -static u4 -computeStackTraceHash(const StackTraceEntry *stackTraceEntry) -{ - u4 hash = 0; - const char *cp = (const char *) &stackTraceEntry->trace; - int i; - - for (i = 0; i < (int) sizeof(StackTrace); i++) { - hash = hash * 31 + cp[i]; - } - - return hash; -} - -/* Only compare the 'trace' portion of the StackTraceEntry. */ -static int -stackCmp(const void *tableItem, const void *looseItem) -{ - return memcmp(&((StackTraceEntry *) tableItem)->trace, - &((StackTraceEntry *) looseItem)->trace, sizeof(StackTrace)); -} - -static StackTraceEntry * -stackDup(const StackTraceEntry *stackTrace) -{ - StackTraceEntry *newStackTrace = malloc(sizeof(StackTraceEntry)); - memcpy(newStackTrace, stackTrace, sizeof(StackTraceEntry)); - return newStackTrace; -} - -static u4 -hprofLookupStackSerialNumber(const StackTraceEntry *stackTrace) -{ - StackTraceEntry *val; - u4 hashValue; - int serial; - - /* - * Create the hash table on first contact. We can't do this in - * hprofStartupStack, because we have to compute stack trace - * serial numbers and place them into object headers before the - * rest of hprof is triggered by a GC event. - */ - if (gStackTraceHashTable == NULL) { - gStackTraceHashTable = dvmHashTableCreate(512, free); - } - dvmHashTableLock(gStackTraceHashTable); - - hashValue = computeStackTraceHash(stackTrace); - val = dvmHashTableLookup(gStackTraceHashTable, hashValue, (void *)stackTrace, - (HashCompareFunc)stackCmp, false); - if (val == NULL) { - StackTraceEntry *newStackTrace; - - newStackTrace = stackDup(stackTrace); - newStackTrace->trace.serialNumber = ++gSerialNumber; - val = dvmHashTableLookup(gStackTraceHashTable, hashValue, - (void *)newStackTrace, (HashCompareFunc)stackCmp, true); - assert(val != NULL); - } - - /* Mark the trace as live (in use by an object in the current heap). */ - val->live = 1; - - /* Grab the serial number before unlocking the table. */ - serial = val->trace.serialNumber; - - dvmHashTableUnlock(gStackTraceHashTable); - - return serial; -} - -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; -} - -void -hprofFillInStackTrace(void *objectPtr) - -{ - DvmHeapChunk *chunk; - StackTraceEntry stackTraceEntry; - Thread* self; - void* fp; - int i; - - if (objectPtr == NULL) { - return; - } - self = dvmThreadSelf(); - if (self == NULL) { - return; - } - fp = self->curFrame; - - /* Serial number to be filled in later. */ - stackTraceEntry.trace.serialNumber = -1; - - /* - * TODO - The HAT tool doesn't care about thread data, so we can defer - * actually emitting thread records and assigning thread serial numbers. - */ - stackTraceEntry.trace.threadSerialNumber = (int) self; - - memset(&stackTraceEntry.trace.frameIds, 0, - sizeof(stackTraceEntry.trace.frameIds)); - - i = 0; - while ((fp != NULL) && (i < STACK_DEPTH)) { - const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp); - const Method* method = saveArea->method; - StackFrameEntry frame; - - if (!dvmIsBreakFrame(fp)) { - frame.frame.method = method; - if (dvmIsNativeMethod(method)) { - frame.frame.pc = 0; /* no saved PC for native methods */ - } else { - assert(saveArea->xtra.currentPc >= method->insns && - saveArea->xtra.currentPc < - method->insns + dvmGetMethodInsnsSize(method)); - frame.frame.pc = (int) (saveArea->xtra.currentPc - - method->insns); - } - - // Canonicalize the frame and cache it in the hprof context - stackTraceEntry.trace.frameIds[i++] = - hprofLookupStackFrameId(&frame); - } - - assert(fp != saveArea->prevFrame); - fp = saveArea->prevFrame; - } - - /* Store the stack trace serial number in the object header */ - chunk = ptr2chunk(objectPtr); - chunk->stackTraceSerialNumber = - hprofLookupStackSerialNumber(&stackTraceEntry); -} |
