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