1 /*
  2  * Copyright (c) 2011, 2023, 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/recorder/storage/jfrBuffer.hpp"
 31 #include "jfr/support/jfrMethodLookup.hpp"
 32 #include "jfr/support/jfrThreadLocal.hpp"
 33 #include "memory/allocation.inline.hpp"
 34 #include "oops/instanceKlass.inline.hpp"
 35 #include "runtime/continuation.hpp"
 36 #include "runtime/continuationEntry.inline.hpp"
 37 #include "runtime/handles.inline.hpp"
 38 #include "runtime/vframe.inline.hpp"
 39 
 40 static void copy_frames(JfrStackFrame** lhs_frames, u4 length, const JfrStackFrame* rhs_frames) {
 41   assert(lhs_frames != nullptr, "invariant");
 42   assert(rhs_frames != nullptr, "invariant");
 43   if (length > 0) {
 44     *lhs_frames = NEW_C_HEAP_ARRAY(JfrStackFrame, length, mtTracing);
 45     memcpy(*lhs_frames, rhs_frames, length * sizeof(JfrStackFrame));
 46   }
 47 }
 48 
 49 JfrStackFrame::JfrStackFrame(const traceid& id, int bci, int type, const InstanceKlass* ik) :
 50   _klass(ik), _methodid(id), _line(0), _bci(bci), _type(type) {}
 51 
 52 JfrStackFrame::JfrStackFrame(const traceid& id, int bci, int type, int lineno, const InstanceKlass* ik) :
 53   _klass(ik), _methodid(id), _line(lineno), _bci(bci), _type(type) {}
 54 
 55 JfrStackTrace::JfrStackTrace(JfrStackFrame* frames, u4 max_frames) :
 56   _next(nullptr),
 57   _frames(frames),
 58   _id(0),
 59   _hash(0),
 60   _nr_of_frames(0),
 61   _max_frames(max_frames),
 62   _frames_ownership(false),
 63   _reached_root(false),
 64   _lineno(false),
 65   _written(false) {}
 66 
 67 JfrStackTrace::JfrStackTrace(traceid id, const JfrStackTrace& trace, const JfrStackTrace* next) :
 68   _next(next),
 69   _frames(nullptr),
 70   _id(id),
 71   _hash(trace._hash),
 72   _nr_of_frames(trace._nr_of_frames),
 73   _max_frames(trace._max_frames),
 74   _frames_ownership(true),
 75   _reached_root(trace._reached_root),
 76   _lineno(trace._lineno),
 77   _written(false) {
 78   copy_frames(&_frames, trace._nr_of_frames, trace._frames);
 79 }
 80 
 81 JfrStackTrace::~JfrStackTrace() {
 82   if (_frames_ownership) {
 83     FREE_C_HEAP_ARRAY(JfrStackFrame, _frames);
 84   }
 85 }
 86 
 87 template <typename Writer>
 88 static void write_stacktrace(Writer& w, traceid id, bool reached_root, u4 nr_of_frames, const JfrStackFrame* frames) {
 89   w.write((u8)id);
 90   w.write((u1)!reached_root);
 91   w.write(nr_of_frames);
 92   for (u4 i = 0; i < nr_of_frames; ++i) {
 93     frames[i].write(w);
 94   }
 95 }
 96 
 97 void JfrStackTrace::write(JfrChunkWriter& sw) const {
 98   assert(!_written, "invariant");
 99   write_stacktrace(sw, _id, _reached_root, _nr_of_frames, _frames);
100   _written = true;
101 }
102 
103 void JfrStackTrace::write(JfrCheckpointWriter& cpw) const {
104   write_stacktrace(cpw, _id, _reached_root, _nr_of_frames, _frames);
105 }
106 
107 bool JfrStackFrame::equals(const JfrStackFrame& rhs) const {
108   return _methodid == rhs._methodid && _bci == rhs._bci && _type == rhs._type;
109 }
110 
111 bool JfrStackTrace::equals(const JfrStackTrace& rhs) const {
112   if (_reached_root != rhs._reached_root || _nr_of_frames != rhs._nr_of_frames || _hash != rhs._hash) {
113     return false;
114   }
115   for (u4 i = 0; i < _nr_of_frames; ++i) {
116     if (!_frames[i].equals(rhs._frames[i])) {
117       return false;
118     }
119   }
120   return true;
121 }
122 
123 template <typename Writer>
124 static void write_frame(Writer& w, traceid methodid, int line, int bci, u1 type) {
125   w.write((u8)methodid);
126   w.write((u4)line);
127   w.write((u4)bci);
128   w.write((u8)type);
129 }
130 
131 void JfrStackFrame::write(JfrChunkWriter& cw) const {
132   write_frame(cw, _methodid, _line, _bci, _type);
133 }
134 
135 void JfrStackFrame::write(JfrCheckpointWriter& cpw) const {
136   write_frame(cpw, _methodid, _line, _bci, _type);
137 }
138 
139 class JfrVframeStream : public vframeStreamCommon {
140  private:
141   bool _vthread;
142   const ContinuationEntry* _cont_entry;
143   bool _async_mode;
144   bool step_to_sender();
145   void next_frame();
146  public:
147   JfrVframeStream(JavaThread* jt, const frame& fr, bool stop_at_java_call_stub, bool async_mode);
148   void next_vframe();
149 };
150 
151 static RegisterMap::WalkContinuation walk_continuation(JavaThread* jt) {
152   // NOTE: WalkContinuation::skip, because of interactions with ZGC relocation
153   //       and load barriers. This code is run while generating stack traces for
154   //       the ZPage allocation event, even when ZGC is relocating  objects.
155   //       When ZGC is relocating, it is forbidden to run code that performs
156   //       load barriers. With WalkContinuation::include, we visit heap stack
157   //       chunks and could be using load barriers.
158   return (UseZGC && !StackWatermarkSet::processing_started(jt))
159       ? RegisterMap::WalkContinuation::skip
160       : RegisterMap::WalkContinuation::include;
161 }
162 
163 JfrVframeStream::JfrVframeStream(JavaThread* jt, const frame& fr, bool stop_at_java_call_stub, bool async_mode) :
164   vframeStreamCommon(RegisterMap(jt,
165                                  RegisterMap::UpdateMap::skip,
166                                  RegisterMap::ProcessFrames::skip,
167                                  walk_continuation(jt))),
168     _vthread(JfrThreadLocal::is_vthread(jt)),
169     _cont_entry(_vthread ? jt->last_continuation() : nullptr),
170     _async_mode(async_mode) {
171   assert(!_vthread || _cont_entry != nullptr, "invariant");
172   _reg_map.set_async(async_mode);
173   _frame = fr;
174   _stop_at_java_call_stub = stop_at_java_call_stub;
175   while (!fill_from_frame()) {
176     step_to_sender();
177   }
178 }
179 
180 inline bool JfrVframeStream::step_to_sender() {
181   if (_async_mode && !_frame.safe_for_sender(_thread)) {
182     _mode = at_end_mode;
183     return false;
184   }
185   _frame = _frame.sender(&_reg_map);
186   return true;
187 }
188 
189 inline void JfrVframeStream::next_frame() {
190   static constexpr const u4 loop_max = MAX_STACK_DEPTH * 2;
191   u4 loop_count = 0;
192   do {
193     if (_vthread && Continuation::is_continuation_enterSpecial(_frame)) {
194       if (_cont_entry->is_virtual_thread()) {
195         // An entry of a vthread continuation is a termination point.
196         _mode = at_end_mode;
197         break;
198       }
199       _cont_entry = _cont_entry->parent();
200     }
201     if (_async_mode) {
202       ++loop_count;
203       if (loop_count > loop_max) {
204         _mode = at_end_mode;
205         break;
206       }
207     }
208   } while (step_to_sender() && !fill_from_frame());
209 }
210 
211 // Solaris SPARC Compiler1 needs an additional check on the grandparent
212 // of the top_frame when the parent of the top_frame is interpreted and
213 // the grandparent is compiled. However, in this method we do not know
214 // the relationship of the current _frame relative to the top_frame so
215 // we implement a more broad sanity check. When the previous callee is
216 // interpreted and the current sender is compiled, we verify that the
217 // current sender is also walkable. If it is not walkable, then we mark
218 // the current vframeStream as at the end.
219 void JfrVframeStream::next_vframe() {
220   // handle frames with inlining
221   if (_mode == compiled_mode && fill_in_compiled_inlined_sender()) {
222     return;
223   }
224   next_frame();
225 }
226 
227 static const size_t min_valid_free_size_bytes = 16;
228 
229 static inline bool is_full(const JfrBuffer* enqueue_buffer) {
230   return enqueue_buffer->free_size() < min_valid_free_size_bytes;
231 }
232 
233 bool JfrStackTrace::record_async(JavaThread* jt, const frame& frame) {
234   assert(jt != nullptr, "invariant");
235   assert(!_lineno, "invariant");
236   Thread* current_thread = Thread::current();
237   assert(jt != current_thread, "invariant");
238   // Explicitly monitor the available space of the thread-local buffer used for enqueuing klasses as part of tagging methods.
239   // We do this because if space becomes sparse, we cannot rely on the implicit allocation of a new buffer as part of the
240   // regular tag mechanism. If the free list is empty, a malloc could result, and the problem with that is that the thread
241   // we have suspended could be the holder of the malloc lock. If there is no more available space, the attempt is aborted.
242   const JfrBuffer* const enqueue_buffer = JfrTraceIdLoadBarrier::get_sampler_enqueue_buffer(current_thread);
243   HandleMark hm(current_thread); // RegisterMap uses Handles to support continuations.
244   JfrVframeStream vfs(jt, frame, false, true);
245   u4 count = 0;
246   _reached_root = true;
247   _hash = 1;
248   while (!vfs.at_end()) {
249     if (count >= _max_frames) {
250       _reached_root = false;
251       break;
252     }
253     const Method* method = vfs.method();
254     if (!Method::is_valid_method(method) || is_full(enqueue_buffer)) {
255       // we throw away everything we've gathered in this sample since
256       // none of it is safe
257       return false;
258     }
259     const traceid mid = JfrTraceId::load(method);
260     int type = vfs.is_interpreted_frame() ? JfrStackFrame::FRAME_INTERPRETER : JfrStackFrame::FRAME_JIT;
261     int bci = 0;
262     if (method->is_native()) {
263       type = JfrStackFrame::FRAME_NATIVE;
264     } else {
265       bci = vfs.bci();
266     }
267 
268     intptr_t* frame_id = vfs.frame_id();
269     vfs.next_vframe();
270     if (type == JfrStackFrame::FRAME_JIT && !vfs.at_end() && frame_id == vfs.frame_id()) {
271       // This frame and the caller frame are both the same physical
272       // frame, so this frame is inlined into the caller.
273       type = JfrStackFrame::FRAME_INLINE;
274     }
275     _hash = (_hash * 31) + mid;
276     _hash = (_hash * 31) + bci;
277     _hash = (_hash * 31) + type;
278     _frames[count] = JfrStackFrame(mid, bci, type, method->line_number_from_bci(bci), method->method_holder());
279     count++;
280   }
281   _lineno = true;
282   _nr_of_frames = count;
283   return count > 0;
284 }
285 
286 bool JfrStackTrace::record(JavaThread* jt, const frame& frame, int skip) {
287   assert(jt != nullptr, "invariant");
288   assert(jt == Thread::current(), "invariant");
289   assert(!_lineno, "invariant");
290   // Must use ResetNoHandleMark here to bypass if any NoHandleMark exist on stack.
291   // This is because RegisterMap uses Handles to support continuations.
292   ResetNoHandleMark rnhm;
293   HandleMark hm(jt);
294   JfrVframeStream vfs(jt, frame, false, false);
295   u4 count = 0;
296   _reached_root = true;
297   for (int i = 0; i < skip; ++i) {
298     if (vfs.at_end()) {
299       break;
300     }
301     vfs.next_vframe();
302   }
303   _hash = 1;
304   while (!vfs.at_end()) {
305     if (count >= _max_frames) {
306       _reached_root = false;
307       break;
308     }
309     const Method* method = vfs.method();
310     const traceid mid = JfrTraceId::load(method);
311     int type = vfs.is_interpreted_frame() ? JfrStackFrame::FRAME_INTERPRETER : JfrStackFrame::FRAME_JIT;
312     int bci = 0;
313     if (method->is_native()) {
314       type = JfrStackFrame::FRAME_NATIVE;
315     } else {
316       bci = vfs.bci();
317     }
318 
319     intptr_t* frame_id = vfs.frame_id();
320     vfs.next_vframe();
321     if (type == JfrStackFrame::FRAME_JIT && !vfs.at_end() && frame_id == vfs.frame_id()) {
322       // This frame and the caller frame are both the same physical
323       // frame, so this frame is inlined into the caller.
324       type = JfrStackFrame::FRAME_INLINE;
325     }
326     _hash = (_hash * 31) + mid;
327     _hash = (_hash * 31) + bci;
328     _hash = (_hash * 31) + type;
329     _frames[count] = JfrStackFrame(mid, bci, type, method->method_holder());
330     count++;
331   }
332   _nr_of_frames = count;
333   return count > 0;
334 }
335 
336 bool JfrStackTrace::record(JavaThread* current_thread, int skip) {
337   assert(current_thread != nullptr, "invariant");
338   assert(current_thread == Thread::current(), "invariant");
339   if (!current_thread->has_last_Java_frame()) {
340     return false;
341   }
342   return record(current_thread, current_thread->last_frame(), skip);
343 }
344 
345 void JfrStackFrame::resolve_lineno() const {
346   assert(_klass, "no klass pointer");
347   assert(_line == 0, "already have linenumber");
348   const Method* const method = JfrMethodLookup::lookup(_klass, _methodid);
349   assert(method != nullptr, "invariant");
350   assert(method->method_holder() == _klass, "invariant");
351   _line = method->line_number_from_bci(_bci);
352 }
353 
354 void JfrStackTrace::resolve_linenos() const {
355   assert(!_lineno, "invariant");
356   for (unsigned int i = 0; i < _nr_of_frames; i++) {
357     _frames[i].resolve_lineno();
358   }
359   _lineno = true;
360 }