1 /*
   2  * Copyright (c) 2011, 2018, 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/metadata/jfrSerializer.hpp"
  27 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
  28 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
  29 #include "jfr/recorder/service/jfrOptionSet.hpp"
  30 #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
  31 #include "jfr/utilities/jfrTypes.hpp"
  32 #include "memory/allocation.inline.hpp"
  33 #include "runtime/mutexLocker.hpp"
  34 #include "runtime/os.hpp"
  35 #include "runtime/safepoint.hpp"
  36 #include "runtime/task.hpp"
  37 #include "runtime/vframe.hpp"
  38 
  39 class vframeStreamSamples : public vframeStreamCommon {
  40  public:
  41   // constructor that starts with sender of frame fr (top_frame)
  42   vframeStreamSamples(JavaThread *jt, frame fr, bool stop_at_java_call_stub);
  43   void samples_next();
  44   void stop() {}
  45 };
  46 
  47 vframeStreamSamples::vframeStreamSamples(JavaThread *jt, frame fr, bool stop_at_java_call_stub) : vframeStreamCommon(jt) {
  48   _stop_at_java_call_stub = stop_at_java_call_stub;
  49   _frame = fr;
  50 
  51   // We must always have a valid frame to start filling
  52   bool filled_in = fill_from_frame();
  53   assert(filled_in, "invariant");
  54 }
  55 
  56 // Solaris SPARC Compiler1 needs an additional check on the grandparent
  57 // of the top_frame when the parent of the top_frame is interpreted and
  58 // the grandparent is compiled. However, in this method we do not know
  59 // the relationship of the current _frame relative to the top_frame so
  60 // we implement a more broad sanity check. When the previous callee is
  61 // interpreted and the current sender is compiled, we verify that the
  62 // current sender is also walkable. If it is not walkable, then we mark
  63 // the current vframeStream as at the end.
  64 void vframeStreamSamples::samples_next() {
  65   // handle frames with inlining
  66   if (_mode == compiled_mode &&
  67       vframeStreamCommon::fill_in_compiled_inlined_sender()) {
  68     return;
  69   }
  70 
  71   // handle general case
  72   int loop_count = 0;
  73   int loop_max = MaxJavaStackTraceDepth * 2;
  74   do {
  75     loop_count++;
  76     // By the time we get here we should never see unsafe but better safe then segv'd
  77     if (loop_count > loop_max || !_frame.safe_for_sender(_thread)) {
  78       _mode = at_end_mode;
  79       return;
  80     }
  81     _frame = _frame.sender(&_reg_map);
  82   } while (!fill_from_frame());
  83 }
  84 
  85 static JfrStackTraceRepository* _instance = NULL;
  86 
  87 JfrStackTraceRepository& JfrStackTraceRepository::instance() {
  88   return *_instance;
  89 }
  90 
  91 JfrStackTraceRepository* JfrStackTraceRepository::create() {
  92   assert(_instance == NULL, "invariant");
  93   _instance = new JfrStackTraceRepository();
  94   return _instance;
  95 }
  96 
  97 void JfrStackTraceRepository::destroy() {
  98   assert(_instance != NULL, "invarinat");
  99   delete _instance;
 100   _instance = NULL;
 101 }
 102 
 103 JfrStackTraceRepository::JfrStackTraceRepository() : _next_id(0), _entries(0) {
 104   memset(_table, 0, sizeof(_table));
 105 }
 106 class JfrFrameType : public JfrSerializer {
 107  public:
 108   void serialize(JfrCheckpointWriter& writer) {
 109     writer.write_count(JfrStackFrame::NUM_FRAME_TYPES);
 110     writer.write_key(JfrStackFrame::FRAME_INTERPRETER);
 111     writer.write("Interpreted");
 112     writer.write_key(JfrStackFrame::FRAME_JIT);
 113     writer.write("JIT compiled");
 114     writer.write_key(JfrStackFrame::FRAME_INLINE);
 115     writer.write("Inlined");
 116     writer.write_key(JfrStackFrame::FRAME_NATIVE);
 117     writer.write("Native");
 118   }
 119 };
 120 
 121 bool JfrStackTraceRepository::initialize() {
 122   return JfrSerializer::register_serializer(TYPE_FRAMETYPE, false, true, new JfrFrameType());
 123 }
 124 
 125 size_t JfrStackTraceRepository::clear() {
 126   MutexLockerEx lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
 127   if (_entries == 0) {
 128     return 0;
 129   }
 130   for (u4 i = 0; i < TABLE_SIZE; ++i) {
 131     JfrStackTraceRepository::StackTrace* stacktrace = _table[i];
 132     while (stacktrace != NULL) {
 133       JfrStackTraceRepository::StackTrace* next = stacktrace->next();
 134       delete stacktrace;
 135       stacktrace = next;
 136     }
 137   }
 138   memset(_table, 0, sizeof(_table));
 139   const size_t processed = _entries;
 140   _entries = 0;
 141   return processed;
 142 }
 143 
 144 traceid JfrStackTraceRepository::add_trace(const JfrStackTrace& stacktrace) {
 145   MutexLockerEx lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
 146   const size_t index = stacktrace._hash % TABLE_SIZE;
 147   const StackTrace* table_entry = _table[index];
 148 
 149   while (table_entry != NULL) {
 150     if (table_entry->equals(stacktrace)) {
 151       return table_entry->id();
 152     }
 153     table_entry = table_entry->next();
 154   }
 155 
 156   if (!stacktrace.have_lineno()) {
 157     return 0;
 158   }
 159 
 160   traceid id = ++_next_id;
 161   _table[index] = new StackTrace(id, stacktrace, _table[index]);
 162   ++_entries;
 163   return id;
 164 }
 165 
 166 traceid JfrStackTraceRepository::add(const JfrStackTrace& stacktrace) {
 167   traceid tid = instance().add_trace(stacktrace);
 168   if (tid == 0) {
 169     stacktrace.resolve_linenos();
 170     tid = instance().add_trace(stacktrace);
 171   }
 172   assert(tid != 0, "invariant");
 173   return tid;
 174 }
 175 
 176 traceid JfrStackTraceRepository::record(Thread* thread, int skip /* 0 */) {
 177   assert(thread == Thread::current(), "invariant");
 178   JfrThreadLocal* const tl = thread->jfr_thread_local();
 179   assert(tl != NULL, "invariant");
 180   if (tl->has_cached_stack_trace()) {
 181     return tl->cached_stack_trace_id();
 182   }
 183   if (!thread->is_Java_thread() || thread->is_hidden_from_external_view()) {
 184     return 0;
 185   }
 186   JfrStackFrame* frames = tl->stackframes();
 187   if (frames == NULL) {
 188     // pending oom
 189     return 0;
 190   }
 191   assert(frames != NULL, "invariant");
 192   assert(tl->stackframes() == frames, "invariant");
 193   return instance().record_for((JavaThread*)thread, skip,frames, tl->stackdepth());
 194 }
 195 
 196 traceid JfrStackTraceRepository::record_for(JavaThread* thread, int skip, JfrStackFrame *frames, u4 max_frames) {
 197   JfrStackTrace stacktrace(frames, max_frames);
 198   return stacktrace.record_safe(thread, skip) ? add(stacktrace) : 0;
 199 }
 200 
 201 traceid JfrStackTraceRepository::add(const JfrStackTrace* stacktrace, JavaThread* thread) {
 202   assert(stacktrace != NULL, "invariant");
 203   assert(thread != NULL, "invariant");
 204   assert(stacktrace->hash() != 0, "invariant");
 205   return add(*stacktrace);
 206 }
 207 
 208 bool JfrStackTraceRepository::fill_stacktrace_for(JavaThread* thread, JfrStackTrace* stacktrace, int skip) {
 209   assert(thread == Thread::current(), "invariant");
 210   assert(stacktrace != NULL, "invariant");
 211   JfrThreadLocal* const tl = thread->jfr_thread_local();
 212   assert(tl != NULL, "invariant");
 213   const unsigned int cached_stacktrace_hash = tl->cached_stack_trace_hash();
 214   if (cached_stacktrace_hash != 0) {
 215     stacktrace->set_hash(cached_stacktrace_hash);
 216     return true;
 217   }
 218   return stacktrace->record_safe(thread, skip, true);
 219 }
 220 
 221 size_t JfrStackTraceRepository::write_impl(JfrChunkWriter& sw, bool clear) {
 222   MutexLockerEx lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
 223   assert(_entries > 0, "invariant");
 224   int count = 0;
 225   for (u4 i = 0; i < TABLE_SIZE; ++i) {
 226     JfrStackTraceRepository::StackTrace* stacktrace = _table[i];
 227     while (stacktrace != NULL) {
 228       JfrStackTraceRepository::StackTrace* next = stacktrace->next();
 229       if (stacktrace->should_write()) {
 230         stacktrace->write(sw);
 231         ++count;
 232       }
 233       if (clear) {
 234         delete stacktrace;
 235       }
 236       stacktrace = next;
 237     }
 238   }
 239   if (clear) {
 240     memset(_table, 0, sizeof(_table));
 241     _entries = 0;
 242   }
 243   return count;
 244 }
 245 
 246 size_t JfrStackTraceRepository::write(JfrChunkWriter& sw, bool clear) {
 247   return _entries > 0 ? write_impl(sw, clear) : 0;
 248 }
 249 
 250 traceid JfrStackTraceRepository::write(JfrCheckpointWriter& writer, traceid id, unsigned int hash) {
 251   assert(JfrStacktrace_lock->owned_by_self(), "invariant");
 252   const StackTrace* const trace = resolve_entry(hash, id);
 253   assert(trace != NULL, "invariant");
 254   assert(trace->hash() == hash, "invariant");
 255   assert(trace->id() == id, "invariant");
 256   trace->write(writer);
 257   return id;
 258 }
 259 
 260 JfrStackTraceRepository::StackTrace::StackTrace(traceid id, const JfrStackTrace& trace, JfrStackTraceRepository::StackTrace* next) :
 261   _next(next),
 262   _frames(NULL),
 263   _id(id),
 264   _nr_of_frames(trace._nr_of_frames),
 265   _hash(trace._hash),
 266   _reached_root(trace._reached_root),
 267   _written(false) {
 268   if (_nr_of_frames > 0) {
 269     _frames = NEW_C_HEAP_ARRAY(JfrStackFrame, _nr_of_frames, mtTracing);
 270     memcpy(_frames, trace._frames, _nr_of_frames * sizeof(JfrStackFrame));
 271   }
 272 }
 273 
 274 JfrStackTraceRepository::StackTrace::~StackTrace() {
 275   if (_frames != NULL) {
 276     FREE_C_HEAP_ARRAY(JfrStackFrame, _frames, mtTracing);
 277   }
 278 }
 279 
 280 bool JfrStackTraceRepository::StackTrace::equals(const JfrStackTrace& rhs) const {
 281   if (_reached_root != rhs._reached_root || _nr_of_frames != rhs._nr_of_frames || _hash != rhs._hash) {
 282     return false;
 283   }
 284   for (u4 i = 0; i < _nr_of_frames; ++i) {
 285     if (!_frames[i].equals(rhs._frames[i])) {
 286       return false;
 287     }
 288   }
 289   return true;
 290 }
 291 
 292 template <typename Writer>
 293 static void write_stacktrace(Writer& w, traceid id, bool reached_root, u4 nr_of_frames, const JfrStackFrame* frames) {
 294   w.write((u8)id);
 295   w.write((u1)!reached_root);
 296   w.write(nr_of_frames);
 297   for (u4 i = 0; i < nr_of_frames; ++i) {
 298     frames[i].write(w);
 299   }
 300 }
 301 
 302 void JfrStackTraceRepository::StackTrace::write(JfrChunkWriter& sw) const {
 303   assert(!_written, "invariant");
 304   write_stacktrace(sw, _id, _reached_root, _nr_of_frames, _frames);
 305   _written = true;
 306 }
 307 
 308 void JfrStackTraceRepository::StackTrace::write(JfrCheckpointWriter& cpw) const {
 309   write_stacktrace(cpw, _id, _reached_root, _nr_of_frames, _frames);
 310 }
 311 
 312 // JfrStackFrame
 313 
 314 bool JfrStackFrame::equals(const JfrStackFrame& rhs) const {
 315   return _methodid == rhs._methodid && _bci == rhs._bci && _type == rhs._type;
 316 }
 317 
 318 template <typename Writer>
 319 static void write_frame(Writer& w, traceid methodid, int line, int bci, u1 type) {
 320   w.write((u8)methodid);
 321   w.write((u4)line);
 322   w.write((u4)bci);
 323   w.write((u8)type);
 324 }
 325 
 326 void JfrStackFrame::write(JfrChunkWriter& cw) const {
 327   write_frame(cw, _methodid, _line, _bci, _type);
 328 }
 329 
 330 void JfrStackFrame::write(JfrCheckpointWriter& cpw) const {
 331   write_frame(cpw, _methodid, _line, _bci, _type);
 332 }
 333 
 334 // invariant is that the entry to be resolved actually exists in the table
 335 const JfrStackTraceRepository::StackTrace* JfrStackTraceRepository::resolve_entry(unsigned int hash, traceid id) const {
 336   const size_t index = (hash % TABLE_SIZE);
 337   const StackTrace* trace = _table[index];
 338   while (trace != NULL && trace->id() != id) {
 339     trace = trace->next();
 340   }
 341   assert(trace != NULL, "invariant");
 342   assert(trace->hash() == hash, "invariant");
 343   assert(trace->id() == id, "invariant");
 344   return trace;
 345 }
 346 
 347 void JfrStackFrame::resolve_lineno() const {
 348   assert(_method, "no method pointer");
 349   assert(_line == 0, "already have linenumber");
 350   _line = _method->line_number_from_bci(_bci);
 351   _method = NULL;
 352 }
 353 
 354 void JfrStackTrace::set_frame(u4 frame_pos, JfrStackFrame& frame) {
 355   assert(frame_pos < _max_frames, "illegal frame_pos");
 356   _frames[frame_pos] = frame;
 357 }
 358 
 359 void JfrStackTrace::resolve_linenos() const {
 360   for(unsigned int i = 0; i < _nr_of_frames; i++) {
 361     _frames[i].resolve_lineno();
 362   }
 363   _lineno = true;
 364 }
 365 
 366 bool JfrStackTrace::record_safe(JavaThread* thread, int skip, bool leakp /* false */) {
 367   assert(SafepointSynchronize::safepoint_safe(thread, thread->thread_state())
 368          || thread == Thread::current(), "Thread stack needs to be walkable");
 369   vframeStream vfs(thread);
 370   u4 count = 0;
 371   _reached_root = true;
 372   for(int i = 0; i < skip; i++) {
 373     if (vfs.at_end()) {
 374       break;
 375     }
 376     vfs.next();
 377   }
 378 
 379   while (!vfs.at_end()) {
 380     if (count >= _max_frames) {
 381       _reached_root = false;
 382       break;
 383     }
 384     const Method* method = vfs.method();
 385     const traceid mid = JfrTraceId::use(method, leakp);
 386     int type = vfs.is_interpreted_frame() ? JfrStackFrame::FRAME_INTERPRETER : JfrStackFrame::FRAME_JIT;
 387     int bci = 0;
 388     if (method->is_native()) {
 389       type = JfrStackFrame::FRAME_NATIVE;
 390     } else {
 391       bci = vfs.bci();
 392     }
 393     // Can we determine if it's inlined?
 394     _hash = (_hash << 2) + (unsigned int)(((size_t)mid >> 2) + (bci << 4) + type);
 395     _frames[count] = JfrStackFrame(mid, bci, type, method);
 396     vfs.next();
 397     count++;
 398   }
 399 
 400   _nr_of_frames = count;
 401   return true;
 402 }
 403 
 404 bool JfrStackTrace::record_thread(JavaThread& thread, frame& frame) {
 405   vframeStreamSamples st(&thread, frame, false);
 406   u4 count = 0;
 407   _reached_root = true;
 408 
 409   while (!st.at_end()) {
 410     if (count >= _max_frames) {
 411       _reached_root = false;
 412       break;
 413     }
 414     const Method* method = st.method();
 415     if (!method->is_valid_method()) {
 416       // we throw away everything we've gathered in this sample since
 417       // none of it is safe
 418       return false;
 419     }
 420     const traceid mid = JfrTraceId::use(method);
 421     int type = st.is_interpreted_frame() ? JfrStackFrame::FRAME_INTERPRETER : JfrStackFrame::FRAME_JIT;
 422     int bci = 0;
 423     if (method->is_native()) {
 424       type = JfrStackFrame::FRAME_NATIVE;
 425     } else {
 426       bci = st.bci();
 427     }
 428     const int lineno = method->line_number_from_bci(bci);
 429     // Can we determine if it's inlined?
 430     _hash = (_hash << 2) + (unsigned int)(((size_t)mid >> 2) + (bci << 4) + type);
 431     _frames[count] = JfrStackFrame(mid, bci, type, lineno);
 432     st.samples_next();
 433     count++;
 434   }
 435 
 436   _lineno = true;
 437   _nr_of_frames = count;
 438   return true;
 439 }
 440 
 441 void JfrStackTraceRepository::write_metadata(JfrCheckpointWriter& writer) {
 442   JfrFrameType fct;
 443   writer.write_type(TYPE_FRAMETYPE);
 444   fct.serialize(writer);
 445 }