summaryrefslogtreecommitdiffstats
path: root/vm/hprof/HprofStack.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm/hprof/HprofStack.c')
-rw-r--r--vm/hprof/HprofStack.c266
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);
-}