/* * Pop one frame pushed on by JNI PushLocalFrame. * * If we've gone too far, the previous frame is either a break frame or * an interpreted frame. Either way, the method pointer won't match. */ bool dvmPopLocalFrame(Thread* self) { StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->interpSave.curFrame); assert(!dvmIsBreakFrame((u4*)self->interpSave.curFrame)); if (saveBlock->method != SAVEAREA_FROM_FP(saveBlock->prevFrame)->method) { /* * The previous frame doesn't have the same method pointer -- we've * been asked to pop too much. */ assert(dvmIsBreakFrame((u4*)saveBlock->prevFrame) || !dvmIsNativeMethod( SAVEAREA_FROM_FP(saveBlock->prevFrame)->method)); return false; } LOGVV("POP JNI local frame: removing %s, now %s", saveBlock->method->name, SAVEAREA_FROM_FP(saveBlock->prevFrame)->method->name); dvmPopJniLocals(self, saveBlock); self->interpSave.curFrame = saveBlock->prevFrame; #ifdef WITH_OFFLOAD offStackFramePopped(self); #endif return true; }
/* * Pop a frame we added. There should be one method frame and one break * frame. * * If JNI Push/PopLocalFrame calls were mismatched, we might end up * popping multiple method frames before we find the break. * * Returns "false" if there was no frame to pop. */ static bool dvmPopFrame(Thread* self) { StackSaveArea* saveBlock; if (self->interpSave.curFrame == NULL) return false; saveBlock = SAVEAREA_FROM_FP(self->interpSave.curFrame); assert(!dvmIsBreakFrame((u4*)self->interpSave.curFrame)); /* * Remove everything up to the break frame. If this was a call into * native code, pop the JNI local references table. */ while (saveBlock->prevFrame != NULL && saveBlock->method != NULL) { /* probably a native->native JNI call */ if (dvmIsNativeMethod(saveBlock->method)) { LOGVV("Popping JNI stack frame for %s.%s%s", saveBlock->method->clazz->descriptor, saveBlock->method->name, (SAVEAREA_FROM_FP(saveBlock->prevFrame)->method == NULL) ? "" : " (JNI local)"); dvmPopJniLocals(self, saveBlock); } saveBlock = SAVEAREA_FROM_FP(saveBlock->prevFrame); } if (saveBlock->method != NULL) { ALOGE("PopFrame missed the break"); assert(false); dvmAbort(); // stack trashed -- nowhere to go in this thread } LOGVV("POP frame: cur=%p new=%p", self->interpSave.curFrame, saveBlock->prevFrame); self->interpSave.curFrame = saveBlock->prevFrame; #ifdef WITH_OFFLOAD offStackFramePopped(self); self->breakFrames--; CHECK_BREAK_FRAMES(); #endif return true; }
/* * Pop a frame we added. There should be one method frame and one break * frame. * * If JNI Push/PopLocalFrame calls were mismatched, we might end up * popping multiple method frames before we find the break. * * Returns "false" if there was no frame to pop. */ static bool dvmPopFrame(Thread* self) { StackSaveArea* saveBlock; if (self->curFrame == NULL) return false; saveBlock = SAVEAREA_FROM_FP(self->curFrame); assert(!dvmIsBreakFrame(self->curFrame)); /* * Remove everything up to the break frame. If this was a call into * native code, pop the JNI local references table. */ while (saveBlock->prevFrame != NULL && saveBlock->method != NULL) { /* probably a native->native JNI call */ if (dvmIsNativeMethod(saveBlock->method)) { LOGVV("Popping JNI stack frame for %s.%s%s\n", saveBlock->method->clazz->descriptor, saveBlock->method->name, (SAVEAREA_FROM_FP(saveBlock->prevFrame)->method == NULL) ? "" : " (JNI local)"); assert(saveBlock->xtra.localRefCookie != 0); //assert(saveBlock->xtra.localRefCookie >= self->jniLocalRefTable.table && // saveBlock->xtra.localRefCookie <=self->jniLocalRefTable.nextEntry); dvmPopJniLocals(self, saveBlock); } saveBlock = SAVEAREA_FROM_FP(saveBlock->prevFrame); } if (saveBlock->method != NULL) { LOGE("PopFrame missed the break\n"); assert(false); dvmAbort(); // stack trashed -- nowhere to go in this thread } LOGVV("POP frame: cur=%p new=%p\n", self->curFrame, saveBlock->prevFrame); self->curFrame = saveBlock->prevFrame; return true; }