X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libjava%2Finterpret-run.cc;h=9be08df488b42b7d1675e466d7ea1ea0319d82c9;hb=24f794d75bfb3483e0db793d07ef728fa0974620;hp=ee9fcad5a68c6a1d6def64320d007818069e17f9;hpb=6a0b579325680d39549f42b00410780c4c43c848;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libjava/interpret-run.cc b/libjava/interpret-run.cc index ee9fcad5a68..9be08df488b 100644 --- a/libjava/interpret-run.cc +++ b/libjava/interpret-run.cc @@ -1,6 +1,6 @@ // interpret-run.cc - Code to interpret bytecode -/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation +/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation This file is part of libgcj. @@ -12,6 +12,8 @@ details. */ * compiled directly. */ using namespace java::lang::reflect; + + pc_t pc = NULL; // FRAME_DESC registers this particular invocation as the top-most // interpreter frame. This lets the stack tracing code (for @@ -20,13 +22,108 @@ details. */ // destructor so it cleans up automatically when the interpreter // returns. java::lang::Thread *thread = java::lang::Thread::currentThread(); + +#ifdef DEBUG + _Jv_InterpFrame frame_desc (meth, thread, NULL, &pc); +#else _Jv_InterpFrame frame_desc (meth, thread); +#endif _Jv_word stack[meth->max_stack]; _Jv_word *sp = stack; _Jv_word locals[meth->max_locals]; +#ifdef DEBUG + // This is the information needed to get and set local variables with + // proper type checking. + frame_desc.locals = locals; + char locals_type[meth->max_locals]; + frame_desc.locals_type = locals_type; + + // Set all slots as invalid until they are written to. + memset (locals_type, 'x', meth->max_locals); + + // We need to set the local variable types for the method arguments since + // they are valid at invocation. + + _Jv_Method *method = meth->get_method (); + int type_ctr = 0; + + // If the method is non-static, we need to set the type for the "this" pointer. + if ((method->accflags & java::lang::reflect::Modifier::STATIC) == 0) + { + if (args) + { + // Set the "this" pointer for this frame. + _Jv_word *this_ptr = reinterpret_cast<_Jv_word *> (args); + frame_desc.obj_ptr = this_ptr[0].o; + } + + frame_desc.locals_type[0] = 'o'; + type_ctr++; + } + + // Now parse the method signature to set the types of the other arguments. + int sig_len = method->signature->len (); + char *signature = method->signature->chars (); + for (int i = 1; signature[i] != ')' && i <= sig_len; i++) + { + if (signature[i] == 'Z' || signature[i] == 'B' || signature[i] == 'C' + || signature[i] == 'S' || signature[i] == 'I') + { + frame_desc.locals_type[type_ctr] = 'i'; + type_ctr++; + continue; + } + else if (signature[i] == 'F') + { + frame_desc.locals_type[type_ctr] = 'f'; + type_ctr++; + continue; + } + else if (signature[i] == 'J') + { + frame_desc.locals_type[type_ctr] = 'l'; + frame_desc.locals_type[type_ctr+1] = 'x'; + type_ctr += 2; + continue; + } + else if (signature[i] == 'D') + { + frame_desc.locals_type[type_ctr] = 'd'; + frame_desc.locals_type[type_ctr+1] = 'x'; + type_ctr += 2; + continue; + } + else if (signature[i] == 'L') + { + frame_desc.locals_type[type_ctr] = 'o'; + type_ctr++; + while (signature[i] != ';') + i++; + continue; + } + else if (signature[i] == '[') + { + frame_desc.locals_type[type_ctr] = 'o'; + type_ctr++; + + // Ignore multi-dimensional arrays. + while (signature[i] == '[') + i++; + + // Check for an object array + if (signature[i] == 'L') + { + while (signature[i] != ';') + i++; + } + continue; + } + } +#endif /* DEBUG */ + #define INSN_LABEL(op) &&insn_##op static const void *const insn_target[] = @@ -217,7 +314,7 @@ details. */ INSN_LABEL(invokespecial), INSN_LABEL(invokestatic), INSN_LABEL(invokeinterface), - 0, /* Unused. */ + INSN_LABEL(breakpoint), INSN_LABEL(new), INSN_LABEL(newarray), INSN_LABEL(anewarray), @@ -244,11 +341,58 @@ details. */ #endif }; - pc_t pc; - #ifdef DIRECT_THREADED +#ifdef DEBUG +#undef NEXT_INSN +#define NEXT_INSN \ + do \ + { \ + pc_t insn = pc++; \ + if (JVMTI_REQUESTED_EVENT (SingleStep)) \ + { \ + JNIEnv *env = _Jv_GetCurrentJNIEnv (); \ + jmethodID method = meth->self; \ + jlocation loc = meth->insn_index (insn); \ + _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \ + env, method, loc); \ + } \ + goto *(insn->insn); \ + } \ + while (0) + +#undef REWRITE_INSN +#define REWRITE_INSN(INSN,SLOT,VALUE) \ + do { \ + if (pc[-2].insn == breakpoint_insn->insn) \ + { \ + using namespace ::gnu::gcj::jvmti; \ + jlocation location = meth->insn_index (pc - 2); \ + _Jv_RewriteBreakpointInsn (meth->self, location, (pc_t) INSN); \ + } \ + else \ + pc[-2].insn = INSN; \ + \ + pc[-1].SLOT = VALUE; \ + } \ + while (0) + +#undef INTERP_REPORT_EXCEPTION +#define INTERP_REPORT_EXCEPTION(Jthrowable) REPORT_EXCEPTION (Jthrowable) +#else // !DEBUG +#undef NEXT_INSN #define NEXT_INSN goto *((pc++)->insn) +#define REWRITE_INSN(INSN,SLOT,VALUE) \ + do { \ + pc[-2].insn = INSN; \ + pc[-1].SLOT = VALUE; \ + } \ + while (0) + +#undef INTERP_REPORT_EXCEPTION +#define INTERP_REPORT_EXCEPTION(Jthrowable) /* not needed when not debugging */ +#endif // !DEBUG + #define INTVAL() ((pc++)->int_val) #define AVAL() ((pc++)->datum) @@ -281,7 +425,22 @@ details. */ #else +#ifdef DEBUG +#define NEXT_INSN \ + do \ + { \ + if (JVMTI_REQUESTED_EVENT (SingleStep)) \ + { \ + JNIEnv *env = _Jv_GetCurrentJNIEnv (); \ + jmethodID method = meth->self; \ + jlocation loc = meth->insn_index (pc); \ + _Jv_JVMTI_PostEvent (JVMTI_EVENT_SINGLE_STEP, thread, \ + env, method, loc); \ + } \ + goto *(insn_target[*pc++]) +#else #define NEXT_INSN goto *(insn_target[*pc++]) +#endif #define GET1S() get1s (pc++) #define GET2S() (pc += 2, get2s (pc- 2)) @@ -291,10 +450,10 @@ details. */ // class'. #define AVAL1U() \ ({ int index = get1u (pc++); \ - resolve_pool_entry (meth->defining_class, index).o; }) + _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; }) #define AVAL2U() \ ({ int index = get2u (pc); pc += 2; \ - resolve_pool_entry (meth->defining_class, index).o; }) + _Jv_Linker::resolve_pool_entry (meth->defining_class, index).o; }) // Note that we don't need to resolve the pool entry here as class // constants are never wide. #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; }) @@ -303,7 +462,7 @@ details. */ #define PCVAL(unionval) unionval.i #define AMPAMP(label) NULL - pc = bytecode (); + pc = meth->bytecode (); #endif /* DIRECT_THREADED */ @@ -381,8 +540,7 @@ details. */ #ifdef DIRECT_THREADED // Rewrite instruction so that we use a faster pre-resolved // method. - pc[-2].insn = &&invokevirtual_resolved; - pc[-1].datum = rmeth; + REWRITE_INSN (&&invokevirtual_resolved, datum, rmeth); #endif /* DIRECT_THREADED */ } goto perform_invoke; @@ -1545,7 +1703,7 @@ details. */ pc_t base_pc = pc - 1; int index = POPI (); - pc_t base = (pc_t) bytecode (); + pc_t base = (pc_t) meth->bytecode (); while ((pc - base) % 4 != 0) ++pc; @@ -1601,7 +1759,7 @@ details. */ unsigned char *base_pc = pc-1; int index = POPI(); - unsigned char* base = bytecode (); + unsigned char* base = meth->bytecode (); while ((pc-base) % 4 != 0) ++pc; @@ -1716,8 +1874,7 @@ details. */ } #ifdef DIRECT_THREADED - pc[-2].insn = newinsn; - pc[-1].datum = field->u.addr; + REWRITE_INSN (newinsn, datum, field->u.addr); #endif /* DIRECT_THREADED */ } NEXT_INSN; @@ -1807,8 +1964,7 @@ details. */ } #ifdef DIRECT_THREADED - pc[-2].insn = newinsn; - pc[-1].int_val = field_offset; + REWRITE_INSN (newinsn, int_val, field_offset); #endif /* DIRECT_THREADED */ } NEXT_INSN; @@ -1923,8 +2079,7 @@ details. */ } #ifdef DIRECT_THREADED - pc[-2].insn = newinsn; - pc[-1].datum = field->u.addr; + REWRITE_INSN (newinsn, datum, field->u.addr); #endif /* DIRECT_THREADED */ } NEXT_INSN; @@ -2022,8 +2177,7 @@ details. */ } #ifdef DIRECT_THREADED - pc[-2].insn = newinsn; - pc[-1].int_val = field_offset; + REWRITE_INSN (newinsn, int_val, field_offset); #endif /* DIRECT_THREADED */ } NEXT_INSN; @@ -2098,8 +2252,7 @@ details. */ #ifdef DIRECT_THREADED // Rewrite instruction so that we use a faster pre-resolved // method. - pc[-2].insn = &&invokespecial_resolved; - pc[-1].datum = rmeth; + REWRITE_INSN (&&invokespecial_resolved, datum, rmeth); #endif /* DIRECT_THREADED */ } goto perform_invoke; @@ -2136,8 +2289,7 @@ details. */ #ifdef DIRECT_THREADED // Rewrite instruction so that we use a faster pre-resolved // method. - pc[-2].insn = &&invokestatic_resolved; - pc[-1].datum = rmeth; + REWRITE_INSN (&&invokestatic_resolved, datum, rmeth); #endif /* DIRECT_THREADED */ } goto perform_invoke; @@ -2175,8 +2327,7 @@ details. */ #ifdef DIRECT_THREADED // Rewrite instruction so that we use a faster pre-resolved // method. - pc[-2].insn = &&invokeinterface_resolved; - pc[-1].datum = rmeth; + REWRITE_INSN (&&invokeinterface_resolved, datum, rmeth); #else // Skip dummy bytes. pc += 2; @@ -2209,13 +2360,16 @@ details. */ /* VM spec, section 3.11.5 */ if ((klass->getModifiers() & Modifier::ABSTRACT) || klass->isInterface()) - throw new java::lang::InstantiationException; + { + jthrowable t = new java::lang::InstantiationException; + INTERP_REPORT_EXCEPTION (t); + throw t; + } jobject res = _Jv_AllocObject (klass); PUSHA (res); #ifdef DIRECT_THREADED - pc[-2].insn = &&new_resolved; - pc[-1].datum = klass; + REWRITE_INSN (&&new_resolved, datum, klass); #endif /* DIRECT_THREADED */ } NEXT_INSN; @@ -2250,8 +2404,7 @@ details. */ PUSHA (result); #ifdef DIRECT_THREADED - pc[-2].insn = &&anewarray_resolved; - pc[-1].datum = klass; + REWRITE_INSN (&&anewarray_resolved, datum, klass); #endif /* DIRECT_THREADED */ } NEXT_INSN; @@ -2278,7 +2431,9 @@ details. */ insn_athrow: { jobject value = POPA(); - throw static_cast(value); + jthrowable t = static_cast (value); + INTERP_REPORT_EXCEPTION (t); + throw t; } NEXT_INSN; @@ -2295,8 +2450,7 @@ details. */ PUSHA (value); #ifdef DIRECT_THREADED - pc[-2].insn = &&checkcast_resolved; - pc[-1].datum = to; + REWRITE_INSN (&&checkcast_resolved, datum, to); #endif /* DIRECT_THREADED */ } NEXT_INSN; @@ -2323,8 +2477,7 @@ details. */ PUSHI (to->isInstance (value)); #ifdef DIRECT_THREADED - pc[-2].insn = &&instanceof_resolved; - pc[-1].datum = to; + REWRITE_INSN (&&instanceof_resolved, datum, to); #endif /* DIRECT_THREADED */ } NEXT_INSN; @@ -2463,45 +2616,59 @@ details. */ } #endif /* DIRECT_THREADED */ - } - catch (java::lang::Throwable *ex) - { -#ifdef DIRECT_THREADED - void *logical_pc = (void *) ((insn_slot *) pc - 1); -#else - int logical_pc = pc - 1 - bytecode (); -#endif - _Jv_InterpException *exc = meth->exceptions (); - jclass exc_class = ex->getClass (); - for (int i = 0; i < meth->exc_count; i++) - { - if (PCVAL (exc[i].start_pc) <= logical_pc - && logical_pc < PCVAL (exc[i].end_pc)) - { -#ifdef DIRECT_THREADED - jclass handler = (jclass) exc[i].handler_type.p; -#else - jclass handler = NULL; - if (exc[i].handler_type.i != 0) - handler = (_Jv_Linker::resolve_pool_entry (defining_class, - exc[i].handler_type.i)).clazz; -#endif /* DIRECT_THREADED */ + insn_breakpoint: + { + JvAssert (JVMTI_REQUESTED_EVENT (Breakpoint)); - if (handler == NULL || handler->isAssignableFrom (exc_class)) - { + // Send JVMTI notification + using namespace ::java::lang; + jmethodID method = meth->self; + jlocation location = meth->insn_index (pc - 1); + Thread *thread = Thread::currentThread (); + JNIEnv *jni_env = _Jv_GetCurrentJNIEnv (); + + // Save the insn here since the breakpoint could be removed + // before the JVMTI notification returns. + using namespace gnu::gcj::jvmti; + Breakpoint *bp + = BreakpointManager::getBreakpoint (reinterpret_cast (method), + location); + JvAssert (bp != NULL); + pc_t opc = reinterpret_cast (bp->getInsn ()); + + _Jv_JVMTI_PostEvent (JVMTI_EVENT_BREAKPOINT, thread, jni_env, + method, location); + // Continue execution #ifdef DIRECT_THREADED - pc = (insn_slot *) exc[i].handler_pc.p; + goto *(opc->insn); #else - pc = bytecode () + exc[i].handler_pc.i; -#endif /* DIRECT_THREADED */ - sp = stack; - sp++->o = ex; // Push exception. - NEXT_INSN; - } - } - } + goto *(insn_target[*opc]); +#endif + } + } + catch (java::lang::Throwable *ex) + { + // Check if the exception is handled and, if so, set the pc to the start + // of the appropriate catch block. + if (meth->check_handler (&pc, meth, ex)) + { + sp = stack; + sp++->o = ex; // Push exception. +#ifdef DEBUG + if (JVMTI_REQUESTED_EVENT (ExceptionCatch)) + { + using namespace gnu::gcj::jvmti; + jlong catch_meth = reinterpret_cast (meth->get_method ()); + jlong catch_loc = meth->insn_index (pc); + _Jv_JVMTI_PostEvent (JVMTI_EVENT_EXCEPTION_CATCH, thread, + _Jv_GetCurrentJNIEnv (), catch_meth, + catch_loc, ex); + } +#endif + NEXT_INSN; + } // No handler, so re-throw. throw ex;