8186571: Implementation: JEP 307: Parallel Full GC for G1

Improve G1 worst-case latencies by making the full GC parallel.

Reviewed-by: tschatzl, sangheki, ehelin
This commit is contained in:
Stefan Johansson 2017-11-14 11:33:23 +01:00
parent fdab870aff
commit 6929e0f05a
71 changed files with 2799 additions and 903 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2017, 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
@ -247,8 +247,8 @@ public:
_g1(G1CollectedHeap::heap()), _hrclaimer(n_workers) {}
void work(uint worker_id) {
ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted, _chunk_size);
_g1->heap_region_par_iterate(&parKnownGarbageCl, worker_id, &_hrclaimer);
ParKnownGarbageHRClosure par_known_garbage_cl(_hrSorted, _chunk_size);
_g1->heap_region_par_iterate_from_worker_offset(&par_known_garbage_cl, &_hrclaimer, worker_id);
}
};

View file

@ -314,7 +314,7 @@ public:
G1CollectedHeap* g1h = G1CollectedHeap::heap();
G1ConcurrentMark* cm = g1h->concurrent_mark();
G1CreateLiveDataClosure cl(g1h, cm, cm->next_mark_bitmap(), _live_data);
g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer);
g1h->heap_region_par_iterate_from_worker_offset(&cl, &_hr_claimer, worker_id);
}
};
@ -381,7 +381,7 @@ public:
void work(uint worker_id) {
G1FinalizeCardLiveDataClosure cl(G1CollectedHeap::heap(), _bitmap, _live_data);
G1CollectedHeap::heap()->heap_region_par_iterate(&cl, worker_id, &_hr_claimer);
G1CollectedHeap::heap()->heap_region_par_iterate_from_worker_offset(&cl, &_hr_claimer, worker_id);
}
};
@ -560,7 +560,7 @@ public:
_mark_bitmap,
_act_live_data,
&_exp_live_data);
_g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer);
_g1h->heap_region_par_iterate_from_worker_offset(&cl, &_hr_claimer, worker_id);
Atomic::add(cl.failures(), &_failures);
}

View file

@ -38,6 +38,7 @@
#include "gc/g1/g1ConcurrentRefine.hpp"
#include "gc/g1/g1ConcurrentRefineThread.hpp"
#include "gc/g1/g1EvacStats.inline.hpp"
#include "gc/g1/g1FullCollector.hpp"
#include "gc/g1/g1FullGCScope.hpp"
#include "gc/g1/g1GCPhaseTimes.hpp"
#include "gc/g1/g1HeapSizingPolicy.hpp"
@ -48,10 +49,9 @@
#include "gc/g1/g1ParScanThreadState.inline.hpp"
#include "gc/g1/g1Policy.hpp"
#include "gc/g1/g1RegionToSpaceMapper.hpp"
#include "gc/g1/g1RemSet.inline.hpp"
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/g1RootClosures.hpp"
#include "gc/g1/g1RootProcessor.hpp"
#include "gc/g1/g1SerialFullCollector.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/g1YCTypes.hpp"
#include "gc/g1/g1YoungRemSetSamplingThread.hpp"
@ -143,6 +143,12 @@ void G1RegionMappingChangedListener::on_commit(uint start_idx, size_t num_region
reset_from_card_cache(start_idx, num_regions);
}
HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index,
MemRegion mr) {
return new HeapRegion(hrs_index, bot(), mr);
}
// Private methods.
HeapRegion*
@ -1155,7 +1161,6 @@ void G1CollectedHeap::prepare_heap_for_mutators() {
void G1CollectedHeap::abort_refinement() {
if (_hot_card_cache->use_cache()) {
_hot_card_cache->reset_card_counts();
_hot_card_cache->reset_hot_cache();
}
@ -1199,6 +1204,10 @@ void G1CollectedHeap::verify_after_full_collection() {
}
void G1CollectedHeap::print_heap_after_full_collection(G1HeapTransition* heap_transition) {
// Post collection logging.
// We should do this after we potentially resize the heap so
// that all the COMMIT / UNCOMMIT events are generated before
// the compaction events.
print_hrm_post_compaction();
heap_transition->print();
print_heap_after_gc();
@ -1221,23 +1230,18 @@ void G1CollectedHeap::do_full_collection_inner(G1FullGCScope* scope) {
gc_prologue(true);
prepare_heap_for_full_collection();
G1SerialFullCollector serial(scope, ref_processor_stw());
serial.prepare_collection();
serial.collect();
serial.complete_collection();
G1FullCollector collector(scope, ref_processor_stw(), concurrent_mark()->next_mark_bitmap(), workers()->active_workers());
collector.prepare_collection();
collector.collect();
collector.complete_collection();
prepare_heap_for_mutators();
g1_policy()->record_full_collection_end();
gc_epilogue(true);
// Post collection verification.
verify_after_full_collection();
// Post collection logging.
// We should do this after we potentially resize the heap so
// that all the COMMIT / UNCOMMIT events are generated before
// the compaction events.
print_heap_after_full_collection(scope->heap_transition());
}
@ -1269,10 +1273,10 @@ void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) {
}
void G1CollectedHeap::resize_if_necessary_after_full_collection() {
// Include bytes that will be pre-allocated to support collections, as "used".
const size_t used_after_gc = used();
// Capacity, free and used after the GC counted as full regions to
// include the waste in the following calculations.
const size_t capacity_after_gc = capacity();
const size_t free_after_gc = capacity_after_gc - used_after_gc;
const size_t used_after_gc = capacity_after_gc - unused_committed_regions_in_bytes();
// This is enforced in arguments.cpp.
assert(MinHeapFreeRatio <= MaxHeapFreeRatio,
@ -1326,8 +1330,9 @@ void G1CollectedHeap::resize_if_necessary_after_full_collection() {
size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;
log_debug(gc, ergo, heap)("Attempt heap expansion (capacity lower than min desired capacity after Full GC). "
"Capacity: " SIZE_FORMAT "B occupancy: " SIZE_FORMAT "B min_desired_capacity: " SIZE_FORMAT "B (" UINTX_FORMAT " %%)",
capacity_after_gc, used_after_gc, minimum_desired_capacity, MinHeapFreeRatio);
"Capacity: " SIZE_FORMAT "B occupancy: " SIZE_FORMAT "B live: " SIZE_FORMAT "B "
"min_desired_capacity: " SIZE_FORMAT "B (" UINTX_FORMAT " %%)",
capacity_after_gc, used_after_gc, used(), minimum_desired_capacity, MinHeapFreeRatio);
expand(expand_bytes, _workers);
@ -1337,8 +1342,9 @@ void G1CollectedHeap::resize_if_necessary_after_full_collection() {
size_t shrink_bytes = capacity_after_gc - maximum_desired_capacity;
log_debug(gc, ergo, heap)("Attempt heap shrinking (capacity higher than max desired capacity after Full GC). "
"Capacity: " SIZE_FORMAT "B occupancy: " SIZE_FORMAT "B min_desired_capacity: " SIZE_FORMAT "B (" UINTX_FORMAT " %%)",
capacity_after_gc, used_after_gc, minimum_desired_capacity, MinHeapFreeRatio);
"Capacity: " SIZE_FORMAT "B occupancy: " SIZE_FORMAT "B live: " SIZE_FORMAT "B "
"maximum_desired_capacity: " SIZE_FORMAT "B (" UINTX_FORMAT " %%)",
capacity_after_gc, used_after_gc, used(), maximum_desired_capacity, MaxHeapFreeRatio);
shrink(shrink_bytes);
}
@ -1959,6 +1965,10 @@ size_t G1CollectedHeap::capacity() const {
return _hrm.length() * HeapRegion::GrainBytes;
}
size_t G1CollectedHeap::unused_committed_regions_in_bytes() const {
return _hrm.total_free_bytes();
}
void G1CollectedHeap::reset_gc_time_stamps(HeapRegion* hr) {
hr->reset_gc_time_stamp();
}
@ -2262,10 +2272,15 @@ void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const {
_hrm.iterate(cl);
}
void G1CollectedHeap::heap_region_par_iterate(HeapRegionClosure* cl,
uint worker_id,
void G1CollectedHeap::heap_region_par_iterate_from_worker_offset(HeapRegionClosure* cl,
HeapRegionClaimer *hrclaimer,
uint worker_id) const {
_hrm.par_iterate(cl, hrclaimer, hrclaimer->offset_for_worker(worker_id));
}
void G1CollectedHeap::heap_region_par_iterate_from_start(HeapRegionClosure* cl,
HeapRegionClaimer *hrclaimer) const {
_hrm.par_iterate(cl, worker_id, hrclaimer);
_hrm.par_iterate(cl, hrclaimer, 0);
}
void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) {
@ -2276,14 +2291,6 @@ void G1CollectedHeap::collection_set_iterate_from(HeapRegionClosure *cl, uint wo
_collection_set.iterate_from(cl, worker_id, workers()->active_workers());
}
HeapRegion* G1CollectedHeap::next_compaction_region(const HeapRegion* from) const {
HeapRegion* result = _hrm.next_region_in_heap(from);
while (result != NULL && result->is_pinned()) {
result = _hrm.next_region_in_heap(result);
}
return result;
}
HeapWord* G1CollectedHeap::block_start(const void* addr) const {
HeapRegion* hr = heap_region_containing(addr);
return hr->block_start(addr);
@ -2375,7 +2382,7 @@ bool G1CollectedHeap::is_obj_dead_cond(const oop obj,
switch (vo) {
case VerifyOption_G1UsePrevMarking: return is_obj_dead(obj, hr);
case VerifyOption_G1UseNextMarking: return is_obj_ill(obj, hr);
case VerifyOption_G1UseMarkWord: return !obj->is_gc_marked() && !hr->is_archive();
case VerifyOption_G1UseFullMarking: return is_obj_dead_full(obj, hr);
default: ShouldNotReachHere();
}
return false; // keep some compilers happy
@ -2386,10 +2393,7 @@ bool G1CollectedHeap::is_obj_dead_cond(const oop obj,
switch (vo) {
case VerifyOption_G1UsePrevMarking: return is_obj_dead(obj);
case VerifyOption_G1UseNextMarking: return is_obj_ill(obj);
case VerifyOption_G1UseMarkWord: {
HeapRegion* hr = _hrm.addr_to_region((HeapWord*)obj);
return !obj->is_gc_marked() && !hr->is_archive();
}
case VerifyOption_G1UseFullMarking: return is_obj_dead_full(obj);
default: ShouldNotReachHere();
}
return false; // keep some compilers happy

View file

@ -1046,6 +1046,7 @@ public:
// The Concurrent Marking reference processor...
ReferenceProcessor* ref_processor_cm() const { return _ref_processor_cm; }
size_t unused_committed_regions_in_bytes() const;
virtual size_t capacity() const;
virtual size_t used() const;
// This should be called when we're not holding the heap lock. The
@ -1181,6 +1182,8 @@ public:
return barrier_set_cast<G1SATBCardTableLoggingModRefBS>(barrier_set());
}
G1HotCardCache* g1_hot_card_cache() const { return _hot_card_cache; }
// Iteration functions.
// Iterate over all objects, calling "cl.do_object" on each.
@ -1207,14 +1210,17 @@ public:
inline HeapWord* bottom_addr_for_region(uint index) const;
// Iterate over the heap regions in parallel. Assumes that this will be called
// in parallel by a number of worker threads with distinct worker ids
// in the range passed to the HeapRegionClaimer. Applies "blk->doHeapRegion"
// to each of the regions, by attempting to claim the region using the
// HeapRegionClaimer and, if successful, applying the closure to the claimed
// region.
void heap_region_par_iterate(HeapRegionClosure* cl,
uint worker_id,
// Two functions to iterate over the heap regions in parallel. Threads
// compete using the HeapRegionClaimer to claim the regions before
// applying the closure on them.
// The _from_worker_offset version uses the HeapRegionClaimer and
// the worker id to calculate a start offset to prevent all workers to
// start from the point.
void heap_region_par_iterate_from_worker_offset(HeapRegionClosure* cl,
HeapRegionClaimer* hrclaimer,
uint worker_id) const;
void heap_region_par_iterate_from_start(HeapRegionClosure* cl,
HeapRegionClaimer* hrclaimer) const;
// Iterate over the regions (if any) in the current collection set.
@ -1226,8 +1232,6 @@ public:
// collection set regions.
void collection_set_iterate_from(HeapRegionClosure *blk, uint worker_id);
HeapRegion* next_compaction_region(const HeapRegion* from) const;
// Returns the HeapRegion that contains addr. addr must not be NULL.
template <class T>
inline HeapRegion* heap_region_containing(const T addr) const;
@ -1391,6 +1395,9 @@ public:
inline bool is_obj_ill(const oop obj) const;
inline bool is_obj_dead_full(const oop obj, const HeapRegion* hr) const;
inline bool is_obj_dead_full(const oop obj) const;
G1ConcurrentMark* concurrent_mark() const { return _cm; }
// Refinement
@ -1437,7 +1444,7 @@ public:
// vo == UsePrevMarking -> use "prev" marking information,
// vo == UseNextMarking -> use "next" marking information
// vo == UseMarkWord -> use the mark word in the object header
// vo == UseFullMarking -> use "next" marking bitmap but no TAMS
//
// NOTE: Only the "prev" marking information is guaranteed to be
// consistent most of the time, so most calls to this should use
@ -1446,7 +1453,7 @@ public:
// vo == UseNextMarking, which is to verify the "next" marking
// information at the end of remark.
// Currently there is only one place where this is called with
// vo == UseMarkWord, which is to verify the marking during a
// vo == UseFullMarking, which is to verify the marking during a
// full GC.
void verify(VerifyOption vo);

View file

@ -264,6 +264,14 @@ inline bool G1CollectedHeap::is_obj_ill(const oop obj) const {
return is_obj_ill(obj, heap_region_containing(obj));
}
inline bool G1CollectedHeap::is_obj_dead_full(const oop obj, const HeapRegion* hr) const {
return !isMarkedNext(obj) && !hr->is_archive();
}
inline bool G1CollectedHeap::is_obj_dead_full(const oop obj) const {
return is_obj_dead_full(obj, heap_region_containing(obj));
}
inline void G1CollectedHeap::set_humongous_reclaim_candidate(uint region, bool value) {
assert(_hrm.at(region)->is_starts_humongous(), "Must start a humongous object");
_humongous_reclaim_candidates.set_candidate(region, value);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2017, 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
@ -37,11 +37,6 @@ bool G1CollectedHeap::copy_allocation_context_stats(const jint* contexts,
return false;
}
HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index,
MemRegion mr) {
return new HeapRegion(hrs_index, bot(), mr);
}
G1Policy* G1CollectedHeap::create_g1_policy(STWGCTimer* gc_timer) {
return new G1DefaultPolicy(gc_timer);
}

View file

@ -634,7 +634,7 @@ public:
void work(uint worker_id) {
SuspendibleThreadSetJoiner sts_join(_suspendible);
G1CollectedHeap::heap()->heap_region_par_iterate(&_cl, worker_id, &_hr_claimer);
G1CollectedHeap::heap()->heap_region_par_iterate_from_worker_offset(&_cl, &_hr_claimer, worker_id);
}
bool is_complete() {
@ -1140,7 +1140,7 @@ public:
HRRSCleanupTask hrrs_cleanup_task;
G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list,
&hrrs_cleanup_task);
_g1h->heap_region_par_iterate(&g1_note_end, worker_id, &_hrclaimer);
_g1h->heap_region_par_iterate_from_worker_offset(&g1_note_end, &_hrclaimer, worker_id);
assert(g1_note_end.complete(), "Shouldn't have yielded!");
// Now update the lists

View file

@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
#include "gc/g1/heapRegion.hpp"
#include "memory/virtualspace.hpp"
void G1CMBitMap::print_on_error(outputStream* st, const char* prefix) const {
@ -65,3 +66,10 @@ void G1CMBitMap::clear_range(MemRegion mr) {
_bm.at_put_range(addr_to_offset(intersection.start()),
addr_to_offset(intersection.end()), false);
}
void G1CMBitMap::clear_region(HeapRegion* region) {
if (!region->is_empty()) {
MemRegion mr(region->bottom(), region->top());
clear_range(mr);
}
}

View file

@ -28,6 +28,7 @@
#include "gc/g1/g1RegionToSpaceMapper.hpp"
#include "memory/allocation.hpp"
#include "memory/memRegion.hpp"
#include "oops/oopsHierarchy.hpp"
#include "utilities/bitMap.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
@ -35,6 +36,7 @@
class G1CMBitMap;
class G1CMTask;
class G1ConcurrentMark;
class HeapRegion;
// Closure for iteration over bitmaps
class G1CMBitMapClosure VALUE_OBJ_CLASS_SPEC {
@ -96,6 +98,7 @@ public:
void initialize(MemRegion heap, G1RegionToSpaceMapper* storage);
// Read marks
bool is_marked(oop obj) const;
bool is_marked(HeapWord* addr) const {
assert(_covered.contains(addr),
"Address " PTR_FORMAT " is outside underlying space from " PTR_FORMAT " to " PTR_FORMAT,
@ -120,9 +123,12 @@ public:
// Write marks.
inline void mark(HeapWord* addr);
inline void clear(HeapWord* addr);
inline void clear(oop obj);
inline bool par_mark(HeapWord* addr);
inline bool par_mark(oop obj);
void clear_range(MemRegion mr);
void clear_region(HeapRegion* hr);
};
#endif // SHARE_VM_GC_G1_G1CONCURRENTMARKBITMAP_HPP

View file

@ -83,4 +83,16 @@ inline bool G1CMBitMap::par_mark(HeapWord* addr) {
return _bm.par_set_bit(addr_to_offset(addr));
}
inline bool G1CMBitMap::par_mark(oop obj) {
return par_mark((HeapWord*) obj);
}
inline bool G1CMBitMap::is_marked(oop obj) const{
return is_marked((HeapWord*) obj);
}
inline void G1CMBitMap::clear(oop obj) {
clear((HeapWord*) obj);
}
#endif // SHARE_VM_GC_G1_G1CONCURRENTMARKBITMAP_INLINE_HPP

View file

@ -0,0 +1,245 @@
/*
* Copyright (c) 2017, 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 "code/codeCache.hpp"
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1FullCollector.hpp"
#include "gc/g1/g1FullGCAdjustTask.hpp"
#include "gc/g1/g1FullGCCompactTask.hpp"
#include "gc/g1/g1FullGCMarker.inline.hpp"
#include "gc/g1/g1FullGCMarkTask.hpp"
#include "gc/g1/g1FullGCPrepareTask.hpp"
#include "gc/g1/g1FullGCReferenceProcessorExecutor.hpp"
#include "gc/g1/g1FullGCScope.hpp"
#include "gc/g1/g1OopClosures.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/preservedMarks.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "gc/shared/weakProcessor.hpp"
#include "logging/log.hpp"
#include "runtime/biasedLocking.hpp"
#include "utilities/debug.hpp"
static void clear_and_activate_derived_pointers() {
#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
}
static void deactivate_derived_pointers() {
#if COMPILER2_OR_JVMCI
DerivedPointerTable::set_active(false);
#endif
}
static void update_derived_pointers() {
#if COMPILER2_OR_JVMCI
DerivedPointerTable::update_pointers();
#endif
}
G1FullCollector::G1FullCollector(G1FullGCScope* scope,
ReferenceProcessor* reference_processor,
G1CMBitMap* bitmap,
uint workers) :
_scope(scope),
_num_workers(workers),
_mark_bitmap(bitmap),
_oop_queue_set(_num_workers),
_array_queue_set(_num_workers),
_preserved_marks_set(true),
_reference_processor(reference_processor),
_serial_compaction_point(),
_is_alive(_mark_bitmap),
_is_alive_mutator(_reference_processor, &_is_alive) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
_preserved_marks_set.init(_num_workers);
_markers = NEW_C_HEAP_ARRAY(G1FullGCMarker*, _num_workers, mtGC);
_compaction_points = NEW_C_HEAP_ARRAY(G1FullGCCompactionPoint*, _num_workers, mtGC);
for (uint i = 0; i < _num_workers; i++) {
_markers[i] = new G1FullGCMarker(i, _preserved_marks_set.get(i), mark_bitmap());
_compaction_points[i] = new G1FullGCCompactionPoint();
_oop_queue_set.register_queue(i, marker(i)->oop_stack());
_array_queue_set.register_queue(i, marker(i)->objarray_stack());
}
}
G1FullCollector::~G1FullCollector() {
for (uint i = 0; i < _num_workers; i++) {
delete _markers[i];
delete _compaction_points[i];
}
FREE_C_HEAP_ARRAY(G1FullGCMarker*, _markers);
FREE_C_HEAP_ARRAY(G1FullGCCompactionPoint*, _compaction_points);
}
void G1FullCollector::prepare_collection() {
_reference_processor->enable_discovery();
_reference_processor->setup_policy(scope()->should_clear_soft_refs());
// When collecting the permanent generation Method*s may be moving,
// so we either have to flush all bcp data or convert it into bci.
CodeCache::gc_prologue();
// We should save the marks of the currently locked biased monitors.
// The marking doesn't preserve the marks of biased objects.
BiasedLocking::preserve_marks();
// Clear and activate derived pointer collection.
clear_and_activate_derived_pointers();
}
void G1FullCollector::collect() {
phase1_mark_live_objects();
verify_after_marking();
// Don't add any more derived pointers during later phases
deactivate_derived_pointers();
phase2_prepare_compaction();
phase3_adjust_pointers();
phase4_do_compaction();
}
void G1FullCollector::complete_collection() {
// Restore all marks.
restore_marks();
// When the pointers have been adjusted and moved, we can
// update the derived pointer table.
update_derived_pointers();
BiasedLocking::restore_marks();
CodeCache::gc_epilogue();
JvmtiExport::gc_epilogue();
}
void G1FullCollector::phase1_mark_live_objects() {
// Recursively traverse all live objects and mark them.
GCTraceTime(Info, gc, phases) info("Phase 1: Mark live objects", scope()->timer());
// Do the actual marking.
G1FullGCMarkTask marking_task(this);
run_task(&marking_task);
// Process references discovered during marking.
G1FullGCReferenceProcessingExecutor reference_processing(this);
reference_processing.execute(scope()->timer(), scope()->tracer());
// Weak oops cleanup.
{
GCTraceTime(Debug, gc, phases) trace("Phase 1: Weak Processing", scope()->timer());
WeakProcessor::weak_oops_do(&_is_alive, &do_nothing_cl);
}
// Class unloading and cleanup.
if (ClassUnloading) {
GCTraceTime(Debug, gc, phases) debug("Phase 1: Class Unloading and Cleanup", scope()->timer());
// Unload classes and purge the SystemDictionary.
bool purged_class = SystemDictionary::do_unloading(&_is_alive, scope()->timer());
G1CollectedHeap::heap()->complete_cleaning(&_is_alive, purged_class);
} else {
GCTraceTime(Debug, gc, phases) debug("Phase 1: String and Symbol Tables Cleanup", scope()->timer());
// If no class unloading just clean out strings and symbols.
G1CollectedHeap::heap()->partial_cleaning(&_is_alive, true, true, G1StringDedup::is_enabled());
}
scope()->tracer()->report_object_count_after_gc(&_is_alive);
}
void G1FullCollector::prepare_compaction_common() {
G1FullGCPrepareTask task(this);
run_task(&task);
// To avoid OOM when there is memory left.
if (!task.has_freed_regions()) {
task.prepare_serial_compaction();
}
}
void G1FullCollector::phase2_prepare_compaction() {
GCTraceTime(Info, gc, phases) info("Phase 2: Prepare for compaction", scope()->timer());
prepare_compaction_ext(); // Will call prepare_compaction_common() above.
}
void G1FullCollector::phase3_adjust_pointers() {
// Adjust the pointers to reflect the new locations
GCTraceTime(Info, gc, phases) info("Phase 3: Adjust pointers and remembered sets", scope()->timer());
G1FullGCAdjustTask task(this);
run_task(&task);
}
void G1FullCollector::phase4_do_compaction() {
// Compact the heap using the compaction queues created in phase 2.
GCTraceTime(Info, gc, phases) info("Phase 4: Compact heap", scope()->timer());
G1FullGCCompactTask task(this);
run_task(&task);
// Serial compact to avoid OOM when very few free regions.
if (serial_compaction_point()->has_regions()) {
task.serial_compaction();
}
}
void G1FullCollector::restore_marks() {
SharedRestorePreservedMarksTaskExecutor task_executor(G1CollectedHeap::heap()->workers());
_preserved_marks_set.restore(&task_executor);
_preserved_marks_set.reclaim();
}
void G1FullCollector::run_task(AbstractGangTask* task) {
G1CollectedHeap::heap()->workers()->run_task(task, _num_workers);
}
void G1FullCollector::verify_after_marking() {
if (!VerifyDuringGC) {
//Only do verification if VerifyDuringGC is set.
return;
}
HandleMark hm; // handle scope
#if COMPILER2_OR_JVMCI
DerivedPointerTableDeactivate dpt_deact;
#endif
G1CollectedHeap::heap()->prepare_for_verify();
// Note: we can verify only the heap here. When an object is
// marked, the previous value of the mark word (including
// identity hash values, ages, etc) is preserved, and the mark
// word is set to markOop::marked_value - effectively removing
// any hash values from the mark word. These hash values are
// used when verifying the dictionaries and so removing them
// from the mark word can make verification of the dictionaries
// fail. At the end of the GC, the original mark word values
// (including hash values) are restored to the appropriate
// objects.
GCTraceTime(Info, gc, verify)("During GC (full)");
G1CollectedHeap::heap()->verify(VerifyOption_G1UseFullMarking);
}

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_GC_G1_G1FULLCOLLECTOR_HPP
#define SHARE_GC_G1_G1FULLCOLLECTOR_HPP
#include "gc/g1/g1FullGCCompactionPoint.hpp"
#include "gc/g1/g1FullGCMarker.hpp"
#include "gc/g1/g1FullGCOopClosures.hpp"
#include "gc/shared/preservedMarks.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "gc/shared/taskqueue.hpp"
#include "memory/allocation.hpp"
class AbstractGangTask;
class G1CMBitMap;
class G1FullGCMarker;
class G1FullGCScope;
class G1FullGCCompactionPoint;
class ReferenceProcessor;
// The G1FullCollector holds data associated with the current Full GC.
class G1FullCollector : StackObj {
G1FullGCScope* _scope;
uint _num_workers;
G1FullGCMarker** _markers;
G1FullGCCompactionPoint** _compaction_points;
G1CMBitMap* _mark_bitmap;
OopQueueSet _oop_queue_set;
ObjArrayTaskQueueSet _array_queue_set;
PreservedMarksSet _preserved_marks_set;
ReferenceProcessor* _reference_processor;
G1FullGCCompactionPoint _serial_compaction_point;
G1IsAliveClosure _is_alive;
ReferenceProcessorIsAliveMutator _is_alive_mutator;
public:
G1FullCollector(G1FullGCScope* scope,
ReferenceProcessor* reference_processor,
G1CMBitMap* mark_bitmap,
uint workers);
~G1FullCollector();
void prepare_collection();
void collect();
void complete_collection();
G1FullGCScope* scope() { return _scope; }
uint workers() { return _num_workers; }
G1FullGCMarker* marker(uint id) { return _markers[id]; }
G1FullGCCompactionPoint* compaction_point(uint id) { return _compaction_points[id]; }
G1CMBitMap* mark_bitmap() { return _mark_bitmap; }
OopQueueSet* oop_queue_set() { return &_oop_queue_set; }
ObjArrayTaskQueueSet* array_queue_set() { return &_array_queue_set; }
PreservedMarksSet* preserved_mark_set() { return &_preserved_marks_set; }
ReferenceProcessor* reference_processor() { return _reference_processor; }
G1FullGCCompactionPoint* serial_compaction_point() { return &_serial_compaction_point; }
private:
void phase1_mark_live_objects();
void phase2_prepare_compaction();
void phase3_adjust_pointers();
void phase4_do_compaction();
void restore_marks();
void verify_after_marking();
void run_task(AbstractGangTask* task);
// Prepare compaction extension support.
void prepare_compaction_ext();
void prepare_compaction_common();
};
#endif // SHARE_GC_G1_G1FULLCOLLECTOR_HPP

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 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
@ -23,9 +23,8 @@
*/
#include "precompiled.hpp"
#include "gc/g1/g1MarkSweep.hpp"
#include "gc/g1/g1FullCollector.hpp"
void G1MarkSweep::prepare_compaction() {
G1PrepareCompactClosure blk;
G1MarkSweep::prepare_compaction_work(&blk);
void G1FullCollector::prepare_compaction_ext() {
prepare_compaction_common();
}

View file

@ -0,0 +1,119 @@
/*
* Copyright (c) 2017, 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/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
#include "gc/g1/g1FullCollector.hpp"
#include "gc/g1/g1FullGCAdjustTask.hpp"
#include "gc/g1/g1FullGCCompactionPoint.hpp"
#include "gc/g1/g1FullGCMarker.hpp"
#include "gc/g1/g1FullGCOopClosures.inline.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "logging/log.hpp"
#include "utilities/ticks.inline.hpp"
class G1AdjustLiveClosure : public StackObj {
G1AdjustAndRebuildClosure* _adjust_closure;
public:
G1AdjustLiveClosure(G1AdjustAndRebuildClosure* cl) :
_adjust_closure(cl) { }
size_t apply(oop object) {
_adjust_closure->update_compaction_delta(object);
return object->oop_iterate_size(_adjust_closure);
}
};
class G1AdjustRegionClosure : public HeapRegionClosure {
G1CMBitMap* _bitmap;
uint _worker_id;
public:
G1AdjustRegionClosure(G1CMBitMap* bitmap, uint worker_id) :
_bitmap(bitmap),
_worker_id(worker_id) { }
bool doHeapRegion(HeapRegion* r) {
G1AdjustAndRebuildClosure cl(_worker_id);
if (r->is_humongous()) {
oop obj = oop(r->humongous_start_region()->bottom());
cl.update_compaction_delta(obj);
obj->oop_iterate(&cl, MemRegion(r->bottom(), r->top()));
} else if (r->is_open_archive()) {
// Only adjust the open archive regions, the closed ones
// never change.
G1AdjustLiveClosure adjust(&cl);
r->apply_to_marked_objects(_bitmap, &adjust);
// Open archive regions will not be compacted and the marking information is
// no longer needed. Clear it here to avoid having to do it later.
_bitmap->clear_region(r);
} else {
G1AdjustLiveClosure adjust(&cl);
r->apply_to_marked_objects(_bitmap, &adjust);
}
return false;
}
};
G1FullGCAdjustTask::G1FullGCAdjustTask(G1FullCollector* collector) :
G1FullGCTask("G1 Adjust and Rebuild", collector),
_root_processor(G1CollectedHeap::heap(), collector->workers()),
_hrclaimer(collector->workers()),
_adjust(),
_adjust_string_dedup(NULL, &_adjust, G1StringDedup::is_enabled()) {
// Need cleared claim bits for the roots processing
ClassLoaderDataGraph::clear_claimed_marks();
}
void G1FullGCAdjustTask::work(uint worker_id) {
Ticks start = Ticks::now();
ResourceMark rm;
// Adjust preserved marks first since they are not balanced.
G1FullGCMarker* marker = collector()->marker(worker_id);
marker->preserved_stack()->adjust_during_full_gc();
// Adjust the weak_roots.
CLDToOopClosure adjust_cld(&_adjust);
CodeBlobToOopClosure adjust_code(&_adjust, CodeBlobToOopClosure::FixRelocations);
_root_processor.process_full_gc_weak_roots(&_adjust);
// Needs to be last, process_all_roots calls all_tasks_completed(...).
_root_processor.process_all_roots(
&_adjust,
&adjust_cld,
&adjust_code);
// Adjust string dedup if enabled.
if (G1StringDedup::is_enabled()) {
G1StringDedup::parallel_unlink(&_adjust_string_dedup, worker_id);
}
// Now adjust pointers region by region
G1AdjustRegionClosure blk(collector()->mark_bitmap(), worker_id);
G1CollectedHeap::heap()->heap_region_par_iterate_from_worker_offset(&blk, &_hrclaimer, worker_id);
log_task("Adjust and Rebuild task", worker_id, start);
}

View file

@ -22,28 +22,27 @@
*
*/
#ifndef SHARE_VM_GC_G1_G1SERIALCOLLECTOR_HPP
#define SHARE_VM_GC_G1_G1SERIALCOLLECTOR_HPP
#ifndef SHARE_GC_G1_G1FULLGCADJUSTTASK_HPP
#define SHARE_GC_G1_G1FULLGCADJUSTTASK_HPP
#include "memory/allocation.hpp"
#include "gc/g1/g1FullGCOopClosures.hpp"
#include "gc/g1/g1FullGCTask.hpp"
#include "gc/g1/g1RootProcessor.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/heapRegionManager.hpp"
#include "utilities/ticks.hpp"
class G1FullGCScope;
class ReferenceProcessor;
class G1CollectedHeap;
class G1SerialFullCollector : StackObj {
G1FullGCScope* _scope;
ReferenceProcessor* _reference_processor;
ReferenceProcessorIsAliveMutator _is_alive_mutator;
ReferenceProcessorMTDiscoveryMutator _mt_discovery_mutator;
void rebuild_remembered_sets();
class G1FullGCAdjustTask : public G1FullGCTask {
G1RootProcessor _root_processor;
HeapRegionClaimer _hrclaimer;
G1AdjustClosure _adjust;
G1StringDedupUnlinkOrOopsDoClosure _adjust_string_dedup;
public:
G1SerialFullCollector(G1FullGCScope* scope, ReferenceProcessor* reference_processor);
void prepare_collection();
void collect();
void complete_collection();
G1FullGCAdjustTask(G1FullCollector* collector);
void work(uint worker_id);
};
#endif // SHARE_VM_GC_G1_G1SERIALCOLLECTOR_HPP
#endif // SHARE_GC_G1_G1FULLGCADJUSTTASK_HPP

View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 2017, 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/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
#include "gc/g1/g1FullCollector.hpp"
#include "gc/g1/g1FullGCCompactionPoint.hpp"
#include "gc/g1/g1FullGCCompactTask.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "logging/log.hpp"
#include "utilities/ticks.inline.hpp"
class G1ResetHumongousClosure : public HeapRegionClosure {
G1CMBitMap* _bitmap;
public:
G1ResetHumongousClosure(G1CMBitMap* bitmap) :
_bitmap(bitmap) { }
bool doHeapRegion(HeapRegion* current) {
if (current->is_humongous()) {
if (current->is_starts_humongous()) {
oop obj = oop(current->bottom());
if (_bitmap->is_marked(obj)) {
// Clear bitmap and fix mark word.
_bitmap->clear(obj);
obj->init_mark();
} else {
assert(current->is_empty(), "Should have been cleared in phase 2.");
}
}
current->reset_during_compaction();
}
return false;
}
};
size_t G1FullGCCompactTask::G1CompactRegionClosure::apply(oop obj) {
size_t size = obj->size();
HeapWord* destination = (HeapWord*)obj->forwardee();
if (destination == NULL) {
// Object not moving
return size;
}
// copy object and reinit its mark
HeapWord* obj_addr = (HeapWord*) obj;
assert(obj_addr != destination, "everything in this pass should be moving");
Copy::aligned_conjoint_words(obj_addr, destination, size);
oop(destination)->init_mark();
assert(oop(destination)->klass() != NULL, "should have a class");
return size;
}
void G1FullGCCompactTask::compact_region(HeapRegion* hr) {
assert(!hr->is_humongous(), "Should be no humongous regions in compaction queue");
G1CompactRegionClosure compact(collector()->mark_bitmap());
hr->apply_to_marked_objects(collector()->mark_bitmap(), &compact);
// Once all objects have been moved the liveness information
// needs be cleared.
collector()->mark_bitmap()->clear_region(hr);
hr->complete_compaction();
}
void G1FullGCCompactTask::work(uint worker_id) {
Ticks start = Ticks::now();
GrowableArray<HeapRegion*>* compaction_queue = collector()->compaction_point(worker_id)->regions();
for (GrowableArrayIterator<HeapRegion*> it = compaction_queue->begin();
it != compaction_queue->end();
++it) {
compact_region(*it);
}
G1ResetHumongousClosure hc(collector()->mark_bitmap());
G1CollectedHeap::heap()->heap_region_par_iterate_from_worker_offset(&hc, &_claimer, worker_id);
log_task("Compaction task", worker_id, start);
}
void G1FullGCCompactTask::serial_compaction() {
GCTraceTime(Debug, gc, phases) tm("Phase 4: Serial Compaction", collector()->scope()->timer());
GrowableArray<HeapRegion*>* compaction_queue = collector()->serial_compaction_point()->regions();
for (GrowableArrayIterator<HeapRegion*> it = compaction_queue->begin();
it != compaction_queue->end();
++it) {
compact_region(*it);
}
}

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_GC_G1_G1FULLGCCOMPACTTASK_HPP
#define SHARE_GC_G1_G1FULLGCCOMPACTTASK_HPP
#include "gc/g1/g1FullGCCompactionPoint.hpp"
#include "gc/g1/g1FullGCScope.hpp"
#include "gc/g1/g1FullGCTask.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/heapRegionManager.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "utilities/ticks.hpp"
class G1CollectedHeap;
class G1CMBitMap;
class G1FullGCCompactTask : public G1FullGCTask {
protected:
HeapRegionClaimer _claimer;
private:
void compact_region(HeapRegion* hr);
public:
G1FullGCCompactTask(G1FullCollector* collector) :
G1FullGCTask("G1 Compact Task", collector),
_claimer(collector->workers()) { }
void work(uint worker_id);
void serial_compaction();
class G1CompactRegionClosure : public StackObj {
G1CMBitMap* _bitmap;
public:
G1CompactRegionClosure(G1CMBitMap* bitmap) : _bitmap(bitmap) { }
size_t apply(oop object);
};
};
#endif // SHARE_GC_G1_G1FULLGCCOMPACTTASK_HPP

View file

@ -0,0 +1,145 @@
/*
* Copyright (c) 2017, 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/g1/g1FullGCCompactionPoint.hpp"
#include "gc/g1/heapRegion.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/debug.hpp"
G1FullGCCompactionPoint::G1FullGCCompactionPoint() :
_current_region(NULL),
_threshold(NULL),
_compaction_top(NULL) {
_compaction_regions = new (ResourceObj::C_HEAP, mtGC) GrowableArray<HeapRegion*>(32, true, mtGC);
_compaction_region_iterator = _compaction_regions->begin();
}
G1FullGCCompactionPoint::~G1FullGCCompactionPoint() {
delete _compaction_regions;
}
void G1FullGCCompactionPoint::update() {
if (is_initialized()) {
_current_region->set_compaction_top(_compaction_top);
}
}
void G1FullGCCompactionPoint::initialize_values(bool init_threshold) {
_compaction_top = _current_region->compaction_top();
if (init_threshold) {
_threshold = _current_region->initialize_threshold();
}
}
bool G1FullGCCompactionPoint::has_regions() {
return !_compaction_regions->is_empty();
}
bool G1FullGCCompactionPoint::is_initialized() {
return _current_region != NULL;
}
void G1FullGCCompactionPoint::initialize(HeapRegion* hr, bool init_threshold) {
_current_region = hr;
initialize_values(init_threshold);
}
HeapRegion* G1FullGCCompactionPoint::current_region() {
return *_compaction_region_iterator;
}
HeapRegion* G1FullGCCompactionPoint::next_region() {
HeapRegion* next = *(++_compaction_region_iterator);
assert(next != NULL, "Must return valid region");
return next;
}
GrowableArray<HeapRegion*>* G1FullGCCompactionPoint::regions() {
return _compaction_regions;
}
bool G1FullGCCompactionPoint::object_will_fit(size_t size) {
size_t space_left = pointer_delta(_current_region->end(), _compaction_top);
return size <= space_left;
}
void G1FullGCCompactionPoint::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_region();
initialize_values(true);
}
void G1FullGCCompactionPoint::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();
}
// Store a forwarding pointer if the object should be moved.
if ((HeapWord*)object != _compaction_top) {
object->forward_to(oop(_compaction_top));
} else {
if (object->forwardee() != NULL) {
// Object should not move but mark-word is used so it looks like the
// object is forwarded. Need to clear the mark and it's no problem
// since it will be restored by preserved marks. There is an exception
// with BiasedLocking, in this case forwardee() will return NULL
// even if the mark-word is used. This is no problem since
// forwardee() will return NULL in the compaction phase as well.
object->init_mark();
} else {
// Make sure object has the correct mark-word set or that it will be
// fixed when restoring the preserved marks.
assert(object->mark() == markOopDesc::prototype_for_object(object) || // Correct mark
object->mark()->must_be_preserved(object) || // Will be restored by PreservedMarksSet
(UseBiasedLocking && object->has_bias_pattern()), // Will be restored by BiasedLocking
"should have correct prototype obj: " PTR_FORMAT " mark: " PTR_FORMAT " prototype: " PTR_FORMAT,
p2i(object), p2i(object->mark()), p2i(markOopDesc::prototype_for_object(object)));
}
assert(object->forwardee() == NULL, "should be forwarded to NULL");
}
// Update compaction values.
_compaction_top += size;
if (_compaction_top > _threshold) {
_threshold = _current_region->cross_threshold(_compaction_top - size, _compaction_top);
}
}
void G1FullGCCompactionPoint::add(HeapRegion* hr) {
_compaction_regions->append(hr);
}
void G1FullGCCompactionPoint::merge(G1FullGCCompactionPoint* other) {
_compaction_regions->appendAll(other->regions());
}
HeapRegion* G1FullGCCompactionPoint::remove_last() {
return _compaction_regions->pop();
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_GC_G1_G1FULLGCCOMPACTIONPOINT_HPP
#define SHARE_GC_G1_G1FULLGCCOMPACTIONPOINT_HPP
#include "memory/allocation.hpp"
#include "utilities/growableArray.hpp"
class HeapRegion;
class G1FullGCCompactionPoint : public CHeapObj<mtGC> {
HeapRegion* _current_region;
HeapWord* _threshold;
HeapWord* _compaction_top;
GrowableArray<HeapRegion*>* _compaction_regions;
GrowableArrayIterator<HeapRegion*> _compaction_region_iterator;
bool object_will_fit(size_t size);
void initialize_values(bool init_threshold);
void switch_region();
HeapRegion* next_region();
public:
G1FullGCCompactionPoint();
~G1FullGCCompactionPoint();
bool has_regions();
bool is_initialized();
void initialize(HeapRegion* hr, bool init_threshold);
void update();
void forward(oop object, size_t size);
void add(HeapRegion* hr);
void merge(G1FullGCCompactionPoint* other);
HeapRegion* remove_last();
HeapRegion* current_region();
GrowableArray<HeapRegion*>* regions();
};
#endif // SHARE_GC_G1_G1FULLGCCOMPACTIONPOINT_HPP

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2017, 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/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1FullCollector.hpp"
#include "gc/g1/g1FullGCMarker.hpp"
#include "gc/g1/g1FullGCMarkTask.hpp"
#include "gc/g1/g1FullGCOopClosures.inline.hpp"
#include "gc/g1/g1FullGCReferenceProcessorExecutor.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/referenceProcessor.hpp"
G1FullGCMarkTask::G1FullGCMarkTask(G1FullCollector* collector) :
G1FullGCTask("G1 Parallel Marking Task", collector),
_root_processor(G1CollectedHeap::heap(), collector->workers()),
_terminator(collector->workers(), collector->array_queue_set()) {
// Need cleared claim bits for the roots processing
ClassLoaderDataGraph::clear_claimed_marks();
}
void G1FullGCMarkTask::work(uint worker_id) {
Ticks start = Ticks::now();
ResourceMark rm;
G1FullGCMarker* marker = collector()->marker(worker_id);
MarkingCodeBlobClosure code_closure(marker->mark_closure(), !CodeBlobToOopClosure::FixRelocations);
if (ClassUnloading) {
_root_processor.process_strong_roots(
marker->mark_closure(),
marker->cld_closure(),
&code_closure);
} else {
_root_processor.process_all_roots_no_string_table(
marker->mark_closure(),
marker->cld_closure(),
&code_closure);
}
// Mark stack is populated, now process and drain it.
marker->complete_marking(collector()->oop_queue_set(), collector()->array_queue_set(), &_terminator);
// This is the point where the entire marking should have completed.
assert(marker->oop_stack()->is_empty(), "Marking should have completed");
assert(marker->objarray_stack()->is_empty(), "Array marking should have completed");
log_task("Marking task", worker_id, start);
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_GC_G1_G1FULLGCMARKTASK_HPP
#define SHARE_GC_G1_G1FULLGCMARKTASK_HPP
#include "gc/g1/g1FullGCCompactionPoint.hpp"
#include "gc/g1/g1FullGCScope.hpp"
#include "gc/g1/g1FullGCTask.hpp"
#include "gc/g1/g1RootProcessor.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/heapRegionManager.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "utilities/ticks.hpp"
class G1FullGCMarkTask : public G1FullGCTask {
G1RootProcessor _root_processor;
ParallelTaskTerminator _terminator;
public:
G1FullGCMarkTask(G1FullCollector* collector);
void work(uint worker_id);
};
#endif // SHARE_GC_G1_G1FULLGCMARKTASK_HPP

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2017, 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/g1/g1FullGCMarker.inline.hpp"
G1FullGCMarker::G1FullGCMarker(uint worker_id, PreservedMarks* preserved_stack, G1CMBitMap* bitmap) :
_worker_id(worker_id),
_mark_closure(worker_id, this, G1CollectedHeap::heap()->ref_processor_stw()),
_verify_closure(VerifyOption_G1UseFullMarking),
_cld_closure(mark_closure()),
_stack_closure(this),
_preserved_stack(preserved_stack),
_bitmap(bitmap) {
_oop_stack.initialize();
_objarray_stack.initialize();
}
G1FullGCMarker::~G1FullGCMarker() {
assert(is_empty(), "Must be empty at this point");
}
void G1FullGCMarker::complete_marking(OopQueueSet* oop_stacks,
ObjArrayTaskQueueSet* array_stacks,
ParallelTaskTerminator* terminator) {
int hash_seed = 17;
do {
drain_stack();
ObjArrayTask steal_array;
if (array_stacks->steal(_worker_id, &hash_seed, steal_array)) {
follow_array_chunk(objArrayOop(steal_array.obj()), steal_array.index());
} else {
oop steal_oop;
if (oop_stacks->steal(_worker_id, &hash_seed, steal_oop)) {
follow_object(steal_oop);
}
}
} while (!is_empty() || !terminator->offer_termination());
}

View file

@ -0,0 +1,99 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_GC_G1_G1FULLGCMARKER_HPP
#define SHARE_GC_G1_G1FULLGCMARKER_HPP
#include "gc/g1/g1FullGCOopClosures.hpp"
#include "gc/shared/preservedMarks.hpp"
#include "gc/shared/taskqueue.hpp"
#include "memory/iterator.hpp"
#include "oops/markOop.hpp"
#include "oops/oop.hpp"
#include "runtime/timer.hpp"
#include "utilities/chunkedList.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/stack.hpp"
typedef OverflowTaskQueue<oop, mtGC> OopQueue;
typedef OverflowTaskQueue<ObjArrayTask, mtGC> ObjArrayTaskQueue;
typedef GenericTaskQueueSet<OopQueue, mtGC> OopQueueSet;
typedef GenericTaskQueueSet<ObjArrayTaskQueue, mtGC> ObjArrayTaskQueueSet;
class G1CMBitMap;
class G1FullGCMarker : public CHeapObj<mtGC> {
private:
uint _worker_id;
// Backing mark bitmap
G1CMBitMap* _bitmap;
// Mark stack
OopQueue _oop_stack;
ObjArrayTaskQueue _objarray_stack;
PreservedMarks* _preserved_stack;
// Marking closures
G1MarkAndPushClosure _mark_closure;
G1VerifyOopClosure _verify_closure;
G1FollowStackClosure _stack_closure;
CLDToOopClosure _cld_closure;
inline bool is_empty();
inline bool pop_object(oop& obj);
inline bool pop_objarray(ObjArrayTask& array);
inline void push_objarray(oop obj, size_t index);
inline bool mark_object(oop obj);
// Marking helpers
inline void follow_object(oop obj);
inline void follow_array(objArrayOop array);
inline void follow_array_chunk(objArrayOop array, int index);
public:
G1FullGCMarker(uint worker_id, PreservedMarks* preserved_stack, G1CMBitMap* bitmap);
~G1FullGCMarker();
// Stack getters
OopQueue* oop_stack() { return &_oop_stack; }
ObjArrayTaskQueue* objarray_stack() { return &_objarray_stack; }
PreservedMarks* preserved_stack() { return _preserved_stack; }
// Marking entry points
template <class T> inline void mark_and_push(T* p);
inline void follow_klass(Klass* k);
inline void follow_cld(ClassLoaderData* cld);
inline void drain_stack();
void complete_marking(OopQueueSet* oop_stacks,
ObjArrayTaskQueueSet* array_stacks,
ParallelTaskTerminator* terminator);
// Closure getters
CLDToOopClosure* cld_closure() { return &_cld_closure; }
G1MarkAndPushClosure* mark_closure() { return &_mark_closure; }
G1FollowStackClosure* stack_closure() { return &_stack_closure; }
};
#endif // SHARE_GC_G1_G1FULLGCMARKER_HPP

View file

@ -0,0 +1,172 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_GC_G1_G1MARKSTACK_INLINE_HPP
#define SHARE_VM_GC_G1_G1MARKSTACK_INLINE_HPP
#include "gc/g1/g1Allocator.inline.hpp"
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
#include "gc/g1/g1FullGCMarker.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/g1StringDedupQueue.hpp"
#include "gc/shared/preservedMarks.inline.hpp"
#include "utilities/debug.hpp"
inline bool G1FullGCMarker::mark_object(oop obj) {
// Not marking closed archive objects.
if (G1ArchiveAllocator::is_closed_archive_object(obj)) {
return false;
}
// Try to mark.
if (!_bitmap->par_mark(obj)) {
// Lost mark race.
return false;
}
// Marked by us, preserve if needed.
markOop mark = obj->mark();
if (mark->must_be_preserved(obj) &&
!G1ArchiveAllocator::is_open_archive_object(obj)) {
preserved_stack()->push(obj, mark);
}
// Check if deduplicatable string.
if (G1StringDedup::is_enabled()) {
G1StringDedup::enqueue_from_mark(obj, _worker_id);
}
return true;
}
template <class T> inline void G1FullGCMarker::mark_and_push(T* p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
if (mark_object(obj)) {
_oop_stack.push(obj);
assert(_bitmap->is_marked(obj), "Must be marked now - map self");
} else {
assert(_bitmap->is_marked(obj) || G1ArchiveAllocator::is_closed_archive_object(obj),
"Must be marked by other or closed archive object");
}
}
}
inline bool G1FullGCMarker::is_empty() {
return _oop_stack.is_empty() && _objarray_stack.is_empty();
}
inline bool G1FullGCMarker::pop_object(oop& oop) {
return _oop_stack.pop_overflow(oop) || _oop_stack.pop_local(oop);
}
inline void G1FullGCMarker::push_objarray(oop obj, size_t index) {
ObjArrayTask task(obj, index);
assert(task.is_valid(), "bad ObjArrayTask");
_objarray_stack.push(task);
}
inline bool G1FullGCMarker::pop_objarray(ObjArrayTask& arr) {
return _objarray_stack.pop_overflow(arr) || _objarray_stack.pop_local(arr);
}
inline void G1FullGCMarker::follow_array(objArrayOop array) {
follow_klass(array->klass());
// Don't push empty arrays to avoid unnecessary work.
if (array->length() > 0) {
push_objarray(array, 0);
}
}
void G1FullGCMarker::follow_array_chunk(objArrayOop array, int index) {
const int len = array->length();
const int beg_index = index;
assert(beg_index < len || len == 0, "index too large");
const int stride = MIN2(len - beg_index, (int) ObjArrayMarkingStride);
const int end_index = beg_index + stride;
array->oop_iterate_range(mark_closure(), beg_index, end_index);
if (VerifyDuringGC) {
_verify_closure.set_containing_obj(array);
NoHeaderExtendedOopClosure no(&_verify_closure);
array->oop_iterate_range(&no, beg_index, end_index);
if (_verify_closure.failures()) {
assert(false, "Failed");
}
}
if (end_index < len) {
push_objarray(array, end_index); // Push the continuation.
}
}
inline void G1FullGCMarker::follow_object(oop obj) {
assert(_bitmap->is_marked(obj), "should be marked");
if (obj->is_objArray()) {
// Handle object arrays explicitly to allow them to
// be split into chunks if needed.
follow_array((objArrayOop)obj);
} else {
obj->oop_iterate(mark_closure());
if (VerifyDuringGC) {
if (obj->is_instance() && InstanceKlass::cast(obj->klass())->is_reference_instance_klass()) {
return;
}
_verify_closure.set_containing_obj(obj);
obj->oop_iterate_no_header(&_verify_closure);
if (_verify_closure.failures()) {
log_warning(gc, verify)("Failed after %d", _verify_closure._cc);
assert(false, "Failed");
}
}
}
}
void G1FullGCMarker::drain_stack() {
do {
oop obj;
while (pop_object(obj)) {
assert(_bitmap->is_marked(obj), "must be marked");
follow_object(obj);
}
// Process ObjArrays one at a time to avoid marking stack bloat.
ObjArrayTask task;
if (pop_objarray(task)) {
follow_array_chunk(objArrayOop(task.obj()), task.index());
}
} while (!is_empty());
}
inline void G1FullGCMarker::follow_klass(Klass* k) {
oop op = k->klass_holder();
mark_and_push(&op);
}
inline void G1FullGCMarker::follow_cld(ClassLoaderData* cld) {
_cld_closure.do_cld(cld);
}
#endif

View file

@ -0,0 +1,148 @@
/*
* Copyright (c) 2017, 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/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1FullGCMarker.inline.hpp"
#include "gc/g1/g1FullGCOopClosures.inline.hpp"
#include "gc/g1/g1_specialized_oop_closures.hpp"
#include "logging/logStream.hpp"
void G1MarkAndPushClosure::do_oop(oop* p) {
do_oop_nv(p);
}
void G1MarkAndPushClosure::do_oop(narrowOop* p) {
do_oop_nv(p);
}
bool G1MarkAndPushClosure::do_metadata() {
return do_metadata_nv();
}
void G1MarkAndPushClosure::do_klass(Klass* k) {
do_klass_nv(k);
}
void G1MarkAndPushClosure::do_cld(ClassLoaderData* cld) {
do_cld_nv(cld);
}
G1AdjustAndRebuildClosure::G1AdjustAndRebuildClosure(uint worker_id) :
_worker_id(worker_id),
_compaction_delta(0),
_g1h(G1CollectedHeap::heap()) { }
void G1AdjustAndRebuildClosure::update_compaction_delta(oop obj) {
if (G1ArchiveAllocator::is_open_archive_object(obj)) {
_compaction_delta = 0;
return;
}
oop forwardee = obj->forwardee();
if (forwardee == NULL) {
// Object not moved.
_compaction_delta = 0;
} else {
// Object moved to forwardee, calculate delta.
_compaction_delta = calculate_compaction_delta(obj, forwardee);
}
}
void G1AdjustClosure::do_oop(oop* p) { adjust_pointer(p); }
void G1AdjustClosure::do_oop(narrowOop* p) { adjust_pointer(p); }
void G1AdjustAndRebuildClosure::do_oop(oop* p) { do_oop_nv(p); }
void G1AdjustAndRebuildClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
void G1FollowStackClosure::do_void() { _marker->drain_stack(); }
void G1FullKeepAliveClosure::do_oop(oop* p) { do_oop_work(p); }
void G1FullKeepAliveClosure::do_oop(narrowOop* p) { do_oop_work(p); }
G1VerifyOopClosure::G1VerifyOopClosure(VerifyOption option) :
_g1h(G1CollectedHeap::heap()),
_containing_obj(NULL),
_verify_option(option),
_cc(0),
_failures(false) {
}
void G1VerifyOopClosure::print_object(outputStream* out, oop obj) {
#ifdef PRODUCT
Klass* k = obj->klass();
const char* class_name = InstanceKlass::cast(k)->external_name();
out->print_cr("class name %s", class_name);
#else // PRODUCT
obj->print_on(out);
#endif // PRODUCT
}
template <class T> void G1VerifyOopClosure::do_oop_nv(T* p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
_cc++;
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
bool failed = false;
if (!_g1h->is_in_closed_subset(obj) || _g1h->is_obj_dead_cond(obj, _verify_option)) {
MutexLockerEx x(ParGCRareEvent_lock,
Mutex::_no_safepoint_check_flag);
LogStreamHandle(Error, gc, verify) yy;
if (!_failures) {
yy.cr();
yy.print_cr("----------");
}
if (!_g1h->is_in_closed_subset(obj)) {
HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
yy.print_cr("Field " PTR_FORMAT
" of live obj " PTR_FORMAT " in region "
"[" PTR_FORMAT ", " PTR_FORMAT ")",
p2i(p), p2i(_containing_obj),
p2i(from->bottom()), p2i(from->end()));
print_object(&yy, _containing_obj);
yy.print_cr("points to obj " PTR_FORMAT " not in the heap",
p2i(obj));
} else {
HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
HeapRegion* to = _g1h->heap_region_containing((HeapWord*)obj);
yy.print_cr("Field " PTR_FORMAT
" of live obj " PTR_FORMAT " in region "
"[" PTR_FORMAT ", " PTR_FORMAT ")",
p2i(p), p2i(_containing_obj),
p2i(from->bottom()), p2i(from->end()));
print_object(&yy, _containing_obj);
yy.print_cr("points to dead obj " PTR_FORMAT " in region "
"[" PTR_FORMAT ", " PTR_FORMAT ")",
p2i(obj), p2i(to->bottom()), p2i(to->end()));
print_object(&yy, obj);
}
yy.print_cr("----------");
yy.flush();
_failures = true;
failed = true;
}
}
}
// Generate G1 full GC specialized oop_oop_iterate functions.
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1FULL(ALL_KLASS_OOP_OOP_ITERATE_DEFN)

View file

@ -0,0 +1,151 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_GC_G1_G1FULLGCOOPCLOSURES_HPP
#define SHARE_GC_G1_G1FULLGCOOPCLOSURES_HPP
#include "memory/iterator.hpp"
#include "memory/universe.hpp"
class G1CollectedHeap;
class G1FullCollector;
class G1CMBitMap;
class G1FullGCMarker;
// Below are closures used by the G1 Full GC.
class G1IsAliveClosure : public BoolObjectClosure {
G1CMBitMap* _bitmap;
public:
G1IsAliveClosure(G1CMBitMap* bitmap) : _bitmap(bitmap) { }
virtual bool do_object_b(oop p);
};
class G1FullKeepAliveClosure: public OopClosure {
G1FullGCMarker* _marker;
template <class T>
inline void do_oop_work(T* p);
public:
G1FullKeepAliveClosure(G1FullGCMarker* pm) : _marker(pm) { }
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
};
class G1MarkAndPushClosure : public ExtendedOopClosure {
G1FullGCMarker* _marker;
uint _worker_id;
public:
G1MarkAndPushClosure(uint worker, G1FullGCMarker* marker, ReferenceProcessor* ref) :
_marker(marker),
_worker_id(worker),
ExtendedOopClosure(ref) { }
template <class T> inline void do_oop_nv(T* p);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
virtual bool do_metadata();
bool do_metadata_nv();
virtual void do_klass(Klass* k);
void do_klass_nv(Klass* k);
virtual void do_cld(ClassLoaderData* cld);
void do_cld_nv(ClassLoaderData* cld);
};
class G1AdjustClosure : public OopClosure {
public:
template <class T> static inline oop adjust_pointer(T* p);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
};
class G1AdjustAndRebuildClosure : public ExtendedOopClosure {
uint _worker_id;
size_t _compaction_delta;
G1CollectedHeap* _g1h;
inline size_t calculate_compaction_delta(oop current, oop forwardee);
template <class T> inline T* add_compaction_delta(T* p);
public:
G1AdjustAndRebuildClosure(uint worker_id);
void update_compaction_delta(oop obj);
template <class T> inline void add_reference(T* from_field, oop reference, uint worker_id);
template <class T> void do_oop_nv(T* p);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS; }
};
class G1AdjustObjectClosure {
G1AdjustAndRebuildClosure* _closure;
public:
G1AdjustObjectClosure(G1AdjustAndRebuildClosure* cl) : _closure(cl) { }
inline int adjust_object(oop obj);
};
class G1VerifyOopClosure: public OopClosure {
private:
G1CollectedHeap* _g1h;
bool _failures;
oop _containing_obj;
VerifyOption _verify_option;
public:
int _cc;
G1VerifyOopClosure(VerifyOption option);
void set_containing_obj(oop obj) {
_containing_obj = obj;
}
bool failures() { return _failures; }
void print_object(outputStream* out, oop obj);
template <class T> void do_oop_nv(T* p);
void do_oop(oop* p) { do_oop_nv(p); }
void do_oop(narrowOop* p) { do_oop_nv(p); }
};
class G1FollowStackClosure: public VoidClosure {
G1FullGCMarker* _marker;
public:
G1FollowStackClosure(G1FullGCMarker* marker) : _marker(marker) {}
virtual void do_void();
};
#endif // SHARE_GC_G1_G1FULLGCOOPCLOSURES_HPP

View file

@ -0,0 +1,128 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_GC_G1_G1FULLGCOOPCLOSURES_INLINE_HPP
#define SHARE_VM_GC_G1_G1FULLGCOOPCLOSURES_INLINE_HPP
#include "gc/g1/g1Allocator.hpp"
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
#include "gc/g1/g1FullGCMarker.inline.hpp"
#include "gc/g1/g1FullGCOopClosures.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "memory/iterator.inline.hpp"
template <typename T>
inline void G1MarkAndPushClosure::do_oop_nv(T* p) {
_marker->mark_and_push(p);
}
inline bool G1MarkAndPushClosure::do_metadata_nv() {
return true;
}
inline void G1MarkAndPushClosure::do_klass_nv(Klass* k) {
_marker->follow_klass(k);
}
inline void G1MarkAndPushClosure::do_cld_nv(ClassLoaderData* cld) {
_marker->follow_cld(cld);
}
template <class T> inline oop G1AdjustClosure::adjust_pointer(T* p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (oopDesc::is_null(heap_oop)) {
// NULL reference, return NULL.
return NULL;
}
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
assert(Universe::heap()->is_in(obj), "should be in heap");
if (G1ArchiveAllocator::is_archive_object(obj)) {
// Never forwarding archive objects, return current reference.
return obj;
}
oop forwardee = obj->forwardee();
if (forwardee == NULL) {
// Not forwarded, return current reference.
assert(obj->mark() == markOopDesc::prototype_for_object(obj) || // Correct mark
obj->mark()->must_be_preserved(obj) || // Will be restored by PreservedMarksSet
(UseBiasedLocking && obj->has_bias_pattern()), // Will be restored by BiasedLocking
"Must have correct prototype or be preserved, obj: " PTR_FORMAT ", mark: " PTR_FORMAT ", prototype: " PTR_FORMAT,
p2i(obj), p2i(obj->mark()), p2i(markOopDesc::prototype_for_object(obj)));
return obj;
}
// Forwarded, update and return new reference.
assert(Universe::heap()->is_in_reserved(forwardee), "should be in object space");
oopDesc::encode_store_heap_oop_not_null(p, forwardee);
return forwardee;
}
template <class T>
inline void G1AdjustAndRebuildClosure::add_reference(T* from_field, oop reference, uint worker_id) {
if (HeapRegion::is_in_same_region(from_field, reference)) {
return;
}
_g1h->heap_region_containing(reference)->rem_set()->add_reference(from_field, worker_id);
}
inline size_t G1AdjustAndRebuildClosure::calculate_compaction_delta(oop current, oop forwardee) {
return pointer_delta((HeapWord*)forwardee, (HeapWord*)current);
}
template <class T>
inline T* G1AdjustAndRebuildClosure::add_compaction_delta(T* p) {
return (T*)((HeapWord*)p + _compaction_delta);
}
template<typename T>
void G1AdjustAndRebuildClosure::do_oop_nv(T* p) {
oop new_reference = G1AdjustClosure::adjust_pointer(p);
if (new_reference == NULL) {
return;
}
// Update p using the calculated compaction delta to
// get the new field address.
T* new_field = add_compaction_delta(p);
// Update the remembered set.
add_reference(new_field, new_reference, _worker_id);
}
inline int G1AdjustObjectClosure::adjust_object(oop obj) {
_closure->update_compaction_delta(obj);
return obj->oop_iterate_size(_closure);
}
inline bool G1IsAliveClosure::do_object_b(oop p) {
return _bitmap->is_marked(p) || G1ArchiveAllocator::is_closed_archive_object(p);
}
template<typename T>
inline void G1FullKeepAliveClosure::do_oop_work(T* p) {
_marker->mark_and_push(p);
}
#endif

View file

@ -0,0 +1,220 @@
/*
* Copyright (c) 2017, 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/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
#include "gc/g1/g1FullCollector.hpp"
#include "gc/g1/g1FullGCCompactionPoint.hpp"
#include "gc/g1/g1FullGCMarker.hpp"
#include "gc/g1/g1FullGCOopClosures.inline.hpp"
#include "gc/g1/g1FullGCPrepareTask.hpp"
#include "gc/g1/g1HotCardCache.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "logging/log.hpp"
#include "utilities/ticks.inline.hpp"
bool G1FullGCPrepareTask::G1CalculatePointersClosure::doHeapRegion(HeapRegion* hr) {
if (hr->is_humongous()) {
oop obj = oop(hr->humongous_start_region()->bottom());
if (_bitmap->is_marked(obj)) {
if (hr->is_starts_humongous()) {
obj->forward_to(obj);
}
} else {
free_humongous_region(hr);
}
} else if (!hr->is_pinned()) {
prepare_for_compaction(hr);
}
// Reset data structures not valid after Full GC.
reset_region_metadata(hr);
return false;
}
G1FullGCPrepareTask::G1FullGCPrepareTask(G1FullCollector* collector) :
G1FullGCTask("G1 Prepare Compact Task", collector),
_hrclaimer(collector->workers()),
_freed_regions(false) {
}
void G1FullGCPrepareTask::set_freed_regions() {
if (!_freed_regions) {
_freed_regions = true;
}
}
bool G1FullGCPrepareTask::has_freed_regions() {
return _freed_regions;
}
void G1FullGCPrepareTask::work(uint worker_id) {
Ticks start = Ticks::now();
G1FullGCCompactionPoint* compaction_point = collector()->compaction_point(worker_id);
G1CalculatePointersClosure closure(collector()->mark_bitmap(), compaction_point);
G1CollectedHeap::heap()->heap_region_par_iterate_from_start(&closure, &_hrclaimer);
// Update humongous region sets
closure.update_sets();
compaction_point->update();
// Check if any regions was freed by this worker and store in task.
if (closure.freed_regions()) {
set_freed_regions();
}
log_task("Prepare compaction task", worker_id, start);
}
G1FullGCPrepareTask::G1CalculatePointersClosure::G1CalculatePointersClosure(G1CMBitMap* bitmap,
G1FullGCCompactionPoint* cp) :
_g1h(G1CollectedHeap::heap()),
_bitmap(bitmap),
_cp(cp),
_humongous_regions_removed(0) { }
void G1FullGCPrepareTask::G1CalculatePointersClosure::free_humongous_region(HeapRegion* hr) {
FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep");
hr->set_containing_set(NULL);
_humongous_regions_removed++;
_g1h->free_humongous_region(hr, &dummy_free_list, false /* skip_remset */);
prepare_for_compaction(hr);
dummy_free_list.remove_all();
}
void G1FullGCPrepareTask::G1CalculatePointersClosure::reset_region_metadata(HeapRegion* hr) {
hr->reset_gc_time_stamp();
hr->rem_set()->clear();
_g1h->g1_barrier_set()->clear(MemRegion(hr->bottom(), hr->end()));
if (_g1h->g1_hot_card_cache()->use_cache()) {
_g1h->g1_hot_card_cache()->reset_card_counts(hr);
}
}
G1FullGCPrepareTask::G1PrepareCompactLiveClosure::G1PrepareCompactLiveClosure(G1FullGCCompactionPoint* cp) :
_cp(cp) { }
size_t G1FullGCPrepareTask::G1PrepareCompactLiveClosure::apply(oop object) {
size_t size = object->size();
_cp->forward(object, size);
return size;
}
size_t G1FullGCPrepareTask::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;
}
void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_for_compaction_work(G1FullGCCompactionPoint* cp,
HeapRegion* hr) {
G1PrepareCompactLiveClosure prepare_compact(cp);
hr->set_compaction_top(hr->bottom());
hr->apply_to_marked_objects(_bitmap, &prepare_compact);
}
void G1FullGCPrepareTask::G1CalculatePointersClosure::prepare_for_compaction(HeapRegion* hr) {
if (!_cp->is_initialized()) {
hr->set_compaction_top(hr->bottom());
_cp->initialize(hr, true);
}
// Add region to the compaction queue and prepare it.
_cp->add(hr);
prepare_for_compaction_work(_cp, hr);
}
void G1FullGCPrepareTask::prepare_serial_compaction() {
GCTraceTime(Debug, gc, phases) debug("Phase 2: Prepare Serial Compaction", collector()->scope()->timer());
// At this point we know that no regions were completely freed by
// the parallel compaction. That means that the last region of
// all compaction queues still have data in them. We try to compact
// these regions in serial to avoid a premature OOM.
for (uint i = 0; i < collector()->workers(); i++) {
G1FullGCCompactionPoint* cp = collector()->compaction_point(i);
if (cp->has_regions()) {
collector()->serial_compaction_point()->add(cp->remove_last());
}
}
// Update the forwarding information for the regions in the serial
// compaction point.
G1FullGCCompactionPoint* cp = collector()->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 {
assert(!current->is_humongous(), "Should be no humongous regions in compaction queue");
G1RePrepareClosure re_prepare(cp, current);
current->set_compaction_top(current->bottom());
current->apply_to_marked_objects(collector()->mark_bitmap(), &re_prepare);
}
}
cp->update();
}
void G1FullGCPrepareTask::G1CalculatePointersClosure::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.
_g1h->remove_from_old_sets(0, _humongous_regions_removed);
}
bool G1FullGCPrepareTask::G1CalculatePointersClosure::freed_regions() {
if (_humongous_regions_removed > 0) {
// Free regions from dead humongous regions.
return true;
}
if (!_cp->has_regions()) {
// No regions in queue, so no free ones either.
return false;
}
if (_cp->current_region() != _cp->regions()->last()) {
// The current region used for compaction is not the last in the
// queue. That means there is at least one free region in the queue.
return true;
}
// No free regions in the queue.
return false;
}

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_GC_G1_G1FULLGCPREPARETASK_HPP
#define SHARE_GC_G1_G1FULLGCPREPARETASK_HPP
#include "gc/g1/g1FullGCCompactionPoint.hpp"
#include "gc/g1/g1FullGCScope.hpp"
#include "gc/g1/g1FullGCTask.hpp"
#include "gc/g1/g1RootProcessor.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/heapRegionManager.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "utilities/ticks.hpp"
class G1CMBitMap;
class G1FullGCPrepareTask : public G1FullGCTask {
protected:
volatile bool _freed_regions;
HeapRegionClaimer _hrclaimer;
void set_freed_regions();
public:
G1FullGCPrepareTask(G1FullCollector* collector);
void work(uint worker_id);
void prepare_serial_compaction();
bool has_freed_regions();
protected:
class G1CalculatePointersClosure : public HeapRegionClosure {
protected:
G1CollectedHeap* _g1h;
G1CMBitMap* _bitmap;
G1FullGCCompactionPoint* _cp;
uint _humongous_regions_removed;
virtual void prepare_for_compaction(HeapRegion* hr);
void prepare_for_compaction_work(G1FullGCCompactionPoint* cp, HeapRegion* hr);
void free_humongous_region(HeapRegion* hr);
void reset_region_metadata(HeapRegion* hr);
public:
G1CalculatePointersClosure(G1CMBitMap* bitmap,
G1FullGCCompactionPoint* cp);
void update_sets();
bool doHeapRegion(HeapRegion* hr);
bool freed_regions();
};
class G1PrepareCompactLiveClosure : public StackObj {
G1FullGCCompactionPoint* _cp;
public:
G1PrepareCompactLiveClosure(G1FullGCCompactionPoint* cp);
size_t apply(oop object);
};
class G1RePrepareClosure : public StackObj {
G1FullGCCompactionPoint* _cp;
HeapRegion* _current;
public:
G1RePrepareClosure(G1FullGCCompactionPoint* hrcp,
HeapRegion* hr) :
_cp(hrcp),
_current(hr) { }
size_t apply(oop object);
};
};
#endif // SHARE_GC_G1_G1FULLGCPREPARETASK_HPP

View file

@ -0,0 +1,115 @@
/*
* Copyright (c) 2017, 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/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1FullCollector.hpp"
#include "gc/g1/g1FullGCMarker.hpp"
#include "gc/g1/g1FullGCOopClosures.inline.hpp"
#include "gc/g1/g1FullGCReferenceProcessorExecutor.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/referenceProcessor.hpp"
G1FullGCReferenceProcessingExecutor::G1FullGCReferenceProcessingExecutor(G1FullCollector* collector) :
_collector(collector),
_reference_processor(collector->reference_processor()),
_old_mt_degree(_reference_processor->num_q()) {
if (_reference_processor->processing_is_mt()) {
_reference_processor->set_active_mt_degree(_collector->workers());
}
}
G1FullGCReferenceProcessingExecutor::~G1FullGCReferenceProcessingExecutor() {
if (_reference_processor->processing_is_mt()) {
_reference_processor->set_active_mt_degree(_old_mt_degree);
}
}
G1FullGCReferenceProcessingExecutor::G1RefProcTaskProxy::G1RefProcTaskProxy(ProcessTask& proc_task,
G1FullCollector* collector) :
AbstractGangTask("G1 reference processing task"),
_proc_task(proc_task),
_collector(collector),
_terminator(_collector->workers(), _collector->oop_queue_set()) { }
void G1FullGCReferenceProcessingExecutor::G1RefProcTaskProxy::work(uint worker_id) {
G1FullGCMarker* marker = _collector->marker(worker_id);
G1IsAliveClosure is_alive(_collector->mark_bitmap());
G1FullKeepAliveClosure keep_alive(marker);
_proc_task.work(worker_id,
is_alive,
keep_alive,
*marker->stack_closure());
}
G1FullGCReferenceProcessingExecutor::G1RefEnqueueTaskProxy::G1RefEnqueueTaskProxy(EnqueueTask& enq_task) :
AbstractGangTask("G1 reference enqueue task"),
_enq_task(enq_task) { }
void G1FullGCReferenceProcessingExecutor::G1RefEnqueueTaskProxy::work(uint worker_id) {
_enq_task.work(worker_id);
}
void G1FullGCReferenceProcessingExecutor::run_task(AbstractGangTask* task) {
G1CollectedHeap::heap()->workers()->run_task(task, _collector->workers());
}
void G1FullGCReferenceProcessingExecutor::execute(ProcessTask& proc_task) {
G1RefProcTaskProxy proc_task_proxy(proc_task, _collector);
run_task(&proc_task_proxy);
}
// Driver routine for parallel reference processing.
void G1FullGCReferenceProcessingExecutor::execute(EnqueueTask& enq_task) {
G1RefEnqueueTaskProxy enq_task_proxy(enq_task);
run_task(&enq_task_proxy);
}
void G1FullGCReferenceProcessingExecutor::execute(STWGCTimer* timer, G1FullGCTracer* tracer) {
GCTraceTime(Debug, gc, phases) debug("Phase 1: Reference Processing", timer);
// Process reference objects found during marking.
G1FullGCMarker* marker = _collector->marker(0);
G1IsAliveClosure is_alive(_collector->mark_bitmap());
G1FullKeepAliveClosure keep_alive(marker);
ReferenceProcessorPhaseTimes pt(timer, _reference_processor->num_q());
AbstractRefProcTaskExecutor* executor = _reference_processor->processing_is_mt() ? this : NULL;
// Process discovered references, use this executor if multi-threaded
// processing is enabled.
const ReferenceProcessorStats& stats =
_reference_processor->process_discovered_references(&is_alive,
&keep_alive,
marker->stack_closure(),
executor,
&pt);
tracer->report_gc_reference_stats(stats);
pt.print_all_references();
assert(marker->oop_stack()->is_empty(), "Should be no oops on the stack");
// Now enqueue the references.
_reference_processor->enqueue_discovered_references(executor, &pt);
pt.print_enqueue_phase();
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_GC_G1_G1FULLGCREFERENCEPROCESSOREXECUTOR_HPP
#define SHARE_GC_G1_G1FULLGCREFERENCEPROCESSOREXECUTOR_HPP
#include "gc/g1/g1FullGCCompactionPoint.hpp"
#include "gc/g1/g1FullGCScope.hpp"
#include "gc/g1/g1FullGCTask.hpp"
#include "gc/g1/g1RootProcessor.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/heapRegionManager.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "utilities/ticks.hpp"
class G1FullGCTracer;
class STWGCTimer;
class G1FullGCReferenceProcessingExecutor: public AbstractRefProcTaskExecutor {
G1FullCollector* _collector;
ReferenceProcessor* _reference_processor;
uint _old_mt_degree;
public:
G1FullGCReferenceProcessingExecutor(G1FullCollector* collector);
~G1FullGCReferenceProcessingExecutor();
// Do reference processing.
void execute(STWGCTimer* timer, G1FullGCTracer* tracer);
// Executes the given task using concurrent marking worker threads.
virtual void execute(ProcessTask& task);
virtual void execute(EnqueueTask& task);
private:
void run_task(AbstractGangTask* task);
class G1RefProcTaskProxy : public AbstractGangTask {
typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
ProcessTask& _proc_task;
G1FullCollector* _collector;
ParallelTaskTerminator _terminator;
public:
G1RefProcTaskProxy(ProcessTask& proc_task,
G1FullCollector* scope);
virtual void work(uint worker_id);
};
class G1RefEnqueueTaskProxy: public AbstractGangTask {
typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask;
EnqueueTask& _enq_task;
public:
G1RefEnqueueTaskProxy(EnqueueTask& enq_task);
virtual void work(uint worker_id);
};
};
#endif // SHARE_GC_G1_G1FULLGCREFERENCEPROCESSOREXECUTOR_HPP

View file

@ -25,13 +25,6 @@
#include "precompiled.hpp"
#include "gc/g1/g1FullGCScope.hpp"
G1FullGCScope* G1FullGCScope::_instance = NULL;
G1FullGCScope* G1FullGCScope::instance() {
assert(_instance != NULL, "Must be setup already");
return _instance;
}
G1FullGCScope::G1FullGCScope(bool explicit_gc, bool clear_soft) :
_rm(),
_explicit_gc(explicit_gc),
@ -46,12 +39,10 @@ G1FullGCScope::G1FullGCScope(bool explicit_gc, bool clear_soft) :
_memory_stats(true, _g1h->gc_cause()),
_collector_stats(_g1h->g1mm()->full_collection_counters()),
_heap_transition(_g1h) {
assert(_instance == NULL, "Only one scope at a time");
_timer.register_gc_start();
_tracer.report_gc_start(_g1h->gc_cause(), _timer.gc_start());
_g1h->pre_full_gc_dump(&_timer);
_g1h->trace_heap_before_gc(&_tracer);
_instance = this;
}
G1FullGCScope::~G1FullGCScope() {
@ -64,7 +55,6 @@ G1FullGCScope::~G1FullGCScope() {
_g1h->post_full_gc_dump(&_timer);
_timer.register_gc_end();
_tracer.report_gc_end(_timer.gc_end(), _timer.time_partitions());
_instance = NULL;
}
bool G1FullGCScope::is_explicit_gc() {
@ -79,7 +69,7 @@ STWGCTimer* G1FullGCScope::timer() {
return &_timer;
}
SerialOldTracer* G1FullGCScope::tracer() {
G1FullGCTracer* G1FullGCScope::tracer() {
return &_tracer;
}

View file

@ -45,7 +45,7 @@ class G1FullGCScope : public StackObj {
GCIdMark _gc_id;
SvcGCMarker _svc_marker;
STWGCTimer _timer;
SerialOldTracer _tracer;
G1FullGCTracer _tracer;
IsGCActiveMark _active;
GCTraceCPUTime _cpu_time;
ClearedAllSoftRefs _soft_refs;
@ -53,11 +53,7 @@ class G1FullGCScope : public StackObj {
TraceMemoryManagerStats _memory_stats;
G1HeapTransition _heap_transition;
// Singleton instance.
static G1FullGCScope* _instance;
public:
static G1FullGCScope* instance();
G1FullGCScope(bool explicit_gc, bool clear_soft);
~G1FullGCScope();
@ -65,7 +61,7 @@ public:
bool should_clear_soft_refs();
STWGCTimer* timer();
SerialOldTracer* tracer();
G1FullGCTracer* tracer();
G1HeapTransition* heap_transition();
};

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2017, 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/g1/g1FullGCTask.hpp"
#include "logging/log.hpp"
#include "utilities/ticks.inline.hpp"
void G1FullGCTask::log_task(const char* name, uint worker_id, const Ticks& start, const Ticks& stop) {
Tickspan duration = stop - start;
double duration_ms = TimeHelper::counter_to_millis(duration.value());
log_trace(gc, phases)("%s (%u) %.3fms", name, worker_id, duration_ms);
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_GC_G1_G1FULLGCTASK_HPP
#define SHARE_GC_G1_G1FULLGCTASK_HPP
#include "gc/shared/workgroup.hpp"
#include "utilities/ticks.hpp"
class G1FullCollector;
class G1FullGCTask : public AbstractGangTask {
G1FullCollector* _collector;
protected:
G1FullGCTask(const char* name, G1FullCollector* collector) :
AbstractGangTask(name),
_collector(collector) { }
G1FullCollector* collector() { return _collector; }
void log_task(const char* name, uint worker_id, const Ticks& start, const Ticks& stop = Ticks::now());
};
#endif // SHARE_GC_G1_G1FULLGCTASK_HPP

View file

@ -48,7 +48,7 @@ private:
public:
// _vo == UsePrevMarking -> use "prev" marking information,
// _vo == UseNextMarking -> use "next" marking information,
// _vo == UseMarkWord -> use mark word from object header.
// _vo == UseFullMarking -> use "next" marking bitmap but no TAMS
VerifyRootsClosure(VerifyOption vo) :
_g1h(G1CollectedHeap::heap()),
_vo(vo),
@ -63,9 +63,6 @@ public:
if (_g1h->is_obj_dead_cond(obj, _vo)) {
Log(gc, verify) log;
log.error("Root location " PTR_FORMAT " points to dead obj " PTR_FORMAT, p2i(p), p2i(obj));
if (_vo == VerifyOption_G1UseMarkWord) {
log.error(" Mark word: " PTR_FORMAT, p2i(obj->mark()));
}
ResourceMark rm;
LogStream ls(log.error());
obj->print_on(&ls);
@ -95,7 +92,7 @@ class G1VerifyCodeRootOopClosure: public OopClosure {
}
// Don't check the code roots during marking verification in a full GC
if (_vo == VerifyOption_G1UseMarkWord) {
if (_vo == VerifyOption_G1UseFullMarking) {
return;
}
@ -203,7 +200,7 @@ private:
public:
// _vo == UsePrevMarking -> use "prev" marking information,
// _vo == UseNextMarking -> use "next" marking information,
// _vo == UseMarkWord -> use mark word from object header.
// _vo == UseFullMarking -> use "next" marking bitmap but no TAMS.
VerifyObjsInRegionClosure(HeapRegion *hr, VerifyOption vo)
: _live_bytes(0), _hr(hr), _vo(vo) {
_g1h = G1CollectedHeap::heap();
@ -212,15 +209,15 @@ public:
VerifyLivenessOopClosure isLive(_g1h, _vo);
assert(o != NULL, "Huh?");
if (!_g1h->is_obj_dead_cond(o, _vo)) {
// If the object is alive according to the mark word,
// If the object is alive according to the full gc mark,
// then verify that the marking information agrees.
// Note we can't verify the contra-positive of the
// above: if the object is dead (according to the mark
// word), it may not be marked, or may have been marked
// but has since became dead, or may have been allocated
// since the last marking.
if (_vo == VerifyOption_G1UseMarkWord) {
guarantee(!_g1h->is_obj_dead(o), "mark word and concurrent mark mismatch");
if (_vo == VerifyOption_G1UseFullMarking) {
guarantee(!_g1h->is_obj_dead(o), "Full GC marking and concurrent mark mismatch");
}
o->oop_iterate_no_header(&isLive);
@ -299,7 +296,7 @@ private:
public:
// _vo == UsePrevMarking -> use "prev" marking information,
// _vo == UseNextMarking -> use "next" marking information,
// _vo == UseMarkWord -> use mark word from object header.
// _vo == UseFullMarking -> use "next" marking bitmap but no TAMS
VerifyRegionClosure(bool par, VerifyOption vo)
: _par(par),
_vo(vo),
@ -357,7 +354,7 @@ private:
public:
// _vo == UsePrevMarking -> use "prev" marking information,
// _vo == UseNextMarking -> use "next" marking information,
// _vo == UseMarkWord -> use mark word from object header.
// _vo == UseFullMarking -> use "next" marking bitmap but no TAMS
G1ParVerifyTask(G1CollectedHeap* g1h, VerifyOption vo) :
AbstractGangTask("Parallel verify task"),
_g1h(g1h),
@ -372,7 +369,7 @@ public:
void work(uint worker_id) {
HandleMark hm;
VerifyRegionClosure blk(true, _vo);
_g1h->heap_region_par_iterate(&blk, worker_id, &_hrclaimer);
_g1h->heap_region_par_iterate_from_worker_offset(&blk, &_hrclaimer, worker_id);
if (blk.failures()) {
_failures = true;
}
@ -407,7 +404,7 @@ void G1HeapVerifier::verify(VerifyOption vo) {
bool failures = rootsCl.failures() || codeRootsCl.failures();
if (vo != VerifyOption_G1UseMarkWord) {
if (!_g1h->g1_policy()->collector_state()->full_collection()) {
// If we're verifying during a full GC then the region sets
// will have been torn down at the start of the GC. Therefore
// verifying the region sets will fail. So we only verify

View file

@ -48,7 +48,7 @@ public:
// vo == UsePrevMarking -> use "prev" marking information,
// vo == UseNextMarking -> use "next" marking information
// vo == UseMarkWord -> use the mark word in the object header
// vo == UseFullMarking -> use "next" marking bitmap but no TAMS
//
// NOTE: Only the "prev" marking information is guaranteed to be
// consistent most of the time, so most calls to this should use
@ -57,7 +57,7 @@ public:
// vo == UseNextMarking, which is to verify the "next" marking
// information at the end of remark.
// Currently there is only one place where this is called with
// vo == UseMarkWord, which is to verify the marking during a
// vo == UseFullMarking, which is to verify the marking during a
// full GC.
void verify(VerifyOption vo);

View file

@ -110,7 +110,3 @@ void G1HotCardCache::drain(CardTableEntryClosure* cl, uint worker_i) {
void G1HotCardCache::reset_card_counts(HeapRegion* hr) {
_card_counts.clear_region(hr);
}
void G1HotCardCache::reset_card_counts() {
_card_counts.clear_all();
}

View file

@ -128,9 +128,6 @@ class G1HotCardCache: public CHeapObj<mtGC> {
}
}
// Zeros the values in the card counts table for entire committed heap
void reset_card_counts();
// Zeros the values in the card counts table for the given region
void reset_card_counts(HeapRegion* hr);

View file

@ -1,387 +0,0 @@
/*
* Copyright (c) 2001, 2017, 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 "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "code/icBuffer.hpp"
#include "gc/g1/g1FullGCScope.hpp"
#include "gc/g1/g1MarkSweep.hpp"
#include "gc/g1/g1RootProcessor.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/serial/markSweep.inline.hpp"
#include "gc/shared/gcHeapSummary.hpp"
#include "gc/shared/gcLocker.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTrace.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/modRefBarrierSet.hpp"
#include "gc/shared/referencePolicy.hpp"
#include "gc/shared/space.hpp"
#include "gc/shared/weakProcessor.hpp"
#include "oops/instanceRefKlass.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/atomic.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/thread.hpp"
#include "runtime/vmThread.hpp"
#include "utilities/copy.hpp"
#include "utilities/events.hpp"
class HeapRegion;
void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
bool clear_all_softrefs) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
HandleMark hm; // Discard invalid handles created during gc
#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
#ifdef ASSERT
if (G1CollectedHeap::heap()->collector_policy()->should_clear_all_soft_refs()) {
assert(clear_all_softrefs, "Policy should have been checked earler");
}
#endif
// hook up weak ref data so it can be used during Mark-Sweep
assert(GenMarkSweep::ref_processor() == NULL, "no stomping");
assert(rp != NULL, "should be non-NULL");
assert(rp == G1CollectedHeap::heap()->ref_processor_stw(), "Precondition");
GenMarkSweep::set_ref_processor(rp);
rp->setup_policy(clear_all_softrefs);
// When collecting the permanent generation Method*s may be moving,
// so we either have to flush all bcp data or convert it into bci.
CodeCache::gc_prologue();
bool marked_for_unloading = false;
allocate_stacks();
// We should save the marks of the currently locked biased monitors.
// The marking doesn't preserve the marks of biased objects.
BiasedLocking::preserve_marks();
// Process roots and do the marking.
mark_sweep_phase1(marked_for_unloading, clear_all_softrefs);
// Prepare compaction.
mark_sweep_phase2();
#if COMPILER2_OR_JVMCI
// Don't add any more derived pointers during phase3
DerivedPointerTable::set_active(false);
#endif
// Adjust all pointers.
mark_sweep_phase3();
// Do the actual compaction.
mark_sweep_phase4();
GenMarkSweep::restore_marks();
BiasedLocking::restore_marks();
GenMarkSweep::deallocate_stacks();
#if COMPILER2_OR_JVMCI
// Now update the derived pointers.
DerivedPointerTable::update_pointers();
#endif
CodeCache::gc_epilogue();
JvmtiExport::gc_epilogue();
// refs processing: clean slate
GenMarkSweep::set_ref_processor(NULL);
}
STWGCTimer* G1MarkSweep::gc_timer() {
return G1FullGCScope::instance()->timer();
}
SerialOldTracer* G1MarkSweep::gc_tracer() {
return G1FullGCScope::instance()->tracer();
}
void G1MarkSweep::allocate_stacks() {
GenMarkSweep::_preserved_count_max = 0;
GenMarkSweep::_preserved_marks = NULL;
GenMarkSweep::_preserved_count = 0;
}
void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
bool clear_all_softrefs) {
// Recursively traverse all live objects and mark them
GCTraceTime(Info, gc, phases) tm("Phase 1: Mark live objects", gc_timer());
G1CollectedHeap* g1h = G1CollectedHeap::heap();
// Need cleared claim bits for the roots processing
ClassLoaderDataGraph::clear_claimed_marks();
MarkingCodeBlobClosure follow_code_closure(&GenMarkSweep::follow_root_closure, !CodeBlobToOopClosure::FixRelocations);
{
G1RootProcessor root_processor(g1h, 1);
if (ClassUnloading) {
root_processor.process_strong_roots(&GenMarkSweep::follow_root_closure,
&GenMarkSweep::follow_cld_closure,
&follow_code_closure);
} else {
root_processor.process_all_roots_no_string_table(
&GenMarkSweep::follow_root_closure,
&GenMarkSweep::follow_cld_closure,
&follow_code_closure);
}
}
{
GCTraceTime(Debug, gc, phases) trace("Reference Processing", gc_timer());
// Process reference objects found during marking
ReferenceProcessor* rp = GenMarkSweep::ref_processor();
assert(rp == g1h->ref_processor_stw(), "Sanity");
rp->setup_policy(clear_all_softrefs);
ReferenceProcessorPhaseTimes pt(gc_timer(), rp->num_q());
const ReferenceProcessorStats& stats =
rp->process_discovered_references(&GenMarkSweep::is_alive,
&GenMarkSweep::keep_alive,
&GenMarkSweep::follow_stack_closure,
NULL,
&pt);
gc_tracer()->report_gc_reference_stats(stats);
pt.print_all_references();
}
// This is the point where the entire marking should have completed.
assert(GenMarkSweep::_marking_stack.is_empty(), "Marking should have completed");
{
GCTraceTime(Debug, gc, phases) trace("Weak Processing", gc_timer());
WeakProcessor::weak_oops_do(&GenMarkSweep::is_alive, &do_nothing_cl);
}
if (ClassUnloading) {
GCTraceTime(Debug, gc, phases) trace("Class Unloading", gc_timer());
// Unload classes and purge the SystemDictionary.
bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive, gc_timer());
g1h->complete_cleaning(&GenMarkSweep::is_alive, purged_class);
} else {
GCTraceTime(Debug, gc, phases) trace("Cleanup", gc_timer());
g1h->partial_cleaning(&GenMarkSweep::is_alive, true, true, G1StringDedup::is_enabled());
}
if (VerifyDuringGC) {
HandleMark hm; // handle scope
#if COMPILER2_OR_JVMCI
DerivedPointerTableDeactivate dpt_deact;
#endif
g1h->prepare_for_verify();
// Note: we can verify only the heap here. When an object is
// marked, the previous value of the mark word (including
// identity hash values, ages, etc) is preserved, and the mark
// word is set to markOop::marked_value - effectively removing
// any hash values from the mark word. These hash values are
// used when verifying the dictionaries and so removing them
// from the mark word can make verification of the dictionaries
// fail. At the end of the GC, the original mark word values
// (including hash values) are restored to the appropriate
// objects.
GCTraceTime(Info, gc, verify)("During GC (full)");
g1h->verify(VerifyOption_G1UseMarkWord);
}
gc_tracer()->report_object_count_after_gc(&GenMarkSweep::is_alive);
}
void G1MarkSweep::mark_sweep_phase2() {
// Now all live objects are marked, compute the new object addresses.
// It is not required that we traverse spaces in the same order in
// phase2, phase3 and phase4, but the ValidateMarkSweep live oops
// tracking expects us to do so. See comment under phase4.
GCTraceTime(Info, gc, phases) tm("Phase 2: Compute new object addresses", gc_timer());
prepare_compaction();
}
class G1AdjustPointersClosure: public HeapRegionClosure {
public:
bool doHeapRegion(HeapRegion* r) {
if (r->is_humongous()) {
if (r->is_starts_humongous()) {
// We must adjust the pointers on the single H object.
oop obj = oop(r->bottom());
// point all the oops to the new location
MarkSweep::adjust_pointers(obj);
}
} else if (!r->is_closed_archive()) {
// This really ought to be "as_CompactibleSpace"...
r->adjust_pointers();
}
return false;
}
};
void G1MarkSweep::mark_sweep_phase3() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
// Adjust the pointers to reflect the new locations
GCTraceTime(Info, gc, phases) tm("Phase 3: Adjust pointers", gc_timer());
// Need cleared claim bits for the roots processing
ClassLoaderDataGraph::clear_claimed_marks();
CodeBlobToOopClosure adjust_code_closure(&GenMarkSweep::adjust_pointer_closure, CodeBlobToOopClosure::FixRelocations);
{
G1RootProcessor root_processor(g1h, 1);
root_processor.process_all_roots(&GenMarkSweep::adjust_pointer_closure,
&GenMarkSweep::adjust_cld_closure,
&adjust_code_closure);
}
assert(GenMarkSweep::ref_processor() == g1h->ref_processor_stw(), "Sanity");
g1h->ref_processor_stw()->weak_oops_do(&GenMarkSweep::adjust_pointer_closure);
// Now adjust pointers in remaining weak roots. (All of which should
// have been cleared if they pointed to non-surviving objects.)
WeakProcessor::oops_do(&GenMarkSweep::adjust_pointer_closure);
if (G1StringDedup::is_enabled()) {
G1StringDedup::oops_do(&GenMarkSweep::adjust_pointer_closure);
}
GenMarkSweep::adjust_marks();
G1AdjustPointersClosure blk;
g1h->heap_region_iterate(&blk);
}
class G1SpaceCompactClosure: public HeapRegionClosure {
public:
G1SpaceCompactClosure() {}
bool doHeapRegion(HeapRegion* hr) {
if (hr->is_humongous()) {
if (hr->is_starts_humongous()) {
oop obj = oop(hr->bottom());
if (obj->is_gc_marked()) {
obj->init_mark();
} else {
assert(hr->is_empty(), "Should have been cleared in phase 2.");
}
}
hr->reset_during_compaction();
} else if (!hr->is_pinned()) {
hr->compact();
}
return false;
}
};
void G1MarkSweep::mark_sweep_phase4() {
// All pointers are now adjusted, move objects accordingly
// The ValidateMarkSweep live oops tracking expects us to traverse spaces
// in the same order in phase2, phase3 and phase4. We don't quite do that
// here (code and comment not fixed for perm removal), so we tell the validate code
// to use a higher index (saved from phase2) when verifying perm_gen.
G1CollectedHeap* g1h = G1CollectedHeap::heap();
GCTraceTime(Info, gc, phases) tm("Phase 4: Move objects", gc_timer());
G1SpaceCompactClosure blk;
g1h->heap_region_iterate(&blk);
}
void G1MarkSweep::prepare_compaction_work(G1PrepareCompactClosure* blk) {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
g1h->heap_region_iterate(blk);
blk->update_sets();
}
void G1PrepareCompactClosure::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++;
_g1h->free_humongous_region(hr, &dummy_free_list, false /* skip_remset */);
prepare_for_compaction(hr, end);
dummy_free_list.remove_all();
}
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();
}
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.
_g1h->remove_from_old_sets(0, _humongous_regions_removed);
}
bool G1PrepareCompactClosure::doHeapRegion(HeapRegion* hr) {
if (hr->is_humongous()) {
oop obj = oop(hr->humongous_start_region()->bottom());
if (hr->is_starts_humongous() && obj->is_gc_marked()) {
obj->forward_to(obj);
}
if (!obj->is_gc_marked()) {
free_humongous_region(hr);
}
} else if (!hr->is_pinned()) {
prepare_for_compaction(hr, hr->end());
}
return false;
}

View file

@ -1,96 +0,0 @@
/*
* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_GC_G1_G1MARKSWEEP_HPP
#define SHARE_VM_GC_G1_G1MARKSWEEP_HPP
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/heapRegion.hpp"
#include "gc/serial/genMarkSweep.hpp"
#include "gc/shared/generation.hpp"
#include "memory/universe.hpp"
#include "oops/markOop.hpp"
#include "oops/oop.hpp"
#include "runtime/timer.hpp"
#include "utilities/growableArray.hpp"
class ReferenceProcessor;
// G1MarkSweep takes care of global mark-compact garbage collection for a
// G1CollectedHeap using a four-phase pointer forwarding algorithm. All
// generations are assumed to support marking; those that can also support
// compaction.
//
// Class unloading will only occur when a full gc is invoked.
class G1PrepareCompactClosure;
class G1ArchiveRegionMap;
class G1MarkSweep : AllStatic {
public:
static void invoke_at_safepoint(ReferenceProcessor* rp,
bool clear_all_softrefs);
static STWGCTimer* gc_timer();
static SerialOldTracer* gc_tracer();
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();
// Update pointers
static void mark_sweep_phase3();
// Move objects to new positions
static void mark_sweep_phase4();
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;
uint _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(0) { }
void update_sets();
bool doHeapRegion(HeapRegion* hr);
};
#endif // SHARE_VM_GC_G1_G1MARKSWEEP_HPP

View file

@ -30,7 +30,6 @@
#include "gc/g1/g1OopClosures.hpp"
#include "gc/g1/g1ParScanThreadState.inline.hpp"
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/g1RemSet.inline.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "memory/iterator.inline.hpp"

View file

@ -26,7 +26,7 @@
#define SHARE_VM_GC_G1_G1PARSCANTHREADSTATE_INLINE_HPP
#include "gc/g1/g1ParScanThreadState.hpp"
#include "gc/g1/g1RemSet.inline.hpp"
#include "gc/g1/g1RemSet.hpp"
#include "oops/oop.inline.hpp"
template <class T> void G1ParScanThreadState::do_oop_evac(T* p, HeapRegion* from) {

View file

@ -31,7 +31,7 @@
#include "gc/g1/g1GCPhaseTimes.hpp"
#include "gc/g1/g1HotCardCache.hpp"
#include "gc/g1/g1OopClosures.inline.hpp"
#include "gc/g1/g1RemSet.inline.hpp"
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/g1SATBCardTableModRefBS.inline.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionManager.inline.hpp"
@ -532,7 +532,7 @@ public:
void G1RemSet::scrub(uint worker_num, HeapRegionClaimer *hrclaimer) {
G1ScrubRSClosure scrub_cl(&_card_live_data);
_g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer);
_g1->heap_region_par_iterate_from_worker_offset(&scrub_cl, hrclaimer, worker_num);
}
inline void check_card_ptr(jbyte* card_ptr, CardTableModRefBS* ct_bs) {

View file

@ -114,10 +114,6 @@ public:
G1RemSetScanState* scan_state() const { return _scan_state; }
// Record, if necessary, the fact that *p (where "p" is in region "from",
// which is required to be non-NULL) has changed to a new non-NULL value.
template <class T> void par_write_ref(HeapRegion* from, T* p, uint tid);
// Eliminates any remembered set entries that correspond to dead heap ranges.
void scrub(uint worker_num, HeapRegionClaimer* hrclaimer);
@ -191,25 +187,4 @@ public:
size_t cards_skipped() const { return _cards_skipped; }
};
class RebuildRSOopClosure: public ExtendedOopClosure {
HeapRegion* _from;
G1RemSet* _rs;
uint _worker_i;
template <class T> void do_oop_work(T* p);
public:
RebuildRSOopClosure(G1RemSet* rs, uint worker_i = 0) :
_from(NULL), _rs(rs), _worker_i(worker_i)
{}
void set_from(HeapRegion* from) {
assert(from != NULL, "from region must be non-NULL");
_from = from;
}
virtual void do_oop(narrowOop* p) { do_oop_work(p); }
virtual void do_oop(oop* p) { do_oop_work(p); }
};
#endif // SHARE_VM_GC_G1_G1REMSET_HPP

View file

@ -1,62 +0,0 @@
/*
* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_GC_G1_G1REMSET_INLINE_HPP
#define SHARE_VM_GC_G1_G1REMSET_INLINE_HPP
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/heapRegion.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "oops/oop.inline.hpp"
template <class T>
inline void G1RemSet::par_write_ref(HeapRegion* from, T* p, uint tid) {
oop obj = oopDesc::load_decode_heap_oop(p);
if (obj == NULL) {
return;
}
#ifdef ASSERT
// can't do because of races
// assert(oopDesc::is_oop_or_null(obj), "expected an oop");
assert(check_obj_alignment(obj), "not oop aligned");
assert(_g1->is_in_reserved(obj), "must be in heap");
#endif // ASSERT
assert(from->is_in_reserved(p) || from->is_starts_humongous(), "p is not in from");
HeapRegion* to = _g1->heap_region_containing(obj);
if (from != to) {
assert(to->rem_set() != NULL, "Need per-region 'into' remsets.");
to->rem_set()->add_reference(p, tid);
}
}
template <class T>
inline void RebuildRSOopClosure::do_oop_work(T* p) {
assert(_from != NULL, "from region must be non-NULL");
_rs->par_write_ref(_from, p, _worker_i);
}
#endif // SHARE_VM_GC_G1_G1REMSET_INLINE_HPP

View file

@ -26,7 +26,7 @@
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1ConcurrentRefine.hpp"
#include "gc/g1/g1ConcurrentRefineThread.hpp"
#include "gc/g1/g1RemSet.inline.hpp"
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/g1RemSetSummary.hpp"
#include "gc/g1/g1YoungRemSetSamplingThread.hpp"
#include "gc/g1/heapRegion.hpp"

View file

@ -37,6 +37,7 @@
#include "gc/g1/g1RootClosures.hpp"
#include "gc/g1/g1RootProcessor.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/shared/weakProcessor.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/mutex.hpp"
#include "services/management.hpp"
@ -319,6 +320,16 @@ void G1RootProcessor::process_code_cache_roots(CodeBlobClosure* code_closure,
}
}
void G1RootProcessor::process_full_gc_weak_roots(OopClosure* oops) {
if (!_process_strong_tasks.is_task_claimed(G1RP_PS_refProcessor_oops_do)) {
_g1h->ref_processor_stw()->weak_oops_do(oops);
}
if (!_process_strong_tasks.is_task_claimed(G1RP_PS_weakProcessor_oops_do)) {
WeakProcessor::oops_do(oops);
}
}
uint G1RootProcessor::n_workers() const {
return _srs.n_threads();
}

View file

@ -65,6 +65,7 @@ class G1RootProcessor : public StackObj {
G1RP_PS_aot_oops_do,
G1RP_PS_filter_satb_buffers,
G1RP_PS_refProcessor_oops_do,
G1RP_PS_weakProcessor_oops_do,
// Leave this one last.
G1RP_PS_NumElements
};
@ -118,6 +119,10 @@ public:
CLDClosure* clds,
CodeBlobClosure* blobs);
// Apply closure to weak roots in the system. Used during the adjust phase
// for the Full GC.
void process_full_gc_weak_roots(OopClosure* oops);
// Number of worker threads used by the root processor.
uint n_workers() const;
};

View file

@ -1,143 +0,0 @@
/*
* Copyright (c) 2017, 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/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1FullGCScope.hpp"
#include "gc/g1/g1MarkSweep.hpp"
#include "gc/g1/g1RemSet.inline.hpp"
#include "gc/g1/g1SerialFullCollector.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "gc/shared/referenceProcessor.hpp"
G1SerialFullCollector::G1SerialFullCollector(G1FullGCScope* scope,
ReferenceProcessor* reference_processor) :
_scope(scope),
_reference_processor(reference_processor),
_is_alive_mutator(_reference_processor, NULL),
_mt_discovery_mutator(_reference_processor, false) {
// Temporarily make discovery by the STW ref processor single threaded (non-MT)
// and clear the STW ref processor's _is_alive_non_header field.
}
void G1SerialFullCollector::prepare_collection() {
_reference_processor->enable_discovery();
_reference_processor->setup_policy(_scope->should_clear_soft_refs());
}
void G1SerialFullCollector::complete_collection() {
// Enqueue any discovered reference objects that have
// not been removed from the discovered lists.
ReferenceProcessorPhaseTimes pt(NULL, _reference_processor->num_q());
_reference_processor->enqueue_discovered_references(NULL, &pt);
pt.print_enqueue_phase();
// Iterate the heap and rebuild the remembered sets.
rebuild_remembered_sets();
}
void G1SerialFullCollector::collect() {
// Do the actual collection work.
G1MarkSweep::invoke_at_safepoint(_reference_processor, _scope->should_clear_soft_refs());
}
class PostMCRemSetClearClosure: public HeapRegionClosure {
G1CollectedHeap* _g1h;
ModRefBarrierSet* _mr_bs;
public:
PostMCRemSetClearClosure(G1CollectedHeap* g1h, ModRefBarrierSet* mr_bs) :
_g1h(g1h), _mr_bs(mr_bs) {}
bool doHeapRegion(HeapRegion* r) {
HeapRegionRemSet* hrrs = r->rem_set();
_g1h->reset_gc_time_stamps(r);
if (r->is_continues_humongous()) {
// We'll assert that the strong code root list and RSet is empty
assert(hrrs->strong_code_roots_list_length() == 0, "sanity");
assert(hrrs->occupied() == 0, "RSet should be empty");
} else {
hrrs->clear();
}
// You might think here that we could clear just the cards
// corresponding to the used region. But no: if we leave a dirty card
// in a region we might allocate into, then it would prevent that card
// from being enqueued, and cause it to be missed.
// Re: the performance cost: we shouldn't be doing full GC anyway!
_mr_bs->clear(MemRegion(r->bottom(), r->end()));
return false;
}
};
class RebuildRSOutOfRegionClosure: public HeapRegionClosure {
G1CollectedHeap* _g1h;
RebuildRSOopClosure _cl;
public:
RebuildRSOutOfRegionClosure(G1CollectedHeap* g1, uint worker_i = 0) :
_cl(g1->g1_rem_set(), worker_i),
_g1h(g1)
{ }
bool doHeapRegion(HeapRegion* r) {
if (!r->is_continues_humongous()) {
_cl.set_from(r);
r->oop_iterate(&_cl);
}
return false;
}
};
class ParRebuildRSTask: public AbstractGangTask {
G1CollectedHeap* _g1;
HeapRegionClaimer _hrclaimer;
public:
ParRebuildRSTask(G1CollectedHeap* g1) :
AbstractGangTask("ParRebuildRSTask"), _g1(g1), _hrclaimer(g1->workers()->active_workers()) {}
void work(uint worker_id) {
RebuildRSOutOfRegionClosure rebuild_rs(_g1, worker_id);
_g1->heap_region_par_iterate(&rebuild_rs, worker_id, &_hrclaimer);
}
};
void G1SerialFullCollector::rebuild_remembered_sets() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
// First clear the stale remembered sets.
PostMCRemSetClearClosure rs_clear(g1h, g1h->g1_barrier_set());
g1h->heap_region_iterate(&rs_clear);
// Rebuild remembered sets of all regions.
uint n_workers = AdaptiveSizePolicy::calc_active_workers(g1h->workers()->total_workers(),
g1h->workers()->active_workers(),
Threads::number_of_non_daemon_threads());
g1h->workers()->update_active_workers(n_workers);
log_info(gc,task)("Using %u workers of %u to rebuild remembered set", n_workers, g1h->workers()->total_workers());
ParRebuildRSTask rebuild_rs_task(g1h);
g1h->workers()->run_task(&rebuild_rs_task);
}

View file

@ -65,10 +65,10 @@ bool G1StringDedup::is_candidate_from_mark(oop obj) {
return false;
}
void G1StringDedup::enqueue_from_mark(oop java_string) {
void G1StringDedup::enqueue_from_mark(oop java_string, uint worker_id) {
assert(is_enabled(), "String deduplication not enabled");
if (is_candidate_from_mark(java_string)) {
G1StringDedupQueue::push(0 /* worker_id */, java_string);
G1StringDedupQueue::push(worker_id, java_string);
}
}

View file

@ -125,7 +125,7 @@ public:
// Enqueues a deduplication candidate for later processing by the deduplication
// thread. Before enqueuing, these functions apply the appropriate candidate
// selection policy to filters out non-candidates.
static void enqueue_from_mark(oop java_string);
static void enqueue_from_mark(oop java_string, uint worker_id);
static void enqueue_from_evacuation(bool from_young, bool to_young,
unsigned int queue, oop java_string);

View file

@ -41,6 +41,9 @@ class G1ConcurrentRefineOopClosure;
class G1CMOopClosure;
class G1RootRegionScanClosure;
class G1MarkAndPushClosure;
class G1AdjustAndRebuildClosure;
#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1(f) \
f(G1ScanEvacuatedObjClosure,_nv) \
f(G1ScanObjsDuringUpdateRSClosure,_nv) \
@ -49,4 +52,8 @@ class G1RootRegionScanClosure;
f(G1CMOopClosure,_nv) \
f(G1RootRegionScanClosure,_nv)
#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1FULL(f) \
f(G1MarkAndPushClosure,_nv) \
f(G1AdjustAndRebuildClosure,_nv)
#endif // SHARE_VM_GC_G1_G1_SPECIALIZED_OOP_CLOSURES_HPP

View file

@ -42,6 +42,7 @@
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "utilities/growableArray.hpp"
int HeapRegion::LogOfHRGrainBytes = 0;
int HeapRegion::LogOfHRGrainWords = 0;
@ -106,14 +107,6 @@ void HeapRegion::setup_heap_region_size(size_t initial_heap_size, size_t max_hea
}
}
void HeapRegion::reset_after_compaction() {
G1ContiguousSpace::reset_after_compaction();
// After a compaction the mark bitmap is invalid, so we must
// treat all objects as being inside the unmarked area.
zero_marked_bytes();
init_top_at_mark_start();
}
void HeapRegion::hr_clear(bool keep_remset, bool clear_space, bool locked) {
assert(_humongous_start_region == NULL,
"we should have already filtered out humongous regions");
@ -278,10 +271,6 @@ void HeapRegion::report_region_type_change(G1HeapRegionTraceType::Type to) {
(uint)allocation_context());
}
CompactibleSpace* HeapRegion::next_compaction_space() const {
return G1CollectedHeap::heap()->next_compaction_region(this);
}
void HeapRegion::note_self_forwarding_removal_start(bool during_initial_mark,
bool during_conc_mark) {
// We always recreate the prev marking info and we'll explicitly
@ -411,7 +400,7 @@ void HeapRegion::verify_strong_code_roots(VerifyOption vo, bool* failures) const
// We're not verifying code roots.
return;
}
if (vo == VerifyOption_G1UseMarkWord) {
if (vo == VerifyOption_G1UseFullMarking) {
// Marking verification during a full GC is performed after class
// unloading, code cache unloading, etc so the strong code roots
// attached to each heap region are in an inconsistent state. They won't
@ -482,7 +471,7 @@ protected:
public:
// _vo == UsePrevMarking -> use "prev" marking information,
// _vo == UseNextMarking -> use "next" marking information,
// _vo == UseMarkWord -> use mark word from object header.
// _vo == UseFullMarking -> use "next" marking bitmap but no TAMS.
G1VerificationClosure(G1CollectedHeap* g1h, VerifyOption vo) :
_g1h(g1h), _bs(barrier_set_cast<CardTableModRefBS>(g1h->barrier_set())),
_containing_obj(NULL), _failures(false), _n_failures(0), _vo(vo) {
@ -833,7 +822,8 @@ void HeapRegion::verify_rem_set() const {
}
void HeapRegion::prepare_for_compaction(CompactPoint* cp) {
scan_and_forward(this, cp);
// Not used for G1 anymore, but pure virtual in Space.
ShouldNotReachHere();
}
// G1OffsetTableContigSpace code; copied from space.cpp. Hope this can go

View file

@ -57,6 +57,7 @@
class G1CollectedHeap;
class G1CMBitMap;
class G1IsAliveAndApplyClosure;
class HeapRegionRemSet;
class HeapRegionRemSetIterator;
class HeapRegion;
@ -355,8 +356,14 @@ class HeapRegion: public G1ContiguousSpace {
// and the amount of unallocated words if called on top()
size_t block_size(const HeapWord* p) const;
// Scans through the region using the bitmap to determine what
// objects to call size_t ApplyToMarkedClosure::apply(oop) for.
template<typename ApplyToMarkedClosure>
inline void apply_to_marked_objects(G1CMBitMap* bitmap, ApplyToMarkedClosure* closure);
// Override for scan_and_forward support.
void prepare_for_compaction(CompactPoint* cp);
// Update heap region to be consistent after compaction.
void complete_compaction();
inline HeapWord* par_allocate_no_bot_updates(size_t min_word_size, size_t desired_word_size, size_t* word_size);
inline HeapWord* allocate_no_bot_updates(size_t word_size);
@ -672,10 +679,6 @@ class HeapRegion: public G1ContiguousSpace {
_predicted_elapsed_time_ms = ms;
}
virtual CompactibleSpace* next_compaction_space() const;
virtual void reset_after_compaction();
// Routines for managing a list of code roots (attached to the
// this region's RSet) that point into this heap region.
void add_strong_code_root(nmethod* nm);
@ -695,7 +698,7 @@ class HeapRegion: public G1ContiguousSpace {
// vo == UsePrevMarking -> use "prev" marking information,
// vo == UseNextMarking -> use "next" marking information
// vo == UseMarkWord -> use the mark word in the object header
// vo == UseFullMarking -> use "next" marking bitmap but no TAMS
//
// NOTE: Only the "prev" marking information is guaranteed to be
// consistent most of the time, so most calls to this should use
@ -704,7 +707,7 @@ class HeapRegion: public G1ContiguousSpace {
// vo == UseNextMarking, which is to verify the "next" marking
// information at the end of remark.
// Currently there is only one place where this is called with
// vo == UseMarkWord, which is to verify the marking during a
// vo == UseFullMarking, which is to verify the marking during a
// full GC.
void verify(VerifyOption vo, bool *failures) const;

View file

@ -27,10 +27,12 @@
#include "gc/g1/g1BlockOffsetTable.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
#include "gc/g1/heapRegion.hpp"
#include "gc/shared/space.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/prefetch.inline.hpp"
#include "utilities/align.hpp"
inline HeapWord* G1ContiguousSpace::allocate_impl(size_t min_word_size,
@ -180,6 +182,45 @@ inline size_t HeapRegion::block_size(const HeapWord *addr) const {
return block_size_using_bitmap(addr, G1CollectedHeap::heap()->concurrent_mark()->prev_mark_bitmap());
}
inline void HeapRegion::complete_compaction() {
// Reset space and bot after compaction is complete if needed.
reset_after_compaction();
if (used_region().is_empty()) {
reset_bot();
}
// After a compaction the mark bitmap is invalid, so we must
// treat all objects as being inside the unmarked area.
zero_marked_bytes();
init_top_at_mark_start();
// Clear unused heap memory in debug builds.
if (ZapUnusedHeapArea) {
mangle_unused_area();
}
}
template<typename ApplyToMarkedClosure>
inline void HeapRegion::apply_to_marked_objects(G1CMBitMap* bitmap, ApplyToMarkedClosure* closure) {
HeapWord* limit = scan_limit();
HeapWord* next_addr = bottom();
while (next_addr < limit) {
Prefetch::write(next_addr, PrefetchScanIntervalInBytes);
// This explicit is_marked check is a way to avoid
// some extra work done by get_next_marked_addr for
// the case where next_addr is marked.
if (bitmap->is_marked(next_addr)) {
oop current = oop(next_addr);
next_addr += closure->apply(current);
} else {
next_addr = bitmap->get_next_marked_addr(next_addr, limit);
}
}
assert(next_addr == limit, "Should stop the scan at the limit.");
}
inline HeapWord* HeapRegion::par_allocate_no_bot_updates(size_t min_word_size,
size_t desired_word_size,
size_t* actual_word_size) {

View file

@ -327,9 +327,7 @@ bool HeapRegionManager::allocate_containing_regions(MemRegion range, size_t* com
return true;
}
void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer) const {
const uint start_index = hrclaimer->start_region_for_worker(worker_id);
void HeapRegionManager::par_iterate(HeapRegionClosure* blk, HeapRegionClaimer* hrclaimer, const uint start_index) const {
// Every worker will actually look at all regions, skipping over regions that
// are currently not committed.
// This also (potentially) iterates over regions newly allocated during GC. This
@ -493,7 +491,7 @@ HeapRegionClaimer::~HeapRegionClaimer() {
}
}
uint HeapRegionClaimer::start_region_for_worker(uint worker_id) const {
uint HeapRegionClaimer::offset_for_worker(uint worker_id) const {
assert(worker_id < _n_workers, "Invalid worker_id.");
return _n_regions * worker_id / _n_workers;
}

View file

@ -189,7 +189,7 @@ public:
return _free_list.length();
}
size_t total_capacity_bytes() const {
size_t total_free_bytes() const {
return num_free_regions() * HeapRegion::GrainBytes;
}
@ -240,7 +240,7 @@ public:
// terminating the iteration early if doHeapRegion() returns true.
void iterate(HeapRegionClosure* blk) const;
void par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer) const;
void par_iterate(HeapRegionClosure* blk, HeapRegionClaimer* hrclaimer, const uint start_index) const;
// Uncommit up to num_regions_to_remove regions that are completely free.
// Return the actual number of uncommitted regions.
@ -274,9 +274,8 @@ class HeapRegionClaimer : public StackObj {
return _n_regions;
}
// Calculate the starting region for given worker so
// that they do not all start from the same region.
uint start_region_for_worker(uint worker_id) const;
// Return a start offset given a worker id.
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;

View file

@ -65,13 +65,6 @@ CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closu
CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure);
inline void MarkSweep::mark_object(oop obj) {
#if INCLUDE_ALL_GCS
if (G1StringDedup::is_enabled()) {
// We must enqueue the object before it is marked
// as we otherwise can't read the object's age.
G1StringDedup::enqueue_from_mark(obj);
}
#endif
// some marks may contain information we need to preserve so we store them away
// and overwrite the mark. We'll restore it at the end of markSweep.
markOop mark = obj->mark();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2017, 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
@ -37,6 +37,7 @@ enum GCName {
G1New,
ConcurrentMarkSweep,
G1Old,
G1Full,
GCNameEndSentinel
};
@ -53,6 +54,7 @@ class GCNameHelper {
case G1New: return "G1New";
case ConcurrentMarkSweep: return "ConcurrentMarkSweep";
case G1Old: return "G1Old";
case G1Full: return "G1Full";
default: ShouldNotReachHere(); return NULL;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017, 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
@ -289,6 +289,12 @@ class G1NewTracer : public YoungGCTracer {
double predicted_marking_length,
bool prediction_active);
};
class G1FullGCTracer : public OldGCTracer {
public:
G1FullGCTracer() : OldGCTracer(G1Full) {}
};
#endif
class CMSTracer : public OldGCTracer {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, 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
@ -37,6 +37,18 @@ void PreservedMarks::restore() {
assert_empty();
}
void PreservedMarks::adjust_during_full_gc() {
StackIterator<OopAndMarkOop, mtGC> iter(_stack);
while (!iter.is_empty()) {
OopAndMarkOop* elem = iter.next_addr();
oop obj = elem->get_oop();
if (obj->is_forwarded()) {
elem->set_oop(obj->forwardee());
}
}
}
void PreservedMarks::restore_and_increment(volatile size_t* const total_size_addr) {
const size_t stack_size = size();
restore();
@ -104,7 +116,6 @@ public:
}
};
void PreservedMarksSet::reclaim() {
assert_empty();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, 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
@ -35,7 +35,7 @@ class WorkGang;
class PreservedMarks VALUE_OBJ_CLASS_SPEC {
private:
class OopAndMarkOop {
class OopAndMarkOop VALUE_OBJ_CLASS_SPEC {
private:
oop _o;
markOop _m;
@ -43,23 +43,26 @@ private:
public:
OopAndMarkOop(oop obj, markOop m) : _o(obj), _m(m) { }
void set_mark() const {
_o->set_mark(_m);
}
oop get_oop() { return _o; }
void set_mark() const { _o->set_mark(_m); }
void set_oop(oop obj) { _o = obj; }
};
typedef Stack<OopAndMarkOop, mtGC> OopAndMarkOopStack;
OopAndMarkOopStack _stack;
inline bool should_preserve_mark(oop obj, markOop m) const;
inline void push(oop obj, markOop m);
public:
size_t size() const { return _stack.size(); }
inline void push(oop obj, markOop m);
inline void push_if_necessary(oop obj, markOop m);
// Iterate over the stack, restore all preserved marks, and
// reclaim the memory taken up by the stack segments.
void restore();
// Iterate over the stack, adjust all preserved marks according
// to their forwarding location stored in the mark.
void adjust_during_full_gc();
void restore_and_increment(volatile size_t* const _total_size_addr);
inline static void init_forwarded_mark(oop obj);

View file

@ -110,7 +110,8 @@ class NoHeaderExtendedOopClosure;
#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) \
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f) \
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_CMS(f) \
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1(f)
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1(f) \
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1FULL(f)
#else // INCLUDE_ALL_GCS
#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) \
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f)

View file

@ -369,6 +369,7 @@ public:
typedef typename T::element_type E;
GenericTaskQueueSet(int n);
~GenericTaskQueueSet();
bool steal_best_of_2(uint queue_num, int* seed, E& t);

View file

@ -42,6 +42,11 @@ inline GenericTaskQueueSet<T, F>::GenericTaskQueueSet(int n) : _n(n) {
}
}
template <class T, MEMFLAGS F>
inline GenericTaskQueueSet<T, F>::~GenericTaskQueueSet() {
FREE_C_HEAP_ARRAY(T*, _queues);
}
template<class E, MEMFLAGS F, unsigned int N>
inline void GenericTaskQueue<E, F, N>::initialize() {
_elems = ArrayAllocator<E>::allocate(N, F);
@ -49,7 +54,6 @@ inline void GenericTaskQueue<E, F, N>::initialize() {
template<class E, MEMFLAGS F, unsigned int N>
inline GenericTaskQueue<E, F, N>::~GenericTaskQueue() {
assert(false, "This code is currently never called");
ArrayAllocator<E>::free(const_cast<E*>(_elems), N);
}

View file

@ -90,7 +90,7 @@ enum VerifyOption {
// G1
VerifyOption_G1UsePrevMarking = VerifyOption_Default,
VerifyOption_G1UseNextMarking = VerifyOption_G1UsePrevMarking + 1,
VerifyOption_G1UseMarkWord = VerifyOption_G1UseNextMarking + 1
VerifyOption_G1UseFullMarking = VerifyOption_G1UseNextMarking + 1
};
class Universe: AllStatic {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2017, 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
@ -36,6 +36,7 @@ public enum GCName {
G1New ("G1New"),
ConcurrentMarkSweep ("ConcurrentMarkSweep"),
G1Old ("G1Old"),
G1Full ("G1Full"),
GCNameEndSentinel ("GCNameEndSentinel");
private final String value;

View file

@ -0,0 +1,116 @@
/*
* Copyright (c) 2017, 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/g1/g1BlockOffsetTable.hpp"
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "unittest.hpp"
class VerifyAndCountMarkClosure : public StackObj {
int _count;
G1CMBitMap* _bm;
void ensure_marked(HeapWord* addr) {
ASSERT_TRUE(_bm->is_marked(addr));
}
public:
VerifyAndCountMarkClosure(G1CMBitMap* bm) : _count(0), _bm(bm) { }
virtual size_t apply(oop object) {
_count++;
ensure_marked((HeapWord*) object);
// Must return positive size to advance the iteration.
return MinObjAlignment;
}
void reset() {
_count = 0;
}
int count() {
return _count;
}
};
#define MARK_OFFSET_1 ( 17 * MinObjAlignment)
#define MARK_OFFSET_2 ( 99 * MinObjAlignment)
#define MARK_OFFSET_3 (337 * MinObjAlignment)
TEST_OTHER_VM(HeapRegion, apply_to_marked_objects) {
if (!UseG1GC) {
return;
}
G1CollectedHeap* heap = G1CollectedHeap::heap();
// Using region 0 for testing.
HeapRegion* region = heap->heap_region_containing(heap->bottom_addr_for_region(0));
// Mark some "oops" in the bitmap.
G1CMBitMap* bitmap = heap->concurrent_mark()->next_mark_bitmap();
bitmap->mark(region->bottom());
bitmap->mark(region->bottom() + MARK_OFFSET_1);
bitmap->mark(region->bottom() + MARK_OFFSET_2);
bitmap->mark(region->bottom() + MARK_OFFSET_3);
bitmap->mark(region->end());
VerifyAndCountMarkClosure cl(bitmap);
// When top is equal to bottom the closure should not be
// applied to any object because apply_to_marked_objects
// will stop at HeapRegion::scan_limit which is equal to top.
region->set_top(region->bottom());
region->apply_to_marked_objects(bitmap, &cl);
EXPECT_EQ(0, cl.count());
cl.reset();
// Set top to offset_1 and expect only to find 1 entry (bottom)
region->set_top(region->bottom() + MARK_OFFSET_1);
region->apply_to_marked_objects(bitmap, &cl);
EXPECT_EQ(1, cl.count());
cl.reset();
// Set top to (offset_2 + 1) and expect only to find 3
// entries (bottom, offset_1 and offset_2)
region->set_top(region->bottom() + MARK_OFFSET_2 + MinObjAlignment);
region->apply_to_marked_objects(bitmap, &cl);
EXPECT_EQ(3, cl.count());
cl.reset();
// Still expect same 3 entries when top is (offset_3 - 1)
region->set_top(region->bottom() + MARK_OFFSET_3 - MinObjAlignment);
region->apply_to_marked_objects(bitmap, &cl);
EXPECT_EQ(3, cl.count());
cl.reset();
// Setting top to end should render 4 entries.
region->set_top(region->end());
region->apply_to_marked_objects(bitmap, &cl);
EXPECT_EQ(4, cl.count());
cl.reset();
}

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2017, 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/shared/preservedMarks.inline.hpp"
#include "unittest.hpp"
class ScopedDisabledBiasedLocking {
bool _orig;
public:
ScopedDisabledBiasedLocking() : _orig(UseBiasedLocking) { UseBiasedLocking = false; }
~ScopedDisabledBiasedLocking() { UseBiasedLocking = _orig; }
};
// Class to create a "fake" oop with a mark that will
// return true for calls to must_be_preserved().
class FakeOop {
oopDesc _oop;
public:
FakeOop() : _oop() { _oop.set_mark(originalMark()); }
oop get_oop() { return &_oop; }
markOop mark() { return _oop.mark(); }
void set_mark(markOop m) { _oop.set_mark(m); }
void forward_to(oop obj) {
markOop m = markOopDesc::encode_pointer_as_mark(obj);
_oop.set_mark(m);
}
static markOop originalMark() { return markOop(markOopDesc::lock_mask_in_place); }
static markOop changedMark() { return markOop(0x4711); }
};
TEST_VM(PreservedMarks, iterate_and_restore) {
// Need to disable biased locking to easily
// create oops that "must_be_preseved"
ScopedDisabledBiasedLocking dbl;
PreservedMarks pm;
FakeOop o1;
FakeOop o2;
FakeOop o3;
FakeOop o4;
// Make sure initial marks are correct.
ASSERT_EQ(o1.mark(), FakeOop::originalMark());
ASSERT_EQ(o2.mark(), FakeOop::originalMark());
ASSERT_EQ(o3.mark(), FakeOop::originalMark());
ASSERT_EQ(o4.mark(), FakeOop::originalMark());
// Change the marks and verify change.
o1.set_mark(FakeOop::changedMark());
o2.set_mark(FakeOop::changedMark());
ASSERT_EQ(o1.mark(), FakeOop::changedMark());
ASSERT_EQ(o2.mark(), FakeOop::changedMark());
// Push o1 and o2 to have their marks preserved.
pm.push(o1.get_oop(), o1.mark());
pm.push(o2.get_oop(), o2.mark());
// Fake a move from o1->o3 and o2->o4.
o1.forward_to(o3.get_oop());
o2.forward_to(o4.get_oop());
ASSERT_EQ(o1.get_oop()->forwardee(), o3.get_oop());
ASSERT_EQ(o2.get_oop()->forwardee(), o4.get_oop());
// Adjust will update the PreservedMarks stack to
// make sure the mark is updated at the new location.
pm.adjust_during_full_gc();
// Restore all preserved and verify that the changed
// mark is now present at o3 and o4.
pm.restore();
ASSERT_EQ(o3.mark(), FakeOop::changedMark());
ASSERT_EQ(o4.mark(), FakeOop::changedMark());
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, 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
@ -156,8 +156,9 @@ public class TestMaxMinHeapFreeRatioFlags {
if (args.length != 3) {
throw new IllegalArgumentException("Expected 3 args: <minRatio> <maxRatio> <shrinkHeapInSteps>");
}
if (GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.PSOld) {
System.out.println("Test is not applicable to parallel GC");
if (GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.PSOld ||
GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.G1) {
System.out.println("Test is not applicable to parallel full GCs");
return;
}