6936709: AsyncGetCallTrace doesn't handle inexact stack walking properly

Thu, 01 Apr 2010 16:06:57 -0700

author
never
date
Thu, 01 Apr 2010 16:06:57 -0700
changeset 1784
547cbe6dacc5
parent 1783
7f4deda46b04
child 1785
1c9c45172908

6936709: AsyncGetCallTrace doesn't handle inexact stack walking properly
Reviewed-by: kvn

src/share/vm/prims/forte.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/prims/forte.cpp	Wed Mar 31 16:29:10 2010 -0700
     1.2 +++ b/src/share/vm/prims/forte.cpp	Thu Apr 01 16:06:57 2010 -0700
     1.3 @@ -55,12 +55,11 @@
     1.4  };
     1.5  
     1.6  
     1.7 -static void is_decipherable_compiled_frame(frame* fr, RegisterMap* map,
     1.8 -  bool* is_compiled_p, bool* is_walkable_p);
     1.9 +static bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm);
    1.10  static bool is_decipherable_interpreted_frame(JavaThread* thread,
    1.11 -                                                frame* fr,
    1.12 -                                                methodOop* method_p,
    1.13 -                                                int* bci_p);
    1.14 +                                              frame* fr,
    1.15 +                                              methodOop* method_p,
    1.16 +                                              int* bci_p);
    1.17  
    1.18  
    1.19  
    1.20 @@ -122,41 +121,43 @@
    1.21  // Determine if 'fr' is a decipherable compiled frame. We are already
    1.22  // assured that fr is for a java nmethod.
    1.23  
    1.24 -static bool is_decipherable_compiled_frame(frame* fr) {
    1.25 -
    1.26 -  assert(fr->cb() != NULL && fr->cb()->is_nmethod(), "invariant");
    1.27 -  nmethod* nm = (nmethod*) fr->cb();
    1.28 +static bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm) {
    1.29    assert(nm->is_java_method(), "invariant");
    1.30  
    1.31 -  // First try and find an exact PcDesc
    1.32 +  if (thread->has_last_Java_frame() && thread->last_Java_pc() == fr->pc()) {
    1.33 +    // We're stopped at a call into the JVM so look for a PcDesc with
    1.34 +    // the actual pc reported by the frame.
    1.35 +    PcDesc* pc_desc = nm->pc_desc_at(fr->pc());
    1.36  
    1.37 -  PcDesc* pc_desc = nm->pc_desc_at(fr->pc());
    1.38 -
    1.39 -  // Did we find a useful PcDesc?
    1.40 -  if (pc_desc != NULL &&
    1.41 -      pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) {
    1.42 -
    1.43 -    address probe_pc = fr->pc() + 1;
    1.44 -    pc_desc = nm->pc_desc_near(probe_pc);
    1.45 -
    1.46 -    // Now do we have a useful PcDesc?
    1.47 -
    1.48 +    // Did we find a useful PcDesc?
    1.49      if (pc_desc != NULL &&
    1.50 -        pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) {
    1.51 -      // No debug information available for this pc
    1.52 -      // vframeStream would explode if we try and walk the frames.
    1.53 -      return false;
    1.54 +        pc_desc->scope_decode_offset() != DebugInformationRecorder::serialized_null) {
    1.55 +      return true;
    1.56      }
    1.57 -
    1.58 -    // This PcDesc is useful however we must adjust the frame's pc
    1.59 -    // so that the vframeStream lookups will use this same pc
    1.60 -
    1.61 -    fr->set_pc(pc_desc->real_pc(nm));
    1.62    }
    1.63  
    1.64 +  // We're at some random pc in the nmethod so search for the PcDesc
    1.65 +  // whose pc is greater than the current PC.  It's done this way
    1.66 +  // because the extra PcDescs that are recorded for improved debug
    1.67 +  // info record the end of the region covered by the ScopeDesc
    1.68 +  // instead of the beginning.
    1.69 +  PcDesc* pc_desc = nm->pc_desc_near(fr->pc() + 1);
    1.70 +
    1.71 +  // Now do we have a useful PcDesc?
    1.72 +  if (pc_desc == NULL ||
    1.73 +      pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) {
    1.74 +    // No debug information available for this pc
    1.75 +    // vframeStream would explode if we try and walk the frames.
    1.76 +    return false;
    1.77 +  }
    1.78 +
    1.79 +  // This PcDesc is useful however we must adjust the frame's pc
    1.80 +  // so that the vframeStream lookups will use this same pc
    1.81 +  fr->set_pc(pc_desc->real_pc(nm));
    1.82    return true;
    1.83  }
    1.84  
    1.85 +
    1.86  // Determine if 'fr' is a walkable interpreted frame. Returns false
    1.87  // if it is not. *method_p, and *bci_p are not set when false is
    1.88  // returned. *method_p is non-NULL if frame was executing a Java
    1.89 @@ -166,9 +167,9 @@
    1.90  // even if a valid BCI cannot be found.
    1.91  
    1.92  static bool is_decipherable_interpreted_frame(JavaThread* thread,
    1.93 -                                                frame* fr,
    1.94 -                                                methodOop* method_p,
    1.95 -                                                int* bci_p) {
    1.96 +                                              frame* fr,
    1.97 +                                              methodOop* method_p,
    1.98 +                                              int* bci_p) {
    1.99    assert(fr->is_interpreted_frame(), "just checking");
   1.100  
   1.101    // top frame is an interpreted frame
   1.102 @@ -323,13 +324,15 @@
   1.103        // have a PCDesc that can get us a bci however we did find
   1.104        // a method
   1.105  
   1.106 -      if (!is_decipherable_compiled_frame(&candidate)) {
   1.107 +      if (!is_decipherable_compiled_frame(thread, &candidate, nm)) {
   1.108          return false;
   1.109        }
   1.110  
   1.111        // is_decipherable_compiled_frame may modify candidate's pc
   1.112        *initial_frame_p = candidate;
   1.113  
   1.114 +      assert(nm->pc_desc_at(candidate.pc()) != NULL, "if it's decipherable then pc must be valid");
   1.115 +
   1.116        return true;
   1.117      }
   1.118  

mercurial