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
32ZPhysicalMemory::ZPhysicalMemory() :
33 _nsegments(0),
34 _segments(NULL) {}
35
36ZPhysicalMemory::ZPhysicalMemory(const ZPhysicalMemorySegment& segment) :
37 _nsegments(0),
38 _segments(NULL) {
39 add_segment(segment);
40}
41
42ZPhysicalMemory::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
52const 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
66ZPhysicalMemory::~ZPhysicalMemory() {
67 delete [] _segments;
68 _segments = NULL;
69 _nsegments = 0;
70}
71
72size_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
82void 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
106ZPhysicalMemory 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
133bool ZPhysicalMemoryManager::is_initialized() const {
134 return _backing.is_initialized();
135}
136
137void ZPhysicalMemoryManager::warn_commit_limits(size_t max) const {
138 _backing.warn_commit_limits(max);
139}
140
141bool ZPhysicalMemoryManager::supports_uncommit() {
142 return _backing.supports_uncommit();
143}
144
145void 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
151void 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
160size_t ZPhysicalMemoryManager::commit(size_t size) {
161 return _backing.commit(size);
162}
163
164size_t ZPhysicalMemoryManager::uncommit(size_t size) {
165 return _backing.uncommit(size);
166}
167
168ZPhysicalMemory ZPhysicalMemoryManager::alloc(size_t size) {
169 return _backing.alloc(size);
170}
171
172void ZPhysicalMemoryManager::free(const ZPhysicalMemory& pmem) {
173 _backing.free(pmem);
174}
175
176void ZPhysicalMemoryManager::map(const ZPhysicalMemory& pmem, uintptr_t offset) const {
177 _backing.map(pmem, offset);
178 nmt_commit(pmem, offset);
179}
180
181void ZPhysicalMemoryManager::unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
182 nmt_uncommit(pmem, offset);
183 _backing.unmap(pmem, offset);
184}
185
186void ZPhysicalMemoryManager::debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const {
187 _backing.debug_map(pmem, offset);
188}
189
190void ZPhysicalMemoryManager::debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
191 _backing.debug_unmap(pmem, offset);
192}
193