/* * Visits all stack slots except those belonging to native method * arguments. */ static void visitThreadStack(RootVisitor *visitor, Thread *thread, void *arg) { assert(visitor != NULL); assert(thread != NULL); u4 threadId = thread->threadId; const StackSaveArea *saveArea; for (u4 *fp = (u4 *)thread->interpSave.curFrame; fp != NULL; fp = (u4 *)saveArea->prevFrame) { Method *method; saveArea = SAVEAREA_FROM_FP(fp); method = (Method *)saveArea->method; if (method != NULL && !dvmIsNativeMethod(method)) { #ifdef FASTIVA // @zee do not call any malloc in gc task. // cf) dvmGetExpandedRegisterMap() const RegisterMap* pMap = NULL; #else const RegisterMap* pMap = dvmGetExpandedRegisterMap(method); #endif const u1* regVector = NULL; #ifndef FASTIVA if (pMap != NULL) { /* found map, get registers for this address */ int addr = saveArea->xtra.currentPc - method->insns; regVector = dvmRegisterMapGetLine(pMap, addr); } #endif if (regVector == NULL) { /* * Either there was no register map or there is no * info for the current PC. Perform a conservative * scan. */ for (size_t i = 0; i < method->registersSize; ++i) { if (dvmIsValidObject((Object *)fp[i])) { (*visitor)(&fp[i], threadId, ROOT_JAVA_FRAME, arg); } } } else { /* * Precise scan. v0 is at the lowest address on the * interpreted stack, and is the first bit in the * register vector, so we can walk through the * register map and memory in the same direction. * * A '1' bit indicates a live reference. */ u2 bits = 1 << 1; for (size_t i = 0; i < method->registersSize; ++i) { bits >>= 1; if (bits == 1) { /* set bit 9 so we can tell when we're empty */ bits = *regVector++ | 0x0100; } if ((bits & 0x1) != 0) { /* * Register is marked as live, it's a valid root. */ #if WITH_EXTRA_GC_CHECKS if (fp[i] != 0 && !dvmIsValidObject((Object *)fp[i])) { /* this is very bad */ ALOGE("PGC: invalid ref in reg %d: %#x", method->registersSize - 1 - i, fp[i]); ALOGE("PGC: %s.%s addr %#x", method->clazz->descriptor, method->name, saveArea->xtra.currentPc - method->insns); continue; } #endif (*visitor)(&fp[i], threadId, ROOT_JAVA_FRAME, arg); } } dvmReleaseRegisterMapLine(pMap, regVector); } } /* * Don't fall into an infinite loop if things get corrupted. */ assert((uintptr_t)saveArea->prevFrame > (uintptr_t)fp || saveArea->prevFrame == NULL); } #ifdef FASTIVA int* stack_bottom = (int*)thread->m_pNativeStackBottom; int* stack_top = (int*)thread->m_pNativeStackPointer; const bool DUMP_STACK = 0; if (DUMP_STACK) { ALOGE("##### scan_stack %i %p~%p", thread->systemTid, stack_top, stack_bottom); } assert(thread->status != THREAD_RUNNING || thread == dvmThreadSelf()); while (stack_top < stack_bottom) { if (dvmIsValidObject((Object*)stack_top[0])) { (*visitor)(stack_top, threadId, ROOT_JAVA_FRAME, arg); } stack_top ++; } #endif }
/* * Visits all stack slots. TODO: visit native methods. */ static void visitThreadStack(Visitor *visitor, Thread *thread, void *arg) { const StackSaveArea *saveArea; u4 *framePtr; assert(visitor != NULL); assert(thread != NULL); framePtr = (u4 *)thread->curFrame; for (; framePtr != NULL; framePtr = saveArea->prevFrame) { Method *method; saveArea = SAVEAREA_FROM_FP(framePtr); method = (Method *)saveArea->method; if (method != NULL && !dvmIsNativeMethod(method)) { const RegisterMap* pMap = dvmGetExpandedRegisterMap(method); const u1* regVector = NULL; size_t i; if (pMap != NULL) { /* found map, get registers for this address */ int addr = saveArea->xtra.currentPc - method->insns; regVector = dvmRegisterMapGetLine(pMap, addr); } if (regVector == NULL) { /* * Either there was no register map or there is no * info for the current PC. Perform a conservative * scan. */ for (i = 0; i < method->registersSize; ++i) { if (dvmIsValidObject((Object *)framePtr[i])) { (*visitor)(&framePtr[i], arg); } } } else { /* * Precise scan. v0 is at the lowest address on the * interpreted stack, and is the first bit in the * register vector, so we can walk through the * register map and memory in the same direction. * * A '1' bit indicates a live reference. */ u2 bits = 1 << 1; for (i = 0; i < method->registersSize; ++i) { bits >>= 1; if (bits == 1) { /* set bit 9 so we can tell when we're empty */ bits = *regVector++ | 0x0100; } if ((bits & 0x1) != 0) { /* * Register is marked as live, it's a valid root. */ (*visitor)(&framePtr[i], arg); } } dvmReleaseRegisterMapLine(pMap, regVector); } } /* * Don't fall into an infinite loop if things get corrupted. */ assert((uintptr_t)saveArea->prevFrame > (uintptr_t)framePtr || saveArea->prevFrame == NULL); } }