1 /* 2 * Copyright (c) 2015, 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 #include "precompiled.hpp" 25 #include "gc/z/zPhysicalMemory.inline.hpp" 26 #include "logging/log.hpp" 27 #include "memory/allocation.inline.hpp" 28 #include "services/memTracker.hpp" 29 #include "utilities/debug.hpp" 30 #include "utilities/globalDefinitions.hpp" 31 32 ZPhysicalMemory::ZPhysicalMemory() : 33 _nsegments(0), 34 _segments(NULL) {} 35 36 ZPhysicalMemory::ZPhysicalMemory(const ZPhysicalMemorySegment& segment) : 37 _nsegments(0), 38 _segments(NULL) { 39 add_segment(segment); 40 } 41 42 ZPhysicalMemory::ZPhysicalMemory(const ZPhysicalMemory& pmem) : 43 _nsegments(0), 44 _segments(NULL) { 45 46 // Copy segments 47 for (size_t i = 0; i < pmem.nsegments(); i++) { 48 add_segment(pmem.segment(i)); 49 } 50 } 51 52 const ZPhysicalMemory& ZPhysicalMemory::operator=(const ZPhysicalMemory& pmem) { 53 // Free segments 54 delete [] _segments; 55 _segments = NULL; 56 _nsegments = 0; 57 58 // Copy segments 59 for (size_t i = 0; i < pmem.nsegments(); i++) { 60 add_segment(pmem.segment(i)); 61 } 62 63 return *this; 64 } 65 66 ZPhysicalMemory::~ZPhysicalMemory() { 67 delete [] _segments; 68 _segments = NULL; 69 _nsegments = 0; 70 } 71 72 size_t ZPhysicalMemory::size() const { 73 size_t size = 0; 74 75 for (size_t i = 0; i < _nsegments; i++) { 76 size += _segments[i].size(); 77 } 78 79 return size; 80 } 81 82 void ZPhysicalMemory::add_segment(const ZPhysicalMemorySegment& segment) { 83 // Try merge with last segment 84 if (_nsegments > 0) { 85 ZPhysicalMemorySegment& last = _segments[_nsegments - 1]; 86 assert(last.end() <= segment.start(), "Segments added out of order"); 87 if (last.end() == segment.start()) { 88 last = ZPhysicalMemorySegment(last.start(), last.size() + segment.size()); 89 return; 90 } 91 } 92 93 // Resize array 94 ZPhysicalMemorySegment* const old_segments = _segments; 95 _segments = new ZPhysicalMemorySegment[_nsegments + 1]; 96 for (size_t i = 0; i < _nsegments; i++) { 97 _segments[i] = old_segments[i]; 98 } 99 delete [] old_segments; 100 101 // Add new segment 102 _segments[_nsegments] = segment; 103 _nsegments++; 104 } 105 106 ZPhysicalMemory ZPhysicalMemory::split(size_t size) { 107 ZPhysicalMemory pmem; 108 size_t nsegments = 0; 109 110 for (size_t i = 0; i < _nsegments; i++) { 111 const ZPhysicalMemorySegment& segment = _segments[i]; 112 if (pmem.size() < size) { 113 if (pmem.size() + segment.size() <= size) { 114 // Transfer segment 115 pmem.add_segment(segment); 116 } else { 117 // Split segment 118 const size_t split_size = size - pmem.size(); 119 pmem.add_segment(ZPhysicalMemorySegment(segment.start(), split_size)); 120 _segments[nsegments++] = ZPhysicalMemorySegment(segment.start() + split_size, segment.size() - split_size); 121 } 122 } else { 123 // Keep segment 124 _segments[nsegments++] = segment; 125 } 126 } 127 128 _nsegments = nsegments; 129 130 return pmem; 131 } 132 133 bool ZPhysicalMemoryManager::is_initialized() const { 134 return _backing.is_initialized(); 135 } 136 137 void ZPhysicalMemoryManager::warn_commit_limits(size_t max) const { 138 _backing.warn_commit_limits(max); 139 } 140 141 bool ZPhysicalMemoryManager::supports_uncommit() { 142 return _backing.supports_uncommit(); 143 } 144 145 void ZPhysicalMemoryManager::nmt_commit(const ZPhysicalMemory& pmem, uintptr_t offset) const { 146 const uintptr_t addr = _backing.nmt_address(offset); 147 const size_t size = pmem.size(); 148 MemTracker::record_virtual_memory_commit((void*)addr, size, CALLER_PC); 149 } 150 151 void ZPhysicalMemoryManager::nmt_uncommit(const ZPhysicalMemory& pmem, uintptr_t offset) const { 152 if (MemTracker::tracking_level() > NMT_minimal) { 153 const uintptr_t addr = _backing.nmt_address(offset); 154 const size_t size = pmem.size(); 155 Tracker tracker(Tracker::uncommit); 156 tracker.record((address)addr, size); 157 } 158 } 159 160 size_t ZPhysicalMemoryManager::commit(size_t size) { 161 return _backing.commit(size); 162 } 163 164 size_t ZPhysicalMemoryManager::uncommit(size_t size) { 165 return _backing.uncommit(size); 166 } 167 168 ZPhysicalMemory ZPhysicalMemoryManager::alloc(size_t size) { 169 return _backing.alloc(size); 170 } 171 172 void ZPhysicalMemoryManager::free(const ZPhysicalMemory& pmem) { 173 _backing.free(pmem); 174 } 175 176 void ZPhysicalMemoryManager::pretouch(uintptr_t offset, size_t size) const { 177 _backing.pretouch(offset, size); 178 } 179 180 void ZPhysicalMemoryManager::map(const ZPhysicalMemory& pmem, uintptr_t offset) const { 181 _backing.map(pmem, offset); 182 nmt_commit(pmem, offset); 183 } 184 185 void ZPhysicalMemoryManager::unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const { 186 nmt_uncommit(pmem, offset); 187 _backing.unmap(pmem, offset); 188 } 189 190 void ZPhysicalMemoryManager::debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const { 191 _backing.debug_map(pmem, offset); 192 } 193 194 void ZPhysicalMemoryManager::debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const { 195 _backing.debug_unmap(pmem, offset); 196 }