📄 frame.c
字号:
#if ENABLE_JAVA_DEBUGGER START_TEMPORARY_ROOTS DECLARE_TEMPORARY_FRAME_ROOT(saveFp, (getFP())); DECLARE_TEMPORARY_FRAME_ROOT(thisFP, (getFP())); BYTE *saveIp;#else FRAME thisFP;#endif BYTE* thisIP; OBJECT synchronized; unsigned short ipOffset = 0; /* The KVM has already updated the program counter in the saved pc of * method calls. So we need to correct the pc for all frames except * the top one, and the ones just below RunCustomCode * * But if we're running a native method, then there's a missing frame * at the top (we don't push frames for native methods), so we need * the correction. */ int ipCorrection = (CurrentNativeMethod == NULL) ? 0 : 1;restartOnError: thisFP = getFP(); thisIP = getIP();#if ENABLE_JAVA_DEBUGGER saveIp = thisIP; saveFp = thisFP;#endif if (CurrentThread == NULL) { /* If we don't have any active threads in the system, there is no point * in trying to unwind stack frames. Print the detailed error message * contained in the second slot of the exception option and then exit. * (this code should get executed only if there is an exception before * the VM has started properly). */ STRING_INSTANCE string = unhand(exceptionH)->message; if (string != NULL) { fatalError(getStringContents(string)); } ERROR_THROW(-1); }#if INCLUDEDEBUGCODE if (traceexceptions) { Log->throwException(unhand(exceptionH)); }#endif while (thisFP != NULL) { /* Check if the current execution frame/method */ /* has an exception handler table */ METHOD thisMethod = thisFP->thisMethod; HANDLERTABLE handlerTable = thisMethod->u.java.handlers; if (handlerTable != NULL) { HANDLER thisHandler; START_TEMPORARY_ROOTS INSTANCE_CLASS thisClass = thisFP->thisMethod->ofClass ; DECLARE_TEMPORARY_FRAME_ROOT(thisFPx, thisFP); ipOffset = thisIP - thisMethod->u.java.code; thisHandler = findHandler(thisClass, handlerTable, exceptionH, (unsigned short)(ipOffset - ipCorrection)); thisFP = thisFPx; END_TEMPORARY_ROOTS if (thisHandler != NULL) { #if INCLUDEDEBUGCODE if ((tracemethodcalls || tracemethodcallsverbose) && getFP() != thisFP) { exceptionCaughtTracing(exceptionH, thisHandler); }#endif /* INCLUDEDEBUGCODE */ setFP(thisFP); setIP(thisMethod->u.java.code + thisHandler->handlerPC); setLP(FRAMELOCALS(thisFP)); setCP(thisFP->thisMethod->ofClass->constPool); setStackHeight(1); topStackAsType(THROWABLE_INSTANCE) = unhand(exceptionH);#if ENABLE_JAVA_DEBUGGER START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(THREAD, thisThread, CurrentThread); if (vmDebugReady) { CEModPtr cep = GetCEModifier(); cep->exp.classID = GET_CLASS_DEBUGGERID(&((THROWABLE_INSTANCE)unhand(exceptionH))->ofClass->clazz); cep->exp.sig_caught = TRUE; cep->exp.sig_uncaught = FALSE; cep->threadID = getObjectID((OBJECT)thisThread->javaThread); setEvent_Exception(exceptionH, saveFp, saveIp, thisMethod, (unsigned long)thisHandler->handlerPC, cep); FreeCEModifier(cep); } END_TEMPORARY_ROOTS#endif /* ENABLE_JAVA_DEBUGGER */ goto leave; } } else if (thisMethod == RunCustomCodeMethod) { START_TEMPORARY_ROOTS DECLARE_TEMPORARY_FRAME_ROOT(thisFPx, thisFP); void **bottomStack = (void **)(thisFPx + 1); CustomCodeCallbackFunction func = (CustomCodeCallbackFunction)(bottomStack[0]); /* Overwrite the slot contain callback function with error */ bottomStack[0] = unhand(exceptionH); func(&thisFPx); /* may GC */ thisFP = thisFPx; bottomStack = (void **)(thisFP + 1); /* in case of GC */ unhand(exceptionH) = bottomStack[0]; END_TEMPORARY_ROOTS } synchronized = thisFP->syncObject; if (synchronized != NULL) { char *errorIfFailure; enum MonitorStatusType result = monitorExit(synchronized, &errorIfFailure); thisFP->syncObject = NULL; if (result == MonitorStatusError) { setFP(thisFP); setIP(thisIP); setStackHeight(0); /* GC's may be confused if we don't adjust */ unhand(exceptionH) = (THROWABLE_INSTANCE)instantiate((INSTANCE_CLASS)getClass(errorIfFailure)); goto restartOnError; } } thisIP = thisFP->previousIp; thisFP = thisFP->previousFp; ipCorrection = (thisMethod == RunCustomCodeMethod) ? 0 : 1; } /* If we've gotten here, then there is no exception handler */ /* in any of the stack frames on the stack. In debug mode, */ /* we'll report an uncaught exception. */#if INCLUDEDEBUGCODE Log->uncaughtException(unhand(exceptionH));#endif#if ENABLE_JAVA_DEBUGGER START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(THREAD, thisThread, CurrentThread); if (vmDebugReady) { CEModPtr cep = GetCEModifier(); cep->exp.classID = GET_CLASS_DEBUGGERID(&((THROWABLE_INSTANCE)unhand(exceptionH))->ofClass->clazz); cep->exp.sig_caught = FALSE; cep->exp.sig_uncaught = TRUE; cep->threadID = getObjectID((OBJECT)thisThread->javaThread); setEvent_Exception(exceptionH, saveFp, saveIp, NIL, (unsigned long)0, cep); FreeCEModifier(cep); } if (CurrentThread == NIL) { /* * suspended via the debugger when the event was sent. */ DismantleThread(thisThread); } else { stopThread(); /* If the VM has no more threads to run, exit immediately */ if (AliveThreadCount == 0 && AllThreads == NULL) { ERROR_THROW(FATAL_ERROR_EXIT_CODE); } } END_TEMPORARY_ROOTSleave: END_TEMPORARY_ROOTS /* this matches the one at the very top */#else#if INCLUDEDEBUGCODE printExceptionStackTrace(exceptionH);#endif stopThread(); /* If the VM has no more threads to run, exit immediately */ if (AliveThreadCount == 0 && AllThreads == NULL) { ERROR_THROW(FATAL_ERROR_EXIT_CODE); }leave: ;#endif /* ENABLE_JAVA_DEBUGGER */}/*========================================================================= * Operations for raising exceptions and errors from within the VM * (see the detailed comparison of these operations in frame.h) *=======================================================================*//*========================================================================= * FUNCTION: raiseException() * TYPE: internal exception handling operation * OVERVIEW: Raise an exception. This operation is intended * to be used from within the VM only. It should * be used for reporting only those exceptions and * errors that are known to be "safe" and "harmless", * i.e., the internal consistency and integrity of * the VM should not be endangered in any way. * * Upon execution, the operation tries to load the * exception class with the given name, instantiate an * instance of that class, and * passes the object to the exception handler routines * of the VM. The operation will fail if the class can't * be found or there is not enough memory to load it or * create an instance of it. * INTERFACE: * parameters: exception class name * returns: <nothing> * NOTE: Since this operation needs to allocate two new objects * it should not be used for reporting memory-related * problems. *=======================================================================*/void raiseException(const char* exceptionClassName){ INSTANCE_CLASS exceptionClass= (INSTANCE_CLASS)getClass(exceptionClassName); if (exceptionClass == NULL) { sprintf(str_buffer, KVM_MSG_ILLEGAL_EXCEPTION_NAME_1STRPARAM, exceptionClassName); AlertUser(str_buffer); exceptionClass = JavaLangThrowable; } START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(THROWABLE_INSTANCE, exception, (THROWABLE_INSTANCE)instantiate(exceptionClass)); if (exception != NULL) { /* Otherwise, we will have already thrown an OutOfMemoryError */ /* Add to this exception the backtrace using the current stack */#if PRINT_BACKTRACE fillInStackTrace(&exception);#endif throwException(&exception); } END_TEMPORARY_ROOTS}/*========================================================================= * FUNCTION: raiseExceptionMsg() * TYPE: internal exception handling operation * OVERVIEW: Raise an exception with a message. This operation is intended * to be used from within the VM only. It should * be used for reporting only those exceptions and * errors that are known to be "safe" and "harmless", * i.e., the internal consistency and integrity of * the VM should not be endangered in any way. * * Upon execution, the operation tries to load the * exception class with the given name, instantiate an * instance of that class, and * passes the object to the exception handler routines * of the VM. The operation will fail if the class can't * be found or there is not enough memory to load it or * create an instance of it. * INTERFACE: * parameters: exception class name * String message * returns: <nothing> * NOTE: Since this operation needs to allocate two new objects * it should not be used for reporting memory-related * problems. *=======================================================================*/void raiseExceptionMsg(const char* exceptionClassName, STRING_INSTANCE msgArg){ START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(STRING_INSTANCE, msg, msgArg); INSTANCE_CLASS exceptionClass = (INSTANCE_CLASS)getClass(exceptionClassName); DECLARE_TEMPORARY_ROOT(THROWABLE_INSTANCE, exception, (THROWABLE_INSTANCE)instantiate(exceptionClass)); if (exception != NULL) { /* Otherwise, we will have already thrown an OutOfMemoryError */ /* Add to this exception the backtrace using the current stack */#if PRINT_BACKTRACE fillInStackTrace(&exception);#endif /* Store the String into the exception. */ exception->message = msg; throwException(&exception); } END_TEMPORARY_ROOTS}/*========================================================================= * FUNCTION: fatalVMError() * TYPE: internal error handling operation * OVERVIEW: Report a fatal error indicating that some severe * unexpected situation has been encountered by the VM. * This may be due to a bug in the VM. VM execution will * be stopped. This operation should be called only from * inside the VM. * INTERFACE: * parameters: error message string * returns: <nothing> *=======================================================================*/void fatalVMError(const char* errorMessage){ if (INCLUDEDEBUGCODE) { printVMstatus(); } fatalError(errorMessage);}/*========================================================================= * FUNCTION: fatalError() * TYPE: internal error handling operation * OVERVIEW: Report a fatal error indicating that the execution * of erroneous Java code might have endangered the * integrity of the VM. VM will be stopped. This * operation should be called only the from inside the VM. * INTERFACE: * parameters: error message string. * returns: <nothing> *=======================================================================*/void fatalError(const char* errorMessage){ AlertUser(errorMessage); ERROR_THROW(FATAL_ERROR_EXIT_CODE);}/*========================================================================= * Stack tracing operations *=======================================================================*/#if INCLUDEDEBUGCODE/*========================================================================= * FUNCTION: frameDepth(); * OVERVIEW: Returns the current stack depth of the Java stack. * INTERFACE: * parameters: none * returns: depth * * COMMENTS: Do not call this function is fp == 0. *=======================================================================*/static intframeDepth() { int depth = 0; FRAME thisFP = getFP(); while (thisFP->previousIp != KILLTHREAD) { depth++; thisFP = thisFP->previousFp; } return depth;}/*========================================================================= * FUNCTION: frameTracing(); * OVERVIEW: Print a message to stdout indicating that a frame has * been entered or exited. * INTERFACE: * parameters: method: Method we're calling * glyph: "=>" or "<=" * offset: Actual depth is frameDepth() + offset *=======================================================================*/void frameTracing(METHOD method, char *glyph, int offset) { ASSERTING_NO_ALLOCATION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -