1 /* 2 * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "gc/parallel/psVirtualspace.hpp" 27 #include "memory/virtualspace.hpp" 28 #include "runtime/os.hpp" 29 30 // PSVirtualSpace 31 32 PSVirtualSpace::PSVirtualSpace(ReservedSpace rs, size_t alignment) : 33 _alignment(alignment) 34 { 35 set_reserved(rs); 36 set_committed(reserved_low_addr(), reserved_low_addr()); 37 DEBUG_ONLY(verify()); 38 } 39 40 PSVirtualSpace::PSVirtualSpace(ReservedSpace rs) : 41 _alignment(os::vm_page_size()) 42 { 43 set_reserved(rs); 44 set_committed(reserved_low_addr(), reserved_low_addr()); 45 DEBUG_ONLY(verify()); 46 } 47 48 // Deprecated. 49 PSVirtualSpace::PSVirtualSpace(): 50 _alignment(os::vm_page_size()), 51 _reserved_low_addr(NULL), 52 _reserved_high_addr(NULL), 53 _committed_low_addr(NULL), 54 _committed_high_addr(NULL), 55 _special(false) { 56 } 57 58 // Deprecated. 59 bool PSVirtualSpace::initialize(ReservedSpace rs, 60 size_t commit_size) { 61 set_reserved(rs); 62 set_committed(reserved_low_addr(), reserved_low_addr()); 63 64 // Commit to initial size. 65 assert(commit_size <= rs.size(), "commit_size too big"); 66 bool result = commit_size > 0 ? expand_by(commit_size) : true; 67 DEBUG_ONLY(verify()); 68 return result; 69 } 70 71 PSVirtualSpace::~PSVirtualSpace() { 72 release(); 73 } 74 75 bool PSVirtualSpace::contains(void* p) const { 76 char* const cp = (char*)p; 77 return cp >= committed_low_addr() && cp < committed_high_addr(); 78 } 79 80 void PSVirtualSpace::release() { 81 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); 82 // This may not release memory it didn't reserve. 83 // Use rs.release() to release the underlying memory instead. 84 _reserved_low_addr = _reserved_high_addr = NULL; 85 _committed_low_addr = _committed_high_addr = NULL; 86 _special = false; 87 } 88 89 bool PSVirtualSpace::expand_by(size_t bytes) { 90 assert(is_aligned(bytes), "arg not aligned"); 91 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); 92 93 if (uncommitted_size() < bytes) { 94 return false; 95 } 96 97 char* const base_addr = committed_high_addr(); 98 bool result = special() || 99 os::commit_memory(base_addr, bytes, alignment(), !ExecMem); 100 if (result) { 101 _committed_high_addr += bytes; 102 } 103 104 return result; 105 } 106 107 bool PSVirtualSpace::shrink_by(size_t bytes) { 108 assert(is_aligned(bytes), "arg not aligned"); 109 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); 110 111 if (committed_size() < bytes) { 112 return false; 113 } 114 115 char* const base_addr = committed_high_addr() - bytes; 116 bool result = special() || os::uncommit_memory(base_addr, bytes, !ExecMem); 117 if (result) { 118 _committed_high_addr -= bytes; 119 } 120 121 return result; 122 } 123 124 size_t 125 PSVirtualSpace::expand_into(PSVirtualSpace* other_space, size_t bytes) { 126 assert(is_aligned(bytes), "arg not aligned"); 127 assert(grows_up(), "this space must grow up"); 128 assert(other_space->grows_down(), "other space must grow down"); 129 assert(reserved_high_addr() == other_space->reserved_low_addr(), 130 "spaces not contiguous"); 131 assert(special() == other_space->special(), "one space is special, the other is not"); 132 DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); 133 DEBUG_ONLY(PSVirtualSpaceVerifier other_verifier(other_space)); 134 135 size_t bytes_needed = bytes; 136 137 // First use the uncommitted region in this space. 138 size_t tmp_bytes = MIN2(uncommitted_size(), bytes_needed); 139 if (tmp_bytes > 0) { 140 if (expand_by(tmp_bytes)) { 141 bytes_needed -= tmp_bytes; 142 } else { 143 return 0; 144 } 145 } 146 147 // Next take from the uncommitted region in the other space, and commit it. 148 tmp_bytes = MIN2(other_space->uncommitted_size(), bytes_needed); 149 if (tmp_bytes > 0) { 150 char* const commit_base = committed_high_addr(); 151 if (other_space->special() || 152 os::commit_memory(commit_base, tmp_bytes, alignment(), !ExecMem)) { 153 // Reduce the reserved region in the other space. 154 other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes, 155 other_space->reserved_high_addr(), 156 other_space->special()); 157 158 // Grow both reserved and committed in this space. 159 _reserved_high_addr += tmp_bytes; 160 _committed_high_addr += tmp_bytes; 161 bytes_needed -= tmp_bytes; 162 } else { 163 return bytes - bytes_needed; 164 } 165 } 166 167 // Finally take from the already committed region in the other space. 168 tmp_bytes = bytes_needed; 169 if (tmp_bytes > 0) { 170 // Reduce both committed and reserved in the other space. 171 other_space->set_committed(other_space->committed_low_addr() + tmp_bytes, 172 other_space->committed_high_addr()); 173 other_space->set_reserved(other_space->reserved_low_addr() + tmp_bytes, 174 other_space->reserved_high_addr(), 175 other_space->special()); 176 177 // Grow both reserved and committed in this space. 178 _reserved_high_addr += tmp_bytes; 179 _committed_high_addr += tmp_bytes; 180 } 181 182 return bytes; 183 } 184 185 #ifndef PRODUCT 186 bool PSVirtualSpace::is_aligned(size_t value, size_t align) { 187 const size_t tmp_value = value + align - 1; 188 const size_t mask = ~(align - 1); 189 return (tmp_value & mask) == value; 190 } 191 192 bool PSVirtualSpace::is_aligned(size_t value) const { 193 return is_aligned(value, alignment()); 194 } 195 196 bool PSVirtualSpace::is_aligned(char* value) const { 197 return is_aligned((size_t)value); 198 } 199 200 void PSVirtualSpace::verify() const { 201 assert(is_aligned(alignment(), os::vm_page_size()), "bad alignment"); 202 assert(is_aligned(reserved_low_addr()), "bad reserved_low_addr"); 203 assert(is_aligned(reserved_high_addr()), "bad reserved_high_addr"); 204 assert(is_aligned(committed_low_addr()), "bad committed_low_addr"); 205 assert(is_aligned(committed_high_addr()), "bad committed_high_addr"); 206 207 // Reserved region must be non-empty or both addrs must be 0. 208 assert(reserved_low_addr() < reserved_high_addr() || 209 reserved_low_addr() == NULL && reserved_high_addr() == NULL, 210 "bad reserved addrs"); 211 assert(committed_low_addr() <= committed_high_addr(), "bad committed addrs"); 212 213 if (grows_up()) { 214 assert(reserved_low_addr() == committed_low_addr(), "bad low addrs"); 215 assert(reserved_high_addr() >= committed_high_addr(), "bad high addrs"); 216 } else { 217 assert(reserved_high_addr() == committed_high_addr(), "bad high addrs"); 218 assert(reserved_low_addr() <= committed_low_addr(), "bad low addrs"); 219 } 220 } 221 222 #endif // #ifndef PRODUCT 223 224 void PSVirtualSpace::print_space_boundaries_on(outputStream* st) const { 225 st->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ")", 226 p2i(low_boundary()), p2i(high()), p2i(high_boundary())); 227 }