diff options
author | Kyle Galloway <kgallowa@redhat.com> | 2007-04-02 13:45:52 +0000 |
---|---|---|
committer | Kyle Galloway <kgallowa@gcc.gnu.org> | 2007-04-02 13:45:52 +0000 |
commit | bfd6b6cb22d3749997c42d30a1030827d275a7b7 (patch) | |
tree | 9b7cc1b138514f8f786690b4f8a0406922ece04b | |
parent | c6756b72575a6e705a754474d476f4fb9b838b33 (diff) | |
download | gcc-bfd6b6cb22d3749997c42d30a1030827d275a7b7.zip gcc-bfd6b6cb22d3749997c42d30a1030827d275a7b7.tar.gz gcc-bfd6b6cb22d3749997c42d30a1030827d275a7b7.tar.bz2 |
interpret-run.cc: Add code to properly set up variable slots when debugging.
2007-04-02 Kyle Galloway <kgallowa@redhat.com>
* interpret-run.cc: Add code to properly set up variable slots
when debugging.
* gnu/classpath/jdwp/natVMFrame.cc (checkJVMTIError): New function.
(getObjectJVMTI): New function.
(setObjectJVMTI): New function.
(getIntJVMTI): New function.
(setIntJVMTI): New function.
(getLongJVMTI): New function.
(setLongJVMTI): New function.
(getFloatJVMTI): New function.
(setFloatJVMTI): New function.
(getDoubleJVMTI): New function.
(setDoubleJVMTI): New function.
(getFrameDepth): New function.
(getValue): Implement.
(setValue): Implement.
From-SVN: r123427
-rw-r--r-- | libjava/ChangeLog | 19 | ||||
-rw-r--r-- | libjava/gnu/classpath/jdwp/natVMFrame.cc | 307 | ||||
-rw-r--r-- | libjava/interpret-run.cc | 94 |
3 files changed, 401 insertions, 19 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 86b682a..bc7e363 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,5 +1,24 @@ 2007-04-02 Kyle Galloway <kgallowa@redhat.com> + * interpret-run.cc: Add code to properly set up variable slots + when debugging. + * gnu/classpath/jdwp/natVMFrame.cc (checkJVMTIError): New function. + (getObjectJVMTI): New function. + (setObjectJVMTI): New function. + (getIntJVMTI): New function. + (setIntJVMTI): New function. + (getLongJVMTI): New function. + (setLongJVMTI): New function. + (getFloatJVMTI): New function. + (setFloatJVMTI): New function. + (getDoubleJVMTI): New function. + (setDoubleJVMTI): New function. + (getFrameDepth): New function. + (getValue): Implement. + (setValue): Implement. + +2007-04-02 Kyle Galloway <kgallowa@redhat.com> + * classpath/gnu/classpath/jdwp/processor/ThreadReferenceCommandSet.java (executeResume): Call VMVirtualMachine.resumeThread. diff --git a/libjava/gnu/classpath/jdwp/natVMFrame.cc b/libjava/gnu/classpath/jdwp/natVMFrame.cc index 894791c..e32e733 100644 --- a/libjava/gnu/classpath/jdwp/natVMFrame.cc +++ b/libjava/gnu/classpath/jdwp/natVMFrame.cc @@ -8,23 +8,316 @@ This software is copyrighted work licensed under the terms of the Libgcj License. Please consult the file "LIBGCJ_LICENSE" for details. */ +#include <config.h> #include <gcj/cni.h> #include <jvm.h> +#include <jvmti.h> +#include "jvmti-int.h" + +#include <java-interp.h> #include <gnu/classpath/jdwp/VMFrame.h> +#include <gnu/classpath/jdwp/VMVirtualMachine.h> +#include <gnu/classpath/jdwp/exception/InvalidFrameException.h> +#include <gnu/classpath/jdwp/exception/InvalidSlotException.h> +#include <gnu/classpath/jdwp/exception/InvalidThreadException.h> +#include <gnu/classpath/jdwp/exception/JdwpInternalErrorException.h> +#include <gnu/classpath/jdwp/exception/TypeMismatchException.h> +#include <gnu/classpath/jdwp/util/NullObject.h> +#include <gnu/classpath/jdwp/value/ByteValue.h> +#include <gnu/classpath/jdwp/value/BooleanValue.h> +#include <gnu/classpath/jdwp/value/CharValue.h> +#include <gnu/classpath/jdwp/value/DoubleValue.h> +#include <gnu/classpath/jdwp/value/FloatValue.h> +#include <gnu/classpath/jdwp/value/IntValue.h> +#include <gnu/classpath/jdwp/value/LongValue.h> +#include <gnu/classpath/jdwp/value/ObjectValue.h> +#include <gnu/classpath/jdwp/value/ShortValue.h> #include <gnu/classpath/jdwp/value/Value.h> +#include <gnu/classpath/jdwp/value/VoidValue.h> using namespace java::lang; +using namespace gnu::classpath::jdwp; +using namespace gnu::classpath::jdwp::exception; + -gnu::classpath::jdwp::value::Value * -gnu::classpath::jdwp::VMFrame::getValue (MAYBE_UNUSED jint slot, - MAYBE_UNUSED jbyte tag) +// All the jvmti GetLocalXX and SetLocalXX functions return the same potential +// errors, so this function handles them all and throws the appropriate JDWP +// exception. +static void +checkJVMTIError (jvmtiEnv *env, jthread thread, jvmtiError jerr, jint slot, + jbyte sig) { - return 0; + if (jerr != JVMTI_ERROR_NONE) + { + char *error; + env->GetErrorName (jerr, &error); + String *msg = reinterpret_cast<String *> (JvNewStringUTF (error)); + env->Deallocate ((unsigned char *) error); + + if (jerr == JVMTI_ERROR_INVALID_THREAD) + throw new InvalidThreadException ((jlong) thread); + else if (jerr == JVMTI_ERROR_NO_MORE_FRAMES) + throw new InvalidFrameException (msg); + else if (jerr == JVMTI_ERROR_INVALID_SLOT) + throw new InvalidSlotException (slot); + else if (jerr == JVMTI_ERROR_TYPE_MISMATCH) + throw new TypeMismatchException (sig); + else + throw new JdwpInternalErrorException (msg); + } } -void -gnu::classpath::jdwp::VMFrame::setValue (MAYBE_UNUSED jint slot, - MAYBE_UNUSED gnu::classpath::jdwp::value::Value *value) + +static jobject +getObjectJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig) +{ + jobject value; + jvmtiError jerr = env->GetLocalObject (thread, depth, slot, &value); + + checkJVMTIError (env, thread, jerr, slot, sig); + + return value; +} + +static void +setObjectJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, + jbyte sig, jobject value) +{ + if (value->getClass ()->isAssignableFrom (&util::NullObject::class$)) + value = NULL; + + jvmtiError jerr = env->SetLocalObject (thread, depth, slot, value); + + checkJVMTIError (env, thread, jerr, slot, sig); +} + +static jint +getIntJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig) +{ + jint value; + jvmtiError jerr = env->GetLocalInt (thread, depth, slot, &value); + + checkJVMTIError (env, thread, jerr, slot, sig); + return value; +} + +static void +setIntJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig, + jint value) +{ + jvmtiError jerr = env->SetLocalInt (thread, depth, slot, value); + + checkJVMTIError (env, thread, jerr, slot, sig); +} + +static jlong +getLongJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig) +{ + jlong value; + jvmtiError jerr = env->GetLocalLong (thread, depth, slot, &value); + + checkJVMTIError (env, thread, jerr, slot, sig); + + return value; +} + +static void +setLongJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig, + jlong value) +{ + jvmtiError jerr = env->SetLocalLong (thread, depth, slot, value); + + checkJVMTIError (env, thread, jerr, slot, sig); +} + +static jfloat +getFloatJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig) +{ + jfloat value; + jvmtiError jerr = env->GetLocalFloat (thread, depth, slot, &value); + + checkJVMTIError (env, thread, jerr, slot, sig); + + return value; +} + +static void +setFloatJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig, + jfloat value) { + jvmtiError jerr = env->SetLocalFloat (thread, depth, slot, value); + + checkJVMTIError (env, thread, jerr, slot, sig); +} + +static jdouble +getDoubleJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, + jbyte sig) +{ + jdouble value; + jvmtiError jerr = env->GetLocalDouble (thread, depth, slot, &value); + + checkJVMTIError (env, thread, jerr, slot, sig); + + return value; +} + +static void +setDoubleJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, + jbyte sig, jdouble value) +{ + jvmtiError jerr = env->SetLocalDouble (thread, depth, slot, value); + + checkJVMTIError (env, thread, jerr, slot, sig); +} + +// This is necessary since JVMTI requires a stack depth as a parameter in all +// its local variable functions. Since JDWP needs frameids, we have to run +// through the call stack to translate these ids into the parameters JVMTI +// wants. +static jint +getFrameDepth (_Jv_Frame *frame) +{ + jint depth = 0; + _Jv_Frame *top_frame = (_Jv_Frame *) frame->thread->frame; + jint num_frames = VMVirtualMachine::getFrameCount (frame->thread); + + while (frame != top_frame) + { + top_frame = top_frame->next; + depth++; + + if (depth >= num_frames || top_frame == NULL) + throw new InvalidFrameException ((jlong) frame); + } + + return depth; +} + +using namespace gnu::classpath::jdwp::value; + +Value * +gnu::classpath::jdwp::VMFrame::getValue (jint slot, jbyte sig) +{ + _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (id); + jint depth = getFrameDepth (frame); + jthread thread = reinterpret_cast<jthread> (frame->thread); + jvmtiEnv *env = _Jv_GetJDWP_JVMTIEnv (); + + Value *value = NULL; + + switch (sig) + { + case 'B': + value = new ByteValue ((jbyte) getIntJVMTI (env, thread, slot, depth, + sig)); + break; + case 'Z': + value = new BooleanValue ((jboolean) getIntJVMTI (env, thread, slot, + depth, sig)); + break; + case 'C': + value = new CharValue ((jchar) getIntJVMTI (env, thread, slot, depth, + sig)); + break; + case 'S': + value = new ShortValue ((jshort) getIntJVMTI (env, thread, slot, depth, + sig)); + break; + case 'I': + value = new IntValue (getIntJVMTI (env, thread, slot, depth, sig)); + break; + case 'J': + value = new LongValue (getLongJVMTI (env, thread, slot, depth, sig)); + break; + case 'F': + value = new FloatValue (getFloatJVMTI (env, thread, slot, depth, sig)); + break; + case 'D': + value = new DoubleValue (getDoubleJVMTI (env, thread, slot, depth, sig)); + break; + case 'V': + value = new VoidValue (); + break; + default: + Object *obj = getObjectJVMTI (env, thread, slot, depth, sig); + if (obj == NULL) + obj = new util::NullObject (); + value = new ObjectValue (obj); + break; + } + + return value; +} + +void +gnu::classpath::jdwp::VMFrame::setValue (jint slot, Value* value) +{ + jbyte sig = value->getTag (); + + _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (id); + jint depth = getFrameDepth (frame); + jthread thread = reinterpret_cast<jthread> (frame->thread); + jvmtiEnv *env = _Jv_GetJDWP_JVMTIEnv (); + + switch (sig) + { + case 'B': + { + ByteValue *val = reinterpret_cast<ByteValue *> (value); + setIntJVMTI (env, thread, slot, depth, sig, (jint) val->getValue ()); + break; + } + case 'Z': + { + BooleanValue *val = reinterpret_cast<BooleanValue *> (value); + setIntJVMTI (env, thread, slot, depth, sig, (jint) val->getValue ()); + break; + } + case 'C': + { + CharValue *val = reinterpret_cast<CharValue *> (value); + setIntJVMTI (env, thread, slot, depth, sig, (jint) val->getValue ()); + break; + } + case 'S': + { + ShortValue *val = reinterpret_cast<ShortValue *> (value); + setIntJVMTI (env, thread, slot, depth, sig, (jint) val->getValue ()); + break; + } + case 'I': + { + IntValue *val = reinterpret_cast<IntValue *> (value); + setIntJVMTI (env, thread, slot, depth, sig, val->getValue ()); + break; + } + case 'J': + { + LongValue *val = reinterpret_cast<LongValue *> (value); + setLongJVMTI (env, thread, slot, depth, sig, val->getValue ()); + break; + } + case 'F': + { + FloatValue *val = reinterpret_cast<FloatValue *> (value); + setFloatJVMTI (env, thread, slot, depth, sig, val->getValue ()); + break; + } + case 'D': + { + DoubleValue *val = reinterpret_cast<DoubleValue *> (value); + setDoubleJVMTI (env, thread, slot, depth, sig, val->getValue ()); + break; + } + case 'V': + break; + default: + { + ObjectValue *val = reinterpret_cast<ObjectValue *> (value); + setObjectJVMTI (env, thread, slot, depth, sig, val->getObject()); + break; + } + } } diff --git a/libjava/interpret-run.cc b/libjava/interpret-run.cc index 9d37c19..30e55da 100644 --- a/libjava/interpret-run.cc +++ b/libjava/interpret-run.cc @@ -27,12 +27,91 @@ details. */ _Jv_word locals[meth->max_locals]; -#ifdef DEBUG +#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]; - memset (locals_type, 'x', meth->max_locals); frame_desc.locals_type = locals_type; -#endif + + // 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) + { + // 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 @@ -356,15 +435,6 @@ details. */ */ memcpy ((void*) locals, (void*) args, meth->args_raw_size); -#ifdef DEBUG - // Get the object pointer for this method, after checking that it is - // non-static. - _Jv_Method *method = meth->get_method (); - - if ((method->accflags & java::lang::reflect::Modifier::STATIC) == 0) - frame_desc.obj_ptr = locals[0].o; -#endif - _Jv_word *pool_data = meth->defining_class->constants.data; /* These three are temporaries for common code used by several |