diff -u -r ./hotspot/src_/share/vm/prims/jvmtiEnv.cpp ./hotspot/src/share/vm/prims/jvmtiEnv.cpp
--- ./hotspot/src_/share/vm/prims/jvmtiEnv.cpp 2013-12-19 01:10:36.297992000 +0100
+++ ./hotspot/src/share/vm/prims/jvmtiEnv.cpp 2014-02-10 14:52:14.734339000 +0100
@@ -1982,6 +1982,106 @@
//
+ // Operand Stack functions
+ //
+
+// Threads_lock NOT held, java_thread not protected by lock
+// java_thread - pre-checked
+// java_thread - unchecked
+// depth - pre-checked as non-negative
+// value_ptr - pre-checked for NULL
+jvmtiError
+JvmtiEnv::GetOperandObject(JavaThread* java_thread, jint depth, jint slot, jobject* value_ptr) {
+ JavaThread* current_thread = JavaThread::current();
+ // rm object is created to clean up the javaVFrame created in
+ // doit_prologue(), but after doit() is finished with it.
+ ResourceMark rm(current_thread);
+
+ VM_GetOperand op(java_thread, current_thread, depth, slot);
+ VMThread::execute(&op);
+ jvmtiError err = op.result();
+ if (err != JVMTI_ERROR_NONE) {
+ return err;
+ } else {
+ *value_ptr = op.value().l;
+ return JVMTI_ERROR_NONE;
+ }
+} /* end GetOperandObject */
+
+
+// Threads_lock NOT held, java_thread not protected by lock
+// java_thread - pre-checked
+// java_thread - unchecked
+// depth - pre-checked as non-negative
+// value_ptr - pre-checked for NULL
+jvmtiError
+JvmtiEnv::GetOperandInt(JavaThread* java_thread, jint depth, jint slot, jint* value_ptr) {
+ // rm object is created to clean up the javaVFrame created in
+ // doit_prologue(), but after doit() is finished with it.
+ ResourceMark rm;
+
+ VM_GetOperand op(java_thread, depth, slot, T_INT);
+ VMThread::execute(&op);
+ *value_ptr = op.value().i;
+ return op.result();
+} /* end GetOperandInt */
+
+
+// Threads_lock NOT held, java_thread not protected by lock
+// java_thread - pre-checked
+// java_thread - unchecked
+// depth - pre-checked as non-negative
+// value_ptr - pre-checked for NULL
+jvmtiError
+JvmtiEnv::GetOperandLong(JavaThread* java_thread, jint depth, jint slot, jlong* value_ptr) {
+ // rm object is created to clean up the javaVFrame created in
+ // doit_prologue(), but after doit() is finished with it.
+ ResourceMark rm;
+
+ VM_GetOperand op(java_thread, depth, slot, T_LONG);
+ VMThread::execute(&op);
+ *value_ptr = op.value().j;
+ return op.result();
+} /* end GetOperandLong */
+
+
+// Threads_lock NOT held, java_thread not protected by lock
+// java_thread - pre-checked
+// java_thread - unchecked
+// depth - pre-checked as non-negative
+// value_ptr - pre-checked for NULL
+jvmtiError
+JvmtiEnv::GetOperandFloat(JavaThread* java_thread, jint depth, jint slot, jfloat* value_ptr) {
+ // rm object is created to clean up the javaVFrame created in
+ // doit_prologue(), but after doit() is finished with it.
+ ResourceMark rm;
+
+ VM_GetOperand op(java_thread, depth, slot, T_FLOAT);
+ VMThread::execute(&op);
+ *value_ptr = op.value().f;
+ return op.result();
+} /* end GetOperandFloat */
+
+
+// Threads_lock NOT held, java_thread not protected by lock
+// java_thread - pre-checked
+// java_thread - unchecked
+// depth - pre-checked as non-negative
+// value_ptr - pre-checked for NULL
+jvmtiError
+JvmtiEnv::GetOperandDouble(JavaThread* java_thread, jint depth, jint slot, jdouble* value_ptr) {
+ // rm object is created to clean up the javaVFrame created in
+ // doit_prologue(), but after doit() is finished with it.
+ ResourceMark rm;
+
+ VM_GetOperand op(java_thread, depth, slot, T_DOUBLE);
+ VMThread::execute(&op);
+ *value_ptr = op.value().d;
+ return op.result();
+} /* end GetOperandDouble */
+
+
+ //
// Breakpoint functions
//
diff -u -r ./hotspot/src_/share/vm/prims/jvmtiImpl.cpp ./hotspot/src/share/vm/prims/jvmtiImpl.cpp
--- ./hotspot/src_/share/vm/prims/jvmtiImpl.cpp 2013-12-19 01:10:36.309992000 +0100
+++ ./hotspot/src/share/vm/prims/jvmtiImpl.cpp 2014-02-10 14:57:14.350344000 +0100
@@ -827,6 +827,147 @@
JavaThread* thread, JavaThread* caller_thread, jint depth)
: VM_GetOrSetLocal(thread, caller_thread, depth, 0) {}
+
+///////////////////////////////////////////////////////////////
+//
+// class VM_GetOperand
+//
+
+// Constructor for non-object getter
+VM_GetOperand::VM_GetOperand(JavaThread* thread, jint depth, int index, BasicType type)
+ : _thread(thread)
+ , _calling_thread(NULL)
+ , _depth(depth)
+ , _index(index)
+ , _type(type)
+ , _jvf(NULL)
+ , _result(JVMTI_ERROR_NONE)
+{
+}
+
+// Constructor for object getter
+VM_GetOperand::VM_GetOperand(JavaThread* thread, JavaThread* calling_thread, jint depth, int index)
+ : _thread(thread)
+ , _calling_thread(calling_thread)
+ , _depth(depth)
+ , _index(index)
+ , _type(T_OBJECT)
+ , _jvf(NULL)
+ , _result(JVMTI_ERROR_NONE)
+{
+}
+
+vframe *VM_GetOperand::get_vframe() {
+ if (!_thread->has_last_Java_frame()) {
+ return NULL;
+ }
+ RegisterMap reg_map(_thread);
+ vframe *vf = _thread->last_java_vframe(®_map);
+ int d = 0;
+ while ((vf != NULL) && (d < _depth)) {
+ vf = vf->java_sender();
+ d++;
+ }
+ return vf;
+}
+
+javaVFrame *VM_GetOperand::get_java_vframe() {
+ vframe* vf = get_vframe();
+ if (vf == NULL) {
+ _result = JVMTI_ERROR_NO_MORE_FRAMES;
+ return NULL;
+ }
+ javaVFrame *jvf = (javaVFrame*)vf;
+
+ if (!vf->is_java_frame()) {
+ _result = JVMTI_ERROR_OPAQUE_FRAME;
+ return NULL;
+ }
+ return jvf;
+}
+
+// Checks error conditions:
+// JVMTI_ERROR_INVALID_SLOT
+// Returns: 'true' - everything is Ok, 'false' - error code
+bool VM_GetOperand::check_slot_type(javaVFrame* jvf) {
+ // index checking
+ StackValueCollection *expressions = _jvf->expressions();
+ jint size = expressions->size();
+ size -= (_type == T_LONG || _type == T_DOUBLE) ? 1 : 0;
+
+ if (_index < 0 || _index >= size) {
+ _result = JVMTI_ERROR_INVALID_SLOT;
+ return false;
+ }
+
+ // FIXME insert proper type-checking code here
+
+ return true;
+}
+
+bool VM_GetOperand::doit_prologue() {
+ _jvf = get_java_vframe();
+ NULL_CHECK(_jvf, false);
+
+ if (_jvf->method()->is_native()) {
+ if (getting_receiver() && !_jvf->method()->is_static()) {
+ return true;
+ } else {
+ _result = JVMTI_ERROR_OPAQUE_FRAME;
+ return false;
+ }
+ }
+
+ if (!check_slot_type(_jvf)) {
+ return false;
+ }
+ return true;
+}
+
+void VM_GetOperand::doit() {
+ // get
+ if (_jvf->method()->is_native() && _jvf->is_compiled_frame()) {
+ assert(getting_receiver(), "Can only get here when getting receiver");
+ oop receiver = _jvf->fr().get_native_receiver();
+ _value.l = JNIHandles::make_local(_calling_thread, receiver);
+ } else {
+ StackValueCollection *expressions = _jvf->expressions();
+
+ if (expressions->at(_index)->type() == T_CONFLICT) {
+ memset(&_value, 0, sizeof(_value));
+ _value.l = NULL;
+ return;
+ }
+
+ switch (_type) {
+ case T_INT: _value.i = expressions->int_at (_index); break;
+ case T_LONG: _value.j = expressions->long_at (_index); break;
+ case T_FLOAT: _value.f = expressions->float_at (_index); break;
+ case T_DOUBLE: _value.d = expressions->double_at(_index); break;
+ case T_OBJECT: {
+ // Wrap the oop to be returned in a local JNI handle since
+ // oops_do() no longer applies after doit() is finished.
+ intptr_t temp = expressions->at(_index)->get_int();
+ intptr_t *addr = &temp;
+ _value.l = JNIHandles::make_local(_calling_thread, *(oop *)addr);
+ break;
+ }
+ default: ShouldNotReachHere();
+ }
+ }
+}
+
+
+bool VM_GetOperand::allow_nested_vm_operations() const {
+ return true; // May need to deoptimize
+}
+
+
+VM_GetOperandReceiver::VM_GetOperandReceiver(
+ JavaThread* thread, JavaThread* caller_thread, jint depth)
+ : VM_GetOperand(thread, caller_thread, depth, 0) {}
+
+
/////////////////////////////////////////////////////////////////////////////////////////
//
diff -u -r ./hotspot/src_/share/vm/prims/jvmtiImpl.hpp ./hotspot/src/share/vm/prims/jvmtiImpl.hpp
--- ./hotspot/src_/share/vm/prims/jvmtiImpl.hpp 2013-12-19 01:10:36.309992000 +0100
+++ ./hotspot/src/share/vm/prims/jvmtiImpl.hpp 2014-02-10 14:54:03.762341000 +0100
@@ -400,6 +400,58 @@
///////////////////////////////////////////////////////////////
+// This is a copy of VM_GetOrSetLocal modified to access operands
+// instead of local variables.
+//
+class VM_GetOperand : public VM_Operation {
+ protected:
+ JavaThread* _thread;
+ JavaThread* _calling_thread;
+ jint _depth;
+ jint _index;
+ BasicType _type;
+ jvalue _value;
+ javaVFrame* _jvf;
+
+ // It is possible to get the receiver out of a non-static native wrapper
+ // frame. Use VM_GetReceiver to do this.
+ virtual bool getting_receiver() const { return false; }
+
+ jvmtiError _result;
+
+ vframe* get_vframe();
+ javaVFrame* get_java_vframe();
+ bool check_slot_type(javaVFrame* vf);
+
+public:
+ // Constructor for non-object getter
+ VM_GetOperand(JavaThread* thread, jint depth, jint index, BasicType type);
+
+ // Constructor for object getter
+ VM_GetOperand(JavaThread* thread, JavaThread* calling_thread, jint depth,
+ int index);
+
+ VMOp_Type type() const { return VMOp_GetOperand; }
+ jvalue value() { return _value; }
+ jvmtiError result() { return _result; }
+
+ bool doit_prologue();
+ void doit();
+ bool allow_nested_vm_operations() const;
+ const char* name() const { return "get operands"; }
+};
+
+class VM_GetOperandReceiver : public VM_GetOperand {
+ protected:
+ virtual bool getting_receiver() const { return true; }
+
+ public:
+ VM_GetOperandReceiver(JavaThread* thread, JavaThread* calling_thread, jint depth);
+ const char* name() const { return "get operand receiver"; }
+};
+
+
+///////////////////////////////////////////////////////////////
//
// class JvmtiSuspendControl
//
diff -u -r ./hotspot/src_/share/vm/prims/jvmti.xml ./hotspot/src/share/vm/prims/jvmti.xml
--- ./hotspot/src_/share/vm/prims/jvmti.xml 2013-12-19 01:10:36.293992000 +0100
+++ ./hotspot/src/share/vm/prims/jvmti.xml 2014-02-10 14:50:31.750337000 +0100
@@ -6137,6 +6137,266 @@
+
+
+
+
+ These functions are used to retrieve or set the value of an operand stack slot.
+ The slot is identified by the depth of the frame containing its
+ value and the slot's number within that frame.
+
+
+
+ Get Operand Stack Value - Object
+
+ This function can be used to retrieve the value of an operand
+ stack slot whose type is Object
or a subclass of Object
.
+
+ jvmdi
+
+
+
+
+
+
+
+ The thread of the frame containing the slot's value.
+
+
+
+
+
+ The depth of the frame containing the slot's value.
+
+
+
+
+
+ The slot's number.
+
+
+
+
+
+ On return, points to the slot's value.
+
+
+
+
+
+ Invalid slot
.
+
+
+ The slot's type is not
+ Object
or a subclass of Object
.
+
+
+ Not a visible frame
+
+
+
+
+
+ Get Operand Stack Value - Int
+
+ This function can be used to retrieve the value of an operand
+ stack slot whose type is int
,
+ short
, char
, byte
, or
+ boolean
.
+
+ jvmdi
+
+
+
+
+
+
+
+ The thread of the frame containing the slot's value.
+
+
+
+
+
+ The depth of the frame containing the slot's value.
+
+
+
+
+
+ The slot's number.
+
+
+
+
+
+ On return, points to the slot's value.
+
+
+
+
+
+ Invalid slot
.
+
+
+ The slot's type is not
+ int
, short
,
+ char
, byte
, or
+ boolean
.
+
+
+ Not a visible frame
+
+
+
+
+
+ Get Operand Stack Value - Long
+
+ This function can be used to retrieve the value of an operand
+ stack slot whose type is long
.
+
+ jvmdi
+
+
+
+
+
+
+
+ The thread of the frame containing the slot's value.
+
+
+
+
+
+ The depth of the frame containing the slot's value.
+
+
+
+
+
+ The slot's number.
+
+
+
+
+
+ On return, points to the slot's value.
+
+
+
+
+
+ Invalid slot
.
+
+
+ The variable type is not long
.
+
+
+ Not a visible frame
+
+
+
+
+
+ Get Operand Stack Value - Float
+
+ This function can be used to retrieve the value of an operand
+ stack slot whose type is float
.
+
+ jvmdi
+
+
+
+
+
+
+
+ The thread of the frame containing the slot's value.
+
+
+
+
+
+ The depth of the frame containing the slot's value.
+
+
+
+
+
+ The slot's number.
+
+
+
+
+
+ On return, points to the slot's value.
+
+
+
+
+
+ Invalid slot
.
+
+
+ The variable type is not float
.
+
+
+ Not a visible frame
+
+
+
+
+
+ Get Operand Stack Value - Double
+
+ This function can be used to retrieve the value of an operand
+ stack slot whose type is double
.
+
+ jvmdi
+
+
+
+
+
+
+
+ The thread of the frame containing the slot's value.
+
+
+
+
+
+ The depth of the frame containing the slot's value.
+
+
+
+
+
+ The slot's number.
+
+
+
+
+
+ On return, points to the slot's value.
+
+
+
+
+
+ Invalid slot
.
+
+
+ The variable type is not double
.
+
+
+ Not a visible frame
+
+
+
+
diff -u -r ./hotspot/src_/share/vm/runtime/vm_operations.hpp ./hotspot/src/share/vm/runtime/vm_operations.hpp
--- ./hotspot/src_/share/vm/runtime/vm_operations.hpp 2013-12-19 01:10:36.377992000 +0100
+++ ./hotspot/src/share/vm/runtime/vm_operations.hpp 2014-02-10 14:48:02.346335000 +0100
@@ -87,6 +87,7 @@
template(GetFrameLocation) \
template(ChangeBreakpoints) \
template(GetOrSetLocal) \
+ template(GetOperand) \
template(GetCurrentLocation) \
template(EnterInterpOnlyMode) \
template(ChangeSingleStep) \
diff -u -r ./hotspot/src_/share/vm/prims/jvmtiEnv.cpp ./hotspot/src/share/vm/prims/jvmtiEnv.cpp
--- ./hotspot/src_/share/vm/prims/jvmtiEnv.cpp 2013-12-19 01:10:36.297992000 +0100
+++ ./hotspot/src/share/vm/prims/jvmtiEnv.cpp 2014-02-10 14:52:14.734339000 +0100
@@ -1982,6 +1982,106 @@
//
+ // Operand Stack functions
+ //
+
+// Threads_lock NOT held, java_thread not protected by lock
+// java_thread - pre-checked