Tue, 09 Oct 2012 10:09:34 -0700
7197424: update copyright year to match last edit in jdk8 hotspot repository
Summary: Update copyright year to 2012 for relevant files
Reviewed-by: dholmes, coleenp
1 /*
2 * Copyright (c) 2012, 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 */
25 #ifndef SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP
26 #define SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP
28 #include "memory/allocation.hpp"
29 #include "runtime/mutex.hpp"
30 #include "runtime/mutexLocker.hpp"
31 #include "services/memBaseline.hpp"
32 #include "services/memPtrArray.hpp"
35 // Snapshot pointer array iterator
37 // The pointer array contains malloc-ed pointers
38 class MemPointerIterator : public MemPointerArrayIteratorImpl {
39 public:
40 MemPointerIterator(MemPointerArray* arr):
41 MemPointerArrayIteratorImpl(arr) {
42 assert(arr != NULL, "null array");
43 }
45 #ifdef ASSERT
46 virtual bool is_dup_pointer(const MemPointer* ptr1,
47 const MemPointer* ptr2) const {
48 MemPointerRecord* p1 = (MemPointerRecord*)ptr1;
49 MemPointerRecord* p2 = (MemPointerRecord*)ptr2;
51 if (p1->addr() != p2->addr()) return false;
52 if ((p1->flags() & MemPointerRecord::tag_masks) !=
53 (p2->flags() & MemPointerRecord::tag_masks)) {
54 return false;
55 }
56 // we do see multiple commit/uncommit on the same memory, it is ok
57 return (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_alloc ||
58 (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release;
59 }
61 virtual bool insert(MemPointer* ptr) {
62 if (_pos > 0) {
63 MemPointer* p1 = (MemPointer*)ptr;
64 MemPointer* p2 = (MemPointer*)_array->at(_pos - 1);
65 assert(!is_dup_pointer(p1, p2),
66 err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags()));
67 }
68 if (_pos < _array->length() -1) {
69 MemPointer* p1 = (MemPointer*)ptr;
70 MemPointer* p2 = (MemPointer*)_array->at(_pos + 1);
71 assert(!is_dup_pointer(p1, p2),
72 err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags()));
73 }
74 return _array->insert_at(ptr, _pos);
75 }
77 virtual bool insert_after(MemPointer* ptr) {
78 if (_pos > 0) {
79 MemPointer* p1 = (MemPointer*)ptr;
80 MemPointer* p2 = (MemPointer*)_array->at(_pos - 1);
81 assert(!is_dup_pointer(p1, p2),
82 err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags()));
83 }
84 if (_pos < _array->length() - 1) {
85 MemPointer* p1 = (MemPointer*)ptr;
86 MemPointer* p2 = (MemPointer*)_array->at(_pos + 1);
88 assert(!is_dup_pointer(p1, p2),
89 err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags()));
90 }
91 if (_array->insert_at(ptr, _pos + 1)) {
92 _pos ++;
93 return true;
94 }
95 return false;
96 }
97 #endif
99 virtual MemPointer* locate(address addr) {
100 MemPointer* cur = current();
101 while (cur != NULL && cur->addr() < addr) {
102 cur = next();
103 }
104 return cur;
105 }
106 };
108 class VMMemPointerIterator : public MemPointerIterator {
109 public:
110 VMMemPointerIterator(MemPointerArray* arr):
111 MemPointerIterator(arr) {
112 }
114 // locate an existing record that contains specified address, or
115 // the record, where the record with specified address, should
116 // be inserted.
117 // virtual memory record array is sorted in address order, so
118 // binary search is performed
119 virtual MemPointer* locate(address addr) {
120 int index_low = 0;
121 int index_high = _array->length();
122 int index_mid = (index_high + index_low) / 2;
123 int r = 1;
124 while (index_low < index_high && (r = compare(index_mid, addr)) != 0) {
125 if (r > 0) {
126 index_high = index_mid;
127 } else {
128 index_low = index_mid;
129 }
130 index_mid = (index_high + index_low) / 2;
131 }
132 if (r == 0) {
133 // update current location
134 _pos = index_mid;
135 return _array->at(index_mid);
136 } else {
137 return NULL;
138 }
139 }
141 #ifdef ASSERT
142 virtual bool is_dup_pointer(const MemPointer* ptr1,
143 const MemPointer* ptr2) const {
144 VMMemRegion* p1 = (VMMemRegion*)ptr1;
145 VMMemRegion* p2 = (VMMemRegion*)ptr2;
147 if (p1->addr() != p2->addr()) return false;
148 if ((p1->flags() & MemPointerRecord::tag_masks) !=
149 (p2->flags() & MemPointerRecord::tag_masks)) {
150 return false;
151 }
152 // we do see multiple commit/uncommit on the same memory, it is ok
153 return (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_alloc ||
154 (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release;
155 }
156 #endif
157 // compare if an address falls into a memory region,
158 // return 0, if the address falls into a memory region at specified index
159 // return 1, if memory region pointed by specified index is higher than the address
160 // return -1, if memory region pointed by specified index is lower than the address
161 int compare(int index, address addr) const {
162 VMMemRegion* r = (VMMemRegion*)_array->at(index);
163 assert(r->is_reserve_record(), "Sanity check");
164 if (r->addr() > addr) {
165 return 1;
166 } else if (r->addr() + r->reserved_size() <= addr) {
167 return -1;
168 } else {
169 return 0;
170 }
171 }
172 };
174 class MallocRecordIterator : public MemPointerArrayIterator {
175 private:
176 MemPointerArrayIteratorImpl _itr;
178 public:
179 MallocRecordIterator(MemPointerArray* arr) : _itr(arr) {
180 }
182 MemPointer* current() const {
183 MemPointerRecord* cur = (MemPointerRecord*)_itr.current();
184 assert(cur == NULL || !cur->is_vm_pointer(), "seek error");
185 MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next();
186 if (next == NULL || next->addr() != cur->addr()) {
187 return cur;
188 } else {
189 assert(!cur->is_vm_pointer(), "Sanity check");
190 assert(cur->is_allocation_record() && next->is_deallocation_record(),
191 "sorting order");
192 assert(cur->seq() != next->seq(), "Sanity check");
193 return cur->seq() > next->seq() ? cur : next;
194 }
195 }
197 MemPointer* next() {
198 MemPointerRecord* cur = (MemPointerRecord*)_itr.current();
199 assert(cur == NULL || !cur->is_vm_pointer(), "Sanity check");
200 MemPointerRecord* next = (MemPointerRecord*)_itr.next();
201 if (next == NULL) {
202 return NULL;
203 }
204 if (cur->addr() == next->addr()) {
205 next = (MemPointerRecord*)_itr.next();
206 }
207 return current();
208 }
210 MemPointer* peek_next() const { ShouldNotReachHere(); return NULL; }
211 MemPointer* peek_prev() const { ShouldNotReachHere(); return NULL; }
212 void remove() { ShouldNotReachHere(); }
213 bool insert(MemPointer* ptr) { ShouldNotReachHere(); return false; }
214 bool insert_after(MemPointer* ptr) { ShouldNotReachHere(); return false; }
215 };
217 class StagingArea : public _ValueObj {
218 private:
219 MemPointerArray* _malloc_data;
220 MemPointerArray* _vm_data;
222 public:
223 StagingArea() : _malloc_data(NULL), _vm_data(NULL) {
224 init();
225 }
227 ~StagingArea() {
228 if (_malloc_data != NULL) delete _malloc_data;
229 if (_vm_data != NULL) delete _vm_data;
230 }
232 MallocRecordIterator malloc_record_walker() {
233 return MallocRecordIterator(malloc_data());
234 }
236 MemPointerArrayIteratorImpl virtual_memory_record_walker();
237 bool init();
238 void clear() {
239 assert(_malloc_data != NULL && _vm_data != NULL, "Just check");
240 _malloc_data->shrink();
241 _malloc_data->clear();
242 _vm_data->clear();
243 }
245 inline MemPointerArray* malloc_data() { return _malloc_data; }
246 inline MemPointerArray* vm_data() { return _vm_data; }
247 };
249 class MemBaseline;
250 class MemSnapshot : public CHeapObj<mtNMT> {
251 private:
252 // the following two arrays contain records of all known lived memory blocks
253 // live malloc-ed memory pointers
254 MemPointerArray* _alloc_ptrs;
255 // live virtual memory pointers
256 MemPointerArray* _vm_ptrs;
258 StagingArea _staging_area;
260 // the lock to protect this snapshot
261 Monitor* _lock;
263 NOT_PRODUCT(size_t _untracked_count;)
264 friend class MemBaseline;
266 public:
267 MemSnapshot();
268 virtual ~MemSnapshot();
270 // if we are running out of native memory
271 bool out_of_memory() {
272 return (_alloc_ptrs == NULL ||
273 _staging_area.malloc_data() == NULL ||
274 _staging_area.vm_data() == NULL ||
275 _vm_ptrs == NULL || _lock == NULL ||
276 _alloc_ptrs->out_of_memory() ||
277 _vm_ptrs->out_of_memory());
278 }
280 // merge a per-thread memory recorder into staging area
281 bool merge(MemRecorder* rec);
282 // promote staged data to snapshot
283 bool promote();
286 void wait(long timeout) {
287 assert(_lock != NULL, "Just check");
288 MonitorLockerEx locker(_lock);
289 locker.wait(true, timeout);
290 }
292 NOT_PRODUCT(void print_snapshot_stats(outputStream* st);)
293 NOT_PRODUCT(void check_staging_data();)
294 NOT_PRODUCT(void check_malloc_pointers();)
295 NOT_PRODUCT(bool has_allocation_record(address addr);)
297 private:
298 // copy pointer data from src to dest
299 void copy_pointer(MemPointerRecord* dest, const MemPointerRecord* src);
301 bool promote_malloc_records(MemPointerArrayIterator* itr);
302 bool promote_virtual_memory_records(MemPointerArrayIterator* itr);
303 };
306 #endif // SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP