1 /*
  2  * Copyright (c) 2014, 2020, 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_JFR_LEAKPROFILER_SAMPLING_OBJECTSAMPLE_HPP
 26 #define SHARE_JFR_LEAKPROFILER_SAMPLING_OBJECTSAMPLE_HPP
 27 
 28 #include "jfr/utilities/jfrAllocation.hpp"
 29 #include "jfr/utilities/jfrBlob.hpp"
 30 #include "jfr/utilities/jfrTime.hpp"
 31 #include "jfr/utilities/jfrTypes.hpp"
 32 #include "memory/allocation.hpp"
 33 #include "oops/oop.hpp"
 34 #include "oops/weakHandle.hpp"
 35 #include "utilities/ticks.hpp"
 36 
 37 /*
 38  * Handle for diagnosing Java memory leaks.
 39  *
 40  * The class tracks the time the object was
 41  * allocated, the thread and the stack trace.
 42  */
 43 class ObjectSample : public JfrCHeapObj {
 44   friend class ObjectSampler;
 45   friend class SampleList;
 46  private:
 47   ObjectSample* _next;
 48   ObjectSample* _previous;
 49   JfrBlobHandle _stacktrace;
 50   JfrBlobHandle _thread;
 51   JfrBlobHandle _type_set;
 52   WeakHandle    _object;
 53   Ticks _allocation_time;
 54   traceid _stack_trace_id;
 55   traceid _thread_id;
 56   int _index;
 57   size_t _span;
 58   size_t _allocated;
 59   size_t _heap_used_at_last_gc;
 60   unsigned int _stack_trace_hash;
 61 
 62   void release_references() {
 63     _stacktrace.~JfrBlobHandle();
 64     _thread.~JfrBlobHandle();
 65     _type_set.~JfrBlobHandle();
 66   }
 67 
 68   void reset();
 69 
 70  public:
 71   ObjectSample() : _next(NULL),
 72                    _previous(NULL),
 73                    _stacktrace(),
 74                    _thread(),
 75                    _type_set(),
 76                    _allocation_time(),
 77                    _stack_trace_id(0),
 78                    _thread_id(0),
 79                    _index(0),
 80                    _span(0),
 81                    _allocated(0),
 82                    _heap_used_at_last_gc(0),
 83                    _stack_trace_hash(0) {}
 84 
 85   ObjectSample* next() const {
 86     return _next;
 87   }
 88 
 89   void set_next(ObjectSample* next) {
 90     _next = next;
 91   }
 92 
 93   ObjectSample* prev() const {
 94     return _previous;
 95   }
 96 
 97   void set_prev(ObjectSample* prev) {
 98     _previous = prev;
 99   }
100 
101   bool is_dead() const;
102 
103   const oop object() const;
104   void set_object(oop object);
105 
106   const oop* object_addr() const;
107 
108   void release();
109 
110   int index() const {
111     return _index;
112   }
113 
114   void set_index(int index) {
115     _index = index;
116   }
117 
118   size_t span() const {
119     return _span;
120   }
121 
122   void set_span(size_t span) {
123     _span = span;
124   }
125 
126   void add_span(size_t span) {
127     _span += span;
128   }
129 
130   size_t allocated() const {
131     return _allocated;
132   }
133 
134   void set_allocated(size_t size) {
135     _allocated = size;
136   }
137 
138   const Ticks& allocation_time() const {
139     return _allocation_time;
140   }
141 
142   const void set_allocation_time(const JfrTicks& time) {
143     _allocation_time = Ticks(time.value());
144   }
145 
146   void set_heap_used_at_last_gc(size_t heap_used) {
147     _heap_used_at_last_gc = heap_used;
148   }
149 
150   size_t heap_used_at_last_gc() const {
151     return _heap_used_at_last_gc;
152   }
153 
154   bool has_stack_trace_id() const {
155     return stack_trace_id() != 0;
156   }
157 
158   traceid stack_trace_id() const {
159     return _stack_trace_id;
160   }
161 
162   void set_stack_trace_id(traceid id) {
163     _stack_trace_id = id;
164   }
165 
166   unsigned int stack_trace_hash() const {
167     return _stack_trace_hash;
168   }
169 
170   void set_stack_trace_hash(unsigned int hash) {
171     _stack_trace_hash = hash;
172   }
173 
174   traceid thread_id() const {
175     return _thread_id;
176   }
177 
178   void set_thread_id(traceid id) {
179     _thread_id = id;
180   }
181 
182   bool is_alive_and_older_than(jlong time_stamp) const {
183     return !is_dead() && (JfrTime::is_ft_enabled() ?
184       _allocation_time.ft_value() : _allocation_time.value()) < time_stamp;
185   }
186 
187   const JfrBlobHandle& stacktrace() const {
188     return _stacktrace;
189   }
190 
191   bool has_stacktrace() const {
192     return _stacktrace.valid();
193   }
194 
195   // JfrBlobHandle assignment operator
196   // maintains proper reference counting
197   void set_stacktrace(const JfrBlobHandle& ref) {
198     if (_stacktrace != ref) {
199       _stacktrace = ref;
200     }
201   }
202 
203   const JfrBlobHandle& thread() const {
204     return _thread;
205   }
206 
207   bool has_thread() const {
208     return _thread.valid();
209   }
210 
211   void set_thread(const JfrBlobHandle& ref) {
212     if (_thread != ref) {
213       _thread = ref;
214     }
215   }
216 
217   const JfrBlobHandle& type_set() const {
218     return _type_set;
219   }
220 
221   bool has_type_set() const {
222     return _type_set.valid();
223   }
224 
225   void set_type_set(const JfrBlobHandle& ref) {
226     if (_type_set != ref) {
227       if (_type_set.valid()) {
228         _type_set->set_next(ref);
229         return;
230       }
231       _type_set = ref;
232     }
233   }
234 };
235 
236 #endif // SHARE_JFR_LEAKPROFILER_SAMPLING_OBJECTSAMPLE_HPP