提交 330543aa 编写于 作者: N never

6936709: AsyncGetCallTrace doesn't handle inexact stack walking properly

Reviewed-by: kvn
上级 357affb3
...@@ -55,12 +55,11 @@ class vframeStreamForte : public vframeStreamCommon { ...@@ -55,12 +55,11 @@ class vframeStreamForte : public vframeStreamCommon {
}; };
static void is_decipherable_compiled_frame(frame* fr, RegisterMap* map, static bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm);
bool* is_compiled_p, bool* is_walkable_p);
static bool is_decipherable_interpreted_frame(JavaThread* thread, static bool is_decipherable_interpreted_frame(JavaThread* thread,
frame* fr, frame* fr,
methodOop* method_p, methodOop* method_p,
int* bci_p); int* bci_p);
...@@ -122,41 +121,43 @@ void vframeStreamForte::forte_next() { ...@@ -122,41 +121,43 @@ void vframeStreamForte::forte_next() {
// Determine if 'fr' is a decipherable compiled frame. We are already // Determine if 'fr' is a decipherable compiled frame. We are already
// assured that fr is for a java nmethod. // assured that fr is for a java nmethod.
static bool is_decipherable_compiled_frame(frame* fr) { static bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm) {
assert(fr->cb() != NULL && fr->cb()->is_nmethod(), "invariant");
nmethod* nm = (nmethod*) fr->cb();
assert(nm->is_java_method(), "invariant"); assert(nm->is_java_method(), "invariant");
// First try and find an exact PcDesc if (thread->has_last_Java_frame() && thread->last_Java_pc() == fr->pc()) {
// We're stopped at a call into the JVM so look for a PcDesc with
PcDesc* pc_desc = nm->pc_desc_at(fr->pc()); // the actual pc reported by the frame.
PcDesc* pc_desc = nm->pc_desc_at(fr->pc());
// Did we find a useful PcDesc?
if (pc_desc != NULL &&
pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) {
address probe_pc = fr->pc() + 1;
pc_desc = nm->pc_desc_near(probe_pc);
// Now do we have a useful PcDesc?
// Did we find a useful PcDesc?
if (pc_desc != NULL && if (pc_desc != NULL &&
pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) { pc_desc->scope_decode_offset() != DebugInformationRecorder::serialized_null) {
// No debug information available for this pc return true;
// vframeStream would explode if we try and walk the frames.
return false;
} }
}
// This PcDesc is useful however we must adjust the frame's pc // We're at some random pc in the nmethod so search for the PcDesc
// so that the vframeStream lookups will use this same pc // whose pc is greater than the current PC. It's done this way
// because the extra PcDescs that are recorded for improved debug
// info record the end of the region covered by the ScopeDesc
// instead of the beginning.
PcDesc* pc_desc = nm->pc_desc_near(fr->pc() + 1);
fr->set_pc(pc_desc->real_pc(nm)); // Now do we have a useful PcDesc?
if (pc_desc == NULL ||
pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) {
// No debug information available for this pc
// vframeStream would explode if we try and walk the frames.
return false;
} }
// This PcDesc is useful however we must adjust the frame's pc
// so that the vframeStream lookups will use this same pc
fr->set_pc(pc_desc->real_pc(nm));
return true; return true;
} }
// Determine if 'fr' is a walkable interpreted frame. Returns false // Determine if 'fr' is a walkable interpreted frame. Returns false
// if it is not. *method_p, and *bci_p are not set when false is // if it is not. *method_p, and *bci_p are not set when false is
// returned. *method_p is non-NULL if frame was executing a Java // returned. *method_p is non-NULL if frame was executing a Java
...@@ -166,9 +167,9 @@ static bool is_decipherable_compiled_frame(frame* fr) { ...@@ -166,9 +167,9 @@ static bool is_decipherable_compiled_frame(frame* fr) {
// even if a valid BCI cannot be found. // even if a valid BCI cannot be found.
static bool is_decipherable_interpreted_frame(JavaThread* thread, static bool is_decipherable_interpreted_frame(JavaThread* thread,
frame* fr, frame* fr,
methodOop* method_p, methodOop* method_p,
int* bci_p) { int* bci_p) {
assert(fr->is_interpreted_frame(), "just checking"); assert(fr->is_interpreted_frame(), "just checking");
// top frame is an interpreted frame // top frame is an interpreted frame
...@@ -323,13 +324,15 @@ static bool find_initial_Java_frame(JavaThread* thread, ...@@ -323,13 +324,15 @@ static bool find_initial_Java_frame(JavaThread* thread,
// have a PCDesc that can get us a bci however we did find // have a PCDesc that can get us a bci however we did find
// a method // a method
if (!is_decipherable_compiled_frame(&candidate)) { if (!is_decipherable_compiled_frame(thread, &candidate, nm)) {
return false; return false;
} }
// is_decipherable_compiled_frame may modify candidate's pc // is_decipherable_compiled_frame may modify candidate's pc
*initial_frame_p = candidate; *initial_frame_p = candidate;
assert(nm->pc_desc_at(candidate.pc()) != NULL, "if it's decipherable then pc must be valid");
return true; return true;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册