OSDN Git Service

2007-04-02 Kyle Galloway <kgallowa@redhat.com>
authorkgallowa <kgallowa@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 2 Apr 2007 13:45:52 +0000 (13:45 +0000)
committerkgallowa <kgallowa@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 2 Apr 2007 13:45:52 +0000 (13:45 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@123427 138bc75d-0d04-0410-961f-82ee72b054a4

libjava/ChangeLog
libjava/gnu/classpath/jdwp/natVMFrame.cc
libjava/interpret-run.cc

index 86b682a..bc7e363 100644 (file)
@@ -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.
 
index 894791c..e32e733 100644 (file)
@@ -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;
+      }
+    }
 }
index 9d37c19..30e55da 100644 (file)
@@ -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