1 /* 2 * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved. 3 * 4 * This file is part of the Lock Contention Tracing Subsystem for the HotSpot 5 * Virtual Machine, which is developed at Christian Doppler Laboratory on 6 * Monitoring and Evolution of Very-Large-Scale Software Systems. Please 7 * contact us at <http://mevss.jku.at/> if you need additional information 8 * or have any questions. 9 * 10 * This code is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License version 2 only, as 12 * published by the Free Software Foundation. 13 * 14 * This code is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 * version 2 for more details (a copy is included in the LICENSE file that 18 * accompanied this code). 19 * 20 * You should have received a copy of the GNU General Public License version 21 * 2 along with this work. If not, see <http://www.gnu.org/licenses/>. 22 * 23 */ 24 25 #ifndef SHARE_VM_EVTRACE_TRACESTACK_HPP 26 #define SHARE_VM_EVTRACE_TRACESTACK_HPP 27 28 #include "evtrace/traceTypes.hpp" 29 30 #include "memory/allocation.hpp" 31 #include "runtime/timer.hpp" 32 33 class Method; 34 class CachedTraceStack; 35 class TraceMetadata; 36 37 #define TRACE_STACK_MAX_FRAMES 128 38 39 class CompositeTraceStack; 40 41 struct TraceStackFrame { 42 bool is_compiled; 43 union { 44 struct { 45 nmethod *nm; 46 address pc; 47 } compiled; 48 struct { 49 Method *method; 50 int bci; 51 } interpreted; 52 }; 53 54 intptr_t hash() const; 55 bool equals(const TraceStackFrame& other) const; 56 }; 57 58 class TraceStackBuilder: StackObj { 59 private: 60 TraceStackFrame _frames[TRACE_STACK_MAX_FRAMES]; 61 size_t _count; 62 bool _truncated; 63 intptr_t _hash; 64 65 void add(const TraceStackFrame &f); 66 67 public: 68 TraceStackBuilder(); 69 70 void add_frame(const frame *fr); 71 void set_truncated() { _truncated = true; } 72 73 const TraceStackFrame *frame_at(size_t index) const; 74 75 size_t count() const { return _count; } 76 bool is_full() const { return (_count == EventTracingStackDepthLimit); } 77 bool is_truncated() const { return _truncated; } 78 intptr_t hash() const { return _hash; } 79 80 bool range_equals(size_t offset, const CachedTraceStack *cts, size_t cts_offset, size_t count) const; 81 }; 82 83 class CachedTraceStack: CHeapObj<mtEventTracing> { 84 public: 85 static CachedTraceStack *create(TraceTypes::stack_id id, const CompositeTraceStack &ts); 86 87 const TraceStackFrame *frame_at(size_t index) const; 88 89 TraceTypes::stack_id id() const { return _id; } 90 size_t count() const { return _count; } 91 bool is_truncated() const { return _truncated; } 92 intptr_t hash() const { return _hash; } 93 94 bool has_interpreted_method_from_classloader(const ClassLoaderData *loader) const; 95 bool has_nmethod(const nmethod *nm) const; 96 bool range_equals(size_t offset, const CachedTraceStack *other, size_t other_offset, size_t count) const; 97 98 bool is_valid() const { return _valid; } 99 void invalidate(); 100 101 CachedTraceStack *cache_next(); 102 void set_cache_next(CachedTraceStack *next); 103 104 void operator delete(void* p); 105 106 private: 107 void* operator new(size_t size, size_t nframes) throw (); 108 CachedTraceStack(TraceTypes::stack_id id, const CompositeTraceStack &ts); 109 110 CachedTraceStack * volatile _cache_next; 111 112 const TraceTypes::stack_id _id; 113 const intptr_t _hash; 114 const size_t _count; 115 const bool _truncated; 116 bool _valid; 117 TraceStackFrame _frames[0]; 118 }; 119 120 class CompositeTraceStack: StackObj { 121 private: 122 const TraceStackBuilder &_top; 123 const CachedTraceStack *_bottom; 124 size_t _bottom_offset; 125 intptr_t _hash; 126 size_t _count; 127 bool _truncated; 128 129 public: 130 CompositeTraceStack(TraceStackBuilder &top); 131 132 void set_bottom(const CachedTraceStack *cts, size_t offset); 133 134 bool equals(const CachedTraceStack *cts) const; 135 bool equals(const CompositeTraceStack &other) const; 136 137 const TraceStackFrame *frame_at(size_t index) const; 138 139 intptr_t hash() const { return _hash; } 140 size_t count() const { return _count; } 141 bool is_truncated() const { return _truncated; } 142 }; 143 144 class TraceStackVframeIterator: StackObj { 145 private: 146 const CompositeTraceStack &_ts; 147 int _index; 148 int _decode_offset; 149 Method *_method; 150 int _bci; 151 152 void fill_from_compiled_frame(); 153 154 public: 155 TraceStackVframeIterator(const CompositeTraceStack &ts); 156 157 bool has_next(); 158 void next(); 159 void reset(); 160 161 Method *method() { return _method; } 162 int bci() { return _bci; } 163 }; 164 165 class TraceStackCache: public CHeapObj<mtEventTracing> { 166 private: 167 TraceMetadata *_metadata; 168 169 CachedTraceStack **_table; 170 volatile intptr_t _count; 171 size_t _size; 172 volatile bool _has_invalid_stacks; 173 174 // statistics 175 elapsedTimer _purge_timer; 176 elapsedTimer _maintenance_timer; 177 volatile intptr_t _lookup_counter; 178 volatile intptr_t _lookup_miss_counter; 179 volatile intptr_t _lookup_collision_counter; 180 volatile intptr_t _probe_counter; 181 volatile intptr_t _probe_collision_counter; 182 183 void add_for_rehash(CachedTraceStack *cts); 184 185 class CachedTraceStackPredicate; 186 class UnloadingClassPredicate; 187 class UnloadingNmethodPredicate; 188 class AnyPredicate; 189 void purge_matches(CachedTraceStackPredicate *pr); 190 191 void update_counters_after_lookup(bool present, jlong probes, jlong collisions); 192 193 public: 194 TraceStackCache(TraceMetadata *tm); 195 virtual ~TraceStackCache(); 196 197 const CachedTraceStack * get_or_try_add(const CompositeTraceStack &ts, bool &known, TraceTypes::stack_id preallocated_id = 0); 198 199 void purge_unloading_classes(const ClassLoaderData *loader); 200 void purge_unloading_nmethod(const nmethod *nm); 201 void purge_all(); 202 203 bool has_invalid_stacks() const { return _has_invalid_stacks; } 204 void do_maintenance(); 205 206 intptr_t lookups() { return _lookup_counter; } 207 intptr_t lookup_misses() { return _lookup_miss_counter; } 208 intptr_t lookup_collisions() { return _lookup_collision_counter; } 209 intptr_t probes() { return _probe_counter; } 210 intptr_t probe_collisions() { return _probe_collision_counter; } 211 jlong purge_millis() { return _purge_timer.milliseconds(); } 212 jlong maintenance_millis() { return _maintenance_timer.milliseconds(); } 213 void reset_stats(); 214 }; 215 216 #include "evtrace/traceStack.inline.hpp" 217 218 #endif /* SHARE_VM_EVTRACE_TRACESTACK_HPP */