提交 6c7c728e 编写于 作者: J jcoomes

Merge

......@@ -81,7 +81,7 @@ inline void ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr,
size_t* marked_bytes_array,
BitMap* task_card_bm) {
G1CollectedHeap* g1h = _g1h;
CardTableModRefBS* ct_bs = (CardTableModRefBS*) (g1h->barrier_set());
CardTableModRefBS* ct_bs = g1h->g1_barrier_set();
HeapWord* start = mr.start();
HeapWord* end = mr.end();
......
......@@ -65,9 +65,7 @@ void G1CardCounts::initialize() {
// threshold limit is no more than this.
guarantee(G1ConcRSHotCardLimit <= max_jubyte, "sanity");
ModRefBarrierSet* bs = _g1h->mr_bs();
guarantee(bs->is_a(BarrierSet::CardTableModRef), "Precondition");
_ct_bs = (CardTableModRefBS*)bs;
_ct_bs = _g1h->g1_barrier_set();
_ct_bot = _ct_bs->byte_for_const(_g1h->reserved_region().start());
// Allocate/Reserve the counts table
......
......@@ -125,10 +125,8 @@ class ClearLoggedCardTableEntryClosure: public CardTableEntryClosure {
int _histo[256];
public:
ClearLoggedCardTableEntryClosure() :
_calls(0)
_calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set())
{
_g1h = G1CollectedHeap::heap();
_ctbs = (CardTableModRefBS*)_g1h->barrier_set();
for (int i = 0; i < 256; i++) _histo[i] = 0;
}
bool do_card_ptr(jbyte* card_ptr, int worker_i) {
......@@ -158,11 +156,8 @@ class RedirtyLoggedCardTableEntryClosure: public CardTableEntryClosure {
CardTableModRefBS* _ctbs;
public:
RedirtyLoggedCardTableEntryClosure() :
_calls(0)
{
_g1h = G1CollectedHeap::heap();
_ctbs = (CardTableModRefBS*)_g1h->barrier_set();
}
_calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set()) {}
bool do_card_ptr(jbyte* card_ptr, int worker_i) {
if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) {
_calls++;
......@@ -478,7 +473,7 @@ bool G1CollectedHeap::is_scavengable(const void* p) {
void G1CollectedHeap::check_ct_logs_at_safepoint() {
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
CardTableModRefBS* ct_bs = (CardTableModRefBS*)barrier_set();
CardTableModRefBS* ct_bs = g1_barrier_set();
// Count the dirty cards at the start.
CountNonCleanMemRegionClosure count1(this);
......@@ -1205,7 +1200,7 @@ public:
};
void G1CollectedHeap::clear_rsets_post_compaction() {
PostMCRemSetClearClosure rs_clear(this, mr_bs());
PostMCRemSetClearClosure rs_clear(this, g1_barrier_set());
heap_region_iterate(&rs_clear);
}
......@@ -1777,7 +1772,6 @@ void G1CollectedHeap::update_committed_space(HeapWord* old_end,
}
bool G1CollectedHeap::expand(size_t expand_bytes) {
size_t old_mem_size = _g1_storage.committed_size();
size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
aligned_expand_bytes = align_size_up(aligned_expand_bytes,
HeapRegion::GrainBytes);
......@@ -1787,6 +1781,13 @@ bool G1CollectedHeap::expand(size_t expand_bytes) {
ergo_format_byte("attempted expansion amount"),
expand_bytes, aligned_expand_bytes);
if (_g1_storage.uncommitted_size() == 0) {
ergo_verbose0(ErgoHeapSizing,
"did not expand the heap",
ergo_format_reason("heap already fully expanded"));
return false;
}
// First commit the memory.
HeapWord* old_end = (HeapWord*) _g1_storage.high();
bool successful = _g1_storage.expand_by(aligned_expand_bytes);
......@@ -1845,7 +1846,6 @@ bool G1CollectedHeap::expand(size_t expand_bytes) {
}
void G1CollectedHeap::shrink_helper(size_t shrink_bytes) {
size_t old_mem_size = _g1_storage.committed_size();
size_t aligned_shrink_bytes =
ReservedSpace::page_align_size_down(shrink_bytes);
aligned_shrink_bytes = align_size_down(aligned_shrink_bytes,
......@@ -2045,20 +2045,13 @@ jint G1CollectedHeap::initialize() {
// Create the gen rem set (and barrier set) for the entire reserved region.
_rem_set = collector_policy()->create_rem_set(_reserved, 2);
set_barrier_set(rem_set()->bs());
if (barrier_set()->is_a(BarrierSet::ModRef)) {
_mr_bs = (ModRefBarrierSet*)_barrier_set;
} else {
vm_exit_during_initialization("G1 requires a mod ref bs.");
if (!barrier_set()->is_a(BarrierSet::G1SATBCTLogging)) {
vm_exit_during_initialization("G1 requires a G1SATBLoggingCardTableModRefBS");
return JNI_ENOMEM;
}
// Also create a G1 rem set.
if (mr_bs()->is_a(BarrierSet::CardTableModRef)) {
_g1_rem_set = new G1RemSet(this, (CardTableModRefBS*)mr_bs());
} else {
vm_exit_during_initialization("G1 requires a cardtable mod ref bs.");
return JNI_ENOMEM;
}
_g1_rem_set = new G1RemSet(this, g1_barrier_set());
// Carve out the G1 part of the heap.
......@@ -3681,6 +3674,11 @@ void G1CollectedHeap::gc_prologue(bool full /* Ignored */) {
assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer");
// Fill TLAB's and such
ensure_parsability(true);
if (G1SummarizeRSetStats && (G1SummarizeRSetStatsPeriod > 0) &&
(total_collections() % G1SummarizeRSetStatsPeriod == 0)) {
g1_rem_set()->print_periodic_summary_info("Before GC RS summary");
}
}
void G1CollectedHeap::gc_epilogue(bool full /* Ignored */) {
......@@ -3689,7 +3687,7 @@ void G1CollectedHeap::gc_epilogue(bool full /* Ignored */) {
(G1SummarizeRSetStatsPeriod > 0) &&
// we are at the end of the GC. Total collections has already been increased.
((total_collections() - 1) % G1SummarizeRSetStatsPeriod == 0)) {
g1_rem_set()->print_periodic_summary_info();
g1_rem_set()->print_periodic_summary_info("After GC RS summary");
}
// FIXME: what is this about?
......@@ -4550,7 +4548,7 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num)
: _g1h(g1h),
_refs(g1h->task_queue(queue_num)),
_dcq(&g1h->dirty_card_queue_set()),
_ct_bs((CardTableModRefBS*)_g1h->barrier_set()),
_ct_bs(g1h->g1_barrier_set()),
_g1_rem(g1h->g1_rem_set()),
_hash_seed(17), _queue_num(queue_num),
_term_attempts(0),
......@@ -5979,11 +5977,11 @@ void G1CollectedHeap::update_sets_after_freeing_regions(size_t pre_used,
}
class G1ParCleanupCTTask : public AbstractGangTask {
CardTableModRefBS* _ct_bs;
G1SATBCardTableModRefBS* _ct_bs;
G1CollectedHeap* _g1h;
HeapRegion* volatile _su_head;
public:
G1ParCleanupCTTask(CardTableModRefBS* ct_bs,
G1ParCleanupCTTask(G1SATBCardTableModRefBS* ct_bs,
G1CollectedHeap* g1h) :
AbstractGangTask("G1 Par Cleanup CT Task"),
_ct_bs(ct_bs), _g1h(g1h) { }
......@@ -6006,9 +6004,9 @@ public:
#ifndef PRODUCT
class G1VerifyCardTableCleanup: public HeapRegionClosure {
G1CollectedHeap* _g1h;
CardTableModRefBS* _ct_bs;
G1SATBCardTableModRefBS* _ct_bs;
public:
G1VerifyCardTableCleanup(G1CollectedHeap* g1h, CardTableModRefBS* ct_bs)
G1VerifyCardTableCleanup(G1CollectedHeap* g1h, G1SATBCardTableModRefBS* ct_bs)
: _g1h(g1h), _ct_bs(ct_bs) { }
virtual bool doHeapRegion(HeapRegion* r) {
if (r->is_survivor()) {
......@@ -6022,7 +6020,7 @@ public:
void G1CollectedHeap::verify_not_dirty_region(HeapRegion* hr) {
// All of the region should be clean.
CardTableModRefBS* ct_bs = (CardTableModRefBS*)barrier_set();
G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
MemRegion mr(hr->bottom(), hr->end());
ct_bs->verify_not_dirty_region(mr);
}
......@@ -6035,13 +6033,13 @@ void G1CollectedHeap::verify_dirty_region(HeapRegion* hr) {
// not dirty that area (one less thing to have to do while holding
// a lock). So we can only verify that [bottom(),pre_dummy_top()]
// is dirty.
CardTableModRefBS* ct_bs = (CardTableModRefBS*) barrier_set();
G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
MemRegion mr(hr->bottom(), hr->pre_dummy_top());
ct_bs->verify_dirty_region(mr);
}
void G1CollectedHeap::verify_dirty_young_list(HeapRegion* head) {
CardTableModRefBS* ct_bs = (CardTableModRefBS*) barrier_set();
G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
for (HeapRegion* hr = head; hr != NULL; hr = hr->get_next_young_region()) {
verify_dirty_region(hr);
}
......@@ -6053,7 +6051,7 @@ void G1CollectedHeap::verify_dirty_young_regions() {
#endif
void G1CollectedHeap::cleanUpCardTable() {
CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set());
G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
double start = os::elapsedTime();
{
......
......@@ -31,6 +31,7 @@
#include "gc_implementation/g1/g1HRPrinter.hpp"
#include "gc_implementation/g1/g1MonitoringSupport.hpp"
#include "gc_implementation/g1/g1RemSet.hpp"
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#include "gc_implementation/g1/g1YCTypes.hpp"
#include "gc_implementation/g1/heapRegionSeq.hpp"
#include "gc_implementation/g1/heapRegionSets.hpp"
......@@ -791,8 +792,6 @@ protected:
// The g1 remembered set of the heap.
G1RemSet* _g1_rem_set;
// And it's mod ref barrier set, used to track updates for the above.
ModRefBarrierSet* _mr_bs;
// A set of cards that cover the objects for which the Rsets should be updated
// concurrently after the collection.
......@@ -1127,7 +1126,6 @@ public:
// The rem set and barrier set.
G1RemSet* g1_rem_set() const { return _g1_rem_set; }
ModRefBarrierSet* mr_bs() const { return _mr_bs; }
unsigned get_gc_time_stamp() {
return _gc_time_stamp;
......@@ -1346,6 +1344,10 @@ public:
virtual bool is_in_closed_subset(const void* p) const;
G1SATBCardTableModRefBS* g1_barrier_set() {
return (G1SATBCardTableModRefBS*) barrier_set();
}
// This resets the card table to all zeros. It is used after
// a collection pause which used the card table to claim cards.
void cleanUpCardTable();
......@@ -1875,7 +1877,7 @@ protected:
G1CollectedHeap* _g1h;
RefToScanQueue* _refs;
DirtyCardQueue _dcq;
CardTableModRefBS* _ct_bs;
G1SATBCardTableModRefBS* _ct_bs;
G1RemSet* _g1_rem;
G1ParGCAllocBufferContainer _surviving_alloc_buffer;
......@@ -1914,7 +1916,7 @@ protected:
void add_to_undo_waste(size_t waste) { _undo_waste += waste; }
DirtyCardQueue& dirty_card_queue() { return _dcq; }
CardTableModRefBS* ctbs() { return _ct_bs; }
G1SATBCardTableModRefBS* ctbs() { return _ct_bs; }
template <class T> void immediate_rs_update(HeapRegion* from, T* p, int tid) {
if (!from->is_survivor()) {
......
......@@ -134,7 +134,7 @@ G1CollectedHeap::dirty_young_block(HeapWord* start, size_t word_size) {
assert(containing_hr->is_in(end - 1), "it should also contain end - 1");
MemRegion mr(start, end);
((CardTableModRefBS*)_g1h->barrier_set())->dirty(mr);
g1_barrier_set()->dirty(mr);
}
inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const {
......
......@@ -41,11 +41,11 @@ class UpdateRSetDeferred : public OopsInHeapRegionClosure {
private:
G1CollectedHeap* _g1;
DirtyCardQueue *_dcq;
CardTableModRefBS* _ct_bs;
G1SATBCardTableModRefBS* _ct_bs;
public:
UpdateRSetDeferred(G1CollectedHeap* g1, DirtyCardQueue* dcq) :
_g1(g1), _ct_bs((CardTableModRefBS*)_g1->barrier_set()), _dcq(dcq) {}
_g1(g1), _ct_bs(_g1->g1_barrier_set()), _dcq(dcq) {}
virtual void do_oop(narrowOop* p) { do_oop_work(p); }
virtual void do_oop( oop* p) { do_oop_work(p); }
......
......@@ -220,7 +220,7 @@ class G1PrepareCompactClosure: public HeapRegionClosure {
public:
G1PrepareCompactClosure(CompactibleSpace* cs)
: _g1h(G1CollectedHeap::heap()),
_mrbs(G1CollectedHeap::heap()->mr_bs()),
_mrbs(_g1h->g1_barrier_set()),
_cp(NULL, cs, cs->initialize_threshold()),
_humongous_proxy_set("G1MarkSweep Humongous Proxy Set") { }
......
......@@ -83,7 +83,9 @@ G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
for (uint i = 0; i < n_workers(); i++) {
_cset_rs_update_cl[i] = NULL;
}
_prev_period_summary.initialize(this, n_workers());
if (G1SummarizeRSetStats) {
_prev_period_summary.initialize(this);
}
}
G1RemSet::~G1RemSet() {
......@@ -109,7 +111,7 @@ class ScanRSClosure : public HeapRegionClosure {
CodeBlobToOopClosure* _code_root_cl;
G1BlockOffsetSharedArray* _bot_shared;
CardTableModRefBS *_ct_bs;
G1SATBCardTableModRefBS *_ct_bs;
double _strong_code_root_scan_time_sec;
int _worker_i;
......@@ -130,7 +132,7 @@ public:
{
_g1h = G1CollectedHeap::heap();
_bot_shared = _g1h->bot_shared();
_ct_bs = (CardTableModRefBS*) (_g1h->barrier_set());
_ct_bs = _g1h->g1_barrier_set();
_block_size = MAX2<int>(G1RSetScanBlockSize, 1);
}
......@@ -505,12 +507,7 @@ public:
ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) :
_g1h(G1CollectedHeap::heap()),
_region_bm(region_bm), _card_bm(card_bm),
_ctbs(NULL)
{
ModRefBarrierSet* bs = _g1h->mr_bs();
guarantee(bs->is_a(BarrierSet::CardTableModRef), "Precondition");
_ctbs = (CardTableModRefBS*)bs;
}
_ctbs(_g1h->g1_barrier_set()) {}
bool doHeapRegion(HeapRegion* r) {
if (!r->continuesHumongous()) {
......@@ -731,19 +728,19 @@ bool G1RemSet::refine_card(jbyte* card_ptr, int worker_i,
return has_refs_into_cset;
}
void G1RemSet::print_periodic_summary_info() {
void G1RemSet::print_periodic_summary_info(const char* header) {
G1RemSetSummary current;
current.initialize(this, n_workers());
current.initialize(this);
_prev_period_summary.subtract_from(&current);
print_summary_info(&_prev_period_summary);
print_summary_info(&_prev_period_summary, header);
_prev_period_summary.set(&current);
}
void G1RemSet::print_summary_info() {
G1RemSetSummary current;
current.initialize(this, n_workers());
current.initialize(this);
print_summary_info(&current, " Cumulative RS summary");
}
......
......@@ -145,7 +145,7 @@ public:
virtual void print_summary_info();
// Print accumulated summary info from the last time called.
virtual void print_periodic_summary_info();
virtual void print_periodic_summary_info(const char* header);
// Prepare remembered set for verification.
virtual void prepare_for_verify();
......
......@@ -77,12 +77,12 @@ double G1RemSetSummary::rs_thread_vtime(uint thread) const {
return _rs_threads_vtimes[thread];
}
void G1RemSetSummary::initialize(G1RemSet* remset, uint num_workers) {
void G1RemSetSummary::initialize(G1RemSet* remset) {
assert(_rs_threads_vtimes == NULL, "just checking");
assert(remset != NULL, "just checking");
_remset = remset;
_num_vtimes = num_workers;
_num_vtimes = ConcurrentG1Refine::thread_num();
_rs_threads_vtimes = NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC);
memset(_rs_threads_vtimes, 0, sizeof(double) * _num_vtimes);
......@@ -125,25 +125,115 @@ void G1RemSetSummary::subtract_from(G1RemSetSummary* other) {
_sampling_thread_vtime = other->sampling_thread_vtime() - _sampling_thread_vtime;
}
static double percent_of(size_t numerator, size_t denominator) {
if (denominator != 0) {
return (double)numerator / denominator * 100.0f;
} else {
return 0.0f;
}
}
static size_t round_to_K(size_t value) {
return value / K;
}
class RegionTypeCounter VALUE_OBJ_CLASS_SPEC {
private:
const char* _name;
size_t _rs_mem_size;
size_t _cards_occupied;
size_t _amount;
size_t _code_root_mem_size;
size_t _code_root_elems;
double rs_mem_size_percent_of(size_t total) {
return percent_of(_rs_mem_size, total);
}
double cards_occupied_percent_of(size_t total) {
return percent_of(_cards_occupied, total);
}
double code_root_mem_size_percent_of(size_t total) {
return percent_of(_code_root_mem_size, total);
}
double code_root_elems_percent_of(size_t total) {
return percent_of(_code_root_elems, total);
}
size_t amount() const { return _amount; }
public:
RegionTypeCounter(const char* name) : _name(name), _rs_mem_size(0), _cards_occupied(0),
_amount(0), _code_root_mem_size(0), _code_root_elems(0) { }
void add(size_t rs_mem_size, size_t cards_occupied, size_t code_root_mem_size,
size_t code_root_elems) {
_rs_mem_size += rs_mem_size;
_cards_occupied += cards_occupied;
_code_root_mem_size += code_root_mem_size;
_code_root_elems += code_root_elems;
_amount++;
}
size_t rs_mem_size() const { return _rs_mem_size; }
size_t cards_occupied() const { return _cards_occupied; }
size_t code_root_mem_size() const { return _code_root_mem_size; }
size_t code_root_elems() const { return _code_root_elems; }
void print_rs_mem_info_on(outputStream * out, size_t total) {
out->print_cr(" %8dK (%5.1f%%) by %zd %s regions", round_to_K(rs_mem_size()), rs_mem_size_percent_of(total), amount(), _name);
}
void print_cards_occupied_info_on(outputStream * out, size_t total) {
out->print_cr(" %8d (%5.1f%%) entries by %zd %s regions", cards_occupied(), cards_occupied_percent_of(total), amount(), _name);
}
void print_code_root_mem_info_on(outputStream * out, size_t total) {
out->print_cr(" %8dK (%5.1f%%) by %zd %s regions", round_to_K(code_root_mem_size()), code_root_mem_size_percent_of(total), amount(), _name);
}
void print_code_root_elems_info_on(outputStream * out, size_t total) {
out->print_cr(" %8d (%5.1f%%) elements by %zd %s regions", code_root_elems(), code_root_elems_percent_of(total), amount(), _name);
}
};
class HRRSStatsIter: public HeapRegionClosure {
size_t _occupied;
private:
RegionTypeCounter _young;
RegionTypeCounter _humonguous;
RegionTypeCounter _free;
RegionTypeCounter _old;
RegionTypeCounter _all;
size_t _total_rs_mem_sz;
size_t _max_rs_mem_sz;
HeapRegion* _max_rs_mem_sz_region;
size_t _total_code_root_mem_sz;
size_t total_rs_mem_sz() const { return _all.rs_mem_size(); }
size_t total_cards_occupied() const { return _all.cards_occupied(); }
size_t max_rs_mem_sz() const { return _max_rs_mem_sz; }
HeapRegion* max_rs_mem_sz_region() const { return _max_rs_mem_sz_region; }
size_t _max_code_root_mem_sz;
HeapRegion* _max_code_root_mem_sz_region;
size_t total_code_root_mem_sz() const { return _all.code_root_mem_size(); }
size_t total_code_root_elems() const { return _all.code_root_elems(); }
size_t max_code_root_mem_sz() const { return _max_code_root_mem_sz; }
HeapRegion* max_code_root_mem_sz_region() const { return _max_code_root_mem_sz_region; }
public:
HRRSStatsIter() :
_occupied(0),
_total_rs_mem_sz(0),
_max_rs_mem_sz(0),
_max_rs_mem_sz_region(NULL),
_total_code_root_mem_sz(0),
_max_code_root_mem_sz(0),
_max_code_root_mem_sz_region(NULL)
HRRSStatsIter() : _all("All"), _young("Young"), _humonguous("Humonguous"),
_free("Free"), _old("Old"), _max_code_root_mem_sz_region(NULL), _max_rs_mem_sz_region(NULL),
_max_rs_mem_sz(0), _max_code_root_mem_sz(0)
{}
bool doHeapRegion(HeapRegion* r) {
......@@ -156,46 +246,95 @@ public:
_max_rs_mem_sz = rs_mem_sz;
_max_rs_mem_sz_region = r;
}
_total_rs_mem_sz += rs_mem_sz;
size_t occupied_cards = hrrs->occupied();
size_t code_root_mem_sz = hrrs->strong_code_roots_mem_size();
if (code_root_mem_sz > _max_code_root_mem_sz) {
_max_code_root_mem_sz = code_root_mem_sz;
if (code_root_mem_sz > max_code_root_mem_sz()) {
_max_code_root_mem_sz_region = r;
}
_total_code_root_mem_sz += code_root_mem_sz;
size_t code_root_elems = hrrs->strong_code_roots_list_length();
RegionTypeCounter* current = NULL;
if (r->is_young()) {
current = &_young;
} else if (r->isHumongous()) {
current = &_humonguous;
} else if (r->is_empty()) {
current = &_free;
} else {
current = &_old;
}
current->add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems);
_all.add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems);
size_t occ = hrrs->occupied();
_occupied += occ;
return false;
}
size_t total_rs_mem_sz() { return _total_rs_mem_sz; }
size_t max_rs_mem_sz() { return _max_rs_mem_sz; }
HeapRegion* max_rs_mem_sz_region() { return _max_rs_mem_sz_region; }
size_t total_code_root_mem_sz() { return _total_code_root_mem_sz; }
size_t max_code_root_mem_sz() { return _max_code_root_mem_sz; }
HeapRegion* max_code_root_mem_sz_region() { return _max_code_root_mem_sz_region; }
size_t occupied() { return _occupied; }
};
double calc_percentage(size_t numerator, size_t denominator) {
if (denominator != 0) {
return (double)numerator / denominator * 100.0;
} else {
return 0.0f;
void print_summary_on(outputStream* out) {
RegionTypeCounter* counters[] = { &_young, &_humonguous, &_free, &_old, NULL };
out->print_cr("\n Current rem set statistics");
out->print_cr(" Total per region rem sets sizes = "SIZE_FORMAT"K."
" Max = "SIZE_FORMAT"K.",
round_to_K(total_rs_mem_sz()), round_to_K(max_rs_mem_sz()));
for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
(*current)->print_rs_mem_info_on(out, total_rs_mem_sz());
}
out->print_cr(" Static structures = "SIZE_FORMAT"K,"
" free_lists = "SIZE_FORMAT"K.",
round_to_K(HeapRegionRemSet::static_mem_size()),
round_to_K(HeapRegionRemSet::fl_mem_size()));
out->print_cr(" "SIZE_FORMAT" occupied cards represented.",
total_cards_occupied());
for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
(*current)->print_cards_occupied_info_on(out, total_cards_occupied());
}
// Largest sized rem set region statistics
HeapRegionRemSet* rem_set = max_rs_mem_sz_region()->rem_set();
out->print_cr(" Region with largest rem set = "HR_FORMAT", "
"size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.",
HR_FORMAT_PARAMS(max_rs_mem_sz_region()),
round_to_K(rem_set->mem_size()),
round_to_K(rem_set->occupied()));
// Strong code root statistics
HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set();
out->print_cr(" Total heap region code root sets sizes = "SIZE_FORMAT"K."
" Max = "SIZE_FORMAT"K.",
round_to_K(total_code_root_mem_sz()),
round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()));
for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
(*current)->print_code_root_mem_info_on(out, total_code_root_mem_sz());
}
out->print_cr(" "SIZE_FORMAT" code roots represented.",
total_code_root_elems());
for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
(*current)->print_code_root_elems_info_on(out, total_code_root_elems());
}
out->print_cr(" Region with largest amount of code roots = "HR_FORMAT", "
"size = "SIZE_FORMAT "K, num_elems = "SIZE_FORMAT".",
HR_FORMAT_PARAMS(max_code_root_mem_sz_region()),
round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()),
round_to_K(max_code_root_rem_set->strong_code_roots_list_length()));
}
}
};
void G1RemSetSummary::print_on(outputStream* out) {
out->print_cr("\n Concurrent RS processed "SIZE_FORMAT" cards",
out->print_cr("\n Recent concurrent refinement statistics");
out->print_cr(" Processed "SIZE_FORMAT" cards",
num_concurrent_refined_cards());
out->print_cr(" Of %d completed buffers:", num_processed_buf_total());
out->print_cr(" %8d (%5.1f%%) by concurrent RS threads.",
num_processed_buf_total(),
calc_percentage(num_processed_buf_rs_threads(), num_processed_buf_total()));
percent_of(num_processed_buf_rs_threads(), num_processed_buf_total()));
out->print_cr(" %8d (%5.1f%%) by mutator threads.",
num_processed_buf_mutator(),
calc_percentage(num_processed_buf_mutator(), num_processed_buf_total()));
percent_of(num_processed_buf_mutator(), num_processed_buf_total()));
out->print_cr(" Did %d coarsenings.", num_coarsenings());
out->print_cr(" Concurrent RS threads times (s)");
out->print(" ");
for (uint i = 0; i < _num_vtimes; i++) {
......@@ -207,33 +346,5 @@ void G1RemSetSummary::print_on(outputStream* out) {
HRRSStatsIter blk;
G1CollectedHeap::heap()->heap_region_iterate(&blk);
// RemSet stats
out->print_cr(" Total heap region rem set sizes = "SIZE_FORMAT"K."
" Max = "SIZE_FORMAT"K.",
blk.total_rs_mem_sz()/K, blk.max_rs_mem_sz()/K);
out->print_cr(" Static structures = "SIZE_FORMAT"K,"
" free_lists = "SIZE_FORMAT"K.",
HeapRegionRemSet::static_mem_size() / K,
HeapRegionRemSet::fl_mem_size() / K);
out->print_cr(" "SIZE_FORMAT" occupied cards represented.",
blk.occupied());
HeapRegion* max_rs_mem_sz_region = blk.max_rs_mem_sz_region();
HeapRegionRemSet* max_rs_rem_set = max_rs_mem_sz_region->rem_set();
out->print_cr(" Max size region = "HR_FORMAT", "
"size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.",
HR_FORMAT_PARAMS(max_rs_mem_sz_region),
(max_rs_rem_set->mem_size() + K - 1)/K,
(max_rs_rem_set->occupied() + K - 1)/K);
out->print_cr(" Did %d coarsenings.", num_coarsenings());
// Strong code root stats
out->print_cr(" Total heap region code-root set sizes = "SIZE_FORMAT"K."
" Max = "SIZE_FORMAT"K.",
blk.total_code_root_mem_sz()/K, blk.max_code_root_mem_sz()/K);
HeapRegion* max_code_root_mem_sz_region = blk.max_code_root_mem_sz_region();
HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region->rem_set();
out->print_cr(" Max size region = "HR_FORMAT", "
"size = "SIZE_FORMAT "K, num_elems = "SIZE_FORMAT".",
HR_FORMAT_PARAMS(max_code_root_mem_sz_region),
(max_code_root_rem_set->strong_code_roots_mem_size() + K - 1)/K,
(max_code_root_rem_set->strong_code_roots_list_length()));
blk.print_summary_on(out);
}
......@@ -84,7 +84,7 @@ public:
void subtract_from(G1RemSetSummary* other);
// initialize and get the first sampling
void initialize(G1RemSet* remset, uint num_workers);
void initialize(G1RemSet* remset);
void print_on(outputStream* out);
......
......@@ -64,6 +64,27 @@ G1SATBCardTableModRefBS::write_ref_array_pre_work(T* dst, int count) {
}
}
bool G1SATBCardTableModRefBS::mark_card_deferred(size_t card_index) {
jbyte val = _byte_map[card_index];
// It's already processed
if ((val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val()) {
return false;
}
// Cached bit can be installed either on a clean card or on a claimed card.
jbyte new_val = val;
if (val == clean_card_val()) {
new_val = (jbyte)deferred_card_val();
} else {
if (val & claimed_card_val()) {
new_val = val | (jbyte)deferred_card_val();
}
}
if (new_val != val) {
Atomic::cmpxchg(new_val, &_byte_map[card_index], val);
}
return true;
}
G1SATBCardTableLoggingModRefBS::
G1SATBCardTableLoggingModRefBS(MemRegion whole_heap,
int max_covered_regions) :
......
......@@ -89,6 +89,42 @@ public:
write_ref_array_pre_work(dst, count);
}
}
/*
Claimed and deferred bits are used together in G1 during the evacuation
pause. These bits can have the following state transitions:
1. The claimed bit can be put over any other card state. Except that
the "dirty -> dirty and claimed" transition is checked for in
G1 code and is not used.
2. Deferred bit can be set only if the previous state of the card
was either clean or claimed. mark_card_deferred() is wait-free.
We do not care if the operation is be successful because if
it does not it will only result in duplicate entry in the update
buffer because of the "cache-miss". So it's not worth spinning.
*/
bool is_card_claimed(size_t card_index) {
jbyte val = _byte_map[card_index];
return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val();
}
void set_card_claimed(size_t card_index) {
jbyte val = _byte_map[card_index];
if (val == clean_card_val()) {
val = (jbyte)claimed_card_val();
} else {
val |= (jbyte)claimed_card_val();
}
_byte_map[card_index] = val;
}
bool mark_card_deferred(size_t card_index);
bool is_card_deferred(size_t card_index) {
jbyte val = _byte_map[card_index];
return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
}
};
// Adds card-table logging to the post-barrier.
......
......@@ -40,10 +40,8 @@ class GenerationSizer : public TwoGenerationCollectorPolicy {
void initialize_flags() {
// Do basic sizing work
this->TwoGenerationCollectorPolicy::initialize_flags();
TwoGenerationCollectorPolicy::initialize_flags();
// If the user hasn't explicitly set the number of worker
// threads, set the count.
assert(UseSerialGC ||
!FLAG_IS_DEFAULT(ParallelGCThreads) ||
(ParallelGCThreads > 0),
......
......@@ -23,7 +23,6 @@
*/
#include "precompiled.hpp"
#include "gc_implementation/parallelScavenge/generationSizer.hpp"
#include "gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp"
#include "gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.hpp"
......
......@@ -53,7 +53,6 @@
// Forward decls
class elapsedTimer;
class GenerationSizer;
class PSAdaptiveSizePolicy : public AdaptiveSizePolicy {
friend class PSGCAdaptivePolicyCounters;
......
......@@ -26,7 +26,6 @@
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "gc_implementation/parallelScavenge/generationSizer.hpp"
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
#include "gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp"
#include "gc_implementation/parallelScavenge/psMarkSweep.hpp"
......
......@@ -27,7 +27,6 @@
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
#include "gc_implementation/parallelScavenge/generationSizer.hpp"
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.inline.hpp"
#include "gc_implementation/parallelScavenge/pcTasks.hpp"
#include "gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp"
......
......@@ -27,7 +27,6 @@
#include "code/codeCache.hpp"
#include "gc_implementation/parallelScavenge/cardTableExtension.hpp"
#include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
#include "gc_implementation/parallelScavenge/generationSizer.hpp"
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
#include "gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp"
#include "gc_implementation/parallelScavenge/psMarkSweep.hpp"
......
......@@ -423,60 +423,6 @@ void CardTableModRefBS::write_ref_field_work(void* field, oop newVal) {
inline_write_ref_field(field, newVal);
}
/*
Claimed and deferred bits are used together in G1 during the evacuation
pause. These bits can have the following state transitions:
1. The claimed bit can be put over any other card state. Except that
the "dirty -> dirty and claimed" transition is checked for in
G1 code and is not used.
2. Deferred bit can be set only if the previous state of the card
was either clean or claimed. mark_card_deferred() is wait-free.
We do not care if the operation is be successful because if
it does not it will only result in duplicate entry in the update
buffer because of the "cache-miss". So it's not worth spinning.
*/
bool CardTableModRefBS::claim_card(size_t card_index) {
jbyte val = _byte_map[card_index];
assert(val != dirty_card_val(), "Shouldn't claim a dirty card");
while (val == clean_card_val() ||
(val & (clean_card_mask_val() | claimed_card_val())) != claimed_card_val()) {
jbyte new_val = val;
if (val == clean_card_val()) {
new_val = (jbyte)claimed_card_val();
} else {
new_val = val | (jbyte)claimed_card_val();
}
jbyte res = Atomic::cmpxchg(new_val, &_byte_map[card_index], val);
if (res == val) {
return true;
}
val = res;
}
return false;
}
bool CardTableModRefBS::mark_card_deferred(size_t card_index) {
jbyte val = _byte_map[card_index];
// It's already processed
if ((val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val()) {
return false;
}
// Cached bit can be installed either on a clean card or on a claimed card.
jbyte new_val = val;
if (val == clean_card_val()) {
new_val = (jbyte)deferred_card_val();
} else {
if (val & claimed_card_val()) {
new_val = val | (jbyte)deferred_card_val();
}
}
if (new_val != val) {
Atomic::cmpxchg(new_val, &_byte_map[card_index], val);
}
return true;
}
void CardTableModRefBS::non_clean_card_iterate_possibly_parallel(Space* sp,
MemRegion mr,
......
......@@ -339,34 +339,10 @@ public:
_byte_map[card_index] = dirty_card_val();
}
bool is_card_claimed(size_t card_index) {
jbyte val = _byte_map[card_index];
return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val();
}
void set_card_claimed(size_t card_index) {
jbyte val = _byte_map[card_index];
if (val == clean_card_val()) {
val = (jbyte)claimed_card_val();
} else {
val |= (jbyte)claimed_card_val();
}
_byte_map[card_index] = val;
}
bool claim_card(size_t card_index);
bool is_card_clean(size_t card_index) {
return _byte_map[card_index] == clean_card_val();
}
bool is_card_deferred(size_t card_index) {
jbyte val = _byte_map[card_index];
return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
}
bool mark_card_deferred(size_t card_index);
// Card marking array base (adjusted for heap low boundary)
// This would be the 0th element of _byte_map, if the heap started at 0x0.
// But since the heap starts at some higher address, this points to somewhere
......
......@@ -64,19 +64,21 @@ void CollectorPolicy::initialize_flags() {
vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
}
if (!is_size_aligned(MaxMetaspaceSize, max_alignment())) {
FLAG_SET_ERGO(uintx, MaxMetaspaceSize,
restricted_align_down(MaxMetaspaceSize, max_alignment()));
}
// Do not use FLAG_SET_ERGO to update MaxMetaspaceSize, since this will
// override if MaxMetaspaceSize was set on the command line or not.
// This information is needed later to conform to the specification of the
// java.lang.management.MemoryUsage API.
//
// Ideally, we would be able to set the default value of MaxMetaspaceSize in
// globals.hpp to the aligned value, but this is not possible, since the
// alignment depends on other flags being parsed.
MaxMetaspaceSize = restricted_align_down(MaxMetaspaceSize, max_alignment());
if (MetaspaceSize > MaxMetaspaceSize) {
FLAG_SET_ERGO(uintx, MetaspaceSize, MaxMetaspaceSize);
MetaspaceSize = MaxMetaspaceSize;
}
if (!is_size_aligned(MetaspaceSize, min_alignment())) {
FLAG_SET_ERGO(uintx, MetaspaceSize,
restricted_align_down(MetaspaceSize, min_alignment()));
}
MetaspaceSize = restricted_align_down(MetaspaceSize, min_alignment());
assert(MetaspaceSize <= MaxMetaspaceSize, "Must be");
......@@ -135,15 +137,8 @@ bool CollectorPolicy::use_should_clear_all_soft_refs(bool v) {
GenRemSet* CollectorPolicy::create_rem_set(MemRegion whole_heap,
int max_covered_regions) {
switch (rem_set_name()) {
case GenRemSet::CardTable: {
CardTableRS* res = new CardTableRS(whole_heap, max_covered_regions);
return res;
}
default:
guarantee(false, "unrecognized GenRemSet::Name");
return NULL;
}
assert(rem_set_name() == GenRemSet::CardTable, "unrecognized GenRemSet::Name");
return new CardTableRS(whole_heap, max_covered_regions);
}
void CollectorPolicy::cleared_all_soft_refs() {
......
......@@ -32,13 +32,8 @@
// enumeration.)
uintx GenRemSet::max_alignment_constraint(Name nm) {
switch (nm) {
case GenRemSet::CardTable:
return CardTableRS::ct_max_alignment_constraint();
default:
guarantee(false, "Unrecognized GenRemSet type.");
return (0); // Make Windows compiler happy
}
assert(nm == GenRemSet::CardTable, "Unrecognized GenRemSet type.");
return CardTableRS::ct_max_alignment_constraint();
}
class HasAccumulatedModifiedOopsClosure : public KlassClosure {
......
......@@ -3104,7 +3104,7 @@ size_t Metaspace::align_word_size_up(size_t word_size) {
MetaWord* Metaspace::allocate(size_t word_size, MetadataType mdtype) {
// DumpSharedSpaces doesn't use class metadata area (yet)
// Also, don't use class_vsm() unless UseCompressedClassPointers is true.
if (mdtype == ClassType && using_class_space()) {
if (is_class_space_allocation(mdtype)) {
return class_vsm()->allocate(word_size);
} else {
return vsm()->allocate(word_size);
......@@ -3252,8 +3252,8 @@ Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
MetaspaceAux::dump(gclog_or_tty);
}
// -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support
const char* space_string = (mdtype == ClassType) ? "Compressed class space" :
"Metadata space";
const char* space_string = is_class_space_allocation(mdtype) ? "Compressed class space" :
"Metadata space";
report_java_out_of_memory(space_string);
if (JvmtiExport::should_post_resource_exhausted()) {
......@@ -3261,7 +3261,7 @@ Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR,
space_string);
}
if (mdtype == ClassType) {
if (is_class_space_allocation(mdtype)) {
THROW_OOP_0(Universe::out_of_memory_error_class_metaspace());
} else {
THROW_OOP_0(Universe::out_of_memory_error_metaspace());
......
......@@ -235,6 +235,9 @@ class Metaspace : public CHeapObj<mtClass> {
return NOT_LP64(false) LP64_ONLY(UseCompressedClassPointers && !DumpSharedSpaces);
}
static bool is_class_space_allocation(MetadataType mdType) {
return mdType == ClassType && using_class_space();
}
};
class MetaspaceAux : AllStatic {
......
......@@ -25,140 +25,61 @@
* @test TestSummarizeRSetStats.java
* @bug 8013895
* @library /testlibrary
* @build TestSummarizeRSetStats
* @build TestSummarizeRSetStatsTools TestSummarizeRSetStats
* @summary Verify output of -XX:+G1SummarizeRSetStats
* @run main TestSummarizeRSetStats
*
* Test the output of G1SummarizeRSetStats in conjunction with G1SummarizeRSetStatsPeriod.
*/
import com.oracle.java.testlibrary.*;
import java.lang.Thread;
import java.util.ArrayList;
import java.util.Arrays;
class RunSystemGCs {
// 4M size, both are directly allocated into the old gen
static Object[] largeObject1 = new Object[1024 * 1024];
static Object[] largeObject2 = new Object[1024 * 1024];
static int[] temp;
public static void main(String[] args) {
// create some cross-references between these objects
for (int i = 0; i < largeObject1.length; i++) {
largeObject1[i] = largeObject2;
}
for (int i = 0; i < largeObject2.length; i++) {
largeObject2[i] = largeObject1;
}
int numGCs = Integer.parseInt(args[0]);
if (numGCs > 0) {
// try to force a minor collection: the young gen is 4M, the
// amount of data allocated below is roughly that (4*1024*1024 +
// some header data)
for (int i = 0; i < 1024 ; i++) {
temp = new int[1024];
}
}
for (int i = 0; i < numGCs - 1; i++) {
System.gc();
}
}
}
public class TestSummarizeRSetStats {
public static String runTest(String[] additionalArgs, int numGCs) throws Exception {
ArrayList<String> finalargs = new ArrayList<String>();
String[] defaultArgs = new String[] {
"-XX:+UseG1GC",
"-Xmn4m",
"-Xmx20m",
"-XX:InitiatingHeapOccupancyPercent=100", // we don't want the additional GCs due to initial marking
"-XX:+PrintGC",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:G1HeapRegionSize=1M",
};
finalargs.addAll(Arrays.asList(defaultArgs));
if (additionalArgs != null) {
finalargs.addAll(Arrays.asList(additionalArgs));
}
finalargs.add(RunSystemGCs.class.getName());
finalargs.add(String.valueOf(numGCs));
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
finalargs.toArray(new String[0]));
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldHaveExitValue(0);
String result = output.getStdout();
return result;
}
private static void expectStatistics(String result, int expectedCumulative, int expectedPeriodic) throws Exception {
int actualTotal = result.split("Concurrent RS processed").length - 1;
int actualCumulative = result.split("Cumulative RS summary").length - 1;
if (expectedCumulative != actualCumulative) {
throw new Exception("Incorrect amount of RSet summaries at the end. Expected " + expectedCumulative + ", got " + actualCumulative);
}
if (expectedPeriodic != (actualTotal - actualCumulative)) {
throw new Exception("Incorrect amount of per-period RSet summaries at the end. Expected " + expectedPeriodic + ", got " + (actualTotal - actualCumulative));
}
}
public static void main(String[] args) throws Exception {
String result;
// no RSet statistics output
result = runTest(null, 0);
expectStatistics(result, 0, 0);
if (!TestSummarizeRSetStatsTools.testingG1GC()) {
return;
}
// no remembered set summary output
result = TestSummarizeRSetStatsTools.runTest(null, 0);
TestSummarizeRSetStatsTools.expectRSetSummaries(result, 0, 0);
// no RSet statistics output
result = runTest(null, 2);
expectStatistics(result, 0, 0);
// no remembered set summary output
result = TestSummarizeRSetStatsTools.runTest(null, 2);
TestSummarizeRSetStatsTools.expectRSetSummaries(result, 0, 0);
// no RSet statistics output
result = runTest(new String[] { "-XX:G1SummarizeRSetStatsPeriod=1" }, 3);
expectStatistics(result, 0, 0);
// no remembered set summary output
result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:G1SummarizeRSetStatsPeriod=1" }, 3);
TestSummarizeRSetStatsTools.expectRSetSummaries(result, 0, 0);
// single RSet statistics output at the end
result = runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 0);
expectStatistics(result, 1, 0);
// single remembered set summary output at the end
result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 0);
TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 0);
// single RSet statistics output at the end
result = runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 2);
expectStatistics(result, 1, 0);
// single remembered set summary output at the end
result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 2);
TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 0);
// single RSet statistics output
result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 0);
expectStatistics(result, 1, 0);
// single remembered set summary output
result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 0);
TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 0);
// two times RSet statistics output
result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 1);
expectStatistics(result, 1, 1);
// two times remembered set summary output
result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 1);
TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 2);
// four times RSet statistics output
result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 3);
expectStatistics(result, 1, 3);
// four times remembered set summary output
result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 3);
TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 6);
// three times RSet statistics output
result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=2" }, 3);
expectStatistics(result, 1, 2);
// three times remembered set summary output
result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=2" }, 3);
TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 4);
// single RSet statistics output
result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=100" }, 3);
expectStatistics(result, 1, 1);
// single remembered set summary output
result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=100" }, 3);
TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 2);
}
}
/*
* 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 TestSummarizeRSetStatsPerRegion.java
* @bug 8014078
* @library /testlibrary
* @build TestSummarizeRSetStatsTools TestSummarizeRSetStatsPerRegion
* @summary Verify output of -XX:+G1SummarizeRSetStats in regards to per-region type output
* @run main TestSummarizeRSetStatsPerRegion
*/
import com.oracle.java.testlibrary.*;
import java.lang.Thread;
import java.util.ArrayList;
import java.util.Arrays;
public class TestSummarizeRSetStatsPerRegion {
public static void main(String[] args) throws Exception {
String result;
if (!TestSummarizeRSetStatsTools.testingG1GC()) {
return;
}
// single remembered set summary output at the end
result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 0);
TestSummarizeRSetStatsTools.expectPerRegionRSetSummaries(result, 1, 0);
// two times remembered set summary output
result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 1);
TestSummarizeRSetStatsTools.expectPerRegionRSetSummaries(result, 1, 2);
}
}
/*
* 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 TestSummarizeRSetStatsThreads
* @bug 8025441
* @summary Ensure that various values of worker threads/concurrent
* refinement threads do not crash the VM.
* @key gc
* @library /testlibrary
*/
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.oracle.java.testlibrary.ProcessTools;
import com.oracle.java.testlibrary.OutputAnalyzer;
public class TestSummarizeRSetStatsThreads {
private static void runTest(int refinementThreads, int workerThreads) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+G1SummarizeRSetStats",
"-XX:G1ConcRefinementThreads=" + refinementThreads,
"-XX:ParallelGCThreads=" + workerThreads,
"-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
// check output to contain the string "Concurrent RS threads times (s)" followed by
// the correct number of values in the next line.
// a zero in refinement thread numbers indicates that the value in ParallelGCThreads should be used.
// Additionally use at least one thread.
int expectedNumRefinementThreads = refinementThreads == 0 ? workerThreads : refinementThreads;
expectedNumRefinementThreads = Math.max(1, expectedNumRefinementThreads);
// create the pattern made up of n copies of a floating point number pattern
String numberPattern = String.format("%0" + expectedNumRefinementThreads + "d", 0)
.replace("0", "\\s+\\d+\\.\\d+");
String pattern = "Concurrent RS threads times \\(s\\)$" + numberPattern + "$";
Matcher m = Pattern.compile(pattern, Pattern.MULTILINE).matcher(output.getStdout());
if (!m.find()) {
throw new Exception("Could not find correct output for concurrent RS threads times in stdout," +
" should match the pattern \"" + pattern + "\", but stdout is \n" + output.getStdout());
}
output.shouldHaveExitValue(0);
}
public static void main(String[] args) throws Exception {
if (!TestSummarizeRSetStatsTools.testingG1GC()) {
return;
}
// different valid combinations of number of refinement and gc worker threads
runTest(0, 0);
runTest(0, 5);
runTest(5, 0);
runTest(10, 10);
runTest(1, 2);
runTest(4, 3);
}
}
/*
* 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.
*/
/*
* Common helpers for TestSummarizeRSetStats* tests
*/
import sun.management.ManagementFactoryHelper;
import com.sun.management.HotSpotDiagnosticMXBean;
import com.sun.management.VMOption;
import com.oracle.java.testlibrary.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.lang.Thread;
import java.util.ArrayList;
import java.util.Arrays;
class VerifySummaryOutput {
// 4M size, both are directly allocated into the old gen
static Object[] largeObject1 = new Object[1024 * 1024];
static Object[] largeObject2 = new Object[1024 * 1024];
static int[] temp;
public static void main(String[] args) {
// create some cross-references between these objects
for (int i = 0; i < largeObject1.length; i++) {
largeObject1[i] = largeObject2;
}
for (int i = 0; i < largeObject2.length; i++) {
largeObject2[i] = largeObject1;
}
int numGCs = Integer.parseInt(args[0]);
if (numGCs > 0) {
// try to force a minor collection: the young gen is 4M, the
// amount of data allocated below is roughly that (4*1024*1024 +
// some header data)
for (int i = 0; i < 1024 ; i++) {
temp = new int[1024];
}
}
for (int i = 0; i < numGCs - 1; i++) {
System.gc();
}
}
}
public class TestSummarizeRSetStatsTools {
// the VM is currently run using G1GC, i.e. trying to test G1 functionality.
public static boolean testingG1GC() {
HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean();
VMOption option = diagnostic.getVMOption("UseG1GC");
if (option.getValue().equals("false")) {
System.out.println("Skipping this test. It is only a G1 test.");
return false;
}
return true;
}
public static String runTest(String[] additionalArgs, int numGCs) throws Exception {
ArrayList<String> finalargs = new ArrayList<String>();
String[] defaultArgs = new String[] {
"-XX:+UseG1GC",
"-XX:+UseCompressedOops",
"-Xmn4m",
"-Xmx20m",
"-XX:InitiatingHeapOccupancyPercent=100", // we don't want the additional GCs due to initial marking
"-XX:+PrintGC",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:G1HeapRegionSize=1M",
};
finalargs.addAll(Arrays.asList(defaultArgs));
if (additionalArgs != null) {
finalargs.addAll(Arrays.asList(additionalArgs));
}
finalargs.add(VerifySummaryOutput.class.getName());
finalargs.add(String.valueOf(numGCs));
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
finalargs.toArray(new String[0]));
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldHaveExitValue(0);
String result = output.getStdout();
return result;
}
private static void checkCounts(int expected, int actual, String which) throws Exception {
if (expected != actual) {
throw new Exception("RSet summaries mention " + which + " regions an incorrect number of times. Expected " + expected + ", got " + actual);
}
}
public static void expectPerRegionRSetSummaries(String result, int expectedCumulative, int expectedPeriodic) throws Exception {
expectRSetSummaries(result, expectedCumulative, expectedPeriodic);
int actualYoung = result.split("Young regions").length - 1;
int actualHumonguous = result.split("Humonguous regions").length - 1;
int actualFree = result.split("Free regions").length - 1;
int actualOther = result.split("Old regions").length - 1;
// the strings we check for above are printed four times per summary
int expectedPerRegionTypeInfo = (expectedCumulative + expectedPeriodic) * 4;
checkCounts(expectedPerRegionTypeInfo, actualYoung, "Young");
checkCounts(expectedPerRegionTypeInfo, actualHumonguous, "Humonguous");
checkCounts(expectedPerRegionTypeInfo, actualFree, "Free");
checkCounts(expectedPerRegionTypeInfo, actualOther, "Old");
}
public static void expectRSetSummaries(String result, int expectedCumulative, int expectedPeriodic) throws Exception {
int actualTotal = result.split("concurrent refinement").length - 1;
int actualCumulative = result.split("Cumulative RS summary").length - 1;
if (expectedCumulative != actualCumulative) {
throw new Exception("Incorrect amount of RSet summaries at the end. Expected " + expectedCumulative + ", got " + actualCumulative);
}
if (expectedPeriodic != (actualTotal - actualCumulative)) {
throw new Exception("Incorrect amount of per-period RSet summaries at the end. Expected " + expectedPeriodic + ", got " + (actualTotal - actualCumulative));
}
}
}
......@@ -107,7 +107,6 @@ public class G1AddMetaspaceDependency {
Loader f_loader = new Loader(b_name, b_bytes, a_name, a_loader);
Loader g_loader = new Loader(b_name, b_bytes, a_name, a_loader);
byte[] b = new byte[20 * 2 << 20];
Class<?> c;
c = b_loader.loadClass(b_name);
c = c_loader.loadClass(b_name);
......
......@@ -29,10 +29,11 @@ import static com.oracle.java.testlibrary.Asserts.*;
/* @test TestPerfCountersAndMemoryPools
* @bug 8023476
* @library /testlibrary
* @summary Tests that a MemoryPoolMXBeans and PerfCounters for metaspace
* report the same data.
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData TestPerfCountersAndMemoryPools
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData TestPerfCountersAndMemoryPools
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData -Xint TestPerfCountersAndMemoryPools
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData -Xint TestPerfCountersAndMemoryPools
*/
public class TestPerfCountersAndMemoryPools {
public static void main(String[] args) throws Exception {
......@@ -43,11 +44,11 @@ public class TestPerfCountersAndMemoryPools {
}
}
private static MemoryUsage getMemoryUsage(String memoryPoolName) {
private static MemoryPoolMXBean getMemoryPool(String memoryPoolName) {
List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
for (MemoryPoolMXBean pool : pools) {
if (pool.getName().equals(memoryPoolName)) {
return pool.getUsage();
return pool;
}
}
......@@ -57,19 +58,18 @@ public class TestPerfCountersAndMemoryPools {
private static void checkMemoryUsage(String memoryPoolName, String perfNS)
throws Exception {
// Need to do a gc before each comparison to update the perf counters
MemoryPoolMXBean pool = getMemoryPool(memoryPoolName);
// Must do a GC to update performance counters
System.gc();
MemoryUsage mu = getMemoryUsage(memoryPoolName);
assertEQ(getMinCapacity(perfNS), mu.getInit());
assertEQ(getMinCapacity(perfNS), pool.getUsage().getInit());
// Must do a second GC to update the perfomance counters again, since
// the call pool.getUsage().getInit() could have allocated some
// metadata.
System.gc();
mu = getMemoryUsage(memoryPoolName);
assertEQ(getUsed(perfNS), mu.getUsed());
System.gc();
mu = getMemoryUsage(memoryPoolName);
assertEQ(getCapacity(perfNS), mu.getCommitted());
assertEQ(getUsed(perfNS), pool.getUsage().getUsed());
assertEQ(getCapacity(perfNS), pool.getUsage().getCommitted());
}
private static long getMinCapacity(String ns) throws Exception {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册