提交 c880d585 编写于 作者: K kamg

7004582: Add GetThisObject() function to JVMTI 1.2

Summary: Add 'GetThisObject' function
Reviewed-by: never, coleenp
上级 c2c924e3
...@@ -619,8 +619,8 @@ nmethod::nmethod( ...@@ -619,8 +619,8 @@ nmethod::nmethod(
OopMapSet* oop_maps ) OopMapSet* oop_maps )
: CodeBlob("native nmethod", code_buffer, sizeof(nmethod), : CodeBlob("native nmethod", code_buffer, sizeof(nmethod),
nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps), nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps),
_compiled_synchronized_native_basic_lock_owner_sp_offset(basic_lock_owner_sp_offset), _native_receiver_sp_offset(basic_lock_owner_sp_offset),
_compiled_synchronized_native_basic_lock_sp_offset(basic_lock_sp_offset) _native_basic_lock_sp_offset(basic_lock_sp_offset)
{ {
{ {
debug_only(No_Safepoint_Verifier nsv;) debug_only(No_Safepoint_Verifier nsv;)
...@@ -696,8 +696,8 @@ nmethod::nmethod( ...@@ -696,8 +696,8 @@ nmethod::nmethod(
int frame_size) int frame_size)
: CodeBlob("dtrace nmethod", code_buffer, sizeof(nmethod), : CodeBlob("dtrace nmethod", code_buffer, sizeof(nmethod),
nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, NULL), nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, NULL),
_compiled_synchronized_native_basic_lock_owner_sp_offset(in_ByteSize(-1)), _native_receiver_sp_offset(in_ByteSize(-1)),
_compiled_synchronized_native_basic_lock_sp_offset(in_ByteSize(-1)) _native_basic_lock_sp_offset(in_ByteSize(-1))
{ {
{ {
debug_only(No_Safepoint_Verifier nsv;) debug_only(No_Safepoint_Verifier nsv;)
...@@ -790,8 +790,8 @@ nmethod::nmethod( ...@@ -790,8 +790,8 @@ nmethod::nmethod(
) )
: CodeBlob("nmethod", code_buffer, sizeof(nmethod), : CodeBlob("nmethod", code_buffer, sizeof(nmethod),
nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps), nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps),
_compiled_synchronized_native_basic_lock_owner_sp_offset(in_ByteSize(-1)), _native_receiver_sp_offset(in_ByteSize(-1)),
_compiled_synchronized_native_basic_lock_sp_offset(in_ByteSize(-1)) _native_basic_lock_sp_offset(in_ByteSize(-1))
{ {
assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR"); assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR");
{ {
......
...@@ -210,7 +210,7 @@ class nmethod : public CodeBlob { ...@@ -210,7 +210,7 @@ class nmethod : public CodeBlob {
ExceptionCache *_exception_cache; ExceptionCache *_exception_cache;
PcDescCache _pc_desc_cache; PcDescCache _pc_desc_cache;
// These are only used for compiled synchronized native methods to // These are used for compiled synchronized native methods to
// locate the owner and stack slot for the BasicLock so that we can // locate the owner and stack slot for the BasicLock so that we can
// properly revoke the bias of the owner if necessary. They are // properly revoke the bias of the owner if necessary. They are
// needed because there is no debug information for compiled native // needed because there is no debug information for compiled native
...@@ -220,8 +220,10 @@ class nmethod : public CodeBlob { ...@@ -220,8 +220,10 @@ class nmethod : public CodeBlob {
// sharing between platforms. Note that currently biased locking // sharing between platforms. Note that currently biased locking
// will never cause Class instances to be biased but this code // will never cause Class instances to be biased but this code
// handles the static synchronized case as well. // handles the static synchronized case as well.
ByteSize _compiled_synchronized_native_basic_lock_owner_sp_offset; // JVMTI's GetLocalInstance() also uses these offsets to find the receiver
ByteSize _compiled_synchronized_native_basic_lock_sp_offset; // for non-static native wrapper frames.
ByteSize _native_receiver_sp_offset;
ByteSize _native_basic_lock_sp_offset;
friend class nmethodLocker; friend class nmethodLocker;
...@@ -676,11 +678,11 @@ public: ...@@ -676,11 +678,11 @@ public:
bool is_patchable_at(address instr_address); bool is_patchable_at(address instr_address);
// UseBiasedLocking support // UseBiasedLocking support
ByteSize compiled_synchronized_native_basic_lock_owner_sp_offset() { ByteSize native_receiver_sp_offset() {
return _compiled_synchronized_native_basic_lock_owner_sp_offset; return _native_receiver_sp_offset;
} }
ByteSize compiled_synchronized_native_basic_lock_sp_offset() { ByteSize native_basic_lock_sp_offset() {
return _compiled_synchronized_native_basic_lock_sp_offset; return _native_basic_lock_sp_offset;
} }
// support for code generation // support for code generation
......
...@@ -5649,6 +5649,45 @@ class C2 extends C1 implements I2 { ...@@ -5649,6 +5649,45 @@ class C2 extends C1 implements I2 {
</errors> </errors>
</function> </function>
<function id="GetLocalInstance" num="155" since="1.2">
<synopsis>Get Local Instance</synopsis>
<description>
This function can be used to retrieve the value of the local object
variable at slot 0 (the "<code>this</code>" object) from non-static
frames. This function can retrieve the "<code>this</code>" object from
native method frames, whereas <code>GetLocalObject()</code> would
return <code>JVMTI_ERROR_OPAQUE_FRAME</code> in those cases.
</description>
<origin>new</origin>
<capabilities>
<required id="can_access_local_variables"></required>
</capabilities>
<parameters>
<param id="thread">
<jthread null="current" frame="frame"/>
<description>
The thread of the frame containing the variable's value.
</description>
</param>
<param id="depth">
<jframeID thread="thread"/>
<description>
The depth of the frame containing the variable's value.
</description>
</param>
<param id="value_ptr">
<outptr><jobject/></outptr>
<description>
On return, points to the variable's value.
</description>
</param>
</parameters>
<errors>
<error id="JVMTI_ERROR_INVALID_SLOT">
If the specified frame is a static method frame.
</error>
</errors>
</function>
<function id="GetLocalInt" num="22"> <function id="GetLocalInt" num="22">
<synopsis>Get Local Variable - Int</synopsis> <synopsis>Get Local Variable - Int</synopsis>
<description> <description>
......
...@@ -1796,6 +1796,29 @@ JvmtiEnv::GetLocalObject(JavaThread* java_thread, jint depth, jint slot, jobject ...@@ -1796,6 +1796,29 @@ JvmtiEnv::GetLocalObject(JavaThread* java_thread, jint depth, jint slot, jobject
} }
} /* end GetLocalObject */ } /* end GetLocalObject */
// Threads_lock NOT held, java_thread not protected by lock
// java_thread - pre-checked
// java_thread - unchecked
// depth - pre-checked as non-negative
// value - pre-checked for NULL
jvmtiError
JvmtiEnv::GetLocalInstance(JavaThread* java_thread, jint depth, jobject* value){
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_GetReceiver op(java_thread, current_thread, depth);
VMThread::execute(&op);
jvmtiError err = op.result();
if (err != JVMTI_ERROR_NONE) {
return err;
} else {
*value = op.value().l;
return JVMTI_ERROR_NONE;
}
} /* end GetLocalInstance */
// Threads_lock NOT held, java_thread not protected by lock // Threads_lock NOT held, java_thread not protected by lock
// java_thread - pre-checked // java_thread - pre-checked
......
...@@ -586,7 +586,6 @@ VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, JavaThread* calling_threa ...@@ -586,7 +586,6 @@ VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, JavaThread* calling_threa
{ {
} }
vframe *VM_GetOrSetLocal::get_vframe() { vframe *VM_GetOrSetLocal::get_vframe() {
if (!_thread->has_last_Java_frame()) { if (!_thread->has_last_Java_frame()) {
return NULL; return NULL;
...@@ -609,7 +608,7 @@ javaVFrame *VM_GetOrSetLocal::get_java_vframe() { ...@@ -609,7 +608,7 @@ javaVFrame *VM_GetOrSetLocal::get_java_vframe() {
} }
javaVFrame *jvf = (javaVFrame*)vf; javaVFrame *jvf = (javaVFrame*)vf;
if (!vf->is_java_frame() || jvf->method()->is_native()) { if (!vf->is_java_frame()) {
_result = JVMTI_ERROR_OPAQUE_FRAME; _result = JVMTI_ERROR_OPAQUE_FRAME;
return NULL; return NULL;
} }
...@@ -740,6 +739,15 @@ bool VM_GetOrSetLocal::doit_prologue() { ...@@ -740,6 +739,15 @@ bool VM_GetOrSetLocal::doit_prologue() {
_jvf = get_java_vframe(); _jvf = get_java_vframe();
NULL_CHECK(_jvf, false); 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)) { if (!check_slot_type(_jvf)) {
return false; return false;
} }
...@@ -781,40 +789,46 @@ void VM_GetOrSetLocal::doit() { ...@@ -781,40 +789,46 @@ void VM_GetOrSetLocal::doit() {
HandleMark hm; HandleMark hm;
switch (_type) { switch (_type) {
case T_INT: locals->set_int_at (_index, _value.i); break; case T_INT: locals->set_int_at (_index, _value.i); break;
case T_LONG: locals->set_long_at (_index, _value.j); break; case T_LONG: locals->set_long_at (_index, _value.j); break;
case T_FLOAT: locals->set_float_at (_index, _value.f); break; case T_FLOAT: locals->set_float_at (_index, _value.f); break;
case T_DOUBLE: locals->set_double_at(_index, _value.d); break; case T_DOUBLE: locals->set_double_at(_index, _value.d); break;
case T_OBJECT: { case T_OBJECT: {
Handle ob_h(JNIHandles::resolve_external_guard(_value.l)); Handle ob_h(JNIHandles::resolve_external_guard(_value.l));
locals->set_obj_at (_index, ob_h); locals->set_obj_at (_index, ob_h);
break; break;
} }
default: ShouldNotReachHere(); default: ShouldNotReachHere();
} }
_jvf->set_locals(locals); _jvf->set_locals(locals);
} else { } else {
StackValueCollection *locals = _jvf->locals(); if (_jvf->method()->is_native() && _jvf->is_compiled_frame()) {
assert(getting_receiver(), "Can only get here when getting receiver");
if (locals->at(_index)->type() == T_CONFLICT) { oop receiver = _jvf->fr().get_native_receiver();
memset(&_value, 0, sizeof(_value)); _value.l = JNIHandles::make_local(_calling_thread, receiver);
_value.l = NULL; } else {
return; StackValueCollection *locals = _jvf->locals();
}
if (locals->at(_index)->type() == T_CONFLICT) {
memset(&_value, 0, sizeof(_value));
_value.l = NULL;
return;
}
switch (_type) { switch (_type) {
case T_INT: _value.i = locals->int_at (_index); break; case T_INT: _value.i = locals->int_at (_index); break;
case T_LONG: _value.j = locals->long_at (_index); break; case T_LONG: _value.j = locals->long_at (_index); break;
case T_FLOAT: _value.f = locals->float_at (_index); break; case T_FLOAT: _value.f = locals->float_at (_index); break;
case T_DOUBLE: _value.d = locals->double_at(_index); break; case T_DOUBLE: _value.d = locals->double_at(_index); break;
case T_OBJECT: { case T_OBJECT: {
// Wrap the oop to be returned in a local JNI handle since // Wrap the oop to be returned in a local JNI handle since
// oops_do() no longer applies after doit() is finished. // oops_do() no longer applies after doit() is finished.
oop obj = locals->obj_at(_index)(); oop obj = locals->obj_at(_index)();
_value.l = JNIHandles::make_local(_calling_thread, obj); _value.l = JNIHandles::make_local(_calling_thread, obj);
break; break;
} }
default: ShouldNotReachHere(); default: ShouldNotReachHere();
}
} }
} }
} }
...@@ -825,6 +839,10 @@ bool VM_GetOrSetLocal::allow_nested_vm_operations() const { ...@@ -825,6 +839,10 @@ bool VM_GetOrSetLocal::allow_nested_vm_operations() const {
} }
VM_GetReceiver::VM_GetReceiver(
JavaThread* thread, JavaThread* caller_thread, jint depth)
: VM_GetOrSetLocal(thread, caller_thread, depth, 0) {}
///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////
// //
......
...@@ -355,7 +355,7 @@ bool JvmtiCurrentBreakpoints::is_breakpoint(address bcp) { ...@@ -355,7 +355,7 @@ bool JvmtiCurrentBreakpoints::is_breakpoint(address bcp) {
// to the thread simultaneously. // to the thread simultaneously.
// //
class VM_GetOrSetLocal : public VM_Operation { class VM_GetOrSetLocal : public VM_Operation {
private: protected:
JavaThread* _thread; JavaThread* _thread;
JavaThread* _calling_thread; JavaThread* _calling_thread;
jint _depth; jint _depth;
...@@ -365,6 +365,10 @@ private: ...@@ -365,6 +365,10 @@ private:
javaVFrame* _jvf; javaVFrame* _jvf;
bool _set; bool _set;
// 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; jvmtiError _result;
vframe* get_vframe(); vframe* get_vframe();
...@@ -395,6 +399,15 @@ public: ...@@ -395,6 +399,15 @@ public:
static bool is_assignable(const char* ty_sign, Klass* klass, Thread* thread); static bool is_assignable(const char* ty_sign, Klass* klass, Thread* thread);
}; };
class VM_GetReceiver : public VM_GetOrSetLocal {
protected:
virtual bool getting_receiver() const { return true; }
public:
VM_GetReceiver(JavaThread* thread, JavaThread* calling_thread, jint depth);
const char* name() const { return "get receiver"; }
};
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// //
......
...@@ -1071,28 +1071,20 @@ oop* frame::oopmapreg_to_location(VMReg reg, const RegisterMap* reg_map) const { ...@@ -1071,28 +1071,20 @@ oop* frame::oopmapreg_to_location(VMReg reg, const RegisterMap* reg_map) const {
} }
} }
BasicLock* frame::compiled_synchronized_native_monitor(nmethod* nm) { BasicLock* frame::get_native_monitor() {
if (nm == NULL) { nmethod* nm = (nmethod*)_cb;
assert(_cb != NULL && _cb->is_nmethod() && assert(_cb != NULL && _cb->is_nmethod() && nm->method()->is_native(),
nm->method()->is_native() && "Should not call this unless it's a native nmethod");
nm->method()->is_synchronized(), int byte_offset = in_bytes(nm->native_basic_lock_sp_offset());
"should not call this otherwise");
nm = (nmethod*) _cb;
}
int byte_offset = in_bytes(nm->compiled_synchronized_native_basic_lock_sp_offset());
assert(byte_offset >= 0, "should not see invalid offset"); assert(byte_offset >= 0, "should not see invalid offset");
return (BasicLock*) &sp()[byte_offset / wordSize]; return (BasicLock*) &sp()[byte_offset / wordSize];
} }
oop frame::compiled_synchronized_native_monitor_owner(nmethod* nm) { oop frame::get_native_receiver() {
if (nm == NULL) { nmethod* nm = (nmethod*)_cb;
assert(_cb != NULL && _cb->is_nmethod() && assert(_cb != NULL && _cb->is_nmethod() && nm->method()->is_native(),
nm->method()->is_native() && "Should not call this unless it's a native nmethod");
nm->method()->is_synchronized(), int byte_offset = in_bytes(nm->native_receiver_sp_offset());
"should not call this otherwise");
nm = (nmethod*) _cb;
}
int byte_offset = in_bytes(nm->compiled_synchronized_native_basic_lock_owner_sp_offset());
assert(byte_offset >= 0, "should not see invalid offset"); assert(byte_offset >= 0, "should not see invalid offset");
oop owner = ((oop*) sp())[byte_offset / wordSize]; oop owner = ((oop*) sp())[byte_offset / wordSize];
assert( Universe::heap()->is_in(owner), "bad receiver" ); assert( Universe::heap()->is_in(owner), "bad receiver" );
......
...@@ -254,10 +254,10 @@ class frame VALUE_OBJ_CLASS_SPEC { ...@@ -254,10 +254,10 @@ class frame VALUE_OBJ_CLASS_SPEC {
// Return the monitor owner and BasicLock for compiled synchronized // Return the monitor owner and BasicLock for compiled synchronized
// native methods so that biased locking can revoke the receiver's // native methods so that biased locking can revoke the receiver's
// bias if necessary. Takes optional nmethod for this frame as // bias if necessary. This is also used by JVMTI's GetLocalInstance method
// argument to avoid performing repeated lookups in code cache. // (via VM_GetReceiver) to retrieve the receiver from a native wrapper frame.
BasicLock* compiled_synchronized_native_monitor (nmethod* nm = NULL); BasicLock* get_native_monitor();
oop compiled_synchronized_native_monitor_owner(nmethod* nm = NULL); oop get_native_receiver();
// Find receiver for an invoke when arguments are just pushed on stack (i.e., callee stack-frame is // Find receiver for an invoke when arguments are just pushed on stack (i.e., callee stack-frame is
// not setup) // not setup)
......
...@@ -207,8 +207,8 @@ GrowableArray<MonitorInfo*>* compiledVFrame::monitors() const { ...@@ -207,8 +207,8 @@ GrowableArray<MonitorInfo*>* compiledVFrame::monitors() const {
GrowableArray<MonitorInfo*> *monitors = new GrowableArray<MonitorInfo*>(1); GrowableArray<MonitorInfo*> *monitors = new GrowableArray<MonitorInfo*>(1);
// Casting away const // Casting away const
frame& fr = (frame&) _fr; frame& fr = (frame&) _fr;
MonitorInfo* info = new MonitorInfo(fr.compiled_synchronized_native_monitor_owner(nm), MonitorInfo* info = new MonitorInfo(
fr.compiled_synchronized_native_monitor(nm), false, false); fr.get_native_receiver(), fr.get_native_monitor(), false, false);
monitors->push(info); monitors->push(info);
return monitors; return monitors;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册