< prev index next >

src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.cpp

Print this page

 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #include "precompiled.hpp"
 26 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
 27 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
 28 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
 29 #include "jfr/recorder/stacktrace/jfrStackTrace.hpp"
 30 #include "jfr/support/jfrMethodLookup.hpp"

 31 #include "memory/allocation.inline.hpp"
 32 #include "oops/instanceKlass.inline.hpp"

 33 #include "runtime/vframe.inline.hpp"
 34 
 35 static void copy_frames(JfrStackFrame** lhs_frames, u4 length, const JfrStackFrame* rhs_frames) {
 36   assert(lhs_frames != NULL, "invariant");
 37   assert(rhs_frames != NULL, "invariant");
 38   if (length > 0) {
 39     *lhs_frames = NEW_C_HEAP_ARRAY(JfrStackFrame, length, mtTracing);
 40     memcpy(*lhs_frames, rhs_frames, length * sizeof(JfrStackFrame));
 41   }
 42 }
 43 
 44 JfrStackFrame::JfrStackFrame(const traceid& id, int bci, int type, const InstanceKlass* ik) :
 45   _klass(ik), _methodid(id), _line(0), _bci(bci), _type(type) {}
 46 
 47 JfrStackFrame::JfrStackFrame(const traceid& id, int bci, int type, int lineno, const InstanceKlass* ik) :
 48   _klass(ik), _methodid(id), _line(lineno), _bci(bci), _type(type) {}
 49 
 50 JfrStackTrace::JfrStackTrace(JfrStackFrame* frames, u4 max_frames) :
 51   _next(NULL),
 52   _frames(frames),

114   }
115   return true;
116 }
117 
118 template <typename Writer>
119 static void write_frame(Writer& w, traceid methodid, int line, int bci, u1 type) {
120   w.write((u8)methodid);
121   w.write((u4)line);
122   w.write((u4)bci);
123   w.write((u8)type);
124 }
125 
126 void JfrStackFrame::write(JfrChunkWriter& cw) const {
127   write_frame(cw, _methodid, _line, _bci, _type);
128 }
129 
130 void JfrStackFrame::write(JfrCheckpointWriter& cpw) const {
131   write_frame(cpw, _methodid, _line, _bci, _type);
132 }
133 
134 class vframeStreamSamples : public vframeStreamCommon {














135  public:
136   // constructor that starts with sender of frame fr (top_frame)
137   vframeStreamSamples(JavaThread *jt, frame fr, bool stop_at_java_call_stub) : vframeStreamCommon(jt, false /* process_frames */) {
138     _stop_at_java_call_stub = stop_at_java_call_stub;
139     _frame = fr;
140 
141     // We must always have a valid frame to start filling
142     bool filled_in = fill_from_frame();
143     assert(filled_in, "invariant");
144   }
145   void samples_next();
146   void stop() {}
147 };
148 















































































149 // Solaris SPARC Compiler1 needs an additional check on the grandparent
150 // of the top_frame when the parent of the top_frame is interpreted and
151 // the grandparent is compiled. However, in this method we do not know
152 // the relationship of the current _frame relative to the top_frame so
153 // we implement a more broad sanity check. When the previous callee is
154 // interpreted and the current sender is compiled, we verify that the
155 // current sender is also walkable. If it is not walkable, then we mark
156 // the current vframeStream as at the end.
157 void vframeStreamSamples::samples_next() {
158   // handle frames with inlining
159   if (_mode == compiled_mode &&
160     vframeStreamCommon::fill_in_compiled_inlined_sender()) {
161     return;
162   }
163 
164   // handle general case
165   u4 loop_count = 0;
166   u4 loop_max = MAX_STACK_DEPTH * 2;
167   do {
168     loop_count++;
169     // By the time we get here we should never see unsafe but better safe then segv'd
170     if (loop_count > loop_max || !_frame.safe_for_sender(_thread)) {
171       _mode = at_end_mode;
172       return;
173     }
174     _frame = _frame.sender(&_reg_map);
175   } while (!fill_from_frame());
176 }
177 
178 bool JfrStackTrace::record_thread(JavaThread& thread, frame& frame) {
179   vframeStreamSamples st(&thread, frame, false);









180   u4 count = 0;
181   _reached_root = true;






182 
183   _hash = 1;
184   while (!st.at_end()) {
185     if (count >= _max_frames) {
186       _reached_root = false;
187       break;
188     }
189     const Method* method = st.method();
190     if (!Method::is_valid_method(method)) {
191       // we throw away everything we've gathered in this sample since
192       // none of it is safe
193       return false;


194     }
195     const traceid mid = JfrTraceId::load(method);
196     int type = st.is_interpreted_frame() ? JfrStackFrame::FRAME_INTERPRETER : JfrStackFrame::FRAME_JIT;
197     int bci = 0;
198     if (method->is_native()) {
199       type = JfrStackFrame::FRAME_NATIVE;
200     } else {
201       bci = st.bci();
202     }
203 
204     intptr_t* frame_id = st.frame_id();
205     st.samples_next();
206     if (type == JfrStackFrame::FRAME_JIT && !st.at_end() && frame_id == st.frame_id()) {
207       // This frame and the caller frame are both the same physical
208       // frame, so this frame is inlined into the caller.
209       type = JfrStackFrame::FRAME_INLINE;
210     }
211 
212     const int lineno = method->line_number_from_bci(bci);
213     _hash = (_hash * 31) + mid;
214     _hash = (_hash * 31) + bci;
215     _hash = (_hash * 31) + type;
216     _frames[count] = JfrStackFrame(mid, bci, type, lineno, method->method_holder());
217     count++;
218   }
219 
220   _lineno = true;




221   _nr_of_frames = count;
222   return true;


















223 }
224 
225 void JfrStackFrame::resolve_lineno() const {
226   assert(_klass, "no klass pointer");
227   assert(_line == 0, "already have linenumber");
228   const Method* const method = JfrMethodLookup::lookup(_klass, _methodid);
229   assert(method != NULL, "invariant");
230   assert(method->method_holder() == _klass, "invariant");
231   _line = method->line_number_from_bci(_bci);
232 }
233 
234 void JfrStackTrace::resolve_linenos() const {

235   for (unsigned int i = 0; i < _nr_of_frames; i++) {
236     _frames[i].resolve_lineno();
237   }
238   _lineno = true;
239 }
240 
241 bool JfrStackTrace::record_safe(JavaThread* thread, int skip) {
242   assert(thread == Thread::current(), "Thread stack needs to be walkable");
243   vframeStream vfs(thread, false /* stop_at_java_call_stub */, false /* process_frames */);
244   u4 count = 0;
245   _reached_root = true;
246   for (int i = 0; i < skip; i++) {
247     if (vfs.at_end()) {
248       break;
249     }
250     vfs.next();
251   }
252 
253   _hash = 1;
254   while (!vfs.at_end()) {
255     if (count >= _max_frames) {
256       _reached_root = false;
257       break;
258     }
259     const Method* method = vfs.method();
260     const traceid mid = JfrTraceId::load(method);
261     int type = vfs.is_interpreted_frame() ? JfrStackFrame::FRAME_INTERPRETER : JfrStackFrame::FRAME_JIT;
262     int bci = 0;
263     if (method->is_native()) {
264       type = JfrStackFrame::FRAME_NATIVE;
265     }
266     else {
267       bci = vfs.bci();
268     }
269     intptr_t* frame_id = vfs.frame_id();
270     vfs.next();
271     if (type == JfrStackFrame::FRAME_JIT && !vfs.at_end() && frame_id == vfs.frame_id()) {
272       // This frame and the caller frame are both the same physical
273       // frame, so this frame is inlined into the caller.
274       type = JfrStackFrame::FRAME_INLINE;
275     }
276 
277     _hash = (_hash * 31) + mid;
278     _hash = (_hash * 31) + bci;
279     _hash = (_hash * 31) + type;
280     _frames[count] = JfrStackFrame(mid, bci, type, method->method_holder());
281     count++;
282   }
283 
284   _nr_of_frames = count;
285   return true;
286 }
287 

 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #include "precompiled.hpp"
 26 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
 27 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
 28 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
 29 #include "jfr/recorder/stacktrace/jfrStackTrace.hpp"
 30 #include "jfr/support/jfrMethodLookup.hpp"
 31 
 32 #include "memory/allocation.inline.hpp"
 33 #include "oops/instanceKlass.inline.hpp"
 34 #include "runtime/handles.inline.hpp"
 35 #include "runtime/vframe.inline.hpp"
 36 
 37 static void copy_frames(JfrStackFrame** lhs_frames, u4 length, const JfrStackFrame* rhs_frames) {
 38   assert(lhs_frames != NULL, "invariant");
 39   assert(rhs_frames != NULL, "invariant");
 40   if (length > 0) {
 41     *lhs_frames = NEW_C_HEAP_ARRAY(JfrStackFrame, length, mtTracing);
 42     memcpy(*lhs_frames, rhs_frames, length * sizeof(JfrStackFrame));
 43   }
 44 }
 45 
 46 JfrStackFrame::JfrStackFrame(const traceid& id, int bci, int type, const InstanceKlass* ik) :
 47   _klass(ik), _methodid(id), _line(0), _bci(bci), _type(type) {}
 48 
 49 JfrStackFrame::JfrStackFrame(const traceid& id, int bci, int type, int lineno, const InstanceKlass* ik) :
 50   _klass(ik), _methodid(id), _line(lineno), _bci(bci), _type(type) {}
 51 
 52 JfrStackTrace::JfrStackTrace(JfrStackFrame* frames, u4 max_frames) :
 53   _next(NULL),
 54   _frames(frames),

116   }
117   return true;
118 }
119 
120 template <typename Writer>
121 static void write_frame(Writer& w, traceid methodid, int line, int bci, u1 type) {
122   w.write((u8)methodid);
123   w.write((u4)line);
124   w.write((u4)bci);
125   w.write((u8)type);
126 }
127 
128 void JfrStackFrame::write(JfrChunkWriter& cw) const {
129   write_frame(cw, _methodid, _line, _bci, _type);
130 }
131 
132 void JfrStackFrame::write(JfrCheckpointWriter& cpw) const {
133   write_frame(cpw, _methodid, _line, _bci, _type);
134 }
135 
136 class JfrVframeStream : public vframeStreamCommon {
137  private:
138   oop _continuation;
139   oop _continuation_scope;
140   bool _continuation_scope_end_condition;
141   bool _async_mode;
142 
143   bool at_continuation_entry_frame() const;
144   bool at_continuation_scope_entry_frame();
145   void set_parent_continuation();
146   void set_continuation_scope();
147   void seek_stable_frame();
148   bool get_sender_frame();
149   void up();
150   DEBUG_ONLY(void assert_continuation_state() const;)
151  public:
152   JfrVframeStream(JavaThread* jt, const frame& fr, bool async_mode);
153   void next_vframe();
154   bool continuation_scope_end_condition() const;








155 };
156 
157 inline void JfrVframeStream::seek_stable_frame() {
158   while (!fill_from_frame()) {
159     if (at_continuation_entry_frame()) {
160       set_parent_continuation();
161     }
162     get_sender_frame();
163   }
164 }
165 
166 JfrVframeStream::JfrVframeStream(JavaThread* jt, const frame& fr, bool async_mode) : vframeStreamCommon(RegisterMap(jt, false, false, true)),
167 _continuation(jt->last_continuation()->cont_oop()), _continuation_scope(NULL), _continuation_scope_end_condition(false), _async_mode(async_mode) {
168   _stop_at_java_call_stub = false;
169   _frame = fr;
170   seek_stable_frame();
171   if (at_continuation_entry_frame()) {
172     set_parent_continuation();
173     if (get_sender_frame()) {
174       seek_stable_frame();
175     }
176   }
177   set_continuation_scope();
178   DEBUG_ONLY(assert_continuation_state();)
179 }
180 
181 inline bool JfrVframeStream::at_continuation_entry_frame() const {
182   return _continuation != (oop)NULL && Continuation::is_continuation_enterSpecial(_frame);
183 }
184 
185 inline void JfrVframeStream::set_parent_continuation() {
186   _continuation = jdk_internal_vm_Continuation::parent(_continuation);
187 }
188 
189 inline void JfrVframeStream::set_continuation_scope() {
190   if (_continuation != (oop)NULL) {
191     _continuation_scope = jdk_internal_vm_Continuation::scope(_continuation);
192   }
193 }
194 
195 #ifdef ASSERT
196 void JfrVframeStream::assert_continuation_state() const {
197   assert(_reg_map.cont() == (oop)NULL || (_continuation == _reg_map.cont()),
198     "map.cont: " INTPTR_FORMAT " JfrVframeStream: " INTPTR_FORMAT,
199     p2i((oopDesc*)_reg_map.cont()), p2i((oopDesc*)_continuation));
200 }
201 #endif
202 
203 inline bool JfrVframeStream::at_continuation_scope_entry_frame() {
204   assert(_continuation_scope == (oop)NULL || _continuation != (oop)NULL, "must be");
205   if (!at_continuation_entry_frame()) {
206     return false;
207   }
208   if (_continuation_scope != (oop)NULL && jdk_internal_vm_Continuation::scope(_continuation) == _continuation_scope) {
209     return true;
210   }
211   set_parent_continuation();
212   // set_continuation_scope();
213   DEBUG_ONLY(assert_continuation_state();)
214   return false;
215 }
216 
217 inline bool JfrVframeStream::get_sender_frame() {
218   if (_async_mode && !_frame.safe_for_sender(_thread)) {
219     _mode = at_end_mode;
220     return false;
221   }
222   _frame = _frame.sender(&_reg_map);
223   return true;
224 }
225 
226 inline void JfrVframeStream::up() {
227   do {
228     if (at_continuation_scope_entry_frame()) {
229       _continuation_scope_end_condition = true;
230       _mode = at_end_mode;
231       return;
232     }
233   } while (get_sender_frame() && !fill_from_frame());
234 }
235 
236 // Solaris SPARC Compiler1 needs an additional check on the grandparent
237 // of the top_frame when the parent of the top_frame is interpreted and
238 // the grandparent is compiled. However, in this method we do not know
239 // the relationship of the current _frame relative to the top_frame so
240 // we implement a more broad sanity check. When the previous callee is
241 // interpreted and the current sender is compiled, we verify that the
242 // current sender is also walkable. If it is not walkable, then we mark
243 // the current vframeStream as at the end.
244 void JfrVframeStream::next_vframe() {
245   // handle frames with inlining
246   if (_mode == compiled_mode && fill_in_compiled_inlined_sender()) {

247     return;
248   }

249   // handle general case
250   up();
251 }
252 
253 inline bool JfrVframeStream::continuation_scope_end_condition() const {
254   assert(_mode == at_end_mode, "invariant");
255   return _continuation_scope_end_condition;





256 }
257 
258 inline bool is_virtual(JavaThread* jt) {
259   assert(jt != NULL, "invariant");
260   assert(jt->threadObj() != (oop)NULL, "invariant");
261   return jt->vthread() != jt->threadObj();
262 }
263 
264 bool JfrStackTrace::record(JavaThread* jt, const frame& frame, int skip, bool async_mode, bool* virtual_thread) {
265   assert(jt != NULL, "invariant");
266   Thread* current_thread = Thread::current();
267   HandleMark hm(current_thread); // TODO: RegisterMap uses Handles for continuations. But some callers here have NoHandleMark set.
268   JfrVframeStream vfs(jt, frame, async_mode);
269   u4 count = 0;
270   _reached_root = true;
271   for (int i = 0; i < skip; ++i) {
272     if (vfs.at_end()) {
273       break;
274     }
275     vfs.next_vframe();
276   }
277 
278   _hash = 1;
279   while (!vfs.at_end()) {
280     if (count >= _max_frames) {
281       _reached_root = false;
282       break;
283     }
284     const Method* method = vfs.method();
285     if (async_mode) {
286       if (!Method::is_valid_method(method)) {
287         // we throw away everything we've gathered
288         // in this sample since none of it is safe
289         return false;
290       }
291     }
292     const traceid mid = JfrTraceId::load(method);
293     int type = vfs.is_interpreted_frame() ? JfrStackFrame::FRAME_INTERPRETER : JfrStackFrame::FRAME_JIT;
294     int bci = 0;
295     if (method->is_native()) {
296       type = JfrStackFrame::FRAME_NATIVE;
297     } else {
298       bci = vfs.bci();
299     }
300 
301     intptr_t* frame_id = vfs.frame_id();
302     vfs.next_vframe();
303     if (type == JfrStackFrame::FRAME_JIT && !vfs.at_end() && frame_id == vfs.frame_id()) {
304       // This frame and the caller frame are both the same physical
305       // frame, so this frame is inlined into the caller.
306       type = JfrStackFrame::FRAME_INLINE;
307     }
308 
309     const int lineno = async_mode ? method->line_number_from_bci(bci) : 0;
310     _hash = (_hash * 31) + mid;
311     _hash = (_hash * 31) + bci;
312     _hash = (_hash * 31) + type;
313     _frames[count] = JfrStackFrame(mid, bci, type, lineno, method->method_holder());
314     count++;
315   }
316 
317   if (async_mode) {
318     assert(virtual_thread != NULL, "invariant");
319     assert(_lineno, "invarinat");
320     *virtual_thread = _reached_root ? vfs.continuation_scope_end_condition() : is_virtual(jt);
321   }
322   _nr_of_frames = count;
323   return count > 0;
324 }
325 
326 bool JfrStackTrace::record_async(JavaThread* other_thread, frame& frame, bool* virtual_thread) {
327   assert(other_thread != NULL, "invariant");
328   assert(other_thread != Thread::current(), "invariant");
329   assert(virtual_thread != NULL, "invariant");
330   _lineno = true;
331   return record(other_thread, frame, 0, true, virtual_thread);
332 }
333 
334 bool JfrStackTrace::record(JavaThread* current_thread, int skip) {
335   assert(current_thread != NULL, "invariant");
336   assert(current_thread == Thread::current(), "invariant");
337   if (!current_thread->has_last_Java_frame()) {
338     return false;
339   }
340   _lineno = false;
341   return record(current_thread, current_thread->last_frame(), skip, false, NULL);
342 }
343 
344 void JfrStackFrame::resolve_lineno() const {
345   assert(_klass, "no klass pointer");
346   assert(_line == 0, "already have linenumber");
347   const Method* const method = JfrMethodLookup::lookup(_klass, _methodid);
348   assert(method != NULL, "invariant");
349   assert(method->method_holder() == _klass, "invariant");
350   _line = method->line_number_from_bci(_bci);
351 }
352 
353 void JfrStackTrace::resolve_linenos() const {
354   assert(!_lineno, "invariant");
355   for (unsigned int i = 0; i < _nr_of_frames; i++) {
356     _frames[i].resolve_lineno();
357   }
358   _lineno = true;
359 }
















































< prev index next >