Wed, 31 Jan 2018 19:24:57 -0500
8189170: Add option to disable stack overflow checking in primordial thread for use with JNI_CreateJavaJVM
Reviewed-by: dcubed
1 /*
2 * Copyright (c) 2012, 2017, 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"
26 #include "memory/allocation.hpp"
27 #include "runtime/safepoint.hpp"
28 #include "runtime/thread.inline.hpp"
29 #include "services/memBaseline.hpp"
30 #include "services/memTracker.hpp"
32 /*
33 * Sizes are sorted in descenting order for reporting
34 */
35 int compare_malloc_size(const MallocSite& s1, const MallocSite& s2) {
36 if (s1.size() == s2.size()) {
37 return 0;
38 } else if (s1.size() > s2.size()) {
39 return -1;
40 } else {
41 return 1;
42 }
43 }
46 int compare_virtual_memory_size(const VirtualMemoryAllocationSite& s1,
47 const VirtualMemoryAllocationSite& s2) {
48 if (s1.reserved() == s2.reserved()) {
49 return 0;
50 } else if (s1.reserved() > s2.reserved()) {
51 return -1;
52 } else {
53 return 1;
54 }
55 }
57 // Sort into allocation site addresses order for baseline comparison
58 int compare_malloc_site(const MallocSite& s1, const MallocSite& s2) {
59 return s1.call_stack()->compare(*s2.call_stack());
60 }
62 // Sort into allocation site addresses and memory type order for baseline comparison
63 int compare_malloc_site_and_type(const MallocSite& s1, const MallocSite& s2) {
64 int res = compare_malloc_site(s1, s2);
65 if (res == 0) {
66 res = (int)(s1.flags() - s2.flags());
67 }
69 return res;
70 }
72 int compare_virtual_memory_site(const VirtualMemoryAllocationSite& s1,
73 const VirtualMemoryAllocationSite& s2) {
74 return s1.call_stack()->compare(*s2.call_stack());
75 }
77 /*
78 * Walker to walk malloc allocation site table
79 */
80 class MallocAllocationSiteWalker : public MallocSiteWalker {
81 private:
82 SortedLinkedList<MallocSite, compare_malloc_size> _malloc_sites;
83 size_t _count;
85 // Entries in MallocSiteTable with size = 0 and count = 0,
86 // when the malloc site is not longer there.
87 public:
88 MallocAllocationSiteWalker() : _count(0) { }
90 inline size_t count() const { return _count; }
92 LinkedList<MallocSite>* malloc_sites() {
93 return &_malloc_sites;
94 }
96 bool do_malloc_site(const MallocSite* site) {
97 if (site->size() >= MemBaseline::SIZE_THRESHOLD) {
98 if (_malloc_sites.add(*site) != NULL) {
99 _count++;
100 return true;
101 } else {
102 return false; // OOM
103 }
104 } else {
105 // malloc site does not meet threshold, ignore and continue
106 return true;
107 }
108 }
109 };
111 // Compare virtual memory region's base address
112 int compare_virtual_memory_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2) {
113 return r1.compare(r2);
114 }
116 // Walk all virtual memory regions for baselining
117 class VirtualMemoryAllocationWalker : public VirtualMemoryWalker {
118 private:
119 SortedLinkedList<ReservedMemoryRegion, compare_virtual_memory_base>
120 _virtual_memory_regions;
121 size_t _count;
123 public:
124 VirtualMemoryAllocationWalker() : _count(0) { }
126 bool do_allocation_site(const ReservedMemoryRegion* rgn) {
127 if (rgn->size() >= MemBaseline::SIZE_THRESHOLD) {
128 if (_virtual_memory_regions.add(*rgn) != NULL) {
129 _count ++;
130 return true;
131 } else {
132 return false;
133 }
134 }
135 return true;
136 }
138 LinkedList<ReservedMemoryRegion>* virtual_memory_allocations() {
139 return &_virtual_memory_regions;
140 }
141 };
144 bool MemBaseline::baseline_summary() {
145 MallocMemorySummary::snapshot(&_malloc_memory_snapshot);
146 VirtualMemorySummary::snapshot(&_virtual_memory_snapshot);
147 return true;
148 }
150 bool MemBaseline::baseline_allocation_sites() {
151 // Malloc allocation sites
152 MallocAllocationSiteWalker malloc_walker;
153 if (!MallocSiteTable::walk_malloc_site(&malloc_walker)) {
154 return false;
155 }
157 _malloc_sites.move(malloc_walker.malloc_sites());
158 // The malloc sites are collected in size order
159 _malloc_sites_order = by_size;
161 // Virtual memory allocation sites
162 VirtualMemoryAllocationWalker virtual_memory_walker;
163 if (!VirtualMemoryTracker::walk_virtual_memory(&virtual_memory_walker)) {
164 return false;
165 }
167 // Virtual memory allocations are collected in call stack order
168 _virtual_memory_allocations.move(virtual_memory_walker.virtual_memory_allocations());
170 if (!aggregate_virtual_memory_allocation_sites()) {
171 return false;
172 }
173 // Virtual memory allocation sites are aggregrated in call stack order
174 _virtual_memory_sites_order = by_address;
176 return true;
177 }
179 bool MemBaseline::baseline(bool summaryOnly) {
180 reset();
182 _class_count = InstanceKlass::number_of_instance_classes();
184 if (!baseline_summary()) {
185 return false;
186 }
188 _baseline_type = Summary_baselined;
190 // baseline details
191 if (!summaryOnly &&
192 MemTracker::tracking_level() == NMT_detail) {
193 baseline_allocation_sites();
194 _baseline_type = Detail_baselined;
195 }
197 return true;
198 }
200 int compare_allocation_site(const VirtualMemoryAllocationSite& s1,
201 const VirtualMemoryAllocationSite& s2) {
202 return s1.call_stack()->compare(*s2.call_stack());
203 }
205 bool MemBaseline::aggregate_virtual_memory_allocation_sites() {
206 SortedLinkedList<VirtualMemoryAllocationSite, compare_allocation_site> allocation_sites;
208 VirtualMemoryAllocationIterator itr = virtual_memory_allocations();
209 const ReservedMemoryRegion* rgn;
210 VirtualMemoryAllocationSite* site;
211 while ((rgn = itr.next()) != NULL) {
212 VirtualMemoryAllocationSite tmp(*rgn->call_stack());
213 site = allocation_sites.find(tmp);
214 if (site == NULL) {
215 LinkedListNode<VirtualMemoryAllocationSite>* node =
216 allocation_sites.add(tmp);
217 if (node == NULL) return false;
218 site = node->data();
219 }
220 site->reserve_memory(rgn->size());
221 site->commit_memory(rgn->committed_size());
222 }
224 _virtual_memory_sites.move(&allocation_sites);
225 return true;
226 }
228 MallocSiteIterator MemBaseline::malloc_sites(SortingOrder order) {
229 assert(!_malloc_sites.is_empty(), "Not detail baseline");
230 switch(order) {
231 case by_size:
232 malloc_sites_to_size_order();
233 break;
234 case by_site:
235 malloc_sites_to_allocation_site_order();
236 break;
237 case by_site_and_type:
238 malloc_sites_to_allocation_site_and_type_order();
239 break;
240 case by_address:
241 default:
242 ShouldNotReachHere();
243 }
244 return MallocSiteIterator(_malloc_sites.head());
245 }
247 VirtualMemorySiteIterator MemBaseline::virtual_memory_sites(SortingOrder order) {
248 assert(!_virtual_memory_sites.is_empty(), "Not detail baseline");
249 switch(order) {
250 case by_size:
251 virtual_memory_sites_to_size_order();
252 break;
253 case by_site:
254 virtual_memory_sites_to_reservation_site_order();
255 break;
256 case by_address:
257 default:
258 ShouldNotReachHere();
259 }
260 return VirtualMemorySiteIterator(_virtual_memory_sites.head());
261 }
264 // Sorting allocations sites in different orders
265 void MemBaseline::malloc_sites_to_size_order() {
266 if (_malloc_sites_order != by_size) {
267 SortedLinkedList<MallocSite, compare_malloc_size> tmp;
269 // Add malloc sites to sorted linked list to sort into size order
270 tmp.move(&_malloc_sites);
271 _malloc_sites.set_head(tmp.head());
272 tmp.set_head(NULL);
273 _malloc_sites_order = by_size;
274 }
275 }
277 void MemBaseline::malloc_sites_to_allocation_site_order() {
278 if (_malloc_sites_order != by_site && _malloc_sites_order != by_site_and_type) {
279 SortedLinkedList<MallocSite, compare_malloc_site> tmp;
280 // Add malloc sites to sorted linked list to sort into site (address) order
281 tmp.move(&_malloc_sites);
282 _malloc_sites.set_head(tmp.head());
283 tmp.set_head(NULL);
284 _malloc_sites_order = by_site;
285 }
286 }
288 void MemBaseline::malloc_sites_to_allocation_site_and_type_order() {
289 if (_malloc_sites_order != by_site_and_type) {
290 SortedLinkedList<MallocSite, compare_malloc_site_and_type> tmp;
291 // Add malloc sites to sorted linked list to sort into site (address) order
292 tmp.move(&_malloc_sites);
293 _malloc_sites.set_head(tmp.head());
294 tmp.set_head(NULL);
295 _malloc_sites_order = by_site_and_type;
296 }
297 }
299 void MemBaseline::virtual_memory_sites_to_size_order() {
300 if (_virtual_memory_sites_order != by_size) {
301 SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_size> tmp;
303 tmp.move(&_virtual_memory_sites);
305 _virtual_memory_sites.set_head(tmp.head());
306 tmp.set_head(NULL);
307 _virtual_memory_sites_order = by_size;
308 }
309 }
311 void MemBaseline::virtual_memory_sites_to_reservation_site_order() {
312 if (_virtual_memory_sites_order != by_size) {
313 SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_site> tmp;
315 tmp.move(&_virtual_memory_sites);
317 _virtual_memory_sites.set_head(tmp.head());
318 tmp.set_head(NULL);
320 _virtual_memory_sites_order = by_size;
321 }
322 }