1 Star 0 Fork 81

fuowang/openjdk-1.8.0

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
Parallel-Full-GC-for-G1.patch 83.92 KB
一键复制 编辑 原始数据 按行查看 历史
kuen 提交于 2021-11-01 20:19 . I4GEZM: upgrade to jdk8u312-ga
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122
From abe008c9f30db79afb44f87bd8cab37bd1486e4b Mon Sep 17 00:00:00 2001
From: wangkun <wangkun49@huawei.com>
Date: Mon, 13 Sep 2021 17:34:39 +0800
Subject: [PATCH 19/23] Parallel Full GC for G1.
Summary:gc:g1:Parallel Full GC for G1. (prepare/adjust/compact in parallel; uses claimer instead of claim value; code clean)
LLT: N/A
Patch Type:huawei
Bug url: N/A
---
.../gc_implementation/g1/concurrentMark.cpp | 66 +-
.../g1/g1BlockOffsetTable.inline.hpp | 4 +-
.../gc_implementation/g1/g1CollectedHeap.cpp | 168 +----
.../gc_implementation/g1/g1CollectedHeap.hpp | 21 +-
.../g1/g1CollectorPolicy.cpp | 16 +-
.../vm/gc_implementation/g1/g1EvacFailure.hpp | 13 +-
.../vm/gc_implementation/g1/g1MarkSweep.cpp | 583 ++++++++++++++++--
.../vm/gc_implementation/g1/g1MarkSweep.hpp | 45 +-
.../gc_implementation/g1/g1MarkSweep_ext.cpp | 31 -
.../vm/gc_implementation/g1/g1RemSet.cpp | 7 +-
.../vm/gc_implementation/g1/g1RemSet.hpp | 2 +-
.../vm/gc_implementation/g1/g1_globals.hpp | 3 +
.../vm/gc_implementation/g1/heapRegion.cpp | 20 +-
.../vm/gc_implementation/g1/heapRegion.hpp | 44 +-
.../g1/heapRegionManager.cpp | 42 +-
.../g1/heapRegionManager.hpp | 25 +-
hotspot/src/share/vm/memory/space.cpp | 9 +-
hotspot/src/share/vm/memory/space.hpp | 6 +-
hotspot/src/share/vm/memory/space.inline.hpp | 61 ++
hotspot/src/share/vm/runtime/mutexLocker.cpp | 4 +
hotspot/src/share/vm/runtime/mutexLocker.hpp | 2 +
...rReclaimHumongousRegionsClearMarkBits.java | 4 +-
...tEagerReclaimHumongousRegionsWithRefs.java | 4 +-
.../jfr/event/gc/detailed/ExecuteOOMApp.java | 4 +-
.../TestG1ConcurrentModeFailureEvent.java | 36 +-
25 files changed, 789 insertions(+), 431 deletions(-)
delete mode 100644 hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep_ext.cpp
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
index 52bd8cc5e..447bee183 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
@@ -1666,6 +1666,8 @@ protected:
int _failures;
bool _verbose;
+ HeapRegionClaimer _hrclaimer;
+
public:
G1ParVerifyFinalCountTask(G1CollectedHeap* g1h,
BitMap* region_bm, BitMap* card_bm,
@@ -1687,6 +1689,7 @@ public:
} else {
_n_workers = 1;
}
+ _hrclaimer.set_workers(_n_workers);
assert(_expected_card_bm->size() == _actual_card_bm->size(), "sanity");
assert(_expected_region_bm->size() == _actual_region_bm->size(), "sanity");
@@ -1706,8 +1709,7 @@ public:
if (G1CollectedHeap::use_parallel_gc_threads()) {
_g1h->heap_region_par_iterate_chunked(&verify_cl,
worker_id,
- _n_workers,
- HeapRegion::VerifyCountClaimValue);
+ &_hrclaimer);
} else {
_g1h->heap_region_iterate(&verify_cl);
}
@@ -1796,6 +1798,7 @@ protected:
BitMap* _actual_card_bm;
uint _n_workers;
+ HeapRegionClaimer _hrclaimer;
public:
G1ParFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm)
@@ -1812,6 +1815,7 @@ public:
} else {
_n_workers = 1;
}
+ _hrclaimer.set_workers(_n_workers);
}
void work(uint worker_id) {
@@ -1824,8 +1828,7 @@ public:
if (G1CollectedHeap::use_parallel_gc_threads()) {
_g1h->heap_region_par_iterate_chunked(&final_update_cl,
worker_id,
- _n_workers,
- HeapRegion::FinalCountClaimValue);
+ &_hrclaimer);
} else {
_g1h->heap_region_iterate(&final_update_cl);
}
@@ -1912,12 +1915,15 @@ protected:
size_t _max_live_bytes;
size_t _freed_bytes;
FreeRegionList* _cleanup_list;
+ HeapRegionClaimer _hrclaimer;
public:
G1ParNoteEndTask(G1CollectedHeap* g1h,
- FreeRegionList* cleanup_list) :
+ FreeRegionList* cleanup_list,
+ uint n_workers) :
AbstractGangTask("G1 note end"), _g1h(g1h),
- _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list) { }
+ _max_live_bytes(0), _freed_bytes(0),
+ _cleanup_list(cleanup_list), _hrclaimer(n_workers) { }
void work(uint worker_id) {
double start = os::elapsedTime();
@@ -1926,9 +1932,7 @@ public:
G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list,
&hrrs_cleanup_task);
if (G1CollectedHeap::use_parallel_gc_threads()) {
- _g1h->heap_region_par_iterate_chunked(&g1_note_end, worker_id,
- _g1h->workers()->active_workers(),
- HeapRegion::NoteEndClaimValue);
+ _g1h->heap_region_par_iterate_chunked(&g1_note_end, worker_id, &_hrclaimer);
} else {
_g1h->heap_region_iterate(&g1_note_end);
}
@@ -1974,16 +1978,16 @@ protected:
G1RemSet* _g1rs;
BitMap* _region_bm;
BitMap* _card_bm;
+ HeapRegionClaimer _hrclaimer;
public:
- G1ParScrubRemSetTask(G1CollectedHeap* g1h,
- BitMap* region_bm, BitMap* card_bm) :
+ G1ParScrubRemSetTask(G1CollectedHeap* g1h, BitMap* region_bm,
+ BitMap* card_bm, uint n_workers) :
AbstractGangTask("G1 ScrubRS"), _g1rs(g1h->g1_rem_set()),
- _region_bm(region_bm), _card_bm(card_bm) { }
+ _region_bm(region_bm), _card_bm(card_bm), _hrclaimer(n_workers) { }
void work(uint worker_id) {
if (G1CollectedHeap::use_parallel_gc_threads()) {
- _g1rs->scrub_par(_region_bm, _card_bm, worker_id,
- HeapRegion::ScrubRemSetClaimValue);
+ _g1rs->scrub_par(_region_bm, _card_bm, worker_id, &_hrclaimer);
} else {
_g1rs->scrub(_region_bm, _card_bm);
}
@@ -2026,9 +2030,6 @@ void ConcurrentMark::cleanup() {
G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm);
if (G1CollectedHeap::use_parallel_gc_threads()) {
- assert(g1h->check_heap_region_claim_values(HeapRegion::InitialClaimValue),
- "sanity check");
-
g1h->set_par_threads();
n_workers = g1h->n_par_threads();
assert(g1h->n_par_threads() == n_workers,
@@ -2036,9 +2037,6 @@ void ConcurrentMark::cleanup() {
g1h->workers()->run_task(&g1_par_count_task);
// Done with the parallel phase so reset to 0.
g1h->set_par_threads(0);
-
- assert(g1h->check_heap_region_claim_values(HeapRegion::FinalCountClaimValue),
- "sanity check");
} else {
n_workers = 1;
g1_par_count_task.work(0);
@@ -2063,9 +2061,6 @@ void ConcurrentMark::cleanup() {
g1h->workers()->run_task(&g1_par_verify_task);
// Done with the parallel phase so reset to 0.
g1h->set_par_threads(0);
-
- assert(g1h->check_heap_region_claim_values(HeapRegion::VerifyCountClaimValue),
- "sanity check");
} else {
g1_par_verify_task.work(0);
}
@@ -2091,14 +2086,11 @@ void ConcurrentMark::cleanup() {
g1h->reset_gc_time_stamp();
// Note end of marking in all heap regions.
- G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list);
+ G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list, n_workers);
if (G1CollectedHeap::use_parallel_gc_threads()) {
g1h->set_par_threads((int)n_workers);
g1h->workers()->run_task(&g1_par_note_end_task);
g1h->set_par_threads(0);
-
- assert(g1h->check_heap_region_claim_values(HeapRegion::NoteEndClaimValue),
- "sanity check");
} else {
g1_par_note_end_task.work(0);
}
@@ -2115,15 +2107,11 @@ void ConcurrentMark::cleanup() {
// regions.
if (G1ScrubRemSets) {
double rs_scrub_start = os::elapsedTime();
- G1ParScrubRemSetTask g1_par_scrub_rs_task(g1h, &_region_bm, &_card_bm);
+ G1ParScrubRemSetTask g1_par_scrub_rs_task(g1h, &_region_bm, &_card_bm, n_workers);
if (G1CollectedHeap::use_parallel_gc_threads()) {
g1h->set_par_threads((int)n_workers);
g1h->workers()->run_task(&g1_par_scrub_rs_task);
g1h->set_par_threads(0);
-
- assert(g1h->check_heap_region_claim_values(
- HeapRegion::ScrubRemSetClaimValue),
- "sanity check");
} else {
g1_par_scrub_rs_task.work(0);
}
@@ -3299,6 +3287,7 @@ protected:
BitMap* _cm_card_bm;
uint _max_worker_id;
int _active_workers;
+ HeapRegionClaimer _hrclaimer;
public:
G1AggregateCountDataTask(G1CollectedHeap* g1h,
@@ -3309,15 +3298,14 @@ public:
AbstractGangTask("Count Aggregation"),
_g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm),
_max_worker_id(max_worker_id),
- _active_workers(n_workers) { }
+ _active_workers(n_workers),
+ _hrclaimer(_active_workers) { }
void work(uint worker_id) {
AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id);
if (G1CollectedHeap::use_parallel_gc_threads()) {
- _g1h->heap_region_par_iterate_chunked(&cl, worker_id,
- _active_workers,
- HeapRegion::AggregateCountClaimValue);
+ _g1h->heap_region_par_iterate_chunked(&cl, worker_id, &_hrclaimer);
} else {
_g1h->heap_region_iterate(&cl);
}
@@ -3334,15 +3322,9 @@ void ConcurrentMark::aggregate_count_data() {
_max_worker_id, n_workers);
if (G1CollectedHeap::use_parallel_gc_threads()) {
- assert(_g1h->check_heap_region_claim_values(HeapRegion::InitialClaimValue),
- "sanity check");
_g1h->set_par_threads(n_workers);
_g1h->workers()->run_task(&g1_par_agg_task);
_g1h->set_par_threads(0);
-
- assert(_g1h->check_heap_region_claim_values(HeapRegion::AggregateCountClaimValue),
- "sanity check");
- _g1h->reset_heap_region_claim_values();
} else {
g1_par_agg_task.work(0);
}
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp
index b2d3b282b..912acdbe0 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp
@@ -134,7 +134,9 @@ inline HeapWord*
G1BlockOffsetArray::block_at_or_preceding(const void* addr,
bool has_max_index,
size_t max_index) const {
- assert(_array->offset_array(0) == 0, "objects can't cross covered areas");
+ assert(_array->offset_array(_array->index_for(
+ G1CollectedHeap::heap()->heap_region_containing(addr)->bottom())) == 0,
+ "objects can't cross covered areas");
size_t index = _array->index_for(addr);
// We must make sure that the offset table entry we use is valid. If
// "addr" is past the end, start at the last known one and go forward.
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
index ce015b85d..1afc2e331 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
@@ -383,7 +383,6 @@ void G1RegionMappingChangedListener::on_commit(uint start_idx, size_t num_region
void G1CollectedHeap::run_task(AbstractGangTask* task) {
workers()->run_task(task);
- reset_heap_region_claim_values();
}
void G1CollectedHeap::push_dirty_cards_region(HeapRegion* hr)
@@ -1215,17 +1214,17 @@ public:
class ParRebuildRSTask: public AbstractGangTask {
G1CollectedHeap* _g1;
+ HeapRegionClaimer _hrclaimer;
+
public:
ParRebuildRSTask(G1CollectedHeap* g1)
: AbstractGangTask("ParRebuildRSTask"),
- _g1(g1)
+ _g1(g1), _hrclaimer(g1->workers()->active_workers())
{ }
void work(uint worker_id) {
RebuildRSOutOfRegionClosure rebuild_rs(_g1, worker_id);
- _g1->heap_region_par_iterate_chunked(&rebuild_rs, worker_id,
- _g1->workers()->active_workers(),
- HeapRegion::RebuildRSClaimValue);
+ _g1->heap_region_par_iterate_chunked(&rebuild_rs, worker_id, &_hrclaimer);
}
};
@@ -1454,8 +1453,6 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
set_par_threads(n_workers);
ParRebuildRSTask rebuild_rs_task(this);
- assert(check_heap_region_claim_values(
- HeapRegion::InitialClaimValue), "sanity check");
assert(UseDynamicNumberOfGCThreads ||
workers()->active_workers() == workers()->total_workers(),
"Unless dynamic should use total workers");
@@ -1465,9 +1462,6 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
set_par_threads(workers()->active_workers());
workers()->run_task(&rebuild_rs_task);
set_par_threads(0);
- assert(check_heap_region_claim_values(
- HeapRegion::RebuildRSClaimValue), "sanity check");
- reset_heap_region_claim_values();
} else {
RebuildRSOutOfRegionClosure rebuild_rs(this);
heap_region_iterate(&rebuild_rs);
@@ -1553,7 +1547,6 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
gc_timer->register_gc_end();
gc_tracer->report_gc_end(gc_timer->gc_end(), gc_timer->time_partitions());
}
-
return true;
}
@@ -1574,8 +1567,8 @@ G1CollectedHeap::
resize_if_necessary_after_full_collection(size_t word_size) {
// Include the current allocation, if any, and bytes that will be
// pre-allocated to support collections, as "used".
- const size_t used_after_gc = used();
const size_t capacity_after_gc = capacity();
+ const size_t used_after_gc = capacity_after_gc - num_free_regions() * HeapRegion::GrainBytes;
const size_t free_after_gc = capacity_after_gc - used_after_gc;
// This is enforced in arguments.cpp.
@@ -2678,13 +2671,15 @@ class G1ParallelObjectIterator : public ParallelObjectIterator {
private:
G1CollectedHeap* _heap;
uint _num_threads;
+ HeapRegionClaimer _claimer;
public:
G1ParallelObjectIterator(uint thread_num) :
- _heap(G1CollectedHeap::heap()),_num_threads(thread_num) {}
+ _heap(G1CollectedHeap::heap()),_num_threads(thread_num),
+ _claimer(thread_num) { }
virtual void object_iterate(ObjectClosure* cl, uint worker_id) {
- _heap->object_iterate_parallel(cl, worker_id,_num_threads);
+ _heap->object_iterate_parallel(cl, worker_id, &_claimer);
}
};
@@ -2692,9 +2687,10 @@ ParallelObjectIterator* G1CollectedHeap::parallel_object_iterator(uint thread_nu
return new G1ParallelObjectIterator(thread_num);
}
-void G1CollectedHeap::object_iterate_parallel(ObjectClosure* cl, uint worker_id, uint num_workers) {
+void G1CollectedHeap::object_iterate_parallel(ObjectClosure* cl, uint worker_id,
+ HeapRegionClaimer* claimer) {
IterateObjectClosureRegionClosure blk(cl);
- heap_region_par_iterate_chunked(&blk, worker_id, num_workers, HeapRegion::ParInspectClaimValue);
+ heap_region_par_iterate_chunked(&blk, worker_id, claimer);
}
@@ -2722,109 +2718,10 @@ void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const {
void
G1CollectedHeap::heap_region_par_iterate_chunked(HeapRegionClosure* cl,
uint worker_id,
- uint num_workers,
- jint claim_value) const {
- _hrm.par_iterate(cl, worker_id, num_workers, claim_value);
-}
-
-class ResetClaimValuesClosure: public HeapRegionClosure {
-public:
- bool doHeapRegion(HeapRegion* r) {
- r->set_claim_value(HeapRegion::InitialClaimValue);
- return false;
- }
-};
-
-void G1CollectedHeap::reset_heap_region_claim_values() {
- ResetClaimValuesClosure blk;
- heap_region_iterate(&blk);
-}
-
-void G1CollectedHeap::reset_cset_heap_region_claim_values() {
- ResetClaimValuesClosure blk;
- collection_set_iterate(&blk);
-}
-
-#ifdef ASSERT
-// This checks whether all regions in the heap have the correct claim
-// value. I also piggy-backed on this a check to ensure that the
-// humongous_start_region() information on "continues humongous"
-// regions is correct.
-
-class CheckClaimValuesClosure : public HeapRegionClosure {
-private:
- jint _claim_value;
- uint _failures;
- HeapRegion* _sh_region;
-
-public:
- CheckClaimValuesClosure(jint claim_value) :
- _claim_value(claim_value), _failures(0), _sh_region(NULL) { }
- bool doHeapRegion(HeapRegion* r) {
- if (r->claim_value() != _claim_value) {
- gclog_or_tty->print_cr("Region " HR_FORMAT ", "
- "claim value = %d, should be %d",
- HR_FORMAT_PARAMS(r),
- r->claim_value(), _claim_value);
- ++_failures;
- }
- if (!r->isHumongous()) {
- _sh_region = NULL;
- } else if (r->startsHumongous()) {
- _sh_region = r;
- } else if (r->continuesHumongous()) {
- if (r->humongous_start_region() != _sh_region) {
- gclog_or_tty->print_cr("Region " HR_FORMAT ", "
- "HS = " PTR_FORMAT ", should be " PTR_FORMAT,
- HR_FORMAT_PARAMS(r),
- p2i(r->humongous_start_region()),
- p2i(_sh_region));
- ++_failures;
- }
- }
- return false;
- }
- uint failures() { return _failures; }
-};
-
-bool G1CollectedHeap::check_heap_region_claim_values(jint claim_value) {
- CheckClaimValuesClosure cl(claim_value);
- heap_region_iterate(&cl);
- return cl.failures() == 0;
+ HeapRegionClaimer *hrclaimer) const {
+ _hrm.par_iterate(cl, worker_id, hrclaimer);
}
-class CheckClaimValuesInCSetHRClosure: public HeapRegionClosure {
-private:
- jint _claim_value;
- uint _failures;
-
-public:
- CheckClaimValuesInCSetHRClosure(jint claim_value) :
- _claim_value(claim_value), _failures(0) { }
-
- uint failures() { return _failures; }
-
- bool doHeapRegion(HeapRegion* hr) {
- assert(hr->in_collection_set(), "how?");
- assert(!hr->isHumongous(), "H-region in CSet");
- if (hr->claim_value() != _claim_value) {
- gclog_or_tty->print_cr("CSet Region " HR_FORMAT ", "
- "claim value = %d, should be %d",
- HR_FORMAT_PARAMS(hr),
- hr->claim_value(), _claim_value);
- _failures += 1;
- }
- return false;
- }
-};
-
-bool G1CollectedHeap::check_cset_heap_region_claim_values(jint claim_value) {
- CheckClaimValuesInCSetHRClosure cl(claim_value);
- collection_set_iterate(&cl);
- return cl.failures() == 0;
-}
-#endif // ASSERT
-
// Clear the cached CSet starting regions and (more importantly)
// the time stamps. Called when we reset the GC time stamp.
void G1CollectedHeap::clear_cset_start_regions() {
@@ -3348,6 +3245,7 @@ private:
G1CollectedHeap* _g1h;
VerifyOption _vo;
bool _failures;
+ HeapRegionClaimer _hrclaimer;
public:
// _vo == UsePrevMarking -> use "prev" marking information,
@@ -3357,7 +3255,8 @@ public:
AbstractGangTask("Parallel verify task"),
_g1h(g1h),
_vo(vo),
- _failures(false) { }
+ _failures(false),
+ _hrclaimer(g1h->workers()->active_workers()) { }
bool failures() {
return _failures;
@@ -3366,9 +3265,7 @@ public:
void work(uint worker_id) {
HandleMark hm;
VerifyRegionClosure blk(true, _vo);
- _g1h->heap_region_par_iterate_chunked(&blk, worker_id,
- _g1h->workers()->active_workers(),
- HeapRegion::ParVerifyClaimValue);
+ _g1h->heap_region_par_iterate_chunked(&blk, worker_id, &_hrclaimer);
if (blk.failures()) {
_failures = true;
}
@@ -3411,9 +3308,6 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) {
if (!silent) { gclog_or_tty->print("HeapRegions "); }
if (GCParallelVerificationEnabled && ParallelGCThreads > 1) {
- assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
- "sanity check");
-
G1ParVerifyTask task(this, vo);
assert(UseDynamicNumberOfGCThreads ||
workers()->active_workers() == workers()->total_workers(),
@@ -3425,16 +3319,6 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) {
if (task.failures()) {
failures = true;
}
-
- // Checks that the expected amount of parallel work was done.
- // The implication is that n_workers is > 0.
- assert(check_heap_region_claim_values(HeapRegion::ParVerifyClaimValue),
- "sanity check");
-
- reset_heap_region_claim_values();
-
- assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
- "sanity check");
} else {
VerifyRegionClosure blk(false, vo);
heap_region_iterate(&blk);
@@ -4164,8 +4048,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
}
assert(check_young_list_well_formed(), "young list should be well formed");
- assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
- "sanity check");
// Don't dynamically change the number of GC threads this early. A value of
// 0 is used to indicate serial work. When parallel work is done,
@@ -4508,8 +4390,6 @@ void G1CollectedHeap::finalize_for_evac_failure() {
}
void G1CollectedHeap::remove_self_forwarding_pointers() {
- assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
-
double remove_self_forwards_start = os::elapsedTime();
G1ParRemoveSelfForwardPtrsTask rsfp_task(this);
@@ -4522,13 +4402,6 @@ void G1CollectedHeap::remove_self_forwarding_pointers() {
rsfp_task.work(0);
}
- assert(check_cset_heap_region_claim_values(HeapRegion::ParEvacFailureClaimValue), "sanity");
-
- // Reset the claim values in the regions in the collection set.
- reset_cset_heap_region_claim_values();
-
- assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
-
// Now restore saved marks, if any.
assert(_objs_with_preserved_marks.size() ==
_preserved_marks_of_objs.size(), "Both or none.");
@@ -6000,11 +5873,6 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
purge_code_root_memory();
- if (g1_policy()->during_initial_mark_pause()) {
- // Reset the claim values set during marking the strong code roots
- reset_heap_region_claim_values();
- }
-
finalize_for_evac_failure();
if (evacuation_failed()) {
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
index f4ab7c0bd..2858ebfba 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
@@ -216,6 +216,7 @@ class G1CollectedHeap : public SharedHeap {
friend class CountRCClosure;
friend class EvacPopObjClosure;
friend class G1ParCleanupCTTask;
+ friend class HeapRegionClaimer;
friend class G1FreeHumongousRegionClosure;
friend class FreeRegionList;
@@ -1294,7 +1295,7 @@ public:
void cleanUpCardTable();
// Iteration functions.
- void object_iterate_parallel(ObjectClosure* cl, uint worker_id, uint num_workers);
+ void object_iterate_parallel(ObjectClosure* cl, uint worker_id, HeapRegionClaimer* claimer);
// Iterate over all the ref-containing fields of all objects, calling
// "cl.do_oop" on each.
@@ -1338,23 +1339,7 @@ public:
// i.e., that a closure never attempt to abort a traversal.
void heap_region_par_iterate_chunked(HeapRegionClosure* cl,
uint worker_id,
- uint num_workers,
- jint claim_value) const;
-
- // It resets all the region claim values to the default.
- void reset_heap_region_claim_values();
-
- // Resets the claim values of regions in the current
- // collection set to the default.
- void reset_cset_heap_region_claim_values();
-
-#ifdef ASSERT
- bool check_heap_region_claim_values(jint claim_value);
-
- // Same as the routine above but only checks regions in the
- // current collection set.
- bool check_cset_heap_region_claim_values(jint claim_value);
-#endif // ASSERT
+ HeapRegionClaimer *hrclaimer) const;
// Clear the cached cset start regions and (more importantly)
// the time stamps. Called when we reset the GC time stamp.
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
index 237932465..6d817883a 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
@@ -1606,19 +1606,19 @@ class ParKnownGarbageTask: public AbstractGangTask {
CollectionSetChooser* _hrSorted;
uint _chunk_size;
G1CollectedHeap* _g1;
+ HeapRegionClaimer _hrclaimer;
+
public:
- ParKnownGarbageTask(CollectionSetChooser* hrSorted, uint chunk_size) :
+ ParKnownGarbageTask(CollectionSetChooser* hrSorted, uint chunk_size, uint n_workers) :
AbstractGangTask("ParKnownGarbageTask"),
_hrSorted(hrSorted), _chunk_size(chunk_size),
- _g1(G1CollectedHeap::heap()) { }
+ _g1(G1CollectedHeap::heap()), _hrclaimer(n_workers) { }
void work(uint worker_id) {
ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted, _chunk_size);
// Back to zero for the claim value.
- _g1->heap_region_par_iterate_chunked(&parKnownGarbageCl, worker_id,
- _g1->workers()->active_workers(),
- HeapRegion::InitialClaimValue);
+ _g1->heap_region_par_iterate_chunked(&parKnownGarbageCl, worker_id, &_hrclaimer);
}
};
@@ -1650,11 +1650,9 @@ G1CollectorPolicy::record_concurrent_mark_cleanup_end(int no_of_gc_threads) {
_collectionSetChooser->prepare_for_par_region_addition(_g1->num_regions(),
WorkUnit);
ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser,
- (int) WorkUnit);
+ (int) WorkUnit,
+ no_of_gc_threads);
_g1->workers()->run_task(&parKnownGarbageTask);
-
- assert(_g1->check_heap_region_claim_values(HeapRegion::InitialClaimValue),
- "sanity check");
} else {
KnownGarbageClosure knownGarbagecl(_collectionSetChooser);
_g1->heap_region_iterate(&knownGarbagecl);
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp
index e62834010..f3930a89d 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp
@@ -177,15 +177,16 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure {
G1CollectedHeap* _g1h;
ConcurrentMark* _cm;
uint _worker_id;
+ HeapRegionClaimer* _hrclaimer;
DirtyCardQueue _dcq;
UpdateRSetDeferred _update_rset_cl;
public:
RemoveSelfForwardPtrHRClosure(G1CollectedHeap* g1h,
- uint worker_id) :
+ uint worker_id, HeapRegionClaimer* hrclaimer) :
_g1h(g1h), _dcq(&g1h->dirty_card_queue_set()), _update_rset_cl(g1h, &_dcq),
- _worker_id(worker_id), _cm(_g1h->concurrent_mark()) {
+ _worker_id(worker_id), _hrclaimer(hrclaimer), _cm(_g1h->concurrent_mark()) {
}
bool doHeapRegion(HeapRegion *hr) {
@@ -195,7 +196,7 @@ public:
assert(!hr->isHumongous(), "sanity");
assert(hr->in_collection_set(), "bad CS");
- if (hr->claimHeapRegion(HeapRegion::ParEvacFailureClaimValue)) {
+ if (_hrclaimer->claim_region(hr->hrm_index())) {
if (hr->evacuation_failed()) {
RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, &_update_rset_cl,
during_initial_mark,
@@ -233,14 +234,16 @@ public:
class G1ParRemoveSelfForwardPtrsTask: public AbstractGangTask {
protected:
G1CollectedHeap* _g1h;
+ HeapRegionClaimer _hrclaimer;
public:
G1ParRemoveSelfForwardPtrsTask(G1CollectedHeap* g1h) :
AbstractGangTask("G1 Remove Self-forwarding Pointers"),
- _g1h(g1h) { }
+ _g1h(g1h),
+ _hrclaimer(G1CollectedHeap::heap()->workers()->active_workers()) { }
void work(uint worker_id) {
- RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, worker_id);
+ RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, worker_id, &_hrclaimer);
HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id);
_g1h->collection_set_iterate_from(hr, &rsfp_cl);
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
index 24115acaf..2a14b967a 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
@@ -34,6 +34,7 @@
#include "gc_implementation/g1/g1RootProcessor.hpp"
#include "gc_implementation/g1/g1StringDedup.hpp"
#include "gc_implementation/shared/gcHeapSummary.hpp"
+#include "gc_implementation/shared/liveRange.hpp"
#include "gc_implementation/shared/gcTimer.hpp"
#include "gc_implementation/shared/gcTrace.hpp"
#include "gc_implementation/shared/gcTraceTime.hpp"
@@ -58,9 +59,173 @@
class HeapRegion;
+
+class G1FullGCCompactionPoint : public CompactPoint {
+ HeapRegion* _current_region;
+ HeapWord* _threshold;
+ HeapWord* _compaction_top;
+ GrowableArray<HeapRegion*>* _compaction_regions;
+ GrowableArrayIterator<HeapRegion*> _compaction_region_iterator;
+ GrowableArray<HeapRegion*>* _marked_huge_regions;
+
+ virtual HeapRegion* next_compaction_space() {
+ HeapRegion* next = *(++_compaction_region_iterator);
+ assert(next != NULL, "Must return valid region");
+ return next;
+ }
+
+public:
+ G1FullGCCompactionPoint() :
+ _current_region(NULL),
+ _threshold(NULL),
+ _compaction_top(NULL),
+ _compaction_regions(new (ResourceObj::C_HEAP, mtGC)
+ GrowableArray<HeapRegion*>(32/* initial size */, true, mtGC)),
+ _compaction_region_iterator(_compaction_regions->begin()),
+ _marked_huge_regions(new (ResourceObj::C_HEAP, mtGC)
+ GrowableArray<HeapRegion*>(32/* initial size */, true, mtGC)) {
+ }
+ virtual ~G1FullGCCompactionPoint() {
+ delete _compaction_regions;
+ delete _marked_huge_regions;
+ }
+
+ bool is_initialized() {
+ return _current_region != NULL;
+ }
+
+ void initialize(HeapRegion* hr, bool init_threshold) {
+ _current_region = hr;
+ initialize_values(init_threshold);
+ }
+
+ void initialize_values(bool init_threshold) {
+ _compaction_top = _current_region->compaction_top();
+ if (init_threshold) {
+ _threshold = _current_region->initialize_threshold();
+ }
+ }
+
+ void update() {
+ if (is_initialized()) {
+ _current_region->set_compaction_top(_compaction_top);
+ }
+ }
+
+ bool object_will_fit(size_t size) {
+ size_t space_left = pointer_delta(_current_region->end(), _compaction_top);
+ return size <= space_left;
+ }
+
+ void switch_region() {
+ // Save compaction top in the region.
+ _current_region->set_compaction_top(_compaction_top);
+ // Get the next region and re-initialize the values.
+ _current_region = next_compaction_space();
+ initialize_values(true);
+ }
+
+ void forward(oop object, size_t size) {
+ assert(_current_region != NULL, "Must have been initialized");
+
+ // Ensure the object fit in the current region.
+ while (!object_will_fit(size)) {
+ switch_region();
+ }
+
+ if ((HeapWord*)object != _compaction_top) {
+ object->forward_to(oop(_compaction_top));
+ } else {
+ object->init_mark();
+ }
+
+ // Update compaction values.
+ _compaction_top += size;
+ if (_compaction_top > _threshold) {
+ _threshold = _current_region->cross_threshold(_compaction_top - size, _compaction_top);
+ }
+ }
+
+ void add(HeapRegion* hr) {
+ _compaction_regions->append(hr);
+ }
+ void add_huge(HeapRegion* hr) {
+ _marked_huge_regions->append(hr);
+ }
+ HeapRegion* current_region() {
+ return *_compaction_region_iterator;
+ }
+ const GrowableArray<HeapRegion*>* regions() const {
+ return _compaction_regions;
+ }
+ const GrowableArray<HeapRegion*>* huge_regions() const {
+ return _marked_huge_regions;
+ }
+
+ HeapRegion* remove_last() {
+ return _compaction_regions->pop();
+ }
+
+ bool has_region() {
+ return !_compaction_regions->is_empty();
+ }
+};
+
+class G1FullGCCompactionPoints : StackObj {
+private:
+ G1FullGCCompactionPoint** _cps;
+ uint _num_workers;
+ G1FullGCCompactionPoint* _serial_compaction_point;
+public:
+ G1FullGCCompactionPoints(uint num_workers) : _num_workers(num_workers) {
+ _cps = NEW_C_HEAP_ARRAY(G1FullGCCompactionPoint*, _num_workers, mtGC);
+ for (uint i = 0; i < _num_workers; i++) {
+ _cps[i] = new G1FullGCCompactionPoint();
+ }
+ _serial_compaction_point = new G1FullGCCompactionPoint();
+ }
+ ~G1FullGCCompactionPoints() {
+ for (uint i = 0; i < _num_workers; i++) {
+ delete _cps[i];
+ }
+ FREE_C_HEAP_ARRAY(G1FullGCCompactionPoint*, _cps, mtGC);
+ delete _serial_compaction_point;
+ }
+
+ G1FullGCCompactionPoint* cp_at(uint i) { return _cps[i]; }
+ uint num_workers() { return _num_workers; }
+
+ G1FullGCCompactionPoint* serial_compaction_point() { return _serial_compaction_point; }
+};
+
+size_t G1RePrepareClosure::apply(oop obj) {
+ // We only re-prepare objects forwarded within the current region, so
+ // skip objects that are already forwarded to another region.
+ oop forwarded_to = obj->forwardee();
+
+ if (forwarded_to != NULL && !_current->is_in(forwarded_to)) {
+ return obj->size();
+ }
+
+ // Get size and forward.
+ size_t size = obj->size();
+ _cp->forward(obj, size);
+
+ return size;
+}
+
+bool G1MarkSweep::_parallel_prepare_compact = false;
+bool G1MarkSweep::_parallel_adjust = false;
+
void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
bool clear_all_softrefs) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
+ uint active_workers = G1CollectedHeap::heap()->workers()->active_workers();
+
+ if (G1ParallelFullGC) {
+ _parallel_prepare_compact = true;
+ _parallel_adjust = true;
+ }
SharedHeap* sh = SharedHeap::heap();
#ifdef ASSERT
@@ -89,16 +254,20 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
// The marking doesn't preserve the marks of biased objects.
BiasedLocking::preserve_marks();
- mark_sweep_phase1(marked_for_unloading, clear_all_softrefs);
+ {
+ G1FullGCCompactionPoints cps(active_workers);
+
+ mark_sweep_phase1(marked_for_unloading, clear_all_softrefs);
- mark_sweep_phase2();
+ mark_sweep_phase2(&cps);
- // Don't add any more derived pointers during phase3
- COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
+ // Don't add any more derived pointers during phase3
+ COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
- mark_sweep_phase3();
+ mark_sweep_phase3();
- mark_sweep_phase4();
+ mark_sweep_phase4(&cps);
+ }
GenMarkSweep::restore_marks();
BiasedLocking::restore_marks();
@@ -209,7 +378,170 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
}
-void G1MarkSweep::mark_sweep_phase2() {
+class G1ParallelPrepareCompactClosure : public HeapRegionClosure {
+protected:
+ G1CollectedHeap* _g1h;
+ ModRefBarrierSet* _mrbs;
+ G1FullGCCompactionPoint* _cp;
+ GrowableArray<HeapRegion*>* _start_humongous_regions_to_be_freed;
+
+protected:
+ virtual void prepare_for_compaction(HeapRegion* hr, HeapWord* end) {
+ if (_cp->space == NULL) {
+ _cp->space = hr;
+ _cp->threshold = hr->initialize_threshold();
+ }
+ _cp->add(hr);
+ hr->prepare_for_compaction(_cp);
+ // Also clear the part of the card table that will be unused after compaction.
+ _mrbs->clear(MemRegion(hr->compaction_top(), end));
+ }
+
+public:
+ G1ParallelPrepareCompactClosure(G1FullGCCompactionPoint* cp) :
+ _g1h(G1CollectedHeap::heap()),
+ _mrbs(_g1h->g1_barrier_set()),
+ _cp(cp),
+ _start_humongous_regions_to_be_freed(
+ new (ResourceObj::C_HEAP, mtGC) GrowableArray<HeapRegion*>(32, true, mtGC)) {
+ }
+
+ ~G1ParallelPrepareCompactClosure() {
+ delete _start_humongous_regions_to_be_freed;
+ }
+
+ const GrowableArray<HeapRegion*>* start_humongous_regions_to_be_freed() const {
+ return _start_humongous_regions_to_be_freed;
+ }
+
+ bool doHeapRegion(HeapRegion* hr) {
+ if (hr->isHumongous()) {
+ if (hr->startsHumongous()) {
+ oop obj = oop(hr->bottom());
+ if (obj->is_gc_marked()) {
+ obj->forward_to(obj);
+ _cp->add_huge(hr);
+ } else {
+ _start_humongous_regions_to_be_freed->append(hr);
+ }
+ } else {
+ assert(hr->continuesHumongous(), "Invalid humongous.");
+ }
+ } else {
+ prepare_for_compaction(hr, hr->end());
+ }
+ return false;
+ }
+
+ bool freed_regions() {
+ if (_start_humongous_regions_to_be_freed->length() != 0) {
+ return true;
+ }
+
+ if (!_cp->has_region()) {
+ return false;
+ }
+
+ if (_cp->current_region() != _cp->regions()->top()) {
+ return true;
+ }
+
+ return false;
+ }
+};
+
+class G1FullGCPrepareTask : public AbstractGangTask {
+protected:
+ HeapRegionClaimer _hrclaimer;
+ G1FullGCCompactionPoints* _cps;
+ GrowableArray<HeapRegion*>* _all_start_humongous_regions_to_be_freed;
+ HeapRegionSetCount _humongous_regions_removed;
+ bool _freed_regions;
+
+protected:
+ void free_humongous_region(HeapRegion* hr) {
+ FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep");
+ assert(hr->startsHumongous(),
+ "Only the start of a humongous region should be freed.");
+ hr->set_containing_set(NULL);
+ _humongous_regions_removed.increment(1u, hr->capacity());
+ G1CollectedHeap::heap()->free_humongous_region(hr, &dummy_free_list, false);
+ dummy_free_list.remove_all();
+ }
+
+ void update_sets() {
+ // We'll recalculate total used bytes and recreate the free list
+ // at the end of the GC, so no point in updating those values here.
+ HeapRegionSetCount empty_set;
+ G1CollectedHeap::heap()->remove_from_old_sets(empty_set, _humongous_regions_removed);
+ }
+
+public:
+ G1FullGCPrepareTask(G1FullGCCompactionPoints* cps) :
+ AbstractGangTask("G1 Prepare Task"),
+ _hrclaimer(G1CollectedHeap::heap()->workers()->active_workers()),
+ _cps(cps),
+ _all_start_humongous_regions_to_be_freed(
+ new (ResourceObj::C_HEAP, mtGC) GrowableArray<HeapRegion*>(32, true, mtGC)),
+ _humongous_regions_removed(),
+ _freed_regions(false) { }
+
+ virtual ~G1FullGCPrepareTask() {
+ delete _all_start_humongous_regions_to_be_freed;
+ }
+
+ void work(uint worker_id) {
+ Ticks start = Ticks::now();
+ G1ParallelPrepareCompactClosure closure(_cps->cp_at(worker_id));
+ G1CollectedHeap::heap()->heap_region_par_iterate_chunked(&closure, worker_id, &_hrclaimer);
+ {
+ MutexLockerEx mu(FreeHumongousRegions_lock, Mutex::_no_safepoint_check_flag);
+ _all_start_humongous_regions_to_be_freed->appendAll(closure.start_humongous_regions_to_be_freed());
+ if (closure.freed_regions()) {
+ _freed_regions = true;
+ }
+ }
+ }
+
+ void free_humongous_regions() {
+ for (GrowableArrayIterator<HeapRegion*> it = _all_start_humongous_regions_to_be_freed->begin();
+ it != _all_start_humongous_regions_to_be_freed->end();
+ ++it) {
+ free_humongous_region(*it);
+ }
+ update_sets();
+ }
+
+ bool freed_regions() {
+ return _freed_regions;
+ }
+
+ void prepare_serial_compaction() {
+ for (uint i = 0; i < _cps->num_workers(); i++) {
+ G1FullGCCompactionPoint* cp = _cps->cp_at(i);
+ if (cp->has_region()) {
+ _cps->serial_compaction_point()->add(cp->remove_last());
+ }
+ }
+
+ G1FullGCCompactionPoint* cp = _cps->serial_compaction_point();
+ for (GrowableArrayIterator<HeapRegion*> it = cp->regions()->begin(); it != cp->regions()->end(); ++it) {
+ HeapRegion* current = *it;
+ if (!cp->is_initialized()) {
+ // Initialize the compaction point. Nothing more is needed for the first heap region
+ // since it is already prepared for compaction.
+ cp->initialize(current, false);
+ } else {
+ G1RePrepareClosure re_prepare(cp, current);
+ current->set_compaction_top(current->bottom());
+ current->apply_to_marked_objects(&re_prepare);
+ }
+ }
+ cp->update();
+ }
+};
+
+void G1MarkSweep::mark_sweep_phase2(G1FullGCCompactionPoints* cps) {
// Now all live objects are marked, compute the new object addresses.
// It is not required that we traverse spaces in the same order in
@@ -219,9 +551,21 @@ void G1MarkSweep::mark_sweep_phase2() {
GCTraceTime tm("phase 2", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id());
GenMarkSweep::trace("2");
- prepare_compaction();
+ if (!_parallel_prepare_compact) {
+ prepare_compaction();
+ } else {
+ G1FullGCPrepareTask task(cps);
+ FlexibleWorkGang* flexible = G1CollectedHeap::heap()->workers();
+ flexible->run_task(&task);
+ task.free_humongous_regions();
+
+ if (!task.freed_regions()) {
+ task.prepare_serial_compaction();
+ }
+ }
}
+
class G1AdjustPointersClosure: public HeapRegionClosure {
public:
bool doHeapRegion(HeapRegion* r) {
@@ -240,6 +584,25 @@ class G1AdjustPointersClosure: public HeapRegionClosure {
}
};
+class G1FullGCAdjustTask : public AbstractGangTask {
+ HeapRegionClaimer _hrclaimer;
+ G1AdjustPointersClosure _adjust;
+
+public:
+ G1FullGCAdjustTask() :
+ AbstractGangTask("G1 Adjust Task"),
+ _hrclaimer(G1CollectedHeap::heap()->workers()->active_workers()),
+ _adjust() {
+ }
+ virtual ~G1FullGCAdjustTask() { }
+
+ void work(uint worker_id) {
+ Ticks start = Ticks::now();
+ G1AdjustPointersClosure blk;
+ G1CollectedHeap::heap()->heap_region_par_iterate_chunked(&blk, worker_id, &_hrclaimer);
+ }
+};
+
void G1MarkSweep::mark_sweep_phase3() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
@@ -250,7 +613,8 @@ void G1MarkSweep::mark_sweep_phase3() {
// Need cleared claim bits for the roots processing
ClassLoaderDataGraph::clear_claimed_marks();
- CodeBlobToOopClosure adjust_code_closure(&GenMarkSweep::adjust_pointer_closure, CodeBlobToOopClosure::FixRelocations);
+ CodeBlobToOopClosure adjust_code_closure(&GenMarkSweep::adjust_pointer_closure,
+ CodeBlobToOopClosure::FixRelocations);
{
G1RootProcessor root_processor(g1h);
root_processor.process_all_roots(&GenMarkSweep::adjust_pointer_closure,
@@ -272,13 +636,19 @@ void G1MarkSweep::mark_sweep_phase3() {
GenMarkSweep::adjust_marks();
- G1AdjustPointersClosure blk;
- g1h->heap_region_iterate(&blk);
+ if (!_parallel_adjust) {
+ G1AdjustPointersClosure blk;
+ g1h->heap_region_iterate(&blk);
+ } else {
+ G1FullGCAdjustTask task;
+ FlexibleWorkGang* flexible = G1CollectedHeap::heap()->workers();
+ flexible->run_task(&task);
+ }
}
+
class G1SpaceCompactClosure: public HeapRegionClosure {
public:
- G1SpaceCompactClosure() {}
bool doHeapRegion(HeapRegion* hr) {
if (hr->isHumongous()) {
@@ -298,7 +668,60 @@ public:
}
};
-void G1MarkSweep::mark_sweep_phase4() {
+class G1FullGCCompactTask : public AbstractGangTask {
+ HeapRegionClaimer _hrclaimer;
+ G1FullGCCompactionPoints* _cps;
+
+ void compact_region(HeapRegion* hr) {
+ hr->compact();
+
+ hr->reset_after_compaction();
+ if (hr->used_region().is_empty()) {
+ hr->reset_bot();
+ }
+ }
+
+public:
+ G1FullGCCompactTask(G1FullGCCompactionPoints* cps) :
+ AbstractGangTask("G1 Compact Task"),
+ _hrclaimer(G1CollectedHeap::heap()->workers()->active_workers()),
+ _cps(cps) {
+ }
+ virtual ~G1FullGCCompactTask() { }
+
+ void work(uint worker_id) {
+ Ticks start = Ticks::now();
+ const GrowableArray<HeapRegion*>* compaction_queue = _cps->cp_at(worker_id)->regions();
+ for (GrowableArrayIterator<HeapRegion*> it = compaction_queue->begin();
+ it != compaction_queue->end();
+ ++it) {
+ HeapRegion* hr = *it;
+ compact_region(hr);
+ }
+
+ const GrowableArray<HeapRegion*>* marked_huge_regions = _cps->cp_at(worker_id)->huge_regions();
+ for (GrowableArrayIterator<HeapRegion*> it = marked_huge_regions->begin();
+ it != marked_huge_regions->end();
+ ++it) {
+ HeapRegion* hr = *it;
+ oop obj = oop(hr->bottom());
+ assert(obj->is_gc_marked(), "Must be");
+ obj->init_mark();
+ hr->reset_during_compaction();
+ }
+ }
+
+ void serial_compaction() {
+ const GrowableArray<HeapRegion*>* compaction_queue = _cps->serial_compaction_point()->regions();
+ for (GrowableArrayIterator<HeapRegion*> it = compaction_queue->begin();
+ it != compaction_queue->end();
+ ++it) {
+ compact_region(*it);
+ }
+ }
+};
+
+void G1MarkSweep::mark_sweep_phase4(G1FullGCCompactionPoints* cps) {
// All pointers are now adjusted, move objects accordingly
// The ValidateMarkSweep live oops tracking expects us to traverse spaces
@@ -310,72 +733,100 @@ void G1MarkSweep::mark_sweep_phase4() {
GCTraceTime tm("phase 4", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id());
GenMarkSweep::trace("4");
- G1SpaceCompactClosure blk;
- g1h->heap_region_iterate(&blk);
+ if (!_parallel_prepare_compact) {
+ G1SpaceCompactClosure blk;
+ g1h->heap_region_iterate(&blk);
+ } else {
+ G1FullGCCompactTask task(cps);
+ FlexibleWorkGang* flexible = G1CollectedHeap::heap()->workers();
+ flexible->run_task(&task);
+ if (cps->serial_compaction_point()->has_region()) {
+ task.serial_compaction();
+ }
+ }
}
-void G1MarkSweep::prepare_compaction_work(G1PrepareCompactClosure* blk) {
- G1CollectedHeap* g1h = G1CollectedHeap::heap();
- g1h->heap_region_iterate(blk);
- blk->update_sets();
-}
+class G1PrepareCompactClosure : public HeapRegionClosure {
+protected:
+ G1CollectedHeap* _g1h;
+ ModRefBarrierSet* _mrbs;
+ CompactPoint _cp;
+ HeapRegionSetCount _humongous_regions_removed;
+
+ virtual void prepare_for_compaction(HeapRegion* hr, HeapWord* end) {
+ // If this is the first live region that we came across which we can compact,
+ // initialize the CompactPoint.
+ if (!is_cp_initialized()) {
+ _cp.space = hr;
+ _cp.threshold = hr->initialize_threshold();
+ }
+ prepare_for_compaction_work(&_cp, hr, end);
+ }
-void G1PrepareCompactClosure::free_humongous_region(HeapRegion* hr) {
- HeapWord* end = hr->end();
- FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep");
+ void prepare_for_compaction_work(CompactPoint* cp, HeapRegion* hr, HeapWord* end) {
+ hr->prepare_for_compaction(cp);
+ // Also clear the part of the card table that will be unused after
+ // compaction.
+ _mrbs->clear(MemRegion(hr->compaction_top(), end));
+ }
- assert(hr->startsHumongous(),
- "Only the start of a humongous region should be freed.");
+ void free_humongous_region(HeapRegion* hr) {
+ HeapWord* end = hr->end();
+ FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep");
- hr->set_containing_set(NULL);
- _humongous_regions_removed.increment(1u, hr->capacity());
+ assert(hr->startsHumongous(),
+ "Only the start of a humongous region should be freed.");
- _g1h->free_humongous_region(hr, &dummy_free_list, false /* par */);
- prepare_for_compaction(hr, end);
- dummy_free_list.remove_all();
-}
+ hr->set_containing_set(NULL);
+ _humongous_regions_removed.increment(1u, hr->capacity());
-void G1PrepareCompactClosure::prepare_for_compaction(HeapRegion* hr, HeapWord* end) {
- // If this is the first live region that we came across which we can compact,
- // initialize the CompactPoint.
- if (!is_cp_initialized()) {
- _cp.space = hr;
- _cp.threshold = hr->initialize_threshold();
+ _g1h->free_humongous_region(hr, &dummy_free_list, false /* par */);
+ prepare_for_compaction(hr, end);
+ dummy_free_list.remove_all();
}
- prepare_for_compaction_work(&_cp, hr, end);
-}
-
-void G1PrepareCompactClosure::prepare_for_compaction_work(CompactPoint* cp,
- HeapRegion* hr,
- HeapWord* end) {
- hr->prepare_for_compaction(cp);
- // Also clear the part of the card table that will be unused after
- // compaction.
- _mrbs->clear(MemRegion(hr->compaction_top(), end));
-}
-void G1PrepareCompactClosure::update_sets() {
- // We'll recalculate total used bytes and recreate the free list
- // at the end of the GC, so no point in updating those values here.
- HeapRegionSetCount empty_set;
- _g1h->remove_from_old_sets(empty_set, _humongous_regions_removed);
-}
+ bool is_cp_initialized() const { return _cp.space != NULL; }
-bool G1PrepareCompactClosure::doHeapRegion(HeapRegion* hr) {
- if (hr->isHumongous()) {
- if (hr->startsHumongous()) {
- oop obj = oop(hr->bottom());
- if (obj->is_gc_marked()) {
- obj->forward_to(obj);
- } else {
- free_humongous_region(hr);
+public:
+ G1PrepareCompactClosure() :
+ _g1h(G1CollectedHeap::heap()),
+ _mrbs(_g1h->g1_barrier_set()),
+ _humongous_regions_removed() { }
+ ~G1PrepareCompactClosure() { }
+
+ void update_sets() {
+ // We'll recalculate total used bytes and recreate the free list
+ // at the end of the GC, so no point in updating those values here.
+ HeapRegionSetCount empty_set;
+ _g1h->remove_from_old_sets(empty_set, _humongous_regions_removed);
+ }
+ bool doHeapRegion(HeapRegion* hr) {
+ if (hr->isHumongous()) {
+ if (hr->startsHumongous()) {
+ oop obj = oop(hr->bottom());
+ if (obj->is_gc_marked()) {
+ obj->forward_to(obj);
+ } else {
+ free_humongous_region(hr);
+ }
+ } else {
+ assert(hr->continuesHumongous(), "Invalid humongous.");
}
} else {
- assert(hr->continuesHumongous(), "Invalid humongous.");
+ prepare_for_compaction(hr, hr->end());
}
- } else {
- prepare_for_compaction(hr, hr->end());
+ return false;
}
- return false;
+};
+
+void G1MarkSweep::prepare_compaction() {
+ G1PrepareCompactClosure blk;
+ G1MarkSweep::prepare_compaction_work(&blk);
+}
+
+void G1MarkSweep::prepare_compaction_work(G1PrepareCompactClosure* blk) {
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+ g1h->heap_region_iterate(blk);
+ blk->update_sets();
}
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp
index cdde980d3..82aa6b63e 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp
@@ -44,6 +44,21 @@ class ReferenceProcessor;
//
// Class unloading will only occur when a full gc is invoked.
class G1PrepareCompactClosure;
+class G1FullGCCompactionPoints;
+class G1FullGCCompactionPoint;
+
+class G1RePrepareClosure : public StackObj {
+ G1FullGCCompactionPoint* _cp;
+ HeapRegion* _current;
+
+ public:
+ G1RePrepareClosure(G1FullGCCompactionPoint* hrcp,
+ HeapRegion* hr) :
+ _cp(hrcp),
+ _current(hr) { }
+
+ size_t apply(oop obj);
+};
class G1MarkSweep : AllStatic {
friend class VM_G1MarkSweep;
@@ -57,43 +72,25 @@ class G1MarkSweep : AllStatic {
static STWGCTimer* gc_timer() { return GenMarkSweep::_gc_timer; }
static SerialOldTracer* gc_tracer() { return GenMarkSweep::_gc_tracer; }
+ private:
+ static bool _parallel_prepare_compact;
+ static bool _parallel_adjust;
+
private:
// Mark live objects
static void mark_sweep_phase1(bool& marked_for_deopt,
bool clear_all_softrefs);
// Calculate new addresses
- static void mark_sweep_phase2();
+ static void mark_sweep_phase2(G1FullGCCompactionPoints* cps);
// Update pointers
static void mark_sweep_phase3();
// Move objects to new positions
- static void mark_sweep_phase4();
+ static void mark_sweep_phase4(G1FullGCCompactionPoints* cps);
static void allocate_stacks();
static void prepare_compaction();
static void prepare_compaction_work(G1PrepareCompactClosure* blk);
};
-class G1PrepareCompactClosure : public HeapRegionClosure {
- protected:
- G1CollectedHeap* _g1h;
- ModRefBarrierSet* _mrbs;
- CompactPoint _cp;
- HeapRegionSetCount _humongous_regions_removed;
-
- virtual void prepare_for_compaction(HeapRegion* hr, HeapWord* end);
- void prepare_for_compaction_work(CompactPoint* cp, HeapRegion* hr, HeapWord* end);
- void free_humongous_region(HeapRegion* hr);
- bool is_cp_initialized() const { return _cp.space != NULL; }
-
- public:
- G1PrepareCompactClosure() :
- _g1h(G1CollectedHeap::heap()),
- _mrbs(_g1h->g1_barrier_set()),
- _humongous_regions_removed() { }
-
- void update_sets();
- bool doHeapRegion(HeapRegion* hr);
-};
-
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1MARKSWEEP_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep_ext.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep_ext.cpp
deleted file mode 100644
index 006e787be..000000000
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep_ext.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2001, 2014, 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc_implementation/g1/g1MarkSweep.hpp"
-
-void G1MarkSweep::prepare_compaction() {
- G1PrepareCompactClosure blk;
- G1MarkSweep::prepare_compaction_work(&blk);
-}
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp
index 471844444..b214c6b37 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp
@@ -410,12 +410,9 @@ void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) {
}
void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm,
- uint worker_num, int claim_val) {
+ uint worker_num, HeapRegionClaimer *hrclaimer) {
ScrubRSClosure scrub_cl(region_bm, card_bm);
- _g1->heap_region_par_iterate_chunked(&scrub_cl,
- worker_num,
- n_workers(),
- claim_val);
+ _g1->heap_region_par_iterate_chunked(&scrub_cl, worker_num, hrclaimer);
}
G1TriggerClosure::G1TriggerClosure() :
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp
index 9839e86c5..4a9b286a6 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp
@@ -131,7 +131,7 @@ public:
// parallel thread id of the current thread, and "claim_val" is the
// value that should be used to claim heap regions.
void scrub_par(BitMap* region_bm, BitMap* card_bm,
- uint worker_num, int claim_val);
+ uint worker_num, HeapRegionClaimer *hrclaimer);
// Refine the card corresponding to "card_ptr".
// If check_for_refs_into_cset is true, a true result is returned
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp
index db7ddeced..ee7f14278 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp
@@ -359,6 +359,9 @@
experimental(uintx, G1UncommitDelay, 50, \
"Starup delay in seconds for periodic uncommit.") \
\
+ product(bool, G1ParallelFullGC, false, \
+ "Enable Parallel Full GC for G1") \
+ \
G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp
index 131cdeacd..9b9afa335 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp
@@ -28,6 +28,7 @@
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1NUMA.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
+#include "gc_implementation/g1/g1MarkSweep.hpp"
#include "gc_implementation/g1/heapRegion.inline.hpp"
#include "gc_implementation/g1/heapRegionBounds.inline.hpp"
#include "gc_implementation/g1/heapRegionRemSet.hpp"
@@ -180,7 +181,6 @@ void HeapRegion::hr_clear(bool par, bool clear_space, bool locked) {
} else {
hrrs->clear();
}
- _claimed = InitialClaimValue;
}
zero_marked_bytes();
@@ -284,17 +284,6 @@ void HeapRegion::clear_humongous() {
_humongous_start_region = NULL;
}
-bool HeapRegion::claimHeapRegion(jint claimValue) {
- jint current = _claimed;
- if (current != claimValue) {
- jint res = Atomic::cmpxchg(claimValue, &_claimed, current);
- if (res == current) {
- return true;
- }
- }
- return false;
-}
-
HeapRegion::HeapRegion(uint hrm_index,
G1BlockOffsetSharedArray* sharedOffsetArray,
MemRegion mr) :
@@ -304,7 +293,7 @@ HeapRegion::HeapRegion(uint hrm_index,
_humongous_start_region(NULL),
_in_collection_set(false),
_next_in_special_set(NULL), _orig_end(NULL),
- _claimed(InitialClaimValue), _evacuation_failed(false),
+ _evacuation_failed(false),
_prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0),
_next_young_region(NULL),
_next_dirty_cards_region(NULL), _next(NULL), _prev(NULL),
@@ -327,7 +316,6 @@ void HeapRegion::initialize(MemRegion mr, bool clear_space, bool mangle_space) {
_in_collection_set = false;
_next_in_special_set = NULL;
_orig_end = NULL;
- _claimed = InitialClaimValue;
_evacuation_failed = false;
_prev_marked_bytes = 0;
_next_marked_bytes = 0;
@@ -1184,6 +1172,10 @@ void G1OffsetTableContigSpace::object_iterate(ObjectClosure* blk) {
}
}
+void G1OffsetTableContigSpace::apply_to_marked_objects(G1RePrepareClosure* closure) {
+ SCAN_AND_REPREPARE(closure);
+}
+
#define block_is_always_obj(q) true
void G1OffsetTableContigSpace::prepare_for_compaction(CompactPoint* cp) {
SCAN_AND_FORWARD(cp, top, block_is_always_obj, block_size);
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp
index bc9527a87..5d2415e84 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp
@@ -52,6 +52,7 @@ class HeapRegionRemSetIterator;
class HeapRegion;
class HeapRegionSetBase;
class nmethod;
+class G1RePrepareClosure;
#define HR_FORMAT "%u:(%s)[" PTR_FORMAT "," PTR_FORMAT "," PTR_FORMAT "]"
#define HR_FORMAT_PARAMS(_hr_) \
@@ -152,7 +153,7 @@ class G1OffsetTableContigSpace: public CompactibleSpace {
void object_iterate(ObjectClosure* blk);
void safe_object_iterate(ObjectClosure* blk);
-
+ void apply_to_marked_objects(G1RePrepareClosure* closure);
void set_bottom(HeapWord* value);
void set_end(HeapWord* value);
@@ -255,9 +256,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
HeapRegionSetBase* _containing_set;
#endif // ASSERT
- // For parallel heapRegion traversal.
- jint _claimed;
-
// We use concurrent marking to determine the amount of live data
// in each heap region.
size_t _prev_marked_bytes; // Bytes known to be live via last completed marking.
@@ -281,15 +279,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
// If a collection pause is in progress, this is the top at the start
// of that pause.
- void init_top_at_mark_start() {
- assert(_prev_marked_bytes == 0 &&
- _next_marked_bytes == 0,
- "Must be called after zero_marked_bytes.");
- HeapWord* bot = bottom();
- _prev_top_at_mark_start = bot;
- _next_top_at_mark_start = bot;
- }
-
// Cached attributes used in the collection set policy information
// The RSet length that was added to the total value
@@ -315,6 +304,15 @@ class HeapRegion: public G1OffsetTableContigSpace {
// there's clearing to be done ourselves. We also always mangle the space.
virtual void initialize(MemRegion mr, bool clear_space = false, bool mangle_space = SpaceDecorator::Mangle);
+ void init_top_at_mark_start() {
+ assert(_prev_marked_bytes == 0 &&
+ _next_marked_bytes == 0,
+ "Must be called after zero_marked_bytes.");
+ HeapWord* bot = bottom();
+ _prev_top_at_mark_start = bot;
+ _next_top_at_mark_start = bot;
+ }
+
static int LogOfHRGrainBytes;
static int LogOfHRGrainWords;
@@ -337,20 +335,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
// up once during initialization time.
static void setup_heap_region_size(size_t initial_heap_size, size_t max_heap_size);
- enum ClaimValues {
- InitialClaimValue = 0,
- FinalCountClaimValue = 1,
- NoteEndClaimValue = 2,
- ScrubRemSetClaimValue = 3,
- ParVerifyClaimValue = 4,
- RebuildRSClaimValue = 5,
- ParEvacFailureClaimValue = 6,
- AggregateCountClaimValue = 7,
- VerifyCountClaimValue = 8,
- ParMarkRootClaimValue = 9,
- ParInspectClaimValue = 10
- };
-
// All allocated blocks are occupied by objects in a HeapRegion
bool block_is_obj(const HeapWord* p) const;
@@ -697,12 +681,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
return (HeapWord *) obj >= next_top_at_mark_start();
}
- // For parallel heapRegion traversal.
- bool claimHeapRegion(int claimValue);
- jint claim_value() { return _claimed; }
- // Use this carefully: only when you're sure no one is claiming...
- void set_claim_value(int claimValue) { _claimed = claimValue; }
-
// Returns the "evacuation_failed" property of the region.
bool evacuation_failed() { return _evacuation_failed; }
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp
index 818f66811..56e2d32df 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp
@@ -31,6 +31,36 @@
#include "gc_implementation/g1/concurrentG1Refine.hpp"
#include "memory/allocation.hpp"
+HeapRegionClaimer::HeapRegionClaimer(uint n_workers) :
+ _n_workers(n_workers), _n_regions(G1CollectedHeap::heap()->_hrm._allocated_heapregions_length), _claims(NULL) {
+ uint* new_claims = NEW_C_HEAP_ARRAY(uint, _n_regions, mtGC);
+ memset(new_claims, Unclaimed, sizeof(*_claims) * _n_regions);
+ _claims = new_claims;
+}
+
+HeapRegionClaimer::~HeapRegionClaimer() {
+ if (_claims != NULL) {
+ FREE_C_HEAP_ARRAY(uint, _claims, mtGC);
+ }
+}
+
+uint HeapRegionClaimer::offset_for_worker(uint worker_id) const {
+ assert(worker_id < _n_workers, "Invalid worker_id.");
+ return _n_regions * worker_id / _n_workers;
+}
+
+bool HeapRegionClaimer::is_region_claimed(uint region_index) const {
+ assert(region_index < _n_regions, "Invalid index.");
+ return _claims[region_index] == Claimed;
+}
+
+bool HeapRegionClaimer::claim_region(uint region_index) {
+ assert(region_index < _n_regions, "Invalid index.");
+ uint old_val = Atomic::cmpxchg(Claimed, &_claims[region_index], Unclaimed);
+ return old_val == Unclaimed;
+}
+
+
void HeapRegionManager::initialize(G1RegionToSpaceMapper* heap_storage,
G1RegionToSpaceMapper* prev_bitmap,
G1RegionToSpaceMapper* next_bitmap,
@@ -360,8 +390,8 @@ uint HeapRegionManager::start_region_for_worker(uint worker_i, uint num_workers,
return num_regions * worker_i / num_workers;
}
-void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint num_workers, jint claim_value) const {
- const uint start_index = start_region_for_worker(worker_id, num_workers, _allocated_heapregions_length);
+void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer) const {
+ const uint start_index = hrclaimer->offset_for_worker(worker_id);
// Every worker will actually look at all regions, skipping over regions that
// are currently not committed.
@@ -378,11 +408,11 @@ void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint
// We'll ignore "continues humongous" regions (we'll process them
// when we come across their corresponding "start humongous"
// region) and regions already claimed.
- if (r->claim_value() == claim_value || r->continuesHumongous()) {
+ if (hrclaimer->is_region_claimed(index) || r->continuesHumongous()) {
continue;
}
// OK, try to claim it
- if (!r->claimHeapRegion(claim_value)) {
+ if (!hrclaimer->claim_region(index)) {
continue;
}
// Success!
@@ -402,10 +432,10 @@ void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint
assert(chr->humongous_start_region() == r,
err_msg("Must work on humongous continuation of the original start region "
PTR_FORMAT ", but is " PTR_FORMAT, p2i(r), p2i(chr)));
- assert(chr->claim_value() != claim_value,
+ assert(!hrclaimer->is_region_claimed(ch_index),
"Must not have been claimed yet because claiming of humongous continuation first claims the start region");
- bool claim_result = chr->claimHeapRegion(claim_value);
+ bool claim_result = hrclaimer->claim_region(ch_index);
// We should always be able to claim it; no one else should
// be trying to claim this region.
guarantee(claim_result, "We should always be able to claim the continuesHumongous part of the humongous object");
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp
index a06fa4f56..25f3a223f 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp
@@ -39,6 +39,28 @@ class G1HeapRegionTable : public G1BiasedMappedArray<HeapRegion*> {
virtual HeapRegion* default_value() const { return NULL; }
};
+class HeapRegionClaimer : public StackObj {
+ uint _n_workers;
+ uint _n_regions;
+ volatile uint* _claims;
+ static const uint Unclaimed = 0;
+ static const uint Claimed = 1;
+public:
+ HeapRegionClaimer(uint n_workers = 0);
+ ~HeapRegionClaimer();
+ inline void set_workers(uint n_workers) {
+ assert(n_workers > 0, "Need at least one worker.");
+ _n_workers = n_workers;
+ }
+ // Calculate the starting region for given worker so
+ // that they do not all start from the same region.
+ uint offset_for_worker(uint worker_id) const;
+ // Check if region has been claimed with this HRClaimer.
+ bool is_region_claimed(uint region_index) const;
+ // Claim the given region, returns true if successfully claimed.
+ bool claim_region(uint region_index);
+};
+
// This class keeps track of the actual heap memory, auxiliary data
// and its metadata (i.e., HeapRegion instances) and the list of free regions.
//
@@ -68,6 +90,7 @@ class G1HeapRegionTable : public G1BiasedMappedArray<HeapRegion*> {
class HeapRegionManager: public CHeapObj<mtGC> {
friend class VMStructs;
friend class FreeRegionList;
+ friend class HeapRegionClaimer;
G1HeapRegionTable _regions;
@@ -239,7 +262,7 @@ public:
// terminating the iteration early if doHeapRegion() returns true.
void iterate(HeapRegionClosure* blk) const;
- void par_iterate(HeapRegionClosure* blk, uint worker_id, uint no_of_par_workers, jint claim_value) const;
+ void par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer) const;
// Uncommit up to num_regions_to_remove regions that are completely free.
// Return the actual number of uncommitted regions.
diff --git a/hotspot/src/share/vm/memory/space.cpp b/hotspot/src/share/vm/memory/space.cpp
index 317384f23..ff9d1de55 100644
--- a/hotspot/src/share/vm/memory/space.cpp
+++ b/hotspot/src/share/vm/memory/space.cpp
@@ -386,7 +386,14 @@ HeapWord* CompactibleSpace::forward(oop q, size_t size,
while (size > compaction_max_size) {
// switch to next compaction space
cp->space->set_compaction_top(compact_top);
- cp->space = cp->space->next_compaction_space();
+
+ CompactibleSpace* tmp = cp->next_compaction_space();
+ if (tmp == NULL) {
+ cp->space = cp->space->next_compaction_space();
+ } else {
+ cp->space = tmp;
+ }
+
if (cp->space == NULL) {
cp->gen = GenCollectedHeap::heap()->prev_gen(cp->gen);
assert(cp->gen != NULL, "compaction must succeed");
diff --git a/hotspot/src/share/vm/memory/space.hpp b/hotspot/src/share/vm/memory/space.hpp
index a4c3f9e3d..5b150c46f 100644
--- a/hotspot/src/share/vm/memory/space.hpp
+++ b/hotspot/src/share/vm/memory/space.hpp
@@ -325,7 +325,7 @@ public:
// A structure to represent a point at which objects are being copied
// during compaction.
-class CompactPoint : public StackObj {
+class CompactPoint : public CHeapObj<mtGC> {
public:
Generation* gen;
CompactibleSpace* space;
@@ -333,6 +333,8 @@ public:
CompactPoint(Generation* g = NULL) :
gen(g), space(NULL), threshold(0) {}
+
+ virtual CompactibleSpace* next_compaction_space() { return NULL; }
};
// A space that supports compaction operations. This is usually, but not
@@ -349,7 +351,7 @@ private:
public:
CompactibleSpace() :
- _compaction_top(NULL), _next_compaction_space(NULL) {}
+ _compaction_top(NULL), _next_compaction_space(NULL), _end_of_live(NULL), _first_dead(NULL) {}
virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space);
virtual void clear(bool mangle_space);
diff --git a/hotspot/src/share/vm/memory/space.inline.hpp b/hotspot/src/share/vm/memory/space.inline.hpp
index 007cebd16..f07eedcea 100644
--- a/hotspot/src/share/vm/memory/space.inline.hpp
+++ b/hotspot/src/share/vm/memory/space.inline.hpp
@@ -156,6 +156,67 @@ inline HeapWord* Space::block_start(const void* p) {
cp->space->set_compaction_top(compact_top); \
}
+#define SCAN_AND_REPREPARE(re_prepare) { \
+ HeapWord* q = bottom(); \
+ HeapWord* t = _end_of_live; /* Established by "prepare_for_compaction". */ \
+ \
+ assert(_first_dead <= _end_of_live, "Stands to reason, no?"); \
+ \
+ if (q < t && _first_dead > q && \
+ !oop(q)->is_gc_marked()) { \
+ /* we have a chunk of the space which hasn't moved and we've \
+ * reinitialized the mark word during the previous pass, so we can't \
+ * use is_gc_marked for the traversal. */ \
+ HeapWord* end = _first_dead; \
+ \
+ while (q < end) { \
+ /* I originally tried to conjoin "block_start(q) == q" to the \
+ * assertion below, but that doesn't work, because you can't \
+ * accurately traverse previous objects to get to the current one \
+ * after their pointers have been \
+ * updated, until the actual compaction is done. dld, 4/00 */ \
+ assert(block_is_obj(q), \
+ "should be at block boundaries, and should be looking at objs"); \
+ \
+ /* point all the oops to the new location */ \
+ size_t size = re_prepare->apply(oop(q)); \
+ \
+ q += size; \
+ } \
+ \
+ if (_first_dead == t) { \
+ q = t; \
+ } else { \
+ /* $$$ This is funky. Using this to read the previously written \
+ * LiveRange. See also use below. */ \
+ q = (HeapWord*)oop(_first_dead)->mark()->decode_pointer(); \
+ } \
+ } \
+ \
+ const intx interval = PrefetchScanIntervalInBytes; \
+ \
+ debug_only(HeapWord* prev_q = NULL); \
+ while (q < t) { \
+ /* prefetch beyond q */ \
+ Prefetch::write(q, interval); \
+ if (oop(q)->is_gc_marked()) { \
+ /* q is alive */ \
+ /* point all the oops to the new location */ \
+ size_t size = re_prepare->apply(oop(q)); \
+ debug_only(prev_q = q); \
+ q += size; \
+ } else { \
+ /* q is not a live object, so its mark should point at the next \
+ * live object */ \
+ debug_only(prev_q = q); \
+ q = (HeapWord*) oop(q)->mark()->decode_pointer(); \
+ assert(q > prev_q, "we should be moving forward through memory"); \
+ } \
+ } \
+ \
+ assert(q == t, "just checking"); \
+}
+
#define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) { \
/* adjust all the interior pointers to point at the new locations of objects \
* Used by MarkSweep::mark_sweep_phase3() */ \
diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp
index 2dcda097e..a96ae50eb 100644
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp
@@ -127,6 +127,8 @@ Monitor* Service_lock = NULL;
Monitor* PeriodicTask_lock = NULL;
Monitor* RedefineClasses_lock = NULL;
+Mutex* FreeHumongousRegions_lock = NULL;
+
#ifdef INCLUDE_JFR
Mutex* JfrStacktrace_lock = NULL;
Monitor* JfrMsg_lock = NULL;
@@ -286,6 +288,8 @@ void mutex_init() {
def(PeriodicTask_lock , Monitor, nonleaf+5, true);
def(RedefineClasses_lock , Monitor, nonleaf+5, true);
+ def(FreeHumongousRegions_lock , Mutex , nonleaf, false);
+
#if INCLUDE_JFR
def(JfrMsg_lock , Monitor, leaf, true);
def(JfrBuffer_lock , Mutex, leaf, true);
diff --git a/hotspot/src/share/vm/runtime/mutexLocker.hpp b/hotspot/src/share/vm/runtime/mutexLocker.hpp
index ec642a24e..428c80181 100644
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp
@@ -143,6 +143,8 @@ extern Monitor* Service_lock; // a lock used for service thre
extern Monitor* PeriodicTask_lock; // protects the periodic task structure
extern Monitor* RedefineClasses_lock; // locks classes from parallel redefinition
+extern Mutex* FreeHumongousRegions_lock; // locks humongous regions from freeing in parallel
+
#if INCLUDE_JFR
extern Mutex* JfrStacktrace_lock; // used to guard access to the JFR stacktrace table
extern Monitor* JfrMsg_lock; // protects JFR messaging
diff --git a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java
index 5b4e69477..d08d9c106 100644
--- a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java
+++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java
@@ -45,7 +45,7 @@ class ObjectWithSomeRefs {
public ObjectWithSomeRefs other4;
}
-class ReclaimRegionFast {
+class ReclaimRegionClearMarkBitsFast {
public static final long MAX_MILLIS_FOR_RUN = 50 * 1000; // The maximum runtime for the actual test.
public static final int M = 1024*1024;
@@ -123,7 +123,7 @@ public class TestEagerReclaimHumongousRegionsClearMarkBits {
"-XX:ConcGCThreads=1", // Want to make marking as slow as possible.
"-XX:+IgnoreUnrecognizedVMOptions", // G1VerifyBitmaps is develop only.
"-XX:+G1VerifyBitmaps",
- ReclaimRegionFast.class.getName());
+ ReclaimRegionClearMarkBitsFast.class.getName());
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldHaveExitValue(0);
}
diff --git a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java
index d12e25af7..16d410fdc 100644
--- a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java
+++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java
@@ -45,7 +45,7 @@ class RefHolder {
Object ref;
}
-class ReclaimRegionFast {
+class ReclaimRegionWithRefsFast {
public static final int M = 1024*1024;
@@ -93,7 +93,7 @@ public class TestEagerReclaimHumongousRegionsWithRefs {
"-Xmx128M",
"-Xmn16M",
"-XX:+PrintGC",
- ReclaimRegionFast.class.getName());
+ ReclaimRegionWithRefsFast.class.getName());
Pattern p = Pattern.compile("Full GC");
diff --git a/jdk/test/jdk/jfr/event/gc/detailed/ExecuteOOMApp.java b/jdk/test/jdk/jfr/event/gc/detailed/ExecuteOOMApp.java
index 048bbad0..af0f4096 100644
--- a/jdk/test/jdk/jfr/event/gc/detailed/ExecuteOOMApp.java
+++ b/jdk/test/jdk/jfr/event/gc/detailed/ExecuteOOMApp.java
@@ -55,8 +55,8 @@ public class ExecuteOOMApp {
return false;
}
- out.shouldHaveExitValue(0);
System.out.println(out.getOutput());
+ out.shouldHaveExitValue(0);
return true;
}
diff --git a/jdk/test/jdk/jfr/event/gc/detailed/TestG1ConcurrentModeFailureEvent.java b/jdk/test/jdk/jfr/event/gc/detailed/TestG1ConcurrentModeFailureEvent.java
index ab7005500..e551facb2 100644
--- a/jdk/test/jdk/jfr/event/gc/detailed/TestG1ConcurrentModeFailureEvent.java
+++ b/jdk/test/jdk/jfr/event/gc/detailed/TestG1ConcurrentModeFailureEvent.java
@@ -56,23 +56,27 @@ public class TestG1ConcurrentModeFailureEvent {
private final static int BYTES_TO_ALLOCATE = 1024 * 512;
public static void main(String[] args) throws Exception {
- String[] vmFlags = {"-Xmx512m", "-Xms512m", "-XX:MaxTenuringThreshold=0", "-Xloggc:testG1GC.log", "-verbose:gc",
- "-XX:+UseG1GC", "-XX:+UnlockExperimentalVMOptions", "-XX:-UseFastUnorderedTimeStamps"};
-
- if (!ExecuteOOMApp.execute(EVENT_SETTINGS_FILE, JFR_FILE, vmFlags, BYTES_TO_ALLOCATE)) {
- System.out.println("OOM happened in the other thread(not test thread). Skip test.");
- // Skip test, process terminates due to the OOME error in the different thread
- return;
- }
+ String[][] vmFlags = {
+ {"-Xmx512m", "-Xms512m", "-XX:MaxTenuringThreshold=0", "-Xloggc:testG1GC.log", "-verbose:gc",
+ "-XX:+UseG1GC", "-XX:+UnlockExperimentalVMOptions", "-XX:-UseFastUnorderedTimeStamps"},
+ {"-Xmx512m", "-Xms512m", "-XX:MaxTenuringThreshold=0", "-Xloggc:testG1GC.log", "-verbose:gc",
+ "-XX:+UseG1GC", "-XX:+G1ParallelFullGC", "-XX:+UnlockExperimentalVMOptions", "-XX:-UseFastUnorderedTimeStamps"}};
+ for (int i = 0; i < vmFlags.length; i++) {
+ if (!ExecuteOOMApp.execute(EVENT_SETTINGS_FILE, JFR_FILE, vmFlags[i], BYTES_TO_ALLOCATE)) {
+ System.out.println("OOM happened in the other thread(not test thread). Skip test.");
+ // Skip test, process terminates due to the OOME error in the different thread
+ return;
+ }
- Optional<RecordedEvent> event = RecordingFile.readAllEvents(Paths.get(JFR_FILE)).stream().findFirst();
- if (event.isPresent()) {
- Asserts.assertEquals(EVENT_NAME, event.get().getEventType().getName(), "Wrong event type");
- } else {
- // No event received. Check if test did trigger the event.
- boolean isEventTriggered = fileContainsString("testG1GC.log", "concurrent-mark-abort");
- System.out.println("isEventTriggered=" +isEventTriggered);
- Asserts.assertFalse(isEventTriggered, "Event found in log, but not in JFR");
+ Optional<RecordedEvent> event = RecordingFile.readAllEvents(Paths.get(JFR_FILE)).stream().findFirst();
+ if (event.isPresent()) {
+ Asserts.assertEquals(EVENT_NAME, event.get().getEventType().getName(), "Wrong event type");
+ } else {
+ // No event received. Check if test did trigger the event.
+ boolean isEventTriggered = fileContainsString("testG1GC.log", "concurrent-mark-abort");
+ System.out.println("isEventTriggered=" +isEventTriggered);
+ Asserts.assertFalse(isEventTriggered, "Event found in log, but not in JFR");
+ }
}
}
--
2.22.0
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/fuowang/openjdk-1.8.0.git
git@gitee.com:fuowang/openjdk-1.8.0.git
fuowang
openjdk-1.8.0
openjdk-1.8.0
master

搜索帮助