// See comments on request_old_gen_expansion() bool AdjoiningGenerations::request_young_gen_expansion(size_t expand_in_bytes) { assert(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary, "runtime check"); // If eden is not empty, the boundary can be moved but no advantage // can be made of the move since eden cannot be moved. if (!young_gen()->eden_space()->is_empty()) { return false; } bool result = false; const size_t young_gen_available = young_gen()->available_for_expansion(); const size_t old_gen_available = old_gen()->available_for_contraction(); const size_t alignment = virtual_spaces()->alignment(); size_t change_in_bytes = MIN3(young_gen_available, old_gen_available, align_size_up_(expand_in_bytes, alignment)); if (change_in_bytes == 0) { return false; } if (TraceAdaptiveGCBoundary) { gclog_or_tty->print_cr("Before expansion of young gen with boundary move"); gclog_or_tty->print_cr(" Requested change: 0x%zx Attempted change: 0x%zx", expand_in_bytes, change_in_bytes); if (!PrintHeapAtGC) { Universe::print_on(gclog_or_tty); } gclog_or_tty->print_cr(" PSYoungGen max size: " SIZE_FORMAT "K", young_gen()->max_size()/K); } // Move the boundary between the generations down (smaller old gen). MutexLocker x(ExpandHeap_lock); if (virtual_spaces()->adjust_boundary_down(change_in_bytes)) { young_gen()->reset_after_change(); old_gen()->reset_after_change(); result = true; } // The total reserved for the generations should match the sum // of the two even if the boundary is moving. assert(reserved_byte_size() == old_gen()->max_gen_size() + young_gen()->max_size(), "Space is missing"); young_gen()->space_invariants(); old_gen()->space_invariants(); if (TraceAdaptiveGCBoundary) { gclog_or_tty->print_cr("After expansion of young gen with boundary move"); if (!PrintHeapAtGC) { Universe::print_on(gclog_or_tty); } gclog_or_tty->print_cr(" PSYoungGen max size: " SIZE_FORMAT "K", young_gen()->max_size()/K); } return result; }
// Make checks on the current sizes of the generations and // the constraints on the sizes of the generations. Push // up the boundary within the constraints. A partial // push can occur. void AdjoiningGenerations::request_old_gen_expansion(size_t expand_in_bytes) { assert(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary, "runtime check"); assert_lock_strong(ExpandHeap_lock); assert_locked_or_safepoint(Heap_lock); // These sizes limit the amount the boundaries can move. Effectively, // the generation says how much it is willing to yield to the other // generation. const size_t young_gen_available = young_gen()->available_for_contraction(); const size_t old_gen_available = old_gen()->available_for_expansion(); const size_t alignment = virtual_spaces()->alignment(); size_t change_in_bytes = MIN3(young_gen_available, old_gen_available, align_size_up_(expand_in_bytes, alignment)); if (change_in_bytes == 0) { return; } if (TraceAdaptiveGCBoundary) { gclog_or_tty->print_cr("Before expansion of old gen with boundary move"); gclog_or_tty->print_cr(" Requested change: " SIZE_FORMAT_HEX " Attempted change: " SIZE_FORMAT_HEX, expand_in_bytes, change_in_bytes); if (!PrintHeapAtGC) { Universe::print_on(gclog_or_tty); } gclog_or_tty->print_cr(" PSOldGen max size: " SIZE_FORMAT "K", old_gen()->max_gen_size()/K); } // Move the boundary between the generations up (smaller young gen). if (virtual_spaces()->adjust_boundary_up(change_in_bytes)) { young_gen()->reset_after_change(); old_gen()->reset_after_change(); } // The total reserved for the generations should match the sum // of the two even if the boundary is moving. assert(reserved_byte_size() == old_gen()->max_gen_size() + young_gen()->max_size(), "Space is missing"); young_gen()->space_invariants(); old_gen()->space_invariants(); if (TraceAdaptiveGCBoundary) { gclog_or_tty->print_cr("After expansion of old gen with boundary move"); if (!PrintHeapAtGC) { Universe::print_on(gclog_or_tty); } gclog_or_tty->print_cr(" PSOldGen max size: " SIZE_FORMAT "K", old_gen()->max_gen_size()/K); } }