1 /*
2  * Copyright (c) 2017, 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 #include "precompiled.hpp"
26 #include "jfr/leakprofiler/sampling/objectSample.hpp"
27 #include "jfr/leakprofiler/sampling/sampleList.hpp"
28 #include "oops/oop.inline.hpp"
29 
SampleList(size_t limit,size_t cache_size)30 SampleList::SampleList(size_t limit, size_t cache_size) :
31   _free_list(),
32   _in_use_list(),
33   _last_resolved(NULL),
34   _allocated(0),
35   _limit(limit),
36   _cache_size(cache_size) {
37 }
38 
~SampleList()39 SampleList::~SampleList() {
40   deallocate_samples(_free_list);
41   deallocate_samples(_in_use_list);
42 }
43 
last() const44 ObjectSample* SampleList::last() const {
45   return _in_use_list.head();
46 }
47 
first() const48 ObjectSample* SampleList::first() const {
49   return _in_use_list.tail();
50 }
51 
last_resolved() const52 const ObjectSample* SampleList::last_resolved() const {
53   return _last_resolved;
54 }
55 
set_last_resolved(const ObjectSample * sample)56 void SampleList::set_last_resolved(const ObjectSample* sample) {
57   assert(last() == sample, "invariant");
58   _last_resolved = sample;
59 }
60 
link(ObjectSample * sample)61 void SampleList::link(ObjectSample* sample) {
62   assert(sample != NULL, "invariant");
63   _in_use_list.prepend(sample);
64 }
65 
unlink(ObjectSample * sample)66 void SampleList::unlink(ObjectSample* sample) {
67   assert(sample != NULL, "invariant");
68   if (_last_resolved == sample) {
69     _last_resolved = sample->next();
70   }
71   reset(_in_use_list.remove(sample));
72 }
73 
reuse(ObjectSample * sample)74 ObjectSample* SampleList::reuse(ObjectSample* sample) {
75   assert(sample != NULL, "invariant");
76   unlink(sample);
77   link(sample);
78   return sample;
79 }
80 
populate_cache()81 void SampleList::populate_cache() {
82   if (_free_list.count() < _cache_size) {
83     const size_t cache_delta = _cache_size - _free_list.count();
84     for (size_t i = 0; i < cache_delta; ++i) {
85       ObjectSample* sample = newSample();
86       if (sample != NULL) {
87         _free_list.append(sample);
88       }
89     }
90   }
91 }
92 
newSample() const93 ObjectSample* SampleList::newSample() const {
94   if (_limit == _allocated) {
95     return NULL;
96   }
97   ++_allocated;
98   return new ObjectSample();
99 }
100 
get()101 ObjectSample* SampleList::get() {
102   ObjectSample* sample = _free_list.head();
103   if (sample != NULL) {
104     link(_free_list.remove(sample));
105   } else {
106     sample = newSample();
107     if (sample != NULL) {
108       _in_use_list.prepend(sample);
109     }
110   }
111   if (_cache_size > 0 && sample != NULL) {
112     populate_cache();
113   }
114   return sample;
115 }
116 
release(ObjectSample * sample)117 void SampleList::release(ObjectSample* sample) {
118   assert(sample != NULL, "invariant");
119   unlink(sample);
120   _free_list.append(sample);
121 }
122 
deallocate_samples(List & list)123 void SampleList::deallocate_samples(List& list) {
124   if (list.count() > 0) {
125     ObjectSample* sample = list.head();
126     while (sample != NULL) {
127       list.remove(sample);
128       delete sample;
129       sample = list.head();
130     }
131   }
132   assert(list.count() == 0, "invariant");
133 }
134 
reset(ObjectSample * sample)135 void SampleList::reset(ObjectSample* sample) {
136   assert(sample != NULL, "invariant");
137   sample->reset();
138 }
139 
is_full() const140 bool SampleList::is_full() const {
141   return _in_use_list.count() == _limit;
142 }
143 
count() const144 size_t SampleList::count() const {
145   return _in_use_list.count();
146 }
147