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 "gc/serial/genMarkSweep.hpp"
27 #include "gc/serial/tenuredGeneration.inline.hpp"
28 #include "gc/shared/blockOffsetTable.inline.hpp"
29 #include "gc/shared/cardGeneration.inline.hpp"
30 #include "gc/shared/collectorCounters.hpp"
31 #include "gc/shared/gcTimer.hpp"
32 #include "gc/shared/genOopClosures.inline.hpp"
33 #include "gc/shared/generationSpec.hpp"
34 #include "gc/shared/space.hpp"
35 #include "memory/allocation.inline.hpp"
36 #include "oops/oop.inline.hpp"
37 #include "runtime/java.hpp"
38 #include "utilities/macros.hpp"
39 #if INCLUDE_ALL_GCS
40 #include "gc/cms/parOopClosures.hpp"
41 #endif
42
43 TenuredGeneration::TenuredGeneration(ReservedSpace rs,
44 size_t initial_byte_size,
45 CardTableRS* remset) :
46 CardGeneration(rs, initial_byte_size, remset)
47 {
48 HeapWord* bottom = (HeapWord*) _virtual_space.low();
49 HeapWord* end = (HeapWord*) _virtual_space.high();
50 _the_space = new TenuredSpace(_bts, MemRegion(bottom, end));
51 _the_space->reset_saved_mark();
52 _shrink_factor = 0;
53 _capacity_at_prologue = 0;
54
64
65 _gc_counters = new CollectorCounters("MSC", 1);
66
67 _space_counters = new CSpaceCounters(gen_name, 0,
68 _virtual_space.reserved_size(),
69 _the_space, _gen_counters);
70 }
71
72 void TenuredGeneration::gc_prologue(bool full) {
73 _capacity_at_prologue = capacity();
74 _used_at_prologue = used();
75 }
76
77 bool TenuredGeneration::should_collect(bool full,
78 size_t size,
79 bool is_tlab) {
80 // This should be one big conditional or (||), but I want to be able to tell
81 // why it returns what it returns (without re-evaluating the conditionals
82 // in case they aren't idempotent), so I'm doing it this way.
83 // DeMorgan says it's okay.
84 bool result = false;
85 if (!result && full) {
86 result = true;
87 if (PrintGC && Verbose) {
88 gclog_or_tty->print_cr("TenuredGeneration::should_collect: because"
89 " full");
90 }
91 }
92 if (!result && should_allocate(size, is_tlab)) {
93 result = true;
94 if (PrintGC && Verbose) {
95 gclog_or_tty->print_cr("TenuredGeneration::should_collect: because"
96 " should_allocate(" SIZE_FORMAT ")",
97 size);
98 }
99 }
100 // If we don't have very much free space.
101 // XXX: 10000 should be a percentage of the capacity!!!
102 if (!result && free() < 10000) {
103 result = true;
104 if (PrintGC && Verbose) {
105 gclog_or_tty->print_cr("TenuredGeneration::should_collect: because"
106 " free(): " SIZE_FORMAT,
107 free());
108 }
109 }
110 // If we had to expand to accommodate promotions from the young generation
111 if (!result && _capacity_at_prologue < capacity()) {
112 result = true;
113 if (PrintGC && Verbose) {
114 gclog_or_tty->print_cr("TenuredGeneration::should_collect: because"
115 "_capacity_at_prologue: " SIZE_FORMAT " < capacity(): " SIZE_FORMAT,
116 _capacity_at_prologue, capacity());
117 }
118 }
119 return result;
120 }
121
122 void TenuredGeneration::compute_new_size() {
123 assert_locked_or_safepoint(Heap_lock);
124
125 // Compute some numbers about the state of the heap.
126 const size_t used_after_gc = used();
127 const size_t capacity_after_gc = capacity();
128
129 CardGeneration::compute_new_size();
130
131 assert(used() == used_after_gc && used_after_gc <= capacity(),
132 "used: " SIZE_FORMAT " used_after_gc: " SIZE_FORMAT
133 " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity());
134 }
135
136 void TenuredGeneration::update_gc_stats(Generation* current_generation,
137 bool full) {
138 // If the young generation has been collected, gather any statistics
139 // that are of interest at this point.
148 // average will incorrectly lessen the average. It is, however,
149 // also possible that no promotion was needed.
150 if (used_before_gc >= _used_at_prologue) {
151 size_t promoted_in_bytes = used_before_gc - _used_at_prologue;
152 gc_stats()->avg_promoted()->sample(promoted_in_bytes);
153 }
154 }
155 }
156
157 void TenuredGeneration::update_counters() {
158 if (UsePerfData) {
159 _space_counters->update_all();
160 _gen_counters->update_all();
161 }
162 }
163
164 bool TenuredGeneration::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const {
165 size_t available = max_contiguous_available();
166 size_t av_promo = (size_t)gc_stats()->avg_promoted()->padded_average();
167 bool res = (available >= av_promo) || (available >= max_promotion_in_bytes);
168 if (PrintGC && Verbose) {
169 gclog_or_tty->print_cr(
170 "Tenured: promo attempt is%s safe: available(" SIZE_FORMAT ") %s av_promo(" SIZE_FORMAT "),"
171 "max_promo(" SIZE_FORMAT ")",
172 res? "":" not", available, res? ">=":"<",
173 av_promo, max_promotion_in_bytes);
174 }
175 return res;
176 }
177
178 void TenuredGeneration::collect(bool full,
179 bool clear_all_soft_refs,
180 size_t size,
181 bool is_tlab) {
182 GenCollectedHeap* gch = GenCollectedHeap::heap();
183
184 // Temporarily expand the span of our ref processor, so
185 // refs discovery is over the entire heap, not just this generation
186 ReferenceProcessorSpanMutator
187 x(ref_processor(), gch->reserved_region());
188
189 STWGCTimer* gc_timer = GenMarkSweep::gc_timer();
190 gc_timer->register_gc_start();
191
192 SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer();
193 gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start());
194
|
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 "gc/serial/genMarkSweep.hpp"
27 #include "gc/serial/tenuredGeneration.inline.hpp"
28 #include "gc/shared/blockOffsetTable.inline.hpp"
29 #include "gc/shared/cardGeneration.inline.hpp"
30 #include "gc/shared/collectorCounters.hpp"
31 #include "gc/shared/gcTimer.hpp"
32 #include "gc/shared/genOopClosures.inline.hpp"
33 #include "gc/shared/generationSpec.hpp"
34 #include "gc/shared/space.hpp"
35 #include "logging/log.hpp"
36 #include "memory/allocation.inline.hpp"
37 #include "oops/oop.inline.hpp"
38 #include "runtime/java.hpp"
39 #include "utilities/macros.hpp"
40 #if INCLUDE_ALL_GCS
41 #include "gc/cms/parOopClosures.hpp"
42 #endif
43
44 TenuredGeneration::TenuredGeneration(ReservedSpace rs,
45 size_t initial_byte_size,
46 CardTableRS* remset) :
47 CardGeneration(rs, initial_byte_size, remset)
48 {
49 HeapWord* bottom = (HeapWord*) _virtual_space.low();
50 HeapWord* end = (HeapWord*) _virtual_space.high();
51 _the_space = new TenuredSpace(_bts, MemRegion(bottom, end));
52 _the_space->reset_saved_mark();
53 _shrink_factor = 0;
54 _capacity_at_prologue = 0;
55
65
66 _gc_counters = new CollectorCounters("MSC", 1);
67
68 _space_counters = new CSpaceCounters(gen_name, 0,
69 _virtual_space.reserved_size(),
70 _the_space, _gen_counters);
71 }
72
73 void TenuredGeneration::gc_prologue(bool full) {
74 _capacity_at_prologue = capacity();
75 _used_at_prologue = used();
76 }
77
78 bool TenuredGeneration::should_collect(bool full,
79 size_t size,
80 bool is_tlab) {
81 // This should be one big conditional or (||), but I want to be able to tell
82 // why it returns what it returns (without re-evaluating the conditionals
83 // in case they aren't idempotent), so I'm doing it this way.
84 // DeMorgan says it's okay.
85 if (full) {
86 log_trace(gc)("TenuredGeneration::should_collect: because full");
87 return true;
88 }
89 if (should_allocate(size, is_tlab)) {
90 log_trace(gc)("TenuredGeneration::should_collect: because should_allocate(" SIZE_FORMAT ")", size);
91 return true;
92 }
93 // If we don't have very much free space.
94 // XXX: 10000 should be a percentage of the capacity!!!
95 if (free() < 10000) {
96 log_trace(gc)("TenuredGeneration::should_collect: because free(): " SIZE_FORMAT, free());
97 return true;
98 }
99 // If we had to expand to accommodate promotions from the young generation
100 if (_capacity_at_prologue < capacity()) {
101 log_trace(gc)("TenuredGeneration::should_collect: because_capacity_at_prologue: " SIZE_FORMAT " < capacity(): " SIZE_FORMAT,
102 _capacity_at_prologue, capacity());
103 return true;
104 }
105
106 return false;
107 }
108
109 void TenuredGeneration::compute_new_size() {
110 assert_locked_or_safepoint(Heap_lock);
111
112 // Compute some numbers about the state of the heap.
113 const size_t used_after_gc = used();
114 const size_t capacity_after_gc = capacity();
115
116 CardGeneration::compute_new_size();
117
118 assert(used() == used_after_gc && used_after_gc <= capacity(),
119 "used: " SIZE_FORMAT " used_after_gc: " SIZE_FORMAT
120 " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity());
121 }
122
123 void TenuredGeneration::update_gc_stats(Generation* current_generation,
124 bool full) {
125 // If the young generation has been collected, gather any statistics
126 // that are of interest at this point.
135 // average will incorrectly lessen the average. It is, however,
136 // also possible that no promotion was needed.
137 if (used_before_gc >= _used_at_prologue) {
138 size_t promoted_in_bytes = used_before_gc - _used_at_prologue;
139 gc_stats()->avg_promoted()->sample(promoted_in_bytes);
140 }
141 }
142 }
143
144 void TenuredGeneration::update_counters() {
145 if (UsePerfData) {
146 _space_counters->update_all();
147 _gen_counters->update_all();
148 }
149 }
150
151 bool TenuredGeneration::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const {
152 size_t available = max_contiguous_available();
153 size_t av_promo = (size_t)gc_stats()->avg_promoted()->padded_average();
154 bool res = (available >= av_promo) || (available >= max_promotion_in_bytes);
155
156 log_trace(gc)("Tenured: promo attempt is%s safe: available(" SIZE_FORMAT ") %s av_promo(" SIZE_FORMAT "), max_promo(" SIZE_FORMAT ")",
157 res? "":" not", available, res? ">=":"<", av_promo, max_promotion_in_bytes);
158
159 return res;
160 }
161
162 void TenuredGeneration::collect(bool full,
163 bool clear_all_soft_refs,
164 size_t size,
165 bool is_tlab) {
166 GenCollectedHeap* gch = GenCollectedHeap::heap();
167
168 // Temporarily expand the span of our ref processor, so
169 // refs discovery is over the entire heap, not just this generation
170 ReferenceProcessorSpanMutator
171 x(ref_processor(), gch->reserved_region());
172
173 STWGCTimer* gc_timer = GenMarkSweep::gc_timer();
174 gc_timer->register_gc_start();
175
176 SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer();
177 gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start());
178
|