comparison src/share/vm/prims/forte.cpp @ 1349:547cbe6dacc5

6936709: AsyncGetCallTrace doesn't handle inexact stack walking properly Reviewed-by: kvn
author never
date Thu, 01 Apr 2010 16:06:57 -0700
parents d1605aabd0a1
children cff162798819
comparison
equal deleted inserted replaced
1348:7f4deda46b04 1349:547cbe6dacc5
53 vframeStreamForte(JavaThread *jt, frame fr, bool stop_at_java_call_stub); 53 vframeStreamForte(JavaThread *jt, frame fr, bool stop_at_java_call_stub);
54 void forte_next(); 54 void forte_next();
55 }; 55 };
56 56
57 57
58 static void is_decipherable_compiled_frame(frame* fr, RegisterMap* map, 58 static bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm);
59 bool* is_compiled_p, bool* is_walkable_p);
60 static bool is_decipherable_interpreted_frame(JavaThread* thread, 59 static bool is_decipherable_interpreted_frame(JavaThread* thread,
61 frame* fr, 60 frame* fr,
62 methodOop* method_p, 61 methodOop* method_p,
63 int* bci_p); 62 int* bci_p);
64 63
65 64
66 65
67 66
68 vframeStreamForte::vframeStreamForte(JavaThread *jt, 67 vframeStreamForte::vframeStreamForte(JavaThread *jt,
120 } 119 }
121 120
122 // Determine if 'fr' is a decipherable compiled frame. We are already 121 // Determine if 'fr' is a decipherable compiled frame. We are already
123 // assured that fr is for a java nmethod. 122 // assured that fr is for a java nmethod.
124 123
125 static bool is_decipherable_compiled_frame(frame* fr) { 124 static bool is_decipherable_compiled_frame(JavaThread* thread, frame* fr, nmethod* nm) {
126
127 assert(fr->cb() != NULL && fr->cb()->is_nmethod(), "invariant");
128 nmethod* nm = (nmethod*) fr->cb();
129 assert(nm->is_java_method(), "invariant"); 125 assert(nm->is_java_method(), "invariant");
130 126
131 // First try and find an exact PcDesc 127 if (thread->has_last_Java_frame() && thread->last_Java_pc() == fr->pc()) {
132 128 // We're stopped at a call into the JVM so look for a PcDesc with
133 PcDesc* pc_desc = nm->pc_desc_at(fr->pc()); 129 // the actual pc reported by the frame.
134 130 PcDesc* pc_desc = nm->pc_desc_at(fr->pc());
135 // Did we find a useful PcDesc? 131
136 if (pc_desc != NULL && 132 // Did we find a useful PcDesc?
133 if (pc_desc != NULL &&
134 pc_desc->scope_decode_offset() != DebugInformationRecorder::serialized_null) {
135 return true;
136 }
137 }
138
139 // We're at some random pc in the nmethod so search for the PcDesc
140 // whose pc is greater than the current PC. It's done this way
141 // because the extra PcDescs that are recorded for improved debug
142 // info record the end of the region covered by the ScopeDesc
143 // instead of the beginning.
144 PcDesc* pc_desc = nm->pc_desc_near(fr->pc() + 1);
145
146 // Now do we have a useful PcDesc?
147 if (pc_desc == NULL ||
137 pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) { 148 pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) {
138 149 // No debug information available for this pc
139 address probe_pc = fr->pc() + 1; 150 // vframeStream would explode if we try and walk the frames.
140 pc_desc = nm->pc_desc_near(probe_pc); 151 return false;
141 152 }
142 // Now do we have a useful PcDesc? 153
143 154 // This PcDesc is useful however we must adjust the frame's pc
144 if (pc_desc != NULL && 155 // so that the vframeStream lookups will use this same pc
145 pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) { 156 fr->set_pc(pc_desc->real_pc(nm));
146 // No debug information available for this pc
147 // vframeStream would explode if we try and walk the frames.
148 return false;
149 }
150
151 // This PcDesc is useful however we must adjust the frame's pc
152 // so that the vframeStream lookups will use this same pc
153
154 fr->set_pc(pc_desc->real_pc(nm));
155 }
156
157 return true; 157 return true;
158 } 158 }
159
159 160
160 // Determine if 'fr' is a walkable interpreted frame. Returns false 161 // Determine if 'fr' is a walkable interpreted frame. Returns false
161 // if it is not. *method_p, and *bci_p are not set when false is 162 // if it is not. *method_p, and *bci_p are not set when false is
162 // returned. *method_p is non-NULL if frame was executing a Java 163 // returned. *method_p is non-NULL if frame was executing a Java
163 // method. *bci_p is != -1 if a valid BCI in the Java method could 164 // method. *bci_p is != -1 if a valid BCI in the Java method could
164 // be found. 165 // be found.
165 // Note: this method returns true when a valid Java method is found 166 // Note: this method returns true when a valid Java method is found
166 // even if a valid BCI cannot be found. 167 // even if a valid BCI cannot be found.
167 168
168 static bool is_decipherable_interpreted_frame(JavaThread* thread, 169 static bool is_decipherable_interpreted_frame(JavaThread* thread,
169 frame* fr, 170 frame* fr,
170 methodOop* method_p, 171 methodOop* method_p,
171 int* bci_p) { 172 int* bci_p) {
172 assert(fr->is_interpreted_frame(), "just checking"); 173 assert(fr->is_interpreted_frame(), "just checking");
173 174
174 // top frame is an interpreted frame 175 // top frame is an interpreted frame
175 // check if it is walkable (i.e. valid methodOop and valid bci) 176 // check if it is walkable (i.e. valid methodOop and valid bci)
176 177
321 322
322 // If it isn't decipherable then we have found a pc that doesn't 323 // If it isn't decipherable then we have found a pc that doesn't
323 // have a PCDesc that can get us a bci however we did find 324 // have a PCDesc that can get us a bci however we did find
324 // a method 325 // a method
325 326
326 if (!is_decipherable_compiled_frame(&candidate)) { 327 if (!is_decipherable_compiled_frame(thread, &candidate, nm)) {
327 return false; 328 return false;
328 } 329 }
329 330
330 // is_decipherable_compiled_frame may modify candidate's pc 331 // is_decipherable_compiled_frame may modify candidate's pc
331 *initial_frame_p = candidate; 332 *initial_frame_p = candidate;
333
334 assert(nm->pc_desc_at(candidate.pc()) != NULL, "if it's decipherable then pc must be valid");
332 335
333 return true; 336 return true;
334 } 337 }
335 338
336 // Must be some stub frame that we don't care about 339 // Must be some stub frame that we don't care about