8173309: jvmtiDeferredLocalVariableSet may update the wrong frame
Reviewed-by: kvn
--- a/hotspot/src/share/vm/runtime/vframe_hp.cpp Tue Jan 24 09:40:05 2017 +0100
+++ b/hotspot/src/share/vm/runtime/vframe_hp.cpp Wed Jan 25 19:18:43 2017 -0800
@@ -158,7 +158,7 @@
deferred = new(ResourceObj::C_HEAP, mtCompiler) GrowableArray<jvmtiDeferredLocalVariableSet*> (1, true);
thread()->set_deferred_locals(deferred);
}
- deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id()));
+ deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id(), vframe_id()));
assert(deferred->top()->id() == fr().id(), "Huh? Must match");
deferred->top()->set_local_at(index, type, value);
}
@@ -243,6 +243,7 @@
compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, CompiledMethod* nm)
: javaVFrame(fr, reg_map, thread) {
_scope = NULL;
+ _vframe_id = 0;
// Compiled method (native stub or Java code)
// native wrappers have no scope data, it is implied
if (!nm->is_compiled() || !nm->as_compiled_method()->is_native_method()) {
@@ -250,9 +251,10 @@
}
}
-compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope)
+compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope, int vframe_id)
: javaVFrame(fr, reg_map, thread) {
_scope = scope;
+ _vframe_id = vframe_id;
guarantee(_scope != NULL, "scope must be present");
}
@@ -316,14 +318,15 @@
} else {
return scope()->is_top()
? vframe::sender()
- : new compiledVFrame(&f, register_map(), thread(), scope()->sender());
+ : new compiledVFrame(&f, register_map(), thread(), scope()->sender(), vframe_id() + 1);
}
}
-jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id) {
+jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id, int vframe_id) {
_method = method;
_bci = bci;
_id = id;
+ _vframe_id = vframe_id;
// Alway will need at least one, must be on C heap
_locals = new(ResourceObj::C_HEAP, mtCompiler) GrowableArray<jvmtiDeferredLocalVariable*> (1, true);
}
@@ -339,7 +342,11 @@
bool jvmtiDeferredLocalVariableSet::matches(vframe* vf) {
if (!vf->is_compiled_frame()) return false;
compiledVFrame* cvf = (compiledVFrame*)vf;
- return cvf->fr().id() == id() && cvf->method() == method() && cvf->bci() == bci();
+ if (cvf->fr().id() == id() && cvf->vframe_id() == vframe_id()) {
+ assert(cvf->method() == method() && cvf->bci() == bci(), "must agree");
+ return true;
+ }
+ return false;
}
void jvmtiDeferredLocalVariableSet::set_local_at(int idx, BasicType type, jvalue val) {
--- a/hotspot/src/share/vm/runtime/vframe_hp.hpp Tue Jan 24 09:40:05 2017 +0100
+++ b/hotspot/src/share/vm/runtime/vframe_hp.hpp Wed Jan 25 19:18:43 2017 -0800
@@ -36,6 +36,7 @@
StackValueCollection* locals() const;
StackValueCollection* expressions() const;
GrowableArray<MonitorInfo*>* monitors() const;
+ int vframe_id() const { return _vframe_id; }
void set_locals(StackValueCollection* values) const;
@@ -68,14 +69,14 @@
protected:
ScopeDesc* _scope;
-
+ int _vframe_id;
//StackValue resolve(ScopeValue* sv) const;
BasicLock* resolve_monitor_lock(Location location) const;
StackValue *create_stack_value(ScopeValue *sv) const;
private:
- compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope);
+ compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope, int vframe_id);
#ifndef PRODUCT
public:
@@ -95,6 +96,7 @@
Method* _method;
int _bci;
intptr_t* _id;
+ int _vframe_id;
GrowableArray<jvmtiDeferredLocalVariable*>* _locals;
public:
@@ -102,6 +104,7 @@
Method* method() const { return _method; }
int bci() const { return _bci; }
intptr_t* id() const { return _id; }
+ int vframe_id() const { return _vframe_id; }
GrowableArray<jvmtiDeferredLocalVariable*>* locals() const { return _locals; }
void set_local_at(int idx, BasicType typ, jvalue val);
@@ -111,7 +114,7 @@
void oops_do(OopClosure* f);
// constructor
- jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id);
+ jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id, int vframe_id);
// destructor
~jvmtiDeferredLocalVariableSet();