This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[RFA] JMTI GetLocal____ methods
- From: Kyle Galloway <kgallowa at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: Thu, 15 Feb 2007 14:46:40 -0500
- Subject: [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