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 const Method* _method; 40 traceid _methodid; 41 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(); 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 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(); 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 void set_frame(u4 frame_pos, JfrStackFrame& frame); 89 void set_reached_root(bool reached_root) { _reached_root = reached_root; } 90 bool full_stacktrace() const { return _reached_root; } 91 bool have_lineno() const { return _lineno; } 92 }; 93 94 class JfrStackTraceRepository : public JfrCHeapObj { 95 friend class JfrRecorder; 96 friend class JfrRecorderService; 97 friend class ObjectSampler; 98 friend class WriteObjectSampleStacktrace; 99 100 class StackTrace : public JfrCHeapObj { 101 friend class JfrStackTrace; 102 friend class JfrStackTraceRepository; 103 private: 104 StackTrace* _next; 105 JfrStackFrame* _frames; 106 const traceid _id; 107 u4 _nr_of_frames; 108 unsigned int _hash; 109 bool _reached_root; 110 mutable bool _written; 111 112 unsigned int hash() const { return _hash; } 113 bool should_write() const { return !_written; } 114 115 public: 116 StackTrace(traceid id, const JfrStackTrace& trace, StackTrace* next); 117 ~StackTrace(); 118 traceid id() const { return _id; } 119 StackTrace* next() const { return _next; } 120 void write(JfrChunkWriter& cw) const; 121 void write(JfrCheckpointWriter& cpw) const; 122 bool equals(const JfrStackTrace& rhs) const; 123 }; 124 125 private: 126 static const u4 TABLE_SIZE = 2053; 127 StackTrace* _table[TABLE_SIZE]; 128 traceid _next_id; 129 u4 _entries; 130 131 size_t write_impl(JfrChunkWriter& cw, bool clear); 132 traceid record_for(JavaThread* thread, int skip, JfrStackFrame* frames, u4 max_frames); 133 traceid record_for(JavaThread* thread, int skip, JfrStackFrame* frames, u4 max_frames, unsigned int* hash); 134 traceid add_trace(const JfrStackTrace& stacktrace); 135 const StackTrace* resolve_entry(unsigned int hash, traceid id) const; 136 137 static void write_metadata(JfrCheckpointWriter& cpw); 138 139 JfrStackTraceRepository(); 140 static JfrStackTraceRepository& instance(); 141 public: 142 static JfrStackTraceRepository* create(); 143 bool initialize(); 144 static void destroy(); 145 static traceid add(const JfrStackTrace& stacktrace); 146 static traceid record(Thread* thread, int skip = 0); 147 static traceid record(Thread* thread, int skip, unsigned int* hash); 148 traceid write(JfrCheckpointWriter& cpw, traceid id, unsigned int hash); 149 size_t write(JfrChunkWriter& cw, bool clear); 150 size_t clear(); 151 }; 152 153 #endif // SHARE_VM_JFR_RECORDER_STACKTRACE_JFRSTACKTRACEREPOSITORY_HPP