size_t PSVirtualSpace::expand_into(PSVirtualSpace* other_space, size_t bytes) { assert(is_aligned(bytes), "arg not aligned"); assert(grows_up(), "this space must grow up"); assert(other_space->grows_down(), "other space must grow down"); assert(reserved_high_addr() == other_space->reserved_low_addr(), "spaces not contiguous"); assert(special() == other_space->special(), "one space is special, the other is not"); DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space)); size_t bytes_needed = bytes; // First use the uncommitted region in this space. size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed); if (tmp_bytes > 0) { if (expand_by(tmp_bytes)) { bytes_needed -= tmp_bytes; } else { return 0; } } // Next take from the uncommitted region in the other space, and commit it. tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed); if (tmp_bytes > 0) { char* const commit_base = committed_high_addr(); if (other_space->special() || os::commit_memory(commit_base, tmp_bytes, alignment(), !ExecMem)) { // Reduce the reserved region in the other space. other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes, other_space->reserved_high_addr(), other_space->special()); // Grow both reserved and committed in this space. _reserved_high_addr += tmp_bytes; _committed_high_addr += tmp_bytes; bytes_needed -= tmp_bytes; } else { return bytes - bytes_needed; } } // Finally take from the already committed region in the other space. tmp_bytes = bytes_needed; if (tmp_bytes > 0) { // Reduce both committed and reserved in the other space. other_space->set_committed(other_space->committed_low_addr() + tmp_bytes, other_space->committed_high_addr()); other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes, other_space->reserved_high_addr(), other_space->special()); // Grow both reserved and committed in this space. _reserved_high_addr += tmp_bytes; _committed_high_addr += tmp_bytes; } return bytes; }
bool PSVirtualSpace::expand_by(size_t bytes, bool pre_touch) { assert(is_aligned(bytes), "arg not aligned"); DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); if (uncommitted_size() < bytes) { return false; } char* const base_addr = committed_high_addr(); bool result=os::commit_memory(_account,base_addr,bytes,alignment(),Modules::ParGC_PSVirtualSpace); if (result) { _committed_high_addr += bytes; } if (pre_touch || AlwaysPreTouch) { for (char* curr = base_addr; curr < _committed_high_addr; curr += os::vm_page_size()) { char tmp = *curr; *curr = 0; } } return result; }
void PSVirtualSpace::verify() const { assert(is_aligned(alignment(), os::vm_page_size()), "bad alignment"); assert(is_aligned(reserved_low_addr()), "bad reserved_low_addr"); assert(is_aligned(reserved_high_addr()), "bad reserved_high_addr"); assert(is_aligned(committed_low_addr()), "bad committed_low_addr"); assert(is_aligned(committed_high_addr()), "bad committed_high_addr"); // Reserved region must be non-empty or both addrs must be 0. assert(reserved_low_addr() < reserved_high_addr() || reserved_low_addr() == NULL && reserved_high_addr() == NULL, "bad reserved addrs"); assert(committed_low_addr() <= committed_high_addr(), "bad committed addrs"); if (grows_up()) { assert(reserved_low_addr() == committed_low_addr(), "bad low addrs"); assert(reserved_high_addr() >= committed_high_addr(), "bad high addrs"); } else { assert(reserved_high_addr() == committed_high_addr(), "bad high addrs"); assert(reserved_low_addr() <= committed_low_addr(), "bad low addrs"); } }
bool PSVirtualSpace::shrink_by(size_t bytes) { assert(is_aligned(bytes), "arg not aligned"); DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); if (committed_size() < bytes) { return false; } char* const base_addr = committed_high_addr() - bytes; os::uncommit_memory(base_addr,bytes,Modules::ParGC_PSVirtualSpace); return true; }
void PSVirtualSpace::print() const { gclog_or_tty->print_cr("virtual space [" PTR_FORMAT "]: alignment=" SIZE_FORMAT "K grows %s", this, alignment() / K, grows_up() ? "up" : "down"); gclog_or_tty->print_cr(" reserved=" SIZE_FORMAT "K" " [" PTR_FORMAT "," PTR_FORMAT "]" " committed=" SIZE_FORMAT "K" " [" PTR_FORMAT "," PTR_FORMAT "]", reserved_size() / K, reserved_low_addr(), reserved_high_addr(), committed_size() / K, committed_low_addr(), committed_high_addr()); }
void PSVirtualSpace::print() const { gclog_or_tty->print_cr("virtual space [" PTR_FORMAT "]: alignment=" SIZE_FORMAT "K grows %s%s", p2i(this), alignment() / K, grows_up() ? "up" : "down", special() ? " (pinned in memory)" : ""); gclog_or_tty->print_cr(" reserved=" SIZE_FORMAT "K" " [" PTR_FORMAT "," PTR_FORMAT "]" " committed=" SIZE_FORMAT "K" " [" PTR_FORMAT "," PTR_FORMAT "]", reserved_size() / K, p2i(reserved_low_addr()), p2i(reserved_high_addr()), committed_size() / K, p2i(committed_low_addr()), p2i(committed_high_addr())); }
bool PSVirtualSpace::shrink_by(size_t bytes) { assert(is_aligned(bytes), "arg not aligned"); DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); if (committed_size() < bytes) { return false; } char* const base_addr = committed_high_addr() - bytes; bool result = special() || os::uncommit_memory(base_addr, bytes); if (result) { _committed_high_addr -= bytes; } return result; }
bool PSVirtualSpace::expand_by(size_t bytes) { assert(is_aligned(bytes), "arg not aligned"); DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); if (uncommitted_size() < bytes) { return false; } char* const base_addr = committed_high_addr(); bool result = os::commit_memory(base_addr, bytes, alignment()); if (result) { _committed_high_addr += bytes; } return result; }
bool PSVirtualSpace::contains(void* p) const { char* const cp = (char*)p; return cp >= committed_low_addr() && cp < committed_high_addr(); }
inline size_t PSVirtualSpace::committed_size() const { return pointer_delta(committed_high_addr(), committed_low_addr()); }
char* high() const { return committed_high_addr(); }