--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp Fri May 17 08:00:01 2013 +0200
@@ -74,7 +74,7 @@
define_pd_global(bool, UseMembar, false);
// GC Ergo Flags
-define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread
+define_pd_global(uintx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
\
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Fri May 17 08:00:01 2013 +0200
@@ -77,7 +77,7 @@
#endif
// GC Ergo Flags
-define_pd_global(intx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread
+define_pd_global(uintx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
\
--- a/hotspot/src/cpu/zero/vm/globals_zero.hpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp Fri May 17 08:00:01 2013 +0200
@@ -55,7 +55,7 @@
define_pd_global(bool, UseMembar, true);
// GC Ergo Flags
-define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread
+define_pd_global(uintx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct)
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri May 17 08:00:01 2013 +0200
@@ -692,8 +692,7 @@
_cmsGen ->init_initiating_occupancy(CMSInitiatingOccupancyFraction, CMSTriggerRatio);
// Clip CMSBootstrapOccupancy between 0 and 100.
- _bootstrap_occupancy = ((double)MIN2((uintx)100, MAX2((uintx)0, CMSBootstrapOccupancy)))
- /(double)100;
+ _bootstrap_occupancy = ((double)CMSBootstrapOccupancy)/(double)100;
_full_gcs_since_conc_gc = 0;
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri May 17 08:00:01 2013 +0200
@@ -4515,7 +4515,8 @@
_total_used_bytes(0), _total_capacity_bytes(0),
_total_prev_live_bytes(0), _total_next_live_bytes(0),
_hum_used_bytes(0), _hum_capacity_bytes(0),
- _hum_prev_live_bytes(0), _hum_next_live_bytes(0) {
+ _hum_prev_live_bytes(0), _hum_next_live_bytes(0),
+ _total_remset_bytes(0) {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
MemRegion g1_committed = g1h->g1_committed();
MemRegion g1_reserved = g1h->g1_reserved();
@@ -4533,23 +4534,25 @@
HeapRegion::GrainBytes);
_out->print_cr(G1PPRL_LINE_PREFIX);
_out->print_cr(G1PPRL_LINE_PREFIX
- G1PPRL_TYPE_H_FORMAT
- G1PPRL_ADDR_BASE_H_FORMAT
- G1PPRL_BYTE_H_FORMAT
- G1PPRL_BYTE_H_FORMAT
- G1PPRL_BYTE_H_FORMAT
- G1PPRL_DOUBLE_H_FORMAT,
- "type", "address-range",
- "used", "prev-live", "next-live", "gc-eff");
+ G1PPRL_TYPE_H_FORMAT
+ G1PPRL_ADDR_BASE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_DOUBLE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT,
+ "type", "address-range",
+ "used", "prev-live", "next-live", "gc-eff", "remset");
_out->print_cr(G1PPRL_LINE_PREFIX
- G1PPRL_TYPE_H_FORMAT
- G1PPRL_ADDR_BASE_H_FORMAT
- G1PPRL_BYTE_H_FORMAT
- G1PPRL_BYTE_H_FORMAT
- G1PPRL_BYTE_H_FORMAT
- G1PPRL_DOUBLE_H_FORMAT,
- "", "",
- "(bytes)", "(bytes)", "(bytes)", "(bytes/ms)");
+ G1PPRL_TYPE_H_FORMAT
+ G1PPRL_ADDR_BASE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_DOUBLE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT,
+ "", "",
+ "(bytes)", "(bytes)", "(bytes)", "(bytes/ms)", "(bytes)");
}
// It takes as a parameter a reference to one of the _hum_* fields, it
@@ -4591,6 +4594,7 @@
size_t prev_live_bytes = r->live_bytes();
size_t next_live_bytes = r->next_live_bytes();
double gc_eff = r->gc_efficiency();
+ size_t remset_bytes = r->rem_set()->mem_size();
if (r->used() == 0) {
type = "FREE";
} else if (r->is_survivor()) {
@@ -4624,6 +4628,7 @@
_total_capacity_bytes += capacity_bytes;
_total_prev_live_bytes += prev_live_bytes;
_total_next_live_bytes += next_live_bytes;
+ _total_remset_bytes += remset_bytes;
// Print a line for this particular region.
_out->print_cr(G1PPRL_LINE_PREFIX
@@ -4632,14 +4637,17 @@
G1PPRL_BYTE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_BYTE_FORMAT
- G1PPRL_DOUBLE_FORMAT,
+ G1PPRL_DOUBLE_FORMAT
+ G1PPRL_BYTE_FORMAT,
type, bottom, end,
- used_bytes, prev_live_bytes, next_live_bytes, gc_eff);
+ used_bytes, prev_live_bytes, next_live_bytes, gc_eff , remset_bytes);
return false;
}
G1PrintRegionLivenessInfoClosure::~G1PrintRegionLivenessInfoClosure() {
+ // add static memory usages to remembered set sizes
+ _total_remset_bytes += HeapRegionRemSet::fl_mem_size() + HeapRegionRemSet::static_mem_size();
// Print the footer of the output.
_out->print_cr(G1PPRL_LINE_PREFIX);
_out->print_cr(G1PPRL_LINE_PREFIX
@@ -4647,13 +4655,15 @@
G1PPRL_SUM_MB_FORMAT("capacity")
G1PPRL_SUM_MB_PERC_FORMAT("used")
G1PPRL_SUM_MB_PERC_FORMAT("prev-live")
- G1PPRL_SUM_MB_PERC_FORMAT("next-live"),
+ G1PPRL_SUM_MB_PERC_FORMAT("next-live")
+ G1PPRL_SUM_MB_FORMAT("remset"),
bytes_to_mb(_total_capacity_bytes),
bytes_to_mb(_total_used_bytes),
perc(_total_used_bytes, _total_capacity_bytes),
bytes_to_mb(_total_prev_live_bytes),
perc(_total_prev_live_bytes, _total_capacity_bytes),
bytes_to_mb(_total_next_live_bytes),
- perc(_total_next_live_bytes, _total_capacity_bytes));
+ perc(_total_next_live_bytes, _total_capacity_bytes),
+ bytes_to_mb(_total_remset_bytes));
_out->cr();
}
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri May 17 08:00:01 2013 +0200
@@ -1257,6 +1257,9 @@
size_t _hum_prev_live_bytes;
size_t _hum_next_live_bytes;
+ // Accumulator for the remembered set size
+ size_t _total_remset_bytes;
+
static double perc(size_t val, size_t total) {
if (total == 0) {
return 0.0;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp Fri May 17 08:00:01 2013 +0200
@@ -101,20 +101,23 @@
ReservedSpace::allocation_align_size_up(_committed_size),
err_msg("Unaligned? committed_size: " SIZE_FORMAT, _committed_size));
- // Verify that the committed space for the card counts
- // matches our committed max card num.
+ // Verify that the committed space for the card counts matches our
+ // committed max card num. Note for some allocation alignments, the
+ // amount of space actually committed for the counts table will be able
+ // to span more cards than the number spanned by the maximum heap.
size_t prev_committed_size = _committed_size;
- size_t prev_committed_card_num = prev_committed_size / sizeof(jbyte);
+ size_t prev_committed_card_num = committed_to_card_num(prev_committed_size);
+
assert(prev_committed_card_num == _committed_max_card_num,
err_msg("Card mismatch: "
"prev: " SIZE_FORMAT ", "
- "committed: "SIZE_FORMAT,
- prev_committed_card_num, _committed_max_card_num));
+ "committed: "SIZE_FORMAT", "
+ "reserved: "SIZE_FORMAT,
+ prev_committed_card_num, _committed_max_card_num, _reserved_max_card_num));
size_t new_size = (heap_capacity >> CardTableModRefBS::card_shift) * sizeof(jbyte);
size_t new_committed_size = ReservedSpace::allocation_align_size_up(new_size);
- size_t new_committed_card_num =
- MIN2(_reserved_max_card_num, new_committed_size / sizeof(jbyte));
+ size_t new_committed_card_num = committed_to_card_num(new_committed_size);
if (_committed_max_card_num < new_committed_card_num) {
// we need to expand the backing store for the card counts
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp Fri May 17 08:00:01 2013 +0200
@@ -94,6 +94,14 @@
return (jbyte*) (_ct_bot + card_num);
}
+ // Helper routine.
+ // Returns the number of cards that can be counted by the given committed
+ // table size, with a maximum of the number of cards spanned by the max
+ // capacity of the heap.
+ size_t committed_to_card_num(size_t committed_size) {
+ return MIN2(_reserved_max_card_num, committed_size / sizeof(jbyte));
+ }
+
// Clear the counts table for the given (exclusive) index range.
void clear_range(size_t from_card_num, size_t to_card_num);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri May 17 08:00:01 2013 +0200
@@ -1549,7 +1549,7 @@
}
if (G1Log::finer()) {
- g1_policy()->print_detailed_heap_transition();
+ g1_policy()->print_detailed_heap_transition(true /* full */);
}
print_heap_after_gc();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri May 17 08:00:01 2013 +0200
@@ -124,9 +124,12 @@
_last_young_gc(false),
_last_gc_was_young(false),
- _eden_bytes_before_gc(0),
- _survivor_bytes_before_gc(0),
- _capacity_before_gc(0),
+ _eden_used_bytes_before_gc(0),
+ _survivor_used_bytes_before_gc(0),
+ _heap_used_bytes_before_gc(0),
+ _metaspace_used_bytes_before_gc(0),
+ _eden_capacity_bytes_before_gc(0),
+ _heap_capacity_bytes_before_gc(0),
_eden_cset_region_length(0),
_survivor_cset_region_length(0),
@@ -746,7 +749,7 @@
void G1CollectorPolicy::record_full_collection_start() {
_full_collection_start_sec = os::elapsedTime();
- record_heap_size_info_at_start();
+ record_heap_size_info_at_start(true /* full */);
// Release the future to-space so that it is available for compaction into.
_g1->set_full_collection();
}
@@ -803,7 +806,7 @@
_trace_gen0_time_data.record_start_collection(s_w_t_ms);
_stop_world_start = 0.0;
- record_heap_size_info_at_start();
+ record_heap_size_info_at_start(false /* full */);
phase_times()->record_cur_collection_start_sec(start_time_sec);
_pending_cards = _g1->pending_card_num();
@@ -938,14 +941,6 @@
_mmu_tracker->add_pause(end_time_sec - pause_time_ms/1000.0,
end_time_sec, false);
- size_t freed_bytes =
- _cur_collection_pause_used_at_start_bytes - cur_used_bytes;
- size_t surviving_bytes = _collection_set_bytes_used_before - freed_bytes;
-
- double survival_fraction =
- (double)surviving_bytes/
- (double)_collection_set_bytes_used_before;
-
if (update_stats) {
_trace_gen0_time_data.record_end_collection(pause_time_ms, phase_times());
// this is where we update the allocation rate of the application
@@ -998,6 +993,7 @@
}
}
}
+
bool new_in_marking_window = _in_marking_window;
bool new_in_marking_window_im = false;
if (during_initial_mark_pause()) {
@@ -1083,8 +1079,10 @@
}
_rs_length_diff_seq->add((double) rs_length_diff);
- size_t copied_bytes = surviving_bytes;
+ size_t freed_bytes = _heap_used_bytes_before_gc - cur_used_bytes;
+ size_t copied_bytes = _collection_set_bytes_used_before - freed_bytes;
double cost_per_byte_ms = 0.0;
+
if (copied_bytes > 0) {
cost_per_byte_ms = phase_times()->average_last_obj_copy_time() / (double) copied_bytes;
if (_in_marking_window) {
@@ -1148,51 +1146,61 @@
byte_size_in_proper_unit((double)(bytes)), \
proper_unit_for_byte_size((bytes))
-void G1CollectorPolicy::record_heap_size_info_at_start() {
+void G1CollectorPolicy::record_heap_size_info_at_start(bool full) {
YoungList* young_list = _g1->young_list();
- _eden_bytes_before_gc = young_list->eden_used_bytes();
- _survivor_bytes_before_gc = young_list->survivor_used_bytes();
- _capacity_before_gc = _g1->capacity();
-
- _cur_collection_pause_used_at_start_bytes = _g1->used();
+ _eden_used_bytes_before_gc = young_list->eden_used_bytes();
+ _survivor_used_bytes_before_gc = young_list->survivor_used_bytes();
+ _heap_capacity_bytes_before_gc = _g1->capacity();
+ _heap_used_bytes_before_gc = _g1->used();
_cur_collection_pause_used_regions_at_start = _g1->used_regions();
- size_t eden_capacity_before_gc =
- (_young_list_target_length * HeapRegion::GrainBytes) - _survivor_bytes_before_gc;
+ _eden_capacity_bytes_before_gc =
+ (_young_list_target_length * HeapRegion::GrainBytes) - _survivor_used_bytes_before_gc;
- _prev_eden_capacity = eden_capacity_before_gc;
+ if (full) {
+ _metaspace_used_bytes_before_gc = MetaspaceAux::allocated_used_bytes();
+ }
}
void G1CollectorPolicy::print_heap_transition() {
_g1->print_size_transition(gclog_or_tty,
- _cur_collection_pause_used_at_start_bytes, _g1->used(), _g1->capacity());
+ _heap_used_bytes_before_gc,
+ _g1->used(),
+ _g1->capacity());
}
-void G1CollectorPolicy::print_detailed_heap_transition() {
- YoungList* young_list = _g1->young_list();
- size_t eden_bytes = young_list->eden_used_bytes();
- size_t survivor_bytes = young_list->survivor_used_bytes();
- size_t used_before_gc = _cur_collection_pause_used_at_start_bytes;
- size_t used = _g1->used();
- size_t capacity = _g1->capacity();
- size_t eden_capacity =
- (_young_list_target_length * HeapRegion::GrainBytes) - survivor_bytes;
+void G1CollectorPolicy::print_detailed_heap_transition(bool full) {
+ YoungList* young_list = _g1->young_list();
+
+ size_t eden_used_bytes_after_gc = young_list->eden_used_bytes();
+ size_t survivor_used_bytes_after_gc = young_list->survivor_used_bytes();
+ size_t heap_used_bytes_after_gc = _g1->used();
+
+ size_t heap_capacity_bytes_after_gc = _g1->capacity();
+ size_t eden_capacity_bytes_after_gc =
+ (_young_list_target_length * HeapRegion::GrainBytes) - survivor_used_bytes_after_gc;
- gclog_or_tty->print_cr(
- " [Eden: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT") "
- "Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" "
- "Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"
- EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]",
- EXT_SIZE_PARAMS(_eden_bytes_before_gc),
- EXT_SIZE_PARAMS(_prev_eden_capacity),
- EXT_SIZE_PARAMS(eden_bytes),
- EXT_SIZE_PARAMS(eden_capacity),
- EXT_SIZE_PARAMS(_survivor_bytes_before_gc),
- EXT_SIZE_PARAMS(survivor_bytes),
- EXT_SIZE_PARAMS(used_before_gc),
- EXT_SIZE_PARAMS(_capacity_before_gc),
- EXT_SIZE_PARAMS(used),
- EXT_SIZE_PARAMS(capacity));
+ gclog_or_tty->print(
+ " [Eden: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT") "
+ "Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" "
+ "Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"
+ EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]",
+ EXT_SIZE_PARAMS(_eden_used_bytes_before_gc),
+ EXT_SIZE_PARAMS(_eden_capacity_bytes_before_gc),
+ EXT_SIZE_PARAMS(eden_used_bytes_after_gc),
+ EXT_SIZE_PARAMS(eden_capacity_bytes_after_gc),
+ EXT_SIZE_PARAMS(_survivor_used_bytes_before_gc),
+ EXT_SIZE_PARAMS(survivor_used_bytes_after_gc),
+ EXT_SIZE_PARAMS(_heap_used_bytes_before_gc),
+ EXT_SIZE_PARAMS(_heap_capacity_bytes_before_gc),
+ EXT_SIZE_PARAMS(heap_used_bytes_after_gc),
+ EXT_SIZE_PARAMS(heap_capacity_bytes_after_gc));
+
+ if (full) {
+ MetaspaceAux::print_metaspace_change(_metaspace_used_bytes_before_gc);
+ }
+
+ gclog_or_tty->cr();
}
void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Fri May 17 08:00:01 2013 +0200
@@ -175,7 +175,6 @@
CollectionSetChooser* _collectionSetChooser;
double _full_collection_start_sec;
- size_t _cur_collection_pause_used_at_start_bytes;
uint _cur_collection_pause_used_regions_at_start;
// These exclude marking times.
@@ -194,7 +193,6 @@
uint _young_list_target_length;
uint _young_list_fixed_length;
- size_t _prev_eden_capacity; // used for logging
// The max number of regions we can extend the eden by while the GC
// locker is active. This should be >= _young_list_target_length;
@@ -693,11 +691,11 @@
// Records the information about the heap size for reporting in
// print_detailed_heap_transition
- void record_heap_size_info_at_start();
+ void record_heap_size_info_at_start(bool full);
// Print heap sizing transition (with less and more detail).
void print_heap_transition();
- void print_detailed_heap_transition();
+ void print_detailed_heap_transition(bool full = false);
void record_stop_world_start();
void record_concurrent_pause();
@@ -861,9 +859,16 @@
uint _max_survivor_regions;
// For reporting purposes.
- size_t _eden_bytes_before_gc;
- size_t _survivor_bytes_before_gc;
- size_t _capacity_before_gc;
+ // The value of _heap_bytes_before_gc is also used to calculate
+ // the cost of copying.
+
+ size_t _eden_used_bytes_before_gc; // Eden occupancy before GC
+ size_t _survivor_used_bytes_before_gc; // Survivor occupancy before GC
+ size_t _heap_used_bytes_before_gc; // Heap occupancy before GC
+ size_t _metaspace_used_bytes_before_gc; // Metaspace occupancy before GC
+
+ size_t _eden_capacity_bytes_before_gc; // Eden capacity before GC
+ size_t _heap_capacity_bytes_before_gc; // Heap capacity before GC
// The amount of survivor regions after a collection.
uint _recorded_survivor_regions;
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Fri May 17 08:00:01 2013 +0200
@@ -707,10 +707,11 @@
// Cast away const in this case.
MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag);
size_t sum = 0;
- PerRegionTable * cur = _first_all_fine_prts;
- while (cur != NULL) {
- sum += cur->mem_size();
- cur = cur->next();
+ // all PRTs are of the same size so it is sufficient to query only one of them.
+ if (_first_all_fine_prts != NULL) {
+ assert(_last_all_fine_prts != NULL &&
+ _first_all_fine_prts->mem_size() == _last_all_fine_prts->mem_size(), "check that mem_size() is constant");
+ sum += _first_all_fine_prts->mem_size() * _n_fine_entries;
}
sum += (sizeof(PerRegionTable*) * _max_fine_entries);
sum += (_coarse_map.size_in_words() * HeapWordSize);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Fri May 17 08:00:01 2013 +0200
@@ -24,7 +24,6 @@
#include "precompiled.hpp"
#include "gc_implementation/parallelScavenge/parMarkBitMap.hpp"
-#include "gc_implementation/parallelScavenge/parMarkBitMap.inline.hpp"
#include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/os.hpp"
@@ -108,31 +107,6 @@
return false;
}
-size_t
-ParMarkBitMap::live_words_in_range(HeapWord* beg_addr, HeapWord* end_addr) const
-{
- assert(beg_addr <= end_addr, "bad range");
-
- idx_t live_bits = 0;
-
- // The bitmap routines require the right boundary to be word-aligned.
- const idx_t end_bit = addr_to_bit(end_addr);
- const idx_t range_end = BitMap::word_align_up(end_bit);
-
- idx_t beg_bit = find_obj_beg(addr_to_bit(beg_addr), range_end);
- while (beg_bit < end_bit) {
- idx_t tmp_end = find_obj_end(beg_bit, range_end);
- if (tmp_end < end_bit) {
- live_bits += tmp_end - beg_bit + 1;
- beg_bit = find_obj_beg(tmp_end + 1, range_end);
- } else {
- live_bits += end_bit - beg_bit; // No + 1 here; end_bit is not counted.
- return bits_to_words(live_bits);
- }
- }
- return bits_to_words(live_bits);
-}
-
size_t ParMarkBitMap::live_words_in_range(HeapWord* beg_addr, oop end_obj) const
{
assert(beg_addr <= (HeapWord*)end_obj, "bad range");
@@ -244,13 +218,6 @@
return complete;
}
-#ifndef PRODUCT
-void ParMarkBitMap::reset_counters()
-{
- _cas_tries = _cas_retries = _cas_by_another = 0;
-}
-#endif // #ifndef PRODUCT
-
#ifdef ASSERT
void ParMarkBitMap::verify_clear() const
{
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp Fri May 17 08:00:01 2013 +0200
@@ -26,11 +26,11 @@
#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_HPP
#include "memory/memRegion.hpp"
-#include "gc_implementation/parallelScavenge/psVirtualspace.hpp"
-#include "utilities/bitMap.inline.hpp"
+#include "oops/oop.hpp"
+#include "utilities/bitMap.hpp"
-class oopDesc;
class ParMarkBitMapClosure;
+class PSVirtualSpace;
class ParMarkBitMap: public CHeapObj<mtGC>
{
@@ -41,13 +41,11 @@
enum IterationStatus { incomplete, complete, full, would_overflow };
inline ParMarkBitMap();
- inline ParMarkBitMap(MemRegion covered_region);
bool initialize(MemRegion covered_region);
// Atomically mark an object as live.
bool mark_obj(HeapWord* addr, size_t size);
inline bool mark_obj(oop obj, int size);
- inline bool mark_obj(oop obj);
// Return whether the specified begin or end bit is set.
inline bool is_obj_beg(idx_t bit) const;
@@ -77,11 +75,6 @@
// Return the size in words of the object (a search is done for the end bit).
inline size_t obj_size(idx_t beg_bit) const;
inline size_t obj_size(HeapWord* addr) const;
- inline size_t obj_size(oop obj) const;
-
- // Synonyms for the above.
- size_t obj_size_in_words(oop obj) const { return obj_size((HeapWord*)obj); }
- size_t obj_size_in_words(HeapWord* addr) const { return obj_size(addr); }
// Apply live_closure to each live object that lies completely within the
// range [live_range_beg, live_range_end). This is used to iterate over the
@@ -124,15 +117,12 @@
HeapWord* range_end,
HeapWord* dead_range_end) const;
- // Return the number of live words in the range [beg_addr, end_addr) due to
+ // Return the number of live words in the range [beg_addr, end_obj) due to
// objects that start in the range. If a live object extends onto the range,
// the caller must detect and account for any live words due to that object.
// If a live object extends beyond the end of the range, only the words within
- // the range are included in the result.
- size_t live_words_in_range(HeapWord* beg_addr, HeapWord* end_addr) const;
-
- // Same as the above, except the end of the range must be a live object, which
- // is the case when updating pointers. This allows a branch to be removed
+ // the range are included in the result. The end of the range must be a live object,
+ // which is the case when updating pointers. This allows a branch to be removed
// from inside the loop.
size_t live_words_in_range(HeapWord* beg_addr, oop end_obj) const;
@@ -156,22 +146,11 @@
// Clear a range of bits or the entire bitmap (both begin and end bits are
// cleared).
inline void clear_range(idx_t beg, idx_t end);
- inline void clear() { clear_range(0, size()); }
// Return the number of bits required to represent the specified number of
// HeapWords, or the specified region.
static inline idx_t bits_required(size_t words);
static inline idx_t bits_required(MemRegion covered_region);
- static inline idx_t words_required(MemRegion covered_region);
-
-#ifndef PRODUCT
- // CAS statistics.
- size_t cas_tries() { return _cas_tries; }
- size_t cas_retries() { return _cas_retries; }
- size_t cas_by_another() { return _cas_by_another; }
-
- void reset_counters();
-#endif // #ifndef PRODUCT
void print_on_error(outputStream* st) const {
st->print_cr("Marking Bits: (ParMarkBitMap*) " PTR_FORMAT, this);
@@ -197,28 +176,11 @@
BitMap _beg_bits;
BitMap _end_bits;
PSVirtualSpace* _virtual_space;
-
-#ifndef PRODUCT
- size_t _cas_tries;
- size_t _cas_retries;
- size_t _cas_by_another;
-#endif // #ifndef PRODUCT
};
inline ParMarkBitMap::ParMarkBitMap():
- _beg_bits(),
- _end_bits()
-{
- _region_start = 0;
- _virtual_space = 0;
-}
-
-inline ParMarkBitMap::ParMarkBitMap(MemRegion covered_region):
- _beg_bits(),
- _end_bits()
-{
- initialize(covered_region);
-}
+ _beg_bits(), _end_bits(), _region_start(NULL), _region_size(0), _virtual_space(NULL)
+{ }
inline void ParMarkBitMap::clear_range(idx_t beg, idx_t end)
{
@@ -240,12 +202,6 @@
return bits_required(covered_region.word_size());
}
-inline ParMarkBitMap::idx_t
-ParMarkBitMap::words_required(MemRegion covered_region)
-{
- return bits_required(covered_region) / BitsPerWord;
-}
-
inline HeapWord*
ParMarkBitMap::region_start() const
{
@@ -350,11 +306,6 @@
return obj_size(addr_to_bit(addr));
}
-inline size_t ParMarkBitMap::obj_size(oop obj) const
-{
- return obj_size((HeapWord*)obj);
-}
-
inline ParMarkBitMap::IterationStatus
ParMarkBitMap::iterate(ParMarkBitMapClosure* live_closure,
HeapWord* range_beg,
@@ -435,8 +386,10 @@
inline void ParMarkBitMap::verify_addr(HeapWord* addr) const {
// Allow one past the last valid address; useful for loop bounds.
- assert(addr >= region_start(), "addr too small");
- assert(addr <= region_start() + region_size(), "addr too big");
+ assert(addr >= region_start(),
+ err_msg("addr too small, addr: " PTR_FORMAT " region start: " PTR_FORMAT, addr, region_start()));
+ assert(addr <= region_end(),
+ err_msg("addr too big, addr: " PTR_FORMAT " region end: " PTR_FORMAT, addr, region_end()));
}
#endif // #ifdef ASSERT
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.inline.hpp Thu May 16 13:47:55 2013 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_INLINE_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_INLINE_HPP
-
-#include "oops/oop.hpp"
-
-inline bool
-ParMarkBitMap::mark_obj(oop obj)
-{
- return mark_obj(obj, obj->size());
-}
-
-#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_INLINE_HPP
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Fri May 17 08:00:01 2013 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -201,15 +201,232 @@
size_t cur_eden,
size_t max_old_gen_size,
size_t max_eden_size,
- bool is_full_gc,
- GCCause::Cause gc_cause,
- CollectorPolicy* collector_policy) {
+ bool is_full_gc) {
+ compute_eden_space_size(young_live,
+ eden_live,
+ cur_eden,
+ max_eden_size,
+ is_full_gc);
+
+ compute_old_gen_free_space(old_live,
+ cur_eden,
+ max_old_gen_size,
+ is_full_gc);
+}
+
+void PSAdaptiveSizePolicy::compute_eden_space_size(
+ size_t young_live,
+ size_t eden_live,
+ size_t cur_eden,
+ size_t max_eden_size,
+ bool is_full_gc) {
// Update statistics
// Time statistics are updated as we go, update footprint stats here
_avg_base_footprint->sample(BaseFootPrintEstimate);
avg_young_live()->sample(young_live);
avg_eden_live()->sample(eden_live);
+
+ // This code used to return if the policy was not ready , i.e.,
+ // policy_is_ready() returning false. The intent was that
+ // decisions below needed major collection times and so could
+ // not be made before two major collections. A consequence was
+ // adjustments to the young generation were not done until after
+ // two major collections even if the minor collections times
+ // exceeded the requested goals. Now let the young generation
+ // adjust for the minor collection times. Major collection times
+ // will be zero for the first collection and will naturally be
+ // ignored. Tenured generation adjustments are only made at the
+ // full collections so until the second major collection has
+ // been reached, no tenured generation adjustments will be made.
+
+ // Until we know better, desired promotion size uses the last calculation
+ size_t desired_promo_size = _promo_size;
+
+ // Start eden at the current value. The desired value that is stored
+ // in _eden_size is not bounded by constraints of the heap and can
+ // run away.
+ //
+ // As expected setting desired_eden_size to the current
+ // value of desired_eden_size as a starting point
+ // caused desired_eden_size to grow way too large and caused
+ // an overflow down stream. It may have improved performance in
+ // some case but is dangerous.
+ size_t desired_eden_size = cur_eden;
+
+ // Cache some values. There's a bit of work getting these, so
+ // we might save a little time.
+ const double major_cost = major_gc_cost();
+ const double minor_cost = minor_gc_cost();
+
+ // This method sets the desired eden size. That plus the
+ // desired survivor space sizes sets the desired young generation
+ // size. This methods does not know what the desired survivor
+ // size is but expects that other policy will attempt to make
+ // the survivor sizes compatible with the live data in the
+ // young generation. This limit is an estimate of the space left
+ // in the young generation after the survivor spaces have been
+ // subtracted out.
+ size_t eden_limit = max_eden_size;
+
+ const double gc_cost_limit = GCTimeLimit/100.0;
+
+ // Which way should we go?
+ // if pause requirement is not met
+ // adjust size of any generation with average paus exceeding
+ // the pause limit. Adjust one pause at a time (the larger)
+ // and only make adjustments for the major pause at full collections.
+ // else if throughput requirement not met
+ // adjust the size of the generation with larger gc time. Only
+ // adjust one generation at a time.
+ // else
+ // adjust down the total heap size. Adjust down the larger of the
+ // generations.
+
+ // Add some checks for a threshold for a change. For example,
+ // a change less than the necessary alignment is probably not worth
+ // attempting.
+
+
+ if ((_avg_minor_pause->padded_average() > gc_pause_goal_sec()) ||
+ (_avg_major_pause->padded_average() > gc_pause_goal_sec())) {
+ //
+ // Check pauses
+ //
+ // Make changes only to affect one of the pauses (the larger)
+ // at a time.
+ adjust_eden_for_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size);
+
+ } else if (_avg_minor_pause->padded_average() > gc_minor_pause_goal_sec()) {
+ // Adjust only for the minor pause time goal
+ adjust_eden_for_minor_pause_time(is_full_gc, &desired_eden_size);
+
+ } else if(adjusted_mutator_cost() < _throughput_goal) {
+ // This branch used to require that (mutator_cost() > 0.0 in 1.4.2.
+ // This sometimes resulted in skipping to the minimize footprint
+ // code. Change this to try and reduce GC time if mutator time is
+ // negative for whatever reason. Or for future consideration,
+ // bail out of the code if mutator time is negative.
+ //
+ // Throughput
+ //
+ assert(major_cost >= 0.0, "major cost is < 0.0");
+ assert(minor_cost >= 0.0, "minor cost is < 0.0");
+ // Try to reduce the GC times.
+ adjust_eden_for_throughput(is_full_gc, &desired_eden_size);
+
+ } else {
+
+ // Be conservative about reducing the footprint.
+ // Do a minimum number of major collections first.
+ // Have reasonable averages for major and minor collections costs.
+ if (UseAdaptiveSizePolicyFootprintGoal &&
+ young_gen_policy_is_ready() &&
+ avg_major_gc_cost()->average() >= 0.0 &&
+ avg_minor_gc_cost()->average() >= 0.0) {
+ size_t desired_sum = desired_eden_size + desired_promo_size;
+ desired_eden_size = adjust_eden_for_footprint(desired_eden_size, desired_sum);
+ }
+ }
+
+ // Note we make the same tests as in the code block below; the code
+ // seems a little easier to read with the printing in another block.
+ if (PrintAdaptiveSizePolicy) {
+ if (desired_eden_size > eden_limit) {
+ gclog_or_tty->print_cr(
+ "PSAdaptiveSizePolicy::compute_eden_space_size limits:"
+ " desired_eden_size: " SIZE_FORMAT
+ " old_eden_size: " SIZE_FORMAT
+ " eden_limit: " SIZE_FORMAT
+ " cur_eden: " SIZE_FORMAT
+ " max_eden_size: " SIZE_FORMAT
+ " avg_young_live: " SIZE_FORMAT,
+ desired_eden_size, _eden_size, eden_limit, cur_eden,
+ max_eden_size, (size_t)avg_young_live()->average());
+ }
+ if (gc_cost() > gc_cost_limit) {
+ gclog_or_tty->print_cr(
+ "PSAdaptiveSizePolicy::compute_eden_space_size: gc time limit"
+ " gc_cost: %f "
+ " GCTimeLimit: %d",
+ gc_cost(), GCTimeLimit);
+ }
+ }
+
+ // Align everything and make a final limit check
+ const size_t alignment = _intra_generation_alignment;
+ desired_eden_size = align_size_up(desired_eden_size, alignment);
+ desired_eden_size = MAX2(desired_eden_size, alignment);
+
+ eden_limit = align_size_down(eden_limit, alignment);
+
+ // And one last limit check, now that we've aligned things.
+ if (desired_eden_size > eden_limit) {
+ // If the policy says to get a larger eden but
+ // is hitting the limit, don't decrease eden.
+ // This can lead to a general drifting down of the
+ // eden size. Let the tenuring calculation push more
+ // into the old gen.
+ desired_eden_size = MAX2(eden_limit, cur_eden);
+ }
+
+ if (PrintAdaptiveSizePolicy) {
+ // Timing stats
+ gclog_or_tty->print(
+ "PSAdaptiveSizePolicy::compute_eden_space_size: costs"
+ " minor_time: %f"
+ " major_cost: %f"
+ " mutator_cost: %f"
+ " throughput_goal: %f",
+ minor_gc_cost(), major_gc_cost(), mutator_cost(),
+ _throughput_goal);
+
+ // We give more details if Verbose is set
+ if (Verbose) {
+ gclog_or_tty->print( " minor_pause: %f"
+ " major_pause: %f"
+ " minor_interval: %f"
+ " major_interval: %f"
+ " pause_goal: %f",
+ _avg_minor_pause->padded_average(),
+ _avg_major_pause->padded_average(),
+ _avg_minor_interval->average(),
+ _avg_major_interval->average(),
+ gc_pause_goal_sec());
+ }
+
+ // Footprint stats
+ gclog_or_tty->print( " live_space: " SIZE_FORMAT
+ " free_space: " SIZE_FORMAT,
+ live_space(), free_space());
+ // More detail
+ if (Verbose) {
+ gclog_or_tty->print( " base_footprint: " SIZE_FORMAT
+ " avg_young_live: " SIZE_FORMAT
+ " avg_old_live: " SIZE_FORMAT,
+ (size_t)_avg_base_footprint->average(),
+ (size_t)avg_young_live()->average(),
+ (size_t)avg_old_live()->average());
+ }
+
+ // And finally, our old and new sizes.
+ gclog_or_tty->print(" old_eden_size: " SIZE_FORMAT
+ " desired_eden_size: " SIZE_FORMAT,
+ _eden_size, desired_eden_size);
+ gclog_or_tty->cr();
+ }
+
+ set_eden_size(desired_eden_size);
+}
+
+void PSAdaptiveSizePolicy::compute_old_gen_free_space(
+ size_t old_live,
+ size_t cur_eden,
+ size_t max_old_gen_size,
+ bool is_full_gc) {
+
+ // Update statistics
+ // Time statistics are updated as we go, update footprint stats here
if (is_full_gc) {
// old_live is only accurate after a full gc
avg_old_live()->sample(old_live);
@@ -242,32 +459,14 @@
// some case but is dangerous.
size_t desired_eden_size = cur_eden;
-#ifdef ASSERT
- size_t original_promo_size = desired_promo_size;
- size_t original_eden_size = desired_eden_size;
-#endif
-
// Cache some values. There's a bit of work getting these, so
// we might save a little time.
const double major_cost = major_gc_cost();
const double minor_cost = minor_gc_cost();
- // Used for diagnostics
- clear_generation_free_space_flags();
-
// Limits on our growth
size_t promo_limit = (size_t)(max_old_gen_size - avg_old_live()->average());
- // This method sets the desired eden size. That plus the
- // desired survivor space sizes sets the desired young generation
- // size. This methods does not know what the desired survivor
- // size is but expects that other policy will attempt to make
- // the survivor sizes compatible with the live data in the
- // young generation. This limit is an estimate of the space left
- // in the young generation after the survivor spaces have been
- // subtracted out.
- size_t eden_limit = max_eden_size;
-
// But don't force a promo size below the current promo size. Otherwise,
// the promo size will shrink for no good reason.
promo_limit = MAX2(promo_limit, _promo_size);
@@ -290,7 +489,6 @@
// a change less than the necessary alignment is probably not worth
// attempting.
-
if ((_avg_minor_pause->padded_average() > gc_pause_goal_sec()) ||
(_avg_major_pause->padded_average() > gc_pause_goal_sec())) {
//
@@ -298,12 +496,13 @@
//
// Make changes only to affect one of the pauses (the larger)
// at a time.
- adjust_for_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size);
-
+ if (is_full_gc) {
+ set_decide_at_full_gc(decide_at_full_gc_true);
+ adjust_promo_for_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size);
+ }
} else if (_avg_minor_pause->padded_average() > gc_minor_pause_goal_sec()) {
// Adjust only for the minor pause time goal
- adjust_for_minor_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size);
-
+ adjust_promo_for_minor_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size);
} else if(adjusted_mutator_cost() < _throughput_goal) {
// This branch used to require that (mutator_cost() > 0.0 in 1.4.2.
// This sometimes resulted in skipping to the minimize footprint
@@ -316,8 +515,10 @@
assert(major_cost >= 0.0, "major cost is < 0.0");
assert(minor_cost >= 0.0, "minor cost is < 0.0");
// Try to reduce the GC times.
- adjust_for_throughput(is_full_gc, &desired_promo_size, &desired_eden_size);
-
+ if (is_full_gc) {
+ set_decide_at_full_gc(decide_at_full_gc_true);
+ adjust_promo_for_throughput(is_full_gc, &desired_promo_size);
+ }
} else {
// Be conservative about reducing the footprint.
@@ -327,13 +528,10 @@
young_gen_policy_is_ready() &&
avg_major_gc_cost()->average() >= 0.0 &&
avg_minor_gc_cost()->average() >= 0.0) {
- size_t desired_sum = desired_eden_size + desired_promo_size;
- desired_eden_size = adjust_eden_for_footprint(desired_eden_size,
- desired_sum);
if (is_full_gc) {
set_decide_at_full_gc(decide_at_full_gc_true);
- desired_promo_size = adjust_promo_for_footprint(desired_promo_size,
- desired_sum);
+ size_t desired_sum = desired_eden_size + desired_promo_size;
+ desired_promo_size = adjust_promo_for_footprint(desired_promo_size, desired_sum);
}
}
}
@@ -345,7 +543,7 @@
// "free_in_old_gen" was the original value for used for promo_limit
size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average());
gclog_or_tty->print_cr(
- "PSAdaptiveSizePolicy::compute_generation_free_space limits:"
+ "PSAdaptiveSizePolicy::compute_old_gen_free_space limits:"
" desired_promo_size: " SIZE_FORMAT
" promo_limit: " SIZE_FORMAT
" free_in_old_gen: " SIZE_FORMAT
@@ -354,21 +552,9 @@
desired_promo_size, promo_limit, free_in_old_gen,
max_old_gen_size, (size_t) avg_old_live()->average());
}
- if (desired_eden_size > eden_limit) {
- gclog_or_tty->print_cr(
- "AdaptiveSizePolicy::compute_generation_free_space limits:"
- " desired_eden_size: " SIZE_FORMAT
- " old_eden_size: " SIZE_FORMAT
- " eden_limit: " SIZE_FORMAT
- " cur_eden: " SIZE_FORMAT
- " max_eden_size: " SIZE_FORMAT
- " avg_young_live: " SIZE_FORMAT,
- desired_eden_size, _eden_size, eden_limit, cur_eden,
- max_eden_size, (size_t)avg_young_live()->average());
- }
if (gc_cost() > gc_cost_limit) {
gclog_or_tty->print_cr(
- "AdaptiveSizePolicy::compute_generation_free_space: gc time limit"
+ "PSAdaptiveSizePolicy::compute_old_gen_free_space: gc time limit"
" gc_cost: %f "
" GCTimeLimit: %d",
gc_cost(), GCTimeLimit);
@@ -377,46 +563,18 @@
// Align everything and make a final limit check
const size_t alignment = _intra_generation_alignment;
- desired_eden_size = align_size_up(desired_eden_size, alignment);
- desired_eden_size = MAX2(desired_eden_size, alignment);
desired_promo_size = align_size_up(desired_promo_size, alignment);
desired_promo_size = MAX2(desired_promo_size, alignment);
- eden_limit = align_size_down(eden_limit, alignment);
promo_limit = align_size_down(promo_limit, alignment);
- // Is too much time being spent in GC?
- // Is the heap trying to grow beyond it's limits?
-
- const size_t free_in_old_gen =
- (size_t)(max_old_gen_size - avg_old_live()->average());
- if (desired_promo_size > free_in_old_gen && desired_eden_size > eden_limit) {
- check_gc_overhead_limit(young_live,
- eden_live,
- max_old_gen_size,
- max_eden_size,
- is_full_gc,
- gc_cause,
- collector_policy);
- }
-
-
// And one last limit check, now that we've aligned things.
- if (desired_eden_size > eden_limit) {
- // If the policy says to get a larger eden but
- // is hitting the limit, don't decrease eden.
- // This can lead to a general drifting down of the
- // eden size. Let the tenuring calculation push more
- // into the old gen.
- desired_eden_size = MAX2(eden_limit, cur_eden);
- }
desired_promo_size = MIN2(desired_promo_size, promo_limit);
-
if (PrintAdaptiveSizePolicy) {
// Timing stats
gclog_or_tty->print(
- "PSAdaptiveSizePolicy::compute_generation_free_space: costs"
+ "PSAdaptiveSizePolicy::compute_old_gen_free_space: costs"
" minor_time: %f"
" major_cost: %f"
" mutator_cost: %f"
@@ -454,19 +612,13 @@
// And finally, our old and new sizes.
gclog_or_tty->print(" old_promo_size: " SIZE_FORMAT
- " old_eden_size: " SIZE_FORMAT
- " desired_promo_size: " SIZE_FORMAT
- " desired_eden_size: " SIZE_FORMAT,
- _promo_size, _eden_size,
- desired_promo_size, desired_eden_size);
+ " desired_promo_size: " SIZE_FORMAT,
+ _promo_size, desired_promo_size);
gclog_or_tty->cr();
}
- decay_supplemental_growth(is_full_gc);
-
set_promo_size(desired_promo_size);
- set_eden_size(desired_eden_size);
-};
+}
void PSAdaptiveSizePolicy::decay_supplemental_growth(bool is_full_gc) {
// Decay the supplemental increment? Decay the supplement growth
@@ -490,9 +642,39 @@
}
}
-void PSAdaptiveSizePolicy::adjust_for_minor_pause_time(bool is_full_gc,
+void PSAdaptiveSizePolicy::adjust_promo_for_minor_pause_time(bool is_full_gc,
size_t* desired_promo_size_ptr, size_t* desired_eden_size_ptr) {
+ if (PSAdjustTenuredGenForMinorPause) {
+ if (is_full_gc) {
+ set_decide_at_full_gc(decide_at_full_gc_true);
+ }
+ // If the desired eden size is as small as it will get,
+ // try to adjust the old gen size.
+ if (*desired_eden_size_ptr <= _intra_generation_alignment) {
+ // Vary the old gen size to reduce the young gen pause. This
+ // may not be a good idea. This is just a test.
+ if (minor_pause_old_estimator()->decrement_will_decrease()) {
+ set_change_old_gen_for_min_pauses(decrease_old_gen_for_min_pauses_true);
+ *desired_promo_size_ptr =
+ _promo_size - promo_decrement_aligned_down(*desired_promo_size_ptr);
+ } else {
+ set_change_old_gen_for_min_pauses(increase_old_gen_for_min_pauses_true);
+ size_t promo_heap_delta =
+ promo_increment_with_supplement_aligned_up(*desired_promo_size_ptr);
+ if ((*desired_promo_size_ptr + promo_heap_delta) >
+ *desired_promo_size_ptr) {
+ *desired_promo_size_ptr =
+ _promo_size + promo_heap_delta;
+ }
+ }
+ }
+ }
+}
+
+void PSAdaptiveSizePolicy::adjust_eden_for_minor_pause_time(bool is_full_gc,
+ size_t* desired_eden_size_ptr) {
+
// Adjust the young generation size to reduce pause time of
// of collections.
//
@@ -512,49 +694,19 @@
set_change_young_gen_for_min_pauses(
increase_young_gen_for_min_pauses_true);
}
- if (PSAdjustTenuredGenForMinorPause) {
- // If the desired eden size is as small as it will get,
- // try to adjust the old gen size.
- if (*desired_eden_size_ptr <= _intra_generation_alignment) {
- // Vary the old gen size to reduce the young gen pause. This
- // may not be a good idea. This is just a test.
- if (minor_pause_old_estimator()->decrement_will_decrease()) {
- set_change_old_gen_for_min_pauses(
- decrease_old_gen_for_min_pauses_true);
- *desired_promo_size_ptr =
- _promo_size - promo_decrement_aligned_down(*desired_promo_size_ptr);
- } else {
- set_change_old_gen_for_min_pauses(
- increase_old_gen_for_min_pauses_true);
- size_t promo_heap_delta =
- promo_increment_with_supplement_aligned_up(*desired_promo_size_ptr);
- if ((*desired_promo_size_ptr + promo_heap_delta) >
- *desired_promo_size_ptr) {
- *desired_promo_size_ptr =
- _promo_size + promo_heap_delta;
- }
- }
- }
- }
}
-void PSAdaptiveSizePolicy::adjust_for_pause_time(bool is_full_gc,
+void PSAdaptiveSizePolicy::adjust_promo_for_pause_time(bool is_full_gc,
size_t* desired_promo_size_ptr,
size_t* desired_eden_size_ptr) {
size_t promo_heap_delta = 0;
- size_t eden_heap_delta = 0;
- // Add some checks for a threshhold for a change. For example,
+ // Add some checks for a threshold for a change. For example,
// a change less than the required alignment is probably not worth
// attempting.
- if (is_full_gc) {
- set_decide_at_full_gc(decide_at_full_gc_true);
- }
if (_avg_minor_pause->padded_average() > _avg_major_pause->padded_average()) {
- adjust_for_minor_pause_time(is_full_gc,
- desired_promo_size_ptr,
- desired_eden_size_ptr);
+ adjust_promo_for_minor_pause_time(is_full_gc, desired_promo_size_ptr, desired_eden_size_ptr);
// major pause adjustments
} else if (is_full_gc) {
// Adjust for the major pause time only at full gc's because the
@@ -573,6 +725,33 @@
// promo_increment_aligned_up(*desired_promo_size_ptr);
set_change_old_gen_for_maj_pauses(increase_old_gen_for_maj_pauses_true);
}
+ }
+
+ if (PrintAdaptiveSizePolicy && Verbose) {
+ gclog_or_tty->print_cr(
+ "PSAdaptiveSizePolicy::compute_old_gen_free_space "
+ "adjusting gen sizes for major pause (avg %f goal %f). "
+ "desired_promo_size " SIZE_FORMAT " promo delta " SIZE_FORMAT,
+ _avg_major_pause->average(), gc_pause_goal_sec(),
+ *desired_promo_size_ptr, promo_heap_delta);
+ }
+}
+
+void PSAdaptiveSizePolicy::adjust_eden_for_pause_time(bool is_full_gc,
+ size_t* desired_promo_size_ptr,
+ size_t* desired_eden_size_ptr) {
+
+ size_t eden_heap_delta = 0;
+ // Add some checks for a threshold for a change. For example,
+ // a change less than the required alignment is probably not worth
+ // attempting.
+ if (_avg_minor_pause->padded_average() > _avg_major_pause->padded_average()) {
+ adjust_eden_for_minor_pause_time(is_full_gc,
+ desired_eden_size_ptr);
+ // major pause adjustments
+ } else if (is_full_gc) {
+ // Adjust for the major pause time only at full gc's because the
+ // affects of a change can only be seen at full gc's.
if (PSAdjustYoungGenForMajorPause) {
// If the promo size is at the minimum (i.e., the old gen
// size will not actually decrease), consider changing the
@@ -607,43 +786,35 @@
if (PrintAdaptiveSizePolicy && Verbose) {
gclog_or_tty->print_cr(
- "AdaptiveSizePolicy::compute_generation_free_space "
+ "PSAdaptiveSizePolicy::compute_eden_space_size "
"adjusting gen sizes for major pause (avg %f goal %f). "
- "desired_promo_size " SIZE_FORMAT "desired_eden_size "
- SIZE_FORMAT
- " promo delta " SIZE_FORMAT " eden delta " SIZE_FORMAT,
+ "desired_eden_size " SIZE_FORMAT " eden delta " SIZE_FORMAT,
_avg_major_pause->average(), gc_pause_goal_sec(),
- *desired_promo_size_ptr, *desired_eden_size_ptr,
- promo_heap_delta, eden_heap_delta);
+ *desired_eden_size_ptr, eden_heap_delta);
}
}
-void PSAdaptiveSizePolicy::adjust_for_throughput(bool is_full_gc,
- size_t* desired_promo_size_ptr,
- size_t* desired_eden_size_ptr) {
+void PSAdaptiveSizePolicy::adjust_promo_for_throughput(bool is_full_gc,
+ size_t* desired_promo_size_ptr) {
- // Add some checks for a threshhold for a change. For example,
+ // Add some checks for a threshold for a change. For example,
// a change less than the required alignment is probably not worth
// attempting.
- if (is_full_gc) {
- set_decide_at_full_gc(decide_at_full_gc_true);
- }
if ((gc_cost() + mutator_cost()) == 0.0) {
return;
}
if (PrintAdaptiveSizePolicy && Verbose) {
- gclog_or_tty->print("\nPSAdaptiveSizePolicy::adjust_for_throughput("
- "is_full: %d, promo: " SIZE_FORMAT ", cur_eden: " SIZE_FORMAT "): ",
- is_full_gc, *desired_promo_size_ptr, *desired_eden_size_ptr);
+ gclog_or_tty->print("\nPSAdaptiveSizePolicy::adjust_promo_for_throughput("
+ "is_full: %d, promo: " SIZE_FORMAT "): ",
+ is_full_gc, *desired_promo_size_ptr);
gclog_or_tty->print_cr("mutator_cost %f major_gc_cost %f "
"minor_gc_cost %f", mutator_cost(), major_gc_cost(), minor_gc_cost());
}
// Tenured generation
if (is_full_gc) {
-
// Calculate the change to use for the tenured gen.
size_t scaled_promo_heap_delta = 0;
// Can the increment to the generation be scaled?
@@ -720,6 +891,26 @@
*desired_promo_size_ptr, scaled_promo_heap_delta);
}
}
+}
+
+void PSAdaptiveSizePolicy::adjust_eden_for_throughput(bool is_full_gc,
+ size_t* desired_eden_size_ptr) {
+
+ // Add some checks for a threshold for a change. For example,
+ // a change less than the required alignment is probably not worth
+ // attempting.
+
+ if ((gc_cost() + mutator_cost()) == 0.0) {
+ return;
+ }
+
+ if (PrintAdaptiveSizePolicy && Verbose) {
+ gclog_or_tty->print("\nPSAdaptiveSizePolicy::adjust_eden_for_throughput("
+ "is_full: %d, cur_eden: " SIZE_FORMAT "): ",
+ is_full_gc, *desired_eden_size_ptr);
+ gclog_or_tty->print_cr("mutator_cost %f major_gc_cost %f "
+ "minor_gc_cost %f", mutator_cost(), major_gc_cost(), minor_gc_cost());
+ }
// Young generation
size_t scaled_eden_heap_delta = 0;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Fri May 17 08:00:01 2013 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -136,18 +136,24 @@
double gc_minor_pause_goal_sec() const { return _gc_minor_pause_goal_sec; }
// Change the young generation size to achieve a minor GC pause time goal
- void adjust_for_minor_pause_time(bool is_full_gc,
+ void adjust_promo_for_minor_pause_time(bool is_full_gc,
size_t* desired_promo_size_ptr,
size_t* desired_eden_size_ptr);
+ void adjust_eden_for_minor_pause_time(bool is_full_gc,
+ size_t* desired_eden_size_ptr);
// Change the generation sizes to achieve a GC pause time goal
// Returned sizes are not necessarily aligned.
- void adjust_for_pause_time(bool is_full_gc,
+ void adjust_promo_for_pause_time(bool is_full_gc,
+ size_t* desired_promo_size_ptr,
+ size_t* desired_eden_size_ptr);
+ void adjust_eden_for_pause_time(bool is_full_gc,
size_t* desired_promo_size_ptr,
size_t* desired_eden_size_ptr);
// Change the generation sizes to achieve an application throughput goal
// Returned sizes are not necessarily aligned.
- void adjust_for_throughput(bool is_full_gc,
- size_t* desired_promo_size_ptr,
+ void adjust_promo_for_throughput(bool is_full_gc,
+ size_t* desired_promo_size_ptr);
+ void adjust_eden_for_throughput(bool is_full_gc,
size_t* desired_eden_size_ptr);
// Change the generation sizes to achieve minimum footprint
// Returned sizes are not aligned.
@@ -168,9 +174,6 @@
size_t promo_decrement_aligned_down(size_t cur_promo);
size_t promo_increment_with_supplement_aligned_up(size_t cur_promo);
- // Decay the supplemental growth additive.
- void decay_supplemental_growth(bool is_full_gc);
-
// Returns a change that has been scaled down. Result
// is not aligned. (If useful, move to some shared
// location.)
@@ -336,7 +339,7 @@
// perform a Full GC?
bool should_full_GC(size_t live_in_old_gen);
- // Calculates optimial free space sizes for both the old and young
+ // Calculates optimal (free) space sizes for both the young and old
// generations. Stores results in _eden_size and _promo_size.
// Takes current used space in all generations as input, as well
// as an indication if a full gc has just been performed, for use
@@ -347,9 +350,18 @@
size_t cur_eden, // current eden in bytes
size_t max_old_gen_size,
size_t max_eden_size,
- bool is_full_gc,
- GCCause::Cause gc_cause,
- CollectorPolicy* collector_policy);
+ bool is_full_gc);
+
+ void compute_eden_space_size(size_t young_live,
+ size_t eden_live,
+ size_t cur_eden, // current eden in bytes
+ size_t max_eden_size,
+ bool is_full_gc);
+
+ void compute_old_gen_free_space(size_t old_live,
+ size_t cur_eden, // current eden in bytes
+ size_t max_old_gen_size,
+ bool is_full_gc);
// Calculates new survivor space size; returns a new tenuring threshold
// value. Stores new survivor size in _survivor_size.
@@ -390,6 +402,9 @@
// Printing support
virtual bool print_adaptive_size_policy_on(outputStream* st) const;
+
+ // Decay the supplemental growth additive.
+ void decay_supplemental_growth(bool is_full_gc);
};
#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSADAPTIVESIZEPOLICY_HPP
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri May 17 08:00:01 2013 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -92,8 +92,8 @@
const bool clear_all_soft_refs =
heap->collector_policy()->should_clear_all_soft_refs();
- int count = (maximum_heap_compaction)?1:MarkSweepAlwaysCompactCount;
- IntFlagSetting flag_setting(MarkSweepAlwaysCompactCount, count);
+ uint count = maximum_heap_compaction ? 1 : MarkSweepAlwaysCompactCount;
+ UIntFlagSetting flag_setting(MarkSweepAlwaysCompactCount, count);
PSMarkSweep::invoke_no_policy(clear_all_soft_refs || maximum_heap_compaction);
}
@@ -277,18 +277,36 @@
young_gen->from_space()->capacity_in_bytes() +
young_gen->to_space()->capacity_in_bytes(),
"Sizes of space in young gen are out-of-bounds");
+
+ size_t young_live = young_gen->used_in_bytes();
+ size_t eden_live = young_gen->eden_space()->used_in_bytes();
+ size_t old_live = old_gen->used_in_bytes();
+ size_t cur_eden = young_gen->eden_space()->capacity_in_bytes();
+ size_t max_old_gen_size = old_gen->max_gen_size();
size_t max_eden_size = young_gen->max_size() -
young_gen->from_space()->capacity_in_bytes() -
young_gen->to_space()->capacity_in_bytes();
- size_policy->compute_generation_free_space(young_gen->used_in_bytes(),
- young_gen->eden_space()->used_in_bytes(),
- old_gen->used_in_bytes(),
- young_gen->eden_space()->capacity_in_bytes(),
- old_gen->max_gen_size(),
- max_eden_size,
- true /* full gc*/,
- gc_cause,
- heap->collector_policy());
+
+ // Used for diagnostics
+ size_policy->clear_generation_free_space_flags();
+
+ size_policy->compute_generation_free_space(young_live,
+ eden_live,
+ old_live,
+ cur_eden,
+ max_old_gen_size,
+ max_eden_size,
+ true /* full gc*/);
+
+ size_policy->check_gc_overhead_limit(young_live,
+ eden_live,
+ max_old_gen_size,
+ max_eden_size,
+ true /* full gc*/,
+ gc_cause,
+ heap->collector_policy());
+
+ size_policy->decay_supplemental_growth(true /* full gc*/);
heap->resize_old_gen(size_policy->calculated_old_free_size_in_bytes());
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp Fri May 17 08:00:01 2013 +0200
@@ -88,8 +88,7 @@
* by the MarkSweepAlwaysCompactCount parameter. This is a significant
* performance improvement!
*/
- bool skip_dead = (MarkSweepAlwaysCompactCount < 1)
- || ((PSMarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0);
+ bool skip_dead = ((PSMarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0);
size_t allowed_deadspace = 0;
if (skip_dead) {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri May 17 08:00:01 2013 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -948,7 +948,6 @@
pre_gc_values->fill(heap);
- NOT_PRODUCT(_mark_bitmap.reset_counters());
DEBUG_ONLY(add_obj_count = add_obj_size = 0;)
DEBUG_ONLY(mark_bitmap_count = mark_bitmap_size = 0;)
@@ -2042,15 +2041,6 @@
marking_start.update();
marking_phase(vmthread_cm, maximum_heap_compaction);
-#ifndef PRODUCT
- if (TraceParallelOldGCMarkingPhase) {
- gclog_or_tty->print_cr("marking_phase: cas_tries %d cas_retries %d "
- "cas_by_another %d",
- mark_bitmap()->cas_tries(), mark_bitmap()->cas_retries(),
- mark_bitmap()->cas_by_another());
- }
-#endif // #ifndef PRODUCT
-
bool max_on_system_gc = UseMaximumCompactionOnSystemGC
&& gc_cause == GCCause::_java_lang_system_gc;
summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
@@ -2094,19 +2084,36 @@
young_gen->from_space()->capacity_in_bytes() +
young_gen->to_space()->capacity_in_bytes(),
"Sizes of space in young gen are out-of-bounds");
+
+ size_t young_live = young_gen->used_in_bytes();
+ size_t eden_live = young_gen->eden_space()->used_in_bytes();
+ size_t old_live = old_gen->used_in_bytes();
+ size_t cur_eden = young_gen->eden_space()->capacity_in_bytes();
+ size_t max_old_gen_size = old_gen->max_gen_size();
size_t max_eden_size = young_gen->max_size() -
young_gen->from_space()->capacity_in_bytes() -
young_gen->to_space()->capacity_in_bytes();
- size_policy->compute_generation_free_space(
- young_gen->used_in_bytes(),
- young_gen->eden_space()->used_in_bytes(),
- old_gen->used_in_bytes(),
- young_gen->eden_space()->capacity_in_bytes(),
- old_gen->max_gen_size(),
- max_eden_size,
- true /* full gc*/,
- gc_cause,
- heap->collector_policy());
+
+ // Used for diagnostics
+ size_policy->clear_generation_free_space_flags();
+
+ size_policy->compute_generation_free_space(young_live,
+ eden_live,
+ old_live,
+ cur_eden,
+ max_old_gen_size,
+ max_eden_size,
+ true /* full gc*/);
+
+ size_policy->check_gc_overhead_limit(young_live,
+ eden_live,
+ max_old_gen_size,
+ max_eden_size,
+ true /* full gc*/,
+ gc_cause,
+ heap->collector_policy());
+
+ size_policy->decay_supplemental_growth(true /* full gc*/);
heap->resize_old_gen(
size_policy->calculated_old_free_size_in_bytes());
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri May 17 08:00:01 2013 +0200
@@ -552,19 +552,33 @@
young_gen->from_space()->capacity_in_bytes() +
young_gen->to_space()->capacity_in_bytes(),
"Sizes of space in young gen are out-of-bounds");
+
+ size_t young_live = young_gen->used_in_bytes();
+ size_t eden_live = young_gen->eden_space()->used_in_bytes();
+ size_t cur_eden = young_gen->eden_space()->capacity_in_bytes();
+ size_t max_old_gen_size = old_gen->max_gen_size();
size_t max_eden_size = young_gen->max_size() -
young_gen->from_space()->capacity_in_bytes() -
young_gen->to_space()->capacity_in_bytes();
- size_policy->compute_generation_free_space(young_gen->used_in_bytes(),
- young_gen->eden_space()->used_in_bytes(),
- old_gen->used_in_bytes(),
- young_gen->eden_space()->capacity_in_bytes(),
- old_gen->max_gen_size(),
- max_eden_size,
- false /* full gc*/,
- gc_cause,
- heap->collector_policy());
+
+ // Used for diagnostics
+ size_policy->clear_generation_free_space_flags();
+
+ size_policy->compute_eden_space_size(young_live,
+ eden_live,
+ cur_eden,
+ max_eden_size,
+ false /* not full gc*/);
+ size_policy->check_gc_overhead_limit(young_live,
+ eden_live,
+ max_old_gen_size,
+ max_eden_size,
+ false /* not full gc*/,
+ gc_cause,
+ heap->collector_policy());
+
+ size_policy->decay_supplemental_growth(false /* not full gc*/);
}
// Resize the young generation at every collection
// even if new sizes have not been calculated. This is
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp Fri May 17 08:00:01 2013 +0200
@@ -30,7 +30,7 @@
#include "oops/objArrayKlass.inline.hpp"
#include "oops/oop.inline.hpp"
-unsigned int MarkSweep::_total_invocations = 0;
+uint MarkSweep::_total_invocations = 0;
Stack<oop, mtGC> MarkSweep::_marking_stack;
Stack<ObjArrayTask, mtGC> MarkSweep::_objarray_stack;
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp Fri May 17 08:00:01 2013 +0200
@@ -113,7 +113,7 @@
//
protected:
// Total invocations of a MarkSweep collection
- static unsigned int _total_invocations;
+ static uint _total_invocations;
// Traversal stacks used during phase1
static Stack<oop, mtGC> _marking_stack;
@@ -147,7 +147,7 @@
static AdjustKlassClosure adjust_klass_closure;
// Accessors
- static unsigned int total_invocations() { return _total_invocations; }
+ static uint total_invocations() { return _total_invocations; }
// Reference Processing
static ReferenceProcessor* const ref_processor() { return _ref_processor; }
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp Fri May 17 08:00:01 2013 +0200
@@ -264,6 +264,27 @@
// need to do this again
MaxHeapSize = align_size_up(MaxHeapSize, max_alignment());
+ // adjust max heap size if necessary
+ if (NewSize + OldSize > MaxHeapSize) {
+ if (FLAG_IS_CMDLINE(MaxHeapSize)) {
+ // somebody set a maximum heap size with the intention that we should not
+ // exceed it. Adjust New/OldSize as necessary.
+ uintx calculated_size = NewSize + OldSize;
+ double shrink_factor = (double) MaxHeapSize / calculated_size;
+ // align
+ NewSize = align_size_down((uintx) (NewSize * shrink_factor), min_alignment());
+ // OldSize is already aligned because above we aligned MaxHeapSize to
+ // max_alignment(), and we just made sure that NewSize is aligned to
+ // min_alignment(). In initialize_flags() we verified that max_alignment()
+ // is a multiple of min_alignment().
+ OldSize = MaxHeapSize - NewSize;
+ } else {
+ MaxHeapSize = NewSize + OldSize;
+ }
+ }
+ // need to do this again
+ MaxHeapSize = align_size_up(MaxHeapSize, max_alignment());
+
always_do_update_barrier = UseConcMarkSweepGC;
// Check validity of heap flags
@@ -731,7 +752,7 @@
// free memory should be here, especially if they are expensive. If this
// attempt fails, an OOM exception will be thrown.
{
- IntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted
+ UIntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted
gch->do_collection(true /* full */,
true /* clear_all_soft_refs */,
--- a/hotspot/src/share/vm/memory/space.hpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/memory/space.hpp Fri May 17 08:00:01 2013 +0200
@@ -537,9 +537,8 @@
* Occasionally, we want to ensure a full compaction, which is determined \
* by the MarkSweepAlwaysCompactCount parameter. \
*/ \
- int invocations = MarkSweep::total_invocations(); \
- bool skip_dead = (MarkSweepAlwaysCompactCount < 1) \
- ||((invocations % MarkSweepAlwaysCompactCount) != 0); \
+ uint invocations = MarkSweep::total_invocations(); \
+ bool skip_dead = ((invocations % MarkSweepAlwaysCompactCount) != 0); \
\
size_t allowed_deadspace = 0; \
if (skip_dead) { \
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Fri May 17 08:00:01 2013 +0200
@@ -1919,7 +1919,7 @@
status = false;
}
- status = status && verify_percentage(AdaptiveSizePolicyWeight,
+ status = status && verify_interval(AdaptiveSizePolicyWeight, 0, 100,
"AdaptiveSizePolicyWeight");
status = status && verify_percentage(ThresholdTolerance, "ThresholdTolerance");
status = status && verify_percentage(MinHeapFreeRatio, "MinHeapFreeRatio");
@@ -1979,8 +1979,6 @@
FLAG_SET_DEFAULT(UseGCOverheadLimit, false);
}
- status = status && verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit");
-
status = status && check_gc_consistency();
status = status && check_stack_pages();
@@ -2074,6 +2072,52 @@
status = status && verify_interval(G1ConcRSLogCacheSize, 0, 31,
"G1ConcRSLogCacheSize");
}
+ if (UseConcMarkSweepGC) {
+ status = status && verify_min_value(CMSOldPLABNumRefills, 1, "CMSOldPLABNumRefills");
+ status = status && verify_min_value(CMSOldPLABToleranceFactor, 1, "CMSOldPLABToleranceFactor");
+ status = status && verify_min_value(CMSOldPLABMax, 1, "CMSOldPLABMax");
+ status = status && verify_interval(CMSOldPLABMin, 1, CMSOldPLABMax, "CMSOldPLABMin");
+
+ status = status && verify_min_value(CMSYoungGenPerWorker, 1, "CMSYoungGenPerWorker");
+
+ status = status && verify_min_value(CMSSamplingGrain, 1, "CMSSamplingGrain");
+ status = status && verify_interval(CMS_SweepWeight, 0, 100, "CMS_SweepWeight");
+ status = status && verify_interval(CMS_FLSWeight, 0, 100, "CMS_FLSWeight");
+
+ status = status && verify_interval(FLSCoalescePolicy, 0, 4, "FLSCoalescePolicy");
+
+ status = status && verify_min_value(CMSRescanMultiple, 1, "CMSRescanMultiple");
+ status = status && verify_min_value(CMSConcMarkMultiple, 1, "CMSConcMarkMultiple");
+
+ status = status && verify_interval(CMSPrecleanIter, 0, 9, "CMSPrecleanIter");
+ status = status && verify_min_value(CMSPrecleanDenominator, 1, "CMSPrecleanDenominator");
+ status = status && verify_interval(CMSPrecleanNumerator, 0, CMSPrecleanDenominator - 1, "CMSPrecleanNumerator");
+
+ status = status && verify_percentage(CMSBootstrapOccupancy, "CMSBootstrapOccupancy");
+
+ status = status && verify_min_value(CMSPrecleanThreshold, 100, "CMSPrecleanThreshold");
+
+ status = status && verify_percentage(CMSScheduleRemarkEdenPenetration, "CMSScheduleRemarkEdenPenetration");
+ status = status && verify_min_value(CMSScheduleRemarkSamplingRatio, 1, "CMSScheduleRemarkSamplingRatio");
+ status = status && verify_min_value(CMSBitMapYieldQuantum, 1, "CMSBitMapYieldQuantum");
+ status = status && verify_percentage(CMSTriggerRatio, "CMSTriggerRatio");
+ status = status && verify_percentage(CMSIsTooFullPercentage, "CMSIsTooFullPercentage");
+ }
+
+ if (UseParallelGC || UseParallelOldGC) {
+ status = status && verify_interval(ParallelOldDeadWoodLimiterMean, 0, 100, "ParallelOldDeadWoodLimiterMean");
+ status = status && verify_interval(ParallelOldDeadWoodLimiterStdDev, 0, 100, "ParallelOldDeadWoodLimiterStdDev");
+
+ status = status && verify_percentage(YoungGenerationSizeIncrement, "YoungGenerationSizeIncrement");
+ status = status && verify_percentage(TenuredGenerationSizeIncrement, "TenuredGenerationSizeIncrement");
+
+ status = status && verify_min_value(YoungGenerationSizeSupplementDecay, 1, "YoungGenerationSizeSupplementDecay");
+ status = status && verify_min_value(TenuredGenerationSizeSupplementDecay, 1, "TenuredGenerationSizeSupplementDecay");
+
+ status = status && verify_min_value(ParGCCardsPerStrideChunk, 1, "ParGCCardsPerStrideChunk");
+
+ status = status && verify_min_value(ParallelOldGCSplitInterval, 0, "ParallelOldGCSplitInterval");
+ }
#endif // INCLUDE_ALL_GCS
status = status && verify_interval(RefDiscoveryPolicy,
@@ -2093,7 +2137,42 @@
status = status && verify_interval(MarkStackSizeMax,
1, (max_jint - 1), "MarkStackSizeMax");
-
+ status = status && verify_interval(NUMAChunkResizeWeight, 0, 100, "NUMAChunkResizeWeight");
+
+ status = status && verify_min_value(LogEventsBufferEntries, 1, "LogEventsBufferEntries");
+
+ status = status && verify_min_value(HeapSizePerGCThread, (uintx) os::vm_page_size(), "HeapSizePerGCThread");
+
+ status = status && verify_min_value(GCTaskTimeStampEntries, 1, "GCTaskTimeStampEntries");
+
+ status = status && verify_percentage(ParallelGCBufferWastePct, "ParallelGCBufferWastePct");
+ status = status && verify_interval(TargetPLABWastePct, 1, 100, "TargetPLABWastePct");
+
+ status = status && verify_min_value(ParGCStridesPerThread, 1, "ParGCStridesPerThread");
+
+ status = status && verify_min_value(MinRAMFraction, 1, "MinRAMFraction");
+ status = status && verify_min_value(InitialRAMFraction, 1, "InitialRAMFraction");
+ status = status && verify_min_value(MaxRAMFraction, 1, "MaxRAMFraction");
+ status = status && verify_min_value(DefaultMaxRAMFraction, 1, "DefaultMaxRAMFraction");
+
+ status = status && verify_interval(AdaptiveTimeWeight, 0, 100, "AdaptiveTimeWeight");
+ status = status && verify_min_value(AdaptiveSizeDecrementScaleFactor, 1, "AdaptiveSizeDecrementScaleFactor");
+
+ status = status && verify_interval(TLABAllocationWeight, 0, 100, "TLABAllocationWeight");
+ status = status && verify_min_value(MinTLABSize, 1, "MinTLABSize");
+ status = status && verify_min_value(TLABRefillWasteFraction, 1, "TLABRefillWasteFraction");
+
+ status = status && verify_percentage(YoungGenerationSizeSupplement, "YoungGenerationSizeSupplement");
+ status = status && verify_percentage(TenuredGenerationSizeSupplement, "TenuredGenerationSizeSupplement");
+
+ // the "age" field in the oop header is 4 bits; do not want to pull in markOop.hpp
+ // just for that, so hardcode here.
+ status = status && verify_interval(MaxTenuringThreshold, 0, 15, "MaxTenuringThreshold");
+ status = status && verify_interval(InitialTenuringThreshold, 0, MaxTenuringThreshold, "MaxTenuringThreshold");
+ status = status && verify_percentage(TargetSurvivorRatio, "TargetSurvivorRatio");
+ status = status && verify_percentage(MarkSweepDeadRatio, "MarkSweepDeadRatio");
+
+ status = status && verify_min_value(MarkSweepAlwaysCompactCount, 1, "MarkSweepAlwaysCompactCount");
#ifdef SPARC
if (UseConcMarkSweepGC || UseG1GC) {
// Issue a stern warning if the user has explicitly set
@@ -3003,6 +3082,11 @@
set_mode_flags(_int);
}
+ // eventually fix up InitialTenuringThreshold if only MaxTenuringThreshold is set
+ if (FLAG_IS_DEFAULT(InitialTenuringThreshold) && (InitialTenuringThreshold > MaxTenuringThreshold)) {
+ FLAG_SET_ERGO(uintx, InitialTenuringThreshold, MaxTenuringThreshold);
+ }
+
#ifndef COMPILER2
// Don't degrade server performance for footprint
if (FLAG_IS_DEFAULT(UseLargePages) &&
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu May 16 13:47:55 2013 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Fri May 17 08:00:01 2013 +0200
@@ -286,12 +286,12 @@
};
-class IntFlagSetting {
- intx val;
- intx* flag;
+class UIntFlagSetting {
+ uintx val;
+ uintx* flag;
public:
- IntFlagSetting(intx& fl, intx newValue) { flag = &fl; val = fl; fl = newValue; }
- ~IntFlagSetting() { *flag = val; }
+ UIntFlagSetting(uintx& fl, uintx newValue) { flag = &fl; val = fl; fl = newValue; }
+ ~UIntFlagSetting() { *flag = val; }
};
@@ -513,12 +513,12 @@
product(bool, ForceNUMA, false, \
"Force NUMA optimizations on single-node/UMA systems") \
\
- product(intx, NUMAChunkResizeWeight, 20, \
- "Percentage (0-100) used to weight the current sample when " \
+ product(uintx, NUMAChunkResizeWeight, 20, \
+ "Percentage (0-100) used to weigh the current sample when " \
"computing exponentially decaying average for " \
"AdaptiveNUMAChunkSizing") \
\
- product(intx, NUMASpaceResizeRate, 1*G, \
+ product(uintx, NUMASpaceResizeRate, 1*G, \
"Do not reallocate more that this amount per collection") \
\
product(bool, UseAdaptiveNUMAChunkSizing, true, \
@@ -527,7 +527,7 @@
product(bool, NUMAStats, false, \
"Print NUMA stats in detailed heap information") \
\
- product(intx, NUMAPageScanRate, 256, \
+ product(uintx, NUMAPageScanRate, 256, \
"Maximum number of pages to include in the page scan procedure") \
\
product_pd(bool, NeedsDeoptSuspend, \
@@ -715,7 +715,7 @@
diagnostic(bool, LogEvents, true, \
"Enable the various ring buffer event logs") \
\
- diagnostic(intx, LogEventsBufferEntries, 10, \
+ diagnostic(uintx, LogEventsBufferEntries, 10, \
"Enable the various ring buffer event logs") \
\
product(bool, BytecodeVerificationRemote, true, \
@@ -1429,16 +1429,17 @@
product(bool, ParallelGCVerbose, false, \
"Verbose output for parallel GC.") \
\
- product(intx, ParallelGCBufferWastePct, 10, \
- "wasted fraction of parallel allocation buffer.") \
+ product(uintx, ParallelGCBufferWastePct, 10, \
+ "Wasted fraction of parallel allocation buffer.") \
\
diagnostic(bool, ParallelGCRetainPLAB, false, \
"Retain parallel allocation buffers across scavenges; " \
" -- disabled because this currently conflicts with " \
" parallel card scanning under certain conditions ") \
\
- product(intx, TargetPLABWastePct, 10, \
- "target wasted space in last buffer as pct of overall allocation")\
+ product(uintx, TargetPLABWastePct, 10, \
+ "Target wasted space in last buffer as percent of overall " \
+ "allocation") \
\
product(uintx, PLABWeight, 75, \
"Percentage (0-100) used to weight the current sample when" \
@@ -1516,7 +1517,7 @@
product(bool, AlwaysPreTouch, false, \
"It forces all freshly committed pages to be pre-touched.") \
\
- product_pd(intx, CMSYoungGenPerWorker, \
+ product_pd(uintx, CMSYoungGenPerWorker, \
"The maximum size of young gen chosen by default per GC worker " \
"thread available") \
\
@@ -1834,7 +1835,7 @@
product(bool, UseCMSInitiatingOccupancyOnly, false, \
"Only use occupancy as a crierion for starting a CMS collection") \
\
- product(intx, CMSIsTooFullPercentage, 98, \
+ product(uintx, CMSIsTooFullPercentage, 98, \
"An absolute ceiling above which CMS will always consider the " \
"unloading of classes when class unloading is enabled") \
\
@@ -1873,7 +1874,7 @@
develop(uintx, PromotionFailureALotInterval, 5, \
"Total collections between promotion failures alot") \
\
- experimental(intx, WorkStealingSleepMillis, 1, \
+ experimental(uintx, WorkStealingSleepMillis, 1, \
"Sleep time when sleep is used for yields") \
\
experimental(uintx, WorkStealingYieldsBeforeSleep, 5000, \
@@ -2017,7 +2018,7 @@
"Number of collections before the adaptive sizing is started") \
\
product(uintx, AdaptiveSizePolicyOutputInterval, 0, \
- "Collecton interval for printing information; zero => never") \
+ "Collection interval for printing information; zero means never") \
\
product(bool, UseAdaptiveSizePolicyFootprintGoal, true, \
"Use adaptive minimum footprint as a goal") \
@@ -3046,7 +3047,7 @@
product(uintx, MaxMetaspaceExpansion, ScaleForWordSize(4*M), \
"Max expansion of Metaspace without full GC (in bytes)") \
\
- product(intx, QueuedAllocationWarningCount, 0, \
+ product(uintx, QueuedAllocationWarningCount, 0, \
"Number of times an allocation that queues behind a GC " \
"will retry before printing a warning") \
\
@@ -3074,7 +3075,7 @@
"either completely full or completely empty. Par compact also" \
"has a smaller default value; see arguments.cpp.") \
\
- product(intx, MarkSweepAlwaysCompactCount, 4, \
+ product(uintx, MarkSweepAlwaysCompactCount, 4, \
"How often should we fully compact the heap (ignoring the dead " \
"space parameters)") \
\
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java Fri May 17 08:00:01 2013 +0200
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+ * @test TestCMSHeapSizeFlags
+ * @key gc
+ * @bug 8006088
+ * @summary Tests argument processing for initial and maximum heap size for the CMS collector
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestCMSHeapSizeFlags TestMaxHeapSizeTools
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm TestCMSHeapSizeFlags
+ * @author thomas.schatzl@oracle.com
+ */
+
+public class TestCMSHeapSizeFlags {
+
+ public static void main(String args[]) throws Exception {
+ final String gcName = "-XX:+UseConcMarkSweepGC";
+
+ TestMaxHeapSizeTools.checkMinInitialMaxHeapFlags(gcName);
+
+ TestMaxHeapSizeTools.checkGenMaxHeapErgo(gcName);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java Fri May 17 08:00:01 2013 +0200
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+ * @test TestG1HeapSizeFlags
+ * @key gc
+ * @bug 8006088
+ * @summary Tests argument processing for initial and maximum heap size for the G1 collector
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestG1HeapSizeFlags TestMaxHeapSizeTools
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm TestG1HeapSizeFlags
+ * @author thomas.schatzl@oracle.com
+ */
+
+public class TestG1HeapSizeFlags {
+
+ public static void main(String args[]) throws Exception {
+ final String gcName = "-XX:+UseG1GC";
+
+ TestMaxHeapSizeTools.checkMinInitialMaxHeapFlags(gcName);
+
+ TestMaxHeapSizeTools.checkGenMaxHeapErgo(gcName);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestInitialTenuringThreshold.java Fri May 17 08:00:01 2013 +0200
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+ * @test TestInitialTenuringThreshold
+ * @key gc
+ * @bug 8014765
+ * @summary Tests argument processing for initial tenuring threshold
+ * @library /testlibrary
+ * @run main/othervm TestInitialTenuringThreshold
+ * @author thomas.schatzl@oracle.com
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class TestInitialTenuringThreshold {
+
+ public static void runWithThresholds(int initial, int max, boolean shouldfail) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:InitialTenuringThreshold=" + String.valueOf(initial),
+ "-XX:MaxTenuringThreshold=" + String.valueOf(max),
+ "-version"
+ );
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ if (shouldfail) {
+ output.shouldHaveExitValue(1);
+ } else {
+ output.shouldHaveExitValue(0);
+ }
+ }
+
+
+ public static void main(String args[]) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ // some value below the default value of InitialTenuringThreshold of 7
+ "-XX:MaxTenuringThreshold=1",
+ "-version"
+ );
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+ // successful tests
+ runWithThresholds(0, 10, false);
+ runWithThresholds(5, 5, false);
+ // failing tests
+ runWithThresholds(10, 0, true);
+ runWithThresholds(9, 8, true);
+ runWithThresholds(-1, 8, true);
+ runWithThresholds(8, -1, true);
+ runWithThresholds(8, 16, true);
+ runWithThresholds(16, 8, true);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java Fri May 17 08:00:01 2013 +0200
@@ -0,0 +1,295 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+class ErgoArgsPrinter {
+ public static void main(String[] args) throws Exception {
+ WhiteBox wb = WhiteBox.getWhiteBox();
+ wb.printHeapSizes();
+ }
+}
+
+final class MinInitialMaxValues {
+ public long minHeapSize;
+ public long initialHeapSize;
+ public long maxHeapSize;
+
+ public long minAlignment;
+ public long maxAlignment;
+}
+
+class TestMaxHeapSizeTools {
+
+ public static void checkMinInitialMaxHeapFlags(String gcflag) throws Exception {
+ checkInvalidMinInitialHeapCombinations(gcflag);
+ checkValidMinInitialHeapCombinations(gcflag);
+ checkInvalidInitialMaxHeapCombinations(gcflag);
+ checkValidInitialMaxHeapCombinations(gcflag);
+ }
+
+ public static void checkMinInitialErgonomics(String gcflag) throws Exception {
+ // heap sizing ergonomics use the value NewSize + OldSize as default values
+ // for ergonomics calculation. Retrieve these values.
+ long[] values = new long[2];
+ getNewOldSize(gcflag, values);
+
+ // we check cases with values smaller and larger than this default value.
+ long newPlusOldSize = values[0] + values[1];
+ long smallValue = newPlusOldSize / 2;
+ long largeValue = newPlusOldSize * 2;
+
+ // -Xms is not set
+ checkErgonomics(new String[] { gcflag, "-Xmx16M" }, values, -1, -1);
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=0" }, values, -1, -1);
+
+ // -Xms is set to zero
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0" }, values, -1, -1);
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=0" }, values, -1, -1);
+
+ // -Xms is set to small value
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue }, values, -1, -1);
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, values, smallValue, -1);
+
+ // -Xms is set to large value
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue }, values, largeValue, largeValue);
+ // the next case has already been checked elsewhere and gives an error
+ // checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
+ // the next case has already been checked elsewhere too
+ // checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=" + largeValue }, values, values[0], largeValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, values, largeValue, -1);
+ }
+
+ private static long align_up(long value, long alignment) {
+ long alignmentMinusOne = alignment - 1;
+ return (value + alignmentMinusOne) & ~alignmentMinusOne;
+ }
+
+ private static void getNewOldSize(String gcflag, long[] values) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(gcflag,
+ "-XX:+PrintFlagsFinal", "-version");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+
+ String stdout = output.getStdout();
+ values[0] = getFlagValue(" NewSize", stdout);
+ values[1] = getFlagValue(" OldSize", stdout);
+ }
+
+ public static void checkGenMaxHeapErgo(String gcflag) throws Exception {
+ TestMaxHeapSizeTools.checkGenMaxHeapSize(gcflag, 3);
+ TestMaxHeapSizeTools.checkGenMaxHeapSize(gcflag, 4);
+ TestMaxHeapSizeTools.checkGenMaxHeapSize(gcflag, 5);
+ }
+
+ private static void checkInvalidMinInitialHeapCombinations(String gcflag) throws Exception {
+ expectError(new String[] { gcflag, "-Xms8M", "-XX:InitialHeapSize=4M", "-version" });
+ }
+
+ private static void checkValidMinInitialHeapCombinations(String gcflag) throws Exception {
+ expectValid(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-Xms4M", "-version" });
+ expectValid(new String[] { gcflag, "-Xms4M", "-XX:InitialHeapSize=8M", "-version" });
+ expectValid(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-Xms8M", "-version" });
+ // the following is not an error as -Xms sets both minimal and initial heap size
+ expectValid(new String[] { gcflag, "-XX:InitialHeapSize=4M", "-Xms8M", "-version" });
+ }
+
+ private static void checkInvalidInitialMaxHeapCombinations(String gcflag) throws Exception {
+ expectError(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:InitialHeapSize=8M", "-version" });
+ expectError(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-XX:MaxHeapSize=4M", "-version" });
+ }
+
+ private static void checkValidInitialMaxHeapCombinations(String gcflag) throws Exception {
+ expectValid(new String[] { gcflag, "-XX:InitialHeapSize=4M", "-XX:MaxHeapSize=8M", "-version" });
+ expectValid(new String[] { gcflag, "-XX:MaxHeapSize=8M", "-XX:InitialHeapSize=4M", "-version" });
+ expectValid(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:InitialHeapSize=4M", "-version" });
+ // a value of "0" for initial heap size means auto-detect
+ expectValid(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:InitialHeapSize=0M", "-version" });
+ }
+
+ private static long valueAfter(String source, String match) {
+ int start = source.indexOf(match) + match.length();
+ String tail = source.substring(start).split(" ")[0];
+ return Long.parseLong(tail);
+ }
+
+ /**
+ * Executes a new VM process with the given class and parameters.
+ * @param vmargs Arguments to the VM to run
+ * @param classname Name of the class to run
+ * @param arguments Arguments to the class
+ * @param useTestDotJavaDotOpts Use test.java.opts as part of the VM argument string
+ * @return The OutputAnalyzer with the results for the invocation.
+ */
+ public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, String[] arguments, boolean useTestDotJavaDotOpts) throws Exception {
+ ArrayList<String> finalargs = new ArrayList<String>();
+
+ String[] whiteboxOpts = new String[] {
+ "-Xbootclasspath/a:.",
+ "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
+ "-cp", System.getProperty("java.class.path"),
+ };
+
+ if (useTestDotJavaDotOpts) {
+ // System.getProperty("test.java.opts") is '' if no options is set,
+ // we need to skip such a result
+ String[] externalVMOpts = new String[0];
+ if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) {
+ externalVMOpts = System.getProperty("test.java.opts").split(" ");
+ }
+ finalargs.addAll(Arrays.asList(externalVMOpts));
+ }
+
+ finalargs.addAll(Arrays.asList(vmargs));
+ finalargs.addAll(Arrays.asList(whiteboxOpts));
+ finalargs.add(classname);
+ finalargs.addAll(Arrays.asList(arguments));
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+
+ return output;
+ }
+
+ private static void getMinInitialMaxHeap(String[] args, MinInitialMaxValues val) throws Exception {
+ OutputAnalyzer output = runWhiteBoxTest(args, ErgoArgsPrinter.class.getName(), new String[] {}, false);
+
+ // the output we watch for has the following format:
+ //
+ // "Minimum heap X Initial heap Y Maximum heap Z Min alignment A Max Alignment B"
+ //
+ // where A, B, X, Y and Z are sizes in bytes.
+ // Unfortunately there is no other way to retrieve the minimum heap size and
+ // the alignments.
+
+ Matcher m = Pattern.compile("Minimum heap \\d+ Initial heap \\d+ Maximum heap \\d+ Min alignment \\d+ Max alignment \\d+").
+ matcher(output.getStdout());
+ if (!m.find()) {
+ throw new RuntimeException("Could not find heap size string.");
+ }
+
+ String match = m.group();
+
+ // actual values
+ val.minHeapSize = valueAfter(match, "Minimum heap ");
+ val.initialHeapSize = valueAfter(match, "Initial heap ");
+ val.maxHeapSize = valueAfter(match, "Maximum heap ");
+ val.minAlignment = valueAfter(match, "Min alignment ");
+ val.maxAlignment = valueAfter(match, "Max alignment ");
+ }
+
+ /**
+ * Verify whether the VM automatically synchronizes minimum and initial heap size if only
+ * one is given for the GC specified.
+ */
+ public static void checkErgonomics(String[] args, long[] newoldsize,
+ long expectedMin, long expectedInitial) throws Exception {
+
+ MinInitialMaxValues v = new MinInitialMaxValues();
+ getMinInitialMaxHeap(args, v);
+
+ if ((expectedMin != -1) && (align_up(expectedMin, v.minAlignment) != v.minHeapSize)) {
+ throw new RuntimeException("Actual minimum heap size of " + v.minHeapSize +
+ " differs from expected minimum heap size of " + expectedMin);
+ }
+
+ if ((expectedInitial != -1) && (align_up(expectedInitial, v.minAlignment) != v.initialHeapSize)) {
+ throw new RuntimeException("Actual initial heap size of " + v.initialHeapSize +
+ " differs from expected initial heap size of " + expectedInitial);
+ }
+
+ // always check the invariant min <= initial <= max heap size
+ if (!(v.minHeapSize <= v.initialHeapSize && v.initialHeapSize <= v.maxHeapSize)) {
+ throw new RuntimeException("Inconsistent min/initial/max heap sizes, they are " +
+ v.minHeapSize + "/" + v.initialHeapSize + "/" + v.maxHeapSize);
+ }
+ }
+
+ /**
+ * Verify whether the VM respects the given maximum heap size in MB for the
+ * GC specified.
+ * @param gcflag The garbage collector to test as command line flag. E.g. -XX:+UseG1GC
+ * @param maxHeapSize the maximum heap size to verify, in MB.
+ */
+ public static void checkGenMaxHeapSize(String gcflag, long maxHeapsize) throws Exception {
+ final long K = 1024;
+
+ MinInitialMaxValues v = new MinInitialMaxValues();
+ getMinInitialMaxHeap(new String[] { gcflag, "-XX:MaxHeapSize=" + maxHeapsize + "M" }, v);
+
+ long expectedHeapSize = align_up(maxHeapsize * K * K, v.maxAlignment);
+ long actualHeapSize = v.maxHeapSize;
+
+ if (actualHeapSize > expectedHeapSize) {
+ throw new RuntimeException("Heap has " + actualHeapSize +
+ " bytes, expected to be less than " + expectedHeapSize);
+ }
+ }
+
+ private static long getFlagValue(String flag, String where) {
+ Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where);
+ if (!m.find()) {
+ throw new RuntimeException("Could not find value for flag " + flag + " in output string");
+ }
+ String match = m.group();
+ return Long.parseLong(match.substring(match.lastIndexOf(" ") + 1, match.length()));
+ }
+
+ private static void shouldContainOrNot(OutputAnalyzer output, boolean contains, String message) throws Exception {
+ if (contains) {
+ output.shouldContain(message);
+ } else {
+ output.shouldNotContain(message);
+ }
+ }
+
+ private static void expect(String[] flags, boolean hasWarning, boolean hasError, int errorcode) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(flags);
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ shouldContainOrNot(output, hasWarning, "Warning");
+ shouldContainOrNot(output, hasError, "Error");
+ output.shouldHaveExitValue(errorcode);
+ }
+
+ private static void expectError(String[] flags) throws Exception {
+ expect(flags, false, true, 1);
+ }
+
+ private static void expectValid(String[] flags) throws Exception {
+ expect(flags, false, false, 0);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestMinInitialErgonomics.java Fri May 17 08:00:01 2013 +0200
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/**
+ * @test TestMinInitialErgonomics
+ * @key gc
+ * @bug 8006088
+ * @summary Test ergonomics decisions related to minimum and initial heap size.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestMinInitialErgonomics TestMaxHeapSizeTools
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm TestMinInitialErgonomics
+ * @author thomas.schatzl@oracle.com
+ */
+
+public class TestMinInitialErgonomics {
+
+ public static void main(String args[]) throws Exception {
+ final String gcName = "-XX:+UseParallelGC";
+ // check ergonomic decisions about minimum and initial heap size in
+ // a single gc only as ergonomics are the same everywhere.
+ TestMaxHeapSizeTools.checkMinInitialErgonomics(gcName);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java Fri May 17 08:00:01 2013 +0200
@@ -0,0 +1,49 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+ * @test TestParallelHeapSizeFlags
+ * @key gc
+ * @bug 8006088
+ * @summary Tests argument processing for initial and maximum heap size for the
+ * parallel collectors.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestParallelHeapSizeFlags TestMaxHeapSizeTools
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm TestParallelHeapSizeFlags
+ * @author thomas.schatzl@oracle.com
+ */
+
+public class TestParallelHeapSizeFlags {
+
+ public static void main(String args[]) throws Exception {
+ // just pick one of the parallel generational collectors. Sizing logic is the
+ // same.
+ final String gcName = "-XX:+UseParallelOldGC";
+
+ TestMaxHeapSizeTools.checkMinInitialMaxHeapFlags(gcName);
+
+ TestMaxHeapSizeTools.checkGenMaxHeapErgo(gcName);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java Fri May 17 08:00:01 2013 +0200
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+ * @test TestSerialHeapSizeFlags
+ * @key gc
+ * @bug 8006088
+ * @summary Tests argument processing for initial and maximum heap size for the Serial collector
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestSerialHeapSizeFlags TestMaxHeapSizeTools
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm TestSerialHeapSizeFlags
+ * @author thomas.schatzl@oracle.com
+ */
+
+public class TestSerialHeapSizeFlags {
+
+ public static void main(String args[]) throws Exception {
+ final String gcName = "-XX:+UseSerialGC";
+
+ TestMaxHeapSizeTools.checkMinInitialMaxHeapFlags(gcName);
+
+ TestMaxHeapSizeTools.checkGenMaxHeapErgo(gcName);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestPrintGCDetails.java Fri May 17 08:00:01 2013 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestPrintGCDetails
+ * @bug 8010738
+ * @summary Ensure that the PrintGCDetails for a full GC with G1 includes Metaspace.
+ * @key gc
+ * @key regression
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+
+public class TestPrintGCDetails {
+ public static void main(String[] args) throws Exception {
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+ "-XX:+PrintGCDetails",
+ SystemGCTest.class.getName());
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ System.out.println("Output:\n" + output.getOutput());
+
+ output.shouldContain("Metaspace");
+ output.shouldHaveExitValue(0);
+ }
+
+ static class SystemGCTest {
+ public static void main(String [] args) {
+ System.out.println("Calling System.gc()");
+ System.gc();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/TestPrintRegionRememberedSetInfo.java Fri May 17 08:00:01 2013 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test TestPrintRegionRememberedSetInfo
+ * @key gc
+ * @bug 8014240
+ * @summary Test output of G1PrintRegionRememberedSetInfo
+ * @library /testlibrary
+ * @build TestPrintRegionRememberedSetInfo
+ * @author thomas.schatzl@oracle.com
+ */
+
+import com.oracle.java.testlibrary.*;
+import java.lang.Thread;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+class RunAndWaitForMarking {
+ public static void main(String[] args) {
+ System.gc();
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {
+ }
+ }
+}
+
+public class TestPrintRegionRememberedSetInfo {
+
+ public static String runTest(String arg) throws Exception {
+ ArrayList<String> finalargs = new ArrayList<String>();
+ String[] defaultArgs = new String[] {
+ "-XX:+UseG1GC",
+ "-Xmx10m",
+ "-XX:+ExplicitGCInvokesConcurrent",
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+G1PrintRegionLivenessInfo",
+ "-XX:G1HeapRegionSize=1M",
+ "-XX:InitiatingHeapOccupancyPercent=0",
+ };
+
+ finalargs.addAll(Arrays.asList(defaultArgs));
+ finalargs.add(arg);
+
+ finalargs.add(RunAndWaitForMarking.class.getName());
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ finalargs.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+
+ String result = output.getStdout();
+ return result;
+ }
+
+ public static void main(String[] args) throws Exception {
+ String result;
+
+ result = runTest("-XX:+G1PrintRegionLivenessInfo");
+ // check that we got region statistics output
+ if (result.indexOf("PHASE") == -1) {
+ throw new RuntimeException("Unexpected output from -XX:+PrintRegionLivenessInfo found.");
+ }
+
+ result = runTest("-XX:-G1PrintRegionLivenessInfo");
+ if (result.indexOf("remset") != -1) {
+ throw new RuntimeException("Should find remembered set information in output.");
+ }
+ }
+}
+