Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp
38920 views
/*1* Copyright (c) 2003, 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/parallelScavenge/asPSYoungGen.hpp"26#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"27#include "gc_implementation/parallelScavenge/psMarkSweepDecorator.hpp"28#include "gc_implementation/parallelScavenge/psScavenge.hpp"29#include "gc_implementation/parallelScavenge/psYoungGen.hpp"30#include "gc_implementation/shared/gcUtil.hpp"31#include "gc_implementation/shared/spaceDecorator.hpp"32#include "oops/oop.inline.hpp"33#include "runtime/java.hpp"3435ASPSYoungGen::ASPSYoungGen(size_t init_byte_size,36size_t minimum_byte_size,37size_t byte_size_limit) :38PSYoungGen(init_byte_size, minimum_byte_size, byte_size_limit),39_gen_size_limit(byte_size_limit) {40}414243ASPSYoungGen::ASPSYoungGen(PSVirtualSpace* vs,44size_t init_byte_size,45size_t minimum_byte_size,46size_t byte_size_limit) :47//PSYoungGen(init_byte_size, minimum_byte_size, byte_size_limit),48PSYoungGen(vs->committed_size(), minimum_byte_size, byte_size_limit),49_gen_size_limit(byte_size_limit) {5051assert(vs->committed_size() == init_byte_size, "Cannot replace with");5253_virtual_space = vs;54}5556void ASPSYoungGen::initialize_virtual_space(ReservedSpace rs,57size_t alignment) {58assert(_init_gen_size != 0, "Should have a finite size");59_virtual_space = new PSVirtualSpaceHighToLow(rs, alignment);60if (!_virtual_space->expand_by(_init_gen_size)) {61vm_exit_during_initialization("Could not reserve enough space for "62"object heap");63}64}6566void ASPSYoungGen::initialize(ReservedSpace rs, size_t alignment) {67initialize_virtual_space(rs, alignment);68initialize_work();69}7071size_t ASPSYoungGen::available_for_expansion() {72size_t current_committed_size = virtual_space()->committed_size();73assert((gen_size_limit() >= current_committed_size),74"generation size limit is wrong");75ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();76size_t result = gen_size_limit() - current_committed_size;77size_t result_aligned = align_size_down(result, heap->generation_alignment());78return result_aligned;79}8081// Return the number of bytes the young gen is willing give up.82//83// Future implementations could check the survivors and if to_space is in the84// right place (below from_space), take a chunk from to_space.85size_t ASPSYoungGen::available_for_contraction() {86size_t uncommitted_bytes = virtual_space()->uncommitted_size();87if (uncommitted_bytes != 0) {88return uncommitted_bytes;89}9091if (eden_space()->is_empty()) {92// Respect the minimum size for eden and for the young gen as a whole.93ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();94const size_t eden_alignment = heap->space_alignment();95const size_t gen_alignment = heap->generation_alignment();9697assert(eden_space()->capacity_in_bytes() >= eden_alignment,98"Alignment is wrong");99size_t eden_avail = eden_space()->capacity_in_bytes() - eden_alignment;100eden_avail = align_size_down(eden_avail, gen_alignment);101102assert(virtual_space()->committed_size() >= min_gen_size(),103"minimum gen size is wrong");104size_t gen_avail = virtual_space()->committed_size() - min_gen_size();105assert(virtual_space()->is_aligned(gen_avail), "not aligned");106107const size_t max_contraction = MIN2(eden_avail, gen_avail);108// See comment for ASPSOldGen::available_for_contraction()109// for reasons the "increment" fraction is used.110PSAdaptiveSizePolicy* policy = heap->size_policy();111size_t result = policy->eden_increment_aligned_down(max_contraction);112size_t result_aligned = align_size_down(result, gen_alignment);113if (PrintAdaptiveSizePolicy && Verbose) {114gclog_or_tty->print_cr("ASPSYoungGen::available_for_contraction: " SIZE_FORMAT " K",115result_aligned/K);116gclog_or_tty->print_cr(" max_contraction " SIZE_FORMAT " K", max_contraction/K);117gclog_or_tty->print_cr(" eden_avail " SIZE_FORMAT " K", eden_avail/K);118gclog_or_tty->print_cr(" gen_avail " SIZE_FORMAT " K", gen_avail/K);119}120return result_aligned;121}122123return 0;124}125126// The current implementation only considers to the end of eden.127// If to_space is below from_space, to_space is not considered.128// to_space can be.129size_t ASPSYoungGen::available_to_live() {130ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();131const size_t alignment = heap->space_alignment();132133// Include any space that is committed but is not in eden.134size_t available = pointer_delta(eden_space()->bottom(),135virtual_space()->low(),136sizeof(char));137138const size_t eden_capacity = eden_space()->capacity_in_bytes();139if (eden_space()->is_empty() && eden_capacity > alignment) {140available += eden_capacity - alignment;141}142return available;143}144145// Similar to PSYoungGen::resize_generation() but146// allows sum of eden_size and 2 * survivor_size to exceed _max_gen_size147// expands at the low end of the virtual space148// moves the boundary between the generations in order to expand149// some additional diagnostics150// If no additional changes are required, this can be deleted151// and the changes factored back into PSYoungGen::resize_generation().152bool ASPSYoungGen::resize_generation(size_t eden_size, size_t survivor_size) {153const size_t alignment = virtual_space()->alignment();154size_t orig_size = virtual_space()->committed_size();155bool size_changed = false;156157// There used to be a guarantee here that158// (eden_size + 2*survivor_size) <= _max_gen_size159// This requirement is enforced by the calculation of desired_size160// below. It may not be true on entry since the size of the161// eden_size is no bounded by the generation size.162163assert(max_size() == reserved().byte_size(), "max gen size problem?");164assert(min_gen_size() <= orig_size && orig_size <= max_size(),165"just checking");166167// Adjust new generation size168const size_t eden_plus_survivors =169align_size_up(eden_size + 2 * survivor_size, alignment);170size_t desired_size = MAX2(MIN2(eden_plus_survivors, gen_size_limit()),171min_gen_size());172assert(desired_size <= gen_size_limit(), "just checking");173174if (desired_size > orig_size) {175// Grow the generation176size_t change = desired_size - orig_size;177HeapWord* prev_low = (HeapWord*) virtual_space()->low();178if (!virtual_space()->expand_by(change)) {179return false;180}181if (ZapUnusedHeapArea) {182// Mangle newly committed space immediately because it183// can be done here more simply that after the new184// spaces have been computed.185HeapWord* new_low = (HeapWord*) virtual_space()->low();186assert(new_low < prev_low, "Did not grow");187188MemRegion mangle_region(new_low, prev_low);189SpaceMangler::mangle_region(mangle_region);190}191size_changed = true;192} else if (desired_size < orig_size) {193size_t desired_change = orig_size - desired_size;194195// How much is available for shrinking.196size_t available_bytes = limit_gen_shrink(desired_change);197size_t change = MIN2(desired_change, available_bytes);198virtual_space()->shrink_by(change);199size_changed = true;200} else {201if (Verbose && PrintGC) {202if (orig_size == gen_size_limit()) {203gclog_or_tty->print_cr("ASPSYoung generation size at maximum: "204SIZE_FORMAT "K", orig_size/K);205} else if (orig_size == min_gen_size()) {206gclog_or_tty->print_cr("ASPSYoung generation size at minium: "207SIZE_FORMAT "K", orig_size/K);208}209}210}211212if (size_changed) {213reset_after_change();214if (Verbose && PrintGC) {215size_t current_size = virtual_space()->committed_size();216gclog_or_tty->print_cr("ASPSYoung generation size changed: "217SIZE_FORMAT "K->" SIZE_FORMAT "K",218orig_size/K, current_size/K);219}220}221222guarantee(eden_plus_survivors <= virtual_space()->committed_size() ||223virtual_space()->committed_size() == max_size(), "Sanity");224225return true;226}227228// Similar to PSYoungGen::resize_spaces() but229// eden always starts at the low end of the committed virtual space230// current implementation does not allow holes between the spaces231// _young_generation_boundary has to be reset because it changes.232// so additional verification233234void ASPSYoungGen::resize_spaces(size_t requested_eden_size,235size_t requested_survivor_size) {236assert(UseAdaptiveSizePolicy, "sanity check");237assert(requested_eden_size > 0 && requested_survivor_size > 0,238"just checking");239240space_invariants();241242// We require eden and to space to be empty243if ((!eden_space()->is_empty()) || (!to_space()->is_empty())) {244return;245}246247if (PrintAdaptiveSizePolicy && Verbose) {248gclog_or_tty->print_cr("PSYoungGen::resize_spaces(requested_eden_size: "249SIZE_FORMAT250", requested_survivor_size: " SIZE_FORMAT ")",251requested_eden_size, requested_survivor_size);252gclog_or_tty->print_cr(" eden: [" PTR_FORMAT ".." PTR_FORMAT ") "253SIZE_FORMAT,254p2i(eden_space()->bottom()),255p2i(eden_space()->end()),256pointer_delta(eden_space()->end(),257eden_space()->bottom(),258sizeof(char)));259gclog_or_tty->print_cr(" from: [" PTR_FORMAT ".." PTR_FORMAT ") "260SIZE_FORMAT,261p2i(from_space()->bottom()),262p2i(from_space()->end()),263pointer_delta(from_space()->end(),264from_space()->bottom(),265sizeof(char)));266gclog_or_tty->print_cr(" to: [" PTR_FORMAT ".." PTR_FORMAT ") "267SIZE_FORMAT,268p2i(to_space()->bottom()),269p2i(to_space()->end()),270pointer_delta( to_space()->end(),271to_space()->bottom(),272sizeof(char)));273}274275// There's nothing to do if the new sizes are the same as the current276if (requested_survivor_size == to_space()->capacity_in_bytes() &&277requested_survivor_size == from_space()->capacity_in_bytes() &&278requested_eden_size == eden_space()->capacity_in_bytes()) {279if (PrintAdaptiveSizePolicy && Verbose) {280gclog_or_tty->print_cr(" capacities are the right sizes, returning");281}282return;283}284285char* eden_start = (char*)virtual_space()->low();286char* eden_end = (char*)eden_space()->end();287char* from_start = (char*)from_space()->bottom();288char* from_end = (char*)from_space()->end();289char* to_start = (char*)to_space()->bottom();290char* to_end = (char*)to_space()->end();291292assert(eden_start < from_start, "Cannot push into from_space");293294ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();295const size_t alignment = heap->space_alignment();296const bool maintain_minimum =297(requested_eden_size + 2 * requested_survivor_size) <= min_gen_size();298299bool eden_from_to_order = from_start < to_start;300// Check whether from space is below to space301if (eden_from_to_order) {302// Eden, from, to303304if (PrintAdaptiveSizePolicy && Verbose) {305gclog_or_tty->print_cr(" Eden, from, to:");306}307308// Set eden309// "requested_eden_size" is a goal for the size of eden310// and may not be attainable. "eden_size" below is311// calculated based on the location of from-space and312// the goal for the size of eden. from-space is313// fixed in place because it contains live data.314// The calculation is done this way to avoid 32bit315// overflow (i.e., eden_start + requested_eden_size316// may too large for representation in 32bits).317size_t eden_size;318if (maintain_minimum) {319// Only make eden larger than the requested size if320// the minimum size of the generation has to be maintained.321// This could be done in general but policy at a higher322// level is determining a requested size for eden and that323// should be honored unless there is a fundamental reason.324eden_size = pointer_delta(from_start,325eden_start,326sizeof(char));327} else {328eden_size = MIN2(requested_eden_size,329pointer_delta(from_start, eden_start, sizeof(char)));330}331332eden_end = eden_start + eden_size;333assert(eden_end >= eden_start, "addition overflowed");334335// To may resize into from space as long as it is clear of live data.336// From space must remain page aligned, though, so we need to do some337// extra calculations.338339// First calculate an optimal to-space340to_end = (char*)virtual_space()->high();341to_start = (char*)pointer_delta(to_end,342(char*)requested_survivor_size,343sizeof(char));344345// Does the optimal to-space overlap from-space?346if (to_start < (char*)from_space()->end()) {347assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");348349// Calculate the minimum offset possible for from_end350size_t from_size =351pointer_delta(from_space()->top(), from_start, sizeof(char));352353// Should we be in this method if from_space is empty? Why not the set_space method? FIX ME!354if (from_size == 0) {355from_size = alignment;356} else {357from_size = align_size_up(from_size, alignment);358}359360from_end = from_start + from_size;361assert(from_end > from_start, "addition overflow or from_size problem");362363guarantee(from_end <= (char*)from_space()->end(),364"from_end moved to the right");365366// Now update to_start with the new from_end367to_start = MAX2(from_end, to_start);368}369370guarantee(to_start != to_end, "to space is zero sized");371372if (PrintAdaptiveSizePolicy && Verbose) {373gclog_or_tty->print_cr(" [eden_start .. eden_end): "374"[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT,375p2i(eden_start),376p2i(eden_end),377pointer_delta(eden_end, eden_start, sizeof(char)));378gclog_or_tty->print_cr(" [from_start .. from_end): "379"[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT,380p2i(from_start),381p2i(from_end),382pointer_delta(from_end, from_start, sizeof(char)));383gclog_or_tty->print_cr(" [ to_start .. to_end): "384"[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT,385p2i(to_start),386p2i(to_end),387pointer_delta( to_end, to_start, sizeof(char)));388}389} else {390// Eden, to, from391if (PrintAdaptiveSizePolicy && Verbose) {392gclog_or_tty->print_cr(" Eden, to, from:");393}394395// To space gets priority over eden resizing. Note that we position396// to space as if we were able to resize from space, even though from397// space is not modified.398// Giving eden priority was tried and gave poorer performance.399to_end = (char*)pointer_delta(virtual_space()->high(),400(char*)requested_survivor_size,401sizeof(char));402to_end = MIN2(to_end, from_start);403to_start = (char*)pointer_delta(to_end, (char*)requested_survivor_size,404sizeof(char));405// if the space sizes are to be increased by several times then406// 'to_start' will point beyond the young generation. In this case407// 'to_start' should be adjusted.408to_start = MAX2(to_start, eden_start + alignment);409410// Compute how big eden can be, then adjust end.411// See comments above on calculating eden_end.412size_t eden_size;413if (maintain_minimum) {414eden_size = pointer_delta(to_start, eden_start, sizeof(char));415} else {416eden_size = MIN2(requested_eden_size,417pointer_delta(to_start, eden_start, sizeof(char)));418}419eden_end = eden_start + eden_size;420assert(eden_end >= eden_start, "addition overflowed");421422// Don't let eden shrink down to 0 or less.423eden_end = MAX2(eden_end, eden_start + alignment);424to_start = MAX2(to_start, eden_end);425426if (PrintAdaptiveSizePolicy && Verbose) {427gclog_or_tty->print_cr(" [eden_start .. eden_end): "428"[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT,429p2i(eden_start),430p2i(eden_end),431pointer_delta(eden_end, eden_start, sizeof(char)));432gclog_or_tty->print_cr(" [ to_start .. to_end): "433"[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT,434p2i(to_start),435p2i(to_end),436pointer_delta( to_end, to_start, sizeof(char)));437gclog_or_tty->print_cr(" [from_start .. from_end): "438"[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT,439p2i(from_start),440p2i(from_end),441pointer_delta(from_end, from_start, sizeof(char)));442}443}444445446guarantee((HeapWord*)from_start <= from_space()->bottom(),447"from start moved to the right");448guarantee((HeapWord*)from_end >= from_space()->top(),449"from end moved into live data");450assert(is_object_aligned((intptr_t)eden_start), "checking alignment");451assert(is_object_aligned((intptr_t)from_start), "checking alignment");452assert(is_object_aligned((intptr_t)to_start), "checking alignment");453454MemRegion edenMR((HeapWord*)eden_start, (HeapWord*)eden_end);455MemRegion toMR ((HeapWord*)to_start, (HeapWord*)to_end);456MemRegion fromMR((HeapWord*)from_start, (HeapWord*)from_end);457458// Let's make sure the call to initialize doesn't reset "top"!459DEBUG_ONLY(HeapWord* old_from_top = from_space()->top();)460461// For PrintAdaptiveSizePolicy block below462size_t old_from = from_space()->capacity_in_bytes();463size_t old_to = to_space()->capacity_in_bytes();464465if (ZapUnusedHeapArea) {466// NUMA is a special case because a numa space is not mangled467// in order to not prematurely bind its address to memory to468// the wrong memory (i.e., don't want the GC thread to first469// touch the memory). The survivor spaces are not numa470// spaces and are mangled.471if (UseNUMA) {472if (eden_from_to_order) {473mangle_survivors(from_space(), fromMR, to_space(), toMR);474} else {475mangle_survivors(to_space(), toMR, from_space(), fromMR);476}477}478479// If not mangling the spaces, do some checking to verify that480// the spaces are already mangled.481// The spaces should be correctly mangled at this point so482// do some checking here. Note that they are not being mangled483// in the calls to initialize().484// Must check mangling before the spaces are reshaped. Otherwise,485// the bottom or end of one space may have moved into an area486// covered by another space and a failure of the check may487// not correctly indicate which space is not properly mangled.488489HeapWord* limit = (HeapWord*) virtual_space()->high();490eden_space()->check_mangled_unused_area(limit);491from_space()->check_mangled_unused_area(limit);492to_space()->check_mangled_unused_area(limit);493}494// When an existing space is being initialized, it is not495// mangled because the space has been previously mangled.496eden_space()->initialize(edenMR,497SpaceDecorator::Clear,498SpaceDecorator::DontMangle);499to_space()->initialize(toMR,500SpaceDecorator::Clear,501SpaceDecorator::DontMangle);502from_space()->initialize(fromMR,503SpaceDecorator::DontClear,504SpaceDecorator::DontMangle);505506PSScavenge::set_young_generation_boundary(eden_space()->bottom());507508assert(from_space()->top() == old_from_top, "from top changed!");509510if (PrintAdaptiveSizePolicy) {511ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();512assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");513514gclog_or_tty->print("AdaptiveSizePolicy::survivor space sizes: "515"collection: %d "516"(" SIZE_FORMAT ", " SIZE_FORMAT ") -> "517"(" SIZE_FORMAT ", " SIZE_FORMAT ") ",518heap->total_collections(),519old_from, old_to,520from_space()->capacity_in_bytes(),521to_space()->capacity_in_bytes());522gclog_or_tty->cr();523}524space_invariants();525}526void ASPSYoungGen::reset_after_change() {527assert_locked_or_safepoint(Heap_lock);528529_reserved = MemRegion((HeapWord*)virtual_space()->low_boundary(),530(HeapWord*)virtual_space()->high_boundary());531PSScavenge::reference_processor()->set_span(_reserved);532533HeapWord* new_eden_bottom = (HeapWord*)virtual_space()->low();534HeapWord* eden_bottom = eden_space()->bottom();535if (new_eden_bottom != eden_bottom) {536MemRegion eden_mr(new_eden_bottom, eden_space()->end());537eden_space()->initialize(eden_mr,538SpaceDecorator::Clear,539SpaceDecorator::Mangle);540PSScavenge::set_young_generation_boundary(eden_space()->bottom());541}542MemRegion cmr((HeapWord*)virtual_space()->low(),543(HeapWord*)virtual_space()->high());544Universe::heap()->barrier_set()->resize_covered_region(cmr);545546space_invariants();547}548549550