Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp
38920 views
/*1* Copyright (c) 2005, 2014, 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*22*/2324#include "precompiled.hpp"25#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp"26#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"27#include "gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp"28#include "gc_implementation/shared/gcTimer.hpp"29#include "gc_implementation/shared/gcTraceTime.hpp"30#include "gc_implementation/shared/isGCActiveMark.hpp"31#include "memory/gcLocker.inline.hpp"32#include "runtime/interfaceSupport.hpp"33#include "runtime/os.hpp"34#include "utilities/dtrace.hpp"3536PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC3738#ifndef USDT239HS_DTRACE_PROBE_DECL(hs_private, cms__initmark__begin);40HS_DTRACE_PROBE_DECL(hs_private, cms__initmark__end);4142HS_DTRACE_PROBE_DECL(hs_private, cms__remark__begin);43HS_DTRACE_PROBE_DECL(hs_private, cms__remark__end);44#endif /* !USDT2 */4546//////////////////////////////////////////////////////////47// Methods in abstract class VM_CMS_Operation48//////////////////////////////////////////////////////////49void VM_CMS_Operation::acquire_pending_list_lock() {50// The caller may block while communicating51// with the SLT thread in order to acquire/release the PLL.52SurrogateLockerThread* slt = ConcurrentMarkSweepThread::slt();53if (slt != NULL) {54slt->manipulatePLL(SurrogateLockerThread::acquirePLL);55} else {56SurrogateLockerThread::report_missing_slt();57}58}5960void VM_CMS_Operation::release_and_notify_pending_list_lock() {61// The caller may block while communicating62// with the SLT thread in order to acquire/release the PLL.63ConcurrentMarkSweepThread::slt()->64manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);65}6667void VM_CMS_Operation::verify_before_gc() {68if (VerifyBeforeGC &&69GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {70GCTraceTime tm("Verify Before", false, false, _collector->_gc_timer_cm, _collector->_gc_tracer_cm->gc_id());71HandleMark hm;72FreelistLocker x(_collector);73MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);74Universe::heap()->prepare_for_verify();75Universe::verify();76}77}7879void VM_CMS_Operation::verify_after_gc() {80if (VerifyAfterGC &&81GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {82GCTraceTime tm("Verify After", false, false, _collector->_gc_timer_cm, _collector->_gc_tracer_cm->gc_id());83HandleMark hm;84FreelistLocker x(_collector);85MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);86Universe::verify();87}88}8990bool VM_CMS_Operation::lost_race() const {91if (CMSCollector::abstract_state() == CMSCollector::Idling) {92// We lost a race to a foreground collection93// -- there's nothing to do94return true;95}96assert(CMSCollector::abstract_state() == legal_state(),97"Inconsistent collector state?");98return false;99}100101bool VM_CMS_Operation::doit_prologue() {102assert(Thread::current()->is_ConcurrentGC_thread(), "just checking");103assert(!CMSCollector::foregroundGCShouldWait(), "Possible deadlock");104assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(),105"Possible deadlock");106107if (needs_pll()) {108acquire_pending_list_lock();109}110// Get the Heap_lock after the pending_list_lock.111Heap_lock->lock();112if (lost_race()) {113assert(_prologue_succeeded == false, "Initialized in c'tor");114Heap_lock->unlock();115if (needs_pll()) {116release_and_notify_pending_list_lock();117}118} else {119_prologue_succeeded = true;120}121return _prologue_succeeded;122}123124void VM_CMS_Operation::doit_epilogue() {125assert(Thread::current()->is_ConcurrentGC_thread(), "just checking");126assert(!CMSCollector::foregroundGCShouldWait(), "Possible deadlock");127assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(),128"Possible deadlock");129130// Release the Heap_lock first.131Heap_lock->unlock();132if (needs_pll()) {133release_and_notify_pending_list_lock();134}135}136137//////////////////////////////////////////////////////////138// Methods in class VM_CMS_Initial_Mark139//////////////////////////////////////////////////////////140void VM_CMS_Initial_Mark::doit() {141if (lost_race()) {142// Nothing to do.143return;144}145#ifndef USDT2146HS_DTRACE_PROBE(hs_private, cms__initmark__begin);147#else /* USDT2 */148HS_PRIVATE_CMS_INITMARK_BEGIN(149);150#endif /* USDT2 */151152_collector->_gc_timer_cm->register_gc_pause_start("Initial Mark");153154GenCollectedHeap* gch = GenCollectedHeap::heap();155GCCauseSetter gccs(gch, GCCause::_cms_initial_mark);156157VM_CMS_Operation::verify_before_gc();158159IsGCActiveMark x; // stop-world GC active160_collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial, gch->gc_cause());161162VM_CMS_Operation::verify_after_gc();163164_collector->_gc_timer_cm->register_gc_pause_end();165166#ifndef USDT2167HS_DTRACE_PROBE(hs_private, cms__initmark__end);168#else /* USDT2 */169HS_PRIVATE_CMS_INITMARK_END(170);171#endif /* USDT2 */172}173174//////////////////////////////////////////////////////////175// Methods in class VM_CMS_Final_Remark_Operation176//////////////////////////////////////////////////////////177void VM_CMS_Final_Remark::doit() {178if (lost_race()) {179// Nothing to do.180return;181}182#ifndef USDT2183HS_DTRACE_PROBE(hs_private, cms__remark__begin);184#else /* USDT2 */185HS_PRIVATE_CMS_REMARK_BEGIN(186);187#endif /* USDT2 */188189_collector->_gc_timer_cm->register_gc_pause_start("Final Mark");190191GenCollectedHeap* gch = GenCollectedHeap::heap();192GCCauseSetter gccs(gch, GCCause::_cms_final_remark);193194VM_CMS_Operation::verify_before_gc();195196IsGCActiveMark x; // stop-world GC active197_collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal, gch->gc_cause());198199VM_CMS_Operation::verify_after_gc();200201_collector->save_heap_summary();202_collector->_gc_timer_cm->register_gc_pause_end();203204#ifndef USDT2205HS_DTRACE_PROBE(hs_private, cms__remark__end);206#else /* USDT2 */207HS_PRIVATE_CMS_REMARK_END(208);209#endif /* USDT2 */210}211212// VM operation to invoke a concurrent collection of a213// GenCollectedHeap heap.214void VM_GenCollectFullConcurrent::doit() {215assert(Thread::current()->is_VM_thread(), "Should be VM thread");216assert(GCLockerInvokesConcurrent || ExplicitGCInvokesConcurrent, "Unexpected");217218GenCollectedHeap* gch = GenCollectedHeap::heap();219if (_gc_count_before == gch->total_collections()) {220// The "full" of do_full_collection call below "forces"221// a collection; the second arg, 0, below ensures that222// only the young gen is collected. XXX In the future,223// we'll probably need to have something in this interface224// to say do this only if we are sure we will not bail225// out to a full collection in this attempt, but that's226// for the future.227assert(SafepointSynchronize::is_at_safepoint(),228"We can only be executing this arm of if at a safepoint");229GCCauseSetter gccs(gch, _gc_cause);230gch->do_full_collection(gch->must_clear_all_soft_refs(),2310 /* collect only youngest gen */);232} // Else no need for a foreground young gc233assert((_gc_count_before < gch->total_collections()) ||234(GC_locker::is_active() /* gc may have been skipped */235&& (_gc_count_before == gch->total_collections())),236"total_collections() should be monotonically increasing");237238MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);239assert(_full_gc_count_before <= gch->total_full_collections(), "Error");240if (gch->total_full_collections() == _full_gc_count_before) {241// Disable iCMS until the full collection is done, and242// remember that we did so.243CMSCollector::disable_icms();244_disabled_icms = true;245// In case CMS thread was in icms_wait(), wake it up.246CMSCollector::start_icms();247// Nudge the CMS thread to start a concurrent collection.248CMSCollector::request_full_gc(_full_gc_count_before, _gc_cause);249} else {250assert(_full_gc_count_before < gch->total_full_collections(), "Error");251FullGCCount_lock->notify_all(); // Inform the Java thread its work is done252}253}254255bool VM_GenCollectFullConcurrent::evaluate_at_safepoint() const {256Thread* thr = Thread::current();257assert(thr != NULL, "Unexpected tid");258if (!thr->is_Java_thread()) {259assert(thr->is_VM_thread(), "Expected to be evaluated by VM thread");260GenCollectedHeap* gch = GenCollectedHeap::heap();261if (_gc_count_before != gch->total_collections()) {262// No need to do a young gc, we'll just nudge the CMS thread263// in the doit() method above, to be executed soon.264assert(_gc_count_before < gch->total_collections(),265"total_collections() should be monotnically increasing");266return false; // no need for foreground young gc267}268}269return true; // may still need foreground young gc270}271272273void VM_GenCollectFullConcurrent::doit_epilogue() {274Thread* thr = Thread::current();275assert(thr->is_Java_thread(), "just checking");276JavaThread* jt = (JavaThread*)thr;277// Release the Heap_lock first.278Heap_lock->unlock();279release_and_notify_pending_list_lock();280281// It is fine to test whether completed collections has282// exceeded our request count without locking because283// the completion count is monotonically increasing;284// this will break for very long-running apps when the285// count overflows and wraps around. XXX fix me !!!286// e.g. at the rate of 1 full gc per ms, this could287// overflow in about 1000 years.288GenCollectedHeap* gch = GenCollectedHeap::heap();289if (_gc_cause != GCCause::_gc_locker &&290gch->total_full_collections_completed() <= _full_gc_count_before) {291// maybe we should change the condition to test _gc_cause ==292// GCCause::_java_lang_system_gc, instead of293// _gc_cause != GCCause::_gc_locker294assert(_gc_cause == GCCause::_java_lang_system_gc,295"the only way to get here if this was a System.gc()-induced GC");296assert(ExplicitGCInvokesConcurrent, "Error");297// Now, wait for witnessing concurrent gc cycle to complete,298// but do so in native mode, because we want to lock the299// FullGCEvent_lock, which may be needed by the VM thread300// or by the CMS thread, so we do not want to be suspended301// while holding that lock.302ThreadToNativeFromVM native(jt);303MutexLockerEx ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);304// Either a concurrent or a stop-world full gc is sufficient305// witness to our request.306while (gch->total_full_collections_completed() <= _full_gc_count_before) {307FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);308}309}310// Enable iCMS back if we disabled it earlier.311if (_disabled_icms) {312CMSCollector::enable_icms();313}314}315316317