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 #ifndef SHARE_VM_JFR_RECORDER_STACKTRACE_JFRSTACKTRACEREPOSITORY_HPP
  26 #define SHARE_VM_JFR_RECORDER_STACKTRACE_JFRSTACKTRACEREPOSITORY_HPP
  27 
  28 #include "jfr/utilities/jfrAllocation.hpp"
  29 #include "jfr/utilities/jfrTypes.hpp"
  30 
  31 class frame;
  32 class JavaThread;
  33 class JfrCheckpointWriter;
  34 class JfrChunkWriter;
  35 class Method;
  36 
  37 class JfrStackFrame {
  38  private:
  39   mutable const Method* _method;
  40   traceid _methodid;
  41   mutable int _line;
  42   int _bci;
  43   u1 _type;
  44 
  45  public:
  46   enum {
  47     FRAME_INTERPRETER = 0,
  48     FRAME_JIT,
  49     FRAME_INLINE,
  50     FRAME_NATIVE,
  51     NUM_FRAME_TYPES
  52   };
  53 
  54   JfrStackFrame(const traceid& id, int bci, int type, const Method* method) :
  55     _method(method), _methodid(id), _line(0), _bci(bci), _type(type) {}
  56   JfrStackFrame(const traceid& id, int bci, int type, int lineno) :
  57     _method(NULL), _methodid(id), _line(lineno), _bci(bci), _type(type) {}
  58   bool equals(const JfrStackFrame& rhs) const;
  59   void write(JfrChunkWriter& cw) const;
  60   void write(JfrCheckpointWriter& cpw) const;
  61   void resolve_lineno() const;
  62 };
  63 
  64 class JfrStackTrace : public StackObj {
  65   friend class JfrStackTraceRepository;
  66  private:
  67   JfrStackFrame* _frames;
  68   traceid _id;
  69   u4 _nr_of_frames;
  70   unsigned int _hash;
  71   const u4 _max_frames;
  72   bool _reached_root;
  73   mutable bool _lineno;
  74 
  75  public:
  76   JfrStackTrace(JfrStackFrame* frames, u4 max_frames) : _frames(frames),
  77                                                         _id(0),
  78                                                         _nr_of_frames(0),
  79                                                         _hash(0),
  80                                                         _reached_root(false),
  81                                                         _max_frames(max_frames),
  82                                                         _lineno(false) {}
  83   bool record_thread(JavaThread& thread, frame& frame);
  84   bool record_safe(JavaThread* thread, int skip, bool leakp = false);
  85   void resolve_linenos() const;
  86   void set_nr_of_frames(u4 nr_of_frames) { _nr_of_frames = nr_of_frames; }
  87   void set_hash(unsigned int hash) { _hash = hash; }
  88   unsigned int hash() const { return _hash; }
  89   void set_frame(u4 frame_pos, JfrStackFrame& frame);
  90   void set_reached_root(bool reached_root) { _reached_root = reached_root; }
  91   bool full_stacktrace() const { return _reached_root; }
  92   bool have_lineno() const { return _lineno; }
  93 };
  94 
  95 class JfrStackTraceRepository : public JfrCHeapObj {
  96   friend class JfrRecorder;
  97   friend class JfrRecorderService;
  98   friend class ObjectSampler;
  99   friend class RecordStackTrace;
 100   friend class StackTraceWrite;
 101   friend class WriteObjectSampleStacktrace;
 102 
 103   class StackTrace : public JfrCHeapObj {
 104     friend class JfrStackTrace;
 105     friend class JfrStackTraceRepository;
 106    private:
 107     StackTrace* _next;
 108     JfrStackFrame* _frames;
 109     const traceid _id;
 110     u4 _nr_of_frames;
 111     unsigned int _hash;
 112     bool _reached_root;
 113     mutable bool _written;
 114 
 115     unsigned int hash() const { return _hash; }
 116     bool should_write() const { return !_written; }
 117 
 118    public:
 119     StackTrace(traceid id, const JfrStackTrace& trace, StackTrace* next);
 120     ~StackTrace();
 121     traceid id() const { return _id; }
 122     StackTrace* next() const { return _next; }
 123     void write(JfrChunkWriter& cw) const;
 124     void write(JfrCheckpointWriter& cpw) const;
 125     bool equals(const JfrStackTrace& rhs) const;
 126   };
 127 
 128  private:
 129   static const u4 TABLE_SIZE = 2053;
 130   StackTrace* _table[TABLE_SIZE];
 131   u4 _last_entries;
 132   u4 _entries;
 133 
 134   traceid add_trace(const JfrStackTrace& stacktrace);
 135   static traceid add_for_leak_profiler(const JfrStackTrace* stacktrace, JavaThread* thread);
 136   traceid record_for(JavaThread* thread, int skip, JfrStackFrame* frames, u4 max_frames);
 137 
 138   size_t write_impl(JfrChunkWriter& cw, bool clear);
 139   static const StackTrace* lookup_for_leak_profiler(unsigned int hash, traceid id);
 140   static void record_for_leak_profiler(JavaThread* thread, JfrStackTrace* stacktrace, int skip = 0);
 141   static void clear_leak_profiler();
 142   static void write_metadata(JfrCheckpointWriter& cpw);
 143 
 144   static bool fill_stacktrace_for(JavaThread* thread, JfrStackTrace* stacktrace, int skip);
 145 
 146   JfrStackTraceRepository();
 147   static JfrStackTraceRepository* create();
 148   bool initialize();
 149   static void destroy();
 150 
 151   static JfrStackTraceRepository& instance();
 152 
 153  public:
 154   static JfrStackTraceRepository& leak_profiler_instance();
 155   static traceid add(JfrStackTraceRepository& repo, const JfrStackTrace& stacktrace);
 156   static traceid add(const JfrStackTrace& stacktrace);
 157   static traceid record(Thread* thread, int skip = 0);
 158   static traceid write_for_leak_profiler(JfrCheckpointWriter& cpw, traceid id, unsigned int hash);
 159   size_t write(JfrChunkWriter& cw, bool clear);
 160   static size_t clear();
 161   static size_t clear(JfrStackTraceRepository& repo);
 162 };
 163 
 164 #endif // SHARE_VM_JFR_RECORDER_STACKTRACE_JFRSTACKTRACEREPOSITORY_HPP