8261473: Shenandoah: Add breakpoint support

Reviewed-by: rkennke, shade
This commit is contained in:
Zhengyu Gu 2021-02-18 18:32:01 +00:00
parent c4664e6446
commit 9cf4f90d34
7 changed files with 163 additions and 12 deletions

@ -0,0 +1,65 @@
/*
* Copyright (c) 2021, Red Hat, Inc. All rights reserved.
* Copyright (c) 2020, 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/concurrentGCBreakpoints.hpp"
#include "gc/shenandoah/shenandoahBreakpoint.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/debug.hpp"
bool ShenandoahBreakpoint::_start_gc = false;
void ShenandoahBreakpoint::start_gc() {
MonitorLocker ml(ConcurrentGCBreakpoints::monitor());
assert(ConcurrentGCBreakpoints::is_controlled(), "Invalid state");
assert(!_start_gc, "Invalid state");
_start_gc = true;
ml.notify_all();
}
void ShenandoahBreakpoint::at_before_gc() {
MonitorLocker ml(ConcurrentGCBreakpoints::monitor(), Mutex::_no_safepoint_check_flag);
while (ConcurrentGCBreakpoints::is_controlled() && !_start_gc) {
ml.wait();
}
_start_gc = false;
ConcurrentGCBreakpoints::notify_idle_to_active();
}
void ShenandoahBreakpoint::at_after_gc() {
ConcurrentGCBreakpoints::notify_active_to_idle();
}
void ShenandoahBreakpoint::at_after_marking_started() {
ConcurrentGCBreakpoints::at("AFTER MARKING STARTED");
}
void ShenandoahBreakpoint::at_before_marking_completed() {
ConcurrentGCBreakpoints::at("BEFORE MARKING COMPLETED");
}
void ShenandoahBreakpoint::at_after_reference_processing_started() {
ConcurrentGCBreakpoints::at("AFTER CONCURRENT REFERENCE PROCESSING STARTED");
}

@ -0,0 +1,44 @@
/*
* Copyright (c) 2021, Red Hat, Inc. All rights reserved.
* Copyright (c) 2020, 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_SHENANDOAH_SHENANDOAHBREAKPOINT_HPP
#define SHARE_GC_SHENANDOAH_SHENANDOAHBREAKPOINT_HPP
#include "memory/allocation.hpp"
class ShenandoahBreakpoint : public AllStatic {
private:
static bool _start_gc;
public:
static void start_gc();
static void at_before_gc();
static void at_after_gc();
static void at_after_marking_started();
static void at_before_marking_completed();
static void at_after_reference_processing_started();
};
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHBREAKPOINT_HPP

@ -26,6 +26,7 @@
#include "gc/shared/barrierSetNMethod.hpp"
#include "gc/shared/collectorCounters.hpp"
#include "gc/shenandoah/shenandoahBreakpoint.hpp"
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
#include "gc/shenandoah/shenandoahConcurrentGC.hpp"
#include "gc/shenandoah/shenandoahFreeSet.hpp"
@ -42,9 +43,34 @@
#include "gc/shenandoah/shenandoahVMOperations.hpp"
#include "gc/shenandoah/shenandoahWorkGroup.hpp"
#include "gc/shenandoah/shenandoahWorkerPolicy.hpp"
#include "memory/allocation.hpp"
#include "prims/jvmtiTagMap.hpp"
#include "runtime/vmThread.hpp"
#include "utilities/events.hpp"
// Breakpoint support
class ShenandoahBreakpointGCScope : public StackObj {
public:
ShenandoahBreakpointGCScope() {
ShenandoahBreakpoint::at_before_gc();
}
~ShenandoahBreakpointGCScope() {
ShenandoahBreakpoint::at_after_gc();
}
};
class ShenandoahBreakpointMarkScope : public StackObj {
public:
ShenandoahBreakpointMarkScope() {
ShenandoahBreakpoint::at_after_marking_started();
}
~ShenandoahBreakpointMarkScope() {
ShenandoahBreakpoint::at_before_marking_completed();
}
};
ShenandoahConcurrentGC::ShenandoahConcurrentGC() :
_mark(),
_degen_point(ShenandoahDegenPoint::_degenerated_unset) {
@ -60,6 +86,10 @@ void ShenandoahConcurrentGC::cancel() {
bool ShenandoahConcurrentGC::collect(GCCause::Cause cause) {
ShenandoahHeap* const heap = ShenandoahHeap::heap();
if (cause == GCCause::_wb_breakpoint) {
ShenandoahBreakpoint::start_gc();
}
ShenandoahBreakpointGCScope breakpoint_gc_scope;
// Reset for upcoming marking
entry_reset();
@ -67,13 +97,16 @@ bool ShenandoahConcurrentGC::collect(GCCause::Cause cause) {
// Start initial mark under STW
vmop_entry_init_mark();
{
ShenandoahBreakpointMarkScope breakpoint_mark_scope;
// Concurrent mark roots
entry_mark_roots();
if (check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_outside_cycle)) return false;
entry_mark_roots();
if (check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_outside_cycle)) return false;
// Continue concurrent mark
entry_mark();
if (check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_mark)) return false;
// Continue concurrent mark
entry_mark();
if (check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_mark)) return false;
}
// Complete marking under STW, and start evacuation
vmop_entry_final_mark();
@ -621,6 +654,7 @@ void ShenandoahConcurrentGC::op_weak_refs() {
assert(heap->is_concurrent_weak_root_in_progress(), "Only during this phase");
// Concurrent weak refs processing
ShenandoahGCWorkerPhase worker_phase(ShenandoahPhaseTimings::conc_weak_refs);
ShenandoahBreakpoint::at_after_reference_processing_started();
heap->ref_processor()->process_references(ShenandoahPhaseTimings::conc_weak_refs, heap->workers(), true /* concurrent */);
}

@ -23,7 +23,6 @@
*/
#include "precompiled.hpp"
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
#include "gc/shenandoah/shenandoahConcurrentGC.hpp"
#include "gc/shenandoah/shenandoahControlThread.hpp"
@ -478,6 +477,7 @@ void ShenandoahControlThread::request_gc(GCCause::Cause cause) {
cause == GCCause::_metadata_GC_clear_soft_refs ||
cause == GCCause::_full_gc_alot ||
cause == GCCause::_wb_full_gc ||
cause == GCCause::_wb_breakpoint ||
cause == GCCause::_scavenge_alot,
"only requested GCs here");
@ -506,7 +506,10 @@ void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
while (current_gc_id < required_gc_id) {
_gc_requested.set();
_requested_gc_cause = cause;
ml.wait();
if (cause != GCCause::_wb_breakpoint) {
ml.wait();
}
current_gc_id = get_gc_id();
}
}

@ -162,6 +162,11 @@ public:
void prepare_for_verify();
void verify(VerifyOption vo);
// WhiteBox testing support.
bool supports_concurrent_gc_breakpoints() const {
return true;
}
// ---------- Heap counters and metrics
//
private:

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2021, 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
@ -117,14 +117,14 @@ public class TestConcurrentGCBreakpoints {
private static boolean expectSupported() {
return GC.G1.isSelected() ||
GC.Z.isSelected();
GC.Z.isSelected() ||
GC.Shenandoah.isSelected();
}
private static boolean expectUnsupported() {
return GC.Serial.isSelected() ||
GC.Parallel.isSelected() ||
GC.Epsilon.isSelected() ||
GC.Shenandoah.isSelected();
GC.Epsilon.isSelected();
}
public static void main(String[] args) throws Exception {

@ -25,7 +25,7 @@ package gc;
/* @test
* @bug 8256517
* @requires vm.gc.Z
* @requires vm.gc.Z | vm.gc.Shenandoah
* @requires vm.gc != "null"
* @library /test/lib
* @build sun.hotspot.WhiteBox