/** * Check to see if obj is an instance of the type described by sig. * @return true or false */ boolean instance_of (Object *obj, const byte cls) { byte rtCls; if (obj == null) return false; // Check for common cases if (cls == JAVA_LANG_OBJECT) return true; rtCls = get_class_index(obj); if (rtCls == cls) return true; return is_assignable(rtCls, cls); }
void handle_uncaught_exception (Object *exception, const Thread *thread, const MethodRecord *methodRecord, const MethodRecord *rootMethod, byte *pc) { printf ("*** UNCAUGHT EXCEPTION/ERROR: \n"); printf ("-- Exception class : %u\n", (unsigned) get_class_index (exception)); printf ("-- Thread : %u\n", (unsigned) thread->threadId); printf ("-- Method signature : %u\n", (unsigned) methodRecord->signatureId); printf ("-- Root method sig. : %u\n", (unsigned) rootMethod->signatureId); printf ("-- Bytecode offset : %u\n", (unsigned) pc - (int) get_code_ptr(methodRecord)); }
/** * @return 1 or 0. */ STACKWORD instance_of (Object *obj, byte classIndex) { byte rtType; if (obj == null) return 0; rtType = get_class_index(obj); // TBD: support for interfaces if (is_interface (get_class_record(classIndex))) return 1; LABEL_INSTANCE: if (rtType == classIndex) return 1; if (rtType == JAVA_LANG_OBJECT) return 0; rtType = get_class_record(rtType)->parentClass; goto LABEL_INSTANCE; }
void dispatch_virtual (Object *ref, int signature, byte *retAddr) { ClassRecord *classRecord; MethodRecord *methodRecord; int classIndex; #if DEBUG_METHODS printf("dispatch_virtual %d\n", signature); #endif if (ref == JNULL) { throw_new_exception (JAVA_LANG_NULLPOINTEREXCEPTION); return; } // When calling methods on arrays, we use the methods for the Object class... classIndex = get_class_index(ref); LABEL_METHODLOOKUP: classRecord = get_class_record (classIndex); methodRecord = find_method (classRecord, signature); if (methodRecord == null) { #if SAFE if (classIndex == JAVA_LANG_OBJECT) { throw_new_exception (JAVA_LANG_NOSUCHMETHODERROR); return; } #endif classIndex = classRecord->parentClass; goto LABEL_METHODLOOKUP; } if (dispatch_special (methodRecord, retAddr)) { if (is_synchronized(methodRecord)) { current_stackframe()->monitor = ref; enter_monitor (currentThread, ref); } } }
void dispatch_virtual (Object *ref, TWOBYTES signature, byte *retAddr) { MethodRecord *auxMethodRecord; byte auxByte; #if DEBUG_METHODS printf("dispatch_virtual %d\n", signature); #endif if (ref == JNULL) { throw_exception (nullPointerException); return; } auxByte = get_class_index(ref); LABEL_METHODLOOKUP: tempClassRecord = get_class_record (auxByte); auxMethodRecord = find_method (tempClassRecord, signature); if (auxMethodRecord == null) { #if SAFE if (auxByte == JAVA_LANG_OBJECT) { throw_exception (noSuchMethodError); return; } #endif auxByte = tempClassRecord->parentClass; goto LABEL_METHODLOOKUP; } if (dispatch_special (auxMethodRecord, retAddr)) { if (is_synchronized(auxMethodRecord)) { current_stackframe()->monitor = ref; enter_monitor (currentThread, ref); } } }
/** * @return false iff all threads are dead. */ void throw_exception (Object *exception) { Thread *auxThread; #ifdef VERIFY assert (exception != null, EXCEPTIONS0); #endif // VERIFY #if DEBUG_EXCEPTIONS printf("Throw exception\n"); #endif if (currentThread == null) { // No threads have started probably return; } else if (exception == interruptedException) { // Throwing an interrupted exception clears the flag currentThread->interruptState = INTERRUPT_CLEARED; } #ifdef VERIFY assert (currentThread->state > DEAD, EXCEPTIONS1); #endif // VERIFY gExceptionPc = pc; gExcepMethodRec = null; #if 0 trace (-1, get_class_index(exception), 3); #endif LABEL_PROPAGATE: tempStackFrame = current_stackframe(); tempMethodRecord = tempStackFrame->methodRecord; if (gExcepMethodRec == null) gExcepMethodRec = tempMethodRecord; gExceptionRecord = (ExceptionRecord *) (get_binary_base() + tempMethodRecord->exceptionTable); tempCurrentOffset = ptr2word(pc) - ptr2word(get_binary_base() + tempMethodRecord->codeOffset); #if 0 trace (-1, tempCurrentOffset, 5); #endif gNumExceptionHandlers = tempMethodRecord->numExceptionHandlers; #if DEBUG_EXCEPTIONS printf("Num exception handlers=%d\n",gNumExceptionHandlers); #endif while (gNumExceptionHandlers--) { if (gExceptionRecord->start <= tempCurrentOffset /* off by one? < ? */ && tempCurrentOffset <= gExceptionRecord->end) { // Check if exception class applies if (instance_of (exception, gExceptionRecord->classIndex)) { // Clear operand stack init_sp (tempStackFrame, tempMethodRecord); // Push the exception object push_ref (ptr2word (exception)); // Jump to handler: pc = get_binary_base() + tempMethodRecord->codeOffset + gExceptionRecord->handler; #if DEBUG_EXCEPTIONS printf("Found exception handler\n"); #endif return; } } gExceptionRecord++; } // No good handlers in current stack frame - go up. auxThread = currentThread; do_return (0); // Note: return takes care of synchronized methods. if (auxThread->state == DEAD) { #if DEBUG_EXCEPTIONS printf("Thread is dead\n"); #endif if (get_class_index(exception) != JAVA_LANG_THREADDEATH) { #if DEBUG_EXCEPTIONS printf("Handle uncaught exception\n"); #endif handle_uncaught_exception (exception, auxThread, gExcepMethodRec, tempMethodRecord, gExceptionPc); } return; } goto LABEL_PROPAGATE; }