Path: blob/master/src/hotspot/share/gc/z/zDriver.cpp
40961 views
/*1* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include "precompiled.hpp"24#include "gc/shared/gcId.hpp"25#include "gc/shared/gcLocker.hpp"26#include "gc/shared/gcVMOperations.hpp"27#include "gc/shared/isGCActiveMark.hpp"28#include "gc/z/zAbort.inline.hpp"29#include "gc/z/zBreakpoint.hpp"30#include "gc/z/zCollectedHeap.hpp"31#include "gc/z/zDriver.hpp"32#include "gc/z/zHeap.inline.hpp"33#include "gc/z/zMessagePort.inline.hpp"34#include "gc/z/zServiceability.hpp"35#include "gc/z/zStat.hpp"36#include "gc/z/zVerify.hpp"37#include "logging/log.hpp"38#include "memory/universe.hpp"39#include "runtime/vmOperations.hpp"40#include "runtime/vmThread.hpp"4142static const ZStatPhaseCycle ZPhaseCycle("Garbage Collection Cycle");43static const ZStatPhasePause ZPhasePauseMarkStart("Pause Mark Start");44static const ZStatPhaseConcurrent ZPhaseConcurrentMark("Concurrent Mark");45static const ZStatPhaseConcurrent ZPhaseConcurrentMarkContinue("Concurrent Mark Continue");46static const ZStatPhaseConcurrent ZPhaseConcurrentMarkFree("Concurrent Mark Free");47static const ZStatPhasePause ZPhasePauseMarkEnd("Pause Mark End");48static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Concurrent Process Non-Strong References");49static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set");50static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set");51static const ZStatPhasePause ZPhasePauseRelocateStart("Pause Relocate Start");52static const ZStatPhaseConcurrent ZPhaseConcurrentRelocated("Concurrent Relocate");53static const ZStatCriticalPhase ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */);54static const ZStatSampler ZSamplerJavaThreads("System", "Java Threads", ZStatUnitThreads);5556class VM_ZOperation : public VM_Operation {57private:58const uint _gc_id;59bool _gc_locked;60bool _success;6162public:63VM_ZOperation() :64_gc_id(GCId::current()),65_gc_locked(false),66_success(false) {}6768virtual bool needs_inactive_gc_locker() const {69// An inactive GC locker is needed in operations where we change the bad70// mask or move objects. Changing the bad mask will invalidate all oops,71// which makes it conceptually the same thing as moving all objects.72return false;73}7475virtual bool skip_thread_oop_barriers() const {76return true;77}7879virtual bool do_operation() = 0;8081virtual bool doit_prologue() {82Heap_lock->lock();83return true;84}8586virtual void doit() {87// Abort if GC locker state is incompatible88if (needs_inactive_gc_locker() && GCLocker::check_active_before_gc()) {89_gc_locked = true;90return;91}9293// Setup GC id and active marker94GCIdMark gc_id_mark(_gc_id);95IsGCActiveMark gc_active_mark;9697// Verify before operation98ZVerify::before_zoperation();99100// Execute operation101_success = do_operation();102103// Update statistics104ZStatSample(ZSamplerJavaThreads, Threads::number_of_threads());105}106107virtual void doit_epilogue() {108Heap_lock->unlock();109}110111bool gc_locked() const {112return _gc_locked;113}114115bool success() const {116return _success;117}118};119120static bool should_clear_soft_references() {121// Clear if one or more allocations have stalled122const bool stalled = ZHeap::heap()->is_alloc_stalled();123if (stalled) {124// Clear125return true;126}127128// Clear if implied by the GC cause129const GCCause::Cause cause = ZCollectedHeap::heap()->gc_cause();130if (cause == GCCause::_wb_full_gc ||131cause == GCCause::_metadata_GC_clear_soft_refs) {132// Clear133return true;134}135136// Don't clear137return false;138}139140static bool should_boost_worker_threads() {141// Boost worker threads if one or more allocations have stalled142const bool stalled = ZHeap::heap()->is_alloc_stalled();143if (stalled) {144// Boost145return true;146}147148// Boost worker threads if implied by the GC cause149const GCCause::Cause cause = ZCollectedHeap::heap()->gc_cause();150if (cause == GCCause::_wb_full_gc ||151cause == GCCause::_java_lang_system_gc ||152cause == GCCause::_metadata_GC_clear_soft_refs) {153// Boost154return true;155}156157// Don't boost158return false;159}160161class VM_ZMarkStart : public VM_ZOperation {162public:163virtual VMOp_Type type() const {164return VMOp_ZMarkStart;165}166167virtual bool needs_inactive_gc_locker() const {168return true;169}170171virtual bool do_operation() {172ZStatTimer timer(ZPhasePauseMarkStart);173ZServiceabilityPauseTracer tracer;174175// Set up soft reference policy176const bool clear = should_clear_soft_references();177ZHeap::heap()->set_soft_reference_policy(clear);178179// Set up boost mode180const bool boost = should_boost_worker_threads();181ZHeap::heap()->set_boost_worker_threads(boost);182183ZCollectedHeap::heap()->increment_total_collections(true /* full */);184185ZHeap::heap()->mark_start();186return true;187}188};189190class VM_ZMarkEnd : public VM_ZOperation {191public:192virtual VMOp_Type type() const {193return VMOp_ZMarkEnd;194}195196virtual bool do_operation() {197ZStatTimer timer(ZPhasePauseMarkEnd);198ZServiceabilityPauseTracer tracer;199return ZHeap::heap()->mark_end();200}201};202203class VM_ZRelocateStart : public VM_ZOperation {204public:205virtual VMOp_Type type() const {206return VMOp_ZRelocateStart;207}208209virtual bool needs_inactive_gc_locker() const {210return true;211}212213virtual bool do_operation() {214ZStatTimer timer(ZPhasePauseRelocateStart);215ZServiceabilityPauseTracer tracer;216ZHeap::heap()->relocate_start();217return true;218}219};220221class VM_ZVerify : public VM_Operation {222public:223virtual VMOp_Type type() const {224return VMOp_ZVerify;225}226227virtual bool skip_thread_oop_barriers() const {228return true;229}230231virtual void doit() {232ZVerify::after_weak_processing();233}234};235236ZDriver::ZDriver() :237_gc_cycle_port(),238_gc_locker_port() {239set_name("ZDriver");240create_and_start();241}242243void ZDriver::collect(GCCause::Cause cause) {244switch (cause) {245case GCCause::_wb_young_gc:246case GCCause::_wb_conc_mark:247case GCCause::_wb_full_gc:248case GCCause::_dcmd_gc_run:249case GCCause::_java_lang_system_gc:250case GCCause::_full_gc_alot:251case GCCause::_scavenge_alot:252case GCCause::_jvmti_force_gc:253case GCCause::_metadata_GC_clear_soft_refs:254// Start synchronous GC255_gc_cycle_port.send_sync(cause);256break;257258case GCCause::_z_timer:259case GCCause::_z_warmup:260case GCCause::_z_allocation_rate:261case GCCause::_z_allocation_stall:262case GCCause::_z_proactive:263case GCCause::_z_high_usage:264case GCCause::_metadata_GC_threshold:265// Start asynchronous GC266_gc_cycle_port.send_async(cause);267break;268269case GCCause::_gc_locker:270// Restart VM operation previously blocked by the GC locker271_gc_locker_port.signal();272break;273274case GCCause::_wb_breakpoint:275ZBreakpoint::start_gc();276_gc_cycle_port.send_async(cause);277break;278279default:280// Other causes not supported281fatal("Unsupported GC cause (%s)", GCCause::to_string(cause));282break;283}284}285286template <typename T>287bool ZDriver::pause() {288for (;;) {289T op;290VMThread::execute(&op);291if (op.gc_locked()) {292// Wait for GC to become unlocked and restart the VM operation293ZStatTimer timer(ZCriticalPhaseGCLockerStall);294_gc_locker_port.wait();295continue;296}297298// Notify VM operation completed299_gc_locker_port.ack();300301return op.success();302}303}304305void ZDriver::pause_mark_start() {306pause<VM_ZMarkStart>();307}308309void ZDriver::concurrent_mark() {310ZStatTimer timer(ZPhaseConcurrentMark);311ZBreakpoint::at_after_marking_started();312ZHeap::heap()->mark(true /* initial */);313ZBreakpoint::at_before_marking_completed();314}315316bool ZDriver::pause_mark_end() {317return pause<VM_ZMarkEnd>();318}319320void ZDriver::concurrent_mark_continue() {321ZStatTimer timer(ZPhaseConcurrentMarkContinue);322ZHeap::heap()->mark(false /* initial */);323}324325void ZDriver::concurrent_mark_free() {326ZStatTimer timer(ZPhaseConcurrentMarkFree);327ZHeap::heap()->mark_free();328}329330void ZDriver::concurrent_process_non_strong_references() {331ZStatTimer timer(ZPhaseConcurrentProcessNonStrongReferences);332ZBreakpoint::at_after_reference_processing_started();333ZHeap::heap()->process_non_strong_references();334}335336void ZDriver::concurrent_reset_relocation_set() {337ZStatTimer timer(ZPhaseConcurrentResetRelocationSet);338ZHeap::heap()->reset_relocation_set();339}340341void ZDriver::pause_verify() {342if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) {343// Full verification344VM_Verify op;345VMThread::execute(&op);346} else if (ZVerifyRoots || ZVerifyObjects) {347// Limited verification348VM_ZVerify op;349VMThread::execute(&op);350}351}352353void ZDriver::concurrent_select_relocation_set() {354ZStatTimer timer(ZPhaseConcurrentSelectRelocationSet);355ZHeap::heap()->select_relocation_set();356}357358void ZDriver::pause_relocate_start() {359pause<VM_ZRelocateStart>();360}361362void ZDriver::concurrent_relocate() {363ZStatTimer timer(ZPhaseConcurrentRelocated);364ZHeap::heap()->relocate();365}366367void ZDriver::check_out_of_memory() {368ZHeap::heap()->check_out_of_memory();369}370371class ZDriverGCScope : public StackObj {372private:373GCIdMark _gc_id;374GCCause::Cause _gc_cause;375GCCauseSetter _gc_cause_setter;376ZStatTimer _timer;377ZServiceabilityCycleTracer _tracer;378379public:380ZDriverGCScope(GCCause::Cause cause) :381_gc_id(),382_gc_cause(cause),383_gc_cause_setter(ZCollectedHeap::heap(), cause),384_timer(ZPhaseCycle),385_tracer() {386// Update statistics387ZStatCycle::at_start();388}389390~ZDriverGCScope() {391// Calculate boost factor392const double boost_factor = (double)ZHeap::heap()->nconcurrent_worker_threads() /393(double)ZHeap::heap()->nconcurrent_no_boost_worker_threads();394395// Update statistics396ZStatCycle::at_end(_gc_cause, boost_factor);397398// Update data used by soft reference policy399Universe::heap()->update_capacity_and_used_at_gc();400401// Signal that we have completed a visit to all live objects402Universe::heap()->record_whole_heap_examined_timestamp();403}404};405406// Macro to execute a termination check after a concurrent phase. Note407// that it's important that the termination check comes after the call408// to the function f, since we can't abort between pause_relocate_start()409// and concurrent_relocate(). We need to let concurrent_relocate() call410// abort_page() on the remaining entries in the relocation set.411#define concurrent(f) \412do { \413concurrent_##f(); \414if (should_terminate()) { \415return; \416} \417} while (false)418419void ZDriver::gc(GCCause::Cause cause) {420ZDriverGCScope scope(cause);421422// Phase 1: Pause Mark Start423pause_mark_start();424425// Phase 2: Concurrent Mark426concurrent(mark);427428// Phase 3: Pause Mark End429while (!pause_mark_end()) {430// Phase 3.5: Concurrent Mark Continue431concurrent(mark_continue);432}433434// Phase 4: Concurrent Mark Free435concurrent(mark_free);436437// Phase 5: Concurrent Process Non-Strong References438concurrent(process_non_strong_references);439440// Phase 6: Concurrent Reset Relocation Set441concurrent(reset_relocation_set);442443// Phase 7: Pause Verify444pause_verify();445446// Phase 8: Concurrent Select Relocation Set447concurrent(select_relocation_set);448449// Phase 9: Pause Relocate Start450pause_relocate_start();451452// Phase 10: Concurrent Relocate453concurrent(relocate);454}455456void ZDriver::run_service() {457// Main loop458while (!should_terminate()) {459// Wait for GC request460const GCCause::Cause cause = _gc_cycle_port.receive();461if (cause == GCCause::_no_gc) {462continue;463}464465ZBreakpoint::at_before_gc();466467// Run GC468gc(cause);469470// Notify GC completed471_gc_cycle_port.ack();472473// Check for out of memory condition474check_out_of_memory();475476ZBreakpoint::at_after_gc();477}478}479480void ZDriver::stop_service() {481ZAbort::abort();482_gc_cycle_port.send_async(GCCause::_no_gc);483}484485486