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)); }
/** * @param classRecord Record for method class. * @param methodRecord Calle's method record. * @param retAddr What the PC should be upon return. * @return true iff the stack frame was pushed. */ boolean dispatch_special (MethodRecord *methodRecord, byte *retAddr) { #if DEBUG_METHODS int debug_ctr; #endif StackFrame *stackFrame; byte newStackFrameIndex; #if DEBUG_BYTECODE printf ("\n------ dispatch special - %d ------------------\n\n", methodRecord->signatureId); #endif #if DEBUG_METHODS printf ("dispatch_special: %d, %d\n", (int) methodRecord, (int) retAddr); printf ("-- signature id = %d\n", methodRecord->signatureId); printf ("-- code offset = %d\n", methodRecord->codeOffset); printf ("-- flags = %d\n", methodRecord->mflags); printf ("-- num params = %d\n", methodRecord->numParameters); printf ("-- stack ptr = %d\n", (int) get_stack_ptr()); printf ("-- max stack ptr= %d\n", (int) (currentThread->stackArray + (get_array_size(currentThread->stackArray))*2)); #endif pop_words (methodRecord->numParameters); pc = retAddr; if (is_native (methodRecord)) { #if DEBUG_METHODS printf ("-- native\n"); #endif dispatch_native (methodRecord->signatureId, get_stack_ptr() + 1); // Stack frame not pushed return false; } newStackFrameIndex = currentThread->stackFrameArraySize; if (newStackFrameIndex >= get_array_length((Object *) word2ptr (currentThread->stackFrameArray))) { #if !FIXED_STACK_SIZE // int len = get_array_length((Object *) word2ptr (currentThread->stackFrameArray)); int newlen = get_array_length((Object *) word2ptr (currentThread->stackFrameArray)) * 3 / 2; JINT newStackFrameArray = JNULL; // Stack frames are indexed by a byte value so limit the size. if (newlen <= 255) { // increase the stack frame size newStackFrameArray = ptr2word(reallocate_array(word2ptr(currentThread->stackFrameArray), newlen)); } // If can't allocate new stack, give in! if (newStackFrameArray == JNULL) { #endif throw_exception (stackOverflowError); return false; #if !FIXED_STACK_SIZE } // Assign new array currentThread->stackFrameArray = newStackFrameArray; #endif } if (newStackFrameIndex == 0) { // Assign NEW stack frame stackFrame = stackframe_array(); } else { #if DEBUG_METHODS for (debug_ctr = 0; debug_ctr < methodRecord->numParameters; debug_ctr++) printf ("-- param[%d] = %ld\n", debug_ctr, (long) get_stack_ptr()[debug_ctr+1]); #endif // Save OLD stackFrame state stackFrame = stackframe_array() + (newStackFrameIndex - 1); update_stack_frame (stackFrame); // Push NEW stack frame stackFrame++; } // Increment size of stack frame array currentThread->stackFrameArraySize++; // Initialize rest of new stack frame stackFrame->methodRecord = methodRecord; stackFrame->monitor = null; stackFrame->localsBase = get_stack_ptr() + 1; // Initialize auxiliary global variables (registers) pc = get_code_ptr(methodRecord); #if DEBUG_METHODS printf ("pc set to 0x%X\n", (int) pc); #endif init_sp (stackFrame, methodRecord); update_constant_registers (stackFrame); //printf ("m %d stack = %d\n", (int) methodRecord->signatureId, (int) (localsBase - stack_array())); // Check for stack overflow // (stackTop + methodRecord->maxOperands) >= (stack_array() + STACK_SIZE); if (is_stack_overflow (methodRecord)) { #if !FIXED_STACK_SIZE StackFrame *stackBase; int i; // Need at least this many bytes // int len = (int)(stackTop + methodRecord->maxOperands) - (int)(stack_array()) - HEADER_SIZE; // Need to compute new array size (as distinct from number of bytes in array). int newlen = (((int)(stackTop + methodRecord->maxOperands) - (int)(stack_array()) - HEADER_SIZE + 1) / 4) * 3 / 2; JINT newStackArray = ptr2word(reallocate_array(word2ptr(currentThread->stackArray), newlen)); // If can't allocate new stack, give in! if (newStackArray == JNULL) { #endif throw_exception (stackOverflowError); return false; #if !FIXED_STACK_SIZE } // Adjust pointers. newlen = newStackArray - currentThread->stackArray; stackBase = stackframe_array(); stackTop = word2ptr(ptr2word(stackTop) + newlen); localsBase = word2ptr(ptr2word(localsBase) + newlen); #if DEBUG_MEMORY printf("thread=%d, stackTop(%d), localsBase(%d)=%d\n", currentThread->threadId, (int)stackTop, (int)localsBase, (int)(*localsBase)); #endif for (i=currentThread->stackFrameArraySize-1; i >= 0; i--) { stackBase[i].localsBase = word2ptr(ptr2word(stackBase[i].localsBase) + newlen); stackBase[i].stackTop = word2ptr(ptr2word(stackBase[i].stackTop) + newlen); #if DEBUG_MEMORY printf("stackBase[%d].localsBase(%d) = %d\n", i, (int)stackBase[i].localsBase, (int)(*stackBase[i].localsBase)); #endif } // Assign new array currentThread->stackArray = newStackArray; #endif } return true; }
/** * @param classRecord Record for method class. * @param methodRecord Calle's method record. * @param retAddr What the PC should be upon return. * @return true iff the stack frame was pushed. */ boolean dispatch_special (MethodRecord *methodRecord, byte *retAddr) { /** * Note: This code is a little tricky, particularly when used with * a garbage collector. It manipulates the stack frame and in some cases * may need to perform memory allocation. In all cases we must take care * to ensure that if an allocation can be made then any live objects * on the stack must be below the current stack pointer. * In addition to the above we take great care so that this function can * be restarted (to allow us to wait for available memory). To enable this * we avoid making any commitments to changes to global state until both * stacks have been commited. */ #if DEBUG_METHODS int debug_ctr; #endif Object *stackFrameArray; StackFrame *stackFrame; StackFrame *stackBase; int newStackFrameIndex; STACKWORD *newStackTop; #if DEBUG_BYTECODE printf("call method %d ret %x\n", methodRecord - get_method_table(get_class_record(0)), retAddr); printf ("\n------ dispatch special - %d ------------------\n\n", methodRecord->signatureId); #endif #if DEBUG_METHODS printf ("dispatch_special: %d, %d\n", (int) methodRecord, (int) retAddr); printf ("-- signature id = %d\n", methodRecord->signatureId); printf ("-- code offset = %d\n", methodRecord->codeOffset); printf ("-- flags = %d\n", methodRecord->mflags); printf ("-- num params = %d\n", methodRecord->numParameters); //printf ("-- stack ptr = %d\n", (int) get_stack_ptr()); //printf ("-- max stack ptr= %d\n", (int) (currentThread->stackArray + (get_array_size(currentThread->stackArray))*2)); #endif // First deal with the easy case of a native call... if (is_native (methodRecord)) { #if DEBUG_METHODS printf ("-- native\n"); #endif // WARNING: Once the instruction below has been executed we may have // references on the stack that are above the stack pointer. If a GC // gets run when in this state the reference may get collected as // grabage. This means that any native functions that take a reference // parameter and that may end up allocating memory *MUST* protect that // reference before calling the allocator... pop_words_cur (methodRecord->numParameters); switch(dispatch_native (methodRecord->signatureId, get_stack_ptr_cur() + 1)) { case EXEC_RETRY: // Need to re-start the instruction, so reset the state of the stack curStackTop += methodRecord->numParameters; break; case EXEC_CONTINUE: // Normal completion return to the requested point. curPc = retAddr; break; case EXEC_RUN: // We are running new code, curPc will be set. Nothing to do. break; case EXEC_EXCEPTION: // An exception has been thrown. The PC will be set correctly and // the stack may have been adjusted... break; } // Stack frame not pushed return false; } // Now start to build the new stack frames. We start by placing the // the new stack pointer below any params. The params will become locals // in the new frame. newStackTop = get_stack_ptr_cur() - methodRecord->numParameters; newStackFrameIndex = (int)(byte)currentThread->stackFrameIndex; if (newStackFrameIndex >= 255) { throw_new_exception (JAVA_LANG_STACKOVERFLOWERROR); return false; } #if DEBUG_METHODS //for (debug_ctr = 0; debug_ctr < methodRecord->numParameters; debug_ctr++) // printf ("-- param[%d] = %ld\n", debug_ctr, (long) get_stack_ptr()[debug_ctr+1]); #endif stackFrameArray = ref2obj(currentThread->stackFrameArray); stackBase = (StackFrame *)array_start(stackFrameArray); // Setup OLD stackframe ready for return stackFrame = stackBase + (newStackFrameIndex); stackFrame->stackTop = newStackTop; stackFrame->pc = retAddr; // Push NEW stack frame // Increment size of stack frame array but do not commit to it until we have // completely built both new stacks. newStackFrameIndex++; stackFrame++; if (((byte *)stackFrame - (byte *)stackBase) >= get_array_length(stackFrameArray)) { #if FIXED_STACK_SIZE throw_new_exception (JAVA_LANG_STACKOVERFLOWERROR); return false; #else if (expand_call_stack(currentThread) < 0) return false; stackFrame = (StackFrame *)array_start(currentThread->stackFrameArray) + newStackFrameIndex; #endif } // Initialize rest of new stack frame stackFrame->methodRecord = methodRecord; stackFrame->monitor = null; stackFrame->localsBase = newStackTop + 1; // Allocate space for locals etc. newStackTop = init_sp(stackFrame, methodRecord); stackFrame->stackTop = newStackTop; currentThread->stackFrameIndex = newStackFrameIndex; // Check for stack overflow if (is_stack_overflow (newStackTop, methodRecord)) { #if FIXED_STACK_SIZE throw_new_exception (JAVA_LANG_STACKOVERFLOWERROR); return false; #else if (expand_value_stack(currentThread, methodRecord->maxOperands+methodRecord->numLocals) < 0) { currentThread->stackFrameIndex--; return false; } // NOTE at this point newStackTop is no longer valid! newStackTop = stackFrame->stackTop; #endif } // All set. So now we can finally commit to the new stack frames update_constant_registers (stackFrame); curStackTop = newStackTop; // and jump to the start of the new code curPc = get_code_ptr(methodRecord); return true; }