1 /*
  2  * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 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),
 55   _id(0),
 56   _hash(0),
 57   _nr_of_frames(0),
 58   _max_frames(max_frames),
 59   _frames_ownership(false),
 60   _reached_root(false),
 61   _lineno(false),
 62   _written(false) {}
 63 
 64 JfrStackTrace::JfrStackTrace(traceid id, const JfrStackTrace& trace, const JfrStackTrace* next) :
 65   _next(next),
 66   _frames(NULL),
 67   _id(id),
 68   _hash(trace._hash),
 69   _nr_of_frames(trace._nr_of_frames),
 70   _max_frames(trace._max_frames),
 71   _frames_ownership(true),
 72   _reached_root(trace._reached_root),
 73   _lineno(trace._lineno),
 74   _written(false) {
 75   copy_frames(&_frames, trace._nr_of_frames, trace._frames);
 76 }
 77 
 78 JfrStackTrace::~JfrStackTrace() {
 79   if (_frames_ownership) {
 80     FREE_C_HEAP_ARRAY(JfrStackFrame, _frames);
 81   }
 82 }
 83 
 84 template <typename Writer>
 85 static void write_stacktrace(Writer& w, traceid id, bool reached_root, u4 nr_of_frames, const JfrStackFrame* frames) {
 86   w.write((u8)id);
 87   w.write((u1)!reached_root);
 88   w.write(nr_of_frames);
 89   for (u4 i = 0; i < nr_of_frames; ++i) {
 90     frames[i].write(w);
 91   }
 92 }
 93 
 94 void JfrStackTrace::write(JfrChunkWriter& sw) const {
 95   assert(!_written, "invariant");
 96   write_stacktrace(sw, _id, _reached_root, _nr_of_frames, _frames);
 97   _written = true;
 98 }
 99 
100 void JfrStackTrace::write(JfrCheckpointWriter& cpw) const {
101   write_stacktrace(cpw, _id, _reached_root, _nr_of_frames, _frames);
102 }
103 
104 bool JfrStackFrame::equals(const JfrStackFrame& rhs) const {
105   return _methodid == rhs._methodid && _bci == rhs._bci && _type == rhs._type;
106 }
107 
108 bool JfrStackTrace::equals(const JfrStackTrace& rhs) const {
109   if (_reached_root != rhs._reached_root || _nr_of_frames != rhs._nr_of_frames || _hash != rhs._hash) {
110     return false;
111   }
112   for (u4 i = 0; i < _nr_of_frames; ++i) {
113     if (!_frames[i].equals(rhs._frames[i])) {
114       return false;
115     }
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 }