Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/memory/genMarkSweep.cpp
32285 views
/*1* Copyright (c) 2001, 2013, 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 "classfile/javaClasses.hpp"26#include "classfile/symbolTable.hpp"27#include "classfile/systemDictionary.hpp"28#include "classfile/vmSymbols.hpp"29#include "code/codeCache.hpp"30#include "code/icBuffer.hpp"31#include "gc_implementation/shared/gcHeapSummary.hpp"32#include "gc_implementation/shared/gcTimer.hpp"33#include "gc_implementation/shared/gcTrace.hpp"34#include "gc_implementation/shared/gcTraceTime.hpp"35#include "gc_interface/collectedHeap.inline.hpp"36#include "memory/genCollectedHeap.hpp"37#include "memory/genMarkSweep.hpp"38#include "memory/genOopClosures.inline.hpp"39#include "memory/generation.inline.hpp"40#include "memory/modRefBarrierSet.hpp"41#include "memory/referencePolicy.hpp"42#include "memory/space.hpp"43#include "oops/instanceRefKlass.hpp"44#include "oops/oop.inline.hpp"45#include "prims/jvmtiExport.hpp"46#include "runtime/fprofiler.hpp"47#include "runtime/handles.inline.hpp"48#include "runtime/synchronizer.hpp"49#include "runtime/thread.inline.hpp"50#include "runtime/vmThread.hpp"51#include "utilities/copy.hpp"52#include "utilities/events.hpp"5354void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp, bool clear_all_softrefs) {55guarantee(level == 1, "We always collect both old and young.");56assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");5758GenCollectedHeap* gch = GenCollectedHeap::heap();59#ifdef ASSERT60if (gch->collector_policy()->should_clear_all_soft_refs()) {61assert(clear_all_softrefs, "Policy should have been checked earlier");62}63#endif6465// hook up weak ref data so it can be used during Mark-Sweep66assert(ref_processor() == NULL, "no stomping");67assert(rp != NULL, "should be non-NULL");68_ref_processor = rp;69rp->setup_policy(clear_all_softrefs);7071GCTraceTime t1(GCCauseString("Full GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL, _gc_tracer->gc_id());7273gch->trace_heap_before_gc(_gc_tracer);7475// When collecting the permanent generation Method*s may be moving,76// so we either have to flush all bcp data or convert it into bci.77CodeCache::gc_prologue();78Threads::gc_prologue();7980// Increment the invocation count81_total_invocations++;8283// Capture heap size before collection for printing.84size_t gch_prev_used = gch->used();8586// Capture used regions for each generation that will be87// subject to collection, so that card table adjustments can88// be made intelligently (see clear / invalidate further below).89gch->save_used_regions(level);9091allocate_stacks();9293mark_sweep_phase1(level, clear_all_softrefs);9495mark_sweep_phase2();9697// Don't add any more derived pointers during phase398COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));99COMPILER2_PRESENT(DerivedPointerTable::set_active(false));100101mark_sweep_phase3(level);102103mark_sweep_phase4();104105restore_marks();106107// Set saved marks for allocation profiler (and other things? -- dld)108// (Should this be in general part?)109gch->save_marks();110111deallocate_stacks();112113// If compaction completely evacuated all generations younger than this114// one, then we can clear the card table. Otherwise, we must invalidate115// it (consider all cards dirty). In the future, we might consider doing116// compaction within generations only, and doing card-table sliding.117bool all_empty = true;118for (int i = 0; all_empty && i < level; i++) {119Generation* g = gch->get_gen(i);120all_empty = all_empty && gch->get_gen(i)->used() == 0;121}122GenRemSet* rs = gch->rem_set();123Generation* old_gen = gch->get_gen(level);124// Clear/invalidate below make use of the "prev_used_regions" saved earlier.125if (all_empty) {126// We've evacuated all generations below us.127rs->clear_into_younger(old_gen);128} else {129// Invalidate the cards corresponding to the currently used130// region and clear those corresponding to the evacuated region.131rs->invalidate_or_clear(old_gen);132}133134Threads::gc_epilogue();135CodeCache::gc_epilogue();136JvmtiExport::gc_epilogue();137138if (PrintGC && !PrintGCDetails) {139gch->print_heap_change(gch_prev_used);140}141142// refs processing: clean slate143_ref_processor = NULL;144145// Update heap occupancy information which is used as146// input to soft ref clearing policy at the next gc.147Universe::update_heap_info_at_gc();148149// Update time of last gc for all generations we collected150// (which curently is all the generations in the heap).151// We need to use a monotonically non-deccreasing time in ms152// or we will see time-warp warnings and os::javaTimeMillis()153// does not guarantee monotonicity.154jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;155gch->update_time_of_last_gc(now);156157gch->trace_heap_after_gc(_gc_tracer);158}159160void GenMarkSweep::allocate_stacks() {161GenCollectedHeap* gch = GenCollectedHeap::heap();162// Scratch request on behalf of oldest generation; will do no163// allocation.164ScratchBlock* scratch = gch->gather_scratch(gch->_gens[gch->_n_gens-1], 0);165166// $$$ To cut a corner, we'll only use the first scratch block, and then167// revert to malloc.168if (scratch != NULL) {169_preserved_count_max =170scratch->num_words * HeapWordSize / sizeof(PreservedMark);171} else {172_preserved_count_max = 0;173}174175_preserved_marks = (PreservedMark*)scratch;176_preserved_count = 0;177}178179180void GenMarkSweep::deallocate_stacks() {181if (!UseG1GC) {182GenCollectedHeap* gch = GenCollectedHeap::heap();183gch->release_scratch();184}185186_preserved_mark_stack.clear(true);187_preserved_oop_stack.clear(true);188_marking_stack.clear();189_objarray_stack.clear(true);190}191192void GenMarkSweep::mark_sweep_phase1(int level,193bool clear_all_softrefs) {194// Recursively traverse all live objects and mark them195GCTraceTime tm("phase 1", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id());196trace(" 1");197198GenCollectedHeap* gch = GenCollectedHeap::heap();199200// Because follow_root_closure is created statically, cannot201// use OopsInGenClosure constructor which takes a generation,202// as the Universe has not been created when the static constructors203// are run.204follow_root_closure.set_orig_generation(gch->get_gen(level));205206// Need new claim bits before marking starts.207ClassLoaderDataGraph::clear_claimed_marks();208209gch->gen_process_roots(level,210false, // Younger gens are not roots.211true, // activate StrongRootsScope212GenCollectedHeap::SO_None,213ClassUnloading,214&follow_root_closure,215&follow_root_closure,216&follow_cld_closure);217218// Process reference objects found during marking219{220ref_processor()->setup_policy(clear_all_softrefs);221const ReferenceProcessorStats& stats =222ref_processor()->process_discovered_references(223&is_alive, &keep_alive, &follow_stack_closure, NULL, _gc_timer, _gc_tracer->gc_id());224gc_tracer()->report_gc_reference_stats(stats);225}226227// This is the point where the entire marking should have completed.228assert(_marking_stack.is_empty(), "Marking should have completed");229230// Unload classes and purge the SystemDictionary.231bool purged_class = SystemDictionary::do_unloading(&is_alive);232233// Unload nmethods.234CodeCache::do_unloading(&is_alive, purged_class);235236// Prune dead klasses from subklass/sibling/implementor lists.237Klass::clean_weak_klass_links(&is_alive);238239// Delete entries for dead interned strings.240StringTable::unlink(&is_alive);241242// Clean up unreferenced symbols in symbol table.243SymbolTable::unlink();244245gc_tracer()->report_object_count_after_gc(&is_alive);246}247248249void GenMarkSweep::mark_sweep_phase2() {250// Now all live objects are marked, compute the new object addresses.251252// It is imperative that we traverse perm_gen LAST. If dead space is253// allowed a range of dead object may get overwritten by a dead int254// array. If perm_gen is not traversed last a Klass* may get255// overwritten. This is fine since it is dead, but if the class has dead256// instances we have to skip them, and in order to find their size we257// need the Klass*!258//259// It is not required that we traverse spaces in the same order in260// phase2, phase3 and phase4, but the ValidateMarkSweep live oops261// tracking expects us to do so. See comment under phase4.262263GenCollectedHeap* gch = GenCollectedHeap::heap();264265GCTraceTime tm("phase 2", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id());266trace("2");267268gch->prepare_for_compaction();269}270271class GenAdjustPointersClosure: public GenCollectedHeap::GenClosure {272public:273void do_generation(Generation* gen) {274gen->adjust_pointers();275}276};277278void GenMarkSweep::mark_sweep_phase3(int level) {279GenCollectedHeap* gch = GenCollectedHeap::heap();280281// Adjust the pointers to reflect the new locations282GCTraceTime tm("phase 3", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id());283trace("3");284285// Need new claim bits for the pointer adjustment tracing.286ClassLoaderDataGraph::clear_claimed_marks();287288// Because the closure below is created statically, we cannot289// use OopsInGenClosure constructor which takes a generation,290// as the Universe has not been created when the static constructors291// are run.292adjust_pointer_closure.set_orig_generation(gch->get_gen(level));293294gch->gen_process_roots(level,295false, // Younger gens are not roots.296true, // activate StrongRootsScope297GenCollectedHeap::SO_AllCodeCache,298GenCollectedHeap::StrongAndWeakRoots,299&adjust_pointer_closure,300&adjust_pointer_closure,301&adjust_cld_closure);302303gch->gen_process_weak_roots(&adjust_pointer_closure);304305adjust_marks();306GenAdjustPointersClosure blk;307gch->generation_iterate(&blk, true);308}309310class GenCompactClosure: public GenCollectedHeap::GenClosure {311public:312void do_generation(Generation* gen) {313gen->compact();314}315};316317void GenMarkSweep::mark_sweep_phase4() {318// All pointers are now adjusted, move objects accordingly319320// It is imperative that we traverse perm_gen first in phase4. All321// classes must be allocated earlier than their instances, and traversing322// perm_gen first makes sure that all Klass*s have moved to their new323// location before any instance does a dispatch through it's klass!324325// The ValidateMarkSweep live oops tracking expects us to traverse spaces326// in the same order in phase2, phase3 and phase4. We don't quite do that327// here (perm_gen first rather than last), so we tell the validate code328// to use a higher index (saved from phase2) when verifying perm_gen.329GenCollectedHeap* gch = GenCollectedHeap::heap();330331GCTraceTime tm("phase 4", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id());332trace("4");333334GenCompactClosure blk;335gch->generation_iterate(&blk, true);336}337338339