This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] JMTI GetLocal____ methods


This patch implements the JVMTI side functions to Get and Set local variables. getLocalFrame is used by all of these methods to do the common error checking and frame retrieval that is needed in every case.
If it does not return an error, it returns a newly allocated copy of the frame object containing pointers to the actual local variable and local variable type info. The Get/SetLocal___ methods then gt/set the variable, free the frame structure and return.


Questions/comments/concerns?

Thanks,
Kyle

ChangeLog
2007-02-15  Kyle Galloway  <kgallowa@redhat.com>

* interpret.cc: Add extra DEBUG_LOCALS_INSN calls for multi-slot
variables to maintain type info.
* interpret-run.cc: Add local variable info to frame in the debug interpreter.
* jvmti.cc (getLocalFrame): New method.
(GetLocalObject): New method.
(GetLocallInt): New method.
(GetLocalFloat): New method.
(GetLocalLong): New method.
(GetLocalDouble): New method.
(SetLocalObject): New method.
(SetLocalInt): New method.
(SetLocalFloat): New method.
(SetLocalLong): New method.
(SetLocalDouble): New method.




Index: libjava/interpret.cc
===================================================================
--- libjava/interpret.cc	(revision 121999)
+++ libjava/interpret.cc	(working copy)
@@ -190,11 +190,13 @@
 # define STOREL(I)				\
   do {						\
     DEBUG_LOCALS_INSN (I, 'l');			\
+    DEBUG_LOCALS_INSN (I+1, 'l');               \
     (sp -= 2, locals[I].l = sp->l);		\
   } while (0)
 # define STORED(I) 				\
   do {						\
     DEBUG_LOCALS_INSN (I, 'd');			\
+    DEBUG_LOCALS_INSN (I+1, 'd');               \
     (sp -= 2, locals[I].d = sp->d);		\
   } while (0)
 
@@ -202,13 +204,15 @@
 # define STOREL(I)				\
   do {						\
     DEBUG_LOCALS_INSN (I, 'l');			\
+    DEBUG_LOCALS_INSN (I+1, 'l');               \
     jint __idx = (I);				\
     locals[__idx+1].ia[0] = (--sp)->ia[0];	\
     locals[__idx].ia[0] = (--sp)->ia[0]; 	\
   } while (0)
 # define STORED(I)				\
   do {						\
-    DEBUG_LOCALS_INSN(I, 'd');			\
+    DEBUG_LOCALS_INSN (I, 'd');                 \
+    DEBUG_LOCALS_INSN (I+1, 'd');               \
     jint __idx = (I);				\
     locals[__idx+1].ia[0] = (--sp)->ia[0];	\
     locals[__idx].ia[0] = (--sp)->ia[0]; 	\
@@ -928,9 +932,9 @@
 {
 #undef DEBUG
 #undef DEBUG_LOCALS_INSN
-#define DEBUG_LOCALS_INSN(s, t) do {} while(0)
+#define DEBUG_LOCALS_INSN(s, t) do {} while (0)
 
-#include "interpret-run.cc"
+#include  "interpret-run.cc"
 }
 
 void
@@ -938,7 +942,12 @@
 {
 #define DEBUG
 #undef DEBUG_LOCALS_INSN
-#define DEBUG_LOCALS_INSN(s, t) do {} while(0)
+#define DEBUG_LOCALS_INSN(s, t)  \
+do  \
+  {  \
+    frame_desc.locals_type[s] = t; \
+  }  \
+while(0)
 
 #include "interpret-run.cc"
 }
Index: libjava/jvmti.cc
===================================================================
--- libjava/jvmti.cc	(revision 121999)
+++ libjava/jvmti.cc	(working copy)
@@ -167,6 +167,14 @@
     }									\
   while (0)
 
+#define OBJECT_CHECK_VALID(Aobject)					\
+  do									\
+    {									\
+      if (!java::lang::Object::class$.isAssignableFrom (&(Aobject->class$))) \
+	return JVMTI_ERROR_INVALID_OBJECT;				\
+    }									\
+  while (0)
+
 static jvmtiError JNICALL
 _Jv_JVMTI_SuspendThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread)
 {
@@ -211,7 +219,266 @@
   return JVMTI_ERROR_NONE;
 }
 
+// This method performs the common tasks to get and set variables of all types.
+// It is called by the _Jv_JVMTI_Get/SetLocalInt/Object/.... methods.
+static jvmtiError
+getLocalFrame (jvmtiEnv *env, jthread thread, jint depth, jint slot, char type,
+               _Jv_InterpFrame **iframe)
+{
+  using namespace java::lang;
+   
+  REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
+   
+  ILLEGAL_ARGUMENT (depth < 0);
+  
+  THREAD_DEFAULT_TO_CURRENT (thread);
+   
+  Thread *thr = reinterpret_cast<Thread *> (thread);
+  THREAD_CHECK_VALID (thr);
+  THREAD_CHECK_IS_ALIVE (thr);
+  
+  _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thr->frame);
+  
+  for (int i = 0; i < depth; i++)
+    {    
+      frame = frame->next;
+    
+      if (frame == NULL)
+        return JVMTI_ERROR_NO_MORE_FRAMES; 
+    }
+  
+  if (frame->frame_type == frame_native)
+    return JVMTI_ERROR_OPAQUE_FRAME;
+  
+  jint max_locals;
+  jvmtiError jerr = env->GetMaxLocals (reinterpret_cast<jmethodID> 
+                                         (frame->self->get_method ()),
+                                         &max_locals);
+  if (jerr != JVMTI_ERROR_NONE)
+    return jerr; 
+   
+  if (slot < 0 || slot >= max_locals)
+    return JVMTI_ERROR_INVALID_SLOT;
+  
+  _Jv_InterpFrame *tmp_iframe = reinterpret_cast<_Jv_InterpFrame *> (frame);
+  
+  if (tmp_iframe->locals_type[slot] != type)
+    return JVMTI_ERROR_TYPE_MISMATCH;
+  
+  // Allocate memory here so it only needs to be _Jv_Freed if there is no error
+  // returned from this function.  If no error is returned, this must be freed
+  // by the caller.
+  *iframe = reinterpret_cast<_Jv_InterpFrame *> 
+              (_Jv_MallocUnchecked (sizeof (_Jv_InterpFrame)));
+  memcpy (*iframe, tmp_iframe, sizeof (_Jv_InterpFrame));
+  
+  return JVMTI_ERROR_NONE;
+}
+
 static jvmtiError JNICALL
+_Jv_JVMTI_GetLocalObject (jvmtiEnv *env, jthread thread, jint depth, jint slot,
+                          jobject *value)
+{
+  NULL_CHECK (value);
+
+  _Jv_InterpFrame *frame;
+  jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'o', &frame);
+  
+  if (jerr != JVMTI_ERROR_NONE)
+    return jerr;
+  
+  *value = frame->locals[slot].o;
+  
+  _Jv_Free (frame);
+  return JVMTI_ERROR_NONE;
+}
+
+static jvmtiError JNICALL
+_Jv_JVMTI_SetLocalObject (jvmtiEnv *env, jthread thread, jint depth, jint slot,
+                          jobject value)
+{
+  _Jv_InterpFrame *frame;
+  jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'o', &frame);
+  
+  if (jerr != JVMTI_ERROR_NONE)
+    return jerr;
+  
+  java::lang::Object *obj = reinterpret_cast<java::lang::Object *> (value);
+  OBJECT_CHECK_VALID (obj);
+  
+  frame->locals[slot].o = value;
+
+  _Jv_Free (frame);
+  return JVMTI_ERROR_NONE;
+}
+
+static jvmtiError JNICALL
+_Jv_JVMTI_GetLocalInt (jvmtiEnv *env, jthread thread, jint depth, jint slot,
+                       jint *value)
+{
+  NULL_CHECK (value);
+  
+  _Jv_InterpFrame *frame;
+  jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'i', &frame);
+
+  if (jerr != JVMTI_ERROR_NONE)
+    return jerr;
+
+  *value = frame->locals[slot].i;
+
+  _Jv_Free (frame);
+  return JVMTI_ERROR_NONE;
+}
+
+static jvmtiError JNICALL
+_Jv_JVMTI_SetLocalInt (jvmtiEnv *env, jthread thread, jint depth, jint slot,
+                       jint value)
+{
+  _Jv_InterpFrame *frame;
+  jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'i', &frame);
+  
+  if (jerr != JVMTI_ERROR_NONE)
+    return jerr;
+  
+  frame->locals[slot].i = value;
+
+  _Jv_Free (frame);
+  return JVMTI_ERROR_NONE;
+}
+
+static jvmtiError JNICALL
+_Jv_JVMTI_GetLocalLong (jvmtiEnv *env, jthread thread, jint depth, jint slot,
+                        jlong *value)
+{
+  NULL_CHECK (value);
+
+  _Jv_InterpFrame *frame;
+  jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'l', &frame);
+  
+  if (jerr != JVMTI_ERROR_NONE)
+    return jerr;
+
+#if SIZEOF_VOID_P==8
+  *value = frame->locals[slot].l;
+#else
+  _Jv_word2 val;
+  val.ia[0] = frame->locals[slot].ia[0];
+  val.ia[1] = frame->locals[slot+1].ia[0];
+  *value = val.l;
+#endif
+
+  _Jv_Free (frame);   
+  return JVMTI_ERROR_NONE;
+}
+
+static jvmtiError JNICALL
+_Jv_JVMTI_SetLocalLong (jvmtiEnv *env, jthread thread, jint depth, jint slot,
+                        jlong value)
+{
+  _Jv_InterpFrame *frame;
+  jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'l', &frame);
+  
+  if (jerr != JVMTI_ERROR_NONE)
+    return jerr;
+
+#if SIZEOF_VOID_P==8
+  frame->locals[slot].l = value;
+#else
+  _Jv_word2 val;
+	val.l = value;
+	frame->locals[slot].ia[0] = val.ia[0];
+	frame->locals[slot+1].ia[0] = val.ia[1];
+#endif
+
+  _Jv_Free (frame);
+  return JVMTI_ERROR_NONE;
+}
+
+
+static jvmtiError JNICALL
+_Jv_JVMTI_GetLocalFloat (jvmtiEnv *env, jthread thread, jint depth, jint slot,
+                         jfloat *value)
+{
+  NULL_CHECK (value);
+
+  _Jv_InterpFrame *frame;
+  jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'f', &frame);
+  
+  if (jerr != JVMTI_ERROR_NONE)
+    return jerr;
+  
+  *value = frame->locals[slot].f;
+
+  _Jv_Free (frame);
+  return JVMTI_ERROR_NONE;
+}
+
+static jvmtiError JNICALL
+_Jv_JVMTI_SetLocalFloat (jvmtiEnv *env, jthread thread, jint depth, jint slot,
+                         jfloat value)
+{
+  _Jv_InterpFrame *frame;
+  jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'f', &frame);
+  
+  if (jerr != JVMTI_ERROR_NONE)
+    return jerr;
+  
+  frame->locals[slot].f = value;
+
+  _Jv_Free (frame);
+  return JVMTI_ERROR_NONE;
+}
+
+
+static jvmtiError JNICALL
+_Jv_JVMTI_GetLocalDouble (jvmtiEnv *env, jthread thread, jint depth, jint slot,
+                          jdouble *value)
+{
+  NULL_CHECK (value);
+
+  _Jv_InterpFrame *frame;
+  jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'd', &frame);
+  
+  if (jerr != JVMTI_ERROR_NONE)
+    return jerr;
+  
+#if SIZEOF_VOID_P==8
+  *value = frame->locals[slot].d;
+#else
+  _Jv_word2 val;
+  val.ia[0] = frame->locals[slot].ia[0];
+  val.ia[1] = frame->locals[slot+1].ia[0];
+  *value = val.d;
+#endif
+
+  _Jv_Free (frame);
+  return JVMTI_ERROR_NONE;
+}
+
+static jvmtiError JNICALL
+_Jv_JVMTI_SetLocalDouble (jvmtiEnv *env, jthread thread, jint depth, jint slot,
+                          jdouble value)
+{
+  _Jv_InterpFrame *frame;
+  jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'd', &frame);
+  
+  if (jerr != JVMTI_ERROR_NONE)
+    return jerr;
+    
+#if SIZEOF_VOID_P==8
+  frame->locals[slot].d = value;
+#else
+  _Jv_word2 val;
+  val.d = value;
+  frame->locals[slot].ia[0] = val.ia[0];
+  frame->locals[slot+1].ia[0] = val.ia[1]; 
+#endif
+
+  _Jv_Free (frame);
+  return JVMTI_ERROR_NONE;
+}
+
+static jvmtiError JNICALL
 _Jv_JVMTI_GetAllThreads(MAYBE_UNUSED jvmtiEnv *env, jint *thread_cnt,
                         jthread **threads)
 {
@@ -1716,16 +1983,16 @@
   RESERVED,			// reserved18
   UNIMPLEMENTED,		// GetFrameLocation
   UNIMPLEMENTED,		// NotifyPopFrame
-  UNIMPLEMENTED,		// GetLocalObject
-  UNIMPLEMENTED,		// GetLocalInt
-  UNIMPLEMENTED,		// GetLocalLong
-  UNIMPLEMENTED,		// GetLocalFloat
-  UNIMPLEMENTED,		// GetLocalDouble
-  UNIMPLEMENTED,		// SetLocalObject
-  UNIMPLEMENTED,		// SetLocalInt
-  UNIMPLEMENTED,		// SetLocalLong
-  UNIMPLEMENTED,		// SetLocalFloat
-  UNIMPLEMENTED,		// SetLocalDouble
+  _Jv_JVMTI_GetLocalObject,		// GetLocalObject
+  _Jv_JVMTI_GetLocalInt,		// GetLocalInt
+  _Jv_JVMTI_GetLocalLong,		// GetLocalLong
+  _Jv_JVMTI_GetLocalFloat,		// GetLocalFloat
+  _Jv_JVMTI_GetLocalDouble,		// GetLocalDouble
+  _Jv_JVMTI_SetLocalObject,		// SetLocalObject
+  _Jv_JVMTI_SetLocalInt,		// SetLocalInt
+  _Jv_JVMTI_SetLocalLong,		// SetLocalLong
+  _Jv_JVMTI_SetLocalFloat,		// SetLocalFloat
+  _Jv_JVMTI_SetLocalDouble,		// SetLocalDouble
   _Jv_JVMTI_CreateRawMonitor,	// CreateRawMonitor
   _Jv_JVMTI_DestroyRawMonitor,	// DestroyRawMonitor
   _Jv_JVMTI_RawMonitorEnter,	// RawMonitorEnter
Index: libjava/interpret-run.cc
===================================================================
--- libjava/interpret-run.cc	(revision 121957)
+++ libjava/interpret-run.cc	(working copy)
@@ -26,6 +26,11 @@
   _Jv_word *sp = stack;
 
   _Jv_word locals[meth->max_locals];
+#ifdef DEBUG  
+  frame_desc.locals = locals;
+  frame_desc.locals_type 
+    = reinterpret_cast<char *> (_Jv_AllocBytes (meth->max_locals));
+#endif
 
 #define INSN_LABEL(op) &&insn_##op
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]